[PATCH libinput 8/8] tablet: enable the calibration matrix for internal tablets
Peter Hutterer
peter.hutterer at who-t.net
Tue Dec 1 17:46:32 PST 2015
Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
---
src/evdev-tablet.c | 51 +++++++++++++++-
src/evdev.c | 2 +-
src/evdev.h | 4 ++
test/pointer.c | 2 +-
test/tablet.c | 170 +++++++++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 225 insertions(+), 4 deletions(-)
diff --git a/src/evdev-tablet.c b/src/evdev-tablet.c
index d3ec1da..7e3298c 100644
--- a/src/evdev-tablet.c
+++ b/src/evdev-tablet.c
@@ -337,10 +337,47 @@ tablet_check_notify_axes(struct tablet_dispatch *tablet,
double deltas[LIBINPUT_TABLET_TOOL_AXIS_MAX + 1] = {0};
double deltas_discrete[LIBINPUT_TABLET_TOOL_AXIS_MAX + 1] = {0};
double oldval;
+ struct device_coords point, old_point;
+ const struct input_absinfo *absinfo;
- for (a = LIBINPUT_TABLET_TOOL_AXIS_X; a <= LIBINPUT_TABLET_TOOL_AXIS_MAX; a++) {
- const struct input_absinfo *absinfo;
+ /* x/y are special for left-handed and calibration */
+ a = LIBINPUT_TABLET_TOOL_AXIS_X;
+ old_point.x = tablet->axes[a];
+ if (bit_is_set(tablet->changed_axes, a)) {
+ absinfo = libevdev_get_abs_info(device->evdev,
+ axis_to_evcode(a));
+ axis_update_needed = true;
+ if (device->left_handed.enabled)
+ tablet->axes[a] = invert_axis(absinfo);
+ else
+ tablet->axes[a] = absinfo->value;
+ }
+ point.x = tablet->axes[a];
+
+ a = LIBINPUT_TABLET_TOOL_AXIS_Y;
+ old_point.y = tablet->axes[a];
+ if (bit_is_set(tablet->changed_axes, a)) {
+ absinfo = libevdev_get_abs_info(device->evdev,
+ axis_to_evcode(a));
+ axis_update_needed = true;
+
+ if (device->left_handed.enabled)
+ tablet->axes[a] = invert_axis(absinfo);
+ else
+ tablet->axes[a] = absinfo->value;
+ }
+ point.y = tablet->axes[a];
+
+ evdev_transform_absolute(device, &point);
+ evdev_transform_absolute(device, &old_point);
+
+ axes[LIBINPUT_TABLET_TOOL_AXIS_X] = point.x;
+ axes[LIBINPUT_TABLET_TOOL_AXIS_Y] = point.y;
+ deltas[LIBINPUT_TABLET_TOOL_AXIS_X] = point.x - old_point.x;
+ deltas[LIBINPUT_TABLET_TOOL_AXIS_Y] = point.y - old_point.y;
+
+ for (a = LIBINPUT_TABLET_TOOL_AXIS_DISTANCE; a <= LIBINPUT_TABLET_TOOL_AXIS_MAX; a++) {
if (!bit_is_set(tablet->changed_axes, a)) {
axes[a] = tablet->axes[a];
continue;
@@ -1152,6 +1189,14 @@ static struct evdev_dispatch_interface tablet_interface = {
tablet_check_initial_proximity,
};
+static void
+tablet_init_calibration(struct tablet_dispatch *tablet,
+ struct evdev_device *device)
+{
+ if (libevdev_has_property(device->evdev, INPUT_PROP_DIRECT))
+ evdev_init_calibration(device, &tablet->base);
+}
+
static int
tablet_init(struct tablet_dispatch *tablet,
struct evdev_device *device)
@@ -1164,6 +1209,8 @@ tablet_init(struct tablet_dispatch *tablet,
tablet->current_tool_type = LIBINPUT_TOOL_NONE;
list_init(&tablet->tool_list);
+ tablet_init_calibration(tablet, device);
+
for (axis = LIBINPUT_TABLET_TOOL_AXIS_X;
axis <= LIBINPUT_TABLET_TOOL_AXIS_MAX;
axis++) {
diff --git a/src/evdev.c b/src/evdev.c
index 5a73340..993c5d8 100644
--- a/src/evdev.c
+++ b/src/evdev.c
@@ -1178,7 +1178,7 @@ evdev_init_button_scroll(struct evdev_device *device,
return 0;
}
-static void
+void
evdev_init_calibration(struct evdev_device *device,
struct evdev_dispatch *dispatch)
{
diff --git a/src/evdev.h b/src/evdev.h
index d7b372f..75a2cb6 100644
--- a/src/evdev.h
+++ b/src/evdev.h
@@ -290,6 +290,10 @@ void
evdev_transform_absolute(struct evdev_device *device,
struct device_coords *point);
+void
+evdev_init_calibration(struct evdev_device *device,
+ struct evdev_dispatch *dispatch);
+
int
evdev_device_init_pointer_acceleration(struct evdev_device *device,
struct motion_filter *filter);
diff --git a/test/pointer.c b/test/pointer.c
index 5c33d50..d043fa8 100644
--- a/test/pointer.c
+++ b/test/pointer.c
@@ -1600,7 +1600,7 @@ litest_setup_tests(void)
litest_add("pointer:scroll", pointer_scroll_natural_enable_config, LITEST_WHEEL, LITEST_TABLET);
litest_add("pointer:scroll", pointer_scroll_natural_wheel, LITEST_WHEEL, LITEST_TABLET);
- litest_add("pointer:calibration", pointer_no_calibration, LITEST_ANY, LITEST_TOUCH|LITEST_SINGLE_TOUCH|LITEST_ABSOLUTE|LITEST_PROTOCOL_A);
+ litest_add("pointer:calibration", pointer_no_calibration, LITEST_ANY, LITEST_TOUCH|LITEST_SINGLE_TOUCH|LITEST_ABSOLUTE|LITEST_PROTOCOL_A|LITEST_TABLET);
/* tests touchpads too */
litest_add("pointer:left-handed", pointer_left_handed_defaults, LITEST_BUTTON, LITEST_ANY);
diff --git a/test/tablet.c b/test/tablet.c
index 97740f7..c82be49 100644
--- a/test/tablet.c
+++ b/test/tablet.c
@@ -2514,6 +2514,172 @@ START_TEST(tablet_pressure_offset_rubber)
}
END_TEST
+START_TEST(tablet_calibration_has_matrix)
+{
+ struct litest_device *dev = litest_current_device();
+ struct libinput_device *d = dev->libinput_device;
+ enum libinput_config_status status;
+ int rc;
+ float calibration[6] = {1, 0, 0, 0, 1, 0};
+ int has_calibration;
+
+ has_calibration = libevdev_has_property(dev->evdev, INPUT_PROP_DIRECT);
+
+ rc = libinput_device_config_calibration_has_matrix(d);
+ ck_assert_int_eq(rc, has_calibration);
+ 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);
+ if (has_calibration)
+ ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
+ else
+ ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_UNSUPPORTED);
+}
+END_TEST
+
+START_TEST(tablet_calibration_set_matrix_delta)
+{
+ struct litest_device *dev = litest_current_device();
+ struct libinput *li = dev->libinput;
+ struct libinput_device *d = dev->libinput_device;
+ enum libinput_config_status status;
+ float calibration[6] = {0.5, 0, 0, 0, 0.5, 0};
+ struct libinput_event *event;
+ struct libinput_event_tablet_tool *tablet_event;
+ struct axis_replacement axes[] = {
+ { ABS_DISTANCE, 10 },
+ { -1, -1 }
+ };
+ int has_calibration;
+ double dx, dy, mdx, mdy;
+
+ has_calibration = libevdev_has_property(dev->evdev, INPUT_PROP_DIRECT);
+ if (!has_calibration)
+ return;
+
+ litest_tablet_proximity_in(dev, 100, 100, axes);
+ litest_drain_events(li);
+
+ litest_tablet_motion(dev, 80, 80, axes);
+ libinput_dispatch(li);
+
+ event = libinput_get_event(li);
+ tablet_event = litest_is_tablet_event(event,
+ LIBINPUT_EVENT_TABLET_TOOL_AXIS);
+
+ dx = libinput_event_tablet_tool_get_axis_delta(tablet_event,
+ LIBINPUT_TABLET_TOOL_AXIS_X);
+ dy = libinput_event_tablet_tool_get_axis_delta(tablet_event,
+ LIBINPUT_TABLET_TOOL_AXIS_Y);
+ libinput_event_destroy(event);
+ litest_tablet_proximity_out(dev);
+ litest_drain_events(li);
+
+ status = libinput_device_config_calibration_set_matrix(d,
+ calibration);
+ ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
+
+ litest_tablet_proximity_in(dev, 100, 100, axes);
+ litest_drain_events(li);
+
+ litest_tablet_motion(dev, 80, 80, axes);
+ libinput_dispatch(li);
+
+ event = libinput_get_event(li);
+ tablet_event = litest_is_tablet_event(event,
+ LIBINPUT_EVENT_TABLET_TOOL_AXIS);
+
+ mdx = libinput_event_tablet_tool_get_axis_delta(tablet_event,
+ LIBINPUT_TABLET_TOOL_AXIS_X);
+ mdy = libinput_event_tablet_tool_get_axis_delta(tablet_event,
+ LIBINPUT_TABLET_TOOL_AXIS_Y);
+ libinput_event_destroy(event);
+ litest_drain_events(li);
+
+ ck_assert_double_gt(dx, mdx * 2 - 1);
+ ck_assert_double_lt(dx, mdx * 2 + 1);
+ ck_assert_double_gt(dy, mdy * 2 - 1);
+ ck_assert_double_lt(dy, mdy * 2 + 1);
+}
+END_TEST
+
+START_TEST(tablet_calibration_set_matrix)
+{
+ struct litest_device *dev = litest_current_device();
+ struct libinput *li = dev->libinput;
+ struct libinput_device *d = dev->libinput_device;
+ enum libinput_config_status status;
+ float calibration[6] = {0.5, 0, 0, 0, 1, 0};
+ struct libinput_event *event;
+ struct libinput_event_tablet_tool *tablet_event;
+ struct axis_replacement axes[] = {
+ { ABS_DISTANCE, 10 },
+ { -1, -1 }
+ };
+ int has_calibration;
+ double x, y;
+
+ has_calibration = libevdev_has_property(dev->evdev, INPUT_PROP_DIRECT);
+ if (!has_calibration)
+ return;
+
+ litest_drain_events(li);
+
+ status = libinput_device_config_calibration_set_matrix(d,
+ calibration);
+ ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
+
+ litest_tablet_proximity_in(dev, 100, 100, axes);
+ libinput_dispatch(li);
+
+ event = libinput_get_event(li);
+ tablet_event = litest_is_tablet_event(event,
+ LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
+ x = libinput_event_tablet_tool_get_x_transformed(tablet_event, 100);
+ y = libinput_event_tablet_tool_get_y_transformed(tablet_event, 100);
+ libinput_event_destroy(event);
+
+ ck_assert_double_gt(x, 49.0);
+ ck_assert_double_lt(x, 51.0);
+ ck_assert_double_gt(y, 99.0);
+ ck_assert_double_lt(y, 100.0);
+
+ litest_tablet_proximity_out(dev);
+ libinput_dispatch(li);
+ litest_tablet_proximity_in(dev, 50, 50, axes);
+ litest_tablet_proximity_out(dev);
+ litest_drain_events(li);
+
+ calibration[0] = 1;
+ calibration[4] = 0.5;
+ status = libinput_device_config_calibration_set_matrix(d,
+ calibration);
+ ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
+
+ litest_tablet_proximity_in(dev, 100, 100, axes);
+ libinput_dispatch(li);
+
+ event = libinput_get_event(li);
+ tablet_event = litest_is_tablet_event(event,
+ LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
+ x = libinput_event_tablet_tool_get_x_transformed(tablet_event, 100);
+ y = libinput_event_tablet_tool_get_y_transformed(tablet_event, 100);
+ libinput_event_destroy(event);
+
+ ck_assert_double_gt(x, 99.0);
+ ck_assert_double_lt(x, 100.0);
+ ck_assert_double_gt(y, 49.0);
+ ck_assert_double_lt(y, 51.0);
+
+ litest_tablet_proximity_out(dev);
+}
+END_TEST
+
void
litest_setup_tests(void)
{
@@ -2561,4 +2727,8 @@ litest_setup_tests(void)
litest_add_for_device("tablet:pressure", tablet_pressure_offset_none_for_default_pen, LITEST_WACOM_INTUOS);
litest_add_for_device("tablet:pressure", tablet_pressure_offset_pen, LITEST_WACOM_INTUOS);
litest_add_for_device("tablet:pressure", tablet_pressure_offset_rubber, LITEST_WACOM_INTUOS);
+
+ litest_add("tablet:calibration", tablet_calibration_has_matrix, LITEST_TABLET, LITEST_ANY);
+ litest_add("tablet:calibration", tablet_calibration_set_matrix, LITEST_TABLET, LITEST_ANY);
+ litest_add("tablet:calibration", tablet_calibration_set_matrix_delta, LITEST_TABLET, LITEST_ANY);
}
--
2.5.0
More information about the wayland-devel
mailing list