diff --git a/src/evdev.c b/src/evdev.c index 8cfcb332..5f3f3753 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -44,6 +44,7 @@ #include "libinput-private.h" #include "quirks.h" #include "util-input-event.h" +#include "util-udev.h" #if HAVE_LIBWACOM #include @@ -2256,6 +2257,7 @@ evdev_pre_configure_model_quirks(struct evdev_device *device) struct quirks *q; const struct quirk_tuples *t; char *prop; + bool is_virtual; /* Touchpad claims to have 4 slots but only ever sends 2 * https://bugs.freedesktop.org/show_bug.cgi?id=98100 */ @@ -2334,6 +2336,13 @@ evdev_pre_configure_model_quirks(struct evdev_device *device) } } + if (!quirks_get_bool(q, QUIRK_ATTR_IS_VIRTUAL, &is_virtual)) { + is_virtual = !getenv("LIBINPUT_RUNNING_TEST_SUITE") && + udev_device_is_virtual(device->udev_device); + } + if (is_virtual) + device->tags |= EVDEV_TAG_VIRTUAL; + quirks_unref(q); } diff --git a/src/quirks.c b/src/quirks.c index 69a7e31b..8f063d8b 100644 --- a/src/quirks.c +++ b/src/quirks.c @@ -292,6 +292,7 @@ quirk_get_name(enum quirk q) case QUIRK_ATTR_MSC_TIMESTAMP: return "AttrMscTimestamp"; case QUIRK_ATTR_EVENT_CODE: return "AttrEventCode"; case QUIRK_ATTR_INPUT_PROP: return "AttrInputProp"; + case QUIRK_ATTR_IS_VIRTUAL: return "AttrIsVirtual"; default: abort(); } @@ -878,6 +879,13 @@ parse_attr(struct quirks_context *ctx, p->value.tuples.ntuples = nprops; p->type = PT_TUPLES; + rc = true; + } else if (streq(key, quirk_get_name(QUIRK_ATTR_IS_VIRTUAL))) { + p->id = QUIRK_ATTR_IS_VIRTUAL; + if (!parse_boolean_property(value, &b)) + goto out; + p->type = PT_BOOL; + p->value.b = b; rc = true; } else { qlog_error(ctx, "Unknown key %s in %s\n", key, s->name); diff --git a/src/quirks.h b/src/quirks.h index d272ea25..24987c9c 100644 --- a/src/quirks.h +++ b/src/quirks.h @@ -111,6 +111,7 @@ enum quirk { QUIRK_ATTR_MSC_TIMESTAMP, QUIRK_ATTR_EVENT_CODE, QUIRK_ATTR_INPUT_PROP, + QUIRK_ATTR_IS_VIRTUAL, _QUIRK_LAST_ATTR_QUIRK_, /* Guard: do not modify */ }; diff --git a/src/util-udev.h b/src/util-udev.h new file mode 100644 index 00000000..789c73e6 --- /dev/null +++ b/src/util-udev.h @@ -0,0 +1,41 @@ +/* + * Copyright © 2025 Ryan Hendrickson + * + * 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. + */ + +#ifndef UTIL_UDEV_H +#define UTIL_UDEV_H + +#include "config.h" + +#include +#include "util-strings.h" + +static inline bool +udev_device_is_virtual(struct udev_device *udev_device) +{ + const char *path = udev_device_get_syspath(udev_device); + if (!path) + return false; + return strstartswith(path, "/sys/devices/virtual/input/"); +} + +#endif /* UTIL_UDEV_H */