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 | |
parent | 765ef9a31dc3b8551f388858392bfa64ee013c66 (diff) | |
parent | c225c0592c4b3b61a01b6227f293b7fb853d5dbf (diff) |
Merge branch 'wip/logitech-marble-mouse-middleemulation'
-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 | ||||
-rw-r--r-- | test/test-device.c | 13 | ||||
-rw-r--r-- | test/test-pointer.c | 227 | ||||
-rw-r--r-- | test/test-trackpoint.c | 9 | ||||
-rw-r--r-- | udev/90-libinput-model-quirks.hwdb | 4 |
8 files changed, 330 insertions, 55 deletions
diff --git a/src/evdev.c b/src/evdev.c index b6913331..6132d54f 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 967feaf3..392d71cf 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 c9247942..362d81db 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 f8315cfe..93d684ab 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); diff --git a/test/test-device.c b/test/test-device.c index 48ba55db..fdbab20c 100644 --- a/test/test-device.c +++ b/test/test-device.c @@ -1482,6 +1482,18 @@ START_TEST(device_quirks_apple_magicmouse) } END_TEST +START_TEST(device_quirks_logitech_marble_mouse) +{ + struct litest_device *dev = litest_current_device(); + struct libinput *li = dev->libinput; + + litest_drain_events(li); + + ck_assert(!libinput_device_pointer_has_button(dev->libinput_device, + BTN_MIDDLE)); +} +END_TEST + START_TEST(device_capability_at_least_one) { struct litest_device *dev = litest_current_device(); @@ -1648,6 +1660,7 @@ litest_setup_tests_device(void) litest_add_for_device("device:quirks", device_quirks_no_abs_mt_y, LITEST_ANKER_MOUSE_KBD); litest_add_for_device("device:quirks", device_quirks_cyborg_rat_mode_button, LITEST_CYBORG_RAT); litest_add_for_device("device:quirks", device_quirks_apple_magicmouse, LITEST_MAGICMOUSE); + litest_add_for_device("device:quirks", device_quirks_logitech_marble_mouse, LITEST_LOGITECH_TRACKBALL); litest_add("device:capability", device_capability_at_least_one, LITEST_ANY, LITEST_ANY); litest_add("device:capability", device_capability_check_invalid, LITEST_ANY, LITEST_ANY); diff --git a/test/test-pointer.c b/test/test-pointer.c index 6485258e..06c45b2c 100644 --- a/test/test-pointer.c +++ b/test/test-pointer.c @@ -371,13 +371,15 @@ START_TEST(pointer_button) test_button_event(dev, BTN_LEFT, 1); test_button_event(dev, BTN_LEFT, 0); - if (libevdev_has_event_code(dev->evdev, EV_KEY, BTN_RIGHT)) { + if (libinput_device_pointer_has_button(dev->libinput_device, + BTN_RIGHT)) { test_button_event(dev, BTN_RIGHT, 1); test_button_event(dev, BTN_RIGHT, 0); } /* Skip middle button test on trackpoints (used for scrolling) */ - if (libevdev_has_event_code(dev->evdev, EV_KEY, BTN_MIDDLE)) { + if (libinput_device_pointer_has_button(dev->libinput_device, + BTN_MIDDLE)) { test_button_event(dev, BTN_MIDDLE, 1); test_button_event(dev, BTN_MIDDLE, 0); } @@ -904,9 +906,7 @@ START_TEST(pointer_left_handed) BTN_LEFT, LIBINPUT_BUTTON_STATE_RELEASED); - if (libevdev_has_event_code(dev->evdev, - EV_KEY, - BTN_MIDDLE)) { + if (libinput_device_pointer_has_button(d, BTN_MIDDLE)) { litest_button_click(dev, BTN_MIDDLE, 1); litest_button_click(dev, BTN_MIDDLE, 0); litest_assert_button_event(li, @@ -952,6 +952,11 @@ START_TEST(pointer_left_handed_during_click_multiple_buttons) struct libinput *li = dev->libinput; enum libinput_config_status status; + if (!libinput_device_pointer_has_button(d, BTN_MIDDLE)) + return; + + litest_disable_middleemu(dev); + litest_drain_events(li); litest_button_click(dev, BTN_LEFT, 1); libinput_dispatch(li); @@ -1001,11 +1006,15 @@ START_TEST(pointer_scroll_button) litest_button_scroll(dev, BTN_LEFT, -9, 1); litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL, -9); - /* scroll smaller than the threshold should not generate events */ + /* scroll smaller than the threshold should not generate axis events */ litest_button_scroll(dev, BTN_LEFT, 1, 1); - /* left press without movement should not generate events */ - litest_button_scroll(dev, BTN_LEFT, 0, 0); + litest_button_scroll(dev, BTN_LEFT, 0, 0); + litest_assert_button_event(li, BTN_LEFT, + LIBINPUT_BUTTON_STATE_PRESSED); + litest_assert_button_event(li, + BTN_LEFT, + LIBINPUT_BUTTON_STATE_RELEASED); litest_assert_empty_queue(li); /* Restore default scroll behavior */ @@ -1046,6 +1055,11 @@ START_TEST(pointer_scroll_button_no_event_before_timeout) struct libinput *li = device->libinput; int i; + if (!libinput_device_pointer_has_button(device->libinput_device, + BTN_MIDDLE)) + return; + + litest_disable_middleemu(device); disable_button_scrolling(device); libinput_device_config_scroll_set_method(device->libinput_device, @@ -1066,6 +1080,12 @@ START_TEST(pointer_scroll_button_no_event_before_timeout) litest_timeout_buttonscroll(); libinput_dispatch(li); litest_button_click(device, BTN_LEFT, false); + + litest_assert_button_event(li, BTN_LEFT, + LIBINPUT_BUTTON_STATE_PRESSED); + litest_assert_button_event(li, + BTN_LEFT, + LIBINPUT_BUTTON_STATE_RELEASED); litest_assert_empty_queue(li); } END_TEST @@ -1126,19 +1146,41 @@ START_TEST(pointer_scroll_nowheel_defaults) { struct litest_device *dev = litest_current_device(); struct libinput_device *device = dev->libinput_device; - enum libinput_config_scroll_method method; + enum libinput_config_scroll_method method, expected; uint32_t button; + /* button scrolling is only enabled if there is a + middle button present */ + if (libinput_device_pointer_has_button(device, BTN_MIDDLE)) + expected = LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN; + else + expected = LIBINPUT_CONFIG_SCROLL_NO_SCROLL; + method = libinput_device_config_scroll_get_method(device); - ck_assert_int_eq(method, LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN); + ck_assert_int_eq(method, expected); method = libinput_device_config_scroll_get_default_method(device); - ck_assert_int_eq(method, LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN); + ck_assert_int_eq(method, expected); - button = libinput_device_config_scroll_get_button(device); - ck_assert_int_eq(button, BTN_MIDDLE); - button = libinput_device_config_scroll_get_default_button(device); - ck_assert_int_eq(button, BTN_MIDDLE); + if (method == LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN) { + button = libinput_device_config_scroll_get_button(device); + ck_assert_int_eq(button, BTN_MIDDLE); + button = libinput_device_config_scroll_get_default_button(device); + ck_assert_int_eq(button, BTN_MIDDLE); + } +} +END_TEST + +START_TEST(pointer_scroll_defaults_logitech_marble) +{ + struct litest_device *dev = litest_current_device(); + struct libinput_device *device = dev->libinput_device; + enum libinput_config_scroll_method method; + + method = libinput_device_config_scroll_get_method(device); + ck_assert_int_eq(method, LIBINPUT_CONFIG_SCROLL_NO_SCROLL); + method = libinput_device_config_scroll_get_default_method(device); + ck_assert_int_eq(method, LIBINPUT_CONFIG_SCROLL_NO_SCROLL); } END_TEST @@ -1614,7 +1656,8 @@ START_TEST(middlebutton_middleclick) disable_button_scrolling(device); - if (!libevdev_has_event_code(device->evdev, EV_KEY, BTN_MIDDLE)) + if (!libinput_device_pointer_has_button(device->libinput_device, + BTN_MIDDLE)) return; status = libinput_device_config_middle_emulation_set_enabled( @@ -1678,7 +1721,8 @@ START_TEST(middlebutton_middleclick_during) disable_button_scrolling(device); - if (!libevdev_has_event_code(device->evdev, EV_KEY, BTN_MIDDLE)) + if (!libinput_device_pointer_has_button(device->libinput_device, + BTN_MIDDLE)) return; status = libinput_device_config_middle_emulation_set_enabled( @@ -1740,22 +1784,21 @@ START_TEST(middlebutton_default_enabled) struct libinput_device *device = dev->libinput_device; enum libinput_config_status status; int available; - enum libinput_config_middle_emulation_state deflt, state; + enum libinput_config_middle_emulation_state state; + + if (!libinput_device_pointer_has_button(dev->libinput_device, + BTN_MIDDLE)) + return; available = libinput_device_config_middle_emulation_is_available(device); ck_assert(available); - if (libevdev_has_event_code(dev->evdev, EV_KEY, BTN_MIDDLE)) - deflt = LIBINPUT_CONFIG_MIDDLE_EMULATION_DISABLED; - else - deflt = LIBINPUT_CONFIG_MIDDLE_EMULATION_ENABLED; - state = libinput_device_config_middle_emulation_get_enabled(device); - ck_assert_int_eq(state, deflt); + ck_assert_int_eq(state, LIBINPUT_CONFIG_MIDDLE_EMULATION_DISABLED); state = libinput_device_config_middle_emulation_get_default_enabled( device); - ck_assert_int_eq(state, deflt); + ck_assert_int_eq(state, LIBINPUT_CONFIG_MIDDLE_EMULATION_DISABLED); status = libinput_device_config_middle_emulation_set_enabled(device, LIBINPUT_CONFIG_MIDDLE_EMULATION_ENABLED); @@ -1815,7 +1858,7 @@ START_TEST(middlebutton_default_touchpad) available = libinput_device_config_middle_emulation_is_available(device); ck_assert(!available); - if (libevdev_has_event_code(dev->evdev, EV_KEY, BTN_MIDDLE)) + if (libinput_device_pointer_has_button(device, BTN_MIDDLE)) return; state = libinput_device_config_middle_emulation_get_enabled( @@ -1870,6 +1913,134 @@ START_TEST(middlebutton_default_disabled) } END_TEST +START_TEST(middlebutton_button_scrolling) +{ + struct litest_device *dev = litest_current_device(); + struct libinput_device *device = dev->libinput_device; + struct libinput *li = dev->libinput; + enum libinput_config_status status; + struct libinput_event *ev; + struct libinput_event_pointer *pev; + int i; + + status = libinput_device_config_middle_emulation_set_enabled( + device, + LIBINPUT_CONFIG_MIDDLE_EMULATION_ENABLED); + if (status == LIBINPUT_CONFIG_STATUS_UNSUPPORTED) + return; + + status = libinput_device_config_scroll_set_method(device, + LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN); + if (status == LIBINPUT_CONFIG_STATUS_UNSUPPORTED) + return; + + status = libinput_device_config_scroll_set_button(device, BTN_LEFT); + if (status == LIBINPUT_CONFIG_STATUS_UNSUPPORTED) + return; + + litest_drain_events(li); + + litest_event(dev, EV_KEY, BTN_LEFT, 1); + litest_event(dev, EV_SYN, SYN_REPORT, 0); + libinput_dispatch(li); + + /* middle emulation discards */ + litest_assert_empty_queue(li); + + litest_timeout_middlebutton(); + libinput_dispatch(li); + + /* scroll discards */ + litest_assert_empty_queue(li); + litest_timeout_buttonscroll(); + libinput_dispatch(li); + + for (i = 0; i < 10; i++) { + litest_event(dev, EV_REL, REL_Y, 1); + litest_event(dev, EV_SYN, SYN_REPORT, 0); + libinput_dispatch(li); + } + + ev = libinput_get_event(li); + do { + pev = litest_is_axis_event(ev, + LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, + LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS); + ck_assert_double_gt(libinput_event_pointer_get_axis_value(pev, + LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL), + 0.0); + libinput_event_destroy(ev); + ev = libinput_get_event(li); + } while (ev); + + litest_event(dev, EV_KEY, BTN_LEFT, 0); + litest_event(dev, EV_SYN, SYN_REPORT, 0); + libinput_dispatch(li); + + ev = libinput_get_event(li); + pev = litest_is_axis_event(ev, + LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, + LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS); + ck_assert_double_eq(libinput_event_pointer_get_axis_value(pev, + LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL), + 0.0); + libinput_event_destroy(ev); + + /* no button release */ + litest_assert_empty_queue(li); +} +END_TEST + +START_TEST(middlebutton_button_scrolling_middle) +{ + struct litest_device *dev = litest_current_device(); + struct libinput_device *device = dev->libinput_device; + struct libinput *li = dev->libinput; + enum libinput_config_status status; + + status = libinput_device_config_middle_emulation_set_enabled( + device, + LIBINPUT_CONFIG_MIDDLE_EMULATION_ENABLED); + if (status == LIBINPUT_CONFIG_STATUS_UNSUPPORTED) + return; + + status = libinput_device_config_scroll_set_method(device, + LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN); + if (status == LIBINPUT_CONFIG_STATUS_UNSUPPORTED) + return; + + status = libinput_device_config_scroll_set_button(device, BTN_LEFT); + if (status == LIBINPUT_CONFIG_STATUS_UNSUPPORTED) + return; + + litest_drain_events(li); + + /* button scrolling should not stop middle emulation */ + + litest_event(dev, EV_KEY, BTN_LEFT, 1); + litest_event(dev, EV_SYN, SYN_REPORT, 0); + litest_event(dev, EV_KEY, BTN_RIGHT, 1); + litest_event(dev, EV_SYN, SYN_REPORT, 0); + libinput_dispatch(li); + + litest_assert_button_event(li, + BTN_MIDDLE, + LIBINPUT_BUTTON_STATE_PRESSED); + + litest_event(dev, EV_KEY, BTN_LEFT, 0); + litest_event(dev, EV_SYN, SYN_REPORT, 0); + litest_event(dev, EV_KEY, BTN_RIGHT, 0); + litest_event(dev, EV_SYN, SYN_REPORT, 0); + libinput_dispatch(li); + + litest_assert_button_event(li, + BTN_MIDDLE, + LIBINPUT_BUTTON_STATE_RELEASED); + + litest_assert_empty_queue(li); +} +END_TEST + START_TEST(pointer_time_usec) { struct litest_device *dev = litest_current_device(); @@ -1915,10 +2086,12 @@ litest_setup_tests_pointer(void) litest_add_for_device("pointer:button", pointer_button_has_no_button, LITEST_KEYBOARD); litest_add("pointer:scroll", pointer_scroll_wheel, LITEST_WHEEL, LITEST_TABLET); litest_add("pointer:scroll", pointer_scroll_button, LITEST_RELATIVE|LITEST_BUTTON, LITEST_ANY); + litest_add("pointer:scroll", pointer_scroll_button_noscroll, LITEST_ABSOLUTE|LITEST_BUTTON, LITEST_RELATIVE); litest_add("pointer:scroll", pointer_scroll_button_noscroll, LITEST_ANY, LITEST_RELATIVE|LITEST_BUTTON); litest_add("pointer:scroll", pointer_scroll_button_no_event_before_timeout, LITEST_RELATIVE|LITEST_BUTTON, LITEST_ANY); litest_add("pointer:scroll", pointer_scroll_button_middle_emulation, LITEST_RELATIVE|LITEST_BUTTON, LITEST_ANY); litest_add("pointer:scroll", pointer_scroll_nowheel_defaults, LITEST_RELATIVE|LITEST_BUTTON, LITEST_WHEEL); + litest_add_for_device("pointer:scroll", pointer_scroll_defaults_logitech_marble , LITEST_LOGITECH_TRACKBALL); litest_add("pointer:scroll", pointer_scroll_natural_defaults, LITEST_WHEEL, LITEST_TABLET); litest_add("pointer:scroll", pointer_scroll_natural_defaults_noscroll, LITEST_ANY, LITEST_WHEEL); litest_add("pointer:scroll", pointer_scroll_natural_enable_config, LITEST_WHEEL, LITEST_TABLET); @@ -1955,6 +2128,8 @@ litest_setup_tests_pointer(void) litest_add("pointer:middlebutton", middlebutton_default_touchpad, LITEST_TOUCHPAD, LITEST_CLICKPAD); litest_add("pointer:middlebutton", middlebutton_default_disabled, LITEST_ANY, LITEST_BUTTON); litest_add_for_device("pointer:middlebutton", middlebutton_default_alps, LITEST_ALPS_SEMI_MT); + litest_add("pointer:middlebutton", middlebutton_button_scrolling, LITEST_RELATIVE|LITEST_BUTTON, LITEST_CLICKPAD); + litest_add("pointer:middlebutton", middlebutton_button_scrolling_middle, LITEST_RELATIVE|LITEST_BUTTON, LITEST_CLICKPAD); litest_add_ranged("pointer:state", pointer_absolute_initial_state, LITEST_ABSOLUTE, LITEST_ANY, &axis_range); diff --git a/test/test-trackpoint.c b/test/test-trackpoint.c index e9ba0271..adbd46e8 100644 --- a/test/test-trackpoint.c +++ b/test/test-trackpoint.c @@ -85,10 +85,15 @@ START_TEST(trackpoint_scroll) litest_button_scroll(dev, BTN_MIDDLE, -9, 1); litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL, -9); - /* scroll smaller than the threshold should not generate events */ + /* scroll smaller than the threshold should not generate axis events */ litest_button_scroll(dev, BTN_MIDDLE, 1, 1); - /* long middle press without movement should not generate events */ + litest_button_scroll(dev, BTN_MIDDLE, 0, 0); + litest_assert_button_event(li, BTN_MIDDLE, + LIBINPUT_BUTTON_STATE_PRESSED); + litest_assert_button_event(li, + BTN_MIDDLE, + LIBINPUT_BUTTON_STATE_RELEASED); litest_assert_empty_queue(li); } diff --git a/udev/90-libinput-model-quirks.hwdb b/udev/90-libinput-model-quirks.hwdb index c1d6235f..2ff50b68 100644 --- a/udev/90-libinput-model-quirks.hwdb +++ b/udev/90-libinput-model-quirks.hwdb @@ -169,6 +169,10 @@ libinput:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO:*:pvrThinkPadX1Carbon3rd libinput:name:*Logitech M570*:dmi:* LIBINPUT_MODEL_TRACKBALL=1 +# Logitech Marble Mouse trackball +libinput:mouse:input:b0003v046DpC408* + LIBINPUT_MODEL_LOGITECH_MARBLE_MOUSE=1 + ########################################## # Microsoft ########################################## |