From 599fb3de348f73134b4e9d2ee5cabc62ca0b84ab Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Fri, 1 Mar 2019 18:46:06 +0100 Subject: [PATCH] Wayland: Remove wl_shell support This protocol is part of the core Wayland, but it is pretty badly designed and is missing quite a few features, and is in the process of being phased out in compositors. Its support in GLFW requires duplicating pretty much every single window management codepath. This bumps the required compositor versions to the ones which have implemented xdg-shell, approximately two years ago, which seems sensible to me. --- docs/compat.dox | 6 +- include/GLFW/glfw3.h | 7 +- src/wl_init.c | 49 +++++------ src/wl_platform.h | 2 - src/wl_window.c | 205 ++++--------------------------------------- 5 files changed, 40 insertions(+), 229 deletions(-) diff --git a/docs/compat.dox b/docs/compat.dox index 615264b4..25bfc1aa 100644 --- a/docs/compat.dox +++ b/docs/compat.dox @@ -104,11 +104,7 @@ has been configured in the compositor. GLFW uses the [xdg-shell protocol](https://cgit.freedesktop.org/wayland/wayland-protocols/tree/stable/xdg-shell/xdg-shell.xml) to provide better window management. This protocol is part of -wayland-protocols 1.12, and mandatory at build time. If the running compositor -does not support this protocol, the older [wl_shell -interface](https://cgit.freedesktop.org/wayland/wayland/tree/protocol/wayland.xml#n972) -will be used instead. This will result in a worse integration with the -desktop, especially on tiling compositors. +wayland-protocols 1.12, and mandatory at build time. GLFW uses the [relative pointer protocol](https://cgit.freedesktop.org/wayland/wayland-protocols/tree/unstable/relative-pointer/relative-pointer-unstable-v1.xml) diff --git a/include/GLFW/glfw3.h b/include/GLFW/glfw3.h index 68c28a29..a61ec83f 100644 --- a/include/GLFW/glfw3.h +++ b/include/GLFW/glfw3.h @@ -3089,8 +3089,8 @@ GLFWAPI void glfwSetWindowOpacity(GLFWwindow* window, float opacity); * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref * GLFW_PLATFORM_ERROR. * - * @remark @wayland There is no concept of iconification in wl_shell, this - * function will emit @ref GLFW_PLATFORM_ERROR when using this deprecated + * @remark @wayland Once a window is iconified, @ref glfwRestoreWindow won’t + * be able to restore it. This is a design decision of the xdg-shell * protocol. * * @thread_safety This function must only be called from the main thread. @@ -3625,9 +3625,6 @@ GLFWAPI GLFWwindowfocusfun glfwSetWindowFocusCallback(GLFWwindow* window, GLFWwi * * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * - * @remark @wayland The wl_shell protocol has no concept of iconification, - * this callback will never be called when using this deprecated protocol. - * * @thread_safety This function must only be called from the main thread. * * @sa @ref window_iconify diff --git a/src/wl_init.c b/src/wl_init.c index 7bbfb386..36b66c29 100644 --- a/src/wl_init.c +++ b/src/wl_init.c @@ -237,9 +237,7 @@ static void pointerHandleButton(void* data, { _GLFWwindow* window = _glfw.wl.pointerFocus; int glfwButton; - - // Both xdg-shell and wl_shell use the same values. - uint32_t edges = WL_SHELL_SURFACE_RESIZE_NONE; + uint32_t edges = XDG_TOPLEVEL_RESIZE_EDGE_NONE; if (!window) return; @@ -251,46 +249,39 @@ static void pointerHandleButton(void* data, break; case topDecoration: if (window->wl.cursorPosY < _GLFW_DECORATION_WIDTH) - edges = WL_SHELL_SURFACE_RESIZE_TOP; + edges = XDG_TOPLEVEL_RESIZE_EDGE_TOP; else { - if (window->wl.xdg.toplevel) - xdg_toplevel_move(window->wl.xdg.toplevel, _glfw.wl.seat, serial); - else - wl_shell_surface_move(window->wl.shellSurface, _glfw.wl.seat, serial); + xdg_toplevel_move(window->wl.xdg.toplevel, _glfw.wl.seat, serial); } break; case leftDecoration: if (window->wl.cursorPosY < _GLFW_DECORATION_WIDTH) - edges = WL_SHELL_SURFACE_RESIZE_TOP_LEFT; + edges = XDG_TOPLEVEL_RESIZE_EDGE_TOP_LEFT; else - edges = WL_SHELL_SURFACE_RESIZE_LEFT; + edges = XDG_TOPLEVEL_RESIZE_EDGE_LEFT; break; case rightDecoration: if (window->wl.cursorPosY < _GLFW_DECORATION_WIDTH) - edges = WL_SHELL_SURFACE_RESIZE_TOP_RIGHT; + edges = XDG_TOPLEVEL_RESIZE_EDGE_TOP_RIGHT; else - edges = WL_SHELL_SURFACE_RESIZE_RIGHT; + edges = XDG_TOPLEVEL_RESIZE_EDGE_RIGHT; break; case bottomDecoration: if (window->wl.cursorPosX < _GLFW_DECORATION_WIDTH) - edges = WL_SHELL_SURFACE_RESIZE_BOTTOM_LEFT; + edges = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_LEFT; else if (window->wl.cursorPosX > window->wl.width + _GLFW_DECORATION_WIDTH) - edges = WL_SHELL_SURFACE_RESIZE_BOTTOM_RIGHT; + edges = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_RIGHT; else - edges = WL_SHELL_SURFACE_RESIZE_BOTTOM; + edges = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM; break; default: assert(0); } - if (edges != WL_SHELL_SURFACE_RESIZE_NONE) + if (edges != XDG_TOPLEVEL_RESIZE_EDGE_NONE) { - if (window->wl.xdg.toplevel) - xdg_toplevel_resize(window->wl.xdg.toplevel, _glfw.wl.seat, - serial, edges); - else - wl_shell_surface_resize(window->wl.shellSurface, _glfw.wl.seat, - serial, edges); + xdg_toplevel_resize(window->wl.xdg.toplevel, _glfw.wl.seat, + serial, edges); } } else if (button == BTN_RIGHT) @@ -805,11 +796,6 @@ static void registryHandleGlobal(void* data, _glfw.wl.shm = wl_registry_bind(registry, name, &wl_shm_interface, 1); } - else if (strcmp(interface, "wl_shell") == 0) - { - _glfw.wl.shell = - wl_registry_bind(registry, name, &wl_shell_interface, 1); - } else if (strcmp(interface, "wl_output") == 0) { _glfwAddOutputWayland(name, version); @@ -1164,6 +1150,13 @@ int _glfwPlatformInit(void) if (_glfw.wl.seatVersion >= 4) _glfw.wl.timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC); + if (!_glfw.wl.wmBase) + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "Wayland: Failed to find xdg-shell in your compositor"); + return GLFW_FALSE; + } + if (_glfw.wl.pointer && _glfw.wl.shm) { cursorTheme = getenv("XCURSOR_THEME"); @@ -1257,8 +1250,6 @@ void _glfwPlatformTerminate(void) wl_compositor_destroy(_glfw.wl.compositor); if (_glfw.wl.shm) wl_shm_destroy(_glfw.wl.shm); - if (_glfw.wl.shell) - wl_shell_destroy(_glfw.wl.shell); if (_glfw.wl.viewporter) wp_viewporter_destroy(_glfw.wl.viewporter); if (_glfw.wl.decorationManager) diff --git a/src/wl_platform.h b/src/wl_platform.h index 3d281645..13f4ab31 100644 --- a/src/wl_platform.h +++ b/src/wl_platform.h @@ -180,7 +180,6 @@ typedef struct _GLFWwindowWayland GLFWbool transparent; struct wl_surface* surface; struct wl_egl_window* native; - struct wl_shell_surface* shellSurface; struct wl_callback* callback; struct { @@ -227,7 +226,6 @@ typedef struct _GLFWlibraryWayland struct wl_registry* registry; struct wl_compositor* compositor; struct wl_subcompositor* subcompositor; - struct wl_shell* shell; struct wl_shm* shm; struct wl_seat* seat; struct wl_pointer* pointer; diff --git a/src/wl_window.c b/src/wl_window.c index fe4658cb..9c645fab 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -39,72 +39,6 @@ #include -static void shellSurfaceHandlePing(void* data, - struct wl_shell_surface* shellSurface, - uint32_t serial) -{ - wl_shell_surface_pong(shellSurface, serial); -} - -static void shellSurfaceHandleConfigure(void* data, - struct wl_shell_surface* shellSurface, - uint32_t edges, - int32_t width, - int32_t height) -{ - _GLFWwindow* window = data; - float aspectRatio; - float targetRatio; - - if (!window->monitor) - { - if (_glfw.wl.viewporter && window->decorated) - { - width -= _GLFW_DECORATION_HORIZONTAL; - height -= _GLFW_DECORATION_VERTICAL; - } - if (width < 1) - width = 1; - if (height < 1) - height = 1; - - if (window->numer != GLFW_DONT_CARE && window->denom != GLFW_DONT_CARE) - { - aspectRatio = (float)width / (float)height; - targetRatio = (float)window->numer / (float)window->denom; - if (aspectRatio < targetRatio) - height = width / targetRatio; - else if (aspectRatio > targetRatio) - width = height * targetRatio; - } - - if (window->minwidth != GLFW_DONT_CARE && width < window->minwidth) - width = window->minwidth; - else if (window->maxwidth != GLFW_DONT_CARE && width > window->maxwidth) - width = window->maxwidth; - - if (window->minheight != GLFW_DONT_CARE && height < window->minheight) - height = window->minheight; - else if (window->maxheight != GLFW_DONT_CARE && height > window->maxheight) - height = window->maxheight; - } - - _glfwInputWindowSize(window, width, height); - _glfwPlatformSetWindowSize(window, width, height); - _glfwInputWindowDamage(window); -} - -static void shellSurfaceHandlePopupDone(void* data, - struct wl_shell_surface* shellSurface) -{ -} - -static const struct wl_shell_surface_listener shellSurfaceListener = { - shellSurfaceHandlePing, - shellSurfaceHandleConfigure, - shellSurfaceHandlePopupDone -}; - static int createTmpfileCloexec(char* tmpname) { int fd; @@ -529,66 +463,11 @@ static void setFullscreen(_GLFWwindow* window, _GLFWmonitor* monitor, window->wl.xdg.toplevel, monitor->wl.output); } - else if (window->wl.shellSurface) - { - wl_shell_surface_set_fullscreen( - window->wl.shellSurface, - WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT, - refreshRate * 1000, // Convert Hz to mHz. - monitor->wl.output); - } setIdleInhibitor(window, GLFW_TRUE); if (!window->wl.decorations.serverSide) destroyDecorations(window); } -static GLFWbool createShellSurface(_GLFWwindow* window) -{ - if (!_glfw.wl.shell) - { - _glfwInputError(GLFW_PLATFORM_ERROR, - "Wayland: wl_shell protocol not available"); - return GLFW_FALSE; - } - - window->wl.shellSurface = wl_shell_get_shell_surface(_glfw.wl.shell, - window->wl.surface); - if (!window->wl.shellSurface) - { - _glfwInputError(GLFW_PLATFORM_ERROR, - "Wayland: Shell surface creation failed"); - return GLFW_FALSE; - } - - wl_shell_surface_add_listener(window->wl.shellSurface, - &shellSurfaceListener, - window); - - if (window->wl.title) - wl_shell_surface_set_title(window->wl.shellSurface, window->wl.title); - - if (window->monitor) - { - setFullscreen(window, window->monitor, 0); - } - else if (window->wl.maximized) - { - wl_shell_surface_set_maximized(window->wl.shellSurface, NULL); - setIdleInhibitor(window, GLFW_FALSE); - createDecorations(window); - } - else - { - wl_shell_surface_set_toplevel(window->wl.shellSurface); - setIdleInhibitor(window, GLFW_FALSE); - createDecorations(window); - } - - wl_surface_commit(window->wl.surface); - - return GLFW_TRUE; -} - static void xdgToplevelHandleConfigure(void* data, struct xdg_toplevel* toplevel, int32_t width, @@ -949,16 +828,8 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window, if (wndconfig->visible) { - if (_glfw.wl.wmBase) - { - if (!createXdgSurface(window)) - return GLFW_FALSE; - } - else - { - if (!createShellSurface(window)) - return GLFW_FALSE; - } + if (!createXdgSurface(window)) + return GLFW_FALSE; window->wl.visible = GLFW_TRUE; } @@ -966,7 +837,6 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window, { window->wl.xdg.surface = NULL; window->wl.xdg.toplevel = NULL; - window->wl.shellSurface = NULL; window->wl.visible = GLFW_FALSE; } @@ -1008,9 +878,6 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window) if (window->wl.native) wl_egl_window_destroy(window->wl.native); - if (window->wl.shellSurface) - wl_shell_surface_destroy(window->wl.shellSurface); - if (window->wl.xdg.toplevel) xdg_toplevel_destroy(window->wl.xdg.toplevel); @@ -1031,8 +898,6 @@ void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title) window->wl.title = _glfw_strdup(title); if (window->wl.xdg.toplevel) xdg_toplevel_set_title(window->wl.xdg.toplevel, title); - else if (window->wl.shellSurface) - wl_shell_surface_set_title(window->wl.shellSurface, title); } void _glfwPlatformSetWindowIcon(_GLFWwindow* window, @@ -1078,23 +943,15 @@ void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window, int minwidth, int minheight, int maxwidth, int maxheight) { - if (_glfw.wl.wmBase) + if (window->wl.xdg.toplevel) { - if (window->wl.xdg.toplevel) - { - if (minwidth == GLFW_DONT_CARE || minheight == GLFW_DONT_CARE) - minwidth = minheight = 0; - if (maxwidth == GLFW_DONT_CARE || maxheight == GLFW_DONT_CARE) - maxwidth = maxheight = 0; - xdg_toplevel_set_min_size(window->wl.xdg.toplevel, minwidth, minheight); - xdg_toplevel_set_max_size(window->wl.xdg.toplevel, maxwidth, maxheight); - wl_surface_commit(window->wl.surface); - } - } - else - { - // TODO: find out how to trigger a resize. - // The actual limits are checked in the wl_shell_surface::configure handler. + if (minwidth == GLFW_DONT_CARE || minheight == GLFW_DONT_CARE) + minwidth = minheight = 0; + if (maxwidth == GLFW_DONT_CARE || maxheight == GLFW_DONT_CARE) + maxwidth = maxheight = 0; + xdg_toplevel_set_min_size(window->wl.xdg.toplevel, minwidth, minheight); + xdg_toplevel_set_max_size(window->wl.xdg.toplevel, maxwidth, maxheight); + wl_surface_commit(window->wl.surface); } } @@ -1102,7 +959,7 @@ void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int numer, int denom) { // TODO: find out how to trigger a resize. - // The actual limits are checked in the wl_shell_surface::configure handler. + // The actual limits are checked in the xdg_toplevel::configure handler. } void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, @@ -1141,16 +998,8 @@ void _glfwPlatformGetWindowContentScale(_GLFWwindow* window, void _glfwPlatformIconifyWindow(_GLFWwindow* window) { - if (_glfw.wl.wmBase) - { - if (window->wl.xdg.toplevel) - xdg_toplevel_set_minimized(window->wl.xdg.toplevel); - } - else - { - _glfwInputError(GLFW_PLATFORM_ERROR, - "Wayland: Iconify window not supported on wl_shell"); - } + if (window->wl.xdg.toplevel) + xdg_toplevel_set_minimized(window->wl.xdg.toplevel); } void _glfwPlatformRestoreWindow(_GLFWwindow* window) @@ -1162,12 +1011,7 @@ void _glfwPlatformRestoreWindow(_GLFWwindow* window) if (window->wl.maximized) xdg_toplevel_unset_maximized(window->wl.xdg.toplevel); // There is no way to unset minimized, or even to know if we are - // minimized, so there is nothing to do here. - } - else if (window->wl.shellSurface) - { - if (window->monitor || window->wl.maximized) - wl_shell_surface_set_toplevel(window->wl.shellSurface); + // minimized, so there is nothing to do in this case. } _glfwInputWindowMonitor(window, NULL); window->wl.maximized = GLFW_FALSE; @@ -1179,11 +1023,6 @@ void _glfwPlatformMaximizeWindow(_GLFWwindow* window) { xdg_toplevel_set_maximized(window->wl.xdg.toplevel); } - else if (window->wl.shellSurface) - { - // Let the compositor select the best output. - wl_shell_surface_set_maximized(window->wl.shellSurface, NULL); - } window->wl.maximized = GLFW_TRUE; } @@ -1191,10 +1030,7 @@ void _glfwPlatformShowWindow(_GLFWwindow* window) { if (!window->wl.visible) { - if (_glfw.wl.wmBase) - createXdgSurface(window); - else if (!window->wl.shellSurface) - createShellSurface(window); + createXdgSurface(window); window->wl.visible = GLFW_TRUE; } } @@ -1208,11 +1044,6 @@ void _glfwPlatformHideWindow(_GLFWwindow* window) window->wl.xdg.toplevel = NULL; window->wl.xdg.surface = NULL; } - else if (window->wl.shellSurface) - { - wl_shell_surface_destroy(window->wl.shellSurface); - window->wl.shellSurface = NULL; - } window->wl.visible = GLFW_FALSE; } @@ -1243,8 +1074,6 @@ void _glfwPlatformSetWindowMonitor(_GLFWwindow* window, { if (window->wl.xdg.toplevel) xdg_toplevel_unset_fullscreen(window->wl.xdg.toplevel); - else if (window->wl.shellSurface) - wl_shell_surface_set_toplevel(window->wl.shellSurface); setIdleInhibitor(window, GLFW_FALSE); if (!_glfw.wl.decorationManager) createDecorations(window); @@ -1259,8 +1088,8 @@ int _glfwPlatformWindowFocused(_GLFWwindow* window) int _glfwPlatformWindowIconified(_GLFWwindow* window) { - // wl_shell doesn't have any iconified concept, and xdg-shell doesn’t give - // any way to request whether a surface is iconified. + // xdg-shell doesn’t give any way to request whether a surface is + // iconified. return GLFW_FALSE; }