Signed-off-by: Peter Hutterer <[email protected]>
---
 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

_______________________________________________
wayland-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to