diff --git a/doc/touchpad-tap-state-machine.svg b/doc/touchpad-tap-state-machine.svg index 4d6f64e6..318ff7bb 100644 --- a/doc/touchpad-tap-state-machine.svg +++ b/doc/touchpad-tap-state-machine.svg @@ -1,3 +1,3 @@ -no(this section exists for [n] = 1, [n] = 2, and [n] = 3)nonoyesyesyes
IDLE
IDLE
firstfinger downTOUCH_TOUCHTOUCHsecondfinger downTOUCH_TOUCHTOUCH_2thirdfinger downTOUCH_TOUCHTOUCH_3TOUCH_2_RELEASEeitherfinger upremainingfinger upanyfinger upTOUCH_3_RELEASEeitherfinger upTOUCH_3_RELEASE_2remainingfinger upTOUCH_IDLETOUCH_IDLETOUCH_IDLETOUCH_IDLETOUCH_IDLEpalmTOUCH_DEADeitherfinger palmTOUCH_DEADanyfinger palmTOUCH_DEADeitherfinger palmTOUCH_DEADremainingfinger palmTOUCH_DEADremainingfinger palmTOUCH_DEAD2-finger tap3-finger tapfinger 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 taptimeouttimeoutHOLD3-finger taptimeout3-finger tapTOUCH_2_HOLDTOUCH_3_HOLDtimeouttimeoutyestimeoutpalmfinger upTOUCH_DEADTOUCH_IDLEeitherfinger palmeitherfinger upTOUCH_DEADTOUCH_IDLEanyfinger palmanyfinger upTOUCH_DEADTOUCH_IDLETOUCH_DEADDEADBUTTONclickpadbuttonreleaseall fingersTOUCH_DEADnoyesnon-palmfinger count== 0?clickpadbuttonpressanyfinger upTOUCH_IDLEanyfinger palmmove >thresholdmove >thresholdmove >thresholdmove >thresholdmove >thresholdmove >thresholdmove >thresholdmove >thresholdmove >threshold3-finger tapclickpadbuttonpressclickpadbuttonpressclickpadbuttonpressclickpadbuttonpressclickpadbuttonpressclickpadbuttonpressclickpadbuttonpressclickpadbuttonpressclickpadbuttonpress1-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 downset tap stateto DEADfinger downTOUCH_DEADthumbyesdrag state== IDLE?TOUCH_DEADthumbTOUCH_DEADnodrag state== IDLE?drag state== IDLE?drag state== IDLE?3-finger tapfinger downTOUCH_TOUCH3-finger tapfinger downTOUCH_TOUCHfinger downTOUCH_TOUCH3-finger tapall fingersTOUCH_DEADfourthfinger downTOUCH_DEADto draggingstate machine:move >thresholdnoyesdrag state== IDLE?to draggingstate machine:move >threshold
Viewer does not support full SVG 1.1
\ No newline at end of file +no(this section exists for [n] = 1, [n] = 2, and [n] = 3)nonoyesyesyes
IDLE
IDLE
firstfinger downTOUCH_TOUCHTOUCHsecondfinger downTOUCH_TOUCHTOUCH_2thirdfinger downTOUCH_TOUCHTOUCH_3TOUCH_2_RELEASEeitherfinger upremainingfinger upanyfinger upTOUCH_3_RELEASEeitherfinger upTOUCH_3_RELEASE_2remainingfinger upTOUCH_IDLETOUCH_IDLETOUCH_IDLETOUCH_IDLETOUCH_IDLEpalmTOUCH_DEADeitherfinger palmTOUCH_DEADanyfinger palmTOUCH_DEADeitherfinger palmTOUCH_DEADremainingfinger palmTOUCH_DEADremainingfinger palmTOUCH_DEAD2-finger tap3-finger tapfinger 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 taptimeouttimeoutHOLD3-finger taptimeout3-finger tapTOUCH_2_HOLDTOUCH_3_HOLDtimeouttimeoutyestimeoutpalmfinger upTOUCH_DEADTOUCH_IDLEeitherfinger palmeitherfinger upTOUCH_DEADTOUCH_IDLEanyfinger palmanyfinger upTOUCH_DEADTOUCH_IDLETOUCH_DEADDEADBUTTONclickpadbuttonreleaseall fingersTOUCH_DEADnoyesnon-palmfinger count== 0?clickpadbuttonpressanyfinger upTOUCH_IDLEanyfinger palmmove >thresholdmove >thresholdmove >thresholdmove >thresholdmove >thresholdmove >thresholdmove >thresholdmove >thresholdmove >threshold3-finger tapclickpadbuttonpressclickpadbuttonpressclickpadbuttonpressclickpadbuttonpressclickpadbuttonpressclickpadbuttonpressclickpadbuttonpressclickpadbuttonpressclickpadbuttonpress1-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 downset tap stateto DEADfinger downTOUCH_DEADthumbyesdrag state== IDLE?TOUCH_DEADthumbTOUCH_DEADnodrag state== IDLE?drag state== IDLE?drag state== IDLE?3-finger tapfinger downTOUCH_TOUCH3-finger tapfinger downTOUCH_TOUCHfinger downTOUCH_TOUCH3-finger tapall fingersTOUCH_DEADfourthfinger downTOUCH_DEADto draggingstate machine:move >threshold
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 0db0c626..19913a56 100644 --- a/src/evdev-mt-touchpad-tap.c +++ b/src/evdev-mt-touchpad-tap.c @@ -204,11 +204,13 @@ tp_tap_clear_timer(struct tp_dispatch *tp) } static void -tp_tap_move_to_dead(struct tp_dispatch *tp, struct tp_touch *t) +tp_tap_kill_all_touches(struct tp_dispatch *tp) { - tp->tap.state = TAP_STATE_DEAD; - t->tap.state = TAP_TOUCH_STATE_DEAD; - tp_tap_clear_timer(tp); + struct tp_touch *t; + tp_for_each_touch(tp, t) { + if (t->tap.state == TAP_TOUCH_STATE_TOUCH) + t->tap.state = TAP_TOUCH_STATE_DEAD; + } } static void @@ -552,7 +554,7 @@ tp_drag_draglock_continue_handle_event(struct tp_dispatch *tp, /* ignore taps with more than one finger, they shall * only end drag-lock instead of emitting button events * or starting a new drag */ - tp_tap_move_to_dead(tp, t); + tp->tap.state = TAP_STATE_DEAD; break; } case TAP_EVENT_RELEASE: { @@ -709,9 +711,6 @@ tp_drag_handle_event(struct tp_dispatch *tp, break; } - if (tp->tap.drag_state == DRAG_STATE_BUTTON) - tp_tap_clear_timer(tp); - if (current != tp->tap.drag_state) evdev_log_debug(tp->device, "drag: touch %d (%s), drag state %s → %s → %s\n", @@ -778,14 +777,13 @@ tp_tap_touch_handle_event(struct tp_dispatch *tp, tp->tap.state = TAP_STATE_IDLE; break; case TAP_EVENT_MOTION: - tp_tap_move_to_dead(tp, t); + tp->tap.state = TAP_STATE_DEAD; break; case TAP_EVENT_TIMEOUT: if (tp->tap.drag_state == DRAG_STATE_IDLE) tp->tap.state = TAP_STATE_HOLD; else tp->tap.state = TAP_STATE_DEAD; - tp_tap_clear_timer(tp); tp_gesture_tap_timeout(tp, time); break; case TAP_EVENT_BUTTON: @@ -799,8 +797,6 @@ tp_tap_touch_handle_event(struct tp_dispatch *tp, tp->tap.state = TAP_STATE_IDLE; t->tap.is_thumb = true; tp->tap.nfingers_down--; - t->tap.state = TAP_TOUCH_STATE_DEAD; - tp_tap_clear_timer(tp); } break; case TAP_EVENT_PALM: @@ -830,7 +826,7 @@ tp_tap_hold_handle_event(struct tp_dispatch *tp, tp->tap.state = TAP_STATE_IDLE; break; case TAP_EVENT_MOTION: - tp_tap_move_to_dead(tp, t); + tp->tap.state = TAP_STATE_DEAD; break; case TAP_EVENT_TIMEOUT: break; @@ -844,7 +840,6 @@ tp_tap_hold_handle_event(struct tp_dispatch *tp, tp->tap.state = TAP_STATE_IDLE; t->tap.is_thumb = true; tp->tap.nfingers_down--; - t->tap.state = TAP_TOUCH_STATE_DEAD; break; case TAP_EVENT_PALM: tp->tap.state = TAP_STATE_IDLE; @@ -875,7 +870,7 @@ tp_tap_touch2_handle_event(struct tp_dispatch *tp, tp_tap_set_timer(tp, time); break; case TAP_EVENT_MOTION: - tp_tap_move_to_dead(tp, t); + tp->tap.state = TAP_STATE_DEAD; break; case TAP_EVENT_TIMEOUT: if (tp->tap.drag_state == DRAG_STATE_IDLE) @@ -919,7 +914,7 @@ tp_tap_touch2_hold_handle_event(struct tp_dispatch *tp, tp->tap.state = TAP_STATE_HOLD; break; case TAP_EVENT_MOTION: - tp_tap_move_to_dead(tp, t); + tp->tap.state = TAP_STATE_DEAD; break; case TAP_EVENT_TIMEOUT: break; @@ -950,24 +945,16 @@ tp_tap_touch2_release_handle_event(struct tp_dispatch *tp, switch (event) { case TAP_EVENT_TOUCH: - if (tp->tap.drag_state == DRAG_STATE_IDLE) - tp->tap.state = TAP_STATE_TOUCH_2_HOLD; - else { - /* this cannot be a tap anymore, get the dragging - * state machine out of DRAGGING_OR_DOUBLETAP or - * DRAGLOCK_CONTINUE */ - tp_drag_handle_event(tp, t, TAP_EVENT_MOTION, time); - tp->tap.state = TAP_STATE_DEAD; - } - t->tap.state = TAP_TOUCH_STATE_DEAD; - tp_tap_clear_timer(tp); + tp->tap.state = TAP_STATE_TOUCH_2; + tp->tap.saved_press_time = time; + tp_tap_set_timer(tp, time); break; case TAP_EVENT_RELEASE: tp_drag_handle_event(tp, t, TAP_EVENT_2FGTAP, time); tp->tap.state = TAP_STATE_IDLE; break; case TAP_EVENT_MOTION: - tp_tap_move_to_dead(tp, t); + tp->tap.state = TAP_STATE_DEAD; break; case TAP_EVENT_TIMEOUT: if (tp->tap.drag_state == DRAG_STATE_IDLE) @@ -1011,20 +998,18 @@ tp_tap_touch3_handle_event(struct tp_dispatch *tp, switch (event) { case TAP_EVENT_TOUCH: tp->tap.state = TAP_STATE_DEAD; - tp_tap_clear_timer(tp); /* this cannot be a tap anymore, get the dragging state machine * out of DRAGGING_OR_DOUBLETAP or DRAGLOCK_CONTINUE */ tp_drag_handle_event(tp, t, TAP_EVENT_MOTION, time); break; case TAP_EVENT_MOTION: - tp_tap_move_to_dead(tp, t); + tp->tap.state = TAP_STATE_DEAD; break; case TAP_EVENT_TIMEOUT: if (tp->tap.drag_state == DRAG_STATE_IDLE) tp->tap.state = TAP_STATE_TOUCH_3_HOLD; else tp->tap.state = TAP_STATE_DEAD; - tp_tap_clear_timer(tp); tp_gesture_tap_timeout(tp, time); break; case TAP_EVENT_RELEASE: @@ -1065,7 +1050,7 @@ tp_tap_touch3_hold_handle_event(struct tp_dispatch *tp, tp->tap.state = TAP_STATE_TOUCH_2_HOLD; break; case TAP_EVENT_MOTION: - tp_tap_move_to_dead(tp, t); + tp->tap.state = TAP_STATE_DEAD; break; case TAP_EVENT_TIMEOUT: break; @@ -1107,7 +1092,7 @@ tp_tap_touch3_release_handle_event(struct tp_dispatch *tp, break; case TAP_EVENT_MOTION: tp_drag_handle_event(tp, t, TAP_EVENT_3FGTAP, time); - tp_tap_move_to_dead(tp, t); + tp->tap.state = TAP_STATE_DEAD; break; case TAP_EVENT_TIMEOUT: tp_drag_handle_event(tp, t, TAP_EVENT_3FGTAP, time); @@ -1155,7 +1140,7 @@ tp_tap_touch3_release2_handle_event(struct tp_dispatch *tp, break; case TAP_EVENT_MOTION: tp_drag_handle_event(tp, t, TAP_EVENT_3FGTAP, time); - tp_tap_move_to_dead(tp, t); + tp->tap.state = TAP_STATE_DEAD; break; case TAP_EVENT_TIMEOUT: tp_drag_handle_event(tp, t, TAP_EVENT_3FGTAP, time); @@ -1329,6 +1314,11 @@ tp_tap_handle_event(struct tp_dispatch *tp, tp->tap.drag_state == DRAG_STATE_3FGTAP_DRAGGING || tp->tap.drag_state == DRAG_STATE_BUTTON)) tp_tap_clear_timer(tp); + + if ((tp->tap.state == TAP_STATE_IDLE || + tp->tap.state == TAP_STATE_BUTTON || + tp->tap.state == TAP_STATE_DEAD)) + tp_tap_kill_all_touches(tp); } static bool @@ -1389,10 +1379,6 @@ tp_tap_handle_state(struct tp_dispatch *tp, uint64_t time) if (!t->dirty || t->state == TOUCH_NONE) continue; - if (tp->buttons.is_clickpad && - tp->queued & TOUCHPAD_EVENT_BUTTON_PRESS) - t->tap.state = TAP_TOUCH_STATE_DEAD; - /* If a touch was considered thumb for tapping once, we * ignore it for the rest of lifetime */ if (t->tap.is_thumb) @@ -1439,15 +1425,10 @@ tp_tap_handle_state(struct tp_dispatch *tp, uint64_t time) tp_tap_handle_event(tp, t, TAP_EVENT_THUMB, time); } else if (tp->tap.state != TAP_STATE_IDLE && tp_tap_exceeds_motion_threshold(tp, t)) { - struct tp_touch *tmp; /* Any touch exceeding the threshold turns all * touches into DEAD */ - tp_for_each_touch(tp, tmp) { - if (tmp->tap.state == TAP_TOUCH_STATE_TOUCH) - tmp->tap.state = TAP_TOUCH_STATE_DEAD; - } - + tp_tap_kill_all_touches(tp); tp_tap_handle_event(tp, t, TAP_EVENT_MOTION, time); } } @@ -1512,17 +1493,8 @@ static void tp_tap_handle_timeout(uint64_t time, void *data) { struct tp_dispatch *tp = data; - struct tp_touch *t; tp_tap_handle_event(tp, NULL, TAP_EVENT_TIMEOUT, time); - - tp_for_each_touch(tp, t) { - if (t->state == TOUCH_NONE || - t->tap.state == TAP_TOUCH_STATE_IDLE) - continue; - - t->tap.state = TAP_TOUCH_STATE_DEAD; - } } static void diff --git a/src/evdev-mt-touchpad.h b/src/evdev-mt-touchpad.h index d9d75867..e88ccfed 100644 --- a/src/evdev-mt-touchpad.h +++ b/src/evdev-mt-touchpad.h @@ -140,7 +140,8 @@ enum tp_drag_state { enum tp_tap_touch_state { TAP_TOUCH_STATE_IDLE = 16, /**< not in touch */ TAP_TOUCH_STATE_TOUCH, /**< touching, may tap */ - TAP_TOUCH_STATE_DEAD, /**< exceeded motion/timeout */ + TAP_TOUCH_STATE_DEAD, /**< exceeded motion, + or clickpad button pressed */ }; /* For edge scrolling, so we only care about right and bottom */