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.
This commit is contained in:
Camilla Löwy 2025-07-18 15:28:36 +02:00
parent 5245180c56
commit ddbb8e0f2c
3 changed files with 16 additions and 7 deletions

View File

@ -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: Reset key repeat timer when window destroyed (#2741,#2727)
- [Wayland] Bugfix: Memory would leak if reading a data offer failed midway - [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: 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) - [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 Vulkan 'window' surface creation via `VK_EXT_headless_surface`
- [Null] Added EGL context creation on Mesa via `EGL_MESA_platform_surfaceless` - [Null] Added EGL context creation on Mesa via `EGL_MESA_platform_surfaceless`

View File

@ -413,6 +413,7 @@ typedef struct _GLFWwindowWayland
struct wl_buffer* buffer; struct wl_buffer* buffer;
_GLFWfallbackEdgeWayland top, left, right, bottom; _GLFWfallbackEdgeWayland top, left, right, bottom;
struct wl_surface* focus; struct wl_surface* focus;
wl_fixed_t pointerX, pointerY;
} fallback; } fallback;
} _GLFWwindowWayland; } _GLFWwindowWayland;

View File

@ -1446,11 +1446,11 @@ static void pointerHandleMotion(void* userData,
const double xpos = wl_fixed_to_double(sx); const double xpos = wl_fixed_to_double(sx);
const double ypos = wl_fixed_to_double(sy); const double ypos = wl_fixed_to_double(sy);
window->wl.cursorPosX = xpos;
window->wl.cursorPosY = ypos;
if (window->wl.hovered) if (window->wl.hovered)
{ {
window->wl.cursorPosX = xpos;
window->wl.cursorPosY = ypos;
_glfw.wl.cursorPreviousName = NULL; _glfw.wl.cursorPreviousName = NULL;
_glfwInputCursorPos(window, xpos, ypos); _glfwInputCursorPos(window, xpos, ypos);
return; return;
@ -1458,6 +1458,9 @@ static void pointerHandleMotion(void* userData,
if (window->wl.fallback.decorations) if (window->wl.fallback.decorations)
{ {
window->wl.fallback.pointerX = sx;
window->wl.fallback.pointerY = sy;
const char* cursorName = "left_ptr"; const char* cursorName = "left_ptr";
if (window->resizable) if (window->resizable)
@ -1557,36 +1560,39 @@ static void pointerHandleButton(void* userData,
if (window->wl.fallback.decorations) 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) if (button == BTN_LEFT)
{ {
uint32_t edges = XDG_TOPLEVEL_RESIZE_EDGE_NONE; uint32_t edges = XDG_TOPLEVEL_RESIZE_EDGE_NONE;
if (window->wl.fallback.focus == window->wl.fallback.top.surface) 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; edges = XDG_TOPLEVEL_RESIZE_EDGE_TOP;
else else
xdg_toplevel_move(window->wl.xdg.toplevel, _glfw.wl.seat, serial); xdg_toplevel_move(window->wl.xdg.toplevel, _glfw.wl.seat, serial);
} }
else if (window->wl.fallback.focus == window->wl.fallback.left.surface) 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; edges = XDG_TOPLEVEL_RESIZE_EDGE_TOP_LEFT;
else else
edges = XDG_TOPLEVEL_RESIZE_EDGE_LEFT; edges = XDG_TOPLEVEL_RESIZE_EDGE_LEFT;
} }
else if (window->wl.fallback.focus == window->wl.fallback.right.surface) 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; edges = XDG_TOPLEVEL_RESIZE_EDGE_TOP_RIGHT;
else else
edges = XDG_TOPLEVEL_RESIZE_EDGE_RIGHT; edges = XDG_TOPLEVEL_RESIZE_EDGE_RIGHT;
} }
else if (window->wl.fallback.focus == window->wl.fallback.bottom.surface) 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; 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; edges = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_RIGHT;
else else
edges = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM; edges = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM;