From 943262294831375a2e5c7c0d6f83f140c89f1e00 Mon Sep 17 00:00:00 2001 From: Themba Dube Date: Sat, 4 Jan 2020 08:48:37 -0500 Subject: [PATCH 1/3] Allow objects to override bounding-box hit-testing --- src/lv_core/lv_obj.c | 27 +++++++++++++++++++-------- src/lv_core/lv_obj.h | 16 ++++++++++++++++ src/lv_objx/lv_cpicker.c | 5 +++++ 3 files changed, 40 insertions(+), 8 deletions(-) diff --git a/src/lv_core/lv_obj.c b/src/lv_core/lv_obj.c index c84ee346d..c05380603 100644 --- a/src/lv_core/lv_obj.c +++ b/src/lv_core/lv_obj.c @@ -2412,12 +2412,14 @@ bool lv_obj_is_focused(const lv_obj_t * obj) *------------------*/ /** - * Hit-test an object given a particular point in screen space. - * @param obj object to hit-test + * Check if a given screen-space point is on an object's coordinates. + * + * This method is intended to be used mainly by advanced hit testing algorithms to check + * whether the point is even within the object (as an optimization). + * @param obj object to check * @param point screen-space point - * @return true if the object is considered under the point */ -bool lv_obj_hittest(lv_obj_t * obj, lv_point_t * point) { +bool lv_obj_is_point_on_coords(lv_obj_t * obj, lv_point_t * point) { #if LV_USE_EXT_CLICK_AREA == LV_EXT_CLICK_AREA_TINY lv_area_t ext_area; ext_area.x1 = obj->coords.x1 - obj->ext_click_pad_hor; @@ -2439,15 +2441,24 @@ bool lv_obj_hittest(lv_obj_t * obj, lv_point_t * point) { #endif return false; } + return true; +} + +/** + * Hit-test an object given a particular point in screen space. + * @param obj object to hit-test + * @param point screen-space point + * @return true if the object is considered under the point + */ +bool lv_obj_hittest(lv_obj_t * obj, lv_point_t * point) { if(obj->adv_hittest) { lv_hit_test_info_t hit_info; hit_info.point = point; hit_info.result = true; obj->signal_cb(obj, LV_SIGNAL_HIT_TEST, &hit_info); - if(!hit_info.result) - return false; - } - return true; + return hit_info.result; + } else + return lv_obj_is_point_on_coords(obj, point); } /** diff --git a/src/lv_core/lv_obj.h b/src/lv_core/lv_obj.h index cd99382e6..d4886be47 100644 --- a/src/lv_core/lv_obj.h +++ b/src/lv_core/lv_obj.h @@ -940,6 +940,22 @@ lv_event_cb_t lv_obj_get_event_cb(const lv_obj_t * obj); * Other get *-----------------*/ +/** + * Check if a given screen-space point is on an object's coordinates. + * + * This method is intended to be used mainly by advanced hit testing algorithms to check + * whether the point is even within the object (as an optimization). + * @param obj object to check + * @param point screen-space point + */ +bool lv_obj_is_point_on_coords(lv_obj_t * obj, lv_point_t * point); + +/** + * Hit-test an object given a particular point in screen space. + * @param obj object to hit-test + * @param point screen-space point + * @return true if the object is considered under the point + */ bool lv_obj_hittest(lv_obj_t * obj, lv_point_t * point); /** diff --git a/src/lv_objx/lv_cpicker.c b/src/lv_objx/lv_cpicker.c index 4f6be702c..95c6d26aa 100644 --- a/src/lv_objx/lv_cpicker.c +++ b/src/lv_objx/lv_cpicker.c @@ -900,9 +900,14 @@ static lv_res_t lv_cpicker_signal(lv_obj_t * cpicker, lv_signal_t sign, void * p static bool lv_cpicker_hit(lv_obj_t * cpicker, const lv_point_t * p) { + bool is_point_on_coords = lv_obj_is_point_on_coords(cpicker, p); + if(!is_point_on_coords) + return false; + lv_cpicker_ext_t * ext = (lv_cpicker_ext_t *)lv_obj_get_ext_attr(cpicker); if(ext->type != LV_CPICKER_TYPE_DISC || ext->preview) return true; + const lv_style_t * style_main = lv_cpicker_get_style(cpicker, LV_CPICKER_STYLE_MAIN); lv_area_t area_mid; lv_area_copy(&area_mid, &cpicker->coords); From 23625441a87b2a7f13b0906872b4007166bcb900 Mon Sep 17 00:00:00 2001 From: Themba Dube Date: Sat, 4 Jan 2020 08:48:51 -0500 Subject: [PATCH 2/3] Implement advanced hit-testing for zoomed images --- src/lv_objx/lv_img.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/lv_objx/lv_img.c b/src/lv_objx/lv_img.c index 0f52206a4..1740240d5 100644 --- a/src/lv_objx/lv_img.c +++ b/src/lv_objx/lv_img.c @@ -97,6 +97,7 @@ lv_obj_t * lv_img_create(lv_obj_t * par, const lv_obj_t * copy) if(copy == NULL) { lv_obj_set_click(new_img, false); + lv_obj_set_adv_hittest(new_img, true); /*Images have fast hit-testing*/ /* Enable auto size for non screens * because image screens are wallpapers * and must be screen sized*/ @@ -590,6 +591,26 @@ static lv_res_t lv_img_signal(lv_obj_t * img, lv_signal_t sign, void * param) lv_coord_t d = ds.i / 2; img->ext_draw_pad = LV_MATH_MAX(img->ext_draw_pad, d); } + } else if(sign == LV_SIGNAL_HIT_TEST) { + lv_hit_test_info_t *info = param; + if(ext->zoom != 256 && ext->angle == 0) { + lv_coord_t origin_width = lv_area_get_width(&img->coords); + lv_coord_t origin_height = lv_area_get_height(&img->coords); + lv_coord_t scaled_width = (origin_width * ext->zoom + 255) / 256; + lv_coord_t scaled_height = (origin_height * ext->zoom + 255) / 256; + + lv_coord_t width_offset = (origin_width - scaled_width) / 2; + lv_coord_t height_offset = (origin_height - scaled_height) / 2; + + lv_area_t coords; + lv_area_copy(&coords, &img->coords); + coords.x1 += width_offset; + coords.x2 -= width_offset; + coords.y1 += height_offset; + coords.y2 -= height_offset; + info->result = lv_area_is_point_on(&coords, info->point, 0); + } else + info->result = lv_obj_is_point_on_coords(img, info->point); } return res; From 08a125c8605fdd3b2645c7b39f8245c1ea467b17 Mon Sep 17 00:00:00 2001 From: Themba Dube Date: Sat, 4 Jan 2020 08:52:52 -0500 Subject: [PATCH 3/3] Make `lv_obj_is_point_on_coords` accept a constant point --- src/lv_core/lv_obj.c | 2 +- src/lv_core/lv_obj.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lv_core/lv_obj.c b/src/lv_core/lv_obj.c index c05380603..3561e836a 100644 --- a/src/lv_core/lv_obj.c +++ b/src/lv_core/lv_obj.c @@ -2419,7 +2419,7 @@ bool lv_obj_is_focused(const lv_obj_t * obj) * @param obj object to check * @param point screen-space point */ -bool lv_obj_is_point_on_coords(lv_obj_t * obj, lv_point_t * point) { +bool lv_obj_is_point_on_coords(lv_obj_t * obj, const lv_point_t * point) { #if LV_USE_EXT_CLICK_AREA == LV_EXT_CLICK_AREA_TINY lv_area_t ext_area; ext_area.x1 = obj->coords.x1 - obj->ext_click_pad_hor; diff --git a/src/lv_core/lv_obj.h b/src/lv_core/lv_obj.h index d4886be47..d08ad62e5 100644 --- a/src/lv_core/lv_obj.h +++ b/src/lv_core/lv_obj.h @@ -948,7 +948,7 @@ lv_event_cb_t lv_obj_get_event_cb(const lv_obj_t * obj); * @param obj object to check * @param point screen-space point */ -bool lv_obj_is_point_on_coords(lv_obj_t * obj, lv_point_t * point); +bool lv_obj_is_point_on_coords(lv_obj_t * obj, const lv_point_t * point); /** * Hit-test an object given a particular point in screen space.