mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2026-03-21 21:30:36 +01:00
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:
parent
a888a7a61c
commit
ea00ff9114
7 changed files with 248 additions and 41 deletions
59
src/evdev.c
59
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,
|
||||
|
|
|
|||
|
|
@ -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 *
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
147
src/libinput.h
147
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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue