From ddbb8e0f2ccf20ada8e91f28b0b2c1f60c6699f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Fri, 18 Jul 2025 15:28:36 +0200 Subject: [PATCH] Wayland: Fix fallback decoration cursor position If fallback decorations were in use, pointer motion over a decoration surface would cause glfwGetCursorPos to provide incorrect cursor positions. The cursor position is now only updated when the pointer is over the content area of the window, similar to libdecor and XDG decorations. --- README.md | 2 ++ src/wl_platform.h | 1 + src/wl_window.c | 20 +++++++++++++------- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 456c7533..a3fd32b2 100644 --- a/README.md +++ b/README.md @@ -135,6 +135,8 @@ information on what to include when reporting a bug. - [Wayland] Bugfix: Reset key repeat timer when window destroyed (#2741,#2727) - [Wayland] Bugfix: Memory would leak if reading a data offer failed midway - [Wayland] Bugfix: Keyboard leave event handler now processes key repeats (#2736) + - [Wayland] Bugfix: Retrieved cursor position would be incorrect when hovering over + fallback decorations - [X11] Bugfix: Running without a WM could trigger an assert (#2593,#2601,#2631) - [Null] Added Vulkan 'window' surface creation via `VK_EXT_headless_surface` - [Null] Added EGL context creation on Mesa via `EGL_MESA_platform_surfaceless` diff --git a/src/wl_platform.h b/src/wl_platform.h index eb68f7e8..a85a7c2a 100644 --- a/src/wl_platform.h +++ b/src/wl_platform.h @@ -413,6 +413,7 @@ typedef struct _GLFWwindowWayland struct wl_buffer* buffer; _GLFWfallbackEdgeWayland top, left, right, bottom; struct wl_surface* focus; + wl_fixed_t pointerX, pointerY; } fallback; } _GLFWwindowWayland; diff --git a/src/wl_window.c b/src/wl_window.c index 50f770e6..677efd79 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -1446,11 +1446,11 @@ static void pointerHandleMotion(void* userData, const double xpos = wl_fixed_to_double(sx); const double ypos = wl_fixed_to_double(sy); - window->wl.cursorPosX = xpos; - window->wl.cursorPosY = ypos; if (window->wl.hovered) { + window->wl.cursorPosX = xpos; + window->wl.cursorPosY = ypos; _glfw.wl.cursorPreviousName = NULL; _glfwInputCursorPos(window, xpos, ypos); return; @@ -1458,6 +1458,9 @@ static void pointerHandleMotion(void* userData, if (window->wl.fallback.decorations) { + window->wl.fallback.pointerX = sx; + window->wl.fallback.pointerY = sy; + const char* cursorName = "left_ptr"; if (window->resizable) @@ -1557,36 +1560,39 @@ static void pointerHandleButton(void* userData, if (window->wl.fallback.decorations) { + const double xpos = wl_fixed_to_double(window->wl.fallback.pointerX); + const double ypos = wl_fixed_to_double(window->wl.fallback.pointerY); + if (button == BTN_LEFT) { uint32_t edges = XDG_TOPLEVEL_RESIZE_EDGE_NONE; if (window->wl.fallback.focus == window->wl.fallback.top.surface) { - if (window->wl.cursorPosY < GLFW_BORDER_SIZE) + if (ypos < 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) + if (ypos < 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) + if (ypos < 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) + if (xpos < GLFW_BORDER_SIZE) edges = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_LEFT; - else if (window->wl.cursorPosX > window->wl.width + GLFW_BORDER_SIZE) + else if (xpos > window->wl.width + GLFW_BORDER_SIZE) edges = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_RIGHT; else edges = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM;