From af3ceb57551ee410be1641e6c51281d2aef1a978 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Sun, 14 May 2023 17:38:11 -0400 Subject: wayland: Reimplement exporting Change things so that every call to export_handle creates a new handle, and unexport_handle destroys the handle that it is given. --- gdk/wayland/gdktoplevel-wayland.c | 98 ++++++++++++++++++++++++++++++--------- 1 file changed, 75 insertions(+), 23 deletions(-) diff --git a/gdk/wayland/gdktoplevel-wayland.c b/gdk/wayland/gdktoplevel-wayland.c index 459462485a..bd3738ff3d 100644 --- a/gdk/wayland/gdktoplevel-wayland.c +++ b/gdk/wayland/gdktoplevel-wayland.c @@ -54,11 +54,16 @@ static void gdk_wayland_toplevel_sync_parent (GdkWaylandToplevel *to static void gdk_wayland_toplevel_sync_parent_of_imported (GdkWaylandToplevel *toplevel); static void gdk_wayland_surface_create_xdg_toplevel (GdkWaylandToplevel *toplevel); static void gdk_wayland_toplevel_sync_title (GdkWaylandToplevel *toplevel); -static gboolean gdk_wayland_toplevel_is_exported (GdkWaylandToplevel *toplevel); static void unset_transient_for_exported (GdkWaylandToplevel *toplevel); /* {{{ GdkWaylandToplevel definition */ +typedef struct { + struct zxdg_exported_v1 *xdg_exported; + struct zxdg_exported_v2 *xdg_exported_v2; + char *handle; +} GdkWaylandExported; + /** * GdkWaylandToplevel: * @@ -83,8 +88,7 @@ struct _GdkWaylandToplevel GdkWaylandToplevel *transient_for; struct org_kde_kwin_server_decoration *server_decoration; - struct zxdg_exported_v1 *xdg_exported; - struct zxdg_exported_v2 *xdg_exported_v2; + GList *exported; struct { int width; @@ -1274,9 +1278,6 @@ gdk_wayland_toplevel_finalize (GObject *object) display_wayland->toplevels = g_list_remove (display_wayland->toplevels, self); - if (gdk_wayland_toplevel_is_exported (self)) - gdk_wayland_toplevel_unexport_handle (GDK_TOPLEVEL (self)); - g_free (self->application.application_id); g_free (self->application.app_menu_path); g_free (self->application.menubar_path); @@ -1741,8 +1742,12 @@ xdg_exported_handle_v1 (void *data, struct zxdg_exported_v1 *zxdg_exported_v1, const char *handle) { - g_task_return_pointer (G_TASK (data), g_strdup (handle), g_free); - g_object_unref (data); + GTask *task = G_TASK (data); + GdkWaylandExported *exported = (GdkWaylandExported *)g_task_get_task_data (task); + + exported->handle = g_strdup (handle); + g_task_return_pointer (task, g_strdup (handle), g_free); + g_object_unref (task); } static const struct zxdg_exported_v1_listener xdg_exported_listener_v1 = { @@ -1754,8 +1759,12 @@ xdg_exported_handle_v2 (void *data, struct zxdg_exported_v2 *zxdg_exported_v2, const char *handle) { - g_task_return_pointer (G_TASK (data), g_strdup (handle), g_free); - g_object_unref (data); + GTask *task = G_TASK (data); + GdkWaylandExported *exported = (GdkWaylandExported *)g_task_get_task_data (task); + + exported->handle = g_strdup (handle); + g_task_return_pointer (task, g_strdup (handle), g_free); + g_object_unref (task); } static const struct zxdg_exported_v2_listener xdg_exported_listener_v2 = { @@ -1778,19 +1787,27 @@ gdk_wayland_toplevel_real_export_handle (GdkToplevel *toplevel, if (display_wayland->xdg_exporter_v2) { - wayland_toplevel->xdg_exported_v2 = + GdkWaylandExported *exported = g_new0 (GdkWaylandExported, 1); + exported->xdg_exported_v2 = zxdg_exporter_v2_export_toplevel (display_wayland->xdg_exporter_v2, gdk_wayland_surface_get_wl_surface (surface)); - zxdg_exported_v2_add_listener (wayland_toplevel->xdg_exported_v2, + zxdg_exported_v2_add_listener (exported->xdg_exported_v2, &xdg_exported_listener_v2, task); + + wayland_toplevel->exported = g_list_prepend (wayland_toplevel->exported, exported); + g_task_set_task_data (task, exported, NULL); } else if (display_wayland->xdg_exporter) { - wayland_toplevel->xdg_exported = + GdkWaylandExported *exported = g_new0 (GdkWaylandExported, 1); + exported->xdg_exported = zxdg_exporter_v1_export (display_wayland->xdg_exporter, gdk_wayland_surface_get_wl_surface (surface)); - zxdg_exported_v1_add_listener (wayland_toplevel->xdg_exported, + zxdg_exported_v1_add_listener (exported->xdg_exported, &xdg_exported_listener_v1, task); + + wayland_toplevel->exported = g_list_prepend (wayland_toplevel->exported, exported); + g_task_set_task_data (task, exported, NULL); } else { @@ -1808,6 +1825,15 @@ gdk_wayland_toplevel_real_export_handle_finish (GdkToplevel *toplevel, return g_task_propagate_pointer (G_TASK (result), error); } +static void +destroy_exported (GdkWaylandExported *exported) +{ + g_clear_pointer (&exported->handle, g_free); + g_clear_pointer (&exported->xdg_exported_v2, zxdg_exported_v2_destroy); + g_clear_pointer (&exported->xdg_exported, zxdg_exported_v1_destroy); + g_free (exported); +} + static void gdk_wayland_toplevel_real_unexport_handle (GdkToplevel *toplevel, const char *handle) @@ -1815,10 +1841,21 @@ gdk_wayland_toplevel_real_unexport_handle (GdkToplevel *toplevel, GdkWaylandToplevel *wayland_toplevel = GDK_WAYLAND_TOPLEVEL (toplevel); g_return_if_fail (GDK_IS_WAYLAND_TOPLEVEL (toplevel)); - g_return_if_fail (wayland_toplevel->xdg_exported_v2 || wayland_toplevel->xdg_exported); + g_return_if_fail (handle != NULL); + + for (GList *l = wayland_toplevel->exported; l; l = l->next) + { + GdkWaylandExported *exported = l->data; - g_clear_pointer (&wayland_toplevel->xdg_exported_v2, zxdg_exported_v2_destroy); - g_clear_pointer (&wayland_toplevel->xdg_exported, zxdg_exported_v1_destroy); + if (exported->handle && strcmp (exported->handle, handle) == 0) + { + wayland_toplevel->exported = g_list_delete_link (wayland_toplevel->exported, l); + destroy_exported (exported); + return; + } + } + + g_warn_if_reached (); } static gboolean @@ -2253,6 +2290,27 @@ gdk_wayland_toplevel_set_dbus_properties (GdkToplevel *toplevel, void gdk_wayland_toplevel_destroy (GdkToplevel *toplevel) { + GdkWaylandToplevel *self = GDK_WAYLAND_TOPLEVEL (toplevel); + + while (self->exported) + { + GdkWaylandExported *exported = self->exported->data; + self->exported = g_list_delete_link (self->exported, self->exported); + if (exported->handle == NULL) + { + GTask *task; + + if (exported->xdg_exported_v2) + task = G_TASK (wl_proxy_get_user_data ((struct wl_proxy *) exported->xdg_exported_v2)); + else + task = G_TASK (wl_proxy_get_user_data ((struct wl_proxy *) exported->xdg_exported)); + + g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_FAILED, "Surface was destroyed"); + g_object_unref (task); + } + + destroy_exported (exported); + } } /* }}} */ @@ -2397,12 +2455,6 @@ gdk_wayland_toplevel_uninhibit_idle (GdkToplevel *toplevel) * marking surfaces as transient for out-of-process surfaces. */ -static gboolean -gdk_wayland_toplevel_is_exported (GdkWaylandToplevel *toplevel) -{ - return toplevel->xdg_exported != NULL || toplevel->xdg_exported_v2 != NULL; -} - typedef struct { GdkWaylandToplevelExported callback; gpointer user_data; -- cgit v1.2.1