diff --git a/doc/device-configuration-via-udev.dox b/doc/device-configuration-via-udev.dox index e38b93f6..85c5c9c9 100644 --- a/doc/device-configuration-via-udev.dox +++ b/doc/device-configuration-via-udev.dox @@ -67,6 +67,10 @@ to normalize them.
This prefix is reserved as private API, do not use.. See @ref model_specific_configuration for details.
+
LIBINPUT_ATTR_*
+
This prefix is reserved as private API, do not use.. See @ref +model_specific_configuration for details. +
Below is an example udev rule to assign "seat1" to a device from vendor @@ -103,13 +107,13 @@ ENV{ID_MODEL_ID}=="034b", ENV{ID_INPUT_TOUCHPAD}="", ENV{ID_INPUT_TABLET}="1" @section model_specific_configuration Model-specific configuration -libinput reserves the property prefix LIBINPUT_MODEL_ for -model-specific configuration. This prefix is reserved as private API, do -not use. +libinput reserves the property prefixes LIBINPUT_MODEL_ and +LIBINPUT_ATTR_* for model-specific configuration. These prefixes +are reserved as private API, do not use. -The effect of this property may be to enable or disable certain +The effect of these properties may be to enable or disable certain features on a specific device or set of devices, to change configuration -defaults or any other reason. The effects of setting this property, the +defaults or any other reason. The effects of setting these properties, the format of the property and the value of the property are subject to change at any time. diff --git a/src/evdev.c b/src/evdev.c index 29bed728..3d19ee73 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -1551,6 +1551,23 @@ evdev_read_model(struct evdev_device *device) return m->model; } +static inline int +evdev_read_attr_size_prop(struct evdev_device *device, + size_t *size_x, + size_t *size_y) +{ + struct udev_device *udev; + const char *size_prop; + + udev = device->udev_device; + size_prop = udev_device_get_property_value(udev, + "LIBINPUT_ATTR_SIZE_HINT"); + if (!size_prop) + return false; + + return parse_dimension_property(size_prop, size_x, size_y); +} + /* Return 1 if the device is set to the fake resolution or 0 otherwise */ static inline int evdev_fix_abs_resolution(struct evdev_device *device, @@ -1559,6 +1576,8 @@ evdev_fix_abs_resolution(struct evdev_device *device, { struct libinput *libinput = device->base.seat->libinput; struct libevdev *evdev = device->evdev; + const struct input_absinfo *absx, *absy; + size_t widthmm = 0, heightmm = 0; int xres = EVDEV_FAKE_RESOLUTION, yres = EVDEV_FAKE_RESOLUTION; @@ -1570,15 +1589,28 @@ evdev_fix_abs_resolution(struct evdev_device *device, return 0; } - if (libevdev_get_abs_resolution(evdev, xcode) != 0) + absx = libevdev_get_abs_info(evdev, xcode); + absy = libevdev_get_abs_info(evdev, ycode); + + if (absx->resolution != 0 || absy->resolution != 0) return 0; + /* Note: we *do not* override resolutions if provided by the kernel. + * If a device needs this, add it to 60-evdev.hwdb. The libinput + * property is only for general size hints where we can make + * educated guesses but don't know better. + */ + if (evdev_read_attr_size_prop(device, &widthmm, &heightmm)) { + xres = (absx->maximum - absx->minimum)/widthmm; + yres = (absy->maximum - absy->minimum)/heightmm; + } + /* libevdev_set_abs_resolution() changes the absinfo we already have a pointer to, no need to fetch it again */ libevdev_set_abs_resolution(evdev, xcode, xres); libevdev_set_abs_resolution(evdev, ycode, yres); - return 1; + return xres == EVDEV_FAKE_RESOLUTION; } static enum evdev_device_udev_tags