Merge branch 'master' into tablet-support

Conflicts:
	test/litest.h
	test/valgrind.suppressions
This commit is contained in:
Peter Hutterer 2015-03-02 13:57:17 +10:00
commit ea77fd3272
17 changed files with 695 additions and 372 deletions

View file

@ -11,7 +11,22 @@ The following udev properties are supported:
<dt>LIBINPUT_CALIBRATION_MATRIX</dt> <dt>LIBINPUT_CALIBRATION_MATRIX</dt>
<dd>Sets the calibration matrix, see <dd>Sets the calibration matrix, see
libinput_device_config_calibration_get_default_matrix(). If unset, libinput_device_config_calibration_get_default_matrix(). If unset,
defaults to the identity matrix.</dd> defaults to the identity matrix.
The udev property is parsed as 6 floating point numbers separated by a
single space each (scanf(3) format "%f %f %f %f %f %f").
The 6 values represent the first two rows of the calibration matrix as
described in libinput_device_config_calibration_set_matrix().
Example values are:
@code
ENV{LIBINPUT_CALIBRATION_MATRIX}="1 0 0 0 1 0" # default
ENV{LIBINPUT_CALIBRATION_MATRIX}="0 -1 1 1 0 0" # 90 degree clockwise
ENV{LIBINPUT_CALIBRATION_MATRIX}="-1 0 1 0 -1 1" # 180 degree clockwise
ENV{LIBINPUT_CALIBRATION_MATRIX}="0 1 0 -1 0 1" # 270 degree clockwise
ENV{LIBINPUT_CALIBRATION_MATRIX}="-1 0 1 1 0 0" # reflect along y axis
@endcode
</dd>
<dt>LIBINPUT_DEVICE_GROUP</dt> <dt>LIBINPUT_DEVICE_GROUP</dt>
<dd>A string identifying the @ref libinput_device_group for this device. Two <dd>A string identifying the @ref libinput_device_group for this device. Two
devices with the same property value are grouped into the same device group, devices with the same property value are grouped into the same device group,

View file

@ -17,6 +17,7 @@ libinput_la_SOURCES = \
evdev-mt-touchpad-tap.c \ evdev-mt-touchpad-tap.c \
evdev-mt-touchpad-buttons.c \ evdev-mt-touchpad-buttons.c \
evdev-mt-touchpad-edge-scroll.c \ evdev-mt-touchpad-edge-scroll.c \
evdev-mt-touchpad-gestures.c \
filter.c \ filter.c \
filter.h \ filter.h \
filter-private.h \ filter-private.h \

View file

