tablet: enable the calibration matrix for internal tablets

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 2015-12-01 14:05:16 +10:00
parent 20db89f5c9
commit bd0f43eeb6
5 changed files with 225 additions and 4 deletions

View file

@ -326,10 +326,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;
@ -1088,6 +1125,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)
@ -1100,6 +1145,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++) {

View file

@ -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)
{

View file

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

View file

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

View file

@ -2364,6 +2364,172 @@ START_TEST(tablet_pressure_distance_exclusive)
}
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)
{
@ -2408,4 +2574,8 @@ litest_setup_tests(void)
litest_add("tablet:time", tablet_time_usec, LITEST_TABLET, LITEST_ANY);
litest_add("tablet:pressure", tablet_pressure_distance_exclusive, LITEST_TABLET | LITEST_DISTANCE, LITEST_ANY);
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);
}