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>
<dd>Sets the calibration matrix, see
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>
<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,

View file

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

View file

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

View file

@ -86,7 +86,6 @@ tp_edge_scroll_set_state(struct tp_dispatch *tp,
break;
case EDGE_SCROLL_TOUCH_STATE_AREA:
t->scroll.edge = EDGE_NONE;
tp_set_pointer(tp, t);
break;
}
}
@ -317,6 +316,9 @@ tp_edge_scroll_post_events(struct tp_dispatch *tp, uint64_t time)
enum libinput_pointer_axis axis;
double dx, dy, *delta;
if (tp->scroll.method != LIBINPUT_CONFIG_SCROLL_EDGE)
return 0;
tp_for_each_touch(tp, t) {
if (!t->dirty)
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->is_pointer = false;
t->palm.is_palm = false;
t->state = TOUCH_END;
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 >=
tp->buttons.motion_dist * tp->buttons.motion_dist) {
t->pinned.is_pinned = false;
tp_set_pointer(tp, t);
return;
}
@ -439,14 +437,13 @@ tp_pin_fingers(struct tp_dispatch *tp)
struct tp_touch *t;
tp_for_each_touch(tp, t) {
t->is_pointer = false;
t->pinned.is_pinned = true;
t->pinned.center_x = t->x;
t->pinned.center_y = t->y;
}
}
static int
int
tp_touch_active(struct tp_dispatch *tp, struct tp_touch *t)
{
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);
}
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
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);
if ((dirs & DIRECTIONS) && !(dirs & ~DIRECTIONS)) {
t->palm.is_palm = false;
tp_set_pointer(tp, t);
}
}
return;
@ -512,153 +493,6 @@ tp_palm_detect(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time)
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
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_scroll_handle_state(tp, time);
tp_edge_scroll_handle_state(tp, time);
/*
* 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) &&
tp->buttons.is_clickpad)
tp_pin_fingers(tp);
tp_gesture_handle_state(tp, time);
}
static void
@ -790,63 +626,6 @@ tp_post_process_state(struct tp_dispatch *tp, uint64_t time)
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
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);
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;
}
if (tp_post_scroll_events(tp, time) != 0)
if (tp_edge_scroll_post_events(tp, time) != 0)
return;
tp_post_pointer_motion(tp, time);
tp_gesture_post_events(tp, time);
}
static void
@ -925,7 +705,8 @@ tp_remove(struct evdev_dispatch *dispatch)
tp_remove_tap(tp);
tp_remove_buttons(tp);
tp_remove_sendevents(tp);
tp_remove_scroll(tp);
tp_remove_edge_scroll(tp);
tp_remove_gesture(tp);
}
static void
@ -1017,9 +798,8 @@ tp_trackpoint_event(uint64_t time, struct libinput_event *event, void *data)
return;
if (!tp->sendevents.trackpoint_active) {
evdev_stop_scroll(tp->device,
time,
LIBINPUT_POINTER_AXIS_SOURCE_FINGER);
tp_edge_scroll_stop_events(tp, time);
tp_gesture_stop(tp, time);
tp_tap_suspend(tp, time);
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 tp_dispatch *tp = (struct tp_dispatch*)evdev->dispatch;
uint64_t time = libinput_now(device->seat->libinput);
if (method == tp->scroll.method)
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;
return LIBINPUT_CONFIG_STATUS_SUCCESS;
@ -1395,6 +1178,9 @@ tp_init(struct tp_dispatch *tp,
if (tp_init_scroll(tp, device) != 0)
return -1;
if (tp_init_gesture(tp) != 0)
return -1;
device->seat_caps |= EVDEV_DEVICE_POINTER;
return 0;

View file

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

View file

@ -58,6 +58,7 @@ enum evdev_device_udev_tags {
EVDEV_UDEV_TAG_TABLET = (1 << 5),
EVDEV_UDEV_TAG_JOYSTICK = (1 << 6),
EVDEV_UDEV_TAG_ACCELEROMETER = (1 << 7),
EVDEV_UDEV_TAG_BUTTONSET = (1 << 8),
};
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_TOUCHSCREEN", EVDEV_UDEV_TAG_TOUCHSCREEN},
{"ID_INPUT_TABLET", EVDEV_UDEV_TAG_TABLET},
{"ID_INPUT_TABLET_PAD", EVDEV_UDEV_TAG_BUTTONSET},
{"ID_INPUT_JOYSTICK", EVDEV_UDEV_TAG_JOYSTICK},
{"ID_INPUT_ACCELEROMETER", EVDEV_UDEV_TAG_ACCELEROMETER},
@ -524,6 +526,14 @@ evdev_process_touch(struct evdev_device *device,
{
switch (e->code) {
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);
device->mt.slot = e->value;
break;
@ -1400,7 +1410,7 @@ evdev_configure_device(struct evdev_device *device)
}
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,
udev_tags & EVDEV_UDEV_TAG_KEYBOARD ? " Keyboard" : "",
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_TABLET ? " Tablet" : "",
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
make sure we only ignore real joystick devices */
@ -1419,6 +1430,14 @@ evdev_configure_device(struct evdev_device *device)
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 ((absinfo = libevdev_get_abs_info(evdev, ABS_X))) {
@ -1467,10 +1486,9 @@ evdev_configure_device(struct evdev_device *device)
if (!device->mtdev)
return -1;
num_slots = device->mtdev->caps.slot.maximum;
if (device->mtdev->caps.slot.minimum < 0 ||
num_slots <= 0)
return -1;
/* pick 10 slots as default for type A
devices. */
num_slots = 10;
active_slot = device->mtdev->caps.slot.value;
} else {
num_slots = libevdev_get_num_slots(device->evdev);

View file

@ -48,8 +48,7 @@ enum libinput_log_priority {
* @ingroup device
*
* Capabilities on a device. A device may have one or more capabilities
* at a time, and capabilities may appear or disappear during the
* lifetime of the device.
* at a time, capabilities remain static for the lifetime of the device.
*/
enum libinput_device_capability {
LIBINPUT_DEVICE_CAP_KEYBOARD = 0,
@ -94,7 +93,8 @@ enum libinput_button_state {
/**
* @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
* @ref LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL are engaged separately,
@ -411,9 +411,9 @@ libinput_event_get_context(struct libinput_event *event);
/**
* @ingroup event
*
* Return the device associated with this event, if applicable. For device
* added/removed events this is the device added or removed. For all other
* device events, this is the device that generated the event.
* Return the device associated with this event. For device added/removed
* events this is the device added or removed. For all other device events,
* this is the device that generated the event.
*
* 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.
@ -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
* 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.
*
* @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
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
* @ref LIBINPUT_EVENT_POINTER_MOTION.
*
* @return the relative x movement since the last event
* @return The relative x movement since the last event
*/
double
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
* @ref LIBINPUT_EVENT_POINTER_MOTION.
*
* @return the relative y movement since the last event
* @return The relative y movement since the last event
*/
double
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
* @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
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
* @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
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
* @ref LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE.
*
* @return the current absolute x coordinate
* @return The current absolute x coordinate
*/
double
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
* @ref LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE.
*
* @return the current absolute y coordinate
* @return The current absolute y coordinate
*/
double
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 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
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 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
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
* @ref LIBINPUT_EVENT_POINTER_BUTTON.
*
* @return the button triggering this event
* @return The button triggering this event
*/
uint32_t
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
* @ref LIBINPUT_EVENT_POINTER_BUTTON.
*
* @return the button state triggering this event
* @return The button state triggering this event
*/
enum libinput_button_state
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
* 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
* 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
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
* 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
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
* @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
*/
@ -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
* @ref LIBINPUT_EVENT_POINTER_AXIS.
*
* @return the source for this axis event
* @return The source for this axis event
*/
enum libinput_pointer_axis_source
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.
*
* 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
* 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.
*
* @param event The libinput touch event
* @return the current absolute x coordinate
* @return The current absolute x coordinate
*/
double
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.
*
* @param event The libinput touch event
* @return the current absolute y coordinate
* @return The current absolute y coordinate
*/
double
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 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
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 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
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
* 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);
/**
@ -1520,7 +1520,7 @@ libinput_path_remove_device(struct libinput_device *device);
* libinput keeps a single file descriptor for all events. Call into
* 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
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
* 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
*
@ -1563,8 +1567,8 @@ libinput_get_event(struct libinput *libinput);
* libinput_get_event() returns that event.
*
* @param libinput A previously initialized libinput context
* @return The event type of the next available event or LIBINPUT_EVENT_NONE
* if no event is availble.
* @return The event type of the next available event or @ref
* LIBINPUT_EVENT_NONE if no event is availble.
*/
enum libinput_event_type
libinput_next_event_type(struct libinput *libinput);
@ -1572,6 +1576,10 @@ libinput_next_event_type(struct libinput *libinput);
/**
* @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 user_data Caller-specific data passed to the various callback
* interfaces.
@ -1583,8 +1591,10 @@ libinput_set_user_data(struct libinput *libinput,
/**
* @ingroup base
*
* Get the caller-specific data associated with this context, if any.
*
* @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().
*/
void *
@ -1644,10 +1654,11 @@ libinput_unref(struct libinput *libinput);
/**
* @ingroup base
*
* Set the global log priority. Messages with priorities equal to or
* higher than the argument will be printed to the current log handler.
* Set the log priority for the libinput context. Messages with priorities
* 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 priority The minimum priority of log messages to print.
@ -1662,10 +1673,10 @@ libinput_log_set_priority(struct libinput *libinput,
/**
* @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.
*
* 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
* @return The minimum priority of log messages to print.
@ -1698,8 +1709,8 @@ typedef void (*libinput_log_handler)(struct libinput *libinput,
/**
* @ingroup base
*
* Set the global log handler. Messages with priorities equal to or higher
* than the current log priority will be passed to the given
* Set the context's log handler. Messages with priorities equal to or
* higher than the context's log priority will be passed to the given
* log handler.
*
* The default log handler prints to stderr.
@ -1727,7 +1738,7 @@ libinput_log_set_handler(struct libinput *libinput,
* @ingroup seat
*
* 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
* the seat correctly to avoid dangling pointers.
*
@ -1741,7 +1752,7 @@ libinput_seat_ref(struct libinput_seat *seat);
* @ingroup seat
*
* 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
* the seat correctly to avoid dangling pointers.
*
@ -1802,7 +1813,7 @@ libinput_seat_get_context(struct libinput_seat *seat);
* be available to the caller.
*
* @param seat A previously obtained seat
* @return the physical name of this seat
* @return The physical name of this seat
*/
const char *
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.
*
* @param seat A previously obtained seat
* @return the logical name of this seat
* @return The logical name of this seat
*/
const char *
libinput_seat_get_logical_name(struct libinput_seat *seat);
@ -1827,9 +1838,9 @@ libinput_seat_get_logical_name(struct libinput_seat *seat);
* @ingroup device
*
* 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
* device was removed from the system. A caller must ensure to reference
* the device correctly to avoid dangling pointers.
* whenever the refcount reaches 0. This may happen during
* libinput_dispatch() if the device was removed from the system. A caller
* must ensure to reference the device correctly to avoid dangling pointers.
*
* @param device A previously obtained device
* @return The passed device
@ -1841,9 +1852,9 @@ libinput_device_ref(struct libinput_device *device);
* @ingroup device
*
* 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
* device was removed from the system. A caller must ensure to reference
* the device correctly to avoid dangling pointers.
* whenever the refcount reaches 0. This may happen during libinput_dispatch
* if the device was removed from the system. A caller must ensure to
* reference the device correctly to avoid dangling pointers.
*
* @param device A previously obtained 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
* 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
*/
const char *
@ -2020,7 +2031,8 @@ libinput_device_get_output_name(struct libinput_device *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.
* 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.
*
* This command is identical to physically unplugging the device, then
* re-plugging it as member of the new seat,
* @ref LIBINPUT_EVENT_DEVICE_REMOVED and @ref LIBINPUT_EVENT_DEVICE_ADDED
* events are sent accordingly. Those events mark the end of the lifetime
* of this device and the start of a new device.
* re-plugging it as member of the new seat. libinput will generate a
* @ref LIBINPUT_EVENT_DEVICE_REMOVED event and this @ref libinput_device is
* considered removed from the context; it will not generate further events
* 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,
* 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.
* 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
* 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
*
* @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
libinput_device_has_capability(struct libinput_device *device,
@ -2127,10 +2144,10 @@ libinput_device_get_size(struct libinput_device *device,
* @ingroup device
*
* 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 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
* on error.
@ -2150,9 +2167,10 @@ libinput_device_has_button(struct libinput_device *device, uint32_t code) LIBINP
* @ingroup device
*
* 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
* devices of this group were removed from the system. A caller must ensure
* to reference the device group correctly to avoid dangling pointers.
* whenever the refcount reaches 0. This may happen during
* libinput_dispatch() if all devices of this group were removed from the
* system. A caller must ensure to reference the device group correctly to
* avoid dangling pointers.
*
* @param group A previously obtained device group
* @return The passed device group
@ -2164,9 +2182,10 @@ libinput_device_group_ref(struct libinput_device_group *group);
* @ingroup device
*
* 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
* devices of this group were removed from the system. A caller must ensure
* to reference the device group correctly to avoid dangling pointers.
* whenever the refcount reaches 0. This may happen during
* libinput_dispatch() if all devices of this group were removed from the
* system. A caller must ensure to reference the device group correctly to
* avoid dangling pointers.
*
* @param group A previously obtained device group
* @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
* 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.
*/
@ -2254,7 +2273,8 @@ enum libinput_config_tap_state {
/**
* @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.
*
* @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
*
* @return @ref LIBINPUT_CONFIG_TAP_ENABLED if tapping is currently enabled,
* or @ref LIBINPUT_CONFIG_TAP_DISABLED is currently disabled
* @retval LIBINPUT_CONFIG_TAP_ENABLED If tapping is currently enabled
* @retval LIBINPUT_CONFIG_TAP_DISABLED If tapping is currently disabled
*
* @see libinput_device_config_tap_get_finger_count
* @see libinput_device_config_tap_set_enabled
@ -2313,11 +2333,12 @@ libinput_device_config_tap_get_enabled(struct libinput_device *device);
/**
* @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
* @return @ref LIBINPUT_CONFIG_TAP_ENABLED if tapping is enabled by default,
* or @ref LIBINPUT_CONFIG_TAP_DISABLED is disabled by default
* @retval LIBINPUT_CONFIG_TAP_ENABLED If tapping is enabled 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_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.
*
* @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_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,
* this is the identity matrix. If the udev property
* <b>LIBINPUT_CALIBRATION_MATRIX</b> is set on the respective udev device,
* that property's value becomes the default 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
* that property's value becomes the default matrix, see @ref udev_config.
*
* @param device The device to configure
* @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
*
* @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
*
* @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 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_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
*
* @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_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
*
* @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_set_natural_scroll_enabled
@ -2730,9 +2737,7 @@ libinput_device_config_left_handed_is_available(struct libinput_device *device);
/**
* @ingroup config
*
* Set the left-handed configuration of the device. For example, a pointing
* device may reverse it's buttons and send a right button click when the
* left button is pressed, and vice versa.
* Set the left-handed configuration of the device.
*
* The exact behavior is device-dependent. On a mouse and most pointing
* 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 {
/**
* 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,
/**
@ -2898,15 +2903,16 @@ libinput_device_config_click_get_default_method(struct libinput_device *device);
enum libinput_config_scroll_method {
/**
* 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,
/**
* 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),
/**
* 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.
*/
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 button The button which when pressed switches to sending scroll events
*
* @return a config status code
* @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_INVALID the given button does not
* @return A config status code
* @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_INVALID The given button does not
* exist on this device
*
* @see libinput_device_config_scroll_get_methods
@ -3044,11 +3051,11 @@ libinput_device_config_scroll_set_button(struct libinput_device *device,
/**
* @ingroup config
*
* Get the button for the @ref LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN method for
* this device.
* Get the button for the @ref LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN method
* for this device.
*
* If @ref LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN scroll method is not supported,
* or no button is set, this function returns 0.
* If @ref LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN scroll method is not
* supported, or no button is set, this function returns 0.
*
* @note The return value is independent of the currently selected
* 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
*
* Get the default button for LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN method
* for this device.
* Get the default button for the @ref LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN
* method for this device.
*
* If @ref LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN scroll method is not supported,
* or no default button is set, this function returns 0.
*
* @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_set_method

View file

@ -19,6 +19,7 @@ liblitest_la_SOURCES = \
litest-keyboard.c \
litest-mouse.c \
litest-ms-surface-cover.c \
litest-protocol-a-touch-screen.c \
litest-qemu-usb-tablet.c \
litest-synaptics.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_synaptics_hover_device;
extern struct litest_test_device litest_synaptics_carbon3rd_device;
extern struct litest_test_device litest_protocol_a_screen;
struct litest_test_device* devices[] = {
&litest_synaptics_clickpad_device,
@ -121,6 +122,7 @@ struct litest_test_device* devices[] = {
&litest_vmware_virtmouse_device,
&litest_synaptics_hover_device,
&litest_synaptics_carbon3rd_device,
&litest_protocol_a_screen,
NULL,
};
@ -1507,6 +1509,12 @@ litest_timeout_buttonscroll(void)
msleep(300);
}
void
litest_timeout_finger_switch(void)
{
msleep(120);
}
void
litest_push_event_frame(struct litest_device *dev)
{

View file

@ -51,10 +51,11 @@ enum litest_device_type {
LITEST_VMWARE_VIRTMOUSE = -15,
LITEST_SYNAPTICS_HOVER_SEMI_MT = -16,
LITEST_SYNAPTICS_TRACKPOINT_BUTTONS = -17,
LITEST_WACOM_BAMBOO = -18,
LITEST_WACOM_CINTIQ = -19,
LITEST_WACOM_INTUOS = -20,
LITEST_WACOM_ISDV4 = -21,
LITEST_PROTOCOL_A_SCREEN = -18,
LITEST_WACOM_BAMBOO = -19,
LITEST_WACOM_CINTIQ = -20,
LITEST_WACOM_INTUOS = -21,
LITEST_WACOM_ISDV4 = -22,
};
enum litest_device_feature {
@ -74,9 +75,10 @@ enum litest_device_feature {
LITEST_POINTINGSTICK = 1 << 11,
LITEST_FAKE_MT = 1 << 12,
LITEST_ABSOLUTE = 1 << 13,
LITEST_TABLET = 1 << 14,
LITEST_DISTANCE = 1 << 15,
LITEST_TOOL_SERIAL = 1 << 16,
LITEST_PROTOCOL_A = 1 << 14,
LITEST_TABLET = 1 << 15,
LITEST_DISTANCE = 1 << 16,
LITEST_TOOL_SERIAL = 1 << 17,
};
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_softbuttons(void);
void litest_timeout_buttonscroll(void);
void litest_timeout_finger_switch(void);
void litest_push_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_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 */
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
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
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_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);
}

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, 1, 53, 50, 53, 70, 5, 0);
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_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, 1, 53, 50, 53, 70, 5, 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);
/* move with second finger */

View file

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