subsurface: Add function e_comp_wl_subsurface_add() 34/261134/10
authorSeunghun Lee <shiin.lee@samsung.com>
Mon, 12 Jul 2021 09:14:04 +0000 (18:14 +0900)
committerSeunghun Lee <shiin.lee@samsung.com>
Wed, 21 Jul 2021 02:20:17 +0000 (02:20 +0000)
The function e_comp_wl_subsurface_create() is deprecated, and
e_comp_wl_subsurface_add() is added instead.
The purpose of this patch is as followed.

1. Some codes for checking for validating subsurface are repeated in
   e_comp_wl_subsurface and e_policy_wl.
   This is to remove the duplication through gathering duplicated check
   codes into the function.

2. Using suffix 'add' is better than 'create'.
   The 'create' implies it returns an object which later has to be
   destroyed, the 'add', on the other hand, also can be used for
   returning boolean value.

Change-Id: Ieeed62e87a502d0955378ecb8e37779ae732f9d5

src/bin/e_comp_wl_subsurface.c
src/bin/e_comp_wl_subsurface.h
src/bin/e_policy_wl.c

index c40e9612f04667732e7d7293a241a94de0fad06c..71a00bf9e5a8c9ec181c171d107256436fb54578 100644 (file)
@@ -40,7 +40,7 @@ static void       _e_comp_wl_subsurface_place_above(E_Client *parent, E_Client *
 static void       _e_comp_wl_subsurface_place_below(E_Client *parent, E_Client *subc, E_Client *below);
 static void       _e_comp_wl_subsurface_stack_update(E_Client *ec);
 
-static E_Subsurface  *_e_comp_wl_subsurface_create(void);
+static E_Subsurface  *_e_comp_wl_subsurface_create(struct wl_resource *resource, E_Client *ec, E_Client *epc, E_Client *offscreen_parent);
 static void           _e_comp_wl_subsurface_destroy(E_Subsurface *sub);
 static void           _e_comp_wl_subsurface_ec_link(E_Subsurface *sub, E_Client *ec);
 static void           _e_comp_wl_subsurface_parent_link(E_Subsurface *sub, E_Client *parent);
@@ -736,48 +736,16 @@ _e_comp_wl_subcompositor_cb_destroy(struct wl_client *client EINA_UNUSED, struct
 }
 
 static void
-_e_comp_wl_subcompositor_cb_subsurface_get(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, uint32_t id, struct wl_resource *surface_resource, struct wl_resource *parent_resource)
+_e_comp_wl_subcompositor_cb_subsurface_get(struct wl_client *client, struct wl_resource *resource, uint32_t id, struct wl_resource *surface, struct wl_resource *parent_surface)
 {
-   E_Client *ec, *epc = NULL;
-   static const char where[] = "get_subsurface: wl_subsurface@";
-
-   if (!(ec = wl_resource_get_user_data(surface_resource))) return;
-   if (!(epc = wl_resource_get_user_data(parent_resource))) return;
+   Eina_Bool res;
 
-   if (ec == epc)
-     {
-        wl_resource_post_error(resource, WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE,
-                               "%s%d: wl_surface@%d cannot be its own parent",
-                               where, id, wl_resource_get_id(surface_resource));
-        return;
-     }
-
-   if (e_object_is_del(E_OBJECT(ec))) return;
-   if (e_object_is_del(E_OBJECT(epc))) return;
-
-   /* check if this surface is already a sub-surface */
-   if ((ec->comp_data) && (ec->comp_data->sub.data))
-     {
-        wl_resource_post_error(resource,
-                               WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE,
-                               "%s%d: wl_surface@%d is already a sub-surface",
-                               where, id, wl_resource_get_id(surface_resource));
-        return;
-     }
-
-   /* try to create a new subsurface */
-   if (!e_comp_wl_subsurface_create(ec, epc, id, surface_resource))
+   res = e_comp_wl_subsurface_add(client, resource, id,
+                                  surface, parent_surface);
+   if (!res)
      {
-        if (_e_comp_wl_subsurface_circular_reference_check(ec, epc))
-          {
-             wl_resource_post_error(resource,
-                                    WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE,
-                                    "%s%d: wl_surface@%d is an ancestor of parent",
-                                    where, id, wl_resource_get_id(surface_resource));
-          }
-
-        ERR("Failed to create subsurface for surface %d",
-            wl_resource_get_id(surface_resource));
+        ERR("Failed to add subsurface for surface %d",
+            wl_resource_get_id(surface));
      }
 }
 
@@ -1020,7 +988,7 @@ e_comp_wl_subsurface_create(E_Client *ec, E_Client *epc, uint32_t id, struct wl_
     * to not post error to wl_client. */
    e_comp_wl_surface_role_set(ec, e_comp_wl_subsurface_role_name, NULL, 0);
 
-   sub = _e_comp_wl_subsurface_create();
+   sub = E_NEW(E_Subsurface, 1);
    if (!sub)
      {
         ERR("Could not allocate space for E_Subsurface");
@@ -1029,6 +997,8 @@ e_comp_wl_subsurface_create(E_Client *ec, E_Client *epc, uint32_t id, struct wl_
      }
 
    sub->base.resource = res;
+   sub->base.cached_buffer_ref.buffer = NULL;
+   sub->base.synchronized = EINA_TRUE;
 
   /* set resource implementation */
    wl_resource_set_implementation(res, &_e_subsurface_interface, sub,
@@ -1041,15 +1011,109 @@ e_comp_wl_subsurface_create(E_Client *ec, E_Client *epc, uint32_t id, struct wl_
    if (offscreen_parent)
      ELOGF("COMP", "         |offscreen_parent:%p", ec, offscreen_parent);
 
-   /* Delete 'below_obj' if it was created before 'E_Client' becomes subsurface.
-    * It's not for subsurface. */
-   E_FREE_FUNC(ec->comp_data->sub.below_obj, evas_object_del);
-
    e_comp_wl_hook_call(E_COMP_WL_HOOK_SUBSURFACE_CREATE, ec);
 
    return EINA_TRUE;
 }
 
+EINTERN Eina_Bool
+e_comp_wl_subsurface_add(struct wl_client *client, struct wl_resource *resource, uint32_t id, struct wl_resource *surface, struct wl_resource *parent_surface)
+{
+   E_Subsurface *sub;
+   E_Client *ec, *epc = NULL;
+   E_Client *offscreen_parent = NULL;
+   struct wl_resource *subsurf_res;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(client, EINA_FALSE);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(resource, EINA_FALSE);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(surface, EINA_FALSE);
+
+   ec = wl_resource_get_user_data(surface);
+
+   if (parent_surface)
+     epc = wl_resource_get_user_data(parent_surface);
+
+   if ((!epc) ||
+       (e_object_is_del(E_OBJECT(epc))))
+     {
+        ELOGF("SUBSURFACE", "Create with invalid parent(%p)", ec, epc);
+        subsurf_res = wl_resource_create(client, &wl_subsurface_interface,
+                                         1, id);
+        if (!subsurf_res)
+          {
+             wl_resource_post_no_memory(resource);
+             return EINA_FALSE;
+          }
+
+        _e_comp_wl_subsurface_invalid_parent_handle(ec, subsurf_res);
+        return EINA_FALSE;
+     }
+
+   if (ec == epc)
+     {
+        wl_resource_post_error(resource, WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE,
+                               "%d: wl_surface@%d cannot be its own parent",
+                               id, wl_resource_get_id(surface));
+        return EINA_FALSE;
+     }
+
+   if (e_comp_wl_subsurface_check(ec))
+     {
+        wl_resource_post_error(resource, WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE,
+                               "%d: wl_surface@%d is already a sub-surface",
+                               id, wl_resource_get_id(surface));
+        return EINA_FALSE;
+     }
+
+   // reparent remote surface provider's subsurfaces
+   if ((epc->comp_data) &&
+       (epc->comp_data->remote_surface.onscreen_parent))
+     {
+        offscreen_parent = epc;
+        epc = epc->comp_data->remote_surface.onscreen_parent;
+     }
+
+   if (_e_comp_wl_subsurface_circular_reference_check(ec, epc))
+     {
+        ERR("Subsurface parent relationship is a cycle : "
+            "[child win : %zx, %s], [parent win : %zx, %s]",
+            e_client_util_win_get(ec), e_client_util_name_get(ec),
+            e_client_util_win_get(epc), e_client_util_name_get(epc));
+        wl_resource_post_error(resource, WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE,
+                               "%d: wl_surface@%d is an ancestor of parent",
+                               id, wl_resource_get_id(surface));
+        return EINA_FALSE;
+     }
+
+   if (!e_comp_wl_surface_role_set(ec, e_comp_wl_subsurface_role_name,
+                                   resource, WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE))
+     {
+        return EINA_FALSE;
+     }
+
+   subsurf_res = wl_resource_create(client, &wl_subsurface_interface, 1, id);
+   if (!subsurf_res)
+     {
+        wl_resource_post_no_memory(resource);
+        return EINA_FALSE;
+     }
+
+   sub = _e_comp_wl_subsurface_create(subsurf_res, ec, epc, offscreen_parent);
+   if (!sub)
+     {
+        wl_resource_destroy(subsurf_res);
+        wl_resource_post_no_memory(resource);
+        return EINA_FALSE;
+     }
+
+   wl_resource_set_implementation(subsurf_res, &_e_subsurface_interface, sub,
+                                  _e_comp_wl_subsurface_cb_resource_destroy);
+
+   ELOGF("SUBSURFACE", "Create with parent(%p)", ec, epc);
+
+   return EINA_TRUE;
+}
+
 EINTERN void
 e_comp_wl_subsurface_parent_commit(E_Client *ec, Eina_Bool parent_synchronized)
 {
@@ -1544,7 +1608,7 @@ _e_comp_wl_subsurface_stack_update(E_Client *ec)
 }
 
 static E_Subsurface *
-_e_comp_wl_subsurface_create(void)
+_e_comp_wl_subsurface_create(struct wl_resource *resource, E_Client *ec, E_Client *epc, E_Client *offscreen_parent)
 {
    E_Subsurface *sub;
 
@@ -1552,8 +1616,17 @@ _e_comp_wl_subsurface_create(void)
    if (!sub)
      return NULL;
 
+   sub->base.resource = resource;
    sub->base.cached_buffer_ref.buffer = NULL;
    sub->base.synchronized = EINA_TRUE;
+   sub->base.remote_surface.offscreen_parent = offscreen_parent;
+   if (offscreen_parent)
+     ELOGF("SUBSURFACE", "         |offscreen_parent:%p", ec, offscreen_parent);
+
+   _e_comp_wl_subsurface_ec_link(sub, ec);
+   _e_comp_wl_subsurface_parent_link(sub, epc);
+
+   e_comp_wl_hook_call(E_COMP_WL_HOOK_SUBSURFACE_CREATE, ec);
 
    return sub;
 }
@@ -1632,6 +1705,10 @@ _e_comp_wl_subsurface_ec_link(E_Subsurface *sub, E_Client *ec)
    ec->new_client = ec->netwm.ping = EINA_TRUE;
    e_comp->new_clients++;
    e_client_unignore(ec);
+
+   /* Delete 'below_obj' if it was created before 'E_Client' becomes subsurface.
+    * It's not for subsurface. */
+   E_FREE_FUNC(ec->comp_data->sub.below_obj, evas_object_del);
 }
 
 static void
index 4ec3c829209929d9b8a421bf06deb745ec95792b..2f87106530b5b8e6ac73ed0a1cc4469708c11d13 100644 (file)
@@ -14,7 +14,8 @@
 EINTERN void          e_comp_wl_subsurface_resource_stand_alone_mode_set(struct wl_resource *subsurface_resource);
 EINTERN void          e_comp_wl_subsurface_resource_place_below_parent(struct wl_resource *subsurface_resource);
 
-E_API Eina_Bool       e_comp_wl_subsurface_create(E_Client *ec, E_Client *epc, uint32_t id, struct wl_resource *surface_resource);
+E_API Eina_Bool       e_comp_wl_subsurface_create(E_Client *ec, E_Client *epc, uint32_t id, struct wl_resource *surface_resource) EINA_DEPRECATED;
+EINTERN Eina_Bool     e_comp_wl_subsurface_add(struct wl_client *client, struct wl_resource *resource, uint32_t id, struct wl_resource *surface, struct wl_resource *parent_surface);
 
 EINTERN Eina_Bool     e_comp_wl_subsurfaces_init(E_Comp_Wl_Data *wl_comp);
 EINTERN void          e_comp_wl_subsurfaces_shutdown(void);
index 3c8f8a85fa48d312fd8210c9c20dfd16fbc18161..8ef066383cd9459978a611581a8b1d54fb112c9f 100644 (file)
@@ -2067,42 +2067,22 @@ _tzpol_iface_cb_subsurface_get(struct wl_client *client, struct wl_resource *res
 {
    E_Client *ec, *epc;
    E_Comp_Wl_Client_Data *cdata;
+   struct wl_resource *parent_surface = NULL;
+   Eina_Bool res;
 
    ELOGF("TZPOL",
          "SUBSURF   |wl_surface@%d|parent_id:%d",
          NULL, wl_resource_get_id(surface), parent_id);
 
    ec = wl_resource_get_user_data(surface);
-   if (!ec)
-     {
-        wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
-                               "tizen_policy failed: wrong wl_surface@%d resource",
-                               wl_resource_get_id(surface));
-        return;
-     }
-
-   if (e_object_is_del(E_OBJECT(ec))) return;
-
-   /* check if this surface is already a sub-surface */
-   if (e_comp_wl_subsurface_check(ec))
-     {
-        wl_resource_post_error(resource,
-                               WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE,
-                               "wl_surface@%d is already a sub-surface",
-                               wl_resource_get_id(surface));
-        return;
-     }
-
    epc = e_pixmap_find_client_by_res_id(parent_id);
 
    /* This check code is for detecting an error case which tries to create
     * sub-surface relationship with invalid parent. */
    if ((epc) &&
        (!e_object_is_del(E_OBJECT(epc))) &&
-       (!epc->comp_data))
-     {
-        /* Another error case is handled by e_comp_wl_subsurface_create()
-         * at the time this code is written. */
+       ((!epc->comp_data) || (!epc->comp_data->wl_surface)))
+   {
         ELOGF("TZPOL", "Parent(%p internal? %s) doesn't have comp_data. "
               "Possibly it's not the surface created by client. "
               "Cannot be the parent of sub-surface.",
@@ -2116,10 +2096,15 @@ _tzpol_iface_cb_subsurface_get(struct wl_client *client, struct wl_resource *res
         return;
      }
 
+   if ((epc) && (epc->comp_data))
+     parent_surface = epc->comp_data->wl_surface;
+
    /* try to create a new subsurface */
-   if (!e_comp_wl_subsurface_create(ec, epc, id, surface))
+   res = e_comp_wl_subsurface_add(client, resource, id, surface,
+                                  parent_surface);
+   if (!res)
      {
-        ERR("Failed to create subsurface for surface@%d", wl_resource_get_id(surface));
+        ERR("Failed to add subsurface for surface@%d", wl_resource_get_id(surface));
         return;
      }