mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2026-05-14 22:18:08 +02:00
Merge branch 'master' into tablet-support
Added: udev-tag detection for the tablet. libwacom assigns ID_INPUT_TABLET to all known devices but also ID_INPUT_TOUCHPAD to all known devices with a touch interface. That's a bug and should be fixed there but we can work around it by checking both and making sure only one is set. Conflicts: src/evdev.c test/misc.c
This commit is contained in:
commit
2365f7d3d1
19 changed files with 669 additions and 190 deletions
|
|
@ -22,7 +22,7 @@ For more information, visit:
|
|||
http://www.freedesktop.org/wiki/Software/libinput/
|
||||
|
||||
Bugs can be filed in the libinput component of Wayland:
|
||||
https://bugs.freedesktop.org/enter_bug.cgi?product=Wayland
|
||||
https://bugs.freedesktop.org/enter_bug.cgi?product=Wayland&component=libinput
|
||||
|
||||
Online API documentation:
|
||||
http://wayland.freedesktop.org/libinput/doc/latest/modules.html
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
AC_PREREQ([2.64])
|
||||
|
||||
m4_define([libinput_major_version], [0])
|
||||
m4_define([libinput_minor_version], [9])
|
||||
m4_define([libinput_minor_version], [10])
|
||||
m4_define([libinput_micro_version], [0])
|
||||
m4_define([libinput_version],
|
||||
[libinput_major_version.libinput_minor_version.libinput_micro_version])
|
||||
|
|
@ -30,10 +30,11 @@ AM_INIT_AUTOMAKE([1.11 foreign no-dist-gzip dist-xz])
|
|||
# - If binary compatibility has been broken (eg removed or changed interfaces)
|
||||
# change to C+1:0:0
|
||||
# - If the interface is the same as the previous version, change to C:R+1:A
|
||||
LIBINPUT_LT_VERSION=8:0:1
|
||||
LIBINPUT_LT_VERSION=8:1:1
|
||||
AC_SUBST(LIBINPUT_LT_VERSION)
|
||||
|
||||
AM_SILENT_RULES([yes])
|
||||
AC_USE_SYSTEM_EXTENSIONS
|
||||
|
||||
# Check for programs
|
||||
AC_PROG_CC_C99
|
||||
|
|
|
|||
|
|
@ -54,6 +54,13 @@ The movement of a finger can alter the button area behavior:
|
|||
- once a finger has moved out of the button area, it cannot move back in and
|
||||
trigger a right or middle button event
|
||||
|
||||
On some touchpads, notably the 2015 Lenovo X1 Carbon 3rd series, the very
|
||||
bottom end of the touchpad is outside of the sensor range but it is possible
|
||||
to trigger a physical click there. To libinput, the click merely shows up as
|
||||
a left button click without any positional finger data and it is
|
||||
impossible to determine whether it is a left or a right click. libinput
|
||||
ignores such button clicks, this behavior is intentional.
|
||||
|
||||
@section clickfinger Clickfinger behavior
|
||||
|
||||
This is the default behavior on Apple touchpads.
|
||||
|
|
|
|||
|
|
@ -823,6 +823,7 @@ tp_post_clickpadbutton_buttons(struct tp_dispatch *tp, uint64_t time)
|
|||
break;
|
||||
case BUTTON_EVENT_IN_TOP_L:
|
||||
is_top = 1;
|
||||
/* fallthrough */
|
||||
case BUTTON_EVENT_IN_BOTTOM_L:
|
||||
button |= LEFT;
|
||||
break;
|
||||
|
|
@ -832,6 +833,7 @@ tp_post_clickpadbutton_buttons(struct tp_dispatch *tp, uint64_t time)
|
|||
break;
|
||||
case BUTTON_EVENT_IN_TOP_R:
|
||||
is_top = 1;
|
||||
/* fallthrough */
|
||||
case BUTTON_EVENT_IN_BOTTOM_R:
|
||||
button |= RIGHT;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -1107,12 +1107,6 @@ tp_tag_device(struct evdev_device *device,
|
|||
if (udev_device_get_property_value(udev_device,
|
||||
"TOUCHPAD_HAS_TRACKPOINT_BUTTONS"))
|
||||
device->tags |= EVDEV_TAG_TOUCHPAD_TRACKPOINT;
|
||||
|
||||
/* Magic version tag: used by the litest device. Should never be set
|
||||
* in real life but allows us to test for these features without
|
||||
* requiring custom udev rules during make check */
|
||||
if (libevdev_get_id_version(device->evdev) == 0xfffa)
|
||||
device->tags |= EVDEV_TAG_TOUCHPAD_TRACKPOINT;
|
||||
}
|
||||
|
||||
static struct evdev_dispatch_interface tp_interface = {
|
||||
|
|
|
|||
194
src/evdev.c
194
src/evdev.c
|
|
@ -49,6 +49,37 @@ enum evdev_key_type {
|
|||
EVDEV_KEY_TYPE_BUTTON,
|
||||
};
|
||||
|
||||
enum evdev_device_udev_tags {
|
||||
EVDEV_UDEV_TAG_INPUT = (1 << 0),
|
||||
EVDEV_UDEV_TAG_KEYBOARD = (1 << 1),
|
||||
EVDEV_UDEV_TAG_MOUSE = (1 << 2),
|
||||
EVDEV_UDEV_TAG_TOUCHPAD = (1 << 3),
|
||||
EVDEV_UDEV_TAG_TOUCHSCREEN = (1 << 4),
|
||||
EVDEV_UDEV_TAG_TABLET = (1 << 5),
|
||||
EVDEV_UDEV_TAG_JOYSTICK = (1 << 6),
|
||||
EVDEV_UDEV_TAG_ACCELEROMETER = (1 << 7),
|
||||
};
|
||||
|
||||
struct evdev_udev_tag_match {
|
||||
const char *name;
|
||||
enum evdev_device_udev_tags tag;
|
||||
};
|
||||
|
||||
static const struct evdev_udev_tag_match evdev_udev_tag_matches[] = {
|
||||
{"ID_INPUT", EVDEV_UDEV_TAG_INPUT},
|
||||
{"ID_INPUT_KEYBOARD", EVDEV_UDEV_TAG_KEYBOARD},
|
||||
{"ID_INPUT_KEY", EVDEV_UDEV_TAG_KEYBOARD},
|
||||
{"ID_INPUT_MOUSE", EVDEV_UDEV_TAG_MOUSE},
|
||||
{"ID_INPUT_TOUCHPAD", EVDEV_UDEV_TAG_TOUCHPAD},
|
||||
{"ID_INPUT_TOUCHSCREEN", EVDEV_UDEV_TAG_TOUCHSCREEN},
|
||||
{"ID_INPUT_TABLET", EVDEV_UDEV_TAG_TABLET},
|
||||
{"ID_INPUT_JOYSTICK", EVDEV_UDEV_TAG_JOYSTICK},
|
||||
{"ID_INPUT_ACCELEROMETER", EVDEV_UDEV_TAG_ACCELEROMETER},
|
||||
|
||||
/* sentinel value */
|
||||
{ 0 },
|
||||
};
|
||||
|
||||
static void
|
||||
hw_set_key_down(struct evdev_device *device, int code, int pressed)
|
||||
{
|
||||
|
|
@ -1229,10 +1260,12 @@ evdev_device_init_pointer_acceleration(struct evdev_device *device)
|
|||
device->pointer.config.get_default_speed = evdev_accel_config_get_default_speed;
|
||||
device->base.config.accel = &device->pointer.config;
|
||||
|
||||
evdev_accel_config_set_speed(&device->base,
|
||||
evdev_accel_config_get_default_speed(&device->base));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static inline int
|
||||
evdev_need_mtdev(struct evdev_device *device)
|
||||
{
|
||||
|
|
@ -1317,38 +1350,62 @@ evdev_fix_abs_resolution(struct libevdev *evdev,
|
|||
}
|
||||
}
|
||||
|
||||
static enum evdev_device_udev_tags
|
||||
evdev_device_get_udev_tags(struct evdev_device *device,
|
||||
struct udev_device *udev_device)
|
||||
{
|
||||
const char *prop;
|
||||
enum evdev_device_udev_tags tags = 0;
|
||||
const struct evdev_udev_tag_match *match = evdev_udev_tag_matches;
|
||||
|
||||
while (match->name) {
|
||||
prop = udev_device_get_property_value(device->udev_device,
|
||||
match->name);
|
||||
if (prop)
|
||||
tags |= match->tag;
|
||||
|
||||
match++;
|
||||
}
|
||||
return tags;
|
||||
}
|
||||
|
||||
static int
|
||||
evdev_configure_device(struct evdev_device *device)
|
||||
{
|
||||
struct libinput *libinput = device->base.seat->libinput;
|
||||
struct libevdev *evdev = device->evdev;
|
||||
const struct input_absinfo *absinfo;
|
||||
int has_abs, has_rel, has_mt;
|
||||
int has_button, has_keyboard, has_touch, has_joystick_button;
|
||||
struct mt_slot *slots;
|
||||
int num_slots;
|
||||
int active_slot;
|
||||
int slot;
|
||||
unsigned int i;
|
||||
const char *devnode = udev_device_get_devnode(device->udev_device);
|
||||
enum evdev_device_udev_tags udev_tags;
|
||||
|
||||
has_rel = 0;
|
||||
has_abs = 0;
|
||||
has_mt = 0;
|
||||
has_button = 0;
|
||||
has_joystick_button = 0;
|
||||
has_keyboard = 0;
|
||||
has_touch = 0;
|
||||
udev_tags = evdev_device_get_udev_tags(device, device->udev_device);
|
||||
|
||||
for (i = BTN_JOYSTICK; i <= BTN_PINKIE; i++)
|
||||
if (libevdev_has_event_code(evdev, EV_KEY, i))
|
||||
has_joystick_button = 1;
|
||||
if ((udev_tags & EVDEV_UDEV_TAG_INPUT) == 0 ||
|
||||
(udev_tags & ~EVDEV_UDEV_TAG_INPUT) == 0) {
|
||||
log_info(libinput,
|
||||
"input device '%s', %s not tagged as input device\n",
|
||||
device->devname, devnode);
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = BTN_GAMEPAD; i <= BTN_TR2; i++)
|
||||
if (libevdev_has_event_code(evdev, EV_KEY, i))
|
||||
has_joystick_button = 1;
|
||||
log_info(libinput,
|
||||
"input device '%s', %s is tagged by udev as:%s%s%s%s%s%s\n",
|
||||
device->devname, devnode,
|
||||
udev_tags & EVDEV_UDEV_TAG_KEYBOARD ? " Keyboard" : "",
|
||||
udev_tags & EVDEV_UDEV_TAG_MOUSE ? " Mouse" : "",
|
||||
udev_tags & EVDEV_UDEV_TAG_TOUCHPAD ? " Touchpad" : "",
|
||||
udev_tags & EVDEV_UDEV_TAG_TOUCHSCREEN ? " Touchscreen" : "",
|
||||
udev_tags & EVDEV_UDEV_TAG_TABLET ? " Tablet" : "",
|
||||
udev_tags & EVDEV_UDEV_TAG_JOYSTICK ? " Joystick" : "",
|
||||
udev_tags & EVDEV_UDEV_TAG_ACCELEROMETER ? " Accelerometer" : "");
|
||||
|
||||
if (has_joystick_button) {
|
||||
/* libwacom *adds* TABLET, TOUCHPAD but leaves JOYSTICK in place, so
|
||||
make sure we only ignore real joystick devices */
|
||||
if ((udev_tags & EVDEV_UDEV_TAG_JOYSTICK) == udev_tags) {
|
||||
log_info(libinput,
|
||||
"input device '%s', %s is a joystick, ignoring\n",
|
||||
device->devname, devnode);
|
||||
|
|
@ -1363,7 +1420,6 @@ evdev_configure_device(struct evdev_device *device)
|
|||
absinfo))
|
||||
device->abs.fake_resolution = 1;
|
||||
device->abs.absinfo_x = absinfo;
|
||||
has_abs = 1;
|
||||
}
|
||||
if ((absinfo = libevdev_get_abs_info(evdev, ABS_Y))) {
|
||||
if (evdev_fix_abs_resolution(evdev,
|
||||
|
|
@ -1371,7 +1427,6 @@ evdev_configure_device(struct evdev_device *device)
|
|||
absinfo))
|
||||
device->abs.fake_resolution = 1;
|
||||
device->abs.absinfo_y = absinfo;
|
||||
has_abs = 1;
|
||||
}
|
||||
|
||||
/* Fake MT devices have the ABS_MT_SLOT bit set because of
|
||||
|
|
@ -1379,8 +1434,7 @@ evdev_configure_device(struct evdev_device *device)
|
|||
just have too many ABS_ axes */
|
||||
if (libevdev_has_event_code(evdev, EV_ABS, ABS_MT_SLOT) &&
|
||||
libevdev_get_num_slots(evdev) == -1) {
|
||||
has_mt = 0;
|
||||
has_touch = 0;
|
||||
udev_tags &= ~EVDEV_UDEV_TAG_TOUCHSCREEN;
|
||||
} else if (libevdev_has_event_code(evdev, EV_ABS, ABS_MT_POSITION_X) &&
|
||||
libevdev_has_event_code(evdev, EV_ABS, ABS_MT_POSITION_Y)) {
|
||||
absinfo = libevdev_get_abs_info(evdev, ABS_MT_POSITION_X);
|
||||
|
|
@ -1397,8 +1451,6 @@ evdev_configure_device(struct evdev_device *device)
|
|||
device->abs.fake_resolution = 1;
|
||||
device->abs.absinfo_y = absinfo;
|
||||
device->is_mt = 1;
|
||||
has_touch = 1;
|
||||
has_mt = 1;
|
||||
|
||||
/* We only handle the slotted Protocol B in libinput.
|
||||
Devices with ABS_MT_POSITION_* but not ABS_MT_SLOT
|
||||
|
|
@ -1433,83 +1485,55 @@ evdev_configure_device(struct evdev_device *device)
|
|||
}
|
||||
}
|
||||
|
||||
if (libevdev_has_event_code(evdev, EV_REL, REL_X) ||
|
||||
libevdev_has_event_code(evdev, EV_REL, REL_Y))
|
||||
has_rel = 1;
|
||||
|
||||
if (libevdev_has_event_type(evdev, EV_KEY)) {
|
||||
if (!libevdev_has_property(evdev, INPUT_PROP_DIRECT) &&
|
||||
libevdev_has_event_code(evdev, EV_KEY, BTN_TOOL_FINGER) &&
|
||||
!libevdev_has_event_code(evdev, EV_KEY, BTN_TOOL_PEN) &&
|
||||
(has_abs || has_mt)) {
|
||||
device->dispatch = evdev_mt_touchpad_create(device);
|
||||
log_info(libinput,
|
||||
"input device '%s', %s is a touchpad\n",
|
||||
device->devname, devnode);
|
||||
return device->dispatch == NULL ? -1 : 0;
|
||||
} else if (!libevdev_has_event_code(device->evdev, EV_KEY, BTN_TOOL_FINGER) &&
|
||||
libevdev_has_event_code(device->evdev, EV_KEY, BTN_TOOL_PEN) &&
|
||||
has_abs) {
|
||||
device->dispatch = evdev_tablet_create(device);
|
||||
device->seat_caps |= EVDEV_DEVICE_TABLET;
|
||||
log_info(libinput,
|
||||
"input device '%s', %s is a tablet\n",
|
||||
device->devname, devnode);
|
||||
return device->dispatch == NULL ? -1 : 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < KEY_MAX; i++) {
|
||||
if (libevdev_has_event_code(evdev, EV_KEY, i)) {
|
||||
switch (get_key_type(i)) {
|
||||
case EVDEV_KEY_TYPE_NONE:
|
||||
break;
|
||||
case EVDEV_KEY_TYPE_KEY:
|
||||
has_keyboard = 1;
|
||||
break;
|
||||
case EVDEV_KEY_TYPE_BUTTON:
|
||||
has_button = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (libevdev_has_event_code(evdev, EV_KEY, BTN_TOUCH))
|
||||
has_touch = 1;
|
||||
/* libwacom assigns touchpad _and_ tablet to the tablet touch bits,
|
||||
so make sure we don't initialize the tablet interface for the
|
||||
touch device */
|
||||
if ((udev_tags & (EVDEV_UDEV_TAG_TABLET|EVDEV_UDEV_TAG_TOUCHPAD)) ==
|
||||
EVDEV_UDEV_TAG_TABLET) {
|
||||
device->dispatch = evdev_tablet_create(device);
|
||||
device->seat_caps |= EVDEV_DEVICE_TABLET;
|
||||
log_info(libinput,
|
||||
"input device '%s', %s is a tablet\n",
|
||||
device->devname, devnode);
|
||||
return device->dispatch == NULL ? -1 : 0;
|
||||
}
|
||||
if (libevdev_has_event_type(evdev, EV_LED))
|
||||
has_keyboard = 1;
|
||||
|
||||
if ((has_abs || has_rel) && has_button) {
|
||||
if (evdev_device_init_pointer_acceleration(device) == -1)
|
||||
if (udev_tags & EVDEV_UDEV_TAG_TOUCHPAD) {
|
||||
device->dispatch = evdev_mt_touchpad_create(device);
|
||||
log_info(libinput,
|
||||
"input device '%s', %s is a touchpad\n",
|
||||
device->devname, devnode);
|
||||
return device->dispatch == NULL ? -1 : 0;
|
||||
}
|
||||
|
||||
if (udev_tags & EVDEV_UDEV_TAG_MOUSE) {
|
||||
if (!libevdev_has_event_code(evdev, EV_ABS, ABS_X) &&
|
||||
!libevdev_has_event_code(evdev, EV_ABS, ABS_Y) &&
|
||||
evdev_device_init_pointer_acceleration(device) == -1)
|
||||
return -1;
|
||||
|
||||
device->seat_caps |= EVDEV_DEVICE_POINTER;
|
||||
|
||||
log_info(libinput,
|
||||
"input device '%s', %s is a pointer caps =%s%s%s\n",
|
||||
device->devname, devnode,
|
||||
has_abs ? " absolute-motion" : "",
|
||||
has_rel ? " relative-motion": "",
|
||||
has_button ? " button" : "");
|
||||
"input device '%s', %s is a pointer caps\n",
|
||||
device->devname, devnode);
|
||||
|
||||
/* want left-handed config option */
|
||||
device->left_handed.want_enabled = true;
|
||||
/* want natural-scroll config option */
|
||||
device->scroll.natural_scrolling_enabled = true;
|
||||
}
|
||||
|
||||
if (has_rel && has_button) {
|
||||
/* want button scrolling config option */
|
||||
device->scroll.want_button = 1;
|
||||
}
|
||||
|
||||
if (has_keyboard) {
|
||||
if (udev_tags & EVDEV_UDEV_TAG_KEYBOARD) {
|
||||
device->seat_caps |= EVDEV_DEVICE_KEYBOARD;
|
||||
log_info(libinput,
|
||||
"input device '%s', %s is a keyboard\n",
|
||||
device->devname, devnode);
|
||||
}
|
||||
if (has_touch && !has_button) {
|
||||
|
||||
if (udev_tags & EVDEV_UDEV_TAG_TOUCHSCREEN) {
|
||||
device->seat_caps |= EVDEV_DEVICE_TOUCH;
|
||||
log_info(libinput,
|
||||
"input device '%s', %s is a touch device\n",
|
||||
|
|
@ -1578,6 +1602,7 @@ evdev_device_create(struct libinput_seat *seat,
|
|||
int fd;
|
||||
int unhandled_device = 0;
|
||||
const char *devnode = udev_device_get_devnode(udev_device);
|
||||
struct libinput_device_group *group;
|
||||
|
||||
/* Use non-blocking mode so that we can loop on read on
|
||||
* evdev_device_data() until all events on the fd are
|
||||
|
|
@ -1648,6 +1673,12 @@ evdev_device_create(struct libinput_seat *seat,
|
|||
if (!device->source)
|
||||
goto err;
|
||||
|
||||
group = libinput_device_group_create();
|
||||
if (!group)
|
||||
goto err;
|
||||
libinput_device_set_device_group(&device->base, group);
|
||||
libinput_device_group_unref(group);
|
||||
|
||||
list_insert(seat->devices_list.prev, &device->base.link);
|
||||
|
||||
evdev_tag_device(device);
|
||||
|
|
@ -2131,6 +2162,9 @@ evdev_device_destroy(struct evdev_device *device)
|
|||
if (dispatch)
|
||||
dispatch->interface->destroy(dispatch);
|
||||
|
||||
if (device->base.group)
|
||||
libinput_device_group_unref(device->base.group);
|
||||
|
||||
filter_destroy(device->pointer.filter);
|
||||
libinput_seat_unref(device->base.seat);
|
||||
libevdev_free(device->evdev);
|
||||
|
|
|
|||
|
|
@ -286,7 +286,7 @@ create_pointer_accelerator_filter(accel_profile_func_t profile)
|
|||
{
|
||||
struct pointer_accelerator *filter;
|
||||
|
||||
filter = malloc(sizeof *filter);
|
||||
filter = zalloc(sizeof *filter);
|
||||
if (filter == NULL)
|
||||
return NULL;
|
||||
|
||||
|
|
|
|||
|
|
@ -169,8 +169,14 @@ struct libinput_device_config {
|
|||
struct libinput_device_config_click_method *click_method;
|
||||
};
|
||||
|
||||
struct libinput_device_group {
|
||||
int refcount;
|
||||
void *user_data;
|
||||
};
|
||||
|
||||
struct libinput_device {
|
||||
struct libinput_seat *seat;
|
||||
struct libinput_device_group *group;
|
||||
struct list link;
|
||||
struct list event_listeners;
|
||||
void *user_data;
|
||||
|
|
@ -253,6 +259,13 @@ void
|
|||
libinput_device_init(struct libinput_device *device,
|
||||
struct libinput_seat *seat);
|
||||
|
||||
struct libinput_device_group *
|
||||
libinput_device_group_create(void);
|
||||
|
||||
void
|
||||
libinput_device_set_device_group(struct libinput_device *device,
|
||||
struct libinput_device_group *group);
|
||||
|
||||
void
|
||||
libinput_device_add_event_listener(struct libinput_device *device,
|
||||
struct libinput_event_listener *listener,
|
||||
|
|
|
|||
|
|
@ -715,7 +715,7 @@ libinput_add_fd(struct libinput *libinput,
|
|||
struct libinput_source *source;
|
||||
struct epoll_event ep;
|
||||
|
||||
source = malloc(sizeof *source);
|
||||
source = zalloc(sizeof *source);
|
||||
if (!source)
|
||||
return NULL;
|
||||
|
||||
|
|
@ -1603,6 +1603,12 @@ libinput_device_get_context(struct libinput_device *device)
|
|||
return libinput_seat_get_context(device->seat);
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT struct libinput_device_group *
|
||||
libinput_device_get_device_group(struct libinput_device *device)
|
||||
{
|
||||
return device->group;
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT const char *
|
||||
libinput_device_get_sysname(struct libinput_device *device)
|
||||
{
|
||||
|
|
@ -1713,6 +1719,64 @@ libinput_event_touch_get_base_event(struct libinput_event_touch *event)
|
|||
return &event->base;
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT struct libinput_device_group *
|
||||
libinput_device_group_ref(struct libinput_device_group *group)
|
||||
{
|
||||
group->refcount++;
|
||||
return group;
|
||||
}
|
||||
|
||||
struct libinput_device_group *
|
||||
libinput_device_group_create(void)
|
||||
{
|
||||
struct libinput_device_group *group;
|
||||
|
||||
group = zalloc(sizeof *group);
|
||||
if (group)
|
||||
group->refcount = 1;
|
||||
return group;
|
||||
}
|
||||
|
||||
void
|
||||
libinput_device_set_device_group(struct libinput_device *device,
|
||||
struct libinput_device_group *group)
|
||||
{
|
||||
device->group = group;
|
||||
libinput_device_group_ref(group);
|
||||
}
|
||||
|
||||
static void
|
||||
libinput_device_group_destroy(struct libinput_device_group *group)
|
||||
{
|
||||
free(group);
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT struct libinput_device_group *
|
||||
libinput_device_group_unref(struct libinput_device_group *group)
|
||||
{
|
||||
assert(group->refcount > 0);
|
||||
group->refcount--;
|
||||
if (group->refcount == 0) {
|
||||
libinput_device_group_destroy(group);
|
||||
return NULL;
|
||||
} else {
|
||||
return group;
|
||||
}
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT void
|
||||
libinput_device_group_set_user_data(struct libinput_device_group *group,
|
||||
void *user_data)
|
||||
{
|
||||
group->user_data = user_data;
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT void *
|
||||
libinput_device_group_get_user_data(struct libinput_device_group *group)
|
||||
{
|
||||
return group->user_data;
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT const char *
|
||||
libinput_config_status_to_str(enum libinput_config_status status)
|
||||
{
|
||||
|
|
@ -1860,7 +1924,8 @@ LIBINPUT_EXPORT enum libinput_config_status
|
|||
libinput_device_config_accel_set_speed(struct libinput_device *device,
|
||||
double speed)
|
||||
{
|
||||
if (speed < -1.0 || speed > 1.0)
|
||||
/* Need the negation in case speed is NaN */
|
||||
if (!(speed >= -1.0 && speed <= 1.0))
|
||||
return LIBINPUT_CONFIG_STATUS_INVALID;
|
||||
|
||||
if (!libinput_device_config_accel_is_available(device))
|
||||
|
|
|
|||
131
src/libinput.h
131
src/libinput.h
|
|
@ -255,6 +255,16 @@ struct libinput;
|
|||
*/
|
||||
struct libinput_device;
|
||||
|
||||
/**
|
||||
* @ingroup device
|
||||
* @struct libinput_device_group
|
||||
*
|
||||
* A base handle for accessing libinput device groups. This struct is
|
||||
* refcounted, use libinput_device_group_ref() and
|
||||
* libinput_device_group_unref().
|
||||
*/
|
||||
struct libinput_device_group;
|
||||
|
||||
/**
|
||||
* @ingroup seat
|
||||
* @struct libinput_seat
|
||||
|
|
@ -1686,7 +1696,7 @@ libinput_device_ref(struct libinput_device *device);
|
|||
* the device correctly to avoid dangling pointers.
|
||||
*
|
||||
* @param device A previously obtained device
|
||||
* @return NULL if device was destroyed, otherwise the passed device
|
||||
* @return NULL if the device was destroyed, otherwise the passed device
|
||||
*/
|
||||
struct libinput_device *
|
||||
libinput_device_unref(struct libinput_device *device);
|
||||
|
|
@ -1728,6 +1738,66 @@ libinput_device_get_user_data(struct libinput_device *device);
|
|||
struct libinput *
|
||||
libinput_device_get_context(struct libinput_device *device);
|
||||
|
||||
/**
|
||||
* @ingroup device
|
||||
*
|
||||
* Get the device group this device is assigned to. Some physical
|
||||
* devices like graphics tablets are represented by multiple kernel
|
||||
* devices and thus by multiple struct @ref libinput_device.
|
||||
*
|
||||
* libinput assigns these devices to the same @ref libinput_device_group
|
||||
* allowing the caller to identify such devices and adjust configuration
|
||||
* settings accordingly. For example, setting a tablet to left-handed often
|
||||
* means turning it upside down. A touch device on the same tablet would
|
||||
* need to be turned upside down too to work correctly.
|
||||
*
|
||||
* All devices are part of a device group though for most devices the group
|
||||
* will be a singleton. A device is assigned to a device group on @ref
|
||||
* LIBINPUT_EVENT_DEVICE_ADDED and removed from that group on @ref
|
||||
* LIBINPUT_EVENT_DEVICE_REMOVED. It is up to the caller to track how many
|
||||
* devices are in each device group.
|
||||
*
|
||||
* @dot
|
||||
* digraph groups_libinput {
|
||||
* rankdir="TB";
|
||||
* node [
|
||||
* shape="box";
|
||||
* ]
|
||||
*
|
||||
* mouse [ label="mouse"; URL="\ref libinput_device"];
|
||||
* kbd [ label="keyboard"; URL="\ref libinput_device"];
|
||||
*
|
||||
* pen [ label="tablet pen"; URL="\ref libinput_device"];
|
||||
* touch [ label="tablet touch"; URL="\ref libinput_device"];
|
||||
* pad [ label="tablet pad"; URL="\ref libinput_device"];
|
||||
*
|
||||
* group1 [ label="group 1"; URL="\ref libinput_device_group"];
|
||||
* group2 [ label="group 2"; URL="\ref libinput_device_group"];
|
||||
* group3 [ label="group 3"; URL="\ref libinput_device_group"];
|
||||
*
|
||||
* mouse -> group1
|
||||
* kbd -> group2
|
||||
*
|
||||
* pen -> group3;
|
||||
* touch -> group3;
|
||||
* pad -> group3;
|
||||
* }
|
||||
* @enddot
|
||||
*
|
||||
* Device groups do not get re-used once the last device in the group was
|
||||
* removed, i.e. unplugging and re-plugging a physical device with grouped
|
||||
* devices will return a different device group after every unplug.
|
||||
*
|
||||
* The returned device group is not refcounted and may become invalid after
|
||||
* the next call to libinput. Use libinput_device_group_ref() and
|
||||
* libinput_device_group_unref() to continue using the handle outside of the
|
||||
* immediate scope.
|
||||
*
|
||||
* @return The device group this device belongs to
|
||||
*/
|
||||
struct libinput_device_group *
|
||||
libinput_device_get_device_group(struct libinput_device *device);
|
||||
|
||||
/**
|
||||
* @ingroup device
|
||||
*
|
||||
|
|
@ -1837,6 +1907,8 @@ libinput_device_set_seat_logical_name(struct libinput_device *device,
|
|||
const char *name);
|
||||
|
||||
/**
|
||||
* @ingroup device
|
||||
*
|
||||
* Return a udev handle to the device that is this libinput device, if any.
|
||||
* The returned handle has a refcount of at least 1, the caller must call
|
||||
* udev_device_unref() once to release the associated resources.
|
||||
|
|
@ -1913,6 +1985,63 @@ libinput_device_get_size(struct libinput_device *device,
|
|||
int
|
||||
libinput_device_has_button(struct libinput_device *device, uint32_t code);
|
||||
|
||||
/**
|
||||
* @ingroup device
|
||||
*
|
||||
* Increase the refcount of the device group. A device group will be freed
|
||||
* whenever the refcount reaches 0. This may happen during dispatch if all
|
||||
* devices of this group were removed from the system. A caller must ensure
|
||||
* to reference the device group correctly to avoid dangling pointers.
|
||||
*
|
||||
* @param group A previously obtained device group
|
||||
* @return The passed device group
|
||||
*/
|
||||
struct libinput_device_group *
|
||||
libinput_device_group_ref(struct libinput_device_group *group);
|
||||
|
||||
/**
|
||||
* @ingroup device
|
||||
*
|
||||
* Decrease the refcount of the device group. A device group will be freed
|
||||
* whenever the refcount reaches 0. This may happen during dispatch if all
|
||||
* devices of this group were removed from the system. A caller must ensure
|
||||
* to reference the device group correctly to avoid dangling pointers.
|
||||
*
|
||||
* @param group A previously obtained device group
|
||||
* @return NULL if the device group was destroyed, otherwise the passed
|
||||
* device group
|
||||
*/
|
||||
struct libinput_device_group *
|
||||
libinput_device_group_unref(struct libinput_device_group *group);
|
||||
|
||||
/**
|
||||
* @ingroup device
|
||||
*
|
||||
* Set caller-specific data associated with this device group. libinput does
|
||||
* not manage, look at, or modify this data. The caller must ensure the
|
||||
* data is valid.
|
||||
*
|
||||
* @param group A previously obtained device group
|
||||
* @param user_data Caller-specific data pointer
|
||||
* @see libinput_device_group_get_user_data
|
||||
*/
|
||||
void
|
||||
libinput_device_group_set_user_data(struct libinput_device_group *group,
|
||||
void *user_data);
|
||||
|
||||
/**
|
||||
* @ingroup device
|
||||
*
|
||||
* Get the caller-specific data associated with this input device group, if
|
||||
* any.
|
||||
*
|
||||
* @param group A previously obtained group
|
||||
* @return Caller-specific data pointer or NULL if none was set
|
||||
* @see libinput_device_group_set_user_data
|
||||
*/
|
||||
void *
|
||||
libinput_device_group_get_user_data(struct libinput_device_group *group);
|
||||
|
||||
/**
|
||||
* @defgroup config Device configuration
|
||||
*
|
||||
|
|
|
|||
|
|
@ -147,3 +147,11 @@ global:
|
|||
libinput_tool_set_user_data;
|
||||
libinput_tool_unref;
|
||||
} LIBINPUT_0.8.0;
|
||||
|
||||
LIBINPUT_0.11.0 {
|
||||
libinput_device_get_device_group;
|
||||
libinput_device_group_get_user_data;
|
||||
libinput_device_group_ref;
|
||||
libinput_device_group_set_user_data;
|
||||
libinput_device_group_unref;
|
||||
} LIBINPUT_0.9.0;
|
||||
|
|
|
|||
26
src/path.c
26
src/path.c
|
|
@ -291,14 +291,34 @@ libinput_path_create_context(const struct libinput_interface *interface,
|
|||
}
|
||||
|
||||
static inline struct udev_device *
|
||||
udev_device_from_devnode(struct udev *udev, const char *devnode)
|
||||
udev_device_from_devnode(struct libinput *libinput,
|
||||
struct udev *udev,
|
||||
const char *devnode)
|
||||
{
|
||||
struct udev_device *dev;
|
||||
struct stat st;
|
||||
size_t count = 0;
|
||||
|
||||
if (stat(devnode, &st) < 0)
|
||||
return NULL;
|
||||
|
||||
return udev_device_new_from_devnum(udev, 'c', st.st_rdev);
|
||||
dev = udev_device_new_from_devnum(udev, 'c', st.st_rdev);
|
||||
|
||||
while (dev && !udev_device_get_is_initialized(dev)) {
|
||||
udev_device_unref(dev);
|
||||
msleep(10);
|
||||
dev = udev_device_new_from_devnum(udev, 'c', st.st_rdev);
|
||||
|
||||
count++;
|
||||
if (count > 10) {
|
||||
log_bug_libinput(libinput,
|
||||
"udev device never initialized (%s)\n",
|
||||
devnode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT struct libinput_device *
|
||||
|
|
@ -315,7 +335,7 @@ libinput_path_add_device(struct libinput *libinput,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
udev_device = udev_device_from_devnode(udev, path);
|
||||
udev_device = udev_device_from_devnode(libinput, udev, path);
|
||||
if (!udev_device) {
|
||||
log_bug_client(libinput, "Invalid path %s\n", path);
|
||||
return NULL;
|
||||
|
|
|
|||
|
|
@ -661,6 +661,54 @@ START_TEST(device_context)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(device_group_get)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput_device_group *group;
|
||||
|
||||
int userdata = 10;
|
||||
|
||||
group = libinput_device_get_device_group(dev->libinput_device);
|
||||
ck_assert_notnull(group);
|
||||
|
||||
libinput_device_group_ref(group);
|
||||
|
||||
libinput_device_group_set_user_data(group, &userdata);
|
||||
ck_assert_ptr_eq(&userdata,
|
||||
libinput_device_group_get_user_data(group));
|
||||
|
||||
libinput_device_group_unref(group);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(device_group_ref)
|
||||
{
|
||||
struct libinput *li = litest_create_context();
|
||||
struct litest_device *dev = litest_add_device(li,
|
||||
LITEST_MOUSE);
|
||||
struct libinput_device *device = dev->libinput_device;
|
||||
struct libinput_device_group *group;
|
||||
|
||||
group = libinput_device_get_device_group(device);
|
||||
ck_assert_notnull(group);
|
||||
libinput_device_group_ref(group);
|
||||
|
||||
libinput_device_ref(device);
|
||||
litest_drain_events(li);
|
||||
litest_delete_device(dev);
|
||||
litest_drain_events(li);
|
||||
|
||||
/* make sure the device is dead but the group is still around */
|
||||
ck_assert(libinput_device_unref(device) == NULL);
|
||||
|
||||
libinput_device_group_ref(group);
|
||||
ck_assert_notnull(libinput_device_group_unref(group));
|
||||
ck_assert(libinput_device_group_unref(group) == NULL);
|
||||
|
||||
libinput_unref(li);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
int main (int argc, char **argv)
|
||||
{
|
||||
litest_add("device:sendevents", device_sendevents_config, LITEST_ANY, LITEST_TOUCHPAD|LITEST_TABLET);
|
||||
|
|
@ -687,5 +735,8 @@ int main (int argc, char **argv)
|
|||
|
||||
litest_add("device:udev", device_get_udev_handle, LITEST_ANY, LITEST_ANY);
|
||||
|
||||
litest_add("device:group", device_group_get, LITEST_ANY, LITEST_ANY);
|
||||
litest_add_no_device("device:group", device_group_ref);
|
||||
|
||||
return litest_run(argc, argv);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -69,6 +69,8 @@ struct litest_test_device {
|
|||
*/
|
||||
struct input_absinfo *absinfo;
|
||||
struct litest_device_interface *interface;
|
||||
|
||||
const char *udev_rule;
|
||||
};
|
||||
|
||||
struct litest_device_interface {
|
||||
|
|
|
|||
|
|
@ -65,7 +65,6 @@ static struct input_id input_id = {
|
|||
.bustype = 0x11,
|
||||
.vendor = 0x2,
|
||||
.product = 0x7,
|
||||
.version = 0xfffa, /* Magic value, used to detect this test device */
|
||||
};
|
||||
|
||||
static int events[] = {
|
||||
|
|
@ -97,6 +96,16 @@ static struct input_absinfo absinfo[] = {
|
|||
{ .value = -1 }
|
||||
};
|
||||
|
||||
static const char udev_rule[] =
|
||||
"ACTION==\"remove\", GOTO=\"touchpad_end\"\n"
|
||||
"KERNEL!=\"event*\", GOTO=\"touchpad_end\"\n"
|
||||
"ENV{ID_INPUT_TOUCHPAD}==\"\", GOTO=\"touchpad_end\"\n"
|
||||
"\n"
|
||||
"ATTRS{name}==\"litest*X1C3rd*\",\\\n"
|
||||
" ENV{TOUCHPAD_HAS_TRACKPOINT_BUTTONS}=\"1\"\n"
|
||||
"\n"
|
||||
"LABEL=\"touchpad_end\"";
|
||||
|
||||
struct litest_test_device litest_synaptics_carbon3rd_device = {
|
||||
.type = LITEST_SYNAPTICS_TRACKPOINT_BUTTONS,
|
||||
.features = LITEST_TOUCHPAD | LITEST_CLICKPAD | LITEST_BUTTON,
|
||||
|
|
@ -104,8 +113,9 @@ struct litest_test_device litest_synaptics_carbon3rd_device = {
|
|||
.setup = litest_synaptics_carbon3rd_setup,
|
||||
.interface = &interface,
|
||||
|
||||
.name = "SynPS/2 Synaptics TouchPad",
|
||||
.name = "SynPS/2 Synaptics TouchPad X1C3rd",
|
||||
.id = &input_id,
|
||||
.events = events,
|
||||
.absinfo = absinfo,
|
||||
.udev_rule = udev_rule,
|
||||
};
|
||||
|
|
|
|||
109
test/litest.c
109
test/litest.c
|
|
@ -26,6 +26,7 @@
|
|||
|
||||
#include <assert.h>
|
||||
#include <check.h>
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <getopt.h>
|
||||
|
|
@ -44,6 +45,9 @@
|
|||
#include "litest-int.h"
|
||||
#include "libinput-util.h"
|
||||
|
||||
#define UDEV_RULES_D "/run/udev/rules.d"
|
||||
#define UDEV_RULE_PREFIX "99-litest-"
|
||||
|
||||
static int in_debugger = -1;
|
||||
static int verbose = 0;
|
||||
|
||||
|
|
@ -122,6 +126,55 @@ struct litest_test_device* devices[] = {
|
|||
|
||||
static struct list all_tests;
|
||||
|
||||
static void
|
||||
litest_reload_udev_rules(void)
|
||||
{
|
||||
system("udevadm control --reload-rules");
|
||||
}
|
||||
|
||||
static int
|
||||
litest_udev_rule_filter(const struct dirent *entry)
|
||||
{
|
||||
return strncmp(entry->d_name,
|
||||
UDEV_RULE_PREFIX,
|
||||
strlen(UDEV_RULE_PREFIX)) == 0;
|
||||
}
|
||||
|
||||
static void
|
||||
litest_drop_udev_rules(void)
|
||||
{
|
||||
int n;
|
||||
int rc;
|
||||
struct dirent **entries;
|
||||
char path[PATH_MAX];
|
||||
|
||||
n = scandir(UDEV_RULES_D,
|
||||
&entries,
|
||||
litest_udev_rule_filter,
|
||||
alphasort);
|
||||
if (n < 0)
|
||||
return;
|
||||
|
||||
while (n--) {
|
||||
rc = snprintf(path, sizeof(path),
|
||||
"%s/%s",
|
||||
UDEV_RULES_D,
|
||||
entries[n]->d_name);
|
||||
if (rc > 0 &&
|
||||
(size_t)rc == strlen(UDEV_RULES_D) +
|
||||
strlen(entries[n]->d_name) + 1)
|
||||
unlink(path);
|
||||
else
|
||||
fprintf(stderr,
|
||||
"Failed to delete %s. Remaining tests are unreliable\n",
|
||||
entries[n]->d_name);
|
||||
free(entries[n]);
|
||||
}
|
||||
free(entries);
|
||||
|
||||
litest_reload_udev_rules();
|
||||
}
|
||||
|
||||
static void
|
||||
litest_add_tcase_for_device(struct suite *suite,
|
||||
void *func,
|
||||
|
|
@ -142,6 +195,13 @@ litest_add_tcase_for_device(struct suite *suite,
|
|||
t->name = strdup(test_name);
|
||||
t->tc = tcase_create(test_name);
|
||||
list_insert(&suite->tests, &t->node);
|
||||
/* we can't guarantee that we clean up properly if a test fails, the
|
||||
udev rules used for a previous test may still be in place. Add an
|
||||
unchecked fixture to always clean up all rules before/after a
|
||||
test case completes */
|
||||
tcase_add_unchecked_fixture(t->tc,
|
||||
litest_drop_udev_rules,
|
||||
litest_drop_udev_rules);
|
||||
tcase_add_checked_fixture(t->tc, dev->setup,
|
||||
dev->teardown ? dev->teardown : litest_generic_device_teardown);
|
||||
tcase_add_test(t->tc, func);
|
||||
|
|
@ -472,6 +532,40 @@ merge_events(const int *orig, const int *override)
|
|||
return events;
|
||||
}
|
||||
|
||||
static char *
|
||||
litest_init_udev_rules(struct litest_test_device *dev)
|
||||
{
|
||||
int rc;
|
||||
FILE *f;
|
||||
char *path;
|
||||
|
||||
if (!dev->udev_rule)
|
||||
return 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 = asprintf(&path,
|
||||
"%s/%s%s.rules",
|
||||
UDEV_RULES_D,
|
||||
UDEV_RULE_PREFIX,
|
||||
dev->shortname);
|
||||
ck_assert_int_eq(rc,
|
||||
strlen(UDEV_RULES_D) +
|
||||
strlen(UDEV_RULE_PREFIX) +
|
||||
strlen(dev->shortname) + 7);
|
||||
f = fopen(path, "w");
|
||||
ck_assert_notnull(f);
|
||||
ck_assert_int_ge(fputs(dev->udev_rule, f), 0);
|
||||
fclose(f);
|
||||
|
||||
litest_reload_udev_rules();
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
static struct litest_device *
|
||||
litest_create(enum litest_device_type which,
|
||||
const char *name_override,
|
||||
|
|
@ -485,6 +579,7 @@ litest_create(enum litest_device_type which,
|
|||
const struct input_id *id;
|
||||
struct input_absinfo *abs;
|
||||
int *events;
|
||||
char *udev_file;
|
||||
|
||||
dev = devices;
|
||||
while (*dev) {
|
||||
|
|
@ -499,12 +594,17 @@ litest_create(enum litest_device_type which,
|
|||
d = zalloc(sizeof(*d));
|
||||
ck_assert(d != NULL);
|
||||
|
||||
udev_file = litest_init_udev_rules(*dev);
|
||||
|
||||
/* device has custom create method */
|
||||
if ((*dev)->create) {
|
||||
(*dev)->create(d);
|
||||
if (abs_override || events_override)
|
||||
if (abs_override || events_override) {
|
||||
if (udev_file)
|
||||
unlink(udev_file);
|
||||
ck_abort_msg("Custom create cannot"
|
||||
"be overridden");
|
||||
}
|
||||
|
||||
return d;
|
||||
}
|
||||
|
|
@ -519,6 +619,7 @@ litest_create(enum litest_device_type which,
|
|||
abs,
|
||||
events);
|
||||
d->interface = (*dev)->interface;
|
||||
d->udev_rule_file = udev_file;
|
||||
free(abs);
|
||||
free(events);
|
||||
|
||||
|
|
@ -637,6 +738,12 @@ litest_delete_device(struct litest_device *d)
|
|||
if (!d)
|
||||
return;
|
||||
|
||||
if (d->udev_rule_file) {
|
||||
unlink(d->udev_rule_file);
|
||||
free(d->udev_rule_file);
|
||||
d->udev_rule_file = NULL;
|
||||
}
|
||||
|
||||
libinput_device_unref(d->libinput_device);
|
||||
libinput_path_remove_device(d->libinput_device);
|
||||
if (d->owns_context)
|
||||
|
|
|
|||
|
|
@ -91,6 +91,8 @@ struct litest_device {
|
|||
bool skip_ev_syn;
|
||||
|
||||
void *private; /* device-specific data */
|
||||
|
||||
char *udev_rule_file;
|
||||
};
|
||||
|
||||
struct libinput *litest_create_context(void);
|
||||
|
|
|
|||
132
test/misc.c
132
test/misc.c
|
|
@ -145,30 +145,20 @@ END_TEST
|
|||
|
||||
START_TEST(event_conversion_pointer)
|
||||
{
|
||||
struct libevdev_uinput *uinput;
|
||||
struct libinput *li;
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
struct libinput_event *event;
|
||||
int motion = 0, button = 0;
|
||||
|
||||
uinput = create_simple_test_device("litest test device",
|
||||
EV_REL, REL_X,
|
||||
EV_REL, REL_Y,
|
||||
EV_KEY, BTN_LEFT,
|
||||
EV_KEY, BTN_MIDDLE,
|
||||
EV_KEY, BTN_LEFT,
|
||||
-1, -1);
|
||||
li = libinput_path_create_context(&simple_interface, NULL);
|
||||
libinput_path_add_device(li, libevdev_uinput_get_devnode(uinput));
|
||||
|
||||
/* Queue at least two relative motion events as the first one may
|
||||
* be absorbed by the pointer acceleration filter. */
|
||||
libevdev_uinput_write_event(uinput, EV_REL, REL_X, -1);
|
||||
libevdev_uinput_write_event(uinput, EV_REL, REL_Y, -1);
|
||||
libevdev_uinput_write_event(uinput, EV_SYN, SYN_REPORT, 0);
|
||||
libevdev_uinput_write_event(uinput, EV_REL, REL_X, -1);
|
||||
libevdev_uinput_write_event(uinput, EV_REL, REL_Y, -1);
|
||||
libevdev_uinput_write_event(uinput, EV_KEY, BTN_LEFT, 1);
|
||||
libevdev_uinput_write_event(uinput, EV_SYN, SYN_REPORT, 0);
|
||||
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_event(dev, EV_REL, REL_X, -1);
|
||||
litest_event(dev, EV_REL, REL_Y, -1);
|
||||
litest_event(dev, EV_KEY, BTN_LEFT, 1);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
|
||||
libinput_dispatch(li);
|
||||
|
||||
|
|
@ -196,9 +186,6 @@ START_TEST(event_conversion_pointer)
|
|||
libinput_event_destroy(event);
|
||||
}
|
||||
|
||||
libinput_unref(li);
|
||||
libevdev_uinput_destroy(uinput);
|
||||
|
||||
ck_assert_int_gt(motion, 0);
|
||||
ck_assert_int_gt(button, 0);
|
||||
}
|
||||
|
|
@ -206,29 +193,18 @@ END_TEST
|
|||
|
||||
START_TEST(event_conversion_pointer_abs)
|
||||
{
|
||||
struct libevdev_uinput *uinput;
|
||||
struct libinput *li;
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
struct libinput_event *event;
|
||||
int motion = 0, button = 0;
|
||||
|
||||
uinput = create_simple_test_device("litest test device",
|
||||
EV_ABS, ABS_X,
|
||||
EV_ABS, ABS_Y,
|
||||
EV_KEY, BTN_LEFT,
|
||||
EV_KEY, BTN_MIDDLE,
|
||||
EV_KEY, BTN_LEFT,
|
||||
-1, -1);
|
||||
li = libinput_path_create_context(&simple_interface, NULL);
|
||||
libinput_path_add_device(li, libevdev_uinput_get_devnode(uinput));
|
||||
libinput_dispatch(li);
|
||||
|
||||
libevdev_uinput_write_event(uinput, EV_ABS, ABS_X, 10);
|
||||
libevdev_uinput_write_event(uinput, EV_ABS, ABS_Y, 50);
|
||||
libevdev_uinput_write_event(uinput, EV_KEY, BTN_LEFT, 1);
|
||||
libevdev_uinput_write_event(uinput, EV_SYN, SYN_REPORT, 0);
|
||||
libevdev_uinput_write_event(uinput, EV_ABS, ABS_X, 30);
|
||||
libevdev_uinput_write_event(uinput, EV_ABS, ABS_Y, 30);
|
||||
libevdev_uinput_write_event(uinput, EV_SYN, SYN_REPORT, 0);
|
||||
litest_event(dev, EV_ABS, ABS_X, 10);
|
||||
litest_event(dev, EV_ABS, ABS_Y, 50);
|
||||
litest_event(dev, EV_KEY, BTN_LEFT, 1);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
litest_event(dev, EV_ABS, ABS_X, 30);
|
||||
litest_event(dev, EV_ABS, ABS_Y, 30);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
|
||||
libinput_dispatch(li);
|
||||
|
||||
|
|
@ -256,9 +232,6 @@ START_TEST(event_conversion_pointer_abs)
|
|||
libinput_event_destroy(event);
|
||||
}
|
||||
|
||||
libinput_unref(li);
|
||||
libevdev_uinput_destroy(uinput);
|
||||
|
||||
ck_assert_int_gt(motion, 0);
|
||||
ck_assert_int_gt(button, 0);
|
||||
}
|
||||
|
|
@ -266,23 +239,15 @@ END_TEST
|
|||
|
||||
START_TEST(event_conversion_key)
|
||||
{
|
||||
struct libevdev_uinput *uinput;
|
||||
struct libinput *li;
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
struct libinput_event *event;
|
||||
int key = 0;
|
||||
|
||||
uinput = create_simple_test_device("litest test device",
|
||||
EV_KEY, KEY_A,
|
||||
EV_KEY, KEY_B,
|
||||
-1, -1);
|
||||
li = libinput_path_create_context(&simple_interface, NULL);
|
||||
libinput_path_add_device(li, libevdev_uinput_get_devnode(uinput));
|
||||
libinput_dispatch(li);
|
||||
|
||||
libevdev_uinput_write_event(uinput, EV_KEY, KEY_A, 1);
|
||||
libevdev_uinput_write_event(uinput, EV_SYN, SYN_REPORT, 0);
|
||||
libevdev_uinput_write_event(uinput, EV_KEY, KEY_A, 0);
|
||||
libevdev_uinput_write_event(uinput, EV_SYN, SYN_REPORT, 0);
|
||||
litest_event(dev, EV_KEY, KEY_A, 1);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
litest_event(dev, EV_KEY, KEY_A, 0);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
|
||||
libinput_dispatch(li);
|
||||
|
||||
|
|
@ -306,42 +271,28 @@ START_TEST(event_conversion_key)
|
|||
libinput_event_destroy(event);
|
||||
}
|
||||
|
||||
libinput_unref(li);
|
||||
libevdev_uinput_destroy(uinput);
|
||||
|
||||
ck_assert_int_gt(key, 0);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(event_conversion_touch)
|
||||
{
|
||||
struct libevdev_uinput *uinput;
|
||||
struct libinput *li;
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
struct libinput_event *event;
|
||||
int touch = 0;
|
||||
|
||||
uinput = create_simple_test_device("litest test device",
|
||||
EV_KEY, BTN_TOUCH,
|
||||
EV_ABS, ABS_X,
|
||||
EV_ABS, ABS_Y,
|
||||
EV_ABS, ABS_MT_SLOT,
|
||||
EV_ABS, ABS_MT_TRACKING_ID,
|
||||
EV_ABS, ABS_MT_POSITION_X,
|
||||
EV_ABS, ABS_MT_POSITION_Y,
|
||||
-1, -1);
|
||||
li = libinput_path_create_context(&simple_interface, NULL);
|
||||
libinput_path_add_device(li, libevdev_uinput_get_devnode(uinput));
|
||||
libinput_dispatch(li);
|
||||
|
||||
libevdev_uinput_write_event(uinput, EV_KEY, BTN_TOOL_FINGER, 1);
|
||||
libevdev_uinput_write_event(uinput, EV_KEY, BTN_TOUCH, 1);
|
||||
libevdev_uinput_write_event(uinput, EV_ABS, ABS_X, 10);
|
||||
libevdev_uinput_write_event(uinput, EV_ABS, ABS_Y, 10);
|
||||
libevdev_uinput_write_event(uinput, EV_ABS, ABS_MT_SLOT, 0);
|
||||
libevdev_uinput_write_event(uinput, EV_ABS, ABS_MT_TRACKING_ID, 1);
|
||||
libevdev_uinput_write_event(uinput, EV_ABS, ABS_MT_POSITION_X, 10);
|
||||
libevdev_uinput_write_event(uinput, EV_ABS, ABS_MT_POSITION_Y, 10);
|
||||
libevdev_uinput_write_event(uinput, EV_SYN, SYN_REPORT, 0);
|
||||
litest_event(dev, EV_KEY, BTN_TOOL_FINGER, 1);
|
||||
litest_event(dev, EV_KEY, BTN_TOUCH, 1);
|
||||
litest_event(dev, EV_ABS, ABS_X, 10);
|
||||
litest_event(dev, EV_ABS, ABS_Y, 10);
|
||||
litest_event(dev, EV_ABS, ABS_MT_SLOT, 0);
|
||||
litest_event(dev, EV_ABS, ABS_MT_TRACKING_ID, 1);
|
||||
litest_event(dev, EV_ABS, ABS_MT_POSITION_X, 10);
|
||||
litest_event(dev, EV_ABS, ABS_MT_POSITION_Y, 10);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
|
||||
libinput_dispatch(li);
|
||||
|
||||
|
|
@ -366,9 +317,6 @@ START_TEST(event_conversion_touch)
|
|||
libinput_event_destroy(event);
|
||||
}
|
||||
|
||||
libinput_unref(li);
|
||||
libevdev_uinput_destroy(uinput);
|
||||
|
||||
ck_assert_int_gt(touch, 0);
|
||||
}
|
||||
END_TEST
|
||||
|
|
@ -639,11 +587,13 @@ END_TEST
|
|||
|
||||
int main (int argc, char **argv) {
|
||||
litest_add_no_device("events:conversion", event_conversion_device_notify);
|
||||
litest_add_no_device("events:conversion", event_conversion_pointer);
|
||||
litest_add_no_device("events:conversion", event_conversion_pointer_abs);
|
||||
litest_add_no_device("events:conversion", event_conversion_key);
|
||||
litest_add_no_device("events:conversion", event_conversion_touch);
|
||||
litest_add_for_device("events:conversion", event_conversion_pointer, LITEST_MOUSE);
|
||||
litest_add_for_device("events:conversion", event_conversion_pointer, LITEST_MOUSE);
|
||||
litest_add_for_device("events:conversion", event_conversion_pointer_abs, LITEST_XEN_VIRTUAL_POINTER);
|
||||
litest_add_for_device("events:conversion", event_conversion_key, LITEST_KEYBOARD);
|
||||
litest_add_for_device("events:conversion", event_conversion_touch, LITEST_WACOM_TOUCH);
|
||||
litest_add_no_device("bitfield_helpers", bitfield_helpers);
|
||||
|
||||
litest_add_no_device("context:refcount", context_ref_counting);
|
||||
litest_add_no_device("config:status string", config_status_string);
|
||||
|
||||
|
|
|
|||
|
|
@ -732,6 +732,86 @@ START_TEST(pointer_scroll_button)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(pointer_accel_defaults)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput_device *device = dev->libinput_device;
|
||||
enum libinput_config_status status;
|
||||
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);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
for (speed = -1.0; speed <= 1.0; speed += 0.2) {
|
||||
status = libinput_device_config_accel_set_speed(device,
|
||||
speed);
|
||||
ck_assert_int_eq(status,
|
||||
LIBINPUT_CONFIG_STATUS_SUCCESS);
|
||||
ck_assert(libinput_device_config_accel_get_speed(device) == speed);
|
||||
}
|
||||
|
||||
for (speed = 1.2; speed <= -2.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) == 1.0);
|
||||
}
|
||||
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(pointer_accel_invalid)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput_device *device = dev->libinput_device;
|
||||
enum libinput_config_status status;
|
||||
|
||||
ck_assert(libinput_device_config_accel_is_available(device));
|
||||
|
||||
status = libinput_device_config_accel_set_speed(device,
|
||||
NAN);
|
||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_INVALID);
|
||||
status = libinput_device_config_accel_set_speed(device,
|
||||
INFINITY);
|
||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_INVALID);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(pointer_accel_defaults_absolute)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput_device *device = dev->libinput_device;
|
||||
enum libinput_config_status status;
|
||||
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);
|
||||
|
||||
for (speed = -2.0; speed <= 2.0; speed += 0.2) {
|
||||
status = libinput_device_config_accel_set_speed(device,
|
||||
speed);
|
||||
if (speed >= -1.0 && speed <= 1.0)
|
||||
ck_assert_int_eq(status,
|
||||
LIBINPUT_CONFIG_STATUS_UNSUPPORTED);
|
||||
else
|
||||
ck_assert_int_eq(status,
|
||||
LIBINPUT_CONFIG_STATUS_INVALID);
|
||||
ck_assert(libinput_device_config_accel_get_speed(device) == 0.0);
|
||||
}
|
||||
}
|
||||
END_TEST
|
||||
|
||||
int main (int argc, char **argv) {
|
||||
|
||||
litest_add("pointer:motion", pointer_motion_relative, LITEST_RELATIVE, LITEST_ANY);
|
||||
|
|
@ -754,5 +834,9 @@ int main (int argc, char **argv) {
|
|||
litest_add("pointer:left-handed", pointer_left_handed_during_click, LITEST_RELATIVE|LITEST_BUTTON, LITEST_ANY);
|
||||
litest_add("pointer:left-handed", pointer_left_handed_during_click_multiple_buttons, LITEST_RELATIVE|LITEST_BUTTON, LITEST_ANY);
|
||||
|
||||
litest_add("pointer:accel", pointer_accel_defaults, LITEST_RELATIVE, LITEST_ANY);
|
||||
litest_add("pointer:accel", pointer_accel_invalid, LITEST_RELATIVE, LITEST_ANY);
|
||||
litest_add("pointer:accel", pointer_accel_defaults_absolute, LITEST_ABSOLUTE, LITEST_ANY);
|
||||
|
||||
return litest_run(argc, argv);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue