1a46c0ec8Sopenharmony_ci/* 2a46c0ec8Sopenharmony_ci * Copyright © 2013-2015 Red Hat, Inc. 3a46c0ec8Sopenharmony_ci * 4a46c0ec8Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 5a46c0ec8Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 6a46c0ec8Sopenharmony_ci * to deal in the Software without restriction, including without limitation 7a46c0ec8Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8a46c0ec8Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 9a46c0ec8Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 10a46c0ec8Sopenharmony_ci * 11a46c0ec8Sopenharmony_ci * The above copyright notice and this permission notice (including the next 12a46c0ec8Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 13a46c0ec8Sopenharmony_ci * Software. 14a46c0ec8Sopenharmony_ci * 15a46c0ec8Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16a46c0ec8Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17a46c0ec8Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18a46c0ec8Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19a46c0ec8Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20a46c0ec8Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21a46c0ec8Sopenharmony_ci * DEALINGS IN THE SOFTWARE. 22a46c0ec8Sopenharmony_ci */ 23a46c0ec8Sopenharmony_ci 24a46c0ec8Sopenharmony_ci#include "config.h" 25a46c0ec8Sopenharmony_ci 26a46c0ec8Sopenharmony_ci#include <assert.h> 27a46c0ec8Sopenharmony_ci#include <stdbool.h> 28a46c0ec8Sopenharmony_ci#include <stdio.h> 29a46c0ec8Sopenharmony_ci 30a46c0ec8Sopenharmony_ci#include "evdev-mt-touchpad.h" 31a46c0ec8Sopenharmony_ci 32a46c0ec8Sopenharmony_ci#define DEFAULT_TAP_TIMEOUT_PERIOD ms2us(180) 33a46c0ec8Sopenharmony_ci#define DEFAULT_DRAG_TIMEOUT_PERIOD_BASE ms2us(160) 34a46c0ec8Sopenharmony_ci#define DEFAULT_DRAG_TIMEOUT_PERIOD_PERFINGER ms2us(20) 35a46c0ec8Sopenharmony_ci#define DEFAULT_DRAGLOCK_TIMEOUT_PERIOD ms2us(300) 36a46c0ec8Sopenharmony_ci#define DEFAULT_TAP_MOVE_THRESHOLD 1.3 /* mm */ 37a46c0ec8Sopenharmony_ci 38a46c0ec8Sopenharmony_cienum tap_event { 39a46c0ec8Sopenharmony_ci TAP_EVENT_TOUCH = 12, 40a46c0ec8Sopenharmony_ci TAP_EVENT_MOTION, 41a46c0ec8Sopenharmony_ci TAP_EVENT_RELEASE, 42a46c0ec8Sopenharmony_ci TAP_EVENT_BUTTON, 43a46c0ec8Sopenharmony_ci TAP_EVENT_TIMEOUT, 44a46c0ec8Sopenharmony_ci TAP_EVENT_THUMB, 45a46c0ec8Sopenharmony_ci TAP_EVENT_PALM, 46a46c0ec8Sopenharmony_ci TAP_EVENT_PALM_UP, 47a46c0ec8Sopenharmony_ci}; 48a46c0ec8Sopenharmony_ci 49a46c0ec8Sopenharmony_ci/***************************************** 50a46c0ec8Sopenharmony_ci * DO NOT EDIT THIS FILE! 51a46c0ec8Sopenharmony_ci * 52a46c0ec8Sopenharmony_ci * Look at the state diagram in doc/touchpad-tap-state-machine.svg 53a46c0ec8Sopenharmony_ci * (generated with https://www.diagrams.net) 54a46c0ec8Sopenharmony_ci * 55a46c0ec8Sopenharmony_ci * Any changes in this file must be represented in the diagram. 56a46c0ec8Sopenharmony_ci */ 57a46c0ec8Sopenharmony_ci 58a46c0ec8Sopenharmony_cistatic inline const char* 59a46c0ec8Sopenharmony_citap_state_to_str(enum tp_tap_state state) 60a46c0ec8Sopenharmony_ci{ 61a46c0ec8Sopenharmony_ci switch(state) { 62a46c0ec8Sopenharmony_ci CASE_RETURN_STRING(TAP_STATE_IDLE); 63a46c0ec8Sopenharmony_ci CASE_RETURN_STRING(TAP_STATE_HOLD); 64a46c0ec8Sopenharmony_ci CASE_RETURN_STRING(TAP_STATE_TOUCH); 65a46c0ec8Sopenharmony_ci CASE_RETURN_STRING(TAP_STATE_1FGTAP_TAPPED); 66a46c0ec8Sopenharmony_ci CASE_RETURN_STRING(TAP_STATE_2FGTAP_TAPPED); 67a46c0ec8Sopenharmony_ci CASE_RETURN_STRING(TAP_STATE_3FGTAP_TAPPED); 68a46c0ec8Sopenharmony_ci CASE_RETURN_STRING(TAP_STATE_TOUCH_2); 69a46c0ec8Sopenharmony_ci CASE_RETURN_STRING(TAP_STATE_TOUCH_2_HOLD); 70a46c0ec8Sopenharmony_ci CASE_RETURN_STRING(TAP_STATE_TOUCH_2_RELEASE); 71a46c0ec8Sopenharmony_ci CASE_RETURN_STRING(TAP_STATE_TOUCH_3); 72a46c0ec8Sopenharmony_ci CASE_RETURN_STRING(TAP_STATE_TOUCH_3_HOLD); 73a46c0ec8Sopenharmony_ci CASE_RETURN_STRING(TAP_STATE_TOUCH_3_RELEASE); 74a46c0ec8Sopenharmony_ci CASE_RETURN_STRING(TAP_STATE_TOUCH_3_RELEASE_2); 75a46c0ec8Sopenharmony_ci CASE_RETURN_STRING(TAP_STATE_1FGTAP_DRAGGING); 76a46c0ec8Sopenharmony_ci CASE_RETURN_STRING(TAP_STATE_2FGTAP_DRAGGING); 77a46c0ec8Sopenharmony_ci CASE_RETURN_STRING(TAP_STATE_3FGTAP_DRAGGING); 78a46c0ec8Sopenharmony_ci CASE_RETURN_STRING(TAP_STATE_1FGTAP_DRAGGING_WAIT); 79a46c0ec8Sopenharmony_ci CASE_RETURN_STRING(TAP_STATE_2FGTAP_DRAGGING_WAIT); 80a46c0ec8Sopenharmony_ci CASE_RETURN_STRING(TAP_STATE_3FGTAP_DRAGGING_WAIT); 81a46c0ec8Sopenharmony_ci CASE_RETURN_STRING(TAP_STATE_1FGTAP_DRAGGING_OR_DOUBLETAP); 82a46c0ec8Sopenharmony_ci CASE_RETURN_STRING(TAP_STATE_2FGTAP_DRAGGING_OR_DOUBLETAP); 83a46c0ec8Sopenharmony_ci CASE_RETURN_STRING(TAP_STATE_3FGTAP_DRAGGING_OR_DOUBLETAP); 84a46c0ec8Sopenharmony_ci CASE_RETURN_STRING(TAP_STATE_1FGTAP_DRAGGING_OR_TAP); 85a46c0ec8Sopenharmony_ci CASE_RETURN_STRING(TAP_STATE_2FGTAP_DRAGGING_OR_TAP); 86a46c0ec8Sopenharmony_ci CASE_RETURN_STRING(TAP_STATE_3FGTAP_DRAGGING_OR_TAP); 87a46c0ec8Sopenharmony_ci CASE_RETURN_STRING(TAP_STATE_1FGTAP_DRAGGING_2); 88a46c0ec8Sopenharmony_ci CASE_RETURN_STRING(TAP_STATE_2FGTAP_DRAGGING_2); 89a46c0ec8Sopenharmony_ci CASE_RETURN_STRING(TAP_STATE_3FGTAP_DRAGGING_2); 90a46c0ec8Sopenharmony_ci CASE_RETURN_STRING(TAP_STATE_DEAD); 91a46c0ec8Sopenharmony_ci } 92a46c0ec8Sopenharmony_ci return NULL; 93a46c0ec8Sopenharmony_ci} 94a46c0ec8Sopenharmony_ci 95a46c0ec8Sopenharmony_cistatic inline const char* 96a46c0ec8Sopenharmony_citap_event_to_str(enum tap_event event) 97a46c0ec8Sopenharmony_ci{ 98a46c0ec8Sopenharmony_ci switch(event) { 99a46c0ec8Sopenharmony_ci CASE_RETURN_STRING(TAP_EVENT_TOUCH); 100a46c0ec8Sopenharmony_ci CASE_RETURN_STRING(TAP_EVENT_MOTION); 101a46c0ec8Sopenharmony_ci CASE_RETURN_STRING(TAP_EVENT_RELEASE); 102a46c0ec8Sopenharmony_ci CASE_RETURN_STRING(TAP_EVENT_TIMEOUT); 103a46c0ec8Sopenharmony_ci CASE_RETURN_STRING(TAP_EVENT_BUTTON); 104a46c0ec8Sopenharmony_ci CASE_RETURN_STRING(TAP_EVENT_THUMB); 105a46c0ec8Sopenharmony_ci CASE_RETURN_STRING(TAP_EVENT_PALM); 106a46c0ec8Sopenharmony_ci CASE_RETURN_STRING(TAP_EVENT_PALM_UP); 107a46c0ec8Sopenharmony_ci } 108a46c0ec8Sopenharmony_ci return NULL; 109a46c0ec8Sopenharmony_ci} 110a46c0ec8Sopenharmony_ci 111a46c0ec8Sopenharmony_cistatic inline void 112a46c0ec8Sopenharmony_cilog_tap_bug(struct tp_dispatch *tp, struct tp_touch *t, enum tap_event event) 113a46c0ec8Sopenharmony_ci{ 114a46c0ec8Sopenharmony_ci evdev_log_bug_libinput(tp->device, 115a46c0ec8Sopenharmony_ci "%d: invalid tap event %s in state %s\n", 116a46c0ec8Sopenharmony_ci t->index, 117a46c0ec8Sopenharmony_ci tap_event_to_str(event), 118a46c0ec8Sopenharmony_ci tap_state_to_str(tp->tap.state)); 119a46c0ec8Sopenharmony_ci 120a46c0ec8Sopenharmony_ci} 121a46c0ec8Sopenharmony_ci 122a46c0ec8Sopenharmony_cistatic void 123a46c0ec8Sopenharmony_citp_tap_notify(struct tp_dispatch *tp, 124a46c0ec8Sopenharmony_ci uint64_t time, 125a46c0ec8Sopenharmony_ci int nfingers, 126a46c0ec8Sopenharmony_ci enum libinput_button_state state) 127a46c0ec8Sopenharmony_ci{ 128a46c0ec8Sopenharmony_ci int32_t button; 129a46c0ec8Sopenharmony_ci int32_t button_map[2][3] = { 130a46c0ec8Sopenharmony_ci { BTN_LEFT, BTN_RIGHT, BTN_MIDDLE }, 131a46c0ec8Sopenharmony_ci { BTN_LEFT, BTN_MIDDLE, BTN_RIGHT }, 132a46c0ec8Sopenharmony_ci }; 133a46c0ec8Sopenharmony_ci 134a46c0ec8Sopenharmony_ci assert(tp->tap.map < ARRAY_LENGTH(button_map)); 135a46c0ec8Sopenharmony_ci 136a46c0ec8Sopenharmony_ci if (nfingers < 1 || nfingers > 3) 137a46c0ec8Sopenharmony_ci return; 138a46c0ec8Sopenharmony_ci 139a46c0ec8Sopenharmony_ci button = button_map[tp->tap.map][nfingers - 1]; 140a46c0ec8Sopenharmony_ci 141a46c0ec8Sopenharmony_ci if (state == LIBINPUT_BUTTON_STATE_PRESSED) 142a46c0ec8Sopenharmony_ci tp->tap.buttons_pressed |= bit(nfingers); 143a46c0ec8Sopenharmony_ci else 144a46c0ec8Sopenharmony_ci tp->tap.buttons_pressed &= ~bit(nfingers); 145a46c0ec8Sopenharmony_ci 146a46c0ec8Sopenharmony_ci evdev_pointer_notify_button(tp->device, 147a46c0ec8Sopenharmony_ci time, 148a46c0ec8Sopenharmony_ci button, 149a46c0ec8Sopenharmony_ci state); 150a46c0ec8Sopenharmony_ci} 151a46c0ec8Sopenharmony_ci 152a46c0ec8Sopenharmony_cistatic void 153a46c0ec8Sopenharmony_citp_tap_set_timer(struct tp_dispatch *tp, uint64_t time) 154a46c0ec8Sopenharmony_ci{ 155a46c0ec8Sopenharmony_ci libinput_timer_set(&tp->tap.timer, time + DEFAULT_TAP_TIMEOUT_PERIOD); 156a46c0ec8Sopenharmony_ci} 157a46c0ec8Sopenharmony_ci 158a46c0ec8Sopenharmony_cistatic void 159a46c0ec8Sopenharmony_citp_tap_set_drag_timer(struct tp_dispatch *tp, uint64_t time, 160a46c0ec8Sopenharmony_ci int nfingers_tapped) 161a46c0ec8Sopenharmony_ci{ 162a46c0ec8Sopenharmony_ci libinput_timer_set(&tp->tap.timer, 163a46c0ec8Sopenharmony_ci time + DEFAULT_DRAG_TIMEOUT_PERIOD_BASE + 164a46c0ec8Sopenharmony_ci (nfingers_tapped * 165a46c0ec8Sopenharmony_ci DEFAULT_DRAG_TIMEOUT_PERIOD_PERFINGER)); 166a46c0ec8Sopenharmony_ci} 167a46c0ec8Sopenharmony_ci 168a46c0ec8Sopenharmony_cistatic void 169a46c0ec8Sopenharmony_citp_tap_set_draglock_timer(struct tp_dispatch *tp, uint64_t time) 170a46c0ec8Sopenharmony_ci{ 171a46c0ec8Sopenharmony_ci libinput_timer_set(&tp->tap.timer, 172a46c0ec8Sopenharmony_ci time + DEFAULT_DRAGLOCK_TIMEOUT_PERIOD); 173a46c0ec8Sopenharmony_ci} 174a46c0ec8Sopenharmony_ci 175a46c0ec8Sopenharmony_cistatic void 176a46c0ec8Sopenharmony_citp_tap_clear_timer(struct tp_dispatch *tp) 177a46c0ec8Sopenharmony_ci{ 178a46c0ec8Sopenharmony_ci libinput_timer_cancel(&tp->tap.timer); 179a46c0ec8Sopenharmony_ci} 180a46c0ec8Sopenharmony_ci 181a46c0ec8Sopenharmony_cistatic void 182a46c0ec8Sopenharmony_citp_tap_move_to_dead(struct tp_dispatch *tp, struct tp_touch *t) 183a46c0ec8Sopenharmony_ci{ 184a46c0ec8Sopenharmony_ci tp->tap.state = TAP_STATE_DEAD; 185a46c0ec8Sopenharmony_ci t->tap.state = TAP_TOUCH_STATE_DEAD; 186a46c0ec8Sopenharmony_ci tp_tap_clear_timer(tp); 187a46c0ec8Sopenharmony_ci} 188a46c0ec8Sopenharmony_ci 189a46c0ec8Sopenharmony_cistatic void 190a46c0ec8Sopenharmony_citp_tap_idle_handle_event(struct tp_dispatch *tp, 191a46c0ec8Sopenharmony_ci struct tp_touch *t, 192a46c0ec8Sopenharmony_ci enum tap_event event, uint64_t time) 193a46c0ec8Sopenharmony_ci{ 194a46c0ec8Sopenharmony_ci switch (event) { 195a46c0ec8Sopenharmony_ci case TAP_EVENT_TOUCH: 196a46c0ec8Sopenharmony_ci tp->tap.state = TAP_STATE_TOUCH; 197a46c0ec8Sopenharmony_ci tp->tap.saved_press_time = time; 198a46c0ec8Sopenharmony_ci tp_tap_set_timer(tp, time); 199a46c0ec8Sopenharmony_ci break; 200a46c0ec8Sopenharmony_ci case TAP_EVENT_RELEASE: 201a46c0ec8Sopenharmony_ci break; 202a46c0ec8Sopenharmony_ci case TAP_EVENT_MOTION: 203a46c0ec8Sopenharmony_ci log_tap_bug(tp, t, event); 204a46c0ec8Sopenharmony_ci break; 205a46c0ec8Sopenharmony_ci case TAP_EVENT_TIMEOUT: 206a46c0ec8Sopenharmony_ci break; 207a46c0ec8Sopenharmony_ci case TAP_EVENT_BUTTON: 208a46c0ec8Sopenharmony_ci tp->tap.state = TAP_STATE_DEAD; 209a46c0ec8Sopenharmony_ci break; 210a46c0ec8Sopenharmony_ci case TAP_EVENT_THUMB: 211a46c0ec8Sopenharmony_ci log_tap_bug(tp, t, event); 212a46c0ec8Sopenharmony_ci break; 213a46c0ec8Sopenharmony_ci case TAP_EVENT_PALM: 214a46c0ec8Sopenharmony_ci tp->tap.state = TAP_STATE_IDLE; 215a46c0ec8Sopenharmony_ci break; 216a46c0ec8Sopenharmony_ci case TAP_EVENT_PALM_UP: 217a46c0ec8Sopenharmony_ci break; 218a46c0ec8Sopenharmony_ci } 219a46c0ec8Sopenharmony_ci} 220a46c0ec8Sopenharmony_ci 221a46c0ec8Sopenharmony_cistatic void 222a46c0ec8Sopenharmony_citp_tap_touch_handle_event(struct tp_dispatch *tp, 223a46c0ec8Sopenharmony_ci struct tp_touch *t, 224a46c0ec8Sopenharmony_ci enum tap_event event, uint64_t time) 225a46c0ec8Sopenharmony_ci{ 226a46c0ec8Sopenharmony_ci 227a46c0ec8Sopenharmony_ci switch (event) { 228a46c0ec8Sopenharmony_ci case TAP_EVENT_TOUCH: 229a46c0ec8Sopenharmony_ci tp->tap.state = TAP_STATE_TOUCH_2; 230a46c0ec8Sopenharmony_ci tp->tap.saved_press_time = time; 231a46c0ec8Sopenharmony_ci tp_tap_set_timer(tp, time); 232a46c0ec8Sopenharmony_ci break; 233a46c0ec8Sopenharmony_ci case TAP_EVENT_RELEASE: 234a46c0ec8Sopenharmony_ci tp_tap_notify(tp, 235a46c0ec8Sopenharmony_ci tp->tap.saved_press_time, 236a46c0ec8Sopenharmony_ci 1, 237a46c0ec8Sopenharmony_ci LIBINPUT_BUTTON_STATE_PRESSED); 238a46c0ec8Sopenharmony_ci if (tp->tap.drag_enabled) { 239a46c0ec8Sopenharmony_ci tp->tap.state = TAP_STATE_1FGTAP_TAPPED; 240a46c0ec8Sopenharmony_ci tp->tap.saved_release_time = time; 241a46c0ec8Sopenharmony_ci tp_tap_set_drag_timer(tp, time, 1); 242a46c0ec8Sopenharmony_ci } else { 243a46c0ec8Sopenharmony_ci tp_tap_notify(tp, 244a46c0ec8Sopenharmony_ci time, 245a46c0ec8Sopenharmony_ci 1, 246a46c0ec8Sopenharmony_ci LIBINPUT_BUTTON_STATE_RELEASED); 247a46c0ec8Sopenharmony_ci tp->tap.state = TAP_STATE_IDLE; 248a46c0ec8Sopenharmony_ci } 249a46c0ec8Sopenharmony_ci break; 250a46c0ec8Sopenharmony_ci case TAP_EVENT_MOTION: 251a46c0ec8Sopenharmony_ci tp_tap_move_to_dead(tp, t); 252a46c0ec8Sopenharmony_ci break; 253a46c0ec8Sopenharmony_ci case TAP_EVENT_TIMEOUT: 254a46c0ec8Sopenharmony_ci tp->tap.state = TAP_STATE_HOLD; 255a46c0ec8Sopenharmony_ci tp_tap_clear_timer(tp); 256a46c0ec8Sopenharmony_ci tp_gesture_tap_timeout(tp, time); 257a46c0ec8Sopenharmony_ci break; 258a46c0ec8Sopenharmony_ci case TAP_EVENT_BUTTON: 259a46c0ec8Sopenharmony_ci tp->tap.state = TAP_STATE_DEAD; 260a46c0ec8Sopenharmony_ci break; 261a46c0ec8Sopenharmony_ci case TAP_EVENT_THUMB: 262a46c0ec8Sopenharmony_ci tp->tap.state = TAP_STATE_IDLE; 263a46c0ec8Sopenharmony_ci t->tap.is_thumb = true; 264a46c0ec8Sopenharmony_ci tp->tap.nfingers_down--; 265a46c0ec8Sopenharmony_ci t->tap.state = TAP_TOUCH_STATE_DEAD; 266a46c0ec8Sopenharmony_ci tp_tap_clear_timer(tp); 267a46c0ec8Sopenharmony_ci break; 268a46c0ec8Sopenharmony_ci case TAP_EVENT_PALM: 269a46c0ec8Sopenharmony_ci tp->tap.state = TAP_STATE_IDLE; 270a46c0ec8Sopenharmony_ci tp_tap_clear_timer(tp); 271a46c0ec8Sopenharmony_ci break; 272a46c0ec8Sopenharmony_ci case TAP_EVENT_PALM_UP: 273a46c0ec8Sopenharmony_ci break; 274a46c0ec8Sopenharmony_ci } 275a46c0ec8Sopenharmony_ci} 276a46c0ec8Sopenharmony_ci 277a46c0ec8Sopenharmony_cistatic void 278a46c0ec8Sopenharmony_citp_tap_hold_handle_event(struct tp_dispatch *tp, 279a46c0ec8Sopenharmony_ci struct tp_touch *t, 280a46c0ec8Sopenharmony_ci enum tap_event event, uint64_t time) 281a46c0ec8Sopenharmony_ci{ 282a46c0ec8Sopenharmony_ci 283a46c0ec8Sopenharmony_ci switch (event) { 284a46c0ec8Sopenharmony_ci case TAP_EVENT_TOUCH: 285a46c0ec8Sopenharmony_ci tp->tap.state = TAP_STATE_TOUCH_2; 286a46c0ec8Sopenharmony_ci tp->tap.saved_press_time = time; 287a46c0ec8Sopenharmony_ci tp_tap_set_timer(tp, time); 288a46c0ec8Sopenharmony_ci break; 289a46c0ec8Sopenharmony_ci case TAP_EVENT_RELEASE: 290a46c0ec8Sopenharmony_ci tp->tap.state = TAP_STATE_IDLE; 291a46c0ec8Sopenharmony_ci break; 292a46c0ec8Sopenharmony_ci case TAP_EVENT_MOTION: 293a46c0ec8Sopenharmony_ci tp_tap_move_to_dead(tp, t); 294a46c0ec8Sopenharmony_ci break; 295a46c0ec8Sopenharmony_ci case TAP_EVENT_TIMEOUT: 296a46c0ec8Sopenharmony_ci break; 297a46c0ec8Sopenharmony_ci case TAP_EVENT_BUTTON: 298a46c0ec8Sopenharmony_ci tp->tap.state = TAP_STATE_DEAD; 299a46c0ec8Sopenharmony_ci break; 300a46c0ec8Sopenharmony_ci case TAP_EVENT_THUMB: 301a46c0ec8Sopenharmony_ci tp->tap.state = TAP_STATE_IDLE; 302a46c0ec8Sopenharmony_ci t->tap.is_thumb = true; 303a46c0ec8Sopenharmony_ci tp->tap.nfingers_down--; 304a46c0ec8Sopenharmony_ci t->tap.state = TAP_TOUCH_STATE_DEAD; 305a46c0ec8Sopenharmony_ci break; 306a46c0ec8Sopenharmony_ci case TAP_EVENT_PALM: 307a46c0ec8Sopenharmony_ci tp->tap.state = TAP_STATE_IDLE; 308a46c0ec8Sopenharmony_ci break; 309a46c0ec8Sopenharmony_ci case TAP_EVENT_PALM_UP: 310a46c0ec8Sopenharmony_ci break; 311a46c0ec8Sopenharmony_ci } 312a46c0ec8Sopenharmony_ci} 313a46c0ec8Sopenharmony_ci 314a46c0ec8Sopenharmony_cistatic void 315a46c0ec8Sopenharmony_citp_tap_tapped_handle_event(struct tp_dispatch *tp, 316a46c0ec8Sopenharmony_ci struct tp_touch *t, 317a46c0ec8Sopenharmony_ci enum tap_event event, uint64_t time, 318a46c0ec8Sopenharmony_ci int nfingers_tapped) 319a46c0ec8Sopenharmony_ci{ 320a46c0ec8Sopenharmony_ci switch (event) { 321a46c0ec8Sopenharmony_ci case TAP_EVENT_MOTION: 322a46c0ec8Sopenharmony_ci case TAP_EVENT_RELEASE: 323a46c0ec8Sopenharmony_ci log_tap_bug(tp, t, event); 324a46c0ec8Sopenharmony_ci break; 325a46c0ec8Sopenharmony_ci case TAP_EVENT_TOUCH: { 326a46c0ec8Sopenharmony_ci enum tp_tap_state dest[3] = { 327a46c0ec8Sopenharmony_ci TAP_STATE_1FGTAP_DRAGGING_OR_DOUBLETAP, 328a46c0ec8Sopenharmony_ci TAP_STATE_2FGTAP_DRAGGING_OR_DOUBLETAP, 329a46c0ec8Sopenharmony_ci TAP_STATE_3FGTAP_DRAGGING_OR_DOUBLETAP, 330a46c0ec8Sopenharmony_ci }; 331a46c0ec8Sopenharmony_ci assert(nfingers_tapped >= 1 && nfingers_tapped <= 3); 332a46c0ec8Sopenharmony_ci tp->tap.state = dest[nfingers_tapped - 1]; 333a46c0ec8Sopenharmony_ci tp->tap.saved_press_time = time; 334a46c0ec8Sopenharmony_ci tp_tap_set_timer(tp, time); 335a46c0ec8Sopenharmony_ci break; 336a46c0ec8Sopenharmony_ci } 337a46c0ec8Sopenharmony_ci case TAP_EVENT_TIMEOUT: 338a46c0ec8Sopenharmony_ci tp->tap.state = TAP_STATE_IDLE; 339a46c0ec8Sopenharmony_ci tp_tap_notify(tp, 340a46c0ec8Sopenharmony_ci tp->tap.saved_release_time, 341a46c0ec8Sopenharmony_ci nfingers_tapped, 342a46c0ec8Sopenharmony_ci LIBINPUT_BUTTON_STATE_RELEASED); 343a46c0ec8Sopenharmony_ci break; 344a46c0ec8Sopenharmony_ci case TAP_EVENT_BUTTON: 345a46c0ec8Sopenharmony_ci tp->tap.state = TAP_STATE_DEAD; 346a46c0ec8Sopenharmony_ci tp_tap_notify(tp, 347a46c0ec8Sopenharmony_ci tp->tap.saved_release_time, 348a46c0ec8Sopenharmony_ci nfingers_tapped, 349a46c0ec8Sopenharmony_ci LIBINPUT_BUTTON_STATE_RELEASED); 350a46c0ec8Sopenharmony_ci break; 351a46c0ec8Sopenharmony_ci case TAP_EVENT_THUMB: 352a46c0ec8Sopenharmony_ci log_tap_bug(tp, t, event); 353a46c0ec8Sopenharmony_ci break; 354a46c0ec8Sopenharmony_ci case TAP_EVENT_PALM: 355a46c0ec8Sopenharmony_ci log_tap_bug(tp, t, event); 356a46c0ec8Sopenharmony_ci break; 357a46c0ec8Sopenharmony_ci case TAP_EVENT_PALM_UP: 358a46c0ec8Sopenharmony_ci break; 359a46c0ec8Sopenharmony_ci } 360a46c0ec8Sopenharmony_ci} 361a46c0ec8Sopenharmony_ci 362a46c0ec8Sopenharmony_cistatic void 363a46c0ec8Sopenharmony_citp_tap_touch2_handle_event(struct tp_dispatch *tp, 364a46c0ec8Sopenharmony_ci struct tp_touch *t, 365a46c0ec8Sopenharmony_ci enum tap_event event, uint64_t time) 366a46c0ec8Sopenharmony_ci{ 367a46c0ec8Sopenharmony_ci 368a46c0ec8Sopenharmony_ci switch (event) { 369a46c0ec8Sopenharmony_ci case TAP_EVENT_TOUCH: 370a46c0ec8Sopenharmony_ci tp->tap.state = TAP_STATE_TOUCH_3; 371a46c0ec8Sopenharmony_ci tp->tap.saved_press_time = time; 372a46c0ec8Sopenharmony_ci tp_tap_set_timer(tp, time); 373a46c0ec8Sopenharmony_ci break; 374a46c0ec8Sopenharmony_ci case TAP_EVENT_RELEASE: 375a46c0ec8Sopenharmony_ci tp->tap.state = TAP_STATE_TOUCH_2_RELEASE; 376a46c0ec8Sopenharmony_ci tp->tap.saved_release_time = time; 377a46c0ec8Sopenharmony_ci tp_tap_set_timer(tp, time); 378a46c0ec8Sopenharmony_ci break; 379a46c0ec8Sopenharmony_ci case TAP_EVENT_MOTION: 380a46c0ec8Sopenharmony_ci tp_tap_move_to_dead(tp, t); 381a46c0ec8Sopenharmony_ci break; 382a46c0ec8Sopenharmony_ci case TAP_EVENT_TIMEOUT: 383a46c0ec8Sopenharmony_ci tp->tap.state = TAP_STATE_TOUCH_2_HOLD; 384a46c0ec8Sopenharmony_ci tp_gesture_tap_timeout(tp, time); 385a46c0ec8Sopenharmony_ci break; 386a46c0ec8Sopenharmony_ci case TAP_EVENT_BUTTON: 387a46c0ec8Sopenharmony_ci tp->tap.state = TAP_STATE_DEAD; 388a46c0ec8Sopenharmony_ci break; 389a46c0ec8Sopenharmony_ci case TAP_EVENT_THUMB: 390a46c0ec8Sopenharmony_ci break; 391a46c0ec8Sopenharmony_ci case TAP_EVENT_PALM: 392a46c0ec8Sopenharmony_ci tp->tap.state = TAP_STATE_TOUCH; 393a46c0ec8Sopenharmony_ci break; 394a46c0ec8Sopenharmony_ci case TAP_EVENT_PALM_UP: 395a46c0ec8Sopenharmony_ci break; 396a46c0ec8Sopenharmony_ci } 397a46c0ec8Sopenharmony_ci} 398a46c0ec8Sopenharmony_ci 399a46c0ec8Sopenharmony_cistatic void 400a46c0ec8Sopenharmony_citp_tap_touch2_hold_handle_event(struct tp_dispatch *tp, 401a46c0ec8Sopenharmony_ci struct tp_touch *t, 402a46c0ec8Sopenharmony_ci enum tap_event event, uint64_t time) 403a46c0ec8Sopenharmony_ci{ 404a46c0ec8Sopenharmony_ci 405a46c0ec8Sopenharmony_ci switch (event) { 406a46c0ec8Sopenharmony_ci case TAP_EVENT_TOUCH: 407a46c0ec8Sopenharmony_ci tp->tap.state = TAP_STATE_TOUCH_3; 408a46c0ec8Sopenharmony_ci tp->tap.saved_press_time = time; 409a46c0ec8Sopenharmony_ci tp_tap_set_timer(tp, time); 410a46c0ec8Sopenharmony_ci break; 411a46c0ec8Sopenharmony_ci case TAP_EVENT_RELEASE: 412a46c0ec8Sopenharmony_ci tp->tap.state = TAP_STATE_HOLD; 413a46c0ec8Sopenharmony_ci break; 414a46c0ec8Sopenharmony_ci case TAP_EVENT_MOTION: 415a46c0ec8Sopenharmony_ci tp_tap_move_to_dead(tp, t); 416a46c0ec8Sopenharmony_ci break; 417a46c0ec8Sopenharmony_ci case TAP_EVENT_TIMEOUT: 418a46c0ec8Sopenharmony_ci tp->tap.state = TAP_STATE_TOUCH_2_HOLD; 419a46c0ec8Sopenharmony_ci break; 420a46c0ec8Sopenharmony_ci case TAP_EVENT_BUTTON: 421a46c0ec8Sopenharmony_ci tp->tap.state = TAP_STATE_DEAD; 422a46c0ec8Sopenharmony_ci break; 423a46c0ec8Sopenharmony_ci case TAP_EVENT_THUMB: 424a46c0ec8Sopenharmony_ci break; 425a46c0ec8Sopenharmony_ci case TAP_EVENT_PALM: 426a46c0ec8Sopenharmony_ci tp->tap.state = TAP_STATE_HOLD; 427a46c0ec8Sopenharmony_ci break; 428a46c0ec8Sopenharmony_ci case TAP_EVENT_PALM_UP: 429a46c0ec8Sopenharmony_ci break; 430a46c0ec8Sopenharmony_ci } 431a46c0ec8Sopenharmony_ci} 432a46c0ec8Sopenharmony_ci 433a46c0ec8Sopenharmony_cistatic void 434a46c0ec8Sopenharmony_citp_tap_touch2_release_handle_event(struct tp_dispatch *tp, 435a46c0ec8Sopenharmony_ci struct tp_touch *t, 436a46c0ec8Sopenharmony_ci enum tap_event event, uint64_t time) 437a46c0ec8Sopenharmony_ci{ 438a46c0ec8Sopenharmony_ci 439a46c0ec8Sopenharmony_ci switch (event) { 440a46c0ec8Sopenharmony_ci case TAP_EVENT_TOUCH: 441a46c0ec8Sopenharmony_ci tp->tap.state = TAP_STATE_TOUCH_2_HOLD; 442a46c0ec8Sopenharmony_ci t->tap.state = TAP_TOUCH_STATE_DEAD; 443a46c0ec8Sopenharmony_ci tp_tap_clear_timer(tp); 444a46c0ec8Sopenharmony_ci break; 445a46c0ec8Sopenharmony_ci case TAP_EVENT_RELEASE: 446a46c0ec8Sopenharmony_ci tp_tap_notify(tp, 447a46c0ec8Sopenharmony_ci tp->tap.saved_press_time, 448a46c0ec8Sopenharmony_ci 2, 449a46c0ec8Sopenharmony_ci LIBINPUT_BUTTON_STATE_PRESSED); 450a46c0ec8Sopenharmony_ci if (tp->tap.drag_enabled) { 451a46c0ec8Sopenharmony_ci tp->tap.state = TAP_STATE_2FGTAP_TAPPED; 452a46c0ec8Sopenharmony_ci tp_tap_set_drag_timer(tp, time, 2); 453a46c0ec8Sopenharmony_ci } else { 454a46c0ec8Sopenharmony_ci tp_tap_notify(tp, 455a46c0ec8Sopenharmony_ci tp->tap.saved_release_time, 456a46c0ec8Sopenharmony_ci 2, 457a46c0ec8Sopenharmony_ci LIBINPUT_BUTTON_STATE_RELEASED); 458a46c0ec8Sopenharmony_ci tp->tap.state = TAP_STATE_IDLE; 459a46c0ec8Sopenharmony_ci } 460a46c0ec8Sopenharmony_ci break; 461a46c0ec8Sopenharmony_ci case TAP_EVENT_MOTION: 462a46c0ec8Sopenharmony_ci tp_tap_move_to_dead(tp, t); 463a46c0ec8Sopenharmony_ci break; 464a46c0ec8Sopenharmony_ci case TAP_EVENT_TIMEOUT: 465a46c0ec8Sopenharmony_ci tp->tap.state = TAP_STATE_HOLD; 466a46c0ec8Sopenharmony_ci break; 467a46c0ec8Sopenharmony_ci case TAP_EVENT_BUTTON: 468a46c0ec8Sopenharmony_ci tp->tap.state = TAP_STATE_DEAD; 469a46c0ec8Sopenharmony_ci break; 470a46c0ec8Sopenharmony_ci case TAP_EVENT_THUMB: 471a46c0ec8Sopenharmony_ci break; 472a46c0ec8Sopenharmony_ci case TAP_EVENT_PALM: 473a46c0ec8Sopenharmony_ci /* There's only one saved press time and it's overwritten by 474a46c0ec8Sopenharmony_ci * the last touch down. So in the case of finger down, palm 475a46c0ec8Sopenharmony_ci * down, finger up, palm detected, we use the 476a46c0ec8Sopenharmony_ci * palm touch's press time here instead of the finger's press 477a46c0ec8Sopenharmony_ci * time. Let's wait and see if that's an issue. 478a46c0ec8Sopenharmony_ci */ 479a46c0ec8Sopenharmony_ci tp_tap_notify(tp, 480a46c0ec8Sopenharmony_ci tp->tap.saved_press_time, 481a46c0ec8Sopenharmony_ci 1, 482a46c0ec8Sopenharmony_ci LIBINPUT_BUTTON_STATE_PRESSED); 483a46c0ec8Sopenharmony_ci if (tp->tap.drag_enabled) { 484a46c0ec8Sopenharmony_ci /* For a single-finger tap the timer delay is the same 485a46c0ec8Sopenharmony_ci * as for the release of the finger that became a palm, 486a46c0ec8Sopenharmony_ci * no reset necessary */ 487a46c0ec8Sopenharmony_ci tp->tap.state = TAP_STATE_1FGTAP_TAPPED; 488a46c0ec8Sopenharmony_ci } else { 489a46c0ec8Sopenharmony_ci tp_tap_notify(tp, 490a46c0ec8Sopenharmony_ci tp->tap.saved_release_time, 491a46c0ec8Sopenharmony_ci 1, 492a46c0ec8Sopenharmony_ci LIBINPUT_BUTTON_STATE_RELEASED); 493a46c0ec8Sopenharmony_ci tp->tap.state = TAP_STATE_IDLE; 494a46c0ec8Sopenharmony_ci } 495a46c0ec8Sopenharmony_ci break; 496a46c0ec8Sopenharmony_ci case TAP_EVENT_PALM_UP: 497a46c0ec8Sopenharmony_ci break; 498a46c0ec8Sopenharmony_ci } 499a46c0ec8Sopenharmony_ci} 500a46c0ec8Sopenharmony_ci 501a46c0ec8Sopenharmony_cistatic void 502a46c0ec8Sopenharmony_citp_tap_touch3_handle_event(struct tp_dispatch *tp, 503a46c0ec8Sopenharmony_ci struct tp_touch *t, 504a46c0ec8Sopenharmony_ci enum tap_event event, uint64_t time) 505a46c0ec8Sopenharmony_ci{ 506a46c0ec8Sopenharmony_ci 507a46c0ec8Sopenharmony_ci switch (event) { 508a46c0ec8Sopenharmony_ci case TAP_EVENT_TOUCH: 509a46c0ec8Sopenharmony_ci tp->tap.state = TAP_STATE_DEAD; 510a46c0ec8Sopenharmony_ci tp_tap_clear_timer(tp); 511a46c0ec8Sopenharmony_ci break; 512a46c0ec8Sopenharmony_ci case TAP_EVENT_MOTION: 513a46c0ec8Sopenharmony_ci tp_tap_move_to_dead(tp, t); 514a46c0ec8Sopenharmony_ci break; 515a46c0ec8Sopenharmony_ci case TAP_EVENT_TIMEOUT: 516a46c0ec8Sopenharmony_ci tp->tap.state = TAP_STATE_TOUCH_3_HOLD; 517a46c0ec8Sopenharmony_ci tp_tap_clear_timer(tp); 518a46c0ec8Sopenharmony_ci tp_gesture_tap_timeout(tp, time); 519a46c0ec8Sopenharmony_ci break; 520a46c0ec8Sopenharmony_ci case TAP_EVENT_RELEASE: 521a46c0ec8Sopenharmony_ci tp->tap.state = TAP_STATE_TOUCH_3_RELEASE; 522a46c0ec8Sopenharmony_ci tp->tap.saved_release_time = time; 523a46c0ec8Sopenharmony_ci tp_tap_set_timer(tp, time); 524a46c0ec8Sopenharmony_ci break; 525a46c0ec8Sopenharmony_ci case TAP_EVENT_BUTTON: 526a46c0ec8Sopenharmony_ci tp->tap.state = TAP_STATE_DEAD; 527a46c0ec8Sopenharmony_ci break; 528a46c0ec8Sopenharmony_ci case TAP_EVENT_THUMB: 529a46c0ec8Sopenharmony_ci break; 530a46c0ec8Sopenharmony_ci case TAP_EVENT_PALM: 531a46c0ec8Sopenharmony_ci tp->tap.state = TAP_STATE_TOUCH_2; 532a46c0ec8Sopenharmony_ci break; 533a46c0ec8Sopenharmony_ci case TAP_EVENT_PALM_UP: 534a46c0ec8Sopenharmony_ci break; 535a46c0ec8Sopenharmony_ci } 536a46c0ec8Sopenharmony_ci} 537a46c0ec8Sopenharmony_ci 538a46c0ec8Sopenharmony_cistatic void 539a46c0ec8Sopenharmony_citp_tap_touch3_hold_handle_event(struct tp_dispatch *tp, 540a46c0ec8Sopenharmony_ci struct tp_touch *t, 541a46c0ec8Sopenharmony_ci enum tap_event event, uint64_t time) 542a46c0ec8Sopenharmony_ci{ 543a46c0ec8Sopenharmony_ci 544a46c0ec8Sopenharmony_ci switch (event) { 545a46c0ec8Sopenharmony_ci case TAP_EVENT_TOUCH: 546a46c0ec8Sopenharmony_ci tp->tap.state = TAP_STATE_DEAD; 547a46c0ec8Sopenharmony_ci tp_tap_set_timer(tp, time); 548a46c0ec8Sopenharmony_ci break; 549a46c0ec8Sopenharmony_ci case TAP_EVENT_RELEASE: 550a46c0ec8Sopenharmony_ci tp->tap.state = TAP_STATE_TOUCH_2_HOLD; 551a46c0ec8Sopenharmony_ci break; 552a46c0ec8Sopenharmony_ci case TAP_EVENT_MOTION: 553a46c0ec8Sopenharmony_ci tp_tap_move_to_dead(tp, t); 554a46c0ec8Sopenharmony_ci break; 555a46c0ec8Sopenharmony_ci case TAP_EVENT_TIMEOUT: 556a46c0ec8Sopenharmony_ci break; 557a46c0ec8Sopenharmony_ci case TAP_EVENT_BUTTON: 558a46c0ec8Sopenharmony_ci tp->tap.state = TAP_STATE_DEAD; 559a46c0ec8Sopenharmony_ci break; 560a46c0ec8Sopenharmony_ci case TAP_EVENT_THUMB: 561a46c0ec8Sopenharmony_ci break; 562a46c0ec8Sopenharmony_ci case TAP_EVENT_PALM: 563a46c0ec8Sopenharmony_ci tp->tap.state = TAP_STATE_TOUCH_2_HOLD; 564a46c0ec8Sopenharmony_ci break; 565a46c0ec8Sopenharmony_ci case TAP_EVENT_PALM_UP: 566a46c0ec8Sopenharmony_ci break; 567a46c0ec8Sopenharmony_ci } 568a46c0ec8Sopenharmony_ci} 569a46c0ec8Sopenharmony_ci 570a46c0ec8Sopenharmony_cistatic void 571a46c0ec8Sopenharmony_citp_tap_touch3_release_handle_event(struct tp_dispatch *tp, 572a46c0ec8Sopenharmony_ci struct tp_touch *t, 573a46c0ec8Sopenharmony_ci enum tap_event event, uint64_t time) 574a46c0ec8Sopenharmony_ci{ 575a46c0ec8Sopenharmony_ci 576a46c0ec8Sopenharmony_ci switch (event) { 577a46c0ec8Sopenharmony_ci case TAP_EVENT_TOUCH: 578a46c0ec8Sopenharmony_ci tp_tap_notify(tp, 579a46c0ec8Sopenharmony_ci tp->tap.saved_press_time, 580a46c0ec8Sopenharmony_ci 3, 581a46c0ec8Sopenharmony_ci LIBINPUT_BUTTON_STATE_PRESSED); 582a46c0ec8Sopenharmony_ci tp_tap_notify(tp, 583a46c0ec8Sopenharmony_ci tp->tap.saved_release_time, 584a46c0ec8Sopenharmony_ci 3, 585a46c0ec8Sopenharmony_ci LIBINPUT_BUTTON_STATE_RELEASED); 586a46c0ec8Sopenharmony_ci tp->tap.state = TAP_STATE_TOUCH_3; 587a46c0ec8Sopenharmony_ci tp->tap.saved_press_time = time; 588a46c0ec8Sopenharmony_ci tp_tap_set_timer(tp, time); 589a46c0ec8Sopenharmony_ci break; 590a46c0ec8Sopenharmony_ci case TAP_EVENT_RELEASE: 591a46c0ec8Sopenharmony_ci tp->tap.state = TAP_STATE_TOUCH_3_RELEASE_2; 592a46c0ec8Sopenharmony_ci tp_tap_set_timer(tp, time); 593a46c0ec8Sopenharmony_ci break; 594a46c0ec8Sopenharmony_ci case TAP_EVENT_MOTION: 595a46c0ec8Sopenharmony_ci tp_tap_notify(tp, 596a46c0ec8Sopenharmony_ci tp->tap.saved_press_time, 597a46c0ec8Sopenharmony_ci 3, 598a46c0ec8Sopenharmony_ci LIBINPUT_BUTTON_STATE_PRESSED); 599a46c0ec8Sopenharmony_ci tp_tap_notify(tp, 600a46c0ec8Sopenharmony_ci tp->tap.saved_release_time, 601a46c0ec8Sopenharmony_ci 3, 602a46c0ec8Sopenharmony_ci LIBINPUT_BUTTON_STATE_RELEASED); 603a46c0ec8Sopenharmony_ci tp_tap_move_to_dead(tp, t); 604a46c0ec8Sopenharmony_ci break; 605a46c0ec8Sopenharmony_ci case TAP_EVENT_TIMEOUT: 606a46c0ec8Sopenharmony_ci tp_tap_notify(tp, 607a46c0ec8Sopenharmony_ci tp->tap.saved_press_time, 608a46c0ec8Sopenharmony_ci 3, 609a46c0ec8Sopenharmony_ci LIBINPUT_BUTTON_STATE_PRESSED); 610a46c0ec8Sopenharmony_ci tp_tap_notify(tp, 611a46c0ec8Sopenharmony_ci tp->tap.saved_release_time, 612a46c0ec8Sopenharmony_ci 3, 613a46c0ec8Sopenharmony_ci LIBINPUT_BUTTON_STATE_RELEASED); 614a46c0ec8Sopenharmony_ci tp->tap.state = TAP_STATE_TOUCH_2_HOLD; 615a46c0ec8Sopenharmony_ci break; 616a46c0ec8Sopenharmony_ci case TAP_EVENT_BUTTON: 617a46c0ec8Sopenharmony_ci tp_tap_notify(tp, 618a46c0ec8Sopenharmony_ci tp->tap.saved_press_time, 619a46c0ec8Sopenharmony_ci 3, 620a46c0ec8Sopenharmony_ci LIBINPUT_BUTTON_STATE_PRESSED); 621a46c0ec8Sopenharmony_ci tp_tap_notify(tp, 622a46c0ec8Sopenharmony_ci tp->tap.saved_release_time, 623a46c0ec8Sopenharmony_ci 3, 624a46c0ec8Sopenharmony_ci LIBINPUT_BUTTON_STATE_RELEASED); 625a46c0ec8Sopenharmony_ci tp->tap.state = TAP_STATE_DEAD; 626a46c0ec8Sopenharmony_ci break; 627a46c0ec8Sopenharmony_ci case TAP_EVENT_THUMB: 628a46c0ec8Sopenharmony_ci break; 629a46c0ec8Sopenharmony_ci case TAP_EVENT_PALM: 630a46c0ec8Sopenharmony_ci tp->tap.state = TAP_STATE_TOUCH_2_RELEASE; 631a46c0ec8Sopenharmony_ci break; 632a46c0ec8Sopenharmony_ci case TAP_EVENT_PALM_UP: 633a46c0ec8Sopenharmony_ci break; 634a46c0ec8Sopenharmony_ci } 635a46c0ec8Sopenharmony_ci} 636a46c0ec8Sopenharmony_ci 637a46c0ec8Sopenharmony_cistatic void 638a46c0ec8Sopenharmony_citp_tap_touch3_release2_handle_event(struct tp_dispatch *tp, 639a46c0ec8Sopenharmony_ci struct tp_touch *t, 640a46c0ec8Sopenharmony_ci enum tap_event event, uint64_t time) 641a46c0ec8Sopenharmony_ci{ 642a46c0ec8Sopenharmony_ci 643a46c0ec8Sopenharmony_ci switch (event) { 644a46c0ec8Sopenharmony_ci case TAP_EVENT_TOUCH: 645a46c0ec8Sopenharmony_ci tp_tap_notify(tp, 646a46c0ec8Sopenharmony_ci tp->tap.saved_press_time, 647a46c0ec8Sopenharmony_ci 3, 648a46c0ec8Sopenharmony_ci LIBINPUT_BUTTON_STATE_PRESSED); 649a46c0ec8Sopenharmony_ci tp_tap_notify(tp, 650a46c0ec8Sopenharmony_ci tp->tap.saved_release_time, 651a46c0ec8Sopenharmony_ci 3, 652a46c0ec8Sopenharmony_ci LIBINPUT_BUTTON_STATE_RELEASED); 653a46c0ec8Sopenharmony_ci tp->tap.state = TAP_STATE_TOUCH_2; 654a46c0ec8Sopenharmony_ci tp->tap.saved_press_time = time; 655a46c0ec8Sopenharmony_ci tp_tap_set_timer(tp, time); 656a46c0ec8Sopenharmony_ci break; 657a46c0ec8Sopenharmony_ci case TAP_EVENT_RELEASE: 658a46c0ec8Sopenharmony_ci tp_tap_notify(tp, 659a46c0ec8Sopenharmony_ci tp->tap.saved_press_time, 660a46c0ec8Sopenharmony_ci 3, 661a46c0ec8Sopenharmony_ci LIBINPUT_BUTTON_STATE_PRESSED); 662a46c0ec8Sopenharmony_ci if (tp->tap.drag_enabled) { 663a46c0ec8Sopenharmony_ci tp->tap.state = TAP_STATE_3FGTAP_TAPPED; 664a46c0ec8Sopenharmony_ci tp_tap_set_drag_timer(tp, time, 3); 665a46c0ec8Sopenharmony_ci } else { 666a46c0ec8Sopenharmony_ci tp_tap_notify(tp, 667a46c0ec8Sopenharmony_ci tp->tap.saved_release_time, 668a46c0ec8Sopenharmony_ci 3, 669a46c0ec8Sopenharmony_ci LIBINPUT_BUTTON_STATE_RELEASED); 670a46c0ec8Sopenharmony_ci tp->tap.state = TAP_STATE_IDLE; 671a46c0ec8Sopenharmony_ci } 672a46c0ec8Sopenharmony_ci break; 673a46c0ec8Sopenharmony_ci case TAP_EVENT_MOTION: 674a46c0ec8Sopenharmony_ci tp_tap_notify(tp, 675a46c0ec8Sopenharmony_ci tp->tap.saved_press_time, 676a46c0ec8Sopenharmony_ci 3, 677a46c0ec8Sopenharmony_ci LIBINPUT_BUTTON_STATE_PRESSED); 678a46c0ec8Sopenharmony_ci tp_tap_notify(tp, 679a46c0ec8Sopenharmony_ci tp->tap.saved_release_time, 680a46c0ec8Sopenharmony_ci 3, 681a46c0ec8Sopenharmony_ci LIBINPUT_BUTTON_STATE_RELEASED); 682a46c0ec8Sopenharmony_ci tp_tap_move_to_dead(tp, t); 683a46c0ec8Sopenharmony_ci break; 684a46c0ec8Sopenharmony_ci case TAP_EVENT_TIMEOUT: 685a46c0ec8Sopenharmony_ci tp_tap_notify(tp, 686a46c0ec8Sopenharmony_ci tp->tap.saved_press_time, 687a46c0ec8Sopenharmony_ci 3, 688a46c0ec8Sopenharmony_ci LIBINPUT_BUTTON_STATE_PRESSED); 689a46c0ec8Sopenharmony_ci tp_tap_notify(tp, 690a46c0ec8Sopenharmony_ci tp->tap.saved_release_time, 691a46c0ec8Sopenharmony_ci 3, 692a46c0ec8Sopenharmony_ci LIBINPUT_BUTTON_STATE_RELEASED); 693a46c0ec8Sopenharmony_ci tp->tap.state = TAP_STATE_HOLD; 694a46c0ec8Sopenharmony_ci break; 695a46c0ec8Sopenharmony_ci case TAP_EVENT_BUTTON: 696a46c0ec8Sopenharmony_ci tp_tap_notify(tp, 697a46c0ec8Sopenharmony_ci tp->tap.saved_press_time, 698a46c0ec8Sopenharmony_ci 3, 699a46c0ec8Sopenharmony_ci LIBINPUT_BUTTON_STATE_PRESSED); 700a46c0ec8Sopenharmony_ci tp_tap_notify(tp, 701a46c0ec8Sopenharmony_ci tp->tap.saved_release_time, 702a46c0ec8Sopenharmony_ci 3, 703a46c0ec8Sopenharmony_ci LIBINPUT_BUTTON_STATE_RELEASED); 704a46c0ec8Sopenharmony_ci tp->tap.state = TAP_STATE_DEAD; 705a46c0ec8Sopenharmony_ci break; 706a46c0ec8Sopenharmony_ci case TAP_EVENT_THUMB: 707a46c0ec8Sopenharmony_ci break; 708a46c0ec8Sopenharmony_ci case TAP_EVENT_PALM: 709a46c0ec8Sopenharmony_ci tp_tap_notify(tp, 710a46c0ec8Sopenharmony_ci tp->tap.saved_press_time, 711a46c0ec8Sopenharmony_ci 2, 712a46c0ec8Sopenharmony_ci LIBINPUT_BUTTON_STATE_PRESSED); 713a46c0ec8Sopenharmony_ci if (tp->tap.drag_enabled) { 714a46c0ec8Sopenharmony_ci /* Resetting the timer to the appropriate delay 715a46c0ec8Sopenharmony_ci * for a two-finger tap would be ideal, but the 716a46c0ec8Sopenharmony_ci * timestamp of the last real finger release is lost, 717a46c0ec8Sopenharmony_ci * so the in-progress similar delay for release 718a46c0ec8Sopenharmony_ci * of the finger which became a palm instead 719a46c0ec8Sopenharmony_ci * will have to do */ 720a46c0ec8Sopenharmony_ci tp->tap.state = TAP_STATE_2FGTAP_TAPPED; 721a46c0ec8Sopenharmony_ci } else { 722a46c0ec8Sopenharmony_ci tp_tap_notify(tp, 723a46c0ec8Sopenharmony_ci tp->tap.saved_release_time, 724a46c0ec8Sopenharmony_ci 2, 725a46c0ec8Sopenharmony_ci LIBINPUT_BUTTON_STATE_RELEASED); 726a46c0ec8Sopenharmony_ci tp->tap.state = TAP_STATE_IDLE; 727a46c0ec8Sopenharmony_ci } 728a46c0ec8Sopenharmony_ci break; 729a46c0ec8Sopenharmony_ci case TAP_EVENT_PALM_UP: 730a46c0ec8Sopenharmony_ci break; 731a46c0ec8Sopenharmony_ci } 732a46c0ec8Sopenharmony_ci} 733a46c0ec8Sopenharmony_ci 734a46c0ec8Sopenharmony_cistatic void 735a46c0ec8Sopenharmony_citp_tap_dragging_or_doubletap_handle_event(struct tp_dispatch *tp, 736a46c0ec8Sopenharmony_ci struct tp_touch *t, 737a46c0ec8Sopenharmony_ci enum tap_event event, uint64_t time, 738a46c0ec8Sopenharmony_ci int nfingers_tapped) 739a46c0ec8Sopenharmony_ci{ 740a46c0ec8Sopenharmony_ci switch (event) { 741a46c0ec8Sopenharmony_ci case TAP_EVENT_TOUCH: { 742a46c0ec8Sopenharmony_ci tp_tap_notify(tp, 743a46c0ec8Sopenharmony_ci tp->tap.saved_release_time, 744a46c0ec8Sopenharmony_ci nfingers_tapped, 745a46c0ec8Sopenharmony_ci LIBINPUT_BUTTON_STATE_RELEASED); 746a46c0ec8Sopenharmony_ci tp->tap.state = TAP_STATE_TOUCH_2; 747a46c0ec8Sopenharmony_ci tp->tap.saved_press_time = time; 748a46c0ec8Sopenharmony_ci tp_tap_set_timer(tp, time); 749a46c0ec8Sopenharmony_ci break; 750a46c0ec8Sopenharmony_ci } 751a46c0ec8Sopenharmony_ci case TAP_EVENT_RELEASE: 752a46c0ec8Sopenharmony_ci tp->tap.state = TAP_STATE_1FGTAP_TAPPED; 753a46c0ec8Sopenharmony_ci tp_tap_notify(tp, 754a46c0ec8Sopenharmony_ci tp->tap.saved_release_time, 755a46c0ec8Sopenharmony_ci nfingers_tapped, 756a46c0ec8Sopenharmony_ci LIBINPUT_BUTTON_STATE_RELEASED); 757a46c0ec8Sopenharmony_ci tp_tap_notify(tp, 758a46c0ec8Sopenharmony_ci tp->tap.saved_press_time, 759a46c0ec8Sopenharmony_ci 1, 760a46c0ec8Sopenharmony_ci LIBINPUT_BUTTON_STATE_PRESSED); 761a46c0ec8Sopenharmony_ci tp->tap.saved_release_time = time; 762a46c0ec8Sopenharmony_ci tp_tap_set_timer(tp, time); 763a46c0ec8Sopenharmony_ci break; 764a46c0ec8Sopenharmony_ci case TAP_EVENT_MOTION: 765a46c0ec8Sopenharmony_ci case TAP_EVENT_TIMEOUT: { 766a46c0ec8Sopenharmony_ci enum tp_tap_state dest[3] = { 767a46c0ec8Sopenharmony_ci TAP_STATE_1FGTAP_DRAGGING, 768a46c0ec8Sopenharmony_ci TAP_STATE_2FGTAP_DRAGGING, 769a46c0ec8Sopenharmony_ci TAP_STATE_3FGTAP_DRAGGING, 770a46c0ec8Sopenharmony_ci }; 771a46c0ec8Sopenharmony_ci assert(nfingers_tapped >= 1 && nfingers_tapped <= 3); 772a46c0ec8Sopenharmony_ci tp->tap.state = dest[nfingers_tapped - 1]; 773a46c0ec8Sopenharmony_ci break; 774a46c0ec8Sopenharmony_ci } 775a46c0ec8Sopenharmony_ci case TAP_EVENT_BUTTON: 776a46c0ec8Sopenharmony_ci tp->tap.state = TAP_STATE_DEAD; 777a46c0ec8Sopenharmony_ci tp_tap_notify(tp, 778a46c0ec8Sopenharmony_ci tp->tap.saved_release_time, 779a46c0ec8Sopenharmony_ci nfingers_tapped, 780a46c0ec8Sopenharmony_ci LIBINPUT_BUTTON_STATE_RELEASED); 781a46c0ec8Sopenharmony_ci break; 782a46c0ec8Sopenharmony_ci case TAP_EVENT_THUMB: 783a46c0ec8Sopenharmony_ci break; 784a46c0ec8Sopenharmony_ci case TAP_EVENT_PALM: { 785a46c0ec8Sopenharmony_ci enum tp_tap_state dest[3] = { 786a46c0ec8Sopenharmony_ci TAP_STATE_1FGTAP_TAPPED, 787a46c0ec8Sopenharmony_ci TAP_STATE_2FGTAP_TAPPED, 788a46c0ec8Sopenharmony_ci TAP_STATE_3FGTAP_TAPPED, 789a46c0ec8Sopenharmony_ci }; 790a46c0ec8Sopenharmony_ci assert(nfingers_tapped >= 1 && nfingers_tapped <= 3); 791a46c0ec8Sopenharmony_ci tp->tap.state = dest[nfingers_tapped - 1]; 792a46c0ec8Sopenharmony_ci break; 793a46c0ec8Sopenharmony_ci } 794a46c0ec8Sopenharmony_ci case TAP_EVENT_PALM_UP: 795a46c0ec8Sopenharmony_ci break; 796a46c0ec8Sopenharmony_ci } 797a46c0ec8Sopenharmony_ci} 798a46c0ec8Sopenharmony_ci 799a46c0ec8Sopenharmony_cistatic void 800a46c0ec8Sopenharmony_citp_tap_dragging_handle_event(struct tp_dispatch *tp, 801a46c0ec8Sopenharmony_ci struct tp_touch *t, 802a46c0ec8Sopenharmony_ci enum tap_event event, uint64_t time, 803a46c0ec8Sopenharmony_ci int nfingers_tapped) 804a46c0ec8Sopenharmony_ci{ 805a46c0ec8Sopenharmony_ci 806a46c0ec8Sopenharmony_ci switch (event) { 807a46c0ec8Sopenharmony_ci case TAP_EVENT_TOUCH: { 808a46c0ec8Sopenharmony_ci enum tp_tap_state dest[3] = { 809a46c0ec8Sopenharmony_ci TAP_STATE_1FGTAP_DRAGGING_2, 810a46c0ec8Sopenharmony_ci TAP_STATE_2FGTAP_DRAGGING_2, 811a46c0ec8Sopenharmony_ci TAP_STATE_3FGTAP_DRAGGING_2, 812a46c0ec8Sopenharmony_ci }; 813a46c0ec8Sopenharmony_ci assert(nfingers_tapped >= 1 && nfingers_tapped <= 3); 814a46c0ec8Sopenharmony_ci tp->tap.state = dest[nfingers_tapped - 1]; 815a46c0ec8Sopenharmony_ci break; 816a46c0ec8Sopenharmony_ci } 817a46c0ec8Sopenharmony_ci case TAP_EVENT_RELEASE: 818a46c0ec8Sopenharmony_ci if (tp->tap.drag_lock_enabled) { 819a46c0ec8Sopenharmony_ci enum tp_tap_state dest[3] = { 820a46c0ec8Sopenharmony_ci TAP_STATE_1FGTAP_DRAGGING_WAIT, 821a46c0ec8Sopenharmony_ci TAP_STATE_2FGTAP_DRAGGING_WAIT, 822a46c0ec8Sopenharmony_ci TAP_STATE_3FGTAP_DRAGGING_WAIT, 823a46c0ec8Sopenharmony_ci }; 824a46c0ec8Sopenharmony_ci assert(nfingers_tapped >= 1 && nfingers_tapped <= 3); 825a46c0ec8Sopenharmony_ci tp->tap.state = dest[nfingers_tapped - 1]; 826a46c0ec8Sopenharmony_ci tp_tap_set_draglock_timer(tp, time); 827a46c0ec8Sopenharmony_ci } else { 828a46c0ec8Sopenharmony_ci tp_tap_notify(tp, 829a46c0ec8Sopenharmony_ci time, 830a46c0ec8Sopenharmony_ci nfingers_tapped, 831a46c0ec8Sopenharmony_ci LIBINPUT_BUTTON_STATE_RELEASED); 832a46c0ec8Sopenharmony_ci tp->tap.state = TAP_STATE_IDLE; 833a46c0ec8Sopenharmony_ci } 834a46c0ec8Sopenharmony_ci break; 835a46c0ec8Sopenharmony_ci case TAP_EVENT_MOTION: 836a46c0ec8Sopenharmony_ci case TAP_EVENT_TIMEOUT: 837a46c0ec8Sopenharmony_ci /* noop */ 838a46c0ec8Sopenharmony_ci break; 839a46c0ec8Sopenharmony_ci case TAP_EVENT_BUTTON: 840a46c0ec8Sopenharmony_ci tp->tap.state = TAP_STATE_DEAD; 841a46c0ec8Sopenharmony_ci tp_tap_notify(tp, 842a46c0ec8Sopenharmony_ci time, 843a46c0ec8Sopenharmony_ci nfingers_tapped, 844a46c0ec8Sopenharmony_ci LIBINPUT_BUTTON_STATE_RELEASED); 845a46c0ec8Sopenharmony_ci break; 846a46c0ec8Sopenharmony_ci case TAP_EVENT_THUMB: 847a46c0ec8Sopenharmony_ci break; 848a46c0ec8Sopenharmony_ci case TAP_EVENT_PALM: 849a46c0ec8Sopenharmony_ci tp_tap_notify(tp, 850a46c0ec8Sopenharmony_ci tp->tap.saved_release_time, 851a46c0ec8Sopenharmony_ci nfingers_tapped, 852a46c0ec8Sopenharmony_ci LIBINPUT_BUTTON_STATE_RELEASED); 853a46c0ec8Sopenharmony_ci tp->tap.state = TAP_STATE_IDLE; 854a46c0ec8Sopenharmony_ci break; 855a46c0ec8Sopenharmony_ci case TAP_EVENT_PALM_UP: 856a46c0ec8Sopenharmony_ci break; 857a46c0ec8Sopenharmony_ci } 858a46c0ec8Sopenharmony_ci} 859a46c0ec8Sopenharmony_ci 860a46c0ec8Sopenharmony_cistatic void 861a46c0ec8Sopenharmony_citp_tap_dragging_wait_handle_event(struct tp_dispatch *tp, 862a46c0ec8Sopenharmony_ci struct tp_touch *t, 863a46c0ec8Sopenharmony_ci enum tap_event event, uint64_t time, 864a46c0ec8Sopenharmony_ci int nfingers_tapped) 865a46c0ec8Sopenharmony_ci{ 866a46c0ec8Sopenharmony_ci 867a46c0ec8Sopenharmony_ci switch (event) { 868a46c0ec8Sopenharmony_ci case TAP_EVENT_TOUCH: { 869a46c0ec8Sopenharmony_ci enum tp_tap_state dest[3] = { 870a46c0ec8Sopenharmony_ci TAP_STATE_1FGTAP_DRAGGING_OR_TAP, 871a46c0ec8Sopenharmony_ci TAP_STATE_2FGTAP_DRAGGING_OR_TAP, 872a46c0ec8Sopenharmony_ci TAP_STATE_3FGTAP_DRAGGING_OR_TAP, 873a46c0ec8Sopenharmony_ci }; 874a46c0ec8Sopenharmony_ci assert(nfingers_tapped >= 1 && nfingers_tapped <= 3); 875a46c0ec8Sopenharmony_ci tp->tap.state = dest[nfingers_tapped - 1]; 876a46c0ec8Sopenharmony_ci tp_tap_set_timer(tp, time); 877a46c0ec8Sopenharmony_ci break; 878a46c0ec8Sopenharmony_ci } 879a46c0ec8Sopenharmony_ci case TAP_EVENT_RELEASE: 880a46c0ec8Sopenharmony_ci case TAP_EVENT_MOTION: 881a46c0ec8Sopenharmony_ci log_tap_bug(tp, t, event); 882a46c0ec8Sopenharmony_ci break; 883a46c0ec8Sopenharmony_ci case TAP_EVENT_TIMEOUT: 884a46c0ec8Sopenharmony_ci tp->tap.state = TAP_STATE_IDLE; 885a46c0ec8Sopenharmony_ci tp_tap_notify(tp, 886a46c0ec8Sopenharmony_ci time, 887a46c0ec8Sopenharmony_ci nfingers_tapped, 888a46c0ec8Sopenharmony_ci LIBINPUT_BUTTON_STATE_RELEASED); 889a46c0ec8Sopenharmony_ci break; 890a46c0ec8Sopenharmony_ci case TAP_EVENT_BUTTON: 891a46c0ec8Sopenharmony_ci tp->tap.state = TAP_STATE_DEAD; 892a46c0ec8Sopenharmony_ci tp_tap_notify(tp, 893a46c0ec8Sopenharmony_ci time, 894a46c0ec8Sopenharmony_ci nfingers_tapped, 895a46c0ec8Sopenharmony_ci LIBINPUT_BUTTON_STATE_RELEASED); 896a46c0ec8Sopenharmony_ci break; 897a46c0ec8Sopenharmony_ci case TAP_EVENT_THUMB: 898a46c0ec8Sopenharmony_ci case TAP_EVENT_PALM: 899a46c0ec8Sopenharmony_ci log_tap_bug(tp, t, event); 900a46c0ec8Sopenharmony_ci break; 901a46c0ec8Sopenharmony_ci case TAP_EVENT_PALM_UP: 902a46c0ec8Sopenharmony_ci break; 903a46c0ec8Sopenharmony_ci } 904a46c0ec8Sopenharmony_ci} 905a46c0ec8Sopenharmony_ci 906a46c0ec8Sopenharmony_cistatic void 907a46c0ec8Sopenharmony_citp_tap_dragging_tap_handle_event(struct tp_dispatch *tp, 908a46c0ec8Sopenharmony_ci struct tp_touch *t, 909a46c0ec8Sopenharmony_ci enum tap_event event, uint64_t time, 910a46c0ec8Sopenharmony_ci int nfingers_tapped) 911a46c0ec8Sopenharmony_ci{ 912a46c0ec8Sopenharmony_ci 913a46c0ec8Sopenharmony_ci switch (event) { 914a46c0ec8Sopenharmony_ci case TAP_EVENT_TOUCH: { 915a46c0ec8Sopenharmony_ci tp_tap_notify(tp, 916a46c0ec8Sopenharmony_ci time, 917a46c0ec8Sopenharmony_ci nfingers_tapped, 918a46c0ec8Sopenharmony_ci LIBINPUT_BUTTON_STATE_RELEASED); 919a46c0ec8Sopenharmony_ci tp_tap_clear_timer(tp); 920a46c0ec8Sopenharmony_ci tp_tap_move_to_dead(tp, t); 921a46c0ec8Sopenharmony_ci break; 922a46c0ec8Sopenharmony_ci } 923a46c0ec8Sopenharmony_ci case TAP_EVENT_RELEASE: 924a46c0ec8Sopenharmony_ci tp->tap.state = TAP_STATE_IDLE; 925a46c0ec8Sopenharmony_ci tp_tap_notify(tp, 926a46c0ec8Sopenharmony_ci time, 927a46c0ec8Sopenharmony_ci nfingers_tapped, 928a46c0ec8Sopenharmony_ci LIBINPUT_BUTTON_STATE_RELEASED); 929a46c0ec8Sopenharmony_ci break; 930a46c0ec8Sopenharmony_ci case TAP_EVENT_MOTION: 931a46c0ec8Sopenharmony_ci case TAP_EVENT_TIMEOUT: { 932a46c0ec8Sopenharmony_ci enum tp_tap_state dest[3] = { 933a46c0ec8Sopenharmony_ci TAP_STATE_1FGTAP_DRAGGING, 934a46c0ec8Sopenharmony_ci TAP_STATE_2FGTAP_DRAGGING, 935a46c0ec8Sopenharmony_ci TAP_STATE_3FGTAP_DRAGGING, 936a46c0ec8Sopenharmony_ci }; 937a46c0ec8Sopenharmony_ci assert(nfingers_tapped >= 1 && nfingers_tapped <= 3); 938a46c0ec8Sopenharmony_ci tp->tap.state = dest[nfingers_tapped - 1]; 939a46c0ec8Sopenharmony_ci break; 940a46c0ec8Sopenharmony_ci } 941a46c0ec8Sopenharmony_ci case TAP_EVENT_BUTTON: 942a46c0ec8Sopenharmony_ci tp->tap.state = TAP_STATE_DEAD; 943a46c0ec8Sopenharmony_ci tp_tap_notify(tp, 944a46c0ec8Sopenharmony_ci time, 945a46c0ec8Sopenharmony_ci nfingers_tapped, 946a46c0ec8Sopenharmony_ci LIBINPUT_BUTTON_STATE_RELEASED); 947a46c0ec8Sopenharmony_ci break; 948a46c0ec8Sopenharmony_ci case TAP_EVENT_THUMB: 949a46c0ec8Sopenharmony_ci break; 950a46c0ec8Sopenharmony_ci case TAP_EVENT_PALM: { 951a46c0ec8Sopenharmony_ci enum tp_tap_state dest[3] = { 952a46c0ec8Sopenharmony_ci TAP_STATE_1FGTAP_DRAGGING_WAIT, 953a46c0ec8Sopenharmony_ci TAP_STATE_2FGTAP_DRAGGING_WAIT, 954a46c0ec8Sopenharmony_ci TAP_STATE_3FGTAP_DRAGGING_WAIT, 955a46c0ec8Sopenharmony_ci }; 956a46c0ec8Sopenharmony_ci assert(nfingers_tapped >= 1 && nfingers_tapped <= 3); 957a46c0ec8Sopenharmony_ci tp->tap.state = dest[nfingers_tapped - 1]; 958a46c0ec8Sopenharmony_ci break; 959a46c0ec8Sopenharmony_ci } 960a46c0ec8Sopenharmony_ci case TAP_EVENT_PALM_UP: 961a46c0ec8Sopenharmony_ci break; 962a46c0ec8Sopenharmony_ci } 963a46c0ec8Sopenharmony_ci} 964a46c0ec8Sopenharmony_ci 965a46c0ec8Sopenharmony_cistatic void 966a46c0ec8Sopenharmony_citp_tap_dragging2_handle_event(struct tp_dispatch *tp, 967a46c0ec8Sopenharmony_ci struct tp_touch *t, 968a46c0ec8Sopenharmony_ci enum tap_event event, uint64_t time, 969a46c0ec8Sopenharmony_ci int nfingers_tapped) 970a46c0ec8Sopenharmony_ci{ 971a46c0ec8Sopenharmony_ci 972a46c0ec8Sopenharmony_ci switch (event) { 973a46c0ec8Sopenharmony_ci case TAP_EVENT_RELEASE: { 974a46c0ec8Sopenharmony_ci enum tp_tap_state dest[3] = { 975a46c0ec8Sopenharmony_ci TAP_STATE_1FGTAP_DRAGGING, 976a46c0ec8Sopenharmony_ci TAP_STATE_2FGTAP_DRAGGING, 977a46c0ec8Sopenharmony_ci TAP_STATE_3FGTAP_DRAGGING, 978a46c0ec8Sopenharmony_ci }; 979a46c0ec8Sopenharmony_ci assert(nfingers_tapped >= 1 && nfingers_tapped <= 3); 980a46c0ec8Sopenharmony_ci tp->tap.state = dest[nfingers_tapped - 1]; 981a46c0ec8Sopenharmony_ci break; 982a46c0ec8Sopenharmony_ci } 983a46c0ec8Sopenharmony_ci case TAP_EVENT_TOUCH: 984a46c0ec8Sopenharmony_ci tp->tap.state = TAP_STATE_DEAD; 985a46c0ec8Sopenharmony_ci tp_tap_notify(tp, 986a46c0ec8Sopenharmony_ci time, 987a46c0ec8Sopenharmony_ci nfingers_tapped, 988a46c0ec8Sopenharmony_ci LIBINPUT_BUTTON_STATE_RELEASED); 989a46c0ec8Sopenharmony_ci break; 990a46c0ec8Sopenharmony_ci case TAP_EVENT_MOTION: 991a46c0ec8Sopenharmony_ci case TAP_EVENT_TIMEOUT: 992a46c0ec8Sopenharmony_ci /* noop */ 993a46c0ec8Sopenharmony_ci break; 994a46c0ec8Sopenharmony_ci case TAP_EVENT_BUTTON: 995a46c0ec8Sopenharmony_ci tp->tap.state = TAP_STATE_DEAD; 996a46c0ec8Sopenharmony_ci tp_tap_notify(tp, 997a46c0ec8Sopenharmony_ci time, 998a46c0ec8Sopenharmony_ci nfingers_tapped, 999a46c0ec8Sopenharmony_ci LIBINPUT_BUTTON_STATE_RELEASED); 1000a46c0ec8Sopenharmony_ci break; 1001a46c0ec8Sopenharmony_ci case TAP_EVENT_THUMB: 1002a46c0ec8Sopenharmony_ci break; 1003a46c0ec8Sopenharmony_ci case TAP_EVENT_PALM: { 1004a46c0ec8Sopenharmony_ci enum tp_tap_state dest[3] = { 1005a46c0ec8Sopenharmony_ci TAP_STATE_1FGTAP_DRAGGING, 1006a46c0ec8Sopenharmony_ci TAP_STATE_2FGTAP_DRAGGING, 1007a46c0ec8Sopenharmony_ci TAP_STATE_3FGTAP_DRAGGING, 1008a46c0ec8Sopenharmony_ci }; 1009a46c0ec8Sopenharmony_ci assert(nfingers_tapped >= 1 && nfingers_tapped <= 3); 1010a46c0ec8Sopenharmony_ci tp->tap.state = dest[nfingers_tapped - 1]; 1011a46c0ec8Sopenharmony_ci break; 1012a46c0ec8Sopenharmony_ci } 1013a46c0ec8Sopenharmony_ci case TAP_EVENT_PALM_UP: 1014a46c0ec8Sopenharmony_ci break; 1015a46c0ec8Sopenharmony_ci } 1016a46c0ec8Sopenharmony_ci} 1017a46c0ec8Sopenharmony_ci 1018a46c0ec8Sopenharmony_cistatic void 1019a46c0ec8Sopenharmony_citp_tap_dead_handle_event(struct tp_dispatch *tp, 1020a46c0ec8Sopenharmony_ci struct tp_touch *t, 1021a46c0ec8Sopenharmony_ci enum tap_event event, 1022a46c0ec8Sopenharmony_ci uint64_t time) 1023a46c0ec8Sopenharmony_ci{ 1024a46c0ec8Sopenharmony_ci 1025a46c0ec8Sopenharmony_ci switch (event) { 1026a46c0ec8Sopenharmony_ci case TAP_EVENT_RELEASE: 1027a46c0ec8Sopenharmony_ci if (tp->tap.nfingers_down == 0) 1028a46c0ec8Sopenharmony_ci tp->tap.state = TAP_STATE_IDLE; 1029a46c0ec8Sopenharmony_ci break; 1030a46c0ec8Sopenharmony_ci case TAP_EVENT_TOUCH: 1031a46c0ec8Sopenharmony_ci case TAP_EVENT_MOTION: 1032a46c0ec8Sopenharmony_ci case TAP_EVENT_TIMEOUT: 1033a46c0ec8Sopenharmony_ci case TAP_EVENT_BUTTON: 1034a46c0ec8Sopenharmony_ci break; 1035a46c0ec8Sopenharmony_ci case TAP_EVENT_THUMB: 1036a46c0ec8Sopenharmony_ci break; 1037a46c0ec8Sopenharmony_ci case TAP_EVENT_PALM: 1038a46c0ec8Sopenharmony_ci case TAP_EVENT_PALM_UP: 1039a46c0ec8Sopenharmony_ci if (tp->tap.nfingers_down == 0) 1040a46c0ec8Sopenharmony_ci tp->tap.state = TAP_STATE_IDLE; 1041a46c0ec8Sopenharmony_ci break; 1042a46c0ec8Sopenharmony_ci } 1043a46c0ec8Sopenharmony_ci} 1044a46c0ec8Sopenharmony_ci 1045a46c0ec8Sopenharmony_cistatic void 1046a46c0ec8Sopenharmony_citp_tap_handle_event(struct tp_dispatch *tp, 1047a46c0ec8Sopenharmony_ci struct tp_touch *t, 1048a46c0ec8Sopenharmony_ci enum tap_event event, 1049a46c0ec8Sopenharmony_ci uint64_t time) 1050a46c0ec8Sopenharmony_ci{ 1051a46c0ec8Sopenharmony_ci enum tp_tap_state current; 1052a46c0ec8Sopenharmony_ci 1053a46c0ec8Sopenharmony_ci current = tp->tap.state; 1054a46c0ec8Sopenharmony_ci 1055a46c0ec8Sopenharmony_ci switch(tp->tap.state) { 1056a46c0ec8Sopenharmony_ci case TAP_STATE_IDLE: 1057a46c0ec8Sopenharmony_ci tp_tap_idle_handle_event(tp, t, event, time); 1058a46c0ec8Sopenharmony_ci break; 1059a46c0ec8Sopenharmony_ci case TAP_STATE_TOUCH: 1060a46c0ec8Sopenharmony_ci tp_tap_touch_handle_event(tp, t, event, time); 1061a46c0ec8Sopenharmony_ci break; 1062a46c0ec8Sopenharmony_ci case TAP_STATE_HOLD: 1063a46c0ec8Sopenharmony_ci tp_tap_hold_handle_event(tp, t, event, time); 1064a46c0ec8Sopenharmony_ci break; 1065a46c0ec8Sopenharmony_ci case TAP_STATE_1FGTAP_TAPPED: 1066a46c0ec8Sopenharmony_ci tp_tap_tapped_handle_event(tp, t, event, time, 1); 1067a46c0ec8Sopenharmony_ci break; 1068a46c0ec8Sopenharmony_ci case TAP_STATE_2FGTAP_TAPPED: 1069a46c0ec8Sopenharmony_ci tp_tap_tapped_handle_event(tp, t, event, time, 2); 1070a46c0ec8Sopenharmony_ci break; 1071a46c0ec8Sopenharmony_ci case TAP_STATE_3FGTAP_TAPPED: 1072a46c0ec8Sopenharmony_ci tp_tap_tapped_handle_event(tp, t, event, time, 3); 1073a46c0ec8Sopenharmony_ci break; 1074a46c0ec8Sopenharmony_ci case TAP_STATE_TOUCH_2: 1075a46c0ec8Sopenharmony_ci tp_tap_touch2_handle_event(tp, t, event, time); 1076a46c0ec8Sopenharmony_ci break; 1077a46c0ec8Sopenharmony_ci case TAP_STATE_TOUCH_2_HOLD: 1078a46c0ec8Sopenharmony_ci tp_tap_touch2_hold_handle_event(tp, t, event, time); 1079a46c0ec8Sopenharmony_ci break; 1080a46c0ec8Sopenharmony_ci case TAP_STATE_TOUCH_2_RELEASE: 1081a46c0ec8Sopenharmony_ci tp_tap_touch2_release_handle_event(tp, t, event, time); 1082a46c0ec8Sopenharmony_ci break; 1083a46c0ec8Sopenharmony_ci case TAP_STATE_TOUCH_3: 1084a46c0ec8Sopenharmony_ci tp_tap_touch3_handle_event(tp, t, event, time); 1085a46c0ec8Sopenharmony_ci break; 1086a46c0ec8Sopenharmony_ci case TAP_STATE_TOUCH_3_HOLD: 1087a46c0ec8Sopenharmony_ci tp_tap_touch3_hold_handle_event(tp, t, event, time); 1088a46c0ec8Sopenharmony_ci break; 1089a46c0ec8Sopenharmony_ci case TAP_STATE_TOUCH_3_RELEASE: 1090a46c0ec8Sopenharmony_ci tp_tap_touch3_release_handle_event(tp, t, event, time); 1091a46c0ec8Sopenharmony_ci break; 1092a46c0ec8Sopenharmony_ci case TAP_STATE_TOUCH_3_RELEASE_2: 1093a46c0ec8Sopenharmony_ci tp_tap_touch3_release2_handle_event(tp, t, event, time); 1094a46c0ec8Sopenharmony_ci break; 1095a46c0ec8Sopenharmony_ci case TAP_STATE_1FGTAP_DRAGGING_OR_DOUBLETAP: 1096a46c0ec8Sopenharmony_ci tp_tap_dragging_or_doubletap_handle_event(tp, t, event, time, 1097a46c0ec8Sopenharmony_ci 1); 1098a46c0ec8Sopenharmony_ci break; 1099a46c0ec8Sopenharmony_ci case TAP_STATE_2FGTAP_DRAGGING_OR_DOUBLETAP: 1100a46c0ec8Sopenharmony_ci tp_tap_dragging_or_doubletap_handle_event(tp, t, event, time, 1101a46c0ec8Sopenharmony_ci 2); 1102a46c0ec8Sopenharmony_ci break; 1103a46c0ec8Sopenharmony_ci case TAP_STATE_3FGTAP_DRAGGING_OR_DOUBLETAP: 1104a46c0ec8Sopenharmony_ci tp_tap_dragging_or_doubletap_handle_event(tp, t, event, time, 1105a46c0ec8Sopenharmony_ci 3); 1106a46c0ec8Sopenharmony_ci break; 1107a46c0ec8Sopenharmony_ci case TAP_STATE_1FGTAP_DRAGGING: 1108a46c0ec8Sopenharmony_ci tp_tap_dragging_handle_event(tp, t, event, time, 1); 1109a46c0ec8Sopenharmony_ci break; 1110a46c0ec8Sopenharmony_ci case TAP_STATE_2FGTAP_DRAGGING: 1111a46c0ec8Sopenharmony_ci tp_tap_dragging_handle_event(tp, t, event, time, 2); 1112a46c0ec8Sopenharmony_ci break; 1113a46c0ec8Sopenharmony_ci case TAP_STATE_3FGTAP_DRAGGING: 1114a46c0ec8Sopenharmony_ci tp_tap_dragging_handle_event(tp, t, event, time, 3); 1115a46c0ec8Sopenharmony_ci break; 1116a46c0ec8Sopenharmony_ci case TAP_STATE_1FGTAP_DRAGGING_WAIT: 1117a46c0ec8Sopenharmony_ci tp_tap_dragging_wait_handle_event(tp, t, event, time, 1); 1118a46c0ec8Sopenharmony_ci break; 1119a46c0ec8Sopenharmony_ci case TAP_STATE_2FGTAP_DRAGGING_WAIT: 1120a46c0ec8Sopenharmony_ci tp_tap_dragging_wait_handle_event(tp, t, event, time, 2); 1121a46c0ec8Sopenharmony_ci break; 1122a46c0ec8Sopenharmony_ci case TAP_STATE_3FGTAP_DRAGGING_WAIT: 1123a46c0ec8Sopenharmony_ci tp_tap_dragging_wait_handle_event(tp, t, event, time, 3); 1124a46c0ec8Sopenharmony_ci break; 1125a46c0ec8Sopenharmony_ci case TAP_STATE_1FGTAP_DRAGGING_OR_TAP: 1126a46c0ec8Sopenharmony_ci tp_tap_dragging_tap_handle_event(tp, t, event, time, 1); 1127a46c0ec8Sopenharmony_ci break; 1128a46c0ec8Sopenharmony_ci case TAP_STATE_2FGTAP_DRAGGING_OR_TAP: 1129a46c0ec8Sopenharmony_ci tp_tap_dragging_tap_handle_event(tp, t, event, time, 2); 1130a46c0ec8Sopenharmony_ci break; 1131a46c0ec8Sopenharmony_ci case TAP_STATE_3FGTAP_DRAGGING_OR_TAP: 1132a46c0ec8Sopenharmony_ci tp_tap_dragging_tap_handle_event(tp, t, event, time, 3); 1133a46c0ec8Sopenharmony_ci break; 1134a46c0ec8Sopenharmony_ci case TAP_STATE_1FGTAP_DRAGGING_2: 1135a46c0ec8Sopenharmony_ci tp_tap_dragging2_handle_event(tp, t, event, time, 1); 1136a46c0ec8Sopenharmony_ci break; 1137a46c0ec8Sopenharmony_ci case TAP_STATE_2FGTAP_DRAGGING_2: 1138a46c0ec8Sopenharmony_ci tp_tap_dragging2_handle_event(tp, t, event, time, 2); 1139a46c0ec8Sopenharmony_ci break; 1140a46c0ec8Sopenharmony_ci case TAP_STATE_3FGTAP_DRAGGING_2: 1141a46c0ec8Sopenharmony_ci tp_tap_dragging2_handle_event(tp, t, event, time, 3); 1142a46c0ec8Sopenharmony_ci break; 1143a46c0ec8Sopenharmony_ci case TAP_STATE_DEAD: 1144a46c0ec8Sopenharmony_ci tp_tap_dead_handle_event(tp, t, event, time); 1145a46c0ec8Sopenharmony_ci break; 1146a46c0ec8Sopenharmony_ci } 1147a46c0ec8Sopenharmony_ci 1148a46c0ec8Sopenharmony_ci if (tp->tap.state == TAP_STATE_IDLE || tp->tap.state == TAP_STATE_DEAD) 1149a46c0ec8Sopenharmony_ci tp_tap_clear_timer(tp); 1150a46c0ec8Sopenharmony_ci 1151a46c0ec8Sopenharmony_ci if (current != tp->tap.state) 1152a46c0ec8Sopenharmony_ci evdev_log_debug(tp->device, 1153a46c0ec8Sopenharmony_ci "tap: touch %d (%s), tap state %s → %s → %s\n", 1154a46c0ec8Sopenharmony_ci t ? (int)t->index : -1, 1155a46c0ec8Sopenharmony_ci t ? touch_state_to_str(t->state) : "", 1156a46c0ec8Sopenharmony_ci tap_state_to_str(current), 1157a46c0ec8Sopenharmony_ci tap_event_to_str(event), 1158a46c0ec8Sopenharmony_ci tap_state_to_str(tp->tap.state)); 1159a46c0ec8Sopenharmony_ci} 1160a46c0ec8Sopenharmony_ci 1161a46c0ec8Sopenharmony_cistatic bool 1162a46c0ec8Sopenharmony_citp_tap_exceeds_motion_threshold(struct tp_dispatch *tp, 1163a46c0ec8Sopenharmony_ci struct tp_touch *t) 1164a46c0ec8Sopenharmony_ci{ 1165a46c0ec8Sopenharmony_ci struct phys_coords mm = 1166a46c0ec8Sopenharmony_ci tp_phys_delta(tp, device_delta(t->point, t->tap.initial)); 1167a46c0ec8Sopenharmony_ci 1168a46c0ec8Sopenharmony_ci /* if we have more fingers down than slots, we know that synaptics 1169a46c0ec8Sopenharmony_ci * touchpads are likely to give us pointer jumps. 1170a46c0ec8Sopenharmony_ci * This triggers the movement threshold, making three-finger taps 1171a46c0ec8Sopenharmony_ci * less reliable (#101435) 1172a46c0ec8Sopenharmony_ci * 1173a46c0ec8Sopenharmony_ci * This uses the real nfingers_down, not the one for taps. 1174a46c0ec8Sopenharmony_ci */ 1175a46c0ec8Sopenharmony_ci if (tp->device->model_flags & EVDEV_MODEL_SYNAPTICS_SERIAL_TOUCHPAD && 1176a46c0ec8Sopenharmony_ci (tp->nfingers_down > 2 || tp->old_nfingers_down > 2) && 1177a46c0ec8Sopenharmony_ci (tp->nfingers_down > tp->num_slots || 1178a46c0ec8Sopenharmony_ci tp->old_nfingers_down > tp->num_slots)) { 1179a46c0ec8Sopenharmony_ci return false; 1180a46c0ec8Sopenharmony_ci } 1181a46c0ec8Sopenharmony_ci 1182a46c0ec8Sopenharmony_ci /* Semi-mt devices will give us large movements on finger release, 1183a46c0ec8Sopenharmony_ci * depending which touch is released. Make sure we ignore any 1184a46c0ec8Sopenharmony_ci * movement in the same frame as a finger change. 1185a46c0ec8Sopenharmony_ci */ 1186a46c0ec8Sopenharmony_ci if (tp->semi_mt && tp->nfingers_down != tp->old_nfingers_down) 1187a46c0ec8Sopenharmony_ci return false; 1188a46c0ec8Sopenharmony_ci 1189a46c0ec8Sopenharmony_ci return length_in_mm(mm) > DEFAULT_TAP_MOVE_THRESHOLD; 1190a46c0ec8Sopenharmony_ci} 1191a46c0ec8Sopenharmony_ci 1192a46c0ec8Sopenharmony_cistatic bool 1193a46c0ec8Sopenharmony_citp_tap_enabled(struct tp_dispatch *tp) 1194a46c0ec8Sopenharmony_ci{ 1195a46c0ec8Sopenharmony_ci return tp->tap.enabled && !tp->tap.suspended; 1196a46c0ec8Sopenharmony_ci} 1197a46c0ec8Sopenharmony_ci 1198a46c0ec8Sopenharmony_ciint 1199a46c0ec8Sopenharmony_citp_tap_handle_state(struct tp_dispatch *tp, uint64_t time) 1200a46c0ec8Sopenharmony_ci{ 1201a46c0ec8Sopenharmony_ci struct tp_touch *t; 1202a46c0ec8Sopenharmony_ci int filter_motion = 0; 1203a46c0ec8Sopenharmony_ci 1204a46c0ec8Sopenharmony_ci if (!tp_tap_enabled(tp)) 1205a46c0ec8Sopenharmony_ci return 0; 1206a46c0ec8Sopenharmony_ci 1207a46c0ec8Sopenharmony_ci /* Handle queued button pressed events from clickpads. For touchpads 1208a46c0ec8Sopenharmony_ci * with separate physical buttons, ignore button pressed events so they 1209a46c0ec8Sopenharmony_ci * don't interfere with tapping. */ 1210a46c0ec8Sopenharmony_ci if (tp->buttons.is_clickpad && tp->queued & TOUCHPAD_EVENT_BUTTON_PRESS) 1211a46c0ec8Sopenharmony_ci tp_tap_handle_event(tp, NULL, TAP_EVENT_BUTTON, time); 1212a46c0ec8Sopenharmony_ci 1213a46c0ec8Sopenharmony_ci tp_for_each_touch(tp, t) { 1214a46c0ec8Sopenharmony_ci if (!t->dirty || t->state == TOUCH_NONE) 1215a46c0ec8Sopenharmony_ci continue; 1216a46c0ec8Sopenharmony_ci 1217a46c0ec8Sopenharmony_ci if (tp->buttons.is_clickpad && 1218a46c0ec8Sopenharmony_ci tp->queued & TOUCHPAD_EVENT_BUTTON_PRESS) 1219a46c0ec8Sopenharmony_ci t->tap.state = TAP_TOUCH_STATE_DEAD; 1220a46c0ec8Sopenharmony_ci 1221a46c0ec8Sopenharmony_ci /* If a touch was considered thumb for tapping once, we 1222a46c0ec8Sopenharmony_ci * ignore it for the rest of lifetime */ 1223a46c0ec8Sopenharmony_ci if (t->tap.is_thumb) 1224a46c0ec8Sopenharmony_ci continue; 1225a46c0ec8Sopenharmony_ci 1226a46c0ec8Sopenharmony_ci /* A palm tap needs to be properly released because we might 1227a46c0ec8Sopenharmony_ci * be who-knows-where in the state machine. Otherwise, we 1228a46c0ec8Sopenharmony_ci * ignore any event from it. 1229a46c0ec8Sopenharmony_ci */ 1230a46c0ec8Sopenharmony_ci if (t->tap.is_palm) { 1231a46c0ec8Sopenharmony_ci if (t->state == TOUCH_END) 1232a46c0ec8Sopenharmony_ci tp_tap_handle_event(tp, 1233a46c0ec8Sopenharmony_ci t, 1234a46c0ec8Sopenharmony_ci TAP_EVENT_PALM_UP, 1235a46c0ec8Sopenharmony_ci time); 1236a46c0ec8Sopenharmony_ci continue; 1237a46c0ec8Sopenharmony_ci } 1238a46c0ec8Sopenharmony_ci 1239a46c0ec8Sopenharmony_ci if (t->state == TOUCH_HOVERING) 1240a46c0ec8Sopenharmony_ci continue; 1241a46c0ec8Sopenharmony_ci 1242a46c0ec8Sopenharmony_ci if (t->palm.state != PALM_NONE) { 1243a46c0ec8Sopenharmony_ci assert(!t->tap.is_palm); 1244a46c0ec8Sopenharmony_ci t->tap.is_palm = true; 1245a46c0ec8Sopenharmony_ci t->tap.state = TAP_TOUCH_STATE_DEAD; 1246a46c0ec8Sopenharmony_ci if (t->state != TOUCH_BEGIN) { 1247a46c0ec8Sopenharmony_ci tp_tap_handle_event(tp, t, TAP_EVENT_PALM, time); 1248a46c0ec8Sopenharmony_ci assert(tp->tap.nfingers_down > 0); 1249a46c0ec8Sopenharmony_ci tp->tap.nfingers_down--; 1250a46c0ec8Sopenharmony_ci } 1251a46c0ec8Sopenharmony_ci } else if (t->state == TOUCH_BEGIN) { 1252a46c0ec8Sopenharmony_ci /* The simple version: if a touch is a thumb on 1253a46c0ec8Sopenharmony_ci * begin we ignore it. All other thumb touches 1254a46c0ec8Sopenharmony_ci * follow the normal tap state for now */ 1255a46c0ec8Sopenharmony_ci if (tp_thumb_ignored_for_tap(tp, t)) { 1256a46c0ec8Sopenharmony_ci t->tap.is_thumb = true; 1257a46c0ec8Sopenharmony_ci continue; 1258a46c0ec8Sopenharmony_ci } 1259a46c0ec8Sopenharmony_ci 1260a46c0ec8Sopenharmony_ci t->tap.state = TAP_TOUCH_STATE_TOUCH; 1261a46c0ec8Sopenharmony_ci t->tap.initial = t->point; 1262a46c0ec8Sopenharmony_ci tp->tap.nfingers_down++; 1263a46c0ec8Sopenharmony_ci tp_tap_handle_event(tp, t, TAP_EVENT_TOUCH, time); 1264a46c0ec8Sopenharmony_ci } else if (t->state == TOUCH_END) { 1265a46c0ec8Sopenharmony_ci if (t->was_down) { 1266a46c0ec8Sopenharmony_ci assert(tp->tap.nfingers_down >= 1); 1267a46c0ec8Sopenharmony_ci tp->tap.nfingers_down--; 1268a46c0ec8Sopenharmony_ci tp_tap_handle_event(tp, t, TAP_EVENT_RELEASE, time); 1269a46c0ec8Sopenharmony_ci } 1270a46c0ec8Sopenharmony_ci t->tap.state = TAP_TOUCH_STATE_IDLE; 1271a46c0ec8Sopenharmony_ci } else if (tp->tap.state != TAP_STATE_IDLE && 1272a46c0ec8Sopenharmony_ci tp_thumb_ignored(tp, t)) { 1273a46c0ec8Sopenharmony_ci tp_tap_handle_event(tp, t, TAP_EVENT_THUMB, time); 1274a46c0ec8Sopenharmony_ci } else if (tp->tap.state != TAP_STATE_IDLE && 1275a46c0ec8Sopenharmony_ci tp_tap_exceeds_motion_threshold(tp, t)) { 1276a46c0ec8Sopenharmony_ci struct tp_touch *tmp; 1277a46c0ec8Sopenharmony_ci 1278a46c0ec8Sopenharmony_ci /* Any touch exceeding the threshold turns all 1279a46c0ec8Sopenharmony_ci * touches into DEAD */ 1280a46c0ec8Sopenharmony_ci tp_for_each_touch(tp, tmp) { 1281a46c0ec8Sopenharmony_ci if (tmp->tap.state == TAP_TOUCH_STATE_TOUCH) 1282a46c0ec8Sopenharmony_ci tmp->tap.state = TAP_TOUCH_STATE_DEAD; 1283a46c0ec8Sopenharmony_ci } 1284a46c0ec8Sopenharmony_ci 1285a46c0ec8Sopenharmony_ci tp_tap_handle_event(tp, t, TAP_EVENT_MOTION, time); 1286a46c0ec8Sopenharmony_ci } 1287a46c0ec8Sopenharmony_ci } 1288a46c0ec8Sopenharmony_ci 1289a46c0ec8Sopenharmony_ci /** 1290a46c0ec8Sopenharmony_ci * In any state where motion exceeding the move threshold would 1291a46c0ec8Sopenharmony_ci * move to the next state, filter that motion until we actually 1292a46c0ec8Sopenharmony_ci * exceed it. This prevents small motion events while we're waiting 1293a46c0ec8Sopenharmony_ci * on a decision if a tap is a tap. 1294a46c0ec8Sopenharmony_ci */ 1295a46c0ec8Sopenharmony_ci switch (tp->tap.state) { 1296a46c0ec8Sopenharmony_ci case TAP_STATE_TOUCH: 1297a46c0ec8Sopenharmony_ci case TAP_STATE_1FGTAP_TAPPED: 1298a46c0ec8Sopenharmony_ci case TAP_STATE_2FGTAP_TAPPED: 1299a46c0ec8Sopenharmony_ci case TAP_STATE_3FGTAP_TAPPED: 1300a46c0ec8Sopenharmony_ci case TAP_STATE_1FGTAP_DRAGGING_OR_DOUBLETAP: 1301a46c0ec8Sopenharmony_ci case TAP_STATE_2FGTAP_DRAGGING_OR_DOUBLETAP: 1302a46c0ec8Sopenharmony_ci case TAP_STATE_3FGTAP_DRAGGING_OR_DOUBLETAP: 1303a46c0ec8Sopenharmony_ci case TAP_STATE_1FGTAP_DRAGGING_OR_TAP: 1304a46c0ec8Sopenharmony_ci case TAP_STATE_2FGTAP_DRAGGING_OR_TAP: 1305a46c0ec8Sopenharmony_ci case TAP_STATE_3FGTAP_DRAGGING_OR_TAP: 1306a46c0ec8Sopenharmony_ci case TAP_STATE_TOUCH_2: 1307a46c0ec8Sopenharmony_ci case TAP_STATE_TOUCH_3: 1308a46c0ec8Sopenharmony_ci filter_motion = 1; 1309a46c0ec8Sopenharmony_ci break; 1310a46c0ec8Sopenharmony_ci 1311a46c0ec8Sopenharmony_ci default: 1312a46c0ec8Sopenharmony_ci break; 1313a46c0ec8Sopenharmony_ci 1314a46c0ec8Sopenharmony_ci } 1315a46c0ec8Sopenharmony_ci 1316a46c0ec8Sopenharmony_ci assert(tp->tap.nfingers_down <= tp->nfingers_down); 1317a46c0ec8Sopenharmony_ci if (tp->nfingers_down == 0) 1318a46c0ec8Sopenharmony_ci assert(tp->tap.nfingers_down == 0); 1319a46c0ec8Sopenharmony_ci 1320a46c0ec8Sopenharmony_ci return filter_motion; 1321a46c0ec8Sopenharmony_ci} 1322a46c0ec8Sopenharmony_ci 1323a46c0ec8Sopenharmony_cistatic inline void 1324a46c0ec8Sopenharmony_citp_tap_update_map(struct tp_dispatch *tp) 1325a46c0ec8Sopenharmony_ci{ 1326a46c0ec8Sopenharmony_ci if (tp->tap.state != TAP_STATE_IDLE) 1327a46c0ec8Sopenharmony_ci return; 1328a46c0ec8Sopenharmony_ci 1329a46c0ec8Sopenharmony_ci if (tp->tap.map != tp->tap.want_map) 1330a46c0ec8Sopenharmony_ci tp->tap.map = tp->tap.want_map; 1331a46c0ec8Sopenharmony_ci} 1332a46c0ec8Sopenharmony_ci 1333a46c0ec8Sopenharmony_civoid 1334a46c0ec8Sopenharmony_citp_tap_post_process_state(struct tp_dispatch *tp) 1335a46c0ec8Sopenharmony_ci{ 1336a46c0ec8Sopenharmony_ci tp_tap_update_map(tp); 1337a46c0ec8Sopenharmony_ci} 1338a46c0ec8Sopenharmony_ci 1339a46c0ec8Sopenharmony_cistatic void 1340a46c0ec8Sopenharmony_citp_tap_handle_timeout(uint64_t time, void *data) 1341a46c0ec8Sopenharmony_ci{ 1342a46c0ec8Sopenharmony_ci struct tp_dispatch *tp = data; 1343a46c0ec8Sopenharmony_ci struct tp_touch *t; 1344a46c0ec8Sopenharmony_ci 1345a46c0ec8Sopenharmony_ci tp_tap_handle_event(tp, NULL, TAP_EVENT_TIMEOUT, time); 1346a46c0ec8Sopenharmony_ci 1347a46c0ec8Sopenharmony_ci tp_for_each_touch(tp, t) { 1348a46c0ec8Sopenharmony_ci if (t->state == TOUCH_NONE || 1349a46c0ec8Sopenharmony_ci t->tap.state == TAP_TOUCH_STATE_IDLE) 1350a46c0ec8Sopenharmony_ci continue; 1351a46c0ec8Sopenharmony_ci 1352a46c0ec8Sopenharmony_ci t->tap.state = TAP_TOUCH_STATE_DEAD; 1353a46c0ec8Sopenharmony_ci } 1354a46c0ec8Sopenharmony_ci} 1355a46c0ec8Sopenharmony_ci 1356a46c0ec8Sopenharmony_cistatic void 1357a46c0ec8Sopenharmony_citp_tap_enabled_update(struct tp_dispatch *tp, bool suspended, bool enabled, uint64_t time) 1358a46c0ec8Sopenharmony_ci{ 1359a46c0ec8Sopenharmony_ci bool was_enabled = tp_tap_enabled(tp); 1360a46c0ec8Sopenharmony_ci 1361a46c0ec8Sopenharmony_ci tp->tap.suspended = suspended; 1362a46c0ec8Sopenharmony_ci tp->tap.enabled = enabled; 1363a46c0ec8Sopenharmony_ci 1364a46c0ec8Sopenharmony_ci if (tp_tap_enabled(tp) == was_enabled) 1365a46c0ec8Sopenharmony_ci return; 1366a46c0ec8Sopenharmony_ci 1367a46c0ec8Sopenharmony_ci if (tp_tap_enabled(tp)) { 1368a46c0ec8Sopenharmony_ci struct tp_touch *t; 1369a46c0ec8Sopenharmony_ci 1370a46c0ec8Sopenharmony_ci /* On resume, all touches are considered palms */ 1371a46c0ec8Sopenharmony_ci tp_for_each_touch(tp, t) { 1372a46c0ec8Sopenharmony_ci if (t->state == TOUCH_NONE) 1373a46c0ec8Sopenharmony_ci continue; 1374a46c0ec8Sopenharmony_ci 1375a46c0ec8Sopenharmony_ci t->tap.is_palm = true; 1376a46c0ec8Sopenharmony_ci t->tap.state = TAP_TOUCH_STATE_DEAD; 1377a46c0ec8Sopenharmony_ci } 1378a46c0ec8Sopenharmony_ci 1379a46c0ec8Sopenharmony_ci tp->tap.state = TAP_STATE_IDLE; 1380a46c0ec8Sopenharmony_ci tp->tap.nfingers_down = 0; 1381a46c0ec8Sopenharmony_ci } else { 1382a46c0ec8Sopenharmony_ci tp_release_all_taps(tp, time); 1383a46c0ec8Sopenharmony_ci } 1384a46c0ec8Sopenharmony_ci} 1385a46c0ec8Sopenharmony_ci 1386a46c0ec8Sopenharmony_cistatic int 1387a46c0ec8Sopenharmony_citp_tap_config_count(struct libinput_device *device) 1388a46c0ec8Sopenharmony_ci{ 1389a46c0ec8Sopenharmony_ci struct evdev_dispatch *dispatch = evdev_device(device)->dispatch; 1390a46c0ec8Sopenharmony_ci struct tp_dispatch *tp = tp_dispatch(dispatch); 1391a46c0ec8Sopenharmony_ci 1392a46c0ec8Sopenharmony_ci return min(tp->ntouches, 3U); /* we only do up to 3 finger tap */ 1393a46c0ec8Sopenharmony_ci} 1394a46c0ec8Sopenharmony_ci 1395a46c0ec8Sopenharmony_cistatic enum libinput_config_status 1396a46c0ec8Sopenharmony_citp_tap_config_set_enabled(struct libinput_device *device, 1397a46c0ec8Sopenharmony_ci enum libinput_config_tap_state enabled) 1398a46c0ec8Sopenharmony_ci{ 1399a46c0ec8Sopenharmony_ci struct evdev_dispatch *dispatch = evdev_device(device)->dispatch; 1400a46c0ec8Sopenharmony_ci struct tp_dispatch *tp = tp_dispatch(dispatch); 1401a46c0ec8Sopenharmony_ci 1402a46c0ec8Sopenharmony_ci tp_tap_enabled_update(tp, tp->tap.suspended, 1403a46c0ec8Sopenharmony_ci (enabled == LIBINPUT_CONFIG_TAP_ENABLED), 1404a46c0ec8Sopenharmony_ci libinput_now(device->seat->libinput)); 1405a46c0ec8Sopenharmony_ci 1406a46c0ec8Sopenharmony_ci return LIBINPUT_CONFIG_STATUS_SUCCESS; 1407a46c0ec8Sopenharmony_ci} 1408a46c0ec8Sopenharmony_ci 1409a46c0ec8Sopenharmony_cistatic enum libinput_config_tap_state 1410a46c0ec8Sopenharmony_citp_tap_config_is_enabled(struct libinput_device *device) 1411a46c0ec8Sopenharmony_ci{ 1412a46c0ec8Sopenharmony_ci struct evdev_dispatch *dispatch = evdev_device(device)->dispatch; 1413a46c0ec8Sopenharmony_ci struct tp_dispatch *tp = tp_dispatch(dispatch); 1414a46c0ec8Sopenharmony_ci 1415a46c0ec8Sopenharmony_ci return tp->tap.enabled ? LIBINPUT_CONFIG_TAP_ENABLED : 1416a46c0ec8Sopenharmony_ci LIBINPUT_CONFIG_TAP_DISABLED; 1417a46c0ec8Sopenharmony_ci} 1418a46c0ec8Sopenharmony_ci 1419a46c0ec8Sopenharmony_cistatic enum libinput_config_tap_state 1420a46c0ec8Sopenharmony_citp_tap_default(struct evdev_device *evdev) 1421a46c0ec8Sopenharmony_ci{ 1422a46c0ec8Sopenharmony_ci /** 1423a46c0ec8Sopenharmony_ci * If we don't have a left button we must have tapping enabled by 1424a46c0ec8Sopenharmony_ci * default. 1425a46c0ec8Sopenharmony_ci */ 1426a46c0ec8Sopenharmony_ci if (!libevdev_has_event_code(evdev->evdev, EV_KEY, BTN_LEFT)) 1427a46c0ec8Sopenharmony_ci return LIBINPUT_CONFIG_TAP_ENABLED; 1428a46c0ec8Sopenharmony_ci 1429a46c0ec8Sopenharmony_ci /** 1430a46c0ec8Sopenharmony_ci * Tapping is disabled by default for two reasons: 1431a46c0ec8Sopenharmony_ci * * if you don't know that tapping is a thing (or enabled by 1432a46c0ec8Sopenharmony_ci * default), you get spurious mouse events that make the desktop 1433a46c0ec8Sopenharmony_ci * feel buggy. 1434a46c0ec8Sopenharmony_ci * * if you do know what tapping is and you want it, you 1435a46c0ec8Sopenharmony_ci * usually know where to enable it, or at least you can search for 1436a46c0ec8Sopenharmony_ci * it. 1437a46c0ec8Sopenharmony_ci */ 1438a46c0ec8Sopenharmony_ci return LIBINPUT_CONFIG_TAP_DISABLED; 1439a46c0ec8Sopenharmony_ci} 1440a46c0ec8Sopenharmony_ci 1441a46c0ec8Sopenharmony_cistatic enum libinput_config_tap_state 1442a46c0ec8Sopenharmony_citp_tap_config_get_default(struct libinput_device *device) 1443a46c0ec8Sopenharmony_ci{ 1444a46c0ec8Sopenharmony_ci struct evdev_device *evdev = evdev_device(device); 1445a46c0ec8Sopenharmony_ci 1446a46c0ec8Sopenharmony_ci return tp_tap_default(evdev); 1447a46c0ec8Sopenharmony_ci} 1448a46c0ec8Sopenharmony_ci 1449a46c0ec8Sopenharmony_cistatic enum libinput_config_status 1450a46c0ec8Sopenharmony_citp_tap_config_set_map(struct libinput_device *device, 1451a46c0ec8Sopenharmony_ci enum libinput_config_tap_button_map map) 1452a46c0ec8Sopenharmony_ci{ 1453a46c0ec8Sopenharmony_ci struct evdev_dispatch *dispatch = evdev_device(device)->dispatch; 1454a46c0ec8Sopenharmony_ci struct tp_dispatch *tp = tp_dispatch(dispatch); 1455a46c0ec8Sopenharmony_ci 1456a46c0ec8Sopenharmony_ci tp->tap.want_map = map; 1457a46c0ec8Sopenharmony_ci 1458a46c0ec8Sopenharmony_ci tp_tap_update_map(tp); 1459a46c0ec8Sopenharmony_ci 1460a46c0ec8Sopenharmony_ci return LIBINPUT_CONFIG_STATUS_SUCCESS; 1461a46c0ec8Sopenharmony_ci} 1462a46c0ec8Sopenharmony_ci 1463a46c0ec8Sopenharmony_cistatic enum libinput_config_tap_button_map 1464a46c0ec8Sopenharmony_citp_tap_config_get_map(struct libinput_device *device) 1465a46c0ec8Sopenharmony_ci{ 1466a46c0ec8Sopenharmony_ci struct evdev_dispatch *dispatch = evdev_device(device)->dispatch; 1467a46c0ec8Sopenharmony_ci struct tp_dispatch *tp = tp_dispatch(dispatch); 1468a46c0ec8Sopenharmony_ci 1469a46c0ec8Sopenharmony_ci return tp->tap.want_map; 1470a46c0ec8Sopenharmony_ci} 1471a46c0ec8Sopenharmony_ci 1472a46c0ec8Sopenharmony_cistatic enum libinput_config_tap_button_map 1473a46c0ec8Sopenharmony_citp_tap_config_get_default_map(struct libinput_device *device) 1474a46c0ec8Sopenharmony_ci{ 1475a46c0ec8Sopenharmony_ci return LIBINPUT_CONFIG_TAP_MAP_LRM; 1476a46c0ec8Sopenharmony_ci} 1477a46c0ec8Sopenharmony_ci 1478a46c0ec8Sopenharmony_cistatic enum libinput_config_status 1479a46c0ec8Sopenharmony_citp_tap_config_set_drag_enabled(struct libinput_device *device, 1480a46c0ec8Sopenharmony_ci enum libinput_config_drag_state enabled) 1481a46c0ec8Sopenharmony_ci{ 1482a46c0ec8Sopenharmony_ci struct evdev_dispatch *dispatch = evdev_device(device)->dispatch; 1483a46c0ec8Sopenharmony_ci struct tp_dispatch *tp = tp_dispatch(dispatch); 1484a46c0ec8Sopenharmony_ci 1485a46c0ec8Sopenharmony_ci tp->tap.drag_enabled = enabled; 1486a46c0ec8Sopenharmony_ci 1487a46c0ec8Sopenharmony_ci return LIBINPUT_CONFIG_STATUS_SUCCESS; 1488a46c0ec8Sopenharmony_ci} 1489a46c0ec8Sopenharmony_ci 1490a46c0ec8Sopenharmony_cistatic enum libinput_config_drag_state 1491a46c0ec8Sopenharmony_citp_tap_config_get_drag_enabled(struct libinput_device *device) 1492a46c0ec8Sopenharmony_ci{ 1493a46c0ec8Sopenharmony_ci struct evdev_dispatch *dispatch = evdev_device(device)->dispatch; 1494a46c0ec8Sopenharmony_ci struct tp_dispatch *tp = tp_dispatch(dispatch); 1495a46c0ec8Sopenharmony_ci 1496a46c0ec8Sopenharmony_ci return tp->tap.drag_enabled; 1497a46c0ec8Sopenharmony_ci} 1498a46c0ec8Sopenharmony_ci 1499a46c0ec8Sopenharmony_cistatic inline enum libinput_config_drag_state 1500a46c0ec8Sopenharmony_citp_drag_default(struct evdev_device *device) 1501a46c0ec8Sopenharmony_ci{ 1502a46c0ec8Sopenharmony_ci return LIBINPUT_CONFIG_DRAG_ENABLED; 1503a46c0ec8Sopenharmony_ci} 1504a46c0ec8Sopenharmony_ci 1505a46c0ec8Sopenharmony_cistatic enum libinput_config_drag_state 1506a46c0ec8Sopenharmony_citp_tap_config_get_default_drag_enabled(struct libinput_device *device) 1507a46c0ec8Sopenharmony_ci{ 1508a46c0ec8Sopenharmony_ci struct evdev_device *evdev = evdev_device(device); 1509a46c0ec8Sopenharmony_ci 1510a46c0ec8Sopenharmony_ci return tp_drag_default(evdev); 1511a46c0ec8Sopenharmony_ci} 1512a46c0ec8Sopenharmony_ci 1513a46c0ec8Sopenharmony_cistatic enum libinput_config_status 1514a46c0ec8Sopenharmony_citp_tap_config_set_draglock_enabled(struct libinput_device *device, 1515a46c0ec8Sopenharmony_ci enum libinput_config_drag_lock_state enabled) 1516a46c0ec8Sopenharmony_ci{ 1517a46c0ec8Sopenharmony_ci struct evdev_dispatch *dispatch = evdev_device(device)->dispatch; 1518a46c0ec8Sopenharmony_ci struct tp_dispatch *tp = tp_dispatch(dispatch); 1519a46c0ec8Sopenharmony_ci 1520a46c0ec8Sopenharmony_ci tp->tap.drag_lock_enabled = enabled; 1521a46c0ec8Sopenharmony_ci 1522a46c0ec8Sopenharmony_ci return LIBINPUT_CONFIG_STATUS_SUCCESS; 1523a46c0ec8Sopenharmony_ci} 1524a46c0ec8Sopenharmony_ci 1525a46c0ec8Sopenharmony_cistatic enum libinput_config_drag_lock_state 1526a46c0ec8Sopenharmony_citp_tap_config_get_draglock_enabled(struct libinput_device *device) 1527a46c0ec8Sopenharmony_ci{ 1528a46c0ec8Sopenharmony_ci struct evdev_dispatch *dispatch = evdev_device(device)->dispatch; 1529a46c0ec8Sopenharmony_ci struct tp_dispatch *tp = tp_dispatch(dispatch); 1530a46c0ec8Sopenharmony_ci 1531a46c0ec8Sopenharmony_ci return tp->tap.drag_lock_enabled; 1532a46c0ec8Sopenharmony_ci} 1533a46c0ec8Sopenharmony_ci 1534a46c0ec8Sopenharmony_cistatic inline enum libinput_config_drag_lock_state 1535a46c0ec8Sopenharmony_citp_drag_lock_default(struct evdev_device *device) 1536a46c0ec8Sopenharmony_ci{ 1537a46c0ec8Sopenharmony_ci return LIBINPUT_CONFIG_DRAG_LOCK_DISABLED; 1538a46c0ec8Sopenharmony_ci} 1539a46c0ec8Sopenharmony_ci 1540a46c0ec8Sopenharmony_cistatic enum libinput_config_drag_lock_state 1541a46c0ec8Sopenharmony_citp_tap_config_get_default_draglock_enabled(struct libinput_device *device) 1542a46c0ec8Sopenharmony_ci{ 1543a46c0ec8Sopenharmony_ci struct evdev_device *evdev = evdev_device(device); 1544a46c0ec8Sopenharmony_ci 1545a46c0ec8Sopenharmony_ci return tp_drag_lock_default(evdev); 1546a46c0ec8Sopenharmony_ci} 1547a46c0ec8Sopenharmony_ci 1548a46c0ec8Sopenharmony_civoid 1549a46c0ec8Sopenharmony_citp_init_tap(struct tp_dispatch *tp) 1550a46c0ec8Sopenharmony_ci{ 1551a46c0ec8Sopenharmony_ci char timer_name[64]; 1552a46c0ec8Sopenharmony_ci 1553a46c0ec8Sopenharmony_ci tp->tap.config.count = tp_tap_config_count; 1554a46c0ec8Sopenharmony_ci tp->tap.config.set_enabled = tp_tap_config_set_enabled; 1555a46c0ec8Sopenharmony_ci tp->tap.config.get_enabled = tp_tap_config_is_enabled; 1556a46c0ec8Sopenharmony_ci tp->tap.config.get_default = tp_tap_config_get_default; 1557a46c0ec8Sopenharmony_ci tp->tap.config.set_map = tp_tap_config_set_map; 1558a46c0ec8Sopenharmony_ci tp->tap.config.get_map = tp_tap_config_get_map; 1559a46c0ec8Sopenharmony_ci tp->tap.config.get_default_map = tp_tap_config_get_default_map; 1560a46c0ec8Sopenharmony_ci tp->tap.config.set_drag_enabled = tp_tap_config_set_drag_enabled; 1561a46c0ec8Sopenharmony_ci tp->tap.config.get_drag_enabled = tp_tap_config_get_drag_enabled; 1562a46c0ec8Sopenharmony_ci tp->tap.config.get_default_drag_enabled = tp_tap_config_get_default_drag_enabled; 1563a46c0ec8Sopenharmony_ci tp->tap.config.set_draglock_enabled = tp_tap_config_set_draglock_enabled; 1564a46c0ec8Sopenharmony_ci tp->tap.config.get_draglock_enabled = tp_tap_config_get_draglock_enabled; 1565a46c0ec8Sopenharmony_ci tp->tap.config.get_default_draglock_enabled = tp_tap_config_get_default_draglock_enabled; 1566a46c0ec8Sopenharmony_ci tp->device->base.config.tap = &tp->tap.config; 1567a46c0ec8Sopenharmony_ci 1568a46c0ec8Sopenharmony_ci tp->tap.state = TAP_STATE_IDLE; 1569a46c0ec8Sopenharmony_ci tp->tap.enabled = tp_tap_default(tp->device); 1570a46c0ec8Sopenharmony_ci tp->tap.map = LIBINPUT_CONFIG_TAP_MAP_LRM; 1571a46c0ec8Sopenharmony_ci tp->tap.want_map = tp->tap.map; 1572a46c0ec8Sopenharmony_ci tp->tap.drag_enabled = tp_drag_default(tp->device); 1573a46c0ec8Sopenharmony_ci tp->tap.drag_lock_enabled = tp_drag_lock_default(tp->device); 1574a46c0ec8Sopenharmony_ci 1575a46c0ec8Sopenharmony_ci snprintf(timer_name, 1576a46c0ec8Sopenharmony_ci sizeof(timer_name), 1577a46c0ec8Sopenharmony_ci "%s tap", 1578a46c0ec8Sopenharmony_ci evdev_device_get_sysname(tp->device)); 1579a46c0ec8Sopenharmony_ci libinput_timer_init(&tp->tap.timer, 1580a46c0ec8Sopenharmony_ci tp_libinput_context(tp), 1581a46c0ec8Sopenharmony_ci timer_name, 1582a46c0ec8Sopenharmony_ci tp_tap_handle_timeout, tp); 1583a46c0ec8Sopenharmony_ci} 1584a46c0ec8Sopenharmony_ci 1585a46c0ec8Sopenharmony_civoid 1586a46c0ec8Sopenharmony_citp_remove_tap(struct tp_dispatch *tp) 1587a46c0ec8Sopenharmony_ci{ 1588a46c0ec8Sopenharmony_ci libinput_timer_cancel(&tp->tap.timer); 1589a46c0ec8Sopenharmony_ci} 1590a46c0ec8Sopenharmony_ci 1591a46c0ec8Sopenharmony_civoid 1592a46c0ec8Sopenharmony_citp_release_all_taps(struct tp_dispatch *tp, uint64_t now) 1593a46c0ec8Sopenharmony_ci{ 1594a46c0ec8Sopenharmony_ci struct tp_touch *t; 1595a46c0ec8Sopenharmony_ci int i; 1596a46c0ec8Sopenharmony_ci 1597a46c0ec8Sopenharmony_ci for (i = 1; i <= 3; i++) { 1598a46c0ec8Sopenharmony_ci if (tp->tap.buttons_pressed & bit(i)) 1599a46c0ec8Sopenharmony_ci tp_tap_notify(tp, now, i, LIBINPUT_BUTTON_STATE_RELEASED); 1600a46c0ec8Sopenharmony_ci } 1601a46c0ec8Sopenharmony_ci 1602a46c0ec8Sopenharmony_ci /* To neutralize all current touches, we make them all palms */ 1603a46c0ec8Sopenharmony_ci tp_for_each_touch(tp, t) { 1604a46c0ec8Sopenharmony_ci if (t->state == TOUCH_NONE) 1605a46c0ec8Sopenharmony_ci continue; 1606a46c0ec8Sopenharmony_ci 1607a46c0ec8Sopenharmony_ci if (t->tap.is_palm) 1608a46c0ec8Sopenharmony_ci continue; 1609a46c0ec8Sopenharmony_ci 1610a46c0ec8Sopenharmony_ci t->tap.is_palm = true; 1611a46c0ec8Sopenharmony_ci t->tap.state = TAP_TOUCH_STATE_DEAD; 1612a46c0ec8Sopenharmony_ci } 1613a46c0ec8Sopenharmony_ci 1614a46c0ec8Sopenharmony_ci tp->tap.state = TAP_STATE_IDLE; 1615a46c0ec8Sopenharmony_ci tp->tap.nfingers_down = 0; 1616a46c0ec8Sopenharmony_ci} 1617a46c0ec8Sopenharmony_ci 1618a46c0ec8Sopenharmony_civoid 1619a46c0ec8Sopenharmony_citp_tap_suspend(struct tp_dispatch *tp, uint64_t time) 1620a46c0ec8Sopenharmony_ci{ 1621a46c0ec8Sopenharmony_ci tp_tap_enabled_update(tp, true, tp->tap.enabled, time); 1622a46c0ec8Sopenharmony_ci} 1623a46c0ec8Sopenharmony_ci 1624a46c0ec8Sopenharmony_civoid 1625a46c0ec8Sopenharmony_citp_tap_resume(struct tp_dispatch *tp, uint64_t time) 1626a46c0ec8Sopenharmony_ci{ 1627a46c0ec8Sopenharmony_ci tp_tap_enabled_update(tp, false, tp->tap.enabled, time); 1628a46c0ec8Sopenharmony_ci} 1629a46c0ec8Sopenharmony_ci 1630a46c0ec8Sopenharmony_cibool 1631a46c0ec8Sopenharmony_citp_tap_dragging(const struct tp_dispatch *tp) 1632a46c0ec8Sopenharmony_ci{ 1633a46c0ec8Sopenharmony_ci switch (tp->tap.state) { 1634a46c0ec8Sopenharmony_ci case TAP_STATE_1FGTAP_DRAGGING: 1635a46c0ec8Sopenharmony_ci case TAP_STATE_2FGTAP_DRAGGING: 1636a46c0ec8Sopenharmony_ci case TAP_STATE_3FGTAP_DRAGGING: 1637a46c0ec8Sopenharmony_ci case TAP_STATE_1FGTAP_DRAGGING_2: 1638a46c0ec8Sopenharmony_ci case TAP_STATE_2FGTAP_DRAGGING_2: 1639a46c0ec8Sopenharmony_ci case TAP_STATE_3FGTAP_DRAGGING_2: 1640a46c0ec8Sopenharmony_ci case TAP_STATE_1FGTAP_DRAGGING_WAIT: 1641a46c0ec8Sopenharmony_ci case TAP_STATE_2FGTAP_DRAGGING_WAIT: 1642a46c0ec8Sopenharmony_ci case TAP_STATE_3FGTAP_DRAGGING_WAIT: 1643a46c0ec8Sopenharmony_ci case TAP_STATE_1FGTAP_DRAGGING_OR_TAP: 1644a46c0ec8Sopenharmony_ci case TAP_STATE_2FGTAP_DRAGGING_OR_TAP: 1645a46c0ec8Sopenharmony_ci case TAP_STATE_3FGTAP_DRAGGING_OR_TAP: 1646a46c0ec8Sopenharmony_ci return true; 1647a46c0ec8Sopenharmony_ci default: 1648a46c0ec8Sopenharmony_ci return false; 1649a46c0ec8Sopenharmony_ci } 1650a46c0ec8Sopenharmony_ci} 1651a46c0ec8Sopenharmony_ci 1652a46c0ec8Sopenharmony_cibool 1653a46c0ec8Sopenharmony_citp_tap_dragging_or_double_tapping(const struct tp_dispatch *tp) 1654a46c0ec8Sopenharmony_ci{ 1655a46c0ec8Sopenharmony_ci switch (tp->tap.state) { 1656a46c0ec8Sopenharmony_ci case TAP_STATE_1FGTAP_DRAGGING_OR_DOUBLETAP: 1657a46c0ec8Sopenharmony_ci case TAP_STATE_2FGTAP_DRAGGING_OR_DOUBLETAP: 1658a46c0ec8Sopenharmony_ci case TAP_STATE_3FGTAP_DRAGGING_OR_DOUBLETAP: 1659a46c0ec8Sopenharmony_ci return true; 1660a46c0ec8Sopenharmony_ci default: 1661a46c0ec8Sopenharmony_ci return false; 1662a46c0ec8Sopenharmony_ci } 1663a46c0ec8Sopenharmony_ci} 1664