summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2023-05-14 17:38:11 -0400
committerMatthias Clasen <mclasen@redhat.com>2023-05-14 23:49:44 -0400
commitaf3ceb57551ee410be1641e6c51281d2aef1a978 (patch)
treede0e81d710ab5bdeb38687dee7696adb28108658
parent982a696311ed44add2b4a3c54f59a658928fea11 (diff)
downloadgtk+-af3ceb57551ee410be1641e6c51281d2aef1a978.tar.gz
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.
-rw-r--r--gdk/wayland/gdktoplevel-wayland.c98
1 files 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
{
@@ -1809,16 +1826,36 @@ gdk_wayland_toplevel_real_export_handle_finish (GdkToplevel *toplevel,
}
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)
{
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;