summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Glossop <robgssp@gmail.com>2023-04-11 02:00:52 +0000
committerPeter Hutterer <peter.hutterer@who-t.net>2023-04-11 02:00:52 +0000
commit57f0354ee59179d5e3b0735f6c2d01f7ac37c4af (patch)
tree83c3ad02f859788acbc16cdff0ee6a02438fd281
parent7c84fb87e9a2915ffbbe27a6398abb670bf09f43 (diff)
downloadlibinput-57f0354ee59179d5e3b0735f6c2d01f7ac37c4af.tar.gz
Disregard touchless clicks on flaky devices
Some touchpads, notably those on the Dell XPS 15 9500, are prone to registering touchpad clicks when the case is sufficiently flexed. Ignore these by disregarding any clicks that are registered without touchpad touch. Signed-off-by: Rob Glossop <robgssp@gmail.com>
-rw-r--r--meson.build1
-rw-r--r--quirks/50-system-dell.quirks1
-rw-r--r--src/evdev-mt-touchpad-buttons.c12
-rw-r--r--src/quirks.c1
-rw-r--r--src/quirks.h1
-rw-r--r--test/litest-device-synaptics-phantomclicks.c100
-rw-r--r--test/litest.h1
-rw-r--r--test/test-device.c2
-rw-r--r--test/test-touchpad-buttons.c36
-rw-r--r--test/test-touchpad.c24
10 files changed, 162 insertions, 17 deletions
diff --git a/meson.build b/meson.build
index 211aae2c..e6488eb4 100644
--- a/meson.build
+++ b/meson.build
@@ -791,6 +791,7 @@ if get_option('tests')
'test/litest-device-synaptics-st.c',
'test/litest-device-synaptics-t440.c',
'test/litest-device-synaptics-x1-carbon-3rd.c',
+ 'test/litest-device-synaptics-phantomclicks.c',
'test/litest-device-tablet-mode-switch.c',
'test/litest-device-thinkpad-extrabuttons.c',
'test/litest-device-trackpoint.c',
diff --git a/quirks/50-system-dell.quirks b/quirks/50-system-dell.quirks
index 45ef58b2..4a65020e 100644
--- a/quirks/50-system-dell.quirks
+++ b/quirks/50-system-dell.quirks
@@ -45,6 +45,7 @@ AttrPalmPressureThreshold=150
MatchName=* Touchpad
MatchDMIModalias=dmi:*svnDellInc.:pnXPS159500:*
ModelTouchpadVisibleMarker=0
+ModelTouchpadPhantomClicks=1
[Dell Latitude D620 Trackpoint]
MatchName=*DualPoint Stick
diff --git a/src/evdev-mt-touchpad-buttons.c b/src/evdev-mt-touchpad-buttons.c
index 75ddebb2..8b7813dc 100644
--- a/src/evdev-mt-touchpad-buttons.c
+++ b/src/evdev-mt-touchpad-buttons.c
@@ -1233,6 +1233,18 @@ tp_post_clickpadbutton_buttons(struct tp_dispatch *tp, uint64_t time)
struct tp_touch *t;
uint32_t area = 0;
+ if (evdev_device_has_model_quirk(tp->device,
+ QUIRK_MODEL_TOUCHPAD_PHANTOM_CLICKS) &&
+ tp->nactive_slots == 0) {
+ /* Some touchpads, notably those on the Dell XPS 15 9500,
+ * are prone to registering touchpad clicks when the
+ * case is sufficiently flexed. Ignore these by
+ * disregarding any clicks that are registered without
+ * touchpad touch. */
+ tp->buttons.click_pending = true;
+ return 0;
+ }
+
tp_for_each_touch(tp, t) {
switch (t->button.current) {
case BUTTON_EVENT_IN_AREA:
diff --git a/src/quirks.c b/src/quirks.c
index 7e916009..0fbd53f2 100644
--- a/src/quirks.c
+++ b/src/quirks.c
@@ -267,6 +267,7 @@ quirk_get_name(enum quirk q)
case QUIRK_MODEL_TABLET_MODE_NO_SUSPEND: return "ModelTabletModeNoSuspend";
case QUIRK_MODEL_TABLET_MODE_SWITCH_UNRELIABLE: return "ModelTabletModeSwitchUnreliable";
case QUIRK_MODEL_TOUCHPAD_VISIBLE_MARKER: return "ModelTouchpadVisibleMarker";
+ case QUIRK_MODEL_TOUCHPAD_PHANTOM_CLICKS: return "ModelTouchpadPhantomClicks";
case QUIRK_MODEL_TRACKBALL: return "ModelTrackball";
case QUIRK_MODEL_WACOM_TOUCHPAD: return "ModelWacomTouchpad";
case QUIRK_MODEL_PRESSURE_PAD: return "ModelPressurePad";
diff --git a/src/quirks.h b/src/quirks.h
index 30878546..340d0463 100644
--- a/src/quirks.h
+++ b/src/quirks.h
@@ -87,6 +87,7 @@ enum quirk {
QUIRK_MODEL_TRACKBALL,
QUIRK_MODEL_WACOM_TOUCHPAD,
QUIRK_MODEL_PRESSURE_PAD,
+ QUIRK_MODEL_TOUCHPAD_PHANTOM_CLICKS,
_QUIRK_LAST_MODEL_QUIRK_, /* Guard: do not modify */
diff --git a/test/litest-device-synaptics-phantomclicks.c b/test/litest-device-synaptics-phantomclicks.c
new file mode 100644
index 00000000..2f65270d
--- /dev/null
+++ b/test/litest-device-synaptics-phantomclicks.c
@@ -0,0 +1,100 @@
+/*
+ * Copyright © 2023 Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include "config.h"
+
+#include "litest.h"
+#include "litest-int.h"
+
+static struct input_event down[] = {
+ { .type = EV_ABS, .code = ABS_X, .value = LITEST_AUTO_ASSIGN },
+ { .type = EV_ABS, .code = ABS_Y, .value = LITEST_AUTO_ASSIGN },
+ { .type = EV_ABS, .code = ABS_MT_SLOT, .value = LITEST_AUTO_ASSIGN },
+ { .type = EV_ABS, .code = ABS_MT_TRACKING_ID, .value = LITEST_AUTO_ASSIGN },
+ { .type = EV_ABS, .code = ABS_MT_POSITION_X, .value = LITEST_AUTO_ASSIGN },
+ { .type = EV_ABS, .code = ABS_MT_POSITION_Y, .value = LITEST_AUTO_ASSIGN },
+ { .type = EV_SYN, .code = SYN_REPORT, .value = 0 },
+ { .type = -1, .code = -1 },
+};
+
+static struct input_event move[] = {
+ { .type = EV_ABS, .code = ABS_MT_SLOT, .value = LITEST_AUTO_ASSIGN },
+ { .type = EV_ABS, .code = ABS_X, .value = LITEST_AUTO_ASSIGN },
+ { .type = EV_ABS, .code = ABS_Y, .value = LITEST_AUTO_ASSIGN },
+ { .type = EV_ABS, .code = ABS_MT_POSITION_X, .value = LITEST_AUTO_ASSIGN },
+ { .type = EV_ABS, .code = ABS_MT_POSITION_Y, .value = LITEST_AUTO_ASSIGN },
+ { .type = EV_SYN, .code = SYN_REPORT, .value = 0 },
+ { .type = -1, .code = -1 },
+};
+
+static struct litest_device_interface interface = {
+ .touch_down_events = down,
+ .touch_move_events = move,
+};
+
+static struct input_id input_id = {
+ .bustype = 0x18,
+ .vendor = 0x4f3,
+ .product = 0x311c,
+};
+
+static int events[] = {
+ EV_KEY, BTN_LEFT,
+ EV_KEY, BTN_TOOL_FINGER,
+ EV_KEY, BTN_TOUCH,
+ EV_KEY, BTN_TOOL_DOUBLETAP,
+ EV_KEY, BTN_TOOL_TRIPLETAP,
+ EV_KEY, BTN_TOOL_QUADTAP,
+ EV_KEY, BTN_TOOL_QUINTTAP,
+ INPUT_PROP_MAX, INPUT_PROP_POINTER,
+ INPUT_PROP_MAX, INPUT_PROP_BUTTONPAD,
+ -1, -1,
+};
+
+static struct input_absinfo absinfo[] = {
+ { ABS_X, 0, 4654, 0, 0, 31 },
+ { ABS_Y, 0, 2730, 0, 0, 31 },
+ { ABS_MT_SLOT, 0, 4, 0, 0, 0 },
+ { ABS_MT_POSITION_X, 0, 4654, 0, 0, 31 },
+ { ABS_MT_POSITION_Y, 0, 2730, 0, 0, 31 },
+ { ABS_MT_TOOL_TYPE, 0, 2, 0, 0, 0 },
+ { ABS_MT_TRACKING_ID, 0, 65535, 0, 0, 0 },
+ { .value = -1 }
+};
+
+static const char quirk_file[] =
+"[litest Dell XPS 15 9500 Touchpad]\n"
+"MatchName=litest DELL097D:00 04F3:311C Touchpad\n"
+"ModelTouchpadVisibleMarker=0\n"
+"ModelTouchpadPhantomClicks=1\n";
+
+TEST_DEVICE("synaptics-phantomclicks",
+ .type = LITEST_SYNAPTICS_PHANTOMCLICKS,
+ .features = LITEST_TOUCHPAD | LITEST_CLICKPAD | LITEST_BUTTON,
+ .interface = &interface,
+ .name = "DELL097D:00 04F3:311C Touchpad",
+ .id = &input_id,
+ .events = events,
+ .absinfo = absinfo,
+ .quirk_file = quirk_file,
+)
diff --git a/test/litest.h b/test/litest.h
index 457790b3..71344f90 100644
--- a/test/litest.h
+++ b/test/litest.h
@@ -327,6 +327,7 @@ enum litest_device_type {
LITEST_WACOM_ISDV4_524C_PEN,
LITEST_MOUSE_FORMAT_STRING,
LITEST_LENOVO_SCROLLPOINT,
+ LITEST_SYNAPTICS_PHANTOMCLICKS,
};
#define LITEST_DEVICELESS -2
diff --git a/test/test-device.c b/test/test-device.c
index f7895b28..a117ac65 100644
--- a/test/test-device.c
+++ b/test/test-device.c
@@ -1624,7 +1624,7 @@ START_TEST(device_has_size)
ck_assert_int_eq(rc, 0);
/* This matches the current set of test devices but may fail if
* newer ones are added */
- ck_assert_double_gt(w, 40);
+ ck_assert_double_gt(w, 30);
ck_assert_double_gt(h, 20);
}
END_TEST
diff --git a/test/test-touchpad-buttons.c b/test/test-touchpad-buttons.c
index eccc1eed..f3c7a380 100644
--- a/test/test-touchpad-buttons.c
+++ b/test/test-touchpad-buttons.c
@@ -169,6 +169,12 @@ START_TEST(touchpad_1fg_clickfinger_no_touch)
struct litest_device *dev = litest_current_device();
struct libinput *li = dev->libinput;
+ if (dev->which == LITEST_SYNAPTICS_PHANTOMCLICKS) {
+ /* The XPS 15 9500 touchpad has the ModelTouchpadPhantomClicks
+ * quirk enabled and doesn't generate events without touches. */
+ return;
+ }
+
litest_enable_clickfinger(dev);
litest_drain_events(li);
@@ -187,6 +193,26 @@ START_TEST(touchpad_1fg_clickfinger_no_touch)
}
END_TEST
+START_TEST(touchpad_1fg_clickfinger_no_touch_phantomclicks)
+{
+ struct litest_device *dev = litest_current_device();
+ struct libinput *li = dev->libinput;
+
+ litest_enable_clickfinger(dev);
+
+ litest_drain_events(li);
+
+ litest_event(dev, EV_KEY, BTN_LEFT, 1);
+ litest_event(dev, EV_SYN, SYN_REPORT, 0);
+ litest_event(dev, EV_KEY, BTN_LEFT, 0);
+ litest_event(dev, EV_SYN, SYN_REPORT, 0);
+
+ libinput_dispatch(li);
+
+ litest_assert_empty_queue(li);
+}
+END_TEST
+
START_TEST(touchpad_2fg_clickfinger)
{
struct litest_device *dev = litest_current_device();
@@ -1410,7 +1436,7 @@ START_TEST(clickpad_softbutton_left_2nd_fg_move)
litest_assert_empty_queue(li);
litest_touch_down(dev, 1, 20, 20);
- litest_touch_move_to(dev, 1, 20, 20, 80, 20, 10);
+ litest_touch_move_to(dev, 1, 20, 20, 80, 20, 15);
libinput_dispatch(li);
event = libinput_get_event(li);
@@ -1441,7 +1467,7 @@ START_TEST(clickpad_softbutton_left_2nd_fg_move)
/* second finger down */
litest_touch_down(dev, 1, 20, 20);
- litest_touch_move_to(dev, 1, 20, 20, 20, 80, 10);
+ litest_touch_move_to(dev, 1, 20, 20, 20, 80, 15);
libinput_dispatch(li);
event = libinput_get_event(li);
@@ -1492,7 +1518,7 @@ START_TEST(clickpad_softbutton_left_to_right)
*/
litest_touch_down(dev, 0, 30, 90);
- litest_touch_move_to(dev, 0, 30, 90, 90, 90, 10);
+ litest_touch_move_to(dev, 0, 30, 90, 90, 90, 15);
litest_drain_events(li);
litest_event(dev, EV_KEY, BTN_LEFT, 1);
@@ -1528,7 +1554,7 @@ START_TEST(clickpad_softbutton_right_to_left)
*/
litest_touch_down(dev, 0, 80, 90);
- litest_touch_move_to(dev, 0, 80, 90, 30, 90, 10);
+ litest_touch_move_to(dev, 0, 80, 90, 30, 90, 15);
litest_drain_events(li);
litest_event(dev, EV_KEY, BTN_LEFT, 1);
@@ -2130,6 +2156,8 @@ TEST_COLLECTION(touchpad_buttons)
litest_add_for_device(touchpad_clickfinger_appletouch_2fg, LITEST_APPLETOUCH);
litest_add_for_device(touchpad_clickfinger_appletouch_3fg, LITEST_APPLETOUCH);
+ litest_add_for_device(touchpad_1fg_clickfinger_no_touch_phantomclicks, LITEST_SYNAPTICS_PHANTOMCLICKS);
+
litest_add_ranged(touchpad_clickfinger_click_drag, LITEST_CLICKPAD, LITEST_ANY, &finger_count);
litest_add(touchpad_click_defaults_clickfinger, LITEST_APPLE_CLICKPAD, LITEST_ANY);
diff --git a/test/test-touchpad.c b/test/test-touchpad.c
index d72ae0fa..2e057898 100644
--- a/test/test-touchpad.c
+++ b/test/test-touchpad.c
@@ -801,7 +801,7 @@ START_TEST(touchpad_edge_scroll_horiz_clickpad)
litest_enable_edge_scroll(dev);
litest_touch_down(dev, 0, 20, 99);
- litest_touch_move_to(dev, 0, 20, 99, 70, 99, 10);
+ litest_touch_move_to(dev, 0, 20, 99, 70, 99, 15);
litest_touch_up(dev, 0);
libinput_dispatch(li);
@@ -812,7 +812,7 @@ START_TEST(touchpad_edge_scroll_horiz_clickpad)
litest_assert_empty_queue(li);
litest_touch_down(dev, 0, 70, 99);
- litest_touch_move_to(dev, 0, 70, 99, 20, 99, 10);
+ litest_touch_move_to(dev, 0, 70, 99, 20, 99, 15);
litest_touch_up(dev, 0);
libinput_dispatch(li);
@@ -1125,7 +1125,7 @@ START_TEST(touchpad_edge_scroll_buttonareas_click_stops_scroll)
litest_drain_events(li);
litest_touch_down(dev, 0, 20, 95);
- litest_touch_move_to(dev, 0, 20, 95, 70, 95, 10);
+ litest_touch_move_to(dev, 0, 20, 95, 70, 95, 15);
litest_assert_only_axis_events(li, LIBINPUT_EVENT_POINTER_SCROLL_FINGER);
litest_button_click(dev, BTN_LEFT, true);
@@ -1150,7 +1150,7 @@ START_TEST(touchpad_edge_scroll_buttonareas_click_stops_scroll)
* edge scrolling, click, then scrolling without lifting the finger
* is so small we'll let it pass.
*/
- litest_touch_move_to(dev, 0, 70, 95, 90, 95, 10);
+ litest_touch_move_to(dev, 0, 70, 95, 90, 95, 15);
litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);
litest_button_click(dev, BTN_LEFT, false);
@@ -1175,7 +1175,7 @@ START_TEST(touchpad_edge_scroll_clickfinger_click_stops_scroll)
litest_drain_events(li);
litest_touch_down(dev, 0, 20, 95);
- litest_touch_move_to(dev, 0, 20, 95, 70, 95, 10);
+ litest_touch_move_to(dev, 0, 20, 95, 70, 95, 15);
litest_assert_only_axis_events(li, LIBINPUT_EVENT_POINTER_SCROLL_FINGER);
litest_button_click(dev, BTN_LEFT, true);
@@ -1194,7 +1194,7 @@ START_TEST(touchpad_edge_scroll_clickfinger_click_stops_scroll)
libinput_event_destroy(event);
/* clickfinger releases pointer -> expect movement */
- litest_touch_move_to(dev, 0, 70, 95, 90, 95, 10);
+ litest_touch_move_to(dev, 0, 70, 95, 90, 95, 15);
litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);
litest_assert_empty_queue(li);
@@ -1286,7 +1286,7 @@ START_TEST(touchpad_palm_detect_at_top)
litest_drain_events(li);
litest_touch_down(dev, 0, 20, 1);
- litest_touch_move_to(dev, 0, 20, 1, 70, 1, 10);
+ litest_touch_move_to(dev, 0, 20, 1, 70, 1, 15);
litest_touch_up(dev, 0);
litest_assert_empty_queue(li);
@@ -1433,7 +1433,7 @@ START_TEST(touchpad_palm_detect_palm_becomes_pointer)
litest_drain_events(li);
litest_touch_down(dev, 0, 99, 50);
- litest_touch_move_to(dev, 0, 99, 50, 0, 70, 20);
+ litest_touch_move_to(dev, 0, 99, 50, 0, 70, 25);
litest_touch_up(dev, 0);
libinput_dispatch(li);
@@ -1483,11 +1483,11 @@ START_TEST(touchpad_palm_detect_no_palm_moving_into_edges)
litest_drain_events(li);
litest_touch_down(dev, 0, 50, 50);
- litest_touch_move_to(dev, 0, 50, 50, 99, 50, 10);
+ litest_touch_move_to(dev, 0, 50, 50, 99, 50, 15);
litest_drain_events(li);
- litest_touch_move_to(dev, 0, 99, 50, 99, 90, 10);
+ litest_touch_move_to(dev, 0, 99, 50, 99, 90, 15);
libinput_dispatch(li);
litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);
@@ -1513,11 +1513,11 @@ START_TEST(touchpad_palm_detect_no_palm_moving_into_top)
litest_drain_events(li);
litest_touch_down(dev, 0, 50, 50);
- litest_touch_move_to(dev, 0, 50, 50, 0, 2, 10);
+ litest_touch_move_to(dev, 0, 50, 50, 0, 2, 15);
litest_drain_events(li);
- litest_touch_move_to(dev, 0, 0, 2, 50, 50, 10);
+ litest_touch_move_to(dev, 0, 0, 2, 50, 50, 15);
libinput_dispatch(li);
litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);