diff options
-rw-r--r-- | include/linux/input.h | 1 | ||||
-rw-r--r-- | src/evdev.c | 56 | ||||
-rw-r--r-- | src/evdev.h | 5 | ||||
-rw-r--r-- | test/litest-trackpoint.c | 2 | ||||
-rw-r--r-- | test/pointer.c | 4 |
5 files changed, 67 insertions, 1 deletions
diff --git a/include/linux/input.h b/include/linux/input.h index aa98ce7..39b550b 100644 --- a/include/linux/input.h +++ b/include/linux/input.h @@ -163,6 +163,7 @@ struct input_keymap_entry { #define INPUT_PROP_BUTTONPAD 0x02 /* has button(s) under pad */ #define INPUT_PROP_SEMI_MT 0x03 /* touch rectangle only */ #define INPUT_PROP_TOPBUTTONPAD 0x04 /* softbuttons at top of pad */ +#define INPUT_PROP_POINTING_STICK 0x05 /* is a pointing stick */ #define INPUT_PROP_MAX 0x1f #define INPUT_PROP_CNT (INPUT_PROP_MAX + 1) diff --git a/src/evdev.c b/src/evdev.c index 45020ba..85e4d71 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -41,6 +41,7 @@ #include "libinput-private.h" #define DEFAULT_AXIS_STEP_DISTANCE 10 +#define DEFAULT_MIDDLE_BUTTON_SCROLL_TIMEOUT 200 enum evdev_key_type { EVDEV_KEY_TYPE_NONE, @@ -203,6 +204,15 @@ evdev_flush_pending_event(struct evdev_device *device, uint64_t time) device->rel.dx = 0; device->rel.dy = 0; + /* Use unaccelerated deltas for pointing stick scroll */ + if (device->scroll.has_middle_button_scroll && + hw_is_key_down(device, BTN_MIDDLE)) { + if (device->scroll.middle_button_scroll_active) + evdev_post_scroll(device, time, + motion.dx, motion.dy); + break; + } + /* Apply pointer acceleration. */ filter_dispatch(device->pointer.filter, &motion, device, time); @@ -346,6 +356,37 @@ get_key_type(uint16_t code) } static void +evdev_middle_button_scroll_timeout(uint64_t time, void *data) +{ + struct evdev_device *device = data; + + device->scroll.middle_button_scroll_active = true; +} + +static void +evdev_middle_button_scroll_button(struct evdev_device *device, + uint64_t time, int is_press) +{ + if (is_press) { + libinput_timer_set(&device->scroll.timer, + time + DEFAULT_MIDDLE_BUTTON_SCROLL_TIMEOUT); + } else { + libinput_timer_cancel(&device->scroll.timer); + if (device->scroll.middle_button_scroll_active) { + evdev_stop_scroll(device, time); + device->scroll.middle_button_scroll_active = false; + } else { + /* If the button is released quickly enough emit the + * button press/release events. */ + evdev_pointer_notify_button(device, time, BTN_MIDDLE, + LIBINPUT_BUTTON_STATE_PRESSED); + evdev_pointer_notify_button(device, time, BTN_MIDDLE, + LIBINPUT_BUTTON_STATE_RELEASED); + } + } +} + +static void evdev_process_touch_button(struct evdev_device *device, uint64_t time, int value) { @@ -405,6 +446,12 @@ evdev_process_key(struct evdev_device *device, LIBINPUT_KEY_STATE_RELEASED); break; case EVDEV_KEY_TYPE_BUTTON: + if (device->scroll.has_middle_button_scroll && + e->code == BTN_MIDDLE) { + evdev_middle_button_scroll_button(device, time, + e->value); + break; + } evdev_pointer_notify_button( device, time, @@ -946,6 +993,15 @@ evdev_configure_device(struct evdev_device *device) device->mt.slot = active_slot; } } + + if (libevdev_has_property(evdev, INPUT_PROP_POINTING_STICK)) { + libinput_timer_init(&device->scroll.timer, + device->base.seat->libinput, + evdev_middle_button_scroll_timeout, + device); + device->scroll.has_middle_button_scroll = true; + } + if (libevdev_has_event_code(evdev, EV_REL, REL_X) || libevdev_has_event_code(evdev, EV_REL, REL_Y)) has_rel = 1; diff --git a/src/evdev.h b/src/evdev.h index 311dddc..e1506d2 100644 --- a/src/evdev.h +++ b/src/evdev.h @@ -26,10 +26,12 @@ #include "config.h" +#include <stdbool.h> #include "linux/input.h" #include <libevdev/libevdev.h> #include "libinput-private.h" +#include "timer.h" enum evdev_event_type { EVDEV_NONE, @@ -96,6 +98,9 @@ struct evdev_device { } rel; struct { + struct libinput_timer timer; + bool has_middle_button_scroll; + bool middle_button_scroll_active; double threshold; uint32_t direction; } scroll; diff --git a/test/litest-trackpoint.c b/test/litest-trackpoint.c index 25a377c..40b9ed0 100644 --- a/test/litest-trackpoint.c +++ b/test/litest-trackpoint.c @@ -49,6 +49,8 @@ static int events[] = { EV_KEY, BTN_MIDDLE, EV_REL, REL_X, EV_REL, REL_Y, + INPUT_PROP_MAX, INPUT_PROP_POINTER, + INPUT_PROP_MAX, INPUT_PROP_POINTING_STICK, -1, -1, }; diff --git a/test/pointer.c b/test/pointer.c index 82c5245..f704372 100644 --- a/test/pointer.c +++ b/test/pointer.c @@ -132,7 +132,9 @@ START_TEST(pointer_button) test_button_event(dev, BTN_RIGHT, 0); } - if (libevdev_has_event_code(dev->evdev, EV_KEY, BTN_MIDDLE)) { + /* Skip middle button test on trackpoints (used for scrolling) */ + if (!libevdev_has_property(dev->evdev, INPUT_PROP_POINTING_STICK) && + libevdev_has_event_code(dev->evdev, EV_KEY, BTN_MIDDLE)) { test_button_event(dev, BTN_MIDDLE, 1); test_button_event(dev, BTN_MIDDLE, 0); } |