touchpad: fix multitaps with more than one finger while dragging is enabled

Also permits any number of fingers in the tap that terminates drag-lock.

Signed-off-by: satrmb <10471-satrmb@users.noreply.gitlab.freedesktop.org>
This commit is contained in:
satrmb 2020-07-08 13:32:43 +02:00 committed by Peter Hutterer
parent 0e569077fe
commit 44912aa384
2 changed files with 287 additions and 16 deletions

View file

@ -79,9 +79,18 @@ tap_state_to_str(enum tp_tap_state state)
CASE_RETURN_STRING(TAP_STATE_1FGTAP_DRAGGING_OR_DOUBLETAP);
CASE_RETURN_STRING(TAP_STATE_2FGTAP_DRAGGING_OR_DOUBLETAP);
CASE_RETURN_STRING(TAP_STATE_3FGTAP_DRAGGING_OR_DOUBLETAP);
CASE_RETURN_STRING(TAP_STATE_1FGTAP_DRAGGING_OR_DOUBLETAP_2);
CASE_RETURN_STRING(TAP_STATE_2FGTAP_DRAGGING_OR_DOUBLETAP_2);
CASE_RETURN_STRING(TAP_STATE_3FGTAP_DRAGGING_OR_DOUBLETAP_2);
CASE_RETURN_STRING(TAP_STATE_1FGTAP_DRAGGING_OR_DOUBLETAP_2_RELEASE);
CASE_RETURN_STRING(TAP_STATE_2FGTAP_DRAGGING_OR_DOUBLETAP_2_RELEASE);
CASE_RETURN_STRING(TAP_STATE_3FGTAP_DRAGGING_OR_DOUBLETAP_2_RELEASE);
CASE_RETURN_STRING(TAP_STATE_1FGTAP_DRAGGING_OR_TAP);
CASE_RETURN_STRING(TAP_STATE_2FGTAP_DRAGGING_OR_TAP);
CASE_RETURN_STRING(TAP_STATE_3FGTAP_DRAGGING_OR_TAP);
CASE_RETURN_STRING(TAP_STATE_1FGTAP_DRAGGING_OR_TAP_2);
CASE_RETURN_STRING(TAP_STATE_2FGTAP_DRAGGING_OR_TAP_2);
CASE_RETURN_STRING(TAP_STATE_3FGTAP_DRAGGING_OR_TAP_2);
CASE_RETURN_STRING(TAP_STATE_1FGTAP_DRAGGING_2);
CASE_RETURN_STRING(TAP_STATE_2FGTAP_DRAGGING_2);
CASE_RETURN_STRING(TAP_STATE_3FGTAP_DRAGGING_2);
@ -338,6 +347,8 @@ tp_tap_tapped_handle_event(struct tp_dispatch *tp,
log_tap_bug(tp, t, event);
break;
case TAP_EVENT_PALM:
log_tap_bug(tp, t, event);
break;
case TAP_EVENT_PALM_UP:
break;
}
@ -713,12 +724,14 @@ tp_tap_dragging_or_doubletap_handle_event(struct tp_dispatch *tp,
switch (event) {
case TAP_EVENT_TOUCH: {
enum tp_tap_state dest[3] = {
TAP_STATE_1FGTAP_DRAGGING_2,
TAP_STATE_2FGTAP_DRAGGING_2,
TAP_STATE_3FGTAP_DRAGGING_2,
TAP_STATE_1FGTAP_DRAGGING_OR_DOUBLETAP_2,
TAP_STATE_2FGTAP_DRAGGING_OR_DOUBLETAP_2,
TAP_STATE_3FGTAP_DRAGGING_OR_DOUBLETAP_2,
};
assert(nfingers_tapped >= 1 && nfingers_tapped <= 3);
tp->tap.state = dest[nfingers_tapped - 1];
tp->tap.saved_press_time = time;
tp_tap_set_timer(tp, time);
break;
}
case TAP_EVENT_RELEASE:
@ -769,6 +782,139 @@ tp_tap_dragging_or_doubletap_handle_event(struct tp_dispatch *tp,
}
}
static void
tp_tap_dragging_or_doubletap_2_handle_event(struct tp_dispatch *tp,
struct tp_touch *t,
enum tap_event event, uint64_t time,
int nfingers_tapped)
{
switch (event) {
case TAP_EVENT_TOUCH:
tp_tap_notify(tp,
tp->tap.saved_release_time,
nfingers_tapped,
LIBINPUT_BUTTON_STATE_RELEASED);
tp->tap.state = TAP_STATE_TOUCH_3;
tp->tap.saved_press_time = time;
tp_tap_set_timer(tp, time);
break;
case TAP_EVENT_RELEASE: {
enum tp_tap_state dest[3] = {
TAP_STATE_1FGTAP_DRAGGING_OR_DOUBLETAP_2_RELEASE,
TAP_STATE_2FGTAP_DRAGGING_OR_DOUBLETAP_2_RELEASE,
TAP_STATE_3FGTAP_DRAGGING_OR_DOUBLETAP_2_RELEASE,
};
assert(nfingers_tapped >= 1 && nfingers_tapped <= 3);
tp->tap.state = dest[nfingers_tapped - 1];
/* We are overwriting saved_release_time, but if this is indeed
a multitap with two fingers, then we will need its previous
value for the click release event we withheld just in case
this is still a drag. */
tp->tap.saved_multitap_release_time = tp->tap.saved_release_time;
tp->tap.saved_release_time = time;
tp_tap_set_timer(tp, time);
break;
}
case TAP_EVENT_MOTION:
case TAP_EVENT_TIMEOUT: {
enum tp_tap_state dest[3] = {
TAP_STATE_1FGTAP_DRAGGING_2,
TAP_STATE_2FGTAP_DRAGGING_2,
TAP_STATE_3FGTAP_DRAGGING_2,
};
assert(nfingers_tapped >= 1 && nfingers_tapped <= 3);
tp->tap.state = dest[nfingers_tapped - 1];
break;
}
case TAP_EVENT_BUTTON:
tp->tap.state = TAP_STATE_DEAD;
tp_tap_notify(tp,
tp->tap.saved_release_time,
nfingers_tapped,
LIBINPUT_BUTTON_STATE_RELEASED);
break;
case TAP_EVENT_THUMB:
break;
case TAP_EVENT_PALM: {
enum tp_tap_state dest[3] = {
TAP_STATE_1FGTAP_DRAGGING_OR_DOUBLETAP,
TAP_STATE_2FGTAP_DRAGGING_OR_DOUBLETAP,
TAP_STATE_3FGTAP_DRAGGING_OR_DOUBLETAP,
};
assert(nfingers_tapped >= 1 && nfingers_tapped <= 3);
tp->tap.state = dest[nfingers_tapped - 1];
break;
}
case TAP_EVENT_PALM_UP:
break;
}
}
static void
tp_tap_dragging_or_doubletap_2_release_handle_event(struct tp_dispatch *tp,
struct tp_touch *t,
enum tap_event event,
uint64_t time,
int nfingers_tapped)
{
switch (event) {
case TAP_EVENT_TOUCH: {
enum tp_tap_state dest[3] = {
TAP_STATE_1FGTAP_DRAGGING_2,
TAP_STATE_2FGTAP_DRAGGING_2,
TAP_STATE_3FGTAP_DRAGGING_2,
};
assert(nfingers_tapped >= 1 && nfingers_tapped <= 3);
tp->tap.state = dest[nfingers_tapped - 1];
break;
}
case TAP_EVENT_RELEASE:
tp->tap.state = TAP_STATE_2FGTAP_TAPPED;
tp_tap_notify(tp,
tp->tap.saved_multitap_release_time,
nfingers_tapped,
LIBINPUT_BUTTON_STATE_RELEASED);
tp_tap_notify(tp,
tp->tap.saved_press_time,
2,
LIBINPUT_BUTTON_STATE_PRESSED);
tp_tap_set_timer(tp, time);
break;
case TAP_EVENT_MOTION:
case TAP_EVENT_TIMEOUT: {
enum tp_tap_state dest[3] = {
TAP_STATE_1FGTAP_DRAGGING,
TAP_STATE_2FGTAP_DRAGGING,
TAP_STATE_3FGTAP_DRAGGING,
};
assert(nfingers_tapped >= 1 && nfingers_tapped <= 3);
tp->tap.state = dest[nfingers_tapped - 1];
break;
}
case TAP_EVENT_BUTTON:
tp->tap.state = TAP_STATE_DEAD;
tp_tap_notify(tp,
tp->tap.saved_release_time,
nfingers_tapped,
LIBINPUT_BUTTON_STATE_RELEASED);
break;
case TAP_EVENT_THUMB:
break;
case TAP_EVENT_PALM:
tp->tap.state = TAP_STATE_1FGTAP_TAPPED;
tp_tap_notify(tp,
tp->tap.saved_release_time,
nfingers_tapped,
LIBINPUT_BUTTON_STATE_RELEASED);
tp_tap_notify(tp,
tp->tap.saved_press_time,
1,
LIBINPUT_BUTTON_STATE_PRESSED);
case TAP_EVENT_PALM_UP:
break;
}
}
static void
tp_tap_dragging_handle_event(struct tp_dispatch *tp,
struct tp_touch *t,
@ -851,6 +997,7 @@ tp_tap_dragging_wait_handle_event(struct tp_dispatch *tp,
}
case TAP_EVENT_RELEASE:
case TAP_EVENT_MOTION:
log_tap_bug(tp, t, event);
break;
case TAP_EVENT_TIMEOUT:
tp->tap.state = TAP_STATE_IDLE;
@ -868,6 +1015,7 @@ tp_tap_dragging_wait_handle_event(struct tp_dispatch *tp,
break;
case TAP_EVENT_THUMB:
case TAP_EVENT_PALM:
log_tap_bug(tp, t, event);
break;
case TAP_EVENT_PALM_UP:
break;
@ -876,20 +1024,21 @@ tp_tap_dragging_wait_handle_event(struct tp_dispatch *tp,
static void
tp_tap_dragging_tap_handle_event(struct tp_dispatch *tp,
struct tp_touch *t,
enum tap_event event, uint64_t time,
int nfingers_tapped)
struct tp_touch *t,
enum tap_event event, uint64_t time,
int nfingers_tapped)
{
switch (event) {
case TAP_EVENT_TOUCH: {
enum tp_tap_state dest[3] = {
TAP_STATE_1FGTAP_DRAGGING_2,
TAP_STATE_2FGTAP_DRAGGING_2,
TAP_STATE_3FGTAP_DRAGGING_2,
TAP_STATE_1FGTAP_DRAGGING_OR_TAP_2,
TAP_STATE_2FGTAP_DRAGGING_OR_TAP_2,
TAP_STATE_3FGTAP_DRAGGING_OR_TAP_2,
};
assert(nfingers_tapped >= 1 && nfingers_tapped <= 3);
tp->tap.state = dest[nfingers_tapped - 1];
tp_tap_set_timer(tp, time);
break;
}
case TAP_EVENT_RELEASE:
@ -919,12 +1068,76 @@ tp_tap_dragging_tap_handle_event(struct tp_dispatch *tp,
break;
case TAP_EVENT_THUMB:
break;
case TAP_EVENT_PALM:
case TAP_EVENT_PALM: {
enum tp_tap_state dest[3] = {
TAP_STATE_1FGTAP_DRAGGING_WAIT,
TAP_STATE_2FGTAP_DRAGGING_WAIT,
TAP_STATE_3FGTAP_DRAGGING_WAIT,
};
assert(nfingers_tapped >= 1 && nfingers_tapped <= 3);
tp->tap.state = dest[nfingers_tapped - 1];
break;
}
case TAP_EVENT_PALM_UP:
break;
}
}
static void
tp_tap_dragging_tap_2_handle_event(struct tp_dispatch *tp,
struct tp_touch *t,
enum tap_event event, uint64_t time,
int nfingers_tapped)
{
switch (event) {
case TAP_EVENT_TOUCH:
tp_tap_notify(tp,
tp->tap.saved_release_time,
time,
nfingers_tapped,
LIBINPUT_BUTTON_STATE_RELEASED);
tp->tap.state = TAP_STATE_IDLE;
tp_tap_clear_timer(tp);
tp_tap_move_to_dead(tp, t);
break;
case TAP_EVENT_RELEASE: {
enum tp_tap_state dest[3] = {
TAP_STATE_1FGTAP_DRAGGING_OR_TAP,
TAP_STATE_2FGTAP_DRAGGING_OR_TAP,
TAP_STATE_3FGTAP_DRAGGING_OR_TAP,
};
assert(nfingers_tapped >= 1 && nfingers_tapped <= 3);
tp->tap.state = dest[nfingers_tapped - 1];
tp_tap_set_timer(tp, time);
break;
}
case TAP_EVENT_MOTION:
case TAP_EVENT_TIMEOUT: {
enum tp_tap_state dest[3] = {
TAP_STATE_1FGTAP_DRAGGING_2,
TAP_STATE_2FGTAP_DRAGGING_2,
TAP_STATE_3FGTAP_DRAGGING_2,
};
assert(nfingers_tapped >= 1 && nfingers_tapped <= 3);
tp->tap.state = dest[nfingers_tapped - 1];
break;
}
case TAP_EVENT_BUTTON:
tp->tap.state = TAP_STATE_DEAD;
tp_tap_notify(tp,
time,
nfingers_tapped,
LIBINPUT_BUTTON_STATE_RELEASED);
break;
case TAP_EVENT_THUMB:
break;
case TAP_EVENT_PALM: {
enum tp_tap_state dest[3] = {
TAP_STATE_1FGTAP_DRAGGING_OR_TAP,
TAP_STATE_2FGTAP_DRAGGING_OR_TAP,
TAP_STATE_3FGTAP_DRAGGING_OR_TAP,
};
assert(nfingers_tapped >= 1 && nfingers_tapped <= 3);
tp->tap.state = dest[nfingers_tapped - 1];
break;
}
case TAP_EVENT_PALM_UP:
@ -972,9 +1185,9 @@ tp_tap_dragging2_handle_event(struct tp_dispatch *tp,
break;
case TAP_EVENT_PALM: {
enum tp_tap_state dest[3] = {
TAP_STATE_1FGTAP_DRAGGING_OR_DOUBLETAP,
TAP_STATE_2FGTAP_DRAGGING_OR_DOUBLETAP,
TAP_STATE_3FGTAP_DRAGGING_OR_DOUBLETAP,
TAP_STATE_1FGTAP_DRAGGING,
TAP_STATE_2FGTAP_DRAGGING,
TAP_STATE_3FGTAP_DRAGGING,
};
assert(nfingers_tapped >= 1 && nfingers_tapped <= 3);
tp->tap.state = dest[nfingers_tapped - 1];
@ -1074,6 +1287,33 @@ tp_tap_handle_event(struct tp_dispatch *tp,
tp_tap_dragging_or_doubletap_handle_event(tp, t, event, time,
3);
break;
case TAP_STATE_1FGTAP_DRAGGING_OR_DOUBLETAP_2:
tp_tap_dragging_or_doubletap_2_handle_event(tp, t, event, time,
1);
break;
case TAP_STATE_2FGTAP_DRAGGING_OR_DOUBLETAP_2:
tp_tap_dragging_or_doubletap_2_handle_event(tp, t, event, time,
2);
break;
case TAP_STATE_3FGTAP_DRAGGING_OR_DOUBLETAP_2:
tp_tap_dragging_or_doubletap_2_handle_event(tp, t, event, time,
3);
break;
case TAP_STATE_1FGTAP_DRAGGING_OR_DOUBLETAP_2_RELEASE:
tp_tap_dragging_or_doubletap_2_release_handle_event(tp, t,
event, time,
1);
break;
case TAP_STATE_2FGTAP_DRAGGING_OR_DOUBLETAP_2_RELEASE:
tp_tap_dragging_or_doubletap_2_release_handle_event(tp, t,
event, time,
2);
break;
case TAP_STATE_3FGTAP_DRAGGING_OR_DOUBLETAP_2_RELEASE:
tp_tap_dragging_or_doubletap_2_release_handle_event(tp, t,
event, time,
3);
break;
case TAP_STATE_1FGTAP_DRAGGING:
tp_tap_dragging_handle_event(tp, t, event, time, 1);
break;
@ -1101,6 +1341,15 @@ tp_tap_handle_event(struct tp_dispatch *tp,
case TAP_STATE_3FGTAP_DRAGGING_OR_TAP:
tp_tap_dragging_tap_handle_event(tp, t, event, time, 3);
break;
case TAP_STATE_1FGTAP_DRAGGING_OR_TAP_2:
tp_tap_dragging_tap_2_handle_event(tp, t, event, time, 1);
break;
case TAP_STATE_2FGTAP_DRAGGING_OR_TAP_2:
tp_tap_dragging_tap_2_handle_event(tp, t, event, time, 2);
break;
case TAP_STATE_3FGTAP_DRAGGING_OR_TAP_2:
tp_tap_dragging_tap_2_handle_event(tp, t, event, time, 3);
break;
case TAP_STATE_1FGTAP_DRAGGING_2:
tp_tap_dragging2_handle_event(tp, t, event, time, 1);
break;
@ -1278,9 +1527,18 @@ tp_tap_handle_state(struct tp_dispatch *tp, uint64_t time)
case TAP_STATE_1FGTAP_DRAGGING_OR_DOUBLETAP:
case TAP_STATE_2FGTAP_DRAGGING_OR_DOUBLETAP:
case TAP_STATE_3FGTAP_DRAGGING_OR_DOUBLETAP:
case TAP_STATE_1FGTAP_DRAGGING_OR_DOUBLETAP_2:
case TAP_STATE_2FGTAP_DRAGGING_OR_DOUBLETAP_2:
case TAP_STATE_3FGTAP_DRAGGING_OR_DOUBLETAP_2:
case TAP_STATE_1FGTAP_DRAGGING_OR_DOUBLETAP_2_RELEASE:
case TAP_STATE_2FGTAP_DRAGGING_OR_DOUBLETAP_2_RELEASE:
case TAP_STATE_3FGTAP_DRAGGING_OR_DOUBLETAP_2_RELEASE:
case TAP_STATE_1FGTAP_DRAGGING_OR_TAP:
case TAP_STATE_2FGTAP_DRAGGING_OR_TAP:
case TAP_STATE_3FGTAP_DRAGGING_OR_TAP:
case TAP_STATE_1FGTAP_DRAGGING_OR_TAP_2:
case TAP_STATE_2FGTAP_DRAGGING_OR_TAP_2:
case TAP_STATE_3FGTAP_DRAGGING_OR_TAP_2:
case TAP_STATE_TOUCH_2:
case TAP_STATE_TOUCH_3:
filter_motion = 1;
@ -1621,6 +1879,9 @@ tp_tap_dragging(const struct tp_dispatch *tp)
case TAP_STATE_1FGTAP_DRAGGING_OR_TAP:
case TAP_STATE_2FGTAP_DRAGGING_OR_TAP:
case TAP_STATE_3FGTAP_DRAGGING_OR_TAP:
case TAP_STATE_1FGTAP_DRAGGING_OR_TAP_2:
case TAP_STATE_2FGTAP_DRAGGING_OR_TAP_2:
case TAP_STATE_3FGTAP_DRAGGING_OR_TAP_2:
return true;
default:
return false;

View file

@ -119,9 +119,18 @@ enum tp_tap_state {
TAP_STATE_1FGTAP_DRAGGING_OR_DOUBLETAP,
TAP_STATE_2FGTAP_DRAGGING_OR_DOUBLETAP,
TAP_STATE_3FGTAP_DRAGGING_OR_DOUBLETAP,
TAP_STATE_1FGTAP_DRAGGING_OR_DOUBLETAP_2,
TAP_STATE_2FGTAP_DRAGGING_OR_DOUBLETAP_2,
TAP_STATE_3FGTAP_DRAGGING_OR_DOUBLETAP_2,
TAP_STATE_1FGTAP_DRAGGING_OR_DOUBLETAP_2_RELEASE,
TAP_STATE_2FGTAP_DRAGGING_OR_DOUBLETAP_2_RELEASE,
TAP_STATE_3FGTAP_DRAGGING_OR_DOUBLETAP_2_RELEASE,
TAP_STATE_1FGTAP_DRAGGING_OR_TAP,
TAP_STATE_2FGTAP_DRAGGING_OR_TAP,
TAP_STATE_3FGTAP_DRAGGING_OR_TAP,
TAP_STATE_1FGTAP_DRAGGING_OR_TAP_2,
TAP_STATE_2FGTAP_DRAGGING_OR_TAP_2,
TAP_STATE_3FGTAP_DRAGGING_OR_TAP_2,
TAP_STATE_1FGTAP_DRAGGING,
TAP_STATE_2FGTAP_DRAGGING,
TAP_STATE_3FGTAP_DRAGGING,
@ -421,7 +430,8 @@ struct tp_dispatch {
enum tp_tap_state state;
uint32_t buttons_pressed;
uint64_t saved_press_time,
saved_release_time;
saved_release_time,
saved_multitap_release_time;
enum libinput_config_tap_button_map map;
enum libinput_config_tap_button_map want_map;