Merge branch 'master' into tablet-support

This commit is contained in:
Peter Hutterer 2015-08-04 12:32:00 +10:00
commit 6bfc36f9cf
46 changed files with 1115 additions and 335 deletions

View file

@ -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
-------------

View file

@ -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])

View file

@ -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 \

View file

@ -25,6 +25,7 @@
- @subpage faq
- @subpage tools
- @subpage reporting_bugs
@page developers Developers

88
doc/reporting-bugs.dox Normal file
View file

@ -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: <tt>git log -n 1 HEAD</tt> or <tt>git describe
HEAD</tt>. As a last resort: <tt>libinput-list-devices --version</tt>.
- 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 <tt>xinput list-props "your device name"</tt>. Use
<tt>xinput list</tt> 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 <tt>/sys/class/dmi/id/modalias</tt>.
- if the device is a touchpad, the physical dimensions of your touchpad in
mm
@section evemu Recording devices with evemu
<a href="http://www.freedesktop.org/wiki/Evemu/">evemu</a> 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 <tt>/dev/input/eventX</tt> 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.
*/

View file

@ -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

162
doc/touchpads.dox Normal file
View file

@ -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 <b>detect</b> 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 <b>track</b>, 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.
*/

View file

@ -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

View file

@ -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;

View file

@ -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.

View file

@ -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,

View file

@ -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 {

View file

@ -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;
}

View file

@ -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;

View file

@ -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);

View file

@ -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);

View file

@ -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;

View file

@ -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

View file

@ -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) {

View file

@ -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 */

View file

@ -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,

View file

@ -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
*

View file

@ -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.

View file

@ -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;

View file

@ -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",

View file

@ -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);

View file

@ -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 */

View file

@ -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)

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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

View file

@ -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)

View file

@ -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 { \

View file

@ -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);
}

View file

@ -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);

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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",

View file

@ -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);

View file

@ -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);
}

View file

@ -26,12 +26,14 @@
#include <errno.h>
#include <stdbool.h>
#include <stdio.h>
#include <filter.h>
#include <getopt.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <filter.h>
#include <libinput-util.h>
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);

5
udev/.gitignore vendored
View file

@ -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

View file

@ -0,0 +1 @@
KERNELS=="*input*", ATTRS{name}=="litest *", ENV{LIBINPUT_TEST_DEVICE}="1"

View file

@ -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

View file

@ -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

View file

@ -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)