diff --git a/gdk/wayland/gdkdisplay-wayland.c b/gdk/wayland/gdkdisplay-wayland.c index 4bb247e160..3566d69fbe 100644 --- a/gdk/wayland/gdkdisplay-wayland.c +++ b/gdk/wayland/gdkdisplay-wayland.c @@ -440,6 +440,12 @@ gdk_registry_handle_global (void *data, 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 = + wl_registry_bind (display_wayland->wl_registry, id, + &zxdg_importer_v1_interface, 1); + } else handled = FALSE; diff --git a/gdk/wayland/gdkdisplay-wayland.h b/gdk/wayland/gdkdisplay-wayland.h index f21e8b631b..ace514349d 100644 --- a/gdk/wayland/gdkdisplay-wayland.h +++ b/gdk/wayland/gdkdisplay-wayland.h @@ -76,6 +76,7 @@ struct _GdkWaylandDisplay struct gtk_primary_selection_device_manager *primary_selection_manager; struct zwp_tablet_manager_v2 *tablet_manager; struct zxdg_exporter_v1 *xdg_exporter; + struct zxdg_importer_v1 *xdg_importer; GList *async_roundtrips; diff --git a/gdk/wayland/gdkwaylandwindow.h b/gdk/wayland/gdkwaylandwindow.h index 6c006e80a7..566d40524c 100644 --- a/gdk/wayland/gdkwaylandwindow.h +++ b/gdk/wayland/gdkwaylandwindow.h @@ -73,6 +73,10 @@ gboolean gdk_wayland_window_export_handle (GdkWindow GDK_AVAILABLE_IN_3_22 void gdk_wayland_window_unexport_handle (GdkWindow *window); +GDK_AVAILABLE_IN_3_22 +gboolean gdk_wayland_window_set_transient_for_exported (GdkWindow *window, + char *parent_handle_str); + G_END_DECLS #endif /* __GDK_WAYLAND_WINDOW_H__ */ diff --git a/gdk/wayland/gdkwindow-wayland.c b/gdk/wayland/gdkwindow-wayland.c index fe11d943e0..e8769f7a77 100644 --- a/gdk/wayland/gdkwindow-wayland.c +++ b/gdk/wayland/gdkwindow-wayland.c @@ -203,6 +203,8 @@ struct _GdkWindowImplWayland gpointer user_data; GDestroyNotify destroy_func; } exported; + + struct zxdg_imported_v1 *imported_transient_for; }; struct _GdkWindowImplWaylandClass @@ -224,6 +226,8 @@ static void gdk_wayland_window_sync_margin (GdkWindow *window); static void gdk_wayland_window_sync_input_region (GdkWindow *window); static void gdk_wayland_window_sync_opaque_region (GdkWindow *window); +static void unset_transient_for_exported (GdkWindow *window); + GType _gdk_window_impl_wayland_get_type (void); G_DEFINE_TYPE (GdkWindowImplWayland, _gdk_window_impl_wayland, GDK_TYPE_WINDOW_IMPL) @@ -2321,6 +2325,8 @@ gdk_wayland_window_hide_surface (GdkWindow *window) GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (gdk_window_get_display (window)); GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl); + unset_transient_for_exported (window); + if (impl->display_server.wl_surface) { if (impl->dummy_egl_surface) @@ -2983,6 +2989,8 @@ gdk_wayland_window_set_transient_for (GdkWindow *window, return; } + unset_transient_for_exported (window); + if (impl->display_server.wl_subsurface) unmap_subsurface (window); @@ -3915,3 +3923,65 @@ gdk_wayland_window_unexport_handle (GdkWindow *window) g_clear_pointer (&impl->exported.user_data, impl->exported.destroy_func); } + +static void +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); +} + +static void +xdg_imported_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, +}; + +/** + * gdk_wayland_window_set_transient_for_exported: + * + * Stability: unstable + */ +gboolean +gdk_wayland_window_set_transient_for_exported (GdkWindow *window, + char *parent_handle_str) +{ + GdkWindowImplWayland *impl; + GdkWaylandDisplay *display_wayland; + GdkDisplay *display = gdk_window_get_display (window); + + g_return_val_if_fail (GDK_IS_WAYLAND_WINDOW (window), FALSE); + g_return_val_if_fail (GDK_IS_WAYLAND_DISPLAY (display), FALSE); + + impl = GDK_WINDOW_IMPL_WAYLAND (window->impl); + display_wayland = GDK_WAYLAND_DISPLAY (display); + + g_return_val_if_fail (impl->display_server.xdg_surface, FALSE); + + if (!display_wayland->xdg_importer) + { + 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); + + zxdg_imported_v1_set_parent_of (impl->imported_transient_for, + impl->display_server.wl_surface); + + return TRUE; +}