From b8435aab3933d6173fbeb62e0c079d5680e25d53 Mon Sep 17 00:00:00 2001 From: Jason Francis Date: Fri, 28 Jun 2024 22:49:52 +0200 Subject: [PATCH] wayland: Add support for v2 of xdg_foreign protocol --- gdk/wayland/gdkdisplay-wayland.c | 17 +++- gdk/wayland/gdkdisplay-wayland.h | 7 +- gdk/wayland/gdkwindow-wayland.c | 168 +++++++++++++++++++++++-------- gdk/wayland/meson.build | 1 + 4 files changed, 146 insertions(+), 47 deletions(-) diff --git a/gdk/wayland/gdkdisplay-wayland.c b/gdk/wayland/gdkdisplay-wayland.c index 63f26bf769..821242be41 100644 --- a/gdk/wayland/gdkdisplay-wayland.c +++ b/gdk/wayland/gdkdisplay-wayland.c @@ -47,6 +47,7 @@ #include "tablet-unstable-v2-client-protocol.h" #include "xdg-shell-unstable-v6-client-protocol.h" #include "xdg-foreign-unstable-v1-client-protocol.h" +#include "xdg-foreign-unstable-v2-client-protocol.h" #include "server-decoration-client-protocol.h" #ifdef HAVE_TOPLEVEL_STATE_SUSPENDED @@ -493,16 +494,28 @@ gdk_registry_handle_global (void *data, } else if (strcmp (interface, "zxdg_exporter_v1") == 0) { - display_wayland->xdg_exporter = + display_wayland->xdg_exporter_v1 = wl_registry_bind (display_wayland->wl_registry, id, &zxdg_exporter_v1_interface, 1); } else if (strcmp (interface, "zxdg_importer_v1") == 0) { - display_wayland->xdg_importer = + display_wayland->xdg_importer_v1 = wl_registry_bind (display_wayland->wl_registry, id, &zxdg_importer_v1_interface, 1); } + else if (strcmp (interface, "zxdg_exporter_v2") == 0) + { + display_wayland->xdg_exporter_v2 = + wl_registry_bind (display_wayland->wl_registry, id, + &zxdg_exporter_v2_interface, 1); + } + else if (strcmp (interface, "zxdg_importer_v2") == 0) + { + display_wayland->xdg_importer_v2 = + wl_registry_bind (display_wayland->wl_registry, id, + &zxdg_importer_v2_interface, 1); + } else if (strcmp (interface, "zwp_keyboard_shortcuts_inhibit_manager_v1") == 0) { display_wayland->keyboard_shortcuts_inhibit = diff --git a/gdk/wayland/gdkdisplay-wayland.h b/gdk/wayland/gdkdisplay-wayland.h index b91df7668b..eb5e4b3b31 100644 --- a/gdk/wayland/gdkdisplay-wayland.h +++ b/gdk/wayland/gdkdisplay-wayland.h @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -96,8 +97,10 @@ struct _GdkWaylandDisplay struct gtk_primary_selection_device_manager *gtk_primary_selection_manager; struct zwp_primary_selection_device_manager_v1 *zwp_primary_selection_manager_v1; struct zwp_tablet_manager_v2 *tablet_manager; - struct zxdg_exporter_v1 *xdg_exporter; - struct zxdg_importer_v1 *xdg_importer; + struct zxdg_exporter_v1 *xdg_exporter_v1; + struct zxdg_importer_v1 *xdg_importer_v1; + struct zxdg_exporter_v2 *xdg_exporter_v2; + struct zxdg_importer_v2 *xdg_importer_v2; struct zwp_keyboard_shortcuts_inhibit_manager_v1 *keyboard_shortcuts_inhibit; struct org_kde_kwin_server_decoration_manager *server_decoration_manager; struct zxdg_output_manager_v1 *xdg_output_manager; diff --git a/gdk/wayland/gdkwindow-wayland.c b/gdk/wayland/gdkwindow-wayland.c index 7c457dd675..7b24877685 100644 --- a/gdk/wayland/gdkwindow-wayland.c +++ b/gdk/wayland/gdkwindow-wayland.c @@ -133,7 +133,8 @@ struct _GdkWindowImplWayland struct wl_subsurface *wl_subsurface; struct wl_egl_window *egl_window; struct wl_egl_window *dummy_egl_window; - struct zxdg_exported_v1 *xdg_exported; + struct zxdg_exported_v1 *xdg_exported_v1; + struct zxdg_exported_v2 *xdg_exported_v2; struct org_kde_kwin_server_decoration *server_decoration; } display_server; @@ -236,7 +237,8 @@ struct _GdkWindowImplWayland guint idle_source_id; } exported; - struct zxdg_imported_v1 *imported_transient_for; + struct zxdg_imported_v1 *imported_v1_transient_for; + struct zxdg_imported_v2 *imported_v2_transient_for; GHashTable *shortcuts_inhibitors; struct wl_callback *surface_callback; @@ -1323,14 +1325,19 @@ gdk_wayland_window_sync_parent_of_imported (GdkWindow *window) if (!impl->display_server.wl_surface) return; - if (!impl->imported_transient_for) - return; - if (!is_realized_toplevel (window)) return; - zxdg_imported_v1_set_parent_of (impl->imported_transient_for, - impl->display_server.wl_surface); + if (impl->imported_v2_transient_for) + { + zxdg_imported_v2_set_parent_of (impl->imported_v2_transient_for, + impl->display_server.wl_surface); + } + else if (impl->imported_v1_transient_for) + { + zxdg_imported_v1_set_parent_of (impl->imported_v1_transient_for, + impl->display_server.wl_surface); + } } static void @@ -5418,9 +5425,9 @@ invoke_exported_closures (GdkWindow *window) } static void -xdg_exported_handle (void *data, - struct zxdg_exported_v1 *zxdg_exported_v1, - const char *handle) +xdg_exported_v1_handle (void *data, + struct zxdg_exported_v1 *zxdg_exported_v1, + const char *handle) { GdkWindow *window = data; GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl); @@ -5430,8 +5437,20 @@ xdg_exported_handle (void *data, invoke_exported_closures (window); } -static const struct zxdg_exported_v1_listener xdg_exported_listener = { - xdg_exported_handle +static const struct zxdg_exported_v1_listener xdg_exported_v1_listener = { + xdg_exported_v1_handle +}; + +static void +xdg_exported_v2_handle (void *data, + struct zxdg_exported_v2 *zxdg_exported_v2, + const char *handle) +{ + xdg_exported_v1_handle(data, NULL, handle); +} + +static const struct zxdg_exported_v2_listener xdg_exported_v2_listener = { + xdg_exported_v2_handle }; /** @@ -5453,7 +5472,7 @@ gdk_wayland_window_is_exported (GdkWindow *window) { GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl); - return !!impl->display_server.xdg_exported; + return impl->display_server.xdg_exported_v2 || impl->display_server.xdg_exported_v1; } static gboolean @@ -5520,24 +5539,44 @@ gdk_wayland_window_export_handle (GdkWindow *window, impl = GDK_WINDOW_IMPL_WAYLAND (window->impl); display_wayland = GDK_WAYLAND_DISPLAY (display); - if (!display_wayland->xdg_exporter) + if (display_wayland->xdg_exporter_v2) + { + if (!impl->display_server.xdg_exported_v2) + { + struct zxdg_exported_v2 *xdg_exported_v2; + + xdg_exported_v2 = + zxdg_exporter_v2_export_toplevel (display_wayland->xdg_exporter_v2, + impl->display_server.wl_surface); + zxdg_exported_v2_add_listener (xdg_exported_v2, + &xdg_exported_v2_listener, + window); + + impl->display_server.xdg_exported_v2 = xdg_exported_v2; + } + } + else if (display_wayland->xdg_exporter_v1) + { + if (!impl->display_server.xdg_exported_v1) + { + struct zxdg_exported_v1 *xdg_exported_v1; + + xdg_exported_v1 = + zxdg_exporter_v1_export (display_wayland->xdg_exporter_v1, + impl->display_server.wl_surface); + zxdg_exported_v1_add_listener (xdg_exported_v1, + &xdg_exported_v1_listener, + window); + + impl->display_server.xdg_exported_v1 = xdg_exported_v1; + } + } + else { g_warning ("Server is missing xdg_foreign support"); return FALSE; } - if (!impl->display_server.xdg_exported) - { - struct zxdg_exported_v1 *xdg_exported; - - xdg_exported = zxdg_exporter_v1_export (display_wayland->xdg_exporter, - impl->display_server.wl_surface); - zxdg_exported_v1_add_listener (xdg_exported, - &xdg_exported_listener, - window); - - impl->display_server.xdg_exported = xdg_exported; - } closure = g_new0 (ExportedClosure, 1); closure->callback = callback; @@ -5559,8 +5598,16 @@ gdk_wayland_window_unexport (GdkWindow *window) GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl); GList *l; - g_clear_pointer (&impl->display_server.xdg_exported, - zxdg_exported_v1_destroy); + if (impl->display_server.xdg_exported_v2) + { + g_clear_pointer (&impl->display_server.xdg_exported_v2, + zxdg_exported_v2_destroy); + } + else if (impl->display_server.xdg_exported_v1) + { + g_clear_pointer (&impl->display_server.xdg_exported_v1, + zxdg_exported_v1_destroy); + } for (l = impl->exported.closures; l; l = l->next) { @@ -5605,7 +5652,8 @@ gdk_wayland_window_unexport_handle (GdkWindow *window) impl = GDK_WINDOW_IMPL_WAYLAND (window->impl); - g_return_if_fail (impl->display_server.xdg_exported); + g_return_if_fail (impl->display_server.xdg_exported_v2 || + impl->display_server.xdg_exported_v1); impl->exported.export_count--; if (impl->exported.export_count == 0) @@ -5617,20 +5665,40 @@ unset_transient_for_exported (GdkWindow *window) { GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl); - g_clear_pointer (&impl->imported_transient_for, zxdg_imported_v1_destroy); + if (impl->imported_v2_transient_for) + { + g_clear_pointer (&impl->imported_v2_transient_for, + zxdg_imported_v2_destroy); + } + else if (impl->imported_v1_transient_for) + { + g_clear_pointer (&impl->imported_v1_transient_for, + zxdg_imported_v1_destroy); + } } static void -xdg_imported_destroyed (void *data, - struct zxdg_imported_v1 *zxdg_imported_v1) +xdg_imported_v1_destroyed (void *data, + struct zxdg_imported_v1 *zxdg_imported_v1) { GdkWindow *window = data; unset_transient_for_exported (window); } -static const struct zxdg_imported_v1_listener xdg_imported_listener = { - xdg_imported_destroyed, +static const struct zxdg_imported_v1_listener xdg_imported_v1_listener = { + xdg_imported_v1_destroyed, +}; + +static void +xdg_imported_v2_destroyed (void *data, + struct zxdg_imported_v2 *zxdg_imported_v2) +{ + xdg_imported_v1_destroyed (data, NULL); +} + +static const struct zxdg_imported_v2_listener xdg_imported_v2_listener = { + xdg_imported_v2_destroyed, }; /** @@ -5666,20 +5734,34 @@ gdk_wayland_window_set_transient_for_exported (GdkWindow *window, impl = GDK_WINDOW_IMPL_WAYLAND (window->impl); display_wayland = GDK_WAYLAND_DISPLAY (display); - if (!display_wayland->xdg_importer) + if (display_wayland->xdg_importer_v2) + { + gdk_window_set_transient_for (window, NULL); + + impl->imported_v2_transient_for = + zxdg_importer_v2_import_toplevel (display_wayland->xdg_importer_v2, + parent_handle_str); + zxdg_imported_v2_add_listener (impl->imported_v2_transient_for, + &xdg_imported_v2_listener, + window); + } + else if (display_wayland->xdg_importer_v1) + { + gdk_window_set_transient_for (window, NULL); + + impl->imported_v1_transient_for = + zxdg_importer_v1_import (display_wayland->xdg_importer_v1, + parent_handle_str); + zxdg_imported_v1_add_listener (impl->imported_v1_transient_for, + &xdg_imported_v1_listener, + window); + } + else { g_warning ("Server is missing xdg_foreign support"); return FALSE; } - gdk_window_set_transient_for (window, NULL); - - impl->imported_transient_for = - zxdg_importer_v1_import (display_wayland->xdg_importer, parent_handle_str); - zxdg_imported_v1_add_listener (impl->imported_transient_for, - &xdg_imported_listener, - window); - gdk_wayland_window_sync_parent_of_imported (window); return TRUE; diff --git a/gdk/wayland/meson.build b/gdk/wayland/meson.build index ad5dfe5591..af7ea1f698 100644 --- a/gdk/wayland/meson.build +++ b/gdk/wayland/meson.build @@ -53,6 +53,7 @@ proto_sources = [ ['xdg-shell', 'unstable', 'v6', ], ['xdg-shell', 'stable', ], ['xdg-foreign', 'unstable', 'v1', ], + ['xdg-foreign', 'unstable', 'v2', ], ['tablet', 'unstable', 'v2', ], ['keyboard-shortcuts-inhibit', 'unstable', 'v1', ], ['server-decoration', 'private' ],