Commit 5571f2d2 authored by Peter Hutterer's avatar Peter Hutterer

touchpad: hook up disable-while-typing configuration

This is not a frequent toggle, so we don't need to jump through too many hoops
here. We simply enable/disable on command and once any current timeouts have
expired the new setting takes effect.
Signed-off-by: Peter Hutterer's avatarPeter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: default avatarHans de Goede <hdegoede@redhat.com>
parent 55974dca
......@@ -528,7 +528,8 @@ tp_palm_tap_is_palm(struct tp_dispatch *tp, struct tp_touch *t)
static int
tp_palm_detect_dwt(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time)
{
if (tp->dwt.keyboard_active &&
if (tp->dwt.dwt_enabled &&
tp->dwt.keyboard_active &&
t->state == TOUCH_BEGIN) {
t->palm.state = PALM_TYPING;
t->palm.first = t->point;
......@@ -1127,6 +1128,9 @@ tp_keyboard_event(uint64_t time, struct libinput_event *event, void *data)
struct libinput_event_keyboard *kbdev;
unsigned int timeout;
if (!tp->dwt.dwt_enabled)
return;
if (event->type != LIBINPUT_EVENT_KEYBOARD_KEY)
return;
......@@ -1157,6 +1161,22 @@ tp_keyboard_event(uint64_t time, struct libinput_event *event, void *data)
time + timeout);
}
static bool
tp_dwt_device_is_blacklisted(struct evdev_device *device)
{
unsigned int bus = libevdev_get_id_bustype(device->evdev);
/* evemu will set the right bus type */
if (bus == BUS_BLUETOOTH || bus == BUS_VIRTUAL)
return true;
/* Wacom makes touchpads, but not internal ones */
if (libevdev_get_id_vendor(device->evdev) == VENDOR_ID_WACOM)
return true;
return false;
}
static bool
tp_want_dwt(struct evdev_device *touchpad,
struct evdev_device *keyboard)
......@@ -1164,11 +1184,8 @@ tp_want_dwt(struct evdev_device *touchpad,
unsigned int bus_tp = libevdev_get_id_bustype(touchpad->evdev),
bus_kbd = libevdev_get_id_bustype(keyboard->evdev);
if (bus_tp == BUS_BLUETOOTH || bus_kbd == BUS_BLUETOOTH)
return false;
/* evemu will set the right bus type */
if (bus_tp == BUS_VIRTUAL || bus_kbd == BUS_VIRTUAL)
if (tp_dwt_device_is_blacklisted(touchpad) ||
tp_dwt_device_is_blacklisted(keyboard))
return false;
/* If the touchpad is on serio, the keyboard is too, so ignore any
......@@ -1176,10 +1193,6 @@ tp_want_dwt(struct evdev_device *touchpad,
if (bus_tp == BUS_I8042 && bus_kbd != bus_tp)
return false;
/* Wacom makes touchpads, but not internal ones */
if (libevdev_get_id_vendor(touchpad->evdev) == VENDOR_ID_WACOM)
return false;
/* everything else we don't really know, so we have to assume
they go together */
......@@ -1499,6 +1512,77 @@ tp_init_scroll(struct tp_dispatch *tp, struct evdev_device *device)
return 0;
}
static int
tp_dwt_config_is_available(struct libinput_device *device)
{
return 1;
}
static enum libinput_config_status
tp_dwt_config_set(struct libinput_device *device,
enum libinput_config_dwt_state enable)
{
struct evdev_device *evdev = (struct evdev_device*)device;
struct tp_dispatch *tp = (struct tp_dispatch*)evdev->dispatch;
switch(enable) {
case LIBINPUT_CONFIG_DWT_ENABLED:
case LIBINPUT_CONFIG_DWT_DISABLED:
break;
default:
return LIBINPUT_CONFIG_STATUS_INVALID;
}
tp->dwt.dwt_enabled = (enable == LIBINPUT_CONFIG_DWT_ENABLED);
return LIBINPUT_CONFIG_STATUS_SUCCESS;
}
static enum libinput_config_dwt_state
tp_dwt_config_get(struct libinput_device *device)
{
struct evdev_device *evdev = (struct evdev_device*)device;
struct tp_dispatch *tp = (struct tp_dispatch*)evdev->dispatch;
return tp->dwt.dwt_enabled ?
LIBINPUT_CONFIG_DWT_ENABLED :
LIBINPUT_CONFIG_DWT_DISABLED;
}
static bool
tp_dwt_default_enabled(struct tp_dispatch *tp)
{
return true;
}
static enum libinput_config_dwt_state
tp_dwt_config_get_default(struct libinput_device *device)
{
struct evdev_device *evdev = (struct evdev_device*)device;
struct tp_dispatch *tp = (struct tp_dispatch*)evdev->dispatch;
return tp_dwt_default_enabled(tp) ?
LIBINPUT_CONFIG_DWT_ENABLED :
LIBINPUT_CONFIG_DWT_DISABLED;
}
static int
tp_init_dwt(struct tp_dispatch *tp,
struct evdev_device *device)
{
if (tp_dwt_device_is_blacklisted(device))
return 0;
tp->dwt.config.is_available = tp_dwt_config_is_available;
tp->dwt.config.set_enabled = tp_dwt_config_set;
tp->dwt.config.get_enabled = tp_dwt_config_get;
tp->dwt.config.get_default_enabled = tp_dwt_config_get_default;
tp->dwt.dwt_enabled = tp_dwt_default_enabled(tp);
device->base.config.dwt = &tp->dwt.config;
return 0;
}
static int
tp_init_palmdetect(struct tp_dispatch *tp,
struct evdev_device *device)
......@@ -1674,6 +1758,9 @@ tp_init(struct tp_dispatch *tp,
if (tp_init_buttons(tp, device) != 0)
return -1;
if (tp_init_dwt(tp, device) != 0)
return -1;
if (tp_init_palmdetect(tp, device) != 0)
return -1;
......
......@@ -322,6 +322,9 @@ struct tp_dispatch {
} sendevents;
struct {
struct libinput_device_config_dwt config;
bool dwt_enabled;
bool keyboard_active;
struct libinput_event_listener keyboard_listener;
struct libinput_timer keyboard_timer;
......
......@@ -2205,12 +2205,7 @@ END_TEST
static inline bool
has_disable_while_typing(struct litest_device *device)
{
if (libevdev_get_id_vendor(device->evdev) == VENDOR_ID_WACOM)
return false;
if (libevdev_get_id_bustype(device->evdev) == BUS_BLUETOOTH)
return false;
return true;
return libinput_device_config_dwt_is_available(device->libinput_device);
}
START_TEST(touchpad_dwt)
......@@ -2623,6 +2618,278 @@ START_TEST(touchpad_dwt_edge_scroll_interrupt)
}
END_TEST
START_TEST(touchpad_dwt_config_default_on)
{
struct litest_device *dev = litest_current_device();
struct libinput_device *device = dev->libinput_device;
enum libinput_config_status status;
enum libinput_config_dwt_state state;
if (libevdev_get_id_vendor(dev->evdev) == VENDOR_ID_WACOM ||
libevdev_get_id_bustype(dev->evdev) == BUS_BLUETOOTH) {
ck_assert(!libinput_device_config_dwt_is_available(device));
return;
}
ck_assert(libinput_device_config_dwt_is_available(device));
state = libinput_device_config_dwt_get_enabled(device);
ck_assert_int_eq(state, LIBINPUT_CONFIG_DWT_ENABLED);
state = libinput_device_config_dwt_get_default_enabled(device);
ck_assert_int_eq(state, LIBINPUT_CONFIG_DWT_ENABLED);
status = libinput_device_config_dwt_set_enabled(device,
LIBINPUT_CONFIG_DWT_ENABLED);
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
status = libinput_device_config_dwt_set_enabled(device,
LIBINPUT_CONFIG_DWT_DISABLED);
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
status = libinput_device_config_dwt_set_enabled(device, 3);
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_INVALID);
}
END_TEST
START_TEST(touchpad_dwt_config_default_off)
{
struct litest_device *dev = litest_current_device();
struct libinput_device *device = dev->libinput_device;
enum libinput_config_status status;
enum libinput_config_dwt_state state;
ck_assert(!libinput_device_config_dwt_is_available(device));
state = libinput_device_config_dwt_get_enabled(device);
ck_assert_int_eq(state, LIBINPUT_CONFIG_DWT_DISABLED);
state = libinput_device_config_dwt_get_default_enabled(device);
ck_assert_int_eq(state, LIBINPUT_CONFIG_DWT_DISABLED);
status = libinput_device_config_dwt_set_enabled(device,
LIBINPUT_CONFIG_DWT_ENABLED);
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_UNSUPPORTED);
status = libinput_device_config_dwt_set_enabled(device,
LIBINPUT_CONFIG_DWT_DISABLED);
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
status = libinput_device_config_dwt_set_enabled(device, 3);
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_INVALID);
}
END_TEST
static inline void
disable_dwt(struct litest_device *dev)
{
enum libinput_config_status status,
expected = LIBINPUT_CONFIG_STATUS_SUCCESS;
status = libinput_device_config_dwt_set_enabled(dev->libinput_device,
LIBINPUT_CONFIG_DWT_DISABLED);
litest_assert_int_eq(status, expected);
}
static inline void
enable_dwt(struct litest_device *dev)
{
enum libinput_config_status status,
expected = LIBINPUT_CONFIG_STATUS_SUCCESS;
status = libinput_device_config_dwt_set_enabled(dev->libinput_device,
LIBINPUT_CONFIG_DWT_ENABLED);
litest_assert_int_eq(status, expected);
}
START_TEST(touchpad_dwt_disabled)
{
struct litest_device *touchpad = litest_current_device();
struct litest_device *keyboard;
struct libinput *li = touchpad->libinput;
if (!has_disable_while_typing(touchpad))
return;
disable_dwt(touchpad);
keyboard = litest_add_device(li, LITEST_KEYBOARD);
litest_disable_tap(touchpad->libinput_device);
litest_drain_events(li);
litest_keyboard_key(keyboard, KEY_A, true);
litest_keyboard_key(keyboard, KEY_A, false);
litest_assert_only_typed_events(li, LIBINPUT_EVENT_KEYBOARD_KEY);
litest_touch_down(touchpad, 0, 50, 50);
litest_touch_move_to(touchpad, 0, 50, 50, 70, 50, 10, 1);
litest_touch_up(touchpad, 0);
litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);
litest_delete_device(keyboard);
}
END_TEST
START_TEST(touchpad_dwt_disable_during_touch)
{
struct litest_device *touchpad = litest_current_device();
struct litest_device *keyboard;
struct libinput *li = touchpad->libinput;
if (!has_disable_while_typing(touchpad))
return;
enable_dwt(touchpad);
keyboard = litest_add_device(li, LITEST_KEYBOARD);
litest_disable_tap(touchpad->libinput_device);
litest_drain_events(li);
litest_keyboard_key(keyboard, KEY_A, true);
litest_keyboard_key(keyboard, KEY_A, false);
litest_assert_only_typed_events(li, LIBINPUT_EVENT_KEYBOARD_KEY);
litest_touch_down(touchpad, 0, 50, 50);
litest_touch_move_to(touchpad, 0, 50, 50, 70, 50, 10, 1);
litest_assert_empty_queue(li);
disable_dwt(touchpad);
/* touch already down -> keeps being ignored */
litest_touch_move_to(touchpad, 0, 70, 50, 50, 70, 10, 1);
litest_touch_up(touchpad, 0);
litest_assert_empty_queue(li);
litest_delete_device(keyboard);
}
END_TEST
START_TEST(touchpad_dwt_disable_before_touch)
{
struct litest_device *touchpad = litest_current_device();
struct litest_device *keyboard;
struct libinput *li = touchpad->libinput;
if (!has_disable_while_typing(touchpad))
return;
enable_dwt(touchpad);
keyboard = litest_add_device(li, LITEST_KEYBOARD);
litest_disable_tap(touchpad->libinput_device);
litest_drain_events(li);
litest_keyboard_key(keyboard, KEY_A, true);
litest_keyboard_key(keyboard, KEY_A, false);
litest_assert_only_typed_events(li, LIBINPUT_EVENT_KEYBOARD_KEY);
disable_dwt(touchpad);
libinput_dispatch(li);
/* touch down during timeout -> still discarded */
litest_touch_down(touchpad, 0, 50, 50);
litest_touch_move_to(touchpad, 0, 50, 50, 70, 50, 10, 1);
litest_assert_empty_queue(li);
litest_delete_device(keyboard);
}
END_TEST
START_TEST(touchpad_dwt_enable_during_touch)
{
struct litest_device *touchpad = litest_current_device();
struct litest_device *keyboard;
struct libinput *li = touchpad->libinput;
if (!has_disable_while_typing(touchpad))
return;
disable_dwt(touchpad);
keyboard = litest_add_device(li, LITEST_KEYBOARD);
litest_disable_tap(touchpad->libinput_device);
litest_drain_events(li);
litest_keyboard_key(keyboard, KEY_A, true);
litest_keyboard_key(keyboard, KEY_A, false);
litest_assert_only_typed_events(li, LIBINPUT_EVENT_KEYBOARD_KEY);
litest_touch_down(touchpad, 0, 50, 50);
litest_touch_move_to(touchpad, 0, 50, 50, 70, 50, 10, 1);
litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);
enable_dwt(touchpad);
/* touch already down -> still sends events */
litest_touch_move_to(touchpad, 0, 70, 50, 50, 70, 10, 1);
litest_touch_up(touchpad, 0);
litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);
litest_delete_device(keyboard);
}
END_TEST
START_TEST(touchpad_dwt_enable_before_touch)
{
struct litest_device *touchpad = litest_current_device();
struct litest_device *keyboard;
struct libinput *li = touchpad->libinput;
if (!has_disable_while_typing(touchpad))
return;
disable_dwt(touchpad);
keyboard = litest_add_device(li, LITEST_KEYBOARD);
litest_disable_tap(touchpad->libinput_device);
litest_drain_events(li);
litest_keyboard_key(keyboard, KEY_A, true);
litest_keyboard_key(keyboard, KEY_A, false);
litest_assert_only_typed_events(li, LIBINPUT_EVENT_KEYBOARD_KEY);
enable_dwt(touchpad);
libinput_dispatch(li);
litest_touch_down(touchpad, 0, 50, 50);
litest_touch_move_to(touchpad, 0, 50, 50, 70, 50, 10, 1);
litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);
litest_delete_device(keyboard);
}
END_TEST
START_TEST(touchpad_dwt_enable_during_tap)
{
struct litest_device *touchpad = litest_current_device();
struct litest_device *keyboard;
struct libinput *li = touchpad->libinput;
if (!has_disable_while_typing(touchpad))
return;
litest_enable_tap(touchpad->libinput_device);
disable_dwt(touchpad);
keyboard = litest_add_device(li, LITEST_KEYBOARD);
litest_drain_events(li);
litest_keyboard_key(keyboard, KEY_A, true);
litest_keyboard_key(keyboard, KEY_A, false);
litest_assert_only_typed_events(li, LIBINPUT_EVENT_KEYBOARD_KEY);
litest_touch_down(touchpad, 0, 50, 50);
libinput_dispatch(li);
enable_dwt(touchpad);
libinput_dispatch(li);
litest_touch_up(touchpad, 0);
libinput_dispatch(li);
litest_timeout_tap();
litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_BUTTON);
litest_touch_down(touchpad, 0, 50, 50);
litest_touch_move_to(touchpad, 0, 50, 50, 70, 50, 10, 1);
litest_touch_up(touchpad, 0);
litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);
litest_delete_device(keyboard);
}
END_TEST
static int
has_thumb_detect(struct litest_device *dev)
{
......@@ -3197,6 +3464,14 @@ litest_setup_tests(void)
litest_add("touchpad:dwt", touchpad_dwt_click, LITEST_TOUCHPAD, LITEST_ANY);
litest_add("touchpad:dwt", touchpad_dwt_edge_scroll, LITEST_TOUCHPAD, LITEST_CLICKPAD);
litest_add("touchpad:dwt", touchpad_dwt_edge_scroll_interrupt, LITEST_TOUCHPAD, LITEST_CLICKPAD);
litest_add("touchpad:dwt", touchpad_dwt_config_default_on, LITEST_TOUCHPAD, LITEST_ANY);
litest_add("touchpad:dwt", touchpad_dwt_config_default_off, LITEST_ANY, LITEST_TOUCHPAD);
litest_add("touchpad:dwt", touchpad_dwt_disabled, LITEST_TOUCHPAD, LITEST_ANY);
litest_add("touchpad:dwt", touchpad_dwt_disable_during_touch, LITEST_TOUCHPAD, LITEST_ANY);
litest_add("touchpad:dwt", touchpad_dwt_disable_before_touch, LITEST_TOUCHPAD, LITEST_ANY);
litest_add("touchpad:dwt", touchpad_dwt_enable_during_touch, LITEST_TOUCHPAD, LITEST_ANY);
litest_add("touchpad:dwt", touchpad_dwt_enable_before_touch, LITEST_TOUCHPAD, LITEST_ANY);
litest_add("touchpad:dwt", touchpad_dwt_enable_during_tap, LITEST_TOUCHPAD, LITEST_ANY);
litest_add("touchpad:thumb", touchpad_thumb_begin_no_motion, LITEST_TOUCHPAD, LITEST_ANY);
litest_add("touchpad:thumb", touchpad_thumb_update_no_motion, LITEST_TOUCHPAD, LITEST_ANY);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment