raster pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=f6b3c31561276a6c7afc8fb56ae2e5363772782c

commit f6b3c31561276a6c7afc8fb56ae2e5363772782c
Author: Carsten Haitzler (Rasterman) <[email protected]>
Date:   Thu Jul 7 14:10:24 2016 +0900

    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 |  81 +++++++++--------
 src/lib/evas/include/evas_inline.x      |   3 +-
 3 files changed, 164 insertions(+), 69 deletions(-)

diff --git a/src/lib/evas/canvas/evas_events.c 
b/src/lib/evas/canvas/evas_events.c
index e94321d..0d3c356 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)))
-          {
-             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 (!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)
+          {
+             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
+          {
+             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
           {
-             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->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 cabdaf2..40c3ac2 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 (minx != os->cur.bounding_box.x)
+   if (none)
      {
-        os->cur.bounding_box.w += os->cur.bounding_box.x - minx;
-        os->cur.bounding_box.x = minx;
+        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 (miny != os->cur.bounding_box.y)
-     {
-        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;
-     }
+   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 (maxh != os->cur.bounding_box.y + os->cur.bounding_box.h)
+   EINA_COW_STATE_WRITE_BEGIN(obj, state_write, cur)
      {
-        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 ff6a95d..6255614 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.

-- 


Reply via email to