[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