evas event handling3 - fix yet more corner cases for clipped objects

this is a continuation fix from
25d77bc1d2 and
9f0fd66ab8

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
This commit is contained in:
Carsten Haitzler 2016-07-07 14:10:24 +09:00
parent 0fc151cddc
commit f6b3c31561
3 changed files with 166 additions and 71 deletions

View File

@ -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;
}
}

View File

@ -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 */

View File

@ -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.