mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2026-05-07 20:08:19 +02:00
Merge branch 'wip/4fg-tap' into 'main'
Draft: tap: implement support for 4-finger tap as a new gesture See merge request libinput/libinput!1417
This commit is contained in:
commit
5836664641
12 changed files with 475 additions and 97 deletions
|
|
@ -712,12 +712,13 @@ tp_gesture_handle_event_on_state_hold(struct tp_dispatch *tp,
|
||||||
tp->gesture.state = GESTURE_STATE_3FG_DRAG_OR_SWIPE_START;
|
tp->gesture.state = GESTURE_STATE_3FG_DRAG_OR_SWIPE_START;
|
||||||
break;
|
break;
|
||||||
case GESTURE_EVENT_HOLD_TIMEOUT:
|
case GESTURE_EVENT_HOLD_TIMEOUT:
|
||||||
case GESTURE_EVENT_TAP_TIMEOUT:
|
|
||||||
case GESTURE_EVENT_FINGER_DETECTED:
|
case GESTURE_EVENT_FINGER_DETECTED:
|
||||||
case GESTURE_EVENT_3FG_DRAG_OR_SWIPE_TIMEOUT:
|
case GESTURE_EVENT_3FG_DRAG_OR_SWIPE_TIMEOUT:
|
||||||
case GESTURE_EVENT_3FG_DRAG_RELEASE_TIMEOUT:
|
case GESTURE_EVENT_3FG_DRAG_RELEASE_TIMEOUT:
|
||||||
log_gesture_bug(tp, event);
|
log_gesture_bug(tp, event);
|
||||||
break;
|
break;
|
||||||
|
case GESTURE_EVENT_TAP_TIMEOUT:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -72,6 +72,10 @@ tap_state_to_str(enum tp_tap_state state)
|
||||||
CASE_RETURN_STRING(TAP_STATE_TOUCH_3_HOLD);
|
CASE_RETURN_STRING(TAP_STATE_TOUCH_3_HOLD);
|
||||||
CASE_RETURN_STRING(TAP_STATE_TOUCH_3_RELEASE);
|
CASE_RETURN_STRING(TAP_STATE_TOUCH_3_RELEASE);
|
||||||
CASE_RETURN_STRING(TAP_STATE_TOUCH_3_RELEASE_2);
|
CASE_RETURN_STRING(TAP_STATE_TOUCH_3_RELEASE_2);
|
||||||
|
CASE_RETURN_STRING(TAP_STATE_TOUCH_4);
|
||||||
|
CASE_RETURN_STRING(TAP_STATE_TOUCH_4_HOLD);
|
||||||
|
CASE_RETURN_STRING(TAP_STATE_TOUCH_4_RELEASE);
|
||||||
|
CASE_RETURN_STRING(TAP_STATE_TOUCH_4_RELEASE_4);
|
||||||
CASE_RETURN_STRING(TAP_STATE_1FGTAP_DRAGGING);
|
CASE_RETURN_STRING(TAP_STATE_1FGTAP_DRAGGING);
|
||||||
CASE_RETURN_STRING(TAP_STATE_2FGTAP_DRAGGING);
|
CASE_RETURN_STRING(TAP_STATE_2FGTAP_DRAGGING);
|
||||||
CASE_RETURN_STRING(TAP_STATE_3FGTAP_DRAGGING);
|
CASE_RETURN_STRING(TAP_STATE_3FGTAP_DRAGGING);
|
||||||
|
|
@ -132,22 +136,33 @@ tp_tap_notify(struct tp_dispatch *tp,
|
||||||
|
|
||||||
assert(tp->tap.map < ARRAY_LENGTH(button_map));
|
assert(tp->tap.map < ARRAY_LENGTH(button_map));
|
||||||
|
|
||||||
if (nfingers < 1 || nfingers > 3)
|
if (nfingers < 1 || nfingers > 4)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
tp_gesture_cancel(tp, time);
|
tp_gesture_cancel(tp, time);
|
||||||
|
|
||||||
button = button_map[tp->tap.map][nfingers - 1];
|
if (nfingers < 4) {
|
||||||
|
button = button_map[tp->tap.map][nfingers - 1];
|
||||||
|
|
||||||
if (state == LIBINPUT_BUTTON_STATE_PRESSED)
|
if (state == LIBINPUT_BUTTON_STATE_PRESSED)
|
||||||
tp->tap.buttons_pressed |= bit(nfingers);
|
tp->tap.buttons_pressed |= bit(nfingers);
|
||||||
else
|
else
|
||||||
tp->tap.buttons_pressed &= ~bit(nfingers);
|
tp->tap.buttons_pressed &= ~bit(nfingers);
|
||||||
|
|
||||||
evdev_pointer_notify_button(tp->device,
|
evdev_pointer_notify_button(tp->device,
|
||||||
time,
|
time,
|
||||||
evdev_usage_from_uint32_t(button),
|
evdev_usage_from_uint32_t(button),
|
||||||
state);
|
state);
|
||||||
|
} else {
|
||||||
|
if (state == LIBINPUT_BUTTON_STATE_PRESSED) {
|
||||||
|
gesture_notify_tap_begin(&tp->device->base, time, nfingers);
|
||||||
|
} else {
|
||||||
|
gesture_notify_tap_end(&tp->device->base,
|
||||||
|
time,
|
||||||
|
nfingers,
|
||||||
|
false);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -518,8 +533,9 @@ tp_tap_touch3_handle_event(struct tp_dispatch *tp,
|
||||||
|
|
||||||
switch (event) {
|
switch (event) {
|
||||||
case TAP_EVENT_TOUCH:
|
case TAP_EVENT_TOUCH:
|
||||||
tp->tap.state = TAP_STATE_DEAD;
|
tp->tap.state = TAP_STATE_TOUCH_4;
|
||||||
tp_tap_clear_timer(tp);
|
tp->tap.saved_press_time = time;
|
||||||
|
tp_tap_set_timer(tp, time);
|
||||||
break;
|
break;
|
||||||
case TAP_EVENT_MOTION:
|
case TAP_EVENT_MOTION:
|
||||||
tp_tap_move_to_dead(tp, t);
|
tp_tap_move_to_dead(tp, t);
|
||||||
|
|
@ -556,7 +572,8 @@ tp_tap_touch3_hold_handle_event(struct tp_dispatch *tp,
|
||||||
|
|
||||||
switch (event) {
|
switch (event) {
|
||||||
case TAP_EVENT_TOUCH:
|
case TAP_EVENT_TOUCH:
|
||||||
tp->tap.state = TAP_STATE_DEAD;
|
tp->tap.state = TAP_STATE_TOUCH_4;
|
||||||
|
tp->tap.saved_press_time = time;
|
||||||
tp_tap_set_timer(tp, time);
|
tp_tap_set_timer(tp, time);
|
||||||
break;
|
break;
|
||||||
case TAP_EVENT_RELEASE:
|
case TAP_EVENT_RELEASE:
|
||||||
|
|
@ -746,6 +763,238 @@ tp_tap_touch3_release2_handle_event(struct tp_dispatch *tp,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
tp_tap_touch4_handle_event(struct tp_dispatch *tp,
|
||||||
|
struct tp_touch *t,
|
||||||
|
enum tap_event event,
|
||||||
|
usec_t time)
|
||||||
|
{
|
||||||
|
|
||||||
|
switch (event) {
|
||||||
|
case TAP_EVENT_TOUCH:
|
||||||
|
tp->tap.state = TAP_STATE_DEAD;
|
||||||
|
tp_tap_clear_timer(tp);
|
||||||
|
break;
|
||||||
|
case TAP_EVENT_MOTION:
|
||||||
|
tp_tap_move_to_dead(tp, t);
|
||||||
|
break;
|
||||||
|
case TAP_EVENT_TIMEOUT:
|
||||||
|
tp->tap.state = TAP_STATE_TOUCH_4_HOLD;
|
||||||
|
tp_tap_clear_timer(tp);
|
||||||
|
tp_gesture_tap_timeout(tp, time);
|
||||||
|
break;
|
||||||
|
case TAP_EVENT_RELEASE:
|
||||||
|
tp->tap.state = TAP_STATE_TOUCH_4_RELEASE;
|
||||||
|
tp->tap.saved_release_time = time;
|
||||||
|
tp_tap_set_timer(tp, time);
|
||||||
|
break;
|
||||||
|
case TAP_EVENT_BUTTON:
|
||||||
|
tp->tap.state = TAP_STATE_DEAD;
|
||||||
|
break;
|
||||||
|
case TAP_EVENT_THUMB:
|
||||||
|
break;
|
||||||
|
case TAP_EVENT_PALM:
|
||||||
|
tp->tap.state = TAP_STATE_TOUCH_3;
|
||||||
|
break;
|
||||||
|
case TAP_EVENT_PALM_UP:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
tp_tap_touch4_hold_handle_event(struct tp_dispatch *tp,
|
||||||
|
struct tp_touch *t,
|
||||||
|
enum tap_event event,
|
||||||
|
usec_t time)
|
||||||
|
{
|
||||||
|
|
||||||
|
switch (event) {
|
||||||
|
case TAP_EVENT_TOUCH:
|
||||||
|
tp->tap.state = TAP_STATE_DEAD;
|
||||||
|
tp_tap_set_timer(tp, time);
|
||||||
|
break;
|
||||||
|
case TAP_EVENT_RELEASE:
|
||||||
|
tp->tap.state = TAP_STATE_TOUCH_3_HOLD;
|
||||||
|
break;
|
||||||
|
case TAP_EVENT_MOTION:
|
||||||
|
tp_tap_move_to_dead(tp, t);
|
||||||
|
break;
|
||||||
|
case TAP_EVENT_TIMEOUT:
|
||||||
|
break;
|
||||||
|
case TAP_EVENT_BUTTON:
|
||||||
|
tp->tap.state = TAP_STATE_DEAD;
|
||||||
|
break;
|
||||||
|
case TAP_EVENT_THUMB:
|
||||||
|
break;
|
||||||
|
case TAP_EVENT_PALM:
|
||||||
|
tp->tap.state = TAP_STATE_TOUCH_3;
|
||||||
|
break;
|
||||||
|
case TAP_EVENT_PALM_UP:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
tp_tap_touch4_release_handle_event(struct tp_dispatch *tp,
|
||||||
|
struct tp_touch *t,
|
||||||
|
enum tap_event event,
|
||||||
|
usec_t time)
|
||||||
|
{
|
||||||
|
|
||||||
|
switch (event) {
|
||||||
|
case TAP_EVENT_TOUCH:
|
||||||
|
tp_tap_notify(tp,
|
||||||
|
tp->tap.saved_press_time,
|
||||||
|
4,
|
||||||
|
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||||
|
tp_tap_notify(tp,
|
||||||
|
tp->tap.saved_release_time,
|
||||||
|
4,
|
||||||
|
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||||
|
tp->tap.state = TAP_STATE_TOUCH_4_HOLD;
|
||||||
|
tp->tap.saved_press_time = time;
|
||||||
|
tp_tap_set_timer(tp, time);
|
||||||
|
break;
|
||||||
|
case TAP_EVENT_RELEASE:
|
||||||
|
tp->tap.state = TAP_STATE_TOUCH_4_RELEASE_4;
|
||||||
|
tp_tap_set_timer(tp, time);
|
||||||
|
break;
|
||||||
|
case TAP_EVENT_MOTION:
|
||||||
|
tp_tap_notify(tp,
|
||||||
|
tp->tap.saved_press_time,
|
||||||
|
4,
|
||||||
|
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||||
|
tp_tap_notify(tp,
|
||||||
|
tp->tap.saved_release_time,
|
||||||
|
4,
|
||||||
|
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||||
|
tp_tap_move_to_dead(tp, t);
|
||||||
|
break;
|
||||||
|
case TAP_EVENT_TIMEOUT:
|
||||||
|
tp_tap_notify(tp,
|
||||||
|
tp->tap.saved_press_time,
|
||||||
|
4,
|
||||||
|
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||||
|
tp_tap_notify(tp,
|
||||||
|
tp->tap.saved_release_time,
|
||||||
|
4,
|
||||||
|
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||||
|
tp->tap.state = TAP_STATE_TOUCH_3_HOLD;
|
||||||
|
break;
|
||||||
|
case TAP_EVENT_BUTTON:
|
||||||
|
tp_tap_notify(tp,
|
||||||
|
tp->tap.saved_press_time,
|
||||||
|
4,
|
||||||
|
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||||
|
tp_tap_notify(tp,
|
||||||
|
tp->tap.saved_release_time,
|
||||||
|
4,
|
||||||
|
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||||
|
tp->tap.state = TAP_STATE_DEAD;
|
||||||
|
break;
|
||||||
|
case TAP_EVENT_THUMB:
|
||||||
|
break;
|
||||||
|
case TAP_EVENT_PALM:
|
||||||
|
tp->tap.state = TAP_STATE_TOUCH_3_RELEASE;
|
||||||
|
break;
|
||||||
|
case TAP_EVENT_PALM_UP:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
tp_tap_touch4_release4_handle_event(struct tp_dispatch *tp,
|
||||||
|
struct tp_touch *t,
|
||||||
|
enum tap_event event,
|
||||||
|
usec_t time)
|
||||||
|
{
|
||||||
|
|
||||||
|
switch (event) {
|
||||||
|
case TAP_EVENT_TOUCH:
|
||||||
|
tp_tap_notify(tp,
|
||||||
|
tp->tap.saved_press_time,
|
||||||
|
4,
|
||||||
|
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||||
|
tp_tap_notify(tp,
|
||||||
|
tp->tap.saved_release_time,
|
||||||
|
4,
|
||||||
|
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||||
|
tp->tap.state = TAP_STATE_TOUCH_3;
|
||||||
|
tp->tap.saved_press_time = time;
|
||||||
|
tp_tap_set_timer(tp, time);
|
||||||
|
break;
|
||||||
|
case TAP_EVENT_RELEASE:
|
||||||
|
tp_tap_notify(tp,
|
||||||
|
tp->tap.saved_press_time,
|
||||||
|
4,
|
||||||
|
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||||
|
tp_tap_notify(tp,
|
||||||
|
tp->tap.saved_release_time,
|
||||||
|
4,
|
||||||
|
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||||
|
tp->tap.state = TAP_STATE_IDLE;
|
||||||
|
break;
|
||||||
|
case TAP_EVENT_MOTION:
|
||||||
|
tp_tap_notify(tp,
|
||||||
|
tp->tap.saved_press_time,
|
||||||
|
4,
|
||||||
|
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||||
|
tp_tap_notify(tp,
|
||||||
|
tp->tap.saved_release_time,
|
||||||
|
4,
|
||||||
|
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||||
|
tp_tap_move_to_dead(tp, t);
|
||||||
|
break;
|
||||||
|
case TAP_EVENT_TIMEOUT:
|
||||||
|
tp_tap_notify(tp,
|
||||||
|
tp->tap.saved_press_time,
|
||||||
|
4,
|
||||||
|
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||||
|
tp_tap_notify(tp,
|
||||||
|
tp->tap.saved_release_time,
|
||||||
|
4,
|
||||||
|
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||||
|
tp->tap.state = TAP_STATE_HOLD;
|
||||||
|
break;
|
||||||
|
case TAP_EVENT_BUTTON:
|
||||||
|
tp_tap_notify(tp,
|
||||||
|
tp->tap.saved_press_time,
|
||||||
|
4,
|
||||||
|
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||||
|
tp_tap_notify(tp,
|
||||||
|
tp->tap.saved_release_time,
|
||||||
|
4,
|
||||||
|
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||||
|
tp->tap.state = TAP_STATE_DEAD;
|
||||||
|
break;
|
||||||
|
case TAP_EVENT_THUMB:
|
||||||
|
break;
|
||||||
|
case TAP_EVENT_PALM:
|
||||||
|
tp_tap_notify(tp,
|
||||||
|
tp->tap.saved_press_time,
|
||||||
|
3,
|
||||||
|
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||||
|
if (tp->tap.drag_enabled) {
|
||||||
|
/* Resetting the timer to the appropriate delay
|
||||||
|
* for a three-finger tap would be ideal, but the
|
||||||
|
* timestamp of the last real finger release is lost,
|
||||||
|
* so the in-progress similar delay for release
|
||||||
|
* of the finger which became a palm instead
|
||||||
|
* will have to do */
|
||||||
|
tp->tap.state = TAP_STATE_3FGTAP_TAPPED;
|
||||||
|
} else {
|
||||||
|
tp_tap_notify(tp,
|
||||||
|
tp->tap.saved_release_time,
|
||||||
|
3,
|
||||||
|
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||||
|
tp->tap.state = TAP_STATE_IDLE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case TAP_EVENT_PALM_UP:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
tp_tap_dragging_or_doubletap_handle_event(struct tp_dispatch *tp,
|
tp_tap_dragging_or_doubletap_handle_event(struct tp_dispatch *tp,
|
||||||
struct tp_touch *t,
|
struct tp_touch *t,
|
||||||
|
|
@ -1117,6 +1366,18 @@ tp_tap_handle_event(struct tp_dispatch *tp,
|
||||||
case TAP_STATE_TOUCH_3_RELEASE_2:
|
case TAP_STATE_TOUCH_3_RELEASE_2:
|
||||||
tp_tap_touch3_release2_handle_event(tp, t, event, time);
|
tp_tap_touch3_release2_handle_event(tp, t, event, time);
|
||||||
break;
|
break;
|
||||||
|
case TAP_STATE_TOUCH_4:
|
||||||
|
tp_tap_touch4_handle_event(tp, t, event, time);
|
||||||
|
break;
|
||||||
|
case TAP_STATE_TOUCH_4_HOLD:
|
||||||
|
tp_tap_touch4_hold_handle_event(tp, t, event, time);
|
||||||
|
break;
|
||||||
|
case TAP_STATE_TOUCH_4_RELEASE:
|
||||||
|
tp_tap_touch4_release_handle_event(tp, t, event, time);
|
||||||
|
break;
|
||||||
|
case TAP_STATE_TOUCH_4_RELEASE_4:
|
||||||
|
tp_tap_touch4_release4_handle_event(tp, t, event, time);
|
||||||
|
break;
|
||||||
case TAP_STATE_1FGTAP_DRAGGING_OR_DOUBLETAP:
|
case TAP_STATE_1FGTAP_DRAGGING_OR_DOUBLETAP:
|
||||||
tp_tap_dragging_or_doubletap_handle_event(tp, t, event, time, 1);
|
tp_tap_dragging_or_doubletap_handle_event(tp, t, event, time, 1);
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,6 @@
|
||||||
#define DEFAULT_TRACKPOINT_EVENT_TIMEOUT usec_from_millis(40)
|
#define DEFAULT_TRACKPOINT_EVENT_TIMEOUT usec_from_millis(40)
|
||||||
#define DEFAULT_KEYBOARD_ACTIVITY_TIMEOUT_1 usec_from_millis(200)
|
#define DEFAULT_KEYBOARD_ACTIVITY_TIMEOUT_1 usec_from_millis(200)
|
||||||
#define DEFAULT_KEYBOARD_ACTIVITY_TIMEOUT_2 usec_from_millis(500)
|
#define DEFAULT_KEYBOARD_ACTIVITY_TIMEOUT_2 usec_from_millis(500)
|
||||||
#define FAKE_FINGER_OVERFLOW bit(7)
|
|
||||||
#define THUMB_IGNORE_SPEED_THRESHOLD 20 /* mm/s */
|
#define THUMB_IGNORE_SPEED_THRESHOLD 20 /* mm/s */
|
||||||
|
|
||||||
#define MOUSE_HAS_SENT_EVENTS bit(1)
|
#define MOUSE_HAS_SENT_EVENTS bit(1)
|
||||||
|
|
@ -261,7 +260,7 @@ tp_get_touch(struct tp_dispatch *tp, unsigned int slot)
|
||||||
static inline unsigned int
|
static inline unsigned int
|
||||||
tp_fake_finger_count(struct tp_dispatch *tp)
|
tp_fake_finger_count(struct tp_dispatch *tp)
|
||||||
{
|
{
|
||||||
unsigned int fake_touches = tp->fake_touches & ~(FAKE_FINGER_OVERFLOW | 0x1);
|
unsigned int fake_touches = tp->fake_touches & ~0x1;
|
||||||
|
|
||||||
/* Only one of BTN_TOOL_DOUBLETAP/TRIPLETAP/... may be set at any
|
/* Only one of BTN_TOOL_DOUBLETAP/TRIPLETAP/... may be set at any
|
||||||
* time */
|
* time */
|
||||||
|
|
@ -270,9 +269,6 @@ tp_fake_finger_count(struct tp_dispatch *tp)
|
||||||
"Invalid fake finger state %#x\n",
|
"Invalid fake finger state %#x\n",
|
||||||
tp->fake_touches);
|
tp->fake_touches);
|
||||||
|
|
||||||
if (tp->fake_touches & FAKE_FINGER_OVERFLOW)
|
|
||||||
return FAKE_FINGER_OVERFLOW;
|
|
||||||
|
|
||||||
/* don't count BTN_TOUCH */
|
/* don't count BTN_TOUCH */
|
||||||
return ffs(tp->fake_touches >> 1);
|
return ffs(tp->fake_touches >> 1);
|
||||||
}
|
}
|
||||||
|
|
@ -290,33 +286,29 @@ tp_fake_finger_set(struct tp_dispatch *tp, evdev_usage_t usage, bool is_press)
|
||||||
|
|
||||||
switch (evdev_usage_enum(usage)) {
|
switch (evdev_usage_enum(usage)) {
|
||||||
case EVDEV_BTN_TOUCH:
|
case EVDEV_BTN_TOUCH:
|
||||||
if (!is_press)
|
|
||||||
tp->fake_touches &= ~FAKE_FINGER_OVERFLOW;
|
|
||||||
shift = 0;
|
shift = 0;
|
||||||
break;
|
break;
|
||||||
case EVDEV_BTN_TOOL_FINGER:
|
case EVDEV_BTN_TOOL_FINGER:
|
||||||
shift = 1;
|
shift = 1;
|
||||||
break;
|
break;
|
||||||
case EVDEV_BTN_TOOL_DOUBLETAP:
|
case EVDEV_BTN_TOOL_DOUBLETAP:
|
||||||
case EVDEV_BTN_TOOL_TRIPLETAP:
|
shift = 2;
|
||||||
case EVDEV_BTN_TOOL_QUADTAP:
|
break;
|
||||||
shift = evdev_usage_enum(usage) - EVDEV_BTN_TOOL_DOUBLETAP + 2;
|
case EVDEV_BTN_TOOL_TRIPLETAP:
|
||||||
|
shift = 3;
|
||||||
|
break;
|
||||||
|
case EVDEV_BTN_TOOL_QUADTAP:
|
||||||
|
shift = 4;
|
||||||
break;
|
break;
|
||||||
/* when QUINTTAP is released we're either switching to 6 fingers
|
|
||||||
(flag stays in place until BTN_TOUCH is released) or
|
|
||||||
one of DOUBLE/TRIPLE/QUADTAP (will clear the flag on press) */
|
|
||||||
case EVDEV_BTN_TOOL_QUINTTAP:
|
case EVDEV_BTN_TOOL_QUINTTAP:
|
||||||
if (is_press)
|
shift = 5;
|
||||||
tp->fake_touches |= FAKE_FINGER_OVERFLOW;
|
break;
|
||||||
return;
|
|
||||||
default:
|
default:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_press) {
|
if (is_press) {
|
||||||
tp->fake_touches &= ~FAKE_FINGER_OVERFLOW;
|
|
||||||
tp->fake_touches |= bit(shift);
|
tp->fake_touches |= bit(shift);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
tp->fake_touches &= ~bit(shift);
|
tp->fake_touches &= ~bit(shift);
|
||||||
}
|
}
|
||||||
|
|
@ -629,9 +621,6 @@ tp_process_fake_touches(struct tp_dispatch *tp, usec_t time)
|
||||||
unsigned int i, start;
|
unsigned int i, start;
|
||||||
|
|
||||||
nfake_touches = tp_fake_finger_count(tp);
|
nfake_touches = tp_fake_finger_count(tp);
|
||||||
if (nfake_touches == FAKE_FINGER_OVERFLOW)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (tp->device->model_flags & EVDEV_MODEL_SYNAPTICS_SERIAL_TOUCHPAD)
|
if (tp->device->model_flags & EVDEV_MODEL_SYNAPTICS_SERIAL_TOUCHPAD)
|
||||||
tp_restore_synaptics_touches(tp, time);
|
tp_restore_synaptics_touches(tp, time);
|
||||||
|
|
||||||
|
|
@ -1144,9 +1133,6 @@ tp_unhover_pressure(struct tp_dispatch *tp, usec_t time)
|
||||||
unsigned int real_fingers_down = 0;
|
unsigned int real_fingers_down = 0;
|
||||||
|
|
||||||
nfake_touches = tp_fake_finger_count(tp);
|
nfake_touches = tp_fake_finger_count(tp);
|
||||||
if (nfake_touches == FAKE_FINGER_OVERFLOW)
|
|
||||||
nfake_touches = 0;
|
|
||||||
|
|
||||||
for (i = 0; i < (int)tp->num_slots; i++) {
|
for (i = 0; i < (int)tp->num_slots; i++) {
|
||||||
t = tp_get_touch(tp, i);
|
t = tp_get_touch(tp, i);
|
||||||
|
|
||||||
|
|
@ -1270,9 +1256,6 @@ tp_unhover_fake_touches(struct tp_dispatch *tp, usec_t time)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
nfake_touches = tp_fake_finger_count(tp);
|
nfake_touches = tp_fake_finger_count(tp);
|
||||||
if (nfake_touches == FAKE_FINGER_OVERFLOW)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (tp->nfingers_down == nfake_touches &&
|
if (tp->nfingers_down == nfake_touches &&
|
||||||
((tp->nfingers_down == 0 && !tp_fake_finger_is_touching(tp)) ||
|
((tp->nfingers_down == 0 && !tp_fake_finger_is_touching(tp)) ||
|
||||||
(tp->nfingers_down > 0 && tp_fake_finger_is_touching(tp))))
|
(tp->nfingers_down > 0 && tp_fake_finger_is_touching(tp))))
|
||||||
|
|
|
||||||
|
|
@ -116,6 +116,10 @@ enum tp_tap_state {
|
||||||
TAP_STATE_TOUCH_3_HOLD,
|
TAP_STATE_TOUCH_3_HOLD,
|
||||||
TAP_STATE_TOUCH_3_RELEASE,
|
TAP_STATE_TOUCH_3_RELEASE,
|
||||||
TAP_STATE_TOUCH_3_RELEASE_2,
|
TAP_STATE_TOUCH_3_RELEASE_2,
|
||||||
|
TAP_STATE_TOUCH_4,
|
||||||
|
TAP_STATE_TOUCH_4_HOLD,
|
||||||
|
TAP_STATE_TOUCH_4_RELEASE,
|
||||||
|
TAP_STATE_TOUCH_4_RELEASE_4,
|
||||||
TAP_STATE_1FGTAP_DRAGGING_OR_DOUBLETAP,
|
TAP_STATE_1FGTAP_DRAGGING_OR_DOUBLETAP,
|
||||||
TAP_STATE_2FGTAP_DRAGGING_OR_DOUBLETAP,
|
TAP_STATE_2FGTAP_DRAGGING_OR_DOUBLETAP,
|
||||||
TAP_STATE_3FGTAP_DRAGGING_OR_DOUBLETAP,
|
TAP_STATE_3FGTAP_DRAGGING_OR_DOUBLETAP,
|
||||||
|
|
|
||||||
|
|
@ -894,6 +894,15 @@ gesture_notify_hold_end(struct libinput_device *device,
|
||||||
int finger_count,
|
int finger_count,
|
||||||
bool cancelled);
|
bool cancelled);
|
||||||
|
|
||||||
|
void
|
||||||
|
gesture_notify_tap_begin(struct libinput_device *device, usec_t time, int finger_count);
|
||||||
|
|
||||||
|
void
|
||||||
|
gesture_notify_tap_end(struct libinput_device *device,
|
||||||
|
usec_t time,
|
||||||
|
int finger_count,
|
||||||
|
bool cancelled);
|
||||||
|
|
||||||
void
|
void
|
||||||
tablet_notify_axis(struct libinput_device *device,
|
tablet_notify_axis(struct libinput_device *device,
|
||||||
usec_t time,
|
usec_t time,
|
||||||
|
|
|
||||||
|
|
@ -118,6 +118,8 @@ event_type_to_str(enum libinput_event_type type)
|
||||||
CASE_RETURN_STRING(LIBINPUT_EVENT_GESTURE_PINCH_END);
|
CASE_RETURN_STRING(LIBINPUT_EVENT_GESTURE_PINCH_END);
|
||||||
CASE_RETURN_STRING(LIBINPUT_EVENT_GESTURE_HOLD_BEGIN);
|
CASE_RETURN_STRING(LIBINPUT_EVENT_GESTURE_HOLD_BEGIN);
|
||||||
CASE_RETURN_STRING(LIBINPUT_EVENT_GESTURE_HOLD_END);
|
CASE_RETURN_STRING(LIBINPUT_EVENT_GESTURE_HOLD_END);
|
||||||
|
CASE_RETURN_STRING(LIBINPUT_EVENT_GESTURE_TAP_BEGIN);
|
||||||
|
CASE_RETURN_STRING(LIBINPUT_EVENT_GESTURE_TAP_END);
|
||||||
CASE_RETURN_STRING(LIBINPUT_EVENT_SWITCH_TOGGLE);
|
CASE_RETURN_STRING(LIBINPUT_EVENT_SWITCH_TOGGLE);
|
||||||
case LIBINPUT_EVENT_NONE:
|
case LIBINPUT_EVENT_NONE:
|
||||||
abort();
|
abort();
|
||||||
|
|
@ -448,7 +450,9 @@ libinput_event_get_gesture_event(struct libinput_event *event)
|
||||||
LIBINPUT_EVENT_GESTURE_PINCH_UPDATE,
|
LIBINPUT_EVENT_GESTURE_PINCH_UPDATE,
|
||||||
LIBINPUT_EVENT_GESTURE_PINCH_END,
|
LIBINPUT_EVENT_GESTURE_PINCH_END,
|
||||||
LIBINPUT_EVENT_GESTURE_HOLD_BEGIN,
|
LIBINPUT_EVENT_GESTURE_HOLD_BEGIN,
|
||||||
LIBINPUT_EVENT_GESTURE_HOLD_END);
|
LIBINPUT_EVENT_GESTURE_HOLD_END,
|
||||||
|
LIBINPUT_EVENT_GESTURE_TAP_BEGIN,
|
||||||
|
LIBINPUT_EVENT_GESTURE_TAP_END);
|
||||||
|
|
||||||
return (struct libinput_event_gesture *)event;
|
return (struct libinput_event_gesture *)event;
|
||||||
}
|
}
|
||||||
|
|
@ -997,7 +1001,9 @@ libinput_event_gesture_get_time(struct libinput_event_gesture *event)
|
||||||
LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE,
|
LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE,
|
||||||
LIBINPUT_EVENT_GESTURE_SWIPE_END,
|
LIBINPUT_EVENT_GESTURE_SWIPE_END,
|
||||||
LIBINPUT_EVENT_GESTURE_HOLD_BEGIN,
|
LIBINPUT_EVENT_GESTURE_HOLD_BEGIN,
|
||||||
LIBINPUT_EVENT_GESTURE_HOLD_END);
|
LIBINPUT_EVENT_GESTURE_HOLD_END,
|
||||||
|
LIBINPUT_EVENT_GESTURE_TAP_BEGIN,
|
||||||
|
LIBINPUT_EVENT_GESTURE_TAP_END);
|
||||||
|
|
||||||
return usec_to_millis(event->time);
|
return usec_to_millis(event->time);
|
||||||
}
|
}
|
||||||
|
|
@ -1015,7 +1021,9 @@ libinput_event_gesture_get_time_usec(struct libinput_event_gesture *event)
|
||||||
LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE,
|
LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE,
|
||||||
LIBINPUT_EVENT_GESTURE_SWIPE_END,
|
LIBINPUT_EVENT_GESTURE_SWIPE_END,
|
||||||
LIBINPUT_EVENT_GESTURE_HOLD_BEGIN,
|
LIBINPUT_EVENT_GESTURE_HOLD_BEGIN,
|
||||||
LIBINPUT_EVENT_GESTURE_HOLD_END);
|
LIBINPUT_EVENT_GESTURE_HOLD_END,
|
||||||
|
LIBINPUT_EVENT_GESTURE_TAP_BEGIN,
|
||||||
|
LIBINPUT_EVENT_GESTURE_TAP_END);
|
||||||
|
|
||||||
return usec_as_uint64_t(event->time);
|
return usec_as_uint64_t(event->time);
|
||||||
}
|
}
|
||||||
|
|
@ -1033,7 +1041,9 @@ libinput_event_gesture_get_finger_count(struct libinput_event_gesture *event)
|
||||||
LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE,
|
LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE,
|
||||||
LIBINPUT_EVENT_GESTURE_SWIPE_END,
|
LIBINPUT_EVENT_GESTURE_SWIPE_END,
|
||||||
LIBINPUT_EVENT_GESTURE_HOLD_BEGIN,
|
LIBINPUT_EVENT_GESTURE_HOLD_BEGIN,
|
||||||
LIBINPUT_EVENT_GESTURE_HOLD_END);
|
LIBINPUT_EVENT_GESTURE_HOLD_END,
|
||||||
|
LIBINPUT_EVENT_GESTURE_TAP_BEGIN,
|
||||||
|
LIBINPUT_EVENT_GESTURE_TAP_END);
|
||||||
|
|
||||||
return event->finger_count;
|
return event->finger_count;
|
||||||
}
|
}
|
||||||
|
|
@ -1046,7 +1056,8 @@ libinput_event_gesture_get_cancelled(struct libinput_event_gesture *event)
|
||||||
0,
|
0,
|
||||||
LIBINPUT_EVENT_GESTURE_PINCH_END,
|
LIBINPUT_EVENT_GESTURE_PINCH_END,
|
||||||
LIBINPUT_EVENT_GESTURE_SWIPE_END,
|
LIBINPUT_EVENT_GESTURE_SWIPE_END,
|
||||||
LIBINPUT_EVENT_GESTURE_HOLD_END);
|
LIBINPUT_EVENT_GESTURE_HOLD_END,
|
||||||
|
LIBINPUT_EVENT_GESTURE_TAP_END);
|
||||||
|
|
||||||
return event->cancelled;
|
return event->cancelled;
|
||||||
}
|
}
|
||||||
|
|
@ -3217,6 +3228,41 @@ gesture_notify_hold_end(struct libinput_device *device,
|
||||||
0.0);
|
0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gesture_notify_tap_begin(struct libinput_device *device, usec_t time, int finger_count)
|
||||||
|
{
|
||||||
|
const struct normalized_coords zero = { 0.0, 0.0 };
|
||||||
|
|
||||||
|
gesture_notify(device,
|
||||||
|
time,
|
||||||
|
LIBINPUT_EVENT_GESTURE_TAP_BEGIN,
|
||||||
|
finger_count,
|
||||||
|
0,
|
||||||
|
&zero,
|
||||||
|
&zero,
|
||||||
|
0.0,
|
||||||
|
0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gesture_notify_tap_end(struct libinput_device *device,
|
||||||
|
usec_t time,
|
||||||
|
int finger_count,
|
||||||
|
bool cancelled)
|
||||||
|
{
|
||||||
|
const struct normalized_coords zero = { 0.0, 0.0 };
|
||||||
|
|
||||||
|
gesture_notify(device,
|
||||||
|
time,
|
||||||
|
LIBINPUT_EVENT_GESTURE_TAP_END,
|
||||||
|
finger_count,
|
||||||
|
cancelled,
|
||||||
|
&zero,
|
||||||
|
&zero,
|
||||||
|
0.0,
|
||||||
|
0.0);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
switch_notify_toggle(struct libinput_device *device,
|
switch_notify_toggle(struct libinput_device *device,
|
||||||
usec_t time,
|
usec_t time,
|
||||||
|
|
|
||||||
|
|
@ -1036,6 +1036,22 @@ enum libinput_event_type {
|
||||||
LIBINPUT_EVENT_GESTURE_HOLD_BEGIN,
|
LIBINPUT_EVENT_GESTURE_HOLD_BEGIN,
|
||||||
LIBINPUT_EVENT_GESTURE_HOLD_END,
|
LIBINPUT_EVENT_GESTURE_HOLD_END,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A tap gesture signals a number of fingers put down and released in
|
||||||
|
* the same position within a given timeout.
|
||||||
|
*
|
||||||
|
* For historical reasons, taps for one, two and three fingers are
|
||||||
|
* sent as button events, see libinput_device_config_tap_set_button_map()
|
||||||
|
* This gesture is currently only sent for a four-finger tap but may
|
||||||
|
* be sent for other taps in the future.
|
||||||
|
*
|
||||||
|
* See libinput_device_config_tap_set_enabled() for details.
|
||||||
|
*
|
||||||
|
* @since 1.31
|
||||||
|
*/
|
||||||
|
LIBINPUT_EVENT_GESTURE_TAP_BEGIN,
|
||||||
|
LIBINPUT_EVENT_GESTURE_TAP_END,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @since 1.7
|
* @since 1.7
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -108,6 +108,12 @@ event_type_to_str(enum libinput_event_type evtype)
|
||||||
case LIBINPUT_EVENT_GESTURE_HOLD_END:
|
case LIBINPUT_EVENT_GESTURE_HOLD_END:
|
||||||
type = "GESTURE_HOLD_END";
|
type = "GESTURE_HOLD_END";
|
||||||
break;
|
break;
|
||||||
|
case LIBINPUT_EVENT_GESTURE_TAP_BEGIN:
|
||||||
|
type = "GESTURE_TAP_BEGIN";
|
||||||
|
break;
|
||||||
|
case LIBINPUT_EVENT_GESTURE_TAP_END:
|
||||||
|
type = "GESTURE_TAP_END";
|
||||||
|
break;
|
||||||
case LIBINPUT_EVENT_TABLET_TOOL_AXIS:
|
case LIBINPUT_EVENT_TABLET_TOOL_AXIS:
|
||||||
type = "TABLET_TOOL_AXIS";
|
type = "TABLET_TOOL_AXIS";
|
||||||
break;
|
break;
|
||||||
|
|
@ -789,6 +795,7 @@ print_gesture_event_without_coords(struct libinput_event *ev,
|
||||||
|
|
||||||
if (type == LIBINPUT_EVENT_GESTURE_SWIPE_END ||
|
if (type == LIBINPUT_EVENT_GESTURE_SWIPE_END ||
|
||||||
type == LIBINPUT_EVENT_GESTURE_PINCH_END ||
|
type == LIBINPUT_EVENT_GESTURE_PINCH_END ||
|
||||||
|
type == LIBINPUT_EVENT_GESTURE_TAP_END ||
|
||||||
type == LIBINPUT_EVENT_GESTURE_HOLD_END)
|
type == LIBINPUT_EVENT_GESTURE_HOLD_END)
|
||||||
cancelled = libinput_event_gesture_get_cancelled(t);
|
cancelled = libinput_event_gesture_get_cancelled(t);
|
||||||
|
|
||||||
|
|
@ -1076,6 +1083,12 @@ libinput_event_to_str(struct libinput_event *ev,
|
||||||
case LIBINPUT_EVENT_GESTURE_HOLD_END:
|
case LIBINPUT_EVENT_GESTURE_HOLD_END:
|
||||||
event_str = print_gesture_event_without_coords(ev, &opts);
|
event_str = print_gesture_event_without_coords(ev, &opts);
|
||||||
break;
|
break;
|
||||||
|
case LIBINPUT_EVENT_GESTURE_TAP_BEGIN:
|
||||||
|
event_str = print_gesture_event_without_coords(ev, &opts);
|
||||||
|
break;
|
||||||
|
case LIBINPUT_EVENT_GESTURE_TAP_END:
|
||||||
|
event_str = print_gesture_event_without_coords(ev, &opts);
|
||||||
|
break;
|
||||||
case LIBINPUT_EVENT_TABLET_TOOL_AXIS:
|
case LIBINPUT_EVENT_TABLET_TOOL_AXIS:
|
||||||
event_str = print_tablet_axis_event(ev, &opts);
|
event_str = print_tablet_axis_event(ev, &opts);
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -3702,6 +3702,12 @@ litest_event_type_str(enum libinput_event_type type)
|
||||||
case LIBINPUT_EVENT_GESTURE_HOLD_END:
|
case LIBINPUT_EVENT_GESTURE_HOLD_END:
|
||||||
str = "GESTURE HOLD END";
|
str = "GESTURE HOLD END";
|
||||||
break;
|
break;
|
||||||
|
case LIBINPUT_EVENT_GESTURE_TAP_BEGIN:
|
||||||
|
str = "GESTURE TAP BEGIN";
|
||||||
|
break;
|
||||||
|
case LIBINPUT_EVENT_GESTURE_TAP_END:
|
||||||
|
str = "GESTURE TAP END";
|
||||||
|
break;
|
||||||
case LIBINPUT_EVENT_TABLET_TOOL_AXIS:
|
case LIBINPUT_EVENT_TABLET_TOOL_AXIS:
|
||||||
str = "TABLET TOOL AXIS";
|
str = "TABLET TOOL AXIS";
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -1772,7 +1772,7 @@ START_TEST(gestures_3fg_drag_lock_resume_3fg_release_no_motion)
|
||||||
bool wait_for_timeout = litest_test_param_get_bool(test_env->params, "wait");
|
bool wait_for_timeout = litest_test_param_get_bool(test_env->params, "wait");
|
||||||
|
|
||||||
/* tap-enabled for 4fg finger count doesn't make a difference */
|
/* tap-enabled for 4fg finger count doesn't make a difference */
|
||||||
bool expect_tap = finger_count <= 3 && tap_enabled && !wait_for_timeout;
|
bool expect_tap = tap_enabled && !wait_for_timeout;
|
||||||
|
|
||||||
if (litest_slot_count(dev) < 3)
|
if (litest_slot_count(dev) < 3)
|
||||||
return LITEST_NOT_APPLICABLE;
|
return LITEST_NOT_APPLICABLE;
|
||||||
|
|
@ -1845,12 +1845,21 @@ START_TEST(gestures_3fg_drag_lock_resume_3fg_release_no_motion)
|
||||||
BTN_LEFT,
|
BTN_LEFT,
|
||||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||||
litest_checkpoint("Expecting 3fg tap");
|
litest_checkpoint("Expecting 3fg tap");
|
||||||
litest_assert_button_event(li,
|
if (finger_count < 4) {
|
||||||
BTN_MIDDLE,
|
litest_assert_button_event(li,
|
||||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
BTN_MIDDLE,
|
||||||
litest_assert_button_event(li,
|
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||||
BTN_MIDDLE,
|
litest_assert_button_event(li,
|
||||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
BTN_MIDDLE,
|
||||||
|
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||||
|
} else {
|
||||||
|
litest_assert_gesture_event(li,
|
||||||
|
LIBINPUT_EVENT_GESTURE_TAP_BEGIN,
|
||||||
|
finger_count);
|
||||||
|
litest_assert_gesture_event(li,
|
||||||
|
LIBINPUT_EVENT_GESTURE_TAP_END,
|
||||||
|
finger_count);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
litest_assert_empty_queue(li);
|
litest_assert_empty_queue(li);
|
||||||
|
|
|
||||||
|
|
@ -3401,13 +3401,17 @@ START_TEST(touchpad_4fg_tap)
|
||||||
{
|
{
|
||||||
struct litest_device *dev = litest_current_device();
|
struct litest_device *dev = litest_current_device();
|
||||||
struct libinput *li = dev->libinput;
|
struct libinput *li = dev->libinput;
|
||||||
|
bool with_hold = litest_test_param_get_bool(test_env->params, "with-hold");
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (litest_slot_count(dev) <= 4)
|
if (litest_slot_count(dev) <= 4)
|
||||||
return LITEST_NOT_APPLICABLE;
|
return LITEST_NOT_APPLICABLE;
|
||||||
|
|
||||||
litest_enable_tap(dev->libinput_device);
|
litest_enable_tap(dev->libinput_device);
|
||||||
litest_disable_hold_gestures(dev->libinput_device);
|
if (with_hold)
|
||||||
|
litest_enable_hold_gestures(dev->libinput_device);
|
||||||
|
else
|
||||||
|
litest_disable_hold_gestures(dev->libinput_device);
|
||||||
|
|
||||||
for (i = 0; i < 4; i++) {
|
for (i = 0; i < 4; i++) {
|
||||||
litest_drain_events(li);
|
litest_drain_events(li);
|
||||||
|
|
@ -3423,49 +3427,12 @@ START_TEST(touchpad_4fg_tap)
|
||||||
litest_touch_up(dev, (i + 0) % 4);
|
litest_touch_up(dev, (i + 0) % 4);
|
||||||
|
|
||||||
litest_dispatch(li);
|
litest_dispatch(li);
|
||||||
litest_assert_empty_queue(li);
|
litest_assert_gesture_event(li, LIBINPUT_EVENT_GESTURE_TAP_BEGIN, 4);
|
||||||
litest_timeout_tap(li);
|
litest_assert_gesture_event(li, LIBINPUT_EVENT_GESTURE_TAP_END, 4);
|
||||||
litest_assert_empty_queue(li);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
START_TEST(touchpad_4fg_tap_quickrelease)
|
|
||||||
{
|
|
||||||
struct litest_device *dev = litest_current_device();
|
|
||||||
struct libinput *li = dev->libinput;
|
|
||||||
|
|
||||||
if (litest_slot_count(dev) <= 4)
|
|
||||||
return LITEST_NOT_APPLICABLE;
|
|
||||||
|
|
||||||
litest_enable_tap(dev->libinput_device);
|
|
||||||
litest_disable_hold_gestures(dev->libinput_device);
|
|
||||||
litest_drain_events(li);
|
|
||||||
|
|
||||||
litest_touch_down(dev, 0, 50, 50);
|
|
||||||
litest_touch_down(dev, 1, 70, 50);
|
|
||||||
litest_touch_down(dev, 2, 80, 50);
|
|
||||||
litest_touch_down(dev, 3, 90, 50);
|
|
||||||
|
|
||||||
litest_event(dev, EV_ABS, ABS_MT_SLOT, 0);
|
|
||||||
litest_event(dev, EV_ABS, ABS_MT_TRACKING_ID, -1);
|
|
||||||
litest_event(dev, EV_ABS, ABS_MT_SLOT, 1);
|
|
||||||
litest_event(dev, EV_ABS, ABS_MT_TRACKING_ID, -1);
|
|
||||||
litest_event(dev, EV_ABS, ABS_MT_SLOT, 2);
|
|
||||||
litest_event(dev, EV_ABS, ABS_MT_TRACKING_ID, -1);
|
|
||||||
litest_event(dev, EV_ABS, ABS_MT_SLOT, 3);
|
|
||||||
litest_event(dev, EV_ABS, ABS_MT_TRACKING_ID, -1);
|
|
||||||
litest_event(dev, EV_KEY, BTN_TOOL_QUADTAP, 0);
|
|
||||||
litest_event(dev, EV_KEY, BTN_TOUCH, 0);
|
|
||||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
|
||||||
|
|
||||||
litest_dispatch(li);
|
|
||||||
litest_assert_empty_queue(li);
|
|
||||||
litest_timeout_tap(li);
|
|
||||||
litest_assert_empty_queue(li);
|
|
||||||
}
|
|
||||||
END_TEST
|
|
||||||
|
|
||||||
START_TEST(touchpad_move_after_touch)
|
START_TEST(touchpad_move_after_touch)
|
||||||
{
|
{
|
||||||
struct litest_device *dev = litest_current_device();
|
struct litest_device *dev = litest_current_device();
|
||||||
|
|
@ -5001,8 +4968,7 @@ START_TEST(touchpad_tap_palm_on_touch_4)
|
||||||
litest_drain_events(li);
|
litest_drain_events(li);
|
||||||
|
|
||||||
/* 4fg tap with one finger detected as palm, that finger is lifted,
|
/* 4fg tap with one finger detected as palm, that finger is lifted,
|
||||||
other two fingers lifted cause nothing because we terminate
|
then put down again as normal finger -> 3fg tap */
|
||||||
tapping as soon as 4 fingers are down */
|
|
||||||
litest_touch_down(dev, this, 50, 50);
|
litest_touch_down(dev, this, 50, 50);
|
||||||
litest_touch_down(dev, (this + 1) % 4, 60, 50);
|
litest_touch_down(dev, (this + 1) % 4, 60, 50);
|
||||||
litest_touch_down(dev, (this + 2) % 4, 70, 50);
|
litest_touch_down(dev, (this + 2) % 4, 70, 50);
|
||||||
|
|
@ -5016,6 +4982,11 @@ START_TEST(touchpad_tap_palm_on_touch_4)
|
||||||
litest_touch_up(dev, (this + 2) % 4);
|
litest_touch_up(dev, (this + 2) % 4);
|
||||||
litest_touch_up(dev, (this + 3) % 4);
|
litest_touch_up(dev, (this + 3) % 4);
|
||||||
|
|
||||||
|
litest_dispatch(li);
|
||||||
|
litest_assert_button_event(li, BTN_MIDDLE, LIBINPUT_BUTTON_STATE_PRESSED);
|
||||||
|
litest_timeout_tap(li);
|
||||||
|
litest_assert_button_event(li, BTN_MIDDLE, LIBINPUT_BUTTON_STATE_RELEASED);
|
||||||
|
|
||||||
litest_assert_empty_queue(li);
|
litest_assert_empty_queue(li);
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
@ -5596,8 +5567,9 @@ TEST_COLLECTION(touchpad_tap)
|
||||||
litest_add_for_device(touchpad_3fg_tap_slot_release_btntool, LITEST_SYNAPTICS_TOPBUTTONPAD);
|
litest_add_for_device(touchpad_3fg_tap_slot_release_btntool, LITEST_SYNAPTICS_TOPBUTTONPAD);
|
||||||
litest_add(touchpad_3fg_tap_after_scroll, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH);
|
litest_add(touchpad_3fg_tap_after_scroll, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH);
|
||||||
|
|
||||||
litest_add(touchpad_4fg_tap, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH|LITEST_SEMI_MT);
|
litest_with_parameters(params, "with-hold", 'b') {
|
||||||
litest_add(touchpad_4fg_tap_quickrelease, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH|LITEST_SEMI_MT);
|
litest_add_parametrized(touchpad_4fg_tap, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH|LITEST_SEMI_MT, params);
|
||||||
|
}
|
||||||
litest_add(touchpad_5fg_tap, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH|LITEST_SEMI_MT);
|
litest_add(touchpad_5fg_tap, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH|LITEST_SEMI_MT);
|
||||||
litest_add(touchpad_5fg_tap_quickrelease, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH|LITEST_SEMI_MT);
|
litest_add(touchpad_5fg_tap_quickrelease, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH|LITEST_SEMI_MT);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -163,6 +163,11 @@ struct window {
|
||||||
bool active;
|
bool active;
|
||||||
} hold;
|
} hold;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
int nfingers;
|
||||||
|
bool active;
|
||||||
|
} tap;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
double x, y;
|
double x, y;
|
||||||
double x_in, y_in;
|
double x_in, y_in;
|
||||||
|
|
@ -608,6 +613,20 @@ draw_gestures(struct window *w, cairo_t *cr)
|
||||||
cairo_stroke(cr);
|
cairo_stroke(cr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 4fg tap uses the same rings but blue */
|
||||||
|
for (int i = 4; w->tap.active && i > 0; i--) { /* 4 fg max */
|
||||||
|
double r, g, b, tap_alpha;
|
||||||
|
|
||||||
|
r = .2;
|
||||||
|
g = .2;
|
||||||
|
b = .4 + .2 * (i % 2);
|
||||||
|
tap_alpha = i <= w->tap.nfingers ? 1 : .5;
|
||||||
|
|
||||||
|
cairo_set_source_rgba(cr, r, g, b, tap_alpha);
|
||||||
|
cairo_arc(cr, 0, 0, 20 * i, 0, 2 * M_PI);
|
||||||
|
cairo_fill(cr);
|
||||||
|
}
|
||||||
|
|
||||||
cairo_restore(cr);
|
cairo_restore(cr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1672,6 +1691,40 @@ handle_event_hold(struct libinput_event *ev, struct window *w)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
undo_tap(gpointer data)
|
||||||
|
{
|
||||||
|
struct window *w = data;
|
||||||
|
|
||||||
|
w->tap.active = false;
|
||||||
|
gtk_widget_queue_draw(w->area);
|
||||||
|
|
||||||
|
return G_SOURCE_REMOVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
handle_event_tap(struct libinput_event *ev, struct window *w)
|
||||||
|
{
|
||||||
|
struct libinput_event_gesture *g = libinput_event_get_gesture_event(ev);
|
||||||
|
int nfingers;
|
||||||
|
|
||||||
|
nfingers = libinput_event_gesture_get_finger_count(g);
|
||||||
|
|
||||||
|
switch (libinput_event_get_type(ev)) {
|
||||||
|
case LIBINPUT_EVENT_GESTURE_TAP_BEGIN:
|
||||||
|
w->tap.nfingers = nfingers;
|
||||||
|
w->tap.active = true;
|
||||||
|
g_timeout_add(75, undo_tap, w);
|
||||||
|
break;
|
||||||
|
case LIBINPUT_EVENT_GESTURE_TAP_END:
|
||||||
|
/* active is handled by a timer because we get begin/end
|
||||||
|
* at effectively the same time */
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
handle_event_tablet(struct libinput_event *ev, struct window *w)
|
handle_event_tablet(struct libinput_event *ev, struct window *w)
|
||||||
{
|
{
|
||||||
|
|
@ -1812,6 +1865,7 @@ handle_event_libinput(GIOChannel *source, GIOCondition condition, gpointer data)
|
||||||
tools_dispatch(li);
|
tools_dispatch(li);
|
||||||
|
|
||||||
while ((ev = libinput_get_event(li))) {
|
while ((ev = libinput_get_event(li))) {
|
||||||
|
|
||||||
switch (libinput_event_get_type(ev)) {
|
switch (libinput_event_get_type(ev)) {
|
||||||
case LIBINPUT_EVENT_NONE:
|
case LIBINPUT_EVENT_NONE:
|
||||||
abort();
|
abort();
|
||||||
|
|
@ -1865,6 +1919,10 @@ handle_event_libinput(GIOChannel *source, GIOCondition condition, gpointer data)
|
||||||
case LIBINPUT_EVENT_GESTURE_HOLD_END:
|
case LIBINPUT_EVENT_GESTURE_HOLD_END:
|
||||||
handle_event_hold(ev, w);
|
handle_event_hold(ev, w);
|
||||||
break;
|
break;
|
||||||
|
case LIBINPUT_EVENT_GESTURE_TAP_BEGIN:
|
||||||
|
case LIBINPUT_EVENT_GESTURE_TAP_END:
|
||||||
|
handle_event_tap(ev, w);
|
||||||
|
break;
|
||||||
case LIBINPUT_EVENT_TABLET_TOOL_AXIS:
|
case LIBINPUT_EVENT_TABLET_TOOL_AXIS:
|
||||||
case LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY:
|
case LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY:
|
||||||
case LIBINPUT_EVENT_TABLET_TOOL_TIP:
|
case LIBINPUT_EVENT_TABLET_TOOL_TIP:
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue