diff --git a/README.txt b/README.txt
index 0849e1d1..f557f69c 100644
--- a/README.txt
+++ b/README.txt
@@ -56,6 +56,8 @@ Where possible, please provide an
[evemu](http://www.freedesktop.org/wiki/Evemu/) recording of the input
device and/or the event sequence in question.
+See @ref reporting_bugs for more info.
+
Documentation
-------------
diff --git a/configure.ac b/configure.ac
index 65478d63..4a5cd825 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,7 +1,7 @@
AC_PREREQ([2.64])
m4_define([libinput_major_version], [0])
-m4_define([libinput_minor_version], [20])
+m4_define([libinput_minor_version], [21])
m4_define([libinput_micro_version], [0])
m4_define([libinput_version],
[libinput_major_version.libinput_minor_version.libinput_micro_version])
@@ -31,7 +31,7 @@ AM_INIT_AUTOMAKE([1.11 foreign no-dist-gzip dist-xz])
# b) If interfaces have been changed or added, but binary compatibility has
# been preserved, change to C+1:0:A+1
# c) If the interface is the same as the previous version, change to C:R+1:A
-LIBINPUT_LT_VERSION=14:0:4
+LIBINPUT_LT_VERSION=15:0:5
AC_SUBST(LIBINPUT_LT_VERSION)
AM_SILENT_RULES([yes])
diff --git a/doc/Makefile.am b/doc/Makefile.am
index 4c487a3a..ff65e5ce 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -18,13 +18,15 @@ header_files = \
$(srcdir)/normalization-of-relative-motion.dox \
$(srcdir)/palm-detection.dox \
$(srcdir)/page-hierarchy.dox \
+ $(srcdir)/reporting-bugs.dox \
$(srcdir)/scrolling.dox \
$(srcdir)/seats.dox \
$(srcdir)/t440-support.dox \
$(srcdir)/tablet-support.dox \
$(srcdir)/tapping.dox \
$(srcdir)/test-suite.dox \
- $(srcdir)/tools.dox
+ $(srcdir)/tools.dox \
+ $(srcdir)/touchpads.dox
diagram_files = \
$(srcdir)/dot/seats-sketch.gv \
diff --git a/doc/page-hierarchy.dox b/doc/page-hierarchy.dox
index 78592fc2..1e82535f 100644
--- a/doc/page-hierarchy.dox
+++ b/doc/page-hierarchy.dox
@@ -25,6 +25,7 @@
- @subpage faq
- @subpage tools
+- @subpage reporting_bugs
@page developers Developers
diff --git a/doc/reporting-bugs.dox b/doc/reporting-bugs.dox
new file mode 100644
index 00000000..0755a9ee
--- /dev/null
+++ b/doc/reporting-bugs.dox
@@ -0,0 +1,88 @@
+/**
+@page reporting_bugs Reporting bugs
+
+A new bug can be filed here:
+https://bugs.freedesktop.org/enter_bug.cgi?product=Wayland&component=libinput
+
+When reporting bugs against libinput, please follow the instructions below
+and provide the required data. This will speed up triage, resulting in a
+quicker bugfix.
+
+First, try to identify the bugi by reproducing it reliably. The more
+specific a bug description is, the easier it is to fix. The @ref
+libinput-debug-events helper tool can help identify whether the bug is in
+libinput at all. This tool is a direct hook to libinput without a desktop
+stack in between and can thus help to identify whether a bug is in libinput
+or in one of the higher layers. See the @ref libinput-debug-events section
+for information on this tool.
+
+@section triage Required information for triage
+
+When you file a bug, please attach the following information:
+- a virtual description of your input device, see @ref evemu. This is the
+ most important piece of information, do not forget it!
+- the libinput version. Either the package version from your distribution
+ or, when running from git: git log -n 1 HEAD or git describe
+ HEAD. As a last resort: libinput-list-devices --version.
+- the current libinput settings for the device. This is a bit harder to
+ obtain, for now we'll assume you are running X11. The current settings can
+ be obtained with xinput list-props "your device name". Use
+ xinput list to obtain the device name.
+- if the device is a touchpad or a pointing stick, the vendor model number
+ of your laptop, and the content of /sys/class/dmi/id/modalias.
+- if the device is a touchpad, the physical dimensions of your touchpad in
+ mm
+
+@section evemu Recording devices with evemu
+
+evemu records the
+device capabilities together with the event stream from the kernel. On our
+side, this allows us to recreate a virtual device identical to your device
+and re-play the event sequence, hopefully triggering the same bug.
+
+evemu-record takes a /dev/input/eventX event node, but without arguments
+it will simply show the list of devices and let you select:
+@code
+$ sudo evemu-record > scroll.evemu
+Available devices:
+/dev/input/event0: Lid Switch
+/dev/input/event1: Sleep Button
+/dev/input/event2: Power Button
+/dev/input/event3: AT Translated Set 2 keyboard
+/dev/input/event4: SynPS/2 Synaptics TouchPad
+/dev/input/event5: Video Bus
+/dev/input/event6: ELAN Touchscreen
+/dev/input/event10: ThinkPad Extra Buttons
+/dev/input/event11: HDA Intel HDMI HDMI/DP,pcm=3
+/dev/input/event12: HDA Intel HDMI HDMI/DP,pcm=7
+/dev/input/event13: HDA Intel HDMI HDMI/DP,pcm=8
+/dev/input/event14: HDA Intel PCH Dock Mic
+/dev/input/event15: HDA Intel PCH Mic
+/dev/input/event16: HDA Intel PCH Dock Headphone
+/dev/input/event17: HDA Intel PCH Headphone
+/dev/input/event18: Integrated Camera
+/dev/input/event19: TPPS/2 IBM TrackPoint
+Select the device event number [0-19]:
+@endcode
+
+Select the device that triggers the issue, then reproduce the bug and Ctrl+C
+the process. The resulting recording, ("scroll.evemu" in this example) will
+contain the sequence required to reproduce the bug. If the bug fails to
+reproduce during recording, simply Ctrl+C and restart evemu-record.
+Always start the recording from a neutral state, i.e. without any buttons or
+keys down, with the position of the device in the neutral position, without
+touching the screen/touchpad.
+
+@note The longer the recording, the harder it is to identify the event
+sequence triggering the bug. Please keep the event sequence as short as possible.
+
+To verify that the recording contains the bug, you can replay it on your
+device. For example, to replay the sequence recorded in the example above:
+@code
+$ sudo evemu-play /dev/input/event4 < scroll.evemu
+@endcode
+
+If the bug is triggered by replaying on your device, attach the recording to
+the bug report.
+
+*/
diff --git a/doc/scrolling.dox b/doc/scrolling.dox
index 658fe4b6..0c03c98d 100644
--- a/doc/scrolling.dox
+++ b/doc/scrolling.dox
@@ -44,6 +44,13 @@ movements will translate into tiny scroll movements.
Scrolling in both directions at once is possible by meeting the required
distance thresholds to enable each direction separately.
+Two-finger scrolling requires the touchpad to track both touch points with
+reasonable precision. Unfortunately, some so-called "semi-mt" touchpads can
+only track the bounding box of the two fingers rather than the actual
+position of each finger. In addition, that bounding box usually suffers from
+a low resolution, causing jumpy movement during two-finger scrolling.
+libinput does not provide two-finger scrolling on those touchpads.
+
@section edge_scrolling Edge scrolling
On some touchpads, edge scrolling is available, triggered by moving a single
diff --git a/doc/touchpads.dox b/doc/touchpads.dox
new file mode 100644
index 00000000..fa509bc6
--- /dev/null
+++ b/doc/touchpads.dox
@@ -0,0 +1,162 @@
+/**
+@page touchpads Touchpads
+
+This page provides an outline of touchpad devices. Touchpads aren't simply
+categorised into a single type, instead they have a set of properties, a
+combination of number of physical buttons, multitouch support abilities and
+other properties.
+
+@section touchpads_buttons Number of buttons
+
+@subsection touchapds_buttons_phys Physically separate buttons
+
+Touchpads with physical buttons usually provide two buttons, left and right.
+A few touchpads with three buttons exist, and Apple used to have touchpads
+with a single physical buttons until ca 2008. Touchpads with only two
+buttons require the software stack to emulate a middle button. libinput does
+this when both buttons are pressed simultaneously.
+
+Note that many Lenovo laptops provide a pointing stick above the touchpad.
+This pointing stick has a set of physical buttons just above the touchpad.
+While many users use those as substitute touchpad buttons, they logically
+belong to the pointing stick. The *40 and *50 series are an exception here,
+the former had no physical buttons on the touchpad and required the top
+section of the pad to emulate pointing stick buttons, the *50 series has
+physical buttons but they are wired to the touchpads. The kernel re-routes
+those buttons through the trackstick device. See @ref t440_support for more
+information.
+
+@subsection touchpads_buttons_clickpads Clickpads
+
+Clickpads are the most common type of touchpads these days. A Clickpad has
+no separate physical buttons, instead the touchpad itself is clickable as a
+whole, i.e. a user presses down on the touch area and triggers a physical
+click. Clickpads thus only provide a single button, everything else needs to
+be software-emulated. See @ref clickpad_softbuttons for more information.
+
+Clickpads are labelled by the kernel with the @c INPUT_PROP_BUTTONPAD input
+property.
+
+@subsection touchpads_buttons_forcepads Forcepads
+
+Forcepads are Clickpads without a physical button underneath the hardware.
+They provide pressure and may have a vibration element that is
+software-controlled. This element can simulate the feel of a physical
+click or be co-opted for other tasks.
+
+
+@section touchpads_touch Touch capabilities
+
+Virtually all touchpads available now can detect multiple fingers on
+the touchpad, i.e. provide information on how many fingers are on the
+touchpad. The touch capabilities described here specify how many fingers a
+device can track, i.e. provide reliable positional information for.
+In the kernel each finger is tracked in a so-called "slot", the number of
+slots thus equals the number of simultaneous touches a device can track.
+
+@subsection touchapds_touch_st Single-touch touchpads
+
+Single-finger touchpads can track a single touchpoint. Most single-touch
+touchpads can also detect three fingers on the touchpad, but no positional
+information is provided for those. In libinput, these touches are termed
+"fake touches". The kernel sends @c BTN_TOOL_DOUBLETAP, @c
+BTN_TOOL_TRIPLETAP, @c BTN_TOOL_QUADTAP and @c BTN_TOOL_QUINTTAP events when
+multiple fingers are detected.
+
+@subsection touchpads_touch_mt Pure multi-touch touchpads
+
+Pure multi-touch touchpads are those that can track, i.e. identify the
+location of all fingers on the touchpad. Apple's touchpads support 16
+touches, others support 5 touches like the Synaptics touchpads when using
+SMBus.
+
+These touchpads usually also provide extra information. Apple touchpads
+provide an ellipsis and the orientation of the ellipsis for each touch point.
+Other touchpads provide a pressure value for each touch point (see @ref
+touchpads_pressure_handling).
+
+Note that the kernel sends @c BTN_TOOL_DOUBLETAP, @c
+BTN_TOOL_TRIPLETAP, @c BTN_TOOL_QUADTAP and @c BTN_TOOL_QUINTTAP events for
+all touches for backwards compatibility. libinput ignores these events if
+the touchpad can track touches correctly.
+
+@subsection touchpads_touch_partial_mt Partial multi-touch touchpads
+
+The vast majority of touchpads fall into this category, the half-way
+point between single-touch and pure multi-touch. These devices can track N
+fingers, but detect more than N. For example, when using the serial
+protocol, Synaptics touchpads can track two fingers but may detect up to
+five.
+
+The number of slots may limit which features are available in libinput.
+Any device with two slots can support two-finger scrolling, but @ref
+thumb-detection or @ref palm_detection may be limited if only two slots are
+available.
+
+@subsection touchpads_touch_semi_mt Semi-mt touchpads
+
+A sub-class of partial multi-touch touchpads. These touchpads can
+technically detect two fingers but the location of both is limited to the
+bounding box, i.e. the first touch is always the top-left one and the second
+touch is the bottom-right one. Coordinates jump around as fingers move past
+each other.
+
+Many semi-mt touchpads also have a lower resolution for the second touch, or
+both touches. This may limit some features such as @ref gestures or
+@ref scrolling.
+
+Semi-mt are labelled by the kernel with the @c INPUT_PROP_SEMI_MT input
+property.
+
+@section touchpads_mis Other touchpad properties
+
+@subsection touchpads_external External touchpads
+
+External touchpads are USB or Bluetooth touchpads not in a laptop chassis,
+e.g. Apple Magic Trackpad or the Logitech T650. These are usually @ref
+touchpads_buttons_clickpads the biggest difference is that they can be
+removed or added at runtime.
+
+One interaction method that is only possible on external touchpads is a
+thumb resting on the very edge/immediately next to the touchpad. On the far
+edge, touchpads don't always detect the finger location so clicking with a
+thumb barely touching the edge makes it hard or impossible to figure out
+which software button area the finger is on.
+
+These touchpads also don't need @ref palm_detection - since they're not
+located underneath the keyboard, accidental palm touches are a non-issue.
+
+@subsection touchpads_pressure_handling Touchpads pressure handling
+
+Pressure is usually directly related to contact area. Human fingers flatten
+out as the pressure on the pad increases, resulting in a bigger contact area
+and the firmware then calculates that back into a ressure reading.
+
+libinput uses pressure to detect accidental palm contact and thumbs, though
+pressure data is often device-specific and unreliable.
+
+@subsection touchpads_circular Circular touchpads
+
+Only listed for completeness, circular touchpads have not been used in
+laptops for a number of years. These touchpad shaped in an ellipsis or
+straight.
+
+@subsection touchpads_tablets Graphics tablets
+
+Touch-capable graphics tablets are effectively external touchpads, with two
+differentiators: they are larger than normal touchpads and they have no
+regular touchpad buttons. They either work like a @ref
+touchpads_buttons_forcepads Forcepad, or rely on interaction methods that
+don't require buttons (like @ref tapping). Since the physical device is
+shared with the pen input, some touch arbitration is required to avoid touch
+input interfering when the pen is in use.
+
+@subsection touchpads_edge_zone Dedicated edge scroll area
+
+Before @ref twofinger_scrolling became the default scroll method, some
+touchpads provided a marking on the touch area that designates the
+edge to be used for scrolling. A finger movement in that edge zone should
+trigger vertical motions. Some touchpads had markers for a horizontal
+scroll area too at the bottom of the touchpad.
+*/
+
diff --git a/src/evdev-middle-button.c b/src/evdev-middle-button.c
index 48330d39..397b699c 100644
--- a/src/evdev-middle-button.c
+++ b/src/evdev-middle-button.c
@@ -27,7 +27,7 @@
#include "evdev.h"
-#define MIDDLEBUTTON_TIMEOUT 50
+#define MIDDLEBUTTON_TIMEOUT ms2us(50)
/*****************************************
* BEFORE YOU EDIT THIS FILE, look at the state diagram in
diff --git a/src/evdev-mt-touchpad-buttons.c b/src/evdev-mt-touchpad-buttons.c
index 1ee74cad..8822e08c 100644
--- a/src/evdev-mt-touchpad-buttons.c
+++ b/src/evdev-mt-touchpad-buttons.c
@@ -32,8 +32,8 @@
#include "evdev-mt-touchpad.h"
-#define DEFAULT_BUTTON_ENTER_TIMEOUT 100 /* ms */
-#define DEFAULT_BUTTON_LEAVE_TIMEOUT 300 /* ms */
+#define DEFAULT_BUTTON_ENTER_TIMEOUT ms2us(100)
+#define DEFAULT_BUTTON_LEAVE_TIMEOUT ms2us(300)
/*****************************************
* BEFORE YOU EDIT THIS FILE, look at the state diagram in
@@ -714,7 +714,8 @@ tp_init_buttons(struct tp_dispatch *tp,
"%s: clickpad advertising right button\n",
device->devname);
} else if (libevdev_has_event_code(device->evdev, EV_KEY, BTN_LEFT) &&
- !tp->buttons.is_clickpad) {
+ !tp->buttons.is_clickpad &&
+ libevdev_get_id_vendor(device->evdev) != VENDOR_ID_APPLE) {
log_bug_kernel(libinput,
"%s: non clickpad without right button?\n",
device->devname);
@@ -857,14 +858,12 @@ tp_clickfinger_set_button(struct tp_dispatch *tp)
unsigned int nfingers = tp->nfingers_down;
struct tp_touch *t;
struct tp_touch *first = NULL,
- *second = NULL,
- *third = NULL;
- uint32_t close_touches = 0;
+ *second = NULL;
- if (nfingers < 2 || nfingers > 3)
+ if (nfingers != 2)
goto out;
- /* two or three fingers down on the touchpad. Check for distance
+ /* two fingers down on the touchpad. Check for distance
* between the fingers. */
tp_for_each_touch(tp, t) {
if (t->state != TOUCH_BEGIN && t->state != TOUCH_UPDATE)
@@ -877,10 +876,6 @@ tp_clickfinger_set_button(struct tp_dispatch *tp)
first = t;
else if (!second)
second = t;
- else if (!third) {
- third = t;
- break;
- }
}
if (!first || !second) {
@@ -888,15 +883,10 @@ tp_clickfinger_set_button(struct tp_dispatch *tp)
goto out;
}
- close_touches |= tp_check_clickfinger_distance(tp, first, second) << 0;
- close_touches |= tp_check_clickfinger_distance(tp, second, third) << 1;
- close_touches |= tp_check_clickfinger_distance(tp, first, third) << 2;
-
- switch(__builtin_popcount(close_touches)) {
- case 0: nfingers = 1; break;
- case 1: nfingers = 2; break;
- default: nfingers = 3; break;
- }
+ if (tp_check_clickfinger_distance(tp, first, second))
+ nfingers = 2;
+ else
+ nfingers = 1;
out:
switch (nfingers) {
@@ -923,8 +913,8 @@ tp_notify_clickpadbutton(struct tp_dispatch *tp,
struct evdev_dispatch *dispatch = tp->buttons.trackpoint->dispatch;
struct input_event event;
- event.time.tv_sec = time/1000;
- event.time.tv_usec = (time % 1000) * 1000;
+ event.time.tv_sec = time / ms2us(1000);
+ event.time.tv_usec = time % ms2us(1000);
event.type = EV_KEY;
event.code = button;
event.value = (state == LIBINPUT_BUTTON_STATE_PRESSED) ? 1 : 0;
diff --git a/src/evdev-mt-touchpad-edge-scroll.c b/src/evdev-mt-touchpad-edge-scroll.c
index 928f6029..49028087 100644
--- a/src/evdev-mt-touchpad-edge-scroll.c
+++ b/src/evdev-mt-touchpad-edge-scroll.c
@@ -93,7 +93,7 @@ static inline void
tp_edge_scroll_set_timer(struct tp_dispatch *tp,
struct tp_touch *t)
{
- const int DEFAULT_SCROLL_LOCK_TIMEOUT = 300; /* ms */
+ const int DEFAULT_SCROLL_LOCK_TIMEOUT = ms2us(300);
/* if we use software buttons, we disable timeout-based
* edge scrolling. A finger resting on the button areas is
* likely there to trigger a button event.
diff --git a/src/evdev-mt-touchpad-gestures.c b/src/evdev-mt-touchpad-gestures.c
index 1acf1111..d82a6fb9 100644
--- a/src/evdev-mt-touchpad-gestures.c
+++ b/src/evdev-mt-touchpad-gestures.c
@@ -29,8 +29,8 @@
#include "evdev-mt-touchpad.h"
-#define DEFAULT_GESTURE_SWITCH_TIMEOUT 100 /* ms */
-#define DEFAULT_GESTURE_2FG_SCROLL_TIMEOUT 1000 /* ms */
+#define DEFAULT_GESTURE_SWITCH_TIMEOUT ms2us(100)
+#define DEFAULT_GESTURE_2FG_SCROLL_TIMEOUT ms2us(500)
static inline const char*
gesture_state_to_str(enum tp_gesture_2fg_state state)
@@ -157,7 +157,7 @@ tp_gesture_get_active_touches(struct tp_dispatch *tp,
memset(touches, 0, count * sizeof(struct tp_touch *));
- for (i = 0; i < tp->num_slots; i++) {
+ for (i = 0; i < tp->ntouches; i++) {
t = &tp->touches[i];
if (tp_touch_active(tp, t)) {
touches[n++] = t;
@@ -189,8 +189,10 @@ tp_gesture_get_direction(struct tp_dispatch *tp, struct tp_touch *touch)
/*
* Semi-mt touchpads have somewhat inaccurate coordinates when
* 2 fingers are down, so use a slightly larger threshold.
+ * Elantech semi-mt touchpads are accurate enough though.
*/
- if (tp->semi_mt)
+ if (tp->semi_mt &&
+ (tp->device->model_flags & EVDEV_MODEL_ELANTECH_TOUCHPAD) == 0)
move_threshold = TP_MM_TO_DPI_NORMALIZED(4);
else
move_threshold = TP_MM_TO_DPI_NORMALIZED(2);
@@ -264,26 +266,11 @@ tp_gesture_twofinger_handle_state_none(struct tp_dispatch *tp, uint64_t time)
static enum tp_gesture_2fg_state
tp_gesture_twofinger_handle_state_unknown(struct tp_dispatch *tp, uint64_t time)
{
- struct normalized_coords normalized;
- struct device_float_coords delta;
struct tp_touch *first = tp->gesture.touches[0],
*second = tp->gesture.touches[1];
int dir1, dir2;
- delta = device_delta(first->point, second->point);
- normalized = tp_normalize_delta(tp, delta);
-
- /* If fingers are further than 3 cm apart assume pinch */
- if (normalized_length(normalized) > TP_MM_TO_DPI_NORMALIZED(30)) {
- tp_gesture_get_pinch_info(tp,
- &tp->gesture.initial_distance,
- &tp->gesture.angle,
- &tp->gesture.center);
- tp->gesture.prev_scale = 1.0;
- return GESTURE_2FG_STATE_PINCH;
- }
-
- /* Elif fingers have been close together for a while, scroll */
+ /* if fingers stay unmoving for a while, assume (slow) scroll */
if (time > (tp->gesture.initial_time + DEFAULT_GESTURE_2FG_SCROLL_TIMEOUT)) {
tp_gesture_set_scroll_buildup(tp);
return GESTURE_2FG_STATE_SCROLL;
@@ -310,7 +297,7 @@ tp_gesture_twofinger_handle_state_unknown(struct tp_dispatch *tp, uint64_t time)
((dir2 & 0x80) && (dir1 & 0x01))) {
tp_gesture_set_scroll_buildup(tp);
return GESTURE_2FG_STATE_SCROLL;
- } else {
+ } else if (tp->gesture.enabled) {
tp_gesture_get_pinch_info(tp,
&tp->gesture.initial_distance,
&tp->gesture.angle,
@@ -318,6 +305,8 @@ tp_gesture_twofinger_handle_state_unknown(struct tp_dispatch *tp, uint64_t time)
tp->gesture.prev_scale = 1.0;
return GESTURE_2FG_STATE_PINCH;
}
+
+ return GESTURE_2FG_STATE_UNKNOWN;
}
static enum tp_gesture_2fg_state
@@ -578,6 +567,11 @@ tp_gesture_handle_state(struct tp_dispatch *tp, uint64_t time)
int
tp_init_gesture(struct tp_dispatch *tp)
{
+ if (tp->device->model_flags & EVDEV_MODEL_JUMPING_SEMI_MT)
+ tp->gesture.enabled = false;
+ else
+ tp->gesture.enabled = true;
+
tp->gesture.twofinger_state = GESTURE_2FG_STATE_NONE;
libinput_timer_init(&tp->gesture.finger_count_switch_timer,
diff --git a/src/evdev-mt-touchpad-tap.c b/src/evdev-mt-touchpad-tap.c
index b2977545..de4945e6 100644
--- a/src/evdev-mt-touchpad-tap.c
+++ b/src/evdev-mt-touchpad-tap.c
@@ -35,8 +35,8 @@
#include "evdev-mt-touchpad.h"
-#define DEFAULT_TAP_TIMEOUT_PERIOD 180
-#define DEFAULT_DRAG_TIMEOUT_PERIOD 300
+#define DEFAULT_TAP_TIMEOUT_PERIOD ms2us(180)
+#define DEFAULT_DRAG_TIMEOUT_PERIOD ms2us(300)
#define DEFAULT_TAP_MOVE_THRESHOLD TP_MM_TO_DPI_NORMALIZED(3)
enum tap_event {
diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c
index 8be7db30..0d4d8578 100644
--- a/src/evdev-mt-touchpad.c
+++ b/src/evdev-mt-touchpad.c
@@ -30,9 +30,10 @@
#include "evdev-mt-touchpad.h"
-#define DEFAULT_TRACKPOINT_ACTIVITY_TIMEOUT 300 /* ms */
-#define DEFAULT_KEYBOARD_ACTIVITY_TIMEOUT_1 200 /* ms */
-#define DEFAULT_KEYBOARD_ACTIVITY_TIMEOUT_2 500 /* ms */
+#define DEFAULT_TRACKPOINT_ACTIVITY_TIMEOUT ms2us(300)
+#define DEFAULT_KEYBOARD_ACTIVITY_TIMEOUT_1 ms2us(200)
+#define DEFAULT_KEYBOARD_ACTIVITY_TIMEOUT_2 ms2us(500)
+#define THUMB_MOVE_TIMEOUT ms2us(300)
#define FAKE_FINGER_OVERFLOW (1 << 7)
static inline int
@@ -588,7 +589,7 @@ tp_palm_detect_trackpoint(struct tp_dispatch *tp,
static void
tp_palm_detect(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time)
{
- const int PALM_TIMEOUT = 200; /* ms */
+ const int PALM_TIMEOUT = ms2us(200);
const int DIRECTIONS = NE|E|SE|SW|W|NW;
struct device_float_coords delta;
int dirs;
@@ -700,7 +701,7 @@ tp_thumb_detect(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time)
t->thumb.state = THUMB_STATE_YES;
else if (t->point.y > tp->thumb.lower_thumb_line &&
tp->scroll.method != LIBINPUT_CONFIG_SCROLL_EDGE &&
- t->thumb.first_touch_time + 300 < time)
+ t->thumb.first_touch_time + THUMB_MOVE_TIMEOUT < time)
t->thumb.state = THUMB_STATE_YES;
/* now what? we marked it as thumb, so:
@@ -1465,6 +1466,21 @@ tp_init_slots(struct tp_dispatch *tp,
tp->semi_mt = libevdev_has_property(device->evdev, INPUT_PROP_SEMI_MT);
+ /* This device has a terrible resolution when two fingers are down,
+ * causing scroll jumps. The single-touch emulation ABS_X/Y is
+ * accurate but the ABS_MT_POSITION touchpoints report the bounding
+ * box and that causes jumps. So we simply pretend it's a single
+ * touch touchpad with the BTN_TOOL bits.
+ * See https://bugzilla.redhat.com/show_bug.cgi?id=1235175 for an
+ * explanation.
+ */
+ if (tp->semi_mt &&
+ (device->model_flags & EVDEV_MODEL_JUMPING_SEMI_MT)) {
+ tp->num_slots = 1;
+ tp->slot = 0;
+ tp->has_mt = false;
+ }
+
ARRAY_FOR_EACH(max_touches, m) {
if (libevdev_has_event_code(device->evdev,
EV_KEY,
@@ -1522,10 +1538,8 @@ tp_init_accel(struct tp_dispatch *tp, double diagonal)
}
static uint32_t
-tp_scroll_config_scroll_method_get_methods(struct libinput_device *device)
+tp_scroll_get_methods(struct tp_dispatch *tp)
{
- struct evdev_device *evdev = (struct evdev_device*)device;
- struct tp_dispatch *tp = (struct tp_dispatch*)evdev->dispatch;
uint32_t methods = LIBINPUT_CONFIG_SCROLL_EDGE;
if (tp->ntouches >= 2)
@@ -1534,6 +1548,15 @@ tp_scroll_config_scroll_method_get_methods(struct libinput_device *device)
return methods;
}
+static uint32_t
+tp_scroll_config_scroll_method_get_methods(struct libinput_device *device)
+{
+ struct evdev_device *evdev = (struct evdev_device*)device;
+ struct tp_dispatch *tp = (struct tp_dispatch*)evdev->dispatch;
+
+ return tp_scroll_get_methods(tp);
+}
+
static enum libinput_config_status
tp_scroll_config_scroll_method_set_method(struct libinput_device *device,
enum libinput_config_scroll_method method)
@@ -1565,10 +1588,21 @@ tp_scroll_config_scroll_method_get_method(struct libinput_device *device)
static enum libinput_config_scroll_method
tp_scroll_get_default_method(struct tp_dispatch *tp)
{
- if (tp->ntouches >= 2)
- return LIBINPUT_CONFIG_SCROLL_2FG;
+ uint32_t methods;
+ enum libinput_config_scroll_method method;
+
+ methods = tp_scroll_get_methods(tp);
+
+ if (methods & LIBINPUT_CONFIG_SCROLL_2FG)
+ method = LIBINPUT_CONFIG_SCROLL_2FG;
else
- return LIBINPUT_CONFIG_SCROLL_EDGE;
+ method = LIBINPUT_CONFIG_SCROLL_EDGE;
+
+ if ((methods & method) == 0)
+ log_bug_libinput(tp_libinput_context(tp),
+ "Invalid default scroll method %d\n",
+ method);
+ return method;
}
static enum libinput_config_scroll_method
@@ -1732,13 +1766,6 @@ tp_init_thumb(struct tp_dispatch *tp)
if (!tp->buttons.is_clickpad)
return 0;
- abs = libevdev_get_abs_info(device->evdev, ABS_MT_PRESSURE);
- if (!abs)
- return 0;
-
- if (abs->maximum - abs->minimum < 255)
- return 0;
-
/* if the touchpad is less than 50mm high, skip thumb detection.
* it's too small to meaningfully interact with a thumb on the
* touchpad */
@@ -1746,6 +1773,23 @@ tp_init_thumb(struct tp_dispatch *tp)
if (h < 50)
return 0;
+ tp->thumb.detect_thumbs = true;
+ tp->thumb.threshold = INT_MAX;
+
+ /* detect thumbs by pressure in the bottom 15mm, detect thumbs by
+ * lingering in the bottom 8mm */
+ ymax = tp->device->abs.absinfo_y->maximum;
+ yres = tp->device->abs.absinfo_y->resolution;
+ tp->thumb.upper_thumb_line = ymax - yres * 15;
+ tp->thumb.lower_thumb_line = ymax - yres * 8;
+
+ abs = libevdev_get_abs_info(device->evdev, ABS_MT_PRESSURE);
+ if (!abs)
+ goto out;
+
+ if (abs->maximum - abs->minimum < 255)
+ goto out;
+
/* Our reference touchpad is the T440s with 42x42 resolution.
* Higher-res touchpads exhibit higher pressure for the same
* interaction. On the T440s, the threshold value is 100, you don't
@@ -1757,14 +1801,12 @@ tp_init_thumb(struct tp_dispatch *tp)
yres = tp->device->abs.absinfo_y->resolution;
threshold = 100.0 * hypot(xres, yres)/hypot(42, 42);
tp->thumb.threshold = max(100, threshold);
- tp->thumb.detect_thumbs = true;
- /* detect thumbs by pressure in the bottom 15mm, detect thumbs by
- * lingering in the bottom 8mm */
- ymax = tp->device->abs.absinfo_y->maximum;
- yres = tp->device->abs.absinfo_y->resolution;
- tp->thumb.upper_thumb_line = ymax - yres * 15;
- tp->thumb.lower_thumb_line = ymax - yres * 8;
+out:
+ log_debug(tp_libinput_context(tp),
+ "thumb: enabled thumb detection%s on '%s'\n",
+ tp->thumb.threshold != INT_MAX ? " (+pressure)" : "",
+ device->devname);
return 0;
}
@@ -1892,6 +1934,8 @@ tp_init(struct tp_dispatch *tp,
return -1;
device->seat_caps |= EVDEV_DEVICE_POINTER;
+ if (tp->gesture.enabled)
+ device->seat_caps |= EVDEV_DEVICE_GESTURE;
return 0;
}
diff --git a/src/evdev-mt-touchpad.h b/src/evdev-mt-touchpad.h
index 6350a9f6..3bd84258 100644
--- a/src/evdev-mt-touchpad.h
+++ b/src/evdev-mt-touchpad.h
@@ -203,7 +203,7 @@ struct tp_touch {
struct {
enum touch_palm_state state;
struct device_coords first; /* first coordinates if is_palm == true */
- uint32_t time; /* first timestamp if is_palm == true */
+ uint64_t time; /* first timestamp if is_palm == true */
} palm;
struct {
@@ -246,6 +246,7 @@ struct tp_dispatch {
} accel;
struct {
+ bool enabled;
bool started;
unsigned int finger_count;
unsigned int finger_count_pending;
diff --git a/src/evdev.c b/src/evdev.c
index 84768324..e58b007f 100644
--- a/src/evdev.c
+++ b/src/evdev.c
@@ -44,7 +44,7 @@
#include "libinput-private.h"
#define DEFAULT_WHEEL_CLICK_ANGLE 15
-#define DEFAULT_MIDDLE_BUTTON_SCROLL_TIMEOUT 200
+#define DEFAULT_MIDDLE_BUTTON_SCROLL_TIMEOUT ms2us(200)
enum evdev_key_type {
EVDEV_KEY_TYPE_NONE,
@@ -129,7 +129,7 @@ update_key_down_count(struct evdev_device *device, int code, int pressed)
void
evdev_keyboard_notify_key(struct evdev_device *device,
- uint32_t time,
+ uint64_t time,
int key,
enum libinput_key_state state)
{
@@ -144,7 +144,7 @@ evdev_keyboard_notify_key(struct evdev_device *device,
void
evdev_pointer_notify_physical_button(struct evdev_device *device,
- uint32_t time,
+ uint64_t time,
int button,
enum libinput_button_state state)
{
@@ -159,7 +159,7 @@ evdev_pointer_notify_physical_button(struct evdev_device *device,
void
evdev_pointer_notify_button(struct evdev_device *device,
- uint32_t time,
+ uint64_t time,
int button,
enum libinput_button_state state)
{
@@ -457,7 +457,7 @@ evdev_button_scroll_button(struct evdev_device *device,
{
if (is_press) {
libinput_timer_set(&device->scroll.timer,
- time + DEFAULT_MIDDLE_BUTTON_SCROLL_TIMEOUT);
+ time + DEFAULT_MIDDLE_BUTTON_SCROLL_TIMEOUT);
device->scroll.button_down_time = time;
} else {
libinput_timer_cancel(&device->scroll.timer);
@@ -1271,7 +1271,7 @@ static inline void
evdev_process_event(struct evdev_device *device, struct input_event *e)
{
struct evdev_dispatch *dispatch = device->dispatch;
- uint64_t time = e->time.tv_sec * 1000ULL + e->time.tv_usec / 1000;
+ uint64_t time = s2us(e->time.tv_sec) + e->time.tv_usec;
#if 0
if (libevdev_event_is_code(e, EV_SYN, SYN_REPORT))
@@ -1543,6 +1543,8 @@ evdev_read_model_flags(struct evdev_device *device)
{ "LIBINPUT_MODEL_WACOM_TOUCHPAD", EVDEV_MODEL_WACOM_TOUCHPAD },
{ "LIBINPUT_MODEL_ALPS_TOUCHPAD", EVDEV_MODEL_ALPS_TOUCHPAD },
{ "LIBINPUT_MODEL_SYNAPTICS_SERIAL_TOUCHPAD", EVDEV_MODEL_SYNAPTICS_SERIAL_TOUCHPAD },
+ { "LIBINPUT_MODEL_JUMPING_SEMI_MT", EVDEV_MODEL_JUMPING_SEMI_MT },
+ { "LIBINPUT_MODEL_ELANTECH_TOUCHPAD", EVDEV_MODEL_ELANTECH_TOUCHPAD },
{ NULL, EVDEV_MODEL_DEFAULT },
};
const struct model_map *m = model_map;
@@ -1966,7 +1968,6 @@ evdev_configure_device(struct evdev_device *device)
if (udev_tags & EVDEV_UDEV_TAG_TOUCHPAD) {
device->dispatch = evdev_mt_touchpad_create(device);
- device->seat_caps |= EVDEV_DEVICE_GESTURE;
log_info(libinput,
"input device '%s', %s is a touchpad\n",
device->devname, devnode);
@@ -2173,7 +2174,7 @@ evdev_device_create(struct libinput_seat *seat,
device->dpi = DEFAULT_MOUSE_DPI;
/* at most 5 SYN_DROPPED log-messages per 30s */
- ratelimit_init(&device->syn_drop_limit, 30ULL * 1000, 5);
+ ratelimit_init(&device->syn_drop_limit, s2us(30), 5);
matrix_init_identity(&device->abs.calibration);
matrix_init_identity(&device->abs.usermatrix);
diff --git a/src/evdev.h b/src/evdev.h
index 16f8be7a..b7c56c62 100644
--- a/src/evdev.h
+++ b/src/evdev.h
@@ -106,6 +106,8 @@ enum evdev_device_model {
EVDEV_MODEL_WACOM_TOUCHPAD = (1 << 7),
EVDEV_MODEL_ALPS_TOUCHPAD = (1 << 8),
EVDEV_MODEL_SYNAPTICS_SERIAL_TOUCHPAD = (1 << 9),
+ EVDEV_MODEL_JUMPING_SEMI_MT = (1 << 10),
+ EVDEV_MODEL_ELANTECH_TOUCHPAD = (1 << 11),
};
struct mt_slot {
@@ -368,18 +370,18 @@ evdev_notify_resumed_device(struct evdev_device *device);
void
evdev_keyboard_notify_key(struct evdev_device *device,
- uint32_t time,
+ uint64_t time,
int key,
enum libinput_key_state state);
void
evdev_pointer_notify_button(struct evdev_device *device,
- uint32_t time,
+ uint64_t time,
int button,
enum libinput_button_state state);
void
evdev_pointer_notify_physical_button(struct evdev_device *device,
- uint32_t time,
+ uint64_t time,
int button,
enum libinput_button_state state);
diff --git a/src/filter.c b/src/filter.c
index 35449f56..2506ee27 100644
--- a/src/filter.c
+++ b/src/filter.c
@@ -85,13 +85,13 @@ filter_get_speed(struct motion_filter *filter)
* Pointer acceleration filter constants
*/
-#define MAX_VELOCITY_DIFF 1.0 /* units/ms */
-#define MOTION_TIMEOUT 1000 /* (ms) */
+#define MAX_VELOCITY_DIFF 1 /* units/ms */
+#define MOTION_TIMEOUT ms2us(1000)
#define NUM_POINTER_TRACKERS 16
struct pointer_tracker {
struct normalized_coords delta; /* delta to most recent event */
- uint64_t time; /* ms */
+ uint64_t time; /* us */
int dir;
};
@@ -150,8 +150,7 @@ static double
calculate_tracker_velocity(struct pointer_tracker *tracker, uint64_t time)
{
double tdelta = time - tracker->time + 1;
-
- return normalized_length(tracker->delta) / tdelta; /* units/ms */
+ return normalized_length(tracker->delta) / tdelta * 1000.0; /* units/ms */
}
static inline double
@@ -257,7 +256,7 @@ calculate_acceleration(struct pointer_accelerator *accel,
static struct normalized_coords
accelerator_filter(struct motion_filter *filter,
const struct normalized_coords *unaccelerated,
- void *data, uint64_t time)
+ void *data, uint64_t time /* in us */)
{
struct pointer_accelerator *accel =
(struct pointer_accelerator *) filter;
@@ -334,9 +333,9 @@ accelerator_set_speed(struct motion_filter *filter,
assert(speed >= -1.0 && speed <= 1.0);
/* delay when accel kicks in */
- accel_filter->threshold = DEFAULT_THRESHOLD - speed / 4.0;
- if (accel_filter->threshold < 0.2)
- accel_filter->threshold = 0.2;
+ accel_filter->threshold = DEFAULT_THRESHOLD - speed / 4000.0;
+ if (accel_filter->threshold < 0.0002)
+ accel_filter->threshold = 0.0002;
/* adjust max accel factor */
accel_filter->accel = DEFAULT_ACCELERATION + speed * 1.5;
@@ -398,8 +397,8 @@ create_pointer_accelerator_filter(accel_profile_func_t profile,
double
pointer_accel_profile_linear_low_dpi(struct motion_filter *filter,
void *data,
- double speed_in, /* in device units */
- uint64_t time)
+ double speed_in, /* in device units (units/ms) */
+ uint64_t time /* in us */)
{
struct pointer_accelerator *accel_filter =
(struct pointer_accelerator *)filter;
@@ -413,7 +412,7 @@ pointer_accel_profile_linear_low_dpi(struct motion_filter *filter,
max_accel /= dpi_factor;
- s1 = min(1, 0.3 + speed_in * 10);
+ s1 = min(1, 0.3 + speed_in * 10.0);
s2 = 1 + (speed_in - threshold * dpi_factor) * incline;
factor = min(max_accel, s2 > 1 ? s2 : s1);
@@ -425,7 +424,7 @@ double
pointer_accel_profile_linear(struct motion_filter *filter,
void *data,
double speed_in, /* 1000-dpi normalized */
- uint64_t time)
+ uint64_t time /* in us */)
{
struct pointer_accelerator *accel_filter =
(struct pointer_accelerator *)filter;
@@ -446,9 +445,9 @@ pointer_accel_profile_linear(struct motion_filter *filter,
double
touchpad_accel_profile_linear(struct motion_filter *filter,
- void *data,
- double speed_in,
- uint64_t time)
+ void *data,
+ double speed_in,
+ uint64_t time /* in us */)
{
/* Once normalized, touchpads see the same
acceleration as mice. that is technically correct but
@@ -469,7 +468,7 @@ double
touchpad_lenovo_x230_accel_profile(struct motion_filter *filter,
void *data,
double speed_in,
- uint64_t time)
+ uint64_t time /* in us */)
{
/* Keep the magic factor from touchpad_accel_profile_linear. */
const double TP_MAGIC_SLOWDOWN = 0.4;
diff --git a/src/libinput-private.h b/src/libinput-private.h
index c238da99..69ed26e3 100644
--- a/src/libinput-private.h
+++ b/src/libinput-private.h
@@ -307,6 +307,9 @@ open_restricted(struct libinput *libinput,
void
close_restricted(struct libinput *libinput, int fd);
+bool
+ignore_litest_test_suite_device(struct udev_device *device);
+
void
libinput_seat_init(struct libinput_seat *seat,
struct libinput *libinput,
@@ -462,7 +465,7 @@ libinput_now(struct libinput *libinput)
return 0;
}
- return ts.tv_sec * 1000ULL + ts.tv_nsec / 1000000;
+ return s2us(ts.tv_sec) + ns2us(ts.tv_nsec);
}
static inline struct device_float_coords
diff --git a/src/libinput-util.c b/src/libinput-util.c
index a383fa17..d35d7022 100644
--- a/src/libinput-util.c
+++ b/src/libinput-util.c
@@ -72,9 +72,9 @@ list_empty(const struct list *list)
}
void
-ratelimit_init(struct ratelimit *r, uint64_t ival_ms, unsigned int burst)
+ratelimit_init(struct ratelimit *r, uint64_t ival_us, unsigned int burst)
{
- r->interval = ival_ms;
+ r->interval = ival_us;
r->begin = 0;
r->burst = burst;
r->num = 0;
@@ -97,17 +97,17 @@ enum ratelimit_state
ratelimit_test(struct ratelimit *r)
{
struct timespec ts;
- uint64_t mtime;
+ uint64_t utime;
if (r->interval <= 0 || r->burst <= 0)
return RATELIMIT_PASS;
clock_gettime(CLOCK_MONOTONIC, &ts);
- mtime = ts.tv_sec * 1000 + ts.tv_nsec / 1000 / 1000;
+ utime = s2us(ts.tv_sec) + ns2us(ts.tv_nsec);
- if (r->begin <= 0 || r->begin + r->interval < mtime) {
+ if (r->begin <= 0 || r->begin + r->interval < utime) {
/* reset counter */
- r->begin = mtime;
+ r->begin = utime;
r->num = 1;
return RATELIMIT_PASS;
} else if (r->num < r->burst) {
diff --git a/src/libinput-util.h b/src/libinput-util.h
index 11d23780..ccb55677 100644
--- a/src/libinput-util.h
+++ b/src/libinput-util.h
@@ -328,4 +328,34 @@ int parse_mouse_wheel_click_angle_property(const char *prop);
double parse_trackpoint_accel_property(const char *prop);
bool parse_dimension_property(const char *prop, size_t *width, size_t *height);
+static inline uint64_t
+us(uint64_t us)
+{
+ return us;
+}
+
+static inline uint64_t
+ns2us(uint64_t ns)
+{
+ return us(ns / 1000);
+}
+
+static inline uint64_t
+ms2us(uint64_t ms)
+{
+ return us(ms * 1000);
+}
+
+static inline uint64_t
+s2us(uint64_t s)
+{
+ return ms2us(s * 1000);
+}
+
+static inline uint32_t
+us2ms(uint64_t us)
+{
+ return (uint32_t)(us / 1000);
+}
+
#endif /* LIBINPUT_UTIL_H */
diff --git a/src/libinput.c b/src/libinput.c
index 21b3cdc6..3557b8fd 100644
--- a/src/libinput.c
+++ b/src/libinput.c
@@ -86,7 +86,7 @@ struct libinput_event_device_notify {
struct libinput_event_keyboard {
struct libinput_event base;
- uint32_t time;
+ uint64_t time;
uint32_t key;
uint32_t seat_key_count;
enum libinput_key_state state;
@@ -94,7 +94,7 @@ struct libinput_event_keyboard {
struct libinput_event_pointer {
struct libinput_event base;
- uint32_t time;
+ uint64_t time;
struct normalized_coords delta;
struct device_float_coords delta_raw;
struct device_coords absolute;
@@ -108,7 +108,7 @@ struct libinput_event_pointer {
struct libinput_event_touch {
struct libinput_event base;
- uint32_t time;
+ uint64_t time;
int32_t slot;
int32_t seat_slot;
struct device_coords point;
@@ -116,7 +116,7 @@ struct libinput_event_touch {
struct libinput_event_gesture {
struct libinput_event base;
- uint32_t time;
+ uint64_t time;
int finger_count;
int cancelled;
struct normalized_coords delta;
@@ -304,6 +304,17 @@ libinput_event_get_device_notify_event(struct libinput_event *event)
LIBINPUT_EXPORT uint32_t
libinput_event_keyboard_get_time(struct libinput_event_keyboard *event)
+{
+ require_event_type(libinput_event_get_context(&event->base),
+ event->base.type,
+ 0,
+ LIBINPUT_EVENT_KEYBOARD_KEY);
+
+ return us2ms(event->time);
+}
+
+LIBINPUT_EXPORT uint64_t
+libinput_event_keyboard_get_time_usec(struct libinput_event_keyboard *event)
{
require_event_type(libinput_event_get_context(&event->base),
event->base.type,
@@ -349,6 +360,20 @@ libinput_event_keyboard_get_seat_key_count(
LIBINPUT_EXPORT uint32_t
libinput_event_pointer_get_time(struct libinput_event_pointer *event)
+{
+ require_event_type(libinput_event_get_context(&event->base),
+ event->base.type,
+ 0,
+ LIBINPUT_EVENT_POINTER_MOTION,
+ LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE,
+ LIBINPUT_EVENT_POINTER_BUTTON,
+ LIBINPUT_EVENT_POINTER_AXIS);
+
+ return us2ms(event->time);
+}
+
+LIBINPUT_EXPORT uint64_t
+libinput_event_pointer_get_time_usec(struct libinput_event_pointer *event)
{
require_event_type(libinput_event_get_context(&event->base),
event->base.type,
@@ -587,6 +612,21 @@ libinput_event_pointer_get_axis_source(struct libinput_event_pointer *event)
LIBINPUT_EXPORT uint32_t
libinput_event_touch_get_time(struct libinput_event_touch *event)
+{
+ require_event_type(libinput_event_get_context(&event->base),
+ event->base.type,
+ 0,
+ LIBINPUT_EVENT_TOUCH_DOWN,
+ LIBINPUT_EVENT_TOUCH_UP,
+ LIBINPUT_EVENT_TOUCH_MOTION,
+ LIBINPUT_EVENT_TOUCH_CANCEL,
+ LIBINPUT_EVENT_TOUCH_FRAME);
+
+ return us2ms(event->time);
+}
+
+LIBINPUT_EXPORT uint64_t
+libinput_event_touch_get_time_usec(struct libinput_event_touch *event)
{
require_event_type(libinput_event_get_context(&event->base),
event->base.type,
@@ -692,6 +732,22 @@ libinput_event_touch_get_y(struct libinput_event_touch *event)
LIBINPUT_EXPORT uint32_t
libinput_event_gesture_get_time(struct libinput_event_gesture *event)
+{
+ require_event_type(libinput_event_get_context(&event->base),
+ event->base.type,
+ 0,
+ LIBINPUT_EVENT_GESTURE_PINCH_BEGIN,
+ LIBINPUT_EVENT_GESTURE_PINCH_UPDATE,
+ LIBINPUT_EVENT_GESTURE_PINCH_END,
+ LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN,
+ LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE,
+ LIBINPUT_EVENT_GESTURE_SWIPE_END);
+
+ return us2ms(event->time);
+}
+
+LIBINPUT_EXPORT uint64_t
+libinput_event_gesture_get_time_usec(struct libinput_event_gesture *event)
{
require_event_type(libinput_event_get_context(&event->base),
event->base.type,
@@ -1226,6 +1282,16 @@ close_restricted(struct libinput *libinput, int fd)
return libinput->interface->close_restricted(fd, libinput->user_data);
}
+bool
+ignore_litest_test_suite_device(struct udev_device *device)
+{
+ if (!getenv("LIBINPUT_RUNNING_TEST_SUITE") &&
+ udev_device_get_property_value(device, "LIBINPUT_TEST_DEVICE"))
+ return true;
+
+ return false;
+}
+
void
libinput_seat_init(struct libinput_seat *seat,
struct libinput *libinput,
diff --git a/src/libinput.h b/src/libinput.h
index 9a3052c8..212ee351 100644
--- a/src/libinput.h
+++ b/src/libinput.h
@@ -555,6 +555,14 @@ libinput_event_device_notify_get_base_event(struct libinput_event_device_notify
uint32_t
libinput_event_keyboard_get_time(struct libinput_event_keyboard *event);
+/**
+ * @ingroup event_keyboard
+ *
+ * @return The event time for this event in microseconds
+ */
+uint64_t
+libinput_event_keyboard_get_time_usec(struct libinput_event_keyboard *event);
+
/**
* @ingroup event_keyboard
*
@@ -610,6 +618,14 @@ libinput_event_keyboard_get_seat_key_count(
uint32_t
libinput_event_pointer_get_time(struct libinput_event_pointer *event);
+/**
+ * @ingroup event_pointer
+ *
+ * @return The event time for this event in microseconds
+ */
+uint64_t
+libinput_event_pointer_get_time_usec(struct libinput_event_pointer *event);
+
/**
* @ingroup event_pointer
*
@@ -952,6 +968,14 @@ libinput_event_pointer_get_base_event(struct libinput_event_pointer *event);
uint32_t
libinput_event_touch_get_time(struct libinput_event_touch *event);
+/**
+ * @ingroup event_touch
+ *
+ * @return The event time for this event in microseconds
+ */
+uint64_t
+libinput_event_touch_get_time_usec(struct libinput_event_touch *event);
+
/**
* @ingroup event_touch
*
@@ -1104,6 +1128,14 @@ libinput_event_touch_get_base_event(struct libinput_event_touch *event);
uint32_t
libinput_event_gesture_get_time(struct libinput_event_gesture *event);
+/**
+ * @ingroup event_gesture
+ *
+ * @return The event time for this event in microseconds
+ */
+uint64_t
+libinput_event_gesture_get_time_usec(struct libinput_event_gesture *event);
+
/**
* @ingroup event_gesture
*
diff --git a/src/libinput.sym b/src/libinput.sym
index fb1c59b7..15295474 100644
--- a/src/libinput.sym
+++ b/src/libinput.sym
@@ -168,6 +168,10 @@ LIBINPUT_0.21.0 {
libinput_device_config_dwt_set_enabled;
libinput_device_config_dwt_get_enabled;
libinput_device_config_dwt_get_default_enabled;
+ libinput_event_gesture_get_time_usec;
+ libinput_event_keyboard_get_time_usec;
+ libinput_event_pointer_get_time_usec;
+ libinput_event_touch_get_time_usec;
} LIBINPUT_0.20.0;
/* tablet APIs, they are not part of any stable API promise yet.
diff --git a/src/path.c b/src/path.c
index 04c703c1..b14d8b67 100644
--- a/src/path.c
+++ b/src/path.c
@@ -343,6 +343,11 @@ libinput_path_add_device(struct libinput *libinput,
return NULL;
}
+ if (ignore_litest_test_suite_device(udev_device)) {
+ udev_device_unref(udev_device);
+ return NULL;
+ }
+
device = path_create_device(libinput, udev_device, NULL);
udev_device_unref(udev_device);
return device;
diff --git a/src/timer.c b/src/timer.c
index 6a343dbf..5ad23f31 100644
--- a/src/timer.c
+++ b/src/timer.c
@@ -57,8 +57,8 @@ libinput_timer_arm_timer_fd(struct libinput *libinput)
}
if (earliest_expire != UINT64_MAX) {
- its.it_value.tv_sec = earliest_expire / 1000;
- its.it_value.tv_nsec = (earliest_expire % 1000) * 1000 * 1000;
+ its.it_value.tv_sec = earliest_expire / ms2us(1000);
+ its.it_value.tv_nsec = (earliest_expire % ms2us(1000)) * 1000;
}
r = timerfd_settime(libinput->timer.fd, TFD_TIMER_ABSTIME, &its, NULL);
@@ -71,7 +71,10 @@ libinput_timer_set(struct libinput_timer *timer, uint64_t expire)
{
#ifndef NDEBUG
uint64_t now = libinput_now(timer->libinput);
- if (abs(expire - now) > 5000)
+ if (expire < now)
+ log_bug_libinput(timer->libinput,
+ "timer offset negative\n");
+ else if ((expire - now) > ms2us(5000))
log_bug_libinput(timer->libinput,
"timer offset more than 5s, now %"
PRIu64 " expire %" PRIu64 "\n",
diff --git a/src/timer.h b/src/timer.h
index b005fbb8..f8315cfe 100644
--- a/src/timer.h
+++ b/src/timer.h
@@ -33,7 +33,7 @@ struct libinput;
struct libinput_timer {
struct libinput *libinput;
struct list link;
- uint64_t expire; /* in absolute ms CLOCK_MONOTONIC */
+ uint64_t expire; /* in absolute us CLOCK_MONOTONIC */
void (*timer_func)(uint64_t now, void *timer_func_data);
void *timer_func_data;
};
@@ -43,7 +43,7 @@ libinput_timer_init(struct libinput_timer *timer, struct libinput *libinput,
void (*timer_func)(uint64_t now, void *timer_func_data),
void *timer_func_data);
-/* Set timer expire time, in absolute ms CLOCK_MONOTONIC */
+/* Set timer expire time, in absolute us CLOCK_MONOTONIC */
void
libinput_timer_set(struct libinput_timer *timer, uint64_t expire);
diff --git a/src/udev-seat.c b/src/udev-seat.c
index 6b019da2..6bf85de9 100644
--- a/src/udev-seat.c
+++ b/src/udev-seat.c
@@ -62,6 +62,9 @@ device_added(struct udev_device *udev_device,
if (!streq(device_seat, input->seat_id))
return 0;
+ if (ignore_litest_test_suite_device(udev_device))
+ return 0;
+
devnode = udev_device_get_devnode(udev_device);
/* Search for matching logical seat */
diff --git a/test/Makefile.am b/test/Makefile.am
index 75c61480..70a5302f 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -50,8 +50,9 @@ liblitest_la_SOURCES = \
litest.c
liblitest_la_LIBADD = $(top_builddir)/src/libinput-util.la
liblitest_la_CFLAGS = $(AM_CFLAGS) \
- -DLIBINPUT_UDEV_RULES_FILE="\"$(abs_top_builddir)/udev/90-libinput-model-quirks-litest.rules\"" \
- -DLIBINPUT_UDEV_HWDB_FILE="\"$(abs_top_srcdir)/udev/90-libinput-model-quirks.hwdb\""
+ -DLIBINPUT_MODEL_QUIRKS_UDEV_RULES_FILE="\"$(abs_top_builddir)/udev/90-libinput-model-quirks-litest.rules\"" \
+ -DLIBINPUT_MODEL_QUIRKS_UDEV_HWDB_FILE="\"$(abs_top_srcdir)/udev/90-libinput-model-quirks.hwdb\"" \
+ -DLIBINPUT_TEST_DEVICE_RULES_FILE="\"$(abs_top_srcdir)/udev/80-libinput-test-device.rules\""
if HAVE_LIBUNWIND
liblitest_la_LIBADD += $(LIBUNWIND_LIBS) -ldl
liblitest_la_CFLAGS += $(LIBUNWIND_CFLAGS)
diff --git a/test/gestures.c b/test/gestures.c
index b9d73257..9e447248 100644
--- a/test/gestures.c
+++ b/test/gestures.c
@@ -34,8 +34,12 @@ START_TEST(gestures_cap)
struct litest_device *dev = litest_current_device();
struct libinput_device *device = dev->libinput_device;
- ck_assert(libinput_device_has_capability(device,
- LIBINPUT_DEVICE_CAP_GESTURE));
+ if (litest_is_synaptics_semi_mt(dev))
+ ck_assert(!libinput_device_has_capability(device,
+ LIBINPUT_DEVICE_CAP_GESTURE));
+ else
+ ck_assert(libinput_device_has_capability(device,
+ LIBINPUT_DEVICE_CAP_GESTURE));
}
END_TEST
@@ -349,6 +353,41 @@ START_TEST(gestures_spread)
}
END_TEST
+START_TEST(gestures_time_usec)
+{
+ struct litest_device *dev = litest_current_device();
+ struct libinput *li = dev->libinput;
+ struct libinput_event *event;
+ struct libinput_event_gesture *gevent;
+
+ if (libevdev_get_num_slots(dev->evdev) < 3)
+ return;
+
+ litest_drain_events(li);
+
+ litest_touch_down(dev, 0, 40, 40);
+ litest_touch_down(dev, 1, 40, 50);
+ litest_touch_down(dev, 2, 40, 60);
+ libinput_dispatch(li);
+ litest_touch_move_three_touches(dev,
+ 40, 40,
+ 40, 50,
+ 40, 60,
+ 0, 30,
+ 4, 2);
+
+ litest_wait_for_event(li);
+
+ event = libinput_get_event(li);
+ gevent = litest_is_gesture_event(event,
+ LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN,
+ 3);
+ ck_assert_int_eq(libinput_event_gesture_get_time(gevent),
+ libinput_event_gesture_get_time_usec(gevent) / 1000);
+ libinput_event_destroy(event);
+}
+END_TEST
+
void
litest_setup_tests(void)
{
@@ -361,4 +400,6 @@ litest_setup_tests(void)
litest_add_ranged("gestures:swipe", gestures_swipe_3fg, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH, &cardinals);
litest_add_ranged("gestures:pinch", gestures_pinch, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH, &cardinals);
litest_add_ranged("gestures:pinch", gestures_spread, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH, &cardinals);
+
+ litest_add("gesture:time", gestures_time_usec, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH);
}
diff --git a/test/keyboard.c b/test/keyboard.c
index 204d57c4..e9f3bcb1 100644
--- a/test/keyboard.c
+++ b/test/keyboard.c
@@ -311,6 +311,35 @@ START_TEST(keyboard_keys_bad_device)
}
END_TEST
+START_TEST(keyboard_time_usec)
+{
+ struct litest_device *dev = litest_current_device();
+ struct libinput *li = dev->libinput;
+ struct libinput_event_keyboard *kev;
+ struct libinput_event *event;
+
+ if (!libevdev_has_event_code(dev->evdev, EV_KEY, KEY_A))
+ return;
+
+ litest_drain_events(dev->libinput);
+
+ litest_keyboard_key(dev, KEY_A, true);
+
+ litest_wait_for_event(li);
+
+ event = libinput_get_event(li);
+ kev = litest_is_keyboard_event(event,
+ KEY_A,
+ LIBINPUT_KEY_STATE_PRESSED);
+
+ ck_assert_int_eq(libinput_event_keyboard_get_time(kev),
+ libinput_event_keyboard_get_time_usec(kev) / 1000);
+
+ libinput_event_destroy(event);
+ litest_drain_events(dev->libinput);
+}
+END_TEST
+
void
litest_setup_tests(void)
{
@@ -319,4 +348,5 @@ litest_setup_tests(void)
litest_add_no_device("keyboard:key counting", keyboard_key_auto_release);
litest_add("keyboard:keys", keyboard_has_key, LITEST_KEYS, LITEST_ANY);
litest_add("keyboard:keys", keyboard_keys_bad_device, LITEST_ANY, LITEST_ANY);
+ litest_add("keyboard:time", keyboard_time_usec, LITEST_KEYS, LITEST_ANY);
}
diff --git a/test/litest-device-synaptics-hover.c b/test/litest-device-synaptics-hover.c
index 2cc9b725..3c36affa 100644
--- a/test/litest-device-synaptics-hover.c
+++ b/test/litest-device-synaptics-hover.c
@@ -102,6 +102,15 @@ static struct input_absinfo absinfo[] = {
{ .value = -1 }
};
+static const char udev_rule[] =
+"ACTION==\"remove\", GOTO=\"synaptics_semi_mt_end\"\n"
+"KERNEL!=\"event*\", GOTO=\"synaptics_semi_mt_end\"\n"
+"\n"
+"ATTRS{name}==\"SynPS/2 Synaptics TouchPad\",\n"
+" ENV{LIBINPUT_MODEL_JUMPING_SEMI_MT}=\"1\"\n"
+"\n"
+"LABEL=\"synaptics_semi_mt_end\"";
+
struct litest_test_device litest_synaptics_hover_device = {
.type = LITEST_SYNAPTICS_HOVER_SEMI_MT,
.features = LITEST_TOUCHPAD | LITEST_SEMI_MT | LITEST_BUTTON,
@@ -114,6 +123,7 @@ struct litest_test_device litest_synaptics_hover_device = {
.id = &input_id,
.events = events,
.absinfo = absinfo,
+ .udev_rule = udev_rule,
};
static void
diff --git a/test/litest.c b/test/litest.c
index 0e434c8c..6b361f3d 100644
--- a/test/litest.c
+++ b/test/litest.c
@@ -53,8 +53,12 @@
#define UDEV_RULES_D "/run/udev/rules.d"
#define UDEV_RULE_PREFIX "99-litest-"
#define UDEV_HWDB_D "/etc/udev/hwdb.d"
-#define UDEV_COMMON_RULE_FILE UDEV_RULES_D "/91-litest-model-quirks-REMOVEME.rules"
-#define UDEV_COMMON_HWDB_FILE UDEV_HWDB_D "/91-litest-model-quirks-REMOVEME.hwdb"
+#define UDEV_MODEL_QUIRKS_RULE_FILE UDEV_RULES_D \
+ "/91-litest-model-quirks-REMOVEME.rules"
+#define UDEV_MODEL_QUIRKS_HWDB_FILE UDEV_HWDB_D \
+ "/91-litest-model-quirks-REMOVEME.hwdb"
+#define UDEV_TEST_DEVICE_RULE_FILE UDEV_RULES_D \
+ "/91-litest-test-device-REMOVEME.rules"
static int in_debugger = -1;
static int verbose = 0;
@@ -783,6 +787,10 @@ litest_log_handler(struct libinput *libinput,
fprintf(stderr, "litest %s: ", priority);
vfprintf(stderr, format, args);
+
+ if (strstr(format, "client bug: ") ||
+ strstr(format, "libinput bug: "))
+ litest_abort_msg("libinput bug triggered, aborting.\n");
}
static int
@@ -957,19 +965,23 @@ litest_install_model_quirks(void)
"# running, remove this file and update your hwdb: \n"
"# sudo udevadm hwdb --update\n"
"#################################################################\n\n";
- litest_copy_file(UDEV_COMMON_RULE_FILE,
- LIBINPUT_UDEV_RULES_FILE,
+ litest_copy_file(UDEV_MODEL_QUIRKS_RULE_FILE,
+ LIBINPUT_MODEL_QUIRKS_UDEV_RULES_FILE,
warning);
- litest_copy_file(UDEV_COMMON_HWDB_FILE,
- LIBINPUT_UDEV_HWDB_FILE,
+ litest_copy_file(UDEV_MODEL_QUIRKS_HWDB_FILE,
+ LIBINPUT_MODEL_QUIRKS_UDEV_HWDB_FILE,
+ warning);
+ litest_copy_file(UDEV_TEST_DEVICE_RULE_FILE,
+ LIBINPUT_TEST_DEVICE_RULES_FILE,
warning);
}
static inline void
litest_remove_model_quirks(void)
{
- unlink(UDEV_COMMON_RULE_FILE);
- unlink(UDEV_COMMON_HWDB_FILE);
+ unlink(UDEV_MODEL_QUIRKS_RULE_FILE);
+ unlink(UDEV_MODEL_QUIRKS_HWDB_FILE);
+ unlink(UDEV_TEST_DEVICE_RULE_FILE);
}
static void
@@ -1059,6 +1071,7 @@ litest_create(enum litest_device_type which,
litest_abort_msg("Custom create cannot be overridden");
}
+ d->udev_rule_file = udev_file;
return d;
}
@@ -2336,9 +2349,9 @@ litest_assert_scroll(struct libinput *li,
}
} else {
/* Last scroll event, must be 0 */
- litest_assert_int_eq(
+ ck_assert_double_eq(
libinput_event_pointer_get_axis_value(ptrev, axis),
- 0);
+ 0.0);
}
libinput_event_destroy(event);
event = next_event;
@@ -2662,6 +2675,7 @@ main(int argc, char **argv)
list_init(&all_tests);
setenv("CK_DEFAULT_TIMEOUT", "10", 0);
+ setenv("LIBINPUT_RUNNING_TEST_SUITE", "1", 1);
mode = litest_parse_argv(argc, argv);
if (mode == LITEST_MODE_ERROR)
diff --git a/test/litest.h b/test/litest.h
index 3716753d..bf165f07 100644
--- a/test/litest.h
+++ b/test/litest.h
@@ -509,6 +509,99 @@ litest_disable_tap(struct libinput_device *device)
litest_assert_int_eq(status, expected);
}
+static inline bool
+litest_has_2fg_scroll(struct litest_device *dev)
+{
+ struct libinput_device *device = dev->libinput_device;
+
+ return !!(libinput_device_config_scroll_get_methods(device) &
+ LIBINPUT_CONFIG_SCROLL_2FG);
+}
+
+static inline void
+litest_enable_2fg_scroll(struct litest_device *dev)
+{
+ enum libinput_config_status status, expected;
+ struct libinput_device *device = dev->libinput_device;
+
+ status = libinput_device_config_scroll_set_method(device,
+ LIBINPUT_CONFIG_SCROLL_2FG);
+
+ expected = LIBINPUT_CONFIG_STATUS_SUCCESS;
+ litest_assert_int_eq(status, expected);
+}
+
+static inline void
+litest_enable_edge_scroll(struct litest_device *dev)
+{
+ enum libinput_config_status status, expected;
+ struct libinput_device *device = dev->libinput_device;
+
+ status = libinput_device_config_scroll_set_method(device,
+ LIBINPUT_CONFIG_SCROLL_EDGE);
+
+ expected = LIBINPUT_CONFIG_STATUS_SUCCESS;
+ litest_assert_int_eq(status, expected);
+}
+
+static inline void
+litest_enable_clickfinger(struct litest_device *dev)
+{
+ enum libinput_config_status status, expected;
+ struct libinput_device *device = dev->libinput_device;
+
+ status = libinput_device_config_click_set_method(device,
+ LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER);
+ expected = LIBINPUT_CONFIG_STATUS_SUCCESS;
+ litest_assert_int_eq(status, expected);
+}
+
+static inline void
+litest_enable_buttonareas(struct litest_device *dev)
+{
+ enum libinput_config_status status, expected;
+ struct libinput_device *device = dev->libinput_device;
+
+ status = libinput_device_config_click_set_method(device,
+ LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS);
+ expected = LIBINPUT_CONFIG_STATUS_SUCCESS;
+ litest_assert_int_eq(status, expected);
+}
+
+static inline int
+litest_is_synaptics_semi_mt(struct litest_device *dev)
+{
+ struct libevdev *evdev = dev->evdev;
+
+ return libevdev_has_property(evdev, INPUT_PROP_SEMI_MT) &&
+ libevdev_get_id_vendor(evdev) == 0x2 &&
+ libevdev_get_id_product(evdev) == 0x7;
+}
+
+static inline void
+litest_enable_drag_lock(struct libinput_device *device)
+{
+ enum libinput_config_status status, expected;
+
+ expected = LIBINPUT_CONFIG_STATUS_SUCCESS;
+ status = libinput_device_config_tap_set_drag_lock_enabled(device,
+ LIBINPUT_CONFIG_DRAG_LOCK_ENABLED);
+
+ litest_assert_int_eq(status, expected);
+}
+
+static inline void
+litest_disable_drag_lock(struct libinput_device *device)
+{
+ enum libinput_config_status status, expected;
+
+ expected = LIBINPUT_CONFIG_STATUS_SUCCESS;
+ status = libinput_device_config_tap_set_drag_lock_enabled(device,
+ LIBINPUT_CONFIG_DRAG_LOCK_DISABLED);
+
+ litest_assert_int_eq(status, expected);
+}
+
#define CK_DOUBLE_EQ_EPSILON 1E-3
#define ck_assert_double_eq(X,Y) \
do { \
diff --git a/test/misc.c b/test/misc.c
index 7ac95a76..a0c459dc 100644
--- a/test/misc.c
+++ b/test/misc.c
@@ -596,7 +596,7 @@ START_TEST(ratelimit_helpers)
unsigned int i, j;
/* 10 attempts every 100ms */
- ratelimit_init(&rl, 100, 10);
+ ratelimit_init(&rl, ms2us(100), 10);
for (j = 0; j < 3; ++j) {
/* a burst of 9 attempts must succeed */
@@ -772,6 +772,16 @@ START_TEST(dimension_prop_parser)
}
END_TEST
+START_TEST(time_conversion)
+{
+ ck_assert_int_eq(us(10), 10);
+ ck_assert_int_eq(ns2us(10000), 10);
+ ck_assert_int_eq(ms2us(10), 10000);
+ ck_assert_int_eq(s2us(1), 1000000);
+ ck_assert_int_eq(us2ms(10000), 10);
+}
+END_TEST
+
void
litest_setup_tests(void)
{
@@ -794,4 +804,5 @@ litest_setup_tests(void)
litest_add_no_device("misc:parser", wheel_click_parser);
litest_add_no_device("misc:parser", trackpoint_accel_parser);
litest_add_no_device("misc:parser", dimension_prop_parser);
+ litest_add_no_device("misc:time", time_conversion);
}
diff --git a/test/path.c b/test/path.c
index 22db7ae5..0b04b196 100644
--- a/test/path.c
+++ b/test/path.c
@@ -331,7 +331,9 @@ START_TEST(path_add_invalid_path)
li = litest_create_context();
+ litest_disable_log_handler(li);
device = libinput_path_add_device(li, "/tmp/");
+ litest_restore_log_handler(li);
ck_assert(device == NULL);
libinput_dispatch(li);
diff --git a/test/pointer.c b/test/pointer.c
index e971f759..50e502ad 100644
--- a/test/pointer.c
+++ b/test/pointer.c
@@ -897,15 +897,18 @@ START_TEST(pointer_accel_defaults)
double speed;
ck_assert(libinput_device_config_accel_is_available(device));
- ck_assert(libinput_device_config_accel_get_default_speed(device) == 0.0);
- ck_assert(libinput_device_config_accel_get_speed(device) == 0.0);
+ ck_assert_double_eq(libinput_device_config_accel_get_default_speed(device),
+ 0.0);
+ ck_assert_double_eq(libinput_device_config_accel_get_speed(device),
+ 0.0);
for (speed = -2.0; speed < -1.0; speed += 0.2) {
status = libinput_device_config_accel_set_speed(device,
speed);
ck_assert_int_eq(status,
LIBINPUT_CONFIG_STATUS_INVALID);
- ck_assert(libinput_device_config_accel_get_speed(device) == 0.0);
+ ck_assert_double_eq(libinput_device_config_accel_get_speed(device),
+ 0.0);
}
for (speed = -1.0; speed <= 1.0; speed += 0.2) {
@@ -913,7 +916,8 @@ START_TEST(pointer_accel_defaults)
speed);
ck_assert_int_eq(status,
LIBINPUT_CONFIG_STATUS_SUCCESS);
- ck_assert(libinput_device_config_accel_get_speed(device) == speed);
+ ck_assert_double_eq(libinput_device_config_accel_get_speed(device),
+ speed);
}
for (speed = 1.2; speed <= -2.0; speed += 0.2) {
@@ -921,7 +925,8 @@ START_TEST(pointer_accel_defaults)
speed);
ck_assert_int_eq(status,
LIBINPUT_CONFIG_STATUS_INVALID);
- ck_assert(libinput_device_config_accel_get_speed(device) == 1.0);
+ ck_assert_double_eq(libinput_device_config_accel_get_speed(device),
+ 1.0);
}
}
@@ -952,8 +957,10 @@ START_TEST(pointer_accel_defaults_absolute)
double speed;
ck_assert(!libinput_device_config_accel_is_available(device));
- ck_assert(libinput_device_config_accel_get_default_speed(device) == 0.0);
- ck_assert(libinput_device_config_accel_get_speed(device) == 0.0);
+ ck_assert_double_eq(libinput_device_config_accel_get_default_speed(device),
+ 0.0);
+ ck_assert_double_eq(libinput_device_config_accel_get_speed(device),
+ 0.0);
for (speed = -2.0; speed <= 2.0; speed += 0.2) {
status = libinput_device_config_accel_set_speed(device,
@@ -964,7 +971,8 @@ START_TEST(pointer_accel_defaults_absolute)
else
ck_assert_int_eq(status,
LIBINPUT_CONFIG_STATUS_INVALID);
- ck_assert(libinput_device_config_accel_get_speed(device) == 0.0);
+ ck_assert_double_eq(libinput_device_config_accel_get_speed(device),
+ 0.0);
}
}
END_TEST
@@ -975,8 +983,10 @@ START_TEST(pointer_accel_defaults_absolute_relative)
struct libinput_device *device = dev->libinput_device;
ck_assert(libinput_device_config_accel_is_available(device));
- ck_assert(libinput_device_config_accel_get_default_speed(device) == 0.0);
- ck_assert(libinput_device_config_accel_get_speed(device) == 0.0);
+ ck_assert_double_eq(libinput_device_config_accel_get_default_speed(device),
+ 0.0);
+ ck_assert_double_eq(libinput_device_config_accel_get_speed(device),
+ 0.0);
}
END_TEST
@@ -988,7 +998,6 @@ START_TEST(pointer_accel_direction_change)
struct libinput_event_pointer *pev;
int i;
double delta;
- double max_accel;
litest_drain_events(li);
@@ -1008,16 +1017,14 @@ START_TEST(pointer_accel_direction_change)
pev = libinput_event_get_pointer_event(event);
delta = libinput_event_pointer_get_dx(pev);
- ck_assert(delta <= 0.0);
- max_accel = delta;
+ ck_assert_double_le(delta, 0.0);
libinput_event_destroy(event);
event = libinput_get_event(li);
} while (libinput_next_event_type(li) != LIBINPUT_EVENT_NONE);
pev = libinput_event_get_pointer_event(event);
delta = libinput_event_pointer_get_dx(pev);
- ck_assert(delta > 0.0);
- ck_assert(delta < -max_accel);
+ ck_assert_double_gt(delta, 0.0);
libinput_event_destroy(event);
}
END_TEST
@@ -1412,6 +1419,32 @@ START_TEST(middlebutton_default_disabled)
}
END_TEST
+START_TEST(pointer_time_usec)
+{
+ struct litest_device *dev = litest_current_device();
+ struct libinput *li = dev->libinput;
+ struct libinput_event_pointer *ptrev;
+ struct libinput_event *event;
+
+ litest_drain_events(dev->libinput);
+
+ litest_event(dev, EV_REL, REL_X, 1);
+ litest_event(dev, EV_REL, REL_Y, 1);
+ litest_event(dev, EV_SYN, SYN_REPORT, 0);
+
+ litest_wait_for_event(li);
+
+ event = libinput_get_event(li);
+ ptrev = litest_is_motion_event(event);
+
+ ck_assert_int_eq(libinput_event_pointer_get_time(ptrev),
+ libinput_event_pointer_get_time_usec(ptrev) / 1000);
+
+ libinput_event_destroy(event);
+ litest_drain_events(dev->libinput);
+}
+END_TEST
+
void
litest_setup_tests(void)
{
@@ -1459,4 +1492,6 @@ litest_setup_tests(void)
litest_add_for_device("pointer:middlebutton", middlebutton_default_alps, LITEST_ALPS_SEMI_MT);
litest_add_ranged("pointer:state", pointer_absolute_initial_state, LITEST_ABSOLUTE, LITEST_ANY, &axis_range);
+
+ litest_add("pointer:time", pointer_time_usec, LITEST_RELATIVE, LITEST_ANY);
}
diff --git a/test/touch.c b/test/touch.c
index b519613d..eae8007c 100644
--- a/test/touch.c
+++ b/test/touch.c
@@ -652,6 +652,27 @@ START_TEST(touch_initial_state)
}
END_TEST
+START_TEST(touch_time_usec)
+{
+ struct litest_device *dev = litest_current_device();
+ struct libinput *li = dev->libinput;
+ struct libinput_event *event;
+ struct libinput_event_touch *tev;
+
+ litest_drain_events(dev->libinput);
+
+ litest_touch_down(dev, 0, 10, 10);
+
+ litest_wait_for_event(li);
+
+ event = libinput_get_event(li);
+ tev = litest_is_touch_event(event, LIBINPUT_EVENT_TOUCH_DOWN);
+ ck_assert_int_eq(libinput_event_touch_get_time(tev),
+ libinput_event_touch_get_time_usec(tev) / 1000);
+ libinput_event_destroy(event);
+}
+END_TEST
+
void
litest_setup_tests(void)
{
@@ -678,4 +699,6 @@ litest_setup_tests(void)
litest_add("touch:protocol a", touch_protocol_a_2fg_touch, LITEST_PROTOCOL_A, LITEST_ANY);
litest_add_ranged("touch:state", touch_initial_state, LITEST_TOUCH, LITEST_PROTOCOL_A, &axes);
+
+ litest_add("touch:time", touch_time_usec, LITEST_TOUCH, LITEST_TOUCHPAD);
}
diff --git a/test/touchpad-buttons.c b/test/touchpad-buttons.c
index 896b34b4..064c29ef 100644
--- a/test/touchpad-buttons.c
+++ b/test/touchpad-buttons.c
@@ -32,30 +32,6 @@
#include "libinput-util.h"
#include "litest.h"
-static void
-enable_clickfinger(struct litest_device *dev)
-{
- enum libinput_config_status status, expected;
- struct libinput_device *device = dev->libinput_device;
-
- status = libinput_device_config_click_set_method(device,
- LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER);
- expected = LIBINPUT_CONFIG_STATUS_SUCCESS;
- litest_assert_int_eq(status, expected);
-}
-
-static void
-enable_buttonareas(struct litest_device *dev)
-{
- enum libinput_config_status status, expected;
- struct libinput_device *device = dev->libinput_device;
-
- status = libinput_device_config_click_set_method(device,
- LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS);
- expected = LIBINPUT_CONFIG_STATUS_SUCCESS;
- litest_assert_int_eq(status, expected);
-}
-
START_TEST(touchpad_click_defaults_clickfinger)
{
struct litest_device *dev = litest_current_device();
@@ -141,7 +117,7 @@ START_TEST(touchpad_1fg_clickfinger)
struct litest_device *dev = litest_current_device();
struct libinput *li = dev->libinput;
- enable_clickfinger(dev);
+ litest_enable_clickfinger(dev);
litest_drain_events(li);
@@ -166,7 +142,7 @@ START_TEST(touchpad_1fg_clickfinger_no_touch)
struct litest_device *dev = litest_current_device();
struct libinput *li = dev->libinput;
- enable_clickfinger(dev);
+ litest_enable_clickfinger(dev);
litest_drain_events(li);
@@ -189,7 +165,7 @@ START_TEST(touchpad_2fg_clickfinger)
struct litest_device *dev = litest_current_device();
struct libinput *li = dev->libinput;
- enable_clickfinger(dev);
+ litest_enable_clickfinger(dev);
litest_drain_events(li);
@@ -219,7 +195,7 @@ START_TEST(touchpad_3fg_clickfinger)
if (libevdev_get_num_slots(dev->evdev) < 3)
return;
- enable_clickfinger(dev);
+ litest_enable_clickfinger(dev);
litest_drain_events(li);
@@ -254,7 +230,7 @@ START_TEST(touchpad_3fg_clickfinger_btntool)
!libevdev_has_event_code(dev->evdev, EV_KEY, BTN_TOOL_TRIPLETAP))
return;
- enable_clickfinger(dev);
+ litest_enable_clickfinger(dev);
litest_drain_events(li);
@@ -293,7 +269,7 @@ START_TEST(touchpad_4fg_clickfinger)
if (libevdev_get_num_slots(dev->evdev) < 4)
return;
- enable_clickfinger(dev);
+ litest_enable_clickfinger(dev);
litest_drain_events(li);
@@ -338,7 +314,7 @@ START_TEST(touchpad_4fg_clickfinger_btntool_2slots)
!libevdev_has_event_code(dev->evdev, EV_KEY, BTN_TOOL_QUADTAP))
return;
- enable_clickfinger(dev);
+ litest_enable_clickfinger(dev);
litest_drain_events(li);
@@ -384,7 +360,7 @@ START_TEST(touchpad_4fg_clickfinger_btntool_3slots)
!libevdev_has_event_code(dev->evdev, EV_KEY, BTN_TOOL_TRIPLETAP))
return;
- enable_clickfinger(dev);
+ litest_enable_clickfinger(dev);
litest_drain_events(li);
@@ -435,7 +411,7 @@ START_TEST(touchpad_2fg_clickfinger_distance)
h < 50.0)
small_touchpad = true;
- enable_clickfinger(dev);
+ litest_enable_clickfinger(dev);
litest_drain_events(li);
@@ -482,6 +458,78 @@ START_TEST(touchpad_2fg_clickfinger_distance)
}
END_TEST
+START_TEST(touchpad_3fg_clickfinger_distance)
+{
+ struct litest_device *dev = litest_current_device();
+ struct libinput *li = dev->libinput;
+
+ if (libevdev_get_num_slots(dev->evdev) < 3)
+ return;
+
+ litest_enable_clickfinger(dev);
+
+ litest_drain_events(li);
+
+ litest_touch_down(dev, 0, 90, 90);
+ litest_touch_down(dev, 1, 10, 15);
+ litest_touch_down(dev, 2, 10, 15);
+ litest_event(dev, EV_SYN, SYN_REPORT, 0);
+ 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);
+ litest_event(dev, EV_SYN, SYN_REPORT, 0);
+ litest_touch_up(dev, 0);
+ litest_touch_up(dev, 1);
+ litest_touch_up(dev, 2);
+
+ litest_assert_button_event(li,
+ BTN_MIDDLE,
+ LIBINPUT_BUTTON_STATE_PRESSED);
+ litest_assert_button_event(li,
+ BTN_MIDDLE,
+ LIBINPUT_BUTTON_STATE_RELEASED);
+}
+END_TEST
+
+START_TEST(touchpad_3fg_clickfinger_distance_btntool)
+{
+ struct litest_device *dev = litest_current_device();
+ struct libinput *li = dev->libinput;
+
+ if (libevdev_get_num_slots(dev->evdev) > 2)
+ return;
+
+ litest_enable_clickfinger(dev);
+
+ litest_drain_events(li);
+
+ litest_touch_down(dev, 0, 90, 90);
+ litest_touch_down(dev, 1, 10, 15);
+ libinput_dispatch(li);
+ litest_event(dev, EV_KEY, BTN_TOOL_DOUBLETAP, 0);
+ litest_event(dev, EV_KEY, BTN_TOOL_TRIPLETAP, 1);
+ litest_event(dev, EV_SYN, SYN_REPORT, 0);
+ libinput_dispatch(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);
+ litest_event(dev, EV_KEY, BTN_TOOL_DOUBLETAP, 1);
+ litest_event(dev, EV_KEY, BTN_TOOL_TRIPLETAP, 0);
+ litest_event(dev, EV_SYN, SYN_REPORT, 0);
+ litest_touch_up(dev, 0);
+ litest_touch_up(dev, 1);
+
+ litest_assert_button_event(li,
+ BTN_MIDDLE,
+ LIBINPUT_BUTTON_STATE_PRESSED);
+ litest_assert_button_event(li,
+ BTN_MIDDLE,
+ LIBINPUT_BUTTON_STATE_RELEASED);
+}
+END_TEST
+
START_TEST(touchpad_2fg_clickfinger_bottom)
{
struct litest_device *dev = litest_current_device();
@@ -556,7 +604,7 @@ START_TEST(touchpad_clickfinger_to_area_method)
litest_drain_events(li);
- enable_buttonareas(dev);
+ litest_enable_buttonareas(dev);
litest_touch_down(dev, 0, 95, 95);
litest_event(dev, EV_KEY, BTN_LEFT, 1);
@@ -571,7 +619,7 @@ START_TEST(touchpad_clickfinger_to_area_method)
litest_assert_button_event(li, BTN_RIGHT,
LIBINPUT_BUTTON_STATE_RELEASED);
- enable_clickfinger(dev);
+ litest_enable_clickfinger(dev);
litest_drain_events(li);
@@ -599,7 +647,7 @@ START_TEST(touchpad_clickfinger_to_area_method_while_down)
litest_drain_events(li);
- enable_buttonareas(dev);
+ litest_enable_buttonareas(dev);
litest_touch_down(dev, 0, 95, 95);
litest_event(dev, EV_KEY, BTN_LEFT, 1);
@@ -608,7 +656,7 @@ START_TEST(touchpad_clickfinger_to_area_method_while_down)
litest_assert_button_event(li, BTN_RIGHT,
LIBINPUT_BUTTON_STATE_PRESSED);
- enable_clickfinger(dev);
+ litest_enable_clickfinger(dev);
litest_event(dev, EV_KEY, BTN_LEFT, 0);
litest_event(dev, EV_SYN, SYN_REPORT, 0);
@@ -642,7 +690,7 @@ START_TEST(touchpad_area_to_clickfinger_method)
struct litest_device *dev = litest_current_device();
struct libinput *li = dev->libinput;
- enable_clickfinger(dev);
+ litest_enable_clickfinger(dev);
litest_drain_events(li);
@@ -660,7 +708,7 @@ START_TEST(touchpad_area_to_clickfinger_method)
litest_assert_button_event(li, BTN_LEFT,
LIBINPUT_BUTTON_STATE_RELEASED);
- enable_buttonareas(dev);
+ litest_enable_buttonareas(dev);
litest_touch_down(dev, 0, 95, 95);
litest_event(dev, EV_KEY, BTN_LEFT, 1);
@@ -683,7 +731,7 @@ START_TEST(touchpad_area_to_clickfinger_method_while_down)
struct litest_device *dev = litest_current_device();
struct libinput *li = dev->libinput;
- enable_clickfinger(dev);
+ litest_enable_clickfinger(dev);
litest_drain_events(li);
@@ -694,7 +742,7 @@ START_TEST(touchpad_area_to_clickfinger_method_while_down)
litest_assert_button_event(li, BTN_LEFT,
LIBINPUT_BUTTON_STATE_PRESSED);
- enable_buttonareas(dev);
+ litest_enable_buttonareas(dev);
litest_event(dev, EV_KEY, BTN_LEFT, 0);
litest_event(dev, EV_SYN, SYN_REPORT, 0);
@@ -725,11 +773,11 @@ START_TEST(touchpad_clickfinger_3fg_tool_position)
struct litest_device *dev = litest_current_device();
struct libinput *li = dev->libinput;
- enable_clickfinger(dev);
+ litest_enable_clickfinger(dev);
litest_drain_events(li);
- /* one in thumb area, one in normal area. spread is wide so the two
- * real fingers don't count together. we expect a 2-finger click */
+ /* one in thumb area, one in normal area + TRIPLETAP. spread is wide
+ * but any 3fg touch+click counts as middle */
litest_touch_down(dev, 0, 5, 99);
litest_touch_down(dev, 1, 90, 15);
litest_event(dev, EV_KEY, BTN_TOOL_DOUBLETAP, 0);
@@ -743,9 +791,9 @@ START_TEST(touchpad_clickfinger_3fg_tool_position)
litest_event(dev, EV_SYN, SYN_REPORT, 0);
libinput_dispatch(li);
- litest_assert_button_event(li, BTN_RIGHT,
+ litest_assert_button_event(li, BTN_MIDDLE,
LIBINPUT_BUTTON_STATE_PRESSED);
- litest_assert_button_event(li, BTN_RIGHT,
+ litest_assert_button_event(li, BTN_MIDDLE,
LIBINPUT_BUTTON_STATE_RELEASED);
}
END_TEST
@@ -755,7 +803,7 @@ START_TEST(touchpad_clickfinger_4fg_tool_position)
struct litest_device *dev = litest_current_device();
struct libinput *li = dev->libinput;
- enable_clickfinger(dev);
+ litest_enable_clickfinger(dev);
litest_drain_events(li);
litest_touch_down(dev, 0, 5, 99);
@@ -806,7 +854,7 @@ START_TEST(clickpad_btn_left)
struct litest_device *dev = litest_current_device();
struct libinput *li = dev->libinput;
- enable_buttonareas(dev);
+ litest_enable_buttonareas(dev);
litest_drain_events(li);
@@ -1415,7 +1463,7 @@ START_TEST(clickpad_topsoftbuttons_clickfinger)
struct litest_device *dev = litest_current_device();
struct libinput *li = dev->libinput;
- enable_clickfinger(dev);
+ litest_enable_clickfinger(dev);
litest_drain_events(li);
@@ -1462,7 +1510,7 @@ START_TEST(clickpad_topsoftbuttons_clickfinger_dev_disabled)
libinput_device_config_send_events_set_mode(dev->libinput_device,
LIBINPUT_CONFIG_SEND_EVENTS_DISABLED);
- enable_clickfinger(dev);
+ litest_enable_clickfinger(dev);
litest_drain_events(li);
litest_touch_down(dev, 0, 90, 5);
@@ -1513,6 +1561,8 @@ litest_setup_tests(void)
litest_add("touchpad:clickfinger", touchpad_4fg_clickfinger_btntool_2slots, LITEST_CLICKPAD, LITEST_ANY);
litest_add("touchpad:clickfinger", touchpad_4fg_clickfinger_btntool_3slots, LITEST_CLICKPAD, LITEST_ANY);
litest_add("touchpad:clickfinger", touchpad_2fg_clickfinger_distance, LITEST_CLICKPAD, LITEST_ANY);
+ litest_add("touchpad:clickfinger", touchpad_3fg_clickfinger_distance, LITEST_CLICKPAD, LITEST_ANY);
+ litest_add("touchpad:clickfinger", touchpad_3fg_clickfinger_distance_btntool, LITEST_CLICKPAD, LITEST_ANY);
litest_add_for_device("touchpad:clickfinger", touchpad_2fg_clickfinger_bottom, LITEST_SYNAPTICS_TOPBUTTONPAD);
litest_add("touchpad:clickfinger", touchpad_clickfinger_to_area_method, LITEST_CLICKPAD, LITEST_ANY);
litest_add("touchpad:clickfinger",
diff --git a/test/touchpad-tap.c b/test/touchpad-tap.c
index c021f1dc..62c7a5c3 100644
--- a/test/touchpad-tap.c
+++ b/test/touchpad-tap.c
@@ -32,30 +32,6 @@
#include "libinput-util.h"
#include "litest.h"
-static inline void
-enable_drag_lock(struct libinput_device *device)
-{
- enum libinput_config_status status, expected;
-
- expected = LIBINPUT_CONFIG_STATUS_SUCCESS;
- status = libinput_device_config_tap_set_drag_lock_enabled(device,
- LIBINPUT_CONFIG_DRAG_LOCK_ENABLED);
-
- litest_assert_int_eq(status, expected);
-}
-
-static inline void
-disable_drag_lock(struct libinput_device *device)
-{
- enum libinput_config_status status, expected;
-
- expected = LIBINPUT_CONFIG_STATUS_SUCCESS;
- status = libinput_device_config_tap_set_drag_lock_enabled(device,
- LIBINPUT_CONFIG_DRAG_LOCK_DISABLED);
-
- litest_assert_int_eq(status, expected);
-}
-
START_TEST(touchpad_1fg_tap)
{
struct litest_device *dev = litest_current_device();
@@ -265,6 +241,9 @@ START_TEST(touchpad_1fg_multitap_n_drag_2fg)
int range = _i,
ntaps;
+ if (litest_is_synaptics_semi_mt(dev))
+ return;
+
litest_enable_tap(dev->libinput_device);
litest_drain_events(li);
@@ -467,7 +446,7 @@ START_TEST(touchpad_1fg_multitap_n_drag_tap)
ntaps;
litest_enable_tap(dev->libinput_device);
- enable_drag_lock(dev->libinput_device);
+ litest_enable_drag_lock(dev->libinput_device);
litest_drain_events(li);
@@ -540,7 +519,7 @@ START_TEST(touchpad_1fg_multitap_n_drag_tap_click)
ntaps;
litest_enable_tap(dev->libinput_device);
- enable_drag_lock(dev->libinput_device);
+ litest_enable_drag_lock(dev->libinput_device);
litest_drain_events(li);
@@ -621,7 +600,7 @@ START_TEST(touchpad_1fg_tap_n_drag)
struct libinput_event_pointer *ptrev __attribute__((unused));
litest_enable_tap(dev->libinput_device);
- disable_drag_lock(dev->libinput_device);
+ litest_disable_drag_lock(dev->libinput_device);
litest_drain_events(li);
@@ -663,7 +642,7 @@ START_TEST(touchpad_1fg_tap_n_drag_draglock)
struct libinput *li = dev->libinput;
litest_enable_tap(dev->libinput_device);
- enable_drag_lock(dev->libinput_device);
+ litest_enable_drag_lock(dev->libinput_device);
litest_drain_events(li);
@@ -704,7 +683,7 @@ START_TEST(touchpad_1fg_tap_n_drag_draglock_tap)
struct libinput *li = dev->libinput;
litest_enable_tap(dev->libinput_device);
- enable_drag_lock(dev->libinput_device);
+ litest_enable_drag_lock(dev->libinput_device);
litest_drain_events(li);
@@ -746,7 +725,7 @@ START_TEST(touchpad_1fg_tap_n_drag_draglock_tap_click)
struct libinput *li = dev->libinput;
litest_enable_tap(dev->libinput_device);
- enable_drag_lock(dev->libinput_device);
+ litest_enable_drag_lock(dev->libinput_device);
litest_drain_events(li);
@@ -791,7 +770,7 @@ START_TEST(touchpad_1fg_tap_n_drag_draglock_timeout)
struct libinput *li = dev->libinput;
litest_enable_tap(dev->libinput_device);
- enable_drag_lock(dev->libinput_device);
+ litest_enable_drag_lock(dev->libinput_device);
litest_drain_events(li);
@@ -806,6 +785,7 @@ START_TEST(touchpad_1fg_tap_n_drag_draglock_timeout)
litest_assert_empty_queue(li);
litest_touch_up(dev, 0);
+ libinput_dispatch(li);
litest_timeout_tapndrag();
litest_assert_button_event(li, BTN_LEFT,
@@ -821,7 +801,7 @@ START_TEST(touchpad_2fg_tap_n_drag)
struct libinput *li = dev->libinput;
litest_enable_tap(dev->libinput_device);
- disable_drag_lock(dev->libinput_device);
+ litest_disable_drag_lock(dev->libinput_device);
litest_drain_events(li);
diff --git a/test/touchpad.c b/test/touchpad.c
index b910d0ea..6e7ea5ff 100644
--- a/test/touchpad.c
+++ b/test/touchpad.c
@@ -32,65 +32,6 @@
#include "libinput-util.h"
#include "litest.h"
-static bool
-has_2fg_scroll(struct litest_device *dev)
-{
- struct libinput_device *device = dev->libinput_device;
-
- return !!(libinput_device_config_scroll_get_methods(device) &
- LIBINPUT_CONFIG_SCROLL_2FG);
-}
-
-static void
-enable_2fg_scroll(struct litest_device *dev)
-{
- enum libinput_config_status status, expected;
- struct libinput_device *device = dev->libinput_device;
-
- status = libinput_device_config_scroll_set_method(device,
- LIBINPUT_CONFIG_SCROLL_2FG);
-
- expected = LIBINPUT_CONFIG_STATUS_SUCCESS;
- litest_assert_int_eq(status, expected);
-}
-
-static void
-enable_edge_scroll(struct litest_device *dev)
-{
- enum libinput_config_status status, expected;
- struct libinput_device *device = dev->libinput_device;
-
- status = libinput_device_config_scroll_set_method(device,
- LIBINPUT_CONFIG_SCROLL_EDGE);
-
- expected = LIBINPUT_CONFIG_STATUS_SUCCESS;
- litest_assert_int_eq(status, expected);
-}
-
-static void
-enable_clickfinger(struct litest_device *dev)
-{
- enum libinput_config_status status, expected;
- struct libinput_device *device = dev->libinput_device;
-
- status = libinput_device_config_click_set_method(device,
- LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER);
- expected = LIBINPUT_CONFIG_STATUS_SUCCESS;
- litest_assert_int_eq(status, expected);
-}
-
-static void
-enable_buttonareas(struct litest_device *dev)
-{
- enum libinput_config_status status, expected;
- struct libinput_device *device = dev->libinput_device;
-
- status = libinput_device_config_click_set_method(device,
- LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS);
- expected = LIBINPUT_CONFIG_STATUS_SUCCESS;
- litest_assert_int_eq(status, expected);
-}
-
START_TEST(touchpad_1fg_motion)
{
struct litest_device *dev = litest_current_device();
@@ -182,6 +123,10 @@ START_TEST(touchpad_2fg_scroll)
struct litest_device *dev = litest_current_device();
struct libinput *li = dev->libinput;
+ if (!litest_has_2fg_scroll(dev))
+ return;
+
+ litest_enable_2fg_scroll(dev);
litest_drain_events(li);
test_2fg_scroll(dev, 0.1, 40, 0);
@@ -208,6 +153,9 @@ START_TEST(touchpad_2fg_scroll_slow_distance)
const struct input_absinfo *y;
double y_move;
+ if (!litest_has_2fg_scroll(dev))
+ return;
+
/* We want to move > 5 mm. */
y = libevdev_get_abs_info(dev->evdev, ABS_Y);
if (y->resolution) {
@@ -217,6 +165,7 @@ START_TEST(touchpad_2fg_scroll_slow_distance)
y_move = 20.0;
}
+ litest_enable_2fg_scroll(dev);
litest_drain_events(li);
litest_touch_down(dev, 0, 49, 50);
@@ -261,6 +210,10 @@ START_TEST(touchpad_2fg_scroll_source)
struct libinput_event *event;
struct libinput_event_pointer *ptrev;
+ if (!litest_has_2fg_scroll(dev))
+ return;
+
+ litest_enable_2fg_scroll(dev);
litest_drain_events(li);
test_2fg_scroll(dev, 0, 30, 0);
@@ -282,6 +235,10 @@ START_TEST(touchpad_2fg_scroll_semi_mt)
struct litest_device *dev = litest_current_device();
struct libinput *li = dev->libinput;
+ if (!litest_has_2fg_scroll(dev))
+ return;
+
+ litest_enable_2fg_scroll(dev);
litest_drain_events(li);
litest_touch_down(dev, 0, 20, 20);
@@ -302,6 +259,10 @@ START_TEST(touchpad_2fg_scroll_return_to_motion)
struct litest_device *dev = litest_current_device();
struct libinput *li = dev->libinput;
+ if (!litest_has_2fg_scroll(dev))
+ return;
+
+ litest_enable_2fg_scroll(dev);
litest_drain_events(li);
/* start with motion */
@@ -364,11 +325,15 @@ START_TEST(touchpad_scroll_natural_enable_config)
}
END_TEST
-START_TEST(touchpad_scroll_natural)
+START_TEST(touchpad_scroll_natural_2fg)
{
struct litest_device *dev = litest_current_device();
struct libinput *li = dev->libinput;
+ if (!litest_has_2fg_scroll(dev))
+ return;
+
+ litest_enable_2fg_scroll(dev);
litest_drain_events(li);
libinput_device_config_scroll_set_natural_scroll_enabled(dev->libinput_device, 1);
@@ -391,7 +356,7 @@ START_TEST(touchpad_edge_scroll)
struct libinput *li = dev->libinput;
litest_drain_events(li);
- enable_edge_scroll(dev);
+ litest_enable_edge_scroll(dev);
litest_touch_down(dev, 0, 99, 20);
litest_touch_move_to(dev, 0, 99, 20, 99, 80, 10, 0);
@@ -439,6 +404,8 @@ START_TEST(touchpad_scroll_defaults)
ck_assert(method & LIBINPUT_CONFIG_SCROLL_EDGE);
if (libevdev_get_num_slots(evdev) > 1)
ck_assert(method & LIBINPUT_CONFIG_SCROLL_2FG);
+ else
+ ck_assert((method & LIBINPUT_CONFIG_SCROLL_2FG) == 0);
if (libevdev_get_num_slots(evdev) > 1)
expected = LIBINPUT_CONFIG_SCROLL_2FG;
@@ -483,7 +450,7 @@ START_TEST(touchpad_edge_scroll_timeout)
}
litest_drain_events(li);
- enable_edge_scroll(dev);
+ litest_enable_edge_scroll(dev);
litest_touch_down(dev, 0, 99, 20);
libinput_dispatch(li);
@@ -529,7 +496,7 @@ START_TEST(touchpad_edge_scroll_no_motion)
struct libinput *li = dev->libinput;
litest_drain_events(li);
- enable_edge_scroll(dev);
+ litest_enable_edge_scroll(dev);
litest_touch_down(dev, 0, 99, 10);
litest_touch_move_to(dev, 0, 99, 10, 99, 70, 10, 0);
@@ -551,7 +518,7 @@ START_TEST(touchpad_edge_scroll_no_edge_after_motion)
struct libinput *li = dev->libinput;
litest_drain_events(li);
- enable_edge_scroll(dev);
+ litest_enable_edge_scroll(dev);
/* moving into the edge zone must not trigger scroll events */
litest_touch_down(dev, 0, 20, 20);
@@ -573,7 +540,7 @@ START_TEST(touchpad_edge_scroll_source)
struct libinput_event_pointer *ptrev;
litest_drain_events(li);
- enable_edge_scroll(dev);
+ litest_enable_edge_scroll(dev);
litest_touch_down(dev, 0, 99, 20);
litest_touch_move_to(dev, 0, 99, 20, 99, 80, 10, 0);
@@ -598,7 +565,7 @@ START_TEST(touchpad_edge_scroll_no_2fg)
struct libinput *li = dev->libinput;
litest_drain_events(li);
- enable_edge_scroll(dev);
+ litest_enable_edge_scroll(dev);
litest_touch_down(dev, 0, 49, 50);
litest_touch_down(dev, 1, 51, 50);
@@ -617,8 +584,8 @@ START_TEST(touchpad_edge_scroll_into_buttonareas)
struct litest_device *dev = litest_current_device();
struct libinput *li = dev->libinput;
- enable_buttonareas(dev);
- enable_edge_scroll(dev);
+ litest_enable_buttonareas(dev);
+ litest_enable_edge_scroll(dev);
litest_drain_events(li);
litest_touch_down(dev, 0, 99, 40);
@@ -643,8 +610,8 @@ START_TEST(touchpad_edge_scroll_within_buttonareas)
struct litest_device *dev = litest_current_device();
struct libinput *li = dev->libinput;
- enable_buttonareas(dev);
- enable_edge_scroll(dev);
+ litest_enable_buttonareas(dev);
+ litest_enable_edge_scroll(dev);
litest_drain_events(li);
litest_touch_down(dev, 0, 20, 99);
@@ -671,8 +638,8 @@ START_TEST(touchpad_edge_scroll_buttonareas_click_stops_scroll)
struct libinput_event_pointer *ptrev;
double val;
- enable_buttonareas(dev);
- enable_edge_scroll(dev);
+ litest_enable_buttonareas(dev);
+ litest_enable_edge_scroll(dev);
litest_drain_events(li);
litest_touch_down(dev, 0, 20, 95);
@@ -718,8 +685,8 @@ START_TEST(touchpad_edge_scroll_clickfinger_click_stops_scroll)
struct libinput_event_pointer *ptrev;
double val;
- enable_clickfinger(dev);
- enable_edge_scroll(dev);
+ litest_enable_clickfinger(dev);
+ litest_enable_edge_scroll(dev);
litest_drain_events(li);
litest_touch_down(dev, 0, 20, 95);
@@ -763,7 +730,7 @@ START_TEST(touchpad_edge_scroll_into_area)
struct litest_device *dev = litest_current_device();
struct libinput *li = dev->libinput;
- enable_edge_scroll(dev);
+ litest_enable_edge_scroll(dev);
litest_drain_events(li);
/* move into area, move vertically, move back to edge */
@@ -807,10 +774,10 @@ START_TEST(touchpad_palm_detect_at_edge)
struct libinput *li = dev->libinput;
if (!touchpad_has_palm_detect_size(dev) ||
- !has_2fg_scroll(dev))
+ !litest_has_2fg_scroll(dev))
return;
- enable_2fg_scroll(dev);
+ litest_enable_2fg_scroll(dev);
litest_disable_tap(dev->libinput_device);
@@ -836,7 +803,7 @@ START_TEST(touchpad_no_palm_detect_at_edge_for_edge_scrolling)
if (!touchpad_has_palm_detect_size(dev))
return;
- enable_edge_scroll(dev);
+ litest_enable_edge_scroll(dev);
litest_drain_events(li);
@@ -854,10 +821,10 @@ START_TEST(touchpad_palm_detect_at_bottom_corners)
struct libinput *li = dev->libinput;
if (!touchpad_has_palm_detect_size(dev) ||
- !has_2fg_scroll(dev))
+ !litest_has_2fg_scroll(dev))
return;
- enable_2fg_scroll(dev);
+ litest_enable_2fg_scroll(dev);
litest_disable_tap(dev->libinput_device);
@@ -883,10 +850,10 @@ START_TEST(touchpad_palm_detect_at_top_corners)
struct libinput *li = dev->libinput;
if (!touchpad_has_palm_detect_size(dev) ||
- !has_2fg_scroll(dev))
+ !litest_has_2fg_scroll(dev))
return;
- enable_2fg_scroll(dev);
+ litest_enable_2fg_scroll(dev);
litest_disable_tap(dev->libinput_device);
@@ -912,10 +879,10 @@ START_TEST(touchpad_palm_detect_palm_stays_palm)
struct libinput *li = dev->libinput;
if (!touchpad_has_palm_detect_size(dev) ||
- !has_2fg_scroll(dev))
+ !litest_has_2fg_scroll(dev))
return;
- enable_2fg_scroll(dev);
+ litest_enable_2fg_scroll(dev);
litest_disable_tap(dev->libinput_device);
@@ -934,10 +901,10 @@ START_TEST(touchpad_palm_detect_palm_becomes_pointer)
struct libinput *li = dev->libinput;
if (!touchpad_has_palm_detect_size(dev) ||
- !has_2fg_scroll(dev))
+ !litest_has_2fg_scroll(dev))
return;
- enable_2fg_scroll(dev);
+ litest_enable_2fg_scroll(dev);
litest_disable_tap(dev->libinput_device);
@@ -2176,6 +2143,8 @@ START_TEST(touchpad_initial_state)
litest_touch_down(dev, 0, x, y);
litest_touch_move_to(dev, 0, x, y, 80, 80, 10, 1);
litest_touch_up(dev, 0);
+ libinput_dispatch(libinput1);
+ libinput_dispatch(libinput2);
litest_wait_for_event(libinput1);
litest_wait_for_event(libinput2);
@@ -2532,7 +2501,7 @@ START_TEST(touchpad_dwt_edge_scroll)
if (!has_disable_while_typing(touchpad))
return;
- enable_edge_scroll(touchpad);
+ litest_enable_edge_scroll(touchpad);
keyboard = litest_add_device(li, LITEST_KEYBOARD);
litest_drain_events(li);
@@ -2579,7 +2548,7 @@ START_TEST(touchpad_dwt_edge_scroll_interrupt)
if (!has_disable_while_typing(touchpad))
return;
- enable_edge_scroll(touchpad);
+ litest_enable_edge_scroll(touchpad);
keyboard = litest_add_device(li, LITEST_KEYBOARD);
litest_drain_events(li);
@@ -2938,7 +2907,7 @@ START_TEST(touchpad_thumb_update_no_motion)
};
litest_disable_tap(dev->libinput_device);
- enable_clickfinger(dev);
+ litest_enable_clickfinger(dev);
if (!has_thumb_detect(dev))
return;
@@ -2964,7 +2933,7 @@ START_TEST(touchpad_thumb_moving)
};
litest_disable_tap(dev->libinput_device);
- enable_clickfinger(dev);
+ litest_enable_clickfinger(dev);
if (!has_thumb_detect(dev))
return;
@@ -3088,7 +3057,7 @@ START_TEST(touchpad_thumb_edgescroll)
if (!has_thumb_detect(dev))
return;
- enable_edge_scroll(dev);
+ litest_enable_edge_scroll(dev);
litest_disable_tap(dev->libinput_device);
litest_drain_events(li);
@@ -3120,12 +3089,13 @@ START_TEST(touchpad_thumb_tap_begin)
return;
litest_enable_tap(dev->libinput_device);
- enable_clickfinger(dev);
+ litest_enable_clickfinger(dev);
litest_drain_events(li);
/* touch down is a thumb */
litest_touch_down_extended(dev, 0, 50, 99, axes);
litest_touch_up(dev, 0);
+ libinput_dispatch(li);
litest_timeout_tap();
litest_assert_empty_queue(li);
@@ -3133,6 +3103,7 @@ START_TEST(touchpad_thumb_tap_begin)
/* make sure normal tap still works */
litest_touch_down(dev, 0, 50, 99);
litest_touch_up(dev, 0);
+ libinput_dispatch(li);
litest_timeout_tap();
litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_BUTTON);
}
@@ -3151,19 +3122,21 @@ START_TEST(touchpad_thumb_tap_touch)
return;
litest_enable_tap(dev->libinput_device);
- enable_clickfinger(dev);
+ litest_enable_clickfinger(dev);
litest_drain_events(li);
/* event after touch down is thumb */
litest_touch_down(dev, 0, 50, 50);
litest_touch_move_extended(dev, 0, 51, 99, axes);
litest_touch_up(dev, 0);
+ libinput_dispatch(li);
litest_timeout_tap();
litest_assert_empty_queue(li);
/* make sure normal tap still works */
litest_touch_down(dev, 0, 50, 99);
litest_touch_up(dev, 0);
+ libinput_dispatch(li);
litest_timeout_tap();
litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_BUTTON);
}
@@ -3182,11 +3155,12 @@ START_TEST(touchpad_thumb_tap_hold)
return;
litest_enable_tap(dev->libinput_device);
- enable_clickfinger(dev);
+ litest_enable_clickfinger(dev);
litest_drain_events(li);
/* event in state HOLD is thumb */
litest_touch_down(dev, 0, 50, 99);
+ libinput_dispatch(li);
litest_timeout_tap();
libinput_dispatch(li);
litest_touch_move_extended(dev, 0, 51, 99, axes);
@@ -3196,6 +3170,7 @@ START_TEST(touchpad_thumb_tap_hold)
/* make sure normal tap still works */
litest_touch_down(dev, 0, 50, 99);
litest_touch_up(dev, 0);
+ libinput_dispatch(li);
litest_timeout_tap();
litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_BUTTON);
}
@@ -3214,11 +3189,12 @@ START_TEST(touchpad_thumb_tap_hold_2ndfg)
return;
litest_enable_tap(dev->libinput_device);
- enable_clickfinger(dev);
+ litest_enable_clickfinger(dev);
litest_drain_events(li);
/* event in state HOLD is thumb */
litest_touch_down(dev, 0, 50, 99);
+ libinput_dispatch(li);
litest_timeout_tap();
libinput_dispatch(li);
litest_touch_move_extended(dev, 0, 51, 99, axes);
@@ -3234,6 +3210,7 @@ START_TEST(touchpad_thumb_tap_hold_2ndfg)
litest_assert_empty_queue(li);
/* timeout -> into HOLD, no event on release */
+ libinput_dispatch(li);
litest_timeout_tap();
libinput_dispatch(li);
litest_touch_up(dev, 1);
@@ -3242,6 +3219,7 @@ START_TEST(touchpad_thumb_tap_hold_2ndfg)
/* make sure normal tap still works */
litest_touch_down(dev, 0, 50, 99);
litest_touch_up(dev, 0);
+ libinput_dispatch(li);
litest_timeout_tap();
litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_BUTTON);
}
@@ -3266,6 +3244,7 @@ START_TEST(touchpad_thumb_tap_hold_2ndfg_tap)
/* event in state HOLD is thumb */
litest_touch_down(dev, 0, 50, 99);
+ libinput_dispatch(li);
litest_timeout_tap();
libinput_dispatch(li);
litest_touch_move_extended(dev, 0, 51, 99, axes);
@@ -3289,6 +3268,7 @@ START_TEST(touchpad_thumb_tap_hold_2ndfg_tap)
LIBINPUT_BUTTON_STATE_PRESSED);
libinput_event_destroy(libinput_event_pointer_get_base_event(ptrev));
+ libinput_dispatch(li);
litest_timeout_tap();
libinput_dispatch(li);
event = libinput_get_event(li);
@@ -3300,6 +3280,7 @@ START_TEST(touchpad_thumb_tap_hold_2ndfg_tap)
/* make sure normal tap still works */
litest_touch_down(dev, 0, 50, 99);
litest_touch_up(dev, 0);
+ libinput_dispatch(li);
litest_timeout_tap();
litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_BUTTON);
}
@@ -3317,7 +3298,7 @@ START_TEST(touchpad_tool_tripletap_touch_count)
* https://bugs.freedesktop.org/show_bug.cgi?id=91352
*/
litest_drain_events(li);
- enable_clickfinger(dev);
+ litest_enable_clickfinger(dev);
/* touch 1 down */
litest_event(dev, EV_ABS, ABS_MT_SLOT, 0);
@@ -3419,6 +3400,40 @@ START_TEST(touchpad_tool_tripletap_touch_count)
}
END_TEST
+START_TEST(touchpad_time_usec)
+{
+ struct litest_device *dev = litest_current_device();
+ struct libinput *li = dev->libinput;
+ struct libinput_event *event;
+ struct libinput_event_pointer *ptrev;
+
+ litest_disable_tap(dev->libinput_device);
+
+ litest_drain_events(li);
+
+ litest_touch_down(dev, 0, 50, 50);
+ litest_touch_move_to(dev, 0, 50, 50, 80, 50, 5, 0);
+ litest_touch_up(dev, 0);
+
+ libinput_dispatch(li);
+
+ event = libinput_get_event(li);
+ ck_assert_notnull(event);
+
+ while (event) {
+ uint64_t utime;
+
+ ptrev = litest_is_motion_event(event);
+ utime = libinput_event_pointer_get_time_usec(ptrev);
+
+ ck_assert_int_eq(libinput_event_pointer_get_time(ptrev),
+ utime / 1000);
+ libinput_event_destroy(event);
+ event = libinput_get_event(li);
+ }
+}
+END_TEST
+
void
litest_setup_tests(void)
{
@@ -3434,7 +3449,7 @@ litest_setup_tests(void)
litest_add("touchpad:scroll", touchpad_2fg_scroll_semi_mt, LITEST_SEMI_MT, LITEST_SINGLE_TOUCH);
litest_add("touchpad:scroll", touchpad_scroll_natural_defaults, LITEST_TOUCHPAD, LITEST_ANY);
litest_add("touchpad:scroll", touchpad_scroll_natural_enable_config, LITEST_TOUCHPAD, LITEST_ANY);
- litest_add("touchpad:scroll", touchpad_scroll_natural, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH);
+ litest_add("touchpad:scroll", touchpad_scroll_natural_2fg, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH);
litest_add("touchpad:scroll", touchpad_scroll_defaults, LITEST_TOUCHPAD, LITEST_ANY);
litest_add("touchpad:scroll", touchpad_edge_scroll, LITEST_TOUCHPAD, LITEST_ANY);
litest_add("touchpad:scroll", touchpad_edge_scroll_no_motion, LITEST_TOUCHPAD, LITEST_ANY);
@@ -3523,4 +3538,6 @@ litest_setup_tests(void)
litest_add("touchpad:thumb", touchpad_thumb_tap_hold_2ndfg_tap, LITEST_CLICKPAD, LITEST_SINGLE_TOUCH);
litest_add_for_device("touchpad:bugs", touchpad_tool_tripletap_touch_count, LITEST_SYNAPTICS_TOPBUTTONPAD);
+
+ litest_add("touchpad:time", touchpad_time_usec, LITEST_TOUCHPAD, LITEST_ANY);
}
diff --git a/tools/ptraccel-debug.c b/tools/ptraccel-debug.c
index b2dd1f90..1496763b 100644
--- a/tools/ptraccel-debug.c
+++ b/tools/ptraccel-debug.c
@@ -26,12 +26,14 @@
#include
#include
#include
-#include
#include
#include
#include
#include
+#include
+#include
+
static void
print_ptraccel_deltas(struct motion_filter *filter, double step)
{
@@ -50,7 +52,7 @@ print_ptraccel_deltas(struct motion_filter *filter, double step)
for (i = 0.0; i < 15.0; i += step) {
motion.x = i;
motion.y = 0;
- time += 12; /* pretend 80Hz data */
+ time += us(12500); /* pretend 80Hz data */
motion = filter_dispatch(filter, &motion, NULL, time);
@@ -93,7 +95,7 @@ print_ptraccel_movement(struct motion_filter *filter,
for (i = 0; i < nevents; i++) {
motion.x = dx;
motion.y = 0;
- time += 12; /* pretend 80Hz data */
+ time += us(12500); /* pretend 80Hz data */
motion = filter_dispatch(filter, &motion, NULL, time);
@@ -127,7 +129,7 @@ print_ptraccel_sequence(struct motion_filter *filter,
for (i = 0; i < nevents; i++, dx++) {
motion.x = *dx;
motion.y = 0;
- time += 12; /* pretend 80Hz data */
+ time += us(12500); /* pretend 80Hz data */
motion = filter_dispatch(filter, &motion, NULL, time);
diff --git a/udev/.gitignore b/udev/.gitignore
index 2fdaedcf..cad377a8 100644
--- a/udev/.gitignore
+++ b/udev/.gitignore
@@ -1,3 +1,6 @@
libinput-device-group
libinput-model-quirks
-*.rules
+80-libinput-device-groups-litest.rules
+80-libinput-device-groups.rules
+90-libinput-model-quirks-litest.rules
+90-libinput-model-quirks.rules
diff --git a/udev/80-libinput-test-device.rules b/udev/80-libinput-test-device.rules
new file mode 100644
index 00000000..d37b2abe
--- /dev/null
+++ b/udev/80-libinput-test-device.rules
@@ -0,0 +1 @@
+KERNELS=="*input*", ATTRS{name}=="litest *", ENV{LIBINPUT_TEST_DEVICE}="1"
diff --git a/udev/90-libinput-model-quirks.hwdb b/udev/90-libinput-model-quirks.hwdb
index a34b8f17..cf4fbfaa 100644
--- a/udev/90-libinput-model-quirks.hwdb
+++ b/udev/90-libinput-model-quirks.hwdb
@@ -39,6 +39,7 @@ libinput:touchpad:input:b0005v05ACp*
##########################################
libinput:name:*ETPS/2 Elantech Touchpad*:dmi:*
LIBINPUT_ATTR_RESOLUTION_HINT=31x31
+ LIBINPUT_MODEL_ELANTECH_TOUCHPAD=1
##########################################
# Google
diff --git a/udev/Makefile.am b/udev/Makefile.am
index 975f5370..cfb854e1 100644
--- a/udev/Makefile.am
+++ b/udev/Makefile.am
@@ -33,3 +33,4 @@ CLEANFILES = $(litest_rules)
DISTCLEANFILES = \
80-libinput-device-groups.rules \
90-libinput-model-quirks.rules
+EXTRA_DIST = 80-libinput-test-device.rules
diff --git a/udev/libinput-model-quirks.c b/udev/libinput-model-quirks.c
index fc3dbe85..0e737a4b 100644
--- a/udev/libinput-model-quirks.c
+++ b/udev/libinput-model-quirks.c
@@ -68,6 +68,30 @@ handle_touchpad_alps(struct udev_device *device)
printf("LIBINPUT_MODEL_FIRMWARE_VERSION=%d\n", pid);
}
+static void
+handle_touchpad_synaptics(struct udev_device *device)
+{
+ const char *product, *props;
+ int bus, vid, pid, version;
+ int prop;
+
+ product = prop_value(device, "PRODUCT");
+ if (!product)
+ return;
+
+ if (sscanf(product, "%x/%x/%x/%x", &bus, &vid, &pid, &version) != 4)
+ return;
+
+ if (bus != BUS_I8042 || vid != 0x2 || pid != 0x7)
+ return;
+
+ props = prop_value(device, "PROP");
+ if (sscanf(props, "%x", &prop) != 1)
+ return;
+ if (prop & (1 << INPUT_PROP_SEMI_MT))
+ printf("LIBINPUT_MODEL_JUMPING_SEMI_MT=1\n");
+}
+
static void
handle_touchpad(struct udev_device *device)
{
@@ -79,6 +103,8 @@ handle_touchpad(struct udev_device *device)
if (strstr(name, "AlpsPS/2 ALPS") != NULL)
handle_touchpad_alps(device);
+ if (strstr(name, "Synaptics ") != NULL)
+ handle_touchpad_synaptics(device);
}
int main(int argc, char **argv)