evdev: enable middle-button scrolling on middle-button emulation

https://bugs.freedesktop.org/show_bug.cgi?id=94856

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
This commit is contained in:
Peter Hutterer 2016-04-11 10:06:36 +10:00
parent aeb0c21b1c
commit c61dfc80bd
3 changed files with 116 additions and 50 deletions

View file

@ -154,14 +154,17 @@ evdev_pointer_notify_physical_button(struct evdev_device *device,
state))
return;
evdev_pointer_notify_button(device, time, button, state);
evdev_pointer_notify_button(device,
time,
(unsigned int)button,
state);
}
void
evdev_pointer_notify_button(struct evdev_device *device,
uint64_t time,
int button,
enum libinput_button_state state)
static void
evdev_pointer_post_button(struct evdev_device *device,
uint64_t time,
unsigned int button,
enum libinput_button_state state)
{
int down_count;
@ -182,6 +185,59 @@ evdev_pointer_notify_button(struct evdev_device *device,
}
static void
evdev_button_scroll_timeout(uint64_t time, void *data)
{
struct evdev_device *device = data;
device->scroll.button_scroll_active = true;
}
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);
device->scroll.button_down_time = time;
} 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
* button press/release events. */
evdev_pointer_post_button(device,
device->scroll.button_down_time,
device->scroll.button,
LIBINPUT_BUTTON_STATE_PRESSED);
evdev_pointer_post_button(device, time,
device->scroll.button,
LIBINPUT_BUTTON_STATE_RELEASED);
}
}
}
void
evdev_pointer_notify_button(struct evdev_device *device,
uint64_t time,
unsigned int button,
enum libinput_button_state state)
{
if (device->scroll.method == LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN &&
button == device->scroll.button) {
evdev_button_scroll_button(device, time, state);
return;
}
evdev_pointer_post_button(device, time, button, state);
}
void
evdev_device_led_update(struct evdev_device *device, enum libinput_led leds)
{
@ -482,44 +538,6 @@ get_key_type(uint16_t code)
return EVDEV_KEY_TYPE_NONE;
}
static void
evdev_button_scroll_timeout(uint64_t time, void *data)
{
struct evdev_device *device = data;
device->scroll.button_scroll_active = true;
}
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);
device->scroll.button_down_time = time;
} 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
* button press/release events. */
evdev_pointer_notify_button(device,
device->scroll.button_down_time,
device->scroll.button,
LIBINPUT_BUTTON_STATE_PRESSED);
evdev_pointer_notify_button(device, time,
device->scroll.button,
LIBINPUT_BUTTON_STATE_RELEASED);
}
}
}
static void
evdev_process_touch_button(struct evdev_device *device,
uint64_t time, int value)
@ -580,11 +598,6 @@ evdev_process_key(struct evdev_device *device,
LIBINPUT_KEY_STATE_RELEASED);
break;
case EVDEV_KEY_TYPE_BUTTON:
if (device->scroll.method == LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN &&
e->code == device->scroll.button) {
evdev_button_scroll_button(device, time, e->value);
break;
}
evdev_pointer_notify_physical_button(
device,
time,

View file

@ -398,7 +398,7 @@ evdev_keyboard_notify_key(struct evdev_device *device,
void
evdev_pointer_notify_button(struct evdev_device *device,
uint64_t time,
int button,
unsigned int button,
enum libinput_button_state state);
void
evdev_pointer_notify_physical_button(struct evdev_device *device,

View file

@ -923,6 +923,58 @@ START_TEST(pointer_scroll_button_no_event_before_timeout)
}
END_TEST
START_TEST(pointer_scroll_button_middle_emulation)
{
struct litest_device *dev = litest_current_device();
struct libinput_device *device = dev->libinput_device;
struct libinput *li = dev->libinput;
enum libinput_config_status status;
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);
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
status = libinput_device_config_scroll_set_button(device, BTN_MIDDLE);
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
litest_drain_events(li);
litest_button_click(dev, BTN_LEFT, 1);
litest_button_click(dev, BTN_RIGHT, 1);
libinput_dispatch(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);
litest_button_click(dev, BTN_LEFT, 0);
litest_button_click(dev, BTN_RIGHT, 0);
libinput_dispatch(li);
litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, -1);
litest_assert_empty_queue(li);
/* Restore default scroll behavior */
libinput_device_config_scroll_set_method(dev->libinput_device,
libinput_device_config_scroll_get_default_method(
dev->libinput_device));
libinput_device_config_scroll_set_button(dev->libinput_device,
libinput_device_config_scroll_get_default_button(
dev->libinput_device));
}
END_TEST
START_TEST(pointer_scroll_nowheel_defaults)
{
struct litest_device *dev = litest_current_device();
@ -1631,6 +1683,7 @@ litest_setup_tests(void)
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_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("pointer:scroll", pointer_scroll_natural_defaults, LITEST_WHEEL, LITEST_TABLET);
litest_add("pointer:scroll", pointer_scroll_natural_enable_config, LITEST_WHEEL, LITEST_TABLET);