subsurface: Handles restack event only for topmost parent of sub-surface. 60/246160/3
authorSeunghun Lee <shiin.lee@samsung.com>
Mon, 19 Oct 2020 11:15:23 +0000 (20:15 +0900)
committerSeunghun Lee <shiin.lee@samsung.com>
Tue, 27 Oct 2020 02:32:54 +0000 (11:32 +0900)
This patch removes a handler of restack event in e_comp_wl, and adds it
for topmost parent of sub-surface.
Because it's not necessary to handle restack event for sub-surface.
The reason is as follow.

1. Sub-surface can be re-stacked only by a request from wl_client. In
   other words, it shouldn't be re-stacked by compositor policy.
2. A topmost parent of sub-surface can be re-stacked only by compositor
   policy.

For these reason, it's sufficient for sub-surface implementation to add
a handler of restack event for topmost parent.

Change-Id: I6874425fd864c83039911dcf4ece75e5d2c8a79b

src/bin/e_comp_wl.c
src/bin/e_comp_wl_subsurface.c

index 00847c8..1300ce6 100644 (file)
@@ -697,18 +697,6 @@ _e_comp_wl_touch_cancel(void)
    _e_comp_wl_send_touch_cancel(ec);
 }
 
-static void
-_e_comp_wl_evas_cb_restack(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
-{
-   E_Client *ec = (E_Client *)data;
-
-   if ((!ec) || (!ec->comp_data)) return;
-   if (e_object_is_del(E_OBJECT(ec))) return;
-   if (ec->comp_data->sub.restacking) return;
-
-   e_comp_wl_subsurface_stack_update(ec);
-}
-
 static E_Devicemgr_Input_Device *
 _e_comp_wl_device_last_device_get(Ecore_Device_Class dev_class)
 {
@@ -2069,8 +2057,6 @@ _e_comp_wl_client_evas_init(E_Client *ec)
    evas_object_event_callback_add(ec->frame, EVAS_CALLBACK_SHOW,        _e_comp_wl_evas_cb_show,        ec);
    evas_object_event_callback_add(ec->frame, EVAS_CALLBACK_HIDE,        _e_comp_wl_evas_cb_hide,        ec);
    evas_object_event_callback_add(ec->frame, EVAS_CALLBACK_MOVE,        _e_comp_wl_evas_cb_move,        ec);
-   evas_object_event_callback_add(ec->frame, EVAS_CALLBACK_RESTACK,     _e_comp_wl_evas_cb_restack,     ec);
-
 
    evas_object_event_callback_priority_add(ec->frame, EVAS_CALLBACK_MOUSE_IN,    EVAS_CALLBACK_PRIORITY_AFTER, _e_comp_wl_evas_cb_mouse_in,    ec);
    evas_object_event_callback_priority_add(ec->frame, EVAS_CALLBACK_MOUSE_OUT,   EVAS_CALLBACK_PRIORITY_AFTER, _e_comp_wl_evas_cb_mouse_out,   ec);
index 5728416..ea7b903 100644 (file)
@@ -13,6 +13,10 @@ static void       _e_comp_wl_subsurface_parent_commit(E_Client *ec, Eina_Bool pa
 static Eina_Bool  _e_comp_wl_subsurface_synchronized_get(E_Comp_Wl_Subsurf_Data *sdata);
 static void       _e_comp_wl_subsurface_synchronized_commit(E_Client *ec);
 static void       _e_comp_wl_subsurface_remove_from_parent(E_Client *parent, E_Client *subc);
+static void       _e_comp_wl_subsurface_stack_update(E_Client *ec);
+static Eina_Bool  _e_comp_wl_subsurface_empty_check(E_Client *ec);
+
+static void       _e_comp_wl_subsurface_cb_evas_restack(void *data, Evas *e, Evas_Object *obj, void *event_info);
 
 static void
 _e_comp_wl_subsurface_restack_bg_rectangle(E_Client *ec)
@@ -45,13 +49,13 @@ _e_comp_wl_subsurface_restack(E_Client *ec)
 
    if (!ec || !ec->comp_data || e_object_is_del(E_OBJECT(ec))) return;
 
+   ec->comp_data->sub.restacking = EINA_TRUE;
+
    temp = ec;
    EINA_LIST_FOREACH(ec->comp_data->sub.list, l, subc)
      {
         if (!subc || !subc->comp_data || e_object_is_del(E_OBJECT(subc))) continue;
-        subc->comp_data->sub.restacking = EINA_TRUE;
         e_client_stack_above(subc, temp);
-        subc->comp_data->sub.restacking = EINA_FALSE;
         temp = subc;
      }
 
@@ -59,9 +63,7 @@ _e_comp_wl_subsurface_restack(E_Client *ec)
    EINA_LIST_REVERSE_FOREACH(ec->comp_data->sub.below_list, l, subc)
      {
         if (!subc || !subc->comp_data || e_object_is_del(E_OBJECT(subc))) continue;
-        subc->comp_data->sub.restacking = EINA_TRUE;
         e_client_stack_below(subc, temp);
-        subc->comp_data->sub.restacking = EINA_FALSE;
         temp = subc;
      }
 
@@ -70,6 +72,8 @@ _e_comp_wl_subsurface_restack(E_Client *ec)
 
    EINA_LIST_REVERSE_FOREACH(ec->comp_data->sub.below_list, l, subc)
      _e_comp_wl_subsurface_restack(subc);
+
+   ec->comp_data->sub.restacking = EINA_FALSE;
 }
 
 static void
@@ -855,6 +859,10 @@ _e_comp_wl_subsurface_cb_ec_del(void *data EINA_UNUSED, E_Client *ec)
    ec->comp_data->sub.below_list = NULL;
    _e_comp_wl_surface_sub_list_free(ec->comp_data->sub.below_list_pending);
    ec->comp_data->sub.below_list_pending = NULL;
+
+   evas_object_event_callback_del(ec->frame,
+                                  EVAS_CALLBACK_RESTACK,
+                                  _e_comp_wl_subsurface_cb_evas_restack);
 }
 
 static void
@@ -1032,6 +1040,16 @@ e_comp_wl_subsurface_create(E_Client *ec, E_Client *epc, uint32_t id, struct wl_
    {
        E_Layer layer = e_client_layer_get(epc);
        if (layer > E_LAYER_BOTTOM) e_client_layer_set(ec, layer);
+
+       if ((!_e_comp_wl_subsurface_data_get(epc)) &&
+           (_e_comp_wl_subsurface_empty_check(epc)))
+         {
+            /* Add a callback function for restacking of topmost. */
+            evas_object_event_callback_add(epc->frame,
+                                           EVAS_CALLBACK_RESTACK,
+                                           _e_comp_wl_subsurface_cb_evas_restack,
+                                           epc);
+         }
    }
 
    if (epc->comp_data)
@@ -1068,6 +1086,13 @@ e_comp_wl_subsurface_create(E_Client *ec, E_Client *epc, uint32_t id, struct wl_
     * It's not for subsurface. */
    E_FREE_FUNC(ec->comp_data->sub.below_obj, evas_object_del);
 
+   /* Delete a listener for restack of evas.
+    * There is no need to watch restack of evas for sub-surface because
+    * stacking for sub-surface is happened only by client, not compositor. */
+   evas_object_event_callback_del(ec->frame,
+                                  EVAS_CALLBACK_RESTACK,
+                                  _e_comp_wl_subsurface_cb_evas_restack);
+
    e_comp_wl_hook_call(E_COMP_WL_HOOK_SUBSURFACE_CREATE, ec);
 
    return EINA_TRUE;
@@ -1195,59 +1220,28 @@ e_comp_wl_subsurface_restack_bg_rectangle(E_Client *ec)
 EINTERN void
 e_comp_wl_subsurface_restack(E_Client *ec)
 {
-   EINA_SAFETY_ON_NULL_RETURN(ec);
-
-   _e_comp_wl_subsurface_restack(ec);
-}
-
-E_API void
-e_comp_wl_subsurface_stack_update(E_Client *ec)
-{
    E_Client *topmost;
 
    EINA_SAFETY_ON_NULL_RETURN(ec);
 
-   if (!ec->comp_data) return;
-   if (e_object_is_del(E_OBJECT(ec))) return;
-   if (ec->comp_data->sub.restacking) return;
-
-   /* return if ec isn't both a parent of a subsurface and a subsurface itself */
-   if (!ec->comp_data->sub.list && !ec->comp_data->sub.below_list && !ec->comp_data->sub.data)
+   topmost = e_comp_wl_topmost_parent_get(ec);
+   if (topmost != ec)
      {
-        if (ec->comp_data->sub.below_obj)
-          _e_comp_wl_subsurface_restack_bg_rectangle(ec);
+        ELOGF("SUB-COMP",
+              "WARN: This API is only for topmost parent, not sub-surface.",
+              ec);
         return;
      }
 
-   topmost = e_comp_wl_topmost_parent_get(ec);
-
-   _e_comp_wl_subsurface_restack(topmost);
-   _e_comp_wl_subsurface_restack_bg_rectangle(topmost);
-
-   //To update client stack list
-   if ((ec->comp_data->sub.data) &&
-       (ec->comp_data->sub.data->parent))
-     {
-        E_Client *parent;
-        Evas_Object *o;
+   _e_comp_wl_subsurface_restack(ec);
+}
 
-        parent = ec->comp_data->sub.data->parent;
+E_API void
+e_comp_wl_subsurface_stack_update(E_Client *ec)
+{
+   EINA_SAFETY_ON_NULL_RETURN(ec);
 
-        if ((parent->comp_data->sub.list) &&
-            (eina_list_data_find(parent->comp_data->sub.list, ec)))
-          {
-             //stack above done
-             o = evas_object_below_get(ec->frame);
-             e_comp_object_layer_update(ec->frame, o, NULL);
-          }
-        else if ((parent->comp_data->sub.below_list) &&
-                 (eina_list_data_find(parent->comp_data->sub.below_list, ec)))
-          {
-             //stack below done
-             o = evas_object_above_get(ec->frame);
-             e_comp_object_layer_update(ec->frame, NULL, o);
-          }
-     }
+   _e_comp_wl_subsurface_stack_update(ec);
 }
 
 EINTERN Eina_Bool
@@ -1362,6 +1356,18 @@ _e_comp_wl_subsurface_remove_from_parent(E_Client *parent, E_Client *subc)
       eina_list_remove(parent->comp_data->sub.below_list, subc);
    parent->comp_data->sub.below_list_pending =
       eina_list_remove(parent->comp_data->sub.below_list_pending, subc);
+
+   if ((!_e_comp_wl_subsurface_data_get(parent)) &&
+       (_e_comp_wl_subsurface_empty_check(parent)))
+     {
+        /* No need to watch restack of evas since this surface doesn't have
+         * sub-surface anymore. */
+        evas_object_event_callback_del(parent->frame,
+                                       EVAS_CALLBACK_RESTACK,
+                                       _e_comp_wl_subsurface_cb_evas_restack);
+     }
+
+
 }
 
 static E_Comp_Wl_Subsurf_Data *
@@ -1369,3 +1375,78 @@ _e_comp_wl_subsurface_data_get(E_Client *ec)
 {
    return (ec->comp_data) ? (ec->comp_data->sub.data) : NULL;
 }
+
+static void
+_e_comp_wl_subsurface_stack_update(E_Client *ec)
+{
+   E_Client *topmost;
+
+   if (!ec->comp_data) return;
+   if (e_object_is_del(E_OBJECT(ec))) return;
+   if (ec->comp_data->sub.restacking) return;
+
+   /* return if ec isn't both a parent of a subsurface and a subsurface itself */
+   if (!ec->comp_data->sub.list && !ec->comp_data->sub.below_list && !ec->comp_data->sub.data)
+     {
+        if (ec->comp_data->sub.below_obj)
+          _e_comp_wl_subsurface_restack_bg_rectangle(ec);
+        return;
+     }
+
+   topmost = e_comp_wl_topmost_parent_get(ec);
+
+   _e_comp_wl_subsurface_restack(topmost);
+   _e_comp_wl_subsurface_restack_bg_rectangle(topmost);
+
+   //To update client stack list
+   if ((ec->comp_data->sub.data) &&
+       (ec->comp_data->sub.data->parent))
+     {
+        E_Client *parent;
+        Evas_Object *o;
+
+        parent = ec->comp_data->sub.data->parent;
+
+        if ((parent->comp_data->sub.list) &&
+            (eina_list_data_find(parent->comp_data->sub.list, ec)))
+          {
+             //stack above done
+             o = evas_object_below_get(ec->frame);
+             e_comp_object_layer_update(ec->frame, o, NULL);
+          }
+        else if ((parent->comp_data->sub.below_list) &&
+                 (eina_list_data_find(parent->comp_data->sub.below_list, ec)))
+          {
+             //stack below done
+             o = evas_object_above_get(ec->frame);
+             e_comp_object_layer_update(ec->frame, NULL, o);
+          }
+     }
+}
+
+static void
+_e_comp_wl_subsurface_cb_evas_restack(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
+{
+   E_Client *topmost;
+
+   /* Given data must be a topmost E_Client of subsurfaces. */
+   topmost = data;
+   if (topmost->comp_data->sub.restacking)
+     {
+        ELOGF("SUB-COMP", "A topmost parent is getting restacked", topmost);
+        return;
+     }
+
+   _e_comp_wl_subsurface_stack_update(topmost);
+}
+
+
+static Eina_Bool
+_e_comp_wl_subsurface_empty_check(E_Client *ec)
+{
+   return (!ec->comp_data) ||
+      ((eina_list_count(ec->comp_data->sub.list) == 0) &&
+       (eina_list_count(ec->comp_data->sub.list_pending) == 0) &&
+       (eina_list_count(ec->comp_data->sub.below_list) == 0) &&
+       (eina_list_count(ec->comp_data->sub.below_list_pending) == 0));
+}