From d3a7362430a2a0073009c8f4ca9fd4e494b0418f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Wed, 7 Feb 2024 21:34:15 +0100 Subject: [PATCH 01/14] Wayland: Separate window and framebuffer resizing --- src/wl_window.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/wl_window.c b/src/wl_window.c index d7f12660..94970d14 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -306,8 +306,7 @@ static void setContentAreaOpaque(_GLFWwindow* window) wl_region_destroy(region); } - -static void resizeWindow(_GLFWwindow* window) +static void resizeFramebuffer(_GLFWwindow* window) { int scale = window->wl.contentScale; int scaledWidth = window->wl.width * scale; @@ -315,9 +314,16 @@ static void resizeWindow(_GLFWwindow* window) if (window->wl.egl.window) wl_egl_window_resize(window->wl.egl.window, scaledWidth, scaledHeight, 0, 0); + if (!window->wl.transparent) setContentAreaOpaque(window); + _glfwInputFramebufferSize(window, scaledWidth, scaledHeight); +} + +static void resizeWindow(_GLFWwindow* window) +{ + resizeFramebuffer(window); if (!window->wl.decorations.top.surface) return; @@ -363,7 +369,7 @@ void _glfwUpdateContentScaleWayland(_GLFWwindow* window) window->wl.contentScale = maxScale; wl_surface_set_buffer_scale(window->wl.surface, maxScale); _glfwInputWindowContentScale(window, maxScale, maxScale); - resizeWindow(window); + resizeFramebuffer(window); if (window->wl.visible) _glfwInputWindowDamage(window); From 5e97447dd586016b4b82aefa7e1981694176a898 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Wed, 7 Feb 2024 21:55:20 +0100 Subject: [PATCH 02/14] Wayland: Clarify fallback decoration struct name We now have three window decoration paths in the Wayland backend: libdecor decorations, XDG decorations and fallback decorations. This makes it clearer when code relates to the fallback decoration path, which should increasingly (hopefully) not get used. --- src/wl_platform.h | 2 +- src/wl_window.c | 100 +++++++++++++++++++++++----------------------- 2 files changed, 51 insertions(+), 51 deletions(-) diff --git a/src/wl_platform.h b/src/wl_platform.h index 7e8202e9..6da294fc 100644 --- a/src/wl_platform.h +++ b/src/wl_platform.h @@ -414,7 +414,7 @@ typedef struct _GLFWwindowWayland struct wl_buffer* buffer; _GLFWdecorationWayland top, left, right, bottom; _GLFWdecorationSideWayland focus; - } decorations; + } fallback; } _GLFWwindowWayland; // Wayland-specific global data diff --git a/src/wl_window.c b/src/wl_window.c index 94970d14..31c3b7e5 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -226,25 +226,25 @@ static void createFallbackDecorations(_GLFWwindow* window) if (!_glfw.wl.viewporter) return; - if (!window->wl.decorations.buffer) - window->wl.decorations.buffer = createShmBuffer(&image); - if (!window->wl.decorations.buffer) + if (!window->wl.fallback.buffer) + window->wl.fallback.buffer = createShmBuffer(&image); + if (!window->wl.fallback.buffer) return; - createFallbackDecoration(window, &window->wl.decorations.top, window->wl.surface, - window->wl.decorations.buffer, + createFallbackDecoration(window, &window->wl.fallback.top, window->wl.surface, + window->wl.fallback.buffer, 0, -GLFW_CAPTION_HEIGHT, window->wl.width, GLFW_CAPTION_HEIGHT); - createFallbackDecoration(window, &window->wl.decorations.left, window->wl.surface, - window->wl.decorations.buffer, + createFallbackDecoration(window, &window->wl.fallback.left, window->wl.surface, + window->wl.fallback.buffer, -GLFW_BORDER_SIZE, -GLFW_CAPTION_HEIGHT, GLFW_BORDER_SIZE, window->wl.height + GLFW_CAPTION_HEIGHT); - createFallbackDecoration(window, &window->wl.decorations.right, window->wl.surface, - window->wl.decorations.buffer, + createFallbackDecoration(window, &window->wl.fallback.right, window->wl.surface, + window->wl.fallback.buffer, window->wl.width, -GLFW_CAPTION_HEIGHT, GLFW_BORDER_SIZE, window->wl.height + GLFW_CAPTION_HEIGHT); - createFallbackDecoration(window, &window->wl.decorations.bottom, window->wl.surface, - window->wl.decorations.buffer, + createFallbackDecoration(window, &window->wl.fallback.bottom, window->wl.surface, + window->wl.fallback.buffer, -GLFW_BORDER_SIZE, window->wl.height, window->wl.width + GLFW_BORDER_SIZE * 2, GLFW_BORDER_SIZE); } @@ -264,10 +264,10 @@ static void destroyFallbackDecoration(_GLFWdecorationWayland* decoration) static void destroyFallbackDecorations(_GLFWwindow* window) { - destroyFallbackDecoration(&window->wl.decorations.top); - destroyFallbackDecoration(&window->wl.decorations.left); - destroyFallbackDecoration(&window->wl.decorations.right); - destroyFallbackDecoration(&window->wl.decorations.bottom); + destroyFallbackDecoration(&window->wl.fallback.top); + destroyFallbackDecoration(&window->wl.fallback.left); + destroyFallbackDecoration(&window->wl.fallback.right); + destroyFallbackDecoration(&window->wl.fallback.bottom); } static void xdgDecorationHandleConfigure(void* userData, @@ -325,28 +325,28 @@ static void resizeWindow(_GLFWwindow* window) { resizeFramebuffer(window); - if (!window->wl.decorations.top.surface) + if (!window->wl.fallback.top.surface) return; - wp_viewport_set_destination(window->wl.decorations.top.viewport, + wp_viewport_set_destination(window->wl.fallback.top.viewport, window->wl.width, GLFW_CAPTION_HEIGHT); - wl_surface_commit(window->wl.decorations.top.surface); + wl_surface_commit(window->wl.fallback.top.surface); - wp_viewport_set_destination(window->wl.decorations.left.viewport, + wp_viewport_set_destination(window->wl.fallback.left.viewport, GLFW_BORDER_SIZE, window->wl.height + GLFW_CAPTION_HEIGHT); - wl_surface_commit(window->wl.decorations.left.surface); + wl_surface_commit(window->wl.fallback.left.surface); - wl_subsurface_set_position(window->wl.decorations.right.subsurface, + wl_subsurface_set_position(window->wl.fallback.right.subsurface, window->wl.width, -GLFW_CAPTION_HEIGHT); - wp_viewport_set_destination(window->wl.decorations.right.viewport, + wp_viewport_set_destination(window->wl.fallback.right.viewport, GLFW_BORDER_SIZE, window->wl.height + GLFW_CAPTION_HEIGHT); - wl_surface_commit(window->wl.decorations.right.surface); + wl_surface_commit(window->wl.fallback.right.surface); - wl_subsurface_set_position(window->wl.decorations.bottom.subsurface, + wl_subsurface_set_position(window->wl.fallback.bottom.subsurface, -GLFW_BORDER_SIZE, window->wl.height); - wp_viewport_set_destination(window->wl.decorations.bottom.viewport, + wp_viewport_set_destination(window->wl.fallback.bottom.viewport, window->wl.width + GLFW_BORDER_SIZE * 2, GLFW_BORDER_SIZE); - wl_surface_commit(window->wl.decorations.bottom.surface); + wl_surface_commit(window->wl.fallback.bottom.surface); } void _glfwUpdateContentScaleWayland(_GLFWwindow* window) @@ -466,7 +466,7 @@ static void acquireMonitor(_GLFWwindow* window) setIdleInhibitor(window, GLFW_TRUE); - if (window->wl.decorations.top.surface) + if (window->wl.fallback.top.surface) destroyFallbackDecorations(window); } @@ -522,7 +522,7 @@ static void xdgToplevelHandleConfigure(void* userData, if (width && height) { - if (window->wl.decorations.top.surface) + if (window->wl.fallback.top.surface) { window->wl.pending.width = _glfw_max(0, width - GLFW_BORDER_SIZE * 2); window->wl.pending.height = @@ -882,7 +882,7 @@ static GLFWbool createXdgShellObjects(_GLFWwindow* window) int minwidth = window->minwidth; int minheight = window->minheight; - if (window->wl.decorations.top.surface) + if (window->wl.fallback.top.surface) { minwidth += GLFW_BORDER_SIZE * 2; minheight += GLFW_CAPTION_HEIGHT + GLFW_BORDER_SIZE; @@ -896,7 +896,7 @@ static GLFWbool createXdgShellObjects(_GLFWwindow* window) int maxwidth = window->maxwidth; int maxheight = window->maxheight; - if (window->wl.decorations.top.surface) + if (window->wl.fallback.top.surface) { maxwidth += GLFW_BORDER_SIZE * 2; maxheight += GLFW_CAPTION_HEIGHT + GLFW_BORDER_SIZE; @@ -1025,7 +1025,7 @@ static void incrementCursorImage(_GLFWwindow* window) { _GLFWcursor* cursor; - if (!window || window->wl.decorations.focus != GLFW_MAIN_WINDOW) + if (!window || window->wl.fallback.focus != GLFW_MAIN_WINDOW) return; cursor = window->wl.currentCursor; @@ -1276,16 +1276,16 @@ static void pointerHandleEnter(void* userData, _GLFWwindow* window = wl_surface_get_user_data(surface); - if (surface == window->wl.decorations.top.surface) - window->wl.decorations.focus = GLFW_TOP_DECORATION; - else if (surface == window->wl.decorations.left.surface) - window->wl.decorations.focus = GLFW_LEFT_DECORATION; - else if (surface == window->wl.decorations.right.surface) - window->wl.decorations.focus = GLFW_RIGHT_DECORATION; - else if (surface == window->wl.decorations.bottom.surface) - window->wl.decorations.focus = GLFW_BOTTOM_DECORATION; + if (surface == window->wl.fallback.top.surface) + window->wl.fallback.focus = GLFW_TOP_DECORATION; + else if (surface == window->wl.fallback.left.surface) + window->wl.fallback.focus = GLFW_LEFT_DECORATION; + else if (surface == window->wl.fallback.right.surface) + window->wl.fallback.focus = GLFW_RIGHT_DECORATION; + else if (surface == window->wl.fallback.bottom.surface) + window->wl.fallback.focus = GLFW_BOTTOM_DECORATION; else - window->wl.decorations.focus = GLFW_MAIN_WINDOW; + window->wl.fallback.focus = GLFW_MAIN_WINDOW; _glfw.wl.serial = serial; _glfw.wl.pointerEnterSerial = serial; @@ -1340,7 +1340,7 @@ static void pointerHandleMotion(void* userData, const char* cursorName = NULL; - switch (window->wl.decorations.focus) + switch (window->wl.fallback.focus) { case GLFW_MAIN_WINDOW: _glfw.wl.cursorPreviousName = NULL; @@ -1431,7 +1431,7 @@ static void pointerHandleButton(void* userData, return; if (button == BTN_LEFT) { - switch (window->wl.decorations.focus) + switch (window->wl.fallback.focus) { case GLFW_MAIN_WINDOW: break; @@ -1473,7 +1473,7 @@ static void pointerHandleButton(void* userData, } else if (button == BTN_RIGHT) { - if (window->wl.decorations.focus != GLFW_MAIN_WINDOW && + if (window->wl.fallback.focus != GLFW_MAIN_WINDOW && window->wl.xdg.toplevel) { xdg_toplevel_show_window_menu(window->wl.xdg.toplevel, @@ -1485,7 +1485,7 @@ static void pointerHandleButton(void* userData, } // Don’t pass the button to the user if it was related to a decoration. - if (window->wl.decorations.focus != GLFW_MAIN_WINDOW) + if (window->wl.fallback.focus != GLFW_MAIN_WINDOW) return; _glfw.wl.serial = serial; @@ -2100,8 +2100,8 @@ void _glfwDestroyWindowWayland(_GLFWwindow* window) destroyShellObjects(window); - if (window->wl.decorations.buffer) - wl_buffer_destroy(window->wl.decorations.buffer); + if (window->wl.fallback.buffer) + wl_buffer_destroy(window->wl.fallback.buffer); if (window->wl.egl.window) wl_egl_window_destroy(window->wl.egl.window); @@ -2205,7 +2205,7 @@ void _glfwSetWindowSizeLimitsWayland(_GLFWwindow* window, minwidth = minheight = 0; else { - if (window->wl.decorations.top.surface) + if (window->wl.fallback.top.surface) { minwidth += GLFW_BORDER_SIZE * 2; minheight += GLFW_CAPTION_HEIGHT + GLFW_BORDER_SIZE; @@ -2216,7 +2216,7 @@ void _glfwSetWindowSizeLimitsWayland(_GLFWwindow* window, maxwidth = maxheight = 0; else { - if (window->wl.decorations.top.surface) + if (window->wl.fallback.top.surface) { maxwidth += GLFW_BORDER_SIZE * 2; maxheight += GLFW_CAPTION_HEIGHT + GLFW_BORDER_SIZE; @@ -2279,7 +2279,7 @@ void _glfwGetWindowFrameSizeWayland(_GLFWwindow* window, int* left, int* top, int* right, int* bottom) { - if (window->wl.decorations.top.surface) + if (window->wl.fallback.top.surface) { if (top) *top = GLFW_CAPTION_HEIGHT; @@ -2926,7 +2926,7 @@ void _glfwSetCursorWayland(_GLFWwindow* window, _GLFWcursor* cursor) // If we're not in the correct window just save the cursor // the next time the pointer enters the window the cursor will change if (window != _glfw.wl.pointerFocus || - window->wl.decorations.focus != GLFW_MAIN_WINDOW) + window->wl.fallback.focus != GLFW_MAIN_WINDOW) { return; } From ea6dd72c714f6f3949cfaf21ad5c1745d4fb49d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Wed, 7 Feb 2024 22:21:52 +0100 Subject: [PATCH 03/14] Wayland: Fix GLFW_HOVERED for fallback decorations When using the fallback decorations, GLFW_HOVERED was true also when the cursor was over one of the window decorations. This also disentangles the GLFW_HOVERED state from the fallback decorations. Because GLFW_HOVERED should have had the same behavior as GLFW_MAIN_WINDOW, the latter has been removed. --- README.md | 2 ++ src/wl_platform.h | 1 - src/wl_window.c | 84 +++++++++++++++++++++++------------------------ 3 files changed, 44 insertions(+), 43 deletions(-) diff --git a/README.md b/README.md index 49b1d912..177960f6 100644 --- a/README.md +++ b/README.md @@ -181,6 +181,8 @@ information on what to include when reporting a bug. - [Wayland] Added support for `glfwFocusWindow` - [Wayland] Added dynamic loading of all Wayland libraries - [Wayland] Bugfix: `CLOCK_MONOTONIC` was not correctly enabled + - [Wayland] Bugfix: `GLFW_HOVERED` was true when the cursor was over any + fallback window decoration - [X11] Bugfix: Termination would segfault if the IM had been destroyed - [X11] Bugfix: Any IM started after initialization would not be detected - [POSIX] Removed use of deprecated function `gettimeofday` diff --git a/src/wl_platform.h b/src/wl_platform.h index 6da294fc..ba7616ec 100644 --- a/src/wl_platform.h +++ b/src/wl_platform.h @@ -325,7 +325,6 @@ typedef void (* PFN_libdecor_state_free)(struct libdecor_state*); typedef enum _GLFWdecorationSideWayland { - GLFW_MAIN_WINDOW, GLFW_TOP_DECORATION, GLFW_LEFT_DECORATION, GLFW_RIGHT_DECORATION, diff --git a/src/wl_window.c b/src/wl_window.c index 31c3b7e5..a2e13c22 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -1025,7 +1025,7 @@ static void incrementCursorImage(_GLFWwindow* window) { _GLFWcursor* cursor; - if (!window || window->wl.fallback.focus != GLFW_MAIN_WINDOW) + if (!window || !window->wl.hovered) return; cursor = window->wl.currentCursor; @@ -1276,7 +1276,9 @@ static void pointerHandleEnter(void* userData, _GLFWwindow* window = wl_surface_get_user_data(surface); - if (surface == window->wl.fallback.top.surface) + if (surface == window->wl.surface) + window->wl.hovered = GLFW_TRUE; + else if (surface == window->wl.fallback.top.surface) window->wl.fallback.focus = GLFW_TOP_DECORATION; else if (surface == window->wl.fallback.left.surface) window->wl.fallback.focus = GLFW_LEFT_DECORATION; @@ -1284,17 +1286,16 @@ static void pointerHandleEnter(void* userData, window->wl.fallback.focus = GLFW_RIGHT_DECORATION; else if (surface == window->wl.fallback.bottom.surface) window->wl.fallback.focus = GLFW_BOTTOM_DECORATION; - else - window->wl.fallback.focus = GLFW_MAIN_WINDOW; _glfw.wl.serial = serial; _glfw.wl.pointerEnterSerial = serial; _glfw.wl.pointerFocus = window; - window->wl.hovered = GLFW_TRUE; - - _glfwSetCursorWayland(window, window->wl.currentCursor); - _glfwInputCursorEnter(window, GLFW_TRUE); + if (window->wl.hovered) + { + _glfwSetCursorWayland(window, window->wl.currentCursor); + _glfwInputCursorEnter(window, GLFW_TRUE); + } } static void pointerHandleLeave(void* userData, @@ -1312,12 +1313,15 @@ static void pointerHandleLeave(void* userData, if (!window) return; - window->wl.hovered = GLFW_FALSE; - _glfw.wl.serial = serial; _glfw.wl.pointerFocus = NULL; _glfw.wl.cursorPreviousName = NULL; - _glfwInputCursorEnter(window, GLFW_FALSE); + + if (window->wl.hovered) + { + window->wl.hovered = GLFW_FALSE; + _glfwInputCursorEnter(window, GLFW_FALSE); + } } static void pointerHandleMotion(void* userData, @@ -1338,14 +1342,17 @@ static void pointerHandleMotion(void* userData, window->wl.cursorPosX = xpos; window->wl.cursorPosY = ypos; + if (window->wl.hovered) + { + _glfw.wl.cursorPreviousName = NULL; + _glfwInputCursorPos(window, xpos, ypos); + return; + } + const char* cursorName = NULL; switch (window->wl.fallback.focus) { - case GLFW_MAIN_WINDOW: - _glfw.wl.cursorPreviousName = NULL; - _glfwInputCursorPos(window, xpos, ypos); - return; case GLFW_TOP_DECORATION: if (ypos < GLFW_BORDER_SIZE) cursorName = "n-resize"; @@ -1429,12 +1436,28 @@ static void pointerHandleButton(void* userData, if (!window) return; + + if (window->wl.hovered) + { + _glfw.wl.serial = serial; + + /* Makes left, right and middle 0, 1 and 2. Overall order follows evdev + * codes. */ + glfwButton = button - BTN_LEFT; + + _glfwInputMouseClick(window, + glfwButton, + state == WL_POINTER_BUTTON_STATE_PRESSED + ? GLFW_PRESS + : GLFW_RELEASE, + _glfw.wl.xkb.modifiers); + return; + } + if (button == BTN_LEFT) { switch (window->wl.fallback.focus) { - case GLFW_MAIN_WINDOW: - break; case GLFW_TOP_DECORATION: if (window->wl.cursorPosY < GLFW_BORDER_SIZE) edges = XDG_TOPLEVEL_RESIZE_EDGE_TOP; @@ -1468,38 +1491,18 @@ static void pointerHandleButton(void* userData, { xdg_toplevel_resize(window->wl.xdg.toplevel, _glfw.wl.seat, serial, edges); - return; } } else if (button == BTN_RIGHT) { - if (window->wl.fallback.focus != GLFW_MAIN_WINDOW && - window->wl.xdg.toplevel) + if (window->wl.xdg.toplevel) { xdg_toplevel_show_window_menu(window->wl.xdg.toplevel, _glfw.wl.seat, serial, window->wl.cursorPosX, window->wl.cursorPosY); - return; } } - - // Don’t pass the button to the user if it was related to a decoration. - if (window->wl.fallback.focus != GLFW_MAIN_WINDOW) - return; - - _glfw.wl.serial = serial; - - /* Makes left, right and middle 0, 1 and 2. Overall order follows evdev - * codes. */ - glfwButton = button - BTN_LEFT; - - _glfwInputMouseClick(window, - glfwButton, - state == WL_POINTER_BUTTON_STATE_PRESSED - ? GLFW_PRESS - : GLFW_RELEASE, - _glfw.wl.xkb.modifiers); } static void pointerHandleAxis(void* userData, @@ -2925,11 +2928,8 @@ void _glfwSetCursorWayland(_GLFWwindow* window, _GLFWcursor* cursor) // If we're not in the correct window just save the cursor // the next time the pointer enters the window the cursor will change - if (window != _glfw.wl.pointerFocus || - window->wl.fallback.focus != GLFW_MAIN_WINDOW) - { + if (!window->wl.hovered) return; - } // Update pointer lock to match cursor mode if (window->cursorMode == GLFW_CURSOR_DISABLED) From 6ac0835ad2a98925bda1c855937340dc160f1db2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Thu, 8 Feb 2024 00:05:29 +0100 Subject: [PATCH 04/14] Wayland: Cleanup --- src/wl_window.c | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/src/wl_window.c b/src/wl_window.c index a2e13c22..712c58b4 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -1431,9 +1431,6 @@ static void pointerHandleButton(void* userData, uint32_t state) { _GLFWwindow* window = _glfw.wl.pointerFocus; - int glfwButton; - uint32_t edges = XDG_TOPLEVEL_RESIZE_EDGE_NONE; - if (!window) return; @@ -1441,21 +1438,17 @@ static void pointerHandleButton(void* userData, { _glfw.wl.serial = serial; - /* Makes left, right and middle 0, 1 and 2. Overall order follows evdev - * codes. */ - glfwButton = button - BTN_LEFT; - _glfwInputMouseClick(window, - glfwButton, - state == WL_POINTER_BUTTON_STATE_PRESSED - ? GLFW_PRESS - : GLFW_RELEASE, - _glfw.wl.xkb.modifiers); + button - BTN_LEFT, + state == WL_POINTER_BUTTON_STATE_PRESSED, + _glfw.wl.xkb.modifiers); return; } if (button == BTN_LEFT) { + uint32_t edges = XDG_TOPLEVEL_RESIZE_EDGE_NONE; + switch (window->wl.fallback.focus) { case GLFW_TOP_DECORATION: @@ -1484,8 +1477,6 @@ static void pointerHandleButton(void* userData, else edges = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM; break; - default: - assert(0); } if (edges != XDG_TOPLEVEL_RESIZE_EDGE_NONE) { From 4baeadbd667d5a933f47b9669250409d4fb27d22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Wed, 7 Feb 2024 22:56:18 +0100 Subject: [PATCH 05/14] Wayland: Put fallback decorations behind a boolean --- src/wl_platform.h | 1 + src/wl_window.c | 300 ++++++++++++++++++++++++---------------------- 2 files changed, 159 insertions(+), 142 deletions(-) diff --git a/src/wl_platform.h b/src/wl_platform.h index ba7616ec..e880d520 100644 --- a/src/wl_platform.h +++ b/src/wl_platform.h @@ -410,6 +410,7 @@ typedef struct _GLFWwindowWayland struct xdg_activation_token_v1* activationToken; struct { + GLFWbool decorations; struct wl_buffer* buffer; _GLFWdecorationWayland top, left, right, bottom; _GLFWdecorationSideWayland focus; diff --git a/src/wl_window.c b/src/wl_window.c index 712c58b4..c4d96b80 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -247,6 +247,8 @@ static void createFallbackDecorations(_GLFWwindow* window) window->wl.fallback.buffer, -GLFW_BORDER_SIZE, window->wl.height, window->wl.width + GLFW_BORDER_SIZE * 2, GLFW_BORDER_SIZE); + + window->wl.fallback.decorations = GLFW_TRUE; } static void destroyFallbackDecoration(_GLFWdecorationWayland* decoration) @@ -264,6 +266,8 @@ static void destroyFallbackDecoration(_GLFWdecorationWayland* decoration) static void destroyFallbackDecorations(_GLFWwindow* window) { + window->wl.fallback.decorations = GLFW_FALSE; + destroyFallbackDecoration(&window->wl.fallback.top); destroyFallbackDecoration(&window->wl.fallback.left); destroyFallbackDecoration(&window->wl.fallback.right); @@ -325,28 +329,32 @@ static void resizeWindow(_GLFWwindow* window) { resizeFramebuffer(window); - if (!window->wl.fallback.top.surface) - return; + if (window->wl.fallback.decorations) + { + wp_viewport_set_destination(window->wl.fallback.top.viewport, + window->wl.width, + GLFW_CAPTION_HEIGHT); + wl_surface_commit(window->wl.fallback.top.surface); - wp_viewport_set_destination(window->wl.fallback.top.viewport, - window->wl.width, GLFW_CAPTION_HEIGHT); - wl_surface_commit(window->wl.fallback.top.surface); + wp_viewport_set_destination(window->wl.fallback.left.viewport, + GLFW_BORDER_SIZE, + window->wl.height + GLFW_CAPTION_HEIGHT); + wl_surface_commit(window->wl.fallback.left.surface); - wp_viewport_set_destination(window->wl.fallback.left.viewport, - GLFW_BORDER_SIZE, window->wl.height + GLFW_CAPTION_HEIGHT); - wl_surface_commit(window->wl.fallback.left.surface); + wl_subsurface_set_position(window->wl.fallback.right.subsurface, + window->wl.width, -GLFW_CAPTION_HEIGHT); + wp_viewport_set_destination(window->wl.fallback.right.viewport, + GLFW_BORDER_SIZE, + window->wl.height + GLFW_CAPTION_HEIGHT); + wl_surface_commit(window->wl.fallback.right.surface); - wl_subsurface_set_position(window->wl.fallback.right.subsurface, - window->wl.width, -GLFW_CAPTION_HEIGHT); - wp_viewport_set_destination(window->wl.fallback.right.viewport, - GLFW_BORDER_SIZE, window->wl.height + GLFW_CAPTION_HEIGHT); - wl_surface_commit(window->wl.fallback.right.surface); - - wl_subsurface_set_position(window->wl.fallback.bottom.subsurface, - -GLFW_BORDER_SIZE, window->wl.height); - wp_viewport_set_destination(window->wl.fallback.bottom.viewport, - window->wl.width + GLFW_BORDER_SIZE * 2, GLFW_BORDER_SIZE); - wl_surface_commit(window->wl.fallback.bottom.surface); + wl_subsurface_set_position(window->wl.fallback.bottom.subsurface, + -GLFW_BORDER_SIZE, window->wl.height); + wp_viewport_set_destination(window->wl.fallback.bottom.viewport, + window->wl.width + GLFW_BORDER_SIZE * 2, + GLFW_BORDER_SIZE); + wl_surface_commit(window->wl.fallback.bottom.surface); + } } void _glfwUpdateContentScaleWayland(_GLFWwindow* window) @@ -466,7 +474,7 @@ static void acquireMonitor(_GLFWwindow* window) setIdleInhibitor(window, GLFW_TRUE); - if (window->wl.fallback.top.surface) + if (window->wl.fallback.decorations) destroyFallbackDecorations(window); } @@ -522,7 +530,7 @@ static void xdgToplevelHandleConfigure(void* userData, if (width && height) { - if (window->wl.fallback.top.surface) + if (window->wl.fallback.decorations) { window->wl.pending.width = _glfw_max(0, width - GLFW_BORDER_SIZE * 2); window->wl.pending.height = @@ -882,7 +890,7 @@ static GLFWbool createXdgShellObjects(_GLFWwindow* window) int minwidth = window->minwidth; int minheight = window->minheight; - if (window->wl.fallback.top.surface) + if (window->wl.fallback.decorations) { minwidth += GLFW_BORDER_SIZE * 2; minheight += GLFW_CAPTION_HEIGHT + GLFW_BORDER_SIZE; @@ -896,7 +904,7 @@ static GLFWbool createXdgShellObjects(_GLFWwindow* window) int maxwidth = window->maxwidth; int maxheight = window->maxheight; - if (window->wl.fallback.top.surface) + if (window->wl.fallback.decorations) { maxwidth += GLFW_BORDER_SIZE * 2; maxheight += GLFW_CAPTION_HEIGHT + GLFW_BORDER_SIZE; @@ -1276,23 +1284,25 @@ static void pointerHandleEnter(void* userData, _GLFWwindow* window = wl_surface_get_user_data(surface); - if (surface == window->wl.surface) - window->wl.hovered = GLFW_TRUE; - else if (surface == window->wl.fallback.top.surface) - window->wl.fallback.focus = GLFW_TOP_DECORATION; - else if (surface == window->wl.fallback.left.surface) - window->wl.fallback.focus = GLFW_LEFT_DECORATION; - else if (surface == window->wl.fallback.right.surface) - window->wl.fallback.focus = GLFW_RIGHT_DECORATION; - else if (surface == window->wl.fallback.bottom.surface) - window->wl.fallback.focus = GLFW_BOTTOM_DECORATION; + if (window->wl.fallback.decorations) + { + if (surface == window->wl.fallback.top.surface) + window->wl.fallback.focus = GLFW_TOP_DECORATION; + else if (surface == window->wl.fallback.left.surface) + window->wl.fallback.focus = GLFW_LEFT_DECORATION; + else if (surface == window->wl.fallback.right.surface) + window->wl.fallback.focus = GLFW_RIGHT_DECORATION; + else if (surface == window->wl.fallback.bottom.surface) + window->wl.fallback.focus = GLFW_BOTTOM_DECORATION; + } _glfw.wl.serial = serial; _glfw.wl.pointerEnterSerial = serial; _glfw.wl.pointerFocus = window; - if (window->wl.hovered) + if (surface == window->wl.surface) { + window->wl.hovered = GLFW_TRUE; _glfwSetCursorWayland(window, window->wl.currentCursor); _glfwInputCursorEnter(window, GLFW_TRUE); } @@ -1349,77 +1359,80 @@ static void pointerHandleMotion(void* userData, return; } - const char* cursorName = NULL; - - switch (window->wl.fallback.focus) + if (window->wl.fallback.decorations) { - case GLFW_TOP_DECORATION: - if (ypos < GLFW_BORDER_SIZE) - cursorName = "n-resize"; - else - cursorName = "left_ptr"; - break; - case GLFW_LEFT_DECORATION: - if (ypos < GLFW_BORDER_SIZE) - cursorName = "nw-resize"; - else - cursorName = "w-resize"; - break; - case GLFW_RIGHT_DECORATION: - if (ypos < GLFW_BORDER_SIZE) - cursorName = "ne-resize"; - else - cursorName = "e-resize"; - break; - case GLFW_BOTTOM_DECORATION: - if (xpos < GLFW_BORDER_SIZE) - cursorName = "sw-resize"; - else if (xpos > window->wl.width + GLFW_BORDER_SIZE) - cursorName = "se-resize"; - else - cursorName = "s-resize"; - break; - default: - assert(0); - } + const char* cursorName = NULL; - if (_glfw.wl.cursorPreviousName != cursorName) - { - struct wl_surface* surface = _glfw.wl.cursorSurface; - struct wl_cursor_theme* theme = _glfw.wl.cursorTheme; - int scale = 1; - - if (window->wl.contentScale > 1 && _glfw.wl.cursorThemeHiDPI) + switch (window->wl.fallback.focus) { - // We only support up to scale=2 for now, since libwayland-cursor - // requires us to load a different theme for each size. - scale = 2; - theme = _glfw.wl.cursorThemeHiDPI; + case GLFW_TOP_DECORATION: + if (ypos < GLFW_BORDER_SIZE) + cursorName = "n-resize"; + else + cursorName = "left_ptr"; + break; + case GLFW_LEFT_DECORATION: + if (ypos < GLFW_BORDER_SIZE) + cursorName = "nw-resize"; + else + cursorName = "w-resize"; + break; + case GLFW_RIGHT_DECORATION: + if (ypos < GLFW_BORDER_SIZE) + cursorName = "ne-resize"; + else + cursorName = "e-resize"; + break; + case GLFW_BOTTOM_DECORATION: + if (xpos < GLFW_BORDER_SIZE) + cursorName = "sw-resize"; + else if (xpos > window->wl.width + GLFW_BORDER_SIZE) + cursorName = "se-resize"; + else + cursorName = "s-resize"; + break; + default: + assert(0); } - struct wl_cursor* cursor = wl_cursor_theme_get_cursor(theme, cursorName); - if (!cursor) - return; + if (_glfw.wl.cursorPreviousName != cursorName) + { + struct wl_surface* surface = _glfw.wl.cursorSurface; + struct wl_cursor_theme* theme = _glfw.wl.cursorTheme; + int scale = 1; - // TODO: handle animated cursors too. - struct wl_cursor_image* image = cursor->images[0]; - if (!image) - return; + if (window->wl.contentScale > 1 && _glfw.wl.cursorThemeHiDPI) + { + // We only support up to scale=2 for now, since libwayland-cursor + // requires us to load a different theme for each size. + scale = 2; + theme = _glfw.wl.cursorThemeHiDPI; + } - struct wl_buffer* buffer = wl_cursor_image_get_buffer(image); - if (!buffer) - return; + struct wl_cursor* cursor = wl_cursor_theme_get_cursor(theme, cursorName); + if (!cursor) + return; - wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.pointerEnterSerial, - surface, - image->hotspot_x / scale, - image->hotspot_y / scale); - wl_surface_set_buffer_scale(surface, scale); - wl_surface_attach(surface, buffer, 0, 0); - wl_surface_damage(surface, 0, 0, image->width, image->height); - wl_surface_commit(surface); + // TODO: handle animated cursors too. + struct wl_cursor_image* image = cursor->images[0]; + if (!image) + return; - _glfw.wl.cursorPreviousName = cursorName; + struct wl_buffer* buffer = wl_cursor_image_get_buffer(image); + if (!buffer) + return; + + wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.pointerEnterSerial, + surface, + image->hotspot_x / scale, + image->hotspot_y / scale); + wl_surface_set_buffer_scale(surface, scale); + wl_surface_attach(surface, buffer, 0, 0); + wl_surface_damage(surface, 0, 0, image->width, image->height); + wl_surface_commit(surface); + + _glfw.wl.cursorPreviousName = cursorName; + } } } @@ -1445,53 +1458,56 @@ static void pointerHandleButton(void* userData, return; } - if (button == BTN_LEFT) + if (window->wl.fallback.decorations) { - uint32_t edges = XDG_TOPLEVEL_RESIZE_EDGE_NONE; + if (button == BTN_LEFT) + { + uint32_t edges = XDG_TOPLEVEL_RESIZE_EDGE_NONE; - switch (window->wl.fallback.focus) - { - case GLFW_TOP_DECORATION: - if (window->wl.cursorPosY < GLFW_BORDER_SIZE) - edges = XDG_TOPLEVEL_RESIZE_EDGE_TOP; - else - xdg_toplevel_move(window->wl.xdg.toplevel, _glfw.wl.seat, serial); - break; - case GLFW_LEFT_DECORATION: - if (window->wl.cursorPosY < GLFW_BORDER_SIZE) - edges = XDG_TOPLEVEL_RESIZE_EDGE_TOP_LEFT; - else - edges = XDG_TOPLEVEL_RESIZE_EDGE_LEFT; - break; - case GLFW_RIGHT_DECORATION: - if (window->wl.cursorPosY < GLFW_BORDER_SIZE) - edges = XDG_TOPLEVEL_RESIZE_EDGE_TOP_RIGHT; - else - edges = XDG_TOPLEVEL_RESIZE_EDGE_RIGHT; - break; - case GLFW_BOTTOM_DECORATION: - if (window->wl.cursorPosX < GLFW_BORDER_SIZE) - edges = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_LEFT; - else if (window->wl.cursorPosX > window->wl.width + GLFW_BORDER_SIZE) - edges = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_RIGHT; - else - edges = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM; - break; + switch (window->wl.fallback.focus) + { + case GLFW_TOP_DECORATION: + if (window->wl.cursorPosY < GLFW_BORDER_SIZE) + edges = XDG_TOPLEVEL_RESIZE_EDGE_TOP; + else + xdg_toplevel_move(window->wl.xdg.toplevel, _glfw.wl.seat, serial); + break; + case GLFW_LEFT_DECORATION: + if (window->wl.cursorPosY < GLFW_BORDER_SIZE) + edges = XDG_TOPLEVEL_RESIZE_EDGE_TOP_LEFT; + else + edges = XDG_TOPLEVEL_RESIZE_EDGE_LEFT; + break; + case GLFW_RIGHT_DECORATION: + if (window->wl.cursorPosY < GLFW_BORDER_SIZE) + edges = XDG_TOPLEVEL_RESIZE_EDGE_TOP_RIGHT; + else + edges = XDG_TOPLEVEL_RESIZE_EDGE_RIGHT; + break; + case GLFW_BOTTOM_DECORATION: + if (window->wl.cursorPosX < GLFW_BORDER_SIZE) + edges = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_LEFT; + else if (window->wl.cursorPosX > window->wl.width + GLFW_BORDER_SIZE) + edges = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_RIGHT; + else + edges = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM; + break; + } + if (edges != XDG_TOPLEVEL_RESIZE_EDGE_NONE) + { + xdg_toplevel_resize(window->wl.xdg.toplevel, _glfw.wl.seat, + serial, edges); + } } - if (edges != XDG_TOPLEVEL_RESIZE_EDGE_NONE) + else if (button == BTN_RIGHT) { - xdg_toplevel_resize(window->wl.xdg.toplevel, _glfw.wl.seat, - serial, edges); - } - } - else if (button == BTN_RIGHT) - { - if (window->wl.xdg.toplevel) - { - xdg_toplevel_show_window_menu(window->wl.xdg.toplevel, - _glfw.wl.seat, serial, - window->wl.cursorPosX, - window->wl.cursorPosY); + if (window->wl.xdg.toplevel) + { + xdg_toplevel_show_window_menu(window->wl.xdg.toplevel, + _glfw.wl.seat, serial, + window->wl.cursorPosX, + window->wl.cursorPosY); + } } } } @@ -2199,7 +2215,7 @@ void _glfwSetWindowSizeLimitsWayland(_GLFWwindow* window, minwidth = minheight = 0; else { - if (window->wl.fallback.top.surface) + if (window->wl.fallback.decorations) { minwidth += GLFW_BORDER_SIZE * 2; minheight += GLFW_CAPTION_HEIGHT + GLFW_BORDER_SIZE; @@ -2210,7 +2226,7 @@ void _glfwSetWindowSizeLimitsWayland(_GLFWwindow* window, maxwidth = maxheight = 0; else { - if (window->wl.fallback.top.surface) + if (window->wl.fallback.decorations) { maxwidth += GLFW_BORDER_SIZE * 2; maxheight += GLFW_CAPTION_HEIGHT + GLFW_BORDER_SIZE; @@ -2273,7 +2289,7 @@ void _glfwGetWindowFrameSizeWayland(_GLFWwindow* window, int* left, int* top, int* right, int* bottom) { - if (window->wl.fallback.top.surface) + if (window->wl.fallback.decorations) { if (top) *top = GLFW_CAPTION_HEIGHT; From a268b4b3a45ecda64c04dff10c5d9dd603149b68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Wed, 7 Feb 2024 23:56:03 +0100 Subject: [PATCH 06/14] Wayland: Cleanup --- src/wl_platform.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/wl_platform.h b/src/wl_platform.h index e880d520..eb361027 100644 --- a/src/wl_platform.h +++ b/src/wl_platform.h @@ -406,14 +406,14 @@ typedef struct _GLFWwindowWayland struct zwp_locked_pointer_v1* lockedPointer; struct zwp_confined_pointer_v1* confinedPointer; - struct zwp_idle_inhibitor_v1* idleInhibitor; - struct xdg_activation_token_v1* activationToken; + struct zwp_idle_inhibitor_v1* idleInhibitor; + struct xdg_activation_token_v1* activationToken; struct { GLFWbool decorations; - struct wl_buffer* buffer; - _GLFWdecorationWayland top, left, right, bottom; - _GLFWdecorationSideWayland focus; + struct wl_buffer* buffer; + _GLFWdecorationWayland top, left, right, bottom; + _GLFWdecorationSideWayland focus; } fallback; } _GLFWwindowWayland; From 72164e6921fb0e333d773a0fdf93aa791792593f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Thu, 8 Feb 2024 00:22:26 +0100 Subject: [PATCH 07/14] Wayland: Remove fallback decoration edge enum --- src/wl_platform.h | 10 +--- src/wl_window.c | 135 +++++++++++++++++++++++----------------------- 2 files changed, 68 insertions(+), 77 deletions(-) diff --git a/src/wl_platform.h b/src/wl_platform.h index eb361027..0d5d3dfd 100644 --- a/src/wl_platform.h +++ b/src/wl_platform.h @@ -323,14 +323,6 @@ typedef void (* PFN_libdecor_state_free)(struct libdecor_state*); #define libdecor_state_new _glfw.wl.libdecor.libdecor_state_new_ #define libdecor_state_free _glfw.wl.libdecor.libdecor_state_free_ -typedef enum _GLFWdecorationSideWayland -{ - GLFW_TOP_DECORATION, - GLFW_LEFT_DECORATION, - GLFW_RIGHT_DECORATION, - GLFW_BOTTOM_DECORATION -} _GLFWdecorationSideWayland; - typedef struct _GLFWdecorationWayland { struct wl_surface* surface; @@ -413,7 +405,7 @@ typedef struct _GLFWwindowWayland GLFWbool decorations; struct wl_buffer* buffer; _GLFWdecorationWayland top, left, right, bottom; - _GLFWdecorationSideWayland focus; + struct wl_surface* focus; } fallback; } _GLFWwindowWayland; diff --git a/src/wl_window.c b/src/wl_window.c index c4d96b80..4071b4a5 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -1284,18 +1284,6 @@ static void pointerHandleEnter(void* userData, _GLFWwindow* window = wl_surface_get_user_data(surface); - if (window->wl.fallback.decorations) - { - if (surface == window->wl.fallback.top.surface) - window->wl.fallback.focus = GLFW_TOP_DECORATION; - else if (surface == window->wl.fallback.left.surface) - window->wl.fallback.focus = GLFW_LEFT_DECORATION; - else if (surface == window->wl.fallback.right.surface) - window->wl.fallback.focus = GLFW_RIGHT_DECORATION; - else if (surface == window->wl.fallback.bottom.surface) - window->wl.fallback.focus = GLFW_BOTTOM_DECORATION; - } - _glfw.wl.serial = serial; _glfw.wl.pointerEnterSerial = serial; _glfw.wl.pointerFocus = window; @@ -1306,6 +1294,11 @@ static void pointerHandleEnter(void* userData, _glfwSetCursorWayland(window, window->wl.currentCursor); _glfwInputCursorEnter(window, GLFW_TRUE); } + else + { + if (window->wl.fallback.decorations) + window->wl.fallback.focus = surface; + } } static void pointerHandleLeave(void* userData, @@ -1332,6 +1325,11 @@ static void pointerHandleLeave(void* userData, window->wl.hovered = GLFW_FALSE; _glfwInputCursorEnter(window, GLFW_FALSE); } + else + { + if (window->wl.fallback.decorations) + window->wl.fallback.focus = NULL; + } } static void pointerHandleMotion(void* userData, @@ -1363,36 +1361,35 @@ static void pointerHandleMotion(void* userData, { const char* cursorName = NULL; - switch (window->wl.fallback.focus) + if (window->wl.fallback.focus == window->wl.fallback.top.surface) { - case GLFW_TOP_DECORATION: - if (ypos < GLFW_BORDER_SIZE) - cursorName = "n-resize"; - else - cursorName = "left_ptr"; - break; - case GLFW_LEFT_DECORATION: - if (ypos < GLFW_BORDER_SIZE) - cursorName = "nw-resize"; - else - cursorName = "w-resize"; - break; - case GLFW_RIGHT_DECORATION: - if (ypos < GLFW_BORDER_SIZE) - cursorName = "ne-resize"; - else - cursorName = "e-resize"; - break; - case GLFW_BOTTOM_DECORATION: - if (xpos < GLFW_BORDER_SIZE) - cursorName = "sw-resize"; - else if (xpos > window->wl.width + GLFW_BORDER_SIZE) - cursorName = "se-resize"; - else - cursorName = "s-resize"; - break; - default: - assert(0); + if (ypos < GLFW_BORDER_SIZE) + cursorName = "n-resize"; + else + cursorName = "left_ptr"; + } + else if (window->wl.fallback.focus == window->wl.fallback.left.surface) + { + if (ypos < GLFW_BORDER_SIZE) + cursorName = "nw-resize"; + else + cursorName = "w-resize"; + } + else if (window->wl.fallback.focus == window->wl.fallback.right.surface) + { + if (ypos < GLFW_BORDER_SIZE) + cursorName = "ne-resize"; + else + cursorName = "e-resize"; + } + else if (window->wl.fallback.focus == window->wl.fallback.bottom.surface) + { + if (xpos < GLFW_BORDER_SIZE) + cursorName = "sw-resize"; + else if (xpos > window->wl.width + GLFW_BORDER_SIZE) + cursorName = "se-resize"; + else + cursorName = "s-resize"; } if (_glfw.wl.cursorPreviousName != cursorName) @@ -1464,35 +1461,37 @@ static void pointerHandleButton(void* userData, { uint32_t edges = XDG_TOPLEVEL_RESIZE_EDGE_NONE; - switch (window->wl.fallback.focus) + if (window->wl.fallback.focus == window->wl.fallback.top.surface) { - case GLFW_TOP_DECORATION: - if (window->wl.cursorPosY < GLFW_BORDER_SIZE) - edges = XDG_TOPLEVEL_RESIZE_EDGE_TOP; - else - xdg_toplevel_move(window->wl.xdg.toplevel, _glfw.wl.seat, serial); - break; - case GLFW_LEFT_DECORATION: - if (window->wl.cursorPosY < GLFW_BORDER_SIZE) - edges = XDG_TOPLEVEL_RESIZE_EDGE_TOP_LEFT; - else - edges = XDG_TOPLEVEL_RESIZE_EDGE_LEFT; - break; - case GLFW_RIGHT_DECORATION: - if (window->wl.cursorPosY < GLFW_BORDER_SIZE) - edges = XDG_TOPLEVEL_RESIZE_EDGE_TOP_RIGHT; - else - edges = XDG_TOPLEVEL_RESIZE_EDGE_RIGHT; - break; - case GLFW_BOTTOM_DECORATION: - if (window->wl.cursorPosX < GLFW_BORDER_SIZE) - edges = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_LEFT; - else if (window->wl.cursorPosX > window->wl.width + GLFW_BORDER_SIZE) - edges = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_RIGHT; - else - edges = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM; - break; + if (window->wl.cursorPosY < GLFW_BORDER_SIZE) + edges = XDG_TOPLEVEL_RESIZE_EDGE_TOP; + else + xdg_toplevel_move(window->wl.xdg.toplevel, _glfw.wl.seat, serial); } + else if (window->wl.fallback.focus == window->wl.fallback.left.surface) + { + if (window->wl.cursorPosY < GLFW_BORDER_SIZE) + edges = XDG_TOPLEVEL_RESIZE_EDGE_TOP_LEFT; + else + edges = XDG_TOPLEVEL_RESIZE_EDGE_LEFT; + } + else if (window->wl.fallback.focus == window->wl.fallback.right.surface) + { + if (window->wl.cursorPosY < GLFW_BORDER_SIZE) + edges = XDG_TOPLEVEL_RESIZE_EDGE_TOP_RIGHT; + else + edges = XDG_TOPLEVEL_RESIZE_EDGE_RIGHT; + } + else if (window->wl.fallback.focus == window->wl.fallback.bottom.surface) + { + if (window->wl.cursorPosX < GLFW_BORDER_SIZE) + edges = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_LEFT; + else if (window->wl.cursorPosX > window->wl.width + GLFW_BORDER_SIZE) + edges = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_RIGHT; + else + edges = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM; + } + if (edges != XDG_TOPLEVEL_RESIZE_EDGE_NONE) { xdg_toplevel_resize(window->wl.xdg.toplevel, _glfw.wl.seat, From e25c1cc74f79a49a98edc059c39b76f6577d4dc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Thu, 8 Feb 2024 00:39:13 +0100 Subject: [PATCH 08/14] Wayland: Make fallback concepts more distinct --- src/wl_platform.h | 6 +-- src/wl_window.c | 98 +++++++++++++++++++++++------------------------ 2 files changed, 52 insertions(+), 52 deletions(-) diff --git a/src/wl_platform.h b/src/wl_platform.h index 0d5d3dfd..37adcfd1 100644 --- a/src/wl_platform.h +++ b/src/wl_platform.h @@ -323,12 +323,12 @@ typedef void (* PFN_libdecor_state_free)(struct libdecor_state*); #define libdecor_state_new _glfw.wl.libdecor.libdecor_state_new_ #define libdecor_state_free _glfw.wl.libdecor.libdecor_state_free_ -typedef struct _GLFWdecorationWayland +typedef struct _GLFWfallbackEdgeWayland { struct wl_surface* surface; struct wl_subsurface* subsurface; struct wp_viewport* viewport; -} _GLFWdecorationWayland; +} _GLFWfallbackEdgeWayland; typedef struct _GLFWofferWayland { @@ -404,7 +404,7 @@ typedef struct _GLFWwindowWayland struct { GLFWbool decorations; struct wl_buffer* buffer; - _GLFWdecorationWayland top, left, right, bottom; + _GLFWfallbackEdgeWayland top, left, right, bottom; struct wl_surface* focus; } fallback; } _GLFWwindowWayland; diff --git a/src/wl_window.c b/src/wl_window.c index 4071b4a5..995c17a6 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -192,29 +192,28 @@ static struct wl_buffer* createShmBuffer(const GLFWimage* image) return buffer; } -static void createFallbackDecoration(_GLFWwindow* window, - _GLFWdecorationWayland* decoration, - struct wl_surface* parent, - struct wl_buffer* buffer, - int x, int y, - int width, int height) +static void createFallbackEdge(_GLFWwindow* window, + _GLFWfallbackEdgeWayland* edge, + struct wl_surface* parent, + struct wl_buffer* buffer, + int x, int y, + int width, int height) { - decoration->surface = wl_compositor_create_surface(_glfw.wl.compositor); - wl_surface_set_user_data(decoration->surface, window); - wl_proxy_set_tag((struct wl_proxy*) decoration->surface, &_glfw.wl.tag); - decoration->subsurface = - wl_subcompositor_get_subsurface(_glfw.wl.subcompositor, - decoration->surface, parent); - wl_subsurface_set_position(decoration->subsurface, x, y); - decoration->viewport = wp_viewporter_get_viewport(_glfw.wl.viewporter, - decoration->surface); - wp_viewport_set_destination(decoration->viewport, width, height); - wl_surface_attach(decoration->surface, buffer, 0, 0); + edge->surface = wl_compositor_create_surface(_glfw.wl.compositor); + wl_surface_set_user_data(edge->surface, window); + wl_proxy_set_tag((struct wl_proxy*) edge->surface, &_glfw.wl.tag); + edge->subsurface = wl_subcompositor_get_subsurface(_glfw.wl.subcompositor, + edge->surface, parent); + wl_subsurface_set_position(edge->subsurface, x, y); + edge->viewport = wp_viewporter_get_viewport(_glfw.wl.viewporter, + edge->surface); + wp_viewport_set_destination(edge->viewport, width, height); + wl_surface_attach(edge->surface, buffer, 0, 0); struct wl_region* region = wl_compositor_create_region(_glfw.wl.compositor); wl_region_add(region, 0, 0, width, height); - wl_surface_set_opaque_region(decoration->surface, region); - wl_surface_commit(decoration->surface); + wl_surface_set_opaque_region(edge->surface, region); + wl_surface_commit(edge->surface); wl_region_destroy(region); } @@ -231,47 +230,48 @@ static void createFallbackDecorations(_GLFWwindow* window) if (!window->wl.fallback.buffer) return; - createFallbackDecoration(window, &window->wl.fallback.top, window->wl.surface, - window->wl.fallback.buffer, - 0, -GLFW_CAPTION_HEIGHT, - window->wl.width, GLFW_CAPTION_HEIGHT); - createFallbackDecoration(window, &window->wl.fallback.left, window->wl.surface, - window->wl.fallback.buffer, - -GLFW_BORDER_SIZE, -GLFW_CAPTION_HEIGHT, - GLFW_BORDER_SIZE, window->wl.height + GLFW_CAPTION_HEIGHT); - createFallbackDecoration(window, &window->wl.fallback.right, window->wl.surface, - window->wl.fallback.buffer, - window->wl.width, -GLFW_CAPTION_HEIGHT, - GLFW_BORDER_SIZE, window->wl.height + GLFW_CAPTION_HEIGHT); - createFallbackDecoration(window, &window->wl.fallback.bottom, window->wl.surface, - window->wl.fallback.buffer, - -GLFW_BORDER_SIZE, window->wl.height, - window->wl.width + GLFW_BORDER_SIZE * 2, GLFW_BORDER_SIZE); + createFallbackEdge(window, &window->wl.fallback.top, window->wl.surface, + window->wl.fallback.buffer, + 0, -GLFW_CAPTION_HEIGHT, + window->wl.width, GLFW_CAPTION_HEIGHT); + createFallbackEdge(window, &window->wl.fallback.left, window->wl.surface, + window->wl.fallback.buffer, + -GLFW_BORDER_SIZE, -GLFW_CAPTION_HEIGHT, + GLFW_BORDER_SIZE, window->wl.height + GLFW_CAPTION_HEIGHT); + createFallbackEdge(window, &window->wl.fallback.right, window->wl.surface, + window->wl.fallback.buffer, + window->wl.width, -GLFW_CAPTION_HEIGHT, + GLFW_BORDER_SIZE, window->wl.height + GLFW_CAPTION_HEIGHT); + createFallbackEdge(window, &window->wl.fallback.bottom, window->wl.surface, + window->wl.fallback.buffer, + -GLFW_BORDER_SIZE, window->wl.height, + window->wl.width + GLFW_BORDER_SIZE * 2, GLFW_BORDER_SIZE); window->wl.fallback.decorations = GLFW_TRUE; } -static void destroyFallbackDecoration(_GLFWdecorationWayland* decoration) +static void destroyFallbackEdge(_GLFWfallbackEdgeWayland* edge) { - if (decoration->subsurface) - wl_subsurface_destroy(decoration->subsurface); - if (decoration->surface) - wl_surface_destroy(decoration->surface); - if (decoration->viewport) - wp_viewport_destroy(decoration->viewport); - decoration->surface = NULL; - decoration->subsurface = NULL; - decoration->viewport = NULL; + if (edge->subsurface) + wl_subsurface_destroy(edge->subsurface); + if (edge->surface) + wl_surface_destroy(edge->surface); + if (edge->viewport) + wp_viewport_destroy(edge->viewport); + + edge->surface = NULL; + edge->subsurface = NULL; + edge->viewport = NULL; } static void destroyFallbackDecorations(_GLFWwindow* window) { window->wl.fallback.decorations = GLFW_FALSE; - destroyFallbackDecoration(&window->wl.fallback.top); - destroyFallbackDecoration(&window->wl.fallback.left); - destroyFallbackDecoration(&window->wl.fallback.right); - destroyFallbackDecoration(&window->wl.fallback.bottom); + destroyFallbackEdge(&window->wl.fallback.top); + destroyFallbackEdge(&window->wl.fallback.left); + destroyFallbackEdge(&window->wl.fallback.right); + destroyFallbackEdge(&window->wl.fallback.bottom); } static void xdgDecorationHandleConfigure(void* userData, From 4c283e4a3c95e09659bf747c7624d075f3110f33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Thu, 8 Feb 2024 18:55:52 +0100 Subject: [PATCH 09/14] Wayland: Be more specific about scales We are about to introduce another scaling method (fractional-scale-v1), so it will become more important to be specific about what scales are used where and what their units are. This removes 'content scale' from window and monitor structs. A monitor (output) now has just a 'scale', which becomes a 'buffer scale' when applied to a window. A window now has a list of 'output scales' to select its buffer scale from. Content scales are calculated from the respective monitor or window when queried, even if the calculation right now is to just return the same value as before. --- src/wl_monitor.c | 16 ++++++------- src/wl_platform.h | 12 +++++----- src/wl_window.c | 57 ++++++++++++++++++++++++----------------------- 3 files changed, 43 insertions(+), 42 deletions(-) diff --git a/src/wl_monitor.c b/src/wl_monitor.c index 96527a48..56ea56d7 100644 --- a/src/wl_monitor.c +++ b/src/wl_monitor.c @@ -112,16 +112,16 @@ static void outputHandleScale(void* userData, { struct _GLFWmonitor* monitor = userData; - monitor->wl.contentScale = factor; + monitor->wl.scale = factor; for (_GLFWwindow* window = _glfw.windowListHead; window; window = window->next) { - for (int i = 0; i < window->wl.scaleCount; i++) + for (int i = 0; i < window->wl.outputScaleCount; i++) { - if (window->wl.scales[i].output == monitor->wl.output) + if (window->wl.outputScales[i].output == monitor->wl.output) { - window->wl.scales[i].factor = monitor->wl.contentScale; - _glfwUpdateContentScaleWayland(window); + window->wl.outputScales[i].factor = monitor->wl.scale; + _glfwUpdateBufferScaleFromOutputsWayland(window); break; } } @@ -176,7 +176,7 @@ void _glfwAddOutputWayland(uint32_t name, uint32_t version) // The actual name of this output will be set in the geometry handler _GLFWmonitor* monitor = _glfwAllocMonitor("", 0, 0); - monitor->wl.contentScale = 1; + monitor->wl.scale = 1; monitor->wl.output = output; monitor->wl.name = name; @@ -207,9 +207,9 @@ void _glfwGetMonitorContentScaleWayland(_GLFWmonitor* monitor, float* xscale, float* yscale) { if (xscale) - *xscale = (float) monitor->wl.contentScale; + *xscale = (float) monitor->wl.scale; if (yscale) - *yscale = (float) monitor->wl.contentScale; + *yscale = (float) monitor->wl.scale; } void _glfwGetMonitorWorkareaWayland(_GLFWmonitor* monitor, diff --git a/src/wl_platform.h b/src/wl_platform.h index 37adcfd1..23fd8c14 100644 --- a/src/wl_platform.h +++ b/src/wl_platform.h @@ -389,10 +389,10 @@ typedef struct _GLFWwindowWayland // We need to track the monitors the window spans on to calculate the // optimal scaling factor. - int contentScale; - _GLFWscaleWayland* scales; - int scaleCount; - int scaleSize; + int bufferScale; + _GLFWscaleWayland* outputScales; + int outputScaleCount; + int outputScaleSize; struct zwp_relative_pointer_v1* relativePointer; struct zwp_locked_pointer_v1* lockedPointer; @@ -586,7 +586,7 @@ typedef struct _GLFWmonitorWayland int x; int y; - int contentScale; + int scale; } _GLFWmonitorWayland; // Wayland-specific per-cursor data @@ -677,7 +677,7 @@ GLFWbool _glfwGetGammaRampWayland(_GLFWmonitor* monitor, GLFWgammaramp* ramp); void _glfwSetGammaRampWayland(_GLFWmonitor* monitor, const GLFWgammaramp* ramp); void _glfwAddOutputWayland(uint32_t name, uint32_t version); -void _glfwUpdateContentScaleWayland(_GLFWwindow* window); +void _glfwUpdateBufferScaleFromOutputsWayland(_GLFWwindow* window); void _glfwAddSeatListenerWayland(struct wl_seat* seat); void _glfwAddDataDeviceListenerWayland(struct wl_data_device* device); diff --git a/src/wl_window.c b/src/wl_window.c index 995c17a6..e5699ab3 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -312,7 +312,7 @@ static void setContentAreaOpaque(_GLFWwindow* window) static void resizeFramebuffer(_GLFWwindow* window) { - int scale = window->wl.contentScale; + int scale = window->wl.bufferScale; int scaledWidth = window->wl.width * scale; int scaledHeight = window->wl.height * scale; @@ -357,7 +357,7 @@ static void resizeWindow(_GLFWwindow* window) } } -void _glfwUpdateContentScaleWayland(_GLFWwindow* window) +void _glfwUpdateBufferScaleFromOutputsWayland(_GLFWwindow* window) { if (wl_compositor_get_version(_glfw.wl.compositor) < WL_SURFACE_SET_BUFFER_SCALE_SINCE_VERSION) @@ -368,13 +368,13 @@ void _glfwUpdateContentScaleWayland(_GLFWwindow* window) // Get the scale factor from the highest scale monitor. int maxScale = 1; - for (int i = 0; i < window->wl.scaleCount; i++) - maxScale = _glfw_max(window->wl.scales[i].factor, maxScale); + for (int i = 0; i < window->wl.outputScaleCount; i++) + maxScale = _glfw_max(window->wl.outputScales[i].factor, maxScale); // Only change the framebuffer size if the scale changed. - if (window->wl.contentScale != maxScale) + if (window->wl.bufferScale != maxScale) { - window->wl.contentScale = maxScale; + window->wl.bufferScale = maxScale; wl_surface_set_buffer_scale(window->wl.surface, maxScale); _glfwInputWindowContentScale(window, maxScale, maxScale); resizeFramebuffer(window); @@ -396,19 +396,19 @@ static void surfaceHandleEnter(void* userData, if (!window || !monitor) return; - if (window->wl.scaleCount + 1 > window->wl.scaleSize) + if (window->wl.outputScaleCount + 1 > window->wl.outputScaleSize) { - window->wl.scaleSize++; - window->wl.scales = - _glfw_realloc(window->wl.scales, - window->wl.scaleSize * sizeof(_GLFWscaleWayland)); + window->wl.outputScaleSize++; + window->wl.outputScales = + _glfw_realloc(window->wl.outputScales, + window->wl.outputScaleSize * sizeof(_GLFWscaleWayland)); } - window->wl.scaleCount++; - window->wl.scales[window->wl.scaleCount - 1].factor = monitor->wl.contentScale; - window->wl.scales[window->wl.scaleCount - 1].output = output; + window->wl.outputScaleCount++; + window->wl.outputScales[window->wl.outputScaleCount - 1] = + (_GLFWscaleWayland) { output, monitor->wl.scale }; - _glfwUpdateContentScaleWayland(window); + _glfwUpdateBufferScaleFromOutputsWayland(window); } static void surfaceHandleLeave(void* userData, @@ -420,17 +420,18 @@ static void surfaceHandleLeave(void* userData, _GLFWwindow* window = userData; - for (int i = 0; i < window->wl.scaleCount; i++) + for (int i = 0; i < window->wl.outputScaleCount; i++) { - if (window->wl.scales[i].output == output) + if (window->wl.outputScales[i].output == output) { - window->wl.scales[i] = window->wl.scales[window->wl.scaleCount - 1]; - window->wl.scaleCount--; + window->wl.outputScales[i] = + window->wl.outputScales[window->wl.outputScaleCount - 1]; + window->wl.outputScaleCount--; break; } } - _glfwUpdateContentScaleWayland(window); + _glfwUpdateBufferScaleFromOutputsWayland(window); } static const struct wl_surface_listener surfaceListener = @@ -970,7 +971,7 @@ static GLFWbool createNativeSurface(_GLFWwindow* window, window->wl.width = wndconfig->width; window->wl.height = wndconfig->height; - window->wl.contentScale = 1; + window->wl.bufferScale = 1; window->wl.title = _glfw_strdup(wndconfig->title); window->wl.appId = _glfw_strdup(wndconfig->wl.appId); @@ -997,7 +998,7 @@ static void setCursorImage(_GLFWwindow* window, buffer = cursorWayland->buffer; else { - if (window->wl.contentScale > 1 && cursorWayland->cursorHiDPI) + if (window->wl.bufferScale > 1 && cursorWayland->cursorHiDPI) { wlCursor = cursorWayland->cursorHiDPI; scale = 2; @@ -1398,7 +1399,7 @@ static void pointerHandleMotion(void* userData, struct wl_cursor_theme* theme = _glfw.wl.cursorTheme; int scale = 1; - if (window->wl.contentScale > 1 && _glfw.wl.cursorThemeHiDPI) + if (window->wl.bufferScale > 1 && _glfw.wl.cursorThemeHiDPI) { // We only support up to scale=2 for now, since libwayland-cursor // requires us to load a different theme for each size. @@ -2120,7 +2121,7 @@ void _glfwDestroyWindowWayland(_GLFWwindow* window) _glfw_free(window->wl.title); _glfw_free(window->wl.appId); - _glfw_free(window->wl.scales); + _glfw_free(window->wl.outputScales); } void _glfwSetWindowTitleWayland(_GLFWwindow* window, const char* title) @@ -2279,9 +2280,9 @@ void _glfwGetFramebufferSizeWayland(_GLFWwindow* window, int* width, int* height { _glfwGetWindowSizeWayland(window, width, height); if (width) - *width *= window->wl.contentScale; + *width *= window->wl.bufferScale; if (height) - *height *= window->wl.contentScale; + *height *= window->wl.bufferScale; } void _glfwGetWindowFrameSizeWayland(_GLFWwindow* window, @@ -2305,9 +2306,9 @@ void _glfwGetWindowContentScaleWayland(_GLFWwindow* window, float* xscale, float* yscale) { if (xscale) - *xscale = (float) window->wl.contentScale; + *xscale = (float) window->wl.bufferScale; if (yscale) - *yscale = (float) window->wl.contentScale; + *yscale = (float) window->wl.bufferScale; } void _glfwIconifyWindowWayland(_GLFWwindow* window) From 1be7bc546b41efcab84210f15ddb7cdf25171cda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Thu, 8 Feb 2024 19:36:27 +0100 Subject: [PATCH 10/14] Wayland: Clean up data types related to scales --- src/wl_monitor.c | 2 +- src/wl_platform.h | 10 +++++----- src/wl_window.c | 8 ++++---- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/wl_monitor.c b/src/wl_monitor.c index 56ea56d7..66639301 100644 --- a/src/wl_monitor.c +++ b/src/wl_monitor.c @@ -116,7 +116,7 @@ static void outputHandleScale(void* userData, for (_GLFWwindow* window = _glfw.windowListHead; window; window = window->next) { - for (int i = 0; i < window->wl.outputScaleCount; i++) + for (size_t i = 0; i < window->wl.outputScaleCount; i++) { if (window->wl.outputScales[i].output == monitor->wl.output) { diff --git a/src/wl_platform.h b/src/wl_platform.h index 23fd8c14..d54d394a 100644 --- a/src/wl_platform.h +++ b/src/wl_platform.h @@ -340,7 +340,7 @@ typedef struct _GLFWofferWayland typedef struct _GLFWscaleWayland { struct wl_output* output; - int factor; + int32_t factor; } _GLFWscaleWayland; // Wayland-specific per-window data @@ -389,10 +389,10 @@ typedef struct _GLFWwindowWayland // We need to track the monitors the window spans on to calculate the // optimal scaling factor. - int bufferScale; + int32_t bufferScale; _GLFWscaleWayland* outputScales; - int outputScaleCount; - int outputScaleSize; + size_t outputScaleCount; + size_t outputScaleSize; struct zwp_relative_pointer_v1* relativePointer; struct zwp_locked_pointer_v1* lockedPointer; @@ -586,7 +586,7 @@ typedef struct _GLFWmonitorWayland int x; int y; - int scale; + int32_t scale; } _GLFWmonitorWayland; // Wayland-specific per-cursor data diff --git a/src/wl_window.c b/src/wl_window.c index e5699ab3..71be06b7 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -312,7 +312,7 @@ static void setContentAreaOpaque(_GLFWwindow* window) static void resizeFramebuffer(_GLFWwindow* window) { - int scale = window->wl.bufferScale; + int32_t scale = window->wl.bufferScale; int scaledWidth = window->wl.width * scale; int scaledHeight = window->wl.height * scale; @@ -366,9 +366,9 @@ void _glfwUpdateBufferScaleFromOutputsWayland(_GLFWwindow* window) } // Get the scale factor from the highest scale monitor. - int maxScale = 1; + int32_t maxScale = 1; - for (int i = 0; i < window->wl.outputScaleCount; i++) + for (size_t i = 0; i < window->wl.outputScaleCount; i++) maxScale = _glfw_max(window->wl.outputScales[i].factor, maxScale); // Only change the framebuffer size if the scale changed. @@ -420,7 +420,7 @@ static void surfaceHandleLeave(void* userData, _GLFWwindow* window = userData; - for (int i = 0; i < window->wl.outputScaleCount; i++) + for (size_t i = 0; i < window->wl.outputScaleCount; i++) { if (window->wl.outputScales[i].output == output) { From 9953f7ead17011ccc4f747291ef48de8d2ed7184 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Thu, 8 Feb 2024 22:07:11 +0100 Subject: [PATCH 11/14] Wayland: Cache framebuffer size The calculation of framebuffer size is about to get more complicated with the introduction of fractional-scale-v1, so only do it in one place. This is also a tiny preparation for eventually behaving better towards wl_egl_window_resize. --- src/wl_platform.h | 1 + src/wl_window.c | 25 +++++++++++++++---------- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/src/wl_platform.h b/src/wl_platform.h index d54d394a..b1303d9f 100644 --- a/src/wl_platform.h +++ b/src/wl_platform.h @@ -348,6 +348,7 @@ typedef struct _GLFWscaleWayland typedef struct _GLFWwindowWayland { int width, height; + int fbWidth, fbHeight; GLFWbool visible; GLFWbool maximized; GLFWbool activated; diff --git a/src/wl_window.c b/src/wl_window.c index 71be06b7..13879a12 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -312,17 +312,21 @@ static void setContentAreaOpaque(_GLFWwindow* window) static void resizeFramebuffer(_GLFWwindow* window) { - int32_t scale = window->wl.bufferScale; - int scaledWidth = window->wl.width * scale; - int scaledHeight = window->wl.height * scale; + window->wl.fbWidth = window->wl.width * window->wl.bufferScale; + window->wl.fbHeight = window->wl.height * window->wl.bufferScale; if (window->wl.egl.window) - wl_egl_window_resize(window->wl.egl.window, scaledWidth, scaledHeight, 0, 0); + { + wl_egl_window_resize(window->wl.egl.window, + window->wl.fbWidth, + window->wl.fbHeight, + 0, 0); + } if (!window->wl.transparent) setContentAreaOpaque(window); - _glfwInputFramebufferSize(window, scaledWidth, scaledHeight); + _glfwInputFramebufferSize(window, window->wl.fbWidth, window->wl.fbHeight); } static void resizeWindow(_GLFWwindow* window) @@ -971,6 +975,8 @@ static GLFWbool createNativeSurface(_GLFWwindow* window, window->wl.width = wndconfig->width; window->wl.height = wndconfig->height; + window->wl.fbWidth = wndconfig->width; + window->wl.fbHeight = wndconfig->height; window->wl.bufferScale = 1; window->wl.title = _glfw_strdup(wndconfig->title); window->wl.appId = _glfw_strdup(wndconfig->wl.appId); @@ -2044,8 +2050,8 @@ GLFWbool _glfwCreateWindowWayland(_GLFWwindow* window, ctxconfig->source == GLFW_NATIVE_CONTEXT_API) { window->wl.egl.window = wl_egl_window_create(window->wl.surface, - wndconfig->width, - wndconfig->height); + window->wl.fbWidth, + window->wl.fbHeight); if (!window->wl.egl.window) { _glfwInputError(GLFW_PLATFORM_ERROR, @@ -2278,11 +2284,10 @@ void _glfwSetWindowAspectRatioWayland(_GLFWwindow* window, int numer, int denom) void _glfwGetFramebufferSizeWayland(_GLFWwindow* window, int* width, int* height) { - _glfwGetWindowSizeWayland(window, width, height); if (width) - *width *= window->wl.bufferScale; + *width = window->wl.fbWidth; if (height) - *height *= window->wl.bufferScale; + *height = window->wl.fbHeight; } void _glfwGetWindowFrameSizeWayland(_GLFWwindow* window, From edd38207a67ea7d5c9c784a3304d044ab16fc06a Mon Sep 17 00:00:00 2001 From: Victor Chernyakin <56512186+LocalSpook@users.noreply.github.com> Date: Fri, 15 Dec 2023 00:53:32 -0700 Subject: [PATCH 12/14] Linux: Set O_CLOEXEC on evdev fd Closes #2446 --- src/linux_joystick.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/linux_joystick.c b/src/linux_joystick.c index c67f3d77..07d41d37 100644 --- a/src/linux_joystick.c +++ b/src/linux_joystick.c @@ -135,7 +135,7 @@ static GLFWbool openJoystickDevice(const char* path) } _GLFWjoystickLinux linjs = {0}; - linjs.fd = open(path, O_RDONLY | O_NONBLOCK); + linjs.fd = open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC); if (linjs.fd == -1) return GLFW_FALSE; From 6565c0cc04837d3b95dc9d552f73f9bfcf8c8e6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Fri, 9 Feb 2024 14:13:32 +0100 Subject: [PATCH 13/14] Update changelog and add credit Related to #2446 --- CONTRIBUTORS.md | 1 + README.md | 1 + 2 files changed, 2 insertions(+) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 6f426cdd..273d3d49 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -33,6 +33,7 @@ video tutorials. - David Carlier - Arturo Castro - Chi-kwan Chan + - Victor Chernyakin - TheChocolateOre - Ali Chraghi - Joseph Chua diff --git a/README.md b/README.md index 177960f6..3cafbc95 100644 --- a/README.md +++ b/README.md @@ -185,6 +185,7 @@ information on what to include when reporting a bug. fallback window decoration - [X11] Bugfix: Termination would segfault if the IM had been destroyed - [X11] Bugfix: Any IM started after initialization would not be detected + - [Linux] Bugfix: Joystick evdev fds remained open in forks (#2446) - [POSIX] Removed use of deprecated function `gettimeofday` - [POSIX] Bugfix: `CLOCK_MONOTONIC` was not correctly tested for or enabled - [WGL] Disabled the DWM swap interval hack for Windows 8 and later (#1072) From 6f1ddf51a130f2dee6ade5fa4d8217e4071124e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Sun, 11 Feb 2024 12:59:08 +0100 Subject: [PATCH 14/14] Wayland: Remove unused struct member --- src/wl_platform.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/wl_platform.h b/src/wl_platform.h index b1303d9f..3b9a3a3c 100644 --- a/src/wl_platform.h +++ b/src/wl_platform.h @@ -379,7 +379,6 @@ typedef struct _GLFWwindowWayland struct { struct libdecor_frame* frame; - int mode; } libdecor; _GLFWcursor* currentCursor;