mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2026-02-04 15:10:26 +01:00
tablet: Add a left handed mode and tests
On the majority of Wacom tablets, the buttons are on the left side, opposite of the side where the palm is meant to rest. Because of this, it's impossible to use the tablet with your left hand (comfortably, anyway) unless you flip it over, in which case the coordinates need to be inverted for it to match up with the screen properly. This is where left handed mode comes in. When enabled, it reverses all the coordinates so that the tablet may be rotated, and the palm rest on the tablet moved over to the left side. Signed-off-by: Stephen Chandler Paul <thatslyude@gmail.com> Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net> Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
This commit is contained in:
parent
a98d4831b6
commit
1751688cc8
2 changed files with 143 additions and 1 deletions
|
|
@ -85,6 +85,21 @@ tablet_mark_all_axes_changed(struct tablet_dispatch *tablet,
|
|||
tablet_set_status(tablet, TABLET_AXES_UPDATED);
|
||||
}
|
||||
|
||||
static void
|
||||
tablet_change_to_left_handed(struct evdev_device *device)
|
||||
{
|
||||
struct tablet_dispatch *tablet =
|
||||
(struct tablet_dispatch*)device->dispatch;
|
||||
|
||||
if (device->left_handed.enabled == device->left_handed.want_enabled)
|
||||
return;
|
||||
|
||||
if (!tablet_has_status(tablet, TABLET_TOOL_OUT_OF_PROXIMITY))
|
||||
return;
|
||||
|
||||
device->left_handed.enabled = device->left_handed.want_enabled;
|
||||
}
|
||||
|
||||
static void
|
||||
tablet_update_tool(struct tablet_dispatch *tablet,
|
||||
struct evdev_device *device,
|
||||
|
|
@ -120,6 +135,12 @@ normalize_tilt(const struct input_absinfo * absinfo) {
|
|||
return (value * 2) - 1;
|
||||
}
|
||||
|
||||
static inline int32_t
|
||||
invert_axis(const struct input_absinfo *absinfo)
|
||||
{
|
||||
return absinfo->maximum - (absinfo->value - absinfo->minimum);
|
||||
}
|
||||
|
||||
static void
|
||||
tablet_check_notify_axes(struct tablet_dispatch *tablet,
|
||||
struct evdev_device *device,
|
||||
|
|
@ -142,7 +163,10 @@ tablet_check_notify_axes(struct tablet_dispatch *tablet,
|
|||
switch (a) {
|
||||
case LIBINPUT_TABLET_AXIS_X:
|
||||
case LIBINPUT_TABLET_AXIS_Y:
|
||||
tablet->axes[a] = absinfo->value;
|
||||
if (device->left_handed.enabled)
|
||||
tablet->axes[a] = invert_axis(absinfo);
|
||||
else
|
||||
tablet->axes[a] = absinfo->value;
|
||||
break;
|
||||
case LIBINPUT_TABLET_AXIS_DISTANCE:
|
||||
case LIBINPUT_TABLET_AXIS_PRESSURE:
|
||||
|
|
@ -481,6 +505,8 @@ tablet_flush(struct tablet_dispatch *tablet,
|
|||
tablet->axes);
|
||||
tablet_set_status(tablet, TABLET_TOOL_OUT_OF_PROXIMITY);
|
||||
tablet_unset_status(tablet, TABLET_TOOL_LEAVING_PROXIMITY);
|
||||
|
||||
tablet_change_to_left_handed(device);
|
||||
}
|
||||
|
||||
/* Update state */
|
||||
|
|
@ -585,5 +611,7 @@ evdev_tablet_create(struct evdev_device *device)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
evdev_init_left_handed(device, tablet_change_to_left_handed);
|
||||
|
||||
return &tablet->base;
|
||||
}
|
||||
|
|
|
|||
114
test/tablet.c
114
test/tablet.c
|
|
@ -243,6 +243,119 @@ START_TEST(motion)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(left_handed)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
struct libinput_event *event;
|
||||
struct libinput_event_tablet *tablet_event;
|
||||
double libinput_max_x, libinput_max_y;
|
||||
double last_x, last_y;
|
||||
struct axis_replacement axes[] = {
|
||||
{ ABS_DISTANCE, 10 },
|
||||
{ -1, -1 }
|
||||
};
|
||||
|
||||
ck_assert(libinput_device_config_left_handed_is_available(dev->libinput_device));
|
||||
|
||||
libinput_device_get_size (dev->libinput_device,
|
||||
&libinput_max_x,
|
||||
&libinput_max_y);
|
||||
|
||||
/* Test that left-handed mode doesn't go into effect until the tool has
|
||||
* left proximity of the tablet. In order to test this, we have to bring
|
||||
* the tool into proximity and make sure libinput processes the
|
||||
* proximity events so that it updates it's internal tablet state, and
|
||||
* then try setting it to left-handed mode. */
|
||||
litest_tablet_proximity_in(dev, 0, 100, axes);
|
||||
libinput_dispatch(li);
|
||||
libinput_device_config_left_handed_set(dev->libinput_device, 1);
|
||||
|
||||
litest_wait_for_event_of_type(li, LIBINPUT_EVENT_TABLET_AXIS, -1);
|
||||
|
||||
while ((event = libinput_get_event(li))) {
|
||||
tablet_event = libinput_event_get_tablet_event(event);
|
||||
|
||||
last_x = libinput_event_tablet_get_axis_value(
|
||||
tablet_event, LIBINPUT_TABLET_AXIS_X);
|
||||
last_y = libinput_event_tablet_get_axis_value(
|
||||
tablet_event, LIBINPUT_TABLET_AXIS_Y);
|
||||
|
||||
litest_assert_double_eq(last_x, 0);
|
||||
litest_assert_double_eq(last_y, libinput_max_y);
|
||||
|
||||
libinput_event_destroy(event);
|
||||
}
|
||||
|
||||
litest_tablet_motion(dev, 100, 0, axes);
|
||||
litest_wait_for_event_of_type(li, LIBINPUT_EVENT_TABLET_AXIS, -1);
|
||||
|
||||
while ((event = libinput_get_event(li))) {
|
||||
double x, y;
|
||||
tablet_event = libinput_event_get_tablet_event(event);
|
||||
|
||||
x = libinput_event_tablet_get_axis_value(
|
||||
tablet_event, LIBINPUT_TABLET_AXIS_X);
|
||||
y = libinput_event_tablet_get_axis_value(
|
||||
tablet_event, LIBINPUT_TABLET_AXIS_Y);
|
||||
|
||||
litest_assert_double_eq(x, libinput_max_x);
|
||||
litest_assert_double_eq(y, 0);
|
||||
|
||||
litest_assert_double_gt(x, last_x);
|
||||
litest_assert_double_lt(y, last_y);
|
||||
|
||||
libinput_event_destroy(event);
|
||||
}
|
||||
|
||||
litest_tablet_proximity_out(dev);
|
||||
litest_drain_events(li);
|
||||
|
||||
/* Since we've drained the events and libinput's aware the tool is out
|
||||
* of proximity, it should have finally transitioned into left-handed
|
||||
* mode, so the axes should be inverted once we bring it back into
|
||||
* proximity */
|
||||
litest_tablet_proximity_in(dev, 0, 100, axes);
|
||||
|
||||
litest_wait_for_event_of_type(li, LIBINPUT_EVENT_TABLET_AXIS, -1);
|
||||
|
||||
while ((event = libinput_get_event(li))) {
|
||||
tablet_event = libinput_event_get_tablet_event(event);
|
||||
|
||||
last_x = libinput_event_tablet_get_axis_value(
|
||||
tablet_event, LIBINPUT_TABLET_AXIS_X);
|
||||
last_y = libinput_event_tablet_get_axis_value(
|
||||
tablet_event, LIBINPUT_TABLET_AXIS_Y);
|
||||
|
||||
litest_assert_double_eq(last_x, libinput_max_x);
|
||||
litest_assert_double_eq(last_y, 0);
|
||||
|
||||
libinput_event_destroy(event);
|
||||
}
|
||||
|
||||
litest_tablet_motion(dev, 100, 0, axes);
|
||||
litest_wait_for_event_of_type(li, LIBINPUT_EVENT_TABLET_AXIS, -1);
|
||||
|
||||
while ((event = libinput_get_event(li))) {
|
||||
double x, y;
|
||||
tablet_event = libinput_event_get_tablet_event(event);
|
||||
|
||||
x = libinput_event_tablet_get_axis_value(
|
||||
tablet_event, LIBINPUT_TABLET_AXIS_X);
|
||||
y = libinput_event_tablet_get_axis_value(
|
||||
tablet_event, LIBINPUT_TABLET_AXIS_Y);
|
||||
|
||||
litest_assert_double_eq(x, 0);
|
||||
litest_assert_double_eq(y, libinput_max_y);
|
||||
|
||||
litest_assert_double_lt(x, last_x);
|
||||
litest_assert_double_gt(y, last_y);
|
||||
|
||||
libinput_event_destroy(event);
|
||||
}
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(motion_event_state)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
|
|
@ -873,6 +986,7 @@ main(int argc, char **argv)
|
|||
litest_add("tablet:proximity", bad_distance_events, LITEST_TABLET | LITEST_DISTANCE, LITEST_ANY);
|
||||
litest_add("tablet:motion", motion, LITEST_TABLET, LITEST_ANY);
|
||||
litest_add("tablet:motion", motion_event_state, LITEST_TABLET, LITEST_ANY);
|
||||
litest_add("tablet:left_handed", left_handed, LITEST_TABLET, LITEST_ANY);
|
||||
litest_add("tablet:normalization", normalization, LITEST_TABLET, LITEST_ANY);
|
||||
litest_add("tablet:pad", pad_buttons_ignored, LITEST_TABLET, LITEST_ANY);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue