From 45a7edb3fb08f10652c9157243c9191a9b55c9b2 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 1 Sep 2014 17:17:18 +1000 Subject: [PATCH] touchpad: hook up sendevents configuration We may be in the middle of a software button click or a tap, so make sure we go back to the device-neutral state by unwinding. Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- src/evdev-mt-touchpad-buttons.c | 10 ++++ src/evdev-mt-touchpad-tap.c | 6 +++ src/evdev-mt-touchpad.c | 91 +++++++++++++++++++++++++++++++++ src/evdev-mt-touchpad.h | 13 +++++ test/device.c | 10 ++-- 5 files changed, 125 insertions(+), 5 deletions(-) diff --git a/src/evdev-mt-touchpad-buttons.c b/src/evdev-mt-touchpad-buttons.c index f6235a0a..1dd89136 100644 --- a/src/evdev-mt-touchpad-buttons.c +++ b/src/evdev-mt-touchpad-buttons.c @@ -484,6 +484,16 @@ tp_process_button(struct tp_dispatch *tp, return 0; } +void +tp_release_all_buttons(struct tp_dispatch *tp, + uint64_t time) +{ + if (tp->buttons.state) { + tp->buttons.state = 0; + tp->queued |= TOUCHPAD_EVENT_BUTTON_RELEASE; + } +} + int tp_init_buttons(struct tp_dispatch *tp, struct evdev_device *device) diff --git a/src/evdev-mt-touchpad-tap.c b/src/evdev-mt-touchpad-tap.c index a19d51e2..8f055fc1 100644 --- a/src/evdev-mt-touchpad-tap.c +++ b/src/evdev-mt-touchpad-tap.c @@ -693,3 +693,9 @@ tp_destroy_tap(struct tp_dispatch *tp) { libinput_timer_cancel(&tp->tap.timer); } + +void +tp_release_all_taps(struct tp_dispatch *tp, uint64_t now) +{ + tp_tap_handle_timeout(now, tp); +} diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c index 7202a663..cfc41ecb 100644 --- a/src/evdev-mt-touchpad.c +++ b/src/evdev-mt-touchpad.c @@ -641,6 +641,41 @@ tp_destroy(struct evdev_dispatch *dispatch) free(tp); } +static void +tp_suspend(struct tp_dispatch *tp, struct evdev_device *device) +{ + uint64_t now = libinput_now(tp->device->base.seat->libinput); + struct tp_touch *t; + + /* Unroll the touchpad state. + * Release buttons first. If tp is a clickpad, the button event + * must come before the touch up. If it isn't, the order doesn't + * matter anyway + * + * Then cancel all timeouts on the taps, triggering the last set + * of events. + * + * Then lift all touches so the touchpad is in a neutral state. + * + */ + tp_release_all_buttons(tp, now); + tp_release_all_taps(tp, now); + + tp_for_each_touch(tp, t) { + tp_end_touch(tp, t, now); + } + + tp_handle_state(tp, now); + + evdev_device_suspend(device); +} + +static void +tp_resume(struct tp_dispatch *tp, struct evdev_device *device) +{ + evdev_device_resume(device); +} + static struct evdev_dispatch_interface tp_interface = { tp_process, tp_destroy @@ -836,6 +871,54 @@ tp_init(struct tp_dispatch *tp, return 0; } +static uint32_t +tp_sendevents_get_modes(struct libinput_device *device) +{ + return LIBINPUT_CONFIG_SEND_EVENTS_ENABLED | + LIBINPUT_CONFIG_SEND_EVENTS_DISABLED; +} + +static enum libinput_config_status +tp_sendevents_set_mode(struct libinput_device *device, + enum libinput_config_send_events_mode mode) +{ + struct evdev_device *evdev = (struct evdev_device*)device; + struct tp_dispatch *tp = (struct tp_dispatch*)evdev->dispatch; + + if (mode == tp->sendevents.current_mode) + return LIBINPUT_CONFIG_STATUS_SUCCESS; + + switch(mode) { + case LIBINPUT_CONFIG_SEND_EVENTS_ENABLED: + tp_resume(tp, evdev); + break; + case LIBINPUT_CONFIG_SEND_EVENTS_DISABLED: + tp_suspend(tp, evdev); + break; + default: + return LIBINPUT_CONFIG_STATUS_UNSUPPORTED; + } + + tp->sendevents.current_mode = mode; + + return LIBINPUT_CONFIG_STATUS_SUCCESS; +} + +static enum libinput_config_send_events_mode +tp_sendevents_get_mode(struct libinput_device *device) +{ + struct evdev_device *evdev = (struct evdev_device*)device; + struct tp_dispatch *dispatch = (struct tp_dispatch*)evdev->dispatch; + + return dispatch->sendevents.current_mode; +} + +static enum libinput_config_send_events_mode +tp_sendevents_get_default_mode(struct libinput_device *device) +{ + return LIBINPUT_CONFIG_SEND_EVENTS_ENABLED; +} + struct evdev_dispatch * evdev_mt_touchpad_create(struct evdev_device *device) { @@ -850,5 +933,13 @@ evdev_mt_touchpad_create(struct evdev_device *device) return NULL; } + device->base.config.sendevents = &tp->sendevents.config; + + tp->sendevents.current_mode = LIBINPUT_CONFIG_SEND_EVENTS_ENABLED; + tp->sendevents.config.get_modes = tp_sendevents_get_modes; + tp->sendevents.config.set_mode = tp_sendevents_set_mode; + tp->sendevents.config.get_mode = tp_sendevents_get_mode; + tp->sendevents.config.get_default_mode = tp_sendevents_get_default_mode; + return &tp->base; } diff --git a/src/evdev-mt-touchpad.h b/src/evdev-mt-touchpad.h index 83edf4f2..6988b790 100644 --- a/src/evdev-mt-touchpad.h +++ b/src/evdev-mt-touchpad.h @@ -217,6 +217,11 @@ struct tp_dispatch { int32_t right_edge; int32_t left_edge; } palm; + + struct { + struct libinput_device_config_send_events config; + enum libinput_config_send_events_mode current_mode; + } sendevents; }; #define tp_for_each_touch(_tp, _t) \ @@ -248,6 +253,10 @@ tp_process_button(struct tp_dispatch *tp, const struct input_event *e, uint64_t time); +void +tp_release_all_buttons(struct tp_dispatch *tp, + uint64_t time); + int tp_post_button_events(struct tp_dispatch *tp, uint64_t time); @@ -260,4 +269,8 @@ tp_button_touch_active(struct tp_dispatch *tp, struct tp_touch *t); bool tp_button_is_inside_softbutton_area(struct tp_dispatch *tp, struct tp_touch *t); +void +tp_release_all_taps(struct tp_dispatch *tp, + uint64_t time); + #endif diff --git a/test/device.c b/test/device.c index 12947409..8db69fdd 100644 --- a/test/device.c +++ b/test/device.c @@ -262,12 +262,12 @@ END_TEST int main (int argc, char **argv) { - litest_add("device:sendevents", device_sendevents_config, LITEST_ANY, LITEST_TOUCHPAD); - litest_add("device:sendevents", device_sendevents_config_default, LITEST_ANY, LITEST_TOUCHPAD); - litest_add("device:sendevents", device_disable, LITEST_POINTER, LITEST_TOUCHPAD); + litest_add("device:sendevents", device_sendevents_config, LITEST_ANY, LITEST_ANY); + litest_add("device:sendevents", device_sendevents_config_default, LITEST_ANY, LITEST_ANY); + litest_add("device:sendevents", device_disable, LITEST_POINTER, LITEST_ANY); litest_add("device:sendevents", device_disable_events_pending, LITEST_POINTER, LITEST_TOUCHPAD); - litest_add("device:sendevents", device_double_disable, LITEST_ANY, LITEST_TOUCHPAD); - litest_add("device:sendevents", device_double_enable, LITEST_ANY, LITEST_TOUCHPAD); + litest_add("device:sendevents", device_double_disable, LITEST_ANY, LITEST_ANY); + litest_add("device:sendevents", device_double_enable, LITEST_ANY, LITEST_ANY); litest_add_no_device("device:sendevents", device_reenable_syspath_changed); litest_add_no_device("device:sendevents", device_reenable_device_removed); -- 2.34.1