diff --git a/CHANGELOG.md b/CHANGELOG.md index b4451fe2..1e724a75 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -41,6 +41,7 @@ of box drawing characters rendered by foot itself (rather than using font glyphs) (https://codeberg.org/dnkl/foot/issues/474). * `XM`+`xm` to terminfo. +* Mouse buttons 6/7 (mouse wheel left/right). ### Changed diff --git a/input.c b/input.c index 15fcaa0a..ec76c42a 100644 --- a/input.c +++ b/input.c @@ -1449,7 +1449,8 @@ wl_pointer_leave(void *data, struct wl_pointer *wl_pointer, seat->mouse.count = 0; seat->mouse.last_released_button = 0; memset(&seat->mouse.last_time, 0, sizeof(seat->mouse.last_time)); - seat->mouse.axis_aggregated = 0.0; + for (size_t i = 0; i < ALEN(seat->mouse.aggregated); i++) + seat->mouse.aggregated[i] = 0.0; seat->mouse.have_discrete = false; seat->mouse_focus = NULL; @@ -2069,12 +2070,14 @@ alternate_scroll(struct seat *seat, int amount, int button) } static void -mouse_scroll(struct seat *seat, int amount) +mouse_scroll(struct seat *seat, int amount, enum wl_pointer_axis axis) { struct terminal *term = seat->mouse_focus; xassert(term != NULL); - int button = amount < 0 ? BTN_BACK : BTN_FORWARD; + int button = axis == WL_POINTER_AXIS_VERTICAL_SCROLL + ? amount < 0 ? BTN_BACK : BTN_FORWARD + : amount < 0 ? BTN_WHEEL_LEFT : BTN_WHEEL_RIGHT; amount = abs(amount); if (term->mouse_tracking == MOUSE_NONE) { @@ -2109,15 +2112,13 @@ static void wl_pointer_axis(void *data, struct wl_pointer *wl_pointer, uint32_t time, uint32_t axis, wl_fixed_t value) { - if (axis != WL_POINTER_AXIS_VERTICAL_SCROLL) - return; - struct seat *seat = data; if (seat->mouse.have_discrete) return; xassert(seat->mouse_focus != NULL); + xassert(axis < ALEN(seat->mouse.aggregated)); /* * Aggregate scrolled amount until we get at least 1.0 @@ -2125,27 +2126,32 @@ wl_pointer_axis(void *data, struct wl_pointer *wl_pointer, * Without this, very slow scrolling will never actually scroll * anything. */ - seat->mouse.axis_aggregated + seat->mouse.aggregated[axis] += seat->wayl->conf->scrollback.multiplier * wl_fixed_to_double(value); - if (fabs(seat->mouse.axis_aggregated) < seat->mouse_focus->cell_height) + if (fabs(seat->mouse.aggregated[axis]) < seat->mouse_focus->cell_height) return; - int lines = seat->mouse.axis_aggregated / seat->mouse_focus->cell_height; - mouse_scroll(seat, lines); - seat->mouse.axis_aggregated -= (double)lines * seat->mouse_focus->cell_height; + int lines = seat->mouse.aggregated[axis] / seat->mouse_focus->cell_height; + mouse_scroll(seat, lines, axis); + seat->mouse.aggregated[axis] -= (double)lines * seat->mouse_focus->cell_height; } static void wl_pointer_axis_discrete(void *data, struct wl_pointer *wl_pointer, uint32_t axis, int32_t discrete) { - if (axis != WL_POINTER_AXIS_VERTICAL_SCROLL) - return; - struct seat *seat = data; seat->mouse.have_discrete = true; - mouse_scroll(seat, seat->wayl->conf->scrollback.multiplier * discrete); + + int amount = discrete; + + if (axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL) { + /* Treat mouse wheel left/right as regular buttons */ + } else + amount *= seat->wayl->conf->scrollback.multiplier; + + mouse_scroll(seat, amount, axis); } static void @@ -2165,11 +2171,10 @@ static void wl_pointer_axis_stop(void *data, struct wl_pointer *wl_pointer, uint32_t time, uint32_t axis) { - if (axis != WL_POINTER_AXIS_VERTICAL_SCROLL) - return; - struct seat *seat = data; - seat->mouse.axis_aggregated = 0.; + + xassert(axis < ALEN(seat->mouse.aggregated)); + seat->mouse.aggregated[axis] = 0.; } const struct wl_pointer_listener pointer_listener = { diff --git a/input.h b/input.h index 1ecc9e28..68b8719d 100644 --- a/input.h +++ b/input.h @@ -5,6 +5,23 @@ #include "wayland.h" +/* + * Custom defines for mouse wheel left/right buttons. + * + * Libinput does not define these. On Wayland, all scroll events (both + * vertical and horizontal) are reported not as buttons, as ‘axis’ + * events. + * + * Libinput _does_ define BTN_BACK and BTN_FORWARD, which is + * what we use for vertical scroll events. But for horizontal scroll + * events, there aren’t any pre-defined mouse buttons. + * + * Mouse buttons are in the range 0x110 - 0x11f, with joystick defines + * starting at 0x120. + */ +#define BTN_WHEEL_LEFT 0x11e +#define BTN_WHEEL_RIGHT 0x11f + extern const struct wl_keyboard_listener keyboard_listener; extern const struct wl_pointer_listener pointer_listener; diff --git a/terminal.c b/terminal.c index 956b3a9f..de397ec1 100644 --- a/terminal.c +++ b/terminal.c @@ -28,6 +28,7 @@ #include "extract.h" #include "grid.h" #include "ime.h" +#include "input.h" #include "notify.h" #include "quirks.h" #include "reaper.h" @@ -2743,14 +2744,16 @@ static int linux_mouse_button_to_x(int button) { switch (button) { - case BTN_LEFT: return 1; - case BTN_MIDDLE: return 2; - case BTN_RIGHT: return 3; - case BTN_BACK: return 4; - case BTN_FORWARD: return 5; - case BTN_SIDE: return 8; - case BTN_EXTRA: return 9; - case BTN_TASK: return -1; /* TODO: ??? */ + case BTN_LEFT: return 1; + case BTN_MIDDLE: return 2; + case BTN_RIGHT: return 3; + case BTN_BACK: return 4; + case BTN_FORWARD: return 5; + case BTN_WHEEL_LEFT: return 6; /* Foot custom define */ + case BTN_WHEEL_RIGHT: return 7; /* Foot custom define */ + case BTN_SIDE: return 8; + case BTN_EXTRA: return 9; + case BTN_TASK: return -1; /* TODO: ??? */ default: LOG_WARN("unrecognized mouse button: %d (0x%x)", button, button); @@ -2881,7 +2884,7 @@ term_mouse_up(struct terminal *term, int button, int row, int col, return; if (xbutton == 4 || xbutton == 5) { - /* No release events for scroll buttons */ + /* No release events for vertical scroll wheel buttons */ return; } diff --git a/wayland.h b/wayland.h index bc044169..4881c6c5 100644 --- a/wayland.h +++ b/wayland.h @@ -242,7 +242,7 @@ struct seat { struct timeval last_time; /* We used a discrete axis event in the current pointer frame */ - double axis_aggregated; + double aggregated[2]; bool have_discrete; mouse_binding_list_t bindings;