Keep the default behavior of middle button scrolling on trackpoints, this allows turning off middle button scrolling on trackpoints, as well as turning on button scrolling on trackballs.
Signed-off-by: Hans de Goede <hdego...@redhat.com> --- src/evdev.c | 165 +++++++++++++++++++++++++++++++++++++++++++++++++++--------- src/evdev.h | 13 ++++- 2 files changed, 153 insertions(+), 25 deletions(-) diff --git a/src/evdev.c b/src/evdev.c index 2821cc6..765f3e5 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -123,6 +123,10 @@ evdev_pointer_notify_button(struct evdev_device *device, if (state == LIBINPUT_BUTTON_STATE_RELEASED && device->buttons.change_to_left_handed) device->buttons.change_to_left_handed(device); + + if (state == LIBINPUT_BUTTON_STATE_RELEASED && + device->scroll.change_scroll_mode) + device->scroll.change_scroll_mode(device); } } @@ -213,9 +217,9 @@ evdev_flush_pending_event(struct evdev_device *device, uint64_t time) 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) + if (device->scroll.mode == LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN && + hw_is_key_down(device, device->scroll.button)) { + if (device->scroll.button_scroll_active) evdev_post_scroll(device, time, motion.dx, motion.dy); break; @@ -364,31 +368,33 @@ get_key_type(uint16_t code) } static void -evdev_middle_button_scroll_timeout(uint64_t time, void *data) +evdev_button_scroll_timeout(uint64_t time, void *data) { struct evdev_device *device = data; - device->scroll.middle_button_scroll_active = true; + device->scroll.button_scroll_active = true; } static void -evdev_middle_button_scroll_button(struct evdev_device *device, - uint64_t time, int is_press) +evdev_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) { + if (device->scroll.button_scroll_active) { evdev_stop_scroll(device, time); - device->scroll.middle_button_scroll_active = false; + device->scroll.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, + evdev_pointer_notify_button(device, time, + device->scroll.button, LIBINPUT_BUTTON_STATE_PRESSED); - evdev_pointer_notify_button(device, time, BTN_MIDDLE, + evdev_pointer_notify_button(device, time, + device->scroll.button, LIBINPUT_BUTTON_STATE_RELEASED); } } @@ -454,10 +460,9 @@ 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); + if (device->scroll.mode == LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN && + e->code == device->scroll.button) { + evdev_button_scroll_button(device, time, e->value); break; } evdev_pointer_notify_button( @@ -839,6 +844,115 @@ evdev_init_left_handed(struct evdev_device *device, return 0; } +static uint32_t +evdev_scroll_get_modes(struct libinput_device *device) +{ + return LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN; +} + +static void +evdev_change_scroll_mode(struct evdev_device *device) +{ + if (device->scroll.want_mode == device->scroll.mode && + device->scroll.want_button == device->scroll.button) + return; + + if (evdev_any_button_down(device)) + return; + + device->scroll.mode = device->scroll.want_mode; + device->scroll.button = device->scroll.want_button; +} + +static enum libinput_config_status +evdev_scroll_set_mode(struct libinput_device *device, + enum libinput_config_scroll_mode mode) +{ + struct evdev_device *evdev = (struct evdev_device*)device; + + evdev->scroll.want_mode = mode; + evdev->scroll.change_scroll_mode(evdev); + + return LIBINPUT_CONFIG_STATUS_SUCCESS; +} + +static enum libinput_config_scroll_mode +evdev_scroll_get_mode(struct libinput_device *device) +{ + struct evdev_device *evdev = (struct evdev_device *)device; + + /* return the wanted configuration, even if it hasn't taken + * effect yet! */ + return evdev->scroll.want_mode; +} + +static enum libinput_config_scroll_mode +evdev_scroll_get_default_mode(struct libinput_device *device) +{ + struct evdev_device *evdev = (struct evdev_device *)device; + + if (libevdev_has_property(evdev->evdev, INPUT_PROP_POINTING_STICK)) + return LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN; + else + return LIBINPUT_CONFIG_SCROLL_NO_SCROLL; +} + +static enum libinput_config_status +evdev_scroll_set_button(struct libinput_device *device, + uint32_t button) +{ + struct evdev_device *evdev = (struct evdev_device*)device; + + evdev->scroll.want_button = button; + evdev->scroll.change_scroll_mode(evdev); + + return LIBINPUT_CONFIG_STATUS_SUCCESS; +} + +static uint32_t +evdev_scroll_get_button(struct libinput_device *device) +{ + struct evdev_device *evdev = (struct evdev_device *)device; + + /* return the wanted configuration, even if it hasn't taken + * effect yet! */ + return evdev->scroll.want_button; +} + +static uint32_t +evdev_scroll_get_default_button(struct libinput_device *device) +{ + struct evdev_device *evdev = (struct evdev_device *)device; + + if (libevdev_has_property(evdev->evdev, INPUT_PROP_POINTING_STICK)) + return BTN_MIDDLE; + else + return 0; +} + +static int +evdev_init_button_scroll(struct evdev_device *device, + void (*change_scroll_mode)(struct evdev_device *)) +{ + libinput_timer_init(&device->scroll.timer, device->base.seat->libinput, + evdev_button_scroll_timeout, device); + device->scroll.config.get_modes = evdev_scroll_get_modes; + device->scroll.config.set_mode = evdev_scroll_set_mode; + device->scroll.config.get_mode = evdev_scroll_get_mode; + device->scroll.config.get_default_mode = evdev_scroll_get_default_mode; + device->scroll.config.set_button = evdev_scroll_set_button; + device->scroll.config.get_button = evdev_scroll_get_button; + device->scroll.config.get_default_button = evdev_scroll_get_default_button; + device->base.config.scroll_mode = &device->scroll.config; + device->scroll.mode = evdev_scroll_get_default_mode((struct libinput_device *)device); + device->scroll.want_mode = device->scroll.mode; + device->scroll.button = evdev_scroll_get_default_button((struct libinput_device *)device); + device->scroll.want_button = device->scroll.button; + device->scroll.change_scroll_mode = change_scroll_mode; + + return 0; +} + static struct evdev_dispatch * fallback_dispatch_create(struct libinput_device *device) { @@ -857,6 +971,13 @@ fallback_dispatch_create(struct libinput_device *device) return NULL; } + if (evdev_device->scroll.want_button && + evdev_init_button_scroll(evdev_device, + evdev_change_scroll_mode) == -1) { + free(dispatch); + return NULL; + } + device->config.calibration = &dispatch->calibration; dispatch->calibration.has_matrix = evdev_calibration_has_matrix; @@ -1149,14 +1270,6 @@ evdev_configure_device(struct evdev_device *device) } } - 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; @@ -1210,6 +1323,12 @@ evdev_configure_device(struct evdev_device *device) /* want left-handed config option */ device->buttons.want_left_handed = true; } + + if (has_rel && has_button) { + /* want button scrolling config option */ + device->scroll.want_button = 1; + } + if (has_keyboard) { device->seat_caps |= EVDEV_DEVICE_KEYBOARD; log_info(libinput, diff --git a/src/evdev.h b/src/evdev.h index 6867db6..c99fc25 100644 --- a/src/evdev.h +++ b/src/evdev.h @@ -100,8 +100,17 @@ struct evdev_device { struct { struct libinput_timer timer; - bool has_middle_button_scroll; - bool middle_button_scroll_active; + struct libinput_device_config_scroll_mode config; + /* Currently enabled mode, button */ + enum libinput_config_scroll_mode mode; + uint32_t button; + /* set during device init, used at runtime to delay changes + * until all buttons are up */ + enum libinput_config_scroll_mode want_mode; + uint32_t want_button; + /* Checks if buttons are down and commits the setting */ + void (*change_scroll_mode)(struct evdev_device *device); + bool button_scroll_active; double threshold; uint32_t direction; } scroll; -- 2.1.0 _______________________________________________ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel