mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2026-03-07 02:50:34 +01:00
tablet: lock the tablet rotation to the touchpad rotation
Follow-up to 6229df184e
We must not rely on the caller to toggle the left-handed bits correctly since
they may not know which devices belong together (despite device groups). Let's
do the right thing here, if the touchpad is set to left-handed, rotate the
tablet accordingly.
Note that the left-handed setting of the touchpad is left as-is
(right-handed). Until we have notifications about configuration changes, this
is the best we can do.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
This commit is contained in:
parent
829673901c
commit
7f4eb8ada1
3 changed files with 114 additions and 7 deletions
|
|
@ -33,6 +33,11 @@
|
|||
#include <libwacom/libwacom.h>
|
||||
#endif
|
||||
|
||||
enum notify {
|
||||
DONT_NOTIFY,
|
||||
DO_NOTIFY,
|
||||
};
|
||||
|
||||
/* The tablet sends events every ~2ms , 50ms should be plenty enough to
|
||||
detect out-of-range.
|
||||
This value is higher during test suite runs */
|
||||
|
|
@ -256,17 +261,57 @@ tablet_process_absolute(struct tablet_dispatch *tablet,
|
|||
}
|
||||
|
||||
static void
|
||||
tablet_change_to_left_handed(struct evdev_device *device)
|
||||
tablet_apply_rotation(struct evdev_device *device)
|
||||
{
|
||||
struct tablet_dispatch *tablet = tablet_dispatch(device->dispatch);
|
||||
|
||||
if (device->left_handed.enabled == device->left_handed.want_enabled)
|
||||
if (tablet->rotation.rotate == tablet->rotation.want_rotate)
|
||||
return;
|
||||
|
||||
if (!tablet_has_status(tablet, TABLET_TOOL_OUT_OF_PROXIMITY))
|
||||
return;
|
||||
|
||||
tablet->rotation.rotate = tablet->rotation.want_rotate;
|
||||
|
||||
evdev_log_debug(device,
|
||||
"tablet-rotation: rotation is %s\n",
|
||||
tablet->rotation.rotate ? "on" : "off");
|
||||
}
|
||||
|
||||
static void
|
||||
tablet_change_rotation(struct evdev_device *device, enum notify notify)
|
||||
{
|
||||
struct tablet_dispatch *tablet = tablet_dispatch(device->dispatch);
|
||||
struct evdev_device *touch_device = tablet->touch_device;
|
||||
struct evdev_dispatch *dispatch;
|
||||
bool tablet_is_left, touchpad_is_left;
|
||||
|
||||
tablet_is_left = tablet->device->left_handed.enabled;
|
||||
touchpad_is_left = tablet->rotation.touch_device_left_handed_state;
|
||||
|
||||
tablet->rotation.want_rotate = tablet_is_left || touchpad_is_left;
|
||||
tablet_apply_rotation(device);
|
||||
|
||||
if (notify == DO_NOTIFY && touch_device) {
|
||||
bool enable = device->left_handed.want_enabled;
|
||||
|
||||
dispatch = touch_device->dispatch;
|
||||
if (dispatch->interface->left_handed_toggle)
|
||||
dispatch->interface->left_handed_toggle(dispatch,
|
||||
touch_device,
|
||||
enable);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
tablet_change_to_left_handed(struct evdev_device *device)
|
||||
{
|
||||
if (device->left_handed.enabled == device->left_handed.want_enabled)
|
||||
return;
|
||||
|
||||
device->left_handed.enabled = device->left_handed.want_enabled;
|
||||
|
||||
tablet_change_rotation(device, DO_NOTIFY);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -405,7 +450,7 @@ tablet_update_xy(struct tablet_dispatch *tablet,
|
|||
bit_is_set(tablet->changed_axes, LIBINPUT_TABLET_TOOL_AXIS_Y)) {
|
||||
absinfo = libevdev_get_abs_info(device->evdev, ABS_X);
|
||||
|
||||
if (device->left_handed.enabled)
|
||||
if (tablet->rotation.rotate)
|
||||
value = invert_axis(absinfo);
|
||||
else
|
||||
value = absinfo->value;
|
||||
|
|
@ -414,7 +459,7 @@ tablet_update_xy(struct tablet_dispatch *tablet,
|
|||
|
||||
absinfo = libevdev_get_abs_info(device->evdev, ABS_Y);
|
||||
|
||||
if (device->left_handed.enabled)
|
||||
if (tablet->rotation.rotate)
|
||||
value = invert_axis(absinfo);
|
||||
else
|
||||
value = absinfo->value;
|
||||
|
|
@ -1633,6 +1678,7 @@ tablet_send_events(struct tablet_dispatch *tablet,
|
|||
|
||||
if (tablet_send_proximity_out(tablet, tool, device, &axes, time)) {
|
||||
tablet_change_to_left_handed(device);
|
||||
tablet_apply_rotation(device);
|
||||
tablet_history_reset(tablet);
|
||||
}
|
||||
}
|
||||
|
|
@ -1960,15 +2006,19 @@ tablet_device_added(struct evdev_device *device,
|
|||
struct evdev_device *added_device)
|
||||
{
|
||||
struct tablet_dispatch *tablet = tablet_dispatch(device->dispatch);
|
||||
bool is_touchscreen, is_ext_touchpad;
|
||||
|
||||
if (libinput_device_get_device_group(&device->base) !=
|
||||
libinput_device_get_device_group(&added_device->base))
|
||||
return;
|
||||
|
||||
is_touchscreen = evdev_device_has_capability(added_device,
|
||||
LIBINPUT_DEVICE_CAP_TOUCH);
|
||||
is_ext_touchpad = evdev_device_has_capability(added_device,
|
||||
LIBINPUT_DEVICE_CAP_POINTER) &&
|
||||
(added_device->tags & EVDEV_TAG_EXTERNAL_TOUCHPAD);
|
||||
/* Touch screens or external touchpads only */
|
||||
if (evdev_device_has_capability(added_device, LIBINPUT_DEVICE_CAP_TOUCH) ||
|
||||
(evdev_device_has_capability(added_device, LIBINPUT_DEVICE_CAP_POINTER) &&
|
||||
(added_device->tags & EVDEV_TAG_EXTERNAL_TOUCHPAD))) {
|
||||
if (is_touchscreen || is_ext_touchpad) {
|
||||
evdev_log_debug(device,
|
||||
"touch-arbitration: activated for %s<->%s\n",
|
||||
device->devname,
|
||||
|
|
@ -1976,6 +2026,19 @@ tablet_device_added(struct evdev_device *device,
|
|||
tablet->touch_device = added_device;
|
||||
}
|
||||
|
||||
if (is_ext_touchpad) {
|
||||
evdev_log_debug(device,
|
||||
"tablet-rotation: %s will rotate %s\n",
|
||||
device->devname,
|
||||
added_device->devname);
|
||||
tablet->rotation.touch_device = added_device;
|
||||
|
||||
if (libinput_device_config_left_handed_get(&added_device->base)) {
|
||||
tablet->rotation.touch_device_left_handed_state = true;
|
||||
tablet_change_rotation(device, DO_NOTIFY);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -1986,6 +2049,12 @@ tablet_device_removed(struct evdev_device *device,
|
|||
|
||||
if (tablet->touch_device == removed_device)
|
||||
tablet->touch_device = NULL;
|
||||
|
||||
if (tablet->rotation.touch_device == removed_device) {
|
||||
tablet->rotation.touch_device = NULL;
|
||||
tablet->rotation.touch_device_left_handed_state = false;
|
||||
tablet_change_rotation(device, DO_NOTIFY);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -2031,6 +2100,30 @@ tablet_check_initial_proximity(struct evdev_device *device,
|
|||
tablet->current_tool.serial = 0;
|
||||
}
|
||||
|
||||
/* Called when the touchpad toggles to left-handed */
|
||||
static void
|
||||
tablet_left_handed_toggled(struct evdev_dispatch *dispatch,
|
||||
struct evdev_device *device,
|
||||
bool left_handed_enabled)
|
||||
{
|
||||
struct tablet_dispatch *tablet = tablet_dispatch(dispatch);
|
||||
|
||||
if (!tablet->rotation.touch_device)
|
||||
return;
|
||||
|
||||
evdev_log_debug(device,
|
||||
"tablet-rotation: touchpad is %s\n",
|
||||
left_handed_enabled ? "left-handed" : "right-handed");
|
||||
|
||||
/* Our left-handed config is independent even though rotation is
|
||||
* locked. So we rotate when either device is left-handed. But it
|
||||
* can only be actually changed when the device is in a neutral
|
||||
* state, hence the want_rotate.
|
||||
*/
|
||||
tablet->rotation.touch_device_left_handed_state = left_handed_enabled;
|
||||
tablet_change_rotation(device, DONT_NOTIFY);
|
||||
}
|
||||
|
||||
static struct evdev_dispatch_interface tablet_interface = {
|
||||
.process = tablet_process,
|
||||
.suspend = tablet_suspend,
|
||||
|
|
@ -2044,6 +2137,7 @@ static struct evdev_dispatch_interface tablet_interface = {
|
|||
.touch_arbitration_toggle = NULL,
|
||||
.touch_arbitration_update_rect = NULL,
|
||||
.get_switch_state = NULL,
|
||||
.left_handed_toggle = tablet_left_handed_toggled,
|
||||
};
|
||||
|
||||
static void
|
||||
|
|
|
|||
|
|
@ -91,6 +91,15 @@ struct tablet_dispatch {
|
|||
struct evdev_device *touch_device;
|
||||
enum evdev_arbitration_state arbitration;
|
||||
|
||||
struct {
|
||||
/* The device locked for rotation */
|
||||
struct evdev_device *touch_device;
|
||||
/* Last known left-handed state of the touchpad */
|
||||
bool touch_device_left_handed_state;
|
||||
bool rotate;
|
||||
bool want_rotate;
|
||||
} rotation;
|
||||
|
||||
struct {
|
||||
struct libinput_timer prox_out_timer;
|
||||
bool proximity_out_forced;
|
||||
|
|
|
|||
|
|
@ -325,6 +325,10 @@ struct evdev_dispatch_interface {
|
|||
enum libinput_switch_state
|
||||
(*get_switch_state)(struct evdev_dispatch *dispatch,
|
||||
enum libinput_switch which);
|
||||
|
||||
void (*left_handed_toggle)(struct evdev_dispatch *dispatch,
|
||||
struct evdev_device *device,
|
||||
bool left_handed_enabled);
|
||||
};
|
||||
|
||||
enum evdev_dispatch_type {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue