mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2026-03-21 23:50:45 +01:00
Merge branch 'master' into tablet-support
Conflicts: test/litest.h
This commit is contained in:
commit
35b3992792
17 changed files with 1631 additions and 260 deletions
|
|
@ -66,6 +66,12 @@ The Xorg synaptics driver uses 30% of the touchpad dimensions as threshold,
|
|||
libinput does not have this restriction. If two fingers are on the pad
|
||||
while clicking, that is a two-finger click.
|
||||
|
||||
Clickfinger configuration can be enabled through the
|
||||
libinput_device_config_click_set_method() call. If clickfingers are
|
||||
enabled on a touchpad with top software buttons, the top area will keep
|
||||
acting as softbuttons for use with the trackpoint. Clickfingers will be used
|
||||
everywhere else on the touchpad.
|
||||
|
||||
@section special_clickpads Special Clickpads
|
||||
|
||||
The Lenovo *40 series laptops have a clickpad that provides two software button sections, one at
|
||||
|
|
|
|||
|
|
@ -494,10 +494,9 @@ tp_release_all_buttons(struct tp_dispatch *tp,
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
tp_init_softbuttons(struct tp_dispatch *tp,
|
||||
struct evdev_device *device,
|
||||
double topbutton_size_mult)
|
||||
struct evdev_device *device)
|
||||
{
|
||||
int width, height;
|
||||
const struct input_absinfo *absinfo_x, *absinfo_y;
|
||||
|
|
@ -523,6 +522,26 @@ tp_init_softbuttons(struct tp_dispatch *tp,
|
|||
}
|
||||
|
||||
tp->buttons.bottom_area.rightbutton_left_edge = width/2 + xoffset;
|
||||
}
|
||||
|
||||
void
|
||||
tp_init_top_softbuttons(struct tp_dispatch *tp,
|
||||
struct evdev_device *device,
|
||||
double topbutton_size_mult)
|
||||
{
|
||||
int width, height;
|
||||
const struct input_absinfo *absinfo_x, *absinfo_y;
|
||||
int xoffset, yoffset;
|
||||
int yres;
|
||||
|
||||
absinfo_x = device->abs.absinfo_x;
|
||||
absinfo_y = device->abs.absinfo_y;
|
||||
|
||||
xoffset = absinfo_x->minimum,
|
||||
yoffset = absinfo_y->minimum;
|
||||
yres = absinfo_y->resolution;
|
||||
width = abs(absinfo_x->maximum - absinfo_x->minimum);
|
||||
height = abs(absinfo_y->maximum - absinfo_y->minimum);
|
||||
|
||||
if (tp->buttons.has_topbuttons) {
|
||||
/* T440s has the top button line 5mm from the top, event
|
||||
|
|
@ -545,6 +564,89 @@ tp_init_softbuttons(struct tp_dispatch *tp,
|
|||
}
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
tp_button_config_click_get_methods(struct libinput_device *device)
|
||||
{
|
||||
struct evdev_device *evdev = (struct evdev_device*)device;
|
||||
struct tp_dispatch *tp = (struct tp_dispatch*)evdev->dispatch;
|
||||
uint32_t methods = LIBINPUT_CONFIG_CLICK_METHOD_NONE;
|
||||
|
||||
if (tp->buttons.is_clickpad) {
|
||||
methods |= LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS;
|
||||
if (tp->has_mt)
|
||||
methods |= LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER;
|
||||
}
|
||||
|
||||
return methods;
|
||||
}
|
||||
|
||||
static void
|
||||
tp_switch_click_method(struct tp_dispatch *tp)
|
||||
{
|
||||
/*
|
||||
* All we need to do when switching click methods is to change the
|
||||
* bottom_area.top_edge so that when in clickfinger mode the bottom
|
||||
* touchpad area is not dead wrt finger movement starting there.
|
||||
*
|
||||
* We do not need to take any state into account, fingers which are
|
||||
* already down will simply keep the state / area they have assigned
|
||||
* until they are released, and the post_button_events path is state
|
||||
* agnostic.
|
||||
*/
|
||||
|
||||
switch (tp->buttons.click_method) {
|
||||
case LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS:
|
||||
tp_init_softbuttons(tp, tp->device);
|
||||
break;
|
||||
case LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER:
|
||||
case LIBINPUT_CONFIG_CLICK_METHOD_NONE:
|
||||
tp->buttons.bottom_area.top_edge = INT_MAX;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static enum libinput_config_status
|
||||
tp_button_config_click_set_method(struct libinput_device *device,
|
||||
enum libinput_config_click_method method)
|
||||
{
|
||||
struct evdev_device *evdev = (struct evdev_device*)device;
|
||||
struct tp_dispatch *tp = (struct tp_dispatch*)evdev->dispatch;
|
||||
|
||||
tp->buttons.click_method = method;
|
||||
tp_switch_click_method(tp);
|
||||
|
||||
return LIBINPUT_CONFIG_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static enum libinput_config_click_method
|
||||
tp_button_config_click_get_method(struct libinput_device *device)
|
||||
{
|
||||
struct evdev_device *evdev = (struct evdev_device*)device;
|
||||
struct tp_dispatch *tp = (struct tp_dispatch*)evdev->dispatch;
|
||||
|
||||
return tp->buttons.click_method;
|
||||
}
|
||||
|
||||
static enum libinput_config_click_method
|
||||
tp_click_get_default_method(struct tp_dispatch *tp)
|
||||
{
|
||||
if (!tp->buttons.is_clickpad)
|
||||
return LIBINPUT_CONFIG_CLICK_METHOD_NONE;
|
||||
else if (libevdev_get_id_vendor(tp->device->evdev) == VENDOR_ID_APPLE)
|
||||
return LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER;
|
||||
else
|
||||
return LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS;
|
||||
}
|
||||
|
||||
static enum libinput_config_click_method
|
||||
tp_button_config_click_get_default_method(struct libinput_device *device)
|
||||
{
|
||||
struct evdev_device *evdev = (struct evdev_device*)device;
|
||||
struct tp_dispatch *tp = (struct tp_dispatch*)evdev->dispatch;
|
||||
|
||||
return tp_click_get_default_method(tp);
|
||||
}
|
||||
|
||||
int
|
||||
tp_init_buttons(struct tp_dispatch *tp,
|
||||
struct evdev_device *device)
|
||||
|
|
@ -582,15 +684,16 @@ tp_init_buttons(struct tp_dispatch *tp,
|
|||
|
||||
tp->buttons.motion_dist = diagonal * DEFAULT_BUTTON_MOTION_THRESHOLD;
|
||||
|
||||
if (libevdev_get_id_vendor(device->evdev) == VENDOR_ID_APPLE)
|
||||
tp->buttons.use_clickfinger = true;
|
||||
tp->buttons.config_method.get_methods = tp_button_config_click_get_methods;
|
||||
tp->buttons.config_method.set_method = tp_button_config_click_set_method;
|
||||
tp->buttons.config_method.get_method = tp_button_config_click_get_method;
|
||||
tp->buttons.config_method.get_default_method = tp_button_config_click_get_default_method;
|
||||
tp->device->base.config.click_method = &tp->buttons.config_method;
|
||||
|
||||
if (tp->buttons.is_clickpad && !tp->buttons.use_clickfinger) {
|
||||
tp_init_softbuttons(tp, device, 1.0);
|
||||
} else {
|
||||
tp->buttons.bottom_area.top_edge = INT_MAX;
|
||||
tp->buttons.top_area.bottom_edge = INT_MIN;
|
||||
}
|
||||
tp->buttons.click_method = tp_click_get_default_method(tp);
|
||||
tp_switch_click_method(tp);
|
||||
|
||||
tp_init_top_softbuttons(tp, device, 1.0);
|
||||
|
||||
tp_for_each_touch(tp, t) {
|
||||
t->button.state = BUTTON_STATE_NONE;
|
||||
|
|
@ -611,43 +714,6 @@ tp_remove_buttons(struct tp_dispatch *tp)
|
|||
libinput_timer_cancel(&t->button.timer);
|
||||
}
|
||||
|
||||
static int
|
||||
tp_post_clickfinger_buttons(struct tp_dispatch *tp, uint64_t time)
|
||||
{
|
||||
uint32_t current, old, button;
|
||||
enum libinput_button_state state;
|
||||
|
||||
current = tp->buttons.state;
|
||||
old = tp->buttons.old_state;
|
||||
|
||||
if (current == old)
|
||||
return 0;
|
||||
|
||||
if (current) {
|
||||
switch (tp->nfingers_down) {
|
||||
case 1: button = BTN_LEFT; break;
|
||||
case 2: button = BTN_RIGHT; break;
|
||||
case 3: button = BTN_MIDDLE; break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
tp->buttons.active = button;
|
||||
state = LIBINPUT_BUTTON_STATE_PRESSED;
|
||||
} else {
|
||||
button = tp->buttons.active;
|
||||
tp->buttons.active = 0;
|
||||
state = LIBINPUT_BUTTON_STATE_RELEASED;
|
||||
}
|
||||
|
||||
if (button) {
|
||||
evdev_pointer_notify_button(tp->device,
|
||||
time,
|
||||
button,
|
||||
state);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
tp_post_physical_buttons(struct tp_dispatch *tp, uint64_t time)
|
||||
{
|
||||
|
|
@ -683,12 +749,12 @@ tp_post_physical_buttons(struct tp_dispatch *tp, uint64_t time)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
tp_notify_softbutton(struct tp_dispatch *tp,
|
||||
uint64_t time,
|
||||
uint32_t button,
|
||||
uint32_t is_topbutton,
|
||||
enum libinput_button_state state)
|
||||
static int
|
||||
tp_notify_clickpadbutton(struct tp_dispatch *tp,
|
||||
uint64_t time,
|
||||
uint32_t button,
|
||||
uint32_t is_topbutton,
|
||||
enum libinput_button_state state)
|
||||
{
|
||||
/* If we've a trackpoint, send top buttons through the trackpoint */
|
||||
if (is_topbutton && tp->buttons.trackpoint) {
|
||||
|
|
@ -702,18 +768,38 @@ tp_notify_softbutton(struct tp_dispatch *tp,
|
|||
event.value = (state == LIBINPUT_BUTTON_STATE_PRESSED) ? 1 : 0;
|
||||
dispatch->interface->process(dispatch, tp->buttons.trackpoint,
|
||||
&event, time);
|
||||
return;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Ignore button events not for the trackpoint while suspended */
|
||||
if (tp->device->suspended)
|
||||
return;
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* If the user has requested clickfinger replace the button chosen
|
||||
* by the softbutton code with one based on the number of fingers.
|
||||
*/
|
||||
if (tp->buttons.click_method == LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER &&
|
||||
state == LIBINPUT_BUTTON_STATE_PRESSED) {
|
||||
switch (tp->nfingers_down) {
|
||||
case 1: button = BTN_LEFT; break;
|
||||
case 2: button = BTN_RIGHT; break;
|
||||
case 3: button = BTN_MIDDLE; break;
|
||||
default:
|
||||
button = 0;
|
||||
}
|
||||
tp->buttons.active = button;
|
||||
|
||||
if (!button)
|
||||
return 0;
|
||||
}
|
||||
|
||||
evdev_pointer_notify_button(tp->device, time, button, state);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
tp_post_softbutton_buttons(struct tp_dispatch *tp, uint64_t time)
|
||||
tp_post_clickpadbutton_buttons(struct tp_dispatch *tp, uint64_t time)
|
||||
{
|
||||
uint32_t current, old, button, is_top;
|
||||
enum libinput_button_state state;
|
||||
|
|
@ -783,22 +869,18 @@ tp_post_softbutton_buttons(struct tp_dispatch *tp, uint64_t time)
|
|||
tp->buttons.click_pending = false;
|
||||
|
||||
if (button)
|
||||
tp_notify_softbutton(tp, time, button, is_top, state);
|
||||
return tp_notify_clickpadbutton(tp, time, button, is_top, state);
|
||||
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
tp_post_button_events(struct tp_dispatch *tp, uint64_t time)
|
||||
{
|
||||
if (tp->buttons.is_clickpad) {
|
||||
if (tp->buttons.use_clickfinger)
|
||||
return tp_post_clickfinger_buttons(tp, time);
|
||||
else
|
||||
return tp_post_softbutton_buttons(tp, time);
|
||||
}
|
||||
|
||||
return tp_post_physical_buttons(tp, time);
|
||||
if (tp->buttons.is_clickpad)
|
||||
return tp_post_clickpadbutton_buttons(tp, time);
|
||||
else
|
||||
return tp_post_physical_buttons(tp, time);
|
||||
}
|
||||
|
||||
int
|
||||
|
|
|
|||
|
|
@ -294,6 +294,7 @@ tp_edge_scroll_handle_state(struct tp_dispatch *tp, uint64_t time)
|
|||
|
||||
switch (t->state) {
|
||||
case TOUCH_NONE:
|
||||
case TOUCH_HOVERING:
|
||||
break;
|
||||
case TOUCH_BEGIN:
|
||||
tp_edge_scroll_handle_event(tp, t, SCROLL_EVENT_TOUCH);
|
||||
|
|
|
|||
|
|
@ -135,27 +135,96 @@ tp_get_touch(struct tp_dispatch *tp, unsigned int slot)
|
|||
return &tp->touches[slot];
|
||||
}
|
||||
|
||||
static inline void
|
||||
tp_begin_touch(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time)
|
||||
static inline unsigned int
|
||||
tp_fake_finger_count(struct tp_dispatch *tp)
|
||||
{
|
||||
if (t->state == TOUCH_BEGIN || t->state == TOUCH_UPDATE)
|
||||
/* don't count BTN_TOUCH */
|
||||
return ffs(tp->fake_touches >> 1);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
tp_fake_finger_is_touching(struct tp_dispatch *tp)
|
||||
{
|
||||
return tp->fake_touches & 0x1;
|
||||
}
|
||||
|
||||
static inline void
|
||||
tp_fake_finger_set(struct tp_dispatch *tp,
|
||||
unsigned int code,
|
||||
bool is_press)
|
||||
{
|
||||
unsigned int shift;
|
||||
|
||||
switch (code) {
|
||||
case BTN_TOUCH:
|
||||
shift = 0;
|
||||
break;
|
||||
case BTN_TOOL_FINGER:
|
||||
shift = 1;
|
||||
break;
|
||||
case BTN_TOOL_DOUBLETAP:
|
||||
case BTN_TOOL_TRIPLETAP:
|
||||
case BTN_TOOL_QUADTAP:
|
||||
shift = code - BTN_TOOL_DOUBLETAP + 2;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_press)
|
||||
tp->fake_touches |= 1 << shift;
|
||||
else
|
||||
tp->fake_touches &= ~(0x1 << shift);
|
||||
}
|
||||
|
||||
static inline void
|
||||
tp_new_touch(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time)
|
||||
{
|
||||
if (t->state == TOUCH_BEGIN ||
|
||||
t->state == TOUCH_UPDATE ||
|
||||
t->state == TOUCH_HOVERING)
|
||||
return;
|
||||
|
||||
/* we begin the touch as hovering because until BTN_TOUCH happens we
|
||||
* don't know if it's a touch down or not. And BTN_TOUCH may happen
|
||||
* after ABS_MT_TRACKING_ID */
|
||||
tp_motion_history_reset(t);
|
||||
t->dirty = true;
|
||||
t->state = TOUCH_BEGIN;
|
||||
t->has_ended = false;
|
||||
t->state = TOUCH_HOVERING;
|
||||
t->pinned.is_pinned = false;
|
||||
t->millis = time;
|
||||
tp->nfingers_down++;
|
||||
assert(tp->nfingers_down >= 1);
|
||||
tp->queued |= TOUCHPAD_EVENT_MOTION;
|
||||
}
|
||||
|
||||
static inline void
|
||||
tp_begin_touch(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time)
|
||||
{
|
||||
t->dirty = true;
|
||||
t->state = TOUCH_BEGIN;
|
||||
t->millis = time;
|
||||
tp->nfingers_down++;
|
||||
assert(tp->nfingers_down >= 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* End a touch, even if the touch sequence is still active.
|
||||
*/
|
||||
static inline void
|
||||
tp_end_touch(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time)
|
||||
{
|
||||
if (t->state == TOUCH_END || t->state == TOUCH_NONE)
|
||||
switch (t->state) {
|
||||
case TOUCH_HOVERING:
|
||||
t->state = TOUCH_NONE;
|
||||
/* fallthough */
|
||||
case TOUCH_NONE:
|
||||
case TOUCH_END:
|
||||
return;
|
||||
case TOUCH_BEGIN:
|
||||
case TOUCH_UPDATE:
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
t->dirty = true;
|
||||
t->is_pointer = false;
|
||||
|
|
@ -168,6 +237,16 @@ tp_end_touch(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time)
|
|||
tp->queued |= TOUCHPAD_EVENT_MOTION;
|
||||
}
|
||||
|
||||
/**
|
||||
* End the touch sequence on ABS_MT_TRACKING_ID -1 or when the BTN_TOOL_* 0 is received.
|
||||
*/
|
||||
static inline void
|
||||
tp_end_sequence(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time)
|
||||
{
|
||||
t->has_ended = true;
|
||||
tp_end_touch(tp, t, time);
|
||||
}
|
||||
|
||||
static double
|
||||
tp_estimate_delta(int x0, int x1, int x2, int x3)
|
||||
{
|
||||
|
|
@ -218,9 +297,9 @@ tp_process_absolute(struct tp_dispatch *tp,
|
|||
break;
|
||||
case ABS_MT_TRACKING_ID:
|
||||
if (e->value != -1)
|
||||
tp_begin_touch(tp, t, time);
|
||||
tp_new_touch(tp, t, time);
|
||||
else
|
||||
tp_end_touch(tp, t, time);
|
||||
tp_end_sequence(tp, t, time);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -253,41 +332,21 @@ tp_process_fake_touch(struct tp_dispatch *tp,
|
|||
uint64_t time)
|
||||
{
|
||||
struct tp_touch *t;
|
||||
unsigned int fake_touches;
|
||||
unsigned int nfake_touches;
|
||||
unsigned int i, start;
|
||||
unsigned int shift;
|
||||
|
||||
if (e->code != BTN_TOUCH &&
|
||||
(e->code < BTN_TOOL_DOUBLETAP || e->code > BTN_TOOL_QUADTAP))
|
||||
return;
|
||||
tp_fake_finger_set(tp, e->code, e->value != 0);
|
||||
|
||||
shift = e->code == BTN_TOUCH ? 0 : (e->code - BTN_TOOL_DOUBLETAP + 1);
|
||||
nfake_touches = tp_fake_finger_count(tp);
|
||||
|
||||
if (e->value)
|
||||
tp->fake_touches |= 1 << shift;
|
||||
else
|
||||
tp->fake_touches &= ~(0x1 << shift);
|
||||
|
||||
fake_touches = tp->fake_touches;
|
||||
nfake_touches = 0;
|
||||
while (fake_touches) {
|
||||
nfake_touches++;
|
||||
fake_touches >>= 1;
|
||||
}
|
||||
|
||||
/* For single touch tps we use BTN_TOUCH for begin / end of touch 0 */
|
||||
start = tp->has_mt ? tp->real_touches : 0;
|
||||
for (i = start; i < tp->ntouches; i++) {
|
||||
t = tp_get_touch(tp, i);
|
||||
if (i < nfake_touches)
|
||||
tp_begin_touch(tp, t, time);
|
||||
tp_new_touch(tp, t, time);
|
||||
else
|
||||
tp_end_touch(tp, t, time);
|
||||
tp_end_sequence(tp, t, time);
|
||||
}
|
||||
|
||||
/* On mt the actual touch info may arrive after BTN_TOOL_FOO */
|
||||
assert(tp->has_mt || tp->nfingers_down == nfake_touches);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -302,6 +361,7 @@ tp_process_key(struct tp_dispatch *tp,
|
|||
tp_process_button(tp, e, time);
|
||||
break;
|
||||
case BTN_TOUCH:
|
||||
case BTN_TOOL_FINGER:
|
||||
case BTN_TOOL_DOUBLETAP:
|
||||
case BTN_TOOL_TRIPLETAP:
|
||||
case BTN_TOOL_QUADTAP:
|
||||
|
|
@ -325,7 +385,12 @@ tp_unpin_finger(struct tp_dispatch *tp, struct tp_touch *t)
|
|||
tp->buttons.motion_dist * tp->buttons.motion_dist) {
|
||||
t->pinned.is_pinned = false;
|
||||
tp_set_pointer(tp, t);
|
||||
return;
|
||||
}
|
||||
|
||||
/* The finger may slowly drift, adjust the center */
|
||||
t->pinned.center_x = t->x + t->pinned.center_x / 2;
|
||||
t->pinned.center_y = t->y + t->pinned.center_y / 2;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -554,6 +619,61 @@ tp_remove_scroll(struct tp_dispatch *tp)
|
|||
tp_remove_edge_scroll(tp);
|
||||
}
|
||||
|
||||
static void
|
||||
tp_unhover_touches(struct tp_dispatch *tp, uint64_t time)
|
||||
{
|
||||
struct tp_touch *t;
|
||||
unsigned int nfake_touches;
|
||||
int i;
|
||||
|
||||
if (!tp->fake_touches && !tp->nfingers_down)
|
||||
return;
|
||||
|
||||
nfake_touches = tp_fake_finger_count(tp);
|
||||
if (tp->nfingers_down == nfake_touches &&
|
||||
((tp->nfingers_down == 0 && !tp_fake_finger_is_touching(tp)) ||
|
||||
(tp->nfingers_down > 0 && tp_fake_finger_is_touching(tp))))
|
||||
return;
|
||||
|
||||
/* if BTN_TOUCH is set and we have less fingers down than fake
|
||||
* touches, switch each hovering touch to BEGIN
|
||||
* until nfingers_down matches nfake_touches
|
||||
*/
|
||||
if (tp_fake_finger_is_touching(tp) &&
|
||||
tp->nfingers_down < nfake_touches) {
|
||||
for (i = 0; i < (int)tp->ntouches; i++) {
|
||||
t = tp_get_touch(tp, i);
|
||||
|
||||
if (t->state == TOUCH_HOVERING) {
|
||||
tp_begin_touch(tp, t, time);
|
||||
|
||||
if (tp->nfingers_down >= nfake_touches)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* if BTN_TOUCH is unset end all touches, we're hovering now. If we
|
||||
* have too many touches also end some of them. This is done in
|
||||
* reverse order.
|
||||
*/
|
||||
if (tp->nfingers_down > nfake_touches ||
|
||||
!tp_fake_finger_is_touching(tp)) {
|
||||
for (i = tp->ntouches - 1; i >= 0; i--) {
|
||||
t = tp_get_touch(tp, i);
|
||||
|
||||
if (t->state == TOUCH_HOVERING)
|
||||
continue;
|
||||
|
||||
tp_end_touch(tp, t, time);
|
||||
|
||||
if (tp_fake_finger_is_touching(tp) &&
|
||||
tp->nfingers_down == nfake_touches)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
tp_process_state(struct tp_dispatch *tp, uint64_t time)
|
||||
{
|
||||
|
|
@ -561,6 +681,8 @@ tp_process_state(struct tp_dispatch *tp, uint64_t time)
|
|||
struct tp_touch *first = tp_get_touch(tp, 0);
|
||||
unsigned int i;
|
||||
|
||||
tp_unhover_touches(tp, time);
|
||||
|
||||
for (i = 0; i < tp->ntouches; i++) {
|
||||
t = tp_get_touch(tp, i);
|
||||
|
||||
|
|
@ -606,13 +728,18 @@ tp_post_process_state(struct tp_dispatch *tp, uint64_t time)
|
|||
struct tp_touch *t;
|
||||
|
||||
tp_for_each_touch(tp, t) {
|
||||
|
||||
if (!t->dirty)
|
||||
continue;
|
||||
|
||||
if (t->state == TOUCH_END)
|
||||
t->state = TOUCH_NONE;
|
||||
else if (t->state == TOUCH_BEGIN)
|
||||
if (t->state == TOUCH_END) {
|
||||
if (t->has_ended)
|
||||
t->state = TOUCH_NONE;
|
||||
else
|
||||
t->state = TOUCH_HOVERING;
|
||||
} else if (t->state == TOUCH_BEGIN) {
|
||||
t->state = TOUCH_UPDATE;
|
||||
}
|
||||
|
||||
t->dirty = false;
|
||||
}
|
||||
|
|
@ -793,7 +920,7 @@ tp_clear_state(struct tp_dispatch *tp)
|
|||
tp_release_all_taps(tp, now);
|
||||
|
||||
tp_for_each_touch(tp, t) {
|
||||
tp_end_touch(tp, t, now);
|
||||
tp_end_sequence(tp, t, now);
|
||||
}
|
||||
|
||||
tp_handle_state(tp, now);
|
||||
|
|
@ -811,7 +938,7 @@ tp_suspend(struct tp_dispatch *tp, struct evdev_device *device)
|
|||
if (tp->buttons.has_topbuttons) {
|
||||
evdev_notify_suspended_device(device);
|
||||
/* Enlarge topbutton area while suspended */
|
||||
tp_init_softbuttons(tp, device, 1.5);
|
||||
tp_init_top_softbuttons(tp, device, 1.5);
|
||||
} else {
|
||||
evdev_device_suspend(device);
|
||||
}
|
||||
|
|
@ -824,7 +951,7 @@ tp_resume(struct tp_dispatch *tp, struct evdev_device *device)
|
|||
/* tap state-machine is offline while suspended, reset state */
|
||||
tp_clear_state(tp);
|
||||
/* restore original topbutton area size */
|
||||
tp_init_softbuttons(tp, device, 1.0);
|
||||
tp_init_top_softbuttons(tp, device, 1.0);
|
||||
evdev_notify_resumed_device(device);
|
||||
} else {
|
||||
evdev_device_resume(device);
|
||||
|
|
@ -954,6 +1081,7 @@ tp_init_touch(struct tp_dispatch *tp,
|
|||
struct tp_touch *t)
|
||||
{
|
||||
t->tp = tp;
|
||||
t->has_ended = true;
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@ enum touchpad_model {
|
|||
|
||||
enum touch_state {
|
||||
TOUCH_NONE = 0,
|
||||
TOUCH_HOVERING,
|
||||
TOUCH_BEGIN,
|
||||
TOUCH_UPDATE,
|
||||
TOUCH_END
|
||||
|
|
@ -130,6 +131,7 @@ struct tp_motion {
|
|||
struct tp_touch {
|
||||
struct tp_dispatch *tp;
|
||||
enum touch_state state;
|
||||
bool has_ended; /* TRACKING_ID == -1 */
|
||||
bool dirty;
|
||||
bool is_pointer; /* the pointer-controlling touch */
|
||||
int32_t x;
|
||||
|
|
@ -197,7 +199,12 @@ struct tp_dispatch {
|
|||
unsigned int real_touches; /* number of slots */
|
||||
unsigned int ntouches; /* no slots inc. fakes */
|
||||
struct tp_touch *touches; /* len == ntouches */
|
||||
unsigned int fake_touches; /* fake touch mask */
|
||||
/* bit 0: BTN_TOUCH
|
||||
* bit 1: BTN_TOOL_FINGER
|
||||
* bit 2: BTN_TOOL_DOUBLETAP
|
||||
* ...
|
||||
*/
|
||||
unsigned int fake_touches;
|
||||
|
||||
struct {
|
||||
int32_t margin_x;
|
||||
|
|
@ -236,7 +243,10 @@ struct tp_dispatch {
|
|||
} top_area;
|
||||
|
||||
struct evdev_device *trackpoint;
|
||||
} buttons; /* physical buttons */
|
||||
|
||||
enum libinput_config_click_method click_method;
|
||||
struct libinput_device_config_click_method config_method;
|
||||
} buttons;
|
||||
|
||||
struct {
|
||||
struct libinput_device_config_scroll_method config_method;
|
||||
|
|
@ -299,9 +309,9 @@ int
|
|||
tp_init_buttons(struct tp_dispatch *tp, struct evdev_device *device);
|
||||
|
||||
void
|
||||
tp_init_softbuttons(struct tp_dispatch *tp,
|
||||
struct evdev_device *device,
|
||||
double topbutton_size_mult);
|
||||
tp_init_top_softbuttons(struct tp_dispatch *tp,
|
||||
struct evdev_device *device,
|
||||
double topbutton_size_mult);
|
||||
|
||||
void
|
||||
tp_remove_buttons(struct tp_dispatch *tp);
|
||||
|
|
|
|||
|
|
@ -150,6 +150,14 @@ struct libinput_device_config_scroll_method {
|
|||
uint32_t (*get_default_button)(struct libinput_device *device);
|
||||
};
|
||||
|
||||
struct libinput_device_config_click_method {
|
||||
uint32_t (*get_methods)(struct libinput_device *device);
|
||||
enum libinput_config_status (*set_method)(struct libinput_device *device,
|
||||
enum libinput_config_click_method method);
|
||||
enum libinput_config_click_method (*get_method)(struct libinput_device *device);
|
||||
enum libinput_config_click_method (*get_default_method)(struct libinput_device *device);
|
||||
};
|
||||
|
||||
struct libinput_device_config {
|
||||
struct libinput_device_config_tap *tap;
|
||||
struct libinput_device_config_calibration *calibration;
|
||||
|
|
@ -158,6 +166,7 @@ struct libinput_device_config {
|
|||
struct libinput_device_config_natural_scroll *natural_scroll;
|
||||
struct libinput_device_config_left_handed *left_handed;
|
||||
struct libinput_device_config_scroll_method *scroll_method;
|
||||
struct libinput_device_config_click_method *click_method;
|
||||
};
|
||||
|
||||
struct libinput_device {
|
||||
|
|
|
|||
|
|
@ -1961,6 +1961,56 @@ libinput_device_config_left_handed_get_default(struct libinput_device *device)
|
|||
return device->config.left_handed->get_default(device);
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT uint32_t
|
||||
libinput_device_config_click_get_methods(struct libinput_device *device)
|
||||
{
|
||||
if (device->config.click_method)
|
||||
return device->config.click_method->get_methods(device);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT enum libinput_config_status
|
||||
libinput_device_config_click_set_method(struct libinput_device *device,
|
||||
enum libinput_config_click_method method)
|
||||
{
|
||||
if ((libinput_device_config_click_get_methods(device) & method) != method)
|
||||
return LIBINPUT_CONFIG_STATUS_UNSUPPORTED;
|
||||
|
||||
/* Check method is a single valid method */
|
||||
switch (method) {
|
||||
case LIBINPUT_CONFIG_CLICK_METHOD_NONE:
|
||||
case LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS:
|
||||
case LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER:
|
||||
break;
|
||||
default:
|
||||
return LIBINPUT_CONFIG_STATUS_INVALID;
|
||||
}
|
||||
|
||||
if (device->config.click_method)
|
||||
return device->config.click_method->set_method(device, method);
|
||||
else /* method must be _NONE to get here */
|
||||
return LIBINPUT_CONFIG_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT enum libinput_config_click_method
|
||||
libinput_device_config_click_get_method(struct libinput_device *device)
|
||||
{
|
||||
if (device->config.click_method)
|
||||
return device->config.click_method->get_method(device);
|
||||
else
|
||||
return LIBINPUT_CONFIG_CLICK_METHOD_NONE;
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT enum libinput_config_click_method
|
||||
libinput_device_config_click_get_default_method(struct libinput_device *device)
|
||||
{
|
||||
if (device->config.click_method)
|
||||
return device->config.click_method->get_default_method(device);
|
||||
else
|
||||
return LIBINPUT_CONFIG_CLICK_METHOD_NONE;
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT uint32_t
|
||||
libinput_device_config_scroll_get_methods(struct libinput_device *device)
|
||||
{
|
||||
|
|
|
|||
102
src/libinput.h
102
src/libinput.h
|
|
@ -2498,6 +2498,108 @@ libinput_device_config_left_handed_get(struct libinput_device *device);
|
|||
int
|
||||
libinput_device_config_left_handed_get_default(struct libinput_device *device);
|
||||
|
||||
/**
|
||||
* @ingroup config
|
||||
*
|
||||
* The click method defines when to generate software-emulated
|
||||
* buttons, usually on a device that does not have a specific physical
|
||||
* button available.
|
||||
*/
|
||||
enum libinput_config_click_method {
|
||||
/**
|
||||
* Do not send software-emulated button events. This has no effect
|
||||
* on physical button generations.
|
||||
*/
|
||||
LIBINPUT_CONFIG_CLICK_METHOD_NONE = 0,
|
||||
/**
|
||||
* Use software-button areas (see @ref clickfinger) to generate
|
||||
* button events.
|
||||
*/
|
||||
LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS = (1 << 0),
|
||||
/**
|
||||
* The number of fingers decides which button press to generate.
|
||||
*/
|
||||
LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER = (1 << 1),
|
||||
};
|
||||
|
||||
/**
|
||||
* @ingroup config
|
||||
*
|
||||
* Check which button click methods a device supports. The button click
|
||||
* method defines when to generate software-emulated buttons, usually on a
|
||||
* device that does not have a specific physical button available.
|
||||
*
|
||||
* @param device The device to configure
|
||||
*
|
||||
* @return A bitmask of possible methods.
|
||||
*
|
||||
* @see libinput_device_config_click_get_methods
|
||||
* @see libinput_device_config_click_set_method
|
||||
* @see libinput_device_config_click_get_method
|
||||
*/
|
||||
uint32_t
|
||||
libinput_device_config_click_get_methods(struct libinput_device *device);
|
||||
|
||||
/**
|
||||
* @ingroup config
|
||||
*
|
||||
* Set the button click method for this device. The button click
|
||||
* method defines when to generate software-emulated buttons, usually on a
|
||||
* device that does not have a specific physical button available.
|
||||
*
|
||||
* @note The selected click method may not take effect immediately. The
|
||||
* device may require changing to a neutral state first before activating
|
||||
* the new method.
|
||||
*
|
||||
* @param device The device to configure
|
||||
* @param method The button click method
|
||||
*
|
||||
* @return A config status code
|
||||
*
|
||||
* @see libinput_device_config_click_get_methods
|
||||
* @see libinput_device_config_click_get_method
|
||||
* @see libinput_device_config_click_get_default_method
|
||||
*/
|
||||
enum libinput_config_status
|
||||
libinput_device_config_click_set_method(struct libinput_device *device,
|
||||
enum libinput_config_click_method method);
|
||||
/**
|
||||
* @ingroup config
|
||||
*
|
||||
* Get the button click method for this device. The button click
|
||||
* method defines when to generate software-emulated buttons, usually on a
|
||||
* device that does not have a specific physical button available.
|
||||
*
|
||||
* @param device The device to configure
|
||||
*
|
||||
* @return The current button click method for this device
|
||||
*
|
||||
* @see libinput_device_config_click_get_methods
|
||||
* @see libinput_device_config_click_set_method
|
||||
* @see libinput_device_config_click_get_default_method
|
||||
*/
|
||||
enum libinput_config_click_method
|
||||
libinput_device_config_click_get_method(struct libinput_device *device);
|
||||
|
||||
/**
|
||||
* @ingroup config
|
||||
*
|
||||
* Get the default button click method for this device. The button click
|
||||
* method defines when to generate software-emulated buttons, usually on a
|
||||
* device that does not have a specific physical button available.
|
||||
*
|
||||
* @param device The device to configure
|
||||
*
|
||||
* @return The default button click method for this device
|
||||
*
|
||||
* @see libinput_device_config_click_get_methods
|
||||
* @see libinput_device_config_click_set_method
|
||||
* @see libinput_device_config_click_get_method
|
||||
*/
|
||||
enum libinput_config_click_method
|
||||
libinput_device_config_click_get_default_method(struct libinput_device *device);
|
||||
|
||||
|
||||
/**
|
||||
* @ingroup config
|
||||
*
|
||||
|
|
|
|||
|
|
@ -139,3 +139,11 @@ global:
|
|||
local:
|
||||
*;
|
||||
};
|
||||
|
||||
LIBINPUT_0.9.0 {
|
||||
global:
|
||||
libinput_device_config_click_get_default_method;
|
||||
libinput_device_config_click_get_method;
|
||||
libinput_device_config_click_get_methods;
|
||||
libinput_device_config_click_set_method;
|
||||
} LIBINPUT_0.8.0;
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ liblitest_la_SOURCES = \
|
|||
litest-ms-surface-cover.c \
|
||||
litest-qemu-usb-tablet.c \
|
||||
litest-synaptics.c \
|
||||
litest-synaptics-hover.c \
|
||||
litest-synaptics-st.c \
|
||||
litest-synaptics-t440.c \
|
||||
litest-trackpoint.c \
|
||||
|
|
|
|||
|
|
@ -31,21 +31,6 @@
|
|||
#include "litest.h"
|
||||
#include "litest-int.h"
|
||||
|
||||
static int tracking_id;
|
||||
|
||||
/* 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 alps {
|
||||
/* 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];
|
||||
};
|
||||
|
||||
static void alps_create(struct litest_device *d);
|
||||
|
||||
|
|
@ -56,141 +41,28 @@ litest_alps_setup(void)
|
|||
litest_set_current_device(d);
|
||||
}
|
||||
|
||||
static void
|
||||
send_abs_xy(struct litest_device *d, double x, double y)
|
||||
{
|
||||
struct input_event e;
|
||||
int val;
|
||||
|
||||
e.type = EV_ABS;
|
||||
e.code = ABS_X;
|
||||
e.value = LITEST_AUTO_ASSIGN;
|
||||
val = litest_auto_assign_value(d, &e, 0, x, y);
|
||||
litest_event(d, EV_ABS, ABS_X, val);
|
||||
|
||||
e.code = ABS_Y;
|
||||
val = litest_auto_assign_value(d, &e, 0, x, y);
|
||||
litest_event(d, EV_ABS, ABS_Y, val);
|
||||
}
|
||||
|
||||
static void
|
||||
send_abs_mt_xy(struct litest_device *d, double x, double y)
|
||||
{
|
||||
struct input_event e;
|
||||
int val;
|
||||
|
||||
e.type = EV_ABS;
|
||||
e.code = ABS_MT_POSITION_X;
|
||||
e.value = LITEST_AUTO_ASSIGN;
|
||||
val = litest_auto_assign_value(d, &e, 0, x, y);
|
||||
litest_event(d, EV_ABS, ABS_MT_POSITION_X, val);
|
||||
|
||||
e.code = ABS_MT_POSITION_Y;
|
||||
e.value = LITEST_AUTO_ASSIGN;
|
||||
val = litest_auto_assign_value(d, &e, 0, x, y);
|
||||
litest_event(d, EV_ABS, ABS_MT_POSITION_Y, val);
|
||||
}
|
||||
|
||||
static void
|
||||
alps_touch_down(struct litest_device *d, unsigned int slot, double x, double y)
|
||||
{
|
||||
struct alps *alps = d->private;
|
||||
double t, l, r = 0, b = 0; /* top, left, right, bottom */
|
||||
struct litest_semi_mt *semi_mt = d->private;
|
||||
|
||||
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, alps->touches[other].x);
|
||||
t = min(y, alps->touches[other].y);
|
||||
r = max(x, alps->touches[other].x);
|
||||
b = max(y, alps->touches[other].y);
|
||||
}
|
||||
|
||||
send_abs_xy(d, l, t);
|
||||
|
||||
litest_event(d, EV_ABS, ABS_MT_SLOT, 0);
|
||||
|
||||
if (d->ntouches_down == 1)
|
||||
litest_event(d, EV_ABS, ABS_MT_TRACKING_ID, ++tracking_id);
|
||||
|
||||
send_abs_mt_xy(d, l, t);
|
||||
|
||||
if (d->ntouches_down == 2) {
|
||||
litest_event(d, EV_ABS, ABS_MT_SLOT, 1);
|
||||
litest_event(d, EV_ABS, ABS_MT_TRACKING_ID, ++tracking_id);
|
||||
|
||||
send_abs_mt_xy(d, r, b);
|
||||
}
|
||||
|
||||
litest_event(d, EV_SYN, SYN_REPORT, 0);
|
||||
|
||||
alps->touches[slot].x = x;
|
||||
alps->touches[slot].y = y;
|
||||
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 alps *alps = d->private;
|
||||
double t, l, r = 0, b = 0; /* top, left, right, bottom */
|
||||
struct litest_semi_mt *semi_mt = d->private;
|
||||
|
||||
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, alps->touches[other].x);
|
||||
t = min(y, alps->touches[other].y);
|
||||
r = max(x, alps->touches[other].x);
|
||||
b = max(y, alps->touches[other].y);
|
||||
}
|
||||
|
||||
send_abs_xy(d, l, t);
|
||||
|
||||
litest_event(d, EV_ABS, ABS_MT_SLOT, 0);
|
||||
send_abs_mt_xy(d, l, t);
|
||||
|
||||
if (d->ntouches_down == 2) {
|
||||
litest_event(d, EV_ABS, ABS_MT_SLOT, 1);
|
||||
send_abs_mt_xy(d, r, b);
|
||||
}
|
||||
|
||||
litest_event(d, EV_SYN, SYN_REPORT, 0);
|
||||
|
||||
alps->touches[slot].x = x;
|
||||
alps->touches[slot].y = y;
|
||||
litest_semi_mt_touch_move(d, semi_mt, slot, x, y);
|
||||
}
|
||||
|
||||
static void
|
||||
alps_touch_up(struct litest_device *d, unsigned int slot)
|
||||
{
|
||||
struct alps *alps = d->private;
|
||||
struct litest_semi_mt *semi_mt = d->private;
|
||||
|
||||
/* note: ntouches_down is decreased before we get here */
|
||||
if (d->ntouches_down >= 2 || slot > 1)
|
||||
return;
|
||||
|
||||
litest_event(d, EV_ABS, ABS_MT_SLOT, d->ntouches_down);
|
||||
litest_event(d, EV_ABS, ABS_MT_TRACKING_ID, -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) {
|
||||
int other = (slot + 1) % 2;
|
||||
send_abs_xy(d, alps->touches[other].x, alps->touches[other].y);
|
||||
litest_event(d, EV_ABS, ABS_MT_SLOT, 0);
|
||||
send_abs_mt_xy(d, alps->touches[other].x, alps->touches[other].y);
|
||||
}
|
||||
|
||||
litest_event(d, EV_SYN, SYN_REPORT, 0);
|
||||
litest_semi_mt_touch_up(d, semi_mt, slot);
|
||||
}
|
||||
|
||||
static struct litest_device_interface interface = {
|
||||
|
|
@ -247,10 +119,10 @@ struct litest_test_device litest_alps_device = {
|
|||
static void
|
||||
alps_create(struct litest_device *d)
|
||||
{
|
||||
struct alps *alps = zalloc(sizeof(*alps));
|
||||
assert(alps);
|
||||
struct litest_semi_mt *semi_mt = zalloc(sizeof(*semi_mt));
|
||||
assert(semi_mt);
|
||||
|
||||
d->private = alps;
|
||||
d->private = semi_mt;
|
||||
|
||||
d->uinput = litest_create_uinput_device_from_description(litest_alps_device.name,
|
||||
litest_alps_device.id,
|
||||
|
|
|
|||
132
test/litest-synaptics-hover.c
Normal file
132
test/litest-synaptics-hover.c
Normal file
|
|
@ -0,0 +1,132 @@
|
|||
/*
|
||||
* Copyright © 2014 Red Hat, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that copyright
|
||||
* notice and this permission notice appear in supporting documentation, and
|
||||
* that the name of the copyright holders not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. The copyright holders make no representations
|
||||
* about the suitability of this software for any purpose. It is provided "as
|
||||
* is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "libinput-util.h"
|
||||
|
||||
#include "litest.h"
|
||||
#include "litest-int.h"
|
||||
|
||||
static void
|
||||
synaptics_hover_create(struct litest_device *d);
|
||||
|
||||
static void
|
||||
litest_synaptics_hover_setup(void)
|
||||
{
|
||||
struct litest_device *d = litest_create_device(LITEST_SYNAPTICS_HOVER_SEMI_MT);
|
||||
litest_set_current_device(d);
|
||||
}
|
||||
|
||||
static void
|
||||
synaptics_hover_touch_down(struct litest_device *d, unsigned int slot, double x, double y)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
static struct litest_device_interface interface = {
|
||||
.touch_down = synaptics_hover_touch_down,
|
||||
.touch_move = synaptics_hover_touch_move,
|
||||
.touch_up = synaptics_hover_touch_up,
|
||||
};
|
||||
|
||||
static struct input_id input_id = {
|
||||
.bustype = 0x11,
|
||||
.vendor = 0x2,
|
||||
.product = 0x7,
|
||||
};
|
||||
|
||||
static int events[] = {
|
||||
EV_KEY, BTN_LEFT,
|
||||
EV_KEY, BTN_RIGHT,
|
||||
EV_KEY, BTN_TOOL_FINGER,
|
||||
EV_KEY, BTN_TOUCH,
|
||||
EV_KEY, BTN_TOOL_DOUBLETAP,
|
||||
EV_KEY, BTN_TOOL_TRIPLETAP,
|
||||
INPUT_PROP_MAX, INPUT_PROP_POINTER,
|
||||
INPUT_PROP_MAX, INPUT_PROP_SEMI_MT,
|
||||
-1, -1,
|
||||
};
|
||||
|
||||
static struct input_absinfo absinfo[] = {
|
||||
{ ABS_X, 1472, 5472, 0, 0, 60 },
|
||||
{ ABS_Y, 1408, 4498, 0, 0, 85 },
|
||||
{ ABS_PRESSURE, 0, 255, 0, 0, 0 },
|
||||
{ ABS_TOOL_WIDTH, 0, 15, 0, 0, 0 },
|
||||
{ ABS_MT_SLOT, 0, 1, 0, 0, 0 },
|
||||
{ ABS_MT_POSITION_X, 1472, 5472, 0, 0, 60 },
|
||||
{ ABS_MT_POSITION_Y, 1408, 4498, 0, 0, 85 },
|
||||
{ ABS_MT_TRACKING_ID, 0, 65535, 0, 0, 0 },
|
||||
{ .value = -1 }
|
||||
};
|
||||
|
||||
struct litest_test_device litest_synaptics_hover_device = {
|
||||
.type = LITEST_SYNAPTICS_HOVER_SEMI_MT,
|
||||
.features = LITEST_TOUCHPAD | LITEST_SEMI_MT | LITEST_BUTTON,
|
||||
.shortname = "synaptics hover",
|
||||
.setup = litest_synaptics_hover_setup,
|
||||
.interface = &interface,
|
||||
.create = synaptics_hover_create,
|
||||
|
||||
.name = "SynPS/2 Synaptics TouchPad",
|
||||
.id = &input_id,
|
||||
.events = events,
|
||||
.absinfo = absinfo,
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
||||
143
test/litest.c
143
test/litest.c
|
|
@ -94,6 +94,7 @@ extern struct litest_test_device litest_generic_singletouch_device;
|
|||
extern struct litest_test_device litest_qemu_tablet_device;
|
||||
extern struct litest_test_device litest_xen_virtual_pointer_device;
|
||||
extern struct litest_test_device litest_vmware_virtmouse_device;
|
||||
extern struct litest_test_device litest_synaptics_hover_device;
|
||||
|
||||
struct litest_test_device* devices[] = {
|
||||
&litest_synaptics_clickpad_device,
|
||||
|
|
@ -113,6 +114,7 @@ struct litest_test_device* devices[] = {
|
|||
&litest_qemu_tablet_device,
|
||||
&litest_xen_virtual_pointer_device,
|
||||
&litest_vmware_virtmouse_device,
|
||||
&litest_synaptics_hover_device,
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
|
@ -1386,3 +1388,144 @@ litest_pop_event_frame(struct litest_device *dev)
|
|||
dev->skip_ev_syn = false;
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
send_abs_xy(struct litest_device *d, double x, double y)
|
||||
{
|
||||
struct input_event e;
|
||||
int val;
|
||||
|
||||
e.type = EV_ABS;
|
||||
e.code = ABS_X;
|
||||
e.value = LITEST_AUTO_ASSIGN;
|
||||
val = litest_auto_assign_value(d, &e, 0, x, y);
|
||||
litest_event(d, EV_ABS, ABS_X, val);
|
||||
|
||||
e.code = ABS_Y;
|
||||
val = litest_auto_assign_value(d, &e, 0, x, y);
|
||||
litest_event(d, EV_ABS, ABS_Y, val);
|
||||
}
|
||||
|
||||
static void
|
||||
send_abs_mt_xy(struct litest_device *d, double x, double y)
|
||||
{
|
||||
struct input_event e;
|
||||
int val;
|
||||
|
||||
e.type = EV_ABS;
|
||||
e.code = ABS_MT_POSITION_X;
|
||||
e.value = LITEST_AUTO_ASSIGN;
|
||||
val = litest_auto_assign_value(d, &e, 0, x, y);
|
||||
litest_event(d, EV_ABS, ABS_MT_POSITION_X, val);
|
||||
|
||||
e.code = ABS_MT_POSITION_Y;
|
||||
e.value = LITEST_AUTO_ASSIGN;
|
||||
val = litest_auto_assign_value(d, &e, 0, x, y);
|
||||
litest_event(d, EV_ABS, ABS_MT_POSITION_Y, val);
|
||||
}
|
||||
|
||||
void
|
||||
litest_semi_mt_touch_down(struct litest_device *d,
|
||||
struct litest_semi_mt *semi_mt,
|
||||
unsigned int slot,
|
||||
double x, double y)
|
||||
{
|
||||
double t, l, r = 0, b = 0; /* top, left, right, bottom */
|
||||
|
||||
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, semi_mt->touches[other].x);
|
||||
t = min(y, semi_mt->touches[other].y);
|
||||
r = max(x, semi_mt->touches[other].x);
|
||||
b = max(y, semi_mt->touches[other].y);
|
||||
}
|
||||
|
||||
send_abs_xy(d, l, t);
|
||||
|
||||
litest_event(d, EV_ABS, ABS_MT_SLOT, 0);
|
||||
|
||||
if (d->ntouches_down == 1)
|
||||
litest_event(d, EV_ABS, ABS_MT_TRACKING_ID, ++semi_mt->tracking_id);
|
||||
|
||||
send_abs_mt_xy(d, l, t);
|
||||
|
||||
if (d->ntouches_down == 2) {
|
||||
litest_event(d, EV_ABS, ABS_MT_SLOT, 1);
|
||||
litest_event(d, EV_ABS, ABS_MT_TRACKING_ID, ++semi_mt->tracking_id);
|
||||
|
||||
send_abs_mt_xy(d, r, b);
|
||||
}
|
||||
|
||||
litest_event(d, EV_SYN, SYN_REPORT, 0);
|
||||
|
||||
semi_mt->touches[slot].x = x;
|
||||
semi_mt->touches[slot].y = y;
|
||||
}
|
||||
|
||||
void
|
||||
litest_semi_mt_touch_move(struct litest_device *d,
|
||||
struct litest_semi_mt *semi_mt,
|
||||
unsigned int slot,
|
||||
double x, double y)
|
||||
{
|
||||
double t, l, r = 0, b = 0; /* top, left, right, bottom */
|
||||
|
||||
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, semi_mt->touches[other].x);
|
||||
t = min(y, semi_mt->touches[other].y);
|
||||
r = max(x, semi_mt->touches[other].x);
|
||||
b = max(y, semi_mt->touches[other].y);
|
||||
}
|
||||
|
||||
send_abs_xy(d, l, t);
|
||||
|
||||
litest_event(d, EV_ABS, ABS_MT_SLOT, 0);
|
||||
send_abs_mt_xy(d, l, t);
|
||||
|
||||
if (d->ntouches_down == 2) {
|
||||
litest_event(d, EV_ABS, ABS_MT_SLOT, 1);
|
||||
send_abs_mt_xy(d, r, b);
|
||||
}
|
||||
|
||||
litest_event(d, EV_SYN, SYN_REPORT, 0);
|
||||
|
||||
semi_mt->touches[slot].x = x;
|
||||
semi_mt->touches[slot].y = y;
|
||||
}
|
||||
|
||||
void
|
||||
litest_semi_mt_touch_up(struct litest_device *d,
|
||||
struct litest_semi_mt *semi_mt,
|
||||
unsigned int slot)
|
||||
{
|
||||
/* note: ntouches_down is decreased before we get here */
|
||||
if (d->ntouches_down >= 2 || slot > 1)
|
||||
return;
|
||||
|
||||
litest_event(d, EV_ABS, ABS_MT_SLOT, d->ntouches_down);
|
||||
litest_event(d, EV_ABS, ABS_MT_TRACKING_ID, -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) {
|
||||
int other = (slot + 1) % 2;
|
||||
send_abs_xy(d, semi_mt->touches[other].x, semi_mt->touches[other].y);
|
||||
litest_event(d, EV_ABS, ABS_MT_SLOT, 0);
|
||||
send_abs_mt_xy(d, semi_mt->touches[other].x, semi_mt->touches[other].y);
|
||||
}
|
||||
|
||||
litest_event(d, EV_SYN, SYN_REPORT, 0);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,10 +49,11 @@ enum litest_device_type {
|
|||
LITEST_QEMU_TABLET = -13,
|
||||
LITEST_XEN_VIRTUAL_POINTER = -14,
|
||||
LITEST_VMWARE_VIRTMOUSE = -15,
|
||||
LITEST_WACOM_BAMBOO = -16,
|
||||
LITEST_WACOM_CINTIQ = -17,
|
||||
LITEST_WACOM_INTUOS = -18,
|
||||
LITEST_WACOM_ISDV4 = -19,
|
||||
LITEST_SYNAPTICS_HOVER_SEMI_MT = -16,
|
||||
LITEST_WACOM_BAMBOO = -17,
|
||||
LITEST_WACOM_CINTIQ = -18,
|
||||
LITEST_WACOM_INTUOS = -19,
|
||||
LITEST_WACOM_ISDV4 = -20,
|
||||
};
|
||||
|
||||
enum litest_device_feature {
|
||||
|
|
@ -215,6 +216,33 @@ void litest_timeout_buttonscroll(void);
|
|||
void 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,
|
||||
unsigned int slot,
|
||||
double x, double y);
|
||||
void litest_semi_mt_touch_move(struct litest_device *d,
|
||||
struct litest_semi_mt *semi_mt,
|
||||
unsigned int slot,
|
||||
double x, double y);
|
||||
void litest_semi_mt_touch_up(struct litest_device *d,
|
||||
struct litest_semi_mt *semi_mt,
|
||||
unsigned int slot);
|
||||
|
||||
#ifndef ck_assert_notnull
|
||||
#define ck_assert_notnull(ptr) ck_assert_ptr_ne(ptr, NULL)
|
||||
#endif
|
||||
|
|
|
|||
788
test/touchpad.c
788
test/touchpad.c
|
|
@ -711,10 +711,96 @@ START_TEST(touchpad_3fg_tap_btntool_inverted)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(touchpad_click_defaults_clickfinger)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput_device *device = dev->libinput_device;
|
||||
uint32_t methods, method;
|
||||
enum libinput_config_status status;
|
||||
|
||||
/* call this test for apple touchpads */
|
||||
|
||||
methods = libinput_device_config_click_get_methods(device);
|
||||
ck_assert(methods & LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS);
|
||||
ck_assert(methods & LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER);
|
||||
|
||||
method = libinput_device_config_click_get_method(device);
|
||||
ck_assert_int_eq(method, LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER);
|
||||
method = libinput_device_config_click_get_default_method(device);
|
||||
ck_assert_int_eq(method, LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER);
|
||||
|
||||
status = libinput_device_config_click_set_method(device,
|
||||
LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS);
|
||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
|
||||
status = libinput_device_config_click_set_method(device,
|
||||
LIBINPUT_CONFIG_CLICK_METHOD_NONE);
|
||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(touchpad_click_defaults_btnarea)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput_device *device = dev->libinput_device;
|
||||
uint32_t methods, method;
|
||||
enum libinput_config_status status;
|
||||
|
||||
/* call this test for non-apple clickpads */
|
||||
|
||||
methods = libinput_device_config_click_get_methods(device);
|
||||
ck_assert(methods & LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER);
|
||||
ck_assert(methods & LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS);
|
||||
|
||||
method = libinput_device_config_click_get_method(device);
|
||||
ck_assert_int_eq(method, LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS);
|
||||
method = libinput_device_config_click_get_default_method(device);
|
||||
ck_assert_int_eq(method, LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS);
|
||||
|
||||
status = libinput_device_config_click_set_method(device,
|
||||
LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER);
|
||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
|
||||
status = libinput_device_config_click_set_method(device,
|
||||
LIBINPUT_CONFIG_CLICK_METHOD_NONE);
|
||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(touchpad_click_defaults_none)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput_device *device = dev->libinput_device;
|
||||
uint32_t methods, method;
|
||||
enum libinput_config_status status;
|
||||
|
||||
/* call this test for non-clickpads */
|
||||
|
||||
methods = libinput_device_config_click_get_methods(device);
|
||||
ck_assert_int_eq(methods, 0);
|
||||
|
||||
method = libinput_device_config_click_get_method(device);
|
||||
ck_assert_int_eq(method, LIBINPUT_CONFIG_CLICK_METHOD_NONE);
|
||||
method = libinput_device_config_click_get_default_method(device);
|
||||
ck_assert_int_eq(method, LIBINPUT_CONFIG_CLICK_METHOD_NONE);
|
||||
|
||||
status = libinput_device_config_click_set_method(device,
|
||||
LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER);
|
||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_UNSUPPORTED);
|
||||
status = libinput_device_config_click_set_method(device,
|
||||
LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS);
|
||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_UNSUPPORTED);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
|
||||
START_TEST(touchpad_1fg_clickfinger)
|
||||
{
|
||||
struct litest_device *dev = litest_create_device(LITEST_BCM5974);
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
enum libinput_config_status status;
|
||||
|
||||
status = libinput_device_config_click_set_method(dev->libinput_device,
|
||||
LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER);
|
||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
|
||||
|
||||
litest_drain_events(li);
|
||||
|
||||
|
|
@ -731,15 +817,18 @@ START_TEST(touchpad_1fg_clickfinger)
|
|||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
litest_assert_button_event(li, BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
|
||||
litest_delete_device(dev);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(touchpad_2fg_clickfinger)
|
||||
{
|
||||
struct litest_device *dev = litest_create_device(LITEST_BCM5974);
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
enum libinput_config_status status;
|
||||
|
||||
status = libinput_device_config_click_set_method(dev->libinput_device,
|
||||
LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER);
|
||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
|
||||
|
||||
litest_drain_events(li);
|
||||
|
||||
|
|
@ -754,12 +843,202 @@ START_TEST(touchpad_2fg_clickfinger)
|
|||
|
||||
libinput_dispatch(li);
|
||||
|
||||
litest_assert_button_event(li, BTN_RIGHT,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
litest_assert_button_event(li, BTN_RIGHT,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(touchpad_clickfinger_to_area_method)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
enum libinput_config_status status;
|
||||
struct libinput *li = dev->libinput;
|
||||
|
||||
litest_drain_events(li);
|
||||
|
||||
status = libinput_device_config_click_set_method(dev->libinput_device,
|
||||
LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS);
|
||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
|
||||
|
||||
litest_touch_down(dev, 0, 90, 90);
|
||||
litest_event(dev, EV_KEY, BTN_LEFT, 1);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
litest_event(dev, EV_KEY, BTN_LEFT, 0);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
litest_touch_up(dev, 0);
|
||||
libinput_dispatch(li);
|
||||
|
||||
litest_assert_button_event(li, BTN_RIGHT,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
litest_assert_button_event(li, BTN_RIGHT,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
|
||||
status = libinput_device_config_click_set_method(dev->libinput_device,
|
||||
LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER);
|
||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
|
||||
|
||||
litest_drain_events(li);
|
||||
|
||||
/* use bottom right corner to catch accidental softbutton right */
|
||||
litest_touch_down(dev, 0, 90, 90);
|
||||
litest_event(dev, EV_KEY, BTN_LEFT, 1);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
litest_event(dev, EV_KEY, BTN_LEFT, 0);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
litest_touch_up(dev, 0);
|
||||
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);
|
||||
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(touchpad_clickfinger_to_area_method_while_down)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
enum libinput_config_status status;
|
||||
struct libinput *li = dev->libinput;
|
||||
|
||||
litest_drain_events(li);
|
||||
|
||||
status = libinput_device_config_click_set_method(dev->libinput_device,
|
||||
LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS);
|
||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
|
||||
|
||||
litest_touch_down(dev, 0, 90, 90);
|
||||
litest_event(dev, EV_KEY, BTN_LEFT, 1);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
libinput_dispatch(li);
|
||||
litest_assert_button_event(li, BTN_RIGHT,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
|
||||
status = libinput_device_config_click_set_method(dev->libinput_device,
|
||||
LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER);
|
||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
|
||||
|
||||
litest_event(dev, EV_KEY, BTN_LEFT, 0);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
litest_touch_up(dev, 0);
|
||||
libinput_dispatch(li);
|
||||
|
||||
litest_assert_button_event(li, BTN_RIGHT,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
|
||||
|
||||
litest_drain_events(li);
|
||||
|
||||
/* use bottom right corner to catch accidental softbutton right */
|
||||
litest_touch_down(dev, 0, 90, 90);
|
||||
litest_event(dev, EV_KEY, BTN_LEFT, 1);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
litest_event(dev, EV_KEY, BTN_LEFT, 0);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
litest_touch_up(dev, 0);
|
||||
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);
|
||||
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(touchpad_area_to_clickfinger_method)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
enum libinput_config_status status;
|
||||
struct libinput *li = dev->libinput;
|
||||
|
||||
status = libinput_device_config_click_set_method(dev->libinput_device,
|
||||
LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER);
|
||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
|
||||
|
||||
litest_drain_events(li);
|
||||
|
||||
/* use bottom right corner to catch accidental softbutton right */
|
||||
litest_touch_down(dev, 0, 90, 90);
|
||||
litest_event(dev, EV_KEY, BTN_LEFT, 1);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
litest_event(dev, EV_KEY, BTN_LEFT, 0);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
litest_touch_up(dev, 0);
|
||||
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);
|
||||
|
||||
status = libinput_device_config_click_set_method(dev->libinput_device,
|
||||
LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS);
|
||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
|
||||
|
||||
litest_touch_down(dev, 0, 90, 90);
|
||||
litest_event(dev, EV_KEY, BTN_LEFT, 1);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
litest_event(dev, EV_KEY, BTN_LEFT, 0);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
litest_touch_up(dev, 0);
|
||||
libinput_dispatch(li);
|
||||
|
||||
litest_assert_button_event(li, BTN_RIGHT,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
litest_assert_button_event(li, BTN_RIGHT,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(touchpad_area_to_clickfinger_method_while_down)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
enum libinput_config_status status;
|
||||
struct libinput *li = dev->libinput;
|
||||
|
||||
status = libinput_device_config_click_set_method(dev->libinput_device,
|
||||
LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER);
|
||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
|
||||
|
||||
litest_drain_events(li);
|
||||
|
||||
/* use bottom right corner to catch accidental softbutton right */
|
||||
litest_touch_down(dev, 0, 90, 90);
|
||||
litest_event(dev, EV_KEY, BTN_LEFT, 1);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
litest_assert_button_event(li, BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
|
||||
status = libinput_device_config_click_set_method(dev->libinput_device,
|
||||
LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS);
|
||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
|
||||
|
||||
litest_event(dev, EV_KEY, BTN_LEFT, 0);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
litest_touch_up(dev, 0);
|
||||
libinput_dispatch(li);
|
||||
|
||||
litest_assert_button_event(li, BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
|
||||
litest_touch_down(dev, 0, 90, 90);
|
||||
litest_event(dev, EV_KEY, BTN_LEFT, 1);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
litest_event(dev, EV_KEY, BTN_LEFT, 0);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
litest_touch_up(dev, 0);
|
||||
libinput_dispatch(li);
|
||||
|
||||
litest_assert_button_event(li, BTN_RIGHT,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
litest_assert_button_event(li, BTN_RIGHT,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
|
||||
litest_delete_device(dev);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
|
|
@ -1371,6 +1650,99 @@ START_TEST(clickpad_topsoftbuttons_move_out_ignore)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(clickpad_topsoftbuttons_clickfinger)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
|
||||
libinput_device_config_click_set_method(dev->libinput_device,
|
||||
LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER);
|
||||
litest_drain_events(li);
|
||||
|
||||
litest_touch_down(dev, 0, 90, 5);
|
||||
litest_event(dev, EV_KEY, BTN_LEFT, 1);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
litest_event(dev, EV_KEY, BTN_LEFT, 0);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
litest_touch_up(dev, 0);
|
||||
|
||||
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);
|
||||
|
||||
litest_touch_down(dev, 0, 90, 5);
|
||||
litest_touch_down(dev, 1, 10, 5);
|
||||
litest_event(dev, EV_KEY, BTN_LEFT, 1);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
litest_event(dev, EV_KEY, BTN_LEFT, 0);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
litest_touch_up(dev, 0);
|
||||
litest_touch_up(dev, 1);
|
||||
|
||||
litest_assert_button_event(li,
|
||||
BTN_RIGHT,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
litest_assert_button_event(li,
|
||||
BTN_RIGHT,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(clickpad_topsoftbuttons_clickfinger_dev_disabled)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
struct litest_device *trackpoint = litest_add_device(li,
|
||||
LITEST_TRACKPOINT);
|
||||
|
||||
libinput_device_config_click_set_method(dev->libinput_device,
|
||||
LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER);
|
||||
libinput_device_config_send_events_set_mode(dev->libinput_device,
|
||||
LIBINPUT_CONFIG_SEND_EVENTS_DISABLED);
|
||||
litest_drain_events(li);
|
||||
|
||||
litest_touch_down(dev, 0, 90, 5);
|
||||
litest_event(dev, EV_KEY, BTN_LEFT, 1);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
litest_event(dev, EV_KEY, BTN_LEFT, 0);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
litest_touch_up(dev, 0);
|
||||
|
||||
litest_assert_button_event(li,
|
||||
BTN_RIGHT,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
litest_assert_button_event(li,
|
||||
BTN_RIGHT,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
|
||||
litest_assert_empty_queue(li);
|
||||
|
||||
litest_touch_down(dev, 0, 90, 5);
|
||||
litest_touch_down(dev, 1, 10, 5);
|
||||
litest_event(dev, EV_KEY, BTN_LEFT, 1);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
litest_event(dev, EV_KEY, BTN_LEFT, 0);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
litest_touch_up(dev, 0);
|
||||
litest_touch_up(dev, 1);
|
||||
|
||||
litest_assert_button_event(li,
|
||||
BTN_MIDDLE,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
litest_assert_button_event(li,
|
||||
BTN_MIDDLE,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
|
||||
litest_delete_device(trackpoint);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
|
||||
static void
|
||||
test_2fg_scroll(struct litest_device *dev, double dx, double dy, int want_sleep)
|
||||
{
|
||||
|
|
@ -2207,8 +2579,387 @@ START_TEST(touchpad_left_handed_clickpad_delayed)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
static void
|
||||
hover_continue(struct litest_device *dev, unsigned int slot,
|
||||
int x, int y)
|
||||
{
|
||||
litest_event(dev, EV_ABS, ABS_MT_SLOT, slot);
|
||||
litest_event(dev, EV_ABS, ABS_MT_POSITION_X, x);
|
||||
litest_event(dev, EV_ABS, ABS_MT_POSITION_Y, y);
|
||||
litest_event(dev, EV_ABS, ABS_X, x);
|
||||
litest_event(dev, EV_ABS, ABS_Y, y);
|
||||
litest_event(dev, EV_ABS, ABS_PRESSURE, 10);
|
||||
litest_event(dev, EV_ABS, ABS_TOOL_WIDTH, 6);
|
||||
/* WARNING: no SYN_REPORT! */
|
||||
}
|
||||
|
||||
static void
|
||||
hover_start(struct litest_device *dev, unsigned int slot,
|
||||
int x, int y)
|
||||
{
|
||||
static unsigned int tracking_id;
|
||||
|
||||
litest_event(dev, EV_ABS, ABS_MT_SLOT, slot);
|
||||
litest_event(dev, EV_ABS, ABS_MT_TRACKING_ID, ++tracking_id);
|
||||
hover_continue(dev, slot, x, y);
|
||||
/* WARNING: no SYN_REPORT! */
|
||||
}
|
||||
|
||||
START_TEST(touchpad_hover_noevent)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
int i;
|
||||
int x = 2400,
|
||||
y = 2400;
|
||||
|
||||
litest_drain_events(li);
|
||||
|
||||
hover_start(dev, 0, x, y);
|
||||
litest_event(dev, EV_KEY, BTN_TOOL_FINGER, 1);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
|
||||
for (i = 0; i < 10; i++) {
|
||||
x += 200;
|
||||
y -= 200;
|
||||
litest_event(dev, EV_ABS, ABS_MT_POSITION_X, x);
|
||||
litest_event(dev, EV_ABS, ABS_MT_POSITION_Y, y);
|
||||
litest_event(dev, EV_ABS, ABS_X, x);
|
||||
litest_event(dev, EV_ABS, ABS_Y, y);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
}
|
||||
|
||||
litest_event(dev, EV_KEY, BTN_TOOL_FINGER, 0);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
|
||||
litest_assert_empty_queue(li);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(touchpad_hover_down)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
struct libinput_event *event;
|
||||
int i;
|
||||
int x = 2400,
|
||||
y = 2400;
|
||||
|
||||
litest_drain_events(li);
|
||||
|
||||
hover_start(dev, 0, x, y);
|
||||
litest_event(dev, EV_KEY, BTN_TOOL_FINGER, 1);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
|
||||
for (i = 0; i < 10; i++) {
|
||||
x += 200;
|
||||
y -= 200;
|
||||
litest_event(dev, EV_ABS, ABS_MT_POSITION_X, x);
|
||||
litest_event(dev, EV_ABS, ABS_MT_POSITION_Y, y);
|
||||
litest_event(dev, EV_ABS, ABS_X, x);
|
||||
litest_event(dev, EV_ABS, ABS_Y, y);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
}
|
||||
|
||||
litest_assert_empty_queue(li);
|
||||
|
||||
litest_event(dev, EV_ABS, ABS_X, x + 100);
|
||||
litest_event(dev, EV_ABS, ABS_Y, y + 100);
|
||||
litest_event(dev, EV_KEY, BTN_TOUCH, 1);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
libinput_dispatch(li);
|
||||
for (i = 0; i < 10; i++) {
|
||||
x -= 200;
|
||||
y += 200;
|
||||
litest_event(dev, EV_ABS, ABS_MT_POSITION_X, x);
|
||||
litest_event(dev, EV_ABS, ABS_MT_POSITION_Y, y);
|
||||
litest_event(dev, EV_ABS, ABS_X, x);
|
||||
litest_event(dev, EV_ABS, ABS_Y, y);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
}
|
||||
|
||||
libinput_dispatch(li);
|
||||
|
||||
ck_assert_int_ne(libinput_next_event_type(li),
|
||||
LIBINPUT_EVENT_NONE);
|
||||
while ((event = libinput_get_event(li)) != NULL) {
|
||||
ck_assert_int_eq(libinput_event_get_type(event),
|
||||
LIBINPUT_EVENT_POINTER_MOTION);
|
||||
libinput_event_destroy(event);
|
||||
libinput_dispatch(li);
|
||||
}
|
||||
|
||||
/* go back to hover */
|
||||
hover_continue(dev, 0, x, y);
|
||||
litest_event(dev, EV_KEY, BTN_TOUCH, 0);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
|
||||
for (i = 0; i < 10; i++) {
|
||||
x += 200;
|
||||
y -= 200;
|
||||
litest_event(dev, EV_ABS, ABS_MT_POSITION_X, x);
|
||||
litest_event(dev, EV_ABS, ABS_MT_POSITION_Y, y);
|
||||
litest_event(dev, EV_ABS, ABS_X, x);
|
||||
litest_event(dev, EV_ABS, ABS_Y, y);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
}
|
||||
|
||||
litest_event(dev, EV_KEY, BTN_TOOL_FINGER, 0);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
|
||||
litest_assert_empty_queue(li);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(touchpad_hover_down_hover_down)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
struct libinput_event *event;
|
||||
int i, j;
|
||||
int x = 1400,
|
||||
y = 1400;
|
||||
|
||||
litest_drain_events(li);
|
||||
|
||||
/* hover */
|
||||
hover_start(dev, 0, x, y);
|
||||
litest_event(dev, EV_KEY, BTN_TOOL_FINGER, 1);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
litest_assert_empty_queue(li);
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
/* touch */
|
||||
litest_event(dev, EV_ABS, ABS_X, x + 100);
|
||||
litest_event(dev, EV_ABS, ABS_Y, y + 100);
|
||||
litest_event(dev, EV_KEY, BTN_TOUCH, 1);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
libinput_dispatch(li);
|
||||
|
||||
for (j = 0; j < 5; j++) {
|
||||
x += 200;
|
||||
y += 200;
|
||||
litest_event(dev, EV_ABS, ABS_MT_POSITION_X, x);
|
||||
litest_event(dev, EV_ABS, ABS_MT_POSITION_Y, y);
|
||||
litest_event(dev, EV_ABS, ABS_X, x);
|
||||
litest_event(dev, EV_ABS, ABS_Y, y);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
}
|
||||
|
||||
libinput_dispatch(li);
|
||||
|
||||
ck_assert_int_ne(libinput_next_event_type(li),
|
||||
LIBINPUT_EVENT_NONE);
|
||||
while ((event = libinput_get_event(li)) != NULL) {
|
||||
ck_assert_int_eq(libinput_event_get_type(event),
|
||||
LIBINPUT_EVENT_POINTER_MOTION);
|
||||
libinput_event_destroy(event);
|
||||
libinput_dispatch(li);
|
||||
}
|
||||
|
||||
/* go back to hover */
|
||||
hover_continue(dev, 0, x, y);
|
||||
litest_event(dev, EV_KEY, BTN_TOUCH, 0);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
|
||||
for (j = 0; j < 5; j++) {
|
||||
x += 200;
|
||||
y += 200;
|
||||
litest_event(dev, EV_ABS, ABS_MT_POSITION_X, x);
|
||||
litest_event(dev, EV_ABS, ABS_MT_POSITION_Y, y);
|
||||
litest_event(dev, EV_ABS, ABS_X, x);
|
||||
litest_event(dev, EV_ABS, ABS_Y, y);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
}
|
||||
|
||||
litest_assert_empty_queue(li);
|
||||
}
|
||||
|
||||
/* touch */
|
||||
litest_event(dev, EV_KEY, BTN_TOOL_FINGER, 0);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
|
||||
litest_assert_empty_queue(li);
|
||||
|
||||
/* start a new touch to be sure */
|
||||
litest_touch_down(dev, 0, 50, 50);
|
||||
litest_touch_move_to(dev, 0, 50, 50, 70, 70, 10, 10);
|
||||
litest_touch_up(dev, 0);
|
||||
|
||||
libinput_dispatch(li);
|
||||
ck_assert_int_ne(libinput_next_event_type(li),
|
||||
LIBINPUT_EVENT_NONE);
|
||||
while ((event = libinput_get_event(li)) != NULL) {
|
||||
ck_assert_int_eq(libinput_event_get_type(event),
|
||||
LIBINPUT_EVENT_POINTER_MOTION);
|
||||
libinput_event_destroy(event);
|
||||
libinput_dispatch(li);
|
||||
}
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(touchpad_hover_down_up)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
int i;
|
||||
int x = 1400,
|
||||
y = 1400;
|
||||
|
||||
litest_drain_events(li);
|
||||
|
||||
/* hover two fingers, then touch */
|
||||
hover_start(dev, 0, x, y);
|
||||
litest_event(dev, EV_KEY, BTN_TOOL_FINGER, 1);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
litest_assert_empty_queue(li);
|
||||
|
||||
hover_start(dev, 1, x, y);
|
||||
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);
|
||||
litest_assert_empty_queue(li);
|
||||
|
||||
litest_event(dev, EV_KEY, BTN_TOOL_DOUBLETAP, 0);
|
||||
litest_event(dev, EV_KEY, BTN_TOOL_TRIPLETAP, 1);
|
||||
litest_event(dev, EV_KEY, BTN_TOUCH, 1);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
|
||||
litest_assert_empty_queue(li);
|
||||
|
||||
/* hover first finger, end second in same frame */
|
||||
litest_event(dev, EV_ABS, ABS_MT_SLOT, 1);
|
||||
litest_event(dev, EV_ABS, ABS_MT_TRACKING_ID, -1);
|
||||
litest_event(dev, EV_KEY, BTN_TOOL_TRIPLETAP, 0);
|
||||
litest_event(dev, EV_KEY, BTN_TOOL_FINGER, 1);
|
||||
litest_event(dev, EV_KEY, BTN_TOUCH, 0);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
|
||||
litest_assert_empty_queue(li);
|
||||
|
||||
litest_event(dev, EV_KEY, BTN_TOUCH, 1);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
libinput_dispatch(li);
|
||||
|
||||
/* now move the finger */
|
||||
for (i = 0; i < 10; i++) {
|
||||
litest_event(dev, EV_ABS, ABS_MT_SLOT, 0);
|
||||
litest_event(dev, EV_ABS, ABS_MT_POSITION_X, x);
|
||||
litest_event(dev, EV_ABS, ABS_MT_POSITION_Y, y);
|
||||
litest_event(dev, EV_ABS, ABS_X, x);
|
||||
litest_event(dev, EV_ABS, ABS_Y, y);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
x -= 100;
|
||||
y -= 100;
|
||||
}
|
||||
|
||||
litest_assert_only_typed_events(li,
|
||||
LIBINPUT_EVENT_POINTER_MOTION);
|
||||
|
||||
litest_event(dev, EV_ABS, ABS_MT_SLOT, 0);
|
||||
litest_event(dev, EV_ABS, ABS_MT_TRACKING_ID, -1);
|
||||
litest_event(dev, EV_KEY, BTN_TOOL_FINGER, 0);
|
||||
litest_event(dev, EV_KEY, BTN_TOUCH, 0);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
libinput_dispatch(li);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(touchpad_hover_2fg_noevent)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
int i;
|
||||
int x = 2400,
|
||||
y = 2400;
|
||||
|
||||
litest_drain_events(li);
|
||||
|
||||
hover_start(dev, 0, x, y);
|
||||
litest_event(dev, EV_KEY, BTN_TOOL_FINGER, 1);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
|
||||
hover_start(dev, 1, x + 500, y + 500);
|
||||
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);
|
||||
|
||||
for (i = 0; i < 10; i++) {
|
||||
x += 200;
|
||||
y -= 200;
|
||||
litest_event(dev, EV_ABS, ABS_MT_SLOT, 0);
|
||||
litest_event(dev, EV_ABS, ABS_MT_POSITION_X, x);
|
||||
litest_event(dev, EV_ABS, ABS_MT_POSITION_Y, y);
|
||||
litest_event(dev, EV_ABS, ABS_MT_SLOT, 1);
|
||||
litest_event(dev, EV_ABS, ABS_MT_POSITION_X, x + 500);
|
||||
litest_event(dev, EV_ABS, ABS_MT_POSITION_Y, y + 500);
|
||||
litest_event(dev, EV_ABS, ABS_X, x);
|
||||
litest_event(dev, EV_ABS, ABS_Y, y);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
}
|
||||
|
||||
litest_event(dev, EV_KEY, BTN_TOOL_DOUBLETAP, 0);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
|
||||
litest_assert_empty_queue(li);
|
||||
|
||||
litest_event(dev, EV_KEY, BTN_TOOL_FINGER, 0);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
|
||||
litest_assert_empty_queue(li);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(touchpad_hover_2fg_1fg_down)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
struct libinput_event *event;
|
||||
int i;
|
||||
int x = 2400,
|
||||
y = 2400;
|
||||
|
||||
litest_drain_events(li);
|
||||
|
||||
/* 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_KEY, BTN_TOUCH, 1);
|
||||
litest_event(dev, EV_KEY, BTN_TOOL_FINGER, 1);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
|
||||
for (i = 0; i < 10; i++) {
|
||||
x += 200;
|
||||
y -= 200;
|
||||
litest_event(dev, EV_ABS, ABS_MT_SLOT, 0);
|
||||
litest_event(dev, EV_ABS, ABS_MT_POSITION_X, x);
|
||||
litest_event(dev, EV_ABS, ABS_MT_POSITION_Y, y);
|
||||
litest_event(dev, EV_ABS, ABS_MT_SLOT, 1);
|
||||
litest_event(dev, EV_ABS, ABS_MT_POSITION_X, x + 500);
|
||||
litest_event(dev, EV_ABS, ABS_MT_POSITION_Y, y + 500);
|
||||
litest_event(dev, EV_ABS, ABS_X, x);
|
||||
litest_event(dev, EV_ABS, ABS_Y, y);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 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);
|
||||
|
||||
libinput_dispatch(li);
|
||||
|
||||
ck_assert_int_ne(libinput_next_event_type(li),
|
||||
LIBINPUT_EVENT_NONE);
|
||||
while ((event = libinput_get_event(li)) != NULL) {
|
||||
ck_assert_int_eq(libinput_event_get_type(event),
|
||||
LIBINPUT_EVENT_POINTER_MOTION);
|
||||
libinput_event_destroy(event);
|
||||
libinput_dispatch(li);
|
||||
}
|
||||
}
|
||||
END_TEST
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
|
||||
litest_add("touchpad:motion", touchpad_1fg_motion, LITEST_TOUCHPAD, LITEST_ANY);
|
||||
litest_add("touchpad:motion", touchpad_2fg_no_motion, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH);
|
||||
|
|
@ -2246,8 +2997,18 @@ int main(int argc, char **argv) {
|
|||
litest_add("touchpad:tap", clickpad_1fg_tap_click, LITEST_CLICKPAD, LITEST_ANY);
|
||||
litest_add("touchpad:tap", clickpad_2fg_tap_click, LITEST_CLICKPAD, LITEST_SINGLE_TOUCH|LITEST_APPLE_CLICKPAD);
|
||||
|
||||
litest_add_no_device("touchpad:clickfinger", touchpad_1fg_clickfinger);
|
||||
litest_add_no_device("touchpad:clickfinger", touchpad_2fg_clickfinger);
|
||||
litest_add("touchpad:clickfinger", touchpad_1fg_clickfinger, LITEST_CLICKPAD, LITEST_ANY);
|
||||
litest_add("touchpad:clickfinger", touchpad_2fg_clickfinger, LITEST_CLICKPAD, LITEST_ANY);
|
||||
litest_add("touchpad:clickfinger", touchpad_clickfinger_to_area_method, LITEST_CLICKPAD, LITEST_ANY);
|
||||
litest_add("touchpad:clickfinger",
|
||||
touchpad_clickfinger_to_area_method_while_down, LITEST_CLICKPAD, LITEST_ANY);
|
||||
litest_add("touchpad:clickfinger", touchpad_area_to_clickfinger_method, LITEST_CLICKPAD, LITEST_ANY);
|
||||
litest_add("touchpad:clickfinger",
|
||||
touchpad_area_to_clickfinger_method_while_down, LITEST_CLICKPAD, LITEST_ANY);
|
||||
|
||||
litest_add("touchpad:click", touchpad_click_defaults_clickfinger, LITEST_APPLE_CLICKPAD, LITEST_ANY);
|
||||
litest_add("touchpad:click", touchpad_click_defaults_btnarea, LITEST_CLICKPAD, LITEST_APPLE_CLICKPAD);
|
||||
litest_add("touchpad:click", touchpad_click_defaults_none, LITEST_TOUCHPAD, LITEST_CLICKPAD);
|
||||
|
||||
litest_add("touchpad:click", touchpad_btn_left, LITEST_TOUCHPAD, LITEST_CLICKPAD);
|
||||
litest_add("touchpad:click", clickpad_btn_left, LITEST_CLICKPAD, LITEST_ANY);
|
||||
|
|
@ -2266,6 +3027,8 @@ int main(int argc, char **argv) {
|
|||
litest_add("touchpad:topsoftbuttons", clickpad_topsoftbuttons_right, LITEST_TOPBUTTONPAD, LITEST_ANY);
|
||||
litest_add("touchpad:topsoftbuttons", clickpad_topsoftbuttons_middle, LITEST_TOPBUTTONPAD, LITEST_ANY);
|
||||
litest_add("touchpad:topsoftbuttons", clickpad_topsoftbuttons_move_out_ignore, LITEST_TOPBUTTONPAD, LITEST_ANY);
|
||||
litest_add("touchpad:topsoftbuttons", clickpad_topsoftbuttons_clickfinger, LITEST_TOPBUTTONPAD, LITEST_ANY);
|
||||
litest_add("touchpad:topsoftbuttons", clickpad_topsoftbuttons_clickfinger_dev_disabled, LITEST_TOPBUTTONPAD, LITEST_ANY);
|
||||
|
||||
litest_add("touchpad:scroll", touchpad_2fg_scroll, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH);
|
||||
litest_add("touchpad:scroll", touchpad_2fg_scroll_slow_distance, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH);
|
||||
|
|
@ -2295,5 +3058,14 @@ int main(int argc, char **argv) {
|
|||
litest_add("touchpad:left-handed", touchpad_left_handed_delayed, LITEST_TOUCHPAD, LITEST_CLICKPAD);
|
||||
litest_add("touchpad:left-handed", touchpad_left_handed_clickpad_delayed, LITEST_CLICKPAD, LITEST_APPLE_CLICKPAD);
|
||||
|
||||
/* Hover tests aren't generic, they only work on this device and
|
||||
* ignore the semi-mt capability (it doesn't matter for the tests */
|
||||
litest_add_for_device("touchpad:hover", touchpad_hover_noevent, LITEST_SYNAPTICS_HOVER_SEMI_MT);
|
||||
litest_add_for_device("touchpad:hover", touchpad_hover_down, LITEST_SYNAPTICS_HOVER_SEMI_MT);
|
||||
litest_add_for_device("touchpad:hover", touchpad_hover_down_up, LITEST_SYNAPTICS_HOVER_SEMI_MT);
|
||||
litest_add_for_device("touchpad:hover", touchpad_hover_down_hover_down, LITEST_SYNAPTICS_HOVER_SEMI_MT);
|
||||
litest_add_for_device("touchpad:hover", touchpad_hover_2fg_noevent, LITEST_SYNAPTICS_HOVER_SEMI_MT);
|
||||
litest_add_for_device("touchpad:hover", touchpad_hover_2fg_1fg_down, LITEST_SYNAPTICS_HOVER_SEMI_MT);
|
||||
|
||||
return litest_run(argc, argv);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ enum options {
|
|||
OPT_NATURAL_SCROLL_DISABLE,
|
||||
OPT_LEFT_HANDED_ENABLE,
|
||||
OPT_LEFT_HANDED_DISABLE,
|
||||
OPT_CLICK_METHOD,
|
||||
};
|
||||
|
||||
static void
|
||||
|
|
@ -69,6 +70,7 @@ tools_usage()
|
|||
"--disable-natural-scrolling.... enable/disable natural scrolling\n"
|
||||
"--enable-left-handed\n"
|
||||
"--disable-left-handed.... enable/disable left-handed button configuration\n"
|
||||
"--set-click-method=[none|clickfinger|buttonareas] .... set the desired click method\n"
|
||||
"\n"
|
||||
"These options apply to all applicable devices, if a feature\n"
|
||||
"is not explicitly specified it is left at each device's default.\n"
|
||||
|
|
@ -86,6 +88,7 @@ tools_init_options(struct tools_options *options)
|
|||
options->tapping = -1;
|
||||
options->natural_scroll = -1;
|
||||
options->left_handed = -1;
|
||||
options->click_method = -1;
|
||||
options->backend = BACKEND_UDEV;
|
||||
options->seat = "seat0";
|
||||
}
|
||||
|
|
@ -107,6 +110,7 @@ tools_parse_args(int argc, char **argv, struct tools_options *options)
|
|||
{ "disable-natural-scrolling", 0, 0, OPT_NATURAL_SCROLL_DISABLE },
|
||||
{ "enable-left-handed", 0, 0, OPT_LEFT_HANDED_ENABLE },
|
||||
{ "disable-left-handed", 0, 0, OPT_LEFT_HANDED_DISABLE },
|
||||
{ "set-click-method", 1, 0, OPT_CLICK_METHOD },
|
||||
{ 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
|
|
@ -153,6 +157,25 @@ tools_parse_args(int argc, char **argv, struct tools_options *options)
|
|||
case OPT_LEFT_HANDED_DISABLE:
|
||||
options->left_handed = 0;
|
||||
break;
|
||||
case OPT_CLICK_METHOD:
|
||||
if (!optarg) {
|
||||
tools_usage();
|
||||
return 1;
|
||||
}
|
||||
if (strcmp(optarg, "none") == 0) {
|
||||
options->click_method =
|
||||
LIBINPUT_CONFIG_CLICK_METHOD_NONE;
|
||||
} else if (strcmp(optarg, "clickfinger") == 0) {
|
||||
options->click_method =
|
||||
LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER;
|
||||
} else if (strcmp(optarg, "buttonareas") == 0) {
|
||||
options->click_method =
|
||||
LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS;
|
||||
} else {
|
||||
tools_usage();
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
tools_usage();
|
||||
return 1;
|
||||
|
|
@ -263,4 +286,7 @@ tools_device_apply_config(struct libinput_device *device,
|
|||
options->natural_scroll);
|
||||
if (options->left_handed != -1)
|
||||
libinput_device_config_left_handed_set(device, options->left_handed);
|
||||
|
||||
if (options->click_method != -1)
|
||||
libinput_device_config_click_set_method(device, options->click_method);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ struct tools_options {
|
|||
int tapping;
|
||||
int natural_scroll;
|
||||
int left_handed;
|
||||
enum libinput_config_click_method click_method;
|
||||
};
|
||||
|
||||
void tools_init_options(struct tools_options *options);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue