From f6b3c31561276a6c7afc8fb56ae2e5363772782c Mon Sep 17 00:00:00 2001 From: "Carsten Haitzler (Rasterman)" Date: Thu, 7 Jul 2016 14:10:24 +0900 Subject: [PATCH] evas event handling3 - fix yet more corner cases for clipped objects this is a continuation fix from 25d77bc1d24d9fd539c681fa58db976c1ca65051 and 9f0fd66ab818d212fa88faef316ac17625f1a2f5 this fixes yet more corner cases after the above 2 fixes. our clip cache tracking code seems to be broken somewhere and not updating - at least when events are processed so i did ti the slightly slower way and recursed through clippers to figure it out in this path. it all works now it seems but it's got a small speed hit. better be right than a little faster. @fix --- src/lib/evas/canvas/evas_events.c | 149 ++++++++++++++++++++---- src/lib/evas/canvas/evas_object_smart.c | 85 +++++++------- src/lib/evas/include/evas_inline.x | 3 +- 3 files changed, 166 insertions(+), 71 deletions(-) diff --git a/src/lib/evas/canvas/evas_events.c b/src/lib/evas/canvas/evas_events.c index e94321de52..0d3c356729 100644 --- a/src/lib/evas/canvas/evas_events.c +++ b/src/lib/evas/canvas/evas_events.c @@ -143,6 +143,34 @@ _efl_event_desc_get(Evas_Callback_Type type) # define D(...) do { } while (0) #endif +#ifdef DDD_DO +static void +walk_clippers_print(int spaces, Evas_Object_Protected_Data *obj) +{ + int i; + spaces++; + DDD("<<< CLIP %p c[%6i %6i %6ix%6i] c[%6i %6i %6ix%6i]\n", + obj->object, + obj->cur->geometry.x, obj->cur->geometry.y, + obj->cur->geometry.w, obj->cur->geometry.h, + obj->cur->cache.clip.x, obj->cur->cache.clip.y, + obj->cur->cache.clip.w, obj->cur->cache.clip.h + ); + if (obj->cur->clipper) walk_clippers_print(spaces, obj->cur->clipper); + spaces--; +} +#endif + +static void +clip_calc(Evas_Object_Protected_Data *obj, Evas_Coord_Rectangle *c) +{ + if (!obj) return; + RECTS_CLIP_TO_RECT(c->x, c->y, c->w, c->h, + obj->cur->geometry.x, obj->cur->geometry.y, + obj->cur->geometry.w, obj->cur->geometry.h); + clip_calc(obj->cur->clipper, c); +} + static Eina_List * _evas_event_object_list_raw_in_get(Evas *eo_e, Eina_List *in, const Eina_Inlist *list, Evas_Object *stop, @@ -150,6 +178,7 @@ _evas_event_object_list_raw_in_get(Evas *eo_e, Eina_List *in, { Evas_Object *eo_obj; Evas_Object_Protected_Data *obj = NULL; + Evas_Coord_Rectangle c; int inside; #ifdef DDD_DO @@ -171,37 +200,107 @@ _evas_event_object_list_raw_in_get(Evas *eo_e, Eina_List *in, *no_rep = 1; #ifdef DDD_DO spaces--; -#endif DDD("***** NO REP - STOP *****\n"); +#endif return in; } - - evas_object_clip_recalc(obj); - if ((!RECTS_INTERSECT(x, y, 1, 1, - obj->cur->cache.clip.x, - obj->cur->cache.clip.y, - obj->cur->cache.clip.w, - obj->cur->cache.clip.h))) + if (!obj->cur->visible) continue; + // XXX: this below DYNAMICALLY calculates the current clip rect + // by walking clippers to each parent clipper until there are + // no more of them. this is a necessary hack because cache.clip + // cooreds are broken. somewhere along the way in the past few years + // someone has forgotten to flag them as dirty and update them + // so a clicp recalce caqn work... somewhere. maybe a prexy or map fix + // or an optimization. finding this is really hard, so i'm going + // for plan b and doing this on the fly. it's only for event or + // callback handling so its a small percentage of the time, but + // it's better that we get this right + if (obj->is_smart) { - DDD("___ %p g[%6i %6i %6ix%6i] c[%6i %6i %6ix%6i] %s\n", - obj->object, - obj->cur->geometry.x, obj->cur->geometry.y, - obj->cur->geometry.w, obj->cur->geometry.h, - obj->cur->cache.clip.x, obj->cur->cache.clip.y, - obj->cur->cache.clip.w, obj->cur->cache.clip.h, - obj->type); - continue; + Evas_Coord_Rectangle bounding_box = { 0, 0, 0, 0 }; + + evas_object_smart_bounding_box_update(eo_obj, obj); + evas_object_smart_bounding_box_get(obj->object, &bounding_box, NULL); + c = bounding_box; } else { - DDD("OBJ %p g[%6i %6i %6ix%6i] c[%6i %6i %6ix%6i] %s\n", - obj->object, - obj->cur->geometry.x, obj->cur->geometry.y, - obj->cur->geometry.w, obj->cur->geometry.h, - obj->cur->cache.clip.x, obj->cur->cache.clip.y, - obj->cur->cache.clip.w, obj->cur->cache.clip.h, - obj->type); + if (obj->clip.clipees) continue; + c = obj->cur->geometry; } + clip_calc(obj->cur->clipper, &c); + // only worry about objects that intersect INCLUDING clippint + if ((!RECTS_INTERSECT(x, y, 1, 1, c.x, c.y, c.w, c.h))) + { +#ifdef DDD_DO + if (obj->is_smart) + { + Evas_Coord_Rectangle bounding_box = { 0, 0, 0, 0 }; + + evas_object_smart_bounding_box_get(obj->object, &bounding_box, NULL); + DDD("___ %p g[%6i %6i %6ix%6i] c[%6i %6i %6ix%6i] b[%6i %6i %6ix%6i] %s\n", + obj->object, + obj->cur->geometry.x, obj->cur->geometry.y, + obj->cur->geometry.w, obj->cur->geometry.h, + obj->cur->cache.clip.x, obj->cur->cache.clip.y, + obj->cur->cache.clip.w, obj->cur->cache.clip.h, + bounding_box.x, bounding_box.y, + bounding_box.w, bounding_box.h, + obj->type); + } + else + { + DDD("___ %p g[%6i %6i %6ix%6i] c[%6i %6i %6ix%6i] %s\n", + obj->object, + obj->cur->geometry.x, obj->cur->geometry.y, + obj->cur->geometry.w, obj->cur->geometry.h, + obj->cur->cache.clip.x, obj->cur->cache.clip.y, + obj->cur->cache.clip.w, obj->cur->cache.clip.h, + obj->type); + } + if (!strcmp(obj->type, "e_layout")) + { + if (obj->cur->clipper) + walk_clippers_print(spaces, obj->cur->clipper); + } +#endif + continue; + } +#ifdef DDD_DO + else + { + if (obj->is_smart) + { + Evas_Coord_Rectangle bounding_box = { 0, 0, 0, 0 }; + + evas_object_smart_bounding_box_get(obj->object, &bounding_box, NULL); + DDD("OBJ %p g[%6i %6i %6ix%6i] c[%6i %6i %6ix%6i] b[%6i %6i %6ix%6i] %s\n", + obj->object, + obj->cur->geometry.x, obj->cur->geometry.y, + obj->cur->geometry.w, obj->cur->geometry.h, + obj->cur->cache.clip.x, obj->cur->cache.clip.y, + obj->cur->cache.clip.w, obj->cur->cache.clip.h, + bounding_box.x, bounding_box.y, + bounding_box.w, bounding_box.h, + obj->type); + } + else + { + DDD("OBJ %p g[%6i %6i %6ix%6i] c[%6i %6i %6ix%6i] %s\n", + obj->object, + obj->cur->geometry.x, obj->cur->geometry.y, + obj->cur->geometry.w, obj->cur->geometry.h, + obj->cur->cache.clip.x, obj->cur->cache.clip.y, + obj->cur->cache.clip.w, obj->cur->cache.clip.h, + obj->type); + } +// if (!strcmp(obj->type, "e_layout")) + { + if (obj->cur->clipper) + walk_clippers_print(spaces, obj->cur->clipper); + } + } +#endif if (!source) { @@ -275,8 +374,8 @@ _evas_event_object_list_raw_in_get(Evas *eo_e, Eina_List *in, *no_rep = 1; #ifdef DDD_DO spaces--; -#endif DDD("***** NO REP1 *****\n"); +#endif return in; } } @@ -315,8 +414,8 @@ _evas_event_object_list_raw_in_get(Evas *eo_e, Eina_List *in, *no_rep = 1; #ifdef DDD_DO spaces--; -#endif DDD("***** NO REP2 *****\n"); +#endif return in; } } diff --git a/src/lib/evas/canvas/evas_object_smart.c b/src/lib/evas/canvas/evas_object_smart.c index cabdaf26bc..40c3ac21b1 100644 --- a/src/lib/evas/canvas/evas_object_smart.c +++ b/src/lib/evas/canvas/evas_object_smart.c @@ -1371,6 +1371,11 @@ evas_object_smart_need_bounding_box_update(Evas_Object *eo_obj, Evas_Smart_Data evas_object_async_block(obj); if (o->update_boundingbox_needed) return; o->update_boundingbox_needed = EINA_TRUE; + EINA_COW_STATE_WRITE_BEGIN(obj, state_write, cur) + { + state_write->cache.clip.dirty = EINA_TRUE; + } + EINA_COW_STATE_WRITE_END(obj, state_write, cur); if (obj->smart.parent) evas_object_smart_need_bounding_box_update(obj->smart.parent, @@ -1384,10 +1389,12 @@ evas_object_smart_bounding_box_update(Evas_Object *eo_obj, Evas_Object_Protected Evas_Smart_Data *os; Eina_Inlist *list; Evas_Object_Protected_Data *o; - Evas_Coord minx; - Evas_Coord miny; - Evas_Coord maxw = 0; - Evas_Coord maxh = 0; + Evas_Coord minx = 0x7fffffff; + Evas_Coord miny = 0x7fffffff; + Evas_Coord maxx = 0x80000000; + Evas_Coord maxy = 0x80000000; + Evas_Coord tx1, ty1, tx2, ty2; + Eina_Bool none = EINA_TRUE; MAGIC_CHECK(eo_obj, Evas_Object, MAGIC_OBJ); return; @@ -1398,70 +1405,60 @@ evas_object_smart_bounding_box_update(Evas_Object *eo_obj, Evas_Object_Protected if (!os->update_boundingbox_needed) return; os->update_boundingbox_needed = EINA_FALSE; - evas_object_clip_dirty(eo_obj, obj); - if (obj->cur->clipper) evas_object_clip_recalc(obj->cur->clipper); - - minx = obj->layer->evas->output.w; - miny = obj->layer->evas->output.h; list = os->contained; EINA_INLIST_FOREACH(list, o) { - Evas_Coord tx; - Evas_Coord ty; - Evas_Coord tw; - Evas_Coord th; - if (o == obj) continue ; if (o->clip.clipees || o->is_static_clip) continue ; if (!o->cur->visible) continue; + none = EINA_FALSE; + if (o->is_smart) { Evas_Smart_Data *s = eo_data_scope_get(o->object, MY_CLASS); evas_object_smart_bounding_box_update(o->object, o); - tx = s->cur.bounding_box.x; - ty = s->cur.bounding_box.y; - tw = tx + s->cur.bounding_box.w; - th = ty + s->cur.bounding_box.h; + tx1 = s->cur.bounding_box.x; + ty1 = s->cur.bounding_box.y; + tx2 = tx1 + s->cur.bounding_box.w; + ty2 = ty1 + s->cur.bounding_box.h; } else { - tx = o->cur->geometry.x; - ty = o->cur->geometry.y; - tw = tx + o->cur->geometry.w; - th = ty + o->cur->geometry.h; + tx1 = o->cur->geometry.x; + ty1 = o->cur->geometry.y; + tx2 = tx1 + o->cur->geometry.w; + ty2 = ty1 + o->cur->geometry.h; } - if (tx < minx) minx = tx; - if (ty < miny) miny = ty; - if (tw > maxw) maxw = tw; - if (th > maxh) maxh = th; + if (tx1 < minx) minx = tx1; + if (ty1 < miny) miny = ty1; + if (tx2 > maxx) maxx = tx2; + if (ty2 > maxy) maxy = ty2; + } + if (none) + { + minx = obj->cur->geometry.x; + miny = obj->cur->geometry.y; + maxx = obj->cur->geometry.x + obj->cur->geometry.w; + maxy = obj->cur->geometry.y + obj->cur->geometry.h; } - if (minx != os->cur.bounding_box.x) - { - os->cur.bounding_box.w += os->cur.bounding_box.x - minx; - os->cur.bounding_box.x = minx; - } + os->cur.bounding_box.x = minx; + os->cur.bounding_box.y = miny; + os->cur.bounding_box.w = maxx - minx; + os->cur.bounding_box.h = maxy - miny; - if (miny != os->cur.bounding_box.y) + EINA_COW_STATE_WRITE_BEGIN(obj, state_write, cur) { - os->cur.bounding_box.h += os->cur.bounding_box.y - miny; - os->cur.bounding_box.y = miny; - } - - if (maxw != os->cur.bounding_box.x + os->cur.bounding_box.w) - { - os->cur.bounding_box.w = maxw - os->cur.bounding_box.x; - } - - if (maxh != os->cur.bounding_box.y + os->cur.bounding_box.h) - { - os->cur.bounding_box.h = maxh - os->cur.bounding_box.y; + state_write->cache.clip.dirty = EINA_TRUE; } + EINA_COW_STATE_WRITE_END(obj, state_write, cur); + evas_object_clip_recalc(obj); + if (obj->cur->clipper) evas_object_clip_recalc(obj->cur->clipper); } /* all nice and private */ diff --git a/src/lib/evas/include/evas_inline.x b/src/lib/evas/include/evas_inline.x index ff6a95df47..6255614c81 100644 --- a/src/lib/evas/include/evas_inline.x +++ b/src/lib/evas/include/evas_inline.x @@ -309,8 +309,7 @@ evas_object_clip_recalc(Evas_Object_Protected_Data *obj) if (clipper) { // this causes problems... hmmm ????? - if (clipper->cur->cache.clip.dirty) - evas_object_clip_recalc(clipper); + evas_object_clip_recalc(clipper); // I don't know why this test was here in the first place. As I have // no issue showing up due to this, I keep it and move color out of it.