Change calibration into a configuration option
authorPeter Hutterer <peter.hutterer@who-t.net>
Tue, 26 Aug 2014 01:41:19 +0000 (11:41 +1000)
committerPeter Hutterer <peter.hutterer@who-t.net>
Mon, 1 Sep 2014 01:23:54 +0000 (11:23 +1000)
New configuration API:
libinput_device_config_calibration_has_matrix()
libinput_device_config_calibration_set_matrix()
libinput_device_config_calibration_get_matrix()
libinput_device_config_calibration_get_default_matrix()

Deprecates libinput_device_calibrate().

For coordinate transformation, we're using a precalculated matrix. Thus, to
support ..._get_matrix() we need to store the original user-specified matrix
separately, in an unmangled state.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
src/evdev.c
src/evdev.h
src/libinput-private.h
src/libinput.c
src/libinput.h
test/pointer.c
test/touch.c

index 4cd3cfa..0059444 100644 (file)
@@ -578,19 +578,70 @@ fallback_destroy(struct evdev_dispatch *dispatch)
        free(dispatch);
 }
 
+static int
+evdev_calibration_has_matrix(struct libinput_device *libinput_device)
+{
+       struct evdev_device *device = (struct evdev_device*)libinput_device;
+
+       return device->abs.absinfo_x && device->abs.absinfo_y;
+}
+
+static enum libinput_config_status
+evdev_calibration_set_matrix(struct libinput_device *libinput_device,
+                            const float matrix[6])
+{
+       struct evdev_device *device = (struct evdev_device*)libinput_device;
+
+       evdev_device_calibrate(device, matrix);
+
+       return LIBINPUT_CONFIG_STATUS_SUCCESS;
+}
+
+static int
+evdev_calibration_get_matrix(struct libinput_device *libinput_device,
+                            float matrix[6])
+{
+       struct evdev_device *device = (struct evdev_device*)libinput_device;
+
+       matrix_to_farray6(&device->abs.usermatrix, matrix);
+
+       return !matrix_is_identity(&device->abs.usermatrix);
+}
+
+static int
+evdev_calibration_get_default_matrix(struct libinput_device *libinput_device,
+                                    float matrix[6])
+{
+       struct matrix m;
+
+       /* Always return the identity matrix for now. In the future, this
+          should return the WL_CALIBRATION matrix defined as default
+          matrix for this device */
+       matrix_init_identity(&m);
+       matrix_to_farray6(&m, matrix);
+
+       return !matrix_is_identity(&m);
+}
+
 struct evdev_dispatch_interface fallback_interface = {
        fallback_process,
        fallback_destroy
 };
 
 static struct evdev_dispatch *
-fallback_dispatch_create(void)
+fallback_dispatch_create(struct libinput_device *device)
 {
        struct evdev_dispatch *dispatch = malloc(sizeof *dispatch);
        if (dispatch == NULL)
                return NULL;
 
        dispatch->interface = &fallback_interface;
+       device->config.calibration = &dispatch->calibration;
+
+       dispatch->calibration.has_matrix = evdev_calibration_has_matrix;
+       dispatch->calibration.set_matrix = evdev_calibration_set_matrix;
+       dispatch->calibration.get_matrix = evdev_calibration_get_matrix;
+       dispatch->calibration.get_default_matrix = evdev_calibration_get_default_matrix;
 
        return dispatch;
 }
@@ -904,6 +955,7 @@ evdev_device_create(struct libinput_seat *seat,
        device->devname = libevdev_get_name(device->evdev);
 
        matrix_init_identity(&device->abs.calibration);
+       matrix_init_identity(&device->abs.usermatrix);
 
        if (evdev_configure_device(device) == -1)
                goto err;
@@ -915,7 +967,7 @@ evdev_device_create(struct libinput_seat *seat,
 
        /* If the dispatch was not set up use the fallback. */
        if (device->dispatch == NULL)
-               device->dispatch = fallback_dispatch_create();
+               device->dispatch = fallback_dispatch_create(&device->base);
        if (device->dispatch == NULL)
                goto err;
 
@@ -1014,6 +1066,9 @@ evdev_device_calibrate(struct evdev_device *device,
         * order.
         */
 
+       /* back up the user matrix so we can return it on request */
+       matrix_from_farray6(&device->abs.usermatrix, calibration);
+
        /* Un-Normalize */
        matrix_init_translate(&translate,
                              device->abs.absinfo_x->minimum,
index 9196bd2..110ea74 100644 (file)
@@ -74,6 +74,7 @@ struct evdev_device {
 
                int apply_calibration;
                struct matrix calibration;
+               struct matrix usermatrix; /* as supplied by the caller */
        } abs;
 
        struct {
@@ -121,6 +122,7 @@ struct evdev_dispatch_interface {
 
 struct evdev_dispatch {
        struct evdev_dispatch_interface *interface;
+       struct libinput_device_config_calibration calibration;
 };
 
 struct evdev_device *
index 94a3e07..9e084dd 100644 (file)
@@ -89,8 +89,19 @@ struct libinput_device_config_tap {
        enum libinput_config_tap_state (*get_default)(struct libinput_device *device);
 };
 
+struct libinput_device_config_calibration {
+       int (*has_matrix)(struct libinput_device *device);
+       enum libinput_config_status (*set_matrix)(struct libinput_device *device,
+                                                 const float matrix[6]);
+       int (*get_matrix)(struct libinput_device *device,
+                         float matrix[6]);
+       int (*get_default_matrix)(struct libinput_device *device,
+                                                         float matrix[6]);
+};
+
 struct libinput_device_config {
        struct libinput_device_config_tap *tap;
+       struct libinput_device_config_calibration *calibration;
 };
 
 struct libinput_device {
index ed5eba1..20aa1cb 100644 (file)
@@ -1312,3 +1312,40 @@ libinput_device_config_tap_get_default_enabled(struct libinput_device *device)
 
        return device->config.tap->get_default(device);
 }
+
+LIBINPUT_EXPORT int
+libinput_device_config_calibration_has_matrix(struct libinput_device *device)
+{
+       return device->config.calibration ?
+               device->config.calibration->has_matrix(device) : 0;
+}
+
+LIBINPUT_EXPORT enum libinput_config_status
+libinput_device_config_calibration_set_matrix(struct libinput_device *device,
+                                             const float matrix[6])
+{
+       if (!libinput_device_config_calibration_has_matrix(device))
+               return LIBINPUT_CONFIG_STATUS_UNSUPPORTED;
+
+       return device->config.calibration->set_matrix(device, matrix);
+}
+
+LIBINPUT_EXPORT int
+libinput_device_config_calibration_get_matrix(struct libinput_device *device,
+                                             float matrix[6])
+{
+       if (!libinput_device_config_calibration_has_matrix(device))
+               return 0;
+
+       return device->config.calibration->get_matrix(device, matrix);
+}
+
+LIBINPUT_EXPORT int
+libinput_device_config_calibration_get_default_matrix(struct libinput_device *device,
+                                                     float matrix[6])
+{
+       if (!libinput_device_config_calibration_has_matrix(device))
+               return 0;
+
+       return device->config.calibration->get_default_matrix(device, matrix);
+}
index 82970e2..5af0dde 100644 (file)
@@ -1365,45 +1365,12 @@ libinput_device_get_keys(struct libinput_device *device,
 /**
  * @ingroup device
  *
- * Apply the 3x3 transformation matrix to absolute device coordinates. This
- * matrix has no effect on relative events.
- *
- * Given a 6-element array [a, b, c, d, e, f], the matrix is applied as
- * @code
- * [ a  b  c ]   [ x ]
- * [ d  e  f ] * [ y ]
- * [ 0  0  1 ]   [ 1 ]
- * @endcode
- *
- * The translation component (c, f) is expected to be normalized to the
- * device coordinate range. For example, the matrix
- * @code
- * [ 1 0  1 ]
- * [ 0 1 -1 ]
- * [ 0 0  1 ]
- * @endcode
- * moves all coordinates by 1 device-width to the right and 1 device-height
- * up.
- *
- * The rotation matrix for rotation around the origin is defined as
- * @code
- * [ cos(a) -sin(a) 0 ]
- * [ sin(a)  cos(a) 0 ]
- * [   0      0     1 ]
- * @endcode
- * Note that any rotation requires an additional translation component to
- * translate the rotated coordinates back into the original device space.
- * The rotation matrixes for 90, 180 and 270 degrees clockwise are:
- * @code
- * 90 deg cw:          180 deg cw:             270 deg cw:
- * [ 0 -1 1]           [ -1  0 1]              [  0 1 0 ]
- * [ 1  0 0]           [  0 -1 1]              [ -1 0 1 ]
- * [ 0  0 1]           [  0  0 1]              [  0 0 1 ]
- * @endcode
+ * @deprecated Use libinput_device_config_calibration_set_matrix() instead.
  */
 void
 libinput_device_calibrate(struct libinput_device *device,
-                         float calibration[6]);
+                         float calibration[6])
+       LIBINPUT_ATTRIBUTE_DEPRECATED;
 
 /**
  * @ingroup device
@@ -1559,6 +1526,114 @@ libinput_device_config_tap_get_enabled(struct libinput_device *device);
 enum libinput_config_tap_state
 libinput_device_config_tap_get_default_enabled(struct libinput_device *device);
 
+/**
+ * @ingroup config
+ *
+ * Check if the device can be calibrated via a calibration matrix.
+ *
+ * @param device The device to check
+ * @return non-zero if the device can be calibrated, zero otherwise.
+ *
+ * @see libinput_device_config_calibration_set_matrix
+ * @see libinput_device_config_calibration_get_matrix
+ * @see libinput_device_config_calibration_get_default_matrix
+ */
+int
+libinput_device_config_calibration_has_matrix(struct libinput_device *device);
+
+/**
+ * @ingroup config
+ *
+ * Apply the 3x3 transformation matrix to absolute device coordinates. This
+ * matrix has no effect on relative events.
+ *
+ * Given a 6-element array [a, b, c, d, e, f], the matrix is applied as
+ * @code
+ * [ a  b  c ]   [ x ]
+ * [ d  e  f ] * [ y ]
+ * [ 0  0  1 ]   [ 1 ]
+ * @endcode
+ *
+ * The translation component (c, f) is expected to be normalized to the
+ * device coordinate range. For example, the matrix
+ * @code
+ * [ 1 0  1 ]
+ * [ 0 1 -1 ]
+ * [ 0 0  1 ]
+ * @endcode
+ * moves all coordinates by 1 device-width to the right and 1 device-height
+ * up.
+ *
+ * The rotation matrix for rotation around the origin is defined as
+ * @code
+ * [ cos(a) -sin(a) 0 ]
+ * [ sin(a)  cos(a) 0 ]
+ * [   0      0     1 ]
+ * @endcode
+ * Note that any rotation requires an additional translation component to
+ * translate the rotated coordinates back into the original device space.
+ * The rotation matrixes for 90, 180 and 270 degrees clockwise are:
+ * @code
+ * 90 deg cw:          180 deg cw:             270 deg cw:
+ * [ 0 -1 1]           [ -1  0 1]              [  0 1 0 ]
+ * [ 1  0 0]           [  0 -1 1]              [ -1 0 1 ]
+ * [ 0  0 1]           [  0  0 1]              [  0 0 1 ]
+ * @endcode
+ *
+ * @param device The device to configure
+ * @param matrix An array representing the first two rows of a 3x3 matrix as
+ * described above.
+ *
+ * @return A config status code.
+ *
+ * @see libinput_device_config_calibration_has_matrix
+ * @see libinput_device_config_calibration_get_matrix
+ * @see libinput_device_config_calibration_get_default_matrix
+ */
+enum libinput_config_status
+libinput_device_config_calibration_set_matrix(struct libinput_device *device,
+                                             const float matrix[6]);
+
+/**
+ * @ingroup config
+ *
+ * Return the current calibration matrix for this device.
+ *
+ * @param device The device to configure
+ * @param matrix Set to the array representing the first two rows of a 3x3 matrix as
+ * described in libinput_device_config_calibration_set_matrix().
+ *
+ * @return 0 if no calibration is set and the returned matrix is the
+ * identity matrix, 1 otherwise
+ *
+ * @see libinput_device_config_calibration_has_matrix
+ * @see libinput_device_config_calibration_set_matrix
+ * @see libinput_device_config_calibration_get_default_matrix
+ */
+int
+libinput_device_config_calibration_get_matrix(struct libinput_device *device,
+                                             float matrix[6]);
+
+/**
+ * @ingroup config
+ *
+ * Return the default calibration matrix for this device.
+ *
+ * @param device The device to configure
+ * @param matrix Set to the array representing the first two rows of a 3x3 matrix as
+ * described in libinput_device_config_calibration_set_matrix().
+ *
+ * @return 0 if no calibration is set and the returned matrix is the
+ * identity matrix, 1 otherwise
+ *
+ * @see libinput_device_config_calibration_has_matrix
+ * @see libinput_device_config_calibration_set_matrix
+ * @see libinput_device_config_calibration_get_default_matrix
+ */
+int
+libinput_device_config_calibration_get_default_matrix(struct libinput_device *device,
+                                                     float matrix[6]);
+
 #ifdef __cplusplus
 }
 #endif
index c0af460..861ab74 100644 (file)
@@ -385,6 +385,28 @@ START_TEST(pointer_seat_button_count)
 }
 END_TEST
 
+START_TEST(pointer_no_calibration)
+{
+       struct litest_device *dev = litest_current_device();
+       struct libinput_device *d = dev->libinput_device;
+       enum libinput_config_status status;
+       int rc;
+       float calibration[6] = {0};
+
+       rc = libinput_device_config_calibration_has_matrix(d);
+       ck_assert_int_eq(rc, 0);
+       rc = libinput_device_config_calibration_get_matrix(d, calibration);
+       ck_assert_int_eq(rc, 0);
+       rc = libinput_device_config_calibration_get_default_matrix(d,
+                                                                  calibration);
+       ck_assert_int_eq(rc, 0);
+
+       status = libinput_device_config_calibration_set_matrix(d,
+                                                              calibration);
+       ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_UNSUPPORTED);
+}
+END_TEST
+
 int main (int argc, char **argv) {
 
        litest_add("pointer:motion", pointer_motion_relative, LITEST_POINTER, LITEST_ANY);
@@ -393,5 +415,7 @@ int main (int argc, char **argv) {
        litest_add("pointer:scroll", pointer_scroll_wheel, LITEST_WHEEL, LITEST_ANY);
        litest_add_no_device("pointer:seat button count", pointer_seat_button_count);
 
+       litest_add("pointer:calibration", pointer_no_calibration, LITEST_ANY, LITEST_TOUCH|LITEST_SINGLE_TOUCH);
+
        return litest_run(argc, argv);
 }
index 0aab5c8..1c0a4b6 100644 (file)
@@ -232,7 +232,8 @@ START_TEST(touch_calibration_scale)
        li = dev->libinput;
 
        for (calibration = 0.1; calibration < 1; calibration += 0.1) {
-               libinput_device_calibrate(dev->libinput_device, matrix);
+               libinput_device_config_calibration_set_matrix(dev->libinput_device,
+                                                             matrix);
                litest_drain_events(li);
 
                litest_touch_down(dev, 0, 100, 100);
@@ -303,7 +304,8 @@ START_TEST(touch_calibration_rotation)
                        break;
                }
 
-               libinput_device_calibrate(dev->libinput_device, matrix);
+               libinput_device_config_calibration_set_matrix(dev->libinput_device,
+                                                             matrix);
                litest_drain_events(li);
 
                litest_touch_down(dev, 0, 80, 20);
@@ -368,7 +370,8 @@ START_TEST(touch_calibration_translation)
 
        /* translating from 0 up to 1 device width/height */
        for (translate = 0.1; translate <= 1; translate += 0.1) {
-               libinput_device_calibrate(dev->libinput_device, matrix);
+               libinput_device_config_calibration_set_matrix(dev->libinput_device,
+                                                             matrix);
                litest_drain_events(li);
 
                litest_touch_down(dev, 0, 100, 100);