Revert "Revert "Evas clip: Fix rare crash in _render_pre_clipper_change"" 51/82551/2
authorShinwoo Kim <cinoo.kim@samsung.com>
Thu, 4 Aug 2016 04:31:51 +0000 (13:31 +0900)
committerGerrit Code Review <gerrit@review.vlan103.tizen.org>
Mon, 26 Sep 2016 08:22:34 +0000 (01:22 -0700)
This reverts commit 3a366c6b09971daeb5f184a2ebc1e2ed776fd55e.

Change-Id: Ie12b10cf932a10cf4a69f9ae1c466ec5072ef504

src/lib/evas/canvas/evas_clip.c
src/lib/evas/canvas/evas_object_main.c
src/lib/evas/include/evas_private.h

index 874beb8..c7767db 100644 (file)
@@ -213,6 +213,8 @@ _evas_object_clip_mask_unset(Evas_Object_Protected_Data *obj)
 extern const char *o_rect_type;
 extern const char *o_image_type;
 
+static Eina_Bool _clipper_del_cb(void *data, Eo *eo_clip, const Eo_Event_Description *desc EINA_UNUSED, void *info EINA_UNUSED);
+
 EOLIAN void
 _evas_object_clip_set(Eo *eo_obj, Evas_Object_Protected_Data *obj, Evas_Object *eo_clip)
 {
@@ -281,6 +283,8 @@ _evas_object_clip_set(Eo *eo_obj, Evas_Object_Protected_Data *obj, Evas_Object *
      }
    if (obj->cur->clipper)
      {
+        Evas_Object_Protected_Data *old_clip = obj->cur->clipper;
+
        /* unclip */
         obj->cur->clipper->clip.cache_clipees_answer = eina_list_free(obj->cur->clipper->clip.cache_clipees_answer);
         obj->cur->clipper->clip.clipees = eina_list_remove(obj->cur->clipper->clip.clipees, obj);
@@ -320,10 +324,10 @@ _evas_object_clip_set(Eo *eo_obj, Evas_Object_Protected_Data *obj, Evas_Object *
         evas_object_change(eo_obj, obj);
 
         EINA_COW_STATE_WRITE_BEGIN(obj, state_write, cur)
-          {
-             state_write->clipper = NULL;
-          }
+          state_write->clipper = NULL;
         EINA_COW_STATE_WRITE_END(obj, state_write, cur);
+        if (obj->prev->clipper != old_clip)
+          eo_do(old_clip->object, eo_event_callback_del(EO_BASE_EVENT_DEL, _clipper_del_cb, eo_obj));
      }
 
    /* image object clipper */
@@ -350,11 +354,12 @@ _evas_object_clip_set(Eo *eo_obj, Evas_Object_Protected_Data *obj, Evas_Object *
                                   clip->cur->geometry.w, clip->cur->geometry.h);
  */
      }
+
    EINA_COW_STATE_WRITE_BEGIN(obj, state_write, cur)
-     {
-        state_write->clipper = clip;
-     }
+     state_write->clipper = clip;
    EINA_COW_STATE_WRITE_END(obj, state_write, cur);
+   if (obj->prev->clipper != clip)
+     eo_do(clip->object, eo_event_callback_add(EO_BASE_EVENT_DEL, _clipper_del_cb, eo_obj));
 
    clip->clip.cache_clipees_answer = eina_list_free(clip->clip.cache_clipees_answer);
    clip->clip.clipees = eina_list_append(clip->clip.clipees, obj);
@@ -401,7 +406,6 @@ EOLIAN void
 _evas_object_clip_unset(Eo *eo_obj, Evas_Object_Protected_Data *obj)
 {
    if (!obj->cur->clipper) return;
-
    evas_object_async_block(obj);
    obj->clip.cache_clipees_answer = eina_list_free(obj->clip.cache_clipees_answer);
 
@@ -413,6 +417,8 @@ _evas_object_clip_unset(Eo *eo_obj, Evas_Object_Protected_Data *obj)
      }
    if (obj->cur->clipper)
      {
+        Evas_Object_Protected_Data *old_clip = obj->cur->clipper;
+
         obj->cur->clipper->clip.clipees = eina_list_remove(obj->cur->clipper->clip.clipees, obj);
         if (!obj->cur->clipper->clip.clipees)
           {
@@ -445,12 +451,13 @@ _evas_object_clip_unset(Eo *eo_obj, Evas_Object_Protected_Data *obj)
              _evas_object_clip_mask_unset(obj->cur->clipper);
           }
        evas_object_change(obj->cur->clipper->object, obj->cur->clipper);
+
+        EINA_COW_STATE_WRITE_BEGIN(obj, state_write, cur)
+          state_write->clipper = NULL;
+        EINA_COW_STATE_WRITE_END(obj, state_write, cur);
+        if (obj->prev->clipper != old_clip)
+          eo_do(old_clip->object, eo_event_callback_del(EO_BASE_EVENT_DEL, _clipper_del_cb, eo_obj));
      }
-   EINA_COW_STATE_WRITE_BEGIN(obj, state_write, cur)
-     {
-        state_write->clipper = NULL;
-     }
-   EINA_COW_STATE_WRITE_END(obj, state_write, cur);
 
    evas_object_change(eo_obj, obj);
    evas_object_clip_dirty(eo_obj, obj);
@@ -470,6 +477,43 @@ _evas_object_clip_unset(Eo *eo_obj, Evas_Object_Protected_Data *obj)
    evas_object_clip_across_check(eo_obj, obj);
 }
 
