cursor: don't leak bound scroll events from touchpad to clients

Prior to this commit, when we receive fine-grained scroll events from
touchpads that are bound to any mousebind, we leaked the scroll events to
the client unless the accumulated scroll delta exceeds the fixed threshold.
This was annoying for example when a user wants to ZoomIn/Out with
W-Up/Down mousebinds with a touchpad.

So this commit fixes it by not leaking the scroll events nor executing
actions when the accumulated delta doesn't exceed the threshold.
This commit is contained in:
tokyo4j 2025-01-11 23:36:58 +09:00 committed by Hiroaki Yamamoto
parent 1a6b01a83e
commit 08d31145fd

View file

@ -1246,7 +1246,12 @@ cursor_emulate_button(struct seat *seat, uint32_t button,
wlr_seat_pointer_notify_frame(seat->seat);
}
static int
struct scroll_info {
int direction;
bool run_action;
};
static struct scroll_info
compare_delta(const struct wlr_pointer_axis_event *event, double *accum)
{
/*
@ -1260,6 +1265,13 @@ compare_delta(const struct wlr_pointer_axis_event *event, double *accum)
* https://lists.freedesktop.org/archives/wayland-devel/2019-April/040377.html
*/
const double SCROLL_THRESHOLD = 10.0;
struct scroll_info info = {0};
if (event->delta_discrete < 0 || event->delta < 0) {
info.direction = -1;
} else if (event->delta_discrete > 0 || event->delta > 0) {
info.direction = 1;
}
if (event->delta == 0.0) {
/* Delta 0 marks the end of a scroll */
@ -1268,14 +1280,13 @@ compare_delta(const struct wlr_pointer_axis_event *event, double *accum)
/* Accumulate smooth scrolling until we hit threshold */
*accum += event->delta;
}
if (event->delta_discrete < 0 || *accum < -SCROLL_THRESHOLD) {
if (event->delta_discrete != 0 || fabs(*accum) > SCROLL_THRESHOLD) {
*accum = fmod(*accum, SCROLL_THRESHOLD);
return -1;
} else if (event->delta_discrete > 0 || *accum > SCROLL_THRESHOLD) {
*accum = fmod(*accum, SCROLL_THRESHOLD);
return 1;
info.run_action = true;
}
return 0;
return info;
}
static bool
@ -1287,18 +1298,20 @@ handle_cursor_axis(struct server *server, struct cursor_context *ctx,
uint32_t modifiers = keyboard_get_all_modifiers(&server->seat);
enum direction direction = LAB_DIRECTION_INVALID;
struct scroll_info info = {0};
if (event->orientation == WL_POINTER_AXIS_HORIZONTAL_SCROLL) {
int rel = compare_delta(event, &server->seat.smooth_scroll_offset.x);
if (rel < 0) {
info = compare_delta(event, &server->seat.smooth_scroll_offset.x);
if (info.direction < 0) {
direction = LAB_DIRECTION_LEFT;
} else if (rel > 0) {
} else if (info.direction > 0) {
direction = LAB_DIRECTION_RIGHT;
}
} else if (event->orientation == WL_POINTER_AXIS_VERTICAL_SCROLL) {
int rel = compare_delta(event, &server->seat.smooth_scroll_offset.y);
if (rel < 0) {
info = compare_delta(event, &server->seat.smooth_scroll_offset.y);
if (info.direction < 0) {
direction = LAB_DIRECTION_UP;
} else if (rel > 0) {
} else if (info.direction > 0) {
direction = LAB_DIRECTION_DOWN;
}
} else {
@ -1315,7 +1328,13 @@ handle_cursor_axis(struct server *server, struct cursor_context *ctx,
&& modifiers == mousebind->modifiers
&& mousebind->mouse_event == MOUSE_ACTION_SCROLL) {
handled = true;
actions_run(ctx->view, server, &mousebind->actions, ctx);
/*
* Action may not be executed if the accumulated scroll
* delta on touchpads doesn't exceed the threshold
*/
if (info.run_action) {
actions_run(ctx->view, server, &mousebind->actions, ctx);
}
}
}