diff options
author | Peter Hutterer <peter.hutterer@who-t.net> | 2017-02-22 07:56:07 +1000 |
---|---|---|
committer | Peter Hutterer <peter.hutterer@who-t.net> | 2017-02-22 07:56:07 +1000 |
commit | 4ce0fe4a2d2e54e401b1073dfc1c894d596a4a0f (patch) | |
tree | 8a8ee0fac17412f208e9759770c3386b847922da /src | |
parent | 765ef9a31dc3b8551f388858392bfa64ee013c66 (diff) | |
parent | c225c0592c4b3b61a01b6227f293b7fb853d5dbf (diff) |
Merge branch 'wip/logitech-marble-mouse-middleemulation'
Diffstat (limited to 'src')
-rw-r--r-- | src/evdev.c | 89 | ||||
-rw-r--r-- | src/evdev.h | 11 | ||||
-rw-r--r-- | src/timer.c | 22 | ||||
-rw-r--r-- | src/timer.h | 10 |
4 files changed, 105 insertions, 27 deletions
diff --git a/src/evdev.c b/src/evdev.c index b691333..6132d54 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -48,7 +48,7 @@ #endif #define DEFAULT_WHEEL_CLICK_ANGLE 15 -#define DEFAULT_MIDDLE_BUTTON_SCROLL_TIMEOUT ms2us(200) +#define DEFAULT_BUTTON_SCROLL_TIMEOUT ms2us(200) enum evdev_key_type { EVDEV_KEY_TYPE_NONE, @@ -221,27 +221,51 @@ evdev_button_scroll_timeout(uint64_t time, void *data) { struct evdev_device *device = data; - device->scroll.button_scroll_active = true; + device->scroll.button_scroll_state = BUTTONSCROLL_READY; } static void evdev_button_scroll_button(struct evdev_device *device, uint64_t time, int is_press) { - device->scroll.button_scroll_btn_pressed = is_press; - if (is_press) { - libinput_timer_set(&device->scroll.timer, - time + DEFAULT_MIDDLE_BUTTON_SCROLL_TIMEOUT); + enum timer_flags flags = TIMER_FLAG_NONE; + + device->scroll.button_scroll_state = BUTTONSCROLL_BUTTON_DOWN; + + /* Special case: if middle button emulation is enabled and + * our scroll button is the left or right button, we only + * get here *after* the middle button timeout has expired + * for that button press. The time passed is the button-down + * time though (which is in the past), so we have to allow + * for a negative timer to be set. + */ + if (device->middlebutton.enabled && + (device->scroll.button == BTN_LEFT || + device->scroll.button == BTN_RIGHT)) { + flags = TIMER_FLAG_ALLOW_NEGATIVE; + } + + libinput_timer_set_flags(&device->scroll.timer, + time + DEFAULT_BUTTON_SCROLL_TIMEOUT, + flags); device->scroll.button_down_time = time; + log_debug(evdev_libinput_context(device), + "btnscroll: down\n"); } else { libinput_timer_cancel(&device->scroll.timer); - if (device->scroll.button_scroll_active) { - evdev_stop_scroll(device, time, - LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS); - device->scroll.button_scroll_active = false; - } else { - /* If the button is released quickly enough emit the + switch(device->scroll.button_scroll_state) { + case BUTTONSCROLL_IDLE: + log_bug_libinput(evdev_libinput_context(device), + "invalid state IDLE for button up\n"); + break; + case BUTTONSCROLL_BUTTON_DOWN: + case BUTTONSCROLL_READY: + log_debug(evdev_libinput_context(device), + "btnscroll: cancel\n"); + + /* If the button is released quickly enough or + * without scroll events, emit the * button press/release events. */ evdev_pointer_post_button(device, device->scroll.button_down_time, @@ -250,7 +274,16 @@ evdev_button_scroll_button(struct evdev_device *device, evdev_pointer_post_button(device, time, device->scroll.button, LIBINPUT_BUTTON_STATE_RELEASED); + break; + case BUTTONSCROLL_SCROLLING: + log_debug(evdev_libinput_context(device), + "btnscroll: up\n"); + evdev_stop_scroll(device, time, + LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS); + break; } + + device->scroll.button_scroll_state = BUTTONSCROLL_IDLE; } } @@ -359,18 +392,29 @@ evdev_post_trackpoint_scroll(struct evdev_device *device, struct normalized_coords unaccel, uint64_t time) { - if (device->scroll.method != LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN || - !device->scroll.button_scroll_btn_pressed) + if (device->scroll.method != LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN) return false; - if (device->scroll.button_scroll_active) + switch(device->scroll.button_scroll_state) { + case BUTTONSCROLL_IDLE: + return false; + case BUTTONSCROLL_BUTTON_DOWN: + /* if the button is down but scroll is not active, we're within the + timeout where swallow motion events but don't post scroll buttons */ + log_debug(evdev_libinput_context(device), + "btnscroll: discarding\n"); + return true; + case BUTTONSCROLL_READY: + device->scroll.button_scroll_state = BUTTONSCROLL_SCROLLING; + /* fallthrough */ + case BUTTONSCROLL_SCROLLING: evdev_post_scroll(device, time, LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS, &unaccel); - /* if the button is down but scroll is not active, we're within the - timeout where swallow motion events but don't post scroll buttons */ + return true; + } - return true; + assert(!"invalid scroll button state"); } static inline bool @@ -2245,6 +2289,7 @@ evdev_read_model_flags(struct evdev_device *device) MODEL(HP_ZBOOK_STUDIO_G3), MODEL(HP_PAVILION_DM4_TOUCHPAD), MODEL(APPLE_TOUCHPAD_ONEBUTTON), + MODEL(LOGITECH_MARBLE_MOUSE), #undef MODEL { "ID_INPUT_TRACKBALL", EVDEV_MODEL_TRACKBALL }, { NULL, EVDEV_MODEL_DEFAULT }, @@ -2643,7 +2688,9 @@ evdev_configure_device(struct evdev_device *device) /* want natural-scroll config option */ device->scroll.natural_scrolling_enabled = true; /* want button scrolling config option */ - device->scroll.want_button = 1; + if (libevdev_has_event_code(evdev, EV_REL, REL_X) || + libevdev_has_event_code(evdev, EV_REL, REL_Y)) + device->scroll.want_button = 1; } if (udev_tags & EVDEV_UDEV_TAG_KEYBOARD) { @@ -2842,6 +2889,10 @@ evdev_pre_configure_model_quirks(struct evdev_device *device) * https://bugs.freedesktop.org/show_bug.cgi?id=98100 */ if (device->model_flags & EVDEV_MODEL_HP_ZBOOK_STUDIO_G3) libevdev_set_abs_maximum(device->evdev, ABS_MT_SLOT, 1); + + /* Logitech Marble Mouse claims to have a middle button */ + if (device->model_flags & EVDEV_MODEL_LOGITECH_MARBLE_MOUSE) + libevdev_disable_event_code(device->evdev, EV_KEY, BTN_MIDDLE); } struct evdev_device * diff --git a/src/evdev.h b/src/evdev.h index 967feaf..392d71c 100644 --- a/src/evdev.h +++ b/src/evdev.h @@ -126,6 +126,14 @@ enum evdev_device_model { EVDEV_MODEL_HP_ZBOOK_STUDIO_G3 = (1 << 23), EVDEV_MODEL_HP_PAVILION_DM4_TOUCHPAD = (1 << 24), EVDEV_MODEL_APPLE_TOUCHPAD_ONEBUTTON = (1 << 25), + EVDEV_MODEL_LOGITECH_MARBLE_MOUSE = (1 << 26), +}; + +enum evdev_button_scroll_state { + BUTTONSCROLL_IDLE, + BUTTONSCROLL_BUTTON_DOWN, /* button is down */ + BUTTONSCROLL_READY, /* ready for scroll events */ + BUTTONSCROLL_SCROLLING, /* have sent scroll events */ }; struct mt_slot { @@ -187,8 +195,7 @@ struct evdev_device { uint32_t want_button; /* Checks if buttons are down and commits the setting */ void (*change_scroll_method)(struct evdev_device *device); - bool button_scroll_active; - bool button_scroll_btn_pressed; + enum evdev_button_scroll_state button_scroll_state; double threshold; double direction_lock_threshold; uint32_t direction; diff --git a/src/timer.c b/src/timer.c index c924794..362d81d 100644 --- a/src/timer.c +++ b/src/timer.c @@ -67,19 +67,23 @@ libinput_timer_arm_timer_fd(struct libinput *libinput) } void -libinput_timer_set(struct libinput_timer *timer, uint64_t expire) +libinput_timer_set_flags(struct libinput_timer *timer, + uint64_t expire, + uint32_t flags) { #ifndef NDEBUG uint64_t now = libinput_now(timer->libinput); - if (expire < now) - log_bug_libinput(timer->libinput, - "timer offset negative (-%" PRIu64 ")\n", - now - expire); - else if ((expire - now) > ms2us(5000)) + if (expire < now) { + if ((flags & TIMER_FLAG_ALLOW_NEGATIVE) == 0) + log_bug_libinput(timer->libinput, + "timer offset negative (-%" PRIu64 ")\n", + now - expire); + } else if ((expire - now) > ms2us(5000)) { log_bug_libinput(timer->libinput, "timer offset more than 5s, now %" PRIu64 " expire %" PRIu64 "\n", now, expire); + } #endif assert(expire); @@ -92,6 +96,12 @@ libinput_timer_set(struct libinput_timer *timer, uint64_t expire) } void +libinput_timer_set(struct libinput_timer *timer, uint64_t expire) +{ + libinput_timer_set_flags(timer, expire, TIMER_FLAG_NONE); +} + +void libinput_timer_cancel(struct libinput_timer *timer) { if (!timer->expire) diff --git a/src/timer.h b/src/timer.h index f8315cf..93d684a 100644 --- a/src/timer.h +++ b/src/timer.h @@ -47,6 +47,16 @@ libinput_timer_init(struct libinput_timer *timer, struct libinput *libinput, void libinput_timer_set(struct libinput_timer *timer, uint64_t expire); +enum timer_flags { + TIMER_FLAG_NONE = 0, + TIMER_FLAG_ALLOW_NEGATIVE = (1 << 0), +}; + +void +libinput_timer_set_flags(struct libinput_timer *timer, + uint64_t expire, + uint32_t flags); + void libinput_timer_cancel(struct libinput_timer *timer); |