+static Eina_Bool
+_clipper_del_cb(void *data, Eo *eo_clip, const Eo_Event_Description *desc EINA_UNUSED, void *info EINA_UNUSED)
+{
+   Evas_Object *eo_obj = data;
+   Evas_Object_Protected_Data *obj = eo_data_scope_get(eo_obj, EVAS_OBJECT_CLASS);
+
+   if (!obj) return EO_CALLBACK_CONTINUE;
+
+   _evas_object_clip_unset(eo_obj, obj);
+   if (obj->prev->clipper && (obj->prev->clipper->object == eo_clip))
+     {
+        // not removing cb since it's the del cb... it can't be called again!
+        EINA_COW_STATE_WRITE_BEGIN(obj, state_write, prev)
+          state_write->clipper = NULL;
+        EINA_COW_STATE_WRITE_END(obj, state_write, prev);
+     }
+
+   return EO_CALLBACK_CONTINUE;
+}
+
+void
+_evas_object_clip_prev_reset(Evas_Object_Protected_Data *obj, Eina_Bool cur_prev)
+{
+   if (obj->prev->clipper)
+     {
+        Evas_Object_Protected_Data *clip = obj->prev->clipper;
+        if (!cur_prev)
+          {
+             EINA_COW_STATE_WRITE_BEGIN(obj->prev->clipper, state_write, prev)
+               state_write->clipper = NULL;
+             EINA_COW_STATE_WRITE_END(obj->prev->clipper, state_write, prev);
+          }
+        if (clip != obj->cur->clipper)
+          eo_do(clip->object, eo_event_callback_del(EO_BASE_EVENT_DEL, _clipper_del_cb, obj->object));
+     }
+}
+
 EOLIAN Eina_List *
 _evas_object_clipees_get(Eo *eo_obj EINA_UNUSED, Evas_Object_Protected_Data *obj)
 {
index 1fd2348..9f83689 100644 (file)
@@ -159,6 +159,7 @@ evas_object_cur_prev(Evas_Object *eo_obj)
           map_write->prev = map_write->cur;
         EINA_COW_WRITE_END(evas_object_map_cow, obj->map, map_write);
      }
+   _evas_object_clip_prev_reset(obj, EINA_TRUE);
    eina_cow_memcpy(evas_object_state_cow, (const Eina_Cow_Data **) &obj->prev, obj->cur);
 }
 
@@ -704,13 +705,18 @@ _evas_object_eo_base_destructor(Eo *eo_obj, Evas_Object_Protected_Data *obj)
         goto end;
      }
    evas_object_grabs_cleanup(eo_obj, obj);
-   /* "while" should be used for null check of obj->clip.clipees,
-      because evas_objct_clip_unset can set null to obj->clip.clipees */
-   while (obj->clip.clipees)
+   if (obj->clip.clipees)
      {
-        Evas_Object_Protected_Data *tmp;
-        tmp = eina_list_data_get(obj->clip.clipees);
-        evas_object_clip_unset(tmp->object);
+        ERR("object %p still has %d clippees after del callback",
+            eo_obj, eina_list_count(obj->clip.clipees));
+        /* "while" should be used for null check of obj->clip.clipees,
+           because evas_objct_clip_unset can set null to obj->clip.clipees */
+        while (obj->clip.clipees)
+          {
+             Evas_Object_Protected_Data *tmp;
+             tmp = eina_list_data_get(obj->clip.clipees);
+             evas_object_clip_unset(tmp->object);
+          }
      }
    EINA_LIST_FOREACH_SAFE(obj->proxy->proxies, l, l2, proxy)
      {
@@ -734,6 +740,8 @@ _evas_object_eo_base_destructor(Eo *eo_obj, Evas_Object_Protected_Data *obj)
      }
 
    if (obj->cur->clipper) evas_object_clip_unset(eo_obj);
+   _evas_object_clip_prev_reset(obj, EINA_FALSE);
+
    evas_object_map_set(eo_obj, NULL);
    if (obj->is_smart) evas_object_smart_del(eo_obj);
    _evas_object_event_new();
index bfb450e..3c4e6cf 100755 (executable)
@@ -1675,6 +1675,7 @@ void _above_get(Eo *obj, void *_pd, va_list *list);
 void _below_get(Eo *obj, void *_pd, va_list *list);
 void _smart_move_children_relative(Eo *obj, void *_pd, va_list *list);
 void _smart_clipped_clipper_get(Eo *obj, void *_pd, va_list *list);
+void _evas_object_clip_prev_reset(Evas_Object_Protected_Data *obj, Eina_Bool cur_prev);
 
 void _canvas_event_default_flags_set(Eo *e, void *_pd, va_list *list);
 void _canvas_event_default_flags_get(Eo *e, void *_pd, va_list *list);