mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-03-16 05:34:00 -04:00
input: implement support for mouse wheel left/right
We now emit button 6/7 events (when the client application grabs the mouse). This buttons map to mouse wheel horizontal scroll events. Or, left/right tilting, if you like. Wayland report these as ‘axis’ events (just like regular scroll wheel events), and thus we need to translate those scroll events to button events. libinput does not define any mouse buttons for wheel tilts, so we add our own defitions. These are added last in the BTN_* range, just before the BTN_JOYSTICK events.
This commit is contained in:
parent
7a372a8c23
commit
c2cc964116
5 changed files with 55 additions and 29 deletions
|
|
@ -41,6 +41,7 @@
|
||||||
of box drawing characters rendered by foot itself (rather than using
|
of box drawing characters rendered by foot itself (rather than using
|
||||||
font glyphs) (https://codeberg.org/dnkl/foot/issues/474).
|
font glyphs) (https://codeberg.org/dnkl/foot/issues/474).
|
||||||
* `XM`+`xm` to terminfo.
|
* `XM`+`xm` to terminfo.
|
||||||
|
* Mouse buttons 6/7 (mouse wheel left/right).
|
||||||
|
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
|
||||||
43
input.c
43
input.c
|
|
@ -1449,7 +1449,8 @@ wl_pointer_leave(void *data, struct wl_pointer *wl_pointer,
|
||||||
seat->mouse.count = 0;
|
seat->mouse.count = 0;
|
||||||
seat->mouse.last_released_button = 0;
|
seat->mouse.last_released_button = 0;
|
||||||
memset(&seat->mouse.last_time, 0, sizeof(seat->mouse.last_time));
|
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.have_discrete = false;
|
||||||
|
|
||||||
seat->mouse_focus = NULL;
|
seat->mouse_focus = NULL;
|
||||||
|
|
@ -2069,12 +2070,14 @@ alternate_scroll(struct seat *seat, int amount, int button)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
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;
|
struct terminal *term = seat->mouse_focus;
|
||||||
xassert(term != NULL);
|
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);
|
amount = abs(amount);
|
||||||
|
|
||||||
if (term->mouse_tracking == MOUSE_NONE) {
|
if (term->mouse_tracking == MOUSE_NONE) {
|
||||||
|
|
@ -2109,15 +2112,13 @@ static void
|
||||||
wl_pointer_axis(void *data, struct wl_pointer *wl_pointer,
|
wl_pointer_axis(void *data, struct wl_pointer *wl_pointer,
|
||||||
uint32_t time, uint32_t axis, wl_fixed_t value)
|
uint32_t time, uint32_t axis, wl_fixed_t value)
|
||||||
{
|
{
|
||||||
if (axis != WL_POINTER_AXIS_VERTICAL_SCROLL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
struct seat *seat = data;
|
struct seat *seat = data;
|
||||||
|
|
||||||
if (seat->mouse.have_discrete)
|
if (seat->mouse.have_discrete)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
xassert(seat->mouse_focus != NULL);
|
xassert(seat->mouse_focus != NULL);
|
||||||
|
xassert(axis < ALEN(seat->mouse.aggregated));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Aggregate scrolled amount until we get at least 1.0
|
* 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
|
* Without this, very slow scrolling will never actually scroll
|
||||||
* anything.
|
* anything.
|
||||||
*/
|
*/
|
||||||
seat->mouse.axis_aggregated
|
seat->mouse.aggregated[axis]
|
||||||
+= seat->wayl->conf->scrollback.multiplier * wl_fixed_to_double(value);
|
+= 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;
|
return;
|
||||||
|
|
||||||
int lines = seat->mouse.axis_aggregated / seat->mouse_focus->cell_height;
|
int lines = seat->mouse.aggregated[axis] / seat->mouse_focus->cell_height;
|
||||||
mouse_scroll(seat, lines);
|
mouse_scroll(seat, lines, axis);
|
||||||
seat->mouse.axis_aggregated -= (double)lines * seat->mouse_focus->cell_height;
|
seat->mouse.aggregated[axis] -= (double)lines * seat->mouse_focus->cell_height;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
wl_pointer_axis_discrete(void *data, struct wl_pointer *wl_pointer,
|
wl_pointer_axis_discrete(void *data, struct wl_pointer *wl_pointer,
|
||||||
uint32_t axis, int32_t discrete)
|
uint32_t axis, int32_t discrete)
|
||||||
{
|
{
|
||||||
if (axis != WL_POINTER_AXIS_VERTICAL_SCROLL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
struct seat *seat = data;
|
struct seat *seat = data;
|
||||||
seat->mouse.have_discrete = true;
|
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
|
static void
|
||||||
|
|
@ -2165,11 +2171,10 @@ static void
|
||||||
wl_pointer_axis_stop(void *data, struct wl_pointer *wl_pointer,
|
wl_pointer_axis_stop(void *data, struct wl_pointer *wl_pointer,
|
||||||
uint32_t time, uint32_t axis)
|
uint32_t time, uint32_t axis)
|
||||||
{
|
{
|
||||||
if (axis != WL_POINTER_AXIS_VERTICAL_SCROLL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
struct seat *seat = data;
|
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 = {
|
const struct wl_pointer_listener pointer_listener = {
|
||||||
|
|
|
||||||
17
input.h
17
input.h
|
|
@ -5,6 +5,23 @@
|
||||||
|
|
||||||
#include "wayland.h"
|
#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_keyboard_listener keyboard_listener;
|
||||||
extern const struct wl_pointer_listener pointer_listener;
|
extern const struct wl_pointer_listener pointer_listener;
|
||||||
|
|
||||||
|
|
|
||||||
21
terminal.c
21
terminal.c
|
|
@ -28,6 +28,7 @@
|
||||||
#include "extract.h"
|
#include "extract.h"
|
||||||
#include "grid.h"
|
#include "grid.h"
|
||||||
#include "ime.h"
|
#include "ime.h"
|
||||||
|
#include "input.h"
|
||||||
#include "notify.h"
|
#include "notify.h"
|
||||||
#include "quirks.h"
|
#include "quirks.h"
|
||||||
#include "reaper.h"
|
#include "reaper.h"
|
||||||
|
|
@ -2743,14 +2744,16 @@ static int
|
||||||
linux_mouse_button_to_x(int button)
|
linux_mouse_button_to_x(int button)
|
||||||
{
|
{
|
||||||
switch (button) {
|
switch (button) {
|
||||||
case BTN_LEFT: return 1;
|
case BTN_LEFT: return 1;
|
||||||
case BTN_MIDDLE: return 2;
|
case BTN_MIDDLE: return 2;
|
||||||
case BTN_RIGHT: return 3;
|
case BTN_RIGHT: return 3;
|
||||||
case BTN_BACK: return 4;
|
case BTN_BACK: return 4;
|
||||||
case BTN_FORWARD: return 5;
|
case BTN_FORWARD: return 5;
|
||||||
case BTN_SIDE: return 8;
|
case BTN_WHEEL_LEFT: return 6; /* Foot custom define */
|
||||||
case BTN_EXTRA: return 9;
|
case BTN_WHEEL_RIGHT: return 7; /* Foot custom define */
|
||||||
case BTN_TASK: return -1; /* TODO: ??? */
|
case BTN_SIDE: return 8;
|
||||||
|
case BTN_EXTRA: return 9;
|
||||||
|
case BTN_TASK: return -1; /* TODO: ??? */
|
||||||
|
|
||||||
default:
|
default:
|
||||||
LOG_WARN("unrecognized mouse button: %d (0x%x)", button, button);
|
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;
|
return;
|
||||||
|
|
||||||
if (xbutton == 4 || xbutton == 5) {
|
if (xbutton == 4 || xbutton == 5) {
|
||||||
/* No release events for scroll buttons */
|
/* No release events for vertical scroll wheel buttons */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -242,7 +242,7 @@ struct seat {
|
||||||
struct timeval last_time;
|
struct timeval last_time;
|
||||||
|
|
||||||
/* We used a discrete axis event in the current pointer frame */
|
/* We used a discrete axis event in the current pointer frame */
|
||||||
double axis_aggregated;
|
double aggregated[2];
|
||||||
bool have_discrete;
|
bool have_discrete;
|
||||||
|
|
||||||
mouse_binding_list_t bindings;
|
mouse_binding_list_t bindings;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue