mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2026-02-03 13:30:27 +01:00
Add support for LIBINPUT_IGNORE_DEVICE
The recommended way to have libinput ignore specific devices so far was to remove the ID_INPUT* properties from the device. That may also affect other pieces of the stack that need access to this device. For the niche case of a device that should only be ignored by libinput but otherwise be treated normally by the system, we now support the LIBINPUT_IGNORE_DEVICE property. If the property is set to "0", it's equivalent to being unset. This gets around some technical limitations in udev where unsetting a property is impossible via a hwdb entry. https://bugs.freedesktop.org/show_bug.cgi?id=102229 Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
This commit is contained in:
parent
dddcc1f959
commit
00272cfbb1
8 changed files with 196 additions and 0 deletions
|
|
@ -32,6 +32,10 @@ Example values are:
|
|||
devices with the same property value are grouped into the same device group,
|
||||
the value itself is irrelevant otherwise.
|
||||
</dd>
|
||||
<dt>LIBINPUT_IGNORE_DEVICE</dt>
|
||||
<dd>If set to anything other than "0", the device is ignored by libinput.
|
||||
See @ref ignoring_devices for more details.
|
||||
</dd>
|
||||
<dt>ID_SEAT</dt>
|
||||
<dd>Assigns the physical @ref seats "seat" for this device. See
|
||||
libinput_seat_get_physical_name(). Defaults to "seat0".</dd>
|
||||
|
|
@ -105,6 +109,29 @@ ACTION=="add|change", KERNEL=="event[0-9]*", ENV{ID_VENDOR_ID}=="012a", \
|
|||
ENV{ID_MODEL_ID}=="034b", ENV{ID_INPUT_TOUCHPAD}="", ENV{ID_INPUT_TABLET}="1"
|
||||
@endcode
|
||||
|
||||
|
||||
@section ignoring_devices Ignoring specific devices
|
||||
|
||||
If a device has the <b>LIBINPUT_IGNORE_DEVICE</b> udev property set to any
|
||||
value but "0", that device is not initialized by libinput. For a context
|
||||
created with libinput_udev_create_context(), the device is silently ignored
|
||||
and never shows up. If the device is added with libinput_path_add_device()
|
||||
to a context created with libinput_path_create_context(), adding the device
|
||||
will fail and return NULL (see that function's documentation for more
|
||||
information).
|
||||
|
||||
If the property value is exactly "0", then the property is considered unset
|
||||
and libinput initializes the device normally.
|
||||
|
||||
This property should be used for devices that are correctly detected as
|
||||
input devices (see @ref udev_device_type) but that should not be used by
|
||||
libinput. It is recommended that devices that should not be handled as input
|
||||
devices at all unset the <b>ID_INPUT</b> and related properties instead. The
|
||||
<b>LIBINPUT_IGNORE_DEVICE</b> property signals that only libinput should
|
||||
ignore this property but other parts of the stack (if any) should continue
|
||||
treating this device normally.
|
||||
|
||||
|
||||
@section model_specific_configuration Model-specific configuration
|
||||
|
||||
libinput reserves the property prefixes <b>LIBINPUT_MODEL_</b> and
|
||||
|
|
|
|||
|
|
@ -541,6 +541,7 @@ if get_option('tests')
|
|||
'test/litest-device-generic-singletouch.c',
|
||||
'test/litest-device-gpio-keys.c',
|
||||
'test/litest-device-huion-pentablet.c',
|
||||
'test/litest-device-ignored-mouse.c',
|
||||
'test/litest-device-keyboard.c',
|
||||
'test/litest-device-keyboard-all-codes.c',
|
||||
'test/litest-device-keyboard-razer-blackwidow.c',
|
||||
|
|
|
|||
16
src/evdev.c
16
src/evdev.c
|
|
@ -3083,6 +3083,17 @@ libevdev_log_func(const struct libevdev *evdev,
|
|||
log_msg_va(libinput, pri, fmt, args);
|
||||
}
|
||||
|
||||
static bool
|
||||
udev_device_should_be_ignored(struct udev_device *udev_device)
|
||||
{
|
||||
const char *value;
|
||||
|
||||
value = udev_device_get_property_value(udev_device,
|
||||
"LIBINPUT_IGNORE_DEVICE");
|
||||
|
||||
return value && !streq(value, "0");
|
||||
}
|
||||
|
||||
struct evdev_device *
|
||||
evdev_device_create(struct libinput_seat *seat,
|
||||
struct udev_device *udev_device)
|
||||
|
|
@ -3095,6 +3106,11 @@ evdev_device_create(struct libinput_seat *seat,
|
|||
const char *devnode = udev_device_get_devnode(udev_device);
|
||||
const char *sysname = udev_device_get_sysname(udev_device);
|
||||
|
||||
if (udev_device_should_be_ignored(udev_device)) {
|
||||
log_debug(libinput, "%s: device is ignored\n", sysname);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Use non-blocking mode so that we can loop on read on
|
||||
* evdev_device_data() until all events on the fd are
|
||||
* read. mtdev_get() also expects this. */
|
||||
|
|
|
|||
73
test/litest-device-ignored-mouse.c
Normal file
73
test/litest-device-ignored-mouse.c
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* Copyright © 2017 Red Hat, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "litest.h"
|
||||
#include "litest-int.h"
|
||||
|
||||
static void litest_mouse_setup(void)
|
||||
{
|
||||
struct litest_device *d = litest_create_device(LITEST_IGNORED_MOUSE);
|
||||
litest_set_current_device(d);
|
||||
}
|
||||
|
||||
static struct input_id input_id = {
|
||||
.bustype = 0x3,
|
||||
.vendor = 0x17ef,
|
||||
.product = 0x6019,
|
||||
};
|
||||
|
||||
static int events[] = {
|
||||
EV_KEY, BTN_LEFT,
|
||||
EV_KEY, BTN_RIGHT,
|
||||
EV_KEY, BTN_MIDDLE,
|
||||
EV_REL, REL_X,
|
||||
EV_REL, REL_Y,
|
||||
EV_REL, REL_WHEEL,
|
||||
-1 , -1,
|
||||
};
|
||||
|
||||
static const char udev_rule[] =
|
||||
"ACTION==\"remove\", GOTO=\"mouse_end\"\n"
|
||||
"KERNEL!=\"event*\", GOTO=\"mouse_end\"\n"
|
||||
"ENV{ID_INPUT_MOUSE}==\"\", GOTO=\"mouse_end\"\n"
|
||||
"\n"
|
||||
"ATTRS{name}==\"litest Ignored Mouse*\",\\\n"
|
||||
" ENV{LIBINPUT_IGNORE_DEVICE}=\"1\"\n"
|
||||
"\n"
|
||||
"LABEL=\"mouse_end\"";
|
||||
|
||||
struct litest_test_device litest_ignored_mouse_device = {
|
||||
.type = LITEST_IGNORED_MOUSE,
|
||||
.features = LITEST_IGNORED | LITEST_BUTTON | LITEST_RELATIVE,
|
||||
.shortname = "ignored-mouse",
|
||||
.setup = litest_mouse_setup,
|
||||
.interface = NULL,
|
||||
|
||||
.name = "Ignored Mouse",
|
||||
.id = &input_id,
|
||||
.absinfo = NULL,
|
||||
.events = events,
|
||||
.udev_rule = udev_rule,
|
||||
};
|
||||
|
|
@ -415,6 +415,7 @@ extern struct litest_test_device litest_lid_switch_device;
|
|||
extern struct litest_test_device litest_lid_switch_surface3_device;
|
||||
extern struct litest_test_device litest_appletouch_device;
|
||||
extern struct litest_test_device litest_gpio_keys_device;
|
||||
extern struct litest_test_device litest_ignored_mouse_device;
|
||||
|
||||
struct litest_test_device* devices[] = {
|
||||
&litest_synaptics_clickpad_device,
|
||||
|
|
@ -481,6 +482,7 @@ struct litest_test_device* devices[] = {
|
|||
&litest_lid_switch_surface3_device,
|
||||
&litest_appletouch_device,
|
||||
&litest_gpio_keys_device,
|
||||
&litest_ignored_mouse_device,
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
|
@ -610,6 +612,9 @@ litest_add_tcase(const char *suite_name,
|
|||
added = true;
|
||||
} else if (required != LITEST_ANY || excluded != LITEST_ANY) {
|
||||
for (; *dev; dev++) {
|
||||
if ((*dev)->features & LITEST_IGNORED)
|
||||
continue;
|
||||
|
||||
if (filter_device &&
|
||||
fnmatch(filter_device, (*dev)->shortname, 0) != 0)
|
||||
continue;
|
||||
|
|
@ -626,6 +631,9 @@ litest_add_tcase(const char *suite_name,
|
|||
}
|
||||
} else {
|
||||
for (; *dev; dev++) {
|
||||
if ((*dev)->features & LITEST_IGNORED)
|
||||
continue;
|
||||
|
||||
if (filter_device &&
|
||||
fnmatch(filter_device, (*dev)->shortname, 0) != 0)
|
||||
continue;
|
||||
|
|
|
|||
|
|
@ -235,6 +235,7 @@ enum litest_device_type {
|
|||
LITEST_LID_SWITCH_SURFACE3,
|
||||
LITEST_APPLETOUCH,
|
||||
LITEST_GPIO_KEYS,
|
||||
LITEST_IGNORED_MOUSE,
|
||||
};
|
||||
|
||||
enum litest_device_feature {
|
||||
|
|
@ -267,6 +268,7 @@ enum litest_device_feature {
|
|||
LITEST_TRACKBALL = 1 << 24,
|
||||
LITEST_LEDS = 1 << 25,
|
||||
LITEST_SWITCH = 1 << 26,
|
||||
LITEST_IGNORED = 1 << 27,
|
||||
};
|
||||
|
||||
/* this is a semi-mt device, so we keep track of the touches that the tests
|
||||
|
|
|
|||
|
|
@ -961,6 +961,26 @@ START_TEST(path_udev_assign_seat)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(path_ignore_device)
|
||||
{
|
||||
struct litest_device *dev;
|
||||
struct libinput *li;
|
||||
struct libinput_device *device;
|
||||
const char *path;
|
||||
|
||||
dev = litest_create(LITEST_IGNORED_MOUSE, NULL, NULL, NULL, NULL);
|
||||
path = libevdev_uinput_get_devnode(dev->uinput);
|
||||
ck_assert_notnull(path);
|
||||
|
||||
li = litest_create_context();
|
||||
device = libinput_path_add_device(li, path);
|
||||
ck_assert(device == NULL);
|
||||
|
||||
libinput_unref(li);
|
||||
litest_delete_device(dev);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
void
|
||||
litest_setup_tests_path(void)
|
||||
{
|
||||
|
|
@ -987,4 +1007,6 @@ litest_setup_tests_path(void)
|
|||
litest_add_for_device("path:device events", path_double_remove_device, LITEST_SYNAPTICS_CLICKPAD_X220);
|
||||
litest_add_no_device("path:seat", path_seat_recycle);
|
||||
litest_add_for_device("path:udev", path_udev_assign_seat, LITEST_SYNAPTICS_CLICKPAD_X220);
|
||||
|
||||
litest_add_no_device("path:ignore", path_ignore_device);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -560,6 +560,51 @@ START_TEST(udev_path_remove_device)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(udev_ignore_device)
|
||||
{
|
||||
struct udev *udev;
|
||||
struct libinput *li;
|
||||
struct libinput_device *device;
|
||||
struct libinput_event *event;
|
||||
struct litest_device *dev;
|
||||
const char *devname;
|
||||
|
||||
dev = litest_create(LITEST_IGNORED_MOUSE, NULL, NULL, NULL, NULL);
|
||||
devname = libevdev_get_name(dev->evdev);
|
||||
|
||||
udev = udev_new();
|
||||
ck_assert(udev != NULL);
|
||||
|
||||
li = libinput_udev_create_context(&simple_interface, NULL, udev);
|
||||
ck_assert(li != NULL);
|
||||
litest_restore_log_handler(li);
|
||||
|
||||
ck_assert_int_eq(libinput_udev_assign_seat(li, "seat0"), 0);
|
||||
libinput_dispatch(li);
|
||||
|
||||
event = libinput_get_event(li);
|
||||
ck_assert(event != NULL);
|
||||
while (event) {
|
||||
if (libinput_event_get_type(event) ==
|
||||
LIBINPUT_EVENT_DEVICE_ADDED) {
|
||||
const char *name;
|
||||
|
||||
device = libinput_event_get_device(event);
|
||||
name = libinput_device_get_name(device);
|
||||
ck_assert_str_ne(devname, name);
|
||||
}
|
||||
libinput_event_destroy(event);
|
||||
libinput_dispatch(li);
|
||||
event = libinput_get_event(li);
|
||||
}
|
||||
|
||||
libinput_unref(li);
|
||||
udev_unref(udev);
|
||||
|
||||
litest_delete_device(dev);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
void
|
||||
litest_setup_tests_udev(void)
|
||||
{
|
||||
|
|
@ -579,4 +624,6 @@ litest_setup_tests_udev(void)
|
|||
|
||||
litest_add_no_device("udev:path", udev_path_add_device);
|
||||
litest_add_for_device("udev:path", udev_path_remove_device, LITEST_SYNAPTICS_CLICKPAD_X220);
|
||||
|
||||
litest_add_no_device("udev:ignore", udev_ignore_device);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue