From 2ba7e42c136c47d0472a23202c6df3959c3cff74 Mon Sep 17 00:00:00 2001 From: satrmb <10471-satrmb_true-email-is-private_contact-via-web@gitlab.freedesktop.org> Date: Fri, 7 Aug 2020 22:43:10 +0200 Subject: [PATCH] touchpad: allow a hold-and-tap to start a drag, if all fingers are released Signed-off-by: satrmb <10471-satrmb@users.noreply.gitlab.freedesktop.org> --- doc/touchpad-tap-state-machine.svg | 2 +- src/evdev-mt-touchpad-tap.c | 283 +++++++++++++++++++++++------ src/evdev-mt-touchpad.h | 9 + 3 files changed, 241 insertions(+), 53 deletions(-) diff --git a/doc/touchpad-tap-state-machine.svg b/doc/touchpad-tap-state-machine.svg index 6887559f..8429efa4 100644 --- a/doc/touchpad-tap-state-machine.svg +++ b/doc/touchpad-tap-state-machine.svg @@ -1,3 +1,3 @@ -(this section exists for [n] = 1, [n] = 2, and [n] = 3)(this section exists for [m] = 1, [m] = 2, and [m] = 3),for a total of 9 times due to combination with [n]yesnoyesnoyesnonononononononononoyesnononoyesnoyesnoyesyesyesnononononononoyesyesyesnonoyesnonoyesyesyesyesyesyesyesyesyesyesyesyesyesyes
IDLE
IDLE
firstfinger downTOUCH_TOUCHTOUCHsecondfinger downTOUCH_TOUCHTOUCH_2thirdfinger downTOUCH_TOUCHTOUCH_3TOUCH_2_RELEASEyeseitherfinger upyesremainingfinger upanyfinger upTOUCH_3_RELEASEeitherfinger upTOUCH_3_RELEASE_2yesremainingfinger upTOUCH_IDLEyesTOUCH_IDLETOUCH_IDLEyesTOUCH_IDLETOUCH_IDLEpalmTOUCH_DEADeitherfinger palmTOUCH_DEADyesanyfinger palmTOUCH_DEADyeseitherfinger palmTOUCH_DEADyesremainingfinger palmTOUCH_DEADyesremainingfinger palmTOUCH_DEAD2-finger tap3-finger tapyesfinger upTOUCH_IDLE1-finger tapfourthfinger down
IDLE
IDLE
TAPPEDyes2-finger tappalmfinger upbutton [n]pressbutton [n]releaseDRAGGING_OR_DOUBLETAPfinger downtap-and-dragtimeouttimeoutmove >thresholdDRAGGINGpalmfinger upnoyesdrag-lockenabled?DRAGLOCK_WAITDRAGLOCK_CONTINUEfinger uppalmtimeoutmove >thresholddrag-locktimeout1-finger tapyesnonon-palmfinger count== 0?finger down1-finger taptimeouttimeouthold-and-tap enabled?HOLD3-finger tapnohold-and-tap enabled?timeouthold-and-tap enabled?3-finger tapTOUCH_2_HOLDTOUCH_3_HOLDtimeouthold-and-tap enabled?timeoutyesnohold-and-tap enabled?timeouthold-and-tap enabled?palmfinger upTOUCH_DEADTOUCH_IDLEeitherfinger palmeitherfinger upTOUCH_DEADTOUCH_IDLEanyfinger palmanyfinger upTOUCH_DEADTOUCH_IDLETOUCH_TOUCHTOUCH_4_PLUSyesanyfinger palmyesanyfinger upTOUCH_IDLEyesTOUCH_DEADTOUCH_4_PLUS_HOLDtimeouthold-and-tap enabled?anyfinger upTOUCH_IDLEanyfinger palmTOUCH_DEADfourthfinger downTOUCH_TOUCHTOUCH_4_PLUS_RELEASEyesanyfinger palmyesanyfinger upyesTOUCH_DEADTOUCH_IDLEtimeouthold-and-tap enabled?TOUCH_4_PLUS_RELEASE_2timeouthold-and-tap enabled?yesanyfinger palmyesanyfinger upTOUCH_DEADTOUCH_IDLETOUCH_4_PLUS_RELEASE_3timeouthold-and-tap enabled?yesanyfinger palmyesanyfinger upyesTOUCH_DEADTOUCH_IDLE1-finger tap2-finger tap3-finger tapDEADBUTTONclickpadbuttonreleaseall fingersTOUCH_DEADnoyesnon-palmfinger count== 0?clickpadbuttonpressanyfinger upTOUCH_IDLEanyfinger palmmove >thresholdmove >thresholdmove >thresholdmove >thresholdmove >thresholdmove >thresholdmove >thresholdmove >thresholdmove >thresholdhold-and-tap enabled?move >thresholdmove >thresholdhold-and-tap enabled?yesnohold-and-tap enabled?move >thresholdhold-and-tap enabled?3-finger tapmove >thresholdyesnohold-and-tap enabled?move >thresholdyesnohold-and-tap enabled?clickpadbuttonpressclickpadbuttonpressclickpadbuttonpressyesnohold-and-tap enabled?1-finger tapclickpadbuttonpressyesnohold-and-tap enabled?2-finger tapclickpadbuttonpressclickpadbuttonpress3-finger tapyeshold-and-tap enabled?clickpadbuttonpressclickpadbuttonpressclickpadbuttonpressclickpadbuttonpressclickpadbuttonpressclickpadbuttonpressclickpadbuttonpressclickpadbuttonpress1-finger tap3-finger tapbutton [n]releaseBUTTONclickpadbuttonreleaseclickpadbuttonpressbutton [n]releaseclickpadbuttonpressclickpadbuttonpressclickpadbuttonpressclickpadbuttonpressclickpadbuttonpressbutton [n]press
[n] = 1
[n] = 1
[n] = 1
[n] = 1
[n] = 2
[n] = 2
[n] = 3
[n] = 3
notap-and-dragenabled?move >thresholdyesnonon-palmfinger count== 0?nonon-palmfinger count== 0?secondfinger downsecondfinger down1-finger tap2-finger tap
[m] = 1
[m] = 1
yes
[m] = 2
[m] = 2
3-finger tap
[m] = 3
[m] = 3
no[n] == [m]?button [m]pressbutton [m]releaseset tap stateto DEADfinger downTOUCH_TOUCHyeshold-and-tap enabled?TOUCH_DEADnoyesnothat fingerTOUCH_TOUCH?nothat fingerTOUCH_TOUCH?that fingerTOUCH_TOUCH?nothat fingerTOUCH_TOUCH?that fingerTOUCH_TOUCH?nothat fingerTOUCH_TOUCH?that fingerTOUCH_TOUCH?nothat fingerTOUCH_TOUCH?TOUCH_IDLETOUCH_IDLETOUCH_IDLETOUCH_IDLETOUCH_TOUCHfinger count == 0?yesthat fingerTOUCH_TOUCH?nothat fingerTOUCH_TOUCH?TOUCH_IDLEthat fingerTOUCH_TOUCH?nothat fingerTOUCH_TOUCH?nothat fingerTOUCH_TOUCH?that fingerTOUCH_TOUCH?TOUCH_IDLETOUCH_IDLEthat fingerTOUCH_TOUCH?that fingerTOUCH_TOUCH?nothat fingerTOUCH_TOUCH?nothat fingerTOUCH_TOUCH?TOUCH_IDLETOUCH_IDLEnothat fingerTOUCH_TOUCH?nothat fingerTOUCH_TOUCH?TOUCH_IDLETOUCH_TOUCHfinger count == 1?TOUCH_TOUCHfinger count == 2?noTOUCH_TOUCHfinger count == 3?thumbyesnodrag state== IDLE?yesnon-palmfinger count== 1?TOUCH_DEADthumbTOUCH_DEADnoyesnodrag state== IDLE?drag state== IDLE?drag state== IDLE?drag state== IDLE?yesnodrag state== DRAGLOCK_CONTINUE?1-finger tapnoTOUCH_TOUCHfinger count == 3?nohold-and-tap enabled?3-finger tapnohold-and-tap enabled?nohold-and-tap enabled?nonon-palmfinger count== 1?nononon-palmfinger count== 2?nonon-palmfinger count== 3?finger downTOUCH_TOUCHnohold-and-tap enabled?3-finger tapfinger downTOUCH_TOUCHhold-and-tap enabled?finger downTOUCH_TOUCHnohold-and-tap enabled?3-finger tapfinger downTOUCH_TOUCHyeshold-and-tap enabled?finger downTOUCH_TOUCHyeshold-and-tap enabled?finger downTOUCH_TOUCHyeshold-and-tap enabled?1-finger tap2-finger tap3-finger tapall fingersexcept the new oneTOUCH_DEADfinger downTOUCH_TOUCHfinger downTOUCH_TOUCHall fingersTOUCH_DEADno
Viewer does not support full SVG 1.1
\ No newline at end of file +yesnoyesnoyesnonononononononononoyesnononoyesnoyesnoyesyesyesnononononononoyesyesyesnonoyesnonoyesyesyesyesyes(this section exists for [n] = 1, [n] = 2, and [n] = 3)(this section exists for [m] = 1, [m] = 2, and [m] = 3),for a total of 9 times due to combination with [n]yesyesyesyesyesyesyesyesyes
IDLE
IDLE
firstfinger downTOUCH_TOUCHTOUCHsecondfinger downTOUCH_TOUCHTOUCH_2thirdfinger downTOUCH_TOUCHTOUCH_3TOUCH_2_RELEASEyeseitherfinger upyesremainingfinger upanyfinger upTOUCH_3_RELEASEeitherfinger upTOUCH_3_RELEASE_2yesremainingfinger upTOUCH_IDLEyesTOUCH_IDLETOUCH_IDLEyesTOUCH_IDLETOUCH_IDLEpalmTOUCH_DEADeitherfinger palmTOUCH_DEADyesanyfinger palmTOUCH_DEADyeseitherfinger palmTOUCH_DEADyesremainingfinger palmTOUCH_DEADyesremainingfinger palmTOUCH_DEAD2-finger tap3-finger tapyesfinger upTOUCH_IDLE1-finger tapfourthfinger down
IDLE
IDLE
TAPPEDyes2-finger tappalmfinger upbutton [n]pressbutton [n]releaseDRAGGING_OR_DOUBLETAPyesfinger downtap-and-dragtimeouttimeoutmove >thresholdDRAGGINGpalmfinger upnoyesdrag-lockenabled?DRAGLOCK_WAITDRAGLOCK_CONTINUEfinger uppalmtimeoutmove >thresholddrag-locktimeout1-finger tapyesnonon-palmfinger count== 0?finger down1-finger taptimeouttimeouthold-and-tap enabled?HOLD3-finger tapnohold-and-tap enabled?timeouthold-and-tap enabled?3-finger tapTOUCH_2_HOLDTOUCH_3_HOLDtimeouthold-and-tap enabled?timeoutyesnohold-and-tap enabled?timeouthold-and-tap enabled?palmfinger upTOUCH_DEADTOUCH_IDLEeitherfinger palmeitherfinger upTOUCH_DEADTOUCH_IDLEanyfinger palmanyfinger upTOUCH_DEADTOUCH_IDLETOUCH_TOUCHTOUCH_4_PLUSyesanyfinger palmyesanyfinger upTOUCH_IDLEyesTOUCH_DEADTOUCH_4_PLUS_HOLDtimeouthold-and-tap enabled?anyfinger upTOUCH_IDLEanyfinger palmTOUCH_DEADfourthfinger downTOUCH_TOUCHTOUCH_4_PLUS_RELEASEyesanyfinger palmyesanyfinger upyesTOUCH_DEADTOUCH_IDLEtimeouthold-and-tap enabled?TOUCH_4_PLUS_RELEASE_2timeouthold-and-tap enabled?yesanyfinger palmyesanyfinger upTOUCH_DEADTOUCH_IDLETOUCH_4_PLUS_RELEASE_3timeouthold-and-tap enabled?yesanyfinger palmyesanyfinger upyesTOUCH_DEADTOUCH_IDLE1-finger tap2-finger tap3-finger tapDEADBUTTONclickpadbuttonreleaseall fingersTOUCH_DEADnoyesnon-palmfinger count== 0?clickpadbuttonpressanyfinger upTOUCH_IDLEanyfinger palmmove >thresholdmove >thresholdmove >thresholdmove >thresholdmove >thresholdmove >thresholdmove >thresholdmove >thresholdmove >thresholdhold-and-tap enabled?move >thresholdmove >thresholdhold-and-tap enabled?yesnohold-and-tap enabled?move >thresholdhold-and-tap enabled?3-finger tapmove >thresholdyesnohold-and-tap enabled?move >thresholdyesnohold-and-tap enabled?clickpadbuttonpressclickpadbuttonpressclickpadbuttonpressyesnohold-and-tap enabled?1-finger tapclickpadbuttonpressyesnohold-and-tap enabled?2-finger tapclickpadbuttonpressclickpadbuttonpress3-finger tapyeshold-and-tap enabled?clickpadbuttonpressclickpadbuttonpressclickpadbuttonpressclickpadbuttonpressclickpadbuttonpressclickpadbuttonpressclickpadbuttonpressclickpadbuttonpress1-finger tap3-finger tapbutton [n]releaseBUTTONclickpadbuttonreleaseclickpadbuttonpressbutton [n]releaseclickpadbuttonpressclickpadbuttonpressclickpadbuttonpressclickpadbuttonpressclickpadbuttonpressbutton [n]press
[n] = 1
[n] = 1
[n] = 1
[n] = 1
[n] = 2
[n] = 2
[n] = 3
[n] = 3
notap-and-dragenabled?move >thresholdnonon-palmfinger count== 1?nonon-palmfinger count== 0?secondfinger downsecondfinger downDRAGGING_OR_TAPPED1-finger tap2-finger tap
[m] = 1
[m] = 1
yes
[m] = 2
[m] = 2
3-finger tap
[m] = 3
[m] = 3
noyesnon-palmfinger count== 0?finger uppalm
[n] = [m]
[n] = [m]
noyes[n] == [m]?no[n] == [m]?button [m]pressbutton [n]releaseyesclickpadbuttonpressno[n] == [m]?button [m]releasetap-and-dragtimeoutmove >thresholdadditionalfinger downnoyes[n] == [m]?button [m]releaseset tap stateto DEADfinger downTOUCH_TOUCHyeshold-and-tap enabled?TOUCH_DEADnoyesnothat fingerTOUCH_TOUCH?nothat fingerTOUCH_TOUCH?that fingerTOUCH_TOUCH?nothat fingerTOUCH_TOUCH?that fingerTOUCH_TOUCH?nothat fingerTOUCH_TOUCH?that fingerTOUCH_TOUCH?nothat fingerTOUCH_TOUCH?TOUCH_IDLETOUCH_IDLETOUCH_IDLETOUCH_IDLETOUCH_TOUCHfinger count == 0?yesthat fingerTOUCH_TOUCH?nothat fingerTOUCH_TOUCH?TOUCH_IDLEthat fingerTOUCH_TOUCH?nothat fingerTOUCH_TOUCH?nothat fingerTOUCH_TOUCH?that fingerTOUCH_TOUCH?TOUCH_IDLETOUCH_IDLEthat fingerTOUCH_TOUCH?that fingerTOUCH_TOUCH?nothat fingerTOUCH_TOUCH?nothat fingerTOUCH_TOUCH?TOUCH_IDLETOUCH_IDLEnothat fingerTOUCH_TOUCH?nothat fingerTOUCH_TOUCH?TOUCH_IDLETOUCH_TOUCHfinger count == 1?TOUCH_TOUCHfinger count == 2?noTOUCH_TOUCHfinger count == 3?thumbyesnodrag state== IDLE?yesnon-palmfinger count== 1?TOUCH_DEADthumbTOUCH_DEADnoyesnodrag state== IDLE?drag state== IDLE?drag state== IDLE?drag state== IDLE?yesnodrag state== DRAGLOCK_CONTINUE?1-finger tapnoTOUCH_TOUCHfinger count == 3?nohold-and-tap enabled?3-finger tapnohold-and-tap enabled?nohold-and-tap enabled?nonon-palmfinger count== 1?nononon-palmfinger count== 2?nonon-palmfinger count== 3?finger downTOUCH_TOUCHnohold-and-tap enabled?3-finger tapfinger downTOUCH_TOUCHhold-and-tap enabled?finger downTOUCH_TOUCHnohold-and-tap enabled?3-finger tapfinger downTOUCH_TOUCHyeshold-and-tap enabled?finger downTOUCH_TOUCHyeshold-and-tap enabled?finger downTOUCH_TOUCHyeshold-and-tap enabled?1-finger tap2-finger tap3-finger tapall fingersexcept the new oneTOUCH_DEADfinger downTOUCH_TOUCHfinger downTOUCH_TOUCHall fingersTOUCH_DEADno
Viewer does not support full SVG 1.1
\ No newline at end of file diff --git a/src/evdev-mt-touchpad-tap.c b/src/evdev-mt-touchpad-tap.c index 8fa527b0..2977062d 100644 --- a/src/evdev-mt-touchpad-tap.c +++ b/src/evdev-mt-touchpad-tap.c @@ -97,6 +97,15 @@ drag_state_to_str(enum tp_drag_state state) CASE_RETURN_STRING(DRAG_STATE_1FGTAP_DRAGGING); CASE_RETURN_STRING(DRAG_STATE_2FGTAP_DRAGGING); CASE_RETURN_STRING(DRAG_STATE_3FGTAP_DRAGGING); + CASE_RETURN_STRING(DRAG_STATE_1FGTAP_DRAGGING_OR_1FGTAP_TAPPED); + CASE_RETURN_STRING(DRAG_STATE_1FGTAP_DRAGGING_OR_2FGTAP_TAPPED); + CASE_RETURN_STRING(DRAG_STATE_1FGTAP_DRAGGING_OR_3FGTAP_TAPPED); + CASE_RETURN_STRING(DRAG_STATE_2FGTAP_DRAGGING_OR_1FGTAP_TAPPED); + CASE_RETURN_STRING(DRAG_STATE_2FGTAP_DRAGGING_OR_2FGTAP_TAPPED); + CASE_RETURN_STRING(DRAG_STATE_2FGTAP_DRAGGING_OR_3FGTAP_TAPPED); + CASE_RETURN_STRING(DRAG_STATE_3FGTAP_DRAGGING_OR_1FGTAP_TAPPED); + CASE_RETURN_STRING(DRAG_STATE_3FGTAP_DRAGGING_OR_2FGTAP_TAPPED); + CASE_RETURN_STRING(DRAG_STATE_3FGTAP_DRAGGING_OR_3FGTAP_TAPPED); CASE_RETURN_STRING(DRAG_STATE_1FGTAP_DRAGLOCK_WAIT); CASE_RETURN_STRING(DRAG_STATE_2FGTAP_DRAGLOCK_WAIT); CASE_RETURN_STRING(DRAG_STATE_3FGTAP_DRAGLOCK_WAIT); @@ -244,11 +253,7 @@ tp_drag_idle_handle_event(struct tp_dispatch *tp, tp->tap.saved_press_time, 1, LIBINPUT_BUTTON_STATE_PRESSED); - /* taps may end with fingers remaining down, - * those should not start a drag; - * also, the touch in the process of being released - * is still counted for nfingers_down */ - if (tp->tap.drag_enabled && tp->tap.nfingers_down == 1) { + if (tp->tap.drag_enabled) { tp->tap.drag_state = DRAG_STATE_1FGTAP_TAPPED; tp_tap_set_drag_timer(tp, time, 1); } else { @@ -263,7 +268,7 @@ tp_drag_idle_handle_event(struct tp_dispatch *tp, tp->tap.saved_press_time, 2, LIBINPUT_BUTTON_STATE_PRESSED); - if (tp->tap.drag_enabled && tp->tap.nfingers_down == 1) { + if (tp->tap.drag_enabled) { tp->tap.drag_state = DRAG_STATE_2FGTAP_TAPPED; tp_tap_set_drag_timer(tp, time, 2); } else { @@ -278,7 +283,7 @@ tp_drag_idle_handle_event(struct tp_dispatch *tp, tp->tap.saved_press_time, 3, LIBINPUT_BUTTON_STATE_PRESSED); - if (tp->tap.drag_enabled && tp->tap.nfingers_down == 1) { + if (tp->tap.drag_enabled) { tp->tap.drag_state = DRAG_STATE_3FGTAP_TAPPED; tp_tap_set_drag_timer(tp, time, 3); } else { @@ -298,28 +303,43 @@ tp_drag_tapped_handle_event(struct tp_dispatch *tp, int nfingers_tapped) { switch (event) { - case TAP_EVENT_TOUCH: { - enum tp_drag_state dest[3] = { - DRAG_STATE_1FGTAP_DRAGGING_OR_DOUBLETAP, - DRAG_STATE_2FGTAP_DRAGGING_OR_DOUBLETAP, - DRAG_STATE_3FGTAP_DRAGGING_OR_DOUBLETAP, - }; - assert(nfingers_tapped >= 1 && nfingers_tapped <= 3); - tp->tap.drag_state = dest[nfingers_tapped - 1]; - /* saved_release_time may get overwritten by - * a subsequent tap, but then we still need it to end - * the tap that brought us here */ - tp->tap.saved_multitap_release_time = tp->tap.saved_release_time; + case TAP_EVENT_TOUCH: + /* taps may end with fingers remaining down; + * those should not start a drag, unless the remaining + * fingers are lifted as well before any new finger comes down. + * Also, the new finger has already been added to + * tap.nfingers_down, so the check is >1, not >0 */ + if (tp->tap.nfingers_down > 1) { + tp_tap_notify(tp, + tp->tap.saved_release_time, + nfingers_tapped, + LIBINPUT_BUTTON_STATE_RELEASED); + tp->tap.drag_state = DRAG_STATE_IDLE; + break; + + } else { + enum tp_drag_state dest[3] = { + DRAG_STATE_1FGTAP_DRAGGING_OR_DOUBLETAP, + DRAG_STATE_2FGTAP_DRAGGING_OR_DOUBLETAP, + DRAG_STATE_3FGTAP_DRAGGING_OR_DOUBLETAP, + }; + assert(nfingers_tapped >= 1 && nfingers_tapped <= 3); + tp->tap.drag_state = dest[nfingers_tapped - 1]; + /* saved_release_time may get overwritten by + * a subsequent tap, but then we still need it to end + * the tap that brought us here */ + tp->tap.saved_multitap_release_time = tp->tap.saved_release_time; + } break; - } case TAP_EVENT_RELEASE: /* not a bug, just the result of receiving the tap event * that brought us here before the release event that triggered - * the tap event */ + * the tap event; alternatively, this may be a holding finger + * remaining after a hold-and-tap */ break; case TAP_EVENT_MOTION: - log_drag_bug(tp, t, event); - break; + /* taps may end with fingers remaining down, + * with subsequent motion in place of further finger releases */ case TAP_EVENT_TIMEOUT: tp_tap_notify(tp, tp->tap.saved_release_time, @@ -338,11 +358,11 @@ tp_drag_tapped_handle_event(struct tp_dispatch *tp, log_drag_bug(tp, t, event); break; case TAP_EVENT_THUMB: - log_drag_bug(tp, t, event); break; case TAP_EVENT_PALM: /* same as a release event; the palm may have been the last - * touch out of multiple short ones triggering a tap */ + * touch out of multiple short ones triggering a tap, + * or a touch that was holding in a hold-and-tap */ break; case TAP_EVENT_1FGTAP: case TAP_EVENT_2FGTAP: @@ -489,45 +509,162 @@ tp_drag_dragging_handle_event(struct tp_dispatch *tp, case TAP_EVENT_1FGTAP: if (!tp->tap.hold_tap_enabled) log_drag_bug(tp, t, event); - else if (nfingers_tapped != 1) { - tp_tap_notify(tp, - tp->tap.saved_press_time, - 1, - LIBINPUT_BUTTON_STATE_PRESSED); - tp_tap_notify(tp, - tp->tap.saved_release_time, - 1, - LIBINPUT_BUTTON_STATE_RELEASED); + else { + if (nfingers_tapped != 1) + tp_tap_notify(tp, + tp->tap.saved_press_time, + 1, + LIBINPUT_BUTTON_STATE_PRESSED); + /* The release or palm event that triggered this tap event, + * which will follow the tap event, can take us to TAPPED + * if the touch triggering this was the last one */ + enum tp_drag_state dest[3] = { + DRAG_STATE_1FGTAP_DRAGGING_OR_1FGTAP_TAPPED, + DRAG_STATE_2FGTAP_DRAGGING_OR_1FGTAP_TAPPED, + DRAG_STATE_3FGTAP_DRAGGING_OR_1FGTAP_TAPPED, + }; + assert(nfingers_tapped >= 1 && nfingers_tapped <= 3); + tp->tap.drag_state = dest[nfingers_tapped - 1]; + tp_tap_set_drag_timer(tp, time, 1); } break; case TAP_EVENT_2FGTAP: if (!tp->tap.hold_tap_enabled) log_drag_bug(tp, t, event); - else if (nfingers_tapped != 2) { - tp_tap_notify(tp, - tp->tap.saved_press_time, - 2, - LIBINPUT_BUTTON_STATE_PRESSED); - tp_tap_notify(tp, - tp->tap.saved_release_time, - 2, - LIBINPUT_BUTTON_STATE_RELEASED); + else { + if (nfingers_tapped != 2) + tp_tap_notify(tp, + tp->tap.saved_press_time, + 2, + LIBINPUT_BUTTON_STATE_PRESSED); + enum tp_drag_state dest[3] = { + DRAG_STATE_1FGTAP_DRAGGING_OR_2FGTAP_TAPPED, + DRAG_STATE_2FGTAP_DRAGGING_OR_2FGTAP_TAPPED, + DRAG_STATE_3FGTAP_DRAGGING_OR_2FGTAP_TAPPED, + }; + assert(nfingers_tapped >= 1 && nfingers_tapped <= 3); + tp->tap.drag_state = dest[nfingers_tapped - 1]; + tp_tap_set_drag_timer(tp, time, 2); } break; case TAP_EVENT_3FGTAP: if (!tp->tap.hold_tap_enabled) log_drag_bug(tp, t, event); - else if (nfingers_tapped != 3) { - tp_tap_notify(tp, - tp->tap.saved_press_time, - 3, - LIBINPUT_BUTTON_STATE_PRESSED); + else { + if (nfingers_tapped != 3) + tp_tap_notify(tp, + tp->tap.saved_press_time, + 3, + LIBINPUT_BUTTON_STATE_PRESSED); + enum tp_drag_state dest[3] = { + DRAG_STATE_1FGTAP_DRAGGING_OR_3FGTAP_TAPPED, + DRAG_STATE_2FGTAP_DRAGGING_OR_3FGTAP_TAPPED, + DRAG_STATE_3FGTAP_DRAGGING_OR_3FGTAP_TAPPED, + }; + assert(nfingers_tapped >= 1 && nfingers_tapped <= 3); + tp->tap.drag_state = dest[nfingers_tapped - 1]; + tp_tap_set_drag_timer(tp, time, 3); + } + break; + } +} + +static void +tp_drag_dragging_or_tapped_handle_event(struct tp_dispatch *tp, + struct tp_touch *t, + enum tap_event event, uint64_t time, + int nfingers_tapped, + int nfingers_tapped_2) +{ + + switch (event) { + case TAP_EVENT_TOUCH: { + if (nfingers_tapped != nfingers_tapped_2) tp_tap_notify(tp, tp->tap.saved_release_time, - 3, + nfingers_tapped_2, LIBINPUT_BUTTON_STATE_RELEASED); + enum tp_drag_state dest[3] = { + DRAG_STATE_1FGTAP_DRAGGING, + DRAG_STATE_2FGTAP_DRAGGING, + DRAG_STATE_3FGTAP_DRAGGING, + }; + assert(nfingers_tapped >= 1 && nfingers_tapped <= 3); + tp->tap.drag_state = dest[nfingers_tapped - 1]; + break; + } + case TAP_EVENT_RELEASE: + if (tp->tap.nfingers_down == 1) { + if (nfingers_tapped != nfingers_tapped_2) + tp_tap_notify(tp, + time, + nfingers_tapped, + LIBINPUT_BUTTON_STATE_RELEASED); + enum tp_drag_state dest[3] = { + DRAG_STATE_1FGTAP_TAPPED, + DRAG_STATE_2FGTAP_TAPPED, + DRAG_STATE_3FGTAP_TAPPED, + }; + assert(nfingers_tapped_2 >= 1 && + nfingers_tapped_2 <= 3); + tp->tap.drag_state = dest[nfingers_tapped_2 - 1]; } break; + case TAP_EVENT_MOTION: + case TAP_EVENT_TIMEOUT: { + if (nfingers_tapped != nfingers_tapped_2) + tp_tap_notify(tp, + tp->tap.saved_release_time, + nfingers_tapped_2, + LIBINPUT_BUTTON_STATE_RELEASED); + enum tp_drag_state dest[3] = { + DRAG_STATE_1FGTAP_DRAGGING, + DRAG_STATE_2FGTAP_DRAGGING, + DRAG_STATE_3FGTAP_DRAGGING, + }; + assert(nfingers_tapped >= 1 && nfingers_tapped <= 3); + tp->tap.drag_state = dest[nfingers_tapped - 1]; + break; + } + case TAP_EVENT_BUTTON: + if (nfingers_tapped != nfingers_tapped_2) + tp_tap_notify(tp, + tp->tap.saved_release_time, + nfingers_tapped_2, + LIBINPUT_BUTTON_STATE_RELEASED); + tp_tap_notify(tp, + time, + nfingers_tapped, + LIBINPUT_BUTTON_STATE_RELEASED); + tp->tap.drag_state = DRAG_STATE_BUTTON; + break; + case TAP_EVENT_BUTTON_UP: + log_drag_bug(tp, t, event); + break; + case TAP_EVENT_THUMB: + break; + case TAP_EVENT_PALM: + if (tp->tap.nfingers_down == 1) { + if (nfingers_tapped != nfingers_tapped_2) + tp_tap_notify(tp, + time, + nfingers_tapped, + LIBINPUT_BUTTON_STATE_RELEASED); + enum tp_drag_state dest[3] = { + DRAG_STATE_1FGTAP_TAPPED, + DRAG_STATE_2FGTAP_TAPPED, + DRAG_STATE_3FGTAP_TAPPED, + }; + assert(nfingers_tapped_2 >= 1 && + nfingers_tapped_2 <= 3); + tp->tap.drag_state = dest[nfingers_tapped_2 - 1]; + } + break; + case TAP_EVENT_1FGTAP: + case TAP_EVENT_2FGTAP: + case TAP_EVENT_3FGTAP: + log_drag_bug(tp, t, event); + break; } } @@ -733,6 +870,42 @@ tp_drag_handle_event(struct tp_dispatch *tp, case DRAG_STATE_3FGTAP_DRAGGING: tp_drag_dragging_handle_event(tp, t, event, time, 3); break; + case DRAG_STATE_1FGTAP_DRAGGING_OR_1FGTAP_TAPPED: + tp_drag_dragging_or_tapped_handle_event(tp, t, event, time, + 1, 1); + break; + case DRAG_STATE_1FGTAP_DRAGGING_OR_2FGTAP_TAPPED: + tp_drag_dragging_or_tapped_handle_event(tp, t, event, time, + 1, 2); + break; + case DRAG_STATE_1FGTAP_DRAGGING_OR_3FGTAP_TAPPED: + tp_drag_dragging_or_tapped_handle_event(tp, t, event, time, + 1, 3); + break; + case DRAG_STATE_2FGTAP_DRAGGING_OR_1FGTAP_TAPPED: + tp_drag_dragging_or_tapped_handle_event(tp, t, event, time, + 2, 1); + break; + case DRAG_STATE_2FGTAP_DRAGGING_OR_2FGTAP_TAPPED: + tp_drag_dragging_or_tapped_handle_event(tp, t, event, time, + 2, 2); + break; + case DRAG_STATE_2FGTAP_DRAGGING_OR_3FGTAP_TAPPED: + tp_drag_dragging_or_tapped_handle_event(tp, t, event, time, + 2, 3); + break; + case DRAG_STATE_3FGTAP_DRAGGING_OR_1FGTAP_TAPPED: + tp_drag_dragging_or_tapped_handle_event(tp, t, event, time, + 3, 1); + break; + case DRAG_STATE_3FGTAP_DRAGGING_OR_2FGTAP_TAPPED: + tp_drag_dragging_or_tapped_handle_event(tp, t, event, time, + 3, 2); + break; + case DRAG_STATE_3FGTAP_DRAGGING_OR_3FGTAP_TAPPED: + tp_drag_dragging_or_tapped_handle_event(tp, t, event, time, + 3, 3); + break; case DRAG_STATE_1FGTAP_DRAGLOCK_WAIT: tp_drag_draglock_wait_handle_event(tp, t, event, time, 1); break; @@ -1983,6 +2156,15 @@ tp_tap_handle_state(struct tp_dispatch *tp, uint64_t time) case DRAG_STATE_1FGTAP_DRAGGING_OR_DOUBLETAP: case DRAG_STATE_2FGTAP_DRAGGING_OR_DOUBLETAP: case DRAG_STATE_3FGTAP_DRAGGING_OR_DOUBLETAP: + case DRAG_STATE_1FGTAP_DRAGGING_OR_1FGTAP_TAPPED: + case DRAG_STATE_1FGTAP_DRAGGING_OR_2FGTAP_TAPPED: + case DRAG_STATE_1FGTAP_DRAGGING_OR_3FGTAP_TAPPED: + case DRAG_STATE_2FGTAP_DRAGGING_OR_1FGTAP_TAPPED: + case DRAG_STATE_2FGTAP_DRAGGING_OR_2FGTAP_TAPPED: + case DRAG_STATE_2FGTAP_DRAGGING_OR_3FGTAP_TAPPED: + case DRAG_STATE_3FGTAP_DRAGGING_OR_1FGTAP_TAPPED: + case DRAG_STATE_3FGTAP_DRAGGING_OR_2FGTAP_TAPPED: + case DRAG_STATE_3FGTAP_DRAGGING_OR_3FGTAP_TAPPED: case DRAG_STATE_1FGTAP_DRAGLOCK_CONTINUE: case DRAG_STATE_2FGTAP_DRAGLOCK_CONTINUE: case DRAG_STATE_3FGTAP_DRAGLOCK_CONTINUE: @@ -2008,9 +2190,6 @@ tp_tap_handle_state(struct tp_dispatch *tp, uint64_t time) assert(tp->tap.nfingers_down <= tp->nfingers_down); if (tp->nfingers_down == 0 || tp->tap.state == TAP_STATE_IDLE || - tp->tap.drag_state == DRAG_STATE_1FGTAP_TAPPED || - tp->tap.drag_state == DRAG_STATE_2FGTAP_TAPPED || - tp->tap.drag_state == DRAG_STATE_3FGTAP_TAPPED || tp->tap.drag_state == DRAG_STATE_1FGTAP_DRAGLOCK_WAIT || tp->tap.drag_state == DRAG_STATE_2FGTAP_DRAGLOCK_WAIT || tp->tap.drag_state == DRAG_STATE_3FGTAP_DRAGLOCK_WAIT) diff --git a/src/evdev-mt-touchpad.h b/src/evdev-mt-touchpad.h index 1c601886..5cb14a4a 100644 --- a/src/evdev-mt-touchpad.h +++ b/src/evdev-mt-touchpad.h @@ -133,6 +133,15 @@ enum tp_drag_state { DRAG_STATE_1FGTAP_DRAGGING, DRAG_STATE_2FGTAP_DRAGGING, DRAG_STATE_3FGTAP_DRAGGING, + DRAG_STATE_1FGTAP_DRAGGING_OR_1FGTAP_TAPPED, + DRAG_STATE_1FGTAP_DRAGGING_OR_2FGTAP_TAPPED, + DRAG_STATE_1FGTAP_DRAGGING_OR_3FGTAP_TAPPED, + DRAG_STATE_2FGTAP_DRAGGING_OR_1FGTAP_TAPPED, + DRAG_STATE_2FGTAP_DRAGGING_OR_2FGTAP_TAPPED, + DRAG_STATE_2FGTAP_DRAGGING_OR_3FGTAP_TAPPED, + DRAG_STATE_3FGTAP_DRAGGING_OR_1FGTAP_TAPPED, + DRAG_STATE_3FGTAP_DRAGGING_OR_2FGTAP_TAPPED, + DRAG_STATE_3FGTAP_DRAGGING_OR_3FGTAP_TAPPED, DRAG_STATE_1FGTAP_DRAGLOCK_WAIT, DRAG_STATE_2FGTAP_DRAGLOCK_WAIT, DRAG_STATE_3FGTAP_DRAGLOCK_WAIT,