From 91c837ace563cb2bf188dc8ac8e0ae60f616ffe3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Thu, 3 Nov 2022 21:51:29 +0100 Subject: [PATCH] Wayland: Use tags to verify proxy ownership This is in preparation for adding support for libdecor, which creates its own proxies on our display. It will likely also be helpful to some people using native access on Wayland. This is partly based on the implementation of libdecor support in PR #1693 by @ christianrauch. --- src/wl_init.c | 10 +++++++++- src/wl_monitor.c | 1 + src/wl_platform.h | 8 ++++++++ src/wl_window.c | 26 ++++++++++++++++++++++++-- 4 files changed, 42 insertions(+), 3 deletions(-) diff --git a/src/wl_init.c b/src/wl_init.c index e83c6992..cbd9d4ec 100644 --- a/src/wl_init.c +++ b/src/wl_init.c @@ -507,6 +507,8 @@ int _glfwInitWayland(void) _glfw.wl.keyRepeatTimerfd = -1; _glfw.wl.cursorTimerfd = -1; + _glfw.wl.tag = glfwGetVersionString(); + _glfw.wl.client.display_flush = (PFN_wl_display_flush) _glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_display_flush"); _glfw.wl.client.display_cancel_read = (PFN_wl_display_cancel_read) @@ -537,6 +539,10 @@ int _glfwInitWayland(void) _glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_proxy_get_user_data"); _glfw.wl.client.proxy_set_user_data = (PFN_wl_proxy_set_user_data) _glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_proxy_set_user_data"); + _glfw.wl.client.proxy_get_tag = (PFN_wl_proxy_get_tag) + _glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_proxy_get_tag"); + _glfw.wl.client.proxy_set_tag = (PFN_wl_proxy_set_tag) + _glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_proxy_set_tag"); _glfw.wl.client.proxy_get_version = (PFN_wl_proxy_get_version) _glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_proxy_get_version"); _glfw.wl.client.proxy_marshal_flags = (PFN_wl_proxy_marshal_flags) @@ -556,7 +562,9 @@ int _glfwInitWayland(void) !_glfw.wl.client.proxy_marshal_constructor || !_glfw.wl.client.proxy_marshal_constructor_versioned || !_glfw.wl.client.proxy_get_user_data || - !_glfw.wl.client.proxy_set_user_data) + !_glfw.wl.client.proxy_set_user_data || + !_glfw.wl.client.proxy_get_tag || + !_glfw.wl.client.proxy_set_tag) { _glfwInputError(GLFW_PLATFORM_ERROR, "Wayland: Failed to load libwayland-client entry point"); diff --git a/src/wl_monitor.c b/src/wl_monitor.c index 3d4fcbb8..c847eb7e 100644 --- a/src/wl_monitor.c +++ b/src/wl_monitor.c @@ -191,6 +191,7 @@ void _glfwAddOutputWayland(uint32_t name, uint32_t version) monitor->wl.output = output; monitor->wl.name = name; + wl_proxy_set_tag((struct wl_proxy*) output, &_glfw.wl.tag); wl_output_add_listener(output, &outputListener, monitor); } diff --git a/src/wl_platform.h b/src/wl_platform.h index f28038de..81e6b5d7 100644 --- a/src/wl_platform.h +++ b/src/wl_platform.h @@ -61,6 +61,8 @@ typedef struct wl_proxy* (* PFN_wl_proxy_marshal_constructor)(struct wl_proxy*,u typedef struct wl_proxy* (* PFN_wl_proxy_marshal_constructor_versioned)(struct wl_proxy*,uint32_t,const struct wl_interface*,uint32_t,...); typedef void* (* PFN_wl_proxy_get_user_data)(struct wl_proxy*); typedef void (* PFN_wl_proxy_set_user_data)(struct wl_proxy*,void*); +typedef void (* PFN_wl_proxy_set_tag)(struct wl_proxy*,const char*const*); +typedef const char* const* (* PFN_wl_proxy_get_tag)(struct wl_proxy*); typedef uint32_t (* PFN_wl_proxy_get_version)(struct wl_proxy*); typedef struct wl_proxy* (* PFN_wl_proxy_marshal_flags)(struct wl_proxy*,uint32_t,const struct wl_interface*,uint32_t,uint32_t,...); #define wl_display_flush _glfw.wl.client.display_flush @@ -78,6 +80,8 @@ typedef struct wl_proxy* (* PFN_wl_proxy_marshal_flags)(struct wl_proxy*,uint32_ #define wl_proxy_marshal_constructor_versioned _glfw.wl.client.proxy_marshal_constructor_versioned #define wl_proxy_get_user_data _glfw.wl.client.proxy_get_user_data #define wl_proxy_set_user_data _glfw.wl.client.proxy_set_user_data +#define wl_proxy_get_tag _glfw.wl.client.proxy_get_tag +#define wl_proxy_set_tag _glfw.wl.client.proxy_set_tag #define wl_proxy_get_version _glfw.wl.client.proxy_get_version #define wl_proxy_marshal_flags _glfw.wl.client.proxy_marshal_flags @@ -311,6 +315,8 @@ typedef struct _GLFWlibraryWayland _GLFWwindow* dragFocus; uint32_t dragSerial; + const char* tag; + struct wl_cursor_theme* cursorTheme; struct wl_cursor_theme* cursorThemeHiDPI; struct wl_surface* cursorSurface; @@ -388,6 +394,8 @@ typedef struct _GLFWlibraryWayland PFN_wl_proxy_marshal_constructor_versioned proxy_marshal_constructor_versioned; PFN_wl_proxy_get_user_data proxy_get_user_data; PFN_wl_proxy_set_user_data proxy_set_user_data; + PFN_wl_proxy_get_tag proxy_get_tag; + PFN_wl_proxy_set_tag proxy_set_tag; PFN_wl_proxy_get_version proxy_get_version; PFN_wl_proxy_marshal_flags proxy_marshal_flags; } client; diff --git a/src/wl_window.c b/src/wl_window.c index 697b6a0e..5b194e89 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -199,6 +199,7 @@ static void createFallbackDecoration(_GLFWdecorationWayland* decoration, int width, int height) { decoration->surface = wl_compositor_create_surface(_glfw.wl.compositor); + wl_proxy_set_tag((struct wl_proxy*) decoration->surface, &_glfw.wl.tag); decoration->subsurface = wl_subcompositor_get_subsurface(_glfw.wl.subcompositor, decoration->surface, parent); @@ -371,6 +372,9 @@ static void surfaceHandleEnter(void* userData, struct wl_surface* surface, struct wl_output* output) { + if (wl_proxy_get_tag((struct wl_proxy*) output) != &_glfw.wl.tag) + return; + _GLFWwindow* window = userData; _GLFWmonitor* monitor = wl_output_get_user_data(output); @@ -391,6 +395,9 @@ static void surfaceHandleLeave(void* userData, struct wl_surface* surface, struct wl_output* output) { + if (wl_proxy_get_tag((struct wl_proxy*) output) != &_glfw.wl.tag) + return; + _GLFWwindow* window = userData; _GLFWmonitor* monitor = wl_output_get_user_data(output); GLFWbool found = GLFW_FALSE; @@ -729,6 +736,7 @@ static GLFWbool createNativeSurface(_GLFWwindow* window, return GLFW_FALSE; } + wl_proxy_set_tag((struct wl_proxy*) window->wl.surface, &_glfw.wl.tag); wl_surface_add_listener(window->wl.surface, &surfaceListener, window); @@ -1063,6 +1071,9 @@ static void pointerHandleEnter(void* userData, if (!surface) return; + if (wl_proxy_get_tag((struct wl_proxy*) surface) != &_glfw.wl.tag) + return; + _GLFWdecorationSideWayland focus = mainWindow; _GLFWwindow* window = wl_surface_get_user_data(surface); if (!window) @@ -1088,8 +1099,13 @@ static void pointerHandleLeave(void* userData, uint32_t serial, struct wl_surface* surface) { - _GLFWwindow* window = _glfw.wl.pointerFocus; + if (!surface) + return; + if (wl_proxy_get_tag((struct wl_proxy*) surface) != &_glfw.wl.tag) + return; + + _GLFWwindow* window = _glfw.wl.pointerFocus; if (!window) return; @@ -1681,7 +1697,10 @@ static void dataDeviceHandleEnter(void* userData, _GLFWwindow* window = NULL; if (surface) - window = wl_surface_get_user_data(surface); + { + if (wl_proxy_get_tag((struct wl_proxy*) surface) == &_glfw.wl.tag) + window = wl_surface_get_user_data(surface); + } if (window && _glfw.wl.offers[i].text_uri_list) { @@ -1696,6 +1715,9 @@ static void dataDeviceHandleEnter(void* userData, } } + if (wl_proxy_get_tag((struct wl_proxy*) surface) != &_glfw.wl.tag) + return; + if (_glfw.wl.dragOffer) wl_data_offer_accept(offer, serial, "text/uri-list"); else