diff --git a/docs/overview/drawing.md b/docs/overview/drawing.md index 73eeaf788..74d823ad8 100644 --- a/docs/overview/drawing.md +++ b/docs/overview/drawing.md @@ -177,37 +177,25 @@ Finish the drawing of a part. It's a good place to draw extra content on the par This event is used to check whether an object fully covers an area or not. -`lv_event_get_cover_check_info(event)` returns an pointer to an `lv_cover_check_info_t` variable. Its `res` field should be set to the following values considering the `area` field: -- `LV_DRAW_RES_COVER` the areas is fully covered by the object -- `LV_DRAW_RES_NOT_COVER` the areas is not covered by the object -- `LV_DRAW_RES_MASKED` there is a mask on the object so it can not covert the area +`lv_event_get_cover_area(event)` returns an pointer to an area to check and `lv_event_set_cover_res(event, res)` can be used to set one of these results: +- `LV_COVER_RES_COVER` the areas is fully covered by the object +- `LV_COVER_RES_NOT_COVER` the areas is not covered by the object +- `LV_COVER_RES_MASKED` there is a mask on the object so it can not covert the area Here are some cases why can't an object fully cover an area: - It's simply not fully on the that area - It has radius - It has not 100% background opacity - It's an ARGB or chroma keyed image -- It's a text - It has not normal blending mode. In this case LVGL needs to know the colors under the object to make the blending properly +- It's a text, etc In short if for any reason the the area below the object is visible than it doesn't cover that area. -Some guideline how to set the `res` field in `lv_cover_check_info_t`: -- Before sending this event LVGL checks if at least the widget's coordinates fully cover the area or not. If not the event is not called. -- You need to check only the drawing you have added. The existing properties known by widget are handled in the widget's internal events. +Before sending this event LVGL checks if at least the widget's coordinates fully cover the area or not. If not the event is not called. + +You need to check only the drawing you have added. The existing properties known by widget are handled in the widget's internal events. E.g. if a widget has > 0 radius it might not cover an area but you need to handle `radius` only if you will modify it and widget can't know about it. -- If `res` is already set to `LV_DRAW_RES_MASKED` do nothing. In this case an other event already set it and it's the "strongest" state that shouldn't be overwritten. -- If you added a draw mask on the object set `res` to `LV_DRAW_RES_MASKED` -- If there is no draw masks but the object simply not covers the area for any reason set `LV_DRAW_RES_NOT_COVER` -- If the area is fully covered by the object leave `res` unchanged. - -In the practice probably you need to set only `LV_DRAW_RES_MASKED`if you added masks in a MAIN or POST draw events because "normal" cover checks are handles by the widgets. - -However, if you really added masks in MAIN or POST draw events you need to handle `LV_EVENT_COVER_CHECK` event and tell LVGL there are masks on this object. - -If masks are added and removed in `LV_EVENT_DRAW_PART_BEGIN/END`, `LV_EVENT_COVER_CHECK` doesn't need to know about it except the masks affects `LV_PART_MAIN`. -It's because LVGL checks the main part to decide whether an object covers an area or not. -So it doesn't matter e.g. if a tabel's cell is masked because the tables background already covered the area or not. #### LV_EVENT_REFR_EXT_DRAW_SIZE diff --git a/src/core/lv_event.c b/src/core/lv_event.c index 13008b08f..7f7cdda19 100644 --- a/src/core/lv_event.c +++ b/src/core/lv_event.c @@ -319,13 +319,25 @@ lv_hit_test_info_t * lv_event_get_hit_test_info(lv_event_t * e) } } -lv_cover_check_info_t * lv_event_get_cover_check_info(lv_event_t * e) +const lv_area_t * lv_event_get_cover_area(lv_event_t * e) { if(e->code == LV_EVENT_COVER_CHECK) { - return lv_event_get_param(e); + lv_cover_check_info_t * p = lv_event_get_param(e); + return p->area; + } else { + LV_LOG_WARN("Not interpreted with this event code"); + return NULL; + } +} + +void lv_event_set_cover_res(lv_event_t * e, lv_cover_res_t res) +{ + if(e->code == LV_EVENT_COVER_CHECK) { + lv_cover_check_info_t * p = lv_event_get_param(e); + if(p->res == LV_COVER_RES_MASKED) return; /*Do not overwrite masked result*/ + if(res == LV_COVER_RES_NOT_COVER) p->res = res; } else { LV_LOG_WARN("Not interpreted with this event code"); - return 0; } } diff --git a/src/core/lv_event.h b/src/core/lv_event.h index cd243f212..26d02ef05 100644 --- a/src/core/lv_event.h +++ b/src/core/lv_event.h @@ -113,15 +113,12 @@ typedef struct { /** * Used as the event parameter of ::LV_EVENT_COVER_CHECK to check if an area is covered by the object or not. - * `res` should be set like this: - * - If already set to ::LV_DRAW_RES_MASKED do nothing - * - If there is a draw mask on the object set to ::LV_DRAW_RES_MASKED - * - If there is no draw mask but the object simply not covers the area set ::LV_DRAW_RES_NOT_COVER - * - If the area is fully covered by the object leave `res` unchanged. + * In the event use `const lv_area_t * area = lv_event_get_cover_area(e)` to get the area to check + * and `lv_event_set_cover_res(e, res)` to set the result. */ typedef struct { - lv_draw_res_t res; /**< Set to ::LV_DRAW_RES_NOT_COVER or ::LV_DRAW_RES_MASKED. */ - const lv_area_t * area; /**< The area to check */ + lv_cover_res_t res; + const lv_area_t * area; } lv_cover_check_info_t; /********************** @@ -290,12 +287,19 @@ lv_point_t * lv_event_get_self_size_info(lv_event_t * e); lv_hit_test_info_t * lv_event_get_hit_test_info(lv_event_t * e); /** - * Get a pointer to an `lv_cover_check_info_t` variable in which the area cover information should be saved. - * Can be used in `LV_EVENT_COVER_CHECK` + * Get a pointer to an area which should be examined whether the object fully covers it or not. + * Can be used in `LV_EVENT_HIT_TEST` * @param e pointer to an event - * @return pointer to `lv_cover_check_info_t` or NULL if called on an unrelated event + * @return an area with absolute coordinates to check */ -lv_cover_check_info_t * lv_event_get_cover_check_info(lv_event_t * e); +const lv_area_t * lv_event_get_cover_area(lv_event_t * e); + +/** + * Set the result of cover checking. Can be used in `LV_EVENT_COVER_CHECK` + * @param e pointer to an event + * @param res an element of ::lv_cover_check_info_t + */ +void lv_event_set_cover_res(lv_event_t * e, lv_cover_res_t res); /********************** * MACROS diff --git a/src/core/lv_obj.c b/src/core/lv_obj.c index 23a86d5fa..0b28b1e0b 100644 --- a/src/core/lv_obj.c +++ b/src/core/lv_obj.c @@ -454,9 +454,9 @@ static void lv_obj_draw(lv_event_t * e) lv_obj_t * obj = lv_event_get_target(e); if(code == LV_EVENT_COVER_CHECK) { lv_cover_check_info_t * info = lv_event_get_param(e); - if(info->res == LV_DRAW_RES_MASKED) return; + if(info->res == LV_COVER_RES_MASKED) return; if(lv_obj_get_style_clip_corner(obj, LV_PART_MAIN)) { - info->res = LV_DRAW_RES_MASKED; + info->res = LV_COVER_RES_MASKED; return; } @@ -472,27 +472,27 @@ static void lv_obj_draw(lv_event_t * e) coords.y2 += h; if(_lv_area_is_in(info->area, &coords, r) == false) { - info->res = LV_DRAW_RES_NOT_COVER; + info->res = LV_COVER_RES_NOT_COVER; return; } if(lv_obj_get_style_bg_opa(obj, LV_PART_MAIN) < LV_OPA_MAX) { - info->res = LV_DRAW_RES_NOT_COVER; + info->res = LV_COVER_RES_NOT_COVER; return; } #if LV_DRAW_COMPLEX if(lv_obj_get_style_blend_mode(obj, LV_PART_MAIN) != LV_BLEND_MODE_NORMAL) { - info->res = LV_DRAW_RES_NOT_COVER; + info->res = LV_COVER_RES_NOT_COVER; return; } #endif if(lv_obj_get_style_opa(obj, LV_PART_MAIN) < LV_OPA_MAX) { - info->res = LV_DRAW_RES_NOT_COVER; + info->res = LV_COVER_RES_NOT_COVER; return; } - info->res = LV_DRAW_RES_COVER; + info->res = LV_COVER_RES_COVER; } else if(code == LV_EVENT_DRAW_MAIN) { diff --git a/src/core/lv_obj_draw.h b/src/core/lv_obj_draw.h index d394f98cd..1b04bf25c 100644 --- a/src/core/lv_obj_draw.h +++ b/src/core/lv_obj_draw.h @@ -25,12 +25,12 @@ extern "C" { struct _lv_obj_t; -/** Design results*/ +/** Cover check results*/ typedef enum { - LV_DRAW_RES_COVER, /**< Returned on `LV_DRAW_COVER_CHK` if the areas is fully covered*/ - LV_DRAW_RES_NOT_COVER, /**< Returned on `LV_DRAW_COVER_CHK` if the areas is not covered*/ - LV_DRAW_RES_MASKED, /**< Returned on `LV_DRAW_COVER_CHK` if the areas is masked out*/ -}lv_draw_res_t; + LV_COVER_RES_COVER, + LV_COVER_RES_NOT_COVER, + LV_COVER_RES_MASKED, +}lv_cover_res_t; typedef struct { diff --git a/src/core/lv_refr.c b/src/core/lv_refr.c index 90507bf45..d7eafc200 100644 --- a/src/core/lv_refr.c +++ b/src/core/lv_refr.c @@ -574,10 +574,10 @@ static lv_obj_t * lv_refr_get_top_obj(const lv_area_t * area_p, lv_obj_t * obj) /*If this object is fully cover the draw area check the children too*/ if(_lv_area_is_in(area_p, &obj->coords, 0) && lv_obj_has_flag(obj, LV_OBJ_FLAG_HIDDEN) == false) { lv_cover_check_info_t info; - info.res = LV_DRAW_RES_COVER; + info.res = LV_COVER_RES_COVER; info.area = area_p; lv_event_send(obj, LV_EVENT_COVER_CHECK, &info); - if(info.res == LV_DRAW_RES_MASKED) return NULL; + if(info.res == LV_COVER_RES_MASKED) return NULL; uint32_t i; for(i = 0; i < lv_obj_get_child_cnt(obj); i++) { @@ -592,7 +592,7 @@ static lv_obj_t * lv_refr_get_top_obj(const lv_area_t * area_p, lv_obj_t * obj) /*If no better children use this object*/ if(found_p == NULL) { - if(info.res == LV_DRAW_RES_COVER) { + if(info.res == LV_COVER_RES_COVER) { found_p = obj; } } diff --git a/src/extra/widgets/colorwheel/lv_colorwheel.c b/src/extra/widgets/colorwheel/lv_colorwheel.c index df365c284..0169f452f 100644 --- a/src/extra/widgets/colorwheel/lv_colorwheel.c +++ b/src/extra/widgets/colorwheel/lv_colorwheel.c @@ -520,7 +520,7 @@ static void lv_colorwheel_event(const lv_obj_class_t * class_p, lv_event_t * e) } else if(code == LV_EVENT_COVER_CHECK) { lv_cover_check_info_t * info = lv_event_get_param(e); - if(info->res != LV_DRAW_RES_MASKED) info->res = LV_DRAW_RES_NOT_COVER; + if(info->res != LV_COVER_RES_MASKED) info->res = LV_COVER_RES_NOT_COVER; } } diff --git a/src/extra/widgets/imgbtn/lv_imgbtn.c b/src/extra/widgets/imgbtn/lv_imgbtn.c index 77ae4147a..aaa110f1b 100644 --- a/src/extra/widgets/imgbtn/lv_imgbtn.c +++ b/src/extra/widgets/imgbtn/lv_imgbtn.c @@ -180,7 +180,7 @@ static void lv_imgbtn_event(const lv_obj_class_t * class_p, lv_event_t * e) } else if(code == LV_EVENT_COVER_CHECK) { lv_cover_check_info_t * info = lv_event_get_param(e); - if(info->res != LV_DRAW_RES_MASKED) info->res = LV_DRAW_RES_NOT_COVER; + if(info->res != LV_COVER_RES_MASKED) info->res = LV_COVER_RES_NOT_COVER; } } diff --git a/src/widgets/lv_img.c b/src/widgets/lv_img.c index 30be40128..5d7386af2 100644 --- a/src/widgets/lv_img.c +++ b/src/widgets/lv_img.c @@ -490,21 +490,21 @@ static void draw_img(lv_event_t * e) lv_img_t * img = (lv_img_t *)obj; if(code == LV_EVENT_COVER_CHECK) { lv_cover_check_info_t * info = lv_event_get_param(e); - if(info->res == LV_DRAW_RES_MASKED) return; + if(info->res == LV_COVER_RES_MASKED) return; if(img->src_type == LV_IMG_SRC_UNKNOWN || img->src_type == LV_IMG_SRC_SYMBOL) { - info->res = LV_DRAW_RES_NOT_COVER; + info->res = LV_COVER_RES_NOT_COVER; return; } /*Non true color format might have "holes"*/ if(img->cf != LV_IMG_CF_TRUE_COLOR && img->cf != LV_IMG_CF_RAW) { - info->res = LV_DRAW_RES_NOT_COVER; + info->res = LV_COVER_RES_NOT_COVER; return; } /*With not LV_OPA_COVER images can't cover an area */ if(lv_obj_get_style_img_opa(obj, LV_PART_MAIN) != LV_OPA_COVER) { - info->res = LV_DRAW_RES_NOT_COVER; + info->res = LV_COVER_RES_NOT_COVER; return; } @@ -512,7 +512,7 @@ static void draw_img(lv_event_t * e) angle_final += img->angle; if(angle_final != 0) { - info->res = LV_DRAW_RES_NOT_COVER; + info->res = LV_COVER_RES_NOT_COVER; return; } @@ -523,7 +523,7 @@ static void draw_img(lv_event_t * e) const lv_area_t * clip_area = lv_event_get_param(e); if(zoom_final == LV_IMG_ZOOM_NONE) { if(_lv_area_is_in(clip_area, &obj->coords, 0) == false) { - info->res = LV_DRAW_RES_NOT_COVER; + info->res = LV_COVER_RES_NOT_COVER; return; } } @@ -536,7 +536,7 @@ static void draw_img(lv_event_t * e) a.y2 += obj->coords.y1; if(_lv_area_is_in(clip_area, &a, 0) == false) { - info->res = LV_DRAW_RES_NOT_COVER; + info->res = LV_COVER_RES_NOT_COVER; return; } } diff --git a/src/widgets/lv_objx_templ.c b/src/widgets/lv_objx_templ.c index 6b36d1d9b..9576add4b 100644 --- a/src/widgets/lv_objx_templ.c +++ b/src/widgets/lv_objx_templ.c @@ -196,7 +196,7 @@ static lv_draw_res_t lv_templ_draw(lv_obj_t * templ, const lv_area_t * clip_area { /*Return false if the object is not covers the mask_p area*/ if(mode == LV_DRAW_COVER_CHK) { - return LV_DRAW_RES_NOT_COVER; + return LV_COVER_RES_NOT_COVER; } /*Draw the object*/ else if(mode == LV_DRAW_DRAW_MAIN) { @@ -206,7 +206,7 @@ static lv_draw_res_t lv_templ_draw(lv_obj_t * templ, const lv_area_t * clip_area else if(mode == LV_DRAW_DRAW_POST) { } - return LV_DRAW_RES_OK; + return LV_COVER_RES_OK; } /**