[PATCH libinput 2/8] evdev: Add middle button scrolling for trackpoints
Most trackpoint users want to be able to scroll using the trackpoint with the middle button pressed, add support for this. Signed-off-by: Hans de Goede Reviewed-by: Peter Hutterer --- include/linux/input.h| 1 + src/evdev.c | 56 src/evdev.h | 5 + test/litest-trackpoint.c | 2 ++ test/pointer.c | 4 +++- 5 files changed, 67 insertions(+), 1 deletion(-) 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_TOPBUTTONPAD0x04/* 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
Re: [PATCH libinput 2/8] evdev: Add middle button scrolling for trackpoints
On Tue, Sep 16, 2014 at 04:22:36PM +0200, Hans de Goede wrote: > Most trackpoint users want to be able to scroll using the trackpoint with > the middle button pressed, add support for this. > > Signed-off-by: Hans de Goede > Reviewed-by: Peter Hutterer > --- > include/linux/input.h| 1 + > src/evdev.c | 56 > > src/evdev.h | 5 + > test/litest-trackpoint.c | 2 ++ > test/pointer.c | 4 +++- > 5 files changed, 67 insertions(+), 1 deletion(-) > > 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_STICK0x05/* 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; > + } > + Just to verify: the behaviour here is that the scrolling does not activate until after the timeout, regardless of the number of motion events during the timeout period. Is this intentional, or do we need a threshold here? Cheers, Peter > /* 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_
Re: [PATCH libinput 2/8] evdev: Add middle button scrolling for trackpoints
Hi, On 09/18/2014 03:49 AM, Peter Hutterer wrote: > On Tue, Sep 16, 2014 at 04:22:36PM +0200, Hans de Goede wrote: >> Most trackpoint users want to be able to scroll using the trackpoint with >> the middle button pressed, add support for this. >> >> Signed-off-by: Hans de Goede >> Reviewed-by: Peter Hutterer >> --- >> include/linux/input.h| 1 + >> src/evdev.c | 56 >> >> src/evdev.h | 5 + >> test/litest-trackpoint.c | 2 ++ >> test/pointer.c | 4 +++- >> 5 files changed, 67 insertions(+), 1 deletion(-) >> >> 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_BUTTONPAD0x02/* 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; >> +} >> + > > Just to verify: the behaviour here is that the scrolling does not activate > until after the timeout, regardless of the number of motion events during > the timeout period. Is this intentional, or do we need a threshold here? This behavior is copied from the xf86-input-evdev driver, and so far in my testing scrolling through web-pages and pdfs I've not noticed the timeout being an issue. So my vote goes to the KISS approach of keeping this as is. Regards, Hans > > Cheers, >Peter > > >> /* 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