From 127d2ac956cec1bb26df7d66f9b0859129a900e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Tue, 12 Jul 2016 11:49:39 +0800 Subject: [PATCH] wayland: Add API for creating exported window handles Using the xdg_foreign protocol, expose a way to get handles to windows that may be shared between processes. https://bugzilla.gnome.org/show_bug.cgi?id=769788 --- configure.ac | 2 +- gdk/wayland/Makefile.am | 2 + gdk/wayland/gdkdisplay-wayland.c | 7 +++ gdk/wayland/gdkdisplay-wayland.h | 2 + gdk/wayland/gdkwaylandwindow.h | 12 +++++ gdk/wayland/gdkwindow-wayland.c | 87 ++++++++++++++++++++++++++++++++ 6 files changed, 111 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index a4051ec750..431c081476 100644 --- a/configure.ac +++ b/configure.ac @@ -60,7 +60,7 @@ m4_define([cairo_required_version], [1.14.0]) m4_define([gdk_pixbuf_required_version], [2.30.0]) m4_define([introspection_required_version], [1.39.0]) m4_define([wayland_required_version], [1.9.91]) -m4_define([wayland_protocols_required_version], [1.5]) +m4_define([wayland_protocols_required_version], [1.6]) m4_define([mirclient_required_version], [0.22.0]) m4_define([mircookie_required_version], [0.17.0]) m4_define([epoxy_required_version], [1.0]) diff --git a/gdk/wayland/Makefile.am b/gdk/wayland/Makefile.am index 1805d4b308..5b2e64e11b 100644 --- a/gdk/wayland/Makefile.am +++ b/gdk/wayland/Makefile.am @@ -25,6 +25,8 @@ BUILT_SOURCES = \ pointer-gestures-unstable-v1-protocol.c \ xdg-shell-unstable-v6-client-protocol.h \ xdg-shell-unstable-v6-protocol.c \ + xdg-foreign-unstable-v1-client-protocol.h \ + xdg-foreign-unstable-v1-protocol.c \ gtk-primary-selection-client-protocol.h \ gtk-primary-selection-protocol.c \ tablet-unstable-v2-client-protocol.h \ diff --git a/gdk/wayland/gdkdisplay-wayland.c b/gdk/wayland/gdkdisplay-wayland.c index f5b6218698..4bb247e160 100644 --- a/gdk/wayland/gdkdisplay-wayland.c +++ b/gdk/wayland/gdkdisplay-wayland.c @@ -45,6 +45,7 @@ #include "pointer-gestures-unstable-v1-client-protocol.h" #include "tablet-unstable-v2-client-protocol.h" #include "xdg-shell-unstable-v6-client-protocol.h" +#include "xdg-foreign-unstable-v1-client-protocol.h" /** * SECTION:wayland_interaction @@ -433,6 +434,12 @@ gdk_registry_handle_global (void *data, wl_registry_bind(display_wayland->wl_registry, id, &zwp_tablet_manager_v2_interface, 1); } + else if (strcmp (interface, "zxdg_exporter_v1") == 0) + { + display_wayland->xdg_exporter = + wl_registry_bind (display_wayland->wl_registry, id, + &zxdg_exporter_v1_interface, 1); + } else handled = FALSE; diff --git a/gdk/wayland/gdkdisplay-wayland.h b/gdk/wayland/gdkdisplay-wayland.h index a1f51ef536..f21e8b631b 100644 --- a/gdk/wayland/gdkdisplay-wayland.h +++ b/gdk/wayland/gdkdisplay-wayland.h @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -74,6 +75,7 @@ struct _GdkWaylandDisplay struct zwp_pointer_gestures_v1 *pointer_gestures; struct gtk_primary_selection_device_manager *primary_selection_manager; struct zwp_tablet_manager_v2 *tablet_manager; + struct zxdg_exporter_v1 *xdg_exporter; GList *async_roundtrips; diff --git a/gdk/wayland/gdkwaylandwindow.h b/gdk/wayland/gdkwaylandwindow.h index e46ce18d79..6c006e80a7 100644 --- a/gdk/wayland/gdkwaylandwindow.h +++ b/gdk/wayland/gdkwaylandwindow.h @@ -60,6 +60,18 @@ void gdk_wayland_window_set_dbus_properties_libgtk_only (Gdk const char *application_object_path, const char *unique_bus_name); +typedef void (*GdkWaylandWindowExported) (GdkWindow *window, + const char *handle, + gpointer user_data); + +GDK_AVAILABLE_IN_3_22 +gboolean gdk_wayland_window_export_handle (GdkWindow *window, + GdkWaylandWindowExported callback, + gpointer user_data, + GDestroyNotify destroy_func); + +GDK_AVAILABLE_IN_3_22 +void gdk_wayland_window_unexport_handle (GdkWindow *window); G_END_DECLS diff --git a/gdk/wayland/gdkwindow-wayland.c b/gdk/wayland/gdkwindow-wayland.c index 1a2575e607..fe11d943e0 100644 --- a/gdk/wayland/gdkwindow-wayland.c +++ b/gdk/wayland/gdkwindow-wayland.c @@ -118,6 +118,7 @@ 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; } display_server; EGLSurface egl_surface; @@ -196,6 +197,12 @@ struct _GdkWindowImplWayland int height; GdkWindowState state; } pending; + + struct { + GdkWaylandWindowExported callback; + gpointer user_data; + GDestroyNotify destroy_func; + } exported; }; struct _GdkWindowImplWaylandClass @@ -3828,3 +3835,83 @@ _gdk_wayland_window_offset_next_wl_buffer (GdkWindow *window, impl->pending_buffer_offset_x = x; impl->pending_buffer_offset_y = y; } + +static void +xdg_exported_handle (void *data, + struct zxdg_exported_v1 *zxdg_exported_v1, + const char *handle) +{ + GdkWindow *window = data; + GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl); + + impl->exported.callback (window, handle, impl->exported.user_data); + impl->exported.user_data = NULL; +} + +static const struct zxdg_exported_v1_listener xdg_exported_listener = { + xdg_exported_handle +}; + +/** + * gdk_wayland_window_export_handle: + * + * Stability: unstable + */ +gboolean +gdk_wayland_window_export_handle (GdkWindow *window, + GdkWaylandWindowExported callback, + gpointer user_data, + GDestroyNotify destroy_func) +{ + GdkWindowImplWayland *impl; + GdkWaylandDisplay *display_wayland; + GdkDisplay *display = gdk_window_get_display (window); + struct zxdg_exported_v1 *xdg_exported; + + 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_exported, FALSE); + + if (!display_wayland->xdg_exporter) + { + g_warning ("Server is missing xdg_foreign support"); + return FALSE; + } + + 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; + impl->exported.callback = callback; + impl->exported.user_data = user_data; + impl->exported.destroy_func = destroy_func; + + return TRUE; +} + +/** + * gdk_wayland_window_unexport_handle: + * + * Stability: unstable + */ +void +gdk_wayland_window_unexport_handle (GdkWindow *window) +{ + GdkWindowImplWayland *impl; + + g_return_if_fail (GDK_IS_WAYLAND_WINDOW (window)); + + impl = GDK_WINDOW_IMPL_WAYLAND (window->impl); + + g_return_if_fail (impl->display_server.xdg_exported); + + g_clear_pointer (&impl->display_server.xdg_exported, + zxdg_exported_v1_destroy); + g_clear_pointer (&impl->exported.user_data, + impl->exported.destroy_func); +}