Change calibration into a configuration option

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>
This commit is contained in:
Peter Hutterer 2014-08-26 11:41:19 +10:00
parent a888a7a61c
commit ea00ff9114
7 changed files with 248 additions and 41 deletions

View 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,

View 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 *

View 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 {

View 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);
}

View 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

View 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);
}

View 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);