mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2026-05-08 16:00:06 +02:00
Take hold gestures and clickpad state into account
- Avoid entering the drag state if the clickpad is pressed. - Finish hold gestures and cancel other gestures before entering the drag state.
This commit is contained in:
parent
626a0af4ec
commit
f5b83120ae
1 changed files with 71 additions and 6 deletions
|
|
@ -255,6 +255,28 @@ tp_tfd_idle_handle_event(struct tp_dispatch *tp,
|
|||
}
|
||||
}
|
||||
|
||||
/* finishes hold gestures and cancels other gestures */
|
||||
static void
|
||||
tp_tfd_interrupt_gestures(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time)
|
||||
{
|
||||
switch (tp->gesture.state) {
|
||||
case GESTURE_STATE_NONE:
|
||||
case GESTURE_STATE_POINTER_MOTION:
|
||||
break; /* should be harmless enough? */
|
||||
case GESTURE_STATE_HOLD:
|
||||
case GESTURE_STATE_HOLD_AND_MOTION:
|
||||
/* starting a drag should finish a hold gesture -- not
|
||||
cancel it (if there's any difference?) */
|
||||
tp_gesture_stop(tp, time);
|
||||
break;
|
||||
default:
|
||||
tp_gesture_cancel(tp, time);
|
||||
break;
|
||||
}
|
||||
/* TODO: sooner or later, calls between state machines will start resulting
|
||||
in infinite recursion... */
|
||||
}
|
||||
|
||||
/* We don't have the primary button pressed in this state; the
|
||||
press is delayed if the fingers have remained stationary */
|
||||
static void
|
||||
|
|
@ -262,6 +284,11 @@ tp_tfd_possible_drag_handle_event(struct tp_dispatch *tp,
|
|||
struct tp_touch *t,
|
||||
enum tfd_event event, uint64_t time, int nfingers_down)
|
||||
{
|
||||
/* it is possible to use 3 fingers with a clickpad to emulate e.g. middle
|
||||
mouse button clicks, and no-one wants a primary click while doing a middle
|
||||
click on a link, for instance */
|
||||
bool clickpad_pressed = tp->buttons.is_clickpad && tp->buttons.state;
|
||||
|
||||
switch (event) {
|
||||
case TFD_EVENT_TOUCH_COUNT_INCREASE:
|
||||
case TFD_EVENT_TOUCH_COUNT_DECREASE:
|
||||
|
|
@ -276,14 +303,22 @@ tp_tfd_possible_drag_handle_event(struct tp_dispatch *tp,
|
|||
}
|
||||
break;
|
||||
case TFD_EVENT_MOTION:
|
||||
/* this event must ensure it fires upon cursor movement -- alternatively, if
|
||||
impossible, TODO: cursor should be pinned in this state to ensure this */
|
||||
/* this event must ensure it fires upon cursor movement
|
||||
|
||||
alternatively: cursor should be pinned in this state to ensure this.
|
||||
But pinning is not acceptable in this state as long as we check clickpad
|
||||
state and exit early... */
|
||||
switch (nfingers_down) {
|
||||
default:
|
||||
log_tfd_bug(tp, event, nfingers_down);
|
||||
break; // bug
|
||||
case 3:
|
||||
/* perform a press since it hasn't already been done by the timer */
|
||||
if (clickpad_pressed)
|
||||
break;
|
||||
|
||||
/* show special consideration for overlapping hold gestures */
|
||||
tp_tfd_interrupt_gestures(tp, t, time);
|
||||
|
||||
tp->tfd.state = TFD_STATE_DRAG;
|
||||
tp_tfd_notify(tp, time, 1, LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
tp_tfd_clear_timer(tp);
|
||||
|
|
@ -292,8 +327,12 @@ tp_tfd_possible_drag_handle_event(struct tp_dispatch *tp,
|
|||
case TFD_EVENT_RESUME_TIMEOUT:
|
||||
break;
|
||||
case TFD_EVENT_TIMEOUT:
|
||||
/* we've not moved our three fingers so we perform the press after the
|
||||
initial delay */
|
||||
if (clickpad_pressed)
|
||||
break;
|
||||
|
||||
/* show special consideration for overlapping hold gestures */
|
||||
tp_tfd_interrupt_gestures(tp, t, time);
|
||||
|
||||
tp->tfd.state = TFD_STATE_DRAG;
|
||||
tp_tfd_notify(tp, time, 1, LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
break;
|
||||
|
|
@ -658,6 +697,26 @@ tp_tfd_possible_resume_handle_event(struct tp_dispatch *tp,
|
|||
// TODO: It's too easy to trigger 3fd while scrolling and a third finger
|
||||
// touches momentarily. */
|
||||
|
||||
/* Whether to disregard this event for the current state instead of handling it */
|
||||
// static bool
|
||||
// tp_tfd_should_filter_event(struct tp_dispatch *tp,
|
||||
// struct tp_touch *t,
|
||||
// enum tfd_event event,
|
||||
// uint64_t time,
|
||||
// int nfingers_down)
|
||||
// {
|
||||
// switch (tp->tfd.state) {
|
||||
// case TFD_STATE_POSSIBLE_DRAG:
|
||||
// /* don't engage TFD while clickpad is pressed */
|
||||
// return (event == TFD_EVENT_MOTION || event == TFD_EVENT_TIMEOUT) &&
|
||||
// tp->buttons.is_clickpad && tp->queued & TOUCHPAD_EVENT_BUTTON_PRESS;
|
||||
// /* TODO: not very clean since motion and timeouts aren't directly
|
||||
// related to entering the drag state. Consider a more clear solution. */
|
||||
// default:
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
|
||||
static void
|
||||
tp_tfd_handle_event(struct tp_dispatch *tp,
|
||||
struct tp_touch *t,
|
||||
|
|
@ -684,6 +743,12 @@ tp_tfd_handle_event(struct tp_dispatch *tp,
|
|||
break;
|
||||
}
|
||||
|
||||
// /* currently used to prevent TFD while clickpad button is pressed */
|
||||
// /* TODO: consider just inspecting the clickpad state in the POSSIBLE_DRAG
|
||||
// handler to at least gather all state transition decisions in one place? */
|
||||
// if (tp_tfd_should_filter_event(tp, t, event, time, nfingers_down))
|
||||
// return;
|
||||
|
||||
switch(tp->tfd.state) {
|
||||
case TFD_STATE_IDLE:
|
||||
tp_tfd_idle_handle_event(tp, t, event, time, nfingers_down);
|
||||
|
|
@ -833,7 +898,7 @@ tp_tfd_handle_state(struct tp_dispatch *tp, uint64_t time)
|
|||
// if (!tp_tfd_enabled(tp))
|
||||
// return 0;
|
||||
|
||||
/* Handle queued button pressed events from clickpads. */
|
||||
/* Handle queued button pressed events. */
|
||||
if (/* tp->buttons.is_clickpad && */ tp->queued & TOUCHPAD_EVENT_BUTTON_PRESS)
|
||||
tp_tfd_handle_event(tp, NULL, TFD_EVENT_BUTTON, time, active_touches);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue