Fix Wayland cursor offset when the cursor shape changes

The wayland protocol spec
https://wayland.freedesktop.org/docs/html/apa.html#protocol-spec-wl_pointer

States that `set_cursor` must be called with the serial number of the
`enter` event. However, GLFW is passing in the serial number of the latest
received event, which does not meet the protocol spec.

As a result, `set_cursor` calls were simply ignored by the compositor.

This fix complies with the protocol more closely by specifically caching the
`enter` event serial, and using it for all `set_cursor` calls.

Fixes #1706
This commit is contained in:
Waris Boonyasiriwat 2021-05-12 00:30:14 -07:00
parent 9a3a8bc267
commit fc6e6910d7
4 changed files with 10 additions and 5 deletions

View File

@ -229,6 +229,7 @@ information on what to include when reporting a bug.
- [Wayland] Bugfix: Client-Side Decorations were destroyed in the wrong worder
(#1798)
- [Wayland] Bugfix: Monitors physical size could report zero (#1784,#1792)
- [Wayland] Bugfix: Non-arrow cursors are offset from the hotspot (#1706)
- [POSIX] Bugfix: `CLOCK_MONOTONIC` was not correctly tested for or enabled
- [NSGL] Removed enforcement of forward-compatible flag for core contexts
- [NSGL] Bugfix: `GLFW_COCOA_RETINA_FRAMEBUFFER` had no effect on newer
@ -455,7 +456,7 @@ skills.
- Torsten Walluhn
- Patrick Walton
- Xo Wang
- Waris
- Waris Boonyasiriwat
- Jay Weisskopf
- Frank Wille
- Andy Williams
@ -470,6 +471,8 @@ skills.
- Jonas Ådahl
- Lasse Öörni
- Leonard König
- Koray Kilinc
- Joseph Chua
- All the unmentioned and anonymous contributors in the GLFW community, for bug
reports, patches, feedback, testing and encouragement

View File

@ -105,6 +105,7 @@ static void pointerHandleEnter(void* data,
window->wl.decorations.focus = focus;
_glfw.wl.serial = serial;
_glfw.wl.pointerEnterSerial = serial;
_glfw.wl.pointerFocus = window;
window->wl.hovered = GLFW_TRUE;
@ -164,7 +165,7 @@ static void setCursor(_GLFWwindow* window, const char* name)
buffer = wl_cursor_image_get_buffer(image);
if (!buffer)
return;
wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.serial,
wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.pointerEnterSerial,
surface,
image->hotspot_x / scale,
image->hotspot_y / scale);

View File

@ -245,6 +245,7 @@ typedef struct _GLFWlibraryWayland
const char* cursorPreviousName;
int cursorTimerfd;
uint32_t serial;
uint32_t pointerEnterSerial;
int32_t keyboardRepeatRate;
int32_t keyboardRepeatDelay;

View File

@ -675,7 +675,7 @@ static void setCursorImage(_GLFWwindow* window,
cursorWayland->yhot = image->hotspot_y;
}
wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.serial,
wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.pointerEnterSerial,
surface,
cursorWayland->xhot / scale,
cursorWayland->yhot / scale);
@ -1440,7 +1440,7 @@ static void lockPointer(_GLFWwindow* window)
window->wl.pointerLock.relativePointer = relativePointer;
window->wl.pointerLock.lockedPointer = lockedPointer;
wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.serial,
wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.pointerEnterSerial,
NULL, 0, 0);
}
@ -1504,7 +1504,7 @@ void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
}
else if (window->cursorMode == GLFW_CURSOR_HIDDEN)
{
wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.serial, NULL, 0, 0);
wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.pointerEnterSerial, NULL, 0, 0);
}
}