mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2026-02-04 16:20:29 +01:00
Merge branch 'master' into tablet-support
This commit is contained in:
commit
2b99363a1f
15 changed files with 287 additions and 62 deletions
|
|
@ -2,12 +2,24 @@
|
|||
@page scrolling Scrolling
|
||||
|
||||
libinput supports three different types of scrolling methods: @ref
|
||||
twofinger_scrolling, @ref edge_scrolling and @ref button_scrolling. Some devices
|
||||
support multiple methods, though only one can be enabled at a time. See
|
||||
twofinger_scrolling, @ref edge_scrolling and @ref button_scrolling. Some
|
||||
devices support multiple methods, though only one can be enabled at a time.
|
||||
As a general overview:
|
||||
- touchpad devices with physical buttons below the touchpad support edge and
|
||||
two-finger scrolling
|
||||
- touchpad devices without physical buttons (@ref clickpad_softbuttons
|
||||
"clickpads") support two-finger scrolling only
|
||||
- pointing sticks provide on-button scrolling by default
|
||||
- mice and other pointing devices support on-button scrolling but it is not
|
||||
enabled by default
|
||||
|
||||
A device may differ from the above based on its capabilities. See
|
||||
libinput_device_config_scroll_set_method() for documentation on how to
|
||||
switch methods and libinput_device_config_scroll_get_methods() for
|
||||
documentation on how to query a device for available scroll methods.
|
||||
|
||||
@section horizontal_scrolling Horizontal scrolling
|
||||
|
||||
Scroll movements provide vertical and horizontal directions, each
|
||||
scroll event contains both directions where applicable, see
|
||||
libinput_event_pointer_get_axis_value(). libinput does not provide separate
|
||||
|
|
@ -55,6 +67,10 @@ a designated button is held down. For example, Lenovo devices provide a
|
|||
<a href="http://en.wikipedia.org/wiki/Pointing_stick">pointing stick</a> that emulates
|
||||
scroll events when the trackstick's middle mouse button is held down.
|
||||
|
||||
@note On-button scrolling is enabled by default for pointing sticks. This
|
||||
prevents middle-button dragging; all motion events while the middle button is
|
||||
down are converted to scroll events.
|
||||
|
||||
@image html button-scrolling.svg "Button scrolling"
|
||||
|
||||
The button may be changed with
|
||||
|
|
|
|||
|
|
@ -31,7 +31,6 @@
|
|||
|
||||
#include "evdev-mt-touchpad.h"
|
||||
|
||||
#define DEFAULT_BUTTON_MOTION_THRESHOLD 0.02 /* 2% of size */
|
||||
#define DEFAULT_BUTTON_ENTER_TIMEOUT 100 /* ms */
|
||||
#define DEFAULT_BUTTON_LEAVE_TIMEOUT 300 /* ms */
|
||||
|
||||
|
|
@ -709,11 +708,19 @@ tp_init_buttons(struct tp_dispatch *tp,
|
|||
absinfo_x = device->abs.absinfo_x;
|
||||
absinfo_y = device->abs.absinfo_y;
|
||||
|
||||
width = abs(absinfo_x->maximum - absinfo_x->minimum);
|
||||
height = abs(absinfo_y->maximum - absinfo_y->minimum);
|
||||
diagonal = sqrt(width*width + height*height);
|
||||
|
||||
tp->buttons.motion_dist = diagonal * DEFAULT_BUTTON_MOTION_THRESHOLD;
|
||||
/* pinned-finger motion threshold, see tp_unpin_finger.
|
||||
The MAGIC for resolution-less touchpads ends up as 2% of the diagonal */
|
||||
if (device->abs.fake_resolution) {
|
||||
const int BUTTON_MOTION_MAGIC = 0.007;
|
||||
width = abs(absinfo_x->maximum - absinfo_x->minimum);
|
||||
height = abs(absinfo_y->maximum - absinfo_y->minimum);
|
||||
diagonal = sqrt(width*width + height*height);
|
||||
tp->buttons.motion_dist.x_scale_coeff = diagonal * BUTTON_MOTION_MAGIC;
|
||||
tp->buttons.motion_dist.y_scale_coeff = diagonal * BUTTON_MOTION_MAGIC;
|
||||
} else {
|
||||
tp->buttons.motion_dist.x_scale_coeff = 1.0/absinfo_x->resolution;
|
||||
tp->buttons.motion_dist.y_scale_coeff = 1.0/absinfo_y->resolution;
|
||||
}
|
||||
|
||||
tp->buttons.config_method.get_methods = tp_button_config_click_get_methods;
|
||||
tp->buttons.config_method.set_method = tp_button_config_click_set_method;
|
||||
|
|
|
|||
|
|
@ -431,17 +431,15 @@ tp_unpin_finger(struct tp_dispatch *tp, struct tp_touch *t)
|
|||
return;
|
||||
|
||||
xdist = abs(t->point.x - t->pinned.center.x);
|
||||
xdist *= tp->buttons.motion_dist.x_scale_coeff;
|
||||
ydist = abs(t->point.y - t->pinned.center.y);
|
||||
ydist *= tp->buttons.motion_dist.y_scale_coeff;
|
||||
|
||||
if (xdist * xdist + ydist * ydist >=
|
||||
tp->buttons.motion_dist * tp->buttons.motion_dist) {
|
||||
/* 3mm movement -> unpin */
|
||||
if (vector_length(xdist, ydist) >= 3.0) {
|
||||
t->pinned.is_pinned = false;
|
||||
return;
|
||||
}
|
||||
|
||||
/* The finger may slowly drift, adjust the center */
|
||||
t->pinned.center.x = t->point.x + t->pinned.center.x / 2;
|
||||
t->pinned.center.y = t->point.y + t->pinned.center.y / 2;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -666,6 +664,7 @@ tp_process_state(struct tp_dispatch *tp, uint64_t time)
|
|||
struct tp_touch *t;
|
||||
struct tp_touch *first = tp_get_touch(tp, 0);
|
||||
unsigned int i;
|
||||
bool restart_filter = false;
|
||||
|
||||
tp_process_fake_touches(tp, time);
|
||||
tp_unhover_touches(tp, time);
|
||||
|
|
@ -692,8 +691,14 @@ tp_process_state(struct tp_dispatch *tp, uint64_t time)
|
|||
tp_motion_history_push(t);
|
||||
|
||||
tp_unpin_finger(tp, t);
|
||||
|
||||
if (t->state == TOUCH_BEGIN)
|
||||
restart_filter = true;
|
||||
}
|
||||
|
||||
if (restart_filter)
|
||||
filter_restart(tp->device->pointer.filter, tp, time);
|
||||
|
||||
tp_button_handle_state(tp, time);
|
||||
tp_edge_scroll_handle_state(tp, time);
|
||||
|
||||
|
|
@ -1150,7 +1155,7 @@ evdev_tag_touchpad(struct evdev_device *device,
|
|||
*/
|
||||
bustype = libevdev_get_id_bustype(device->evdev);
|
||||
if (bustype == BUS_USB) {
|
||||
if (libevdev_get_id_vendor(device->evdev) == VENDOR_ID_APPLE)
|
||||
if (device->model == EVDEV_MODEL_APPLE_TOUCHPAD)
|
||||
device->tags |= EVDEV_TAG_INTERNAL_TOUCHPAD;
|
||||
} else if (bustype != BUS_BLUETOOTH)
|
||||
device->tags |= EVDEV_TAG_INTERNAL_TOUCHPAD;
|
||||
|
|
@ -1389,7 +1394,6 @@ tp_init_palmdetect(struct tp_dispatch *tp,
|
|||
struct evdev_device *device)
|
||||
{
|
||||
int width, height;
|
||||
unsigned int vendor_id;
|
||||
|
||||
tp->palm.right_edge = INT_MAX;
|
||||
tp->palm.left_edge = INT_MIN;
|
||||
|
|
@ -1400,13 +1404,11 @@ tp_init_palmdetect(struct tp_dispatch *tp,
|
|||
height = abs(device->abs.absinfo_y->maximum -
|
||||
device->abs.absinfo_y->minimum);
|
||||
|
||||
vendor_id = evdev_device_get_id_vendor(device);
|
||||
|
||||
/* Wacom doesn't have internal touchpads,
|
||||
* Apple touchpads are always big enough to warrant palm detection */
|
||||
if (vendor_id == VENDOR_ID_WACOM) {
|
||||
if (device->model == EVDEV_MODEL_WACOM_TOUCHPAD) {
|
||||
return 0;
|
||||
} else if (vendor_id != VENDOR_ID_APPLE) {
|
||||
} else if (device->model != EVDEV_MODEL_APPLE_TOUCHPAD) {
|
||||
/* We don't know how big the touchpad is */
|
||||
if (device->abs.absinfo_x->resolution == 1)
|
||||
return 0;
|
||||
|
|
@ -1489,10 +1491,18 @@ tp_init(struct tp_dispatch *tp,
|
|||
EV_ABS,
|
||||
ABS_MT_DISTANCE);
|
||||
|
||||
tp->hysteresis_margin.x =
|
||||
diagonal / DEFAULT_HYSTERESIS_MARGIN_DENOMINATOR;
|
||||
tp->hysteresis_margin.y =
|
||||
diagonal / DEFAULT_HYSTERESIS_MARGIN_DENOMINATOR;
|
||||
if (device->abs.fake_resolution) {
|
||||
tp->hysteresis_margin.x =
|
||||
diagonal / DEFAULT_HYSTERESIS_MARGIN_DENOMINATOR;
|
||||
tp->hysteresis_margin.y =
|
||||
diagonal / DEFAULT_HYSTERESIS_MARGIN_DENOMINATOR;
|
||||
} else {
|
||||
int res_x = tp->device->abs.absinfo_x->resolution,
|
||||
res_y = tp->device->abs.absinfo_y->resolution;
|
||||
|
||||
tp->hysteresis_margin.x = res_x/2;
|
||||
tp->hysteresis_margin.y = res_y/2;
|
||||
}
|
||||
|
||||
if (tp_init_accel(tp, diagonal) != 0)
|
||||
return -1;
|
||||
|
|
|
|||
|
|
@ -223,7 +223,10 @@ struct tp_dispatch {
|
|||
bool click_pending;
|
||||
uint32_t state;
|
||||
uint32_t old_state;
|
||||
uint32_t motion_dist; /* for pinned touches */
|
||||
struct {
|
||||
double x_scale_coeff;
|
||||
double y_scale_coeff;
|
||||
} motion_dist; /* for pinned touches */
|
||||
unsigned int active; /* currently active button, for release event */
|
||||
bool active_is_topbutton; /* is active a top button? */
|
||||
|
||||
|
|
|
|||
|
|
@ -1514,6 +1514,8 @@ evdev_read_model(struct evdev_device *device)
|
|||
{ "LIBINPUT_MODEL_SYSTEM76_GALAGO", EVDEV_MODEL_SYSTEM76_GALAGO },
|
||||
{ "LIBINPUT_MODEL_SYSTEM76_KUDU", EVDEV_MODEL_SYSTEM76_KUDU },
|
||||
{ "LIBINPUT_MODEL_CLEVO_W740SU", EVDEV_MODEL_CLEVO_W740SU },
|
||||
{ "LIBINPUT_MODEL_APPLE_TOUCHPAD", EVDEV_MODEL_APPLE_TOUCHPAD },
|
||||
{ "LIBINPUT_MODEL_WACOM_TOUCHPAD", EVDEV_MODEL_WACOM_TOUCHPAD },
|
||||
{ NULL, EVDEV_MODEL_DEFAULT },
|
||||
};
|
||||
const struct model_map *m = model_map;
|
||||
|
|
|
|||
|
|
@ -104,6 +104,8 @@ enum evdev_device_model {
|
|||
EVDEV_MODEL_SYSTEM76_GALAGO,
|
||||
EVDEV_MODEL_SYSTEM76_KUDU,
|
||||
EVDEV_MODEL_CLEVO_W740SU,
|
||||
EVDEV_MODEL_APPLE_TOUCHPAD,
|
||||
EVDEV_MODEL_WACOM_TOUCHPAD,
|
||||
};
|
||||
|
||||
struct mt_slot {
|
||||
|
|
|
|||
|
|
@ -32,6 +32,9 @@ struct motion_filter_interface {
|
|||
struct motion_filter *filter,
|
||||
const struct normalized_coords *unaccelerated,
|
||||
void *data, uint64_t time);
|
||||
void (*restart)(struct motion_filter *filter,
|
||||
void *data,
|
||||
uint64_t time);
|
||||
void (*destroy)(struct motion_filter *filter);
|
||||
bool (*set_speed)(struct motion_filter *filter,
|
||||
double speed);
|
||||
|
|
|
|||
33
src/filter.c
33
src/filter.c
|
|
@ -43,6 +43,13 @@ filter_dispatch(struct motion_filter *filter,
|
|||
return filter->interface->filter(filter, unaccelerated, data, time);
|
||||
}
|
||||
|
||||
void
|
||||
filter_restart(struct motion_filter *filter,
|
||||
void *data, uint64_t time)
|
||||
{
|
||||
filter->interface->restart(filter, data, time);
|
||||
}
|
||||
|
||||
void
|
||||
filter_destroy(struct motion_filter *filter)
|
||||
{
|
||||
|
|
@ -273,6 +280,29 @@ accelerator_filter(struct motion_filter *filter,
|
|||
return accelerated;
|
||||
}
|
||||
|
||||
static void
|
||||
accelerator_restart(struct motion_filter *filter,
|
||||
void *data,
|
||||
uint64_t time)
|
||||
{
|
||||
struct pointer_accelerator *accel =
|
||||
(struct pointer_accelerator *) filter;
|
||||
unsigned int offset;
|
||||
struct pointer_tracker *tracker;
|
||||
|
||||
for (offset = 1; offset < NUM_POINTER_TRACKERS; offset++) {
|
||||
tracker = tracker_by_offset(accel, offset);
|
||||
tracker->time = 0;
|
||||
tracker->dir = 0;
|
||||
tracker->delta.x = 0;
|
||||
tracker->delta.y = 0;
|
||||
}
|
||||
|
||||
tracker = tracker_by_offset(accel, 0);
|
||||
tracker->time = time;
|
||||
tracker->dir = UNDEFINED_DIRECTION;
|
||||
}
|
||||
|
||||
static void
|
||||
accelerator_destroy(struct motion_filter *filter)
|
||||
{
|
||||
|
|
@ -309,6 +339,7 @@ accelerator_set_speed(struct motion_filter *filter,
|
|||
|
||||
struct motion_filter_interface accelerator_interface = {
|
||||
accelerator_filter,
|
||||
accelerator_restart,
|
||||
accelerator_destroy,
|
||||
accelerator_set_speed,
|
||||
};
|
||||
|
|
@ -354,7 +385,7 @@ pointer_accel_profile_linear(struct motion_filter *filter,
|
|||
const double threshold = accel_filter->threshold; /* units/ms */
|
||||
const double incline = accel_filter->incline;
|
||||
|
||||
s1 = min(1, speed_in * 5);
|
||||
s1 = min(1, 0.3 + speed_in * 4);
|
||||
s2 = 1 + (speed_in - threshold) * incline;
|
||||
|
||||
return min(max_accel, s2 > 1 ? s2 : s1);
|
||||
|
|
|
|||
|
|
@ -37,6 +37,11 @@ struct normalized_coords
|
|||
filter_dispatch(struct motion_filter *filter,
|
||||
const struct normalized_coords *unaccelerated,
|
||||
void *data, uint64_t time);
|
||||
|
||||
void
|
||||
filter_restart(struct motion_filter *filter,
|
||||
void *data, uint64_t time);
|
||||
|
||||
void
|
||||
filter_destroy(struct motion_filter *filter);
|
||||
|
||||
|
|
|
|||
|
|
@ -308,4 +308,10 @@ int parse_mouse_dpi_property(const char *prop);
|
|||
int parse_mouse_wheel_click_angle_property(const char *prop);
|
||||
double parse_trackpoint_accel_property(const char *prop);
|
||||
|
||||
static inline double
|
||||
vector_length(double x, double y)
|
||||
{
|
||||
return sqrt(x * x + y * y);
|
||||
}
|
||||
|
||||
#endif /* LIBINPUT_UTIL_H */
|
||||
|
|
|
|||
|
|
@ -42,7 +42,9 @@ liblitest_la_SOURCES = \
|
|||
litest-vmware-virtual-usb-mouse.c \
|
||||
litest.c
|
||||
liblitest_la_LIBADD = $(top_builddir)/src/libinput-util.la
|
||||
liblitest_la_CFLAGS = $(AM_CFLAGS)
|
||||
liblitest_la_CFLAGS = $(AM_CFLAGS) \
|
||||
-DLIBINPUT_UDEV_RULES_FILE="\"$(abs_top_srcdir)/udev/90-libinput-model-quirks.rules\"" \
|
||||
-DLIBINPUT_UDEV_HWDB_FILE="\"$(abs_top_srcdir)/udev/90-libinput-model-quirks.hwdb\""
|
||||
if HAVE_LIBUNWIND
|
||||
liblitest_la_LIBADD += $(LIBUNWIND_LIBS) -ldl
|
||||
liblitest_la_CFLAGS += $(LIBUNWIND_CFLAGS)
|
||||
|
|
@ -119,9 +121,13 @@ test_device_LDADD = $(TEST_LIBS)
|
|||
test_device_LDFLAGS = -no-install
|
||||
|
||||
test_litest_selftest_SOURCES = litest-selftest.c litest.c litest-int.h litest.h
|
||||
test_litest_selftest_CFLAGS = -DLITEST_DISABLE_BACKTRACE_LOGGING -DLITEST_NO_MAIN
|
||||
test_litest_selftest_CFLAGS = -DLITEST_DISABLE_BACKTRACE_LOGGING -DLITEST_NO_MAIN $(liblitest_la_CFLAGS)
|
||||
test_litest_selftest_LDADD = $(TEST_LIBS)
|
||||
test_litest_selftest_LDFLAGS = -no-install
|
||||
if HAVE_LIBUNWIND
|
||||
test_litest_selftest_LDADD += $(LIBUNWIND_LIBS) -ldl
|
||||
test_litest_selftest_CFLAGS += $(LIBUNWIND_CFLAGS)
|
||||
endif
|
||||
|
||||
# build-test only
|
||||
test_build_pedantic_c99_SOURCES = build-pedantic.c
|
||||
|
|
|
|||
111
test/litest.c
111
test/litest.c
|
|
@ -40,6 +40,7 @@
|
|||
#include <unistd.h>
|
||||
#include "linux/input.h"
|
||||
#include <sys/ptrace.h>
|
||||
#include <sys/sendfile.h>
|
||||
#include <sys/timerfd.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
|
|
@ -49,6 +50,9 @@
|
|||
|
||||
#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.rules"
|
||||
#define UDEV_COMMON_HWDB_FILE UDEV_HWDB_D "/91-litest-model-quirks-REMOVEME.hwdb"
|
||||
|
||||
static int in_debugger = -1;
|
||||
static int verbose = 0;
|
||||
|
|
@ -56,13 +60,15 @@ const char *filter_test = NULL;
|
|||
const char *filter_device = NULL;
|
||||
const char *filter_group = NULL;
|
||||
|
||||
static inline void litest_remove_model_quirks(void);
|
||||
|
||||
/* defined for the litest selftest */
|
||||
#ifndef LITEST_DISABLE_BACKTRACE_LOGGING
|
||||
#define litest_log(...) fprintf(stderr, __VA_ARGS__)
|
||||
#define litest_vlog(format_, args_) vfprintf(stderr, format_, args_)
|
||||
#else
|
||||
#define litest_log(...) /* __VA_ARGS__ */
|
||||
#define litest_vlog(...) /* __VA_ARGS__ */
|
||||
#define litest_log(...) { /* __VA_ARGS__ */ }
|
||||
#define litest_vlog(...) { /* __VA_ARGS__ */ }
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBUNWIND
|
||||
|
|
@ -382,28 +388,40 @@ struct litest_test_device* devices[] = {
|
|||
|
||||
static struct list all_tests;
|
||||
|
||||
static inline void
|
||||
litest_system(const char *command)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = system(command);
|
||||
|
||||
if (ret == -1) {
|
||||
litest_abort_msg("Failed to execute: %s", command);
|
||||
} else if (WIFEXITED(ret)) {
|
||||
if (WEXITSTATUS(ret))
|
||||
litest_abort_msg("'%s' failed with %d",
|
||||
command,
|
||||
WEXITSTATUS(ret));
|
||||
} else if (WIFSIGNALED(ret)) {
|
||||
litest_abort_msg("'%s' terminated with signal %d",
|
||||
command,
|
||||
WTERMSIG(ret));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
litest_reload_udev_rules(void)
|
||||
{
|
||||
int ret = system("udevadm control --reload-rules");
|
||||
if (ret == -1) {
|
||||
litest_abort_msg("Failed to execute: udevadm");
|
||||
} else if (WIFEXITED(ret)) {
|
||||
if (WEXITSTATUS(ret))
|
||||
litest_abort_msg("udevadm failed with %d",
|
||||
WEXITSTATUS(ret));
|
||||
} else if (WIFSIGNALED(ret)) {
|
||||
litest_abort_msg("udevadm terminated with signal %d",
|
||||
WTERMSIG(ret));
|
||||
}
|
||||
litest_system("udevadm control --reload-rules");
|
||||
litest_system("udevadm hwdb --update");
|
||||
}
|
||||
|
||||
static int
|
||||
litest_udev_rule_filter(const struct dirent *entry)
|
||||
{
|
||||
return strncmp(entry->d_name,
|
||||
UDEV_RULE_PREFIX,
|
||||
strlen(UDEV_RULE_PREFIX)) == 0;
|
||||
return strneq(entry->d_name,
|
||||
UDEV_RULE_PREFIX,
|
||||
strlen(UDEV_RULE_PREFIX));
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -438,6 +456,7 @@ litest_drop_udev_rules(void)
|
|||
}
|
||||
free(entries);
|
||||
|
||||
litest_remove_model_quirks();
|
||||
litest_reload_udev_rules();
|
||||
}
|
||||
|
||||
|
|
@ -881,21 +900,70 @@ merge_events(const int *orig, const int *override)
|
|||
return events;
|
||||
}
|
||||
|
||||
static inline void
|
||||
litest_copy_file(const char *dest, const char *src, const char *header)
|
||||
{
|
||||
int in, out;
|
||||
|
||||
out = open(dest, O_CREAT|O_WRONLY, 0644);
|
||||
litest_assert_int_gt(out, -1);
|
||||
|
||||
if (header)
|
||||
write(out, header, strlen(header));
|
||||
|
||||
in = open(src, O_RDONLY);
|
||||
litest_assert_int_gt(in, -1);
|
||||
/* lazy, just check for error and empty file copy */
|
||||
litest_assert_int_gt(sendfile(out, in, NULL, 4096), 0);
|
||||
close(out);
|
||||
close(in);
|
||||
}
|
||||
|
||||
static inline void
|
||||
litest_install_model_quirks(void)
|
||||
{
|
||||
litest_copy_file(UDEV_COMMON_RULE_FILE, LIBINPUT_UDEV_RULES_FILE, NULL);
|
||||
litest_copy_file(UDEV_COMMON_HWDB_FILE,
|
||||
LIBINPUT_UDEV_HWDB_FILE,
|
||||
"#################################################################\n"
|
||||
"# WARNING: REMOVE THIS FILE\n"
|
||||
"# This is the run-time hwdb file for the libinput test suite and\n"
|
||||
"# should be removed on exit. If the test-suite is not currently \n"
|
||||
"# running, remove this file and update your hwdb: \n"
|
||||
"# sudo udevadm hwdb --update\n"
|
||||
"#################################################################\n\n");
|
||||
}
|
||||
|
||||
static inline void
|
||||
litest_remove_model_quirks(void)
|
||||
{
|
||||
unlink(UDEV_COMMON_RULE_FILE);
|
||||
unlink(UDEV_COMMON_HWDB_FILE);
|
||||
}
|
||||
|
||||
static char *
|
||||
litest_init_udev_rules(struct litest_test_device *dev)
|
||||
{
|
||||
int rc;
|
||||
FILE *f;
|
||||
char *path;
|
||||
|
||||
if (!dev->udev_rule)
|
||||
return NULL;
|
||||
char *path = NULL;
|
||||
|
||||
rc = mkdir(UDEV_RULES_D, 0755);
|
||||
if (rc == -1 && errno != EEXIST)
|
||||
ck_abort_msg("Failed to create udev rules directory (%s)\n",
|
||||
strerror(errno));
|
||||
|
||||
rc = mkdir(UDEV_HWDB_D, 0755);
|
||||
if (rc == -1 && errno != EEXIST)
|
||||
ck_abort_msg("Failed to create udev hwdb directory (%s)\n",
|
||||
strerror(errno));
|
||||
|
||||
litest_install_model_quirks();
|
||||
|
||||
/* device-specific udev rules */
|
||||
if (!dev->udev_rule)
|
||||
goto out;
|
||||
|
||||
rc = xasprintf(&path,
|
||||
"%s/%s%s.rules",
|
||||
UDEV_RULES_D,
|
||||
|
|
@ -911,6 +979,7 @@ litest_init_udev_rules(struct litest_test_device *dev)
|
|||
litest_assert_int_ge(fputs(dev->udev_rule, f), 0);
|
||||
fclose(f);
|
||||
|
||||
out:
|
||||
litest_reload_udev_rules();
|
||||
|
||||
return path;
|
||||
|
|
@ -950,6 +1019,7 @@ litest_create(enum litest_device_type which,
|
|||
if ((*dev)->create) {
|
||||
(*dev)->create(d);
|
||||
if (abs_override || events_override) {
|
||||
litest_remove_model_quirks();
|
||||
if (udev_file)
|
||||
unlink(udev_file);
|
||||
litest_abort_msg("Custom create cannot be overridden");
|
||||
|
|
@ -1128,6 +1198,7 @@ litest_delete_device(struct litest_device *d)
|
|||
return;
|
||||
|
||||
if (d->udev_rule_file) {
|
||||
litest_remove_model_quirks();
|
||||
unlink(d->udev_rule_file);
|
||||
free(d->udev_rule_file);
|
||||
d->udev_rule_file = NULL;
|
||||
|
|
|
|||
|
|
@ -2153,6 +2153,53 @@ START_TEST(clickpad_click_n_drag)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(clickpad_finger_pin)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
struct libevdev *evdev = dev->evdev;
|
||||
const struct input_absinfo *abs;
|
||||
|
||||
abs = libevdev_get_abs_info(evdev, ABS_MT_POSITION_X);
|
||||
ck_assert_notnull(abs);
|
||||
if (abs->resolution == 0)
|
||||
return;
|
||||
|
||||
litest_drain_events(li);
|
||||
|
||||
/* make sure the movement generates pointer events when
|
||||
not pinned */
|
||||
litest_touch_down(dev, 0, 50, 50);
|
||||
litest_touch_move_to(dev, 0, 50, 50, 52, 52, 10, 1);
|
||||
litest_touch_move_to(dev, 0, 52, 52, 48, 48, 10, 1);
|
||||
litest_touch_move_to(dev, 0, 48, 48, 50, 50, 10, 1);
|
||||
litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);
|
||||
|
||||
litest_button_click(dev, BTN_LEFT, true);
|
||||
litest_drain_events(li);
|
||||
|
||||
litest_touch_move_to(dev, 0, 50, 50, 52, 52, 10, 1);
|
||||
litest_touch_move_to(dev, 0, 52, 52, 48, 48, 10, 1);
|
||||
litest_touch_move_to(dev, 0, 48, 48, 50, 50, 10, 1);
|
||||
|
||||
litest_assert_empty_queue(li);
|
||||
|
||||
litest_button_click(dev, BTN_LEFT, false);
|
||||
litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_BUTTON);
|
||||
|
||||
/* still pinned after release */
|
||||
litest_touch_move_to(dev, 0, 50, 50, 52, 52, 10, 1);
|
||||
litest_touch_move_to(dev, 0, 52, 52, 48, 48, 10, 1);
|
||||
litest_touch_move_to(dev, 0, 48, 48, 50, 50, 10, 1);
|
||||
|
||||
litest_assert_empty_queue(li);
|
||||
|
||||
/* move to unpin */
|
||||
litest_touch_move_to(dev, 0, 50, 50, 70, 70, 10, 1);
|
||||
litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(clickpad_softbutton_left)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
|
|
@ -5144,6 +5191,7 @@ litest_setup_tests(void)
|
|||
litest_add("touchpad:click", touchpad_btn_left, LITEST_TOUCHPAD|LITEST_BUTTON, LITEST_CLICKPAD);
|
||||
litest_add("touchpad:click", clickpad_btn_left, LITEST_CLICKPAD, LITEST_ANY);
|
||||
litest_add("touchpad:click", clickpad_click_n_drag, LITEST_CLICKPAD, LITEST_SINGLE_TOUCH);
|
||||
litest_add("touchpad:click", clickpad_finger_pin, LITEST_CLICKPAD, LITEST_ANY);
|
||||
|
||||
litest_add("touchpad:softbutton", clickpad_softbutton_left, LITEST_CLICKPAD, LITEST_APPLE_CLICKPAD);
|
||||
litest_add("touchpad:softbutton", clickpad_softbutton_right, LITEST_CLICKPAD, LITEST_APPLE_CLICKPAD);
|
||||
|
|
|
|||
|
|
@ -15,6 +15,13 @@
|
|||
#
|
||||
# Sort by brand, model
|
||||
|
||||
##########################################
|
||||
# Apple
|
||||
##########################################
|
||||
libinput:touchpad:input:b0003v05ACp*
|
||||
libinput:touchpad:input:b0005v05ACp*
|
||||
LIBINPUT_MODEL_APPLE_TOUCHPAD=1
|
||||
|
||||
##########################################
|
||||
# Google
|
||||
##########################################
|
||||
|
|
@ -23,18 +30,18 @@
|
|||
# extrapolated from the chromiumos touchad-tests repo
|
||||
# https://chromium.googlesource.com/chromiumos/platform/touchpad-tests
|
||||
libinput:name:Cypress APA Trackpad (cyapa):dmi:*pnFalco:pvr*
|
||||
libinput:name:SynPS/2 Synaptics TouchPad:dmi:*pn*Mario*:
|
||||
libinput:name:Cypress APA Trackpad (cyapa):dmi:*pn*Butterfly*:
|
||||
libinput:name:Cypress APA Trackpad (cyapa):dmi:*pn*Peppy*:
|
||||
libinput:name:SynPS/2 Synaptics TouchPad:dmi:*pn*ZGB*:
|
||||
libinput:name:Cypress APA Trackpad (cyapa):dmi:*pn*Parrot*:
|
||||
libinput:name:Cypress APA Trackpad (cyapa):dmi:*bvn*coreboot*:pn*Leon*:
|
||||
libinput:name:Cypress APA Trackpad (cyapa):dmi:*bvn*coreboot*:pn*Falco*:
|
||||
libinput:name:Cypress APA Trackpad (cyapa):dmi:*bvn*coreboot*:pn*Wolf*:
|
||||
libinput:name:Cypress APA Trackpad (cyapa):dmi:*svn*GOOGLE*:pn*Link*:
|
||||
libinput:name:SynPS/2 Synaptics TouchPad:dmi:*pn*Alex*:
|
||||
libinput:name:Cypress APA Trackpad (cyapa):dmi:*svn*SAMSUNG*:pn*Lumpy*:
|
||||
libinput:name:Atmel maXTouch Touchpad:dmi:*svn*GOOGLE*:pn*Samus*:
|
||||
libinput:name:SynPS/2 Synaptics TouchPad:dmi:*pn*Mario*
|
||||
libinput:name:Cypress APA Trackpad (cyapa):dmi:*pn*Butterfly*
|
||||
libinput:name:Cypress APA Trackpad (cyapa):dmi:*pn*Peppy*
|
||||
libinput:name:SynPS/2 Synaptics TouchPad:dmi:*pn*ZGB*
|
||||
libinput:name:Cypress APA Trackpad (cyapa):dmi:*pn*Parrot*
|
||||
libinput:name:Cypress APA Trackpad (cyapa):dmi:*bvn*coreboot*:pn*Leon*
|
||||
libinput:name:Cypress APA Trackpad (cyapa):dmi:*bvn*coreboot*:pn*Falco*
|
||||
libinput:name:Cypress APA Trackpad (cyapa):dmi:*bvn*coreboot*:pn*Wolf*
|
||||
libinput:name:Cypress APA Trackpad (cyapa):dmi:*svn*GOOGLE*:pn*Link*
|
||||
libinput:name:SynPS/2 Synaptics TouchPad:dmi:*pn*Alex*
|
||||
libinput:name:Cypress APA Trackpad (cyapa):dmi:*svn*SAMSUNG*:pn*Lumpy*
|
||||
libinput:name:Atmel maXTouch Touchpad:dmi:*svn*GOOGLE*:pn*Samus*
|
||||
LIBINPUT_MODEL_CHROMEBOOK=1
|
||||
|
||||
##########################################
|
||||
|
|
@ -64,3 +71,9 @@ libinput:name:SynPS/2 Synaptics TouchPad:dmi:*svnSystem76*pvrgalu1*
|
|||
# Kudu Professional
|
||||
libinput:name:SynPS/2 Synaptics TouchPad:dmi:*svnSystem76*pvrkudp1*
|
||||
LIBINPUT_MODEL_SYSTEM76_KUDU=1
|
||||
|
||||
##########################################
|
||||
# Wacom
|
||||
##########################################
|
||||
libinput:touchpad:input:b0003v056Ap*
|
||||
LIBINPUT_MODEL_WACOM_TOUCHPAD=1
|
||||
|
|
|
|||
|
|
@ -13,8 +13,9 @@ KERNEL!="event*", GOTO="libinput_model_quirks_end"
|
|||
|
||||
# hwdb matches:
|
||||
#
|
||||
# libinput:<modalias>
|
||||
IMPORT{builtin}="hwdb --subsystem=input --lookup-prefix=libinput:", \
|
||||
# libinput:touchpad:<modalias>
|
||||
ENV{ID_INPUT_TOUCHPAD}=="1", \
|
||||
IMPORT{builtin}="hwdb --subsystem=input --lookup-prefix=libinput:touchpad:", \
|
||||
GOTO="libinput_model_quirks_end"
|
||||
|
||||
# libinput:name:<name>:dmi:<dmi string>
|
||||
|
|
@ -22,4 +23,5 @@ KERNELS=="input*", \
|
|||
IMPORT{builtin}="hwdb 'libinput:name:$attr{name}:$attr{[dmi/id]modalias}'", \
|
||||
GOTO="libinput_model_quirks_end"
|
||||
|
||||
|
||||
LABEL="libinput_model_quirks_end"
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue