xdg_shell_v6: Do not issue a protocol error 25/302225/1
authorSeunghun Lee <shiin.lee@samsung.com>
Mon, 4 Dec 2023 01:44:06 +0000 (10:44 +0900)
committerTizen Window System <tizen.windowsystem@gmail.com>
Mon, 4 Dec 2023 08:31:31 +0000 (17:31 +0900)
The libds will issue a protocol error for any client that attempts to
request wl_surface.commit after the xdg_toplevel_v6 resource has been
destroyed, but xdg_surface_v6 resource still alive.

The purpose of this commit is to prevent it from happening by setting
ds_xdg_surface_v6->role to DS_XDG_SURFACE_V6_ROLE_TOPLEVEL to fool libds
implementation when xdg_toplevel_v6 resource is destroyed.

Change-Id: I0546e38513f19bbaf1be65fd2b8f90189c682cdf

src/bin/e_xdg_shell_v6.c

index ab1c5c0..21d020b 100644 (file)
@@ -29,6 +29,8 @@ struct _E_Xdg_Toplevel_V6
    struct ds_xdg_toplevel_v6 *ds_toplevel;
    E_Client *ec;
 
+   struct wl_resource *xdg_surface_resource;
+
    struct wl_listener set_parent;
    struct wl_listener set_title;
    struct wl_listener set_app_id;
@@ -41,6 +43,8 @@ struct _E_Xdg_Toplevel_V6
    struct wl_listener configure;
    struct wl_listener ping_timeout;
    struct wl_listener surface_commit;
+   struct wl_listener resource_destroy;
+   struct wl_listener xdg_surface_resource_destroy;
 };
 
 static void _e_xdg_shell_v6_cb_destroy(struct wl_listener *listener, void *data);
@@ -721,6 +725,53 @@ _e_xdg_toplevel_v6_finish(E_Xdg_Toplevel_V6 *toplevel)
 }
 
 static void
+_e_xdg_toplevel_v6_cb_resource_destroy(struct wl_listener *listener, void *data)
+{
+   E_Xdg_Toplevel_V6 *toplevel;
+   struct ds_xdg_surface_v6 *ds_xdg_surface;
+
+   toplevel = wl_container_of(listener, toplevel, resource_destroy);
+   ds_xdg_surface = ds_xdg_surface_v6_from_resource(toplevel->xdg_surface_resource);
+   if (ds_xdg_surface)
+     ds_xdg_surface->role = DS_XDG_SURFACE_V6_ROLE_TOPLEVEL;
+
+   wl_list_remove(&toplevel->resource_destroy.link);
+   wl_list_init(&toplevel->resource_destroy.link);
+}
+
+static void
+_e_xdg_toplevel_v6_cb_xdg_surface_resource_destroy(struct wl_listener *listener, void *data)
+{
+   E_Xdg_Toplevel_V6 *toplevel;
+
+   toplevel = wl_container_of(listener, toplevel, xdg_surface_resource_destroy);
+   wl_list_remove(&toplevel->resource_destroy.link);
+   wl_list_remove(&toplevel->xdg_surface_resource_destroy.link);
+   free(toplevel);
+}
+
+/*
+ * FIXME HACK
+ * The libds will issue a protocol error for any client that attempts to
+ * request wl_surface.commit after the xdg_toplevel_v6 resource has been
+ * destroyed, but xdg_surface_v6 resource still alive.
+ * The purpose of this function is to prevent it from happening by setting
+ * ds_xdg_surface_v6->role to DS_XDG_SURFACE_V6_ROLE_TOPLEVEL to fool libds
+ * implementation when xdg_toplevel_v6 resource is destroyed.
+ */
+static void
+_e_xdg_toplevel_v6_role_keep_handler_init(E_Xdg_Toplevel_V6 *toplevel, struct ds_xdg_surface_v6 *ds_xdg_surface)
+{
+   toplevel->xdg_surface_resource = ds_xdg_surface->resource;
+
+   toplevel->xdg_surface_resource_destroy.notify = _e_xdg_toplevel_v6_cb_xdg_surface_resource_destroy;
+   wl_resource_add_destroy_listener(ds_xdg_surface->resource, &toplevel->xdg_surface_resource_destroy);
+
+   toplevel->resource_destroy.notify = _e_xdg_toplevel_v6_cb_resource_destroy;
+   wl_resource_add_destroy_listener(ds_xdg_surface->toplevel->resource, &toplevel->resource_destroy);
+}
+
+static void
 _e_xdg_toplevel_v6_add(struct ds_xdg_surface_v6 *ds_xdg_surface)
 {
    E_Xdg_Toplevel_V6 *toplevel;
@@ -738,6 +789,7 @@ _e_xdg_toplevel_v6_add(struct ds_xdg_surface_v6 *ds_xdg_surface)
 
    _e_xdg_toplevel_v6_listener_init(toplevel);
    _e_xdg_toplevel_v6_init(toplevel);
+   _e_xdg_toplevel_v6_role_keep_handler_init(toplevel, ds_xdg_surface);
 
    LOG("Created E_Xdg_Toplevel_V6(%p)", toplevel->ec, toplevel);
 }
@@ -753,5 +805,4 @@ _e_xdg_toplevel_v6_cb_xdg_surface_destroy(struct wl_listener *listener, void *da
 
    _e_xdg_toplevel_v6_listener_finish(toplevel);
    _e_xdg_toplevel_v6_finish(toplevel);
-   free(toplevel);
 }