mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2025-12-28 10:50:07 +01:00
touchpad: work palm detection into the tap state machine
Unlike the already-existing thumb detection, a touch may be labelled palm at any time, not just during the initial touch down. This requires full integration into the tap state machine to unwind properly. For most states, a palm detection simply ignores the finger and reverts to the most recent state. One exception is the case of two fingers down, one finger up followed by the remaining finger detected as a palm finger. This triggers a single-finger tap but with timestamps that may be from the wrong finger. Since we're within a short tap timeout anyway this should not matter too much. The special state PALM_UP is only handled in one condition (DEAD). Once a touch is a palm we basically skip over it from then on. If we end up in the DEAD state after a button press we still need to handle the palm up events accordingly to be able to return to IDLE. That transition also requires us to have an accurate count of the real fingers down (palms don't count) so we need a separate nfingers_down counter for tapping. https://bugs.freedesktop.org/show_bug.cgi?id=103210 Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
This commit is contained in:
parent
f35bb9760e
commit
46eab97538
5 changed files with 2056 additions and 969 deletions
File diff suppressed because one or more lines are too long
|
Before Width: | Height: | Size: 127 KiB After Width: | Height: | Size: 166 KiB |
|
|
@ -44,6 +44,8 @@ enum tap_event {
|
|||
TAP_EVENT_BUTTON,
|
||||
TAP_EVENT_TIMEOUT,
|
||||
TAP_EVENT_THUMB,
|
||||
TAP_EVENT_PALM,
|
||||
TAP_EVENT_PALM_UP,
|
||||
};
|
||||
|
||||
/*****************************************
|
||||
|
|
@ -77,6 +79,7 @@ tap_state_to_str(enum tp_tap_state state)
|
|||
CASE_RETURN_STRING(TAP_STATE_DRAGGING_2);
|
||||
CASE_RETURN_STRING(TAP_STATE_MULTITAP);
|
||||
CASE_RETURN_STRING(TAP_STATE_MULTITAP_DOWN);
|
||||
CASE_RETURN_STRING(TAP_STATE_MULTITAP_PALM);
|
||||
CASE_RETURN_STRING(TAP_STATE_DEAD);
|
||||
}
|
||||
return NULL;
|
||||
|
|
@ -92,6 +95,8 @@ tap_event_to_str(enum tap_event event)
|
|||
CASE_RETURN_STRING(TAP_EVENT_TIMEOUT);
|
||||
CASE_RETURN_STRING(TAP_EVENT_BUTTON);
|
||||
CASE_RETURN_STRING(TAP_EVENT_THUMB);
|
||||
CASE_RETURN_STRING(TAP_EVENT_PALM);
|
||||
CASE_RETURN_STRING(TAP_EVENT_PALM_UP);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -178,6 +183,12 @@ tp_tap_idle_handle_event(struct tp_dispatch *tp,
|
|||
case TAP_EVENT_THUMB:
|
||||
log_tap_bug(tp, event);
|
||||
break;
|
||||
case TAP_EVENT_PALM:
|
||||
tp->tap.state = TAP_STATE_IDLE;
|
||||
t->tap.state = TAP_TOUCH_STATE_DEAD;
|
||||
break;
|
||||
case TAP_EVENT_PALM_UP:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -221,9 +232,17 @@ tp_tap_touch_handle_event(struct tp_dispatch *tp,
|
|||
case TAP_EVENT_THUMB:
|
||||
tp->tap.state = TAP_STATE_IDLE;
|
||||
t->tap.is_thumb = true;
|
||||
tp->tap.nfingers_down--;
|
||||
t->tap.state = TAP_TOUCH_STATE_DEAD;
|
||||
tp_tap_clear_timer(tp);
|
||||
break;
|
||||
case TAP_EVENT_PALM:
|
||||
tp->tap.state = TAP_STATE_IDLE;
|
||||
t->tap.state = TAP_TOUCH_STATE_DEAD;
|
||||
tp_tap_clear_timer(tp);
|
||||
break;
|
||||
case TAP_EVENT_PALM_UP:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -251,8 +270,14 @@ tp_tap_hold_handle_event(struct tp_dispatch *tp,
|
|||
case TAP_EVENT_THUMB:
|
||||
tp->tap.state = TAP_STATE_IDLE;
|
||||
t->tap.is_thumb = true;
|
||||
tp->tap.nfingers_down--;
|
||||
t->tap.state = TAP_TOUCH_STATE_DEAD;
|
||||
break;
|
||||
case TAP_EVENT_PALM:
|
||||
tp->tap.state = TAP_STATE_IDLE;
|
||||
break;
|
||||
case TAP_EVENT_PALM_UP:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -286,6 +311,10 @@ tp_tap_tapped_handle_event(struct tp_dispatch *tp,
|
|||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
break;
|
||||
case TAP_EVENT_THUMB:
|
||||
case TAP_EVENT_PALM:
|
||||
log_tap_bug(tp, event);
|
||||
break;
|
||||
case TAP_EVENT_PALM_UP:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -318,6 +347,12 @@ tp_tap_touch2_handle_event(struct tp_dispatch *tp,
|
|||
break;
|
||||
case TAP_EVENT_THUMB:
|
||||
break;
|
||||
case TAP_EVENT_PALM:
|
||||
tp->tap.state = TAP_STATE_TOUCH;
|
||||
tp_tap_set_timer(tp, time); /* overwrite timer */
|
||||
break;
|
||||
case TAP_EVENT_PALM_UP:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -345,6 +380,11 @@ tp_tap_touch2_hold_handle_event(struct tp_dispatch *tp,
|
|||
break;
|
||||
case TAP_EVENT_THUMB:
|
||||
break;
|
||||
case TAP_EVENT_PALM:
|
||||
tp->tap.state = TAP_STATE_HOLD;
|
||||
break;
|
||||
case TAP_EVENT_PALM_UP:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -380,6 +420,31 @@ tp_tap_touch2_release_handle_event(struct tp_dispatch *tp,
|
|||
break;
|
||||
case TAP_EVENT_THUMB:
|
||||
break;
|
||||
case TAP_EVENT_PALM:
|
||||
/* There's only one saved press time and it's overwritten by
|
||||
* the last touch down. So in the case of finger down, palm
|
||||
* down, finger up, palm detected, we use the
|
||||
* palm touch's press time here instead of the finger's press
|
||||
* time. Let's wait and see if that's an issue.
|
||||
*/
|
||||
tp_tap_notify(tp,
|
||||
tp->tap.saved_press_time,
|
||||
1,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
if (tp->tap.drag_enabled) {
|
||||
tp->tap.state = TAP_STATE_TAPPED;
|
||||
tp->tap.saved_release_time = time;
|
||||
tp_tap_set_timer(tp, time);
|
||||
} else {
|
||||
tp_tap_notify(tp,
|
||||
time,
|
||||
1,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
tp->tap.state = TAP_STATE_IDLE;
|
||||
}
|
||||
break;
|
||||
case TAP_EVENT_PALM_UP:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -414,6 +479,11 @@ tp_tap_touch3_handle_event(struct tp_dispatch *tp,
|
|||
break;
|
||||
case TAP_EVENT_THUMB:
|
||||
break;
|
||||
case TAP_EVENT_PALM:
|
||||
tp->tap.state = TAP_STATE_TOUCH_2;
|
||||
break;
|
||||
case TAP_EVENT_PALM_UP:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -439,6 +509,11 @@ tp_tap_touch3_hold_handle_event(struct tp_dispatch *tp,
|
|||
break;
|
||||
case TAP_EVENT_THUMB:
|
||||
break;
|
||||
case TAP_EVENT_PALM:
|
||||
tp->tap.state = TAP_STATE_TOUCH_2_HOLD;
|
||||
break;
|
||||
case TAP_EVENT_PALM_UP:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -472,6 +547,11 @@ tp_tap_dragging_or_doubletap_handle_event(struct tp_dispatch *tp,
|
|||
break;
|
||||
case TAP_EVENT_THUMB:
|
||||
break;
|
||||
case TAP_EVENT_PALM:
|
||||
tp->tap.state = TAP_STATE_TAPPED;
|
||||
break;
|
||||
case TAP_EVENT_PALM_UP:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -507,6 +587,15 @@ tp_tap_dragging_handle_event(struct tp_dispatch *tp,
|
|||
break;
|
||||
case TAP_EVENT_THUMB:
|
||||
break;
|
||||
case TAP_EVENT_PALM:
|
||||
tp_tap_notify(tp,
|
||||
tp->tap.saved_release_time,
|
||||
1,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
tp->tap.state = TAP_STATE_IDLE;
|
||||
break;
|
||||
case TAP_EVENT_PALM_UP:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -533,6 +622,9 @@ tp_tap_dragging_wait_handle_event(struct tp_dispatch *tp,
|
|||
tp_tap_notify(tp, time, 1, LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
break;
|
||||
case TAP_EVENT_THUMB:
|
||||
case TAP_EVENT_PALM:
|
||||
break;
|
||||
case TAP_EVENT_PALM_UP:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -562,6 +654,15 @@ tp_tap_dragging_tap_handle_event(struct tp_dispatch *tp,
|
|||
break;
|
||||
case TAP_EVENT_THUMB:
|
||||
break;
|
||||
case TAP_EVENT_PALM:
|
||||
tp_tap_notify(tp,
|
||||
tp->tap.saved_release_time,
|
||||
1,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
tp->tap.state = TAP_STATE_IDLE;
|
||||
break;
|
||||
case TAP_EVENT_PALM_UP:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -589,6 +690,11 @@ tp_tap_dragging2_handle_event(struct tp_dispatch *tp,
|
|||
break;
|
||||
case TAP_EVENT_THUMB:
|
||||
break;
|
||||
case TAP_EVENT_PALM:
|
||||
tp->tap.state = TAP_STATE_DRAGGING_OR_DOUBLETAP;
|
||||
break;
|
||||
case TAP_EVENT_PALM_UP:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -629,6 +735,9 @@ tp_tap_multitap_handle_event(struct tp_dispatch *tp,
|
|||
tp_tap_clear_timer(tp);
|
||||
break;
|
||||
case TAP_EVENT_THUMB:
|
||||
case TAP_EVENT_PALM:
|
||||
break;
|
||||
case TAP_EVENT_PALM_UP:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -667,6 +776,42 @@ tp_tap_multitap_down_handle_event(struct tp_dispatch *tp,
|
|||
break;
|
||||
case TAP_EVENT_THUMB:
|
||||
break;
|
||||
case TAP_EVENT_PALM:
|
||||
tp->tap.state = TAP_STATE_MULTITAP_PALM;
|
||||
break;
|
||||
case TAP_EVENT_PALM_UP:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
tp_tap_multitap_palm_handle_event(struct tp_dispatch *tp,
|
||||
struct tp_touch *t,
|
||||
enum tap_event event,
|
||||
uint64_t time)
|
||||
{
|
||||
switch (event) {
|
||||
case TAP_EVENT_RELEASE:
|
||||
/* This is the palm finger */
|
||||
break;
|
||||
case TAP_EVENT_TOUCH:
|
||||
tp->tap.state = TAP_STATE_MULTITAP_DOWN;
|
||||
break;
|
||||
case TAP_EVENT_MOTION:
|
||||
break;
|
||||
case TAP_EVENT_TIMEOUT:
|
||||
case TAP_EVENT_BUTTON:
|
||||
tp->tap.state = TAP_STATE_IDLE;
|
||||
tp_tap_clear_timer(tp);
|
||||
tp_tap_notify(tp,
|
||||
tp->tap.saved_release_time,
|
||||
1,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
break;
|
||||
case TAP_EVENT_THUMB:
|
||||
case TAP_EVENT_PALM:
|
||||
case TAP_EVENT_PALM_UP:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -679,7 +824,7 @@ tp_tap_dead_handle_event(struct tp_dispatch *tp,
|
|||
|
||||
switch (event) {
|
||||
case TAP_EVENT_RELEASE:
|
||||
if (tp->nfingers_down == 0)
|
||||
if (tp->tap.nfingers_down == 0)
|
||||
tp->tap.state = TAP_STATE_IDLE;
|
||||
break;
|
||||
case TAP_EVENT_TOUCH:
|
||||
|
|
@ -689,6 +834,11 @@ tp_tap_dead_handle_event(struct tp_dispatch *tp,
|
|||
break;
|
||||
case TAP_EVENT_THUMB:
|
||||
break;
|
||||
case TAP_EVENT_PALM:
|
||||
case TAP_EVENT_PALM_UP:
|
||||
if (tp->tap.nfingers_down == 0)
|
||||
tp->tap.state = TAP_STATE_IDLE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -751,6 +901,9 @@ tp_tap_handle_event(struct tp_dispatch *tp,
|
|||
case TAP_STATE_MULTITAP_DOWN:
|
||||
tp_tap_multitap_down_handle_event(tp, t, event, time);
|
||||
break;
|
||||
case TAP_STATE_MULTITAP_PALM:
|
||||
tp_tap_multitap_palm_handle_event(tp, t, event, time);
|
||||
break;
|
||||
case TAP_STATE_DEAD:
|
||||
tp_tap_dead_handle_event(tp, t, event, time);
|
||||
break;
|
||||
|
|
@ -777,6 +930,8 @@ tp_tap_exceeds_motion_threshold(struct tp_dispatch *tp,
|
|||
* touchpads are likely to give us pointer jumps.
|
||||
* This triggers the movement threshold, making three-finger taps
|
||||
* less reliable (#101435)
|
||||
*
|
||||
* This uses the real nfingers_down, not the one for taps.
|
||||
*/
|
||||
if (tp->device->model_flags & EVDEV_MODEL_SYNAPTICS_SERIAL_TOUCHPAD &&
|
||||
(tp->nfingers_down > 2 || tp->old_nfingers_down > 2) &&
|
||||
|
|
@ -822,10 +977,32 @@ tp_tap_handle_state(struct tp_dispatch *tp, uint64_t time)
|
|||
if (t->tap.is_thumb)
|
||||
continue;
|
||||
|
||||
/* A palm tap needs to be properly relased because we might
|
||||
* be who-knows-where in the state machine. Otherwise, we
|
||||
* ignore any event from it.
|
||||
*/
|
||||
if (t->tap.is_palm) {
|
||||
if (t->state == TOUCH_END)
|
||||
tp_tap_handle_event(tp,
|
||||
t,
|
||||
TAP_EVENT_PALM_UP,
|
||||
time);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (t->state == TOUCH_HOVERING)
|
||||
continue;
|
||||
|
||||
if (t->state == TOUCH_BEGIN) {
|
||||
if (t->palm.state != PALM_NONE) {
|
||||
assert(!t->tap.is_palm);
|
||||
tp_tap_handle_event(tp, t, TAP_EVENT_PALM, time);
|
||||
t->tap.is_palm = true;
|
||||
t->tap.state = TAP_TOUCH_STATE_DEAD;
|
||||
if (t->state != TOUCH_BEGIN) {
|
||||
assert(tp->tap.nfingers_down > 0);
|
||||
tp->tap.nfingers_down--;
|
||||
}
|
||||
} else if (t->state == TOUCH_BEGIN) {
|
||||
/* The simple version: if a touch is a thumb on
|
||||
* begin we ignore it. All other thumb touches
|
||||
* follow the normal tap state for now */
|
||||
|
|
@ -836,6 +1013,7 @@ tp_tap_handle_state(struct tp_dispatch *tp, uint64_t time)
|
|||
|
||||
t->tap.state = TAP_TOUCH_STATE_TOUCH;
|
||||
t->tap.initial = t->point;
|
||||
tp->tap.nfingers_down++;
|
||||
tp_tap_handle_event(tp, t, TAP_EVENT_TOUCH, time);
|
||||
|
||||
/* If we think this is a palm, pretend there's a
|
||||
|
|
@ -846,8 +1024,10 @@ tp_tap_handle_state(struct tp_dispatch *tp, uint64_t time)
|
|||
tp_tap_handle_event(tp, t, TAP_EVENT_MOTION, time);
|
||||
|
||||
} else if (t->state == TOUCH_END) {
|
||||
if (t->was_down)
|
||||
if (t->was_down) {
|
||||
tp->tap.nfingers_down--;
|
||||
tp_tap_handle_event(tp, t, TAP_EVENT_RELEASE, time);
|
||||
}
|
||||
t->tap.state = TAP_TOUCH_STATE_IDLE;
|
||||
} else if (tp->tap.state != TAP_STATE_IDLE &&
|
||||
tp_tap_exceeds_motion_threshold(tp, t)) {
|
||||
|
|
@ -890,6 +1070,10 @@ tp_tap_handle_state(struct tp_dispatch *tp, uint64_t time)
|
|||
|
||||
}
|
||||
|
||||
assert(tp->tap.nfingers_down <= tp->nfingers_down);
|
||||
if (tp->nfingers_down == 0)
|
||||
assert(tp->tap.nfingers_down == 0);
|
||||
|
||||
return filter_motion;
|
||||
}
|
||||
|
||||
|
|
@ -938,9 +1122,19 @@ tp_tap_enabled_update(struct tp_dispatch *tp, bool suspended, bool enabled, uint
|
|||
return;
|
||||
|
||||
if (tp_tap_enabled(tp)) {
|
||||
/* Must restart in DEAD if fingers are down atm */
|
||||
tp->tap.state =
|
||||
tp->nfingers_down ? TAP_STATE_DEAD : TAP_STATE_IDLE;
|
||||
struct tp_touch *t;
|
||||
|
||||
/* On resume, all touches are considered palms */
|
||||
tp_for_each_touch(tp, t) {
|
||||
if (t->state == TOUCH_NONE)
|
||||
continue;
|
||||
|
||||
t->tap.is_palm = true;
|
||||
t->tap.state = TAP_TOUCH_STATE_DEAD;
|
||||
}
|
||||
|
||||
tp->tap.state = TAP_STATE_IDLE;
|
||||
tp->tap.nfingers_down = 0;
|
||||
} else {
|
||||
tp_release_all_taps(tp, time);
|
||||
}
|
||||
|
|
@ -1154,6 +1348,7 @@ tp_remove_tap(struct tp_dispatch *tp)
|
|||
void
|
||||
tp_release_all_taps(struct tp_dispatch *tp, uint64_t now)
|
||||
{
|
||||
struct tp_touch *t;
|
||||
int i;
|
||||
|
||||
for (i = 1; i <= 3; i++) {
|
||||
|
|
@ -1161,7 +1356,20 @@ tp_release_all_taps(struct tp_dispatch *tp, uint64_t now)
|
|||
tp_tap_notify(tp, now, i, LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
}
|
||||
|
||||
tp->tap.state = tp->nfingers_down ? TAP_STATE_DEAD : TAP_STATE_IDLE;
|
||||
/* To neutralize all current touches, we make them all palms */
|
||||
tp_for_each_touch(tp, t) {
|
||||
if (t->state == TOUCH_NONE)
|
||||
continue;
|
||||
|
||||
if (t->tap.is_palm)
|
||||
continue;
|
||||
|
||||
t->tap.is_palm = true;
|
||||
t->tap.state = TAP_TOUCH_STATE_DEAD;
|
||||
}
|
||||
|
||||
tp->tap.state = TAP_STATE_IDLE;
|
||||
tp->tap.nfingers_down = 0;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -290,6 +290,7 @@ tp_begin_touch(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time)
|
|||
t->thumb.state = THUMB_STATE_MAYBE;
|
||||
t->thumb.first_touch_time = time;
|
||||
t->tap.is_thumb = false;
|
||||
t->tap.is_palm = false;
|
||||
assert(tp->nfingers_down >= 1);
|
||||
tp->hysteresis.last_motion_time = time;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -103,6 +103,7 @@ enum tp_tap_state {
|
|||
TAP_STATE_DRAGGING_2,
|
||||
TAP_STATE_MULTITAP,
|
||||
TAP_STATE_MULTITAP_DOWN,
|
||||
TAP_STATE_MULTITAP_PALM,
|
||||
TAP_STATE_DEAD, /**< finger count exceeded */
|
||||
};
|
||||
|
||||
|
|
@ -195,6 +196,7 @@ struct tp_touch {
|
|||
enum tp_tap_touch_state state;
|
||||
struct device_coords initial;
|
||||
bool is_thumb;
|
||||
bool is_palm;
|
||||
} tap;
|
||||
|
||||
struct {
|
||||
|
|
@ -356,6 +358,8 @@ struct tp_dispatch {
|
|||
|
||||
bool drag_enabled;
|
||||
bool drag_lock_enabled;
|
||||
|
||||
unsigned int nfingers_down; /* number of fingers down for tapping (excl. thumb/palm) */
|
||||
} tap;
|
||||
|
||||
struct {
|
||||
|
|
|
|||
|
|
@ -2375,12 +2375,870 @@ START_TEST(touchpad_drag_lock_default_unavailable)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
static inline bool
|
||||
touchpad_has_palm_pressure(struct litest_device *dev)
|
||||
{
|
||||
struct libevdev *evdev = dev->evdev;
|
||||
|
||||
if (libevdev_has_event_code(evdev, EV_ABS, ABS_MT_PRESSURE))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
START_TEST(touchpad_tap_palm_on_idle)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
struct axis_replacement axes[] = {
|
||||
{ ABS_MT_PRESSURE, 75 },
|
||||
{ -1, 0 }
|
||||
};
|
||||
|
||||
if (!touchpad_has_palm_pressure(dev))
|
||||
return;
|
||||
|
||||
litest_enable_tap(dev->libinput_device);
|
||||
litest_drain_events(li);
|
||||
|
||||
/* Finger down is immediately palm */
|
||||
|
||||
litest_touch_down_extended(dev, 0, 50, 50, axes);
|
||||
litest_touch_up(dev, 0);
|
||||
|
||||
libinput_dispatch(li);
|
||||
|
||||
litest_assert_empty_queue(li);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(touchpad_tap_palm_on_touch)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
struct axis_replacement axes[] = {
|
||||
{ ABS_MT_PRESSURE, 75 },
|
||||
{ -1, 0 }
|
||||
};
|
||||
|
||||
if (!touchpad_has_palm_pressure(dev))
|
||||
return;
|
||||
|
||||
litest_enable_tap(dev->libinput_device);
|
||||
litest_drain_events(li);
|
||||
|
||||
/* Finger down is palm after touch begin */
|
||||
|
||||
litest_touch_down(dev, 0, 50, 50);
|
||||
litest_touch_move_to_extended(dev, 0, 50, 50, 50, 50, axes, 1, 1);
|
||||
litest_touch_up(dev, 0);
|
||||
|
||||
libinput_dispatch(li);
|
||||
|
||||
litest_assert_empty_queue(li);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(touchpad_tap_palm_on_touch_hold_timeout)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
struct axis_replacement axes[] = {
|
||||
{ ABS_MT_PRESSURE, 75 },
|
||||
{ -1, 0 }
|
||||
};
|
||||
|
||||
if (!touchpad_has_palm_pressure(dev))
|
||||
return;
|
||||
|
||||
litest_enable_tap(dev->libinput_device);
|
||||
litest_drain_events(li);
|
||||
|
||||
/* Finger down is palm after tap timeout */
|
||||
|
||||
litest_touch_down(dev, 0, 50, 50);
|
||||
libinput_dispatch(li);
|
||||
litest_timeout_tap();
|
||||
libinput_dispatch(li);
|
||||
litest_touch_move_to_extended(dev, 0, 50, 50, 50, 50, axes, 1, 1);
|
||||
litest_touch_up(dev, 0);
|
||||
|
||||
libinput_dispatch(li);
|
||||
|
||||
litest_assert_empty_queue(li);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(touchpad_tap_palm_on_touch_hold_move)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
struct axis_replacement axes[] = {
|
||||
{ ABS_MT_PRESSURE, 75 },
|
||||
{ -1, 0 }
|
||||
};
|
||||
|
||||
if (!touchpad_has_palm_pressure(dev))
|
||||
return;
|
||||
|
||||
litest_enable_tap(dev->libinput_device);
|
||||
litest_drain_events(li);
|
||||
|
||||
/* Finger down is palm after tap move threshold */
|
||||
|
||||
litest_touch_down(dev, 0, 50, 50);
|
||||
litest_touch_move_to(dev, 0, 50, 50, 60, 60, 10, 1);
|
||||
litest_drain_events(li);
|
||||
|
||||
litest_touch_move_to_extended(dev, 0, 50, 50, 50, 50, axes, 1, 1);
|
||||
litest_touch_up(dev, 0);
|
||||
|
||||
libinput_dispatch(li);
|
||||
|
||||
litest_assert_empty_queue(li);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(touchpad_tap_palm_on_tapped)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
struct axis_replacement axes[] = {
|
||||
{ ABS_MT_PRESSURE, 75 },
|
||||
{ -1, 0 }
|
||||
};
|
||||
|
||||
if (!touchpad_has_palm_pressure(dev))
|
||||
return;
|
||||
|
||||
litest_enable_tap(dev->libinput_device);
|
||||
litest_drain_events(li);
|
||||
|
||||
/* tap + palm down */
|
||||
|
||||
litest_touch_down(dev, 0, 50, 50);
|
||||
litest_touch_up(dev, 0);
|
||||
libinput_dispatch(li);
|
||||
|
||||
litest_assert_button_event(li,
|
||||
BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
|
||||
litest_touch_down(dev, 0, 50, 50);
|
||||
litest_touch_move_to_extended(dev, 0, 50, 50, 50, 50, axes, 1, 1);
|
||||
litest_touch_up(dev, 0);
|
||||
|
||||
libinput_dispatch(li);
|
||||
litest_timeout_tap();
|
||||
libinput_dispatch(li);
|
||||
|
||||
litest_assert_button_event(li,
|
||||
BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
|
||||
|
||||
litest_assert_empty_queue(li);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(touchpad_tap_palm_on_tapped_2fg)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
struct axis_replacement axes[] = {
|
||||
{ ABS_MT_PRESSURE, 75 },
|
||||
{ -1, 0 }
|
||||
};
|
||||
|
||||
if (!touchpad_has_palm_pressure(dev))
|
||||
return;
|
||||
|
||||
litest_enable_tap(dev->libinput_device);
|
||||
litest_drain_events(li);
|
||||
|
||||
/* tap + palm down + tap with second finger */
|
||||
|
||||
litest_touch_down(dev, 0, 50, 50);
|
||||
litest_touch_up(dev, 0);
|
||||
libinput_dispatch(li);
|
||||
|
||||
litest_assert_button_event(li,
|
||||
BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
|
||||
litest_touch_down(dev, 0, 50, 50);
|
||||
litest_touch_move_to_extended(dev, 0, 50, 50, 50, 50, axes, 1, 1);
|
||||
|
||||
libinput_dispatch(li);
|
||||
|
||||
litest_touch_down(dev, 1, 50, 50);
|
||||
litest_touch_up(dev, 1);
|
||||
libinput_dispatch(li);
|
||||
|
||||
litest_timeout_tap();
|
||||
libinput_dispatch(li);
|
||||
|
||||
litest_assert_button_event(li,
|
||||
BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
litest_assert_button_event(li,
|
||||
BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
litest_assert_button_event(li,
|
||||
BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
|
||||
|
||||
litest_touch_up(dev, 0);
|
||||
litest_assert_empty_queue(li);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(touchpad_tap_palm_on_drag)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
struct axis_replacement axes[] = {
|
||||
{ ABS_MT_PRESSURE, 75 },
|
||||
{ -1, 0 }
|
||||
};
|
||||
|
||||
if (!touchpad_has_palm_pressure(dev))
|
||||
return;
|
||||
|
||||
litest_enable_tap(dev->libinput_device);
|
||||
litest_drain_events(li);
|
||||
|
||||
/* tap + finger down (->drag), finger turns into palm */
|
||||
|
||||
litest_touch_down(dev, 0, 50, 50);
|
||||
litest_touch_up(dev, 0);
|
||||
libinput_dispatch(li);
|
||||
|
||||
litest_assert_button_event(li,
|
||||
BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
|
||||
litest_touch_down(dev, 0, 50, 50);
|
||||
libinput_dispatch(li);
|
||||
litest_timeout_tap();
|
||||
libinput_dispatch(li);
|
||||
|
||||
litest_touch_move_to_extended(dev, 0, 50, 50, 50, 50, axes, 1, 1);
|
||||
libinput_dispatch(li);
|
||||
|
||||
litest_assert_button_event(li,
|
||||
BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
|
||||
litest_touch_up(dev, 0);
|
||||
litest_assert_empty_queue(li);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(touchpad_tap_palm_on_drag_2fg)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
struct axis_replacement axes[] = {
|
||||
{ ABS_MT_PRESSURE, 75 },
|
||||
{ -1, 0 }
|
||||
};
|
||||
int which = _i; /* ranged test */
|
||||
int this = which % 2,
|
||||
other = (which + 1) % 2;
|
||||
|
||||
if (!touchpad_has_palm_pressure(dev))
|
||||
return;
|
||||
|
||||
litest_enable_tap(dev->libinput_device);
|
||||
litest_drain_events(li);
|
||||
|
||||
/* tap + finger down, 2nd finger down, finger turns to palm */
|
||||
|
||||
litest_touch_down(dev, 0, 50, 50);
|
||||
litest_touch_up(dev, 0);
|
||||
libinput_dispatch(li);
|
||||
|
||||
litest_assert_button_event(li,
|
||||
BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
|
||||
litest_touch_down(dev, this, 50, 50);
|
||||
litest_touch_down(dev, other, 60, 50);
|
||||
libinput_dispatch(li);
|
||||
|
||||
litest_touch_move_to_extended(dev, this, 50, 50, 50, 50, axes, 1, 1);
|
||||
libinput_dispatch(li);
|
||||
|
||||
litest_touch_move_to(dev, other, 60, 50, 65, 50, 10, 1);
|
||||
litest_assert_only_typed_events(li,
|
||||
LIBINPUT_EVENT_POINTER_MOTION);
|
||||
litest_touch_up(dev, other);
|
||||
|
||||
litest_assert_button_event(li,
|
||||
BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
|
||||
litest_touch_up(dev, this);
|
||||
litest_assert_empty_queue(li);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(touchpad_tap_palm_on_touch_2)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
struct axis_replacement axes[] = {
|
||||
{ ABS_MT_PRESSURE, 75 },
|
||||
{ -1, 0 }
|
||||
};
|
||||
int which = _i; /* ranged test */
|
||||
int this = which % 2,
|
||||
other = (which + 1) % 2;
|
||||
|
||||
if (!touchpad_has_palm_pressure(dev))
|
||||
return;
|
||||
|
||||
litest_enable_tap(dev->libinput_device);
|
||||
litest_drain_events(li);
|
||||
|
||||
/* 2fg tap with one finger detected as palm */
|
||||
litest_touch_down(dev, 0, 50, 50);
|
||||
litest_touch_down(dev, 1, 60, 60);
|
||||
litest_drain_events(li);
|
||||
litest_touch_move_to_extended(dev, this, 50, 50, 50, 50, axes, 1, 1);
|
||||
|
||||
|
||||
litest_touch_up(dev, this);
|
||||
litest_touch_up(dev, other);
|
||||
|
||||
libinput_dispatch(li);
|
||||
litest_assert_button_event(li,
|
||||
BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
litest_timeout_tap();
|
||||
litest_assert_button_event(li,
|
||||
BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
|
||||
|
||||
litest_assert_empty_queue(li);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(touchpad_tap_palm_on_touch_2_retouch)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
struct axis_replacement axes[] = {
|
||||
{ ABS_MT_PRESSURE, 75 },
|
||||
{ -1, 0 }
|
||||
};
|
||||
int which = _i; /* ranged test */
|
||||
int this = which % 2,
|
||||
other = (which + 1) % 2;
|
||||
|
||||
|
||||
if (!touchpad_has_palm_pressure(dev))
|
||||
return;
|
||||
|
||||
litest_enable_tap(dev->libinput_device);
|
||||
litest_drain_events(li);
|
||||
|
||||
/* 2fg tap with one finger detected as palm, that finger is lifted
|
||||
* and taps again as not-palm */
|
||||
litest_touch_down(dev, this, 50, 50);
|
||||
litest_touch_down(dev, other, 60, 60);
|
||||
litest_drain_events(li);
|
||||
litest_touch_move_to_extended(dev, this, 50, 50, 50, 50, axes, 1, 1);
|
||||
litest_touch_up(dev, this);
|
||||
libinput_dispatch(li);
|
||||
|
||||
litest_touch_down(dev, this, 70, 70);
|
||||
litest_touch_up(dev, this);
|
||||
litest_touch_up(dev, other);
|
||||
|
||||
libinput_dispatch(li);
|
||||
litest_assert_button_event(li,
|
||||
BTN_RIGHT,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
litest_timeout_tap();
|
||||
litest_assert_button_event(li,
|
||||
BTN_RIGHT,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
|
||||
litest_assert_empty_queue(li);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(touchpad_tap_palm_on_touch_3)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
struct axis_replacement axes[] = {
|
||||
{ ABS_MT_PRESSURE, 75 },
|
||||
{ -1, 0 }
|
||||
};
|
||||
int which = _i; /* ranged test */
|
||||
int this = which % 3;
|
||||
|
||||
if (libevdev_get_abs_maximum(dev->evdev, ABS_MT_SLOT) <= 3)
|
||||
return;
|
||||
|
||||
if (!touchpad_has_palm_pressure(dev))
|
||||
return;
|
||||
|
||||
litest_enable_tap(dev->libinput_device);
|
||||
litest_drain_events(li);
|
||||
|
||||
/* 3fg tap with one finger detected as palm, that finger is lifted,
|
||||
other two fingers lifted cause 2fg tap */
|
||||
litest_touch_down(dev, this, 50, 50);
|
||||
litest_touch_down(dev, (this + 1) % 3, 60, 50);
|
||||
litest_touch_down(dev, (this + 2) % 3, 70, 50);
|
||||
litest_drain_events(li);
|
||||
litest_touch_move_to_extended(dev, this, 50, 50, 50, 50, axes, 1, 1);
|
||||
litest_touch_up(dev, this);
|
||||
libinput_dispatch(li);
|
||||
|
||||
litest_touch_up(dev, (this + 1) % 3);
|
||||
litest_touch_up(dev, (this + 2) % 3);
|
||||
|
||||
libinput_dispatch(li);
|
||||
litest_assert_button_event(li,
|
||||
BTN_RIGHT,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
litest_timeout_tap();
|
||||
litest_assert_button_event(li,
|
||||
BTN_RIGHT,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
|
||||
litest_assert_empty_queue(li);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(touchpad_tap_palm_on_touch_3_retouch)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
struct axis_replacement axes[] = {
|
||||
{ ABS_MT_PRESSURE, 75 },
|
||||
{ -1, 0 }
|
||||
};
|
||||
int which = _i; /* ranged test */
|
||||
int this = which % 3;
|
||||
|
||||
if (libevdev_get_abs_maximum(dev->evdev, ABS_MT_SLOT) <= 3)
|
||||
return;
|
||||
|
||||
if (!touchpad_has_palm_pressure(dev))
|
||||
return;
|
||||
|
||||
litest_enable_tap(dev->libinput_device);
|
||||
litest_drain_events(li);
|
||||
|
||||
/* 3fg tap with one finger detected as palm, that finger is lifted,
|
||||
then put down again as normal finger -> 3fg tap */
|
||||
litest_touch_down(dev, this, 50, 50);
|
||||
litest_touch_down(dev, (this + 1) % 3, 60, 50);
|
||||
litest_touch_down(dev, (this + 2) % 3, 70, 50);
|
||||
litest_drain_events(li);
|
||||
litest_timeout_tap();
|
||||
libinput_dispatch(li);
|
||||
|
||||
litest_touch_move_to_extended(dev, this, 50, 50, 50, 50, axes, 1, 1);
|
||||
litest_touch_up(dev, this);
|
||||
libinput_dispatch(li);
|
||||
|
||||
litest_touch_down(dev, this, 50, 50);
|
||||
litest_touch_up(dev, this);
|
||||
litest_touch_up(dev, (this + 1) % 3);
|
||||
litest_touch_up(dev, (this + 2) % 3);
|
||||
|
||||
libinput_dispatch(li);
|
||||
litest_assert_button_event(li,
|
||||
BTN_MIDDLE,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
litest_timeout_tap();
|
||||
litest_assert_button_event(li,
|
||||
BTN_MIDDLE,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
|
||||
litest_assert_empty_queue(li);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(touchpad_tap_palm_on_touch_4)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
struct axis_replacement axes[] = {
|
||||
{ ABS_MT_PRESSURE, 75 },
|
||||
{ -1, 0 }
|
||||
};
|
||||
int which = _i; /* ranged test */
|
||||
int this = which % 4;
|
||||
|
||||
if (libevdev_get_abs_maximum(dev->evdev, ABS_MT_SLOT) <= 4)
|
||||
return;
|
||||
|
||||
if (!touchpad_has_palm_pressure(dev))
|
||||
return;
|
||||
|
||||
litest_enable_tap(dev->libinput_device);
|
||||
litest_drain_events(li);
|
||||
|
||||
/* 3fg tap with one finger detected as palm, that finger is lifted,
|
||||
other two fingers lifted cause 2fg tap */
|
||||
litest_touch_down(dev, this, 50, 50);
|
||||
litest_touch_down(dev, (this + 1) % 4, 60, 50);
|
||||
litest_touch_down(dev, (this + 2) % 4, 70, 50);
|
||||
litest_touch_down(dev, (this + 3) % 4, 80, 50);
|
||||
litest_drain_events(li);
|
||||
litest_touch_move_to_extended(dev, this, 50, 50, 50, 50, axes, 1, 1);
|
||||
litest_touch_up(dev, this);
|
||||
libinput_dispatch(li);
|
||||
|
||||
litest_touch_up(dev, (this + 1) % 4);
|
||||
litest_touch_up(dev, (this + 2) % 4);
|
||||
litest_touch_up(dev, (this + 3) % 4);
|
||||
|
||||
litest_assert_empty_queue(li);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(touchpad_tap_palm_after_tap)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
struct axis_replacement axes[] = {
|
||||
{ ABS_MT_PRESSURE, 75 },
|
||||
{ -1, 0 }
|
||||
};
|
||||
|
||||
if (!touchpad_has_palm_pressure(dev))
|
||||
return;
|
||||
|
||||
litest_enable_tap(dev->libinput_device);
|
||||
litest_drain_events(li);
|
||||
|
||||
|
||||
litest_touch_down(dev, 0, 50, 50);
|
||||
litest_touch_up(dev, 0);
|
||||
libinput_dispatch(li);
|
||||
|
||||
libinput_dispatch(li);
|
||||
litest_assert_button_event(li,
|
||||
BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
|
||||
litest_touch_down(dev, 0, 50, 50);
|
||||
litest_touch_move_to_extended(dev, 0, 50, 50, 50, 50, axes, 1, 1);
|
||||
litest_touch_up(dev, 0);
|
||||
libinput_dispatch(li);
|
||||
|
||||
litest_timeout_tap();
|
||||
litest_assert_button_event(li,
|
||||
BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
|
||||
|
||||
litest_assert_empty_queue(li);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(touchpad_tap_palm_multitap)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
struct axis_replacement axes[] = {
|
||||
{ ABS_MT_PRESSURE, 75 },
|
||||
{ -1, 0 }
|
||||
};
|
||||
int range = _i, /* ranged test */
|
||||
ntaps;
|
||||
|
||||
if (!touchpad_has_palm_pressure(dev))
|
||||
return;
|
||||
|
||||
litest_enable_tap(dev->libinput_device);
|
||||
litest_drain_events(li);
|
||||
|
||||
for (ntaps = 0; ntaps <= range; ntaps++) {
|
||||
litest_touch_down(dev, 0, 50, 50);
|
||||
litest_touch_up(dev, 0);
|
||||
libinput_dispatch(li);
|
||||
msleep(10);
|
||||
}
|
||||
|
||||
litest_touch_down(dev, 0, 50, 50);
|
||||
litest_touch_move_to_extended(dev, 0, 50, 50, 50, 50, axes, 1, 1);
|
||||
litest_touch_up(dev, 0);
|
||||
libinput_dispatch(li);
|
||||
litest_timeout_tap();
|
||||
libinput_dispatch(li);
|
||||
|
||||
for (ntaps = 0; ntaps <= range; ntaps++) {
|
||||
litest_assert_button_event(li,
|
||||
BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
litest_assert_button_event(li,
|
||||
BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
}
|
||||
|
||||
litest_assert_empty_queue(li);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(touchpad_tap_palm_multitap_timeout)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
struct axis_replacement axes[] = {
|
||||
{ ABS_MT_PRESSURE, 75 },
|
||||
{ -1, 0 }
|
||||
};
|
||||
int range = _i, /* ranged test */
|
||||
ntaps;
|
||||
|
||||
if (!touchpad_has_palm_pressure(dev))
|
||||
return;
|
||||
|
||||
litest_enable_tap(dev->libinput_device);
|
||||
litest_drain_events(li);
|
||||
|
||||
for (ntaps = 0; ntaps <= range; ntaps++) {
|
||||
litest_touch_down(dev, 0, 50, 50);
|
||||
litest_touch_up(dev, 0);
|
||||
libinput_dispatch(li);
|
||||
msleep(10);
|
||||
}
|
||||
|
||||
litest_touch_down(dev, 0, 50, 50);
|
||||
litest_touch_move_to_extended(dev, 0, 50, 50, 50, 50, axes, 1, 1);
|
||||
libinput_dispatch(li);
|
||||
litest_timeout_tap();
|
||||
libinput_dispatch(li);
|
||||
|
||||
for (ntaps = 0; ntaps <= range; ntaps++) {
|
||||
litest_assert_button_event(li,
|
||||
BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
litest_assert_button_event(li,
|
||||
BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
}
|
||||
|
||||
litest_assert_empty_queue(li);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(touchpad_tap_palm_multitap_down_again)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
struct axis_replacement axes[] = {
|
||||
{ ABS_MT_PRESSURE, 75 },
|
||||
{ -1, 0 }
|
||||
};
|
||||
int range = _i, /* ranged test */
|
||||
ntaps;
|
||||
|
||||
if (!touchpad_has_palm_pressure(dev))
|
||||
return;
|
||||
|
||||
litest_enable_tap(dev->libinput_device);
|
||||
litest_drain_events(li);
|
||||
|
||||
for (ntaps = 0; ntaps <= range; ntaps++) {
|
||||
litest_touch_down(dev, 0, 50, 50);
|
||||
litest_touch_up(dev, 0);
|
||||
libinput_dispatch(li);
|
||||
msleep(10);
|
||||
}
|
||||
|
||||
litest_touch_down(dev, 0, 50, 50);
|
||||
litest_touch_move_to_extended(dev, 0, 50, 50, 50, 50, axes, 1, 1);
|
||||
libinput_dispatch(li);
|
||||
|
||||
/* keep palm finger down */
|
||||
for (ntaps = 0; ntaps <= range; ntaps++) {
|
||||
litest_touch_down(dev, 1, 50, 50);
|
||||
litest_touch_up(dev, 1);
|
||||
libinput_dispatch(li);
|
||||
msleep(10);
|
||||
}
|
||||
|
||||
for (ntaps = 0; ntaps <= 2 * range; ntaps++) {
|
||||
litest_assert_button_event(li,
|
||||
BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
litest_assert_button_event(li,
|
||||
BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
}
|
||||
|
||||
litest_touch_up(dev, 0);
|
||||
litest_assert_empty_queue(li);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(touchpad_tap_palm_multitap_click)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
struct axis_replacement axes[] = {
|
||||
{ ABS_MT_PRESSURE, 75 },
|
||||
{ -1, 0 }
|
||||
};
|
||||
int range = _i, /* ranged test */
|
||||
ntaps;
|
||||
|
||||
if (!touchpad_has_palm_pressure(dev))
|
||||
return;
|
||||
|
||||
litest_enable_tap(dev->libinput_device);
|
||||
litest_drain_events(li);
|
||||
|
||||
for (ntaps = 0; ntaps <= range; ntaps++) {
|
||||
litest_touch_down(dev, 0, 50, 50);
|
||||
litest_touch_up(dev, 0);
|
||||
libinput_dispatch(li);
|
||||
msleep(10);
|
||||
}
|
||||
|
||||
litest_touch_down(dev, 0, 50, 50);
|
||||
litest_touch_move_to_extended(dev, 0, 50, 50, 50, 50, axes, 1, 1);
|
||||
libinput_dispatch(li);
|
||||
/* keep palm finger down */
|
||||
|
||||
litest_button_click(dev, BTN_LEFT, true);
|
||||
litest_button_click(dev, BTN_LEFT, false);
|
||||
libinput_dispatch(li);
|
||||
|
||||
for (ntaps = 0; ntaps <= range; ntaps++) {
|
||||
litest_assert_button_event(li,
|
||||
BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
litest_assert_button_event(li,
|
||||
BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
}
|
||||
|
||||
/* the click */
|
||||
litest_assert_button_event(li,
|
||||
BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
litest_assert_button_event(li,
|
||||
BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
litest_touch_up(dev, 0);
|
||||
litest_assert_empty_queue(li);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(touchpad_tap_palm_click_then_tap)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
struct axis_replacement axes[] = {
|
||||
{ ABS_MT_PRESSURE, 75 },
|
||||
{ -1, 0 }
|
||||
};
|
||||
|
||||
if (!touchpad_has_palm_pressure(dev))
|
||||
return;
|
||||
|
||||
litest_enable_tap(dev->libinput_device);
|
||||
litest_drain_events(li);
|
||||
|
||||
litest_touch_down_extended(dev, 0, 50, 50, axes);
|
||||
libinput_dispatch(li);
|
||||
|
||||
litest_button_click(dev, BTN_LEFT, true);
|
||||
litest_button_click(dev, BTN_LEFT, false);
|
||||
libinput_dispatch(li);
|
||||
|
||||
litest_assert_button_event(li,
|
||||
BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
litest_assert_button_event(li,
|
||||
BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
|
||||
litest_touch_up(dev, 0);
|
||||
litest_assert_empty_queue(li);
|
||||
|
||||
litest_touch_down(dev, 0, 50, 50);
|
||||
litest_touch_up(dev, 0);
|
||||
libinput_dispatch(li);
|
||||
litest_timeout_tap();
|
||||
libinput_dispatch(li);
|
||||
|
||||
litest_assert_button_event(li,
|
||||
BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
litest_assert_button_event(li,
|
||||
BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
|
||||
litest_assert_empty_queue(li);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(touchpad_tap_palm_dwt_tap)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct litest_device *keyboard;
|
||||
struct libinput *li = dev->libinput;
|
||||
struct axis_replacement axes[] = {
|
||||
{ ABS_MT_PRESSURE, 75 },
|
||||
{ -1, 0 }
|
||||
};
|
||||
|
||||
if (!touchpad_has_palm_pressure(dev))
|
||||
return;
|
||||
|
||||
keyboard = litest_add_device(li, LITEST_KEYBOARD);
|
||||
|
||||
litest_enable_tap(dev->libinput_device);
|
||||
litest_drain_events(li);
|
||||
|
||||
litest_keyboard_key(keyboard, KEY_A, true);
|
||||
litest_keyboard_key(keyboard, KEY_B, true);
|
||||
litest_keyboard_key(keyboard, KEY_A, false);
|
||||
litest_drain_events(li);
|
||||
|
||||
litest_touch_down(dev, 0, 50, 50);
|
||||
libinput_dispatch(li);
|
||||
|
||||
litest_keyboard_key(keyboard, KEY_B, false);
|
||||
litest_drain_events(li);
|
||||
litest_timeout_dwt_long();
|
||||
libinput_dispatch(li);
|
||||
|
||||
/* Changes to palm after dwt timeout */
|
||||
litest_touch_move_to_extended(dev, 0, 50, 50, 50, 50, axes, 1, 1);
|
||||
libinput_dispatch(li);
|
||||
|
||||
litest_touch_up(dev, 0);
|
||||
libinput_dispatch(li);
|
||||
|
||||
litest_assert_empty_queue(li);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
void
|
||||
litest_setup_tests_touchpad_tap(void)
|
||||
{
|
||||
struct range multitap_range = {3, 5};
|
||||
struct range tap_map_range = { LIBINPUT_CONFIG_TAP_MAP_LRM,
|
||||
LIBINPUT_CONFIG_TAP_MAP_LMR + 1 };
|
||||
struct range range_2fg = {0, 2};
|
||||
struct range range_3fg = {0, 3};
|
||||
struct range range_4fg = {0, 4};
|
||||
|
||||
litest_add("tap-1fg:1fg", touchpad_1fg_tap, LITEST_TOUCHPAD, LITEST_ANY);
|
||||
litest_add("tap-1fg:1fg", touchpad_1fg_doubletap, LITEST_TOUCHPAD, LITEST_ANY);
|
||||
|
|
@ -2455,4 +3313,25 @@ litest_setup_tests_touchpad_tap(void)
|
|||
litest_add("tap:drag", touchpad_drag_disabled, LITEST_TOUCHPAD, LITEST_ANY);
|
||||
litest_add("tap:drag", touchpad_drag_disabled_immediate, LITEST_TOUCHPAD, LITEST_ANY);
|
||||
litest_add_ranged("tap-multitap:drag", touchpad_drag_disabled_multitap_no_drag, LITEST_TOUCHPAD, LITEST_ANY, &multitap_range);
|
||||
|
||||
litest_add("tap:palm", touchpad_tap_palm_on_idle, LITEST_TOUCHPAD, LITEST_ANY);
|
||||
litest_add("tap:palm", touchpad_tap_palm_on_touch, LITEST_TOUCHPAD, LITEST_ANY);
|
||||
litest_add("tap:palm", touchpad_tap_palm_on_touch_hold_timeout, LITEST_TOUCHPAD, LITEST_ANY);
|
||||
litest_add("tap:palm", touchpad_tap_palm_on_touch_hold_move, LITEST_TOUCHPAD, LITEST_ANY);
|
||||
litest_add("tap:palm", touchpad_tap_palm_on_tapped, LITEST_TOUCHPAD, LITEST_ANY);
|
||||
litest_add("tap:palm", touchpad_tap_palm_on_tapped_2fg, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH);
|
||||
litest_add("tap:palm", touchpad_tap_palm_on_drag, LITEST_TOUCHPAD, LITEST_ANY);
|
||||
litest_add_ranged("tap:palm", touchpad_tap_palm_on_drag_2fg, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH, &range_2fg);
|
||||
litest_add_ranged("tap:palm", touchpad_tap_palm_on_touch_2, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH, &range_2fg);
|
||||
litest_add_ranged("tap:palm", touchpad_tap_palm_on_touch_2_retouch, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH, &range_2fg);
|
||||
litest_add_ranged("tap:palm", touchpad_tap_palm_on_touch_3, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH, &range_3fg);
|
||||
litest_add_ranged("tap:palm", touchpad_tap_palm_on_touch_3_retouch, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH, &range_3fg);
|
||||
litest_add_ranged("tap:palm", touchpad_tap_palm_on_touch_4, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH, &range_4fg);
|
||||
litest_add("tap:palm", touchpad_tap_palm_after_tap, LITEST_TOUCHPAD, LITEST_ANY);
|
||||
litest_add_ranged("tap:palm", touchpad_tap_palm_multitap, LITEST_TOUCHPAD, LITEST_ANY, &multitap_range);
|
||||
litest_add_ranged("tap:palm", touchpad_tap_palm_multitap_timeout, LITEST_TOUCHPAD, LITEST_ANY, &multitap_range);
|
||||
litest_add_ranged("tap:palm", touchpad_tap_palm_multitap_down_again, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH, &multitap_range);
|
||||
litest_add_ranged("tap:palm", touchpad_tap_palm_multitap_click, LITEST_TOUCHPAD, LITEST_ANY, &multitap_range);
|
||||
litest_add("tap:palm", touchpad_tap_palm_click_then_tap, LITEST_TOUCHPAD, LITEST_ANY);
|
||||
litest_add("tap:palm", touchpad_tap_palm_dwt_tap, LITEST_TOUCHPAD, LITEST_ANY);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue