mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2026-02-03 21:40:40 +01:00
Merge branch 'touchpad-pressure-based-v2'
This commit is contained in:
commit
00d6b908d3
11 changed files with 804 additions and 242 deletions
|
|
@ -766,6 +766,9 @@ tp_tap_handle_state(struct tp_dispatch *tp, uint64_t time)
|
|||
if (t->tap.is_thumb)
|
||||
continue;
|
||||
|
||||
if (t->state == TOUCH_HOVERING)
|
||||
continue;
|
||||
|
||||
if (t->state == TOUCH_BEGIN) {
|
||||
/* The simple version: if a touch is a thumb on
|
||||
* begin we ignore it. All other thumb touches
|
||||
|
|
@ -787,7 +790,8 @@ 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) {
|
||||
tp_tap_handle_event(tp, t, TAP_EVENT_RELEASE, time);
|
||||
if (t->was_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)) {
|
||||
|
|
|
|||
|
|
@ -214,6 +214,7 @@ tp_new_touch(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time)
|
|||
tp_motion_history_reset(t);
|
||||
t->dirty = true;
|
||||
t->has_ended = false;
|
||||
t->was_down = false;
|
||||
t->state = TOUCH_HOVERING;
|
||||
t->pinned.is_pinned = false;
|
||||
t->millis = time;
|
||||
|
|
@ -226,6 +227,7 @@ tp_begin_touch(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time)
|
|||
t->dirty = true;
|
||||
t->state = TOUCH_BEGIN;
|
||||
t->millis = time;
|
||||
t->was_down = true;
|
||||
tp->nfingers_down++;
|
||||
t->palm.time = time;
|
||||
t->thumb.state = THUMB_STATE_MAYBE;
|
||||
|
|
@ -320,9 +322,6 @@ tp_process_absolute(struct tp_dispatch *tp,
|
|||
case ABS_MT_SLOT:
|
||||
tp->slot = e->value;
|
||||
break;
|
||||
case ABS_MT_DISTANCE:
|
||||
t->distance = e->value;
|
||||
break;
|
||||
case ABS_MT_TRACKING_ID:
|
||||
if (e->value != -1)
|
||||
tp_new_touch(tp, t, time);
|
||||
|
|
@ -363,6 +362,11 @@ tp_process_absolute_st(struct tp_dispatch *tp,
|
|||
t->dirty = true;
|
||||
tp->queued |= TOUCHPAD_EVENT_MOTION;
|
||||
break;
|
||||
case ABS_PRESSURE:
|
||||
t->pressure = e->value;
|
||||
t->dirty = true;
|
||||
tp->queued |= TOUCHPAD_EVENT_OTHERAXIS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -793,26 +797,72 @@ out:
|
|||
}
|
||||
|
||||
static void
|
||||
tp_unhover_abs_distance(struct tp_dispatch *tp, uint64_t time)
|
||||
tp_unhover_pressure(struct tp_dispatch *tp, uint64_t time)
|
||||
{
|
||||
struct tp_touch *t;
|
||||
unsigned int i;
|
||||
int i;
|
||||
unsigned int nfake_touches;
|
||||
unsigned int real_fingers_down = 0;
|
||||
|
||||
for (i = 0; i < tp->ntouches; i++) {
|
||||
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++) {
|
||||
t = tp_get_touch(tp, i);
|
||||
|
||||
if (!t->dirty)
|
||||
continue;
|
||||
|
||||
if (t->state == TOUCH_HOVERING) {
|
||||
if (t->distance == 0) {
|
||||
/* avoid jumps when landing a finger */
|
||||
tp_motion_history_reset(t);
|
||||
tp_begin_touch(tp, t, time);
|
||||
if (t->dirty) {
|
||||
if (t->state == TOUCH_HOVERING) {
|
||||
if (t->pressure >= tp->pressure.high) {
|
||||
/* avoid jumps when landing a finger */
|
||||
tp_motion_history_reset(t);
|
||||
tp_begin_touch(tp, t, time);
|
||||
}
|
||||
} else {
|
||||
if (t->pressure < tp->pressure.low)
|
||||
tp_end_touch(tp, t, time);
|
||||
}
|
||||
} else {
|
||||
if (t->distance > 0)
|
||||
tp_end_touch(tp, t, time);
|
||||
}
|
||||
|
||||
if (t->state == TOUCH_BEGIN ||
|
||||
t->state == TOUCH_UPDATE)
|
||||
real_fingers_down++;
|
||||
}
|
||||
|
||||
if (nfake_touches <= tp->num_slots ||
|
||||
tp->nfingers_down == 0)
|
||||
return;
|
||||
|
||||
/* if we have more fake fingers down than slots, we assume
|
||||
* _all_ fingers have enough pressure, even if some of the slotted
|
||||
* ones don't. Anything else gets insane quickly.
|
||||
*/
|
||||
for (i = 0; i < (int)tp->ntouches; i++) {
|
||||
t = tp_get_touch(tp, i);
|
||||
if (t->state == TOUCH_HOVERING) {
|
||||
/* avoid jumps when landing a finger */
|
||||
tp_motion_history_reset(t);
|
||||
tp_begin_touch(tp, t, time);
|
||||
|
||||
if (tp->nfingers_down >= nfake_touches)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (tp->nfingers_down > nfake_touches ||
|
||||
real_fingers_down == 0) {
|
||||
for (i = tp->ntouches - 1; i >= 0; i--) {
|
||||
t = tp_get_touch(tp, i);
|
||||
|
||||
if (t->state == TOUCH_HOVERING ||
|
||||
t->state == TOUCH_NONE)
|
||||
continue;
|
||||
|
||||
tp_end_touch(tp, t, time);
|
||||
|
||||
if (real_fingers_down > 0 &&
|
||||
tp->nfingers_down == nfake_touches)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -879,8 +929,8 @@ tp_unhover_fake_touches(struct tp_dispatch *tp, uint64_t time)
|
|||
static void
|
||||
tp_unhover_touches(struct tp_dispatch *tp, uint64_t time)
|
||||
{
|
||||
if (tp->reports_distance)
|
||||
tp_unhover_abs_distance(tp, time);
|
||||
if (tp->pressure.use_pressure)
|
||||
tp_unhover_pressure(tp, time);
|
||||
else
|
||||
tp_unhover_fake_touches(tp, time);
|
||||
|
||||
|
|
@ -924,6 +974,7 @@ tp_position_fake_touches(struct tp_dispatch *tp)
|
|||
continue;
|
||||
|
||||
t->point = topmost->point;
|
||||
t->pressure = topmost->pressure;
|
||||
if (!t->dirty)
|
||||
t->dirty = topmost->dirty;
|
||||
}
|
||||
|
|
@ -1791,7 +1842,13 @@ tp_sync_touch(struct tp_dispatch *tp,
|
|||
&t->point.y))
|
||||
t->point.y = libevdev_get_event_value(evdev, EV_ABS, ABS_Y);
|
||||
|
||||
libevdev_fetch_slot_value(evdev, slot, ABS_MT_DISTANCE, &t->distance);
|
||||
if (!libevdev_fetch_slot_value(evdev,
|
||||
slot,
|
||||
ABS_MT_PRESSURE,
|
||||
&t->pressure))
|
||||
t->pressure = libevdev_get_event_value(evdev,
|
||||
EV_ABS,
|
||||
ABS_PRESSURE);
|
||||
}
|
||||
|
||||
static inline void
|
||||
|
|
@ -2313,6 +2370,38 @@ tp_init_hysteresis(struct tp_dispatch *tp)
|
|||
tp->hysteresis_margin.y = res_y/2;
|
||||
}
|
||||
|
||||
static void
|
||||
tp_init_pressure(struct tp_dispatch *tp,
|
||||
struct evdev_device *device)
|
||||
{
|
||||
const struct input_absinfo *abs;
|
||||
unsigned int range;
|
||||
unsigned int code = ABS_PRESSURE;
|
||||
|
||||
if (tp->has_mt)
|
||||
code = ABS_MT_PRESSURE;
|
||||
|
||||
if (!libevdev_has_event_code(device->evdev, EV_ABS, code)) {
|
||||
tp->pressure.use_pressure = false;
|
||||
return;
|
||||
}
|
||||
|
||||
tp->pressure.use_pressure = true;
|
||||
|
||||
abs = libevdev_get_abs_info(device->evdev, code);
|
||||
assert(abs);
|
||||
|
||||
range = abs->maximum - abs->minimum;
|
||||
|
||||
/* Approximately the synaptics defaults */
|
||||
tp->pressure.high = abs->minimum + 0.12 * range;
|
||||
tp->pressure.low = abs->minimum + 0.10 * range;
|
||||
|
||||
log_debug(evdev_libinput_context(device),
|
||||
"%s: using pressure-based touch detection\n",
|
||||
device->devname);
|
||||
}
|
||||
|
||||
static int
|
||||
tp_init(struct tp_dispatch *tp,
|
||||
struct evdev_device *device)
|
||||
|
|
@ -2331,9 +2420,7 @@ tp_init(struct tp_dispatch *tp,
|
|||
|
||||
evdev_device_init_abs_range_warnings(device);
|
||||
|
||||
tp->reports_distance = libevdev_has_event_code(device->evdev,
|
||||
EV_ABS,
|
||||
ABS_MT_DISTANCE);
|
||||
tp_init_pressure(tp, device);
|
||||
|
||||
/* Set the dpi to that of the x axis, because that's what we normalize
|
||||
to when needed*/
|
||||
|
|
|
|||
|
|
@ -153,9 +153,11 @@ struct tp_touch {
|
|||
bool dirty;
|
||||
struct device_coords point;
|
||||
uint64_t millis;
|
||||
int distance; /* distance == 0 means touch */
|
||||
int pressure;
|
||||
|
||||
bool was_down; /* if distance == 0, false for pure hovering
|
||||
touches */
|
||||
|
||||
struct {
|
||||
/* A quirk mostly used on Synaptics touchpads. In a
|
||||
transition to/from fake touches > num_slots, the current
|
||||
|
|
@ -229,7 +231,6 @@ struct tp_dispatch {
|
|||
unsigned int slot; /* current slot */
|
||||
bool has_mt;
|
||||
bool semi_mt;
|
||||
bool reports_distance; /* does the device support true hovering */
|
||||
|
||||
/* true if we're reading events (i.e. not suspended) but we're
|
||||
* ignoring them */
|
||||
|
|
@ -245,6 +246,14 @@ struct tp_dispatch {
|
|||
*/
|
||||
unsigned int fake_touches;
|
||||
|
||||
/* if pressure goes above high -> touch down,
|
||||
if pressure then goes below low -> touch up */
|
||||
struct {
|
||||
bool use_pressure;
|
||||
int high;
|
||||
int low;
|
||||
} pressure;
|
||||
|
||||
struct device_coords hysteresis_margin;
|
||||
|
||||
struct {
|
||||
|
|
|
|||
|
|
@ -30,8 +30,6 @@
|
|||
#include "litest.h"
|
||||
#include "litest-int.h"
|
||||
|
||||
static void alps_dualpoint_create(struct litest_device *d);
|
||||
|
||||
static void
|
||||
litest_alps_dualpoint_setup(void)
|
||||
{
|
||||
|
|
@ -39,34 +37,46 @@ litest_alps_dualpoint_setup(void)
|
|||
litest_set_current_device(d);
|
||||
}
|
||||
|
||||
static void
|
||||
alps_dualpoint_touch_down(struct litest_device *d, unsigned int slot, double x, double y)
|
||||
static struct input_event down[] = {
|
||||
{ .type = EV_ABS, .code = ABS_X, .value = LITEST_AUTO_ASSIGN },
|
||||
{ .type = EV_ABS, .code = ABS_Y, .value = LITEST_AUTO_ASSIGN },
|
||||
{ .type = EV_ABS, .code = ABS_PRESSURE, .value = LITEST_AUTO_ASSIGN },
|
||||
{ .type = EV_ABS, .code = ABS_MT_SLOT, .value = LITEST_AUTO_ASSIGN },
|
||||
{ .type = EV_ABS, .code = ABS_MT_TRACKING_ID, .value = LITEST_AUTO_ASSIGN },
|
||||
{ .type = EV_ABS, .code = ABS_MT_POSITION_X, .value = LITEST_AUTO_ASSIGN },
|
||||
{ .type = EV_ABS, .code = ABS_MT_POSITION_Y, .value = LITEST_AUTO_ASSIGN },
|
||||
{ .type = EV_SYN, .code = SYN_REPORT, .value = 0 },
|
||||
{ .type = -1, .code = -1 },
|
||||
};
|
||||
|
||||
static struct input_event move[] = {
|
||||
{ .type = EV_ABS, .code = ABS_MT_SLOT, .value = LITEST_AUTO_ASSIGN },
|
||||
{ .type = EV_ABS, .code = ABS_X, .value = LITEST_AUTO_ASSIGN },
|
||||
{ .type = EV_ABS, .code = ABS_Y, .value = LITEST_AUTO_ASSIGN },
|
||||
{ .type = EV_ABS, .code = ABS_PRESSURE, .value = LITEST_AUTO_ASSIGN },
|
||||
{ .type = EV_ABS, .code = ABS_MT_POSITION_X, .value = LITEST_AUTO_ASSIGN },
|
||||
{ .type = EV_ABS, .code = ABS_MT_POSITION_Y, .value = LITEST_AUTO_ASSIGN },
|
||||
{ .type = EV_SYN, .code = SYN_REPORT, .value = 0 },
|
||||
{ .type = -1, .code = -1 },
|
||||
};
|
||||
|
||||
static int
|
||||
get_axis_default(struct litest_device *d, unsigned int evcode, int32_t *value)
|
||||
{
|
||||
struct litest_semi_mt *semi_mt = d->private;
|
||||
|
||||
litest_semi_mt_touch_down(d, semi_mt, slot, x, y);
|
||||
}
|
||||
|
||||
static void
|
||||
alps_dualpoint_touch_move(struct litest_device *d, unsigned int slot, double x, double y)
|
||||
{
|
||||
struct litest_semi_mt *semi_mt = d->private;
|
||||
|
||||
litest_semi_mt_touch_move(d, semi_mt, slot, x, y);
|
||||
}
|
||||
|
||||
static void
|
||||
alps_dualpoint_touch_up(struct litest_device *d, unsigned int slot)
|
||||
{
|
||||
struct litest_semi_mt *semi_mt = d->private;
|
||||
|
||||
litest_semi_mt_touch_up(d, semi_mt, slot);
|
||||
switch (evcode) {
|
||||
case ABS_PRESSURE:
|
||||
case ABS_MT_PRESSURE:
|
||||
*value = 30;
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct litest_device_interface interface = {
|
||||
.touch_down = alps_dualpoint_touch_down,
|
||||
.touch_move = alps_dualpoint_touch_move,
|
||||
.touch_up = alps_dualpoint_touch_up,
|
||||
.touch_down_events = down,
|
||||
.touch_move_events = move,
|
||||
|
||||
.get_axis_default = get_axis_default,
|
||||
};
|
||||
|
||||
static struct input_id input_id = {
|
||||
|
|
@ -116,7 +126,6 @@ struct litest_test_device litest_alps_dualpoint_device = {
|
|||
.shortname = "alps dualpoint",
|
||||
.setup = litest_alps_dualpoint_setup,
|
||||
.interface = &interface,
|
||||
.create = alps_dualpoint_create,
|
||||
|
||||
.name = "AlpsPS/2 ALPS DualPoint TouchPad",
|
||||
.id = &input_id,
|
||||
|
|
@ -124,18 +133,3 @@ struct litest_test_device litest_alps_dualpoint_device = {
|
|||
.absinfo = absinfo,
|
||||
.udev_rule = udev_rule,
|
||||
};
|
||||
|
||||
static void
|
||||
alps_dualpoint_create(struct litest_device *d)
|
||||
{
|
||||
struct litest_semi_mt *semi_mt = zalloc(sizeof(*semi_mt));
|
||||
assert(semi_mt);
|
||||
|
||||
d->private = semi_mt;
|
||||
|
||||
d->uinput = litest_create_uinput_device_from_description(litest_alps_dualpoint_device.name,
|
||||
litest_alps_dualpoint_device.id,
|
||||
absinfo,
|
||||
events);
|
||||
d->interface = &interface;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,8 +30,6 @@
|
|||
#include "litest.h"
|
||||
#include "litest-int.h"
|
||||
|
||||
static void alps_create(struct litest_device *d);
|
||||
|
||||
static void
|
||||
litest_alps_setup(void)
|
||||
{
|
||||
|
|
@ -39,34 +37,46 @@ litest_alps_setup(void)
|
|||
litest_set_current_device(d);
|
||||
}
|
||||
|
||||
static void
|
||||
alps_touch_down(struct litest_device *d, unsigned int slot, double x, double y)
|
||||
static struct input_event down[] = {
|
||||
{ .type = EV_ABS, .code = ABS_X, .value = LITEST_AUTO_ASSIGN },
|
||||
{ .type = EV_ABS, .code = ABS_Y, .value = LITEST_AUTO_ASSIGN },
|
||||
{ .type = EV_ABS, .code = ABS_PRESSURE, .value = LITEST_AUTO_ASSIGN },
|
||||
{ .type = EV_ABS, .code = ABS_MT_SLOT, .value = LITEST_AUTO_ASSIGN },
|
||||
{ .type = EV_ABS, .code = ABS_MT_TRACKING_ID, .value = LITEST_AUTO_ASSIGN },
|
||||
{ .type = EV_ABS, .code = ABS_MT_POSITION_X, .value = LITEST_AUTO_ASSIGN },
|
||||
{ .type = EV_ABS, .code = ABS_MT_POSITION_Y, .value = LITEST_AUTO_ASSIGN },
|
||||
{ .type = EV_SYN, .code = SYN_REPORT, .value = 0 },
|
||||
{ .type = -1, .code = -1 },
|
||||
};
|
||||
|
||||
static struct input_event move[] = {
|
||||
{ .type = EV_ABS, .code = ABS_MT_SLOT, .value = LITEST_AUTO_ASSIGN },
|
||||
{ .type = EV_ABS, .code = ABS_X, .value = LITEST_AUTO_ASSIGN },
|
||||
{ .type = EV_ABS, .code = ABS_Y, .value = LITEST_AUTO_ASSIGN },
|
||||
{ .type = EV_ABS, .code = ABS_PRESSURE, .value = LITEST_AUTO_ASSIGN },
|
||||
{ .type = EV_ABS, .code = ABS_MT_POSITION_X, .value = LITEST_AUTO_ASSIGN },
|
||||
{ .type = EV_ABS, .code = ABS_MT_POSITION_Y, .value = LITEST_AUTO_ASSIGN },
|
||||
{ .type = EV_SYN, .code = SYN_REPORT, .value = 0 },
|
||||
{ .type = -1, .code = -1 },
|
||||
};
|
||||
|
||||
static int
|
||||
get_axis_default(struct litest_device *d, unsigned int evcode, int32_t *value)
|
||||
{
|
||||
struct litest_semi_mt *semi_mt = d->private;
|
||||
|
||||
litest_semi_mt_touch_down(d, semi_mt, slot, x, y);
|
||||
}
|
||||
|
||||
static void
|
||||
alps_touch_move(struct litest_device *d, unsigned int slot, double x, double y)
|
||||
{
|
||||
struct litest_semi_mt *semi_mt = d->private;
|
||||
|
||||
litest_semi_mt_touch_move(d, semi_mt, slot, x, y);
|
||||
}
|
||||
|
||||
static void
|
||||
alps_touch_up(struct litest_device *d, unsigned int slot)
|
||||
{
|
||||
struct litest_semi_mt *semi_mt = d->private;
|
||||
|
||||
litest_semi_mt_touch_up(d, semi_mt, slot);
|
||||
switch (evcode) {
|
||||
case ABS_PRESSURE:
|
||||
case ABS_MT_PRESSURE:
|
||||
*value = 30;
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct litest_device_interface interface = {
|
||||
.touch_down = alps_touch_down,
|
||||
.touch_move = alps_touch_move,
|
||||
.touch_up = alps_touch_up,
|
||||
.touch_down_events = down,
|
||||
.touch_move_events = move,
|
||||
|
||||
.get_axis_default = get_axis_default,
|
||||
};
|
||||
|
||||
static struct input_id input_id = {
|
||||
|
|
@ -106,25 +116,9 @@ struct litest_test_device litest_alps_device = {
|
|||
.shortname = "alps semi-mt",
|
||||
.setup = litest_alps_setup,
|
||||
.interface = &interface,
|
||||
.create = alps_create,
|
||||
|
||||
.name = "AlpsPS/2 ALPS GlidePoint",
|
||||
.id = &input_id,
|
||||
.events = events,
|
||||
.absinfo = absinfo,
|
||||
};
|
||||
|
||||
static void
|
||||
alps_create(struct litest_device *d)
|
||||
{
|
||||
struct litest_semi_mt *semi_mt = zalloc(sizeof(*semi_mt));
|
||||
assert(semi_mt);
|
||||
|
||||
d->private = semi_mt;
|
||||
|
||||
d->uinput = litest_create_uinput_device_from_description(litest_alps_device.name,
|
||||
litest_alps_device.id,
|
||||
absinfo,
|
||||
events);
|
||||
d->interface = &interface;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -76,10 +76,24 @@ static struct input_event up[] = {
|
|||
{ .type = -1, .code = -1 },
|
||||
};
|
||||
|
||||
static int
|
||||
get_axis_default(struct litest_device *d, unsigned int evcode, int32_t *value)
|
||||
{
|
||||
switch (evcode) {
|
||||
case ABS_PRESSURE:
|
||||
case ABS_MT_PRESSURE:
|
||||
*value = 30;
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct litest_device_interface interface = {
|
||||
.touch_down_events = down,
|
||||
.touch_move_events = move,
|
||||
.touch_up_events = up,
|
||||
|
||||
.get_axis_default = get_axis_default,
|
||||
};
|
||||
|
||||
static struct input_id input_id = {
|
||||
|
|
|
|||
|
|
@ -30,9 +30,6 @@
|
|||
#include "litest.h"
|
||||
#include "litest-int.h"
|
||||
|
||||
static void
|
||||
synaptics_hover_create(struct litest_device *d);
|
||||
|
||||
static void
|
||||
litest_synaptics_hover_setup(void)
|
||||
{
|
||||
|
|
@ -40,34 +37,46 @@ litest_synaptics_hover_setup(void)
|
|||
litest_set_current_device(d);
|
||||
}
|
||||
|
||||
static void
|
||||
synaptics_hover_touch_down(struct litest_device *d, unsigned int slot, double x, double y)
|
||||
static struct input_event down[] = {
|
||||
{ .type = EV_ABS, .code = ABS_X, .value = LITEST_AUTO_ASSIGN },
|
||||
{ .type = EV_ABS, .code = ABS_Y, .value = LITEST_AUTO_ASSIGN },
|
||||
{ .type = EV_ABS, .code = ABS_PRESSURE, .value = LITEST_AUTO_ASSIGN },
|
||||
{ .type = EV_ABS, .code = ABS_MT_SLOT, .value = LITEST_AUTO_ASSIGN },
|
||||
{ .type = EV_ABS, .code = ABS_MT_TRACKING_ID, .value = LITEST_AUTO_ASSIGN },
|
||||
{ .type = EV_ABS, .code = ABS_MT_POSITION_X, .value = LITEST_AUTO_ASSIGN },
|
||||
{ .type = EV_ABS, .code = ABS_MT_POSITION_Y, .value = LITEST_AUTO_ASSIGN },
|
||||
{ .type = EV_SYN, .code = SYN_REPORT, .value = 0 },
|
||||
{ .type = -1, .code = -1 },
|
||||
};
|
||||
|
||||
static struct input_event move[] = {
|
||||
{ .type = EV_ABS, .code = ABS_MT_SLOT, .value = LITEST_AUTO_ASSIGN },
|
||||
{ .type = EV_ABS, .code = ABS_X, .value = LITEST_AUTO_ASSIGN },
|
||||
{ .type = EV_ABS, .code = ABS_Y, .value = LITEST_AUTO_ASSIGN },
|
||||
{ .type = EV_ABS, .code = ABS_PRESSURE, .value = LITEST_AUTO_ASSIGN },
|
||||
{ .type = EV_ABS, .code = ABS_MT_POSITION_X, .value = LITEST_AUTO_ASSIGN },
|
||||
{ .type = EV_ABS, .code = ABS_MT_POSITION_Y, .value = LITEST_AUTO_ASSIGN },
|
||||
{ .type = EV_SYN, .code = SYN_REPORT, .value = 0 },
|
||||
{ .type = -1, .code = -1 },
|
||||
};
|
||||
|
||||
static int
|
||||
get_axis_default(struct litest_device *d, unsigned int evcode, int32_t *value)
|
||||
{
|
||||
struct litest_semi_mt *semi_mt = d->private;
|
||||
|
||||
litest_semi_mt_touch_down(d, semi_mt, slot, x, y);
|
||||
}
|
||||
|
||||
static void
|
||||
synaptics_hover_touch_move(struct litest_device *d, unsigned int slot, double x, double y)
|
||||
{
|
||||
struct litest_semi_mt *semi_mt = d->private;
|
||||
|
||||
litest_semi_mt_touch_move(d, semi_mt, slot, x, y);
|
||||
}
|
||||
|
||||
static void
|
||||
synaptics_hover_touch_up(struct litest_device *d, unsigned int slot)
|
||||
{
|
||||
struct litest_semi_mt *semi_mt = d->private;
|
||||
|
||||
litest_semi_mt_touch_up(d, semi_mt, slot);
|
||||
switch (evcode) {
|
||||
case ABS_PRESSURE:
|
||||
case ABS_MT_PRESSURE:
|
||||
*value = 30;
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct litest_device_interface interface = {
|
||||
.touch_down = synaptics_hover_touch_down,
|
||||
.touch_move = synaptics_hover_touch_move,
|
||||
.touch_up = synaptics_hover_touch_up,
|
||||
.touch_down_events = down,
|
||||
.touch_move_events = move,
|
||||
|
||||
.get_axis_default = get_axis_default,
|
||||
};
|
||||
|
||||
static struct input_id input_id = {
|
||||
|
|
@ -115,7 +124,6 @@ struct litest_test_device litest_synaptics_hover_device = {
|
|||
.shortname = "synaptics hover",
|
||||
.setup = litest_synaptics_hover_setup,
|
||||
.interface = &interface,
|
||||
.create = synaptics_hover_create,
|
||||
|
||||
.name = "SynPS/2 Synaptics TouchPad",
|
||||
.id = &input_id,
|
||||
|
|
@ -123,19 +131,3 @@ struct litest_test_device litest_synaptics_hover_device = {
|
|||
.absinfo = absinfo,
|
||||
.udev_rule = udev_rule,
|
||||
};
|
||||
|
||||
static void
|
||||
synaptics_hover_create(struct litest_device *d)
|
||||
{
|
||||
struct litest_semi_mt *semi_mt = zalloc(sizeof(*semi_mt));
|
||||
assert(semi_mt);
|
||||
|
||||
d->private = semi_mt;
|
||||
|
||||
d->uinput = litest_create_uinput_device_from_description(
|
||||
litest_synaptics_hover_device.name,
|
||||
litest_synaptics_hover_device.id,
|
||||
absinfo,
|
||||
events);
|
||||
d->interface = &interface;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ litest_synaptics_touchpad_setup(void)
|
|||
static struct input_event down[] = {
|
||||
{ .type = EV_ABS, .code = ABS_X, .value = LITEST_AUTO_ASSIGN },
|
||||
{ .type = EV_ABS, .code = ABS_Y, .value = LITEST_AUTO_ASSIGN },
|
||||
{ .type = EV_ABS, .code = ABS_PRESSURE, .value = 30 },
|
||||
{ .type = EV_ABS, .code = ABS_PRESSURE, .value = LITEST_AUTO_ASSIGN },
|
||||
{ .type = EV_ABS, .code = ABS_TOOL_WIDTH, .value = 7 },
|
||||
{ .type = EV_SYN, .code = SYN_REPORT, .value = 0 },
|
||||
{ .type = -1, .code = -1 },
|
||||
|
|
@ -54,10 +54,23 @@ struct input_event up[] = {
|
|||
{ .type = -1, .code = -1 },
|
||||
};
|
||||
|
||||
static int
|
||||
get_axis_default(struct litest_device *d, unsigned int evcode, int32_t *value)
|
||||
{
|
||||
switch (evcode) {
|
||||
case ABS_PRESSURE:
|
||||
*value = 30;
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct litest_device_interface interface = {
|
||||
.touch_down_events = down,
|
||||
.touch_move_events = move,
|
||||
.touch_up_events = up,
|
||||
|
||||
.get_axis_default = get_axis_default,
|
||||
};
|
||||
|
||||
static struct input_absinfo absinfo[] = {
|
||||
|
|
|
|||
333
test/litest.c
333
test/litest.c
|
|
@ -1206,7 +1206,7 @@ litest_create(enum litest_device_type which,
|
|||
const char *name;
|
||||
const struct input_id *id;
|
||||
struct input_absinfo *abs;
|
||||
int *events;
|
||||
int *events, *e;
|
||||
|
||||
dev = devices;
|
||||
while (*dev) {
|
||||
|
|
@ -1241,6 +1241,18 @@ litest_create(enum litest_device_type which,
|
|||
abs,
|
||||
events);
|
||||
d->interface = (*dev)->interface;
|
||||
|
||||
for (e = events; *e != -1; e += 2) {
|
||||
unsigned int type = *e,
|
||||
code = *(e + 1);
|
||||
|
||||
if (type == INPUT_PROP_MAX &&
|
||||
code == INPUT_PROP_SEMI_MT) {
|
||||
d->semi_mt.is_semi_mt = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
free(abs);
|
||||
free(events);
|
||||
|
||||
|
|
@ -1391,6 +1403,8 @@ litest_delete_device(struct litest_device *d)
|
|||
if (!d)
|
||||
return;
|
||||
|
||||
litest_assert_int_eq(d->skip_ev_syn, 0);
|
||||
|
||||
libinput_device_unref(d->libinput_device);
|
||||
libinput_path_remove_device(d->libinput_device);
|
||||
if (d->owns_context)
|
||||
|
|
@ -1491,12 +1505,13 @@ send_btntool(struct litest_device *d, bool hover)
|
|||
}
|
||||
|
||||
static void
|
||||
litest_slot_start(struct litest_device *d,
|
||||
unsigned int slot,
|
||||
double x,
|
||||
double y,
|
||||
struct axis_replacement *axes,
|
||||
bool touching)
|
||||
slot_start(struct litest_device *d,
|
||||
unsigned int slot,
|
||||
double x,
|
||||
double y,
|
||||
struct axis_replacement *axes,
|
||||
bool touching,
|
||||
bool filter_abs_xy)
|
||||
{
|
||||
struct input_event *ev;
|
||||
|
||||
|
|
@ -1510,8 +1525,9 @@ litest_slot_start(struct litest_device *d,
|
|||
return;
|
||||
}
|
||||
|
||||
ev = d->interface->touch_down_events;
|
||||
while (ev && (int16_t)ev->type != -1 && (int16_t)ev->code != -1) {
|
||||
for (ev = d->interface->touch_down_events;
|
||||
ev && (int16_t)ev->type != -1 && (int16_t)ev->code != -1;
|
||||
ev++) {
|
||||
int value = litest_auto_assign_value(d,
|
||||
ev,
|
||||
slot,
|
||||
|
|
@ -1519,12 +1535,142 @@ litest_slot_start(struct litest_device *d,
|
|||
y,
|
||||
axes,
|
||||
touching);
|
||||
if (value != LITEST_AUTO_ASSIGN)
|
||||
litest_event(d, ev->type, ev->code, value);
|
||||
ev++;
|
||||
if (value == LITEST_AUTO_ASSIGN)
|
||||
continue;
|
||||
|
||||
if (filter_abs_xy && ev->type == EV_ABS &&
|
||||
(ev->code == ABS_X || ev->code == ABS_Y))
|
||||
continue;
|
||||
|
||||
litest_event(d, ev->type, ev->code, value);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
slot_move(struct litest_device *d,
|
||||
unsigned int slot,
|
||||
double x,
|
||||
double y,
|
||||
struct axis_replacement *axes,
|
||||
bool touching,
|
||||
bool filter_abs_xy)
|
||||
{
|
||||
struct input_event *ev;
|
||||
|
||||
if (d->interface->touch_move) {
|
||||
d->interface->touch_move(d, slot, x, y);
|
||||
return;
|
||||
}
|
||||
|
||||
for (ev = d->interface->touch_move_events;
|
||||
ev && (int16_t)ev->type != -1 && (int16_t)ev->code != -1;
|
||||
ev++) {
|
||||
int value = litest_auto_assign_value(d,
|
||||
ev,
|
||||
slot,
|
||||
x,
|
||||
y,
|
||||
axes,
|
||||
touching);
|
||||
if (value == LITEST_AUTO_ASSIGN)
|
||||
continue;
|
||||
|
||||
if (filter_abs_xy && ev->type == EV_ABS &&
|
||||
(ev->code == ABS_X || ev->code == ABS_Y))
|
||||
continue;
|
||||
|
||||
litest_event(d, ev->type, ev->code, value);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
touch_up(struct litest_device *d, unsigned int slot)
|
||||
{
|
||||
struct input_event *ev;
|
||||
struct input_event up[] = {
|
||||
{ .type = EV_ABS, .code = ABS_MT_SLOT, .value = LITEST_AUTO_ASSIGN },
|
||||
{ .type = EV_ABS, .code = ABS_MT_TRACKING_ID, .value = -1 },
|
||||
{ .type = EV_ABS, .code = ABS_MT_PRESSURE, .value = 0 },
|
||||
{ .type = EV_SYN, .code = SYN_REPORT, .value = 0 },
|
||||
{ .type = -1, .code = -1 }
|
||||
};
|
||||
|
||||
litest_assert_int_gt(d->ntouches_down, 0);
|
||||
d->ntouches_down--;
|
||||
|
||||
send_btntool(d, false);
|
||||
|
||||
if (d->interface->touch_up) {
|
||||
d->interface->touch_up(d, slot);
|
||||
return;
|
||||
} else if (d->interface->touch_up_events) {
|
||||
ev = d->interface->touch_up_events;
|
||||
} else
|
||||
ev = up;
|
||||
|
||||
for ( /* */;
|
||||
ev && (int16_t)ev->type != -1 && (int16_t)ev->code != -1;
|
||||
ev++) {
|
||||
int value = litest_auto_assign_value(d,
|
||||
ev,
|
||||
slot,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
false);
|
||||
litest_event(d, ev->type, ev->code, value);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
litest_slot_start(struct litest_device *d,
|
||||
unsigned int slot,
|
||||
double x,
|
||||
double y,
|
||||
struct axis_replacement *axes,
|
||||
bool touching)
|
||||
{
|
||||
double t, l, r = 0, b = 0; /* top, left, right, bottom */
|
||||
bool filter_abs_xy = false;
|
||||
|
||||
if (!d->semi_mt.is_semi_mt) {
|
||||
slot_start(d, slot, x, y, axes, touching, filter_abs_xy);
|
||||
return;
|
||||
}
|
||||
|
||||
if (d->ntouches_down >= 2 || slot > 1)
|
||||
return;
|
||||
|
||||
slot = d->ntouches_down;
|
||||
|
||||
if (d->ntouches_down == 0) {
|
||||
l = x;
|
||||
t = y;
|
||||
} else {
|
||||
int other = (slot + 1) % 2;
|
||||
l = min(x, d->semi_mt.touches[other].x);
|
||||
t = min(y, d->semi_mt.touches[other].y);
|
||||
r = max(x, d->semi_mt.touches[other].x);
|
||||
b = max(y, d->semi_mt.touches[other].y);
|
||||
}
|
||||
|
||||
litest_push_event_frame(d);
|
||||
if (d->ntouches_down == 0)
|
||||
slot_start(d, 0, l, t, axes, touching, filter_abs_xy);
|
||||
else
|
||||
slot_move(d, 0, l, t, axes, touching, filter_abs_xy);
|
||||
|
||||
if (slot == 1) {
|
||||
filter_abs_xy = true;
|
||||
slot_start(d, 1, r, b, axes, touching, filter_abs_xy);
|
||||
}
|
||||
|
||||
litest_pop_event_frame(d);
|
||||
|
||||
d->semi_mt.touches[slot].x = x;
|
||||
d->semi_mt.touches[slot].y = y;
|
||||
}
|
||||
|
||||
void
|
||||
litest_touch_down(struct litest_device *d,
|
||||
unsigned int slot,
|
||||
|
|
@ -1544,43 +1690,6 @@ litest_touch_down_extended(struct litest_device *d,
|
|||
litest_slot_start(d, slot, x, y, axes, true);
|
||||
}
|
||||
|
||||
void
|
||||
litest_touch_up(struct litest_device *d, unsigned int slot)
|
||||
{
|
||||
struct input_event *ev;
|
||||
struct input_event up[] = {
|
||||
{ .type = EV_ABS, .code = ABS_MT_SLOT, .value = LITEST_AUTO_ASSIGN },
|
||||
{ .type = EV_ABS, .code = ABS_MT_TRACKING_ID, .value = -1 },
|
||||
{ .type = EV_SYN, .code = SYN_REPORT, .value = 0 },
|
||||
{ .type = -1, .code = -1 }
|
||||
};
|
||||
|
||||
litest_assert_int_gt(d->ntouches_down, 0);
|
||||
d->ntouches_down--;
|
||||
|
||||
send_btntool(d, false);
|
||||
|
||||
if (d->interface->touch_up) {
|
||||
d->interface->touch_up(d, slot);
|
||||
return;
|
||||
} else if (d->interface->touch_up_events) {
|
||||
ev = d->interface->touch_up_events;
|
||||
} else
|
||||
ev = up;
|
||||
|
||||
while (ev && (int16_t)ev->type != -1 && (int16_t)ev->code != -1) {
|
||||
int value = litest_auto_assign_value(d,
|
||||
ev,
|
||||
slot,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
false);
|
||||
litest_event(d, ev->type, ev->code, value);
|
||||
ev++;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
litest_slot_move(struct litest_device *d,
|
||||
unsigned int slot,
|
||||
|
|
@ -1589,26 +1698,73 @@ litest_slot_move(struct litest_device *d,
|
|||
struct axis_replacement *axes,
|
||||
bool touching)
|
||||
{
|
||||
struct input_event *ev;
|
||||
double t, l, r = 0, b = 0; /* top, left, right, bottom */
|
||||
bool filter_abs_xy = false;
|
||||
|
||||
if (d->interface->touch_move) {
|
||||
d->interface->touch_move(d, slot, x, y);
|
||||
if (!d->semi_mt.is_semi_mt) {
|
||||
slot_move(d, slot, x, y, axes, touching, filter_abs_xy);
|
||||
return;
|
||||
}
|
||||
|
||||
ev = d->interface->touch_move_events;
|
||||
while (ev && (int16_t)ev->type != -1 && (int16_t)ev->code != -1) {
|
||||
int value = litest_auto_assign_value(d,
|
||||
ev,
|
||||
slot,
|
||||
x,
|
||||
y,
|
||||
axes,
|
||||
touching);
|
||||
if (value != LITEST_AUTO_ASSIGN)
|
||||
litest_event(d, ev->type, ev->code, value);
|
||||
ev++;
|
||||
if (d->ntouches_down > 2 || slot > 1)
|
||||
return;
|
||||
|
||||
if (d->ntouches_down == 1) {
|
||||
l = x;
|
||||
t = y;
|
||||
} else {
|
||||
int other = (slot + 1) % 2;
|
||||
l = min(x, d->semi_mt.touches[other].x);
|
||||
t = min(y, d->semi_mt.touches[other].y);
|
||||
r = max(x, d->semi_mt.touches[other].x);
|
||||
b = max(y, d->semi_mt.touches[other].y);
|
||||
}
|
||||
|
||||
litest_push_event_frame(d);
|
||||
slot_move(d, 0, l, t, axes, touching, filter_abs_xy);
|
||||
|
||||
if (d->ntouches_down == 2) {
|
||||
filter_abs_xy = true;
|
||||
slot_move(d, 1, r, b, axes, touching, filter_abs_xy);
|
||||
}
|
||||
|
||||
litest_pop_event_frame(d);
|
||||
|
||||
d->semi_mt.touches[slot].x = x;
|
||||
d->semi_mt.touches[slot].y = y;
|
||||
}
|
||||
|
||||
void
|
||||
litest_touch_up(struct litest_device *d, unsigned int slot)
|
||||
{
|
||||
if (!d->semi_mt.is_semi_mt) {
|
||||
touch_up(d, slot);
|
||||
return;
|
||||
}
|
||||
|
||||
if (d->ntouches_down > 2 || slot > 1)
|
||||
return;
|
||||
|
||||
litest_push_event_frame(d);
|
||||
touch_up(d, d->ntouches_down - 1);
|
||||
|
||||
/* if we have one finger left, send x/y coords for that finger left.
|
||||
this is likely to happen with a real touchpad */
|
||||
if (d->ntouches_down == 1) {
|
||||
bool touching = true;
|
||||
bool filter_abs_xy = false;
|
||||
|
||||
int other = (slot + 1) % 2;
|
||||
slot_move(d,
|
||||
0,
|
||||
d->semi_mt.touches[other].x,
|
||||
d->semi_mt.touches[other].y,
|
||||
NULL,
|
||||
touching,
|
||||
filter_abs_xy);
|
||||
}
|
||||
|
||||
litest_pop_event_frame(d);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -1650,6 +1806,28 @@ litest_touch_move_to(struct litest_device *d,
|
|||
litest_touch_move(d, slot, x_to, y_to);
|
||||
}
|
||||
|
||||
void
|
||||
litest_touch_move_to_extended(struct litest_device *d,
|
||||
unsigned int slot,
|
||||
double x_from, double y_from,
|
||||
double x_to, double y_to,
|
||||
struct axis_replacement *axes,
|
||||
int steps, int sleep_ms)
|
||||
{
|
||||
for (int i = 1; i < steps - 1; i++) {
|
||||
litest_touch_move_extended(d, slot,
|
||||
x_from + (x_to - x_from)/steps * i,
|
||||
y_from + (y_to - y_from)/steps * i,
|
||||
axes);
|
||||
if (sleep_ms) {
|
||||
libinput_dispatch(d->libinput);
|
||||
msleep(sleep_ms);
|
||||
libinput_dispatch(d->libinput);
|
||||
}
|
||||
}
|
||||
litest_touch_move_extended(d, slot, x_to, y_to, axes);
|
||||
}
|
||||
|
||||
static int
|
||||
auto_assign_tablet_value(struct litest_device *d,
|
||||
const struct input_event *ev,
|
||||
|
|
@ -1784,7 +1962,13 @@ litest_hover_start(struct litest_device *d,
|
|||
double x,
|
||||
double y)
|
||||
{
|
||||
litest_slot_start(d, slot, x, y, NULL, 0);
|
||||
struct axis_replacement axes[] = {
|
||||
{ABS_MT_PRESSURE, 0 },
|
||||
{ABS_PRESSURE, 0 },
|
||||
{-1, -1 },
|
||||
};
|
||||
|
||||
litest_slot_start(d, slot, x, y, axes, 0);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -1823,7 +2007,13 @@ void
|
|||
litest_hover_move(struct litest_device *d, unsigned int slot,
|
||||
double x, double y)
|
||||
{
|
||||
litest_slot_move(d, slot, x, y, NULL, false);
|
||||
struct axis_replacement axes[] = {
|
||||
{ABS_MT_PRESSURE, 0 },
|
||||
{ABS_PRESSURE, 0 },
|
||||
{-1, -1 },
|
||||
};
|
||||
|
||||
litest_slot_move(d, slot, x, y, axes, false);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -3045,16 +3235,17 @@ litest_timeout_trackpoint(void)
|
|||
void
|
||||
litest_push_event_frame(struct litest_device *dev)
|
||||
{
|
||||
litest_assert(!dev->skip_ev_syn);
|
||||
dev->skip_ev_syn = true;
|
||||
litest_assert(dev->skip_ev_syn >= 0);
|
||||
dev->skip_ev_syn++;
|
||||
}
|
||||
|
||||
void
|
||||
litest_pop_event_frame(struct litest_device *dev)
|
||||
{
|
||||
litest_assert(dev->skip_ev_syn);
|
||||
dev->skip_ev_syn = false;
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
litest_assert(dev->skip_ev_syn > 0);
|
||||
dev->skip_ev_syn--;
|
||||
if (dev->skip_ev_syn == 0)
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
|||
|
|
@ -265,6 +265,23 @@ enum litest_device_feature {
|
|||
LITEST_SWITCH = 1 << 26,
|
||||
};
|
||||
|
||||
/* this is a semi-mt device, so we keep track of the touches that the tests
|
||||
* send and modify them so that the first touch is always slot 0 and sends
|
||||
* the top-left of the bounding box, the second is always slot 1 and sends
|
||||
* the bottom-right of the bounding box.
|
||||
* Lifting any of two fingers terminates slot 1
|
||||
*/
|
||||
struct litest_semi_mt {
|
||||
bool is_semi_mt;
|
||||
|
||||
int tracking_id;
|
||||
/* The actual touches requested by the test for the two slots
|
||||
* in the 0..100 range used by litest */
|
||||
struct {
|
||||
double x, y;
|
||||
} touches[2];
|
||||
};
|
||||
|
||||
struct litest_device {
|
||||
struct libevdev *evdev;
|
||||
struct libevdev_uinput *uinput;
|
||||
|
|
@ -274,7 +291,8 @@ struct litest_device {
|
|||
struct litest_device_interface *interface;
|
||||
|
||||
int ntouches_down;
|
||||
bool skip_ev_syn;
|
||||
int skip_ev_syn;
|
||||
struct litest_semi_mt semi_mt; /** only used for semi-mt device */
|
||||
|
||||
void *private; /* device-specific data */
|
||||
};
|
||||
|
|
@ -441,6 +459,14 @@ litest_touch_move_to(struct litest_device *d,
|
|||
double x_to, double y_to,
|
||||
int steps, int sleep_ms);
|
||||
|
||||
void
|
||||
litest_touch_move_to_extended(struct litest_device *d,
|
||||
unsigned int slot,
|
||||
double x_from, double y_from,
|
||||
double x_to, double y_to,
|
||||
struct axis_replacement *axes,
|
||||
int steps, int sleep_ms);
|
||||
|
||||
void
|
||||
litest_touch_move_two_touches(struct litest_device *d,
|
||||
double x0, double y0,
|
||||
|
|
@ -681,21 +707,6 @@ litest_push_event_frame(struct litest_device *dev);
|
|||
void
|
||||
litest_pop_event_frame(struct litest_device *dev);
|
||||
|
||||
/* this is a semi-mt device, so we keep track of the touches that the tests
|
||||
* send and modify them so that the first touch is always slot 0 and sends
|
||||
* the top-left of the bounding box, the second is always slot 1 and sends
|
||||
* the bottom-right of the bounding box.
|
||||
* Lifting any of two fingers terminates slot 1
|
||||
*/
|
||||
struct litest_semi_mt {
|
||||
int tracking_id;
|
||||
/* The actual touches requested by the test for the two slots
|
||||
* in the 0..100 range used by litest */
|
||||
struct {
|
||||
double x, y;
|
||||
} touches[2];
|
||||
};
|
||||
|
||||
void
|
||||
litest_semi_mt_touch_down(struct litest_device *d,
|
||||
struct litest_semi_mt *semi_mt,
|
||||
|
|
|
|||
|
|
@ -1686,6 +1686,7 @@ START_TEST(touchpad_semi_mt_hover_down)
|
|||
|
||||
litest_event(dev, EV_ABS, ABS_X, x + 100);
|
||||
litest_event(dev, EV_ABS, ABS_Y, y + 100);
|
||||
litest_event(dev, EV_ABS, ABS_PRESSURE, 50);
|
||||
litest_event(dev, EV_KEY, BTN_TOUCH, 1);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
libinput_dispatch(li);
|
||||
|
|
@ -1712,6 +1713,7 @@ START_TEST(touchpad_semi_mt_hover_down)
|
|||
|
||||
/* go back to hover */
|
||||
hover_continue(dev, 0, x, y);
|
||||
litest_event(dev, EV_ABS, ABS_PRESSURE, 0);
|
||||
litest_event(dev, EV_KEY, BTN_TOUCH, 0);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
|
||||
|
|
@ -1752,6 +1754,7 @@ START_TEST(touchpad_semi_mt_hover_down_hover_down)
|
|||
/* touch */
|
||||
litest_event(dev, EV_ABS, ABS_X, x + 100);
|
||||
litest_event(dev, EV_ABS, ABS_Y, y + 100);
|
||||
litest_event(dev, EV_ABS, ABS_PRESSURE, 50);
|
||||
litest_event(dev, EV_KEY, BTN_TOUCH, 1);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
libinput_dispatch(li);
|
||||
|
|
@ -1773,6 +1776,7 @@ START_TEST(touchpad_semi_mt_hover_down_hover_down)
|
|||
|
||||
/* go back to hover */
|
||||
hover_continue(dev, 0, x, y);
|
||||
litest_event(dev, EV_ABS, ABS_PRESSURE, 0);
|
||||
litest_event(dev, EV_KEY, BTN_TOUCH, 0);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
|
||||
|
|
@ -1796,7 +1800,10 @@ START_TEST(touchpad_semi_mt_hover_down_hover_down)
|
|||
litest_assert_empty_queue(li);
|
||||
|
||||
/* start a new touch to be sure */
|
||||
litest_push_event_frame(dev);
|
||||
litest_touch_down(dev, 0, 50, 50);
|
||||
litest_event(dev, EV_ABS, ABS_PRESSURE, 50);
|
||||
litest_pop_event_frame(dev);
|
||||
litest_touch_move_to(dev, 0, 50, 50, 70, 70, 10, 10);
|
||||
litest_touch_up(dev, 0);
|
||||
|
||||
|
|
@ -1845,6 +1852,7 @@ START_TEST(touchpad_semi_mt_hover_down_up)
|
|||
|
||||
litest_assert_empty_queue(li);
|
||||
|
||||
litest_event(dev, EV_ABS, ABS_PRESSURE, 50);
|
||||
litest_event(dev, EV_KEY, BTN_TOUCH, 1);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
libinput_dispatch(li);
|
||||
|
|
@ -1930,6 +1938,7 @@ START_TEST(touchpad_semi_mt_hover_2fg_1fg_down)
|
|||
/* two slots active, but BTN_TOOL_FINGER only */
|
||||
hover_start(dev, 0, x, y);
|
||||
hover_start(dev, 1, x + 500, y + 500);
|
||||
litest_event(dev, EV_ABS, ABS_PRESSURE, 50);
|
||||
litest_event(dev, EV_KEY, BTN_TOUCH, 1);
|
||||
litest_event(dev, EV_KEY, BTN_TOOL_FINGER, 1);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
|
|
@ -1948,6 +1957,7 @@ START_TEST(touchpad_semi_mt_hover_2fg_1fg_down)
|
|||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
}
|
||||
|
||||
litest_event(dev, EV_ABS, ABS_PRESSURE, 0);
|
||||
litest_event(dev, EV_KEY, BTN_TOUCH, 0);
|
||||
litest_event(dev, EV_KEY, BTN_TOOL_FINGER, 0);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
|
|
@ -1969,6 +1979,7 @@ START_TEST(touchpad_semi_mt_hover_2fg_up)
|
|||
litest_push_event_frame(dev);
|
||||
litest_touch_move(dev, 0, 72, 50);
|
||||
litest_touch_move(dev, 1, 52, 50);
|
||||
litest_event(dev, EV_ABS, ABS_PRESSURE, 0);
|
||||
litest_event(dev, EV_KEY, BTN_TOUCH, 0);
|
||||
litest_pop_event_frame(dev);
|
||||
|
||||
|
|
@ -2152,6 +2163,24 @@ START_TEST(touchpad_hover_2fg_1fg_down)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(touchpad_hover_1fg_tap)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
|
||||
litest_enable_tap(dev->libinput_device);
|
||||
|
||||
litest_drain_events(li);
|
||||
|
||||
litest_hover_start(dev, 0, 50, 50);
|
||||
litest_hover_end(dev, 0);
|
||||
|
||||
libinput_dispatch(li);
|
||||
litest_assert_empty_queue(li);
|
||||
|
||||
}
|
||||
END_TEST
|
||||
|
||||
static void
|
||||
assert_btnevent_from_device(struct litest_device *device,
|
||||
unsigned int button,
|
||||
|
|
@ -4669,6 +4698,222 @@ START_TEST(touchpad_disabled_double_mouse_one_suspended)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
static inline bool
|
||||
touchpad_has_pressure(struct litest_device *dev)
|
||||
{
|
||||
struct libevdev *evdev = dev->evdev;
|
||||
|
||||
if (libevdev_has_event_code(evdev, EV_ABS, ABS_MT_PRESSURE))
|
||||
return true;
|
||||
|
||||
if (libevdev_has_event_code(evdev, EV_ABS, ABS_PRESSURE) &&
|
||||
!libevdev_has_event_code(evdev, EV_ABS, ABS_MT_SLOT))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
START_TEST(touchpad_pressure)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
struct axis_replacement axes[] = {
|
||||
{ ABS_MT_PRESSURE, 1 },
|
||||
{ ABS_PRESSURE, 1 },
|
||||
{ -1, 0 }
|
||||
};
|
||||
double pressure; /* in percent */
|
||||
double threshold = 12.0;
|
||||
|
||||
if (!touchpad_has_pressure(dev))
|
||||
return;
|
||||
|
||||
litest_drain_events(li);
|
||||
|
||||
for (pressure = 1; pressure <= threshold + 1; pressure++) {
|
||||
litest_axis_set_value(axes, ABS_MT_PRESSURE, pressure);
|
||||
litest_axis_set_value(axes, ABS_PRESSURE, pressure);
|
||||
litest_touch_down_extended(dev, 0, 50, 50, axes);
|
||||
litest_touch_move_to_extended(dev, 0,
|
||||
50, 50,
|
||||
80, 80,
|
||||
axes, 10, 1);
|
||||
litest_touch_up(dev, 0);
|
||||
if (pressure < threshold)
|
||||
litest_assert_empty_queue(li);
|
||||
else
|
||||
litest_assert_only_typed_events(li,
|
||||
LIBINPUT_EVENT_POINTER_MOTION);
|
||||
|
||||
}
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(touchpad_pressure_2fg)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
struct axis_replacement axes[] = {
|
||||
{ ABS_MT_PRESSURE, 5 },
|
||||
{ ABS_PRESSURE, 5 },
|
||||
{ -1, 0 }
|
||||
};
|
||||
|
||||
if (!touchpad_has_pressure(dev))
|
||||
return;
|
||||
|
||||
litest_drain_events(li);
|
||||
|
||||
litest_touch_down(dev, 0, 30, 50);
|
||||
litest_touch_down_extended(dev, 1, 50, 50, axes);
|
||||
libinput_dispatch(li);
|
||||
litest_touch_move_to(dev, 0, 50, 50, 80, 80, 10, 1);
|
||||
libinput_dispatch(li);
|
||||
litest_assert_only_typed_events(li,
|
||||
LIBINPUT_EVENT_POINTER_MOTION);
|
||||
litest_touch_move_to_extended(dev, 1,
|
||||
50, 50,
|
||||
80, 80,
|
||||
axes, 10, 1);
|
||||
litest_assert_empty_queue(li);
|
||||
litest_touch_move_to(dev, 0, 80, 80, 20, 50, 10, 1);
|
||||
litest_touch_move_to_extended(dev, 1,
|
||||
80, 80,
|
||||
50, 50,
|
||||
axes, 10, 1);
|
||||
litest_assert_only_typed_events(li,
|
||||
LIBINPUT_EVENT_POINTER_MOTION);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(touchpad_pressure_2fg_st)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
struct axis_replacement axes[] = {
|
||||
{ ABS_MT_PRESSURE, 5 },
|
||||
{ ABS_PRESSURE, 5 },
|
||||
{ -1, 0 }
|
||||
};
|
||||
|
||||
if (!touchpad_has_pressure(dev))
|
||||
return;
|
||||
|
||||
/* This is a bit of a weird test. We expect two fingers to be down as
|
||||
* soon as doubletap is set, regardless of pressure. But we don't
|
||||
* have 2fg scrolling on st devices and 2 fingers down on a touchpad
|
||||
* without 2fg scrolling simply does not generate events. But that's
|
||||
* the same result as if the fingers were ignored because of
|
||||
* pressure and we cannot know the difference.
|
||||
* So this test only keeps your CPU warm, not much else.
|
||||
*/
|
||||
litest_drain_events(li);
|
||||
|
||||
litest_touch_down_extended(dev, 0, 50, 50, axes);
|
||||
libinput_dispatch(li);
|
||||
litest_event(dev, EV_KEY, BTN_TOOL_FINGER, 0);
|
||||
litest_event(dev, EV_KEY, BTN_TOOL_DOUBLETAP, 1);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
libinput_dispatch(li);
|
||||
litest_touch_move_to_extended(dev, 0,
|
||||
50, 50,
|
||||
80, 80,
|
||||
axes, 10, 1);
|
||||
litest_assert_empty_queue(li);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(touchpad_pressure_tap)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
struct axis_replacement axes[] = {
|
||||
{ ABS_MT_PRESSURE, 5 },
|
||||
{ ABS_PRESSURE, 5 },
|
||||
{ -1, 0 }
|
||||
};
|
||||
|
||||
if (!touchpad_has_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_touch_up(dev, 0);
|
||||
litest_assert_empty_queue(li);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(touchpad_pressure_tap_2fg)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
struct axis_replacement axes[] = {
|
||||
{ ABS_MT_PRESSURE, 5 },
|
||||
{ ABS_PRESSURE, 5 },
|
||||
{ -1, 0 }
|
||||
};
|
||||
|
||||
if (!touchpad_has_pressure(dev))
|
||||
return;
|
||||
|
||||
litest_enable_tap(dev->libinput_device);
|
||||
litest_drain_events(li);
|
||||
|
||||
/* tap but too light */
|
||||
litest_touch_down_extended(dev, 0, 40, 50, axes);
|
||||
litest_touch_down_extended(dev, 1, 50, 50, axes);
|
||||
libinput_dispatch(li);
|
||||
litest_touch_up(dev, 0);
|
||||
litest_touch_up(dev, 1);
|
||||
litest_assert_empty_queue(li);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(touchpad_pressure_tap_2fg_1fg_light)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
struct libinput_event *event;
|
||||
struct axis_replacement axes[] = {
|
||||
{ ABS_MT_PRESSURE, 5 },
|
||||
{ ABS_PRESSURE, 5 },
|
||||
{ -1, 0 }
|
||||
};
|
||||
|
||||
if (!touchpad_has_pressure(dev))
|
||||
return;
|
||||
|
||||
litest_enable_tap(dev->libinput_device);
|
||||
litest_drain_events(li);
|
||||
|
||||
/* double-tap with one finger too light */
|
||||
litest_touch_down(dev, 0, 40, 50);
|
||||
litest_touch_down_extended(dev, 1, 50, 50, axes);
|
||||
libinput_dispatch(li);
|
||||
litest_touch_up(dev, 0);
|
||||
litest_touch_up(dev, 1);
|
||||
libinput_dispatch(li);
|
||||
|
||||
event = libinput_get_event(li);
|
||||
litest_is_button_event(event,
|
||||
BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
libinput_event_destroy(event);
|
||||
|
||||
litest_timeout_tap();
|
||||
libinput_dispatch(li);
|
||||
|
||||
event = libinput_get_event(li);
|
||||
litest_is_button_event(event,
|
||||
BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
libinput_event_destroy(event);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
void
|
||||
litest_setup_tests_touchpad(void)
|
||||
{
|
||||
|
|
@ -4740,6 +4985,7 @@ litest_setup_tests_touchpad(void)
|
|||
litest_add("touchpad:hover", touchpad_hover_down_hover_down, LITEST_TOUCHPAD|LITEST_HOVER, LITEST_ANY);
|
||||
litest_add("touchpad:hover", touchpad_hover_2fg_noevent, LITEST_TOUCHPAD|LITEST_HOVER, LITEST_ANY);
|
||||
litest_add("touchpad:hover", touchpad_hover_2fg_1fg_down, LITEST_TOUCHPAD|LITEST_HOVER, LITEST_ANY);
|
||||
litest_add("touchpad:hover", touchpad_hover_1fg_tap, LITEST_TOUCHPAD|LITEST_HOVER, LITEST_ANY);
|
||||
|
||||
litest_add_for_device("touchpad:trackpoint", touchpad_trackpoint_buttons, LITEST_SYNAPTICS_TRACKPOINT_BUTTONS);
|
||||
litest_add_for_device("touchpad:trackpoint", touchpad_trackpoint_mb_scroll, LITEST_SYNAPTICS_TRACKPOINT_BUTTONS);
|
||||
|
|
@ -4808,4 +5054,11 @@ litest_setup_tests_touchpad(void)
|
|||
litest_add_for_device("touchpad:sendevents", touchpad_disabled_on_mouse_suspend_mouse, LITEST_SYNAPTICS_CLICKPAD_X220);
|
||||
litest_add_for_device("touchpad:sendevents", touchpad_disabled_double_mouse, LITEST_SYNAPTICS_CLICKPAD_X220);
|
||||
litest_add_for_device("touchpad:sendevents", touchpad_disabled_double_mouse_one_suspended, LITEST_SYNAPTICS_CLICKPAD_X220);
|
||||
|
||||
litest_add("touchpad:pressure", touchpad_pressure, LITEST_TOUCHPAD, LITEST_ANY);
|
||||
litest_add("touchpad:pressure", touchpad_pressure_2fg, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH);
|
||||
litest_add("touchpad:pressure", touchpad_pressure_2fg_st, LITEST_TOUCHPAD|LITEST_SINGLE_TOUCH, LITEST_ANY);
|
||||
litest_add("touchpad:pressure", touchpad_pressure_tap, LITEST_TOUCHPAD, LITEST_ANY);
|
||||
litest_add("touchpad:pressure", touchpad_pressure_tap_2fg, LITEST_TOUCHPAD, LITEST_ANY);
|
||||
litest_add("touchpad:pressure", touchpad_pressure_tap_2fg_1fg_light, LITEST_TOUCHPAD, LITEST_ANY);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue