diff --git a/lv_conf_template.h b/lv_conf_template.h index d6e450290..1d56890f8 100644 --- a/lv_conf_template.h +++ b/lv_conf_template.h @@ -427,6 +427,10 @@ typedef void * lv_obj_user_data_t; /*Window (dependencies: lv_cont, lv_btn, lv_label, lv_img, lv_page)*/ #define LV_USE_WIN 1 +/* Extended clickable area */ +#define USE_LV_EXTENDED_CLICK_AREA 0 /* Enables obj extension to realize extended clickable area with additional extended coords (1: enabled) */ +#define USE_LV_EXTENDED_CLICK_AREA_TINY 0 /* Enables obj extension to realize extended clickable area with calculation of the fly (1: enabled) */ + /*================== * Non-user section *==================*/ diff --git a/src/lv_core/lv_indev.c b/src/lv_core/lv_indev.c index 632540640..a52322110 100644 --- a/src/lv_core/lv_indev.c +++ b/src/lv_core/lv_indev.c @@ -991,7 +991,13 @@ static lv_obj_t * indev_search_obj(const lv_indev_proc_t * proc, lv_obj_t * obj) /*If the point is on this object*/ /*Check its children too*/ +#if USE_LV_EXTENDED_CLICK_AREA + if(lv_area_is_point_on(&obj->ext_coords, &proc->types.pointer.act_point)) { +#elif USE_LV_EXTENDED_CLICK_AREA_TINY + if(lv_area_ext_is_point_on(&obj->coords, &proc->types.pointer.act_point, obj->ext_padding_hor, obj->ext_padding_ver)) { +#else if(lv_area_is_point_on(&obj->coords, &proc->types.pointer.act_point)) { +#endif lv_obj_t * i; LV_LL_READ(obj->child_ll, i) diff --git a/src/lv_core/lv_obj.c b/src/lv_core/lv_obj.c index 1ff8c74ad..38ce15d21 100644 --- a/src/lv_core/lv_obj.c +++ b/src/lv_core/lv_obj.c @@ -44,6 +44,9 @@ static void refresh_children_style(lv_obj_t * obj); static void delete_children(lv_obj_t * obj); static bool lv_obj_design(lv_obj_t * obj, const lv_area_t * mask_p, lv_design_mode_t mode); static lv_res_t lv_obj_signal(lv_obj_t * obj, lv_signal_t sign, void * param); +#if USE_LV_EXTENDED_CLICK_AREA +static void update_ext_coords(lv_area_t *coords, lv_area_t *ext_coords, uint8_t hor_pad, uint8_t ver_pad); +#endif /********************** * STATIC VARIABLES @@ -145,6 +148,14 @@ lv_obj_t * lv_obj_create(lv_obj_t * parent, const lv_obj_t * copy) new_obj->coords.y2 = lv_disp_get_ver_res(NULL) - 1; new_obj->ext_size = 0; +#if USE_LV_EXTENDED_CLICK_AREA + lv_area_copy(&(new_obj->ext_coords), &(new_obj->coords)); +#endif +#if USE_LV_EXTENDED_CLICK_AREA || USE_LV_EXTENDED_CLICK_AREA_TINY + new_obj->ext_padding_hor = 0; + new_obj->ext_padding_ver = 0; +#endif + /*Init realign*/ #if LV_OBJ_REALIGN new_obj->realign.align = LV_ALIGN_CENTER; @@ -213,6 +224,13 @@ lv_obj_t * lv_obj_create(lv_obj_t * parent, const lv_obj_t * copy) new_obj->coords.y2 = parent->coords.y1 + LV_OBJ_DEF_HEIGHT; new_obj->ext_size = 0; +#if USE_LV_EXTENDED_CLICK_AREA + lv_area_copy(&(new_obj->ext_coords), &(new_obj->coords)); +#endif +#if USE_LV_EXTENDED_CLICK_AREA || USE_LV_EXTENDED_CLICK_AREA_TINY + new_obj->ext_padding_hor = 0; + new_obj->ext_padding_ver = 0; +#endif /*Init realign*/ #if LV_OBJ_REALIGN new_obj->realign.align = LV_ALIGN_CENTER; @@ -269,6 +287,14 @@ lv_obj_t * lv_obj_create(lv_obj_t * parent, const lv_obj_t * copy) lv_area_copy(&new_obj->coords, ©->coords); new_obj->ext_size = copy->ext_size; +#if USE_LV_EXTENDED_CLICK_AREA + lv_area_copy(&new_obj->ext_coords, ©->ext_coords); +#endif +#if USE_LV_EXTENDED_CLICK_AREA || USE_LV_EXTENDED_CLICK_AREA_TINY + new_obj->ext_padding_hor = copy->ext_padding_hor; + new_obj->ext_padding_ver = copy->ext_padding_ver; +#endif + /*Set free data*/ #if LV_USE_USER_DATA_SINGLE memcpy(&new_obj->user_data, ©->user_data, sizeof(lv_obj_user_data_t)); @@ -554,6 +580,10 @@ void lv_obj_set_pos(lv_obj_t * obj, lv_coord_t x, lv_coord_t y) obj->coords.x2 += diff.x; obj->coords.y2 += diff.y; +#if USE_LV_EXTENDED_CLICK_AREA + update_ext_coords(&(obj->coords), &(obj->ext_coords), obj->hor_pad, obj->ver_pad); +#endif + refresh_children_position(obj, diff.x, diff.y); /*Inform the object about its new coordinates*/ @@ -613,6 +643,10 @@ void lv_obj_set_size(lv_obj_t * obj, lv_coord_t w, lv_coord_t h) obj->coords.x2 = obj->coords.x1 + w - 1; obj->coords.y2 = obj->coords.y1 + h - 1; +#if USE_LV_EXTENDED_CLICK_AREA + update_ext_coords(&(obj->coords), &(obj->ext_coords), obj->hor_pad, obj->ver_pad); +#endif + /*Send a signal to the object with its new coordinates*/ obj->signal_cb(obj, LV_SIGNAL_CORD_CHG, &ori); @@ -636,6 +670,24 @@ void lv_obj_set_size(lv_obj_t * obj, lv_coord_t w, lv_coord_t h) #endif } +#if USE_LV_EXTENDED_CLICK_AREA || USE_LV_EXTENDED_CLICK_AREA_TINY +/** + * Set the size of an extended clickable area + * @param obj pointer to an object + * @param w extended width to both sides + * @param h extended height to both sides + */ +void lv_obj_set_ext_paddings(lv_obj_t * obj, uint8_t w, uint8_t h) +{ + obj->ext_padding_hor = w; + obj->ext_padding_ver = h; + +#if USE_LV_EXTENDED_CLICK_AREA + update_ext_coords(&(obj->coords), &(obj->ext_coords), &(obj->ext_paddings)); +#endif +} +#endif + /** * Set the width of an object * @param obj pointer to an object @@ -1587,6 +1639,29 @@ lv_coord_t lv_obj_get_height_fit(lv_obj_t * obj) return lv_obj_get_height(obj) - style->body.padding.top - style->body.padding.bottom; } + +#if USE_LV_EXTENDED_CLICK_AREA || USE_LV_EXTENDED_CLICK_AREA_TINY +/** + * Get the horizontal padding of extended clickable area + * @param obj pointer to an object + * @return the horizontal padding + */ +uint8_t lv_obj_get_ext_hor_padding(const lv_obj_t * obj) +{ + return obj->ext_padding_hor; +} + +/** + * Get the vertical padding of extended clickable area + * @param obj pointer to an object + * @return the vertical padding + */ +uint8_t lv_obj_get_ext_ver_padding(const lv_obj_t * obj) +{ + return obj->ext_padding_ver; +} +#endif + /** * Get the extended size attribute of an object * @param obj pointer to an object @@ -2006,6 +2081,9 @@ static void refresh_children_position(lv_obj_t * obj, lv_coord_t x_diff, lv_coor i->coords.x2 += x_diff; i->coords.y2 += y_diff; +#if USE_LV_EXTENDED_CLICK_AREA + update_ext_coords(&(i->coords), &(i->ext_coords), i->hor_pad, i->ver_pad); +#endif refresh_children_position(i, x_diff, y_diff); } } @@ -2116,3 +2194,19 @@ static void delete_children(lv_obj_t * obj) if(obj->ext_attr != NULL) lv_mem_free(obj->ext_attr); lv_mem_free(obj); /*Free the object itself*/ } + +#if USE_LV_EXTENDED_CLICK_AREA +/** + * Update coordinates of extended clickable area from object's coordinates and ext_paddings + * @param coords coordinates of an object + * @param ext_coords extended coordinates, which will be updated + * @param paddings paddings of extended clickable area + */ +static void update_ext_coords(lv_area_t *coords, lv_area_t *ext_coords, uint8_t hor_pad, uint8_t ver_pad) +{ + ext_coords->x1 = hor_pad > coords->x1 ? 0 : coords->x1 - hor_pad; + ext_coords->x2 = coords->x2 + hor_pad; + ext_coords->y1 = ver_pad > coords->y1 ? 0 : coords->y1 - ver_pad; + ext_coords->y2 = coords->y2 + ver_pad; +} +#endif diff --git a/src/lv_core/lv_obj.h b/src/lv_core/lv_obj.h index 2f75df081..462100473 100644 --- a/src/lv_core/lv_obj.h +++ b/src/lv_core/lv_obj.h @@ -183,6 +183,13 @@ typedef struct _lv_obj_t lv_ll_t child_ll; /*Linked list to store the children objects*/ lv_area_t coords; /*Coordinates of the object (x1, y1, x2, y2)*/ +#if USE_LV_EXTENDED_CLICK_AREA + lv_area_t ext_coords; +#endif +#if USE_LV_EXTENDED_CLICK_AREA || USE_LV_EXTENDED_CLICK_AREA_TINY + uint8_t ext_padding_hor; + uint8_t ext_padding_ver; +#endif lv_event_cb_t event_cb; lv_signal_cb_t signal_cb; /*Object type specific signal function*/ @@ -348,6 +355,16 @@ void lv_obj_set_y(lv_obj_t * obj, lv_coord_t y); */ void lv_obj_set_size(lv_obj_t * obj, lv_coord_t w, lv_coord_t h); +#if USE_LV_EXTENDED_CLICK_AREA || USE_LV_EXTENDED_CLICK_AREA_TINY +/** + * Set the size of an extended clickable area + * @param obj pointer to an object + * @param w extended width to both sides + * @param h extended height to both sides + */ +void lv_obj_set_ext_paddings(lv_obj_t * obj, uint8_t w, uint8_t h); +#endif + /** * Set the width of an object * @param obj pointer to an object @@ -695,6 +712,23 @@ lv_coord_t lv_obj_get_width_fit(lv_obj_t * obj); */ lv_coord_t lv_obj_get_height_fit(lv_obj_t * obj); +#if USE_LV_EXTENDED_CLICK_AREA || USE_LV_EXTENDED_CLICK_AREA_TINY +/** + * Get the horizontal padding of extended clickable area + * @param obj pointer to an object + * @return the horizontal padding + */ +uint8_t lv_obj_get_ext_hor_padding(const lv_obj_t * obj); + +/** + * Get the vertical padding of extended clickable area + * @param obj pointer to an object + * @return the vertical padding + */ +uint8_t lv_obj_get_ext_ver_padding(const lv_obj_t * obj); + +#endif + /** * Get the extended size attribute of an object * @param obj pointer to an object diff --git a/src/lv_misc/lv_area.c b/src/lv_misc/lv_area.c index 45ea1b78c..48047eecc 100644 --- a/src/lv_misc/lv_area.c +++ b/src/lv_misc/lv_area.c @@ -6,6 +6,7 @@ /********************* * INCLUDES *********************/ +#include "lv_conf.h" #include "lv_area.h" #include "lv_math.h" @@ -153,6 +154,29 @@ bool lv_area_is_point_on(const lv_area_t * a_p, const lv_point_t * p_p) return is_on; } +#if USE_LV_EXTENDED_CLICK_AREA_TINY +/** + * Check if a point is on an area + * @param a_p pointer to an area + * @param p_p pointer to a point + * @param ext_hor extended horizontal padding + * @param ext_ver extended horizontal padding + * @return false:the point is out of the area + */ +bool lv_area_ext_is_point_on(const lv_area_t * a_p, const lv_point_t * p_p, uint8_t ext_hor, uint8_t ext_ver) +{ + bool is_on = false; + + if(( (p_p->x + ext_hor) >= a_p->x1 && p_p->x <= (a_p->x2 + ext_hor) ) && + ( (p_p->y + ext_ver) >= a_p->y1 && p_p->y <= (a_p->y2 + ext_ver)) ) { + is_on = true; + } + + return is_on; +} + +#endif + /** * Check if two area has common parts * @param a1_p pointer to an area. diff --git a/src/lv_misc/lv_area.h b/src/lv_misc/lv_area.h index 10e0d6a63..7082cbc2d 100644 --- a/src/lv_misc/lv_area.h +++ b/src/lv_misc/lv_area.h @@ -140,6 +140,18 @@ void lv_area_join(lv_area_t * a_res_p, const lv_area_t * a1_p, const lv_area_t * */ bool lv_area_is_point_on(const lv_area_t * a_p, const lv_point_t * p_p); +#if USE_LV_EXTENDED_CLICK_AREA_TINY +/** + * Check if a point is on an area + * @param a_p pointer to an area + * @param p_p pointer to a point + * @param ext_hor extended horizontal padding + * @param ext_ver extended horizontal padding + * @return false:the point is out of the area + */ +bool lv_area_ext_is_point_on(const lv_area_t * a_p, const lv_point_t * p_p, uint8_t ext_hor, uint8_t ext_ver); +#endif + /** * Check if two area has common parts * @param a1_p pointer to an area.