summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configure.ac2
-rw-r--r--src/libinput-device.c87
2 files changed, 88 insertions, 1 deletions
diff --git a/configure.ac b/configure.ac
index 2a60ff8c..7506ecdb 100644
--- a/configure.ac
+++ b/configure.ac
@@ -160,7 +160,7 @@ AC_ARG_ENABLE(libinput-backend, [ --disable-libinput-backend],,
AM_CONDITIONAL([ENABLE_LIBINPUT_BACKEND], [test x$enable_libinput_backend = xyes])
if test x$enable_libinput_backend = xyes; then
AC_DEFINE([BUILD_LIBINPUT_BACKEND], [1], [Build the libinput input device backend])
- PKG_CHECK_MODULES(LIBINPUT_BACKEND, [libinput >= 0.5.0])
+ PKG_CHECK_MODULES(LIBINPUT_BACKEND, [libinput >= 0.6.0])
fi
diff --git a/src/libinput-device.c b/src/libinput-device.c
index 6e50eebb..76438995 100644
--- a/src/libinput-device.c
+++ b/src/libinput-device.c
@@ -282,6 +282,90 @@ notify_output_destroy(struct wl_listener *listener, void *data)
}
}
+/**
+ * The WL_CALIBRATION property requires a pixel-specific matrix to be
+ * applied after scaling device coordinates to screen coordinates. libinput
+ * can't do that, so we need to convert the calibration to the normalized
+ * format libinput expects.
+ */
+static void
+evdev_device_set_calibration(struct evdev_device *device)
+{
+ struct udev *udev;
+ struct udev_device *udev_device = NULL;
+ const char *sysname = libinput_device_get_sysname(device->device);
+ const char *calibration_values;
+ uint32_t width, height;
+ float calibration[6];
+ enum libinput_config_status status;
+
+ if (!device->output)
+ return;
+
+ width = device->output->width;
+ height = device->output->height;
+ if (width == 0 || height == 0)
+ return;
+
+ /* If libinput has a pre-set calibration matrix, don't override it */
+ if (!libinput_device_config_calibration_has_matrix(device->device) ||
+ libinput_device_config_calibration_get_default_matrix(
+ device->device,
+ calibration) != 0)
+ return;
+
+ udev = udev_new();
+ if (!udev)
+ return;
+
+ udev_device = udev_device_new_from_subsystem_sysname(udev,
+ "input",
+ sysname);
+ if (!udev_device)
+ goto out;
+
+ calibration_values =
+ udev_device_get_property_value(udev_device,
+ "WL_CALIBRATION");
+
+ if (!calibration_values || sscanf(calibration_values,
+ "%f %f %f %f %f %f",
+ &calibration[0],
+ &calibration[1],
+ &calibration[2],
+ &calibration[3],
+ &calibration[4],
+ &calibration[5]) != 6)
+ goto out;
+
+ weston_log("Applying calibration: %f %f %f %f %f %f "
+ "(normalized %f %f)\n",
+ calibration[0],
+ calibration[1],
+ calibration[2],
+ calibration[3],
+ calibration[4],
+ calibration[5],
+ calibration[2] / width,
+ calibration[5] / height);
+
+ /* normalize to a format libinput can use. There is a chance of
+ this being wrong if the width/height don't match the device
+ width/height but I'm not sure how to fix that */
+ calibration[2] /= width;
+ calibration[5] /= height;
+
+ status = libinput_device_config_calibration_set_matrix(device->device,
+ calibration);
+ if (status != LIBINPUT_CONFIG_STATUS_SUCCESS)
+ weston_log("Failed to apply calibration.\n");
+
+out:
+ if (udev_device)
+ udev_device_unref(udev_device);
+ udev_unref(udev);
+}
+
void
evdev_device_set_output(struct evdev_device *device,
struct weston_output *output)
@@ -295,6 +379,7 @@ evdev_device_set_output(struct evdev_device *device,
device->output_destroy_listener.notify = notify_output_destroy;
wl_signal_add(&output->destroy_signal,
&device->output_destroy_listener);
+ evdev_device_set_calibration(device);
}
static void
@@ -318,6 +403,8 @@ configure_device(struct evdev_device *device)
libinput_device_config_tap_set_enabled(device->device,
enable_tap);
}
+
+ evdev_device_set_calibration(device);
}
struct evdev_device *