Add disable-while-typing feature (#1209753)

This commit is contained in:
Peter Hutterer 2015-05-18 16:22:26 +10:00
parent 089f1ffb69
commit 3a8be7cb5d
4 changed files with 379 additions and 1 deletions

View File

@ -0,0 +1,91 @@
From d288eb0a63793ebb64de041960336d6fb57060b0 Mon Sep 17 00:00:00 2001
From: Peter Hutterer <peter.hutterer@who-t.net>
Date: Mon, 20 Apr 2015 16:09:31 +1000
Subject: [PATCH libinput 1/3] touchpad: switch from is_palm to an enum
Preparation to add different palm detection types. Not all of them need to be
un-done when leaving the edge area so a boolean is not enough.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
---
src/evdev-mt-touchpad.c | 10 +++++-----
src/evdev-mt-touchpad.h | 7 ++++++-
2 files changed, 11 insertions(+), 6 deletions(-)
diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c
index 79177fb..d8b44fa 100644
--- a/src/evdev-mt-touchpad.c
+++ b/src/evdev-mt-touchpad.c
@@ -231,7 +231,7 @@ tp_end_touch(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time)
}
t->dirty = true;
- t->palm.is_palm = false;
+ t->palm.state = PALM_NONE;
t->state = TOUCH_END;
t->pinned.is_pinned = false;
t->millis = time;
@@ -455,7 +455,7 @@ int
tp_touch_active(struct tp_dispatch *tp, struct tp_touch *t)
{
return (t->state == TOUCH_BEGIN || t->state == TOUCH_UPDATE) &&
- !t->palm.is_palm &&
+ t->palm.state == PALM_NONE &&
!t->pinned.is_pinned &&
tp_button_touch_active(tp, t) &&
tp_edge_scroll_touch_active(tp, t);
@@ -491,14 +491,14 @@ tp_palm_detect(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time)
we move out of the palm edge zone within the timeout, provided
the direction is within 45 degrees of the horizontal.
*/
- if (t->palm.is_palm) {
+ if (t->palm.state == PALM_EDGE) {
if (time < t->palm.time + PALM_TIMEOUT &&
(t->point.x > tp->palm.left_edge && t->point.x < tp->palm.right_edge)) {
delta = device_delta(t->point, t->palm.first);
dirs = normalized_get_direction(
tp_normalize_delta(tp, delta));
if ((dirs & DIRECTIONS) && !(dirs & ~DIRECTIONS)) {
- t->palm.is_palm = false;
+ t->palm.state = PALM_NONE;
}
}
return;
@@ -517,7 +517,7 @@ tp_palm_detect(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time)
tp_button_is_inside_softbutton_area(tp, t))
return;
- t->palm.is_palm = true;
+ t->palm.state = PALM_EDGE;
t->palm.time = time;
t->palm.first = t->point;
}
diff --git a/src/evdev-mt-touchpad.h b/src/evdev-mt-touchpad.h
index f602359..ba65e41 100644
--- a/src/evdev-mt-touchpad.h
+++ b/src/evdev-mt-touchpad.h
@@ -61,6 +61,11 @@ enum touch_state {
TOUCH_END
};
+enum touch_palm_state {
+ PALM_NONE = 0,
+ PALM_EDGE,
+};
+
enum button_event {
BUTTON_EVENT_IN_BOTTOM_R = 30,
BUTTON_EVENT_IN_BOTTOM_L,
@@ -171,7 +176,7 @@ struct tp_touch {
} scroll;
struct {
- bool is_palm;
+ enum touch_palm_state state;
struct device_coords first; /* first coordinates if is_palm == true */
uint32_t time; /* first timestamp if is_palm == true */
} palm;
--
2.3.5

View File

@ -0,0 +1,209 @@
From d02b670e3796c10fa75b94165886901a0a0c41f4 Mon Sep 17 00:00:00 2001
From: Peter Hutterer <peter.hutterer@who-t.net>
Date: Mon, 20 Apr 2015 15:51:20 +1000
Subject: [PATCH libinput 2/3] touchpad: add timeout-based disable-while-typing
On some touchpads, typing triggers touches in areas of the touchpad that
cannot easily be distinguished from other fingers. Pressure information is
useless too, so we have to go back to a timeout-based handling of touch data.
If we see non-modifier key events, disable the touchpad for a timeout and set
any touches starting during that timeout as palm.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
---
src/evdev-mt-touchpad.c | 90 +++++++++++++++++++++++++++++++++++++++++++++++--
src/evdev-mt-touchpad.h | 7 ++++
2 files changed, 94 insertions(+), 3 deletions(-)
diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c
index d8b44fa..32d8e25 100644
--- a/src/evdev-mt-touchpad.c
+++ b/src/evdev-mt-touchpad.c
@@ -34,6 +34,7 @@
#define DEFAULT_ACCEL_NUMERATOR 3000.0
#define DEFAULT_HYSTERESIS_MARGIN_DENOMINATOR 700.0
#define DEFAULT_TRACKPOINT_ACTIVITY_TIMEOUT 500 /* ms */
+#define DEFAULT_KEYBOARD_ACTIVITY_TIMEOUT 500 /* ms */
#define FAKE_FINGER_OVERFLOW (1 << 7)
static inline int
@@ -487,6 +488,14 @@ tp_palm_detect(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time)
struct device_float_coords delta;
int dirs;
+ if (tp->sendevents.keyboard_active &&
+ t->state == TOUCH_BEGIN) {
+ t->palm.state = PALM_TYPING;
+ t->palm.time = time;
+ t->palm.first = t->point;
+ return;
+ }
+
/* If labelled a touch as palm, we unlabel as palm when
we move out of the palm edge zone within the timeout, provided
the direction is within 45 degrees of the horizontal.
@@ -705,7 +714,9 @@ tp_post_events(struct tp_dispatch *tp, uint64_t time)
filter_motion |= tp_tap_handle_state(tp, time);
filter_motion |= tp_post_button_events(tp, time);
- if (filter_motion || tp->sendevents.trackpoint_active) {
+ if (filter_motion ||
+ tp->sendevents.trackpoint_active ||
+ tp->sendevents.keyboard_active) {
tp_edge_scroll_stop_events(tp, time);
tp_gesture_stop(tp, time);
return;
@@ -755,10 +766,15 @@ static void
tp_remove_sendevents(struct tp_dispatch *tp)
{
libinput_timer_cancel(&tp->sendevents.trackpoint_timer);
+ libinput_timer_cancel(&tp->sendevents.keyboard_timer);
if (tp->buttons.trackpoint)
libinput_device_remove_event_listener(
&tp->sendevents.trackpoint_listener);
+
+ if (tp->sendevents.keyboard)
+ libinput_device_remove_event_listener(
+ &tp->sendevents.keyboard_listener);
}
static void
@@ -881,13 +897,59 @@ tp_trackpoint_event(uint64_t time, struct libinput_event *event, void *data)
}
static void
+tp_keyboard_timeout(uint64_t now, void *data)
+{
+ struct tp_dispatch *tp = data;
+
+ tp_tap_resume(tp, now);
+ tp->sendevents.keyboard_active = false;
+}
+
+static void
+tp_keyboard_event(uint64_t time, struct libinput_event *event, void *data)
+{
+ struct tp_dispatch *tp = data;
+ struct libinput_event_keyboard *kbdev;
+
+ if (event->type != LIBINPUT_EVENT_KEYBOARD_KEY)
+ return;
+
+ kbdev = libinput_event_get_keyboard_event(event);
+ /* modifier keys don't trigger disable-while-typing so things like
+ * ctrl+zoom or ctrl+click are possible */
+ switch (libinput_event_keyboard_get_key(kbdev)) {
+ case KEY_LEFTCTRL:
+ case KEY_RIGHTCTRL:
+ case KEY_LEFTALT:
+ case KEY_RIGHTALT:
+ case KEY_LEFTSHIFT:
+ case KEY_RIGHTSHIFT:
+ case KEY_FN:
+ return;
+ default:
+ break;
+ }
+
+ if (!tp->sendevents.keyboard_active) {
+ tp_edge_scroll_stop_events(tp, time);
+ tp_gesture_stop(tp, time);
+ tp_tap_suspend(tp, time);
+ tp->sendevents.keyboard_active = true;
+ }
+
+ libinput_timer_set(&tp->sendevents.keyboard_timer,
+ time + DEFAULT_KEYBOARD_ACTIVITY_TIMEOUT);
+}
+
+static void
tp_device_added(struct evdev_device *device,
struct evdev_device *added_device)
{
struct tp_dispatch *tp = (struct tp_dispatch*)device->dispatch;
unsigned int bus_tp = libevdev_get_id_bustype(device->evdev),
- bus_trp = libevdev_get_id_bustype(added_device->evdev);
- bool tp_is_internal, trp_is_internal;
+ bus_trp = libevdev_get_id_bustype(added_device->evdev),
+ bus_kbd = libevdev_get_id_bustype(added_device->evdev);
+ bool tp_is_internal, trp_is_internal, kbd_is_internal;
tp_is_internal = bus_tp != BUS_USB && bus_tp != BUS_BLUETOOTH;
trp_is_internal = bus_trp != BUS_USB && bus_trp != BUS_BLUETOOTH;
@@ -903,6 +965,18 @@ tp_device_added(struct evdev_device *device,
tp_trackpoint_event, tp);
}
+ /* FIXME: detect external keyboard better */
+ kbd_is_internal = bus_tp != BUS_BLUETOOTH &&
+ bus_kbd == bus_tp;
+ if (tp_is_internal && kbd_is_internal &&
+ tp->sendevents.keyboard == NULL) {
+ libinput_device_add_event_listener(&added_device->base,
+ &tp->sendevents.keyboard_listener,
+ tp_keyboard_event, tp);
+ tp->sendevents.keyboard = added_device;
+ tp->sendevents.keyboard_active = false;
+ }
+
if (tp->sendevents.current_mode !=
LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE)
return;
@@ -929,6 +1003,12 @@ tp_device_removed(struct evdev_device *device,
tp->buttons.trackpoint = NULL;
}
+ if (removed_device == tp->sendevents.keyboard) {
+ libinput_device_remove_event_listener(
+ &tp->sendevents.keyboard_listener);
+ tp->sendevents.keyboard = NULL;
+ }
+
if (tp->sendevents.current_mode !=
LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE)
return;
@@ -1204,6 +1284,10 @@ tp_init_sendevents(struct tp_dispatch *tp,
libinput_timer_init(&tp->sendevents.trackpoint_timer,
tp->device->base.seat->libinput,
tp_trackpoint_timeout, tp);
+
+ libinput_timer_init(&tp->sendevents.keyboard_timer,
+ tp->device->base.seat->libinput,
+ tp_keyboard_timeout, tp);
return 0;
}
diff --git a/src/evdev-mt-touchpad.h b/src/evdev-mt-touchpad.h
index ba65e41..3d51a39 100644
--- a/src/evdev-mt-touchpad.h
+++ b/src/evdev-mt-touchpad.h
@@ -64,6 +64,7 @@ enum touch_state {
enum touch_palm_state {
PALM_NONE = 0,
PALM_EDGE,
+ PALM_TYPING,
};
enum button_event {
@@ -277,9 +278,15 @@ struct tp_dispatch {
struct {
struct libinput_device_config_send_events config;
enum libinput_config_send_events_mode current_mode;
+
bool trackpoint_active;
struct libinput_event_listener trackpoint_listener;
struct libinput_timer trackpoint_timer;
+
+ bool keyboard_active;
+ struct libinput_event_listener keyboard_listener;
+ struct libinput_timer keyboard_timer;
+ struct evdev_device *keyboard;
} sendevents;
};
--
2.3.5

View File

@ -0,0 +1,71 @@
From c2f8b508b9fc661967516ca07d2100ca8749c101 Mon Sep 17 00:00:00 2001
From: Peter Hutterer <peter.hutterer@who-t.net>
Date: Mon, 20 Apr 2015 16:20:00 +1000
Subject: [PATCH libinput 3/3] touchpad: use a two-stage timeout for
disable-while-typing
Hitting a single key triggers a short timeout, just enough to cover the time
to the next key event. Hitting more than one key triggers the longer timeout.
This should improve responsiveness after single key events when the touchpad is
still the main interaction mode and a key needs to be pressed to advance in
the UI. When typing the hands require physical movement to get back to the
touchpad anyway so a longer timeout is acceptable and more reliable.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
---
src/evdev-mt-touchpad.c | 15 +++++++++++++--
1 file changed, 13 insertions(+), 2 deletions(-)
diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c
index 32d8e25..3ebb559 100644
--- a/src/evdev-mt-touchpad.c
+++ b/src/evdev-mt-touchpad.c
@@ -34,7 +34,8 @@
#define DEFAULT_ACCEL_NUMERATOR 3000.0
#define DEFAULT_HYSTERESIS_MARGIN_DENOMINATOR 700.0
#define DEFAULT_TRACKPOINT_ACTIVITY_TIMEOUT 500 /* ms */
-#define DEFAULT_KEYBOARD_ACTIVITY_TIMEOUT 500 /* ms */
+#define DEFAULT_KEYBOARD_ACTIVITY_TIMEOUT_1 200 /* ms */
+#define DEFAULT_KEYBOARD_ACTIVITY_TIMEOUT_2 500 /* ms */
#define FAKE_FINGER_OVERFLOW (1 << 7)
static inline int
@@ -910,11 +911,18 @@ tp_keyboard_event(uint64_t time, struct libinput_event *event, void *data)
{
struct tp_dispatch *tp = data;
struct libinput_event_keyboard *kbdev;
+ unsigned int timeout;
if (event->type != LIBINPUT_EVENT_KEYBOARD_KEY)
return;
kbdev = libinput_event_get_keyboard_event(event);
+
+ /* Only trigger the timer on key down. */
+ if (libinput_event_keyboard_get_key_state(kbdev) !=
+ LIBINPUT_KEY_STATE_PRESSED)
+ return;
+
/* modifier keys don't trigger disable-while-typing so things like
* ctrl+zoom or ctrl+click are possible */
switch (libinput_event_keyboard_get_key(kbdev)) {
@@ -935,10 +943,13 @@ tp_keyboard_event(uint64_t time, struct libinput_event *event, void *data)
tp_gesture_stop(tp, time);
tp_tap_suspend(tp, time);
tp->sendevents.keyboard_active = true;
+ timeout = DEFAULT_KEYBOARD_ACTIVITY_TIMEOUT_1;
+ } else {
+ timeout = DEFAULT_KEYBOARD_ACTIVITY_TIMEOUT_2;
}
libinput_timer_set(&tp->sendevents.keyboard_timer,
- time + DEFAULT_KEYBOARD_ACTIVITY_TIMEOUT);
+ time + timeout);
}
static void
--
2.3.5

View File

@ -5,7 +5,7 @@
Name: libinput
Version: 0.15.0
Release: 1%{?gitdate:.%{gitdate}git%{gitversion}}%{?dist}
Release: 2%{?gitdate:.%{gitdate}git%{gitversion}}%{?dist}
Summary: Input device library
License: MIT
@ -18,6 +18,10 @@ Source2: commitid
Source0: http://www.freedesktop.org/software/libinput/libinput-%{version}.tar.xz
%endif
Patch01: 0001-touchpad-switch-from-is_palm-to-an-enum.patch
Patch02: 0002-touchpad-add-timeout-based-disable-while-typing.patch
Patch03: 0003-touchpad-use-a-two-stage-timeout-for-disable-while-t.patch
BuildRequires: git
BuildRequires: autoconf automake libtool pkgconfig
BuildRequires: libevdev-devel
@ -93,6 +97,9 @@ find $RPM_BUILD_ROOT -name '*.la' -delete
%changelog
* Mon May 18 2015 Peter Hutterer <peter.hutterer@redhat.com> 0.15.0-2
- Add disable-while-typing feature (#1209753)
* Tue May 05 2015 Peter Hutterer <peter.hutterer@redhat.com> 0.15.0-1
- libinput 0.15.0