mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2026-02-03 20:30:27 +01:00
touchpad: lock the touchpad rotation to the tablet 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 tablet is set to left-handed, rotate the
touchpad accordingly.
Note that the left-handed setting of the tablet 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
7f4eb8ada1
commit
e8bf179f5d
2 changed files with 128 additions and 6 deletions
|
|
@ -43,6 +43,11 @@
|
|||
#define FAKE_FINGER_OVERFLOW (1 << 7)
|
||||
#define THUMB_IGNORE_SPEED_THRESHOLD 20 /* mm/s */
|
||||
|
||||
enum notify {
|
||||
DONT_NOTIFY,
|
||||
DO_NOTIFY,
|
||||
};
|
||||
|
||||
static inline struct tp_history_point*
|
||||
tp_motion_history_offset(struct tp_touch *t, int offset)
|
||||
{
|
||||
|
|
@ -473,8 +478,7 @@ rotated(struct tp_dispatch *tp, unsigned int code, int value)
|
|||
{
|
||||
const struct input_absinfo *absinfo;
|
||||
|
||||
if (!tp->device->left_handed.enabled ||
|
||||
!tp->left_handed.rotate)
|
||||
if (!tp->left_handed.rotate)
|
||||
return value;
|
||||
|
||||
switch (code) {
|
||||
|
|
@ -1935,6 +1939,24 @@ tp_post_events(struct tp_dispatch *tp, uint64_t time)
|
|||
tp_gesture_post_events(tp, time);
|
||||
}
|
||||
|
||||
static void
|
||||
tp_apply_rotation(struct evdev_device *device)
|
||||
{
|
||||
struct tp_dispatch *tp = (struct tp_dispatch *)device->dispatch;
|
||||
|
||||
if (tp->left_handed.want_rotate == tp->left_handed.rotate)
|
||||
return;
|
||||
|
||||
if (tp->nfingers_down)
|
||||
return;
|
||||
|
||||
tp->left_handed.rotate = tp->left_handed.want_rotate;
|
||||
|
||||
evdev_log_debug(device,
|
||||
"touchpad-rotation: rotation is %s\n",
|
||||
tp->left_handed.rotate ? "on" : "off");
|
||||
}
|
||||
|
||||
static void
|
||||
tp_handle_state(struct tp_dispatch *tp,
|
||||
uint64_t time)
|
||||
|
|
@ -1945,6 +1967,7 @@ tp_handle_state(struct tp_dispatch *tp,
|
|||
tp_post_process_state(tp, time);
|
||||
|
||||
tp_clickpad_middlebutton_apply_config(tp->device);
|
||||
tp_apply_rotation(tp->device);
|
||||
}
|
||||
|
||||
static inline void
|
||||
|
|
@ -2553,6 +2576,63 @@ tp_pair_tablet_mode_switch(struct evdev_device *touchpad,
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
tp_change_rotation(struct evdev_device *device, enum notify notify)
|
||||
{
|
||||
struct tp_dispatch *tp = (struct tp_dispatch *)device->dispatch;
|
||||
struct evdev_device *tablet_device = tp->left_handed.tablet_device;
|
||||
bool tablet_is_left, touchpad_is_left;
|
||||
|
||||
if (!tp->left_handed.must_rotate)
|
||||
return;
|
||||
|
||||
touchpad_is_left = device->left_handed.enabled;
|
||||
tablet_is_left = tp->left_handed.tablet_left_handed_state;
|
||||
|
||||
tp->left_handed.want_rotate = touchpad_is_left || tablet_is_left;
|
||||
|
||||
tp_apply_rotation(device);
|
||||
|
||||
if (notify == DO_NOTIFY && tablet_device) {
|
||||
struct evdev_dispatch *dispatch = tablet_device->dispatch;
|
||||
|
||||
if (dispatch->interface->left_handed_toggle)
|
||||
dispatch->interface->left_handed_toggle(dispatch,
|
||||
tablet_device,
|
||||
tp->left_handed.want_rotate);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
tp_pair_tablet(struct evdev_device *touchpad,
|
||||
struct evdev_device *tablet)
|
||||
{
|
||||
struct tp_dispatch *tp = (struct tp_dispatch*)touchpad->dispatch;
|
||||
|
||||
if (!tp->left_handed.must_rotate)
|
||||
return;
|
||||
|
||||
if ((tablet->seat_caps & EVDEV_DEVICE_TABLET) == 0)
|
||||
return;
|
||||
|
||||
if (libinput_device_get_device_group(&touchpad->base) !=
|
||||
libinput_device_get_device_group(&tablet->base))
|
||||
return;
|
||||
|
||||
tp->left_handed.tablet_device = tablet;
|
||||
|
||||
evdev_log_debug(touchpad,
|
||||
"touchpad-rotation: %s will rotate %s\n",
|
||||
touchpad->devname,
|
||||
tablet->devname);
|
||||
|
||||
if (libinput_device_config_left_handed_get(&tablet->base)) {
|
||||
tp->left_handed.want_rotate = true;
|
||||
tp->left_handed.tablet_left_handed_state = true;
|
||||
tp_change_rotation(touchpad, DONT_NOTIFY);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
tp_interface_device_added(struct evdev_device *device,
|
||||
struct evdev_device *added_device)
|
||||
|
|
@ -2563,6 +2643,7 @@ tp_interface_device_added(struct evdev_device *device,
|
|||
tp_dwt_pair_keyboard(device, added_device);
|
||||
tp_pair_lid_switch(device, added_device);
|
||||
tp_pair_tablet_mode_switch(device, added_device);
|
||||
tp_pair_tablet(device, added_device);
|
||||
|
||||
if (tp->sendevents.current_mode !=
|
||||
LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE)
|
||||
|
|
@ -2628,6 +2709,17 @@ tp_interface_device_removed(struct evdev_device *device,
|
|||
if (!found)
|
||||
tp_resume(tp, device, SUSPEND_EXTERNAL_MOUSE);
|
||||
}
|
||||
|
||||
if (removed_device == tp->left_handed.tablet_device) {
|
||||
tp->left_handed.tablet_device = NULL;
|
||||
tp->left_handed.tablet_left_handed_state = false;
|
||||
|
||||
/* Slight awkwardness: removing the tablet causes the
|
||||
* touchpad to rotate back to normal if only the tablet was
|
||||
* set to left-handed. Niche case, nothing to worry about
|
||||
*/
|
||||
tp_change_rotation(device, DO_NOTIFY);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
|
|
@ -2750,6 +2842,30 @@ tp_interface_toggle_touch(struct evdev_dispatch *dispatch,
|
|||
}
|
||||
}
|
||||
|
||||
/* Called when the tablet toggles to left-handed */
|
||||
static void
|
||||
touchpad_left_handed_toggled(struct evdev_dispatch *dispatch,
|
||||
struct evdev_device *device,
|
||||
bool left_handed_enabled)
|
||||
{
|
||||
struct tp_dispatch *tp = tp_dispatch(dispatch);
|
||||
|
||||
if (!tp->left_handed.tablet_device)
|
||||
return;
|
||||
|
||||
evdev_log_debug(device,
|
||||
"touchpad-rotation: tablet 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.
|
||||
*/
|
||||
tp->left_handed.tablet_left_handed_state = left_handed_enabled;
|
||||
tp_change_rotation(device, DONT_NOTIFY);
|
||||
}
|
||||
|
||||
static struct evdev_dispatch_interface tp_interface = {
|
||||
.process = tp_interface_process,
|
||||
.suspend = tp_interface_suspend,
|
||||
|
|
@ -2763,6 +2879,7 @@ static struct evdev_dispatch_interface tp_interface = {
|
|||
.touch_arbitration_toggle = tp_interface_toggle_touch,
|
||||
.touch_arbitration_update_rect = NULL,
|
||||
.get_switch_state = NULL,
|
||||
.left_handed_toggle = touchpad_left_handed_toggled,
|
||||
};
|
||||
|
||||
static void
|
||||
|
|
@ -3726,11 +3843,11 @@ tp_change_to_left_handed(struct evdev_device *device)
|
|||
* so checking physical buttons is enough */
|
||||
|
||||
device->left_handed.enabled = device->left_handed.want_enabled;
|
||||
tp_change_rotation(device, DO_NOTIFY);
|
||||
}
|
||||
|
||||
static bool
|
||||
tp_init_left_handed_rotation(struct tp_dispatch *tp,
|
||||
struct evdev_device *device)
|
||||
tp_requires_rotation(struct tp_dispatch *tp, struct evdev_device *device)
|
||||
{
|
||||
bool rotate = false;
|
||||
#if HAVE_LIBWACOM
|
||||
|
|
@ -3793,12 +3910,13 @@ tp_init_left_handed(struct tp_dispatch *tp,
|
|||
{
|
||||
bool want_left_handed = true;
|
||||
|
||||
tp->left_handed.must_rotate = tp_requires_rotation(tp, device);
|
||||
|
||||
if (device->model_flags & EVDEV_MODEL_APPLE_TOUCHPAD_ONEBUTTON)
|
||||
want_left_handed = false;
|
||||
if (want_left_handed)
|
||||
evdev_init_left_handed(device, tp_change_to_left_handed);
|
||||
|
||||
tp->left_handed.rotate = tp_init_left_handed_rotation(tp, device);
|
||||
}
|
||||
|
||||
struct evdev_dispatch *
|
||||
|
|
|
|||
|
|
@ -487,8 +487,12 @@ struct tp_dispatch {
|
|||
} tablet_mode_switch;
|
||||
|
||||
struct {
|
||||
/* true if the axes need rotation when left-handed is on*/
|
||||
bool rotate;
|
||||
bool want_rotate;
|
||||
|
||||
bool must_rotate; /* true if we should rotate when applicable */
|
||||
struct evdev_device *tablet_device;
|
||||
bool tablet_left_handed_state;
|
||||
} left_handed;
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue