[PATCH libinput 10/11] Change calibration into a configuration option
Hans de Goede
hdegoede at redhat.com
Thu Aug 28 06:16:39 PDT 2014
Hi,
On 08/27/2014 06:31 AM, Peter Hutterer wrote:
> 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 at who-t.net>
Looks good:
Reviewed-by: Hans de Goede <hdegoede at redhat.com>
Regards,
Hans
> ---
> src/evdev.c | 59 +++++++++++++++++++-
> src/evdev.h | 2 +
> src/libinput-private.h | 11 ++++
> src/libinput.c | 37 +++++++++++++
> src/libinput.h | 147 +++++++++++++++++++++++++++++++++++++------------
> test/pointer.c | 24 ++++++++
> test/touch.c | 9 ++-
> 7 files changed, 248 insertions(+), 41 deletions(-)
>
> diff --git a/src/evdev.c b/src/evdev.c
> index 4cd3cfa..0059444 100644
> --- a/src/evdev.c
> +++ b/src/evdev.c
> @@ -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,
> diff --git a/src/evdev.h b/src/evdev.h
> index 9196bd2..110ea74 100644
> --- a/src/evdev.h
> +++ b/src/evdev.h
> @@ -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 *
> diff --git a/src/libinput-private.h b/src/libinput-private.h
> index 94a3e07..9e084dd 100644
> --- a/src/libinput-private.h
> +++ b/src/libinput-private.h
> @@ -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 {
> diff --git a/src/libinput.c b/src/libinput.c
> index ed5eba1..20aa1cb 100644
> --- a/src/libinput.c
> +++ b/src/libinput.c
> @@ -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);
> +}
> diff --git a/src/libinput.h b/src/libinput.h
> index 82970e2..5af0dde 100644
> --- a/src/libinput.h
> +++ b/src/libinput.h
> @@ -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
> diff --git a/test/pointer.c b/test/pointer.c
> index c0af460..861ab74 100644
> --- a/test/pointer.c
> +++ b/test/pointer.c
> @@ -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);
> }
> diff --git a/test/touch.c b/test/touch.c
> index 0aab5c8..1c0a4b6 100644
> --- a/test/touch.c
> +++ b/test/touch.c
> @@ -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);
>
More information about the wayland-devel
mailing list