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: Scroll events were sent twice on some versions of GNOME (#2494)
- [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: Occasional crash when an idle display awakes (#2766)
- [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 =
wl_registry_bind(registry, name, &wl_seat_interface,
_glfw_min(5, version));
_glfw_min(8, version));
_glfwAddSeatListenerWayland(_glfw.wl.seat);
}
}
+2
View File
@@ -478,6 +478,8 @@ typedef struct _GLFWlibraryWayland
double pointerY;
double scrollX;
double scrollY;
double discreteX;
double discreteY;
int button;
int action;
} pending;
+22 -3
View File
@@ -59,6 +59,7 @@
#define GLFW_PENDING_BUTTON 2
#define GLFW_PENDING_MOTION 4
#define GLFW_PENDING_SCROLL 8
#define GLFW_PENDING_DISCRETE 16
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)
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);
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 =
{
pointerHandleEnter,
@@ -1776,7 +1794,8 @@ static const struct wl_pointer_listener pointerListener =
pointerHandleFrame,
pointerHandleAxisSource,
pointerHandleAxisStop,
pointerHandleAxisDiscrete
pointerHandleAxisDiscrete,
pointerHandleAxisValue120
};
static void keyboardHandleKeymap(void* userData,
@@ -1799,7 +1818,7 @@ static void keyboardHandleKeymap(void* userData,
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)
{
close(fd);