@ -156,7 +156,6 @@ tp_button_set_state(struct tp_dispatch *tp, struct tp_touch *t,
break; break;
case BUTTON_STATE_AREA: case BUTTON_STATE_AREA:
t->button.curr = BUTTON_EVENT_IN_AREA; t->button.curr = BUTTON_EVENT_IN_AREA;
tp_set_pointer(tp, t);
break; break;
case BUTTON_STATE_BOTTOM: case BUTTON_STATE_BOTTOM:
t->button.curr = event; t->button.curr = event;

View file

@ -86,7 +86,6 @@ tp_edge_scroll_set_state(struct tp_dispatch *tp,
break; break;
case EDGE_SCROLL_TOUCH_STATE_AREA: case EDGE_SCROLL_TOUCH_STATE_AREA:
t->scroll.edge = EDGE_NONE; t->scroll.edge = EDGE_NONE;
tp_set_pointer(tp, t);
break; break;
} }
} }
@ -317,6 +316,9 @@ tp_edge_scroll_post_events(struct tp_dispatch *tp, uint64_t time)
enum libinput_pointer_axis axis; enum libinput_pointer_axis axis;
double dx, dy, *delta; double dx, dy, *delta;
if (tp->scroll.method != LIBINPUT_CONFIG_SCROLL_EDGE)
return 0;
tp_for_each_touch(tp, t) { tp_for_each_touch(tp, t) {
if (!t->dirty) if (!t->dirty)
continue; continue;

View file

@ -0,0 +1,233 @@
/*
* Copyright © 2015 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.
*/
#include "config.h"
#include <assert.h>
#include <math.h>
#include <stdbool.h>
#include <limits.h>
#include "evdev-mt-touchpad.h"
#define DEFAULT_GESTURE_SWITCH_TIMEOUT 100 /* ms */
static void
tp_get_touches_delta(struct tp_dispatch *tp, double *dx, double *dy, bool average)
{
struct tp_touch *t;
unsigned int i, nchanged = 0;
double tmpx, tmpy;
*dx = 0.0;
*dy = 0.0;
for (i = 0; i < tp->real_touches; i++) {
t = &tp->touches[i];
if (tp_touch_active(tp, t) && t->dirty) {
nchanged++;
tp_get_delta(t, &tmpx, &tmpy);
*dx += tmpx;
*dy += tmpy;
}
}
if (!average || nchanged == 0)
return;
*dx /= nchanged;
*dy /= nchanged;
}
static inline void
tp_get_combined_touches_delta(struct tp_dispatch *tp, double *dx, double *dy)
{
tp_get_touches_delta(tp, dx, dy, false);
}
static inline void
tp_get_average_touches_delta(struct tp_dispatch *tp, double *dx, double *dy)
{
tp_get_touches_delta(tp, dx, dy, true);
}
static void
tp_gesture_start(struct tp_dispatch *tp, uint64_t time)
{
if (tp->gesture.started)
return;
switch (tp->gesture.finger_count) {
case 2:
/* NOP */
break;
}
tp->gesture.started = true;
}
static void
tp_gesture_post_pointer_motion(struct tp_dispatch *tp, uint64_t time)
{
double dx = 0.0, dy = 0.0;
double dx_unaccel, dy_unaccel;
/* When a clickpad is clicked, combine motion of all active touches */
if (tp->buttons.is_clickpad && tp->buttons.state)
tp_get_combined_touches_delta(tp, &dx, &dy);
else
tp_get_average_touches_delta(tp, &dx, &dy);
tp_filter_motion(tp, &dx, &dy, &dx_unaccel, &dy_unaccel, time);
if (dx != 0.0 || dy != 0.0 || dx_unaccel != 0.0 || dy_unaccel != 0.0) {
pointer_notify_motion(&tp->device->base, time,
dx, dy, dx_unaccel, dy_unaccel);
}
}
static void
tp_gesture_post_twofinger_scroll(struct tp_dispatch *tp, uint64_t time)
{
double dx = 0, dy =0;
tp_get_average_touches_delta(tp, &dx, &dy);
tp_filter_motion(tp, &dx, &dy, NULL, NULL, time);
if (dx == 0.0 && dy == 0.0)
return;
tp_gesture_start(tp, time);
evdev_post_scroll(tp->device,
time,
LIBINPUT_POINTER_AXIS_SOURCE_FINGER,
dx, dy);
}
void
tp_gesture_post_events(struct tp_dispatch *tp, uint64_t time)
{
if (tp->gesture.finger_count == 0)
return;
/* When tap-and-dragging, or a clickpad is clicked force 1fg mode */
if (tp_tap_dragging(tp) || (tp->buttons.is_clickpad && tp->buttons.state)) {
tp_gesture_stop(tp, time);
tp->gesture.finger_count = 1;
tp->gesture.finger_count_pending = 0;
}
/* Don't send events when we're unsure in which mode we are */
if (tp->gesture.finger_count_pending)
return;
switch (tp->gesture.finger_count) {
case 1:
tp_gesture_post_pointer_motion(tp, time);
break;
case 2:
tp_gesture_post_twofinger_scroll(tp, time);
break;
}
}
void
tp_gesture_stop_twofinger_scroll(struct tp_dispatch *tp, uint64_t time)
{
evdev_stop_scroll(tp->device,
time,
LIBINPUT_POINTER_AXIS_SOURCE_FINGER);
}
void
tp_gesture_stop(struct tp_dispatch *tp, uint64_t time)
{
if (!tp->gesture.started)
return;
switch (tp->gesture.finger_count) {
case 2:
tp_gesture_stop_twofinger_scroll(tp, time);
break;
}
tp->gesture.started = false;
}
static void
tp_gesture_finger_count_switch_timeout(uint64_t now, void *data)
{
struct tp_dispatch *tp = data;
if (!tp->gesture.finger_count_pending)
return;
tp_gesture_stop(tp, now); /* End current gesture */
tp->gesture.finger_count = tp->gesture.finger_count_pending;
tp->gesture.finger_count_pending = 0;
}
void
tp_gesture_handle_state(struct tp_dispatch *tp, uint64_t time)
{
unsigned int active_touches = 0;
struct tp_touch *t;
tp_for_each_touch(tp, t)
if (tp_touch_active(tp, t))
active_touches++;
if (active_touches != tp->gesture.finger_count) {
/* If all fingers are lifted immediately end the gesture */
if (active_touches == 0) {
tp_gesture_stop(tp, time);
tp->gesture.finger_count = 0;
tp->gesture.finger_count_pending = 0;
/* Immediately switch to new mode to avoid initial latency */
} else if (!tp->gesture.started) {
tp->gesture.finger_count = active_touches;
tp->gesture.finger_count_pending = 0;
/* Else debounce finger changes */
} else if (active_touches != tp->gesture.finger_count_pending) {
tp->gesture.finger_count_pending = active_touches;
libinput_timer_set(&tp->gesture.finger_count_switch_timer,
time + DEFAULT_GESTURE_SWITCH_TIMEOUT);
}
} else {
tp->gesture.finger_count_pending = 0;
}
}
int
tp_init_gesture(struct tp_dispatch *tp)
{
libinput_timer_init(&tp->gesture.finger_count_switch_timer,
tp->device->base.seat->libinput,
tp_gesture_finger_count_switch_timeout, tp);
return 0;
}
void
tp_remove_gesture(struct tp_dispatch *tp)
{
libinput_timer_cancel(&tp->gesture.finger_count_switch_timer);
}

View file

@ -227,7 +227,6 @@ tp_end_touch(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time)
} }
t->dirty = true; t->dirty = true;
t->is_pointer = false;
t->palm.is_palm = false; t->palm.is_palm = false;
t->state = TOUCH_END; t->state = TOUCH_END;
t->pinned.is_pinned = false; t->pinned.is_pinned = false;
@ -424,7 +423,6 @@ tp_unpin_finger(struct tp_dispatch *tp, struct tp_touch *t)
if (xdist * xdist + ydist * ydist >= if (xdist * xdist + ydist * ydist >=
tp->buttons.motion_dist * tp->buttons.motion_dist) { tp->buttons.motion_dist * tp->buttons.motion_dist) {
t->pinned.is_pinned = false; t->pinned.is_pinned = false;
tp_set_pointer(tp, t);
return; return;
} }
@ -439,14 +437,13 @@ tp_pin_fingers(struct tp_dispatch *tp)
struct tp_touch *t; struct tp_touch *t;
tp_for_each_touch(tp, t) { tp_for_each_touch(tp, t) {
t->is_pointer = false;
t->pinned.is_pinned = true; t->pinned.is_pinned = true;
t->pinned.center_x = t->x; t->pinned.center_x = t->x;
t->pinned.center_y = t->y; t->pinned.center_y = t->y;
} }
} }
static int int
tp_touch_active(struct tp_dispatch *tp, struct tp_touch *t) tp_touch_active(struct tp_dispatch *tp, struct tp_touch *t)
{ {
return (t->state == TOUCH_BEGIN || t->state == TOUCH_UPDATE) && return (t->state == TOUCH_BEGIN || t->state == TOUCH_UPDATE) &&
@ -456,21 +453,6 @@ tp_touch_active(struct tp_dispatch *tp, struct tp_touch *t)
tp_edge_scroll_touch_active(tp, t); tp_edge_scroll_touch_active(tp, t);
} }
void
tp_set_pointer(struct tp_dispatch *tp, struct tp_touch *t)
{
struct tp_touch *tmp = NULL;
/* Only set the touch as pointer if we don't have one yet */
tp_for_each_touch(tp, tmp) {
if (tmp->is_pointer)
return;
}
if (tp_touch_active(tp, t))
t->is_pointer = true;
}
static void static void
tp_palm_detect(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time) tp_palm_detect(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time)
{ {
@ -487,7 +469,6 @@ tp_palm_detect(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time)
int dirs = vector_get_direction(t->x - t->palm.x, t->y - t->palm.y); int dirs = vector_get_direction(t->x - t->palm.x, t->y - t->palm.y);
if ((dirs & DIRECTIONS) && !(dirs & ~DIRECTIONS)) { if ((dirs & DIRECTIONS) && !(dirs & ~DIRECTIONS)) {
t->palm.is_palm = false; t->palm.is_palm = false;
tp_set_pointer(tp, t);
} }
} }
return; return;
@ -512,153 +493,6 @@ tp_palm_detect(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time)
t->palm.y = t->y; t->palm.y = t->y;
} }
static void
tp_post_twofinger_scroll(struct tp_dispatch *tp, uint64_t time)
{
struct tp_touch *t;
int nchanged = 0;
double dx = 0, dy =0;
double tmpx, tmpy;
tp_for_each_touch(tp, t) {
if (tp_touch_active(tp, t) && t->dirty) {
nchanged++;
tp_get_delta(t, &tmpx, &tmpy);
dx += tmpx;
dy += tmpy;
}
/* Stop spurious MOTION events at the end of scrolling */
t->is_pointer = false;
}
if (nchanged == 0)
return;
dx /= nchanged;
dy /= nchanged;
tp_filter_motion(tp, &dx, &dy, NULL, NULL, time);
evdev_post_scroll(tp->device,
time,
LIBINPUT_POINTER_AXIS_SOURCE_FINGER,
dx, dy);
tp->scroll.twofinger_state = TWOFINGER_SCROLL_STATE_ACTIVE;
}
static void
tp_twofinger_stop_scroll(struct tp_dispatch *tp, uint64_t time)
{
struct tp_touch *t, *ptr = NULL;
int nfingers_down = 0;
evdev_stop_scroll(tp->device,
time,
LIBINPUT_POINTER_AXIS_SOURCE_FINGER);
/* If we were scrolling and now there's exactly 1 active finger,
switch back to pointer movement */
if (tp->scroll.twofinger_state == TWOFINGER_SCROLL_STATE_ACTIVE) {
tp_for_each_touch(tp, t) {
if (tp_touch_active(tp, t)) {
nfingers_down++;
if (ptr == NULL)
ptr = t;
}
}
if (nfingers_down == 1)
tp_set_pointer(tp, ptr);
}
tp->scroll.twofinger_state = TWOFINGER_SCROLL_STATE_NONE;
}
static int
tp_twofinger_scroll_post_events(struct tp_dispatch *tp, uint64_t time)
{
struct tp_touch *t;
int nfingers_down = 0;
/* No 2fg scrolling during tap-n-drag */
if (tp_tap_dragging(tp))
return 0;
/* No 2fg scrolling while a clickpad is clicked */
if (tp->buttons.is_clickpad && tp->buttons.state)
return 0;
/* Only count active touches for 2 finger scrolling */
tp_for_each_touch(tp, t) {
if (tp_touch_active(tp, t))
nfingers_down++;
}
if (nfingers_down == 2) {
tp_post_twofinger_scroll(tp, time);
return 1;
}
tp_twofinger_stop_scroll(tp, time);
return 0;
}
static void
tp_scroll_handle_state(struct tp_dispatch *tp, uint64_t time)
{
/* Note this must be always called, so that it knows the state of
* touches when the scroll-mode changes.
*/
tp_edge_scroll_handle_state(tp, time);
}
static int
tp_post_scroll_events(struct tp_dispatch *tp, uint64_t time)
{
struct libinput *libinput = tp->device->base.seat->libinput;
switch (tp->scroll.method) {
case LIBINPUT_CONFIG_SCROLL_NO_SCROLL:
break;
case LIBINPUT_CONFIG_SCROLL_2FG:
return tp_twofinger_scroll_post_events(tp, time);
case LIBINPUT_CONFIG_SCROLL_EDGE:
return tp_edge_scroll_post_events(tp, time);
case LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN:
log_bug_libinput(libinput, "Unexpected scroll mode\n");
break;
}
return 0;
}
static void
tp_stop_scroll_events(struct tp_dispatch *tp, uint64_t time)
{
struct libinput *libinput = tp->device->base.seat->libinput;
switch (tp->scroll.method) {
case LIBINPUT_CONFIG_SCROLL_NO_SCROLL:
break;
case LIBINPUT_CONFIG_SCROLL_2FG:
tp_twofinger_stop_scroll(tp, time);
break;
case LIBINPUT_CONFIG_SCROLL_EDGE:
tp_edge_scroll_stop_events(tp, time);
break;
case LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN:
log_bug_libinput(libinput, "Unexpected scroll mode\n");
break;
}
}
static void
tp_remove_scroll(struct tp_dispatch *tp)
{
tp_remove_edge_scroll(tp);
}
static void static void
tp_unhover_touches(struct tp_dispatch *tp, uint64_t time) tp_unhover_touches(struct tp_dispatch *tp, uint64_t time)
{ {
@ -749,7 +583,7 @@ tp_process_state(struct tp_dispatch *tp, uint64_t time)
} }
tp_button_handle_state(tp, time); tp_button_handle_state(tp, time);
tp_scroll_handle_state(tp, time); tp_edge_scroll_handle_state(tp, time);
/* /*
* We have a physical button down event on a clickpad. To avoid * We have a physical button down event on a clickpad. To avoid
@ -760,6 +594,8 @@ tp_process_state(struct tp_dispatch *tp, uint64_t time)
if ((tp->queued & TOUCHPAD_EVENT_BUTTON_PRESS) && if ((tp->queued & TOUCHPAD_EVENT_BUTTON_PRESS) &&
tp->buttons.is_clickpad) tp->buttons.is_clickpad)
tp_pin_fingers(tp); tp_pin_fingers(tp);
tp_gesture_handle_state(tp, time);
} }
static void static void
@ -790,63 +626,6 @@ tp_post_process_state(struct tp_dispatch *tp, uint64_t time)
tp->queued = TOUCHPAD_EVENT_NONE; tp->queued = TOUCHPAD_EVENT_NONE;
} }
static void
tp_get_pointer_delta(struct tp_dispatch *tp, double *dx, double *dy)
{
struct tp_touch *t = tp_current_touch(tp);
if (!t->is_pointer) {
tp_for_each_touch(tp, t) {
if (t->is_pointer)
break;
}
}
if (!t->is_pointer || !t->dirty)
return;
tp_get_delta(t, dx, dy);
}
static void
tp_get_active_touches_delta(struct tp_dispatch *tp, double *dx, double *dy)
{
struct tp_touch *t;
double tdx, tdy;
unsigned int i;
for (i = 0; i < tp->real_touches; i++) {
t = tp_get_touch(tp, i);
if (!tp_touch_active(tp, t) || !t->dirty)
continue;
tp_get_delta(t, &tdx, &tdy);
*dx += tdx;
*dy += tdy;
}
}
static void
tp_post_pointer_motion(struct tp_dispatch *tp, uint64_t time)
{
double dx = 0.0, dy = 0.0;
double dx_unaccel, dy_unaccel;
/* When a clickpad is clicked, combine motion of all active touches */
if (tp->buttons.is_clickpad && tp->buttons.state)
tp_get_active_touches_delta(tp, &dx, &dy);
else
tp_get_pointer_delta(tp, &dx, &dy);
tp_filter_motion(tp, &dx, &dy, &dx_unaccel, &dy_unaccel, time);
if (dx != 0.0 || dy != 0.0 || dx_unaccel != 0.0 || dy_unaccel != 0.0) {
pointer_notify_motion(&tp->device->base, time,
dx, dy, dx_unaccel, dy_unaccel);
}
}
static void static void
tp_post_events(struct tp_dispatch *tp, uint64_t time) tp_post_events(struct tp_dispatch *tp, uint64_t time)
{ {
@ -862,14 +641,15 @@ tp_post_events(struct tp_dispatch *tp, uint64_t time)
filter_motion |= tp_post_button_events(tp, time); filter_motion |= tp_post_button_events(tp, time);
if (filter_motion || tp->sendevents.trackpoint_active) { if (filter_motion || tp->sendevents.trackpoint_active) {
tp_stop_scroll_events(tp, time); tp_edge_scroll_stop_events(tp, time);
tp_gesture_stop(tp, time);
return; return;
} }
if (tp_post_scroll_events(tp, time) != 0) if (tp_edge_scroll_post_events(tp, time) != 0)
return; return;
tp_post_pointer_motion(tp, time); tp_gesture_post_events(tp, time);
} }
static void static void
@ -925,7 +705,8 @@ tp_remove(struct evdev_dispatch *dispatch)
tp_remove_tap(tp); tp_remove_tap(tp);
tp_remove_buttons(tp); tp_remove_buttons(tp);
tp_remove_sendevents(tp); tp_remove_sendevents(tp);
tp_remove_scroll(tp); tp_remove_edge_scroll(tp);
tp_remove_gesture(tp);
} }
static void static void
@ -1017,9 +798,8 @@ tp_trackpoint_event(uint64_t time, struct libinput_event *event, void *data)
return; return;
if (!tp->sendevents.trackpoint_active) { if (!tp->sendevents.trackpoint_active) {
evdev_stop_scroll(tp->device, tp_edge_scroll_stop_events(tp, time);
time, tp_gesture_stop(tp, time);
LIBINPUT_POINTER_AXIS_SOURCE_FINGER);
tp_tap_suspend(tp, time); tp_tap_suspend(tp, time);
tp->sendevents.trackpoint_active = true; tp->sendevents.trackpoint_active = true;
} }
@ -1254,11 +1034,14 @@ tp_scroll_config_scroll_method_set_method(struct libinput_device *device,
{ {
struct evdev_device *evdev = (struct evdev_device*)device; struct evdev_device *evdev = (struct evdev_device*)device;
struct tp_dispatch *tp = (struct tp_dispatch*)evdev->dispatch; struct tp_dispatch *tp = (struct tp_dispatch*)evdev->dispatch;
uint64_t time = libinput_now(device->seat->libinput);
if (method == tp->scroll.method) if (method == tp->scroll.method)
return LIBINPUT_CONFIG_STATUS_SUCCESS; return LIBINPUT_CONFIG_STATUS_SUCCESS;
tp_stop_scroll_events(tp, libinput_now(device->seat->libinput)); tp_edge_scroll_stop_events(tp, time);
tp_gesture_stop_twofinger_scroll(tp, time);
tp->scroll.method = method; tp->scroll.method = method;
return LIBINPUT_CONFIG_STATUS_SUCCESS; return LIBINPUT_CONFIG_STATUS_SUCCESS;
@ -1395,6 +1178,9 @@ tp_init(struct tp_dispatch *tp,
if (tp_init_scroll(tp, device) != 0) if (tp_init_scroll(tp, device) != 0)
return -1; return -1;
if (tp_init_gesture(tp) != 0)
return -1;
device->seat_caps |= EVDEV_DEVICE_POINTER; device->seat_caps |= EVDEV_DEVICE_POINTER;
return 0; return 0;

View file

@ -117,11 +117,6 @@ enum tp_edge_scroll_touch_state {
EDGE_SCROLL_TOUCH_STATE_AREA, EDGE_SCROLL_TOUCH_STATE_AREA,
}; };
enum tp_twofinger_scroll_state {
TWOFINGER_SCROLL_STATE_NONE,
TWOFINGER_SCROLL_STATE_ACTIVE,
};
struct tp_motion { struct tp_motion {
int32_t x; int32_t x;
int32_t y; int32_t y;
@ -132,7 +127,6 @@ struct tp_touch {
enum touch_state state; enum touch_state state;
bool has_ended; /* TRACKING_ID == -1 */ bool has_ended; /* TRACKING_ID == -1 */
bool dirty; bool dirty;
bool is_pointer; /* the pointer-controlling touch */
int32_t x; int32_t x;
int32_t y; int32_t y;
uint64_t millis; uint64_t millis;
@ -215,6 +209,13 @@ struct tp_dispatch {
double y_scale_coeff; double y_scale_coeff;
} accel; } accel;
struct {
bool started;
unsigned int finger_count;
unsigned int finger_count_pending;
struct libinput_timer finger_count_switch_timer;
} gesture;
struct { struct {
bool is_clickpad; /* true for clickpads */ bool is_clickpad; /* true for clickpads */
bool has_topbuttons; bool has_topbuttons;
@ -252,7 +253,6 @@ struct tp_dispatch {
enum libinput_config_scroll_method method; enum libinput_config_scroll_method method;
int32_t right_edge; int32_t right_edge;
int32_t bottom_edge; int32_t bottom_edge;
enum tp_twofinger_scroll_state twofinger_state;
} scroll; } scroll;
enum touchpad_event queued; enum touchpad_event queued;
@ -286,15 +286,15 @@ struct tp_dispatch {
void void
tp_get_delta(struct tp_touch *t, double *dx, double *dy); tp_get_delta(struct tp_touch *t, double *dx, double *dy);
void
tp_set_pointer(struct tp_dispatch *tp, struct tp_touch *t);
void void
tp_filter_motion(struct tp_dispatch *tp, tp_filter_motion(struct tp_dispatch *tp,
double *dx, double *dy, double *dx, double *dy,
double *dx_unaccel, double *dy_unaccel, double *dx_unaccel, double *dy_unaccel,
uint64_t time); uint64_t time);
int
tp_touch_active(struct tp_dispatch *tp, struct tp_touch *t);
int int
tp_tap_handle_state(struct tp_dispatch *tp, uint64_t time); tp_tap_handle_state(struct tp_dispatch *tp, uint64_t time);
@ -367,4 +367,22 @@ tp_edge_scroll_stop_events(struct tp_dispatch *tp, uint64_t time);
int int
tp_edge_scroll_touch_active(struct tp_dispatch *tp, struct tp_touch *t); tp_edge_scroll_touch_active(struct tp_dispatch *tp, struct tp_touch *t);
int
tp_init_gesture(struct tp_dispatch *tp);
void
tp_remove_gesture(struct tp_dispatch *tp);
void
tp_gesture_stop(struct tp_dispatch *tp, uint64_t time);
void
tp_gesture_handle_state(struct tp_dispatch *tp, uint64_t time);
void
tp_gesture_post_events(struct tp_dispatch *tp, uint64_t time);
void
tp_gesture_stop_twofinger_scroll(struct tp_dispatch *tp, uint64_t time);
#endif #endif

View file

@ -58,6 +58,7 @@ enum evdev_device_udev_tags {
EVDEV_UDEV_TAG_TABLET = (1 << 5), EVDEV_UDEV_TAG_TABLET = (1 << 5),
EVDEV_UDEV_TAG_JOYSTICK = (1 << 6), EVDEV_UDEV_TAG_JOYSTICK = (1 << 6),
EVDEV_UDEV_TAG_ACCELEROMETER = (1 << 7), EVDEV_UDEV_TAG_ACCELEROMETER = (1 << 7),
EVDEV_UDEV_TAG_BUTTONSET = (1 << 8),
}; };
struct evdev_udev_tag_match { struct evdev_udev_tag_match {
@ -73,6 +74,7 @@ static const struct evdev_udev_tag_match evdev_udev_tag_matches[] = {
{"ID_INPUT_TOUCHPAD", EVDEV_UDEV_TAG_TOUCHPAD}, {"ID_INPUT_TOUCHPAD", EVDEV_UDEV_TAG_TOUCHPAD},
{"ID_INPUT_TOUCHSCREEN", EVDEV_UDEV_TAG_TOUCHSCREEN}, {"ID_INPUT_TOUCHSCREEN", EVDEV_UDEV_TAG_TOUCHSCREEN},
{"ID_INPUT_TABLET", EVDEV_UDEV_TAG_TABLET}, {"ID_INPUT_TABLET", EVDEV_UDEV_TAG_TABLET},
{"ID_INPUT_TABLET_PAD", EVDEV_UDEV_TAG_BUTTONSET},
{"ID_INPUT_JOYSTICK", EVDEV_UDEV_TAG_JOYSTICK}, {"ID_INPUT_JOYSTICK", EVDEV_UDEV_TAG_JOYSTICK},
{"ID_INPUT_ACCELEROMETER", EVDEV_UDEV_TAG_ACCELEROMETER}, {"ID_INPUT_ACCELEROMETER", EVDEV_UDEV_TAG_ACCELEROMETER},
@ -524,6 +526,14 @@ evdev_process_touch(struct evdev_device *device,
{ {
switch (e->code) { switch (e->code) {
case ABS_MT_SLOT: case ABS_MT_SLOT:
if ((size_t)e->value >= device->mt.slots_len) {
log_bug_libinput(device->base.seat->libinput,
"%s exceeds slots (%d of %d)\n",
device->devname,
e->value,
device->mt.slots_len);
e->value = device->mt.slots_len - 1;
}
evdev_flush_pending_event(device, time); evdev_flush_pending_event(device, time);
device->mt.slot = e->value; device->mt.slot = e->value;
break; break;
@ -1400,7 +1410,7 @@ evdev_configure_device(struct evdev_device *device)
} }
log_info(libinput, log_info(libinput,
"input device '%s', %s is tagged by udev as:%s%s%s%s%s%s%s\n", "input device '%s', %s is tagged by udev as:%s%s%s%s%s%s%s%s\n",
device->devname, devnode, device->devname, devnode,
udev_tags & EVDEV_UDEV_TAG_KEYBOARD ? " Keyboard" : "", udev_tags & EVDEV_UDEV_TAG_KEYBOARD ? " Keyboard" : "",
udev_tags & EVDEV_UDEV_TAG_MOUSE ? " Mouse" : "", udev_tags & EVDEV_UDEV_TAG_MOUSE ? " Mouse" : "",
@ -1408,7 +1418,8 @@ evdev_configure_device(struct evdev_device *device)
udev_tags & EVDEV_UDEV_TAG_TOUCHSCREEN ? " Touchscreen" : "", udev_tags & EVDEV_UDEV_TAG_TOUCHSCREEN ? " Touchscreen" : "",
udev_tags & EVDEV_UDEV_TAG_TABLET ? " Tablet" : "", udev_tags & EVDEV_UDEV_TAG_TABLET ? " Tablet" : "",
udev_tags & EVDEV_UDEV_TAG_JOYSTICK ? " Joystick" : "", udev_tags & EVDEV_UDEV_TAG_JOYSTICK ? " Joystick" : "",
udev_tags & EVDEV_UDEV_TAG_ACCELEROMETER ? " Accelerometer" : ""); udev_tags & EVDEV_UDEV_TAG_ACCELEROMETER ? " Accelerometer" : "",
udev_tags & EVDEV_UDEV_TAG_BUTTONSET ? " Buttonset" : "");
/* libwacom *adds* TABLET, TOUCHPAD but leaves JOYSTICK in place, so /* libwacom *adds* TABLET, TOUCHPAD but leaves JOYSTICK in place, so
make sure we only ignore real joystick devices */ make sure we only ignore real joystick devices */
@ -1419,6 +1430,14 @@ evdev_configure_device(struct evdev_device *device)
return -1; return -1;
} }
/* libwacom assigns tablet _and_ tablet_pad to the pad devices */
if (udev_tags & EVDEV_UDEV_TAG_BUTTONSET) {
log_info(libinput,
"input device '%s', %s is a buttonset, ignoring\n",
device->devname, devnode);
return -1;
}
if (libevdev_has_event_type(evdev, EV_ABS)) { if (libevdev_has_event_type(evdev, EV_ABS)) {
if ((absinfo = libevdev_get_abs_info(evdev, ABS_X))) { if ((absinfo = libevdev_get_abs_info(evdev, ABS_X))) {
@ -1467,10 +1486,9 @@ evdev_configure_device(struct evdev_device *device)
if (!device->mtdev) if (!device->mtdev)
return -1; return -1;
num_slots = device->mtdev->caps.slot.maximum; /* pick 10 slots as default for type A
if (device->mtdev->caps.slot.minimum < 0 || devices. */
num_slots <= 0) num_slots = 10;
return -1;
active_slot = device->mtdev->caps.slot.value; active_slot = device->mtdev->caps.slot.value;
} else { } else {
num_slots = libevdev_get_num_slots(device->evdev); num_slots = libevdev_get_num_slots(device->evdev);

View file

@ -48,8 +48,7 @@ enum libinput_log_priority {
* @ingroup device * @ingroup device
* *
* Capabilities on a device. A device may have one or more capabilities * Capabilities on a device. A device may have one or more capabilities
* at a time, and capabilities may appear or disappear during the * at a time, capabilities remain static for the lifetime of the device.
* lifetime of the device.
*/ */
enum libinput_device_capability { enum libinput_device_capability {
LIBINPUT_DEVICE_CAP_KEYBOARD = 0, LIBINPUT_DEVICE_CAP_KEYBOARD = 0,
@ -94,7 +93,8 @@ enum libinput_button_state {
/** /**
* @ingroup device * @ingroup device
* *
* Axes on a device that are not x or y coordinates. * Axes on a device with the capability @ref LIBINPUT_DEVICE_CAP_POINTER
* that are not x or y coordinates.
* *
* The two scroll axes @ref LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL and * The two scroll axes @ref LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL and
* @ref LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL are engaged separately, * @ref LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL are engaged separately,
@ -411,9 +411,9 @@ libinput_event_get_context(struct libinput_event *event);
/** /**
* @ingroup event * @ingroup event
* *
* Return the device associated with this event, if applicable. For device * Return the device associated with this event. For device added/removed
* added/removed events this is the device added or removed. For all other * events this is the device added or removed. For all other device events,
* device events, this is the device that generated the event. * this is the device that generated the event.
* *
* This device is not refcounted and its lifetime is that of the event. Use * This device is not refcounted and its lifetime is that of the event. Use
* libinput_device_ref() before using the device outside of this scope. * libinput_device_ref() before using the device outside of this scope.
@ -544,10 +544,10 @@ libinput_event_keyboard_get_base_event(struct libinput_event_keyboard *event);
* of keys pressed on all devices on the associated seat after the event was * of keys pressed on all devices on the associated seat after the event was
* triggered. * triggered.
* *
" @note It is an application bug to call this function for events other than * @note It is an application bug to call this function for events other than
* @ref LIBINPUT_EVENT_KEYBOARD_KEY. For other events, this function returns 0. * @ref LIBINPUT_EVENT_KEYBOARD_KEY. For other events, this function returns 0.
* *
* @return the seat wide pressed key count for the key of this event * @return The seat wide pressed key count for the key of this event
*/ */
uint32_t uint32_t
libinput_event_keyboard_get_seat_key_count( libinput_event_keyboard_get_seat_key_count(
@ -584,7 +584,7 @@ libinput_event_pointer_get_time(struct libinput_event_pointer *event);
* @note It is an application bug to call this function for events other than * @note It is an application bug to call this function for events other than
* @ref LIBINPUT_EVENT_POINTER_MOTION. * @ref LIBINPUT_EVENT_POINTER_MOTION.
* *
* @return the relative x movement since the last event * @return The relative x movement since the last event
*/ */
double double
libinput_event_pointer_get_dx(struct libinput_event_pointer *event); libinput_event_pointer_get_dx(struct libinput_event_pointer *event);
@ -605,7 +605,7 @@ libinput_event_pointer_get_dx(struct libinput_event_pointer *event);
* @note It is an application bug to call this function for events other than * @note It is an application bug to call this function for events other than
* @ref LIBINPUT_EVENT_POINTER_MOTION. * @ref LIBINPUT_EVENT_POINTER_MOTION.
* *
* @return the relative y movement since the last event * @return The relative y movement since the last event
*/ */
double double
libinput_event_pointer_get_dy(struct libinput_event_pointer *event); libinput_event_pointer_get_dy(struct libinput_event_pointer *event);
@ -625,7 +625,7 @@ libinput_event_pointer_get_dy(struct libinput_event_pointer *event);
* @note It is an application bug to call this function for events other than * @note It is an application bug to call this function for events other than
* @ref LIBINPUT_EVENT_POINTER_MOTION. * @ref LIBINPUT_EVENT_POINTER_MOTION.
* *
* @return the unaccelerated relative x movement since the last event * @return The unaccelerated relative x movement since the last event
*/ */
double double
libinput_event_pointer_get_dx_unaccelerated( libinput_event_pointer_get_dx_unaccelerated(
@ -646,7 +646,7 @@ libinput_event_pointer_get_dx_unaccelerated(
* @note It is an application bug to call this function for events other than * @note It is an application bug to call this function for events other than
* @ref LIBINPUT_EVENT_POINTER_MOTION. * @ref LIBINPUT_EVENT_POINTER_MOTION.
* *
* @return the unaccelerated relative y movement since the last event * @return The unaccelerated relative y movement since the last event
*/ */
double double
libinput_event_pointer_get_dy_unaccelerated( libinput_event_pointer_get_dy_unaccelerated(
@ -665,7 +665,7 @@ libinput_event_pointer_get_dy_unaccelerated(
* @note It is an application bug to call this function for events other than * @note It is an application bug to call this function for events other than
* @ref LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE. * @ref LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE.
* *
* @return the current absolute x coordinate * @return The current absolute x coordinate
*/ */
double double
libinput_event_pointer_get_absolute_x(struct libinput_event_pointer *event); libinput_event_pointer_get_absolute_x(struct libinput_event_pointer *event);
@ -683,7 +683,7 @@ libinput_event_pointer_get_absolute_x(struct libinput_event_pointer *event);
* @note It is an application bug to call this function for events other than * @note It is an application bug to call this function for events other than
* @ref LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE. * @ref LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE.
* *
* @return the current absolute y coordinate * @return The current absolute y coordinate
*/ */
double double
libinput_event_pointer_get_absolute_y(struct libinput_event_pointer *event); libinput_event_pointer_get_absolute_y(struct libinput_event_pointer *event);
@ -703,7 +703,7 @@ libinput_event_pointer_get_absolute_y(struct libinput_event_pointer *event);
* *
* @param event The libinput pointer event * @param event The libinput pointer event
* @param width The current output screen width * @param width The current output screen width
* @return the current absolute x coordinate transformed to a screen coordinate * @return The current absolute x coordinate transformed to a screen coordinate
*/ */
double double
libinput_event_pointer_get_absolute_x_transformed( libinput_event_pointer_get_absolute_x_transformed(
@ -725,7 +725,7 @@ libinput_event_pointer_get_absolute_x_transformed(
* *
* @param event The libinput pointer event * @param event The libinput pointer event
* @param height The current output screen height * @param height The current output screen height
* @return the current absolute y coordinate transformed to a screen coordinate * @return The current absolute y coordinate transformed to a screen coordinate
*/ */
double double
libinput_event_pointer_get_absolute_y_transformed( libinput_event_pointer_get_absolute_y_transformed(
@ -742,7 +742,7 @@ libinput_event_pointer_get_absolute_y_transformed(
* @note It is an application bug to call this function for events other than * @note It is an application bug to call this function for events other than
* @ref LIBINPUT_EVENT_POINTER_BUTTON. * @ref LIBINPUT_EVENT_POINTER_BUTTON.
* *
* @return the button triggering this event * @return The button triggering this event
*/ */
uint32_t uint32_t
libinput_event_pointer_get_button(struct libinput_event_pointer *event); libinput_event_pointer_get_button(struct libinput_event_pointer *event);
@ -757,7 +757,7 @@ libinput_event_pointer_get_button(struct libinput_event_pointer *event);
* @note It is an application bug to call this function for events other than * @note It is an application bug to call this function for events other than
* @ref LIBINPUT_EVENT_POINTER_BUTTON. * @ref LIBINPUT_EVENT_POINTER_BUTTON.
* *
* @return the button state triggering this event * @return The button state triggering this event
*/ */
enum libinput_button_state enum libinput_button_state
libinput_event_pointer_get_button_state(struct libinput_event_pointer *event); libinput_event_pointer_get_button_state(struct libinput_event_pointer *event);
@ -769,11 +769,11 @@ libinput_event_pointer_get_button_state(struct libinput_event_pointer *event);
* total number of buttons pressed on all devices on the associated seat * total number of buttons pressed on all devices on the associated seat
* after the event was triggered. * after the event was triggered.
* *
" @note It is an application bug to call this function for events other than * @note It is an application bug to call this function for events other than
* @ref LIBINPUT_EVENT_POINTER_BUTTON. For other events, this function * @ref LIBINPUT_EVENT_POINTER_BUTTON. For other events, this function
* returns 0. * returns 0.
* *
* @return the seat wide pressed button count for the key of this event * @return The seat wide pressed button count for the key of this event
*/ */
uint32_t uint32_t
libinput_event_pointer_get_seat_button_count( libinput_event_pointer_get_seat_button_count(
@ -788,7 +788,7 @@ libinput_event_pointer_get_seat_button_count(
* libinput_event_pointer_get_axis_value() returns a value of 0, the event * libinput_event_pointer_get_axis_value() returns a value of 0, the event
* is a scroll stop event. * is a scroll stop event.
* *
* @return non-zero if this event contains a value for this axis * @return Non-zero if this event contains a value for this axis
*/ */
int int
libinput_event_pointer_has_axis(struct libinput_event_pointer *event, libinput_event_pointer_has_axis(struct libinput_event_pointer *event,
@ -814,7 +814,7 @@ libinput_event_pointer_has_axis(struct libinput_event_pointer *event,
* @note It is an application bug to call this function for events other than * @note It is an application bug to call this function for events other than
* @ref LIBINPUT_EVENT_POINTER_AXIS. * @ref LIBINPUT_EVENT_POINTER_AXIS.
* *
* @return the axis value of this event * @return The axis value of this event
* *
* @see libinput_event_pointer_get_axis_value_discrete * @see libinput_event_pointer_get_axis_value_discrete
*/ */
@ -855,7 +855,7 @@ libinput_event_pointer_get_axis_value(struct libinput_event_pointer *event,
* @note It is an application bug to call this function for events other than * @note It is an application bug to call this function for events other than
* @ref LIBINPUT_EVENT_POINTER_AXIS. * @ref LIBINPUT_EVENT_POINTER_AXIS.
* *
* @return the source for this axis event * @return The source for this axis event
*/ */
enum libinput_pointer_axis_source enum libinput_pointer_axis_source
libinput_event_pointer_get_axis_source(struct libinput_event_pointer *event); libinput_event_pointer_get_axis_source(struct libinput_event_pointer *event);
@ -867,7 +867,7 @@ libinput_event_pointer_get_axis_source(struct libinput_event_pointer *event);
* value translates into a discrete step depends on the source. * value translates into a discrete step depends on the source.
* *
* If the source is @ref LIBINPUT_POINTER_AXIS_SOURCE_WHEEL, the discrete * If the source is @ref LIBINPUT_POINTER_AXIS_SOURCE_WHEEL, the discrete
* value correspond to the number of physical mouse clicks. * value correspond to the number of physical mouse wheel clicks.
* *
* If the source is @ref LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS or @ref * If the source is @ref LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS or @ref
* LIBINPUT_POINTER_AXIS_SOURCE_FINGER, the discrete value is always 0. * LIBINPUT_POINTER_AXIS_SOURCE_FINGER, the discrete value is always 0.
@ -947,7 +947,7 @@ libinput_event_touch_get_seat_slot(struct libinput_event_touch *event);
* LIBINPUT_EVENT_TOUCH_DOWN and @ref LIBINPUT_EVENT_TOUCH_MOTION. * LIBINPUT_EVENT_TOUCH_DOWN and @ref LIBINPUT_EVENT_TOUCH_MOTION.
* *
* @param event The libinput touch event * @param event The libinput touch event
* @return the current absolute x coordinate * @return The current absolute x coordinate
*/ */
double double
libinput_event_touch_get_x(struct libinput_event_touch *event); libinput_event_touch_get_x(struct libinput_event_touch *event);
@ -965,7 +965,7 @@ libinput_event_touch_get_x(struct libinput_event_touch *event);
* @ref LIBINPUT_EVENT_TOUCH_MOTION. * @ref LIBINPUT_EVENT_TOUCH_MOTION.
* *
* @param event The libinput touch event * @param event The libinput touch event
* @return the current absolute y coordinate * @return The current absolute y coordinate
*/ */
double double
libinput_event_touch_get_y(struct libinput_event_touch *event); libinput_event_touch_get_y(struct libinput_event_touch *event);
@ -981,7 +981,7 @@ libinput_event_touch_get_y(struct libinput_event_touch *event);
* *
* @param event The libinput touch event * @param event The libinput touch event
* @param width The current output screen width * @param width The current output screen width
* @return the current absolute x coordinate transformed to a screen coordinate * @return The current absolute x coordinate transformed to a screen coordinate
*/ */
double double
libinput_event_touch_get_x_transformed(struct libinput_event_touch *event, libinput_event_touch_get_x_transformed(struct libinput_event_touch *event,
@ -998,7 +998,7 @@ libinput_event_touch_get_x_transformed(struct libinput_event_touch *event,
* *
* @param event The libinput touch event * @param event The libinput touch event
* @param height The current output screen height * @param height The current output screen height
* @return the current absolute y coordinate transformed to a screen coordinate * @return The current absolute y coordinate transformed to a screen coordinate
*/ */
double double
libinput_event_touch_get_y_transformed(struct libinput_event_touch *event, libinput_event_touch_get_y_transformed(struct libinput_event_touch *event,
@ -1390,7 +1390,7 @@ struct libinput_interface {
* @param user_data The user_data provided in * @param user_data The user_data provided in
* libinput_udev_create_context() * libinput_udev_create_context()
* *
* @return the file descriptor, or a negative errno on failure. * @return The file descriptor, or a negative errno on failure.
*/ */
int (*open_restricted)(const char *path, int flags, void *user_data); int (*open_restricted)(const char *path, int flags, void *user_data);
/** /**
@ -1520,7 +1520,7 @@ libinput_path_remove_device(struct libinput_device *device);
* libinput keeps a single file descriptor for all events. Call into * libinput keeps a single file descriptor for all events. Call into
* libinput_dispatch() if any events become available on this fd. * libinput_dispatch() if any events become available on this fd.
* *
* @return the file descriptor used to notify of pending events. * @return The file descriptor used to notify of pending events.
*/ */
int int
libinput_get_fd(struct libinput *libinput); libinput_get_fd(struct libinput *libinput);
@ -1532,7 +1532,11 @@ libinput_get_fd(struct libinput *libinput);
* and processes them internally. Use libinput_get_event() to retrieve the * and processes them internally. Use libinput_get_event() to retrieve the
* events. * events.
* *
* Dispatching does not necessarily queue libinput events. * Dispatching does not necessarily queue libinput events. This function
* should be called immediately once data is available on the file
* descriptor returned by libinput_get_fd(). libinput has a number of
* timing-sensitive features (e.g. tap-to-click), any delay in calling
* libinput_dispatch() may prevent these features from working correctly.
* *
* @param libinput A previously initialized libinput context * @param libinput A previously initialized libinput context
* *
@ -1563,8 +1567,8 @@ libinput_get_event(struct libinput *libinput);
* libinput_get_event() returns that event. * libinput_get_event() returns that event.
* *
* @param libinput A previously initialized libinput context * @param libinput A previously initialized libinput context
* @return The event type of the next available event or LIBINPUT_EVENT_NONE * @return The event type of the next available event or @ref
* if no event is availble. * LIBINPUT_EVENT_NONE if no event is availble.
*/ */
enum libinput_event_type enum libinput_event_type
libinput_next_event_type(struct libinput *libinput); libinput_next_event_type(struct libinput *libinput);
@ -1572,6 +1576,10 @@ libinput_next_event_type(struct libinput *libinput);
/** /**
* @ingroup base * @ingroup base
* *
* Set caller-specific data associated with this context. libinput does
* not manage, look at, or modify this data. The caller must ensure the
* data is valid.
*
* @param libinput A previously initialized libinput context * @param libinput A previously initialized libinput context
* @param user_data Caller-specific data passed to the various callback * @param user_data Caller-specific data passed to the various callback
* interfaces. * interfaces.
@ -1583,8 +1591,10 @@ libinput_set_user_data(struct libinput *libinput,
/** /**
* @ingroup base * @ingroup base
* *
* Get the caller-specific data associated with this context, if any.
*
* @param libinput A previously initialized libinput context * @param libinput A previously initialized libinput context
* @return the caller-specific data previously assigned in * @return The caller-specific data previously assigned in
* libinput_create_udev(). * libinput_create_udev().
*/ */
void * void *
@ -1644,10 +1654,11 @@ libinput_unref(struct libinput *libinput);
/** /**
* @ingroup base * @ingroup base
* *
* Set the global log priority. Messages with priorities equal to or * Set the log priority for the libinput context. Messages with priorities
* higher than the argument will be printed to the current log handler. * equal to or higher than the argument will be printed to the context's
* log handler.
* *
* The default log priority is LIBINPUT_LOG_PRIORITY_ERROR. * The default log priority is @ref LIBINPUT_LOG_PRIORITY_ERROR.
* *
* @param libinput A previously initialized libinput context * @param libinput A previously initialized libinput context
* @param priority The minimum priority of log messages to print. * @param priority The minimum priority of log messages to print.
@ -1662,10 +1673,10 @@ libinput_log_set_priority(struct libinput *libinput,
/** /**
* @ingroup base * @ingroup base
* *
* Get the global log priority. Messages with priorities equal to or * Get the context's log priority. Messages with priorities equal to or
* higher than the argument will be printed to the current log handler. * higher than the argument will be printed to the current log handler.
* *
* The default log priority is LIBINPUT_LOG_PRIORITY_ERROR. * The default log priority is @ref LIBINPUT_LOG_PRIORITY_ERROR.
* *
* @param libinput A previously initialized libinput context * @param libinput A previously initialized libinput context
* @return The minimum priority of log messages to print. * @return The minimum priority of log messages to print.
@ -1698,8 +1709,8 @@ typedef void (*libinput_log_handler)(struct libinput *libinput,
/** /**
* @ingroup base * @ingroup base
* *
* Set the global log handler. Messages with priorities equal to or higher * Set the context's log handler. Messages with priorities equal to or
* than the current log priority will be passed to the given * higher than the context's log priority will be passed to the given
* log handler. * log handler.
* *
* The default log handler prints to stderr. * The default log handler prints to stderr.
@ -1727,7 +1738,7 @@ libinput_log_set_handler(struct libinput *libinput,
* @ingroup seat * @ingroup seat
* *
* Increase the refcount of the seat. A seat will be freed whenever the * Increase the refcount of the seat. A seat will be freed whenever the
* refcount reaches 0. This may happen during dispatch if the * refcount reaches 0. This may happen during libinput_dispatch() if the
* seat was removed from the system. A caller must ensure to reference * seat was removed from the system. A caller must ensure to reference
* the seat correctly to avoid dangling pointers. * the seat correctly to avoid dangling pointers.
* *
@ -1741,7 +1752,7 @@ libinput_seat_ref(struct libinput_seat *seat);
* @ingroup seat * @ingroup seat
* *
* Decrease the refcount of the seat. A seat will be freed whenever the * Decrease the refcount of the seat. A seat will be freed whenever the
* refcount reaches 0. This may happen during dispatch if the * refcount reaches 0. This may happen during libinput_dispatch() if the
* seat was removed from the system. A caller must ensure to reference * seat was removed from the system. A caller must ensure to reference
* the seat correctly to avoid dangling pointers. * the seat correctly to avoid dangling pointers.
* *
@ -1802,7 +1813,7 @@ libinput_seat_get_context(struct libinput_seat *seat);
* be available to the caller. * be available to the caller.
* *
* @param seat A previously obtained seat * @param seat A previously obtained seat
* @return the physical name of this seat * @return The physical name of this seat
*/ */
const char * const char *
libinput_seat_get_physical_name(struct libinput_seat *seat); libinput_seat_get_physical_name(struct libinput_seat *seat);
@ -1814,7 +1825,7 @@ libinput_seat_get_physical_name(struct libinput_seat *seat);
* of devices within the compositor. * of devices within the compositor.
* *
* @param seat A previously obtained seat * @param seat A previously obtained seat
* @return the logical name of this seat * @return The logical name of this seat
*/ */
const char * const char *
libinput_seat_get_logical_name(struct libinput_seat *seat); libinput_seat_get_logical_name(struct libinput_seat *seat);
@ -1827,9 +1838,9 @@ libinput_seat_get_logical_name(struct libinput_seat *seat);
* @ingroup device * @ingroup device
* *
* Increase the refcount of the input device. An input device will be freed * Increase the refcount of the input device. An input device will be freed
* whenever the refcount reaches 0. This may happen during dispatch if the * whenever the refcount reaches 0. This may happen during
* device was removed from the system. A caller must ensure to reference * libinput_dispatch() if the device was removed from the system. A caller
* the device correctly to avoid dangling pointers. * must ensure to reference the device correctly to avoid dangling pointers.
* *
* @param device A previously obtained device * @param device A previously obtained device
* @return The passed device * @return The passed device
@ -1841,9 +1852,9 @@ libinput_device_ref(struct libinput_device *device);
* @ingroup device * @ingroup device
* *
* Decrease the refcount of the input device. An input device will be freed * Decrease the refcount of the input device. An input device will be freed
* whenever the refcount reaches 0. This may happen during dispatch if the * whenever the refcount reaches 0. This may happen during libinput_dispatch
* device was removed from the system. A caller must ensure to reference * if the device was removed from the system. A caller must ensure to
* the device correctly to avoid dangling pointers. * reference the device correctly to avoid dangling pointers.
* *
* @param device A previously obtained device * @param device A previously obtained device
* @return NULL if the device was destroyed, otherwise the passed device * @return NULL if the device was destroyed, otherwise the passed device
@ -2011,7 +2022,7 @@ libinput_device_get_id_vendor(struct libinput_device *device);
* beyond the boundaries of this output. An absolute device has its input * beyond the boundaries of this output. An absolute device has its input
* coordinates mapped to the extents of this output. * coordinates mapped to the extents of this output.
* *
* @return the name of the output this device is mapped to, or NULL if no * @return The name of the output this device is mapped to, or NULL if no
* output is set * output is set
*/ */
const char * const char *
@ -2020,7 +2031,8 @@ libinput_device_get_output_name(struct libinput_device *device);
/** /**
* @ingroup device * @ingroup device
* *
* Get the seat associated with this input device. * Get the seat associated with this input device, see @ref seats for
* details.
* *
* A seat can be uniquely identified by the physical and logical seat name. * A seat can be uniquely identified by the physical and logical seat name.
* There will ever be only one seat instance with a given physical and logical * There will ever be only one seat instance with a given physical and logical
@ -2040,10 +2052,13 @@ libinput_device_get_seat(struct libinput_device *device);
* device and adding it to the new seat. * device and adding it to the new seat.
* *
* This command is identical to physically unplugging the device, then * This command is identical to physically unplugging the device, then
* re-plugging it as member of the new seat, * re-plugging it as member of the new seat. libinput will generate a
* @ref LIBINPUT_EVENT_DEVICE_REMOVED and @ref LIBINPUT_EVENT_DEVICE_ADDED * @ref LIBINPUT_EVENT_DEVICE_REMOVED event and this @ref libinput_device is
* events are sent accordingly. Those events mark the end of the lifetime * considered removed from the context; it will not generate further events
* of this device and the start of a new device. * and will be freed when the refcount reaches zero.
* A @ref LIBINPUT_EVENT_DEVICE_ADDED event is generated with a new @ref
* libinput_device handle. It is the caller's responsibility to update
* references to the new device accordingly.
* *
* If the logical seat name already exists in the device's physical seat, * If the logical seat name already exists in the device's physical seat,
* the device is added to this seat. Otherwise, a new seat is created. * the device is added to this seat. Otherwise, a new seat is created.
@ -2064,7 +2079,9 @@ libinput_device_set_seat_logical_name(struct libinput_device *device,
* *
* Return a udev handle to the device that is this libinput device, if any. * Return a udev handle to the device that is this libinput device, if any.
* The returned handle has a refcount of at least 1, the caller must call * The returned handle has a refcount of at least 1, the caller must call
* udev_device_unref() once to release the associated resources. * <i>udev_device_unref()</i> once to release the associated resources.
* See the [libudev documentation]
* (http://www.freedesktop.org/software/systemd/libudev/) for details.
* *
* Some devices may not have a udev device, or the udev device may be * Some devices may not have a udev device, or the udev device may be
* unobtainable. This function returns NULL if no udev device was available. * unobtainable. This function returns NULL if no udev device was available.
@ -2098,7 +2115,7 @@ libinput_device_led_update(struct libinput_device *device,
* *
* Check if the given device has the specified capability * Check if the given device has the specified capability
* *
* @return 1 if the given device has the capability or 0 if not * @return Non-zero if the given device has the capability or zero otherwise
*/ */
int int
libinput_device_has_capability(struct libinput_device *device, libinput_device_has_capability(struct libinput_device *device,
@ -2127,10 +2144,10 @@ libinput_device_get_size(struct libinput_device *device,
* @ingroup device * @ingroup device
* *
* Check if a @ref LIBINPUT_DEVICE_CAP_POINTER device has a button with the * Check if a @ref LIBINPUT_DEVICE_CAP_POINTER device has a button with the
* passed in code (see linux/input.h). * given code (see linux/input.h).
* *
* @param device A current input device * @param device A current input device
* @param code button code to check for * @param code Button code to check for, e.g. <i>BTN_LEFT</i>
* *
* @return 1 if the device supports this button code, 0 if it does not, -1 * @return 1 if the device supports this button code, 0 if it does not, -1
* on error. * on error.
@ -2150,9 +2167,10 @@ libinput_device_has_button(struct libinput_device *device, uint32_t code) LIBINP
* @ingroup device * @ingroup device
* *
* Increase the refcount of the device group. A device group will be freed * Increase the refcount of the device group. A device group will be freed
* whenever the refcount reaches 0. This may happen during dispatch if all * whenever the refcount reaches 0. This may happen during
* devices of this group were removed from the system. A caller must ensure * libinput_dispatch() if all devices of this group were removed from the
* to reference the device group correctly to avoid dangling pointers. * system. A caller must ensure to reference the device group correctly to
* avoid dangling pointers.
* *
* @param group A previously obtained device group * @param group A previously obtained device group
* @return The passed device group * @return The passed device group
@ -2164,9 +2182,10 @@ libinput_device_group_ref(struct libinput_device_group *group);
* @ingroup device * @ingroup device
* *
* Decrease the refcount of the device group. A device group will be freed * Decrease the refcount of the device group. A device group will be freed
* whenever the refcount reaches 0. This may happen during dispatch if all * whenever the refcount reaches 0. This may happen during
* devices of this group were removed from the system. A caller must ensure * libinput_dispatch() if all devices of this group were removed from the
* to reference the device group correctly to avoid dangling pointers. * system. A caller must ensure to reference the device group correctly to
* avoid dangling pointers.
* *
* @param group A previously obtained device group * @param group A previously obtained device group
* @return NULL if the device group was destroyed, otherwise the passed * @return NULL if the device group was destroyed, otherwise the passed
@ -2213,7 +2232,7 @@ libinput_device_group_get_user_data(struct libinput_device_group *group);
* *
* Some configuration option may be dependent on or mutually exclusive with * Some configuration option may be dependent on or mutually exclusive with
* with other options. The behavior in those cases is * with other options. The behavior in those cases is
* implementation-defined, the caller must ensure that the options are set * implementation-dependent, the caller must ensure that the options are set
* in the right order. * in the right order.
*/ */
@ -2254,7 +2273,8 @@ enum libinput_config_tap_state {
/** /**
* @ingroup config * @ingroup config
* *
* Check if the device supports tap-to-click. See * Check if the device supports tap-to-click and how many fingers can be
* used for tapping. See
* libinput_device_config_tap_set_enabled() for more information. * libinput_device_config_tap_set_enabled() for more information.
* *
* @param device The device to configure * @param device The device to configure
@ -2300,8 +2320,8 @@ libinput_device_config_tap_set_enabled(struct libinput_device *device,
* *
* @param device The device to configure * @param device The device to configure
* *
* @return @ref LIBINPUT_CONFIG_TAP_ENABLED if tapping is currently enabled, * @retval LIBINPUT_CONFIG_TAP_ENABLED If tapping is currently enabled
* or @ref LIBINPUT_CONFIG_TAP_DISABLED is currently disabled * @retval LIBINPUT_CONFIG_TAP_DISABLED If tapping is currently disabled
* *
* @see libinput_device_config_tap_get_finger_count * @see libinput_device_config_tap_get_finger_count
* @see libinput_device_config_tap_set_enabled * @see libinput_device_config_tap_set_enabled
@ -2313,11 +2333,12 @@ libinput_device_config_tap_get_enabled(struct libinput_device *device);
/** /**
* @ingroup config * @ingroup config
* *
* Return the default setting for whether tapping is enabled on this device. * Return the default setting for whether tap-to-click is enabled on this
* device.
* *
* @param device The device to configure * @param device The device to configure
* @return @ref LIBINPUT_CONFIG_TAP_ENABLED if tapping is enabled by default, * @retval LIBINPUT_CONFIG_TAP_ENABLED If tapping is enabled by default
* or @ref LIBINPUT_CONFIG_TAP_DISABLED is disabled by default * @retval LIBINPUT_CONFIG_TAP_DISABLED If tapping Is disabled by default
* *
* @see libinput_device_config_tap_get_finger_count * @see libinput_device_config_tap_get_finger_count
* @see libinput_device_config_tap_set_enabled * @see libinput_device_config_tap_set_enabled
@ -2332,7 +2353,7 @@ libinput_device_config_tap_get_default_enabled(struct libinput_device *device);
* Check if the device can be calibrated via a calibration matrix. * Check if the device can be calibrated via a calibration matrix.
* *
* @param device The device to check * @param device The device to check
* @return non-zero if the device can be calibrated, zero otherwise. * @return Non-zero if the device can be calibrated, zero otherwise.
* *
* @see libinput_device_config_calibration_set_matrix * @see libinput_device_config_calibration_set_matrix
* @see libinput_device_config_calibration_get_matrix * @see libinput_device_config_calibration_get_matrix
@ -2420,21 +2441,7 @@ libinput_device_config_calibration_get_matrix(struct libinput_device *device,
* Return the default calibration matrix for this device. On most devices, * Return the default calibration matrix for this device. On most devices,
* this is the identity matrix. If the udev property * this is the identity matrix. If the udev property
* <b>LIBINPUT_CALIBRATION_MATRIX</b> is set on the respective udev device, * <b>LIBINPUT_CALIBRATION_MATRIX</b> is set on the respective udev device,
* that property's value becomes the default matrix. * that property's value becomes the default matrix, see @ref udev_config.
*
* The udev property is parsed as 6 floating point numbers separated by a
* single space each (scanf(3) format "%f %f %f %f %f %f").
* The 6 values represent the first two rows of the calibration matrix as
* described in libinput_device_config_calibration_set_matrix().
*
* Example values are:
* @code
* ENV{LIBINPUT_CALIBRATION_MATRIX}="1 0 0 0 1 0" # default
* ENV{LIBINPUT_CALIBRATION_MATRIX}="0 -1 1 1 0 0" # 90 degree clockwise
* ENV{LIBINPUT_CALIBRATION_MATRIX}="-1 0 1 0 -1 1" # 180 degree clockwise
* ENV{LIBINPUT_CALIBRATION_MATRIX}="0 1 0 -1 0 1" # 270 degree clockwise
* ENV{LIBINPUT_CALIBRATION_MATRIX}="-1 0 1 1 0 0" # reflect along y axis
* @endcode
* *
* @param device The device to configure * @param device The device to configure
* @param matrix Set to the array representing the first two rows of a 3x3 matrix as * @param matrix Set to the array representing the first two rows of a 3x3 matrix as
@ -2652,7 +2659,7 @@ libinput_device_config_accel_get_default_speed(struct libinput_device *device);
* *
* @param device The device to configure * @param device The device to configure
* *
* @return 0 if natural scrolling is not supported, non-zero if natural * @return Zero if natural scrolling is not supported, non-zero if natural
* scrolling is supported by this device * scrolling is supported by this device
* *
* @see libinput_device_config_set_natural_scroll_enabled * @see libinput_device_config_set_natural_scroll_enabled
@ -2670,7 +2677,7 @@ libinput_device_config_scroll_has_natural_scroll(struct libinput_device *device)
* @param device The device to configure * @param device The device to configure
* @param enable non-zero to enable, zero to disable natural scrolling * @param enable non-zero to enable, zero to disable natural scrolling
* *
* @return a config status code * @return A config status code
* *
* @see libinput_device_config_has_natural_scroll * @see libinput_device_config_has_natural_scroll
* @see libinput_device_config_get_natural_scroll_enabled * @see libinput_device_config_get_natural_scroll_enabled
@ -2686,7 +2693,7 @@ libinput_device_config_scroll_set_natural_scroll_enabled(struct libinput_device
* *
* @param device The device to configure * @param device The device to configure
* *
* @return zero if natural scrolling is disabled, non-zero if enabled * @return Zero if natural scrolling is disabled, non-zero if enabled
* *
* @see libinput_device_config_has_natural_scroll * @see libinput_device_config_has_natural_scroll
* @see libinput_device_config_set_natural_scroll_enabled * @see libinput_device_config_set_natural_scroll_enabled
@ -2702,7 +2709,7 @@ libinput_device_config_scroll_get_natural_scroll_enabled(struct libinput_device
* *
* @param device The device to configure * @param device The device to configure
* *
* @return zero if natural scrolling is disabled by default, non-zero if enabled * @return Zero if natural scrolling is disabled by default, non-zero if enabled
* *
* @see libinput_device_config_has_natural_scroll * @see libinput_device_config_has_natural_scroll
* @see libinput_device_config_set_natural_scroll_enabled * @see libinput_device_config_set_natural_scroll_enabled
@ -2730,9 +2737,7 @@ libinput_device_config_left_handed_is_available(struct libinput_device *device);
/** /**
* @ingroup config * @ingroup config
* *
* Set the left-handed configuration of the device. For example, a pointing * Set the left-handed configuration of the device.
* device may reverse it's buttons and send a right button click when the
* left button is pressed, and vice versa.
* *
* The exact behavior is device-dependent. On a mouse and most pointing * The exact behavior is device-dependent. On a mouse and most pointing
* devices, left and right buttons are swapped but the middle button is * devices, left and right buttons are swapped but the middle button is
@ -2798,7 +2803,7 @@ libinput_device_config_left_handed_get_default(struct libinput_device *device);
enum libinput_config_click_method { enum libinput_config_click_method {
/** /**
* Do not send software-emulated button events. This has no effect * Do not send software-emulated button events. This has no effect
* on physical button generations. * on events generated by physical buttons.
*/ */
LIBINPUT_CONFIG_CLICK_METHOD_NONE = 0, LIBINPUT_CONFIG_CLICK_METHOD_NONE = 0,
/** /**
@ -2898,15 +2903,16 @@ libinput_device_config_click_get_default_method(struct libinput_device *device);
enum libinput_config_scroll_method { enum libinput_config_scroll_method {
/** /**
* Never send scroll events instead of pointer motion events. * Never send scroll events instead of pointer motion events.
* Note scroll wheels, etc. will still send scroll events. * This has no effect on events generated by scroll wheels.
*/ */
LIBINPUT_CONFIG_SCROLL_NO_SCROLL = 0, LIBINPUT_CONFIG_SCROLL_NO_SCROLL = 0,
/** /**
* Send scroll events when 2 fingers are down on the device. * Send scroll events when two fingers are logically down on the
* device.
*/ */
LIBINPUT_CONFIG_SCROLL_2FG = (1 << 0), LIBINPUT_CONFIG_SCROLL_2FG = (1 << 0),
/** /**
* Send scroll events when a finger is moved along the bottom or * Send scroll events when a finger moves along the bottom or
* right edge of a device. * right edge of a device.
*/ */
LIBINPUT_CONFIG_SCROLL_EDGE = (1 << 1), LIBINPUT_CONFIG_SCROLL_EDGE = (1 << 1),
@ -3024,10 +3030,11 @@ libinput_device_config_scroll_get_default_method(struct libinput_device *device)
* @param device The device to configure * @param device The device to configure
* @param button The button which when pressed switches to sending scroll events * @param button The button which when pressed switches to sending scroll events
* *
* @return a config status code * @return A config status code
* @retval LIBINPUT_CONFIG_STATUS_SUCCESS on success * @retval LIBINPUT_CONFIG_STATUS_SUCCESS On success
* @retval LIBINPUT_CONFIG_STATUS_UNSUPPORTED if @ref LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN is not supported * @retval LIBINPUT_CONFIG_STATUS_UNSUPPORTED If @ref
* @retval LIBINPUT_CONFIG_STATUS_INVALID the given button does not * LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN is not supported
* @retval LIBINPUT_CONFIG_STATUS_INVALID The given button does not
* exist on this device * exist on this device
* *
* @see libinput_device_config_scroll_get_methods * @see libinput_device_config_scroll_get_methods
@ -3044,11 +3051,11 @@ libinput_device_config_scroll_set_button(struct libinput_device *device,
/** /**
* @ingroup config * @ingroup config
* *
* Get the button for the @ref LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN method for * Get the button for the @ref LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN method
* this device. * for this device.
* *
* If @ref LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN scroll method is not supported, * If @ref LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN scroll method is not
* or no button is set, this function returns 0. * supported, or no button is set, this function returns 0.
* *
* @note The return value is independent of the currently selected * @note The return value is independent of the currently selected
* scroll-method. For button scrolling to activate, a device must have the * scroll-method. For button scrolling to activate, a device must have the
@ -3071,14 +3078,15 @@ libinput_device_config_scroll_get_button(struct libinput_device *device);
/** /**
* @ingroup config * @ingroup config
* *
* Get the default button for LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN method * Get the default button for the @ref LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN
* for this device. * method for this device.
* *
* If @ref LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN scroll method is not supported, * If @ref LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN scroll method is not supported,
* or no default button is set, this function returns 0. * or no default button is set, this function returns 0.
* *
* @param device The device to configure * @param device The device to configure
* @return The default button for LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN method * @return The default button for the @ref
* LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN method
* *
* @see libinput_device_config_scroll_get_methods * @see libinput_device_config_scroll_get_methods
* @see libinput_device_config_scroll_set_method * @see libinput_device_config_scroll_set_method

View file

@ -19,6 +19,7 @@ liblitest_la_SOURCES = \
litest-keyboard.c \ litest-keyboard.c \
litest-mouse.c \ litest-mouse.c \
litest-ms-surface-cover.c \ litest-ms-surface-cover.c \
litest-protocol-a-touch-screen.c \
litest-qemu-usb-tablet.c \ litest-qemu-usb-tablet.c \
litest-synaptics.c \ litest-synaptics.c \
litest-synaptics-hover.c \ litest-synaptics-hover.c \

View file

@ -0,0 +1,97 @@
/*
* Copyright © 2015 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 "litest.h"
#include "litest-int.h"
static void
litest_protocol_a_touch_setup(void)
{
struct litest_device *d = litest_create_device(LITEST_PROTOCOL_A_SCREEN);
litest_set_current_device(d);
}
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_MT_POSITION_X, .value = LITEST_AUTO_ASSIGN },
{ .type = EV_ABS, .code = ABS_MT_POSITION_Y, .value = LITEST_AUTO_ASSIGN },
{ .type = EV_ABS, .code = ABS_MT_TRACKING_ID, .value = LITEST_AUTO_ASSIGN },
{ .type = EV_SYN, .code = SYN_MT_REPORT, .value = 0 },
{ .type = EV_KEY, .code = BTN_TOUCH, .value = 1 },
{ .type = EV_SYN, .code = SYN_REPORT, .value = 0 },
{ .type = -1, .code = -1 },
};
static struct input_event move[] = {
{ .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_MT_POSITION_X, .value = LITEST_AUTO_ASSIGN },
{ .type = EV_ABS, .code = ABS_MT_POSITION_Y, .value = LITEST_AUTO_ASSIGN },
{ .type = EV_SYN, .code = SYN_MT_REPORT, .value = 0 },
{ .type = EV_KEY, .code = BTN_TOUCH, .value = 1 },
{ .type = EV_SYN, .code = SYN_REPORT, .value = 0 },
{ .type = -1, .code = -1 },
};
static struct litest_device_interface interface = {
.touch_down_events = down,
.touch_move_events = move,
};
static struct input_absinfo absinfo[] = {
{ ABS_X, 0, 32767, 0, 0, 0 },
{ ABS_Y, 0, 32767, 0, 0, 0 },
{ ABS_MT_POSITION_X, 0, 32767, 0, 0, 0 },
{ ABS_MT_POSITION_Y, 0, 32767, 0, 0, 0 },
{ ABS_MT_PRESSURE, 0, 1, 0, 0, 0 },
{ .value = -1 },
};
static struct input_id input_id = {
.bustype = 0x18,
.vendor = 0xeef,
.product = 0x20,
};
static int events[] = {
EV_KEY, BTN_TOUCH,
INPUT_PROP_MAX, INPUT_PROP_DIRECT,
-1, -1,
};
struct litest_test_device litest_protocol_a_screen = {
.type = LITEST_PROTOCOL_A_SCREEN,
.features = LITEST_PROTOCOL_A,
.shortname = "protocol A",
.setup = litest_protocol_a_touch_setup,
.interface = &interface,
.name = "Protocol A touch screen",
.id = &input_id,
.events = events,
.absinfo = absinfo,
};

View file

@ -100,6 +100,7 @@ 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_vmware_virtmouse_device;
extern struct litest_test_device litest_synaptics_hover_device; extern struct litest_test_device litest_synaptics_hover_device;
extern struct litest_test_device litest_synaptics_carbon3rd_device; extern struct litest_test_device litest_synaptics_carbon3rd_device;
extern struct litest_test_device litest_protocol_a_screen;
struct litest_test_device* devices[] = { struct litest_test_device* devices[] = {
&litest_synaptics_clickpad_device, &litest_synaptics_clickpad_device,
@ -121,6 +122,7 @@ struct litest_test_device* devices[] = {
&litest_vmware_virtmouse_device, &litest_vmware_virtmouse_device,
&litest_synaptics_hover_device, &litest_synaptics_hover_device,
&litest_synaptics_carbon3rd_device, &litest_synaptics_carbon3rd_device,
&litest_protocol_a_screen,
NULL, NULL,
}; };
@ -1507,6 +1509,12 @@ litest_timeout_buttonscroll(void)
msleep(300); msleep(300);
} }
void
litest_timeout_finger_switch(void)
{
msleep(120);
}
void void
litest_push_event_frame(struct litest_device *dev) litest_push_event_frame(struct litest_device *dev)
{ {

View file

@ -51,10 +51,11 @@ enum litest_device_type {
LITEST_VMWARE_VIRTMOUSE = -15, LITEST_VMWARE_VIRTMOUSE = -15,
LITEST_SYNAPTICS_HOVER_SEMI_MT = -16, LITEST_SYNAPTICS_HOVER_SEMI_MT = -16,
LITEST_SYNAPTICS_TRACKPOINT_BUTTONS = -17, LITEST_SYNAPTICS_TRACKPOINT_BUTTONS = -17,
LITEST_WACOM_BAMBOO = -18, LITEST_PROTOCOL_A_SCREEN = -18,
LITEST_WACOM_CINTIQ = -19, LITEST_WACOM_BAMBOO = -19,
LITEST_WACOM_INTUOS = -20, LITEST_WACOM_CINTIQ = -20,
LITEST_WACOM_ISDV4 = -21, LITEST_WACOM_INTUOS = -21,
LITEST_WACOM_ISDV4 = -22,
}; };
enum litest_device_feature { enum litest_device_feature {
@ -74,9 +75,10 @@ enum litest_device_feature {
LITEST_POINTINGSTICK = 1 << 11, LITEST_POINTINGSTICK = 1 << 11,
LITEST_FAKE_MT = 1 << 12, LITEST_FAKE_MT = 1 << 12,
LITEST_ABSOLUTE = 1 << 13, LITEST_ABSOLUTE = 1 << 13,
LITEST_TABLET = 1 << 14, LITEST_PROTOCOL_A = 1 << 14,
LITEST_DISTANCE = 1 << 15, LITEST_TABLET = 1 << 15,
LITEST_TOOL_SERIAL = 1 << 16, LITEST_DISTANCE = 1 << 16,
LITEST_TOOL_SERIAL = 1 << 17,
}; };
struct litest_device { struct litest_device {
@ -218,6 +220,7 @@ struct libevdev_uinput * litest_create_uinput_abs_device(const char *name,
void litest_timeout_tap(void); void litest_timeout_tap(void);
void litest_timeout_softbuttons(void); void litest_timeout_softbuttons(void);
void litest_timeout_buttonscroll(void); void litest_timeout_buttonscroll(void);
void litest_timeout_finger_switch(void);
void litest_push_event_frame(struct litest_device *dev); void litest_push_event_frame(struct litest_device *dev);
void litest_pop_event_frame(struct litest_device *dev); void litest_pop_event_frame(struct litest_device *dev);

View file

@ -826,7 +826,7 @@ int main (int argc, char **argv) {
litest_add("pointer:scroll", pointer_scroll_natural_wheel, LITEST_WHEEL, LITEST_ANY); litest_add("pointer:scroll", pointer_scroll_natural_wheel, LITEST_WHEEL, LITEST_ANY);
litest_add_no_device("pointer:seat button count", pointer_seat_button_count); litest_add_no_device("pointer:seat button count", pointer_seat_button_count);
litest_add("pointer:calibration", pointer_no_calibration, LITEST_ANY, LITEST_TOUCH|LITEST_SINGLE_TOUCH|LITEST_ABSOLUTE); litest_add("pointer:calibration", pointer_no_calibration, LITEST_ANY, LITEST_TOUCH|LITEST_SINGLE_TOUCH|LITEST_ABSOLUTE|LITEST_PROTOCOL_A);
/* tests touchpads too */ /* tests touchpads too */
litest_add("pointer:left-handed", pointer_left_handed_defaults, LITEST_BUTTON, LITEST_ANY); litest_add("pointer:left-handed", pointer_left_handed_defaults, LITEST_BUTTON, LITEST_ANY);

View file

@ -465,6 +465,124 @@ START_TEST(fake_mt_no_touch_events)
} }
END_TEST END_TEST
START_TEST(touch_protocol_a_init)
{
struct litest_device *dev = litest_current_device();
struct libinput *li = dev->libinput;
struct libinput_device *device = dev->libinput_device;
ck_assert_int_ne(libinput_next_event_type(li),
LIBINPUT_EVENT_NONE);
ck_assert(libinput_device_has_capability(device,
LIBINPUT_DEVICE_CAP_TOUCH));
}
END_TEST
START_TEST(touch_protocol_a_touch)
{
struct litest_device *dev = litest_current_device();
struct libinput *li = dev->libinput;
struct libinput_event *ev;
struct libinput_event_touch *tev;
double x, y, oldx, oldy;
litest_drain_events(li);
litest_touch_down(dev, 0, 5, 95);
litest_wait_for_event_of_type(li, LIBINPUT_EVENT_TOUCH_DOWN, -1);
ev = libinput_get_event(li);
tev = libinput_event_get_touch_event(ev);
oldx = libinput_event_touch_get_x(tev);
oldy = libinput_event_touch_get_y(tev);
libinput_event_destroy(ev);
litest_touch_move_to(dev, 0, 10, 90, 90, 10, 20, 1);
litest_wait_for_event_of_type(li, LIBINPUT_EVENT_TOUCH_MOTION, -1);
while ((ev = libinput_get_event(li))) {
if (libinput_event_get_type(ev) ==
LIBINPUT_EVENT_TOUCH_FRAME) {
libinput_event_destroy(ev);
continue;
}
ck_assert_int_eq(libinput_event_get_type(ev),
LIBINPUT_EVENT_TOUCH_MOTION);
tev = libinput_event_get_touch_event(ev);
x = libinput_event_touch_get_x(tev);
y = libinput_event_touch_get_y(tev);
ck_assert_int_gt(x, oldx);
ck_assert_int_lt(y, oldy);
oldx = x;
oldy = y;
libinput_event_destroy(ev);
}
litest_touch_up(dev, 0);
litest_wait_for_event_of_type(li, LIBINPUT_EVENT_TOUCH_UP, -1);
}
END_TEST
START_TEST(touch_protocol_a_2fg_touch)
{
struct litest_device *dev = litest_current_device();
struct libinput *li = dev->libinput;
struct libinput_event *ev;
struct libinput_event_touch *tev;
int pos;
litest_drain_events(li);
litest_push_event_frame(dev);
litest_touch_down(dev, 0, 5, 95);
litest_touch_down(dev, 0, 95, 5);
litest_pop_event_frame(dev);
litest_wait_for_event_of_type(li, LIBINPUT_EVENT_TOUCH_DOWN, -1);
ev = libinput_get_event(li);
libinput_event_destroy(ev);
litest_wait_for_event_of_type(li, LIBINPUT_EVENT_TOUCH_DOWN, -1);
ev = libinput_get_event(li);
libinput_event_destroy(ev);
for (pos = 10; pos < 100; pos += 10) {
litest_push_event_frame(dev);
litest_touch_move_to(dev, 0, pos, 100 - pos, pos, 100 - pos, 1, 1);
litest_touch_move_to(dev, 0, 100 - pos, pos, 100 - pos, pos, 1, 1);
litest_pop_event_frame(dev);
litest_wait_for_event_of_type(li, LIBINPUT_EVENT_TOUCH_MOTION, -1);
ev = libinput_get_event(li);
tev = libinput_event_get_touch_event(ev);
ck_assert_int_eq(libinput_event_touch_get_slot(tev),
0);
libinput_event_destroy(ev);
litest_wait_for_event_of_type(li, LIBINPUT_EVENT_TOUCH_MOTION, -1);
ev = libinput_get_event(li);
tev = libinput_event_get_touch_event(ev);
ck_assert_int_eq(libinput_event_touch_get_slot(tev),
1);
libinput_event_destroy(ev);
}
litest_event(dev, EV_SYN, SYN_MT_REPORT, 0);
litest_event(dev, EV_SYN, SYN_REPORT, 0);
litest_wait_for_event_of_type(li, LIBINPUT_EVENT_TOUCH_UP, -1);
litest_wait_for_event_of_type(li, LIBINPUT_EVENT_TOUCH_UP, -1);
}
END_TEST
int int
main(int argc, char **argv) main(int argc, char **argv)
{ {
@ -484,5 +602,9 @@ main(int argc, char **argv)
litest_add("touch:fake-mt", fake_mt_exists, LITEST_FAKE_MT, LITEST_ANY); litest_add("touch:fake-mt", fake_mt_exists, LITEST_FAKE_MT, LITEST_ANY);
litest_add("touch:fake-mt", fake_mt_no_touch_events, LITEST_FAKE_MT, LITEST_ANY); litest_add("touch:fake-mt", fake_mt_no_touch_events, LITEST_FAKE_MT, LITEST_ANY);
litest_add("touch:protocol a", touch_protocol_a_init, LITEST_PROTOCOL_A, LITEST_ANY);
litest_add("touch:protocol a", touch_protocol_a_touch, LITEST_PROTOCOL_A, LITEST_ANY);
litest_add("touch:protocol a", touch_protocol_a_2fg_touch, LITEST_PROTOCOL_A, LITEST_ANY);
return litest_run(argc, argv); return litest_run(argc, argv);
} }

View file

@ -1871,6 +1871,9 @@ START_TEST(touchpad_2fg_scroll_return_to_motion)
litest_touch_move_to(dev, 0, 47, 50, 47, 70, 5, 0); litest_touch_move_to(dev, 0, 47, 50, 47, 70, 5, 0);
litest_touch_move_to(dev, 1, 53, 50, 53, 70, 5, 0); litest_touch_move_to(dev, 1, 53, 50, 53, 70, 5, 0);
litest_touch_up(dev, 1); litest_touch_up(dev, 1);
libinput_dispatch(li);
litest_timeout_finger_switch();
libinput_dispatch(li);
litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS); litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS);
litest_touch_move_to(dev, 0, 47, 70, 47, 50, 10, 0); litest_touch_move_to(dev, 0, 47, 70, 47, 50, 10, 0);
@ -1881,6 +1884,9 @@ START_TEST(touchpad_2fg_scroll_return_to_motion)
litest_touch_move_to(dev, 0, 47, 50, 47, 70, 5, 0); litest_touch_move_to(dev, 0, 47, 50, 47, 70, 5, 0);
litest_touch_move_to(dev, 1, 53, 50, 53, 70, 5, 0); litest_touch_move_to(dev, 1, 53, 50, 53, 70, 5, 0);
litest_touch_up(dev, 0); litest_touch_up(dev, 0);
libinput_dispatch(li);
litest_timeout_finger_switch();
libinput_dispatch(li);
litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS); litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS);
/* move with second finger */ /* move with second finger */

View file

@ -7,6 +7,12 @@
fun:litest_run fun:litest_run
fun:main fun:main
} }
{
mtdev:conditional_jumps_uninitialized_value
Memcheck:Cond
...
fun:mtdev_put_event
}
{ {
<g_type_register_static> <g_type_register_static>
Memcheck:Leak Memcheck:Leak