Wayland: Improve support for discrete scrolling

This adds support for high-resolution scroll input scaled to match
legacy discrete scroll input.  It is available on compositors that
support wl_seat version 8 or later.

High-resolution "discrete" values now replace non-scaled scroll
values when available.
This commit is contained in:
Camilla Löwy
2026-02-05 20:05:19 +01:00
parent 0d15b54c7a
commit 05f57c0bee
4 changed files with 30 additions and 8 deletions
+1
View File
@@ -152,6 +152,7 @@ information on what to include when reporting a bug.
- [Wayland] Bugfix: The `libwayland-client` library was not unloaded at termination - [Wayland] Bugfix: The `libwayland-client` library was not unloaded at termination
- [Wayland] Bugfix: Scroll events were sent twice on some versions of GNOME (#2494) - [Wayland] Bugfix: Scroll events were sent twice on some versions of GNOME (#2494)
- [Wayland] Bugfix: Two-dimensional scroll input was emitted as separate axes - [Wayland] Bugfix: Two-dimensional scroll input was emitted as separate axes
- [Wayland] Bugfix: Mouse wheel scroll distance was incorrect on some compositors
- [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)
- [X11] Bugfix: Occasional crash when an idle display awakes (#2766) - [X11] Bugfix: Occasional crash when an idle display awakes (#2766)
- [X11] Bugfix: Prevent BadWindow when creating small windows with a content scale - [X11] Bugfix: Prevent BadWindow when creating small windows with a content scale
+1 -1
View File
@@ -135,7 +135,7 @@ static void registryHandleGlobal(void* userData,
{ {
_glfw.wl.seat = _glfw.wl.seat =
wl_registry_bind(registry, name, &wl_seat_interface, wl_registry_bind(registry, name, &wl_seat_interface,
_glfw_min(5, version)); _glfw_min(8, version));
_glfwAddSeatListenerWayland(_glfw.wl.seat); _glfwAddSeatListenerWayland(_glfw.wl.seat);
} }
} }
+2
View File
@@ -478,6 +478,8 @@ typedef struct _GLFWlibraryWayland
double pointerY; double pointerY;
double scrollX; double scrollX;
double scrollY; double scrollY;
double discreteX;
double discreteY;
int button; int button;
int action; int action;
} pending; } pending;
+26 -7
View File
@@ -55,10 +55,11 @@
#define GLFW_BORDER_SIZE 4 #define GLFW_BORDER_SIZE 4
#define GLFW_CAPTION_HEIGHT 24 #define GLFW_CAPTION_HEIGHT 24
#define GLFW_PENDING_SURFACE 1 #define GLFW_PENDING_SURFACE 1
#define GLFW_PENDING_BUTTON 2 #define GLFW_PENDING_BUTTON 2
#define GLFW_PENDING_MOTION 4 #define GLFW_PENDING_MOTION 4
#define GLFW_PENDING_SCROLL 8 #define GLFW_PENDING_SCROLL 8
#define GLFW_PENDING_DISCRETE 16
static int createTmpfileCloexec(char* tmpname) static int createTmpfileCloexec(char* tmpname)
{ {
@@ -1740,7 +1741,9 @@ static void pointerHandleFrame(void* userData, struct wl_pointer* pointer)
if (_glfw.wl.pending.events & GLFW_PENDING_BUTTON) if (_glfw.wl.pending.events & GLFW_PENDING_BUTTON)
processPointerButton(_glfw.wl.pending.button, _glfw.wl.pending.action); processPointerButton(_glfw.wl.pending.button, _glfw.wl.pending.action);
if (_glfw.wl.pending.events & GLFW_PENDING_SCROLL) if (_glfw.wl.pending.events & GLFW_PENDING_DISCRETE)
processPointerScroll(_glfw.wl.pending.discreteX, _glfw.wl.pending.discreteY);
else if (_glfw.wl.pending.events & GLFW_PENDING_SCROLL)
processPointerScroll(_glfw.wl.pending.scrollX, _glfw.wl.pending.scrollY); processPointerScroll(_glfw.wl.pending.scrollX, _glfw.wl.pending.scrollY);
memset(&_glfw.wl.pending, 0, sizeof(_glfw.wl.pending)); memset(&_glfw.wl.pending, 0, sizeof(_glfw.wl.pending));
@@ -1766,6 +1769,21 @@ static void pointerHandleAxisDiscrete(void* userData,
{ {
} }
static void pointerHandleAxisValue120(void* data,
struct wl_pointer* pointer,
uint32_t axis,
int32_t value120)
{
if (!_glfw.wl.pointerSurface)
return;
_glfw.wl.pending.events |= GLFW_PENDING_DISCRETE;
if (axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL)
_glfw.wl.pending.discreteX = -(value120 / 120.0);
else if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL)
_glfw.wl.pending.discreteY = -(value120 / 120.0);
}
static const struct wl_pointer_listener pointerListener = static const struct wl_pointer_listener pointerListener =
{ {
pointerHandleEnter, pointerHandleEnter,
@@ -1776,7 +1794,8 @@ static const struct wl_pointer_listener pointerListener =
pointerHandleFrame, pointerHandleFrame,
pointerHandleAxisSource, pointerHandleAxisSource,
pointerHandleAxisStop, pointerHandleAxisStop,
pointerHandleAxisDiscrete pointerHandleAxisDiscrete,
pointerHandleAxisValue120
}; };
static void keyboardHandleKeymap(void* userData, static void keyboardHandleKeymap(void* userData,
@@ -1799,7 +1818,7 @@ static void keyboardHandleKeymap(void* userData,
return; return;
} }
mapStr = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0); mapStr = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
if (mapStr == MAP_FAILED) if (mapStr == MAP_FAILED)
{ {
close(fd); close(fd);