Merge branch 'master' into tablet-support

Conflicts:
	src/libinput-util.h
	test/misc.c
This commit is contained in:
Peter Hutterer 2014-06-25 14:43:45 +10:00
commit 8302b0b7e3
28 changed files with 1108 additions and 356 deletions

View file

@ -1,7 +1,7 @@
AC_PREREQ([2.64])
m4_define([libinput_major_version], [0])
m4_define([libinput_minor_version], [3])
m4_define([libinput_minor_version], [4])
m4_define([libinput_micro_version], [0])
m4_define([libinput_version],
[libinput_major_version.libinput_minor_version.libinput_micro_version])
@ -30,7 +30,7 @@ AM_INIT_AUTOMAKE([1.11 foreign no-dist-gzip dist-xz])
# - If binary compatibility has been broken (eg removed or changed interfaces)
# change to C+1:0:0
# - If the interface is the same as the previous version, change to C:R+1:A
LIBINPUT_LT_VERSION=2:0:0
LIBINPUT_LT_VERSION=3:0:0
AC_SUBST(LIBINPUT_LT_VERSION)
AM_SILENT_RULES([yes])
@ -74,6 +74,21 @@ else
fi
AM_CONDITIONAL([HAVE_DOXYGEN], [test "x$have_doxygen" = "xyes"])
AC_ARG_ENABLE(event-gui,
AS_HELP_STRING([--enable-event-gui], [Build the GUI event viewer (default=auto)]),
[build_eventgui="$enableval"],
[build_eventgui="auto"])
PKG_CHECK_EXISTS([cairo glib-2.0 gtk+-3.0], [HAVE_GUILIBS="yes"], [HAVE_GUILIBS="no"])
if test "x$build_eventgui" = "xauto"; then
build_eventgui="$HAVE_GUILIBS"
fi
if test "x$build_eventgui" = "xyes"; then
PKG_CHECK_MODULES(CAIRO, [cairo])
PKG_CHECK_MODULES(GTK, [glib-2.0 gtk+-3.0])
fi
AM_CONDITIONAL(BUILD_EVENTGUI, [test "x$build_eventgui" = "xyes"])
AC_ARG_ENABLE(tests,
AS_HELP_STRING([--enable-tests], [Build the tests (default=auto)]),
[build_tests="$enableval"],

View file

@ -1570,7 +1570,8 @@ INCLUDE_FILE_PATTERNS =
# undefined via #undef or recursively expanded use the := operator
# instead of the = operator.
PREDEFINED = LIBINPUT_ATTRIBUTE_PRINTF(f,a)=
PREDEFINED = LIBINPUT_ATTRIBUTE_PRINTF(f, a)= \
LIBINPUT_ATTRIBUTE_DEPRECATED
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
# this tag can be used to specify a list of macro names that should be expanded.

View file

@ -452,6 +452,7 @@ tp_button_handle_event(struct tp_dispatch *tp,
enum button_event event,
uint64_t time)
{
struct libinput *libinput = tp->device->base.seat->libinput;
enum button_state current = t->button.state;
switch(t->button.state) {
@ -485,7 +486,8 @@ tp_button_handle_event(struct tp_dispatch *tp,
}
if (current != t->button.state)
log_debug("button state: from %s, event %s to %s\n",
log_debug(libinput,
"button state: from %s, event %s to %s\n",
button_state_to_str(current),
button_event_to_str(event),
button_state_to_str(t->button.state));
@ -538,11 +540,13 @@ tp_process_button(struct tp_dispatch *tp,
const struct input_event *e,
uint64_t time)
{
struct libinput *libinput = tp->device->base.seat->libinput;
uint32_t mask = 1 << (e->code - BTN_LEFT);
/* Ignore other buttons on clickpads */
if (tp->buttons.is_clickpad && e->code != BTN_LEFT) {
log_bug_kernel("received %s button event on a clickpad\n",
log_bug_kernel(libinput,
"received %s button event on a clickpad\n",
libevdev_event_code_get_name(EV_KEY, e->code));
return 0;
}
@ -562,6 +566,7 @@ int
tp_init_buttons(struct tp_dispatch *tp,
struct evdev_device *device)
{
struct libinput *libinput = tp->device->base.seat->libinput;
struct tp_touch *t;
int width, height;
double diagonal;
@ -575,10 +580,12 @@ tp_init_buttons(struct tp_dispatch *tp,
if (libevdev_has_event_code(device->evdev, EV_KEY, BTN_MIDDLE) ||
libevdev_has_event_code(device->evdev, EV_KEY, BTN_RIGHT)) {
if (tp->buttons.is_clickpad)
log_bug_kernel("clickpad advertising right button\n");
log_bug_kernel(libinput,
"clickpad advertising right button\n");
} else {
if (!tp->buttons.is_clickpad)
log_bug_kernel("non clickpad without right button?\n");
log_bug_kernel(libinput,
"non clickpad without right button?\n");
}
absinfo_x = device->abs.absinfo_x;

View file

@ -130,6 +130,7 @@ tp_tap_clear_timer(struct tp_dispatch *tp)
static void
tp_tap_idle_handle_event(struct tp_dispatch *tp, enum tap_event event, uint64_t time)
{
struct libinput *libinput = tp->device->base.seat->libinput;
switch (event) {
case TAP_EVENT_TOUCH:
@ -138,7 +139,8 @@ tp_tap_idle_handle_event(struct tp_dispatch *tp, enum tap_event event, uint64_t
break;
case TAP_EVENT_RELEASE:
case TAP_EVENT_MOTION:
log_bug_libinput("invalid event, no fingers are down\n");
log_bug_libinput(libinput,
"invalid event, no fingers are down\n");
break;
case TAP_EVENT_TIMEOUT:
break;
@ -197,11 +199,13 @@ tp_tap_hold_handle_event(struct tp_dispatch *tp, enum tap_event event, uint64_t
static void
tp_tap_tapped_handle_event(struct tp_dispatch *tp, enum tap_event event, uint64_t time)
{
struct libinput *libinput = tp->device->base.seat->libinput;
switch (event) {
case TAP_EVENT_MOTION:
case TAP_EVENT_RELEASE:
log_bug_libinput("invalid event when fingers are up\n");
log_bug_libinput(libinput,
"invalid event when fingers are up\n");
break;
case TAP_EVENT_TOUCH:
tp->tap.state = TAP_STATE_DRAGGING_OR_DOUBLETAP;
@ -426,7 +430,9 @@ tp_tap_dead_handle_event(struct tp_dispatch *tp, enum tap_event event, uint64_t
static void
tp_tap_handle_event(struct tp_dispatch *tp, enum tap_event event, uint64_t time)
{
struct libinput *libinput = tp->device->base.seat->libinput;
enum tp_tap_state current;
if (!tp->tap.enabled)
return;
@ -477,7 +483,8 @@ tp_tap_handle_event(struct tp_dispatch *tp, enum tap_event event, uint64_t time)
if (tp->tap.state == TAP_STATE_IDLE || tp->tap.state == TAP_STATE_DEAD)
tp_tap_clear_timer(tp);
log_debug("tap state: %s → %s → %s\n",
log_debug(libinput,
"tap state: %s → %s → %s\n",
tap_state_to_str(current),
tap_event_to_str(event),
tap_state_to_str(tp->tap.state));

View file

@ -453,6 +453,8 @@ tp_post_twofinger_scroll(struct tp_dispatch *tp, uint64_t time)
dx += tmpx;
dy += tmpy;
}
/* Stop spurious MOTION events at the end of scrolling */
t->is_pointer = false;
}
if (nchanged == 0)
@ -464,35 +466,25 @@ tp_post_twofinger_scroll(struct tp_dispatch *tp, uint64_t time)
tp_filter_motion(tp, &dx, &dy, time);
/* Require at least three px scrolling to start */
if (dy <= -3.0 || dy >= 3.0) {
tp->scroll.state = SCROLL_STATE_SCROLLING;
tp->scroll.direction |= (1 << LIBINPUT_POINTER_AXIS_VERTICAL_SCROLL);
}
if (dx <= -3.0 || dx >= 3.0) {
tp->scroll.state = SCROLL_STATE_SCROLLING;
tp->scroll.direction |= (1 << LIBINPUT_POINTER_AXIS_HORIZONTAL_SCROLL);
}
if (dy <= -3.0 || dy >= 3.0)
tp->scroll.direction |= (1 << LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL);
if (tp->scroll.state == SCROLL_STATE_NONE)
return;
/* Stop spurious MOTION events at the end of scrolling */
tp_for_each_touch(tp, t)
t->is_pointer = false;
if (dx <= -3.0 || dx >= 3.0)
tp->scroll.direction |= (1 << LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL);
if (dy != 0.0 &&
(tp->scroll.direction & (1 << LIBINPUT_POINTER_AXIS_VERTICAL_SCROLL))) {
(tp->scroll.direction & (1 << LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL))) {
pointer_notify_axis(&tp->device->base,
time,
LIBINPUT_POINTER_AXIS_VERTICAL_SCROLL,
LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL,
dy);
}
if (dx != 0.0 &&
(tp->scroll.direction & (1 << LIBINPUT_POINTER_AXIS_HORIZONTAL_SCROLL))) {
(tp->scroll.direction & (1 << LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL))) {
pointer_notify_axis(&tp->device->base,
time,
LIBINPUT_POINTER_AXIS_HORIZONTAL_SCROLL,
LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL,
dx);
}
}
@ -500,22 +492,18 @@ tp_post_twofinger_scroll(struct tp_dispatch *tp, uint64_t time)
static void
tp_stop_scroll_events(struct tp_dispatch *tp, uint64_t time)
{
if (tp->scroll.state == SCROLL_STATE_NONE)
return;
/* terminate scrolling with a zero scroll event */
if (tp->scroll.direction & (1 << LIBINPUT_POINTER_AXIS_VERTICAL_SCROLL))
if (tp->scroll.direction & (1 << LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL))
pointer_notify_axis(&tp->device->base,
time,
LIBINPUT_POINTER_AXIS_VERTICAL_SCROLL,
LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL,
0);
if (tp->scroll.direction & (1 << LIBINPUT_POINTER_AXIS_HORIZONTAL_SCROLL))
if (tp->scroll.direction & (1 << LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL))
pointer_notify_axis(&tp->device->base,
time,
LIBINPUT_POINTER_AXIS_HORIZONTAL_SCROLL,
LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL,
0);
tp->scroll.state = SCROLL_STATE_NONE;
tp->scroll.direction = 0;
}
@ -732,7 +720,6 @@ static int
tp_init_scroll(struct tp_dispatch *tp)
{
tp->scroll.direction = 0;
tp->scroll.state = SCROLL_STATE_NONE;
return 0;
}

View file

@ -72,11 +72,6 @@ enum button_state {
BUTTON_STATE_IGNORE,
};
enum scroll_state {
SCROLL_STATE_NONE,
SCROLL_STATE_SCROLLING
};
enum tp_tap_state {
TAP_STATE_IDLE = 4,
TAP_STATE_TOUCH,
@ -192,7 +187,6 @@ struct tp_dispatch {
} buttons; /* physical buttons */
struct {
enum scroll_state state;
enum libinput_pointer_axis direction;
} scroll;

View file

@ -53,7 +53,8 @@ tablet_process_absolute(struct tablet_dispatch *tablet,
case ABS_DISTANCE:
axis = evcode_to_axis(e->code);
if (axis == LIBINPUT_TABLET_AXIS_NONE) {
log_bug_libinput("Invalid ABS event code %#x\n",
log_bug_libinput(device->base.seat->libinput,
"Invalid ABS event code %#x\n",
e->code);
break;
}
@ -62,7 +63,8 @@ tablet_process_absolute(struct tablet_dispatch *tablet,
tablet_set_status(tablet, TABLET_AXES_UPDATED);
break;
default:
log_info("Unhandled ABS event code %#x\n", e->code);
log_info(device->base.seat->libinput,
"Unhandled ABS event code %#x\n", e->code);
break;
}
}
@ -153,7 +155,8 @@ tablet_check_notify_axes(struct tablet_dispatch *tablet,
tablet->axes[a] = normalize_tilt(absinfo);
break;
default:
log_bug_libinput("Invalid axis update: %d\n", a);
log_bug_libinput(device->base.seat->libinput,
"Invalid axis update: %d\n", a);
break;
}
@ -184,7 +187,8 @@ tablet_update_button(struct tablet_dispatch *tablet,
mask = &tablet->button_state.stylus_buttons;
button = evcode - BTN_TOUCH;
} else {
log_info("Unhandled button %s (%#x)\n",
log_info(tablet->device->base.seat->libinput,
"Unhandled button %s (%#x)\n",
libevdev_event_code_get_name(EV_KEY, evcode), evcode);
return;
}
@ -250,7 +254,8 @@ tablet_process_misc(struct tablet_dispatch *tablet,
}
break;
default:
log_info("Unhandled MSC event code %s (%#x)\n",
log_info(device->base.seat->libinput,
"Unhandled MSC event code %s (%#x)\n",
libevdev_event_code_get_name(EV_MSC, e->code),
e->code);
break;
@ -432,7 +437,8 @@ tablet_process(struct evdev_dispatch *dispatch,
tablet_flush(tablet, device, time);
break;
default:
log_error("Unexpected event type %s (%#x)\n",
log_error(device->base.seat->libinput,
"Unexpected event type %s (%#x)\n",
libevdev_event_type_get_name(e->type),
e->type);
break;

View file

@ -115,6 +115,7 @@ evdev_device_transform_y(struct evdev_device *device,
static void
evdev_flush_pending_event(struct evdev_device *device, uint64_t time)
{
struct libinput *libinput = device->base.seat->libinput;
struct motion_params motion;
int32_t cx, cy;
double x, y;
@ -147,7 +148,8 @@ evdev_flush_pending_event(struct evdev_device *device, uint64_t time)
break;
if (device->mt.slots[slot].seat_slot != -1) {
log_bug_kernel("%s: Driver sent multiple touch down for the "
log_bug_kernel(libinput,
"%s: Driver sent multiple touch down for the "
"same slot", device->devnode);
break;
}
@ -196,7 +198,8 @@ evdev_flush_pending_event(struct evdev_device *device, uint64_t time)
break;
if (device->abs.seat_slot != -1) {
log_bug_kernel("%s: Driver sent multiple touch down for the "
log_bug_kernel(libinput,
"%s: Driver sent multiple touch down for the "
"same slot", device->devnode);
break;
}
@ -310,8 +313,8 @@ evdev_process_key(struct evdev_device *device,
&device->base,
time,
e->code,
e->value ? LIBINPUT_KEYBOARD_KEY_STATE_PRESSED :
LIBINPUT_KEYBOARD_KEY_STATE_RELEASED);
e->value ? LIBINPUT_KEY_STATE_PRESSED :
LIBINPUT_KEY_STATE_RELEASED);
break;
}
}
@ -390,7 +393,7 @@ evdev_process_relative(struct evdev_device *device,
pointer_notify_axis(
base,
time,
LIBINPUT_POINTER_AXIS_VERTICAL_SCROLL,
LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL,
-1 * e->value * DEFAULT_AXIS_STEP_DISTANCE);
break;
case REL_HWHEEL:
@ -403,7 +406,7 @@ evdev_process_relative(struct evdev_device *device,
pointer_notify_axis(
base,
time,
LIBINPUT_POINTER_AXIS_HORIZONTAL_SCROLL,
LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL,
e->value * DEFAULT_AXIS_STEP_DISTANCE);
break;
default:
@ -591,6 +594,7 @@ configure_pointer_acceleration(struct evdev_device *device)
static int
evdev_configure_device(struct evdev_device *device)
{
struct libinput *libinput = device->base.seat->libinput;
struct libevdev *evdev = device->evdev;
const struct input_absinfo *absinfo;
struct input_absinfo fixed;
@ -696,7 +700,8 @@ evdev_configure_device(struct evdev_device *device)
!libevdev_has_event_code(evdev, EV_KEY, BTN_TOOL_PEN) &&
(has_abs || has_mt)) {
device->dispatch = evdev_mt_touchpad_create(device);
log_info("input device '%s', %s is a touchpad\n",
log_info(libinput,
"input device '%s', %s is a touchpad\n",
device->devname, device->devnode);
} else if (!libevdev_has_event_code(device->evdev, EV_KEY, BTN_TOOL_FINGER) &&
libevdev_has_event_code(device->evdev, EV_KEY, BTN_TOOL_PEN) &&
@ -733,7 +738,8 @@ evdev_configure_device(struct evdev_device *device)
device->seat_caps |= EVDEV_DEVICE_POINTER;
log_info("input device '%s', %s is a pointer caps =%s%s%s\n",
log_info(libinput,
"input device '%s', %s is a pointer caps =%s%s%s\n",
device->devname, device->devnode,
has_abs ? " absolute-motion" : "",
has_rel ? " relative-motion": "",
@ -741,12 +747,14 @@ evdev_configure_device(struct evdev_device *device)
}
if (has_keyboard) {
device->seat_caps |= EVDEV_DEVICE_KEYBOARD;
log_info("input device '%s', %s is a keyboard\n",
log_info(libinput,
"input device '%s', %s is a keyboard\n",
device->devname, device->devnode);
}
if (has_touch && !has_button) {
device->seat_caps |= EVDEV_DEVICE_TOUCH;
log_info("input device '%s', %s is a touch device\n",
log_info(libinput,
"input device '%s', %s is a touch device\n",
device->devname, device->devnode);
}
@ -769,7 +777,8 @@ evdev_device_create(struct libinput_seat *seat,
* read. mtdev_get() also expects this. */
fd = open_restricted(libinput, devnode, O_RDWR | O_NONBLOCK);
if (fd < 0) {
log_info("opening input device '%s' failed (%s).\n",
log_info(libinput,
"opening input device '%s' failed (%s).\n",
devnode, strerror(-fd));
return NULL;
}

View file

@ -58,7 +58,11 @@ struct libinput {
const struct libinput_interface *interface;
const struct libinput_interface_backend *interface_backend;
libinput_log_handler log_handler;
enum libinput_log_priority log_priority;
void *user_data;
int refcount;
};
typedef void (*libinput_seat_destroy_func) (struct libinput_seat *seat);
@ -97,17 +101,21 @@ struct libinput_tool {
typedef void (*libinput_source_dispatch_t)(void *data);
#define log_debug(...) log_msg(LIBINPUT_LOG_PRIORITY_DEBUG, __VA_ARGS__)
#define log_info(...) log_msg(LIBINPUT_LOG_PRIORITY_INFO, __VA_ARGS__)
#define log_error(...) log_msg(LIBINPUT_LOG_PRIORITY_ERROR, __VA_ARGS__)
#define log_bug_kernel(...) log_msg(LIBINPUT_LOG_PRIORITY_ERROR, "kernel bug: " __VA_ARGS__)
#define log_bug_libinput(...) log_msg(LIBINPUT_LOG_PRIORITY_ERROR, "libinput bug: " __VA_ARGS__);
#define log_bug_client(...) log_msg(LIBINPUT_LOG_PRIORITY_ERROR, "client bug: " __VA_ARGS__);
#define log_debug(li_, ...) log_msg((li_), LIBINPUT_LOG_PRIORITY_DEBUG, __VA_ARGS__)
#define log_info(li_, ...) log_msg((li_), LIBINPUT_LOG_PRIORITY_INFO, __VA_ARGS__)
#define log_error(li_, ...) log_msg((li_), LIBINPUT_LOG_PRIORITY_ERROR, __VA_ARGS__)
#define log_bug_kernel(li_, ...) log_msg((li_), LIBINPUT_LOG_PRIORITY_ERROR, "kernel bug: " __VA_ARGS__)
#define log_bug_libinput(li_, ...) log_msg((li_), LIBINPUT_LOG_PRIORITY_ERROR, "libinput bug: " __VA_ARGS__);
#define log_bug_client(li_, ...) log_msg((li_), LIBINPUT_LOG_PRIORITY_ERROR, "client bug: " __VA_ARGS__);
void
log_msg(enum libinput_log_priority priority, const char *format, ...);
log_msg(struct libinput *libinput,
enum libinput_log_priority priority,
const char *format, ...);
void
log_msg_va(enum libinput_log_priority priority,
log_msg_va(struct libinput *libinput,
enum libinput_log_priority priority,
const char *format,
va_list args);
@ -155,7 +163,7 @@ void
keyboard_notify_key(struct libinput_device *device,
uint32_t time,
uint32_t key,
enum libinput_keyboard_key_state state);
enum libinput_key_state state);
void
pointer_notify_motion(struct libinput_device *device,

View file

@ -23,6 +23,8 @@
#ifndef LIBINPUT_UTIL_H
#define LIBINPUT_UTIL_H
#include <unistd.h>
#include "libinput.h"
void
@ -108,4 +110,10 @@ clear_bit(unsigned char *array, int bit)
array[bit / 8] &= ~(1 << (bit % 8));
}
static inline void
msleep(unsigned int ms)
{
usleep(ms * 1000);
}
#endif /* LIBINPUT_UTIL_H */

View file

@ -56,7 +56,7 @@ struct libinput_event_keyboard {
uint32_t time;
uint32_t key;
uint32_t seat_key_count;
enum libinput_keyboard_key_state state;
enum libinput_key_state state;
};
struct libinput_event_pointer {
@ -92,8 +92,8 @@ struct libinput_event_tablet {
};
static void
libinput_default_log_func(enum libinput_log_priority priority,
void *data,
libinput_default_log_func(struct libinput *libinput,
enum libinput_log_priority priority,
const char *format, va_list args)
{
const char *prefix;
@ -109,55 +109,47 @@ libinput_default_log_func(enum libinput_log_priority priority,
vfprintf(stderr, format, args);
}
struct log_data {
enum libinput_log_priority priority;
libinput_log_handler handler;
void *user_data;
};
static struct log_data log_data = {
.priority = LIBINPUT_LOG_PRIORITY_ERROR,
.handler = libinput_default_log_func,
.user_data = NULL,
};
void
log_msg_va(enum libinput_log_priority priority,
log_msg_va(struct libinput *libinput,
enum libinput_log_priority priority,
const char *format,
va_list args)
{
if (log_data.handler && log_data.priority <= priority)
log_data.handler(priority, log_data.user_data, format, args);
if (libinput->log_handler &&
libinput->log_priority <= priority)
libinput->log_handler(libinput, priority, format, args);
}
void
log_msg(enum libinput_log_priority priority, const char *format, ...)
log_msg(struct libinput *libinput,
enum libinput_log_priority priority,
const char *format, ...)
{
va_list args;
va_start(args, format);
log_msg_va(priority, format, args);
log_msg_va(libinput, priority, format, args);
va_end(args);
}
LIBINPUT_EXPORT void
libinput_log_set_priority(enum libinput_log_priority priority)
libinput_log_set_priority(struct libinput *libinput,
enum libinput_log_priority priority)
{
log_data.priority = priority;
libinput->log_priority = priority;
}
LIBINPUT_EXPORT enum libinput_log_priority
libinput_log_get_priority(void)
libinput_log_get_priority(const struct libinput *libinput)
{
return log_data.priority;
return libinput->log_priority;
}
LIBINPUT_EXPORT void
libinput_log_set_handler(libinput_log_handler log_handler,
void *user_data)
libinput_log_set_handler(struct libinput *libinput,
libinput_log_handler log_handler)
{
log_data.handler = log_handler;
log_data.user_data = user_data;
libinput->log_handler = log_handler;
}
static void
@ -342,7 +334,7 @@ libinput_event_keyboard_get_key(struct libinput_event_keyboard *event)
return event->key;
}
LIBINPUT_EXPORT enum libinput_keyboard_key_state
LIBINPUT_EXPORT enum libinput_key_state
libinput_event_keyboard_get_key_state(struct libinput_event_keyboard *event)
{
return event->state;
@ -655,9 +647,12 @@ libinput_init(struct libinput *libinput,
return -1;
}
libinput->log_handler = libinput_default_log_func;
libinput->log_priority = LIBINPUT_LOG_PRIORITY_ERROR;
libinput->interface = interface;
libinput->interface_backend = interface_backend;
libinput->user_data = user_data;
libinput->refcount = 1;
list_init(&libinput->source_destroy_list);
list_init(&libinput->seat_list);
list_init(&libinput->tool_list);
@ -687,8 +682,15 @@ libinput_drop_destroyed_sources(struct libinput *libinput)
list_init(&libinput->source_destroy_list);
}
LIBINPUT_EXPORT void
libinput_destroy(struct libinput *libinput)
LIBINPUT_EXPORT struct libinput *
libinput_ref(struct libinput *libinput)
{
libinput->refcount++;
return libinput;
}
LIBINPUT_EXPORT struct libinput *
libinput_unref(struct libinput *libinput)
{
struct libinput_event *event;
struct libinput_device *device, *next_device;
@ -696,7 +698,12 @@ libinput_destroy(struct libinput *libinput)
struct libinput_tool *tool, *next_tool;
if (libinput == NULL)
return;
return NULL;
assert(libinput->refcount > 0);
libinput->refcount--;
if (libinput->refcount > 0)
return libinput;
libinput_suspend(libinput);
@ -724,6 +731,8 @@ libinput_destroy(struct libinput *libinput)
libinput_drop_destroyed_sources(libinput);
close(libinput->epoll_fd);
free(libinput);
return NULL;
}
LIBINPUT_EXPORT void
@ -769,10 +778,11 @@ libinput_seat_init(struct libinput_seat *seat,
list_insert(&libinput->seat_list, &seat->link);
}
LIBINPUT_EXPORT void
LIBINPUT_EXPORT struct libinput_seat *
libinput_seat_ref(struct libinput_seat *seat)
{
seat->refcount++;
return seat;
}
static void
@ -784,13 +794,17 @@ libinput_seat_destroy(struct libinput_seat *seat)
seat->destroy(seat);
}
LIBINPUT_EXPORT void
LIBINPUT_EXPORT struct libinput_seat *
libinput_seat_unref(struct libinput_seat *seat)
{
assert(seat->refcount > 0);
seat->refcount--;
if (seat->refcount == 0)
if (seat->refcount == 0) {
libinput_seat_destroy(seat);
return NULL;
} else {
return seat;
}
}
LIBINPUT_EXPORT void
@ -825,10 +839,11 @@ libinput_device_init(struct libinput_device *device,
device->refcount = 1;
}
LIBINPUT_EXPORT void
LIBINPUT_EXPORT struct libinput_device *
libinput_device_ref(struct libinput_device *device)
{
device->refcount++;
return device;
}
static void
@ -837,13 +852,17 @@ libinput_device_destroy(struct libinput_device *device)
evdev_device_destroy((struct evdev_device *) device);
}
LIBINPUT_EXPORT void
LIBINPUT_EXPORT struct libinput_device *
libinput_device_unref(struct libinput_device *device)
{
assert(device->refcount > 0);
device->refcount--;
if (device->refcount == 0)
if (device->refcount == 0) {
libinput_device_destroy(device);
return NULL;
} else {
return device;
}
}
LIBINPUT_EXPORT int
@ -879,14 +898,14 @@ libinput_dispatch(struct libinput *libinput)
static uint32_t
update_seat_key_count(struct libinput_seat *seat,
int32_t key,
enum libinput_keyboard_key_state state)
enum libinput_key_state state)
{
assert(key >= 0 && key <= KEY_MAX);
switch (state) {
case LIBINPUT_KEYBOARD_KEY_STATE_PRESSED:
case LIBINPUT_KEY_STATE_PRESSED:
return ++seat->button_count[key];
case LIBINPUT_KEYBOARD_KEY_STATE_RELEASED:
case LIBINPUT_KEY_STATE_RELEASED:
/* We might not have received the first PRESSED event. */
if (seat->button_count[key] == 0)
return 0;
@ -978,7 +997,7 @@ void
keyboard_notify_key(struct libinput_device *device,
uint32_t time,
uint32_t key,
enum libinput_keyboard_key_state state)
enum libinput_key_state state)
{
struct libinput_event_keyboard *key_event;
uint32_t seat_key_count;

View file

@ -33,6 +33,7 @@ extern "C" {
#define LIBINPUT_ATTRIBUTE_PRINTF(_format, _args) \
__attribute__ ((format (printf, _format, _args)))
#define LIBINPUT_ATTRIBUTE_DEPRECATED __attribute__ ((deprecated))
/**
* @mainpage
@ -49,7 +50,7 @@ extern "C" {
*
* Software button areas
* =====================
* On most touchpads, the bottom area of the touchpad is split into a a left
* On most touchpads, the bottom area of the touchpad is split into a left
* and a right-button area. Pressing the touchpad down with a finger in
* those areas will generate clicks as shown in the diagram below:
*
@ -131,9 +132,9 @@ enum libinput_device_capability {
* Logical state of a key. Note that the logical state may not represent
* the physical state of the key.
*/
enum libinput_keyboard_key_state {
LIBINPUT_KEYBOARD_KEY_STATE_RELEASED = 0,
LIBINPUT_KEYBOARD_KEY_STATE_PRESSED = 1
enum libinput_key_state {
LIBINPUT_KEY_STATE_RELEASED = 0,
LIBINPUT_KEY_STATE_PRESSED = 1
};
/**
@ -165,8 +166,8 @@ enum libinput_button_state {
* Axes on a device that are not x or y coordinates.
*/
enum libinput_pointer_axis {
LIBINPUT_POINTER_AXIS_VERTICAL_SCROLL = 0,
LIBINPUT_POINTER_AXIS_HORIZONTAL_SCROLL = 1
LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL = 0,
LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL = 1,
};
/**
@ -462,7 +463,7 @@ libinput_event_keyboard_get_key(struct libinput_event_keyboard *event);
*
* @return The state change of the key
*/
enum libinput_keyboard_key_state
enum libinput_key_state
libinput_event_keyboard_get_key_state(struct libinput_event_keyboard *event);
@ -681,8 +682,8 @@ libinput_event_pointer_get_axis(struct libinput_event_pointer *event);
*
* Return the axis value of the given axis. The interpretation of the value
* is dependent on the axis. For the two scrolling axes
* LIBINPUT_POINTER_AXIS_VERTICAL_SCROLL and
* LIBINPUT_POINTER_AXIS_HORIZONTAL_SCROLL, the value of the event is in
* LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL and
* LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL, the value of the event is in
* relative scroll units, with the positive direction being down or right,
* respectively. The dimension of a scroll unit is equal to one unit of
* motion in the respective axis, where applicable (e.g. touchpad two-finger
@ -1051,7 +1052,7 @@ struct libinput_interface {
* @param path The device path to open
* @param flags Flags as defined by open(2)
* @param user_data The user_data provided in
* libinput_udev_create_for_seat()
* libinput_udev_create_context()
*
* @return the file descriptor, or a negative errno on failure.
*/
@ -1061,7 +1062,7 @@ struct libinput_interface {
*
* @param fd The file descriptor to close
* @param user_data The user_data provided in
* libinput_udev_create_for_seat()
* libinput_udev_create_context()
*/
void (*close_restricted)(int fd, void *user_data);
};
@ -1069,31 +1070,45 @@ struct libinput_interface {
/**
* @ingroup base
*
* Create a new libinput context from udev, for input devices matching
* the given seat ID. New devices or devices removed will appear as events
* during libinput_dispatch.
*
* libinput_udev_create_for_seat() succeeds even if no input device is
* available in this seat, or if devices are available but fail to open in
* @ref libinput_interface::open_restricted. Devices that do not have the
* minimum capabilities to be recognized as pointer, keyboard or touch
* device are ignored. Such devices and those that failed to open
* ignored until the next call to libinput_resume().
* Create a new libinput context from udev. This context is inactive until
* assigned a seat ID with libinput_udev_assign_seat().
*
* @param interface The callback interface
* @param user_data Caller-specific data passed to the various callback
* interfaces.
* @param udev An already initialized udev context
* @param seat_id A seat identifier. This string must not be NULL.
*
* @return An initialized libinput context, ready to handle events or NULL on
* error.
* @return An initialized, but inactive libinput context or NULL on error
*/
struct libinput *
libinput_udev_create_for_seat(const struct libinput_interface *interface,
void *user_data,
struct udev *udev,
const char *seat_id);
libinput_udev_create_context(const struct libinput_interface *interface,
void *user_data,
struct udev *udev);
/**
* @ingroup base
*
* Assign a seat to this libinput context. New devices or the removal of
* existing devices will appear as events during libinput_dispatch().
*
* libinput_udev_assign_seat() succeeds even if no input devices are currently
* available on this seat, or if devices are available but fail to open in
* @ref libinput_interface::open_restricted. Devices that do not have the
* minimum capabilities to be recognized as pointer, keyboard or touch
* device are ignored. Such devices and those that failed to open
* ignored until the next call to libinput_resume().
*
* This function may only be called once per context.
*
* @param libinput A libinput context initialized with
* libinput_udev_create_context()
* @param seat_id A seat identifier. This string must not be NULL.
*
* @return 0 on success or -1 on failure.
*/
int
libinput_udev_assign_seat(struct libinput *libinput,
const char *seat_id);
/**
* @ingroup base
@ -1105,6 +1120,9 @@ libinput_udev_create_for_seat(const struct libinput_interface *interface,
* The context is fully initialized but will not generate events until at
* least one device has been added.
*
* The reference count of the context is initialized to 1. See @ref
* libinput_unref.
*
* @param interface The callback interface
* @param user_data Caller-specific data passed to the various callback
* interfaces.
@ -1133,7 +1151,7 @@ libinput_path_create_context(const struct libinput_interface *interface,
* @return The newly initiated device on success, or NULL on failure.
*
* @note It is an application bug to call this function on a libinput
* context initialized with libinput_udev_create_for_seat().
* context initialized with libinput_udev_create_context().
*/
struct libinput_device *
libinput_path_add_device(struct libinput *libinput,
@ -1155,7 +1173,7 @@ libinput_path_add_device(struct libinput *libinput,
* @param device A libinput device
*
* @note It is an application bug to call this function on a libinput
* context initialized with libinput_udev_create_for_seat().
* context initialized with libinput_udev_create_context().
*/
void
libinput_path_remove_device(struct libinput_device *device);
@ -1254,13 +1272,27 @@ libinput_suspend(struct libinput *libinput);
/**
* @ingroup base
*
* Destroy the libinput context. After this, object references associated with
* the destroyed context are invalid and may not be interacted with.
* Add a reference to the context. A context is destroyed whenever the
* reference count reaches 0. See @ref libinput_unref.
*
* @param libinput A previously initialized valid libinput context
* @return The passed libinput context
*/
struct libinput *
libinput_ref(struct libinput *libinput);
/**
* @ingroup base
*
* Dereference the libinput context. After this, the context may have been
* destroyed, if the last reference was dereferenced. If so, the context is
* invalid and may not be interacted with.
*
* @param libinput A previously initialized libinput context
* @return NULL if context was destroyed otherwise the passed context
*/
void
libinput_destroy(struct libinput *libinput);
struct libinput *
libinput_unref(struct libinput *libinput);
/**
* @ingroup base
@ -1270,13 +1302,15 @@ libinput_destroy(struct libinput *libinput);
*
* The default log priority is LIBINPUT_LOG_PRIORITY_ERROR.
*
* @param libinput A previously initialized libinput context
* @param priority The minimum priority of log messages to print.
*
* @see libinput_log_set_handler
* @see libinput_log_get_priority
*/
void
libinput_log_set_priority(enum libinput_log_priority priority);
libinput_log_set_priority(struct libinput *libinput,
enum libinput_log_priority priority);
/**
* @ingroup base
@ -1286,30 +1320,30 @@ libinput_log_set_priority(enum libinput_log_priority priority);
*
* The default log priority is LIBINPUT_LOG_PRIORITY_ERROR.
*
* @param libinput A previously initialized libinput context
* @return The minimum priority of log messages to print.
*
* @see libinput_log_set_handler
* @see libinput_log_set_priority
*/
enum libinput_log_priority
libinput_log_get_priority(void);
libinput_log_get_priority(const struct libinput *libinput);
/**
* @ingroup base
*
* Log handler type for custom logging.
*
* @param libinput The libinput context
* @param priority The priority of the current message
* @param user_data Caller-specific data pointer as previously passed into
* libinput_log_set_handler()
* @param format Message format in printf-style
* @param args Message arguments
*
* @see libinput_set_log_priority
* @see libinput_log_set_handler
*/
typedef void (*libinput_log_handler)(enum libinput_log_priority priority,
void *user_data,
typedef void (*libinput_log_handler)(struct libinput *libinput,
enum libinput_log_priority priority,
const char *format, va_list args)
LIBINPUT_ATTRIBUTE_PRINTF(3, 0);
@ -1322,6 +1356,7 @@ typedef void (*libinput_log_handler)(enum libinput_log_priority priority,
*
* The default log handler prints to stderr.
*
* @param libinput A previously initialized libinput context
* @param log_handler The log handler for library messages.
* @param user_data Caller-specific data pointer, passed into the log
* handler.
@ -1329,8 +1364,8 @@ typedef void (*libinput_log_handler)(enum libinput_log_priority priority,
* @see libinput_log_set_handler
*/
void
libinput_log_set_handler(libinput_log_handler log_handler,
void *user_data);
libinput_log_set_handler(struct libinput *libinput,
libinput_log_handler log_handler);
/**
* @defgroup seat Initialization and manipulation of seats
@ -1367,8 +1402,9 @@ libinput_log_set_handler(libinput_log_handler log_handler,
* the seat correctly to avoid dangling pointers.
*
* @param seat A previously obtained seat
* @return The passed seat
*/
void
struct libinput_seat *
libinput_seat_ref(struct libinput_seat *seat);
/**
@ -1380,8 +1416,9 @@ libinput_seat_ref(struct libinput_seat *seat);
* the seat correctly to avoid dangling pointers.
*
* @param seat A previously obtained seat
* @return NULL if seat was destroyed, otherwise the passed seat
*/
void
struct libinput_seat *
libinput_seat_unref(struct libinput_seat *seat);
/**
@ -1415,7 +1452,7 @@ libinput_seat_get_user_data(struct libinput_seat *seat);
*
* Return the physical name of the seat. For libinput contexts created from
* udev, this is always the same value as passed into
* libinput_udev_create_for_seat() and all seats from that context will have
* libinput_udev_assign_seat() and all seats from that context will have
* the same physical name.
*
* The physical name of the seat is one that is usually set by the system or
@ -1454,8 +1491,9 @@ libinput_seat_get_logical_name(struct libinput_seat *seat);
* the device correctly to avoid dangling pointers.
*
* @param device A previously obtained device
* @return The passed device
*/
void
struct libinput_device *
libinput_device_ref(struct libinput_device *device);
/**
@ -1467,8 +1505,9 @@ libinput_device_ref(struct libinput_device *device);
* the device correctly to avoid dangling pointers.
*
* @param device A previously obtained device
* @return NULL if device was destroyed, otherwise the passed device
*/
void
struct libinput_device *
libinput_device_unref(struct libinput_device *device);
/**

View file

@ -160,7 +160,9 @@ path_device_enable(struct path_input *input, const char *devnode)
if (path_get_udev_properties(devnode, &sysname,
&seat_name, &seat_logical_name) == -1) {
log_info("failed to obtain sysname for device '%s'.\n", devnode);
log_info(&input->base,
"failed to obtain sysname for device '%s'.\n",
devnode);
return NULL;
}
@ -171,7 +173,9 @@ path_device_enable(struct path_input *input, const char *devnode)
} else {
seat = path_seat_create(input, seat_name, seat_logical_name);
if (!seat) {
log_info("failed to create seat for device '%s'.\n", devnode);
log_info(&input->base,
"failed to create seat for device '%s'.\n",
devnode);
goto out;
}
}
@ -181,10 +185,14 @@ path_device_enable(struct path_input *input, const char *devnode)
if (device == EVDEV_UNHANDLED_DEVICE) {
device = NULL;
log_info("not using input device '%s'.\n", devnode);
log_info(&input->base,
"not using input device '%s'.\n",
devnode);
goto out;
} else if (device == NULL) {
log_info("failed to create input device '%s'.\n", devnode);
log_info(&input->base,
"failed to create input device '%s'.\n",
devnode);
goto out;
}
@ -264,7 +272,7 @@ libinput_path_add_device(struct libinput *libinput,
struct libinput_device *device;
if (libinput->interface_backend != &interface_backend) {
log_bug_client("Mismatching backends.\n");
log_bug_client(libinput, "Mismatching backends.\n");
return NULL;
}
@ -301,7 +309,7 @@ libinput_path_remove_device(struct libinput_device *device)
struct path_device *dev;
if (libinput->interface_backend != &interface_backend) {
log_bug_client("Mismatching backends.\n");
log_bug_client(libinput, "Mismatching backends.\n");
return;
}

View file

@ -22,6 +22,7 @@
#include <assert.h>
#include <errno.h>
#include <inttypes.h>
#include <string.h>
#include <sys/timerfd.h>
#include <unistd.h>
@ -59,12 +60,28 @@ libinput_timer_arm_timer_fd(struct libinput *libinput)
r = timerfd_settime(libinput->timer.fd, TFD_TIMER_ABSTIME, &its, NULL);
if (r)
log_error("timerfd_settime error: %s\n", strerror(errno));
log_error(libinput, "timerfd_settime error: %s\n", strerror(errno));
}
void
libinput_timer_set(struct libinput_timer *timer, uint64_t expire)
{
#ifndef NDEBUG
struct timespec ts;
if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) {
uint64_t now = ts.tv_sec * 1000ULL + ts.tv_nsec / 1000000;
if (abs(expire - now) > 5000)
log_bug_libinput(timer->libinput,
"timer offset more than 5s, now %"
PRIu64 " expire %" PRIu64 "\n",
now, expire);
} else {
log_error(timer->libinput,
"clock_gettime error: %s\n", strerror(errno));
}
#endif
assert(expire);
if (!timer->expire)
@ -96,7 +113,7 @@ libinput_timer_handler(void *data)
r = clock_gettime(CLOCK_MONOTONIC, &ts);
if (r) {
log_error("clock_gettime error: %s\n", strerror(errno));
log_error(libinput, "clock_gettime error: %s\n", strerror(errno));
return;
}

View file

@ -80,10 +80,10 @@ device_added(struct udev_device *udev_device, struct udev_input *input)
libinput_seat_unref(&seat->base);
if (device == EVDEV_UNHANDLED_DEVICE) {
log_info("not using input device '%s'.\n", devnode);
log_info(&input->base, "not using input device '%s'.\n", devnode);
return 0;
} else if (device == NULL) {
log_info("failed to create input device '%s'.\n", devnode);
log_info(&input->base, "failed to create input device '%s'.\n", devnode);
return 0;
}
@ -100,7 +100,8 @@ device_added(struct udev_device *udev_device, struct udev_input *input)
&device->abs.calibration[4],
&device->abs.calibration[5]) == 6) {
device->abs.apply_calibration = 1;
log_info("Applying calibration: %f %f %f %f %f %f\n",
log_info(&input->base,
"Applying calibration: %f %f %f %f %f %f\n",
device->abs.calibration[0],
device->abs.calibration[1],
device->abs.calibration[2],
@ -128,7 +129,8 @@ device_removed(struct udev_device *udev_device, struct udev_input *input)
list_for_each_safe(device, next,
&seat->base.devices_list, base.link) {
if (!strcmp(device->devnode, devnode)) {
log_info("input device %s, %s removed\n",
log_info(&input->base,
"input device %s, %s removed\n",
device->devname, device->devnode);
evdev_device_remove(device);
break;
@ -243,7 +245,8 @@ udev_input_enable(struct libinput *libinput)
input->udev_monitor = udev_monitor_new_from_netlink(udev, "udev");
if (!input->udev_monitor) {
log_info("udev: failed to create the udev monitor\n");
log_info(libinput,
"udev: failed to create the udev monitor\n");
return -1;
}
@ -251,7 +254,7 @@ udev_input_enable(struct libinput *libinput)
"input", NULL);
if (udev_monitor_enable_receiving(input->udev_monitor)) {
log_info("udev: failed to bind the udev monitor\n");
log_info(libinput, "udev: failed to bind the udev monitor\n");
udev_monitor_unref(input->udev_monitor);
input->udev_monitor = NULL;
return -1;
@ -333,14 +336,13 @@ static const struct libinput_interface_backend interface_backend = {
};
LIBINPUT_EXPORT struct libinput *
libinput_udev_create_for_seat(const struct libinput_interface *interface,
void *user_data,
struct udev *udev,
const char *seat_id)
libinput_udev_create_context(const struct libinput_interface *interface,
void *user_data,
struct udev *udev)
{
struct udev_input *input;
if (!interface || !udev || !seat_id)
if (!interface || !udev)
return NULL;
input = zalloc(sizeof *input);
@ -349,19 +351,36 @@ libinput_udev_create_for_seat(const struct libinput_interface *interface,
if (libinput_init(&input->base, interface,
&interface_backend, user_data) != 0) {
libinput_unref(&input->base);
free(input);
return NULL;
}
input->udev = udev_ref(udev);
input->seat_id = strdup(seat_id);
if (udev_input_enable(&input->base) < 0) {
udev_unref(udev);
libinput_destroy(&input->base);
free(input);
return NULL;
}
return &input->base;
}
LIBINPUT_EXPORT int
libinput_udev_assign_seat(struct libinput *libinput,
const char *seat_id)
{
struct udev_input *input = (struct udev_input*)libinput;
if (!seat_id)
return -1;
if (input->seat_id != NULL)
return -1;
if (libinput->interface_backend != &interface_backend) {
log_bug_client(libinput, "Mismatching backends.\n");
return -1;
}
input->seat_id = strdup(seat_id);
if (udev_input_enable(&input->base) < 0)
return -1;
return 0;
}

6
test/50-litest.conf Normal file
View file

@ -0,0 +1,6 @@
# Ignore devices created by libinput's test suite (litest)
Section "InputClass"
Identifier "libinput test suite blacklist"
MatchProduct "litest"
Option "Ignore" "on"
EndSection

View file

@ -64,7 +64,7 @@ START_TEST(keyboard_seat_key_count)
ck_assert_notnull(kev);
ck_assert_int_eq(libinput_event_keyboard_get_key(kev), KEY_A);
ck_assert_int_eq(libinput_event_keyboard_get_key_state(kev),
LIBINPUT_KEYBOARD_KEY_STATE_PRESSED);
LIBINPUT_KEY_STATE_PRESSED);
++expected_key_button_count;
seat_key_count =
@ -93,7 +93,7 @@ START_TEST(keyboard_seat_key_count)
ck_assert_notnull(kev);
ck_assert_int_eq(libinput_event_keyboard_get_key(kev), KEY_A);
ck_assert_int_eq(libinput_event_keyboard_get_key_state(kev),
LIBINPUT_KEYBOARD_KEY_STATE_RELEASED);
LIBINPUT_KEY_STATE_RELEASED);
--expected_key_button_count;
seat_key_count =
@ -108,7 +108,7 @@ START_TEST(keyboard_seat_key_count)
for (i = 0; i < num_devices; ++i)
litest_delete_device(devices[i]);
libinput_destroy(libinput);
libinput_unref(libinput);
}
END_TEST

View file

@ -44,6 +44,7 @@
#include "libinput-util.h"
static int in_debugger = -1;
static int verbose = 0;
struct test {
struct list node;
@ -258,8 +259,8 @@ litest_list_tests(struct list *tests)
}
static void
litest_log_handler(enum libinput_log_priority pri,
void *user_data,
litest_log_handler(struct libinput *libinput,
enum libinput_log_priority pri,
const char *format,
va_list args)
{
@ -275,6 +276,23 @@ litest_log_handler(enum libinput_log_priority pri,
vfprintf(stderr, format, args);
}
static int
open_restricted(const char *path, int flags, void *userdata)
{
return open(path, flags);
}
static void
close_restricted(int fd, void *userdata)
{
close(fd);
}
struct libinput_interface interface = {
.open_restricted = open_restricted,
.close_restricted = close_restricted,
};
static const struct option opts[] = {
{ "list", 0, 0, 'l' },
{ "verbose", 0, 0, 'v' },
@ -312,8 +330,7 @@ litest_run(int argc, char **argv) {
litest_list_tests(&all_tests);
return 0;
case 'v':
libinput_log_set_priority(LIBINPUT_LOG_PRIORITY_DEBUG);
libinput_log_set_handler(litest_log_handler, NULL);
verbose = 1;
break;
default:
fprintf(stderr, "usage: %s [--list]\n", argv[0]);
@ -343,24 +360,6 @@ litest_run(int argc, char **argv) {
return failed;
}
static int
open_restricted(const char *path, int flags, void *userdata)
{
return open(path, flags);
}
static void
close_restricted(int fd, void *userdata)
{
close(fd);
}
const struct libinput_interface interface = {
.open_restricted = open_restricted,
.close_restricted = close_restricted,
};
static struct input_absinfo *
merge_absinfo(const struct input_absinfo *orig,
const struct input_absinfo *override)
@ -491,6 +490,11 @@ litest_create_context(void)
struct libinput *libinput =
libinput_path_create_context(&interface, NULL);
ck_assert_notnull(libinput);
libinput_log_set_handler(libinput, litest_log_handler);
if (verbose)
libinput_log_set_priority(libinput, LIBINPUT_LOG_PRIORITY_DEBUG);
return libinput;
}
@ -581,7 +585,7 @@ litest_delete_device(struct litest_device *d)
libinput_device_unref(d->libinput_device);
if (d->owns_context)
libinput_destroy(d->libinput);
libinput_unref(d->libinput);
libevdev_free(d->evdev);
libevdev_uinput_destroy(d->uinput);
memset(d,0, sizeof(*d));
@ -915,11 +919,13 @@ litest_create_uinput_device_from_description(const char *name,
.flat = 0,
.resolution = 100
};
char buf[512];
dev = libevdev_new();
ck_assert(dev != NULL);
libevdev_set_name(dev, name);
snprintf(buf, sizeof(buf), "litest %s", name);
libevdev_set_name(dev, buf);
if (id) {
libevdev_set_id_bustype(dev, id->bustype);
libevdev_set_id_vendor(dev, id->vendor);

View file

@ -32,7 +32,7 @@
#include "litest.h"
static int log_handler_called;
static void *log_handler_userdata;
static struct libinput *log_handler_context;
static int open_restricted(const char *path, int flags, void *data)
{
@ -51,130 +51,90 @@ const struct libinput_interface simple_interface = {
};
static void
simple_log_handler(enum libinput_log_priority priority,
void *userdata,
simple_log_handler(struct libinput *libinput,
enum libinput_log_priority priority,
const char *format,
va_list args)
{
log_handler_called++;
ck_assert(userdata == log_handler_userdata);
if (log_handler_context)
ck_assert(libinput == log_handler_context);
ck_assert(format != NULL);
}
START_TEST(log_default_priority)
{
enum libinput_log_priority pri;
struct libinput *li;
pri = libinput_log_get_priority();
li = libinput_path_create_context(&simple_interface, NULL);
pri = libinput_log_get_priority(li);
ck_assert_int_eq(pri, LIBINPUT_LOG_PRIORITY_ERROR);
libinput_unref(li);
}
END_TEST
START_TEST(log_handler_invoked)
{
struct libinput *li;
enum libinput_log_priority pri = libinput_log_get_priority();
libinput_log_set_priority(LIBINPUT_LOG_PRIORITY_DEBUG);
libinput_log_set_handler(simple_log_handler, NULL);
log_handler_userdata = NULL;
li = libinput_path_create_context(&simple_interface, NULL);
libinput_log_set_priority(li, LIBINPUT_LOG_PRIORITY_DEBUG);
libinput_log_set_handler(li, simple_log_handler);
log_handler_context = li;
libinput_path_add_device(li, "/tmp");
ck_assert_int_gt(log_handler_called, 0);
log_handler_called = 0;
libinput_destroy(li);
libinput_log_set_priority(pri);
}
END_TEST
libinput_unref(li);
START_TEST(log_userdata_NULL)
{
struct libinput *li;
enum libinput_log_priority pri = libinput_log_get_priority();
libinput_log_set_priority(LIBINPUT_LOG_PRIORITY_DEBUG);
libinput_log_set_handler(simple_log_handler, NULL);
log_handler_userdata = NULL;
li = libinput_path_create_context(&simple_interface, NULL);
libinput_path_add_device(li, "/tmp");
ck_assert_int_gt(log_handler_called, 0);
log_handler_called = 0;
libinput_destroy(li);
libinput_log_set_priority(pri);
}
END_TEST
START_TEST(log_userdata)
{
struct libinput *li;
enum libinput_log_priority pri = libinput_log_get_priority();
libinput_log_set_priority(LIBINPUT_LOG_PRIORITY_DEBUG);
libinput_log_set_handler(simple_log_handler, &li);
log_handler_userdata = &li;
li = libinput_path_create_context(&simple_interface, NULL);
libinput_path_add_device(li, "/tmp");
ck_assert_int_gt(log_handler_called, 0);
log_handler_called = 0;
libinput_destroy(li);
libinput_log_set_priority(pri);
log_handler_context = NULL;
}
END_TEST
START_TEST(log_handler_NULL)
{
struct libinput *li;
enum libinput_log_priority pri = libinput_log_get_priority();
libinput_log_set_priority(LIBINPUT_LOG_PRIORITY_DEBUG);
libinput_log_set_handler(NULL, NULL);
log_handler_userdata = NULL;
li = libinput_path_create_context(&simple_interface, NULL);
libinput_log_set_priority(li, LIBINPUT_LOG_PRIORITY_DEBUG);
libinput_log_set_handler(li, NULL);
libinput_path_add_device(li, "/tmp");
ck_assert_int_eq(log_handler_called, 0);
log_handler_called = 0;
libinput_log_set_handler(simple_log_handler, NULL);
libinput_destroy(li);
libinput_log_set_priority(pri);
libinput_unref(li);
}
END_TEST
START_TEST(log_priority)
{
struct libinput *li;
enum libinput_log_priority pri = libinput_log_get_priority();
libinput_log_set_priority(LIBINPUT_LOG_PRIORITY_ERROR);
libinput_log_set_handler(simple_log_handler, NULL);
log_handler_userdata = NULL;
li = libinput_path_create_context(&simple_interface, NULL);
libinput_log_set_priority(li, LIBINPUT_LOG_PRIORITY_ERROR);
libinput_log_set_handler(li, simple_log_handler);
log_handler_context = li;
libinput_path_add_device(li, "/tmp");
ck_assert_int_eq(log_handler_called, 0);
libinput_log_set_priority(LIBINPUT_LOG_PRIORITY_INFO);
libinput_log_set_priority(li, LIBINPUT_LOG_PRIORITY_INFO);
libinput_path_add_device(li, "/tmp");
ck_assert_int_gt(log_handler_called, 0);
log_handler_called = 0;
libinput_destroy(li);
libinput_log_set_priority(pri);
libinput_unref(li);
log_handler_context = NULL;
}
END_TEST
@ -182,8 +142,6 @@ int main (int argc, char **argv) {
litest_add_no_device("log:defaults", log_default_priority);
litest_add_no_device("log:logging", log_handler_invoked);
litest_add_no_device("log:logging", log_handler_NULL);
litest_add_no_device("log:logging", log_userdata);
litest_add_no_device("log:logging", log_userdata_NULL);
litest_add_no_device("log:logging", log_priority);
return litest_run(argc, argv);

View file

@ -134,7 +134,7 @@ START_TEST(event_conversion_device_notify)
libinput_event_destroy(event);
}
libinput_destroy(li);
libinput_unref(li);
libevdev_uinput_destroy(uinput);
ck_assert_int_gt(device_added, 0);
@ -195,7 +195,7 @@ START_TEST(event_conversion_pointer)
libinput_event_destroy(event);
}
libinput_destroy(li);
libinput_unref(li);
libevdev_uinput_destroy(uinput);
ck_assert_int_gt(motion, 0);
@ -255,7 +255,7 @@ START_TEST(event_conversion_pointer_abs)
libinput_event_destroy(event);
}
libinput_destroy(li);
libinput_unref(li);
libevdev_uinput_destroy(uinput);
ck_assert_int_gt(motion, 0);
@ -305,7 +305,7 @@ START_TEST(event_conversion_key)
libinput_event_destroy(event);
}
libinput_destroy(li);
libinput_unref(li);
libevdev_uinput_destroy(uinput);
ck_assert_int_gt(key, 0);
@ -365,7 +365,7 @@ START_TEST(event_conversion_touch)
libinput_event_destroy(event);
}
libinput_destroy(li);
libinput_unref(li);
libevdev_uinput_destroy(uinput);
ck_assert_int_gt(touch, 0);
@ -409,6 +409,25 @@ START_TEST(bitfield_helpers)
}
END_TEST
START_TEST(context_ref_counting)
{
struct libinput *li;
/* These tests rely on valgrind to detect memory leak and use after
* free errors. */
li = libinput_path_create_context(&simple_interface, NULL);
ck_assert_notnull(li);
ck_assert_ptr_eq(libinput_unref(li), NULL);
li = libinput_path_create_context(&simple_interface, NULL);
ck_assert_notnull(li);
ck_assert_ptr_eq(libinput_ref(li), li);
ck_assert_ptr_eq(libinput_unref(li), li);
ck_assert_ptr_eq(libinput_unref(li), NULL);
}
END_TEST
int main (int argc, char **argv) {
litest_add_no_device("events:conversion", event_conversion_device_notify);
litest_add_no_device("events:conversion", event_conversion_pointer);
@ -416,6 +435,7 @@ int main (int argc, char **argv) {
litest_add_no_device("events:conversion", event_conversion_key);
litest_add_no_device("events:conversion", event_conversion_touch);
litest_add_no_device("bitfield_helpers", bitfield_helpers);
litest_add_no_device("context:refcount", context_ref_counting);
return litest_run(argc, argv);
}

View file

@ -65,7 +65,7 @@ START_TEST(path_create_NULL)
ck_assert(li == NULL);
li = libinput_path_create_context(&simple_interface, NULL);
ck_assert(li != NULL);
libinput_destroy(li);
libinput_unref(li);
ck_assert_int_eq(open_func_count, 0);
ck_assert_int_eq(close_func_count, 0);
@ -92,7 +92,7 @@ START_TEST(path_create_invalid)
ck_assert_int_eq(open_func_count, 0);
ck_assert_int_eq(close_func_count, 0);
libinput_destroy(li);
libinput_unref(li);
ck_assert_int_eq(close_func_count, 0);
open_func_count = 0;
@ -126,7 +126,7 @@ START_TEST(path_create_destroy)
ck_assert_int_eq(open_func_count, 1);
libevdev_uinput_destroy(uinput);
libinput_destroy(li);
libinput_unref(li);
ck_assert_int_eq(close_func_count, 1);
open_func_count = 0;
@ -372,7 +372,7 @@ START_TEST(path_suspend)
libinput_resume(li);
libevdev_uinput_destroy(uinput);
libinput_destroy(li);
libinput_unref(li);
open_func_count = 0;
close_func_count = 0;
@ -406,7 +406,7 @@ START_TEST(path_double_suspend)
libinput_resume(li);
libevdev_uinput_destroy(uinput);
libinput_destroy(li);
libinput_unref(li);
open_func_count = 0;
close_func_count = 0;
@ -440,7 +440,7 @@ START_TEST(path_double_resume)
libinput_resume(li);
libevdev_uinput_destroy(uinput);
libinput_destroy(li);
libinput_unref(li);
open_func_count = 0;
close_func_count = 0;
@ -523,7 +523,7 @@ START_TEST(path_add_device_suspend_resume)
libevdev_uinput_destroy(uinput1);
libevdev_uinput_destroy(uinput2);
libinput_destroy(li);
libinput_unref(li);
open_func_count = 0;
close_func_count = 0;
@ -614,7 +614,7 @@ START_TEST(path_add_device_suspend_resume_fail)
ck_assert_int_eq(nevents, 2);
libevdev_uinput_destroy(uinput2);
libinput_destroy(li);
libinput_unref(li);
open_func_count = 0;
close_func_count = 0;
@ -704,7 +704,7 @@ START_TEST(path_add_device_suspend_resume_remove_device)
ck_assert_int_eq(nevents, 1);
libevdev_uinput_destroy(uinput1);
libinput_destroy(li);
libinput_unref(li);
open_func_count = 0;
close_func_count = 0;
@ -790,7 +790,7 @@ START_TEST(path_seat_recycle)
ck_assert(found == 1);
libinput_destroy(li);
libinput_unref(li);
libevdev_uinput_destroy(uinput);
}

View file

@ -181,8 +181,8 @@ test_wheel_event(struct litest_device *dev, int which, int amount)
ck_assert(ptrev != NULL);
ck_assert_int_eq(libinput_event_pointer_get_axis(ptrev),
which == REL_WHEEL ?
LIBINPUT_POINTER_AXIS_VERTICAL_SCROLL :
LIBINPUT_POINTER_AXIS_HORIZONTAL_SCROLL);
LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL :
LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL);
ck_assert_int_eq(libinput_event_pointer_get_axis_value(ptrev), expected);
libinput_event_destroy(event);
}
@ -292,7 +292,7 @@ START_TEST(pointer_seat_button_count)
for (i = 0; i < num_devices; ++i)
litest_delete_device(devices[i]);
libinput_destroy(libinput);
libinput_unref(libinput);
}
END_TEST

View file

@ -125,7 +125,7 @@ START_TEST(touchpad_1fg_tap)
assert_button_event(li, BTN_LEFT,
LIBINPUT_BUTTON_STATE_PRESSED);
usleep(300000); /* tap-n-drag timeout */
msleep(300); /* tap-n-drag timeout */
assert_button_event(li, BTN_LEFT,
LIBINPUT_BUTTON_STATE_RELEASED);
@ -177,7 +177,7 @@ START_TEST(touchpad_1fg_tap_n_drag)
ck_assert_int_eq(libinput_next_event_type(li), LIBINPUT_EVENT_NONE);
usleep(300000); /* tap-n-drag timeout */
msleep(300); /* tap-n-drag timeout */
assert_button_event(li, BTN_LEFT,
LIBINPUT_BUTTON_STATE_RELEASED);
@ -202,7 +202,31 @@ START_TEST(touchpad_2fg_tap)
assert_button_event(li, BTN_RIGHT,
LIBINPUT_BUTTON_STATE_PRESSED);
usleep(300000); /* tap-n-drag timeout */
msleep(300); /* tap-n-drag timeout */
assert_button_event(li, BTN_RIGHT,
LIBINPUT_BUTTON_STATE_RELEASED);
litest_assert_empty_queue(li);
}
END_TEST
START_TEST(touchpad_2fg_tap_inverted)
{
struct litest_device *dev = litest_current_device();
struct libinput *li = dev->libinput;
litest_drain_events(dev->libinput);
litest_touch_down(dev, 0, 50, 50);
litest_touch_down(dev, 1, 70, 70);
litest_touch_up(dev, 1);
litest_touch_up(dev, 0);
libinput_dispatch(li);
assert_button_event(li, BTN_RIGHT,
LIBINPUT_BUTTON_STATE_PRESSED);
msleep(300); /* tap-n-drag timeout */
assert_button_event(li, BTN_RIGHT,
LIBINPUT_BUTTON_STATE_RELEASED);
@ -681,7 +705,7 @@ START_TEST(clickpad_softbutton_left_1st_fg_move)
/* move out of the area, then wait for softbutton timer */
litest_touch_move_to(dev, 0, 20, 90, 90, 20, 10);
libinput_dispatch(li);
usleep(400000);
msleep(400);
libinput_dispatch(li);
litest_drain_events(li);
@ -982,13 +1006,13 @@ START_TEST(clickpad_topsoftbuttons_move_out_ignore)
litest_touch_down(dev, 0, 50, 5);
libinput_dispatch(li);
usleep(200000);
msleep(200);
libinput_dispatch(li);
litest_assert_empty_queue(li);
litest_touch_move_to(dev, 0, 50, 5, 80, 90, 20);
libinput_dispatch(li);
usleep(400000);
msleep(400);
libinput_dispatch(li);
litest_event(dev, EV_KEY, BTN_LEFT, 1);
@ -1002,6 +1026,95 @@ START_TEST(clickpad_topsoftbuttons_move_out_ignore)
}
END_TEST
static void
test_2fg_scroll(struct litest_device *dev, int dx, int dy, int sleep)
{
struct libinput *li = dev->libinput;
litest_touch_down(dev, 0, 47, 50);
litest_touch_down(dev, 1, 53, 50);
litest_touch_move_to(dev, 0, 47, 50, 47 + dx, 50 + dy, 5);
litest_touch_move_to(dev, 1, 53, 50, 53 + dx, 50 + dy, 5);
/* Avoid a small scroll being seen as a tap */
if (sleep) {
libinput_dispatch(li);
msleep(sleep);
libinput_dispatch(li);
}
litest_touch_up(dev, 1);
litest_touch_up(dev, 0);
libinput_dispatch(li);
}
static void
check_2fg_scroll(struct litest_device *dev, int axis, int dir)
{
struct libinput *li = dev->libinput;
struct libinput_event *event, *next_event;
struct libinput_event_pointer *ptrev;
event = libinput_get_event(li);
next_event = libinput_get_event(li);
ck_assert(next_event != NULL); /* At least 1 scroll + stop scroll */
while (event) {
ck_assert_int_eq(libinput_event_get_type(event),
LIBINPUT_EVENT_POINTER_AXIS);
ptrev = libinput_event_get_pointer_event(event);
ck_assert(ptrev != NULL);
ck_assert_int_eq(libinput_event_pointer_get_axis(ptrev), axis);
if (next_event) {
/* Normal scroll event, check dir */
if (dir > 0) {
ck_assert_int_ge(
libinput_event_pointer_get_axis_value(ptrev),
dir);
} else {
ck_assert_int_le(
libinput_event_pointer_get_axis_value(ptrev),
dir);
}
} else {
/* Last scroll event, must be 0 */
ck_assert_int_eq(
libinput_event_pointer_get_axis_value(ptrev),
0);
}
libinput_event_destroy(event);
event = next_event;
next_event = libinput_get_event(li);
}
}
START_TEST(touchpad_2fg_scroll)
{
struct litest_device *dev = litest_current_device();
struct libinput *li = dev->libinput;
litest_drain_events(li);
/* Note this mixes in a tiny amount of movement in the wrong direction,
which should be ignored */
test_2fg_scroll(dev, 1, 40, 0);
check_2fg_scroll(dev, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, 10);
test_2fg_scroll(dev, 1, -40, 0);
check_2fg_scroll(dev, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, -10);
test_2fg_scroll(dev, 40, 1, 0);
check_2fg_scroll(dev, LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL, 10);
test_2fg_scroll(dev, -40, 1, 0);
check_2fg_scroll(dev, LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL, -10);
/* 2fg scroll smaller than the threshold should not generate events */
test_2fg_scroll(dev, 1, 1, 200);
litest_assert_empty_queue(li);
}
END_TEST
int main(int argc, char **argv) {
litest_add("touchpad:motion", touchpad_1fg_motion, LITEST_TOUCHPAD, LITEST_ANY);
@ -1010,6 +1123,7 @@ int main(int argc, char **argv) {
litest_add("touchpad:tap", touchpad_1fg_tap, LITEST_TOUCHPAD, LITEST_ANY);
litest_add("touchpad:tap", touchpad_1fg_tap_n_drag, LITEST_TOUCHPAD, LITEST_ANY);
litest_add("touchpad:tap", touchpad_2fg_tap, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH);
litest_add("touchpad:tap", touchpad_2fg_tap_inverted, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH);
litest_add("touchpad:tap", touchpad_1fg_tap_click, LITEST_TOUCHPAD, LITEST_ANY);
litest_add("touchpad:tap", touchpad_2fg_tap_click, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH|LITEST_APPLE_CLICKPAD);
litest_add("touchpad:tap", touchpad_2fg_tap_click_apple, LITEST_APPLE_CLICKPAD, LITEST_ANY);
@ -1039,5 +1153,7 @@ int main(int argc, char **argv) {
litest_add("touchpad:topsoftbuttons", clickpad_topsoftbuttons_middle, LITEST_TOPBUTTONPAD, LITEST_ANY);
litest_add("touchpad:topsoftbuttons", clickpad_topsoftbuttons_move_out_ignore, LITEST_TOPBUTTONPAD, LITEST_ANY);
litest_add("touchpad:scroll", touchpad_2fg_scroll, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH);
return litest_run(argc, argv);
}

View file

@ -52,26 +52,25 @@ START_TEST(udev_create_NULL)
{
struct libinput *li;
const struct libinput_interface interface;
struct udev *udev = (struct udev*)0xdeadbeef;
const char *seat = (const char*)0xdeaddead;
struct udev *udev;
li = libinput_udev_create_for_seat(NULL, NULL, NULL, NULL);
udev = udev_new();
li = libinput_udev_create_context(NULL, NULL, NULL);
ck_assert(li == NULL);
li = libinput_udev_create_for_seat(&interface, NULL, NULL, NULL);
ck_assert(li == NULL);
li = libinput_udev_create_for_seat(NULL, NULL, udev, NULL);
ck_assert(li == NULL);
li = libinput_udev_create_for_seat(NULL, NULL, NULL, seat);
li = libinput_udev_create_context(&interface, NULL, NULL);
ck_assert(li == NULL);
li = libinput_udev_create_for_seat(&interface, NULL, udev, NULL);
ck_assert(li == NULL);
li = libinput_udev_create_for_seat(NULL, NULL, udev, seat);
li = libinput_udev_create_context(NULL, NULL, udev);
ck_assert(li == NULL);
li = libinput_udev_create_for_seat(&interface, NULL, NULL, seat);
ck_assert(li == NULL);
li = libinput_udev_create_context(&interface, NULL, udev);
ck_assert(li != NULL);
ck_assert_int_eq(libinput_udev_assign_seat(li, NULL), -1);
libinput_unref(li);
udev_unref(udev);
}
END_TEST
@ -85,8 +84,9 @@ START_TEST(udev_create_seat0)
udev = udev_new();
ck_assert(udev != NULL);
li = libinput_udev_create_for_seat(&simple_interface, NULL, udev, "seat0");
li = libinput_udev_create_context(&simple_interface, NULL, udev);
ck_assert(li != NULL);
ck_assert_int_eq(libinput_udev_assign_seat(li, "seat0"), 0);
fd = libinput_get_fd(li);
ck_assert_int_ge(fd, 0);
@ -97,7 +97,7 @@ START_TEST(udev_create_seat0)
ck_assert(event != NULL);
libinput_event_destroy(event);
libinput_destroy(li);
libinput_unref(li);
udev_unref(udev);
}
END_TEST
@ -113,8 +113,9 @@ START_TEST(udev_create_empty_seat)
ck_assert(udev != NULL);
/* expect a libinput reference, but no events */
li = libinput_udev_create_for_seat(&simple_interface, NULL, udev, "seatdoesntexist");
li = libinput_udev_create_context(&simple_interface, NULL, udev);
ck_assert(li != NULL);
ck_assert_int_eq(libinput_udev_assign_seat(li, "seatdoesntexist"), 0);
fd = libinput_get_fd(li);
ck_assert_int_ge(fd, 0);
@ -124,7 +125,7 @@ START_TEST(udev_create_empty_seat)
ck_assert(event == NULL);
libinput_event_destroy(event);
libinput_destroy(li);
libinput_unref(li);
udev_unref(udev);
}
END_TEST
@ -147,8 +148,9 @@ START_TEST(udev_added_seat_default)
udev = udev_new();
ck_assert(udev != NULL);
li = libinput_udev_create_for_seat(&simple_interface, NULL, udev, "seat0");
li = libinput_udev_create_context(&simple_interface, NULL, udev);
ck_assert(li != NULL);
ck_assert_int_eq(libinput_udev_assign_seat(li, "seat0"), 0);
libinput_dispatch(li);
while (!default_seat_found && (event = libinput_get_event(li))) {
@ -169,7 +171,7 @@ START_TEST(udev_added_seat_default)
ck_assert(default_seat_found);
libinput_destroy(li);
libinput_unref(li);
udev_unref(udev);
}
END_TEST
@ -184,8 +186,9 @@ START_TEST(udev_double_suspend)
udev = udev_new();
ck_assert(udev != NULL);
li = libinput_udev_create_for_seat(&simple_interface, NULL, udev, "seat0");
li = libinput_udev_create_context(&simple_interface, NULL, udev);
ck_assert(li != NULL);
ck_assert_int_eq(libinput_udev_assign_seat(li, "seat0"), 0);
fd = libinput_get_fd(li);
ck_assert_int_ge(fd, 0);
@ -200,7 +203,7 @@ START_TEST(udev_double_suspend)
libinput_resume(li);
libinput_event_destroy(event);
libinput_destroy(li);
libinput_unref(li);
udev_unref(udev);
}
END_TEST
@ -215,8 +218,9 @@ START_TEST(udev_double_resume)
udev = udev_new();
ck_assert(udev != NULL);
li = libinput_udev_create_for_seat(&simple_interface, NULL, udev, "seat0");
li = libinput_udev_create_context(&simple_interface, NULL, udev);
ck_assert(li != NULL);
ck_assert_int_eq(libinput_udev_assign_seat(li, "seat0"), 0);
fd = libinput_get_fd(li);
ck_assert_int_ge(fd, 0);
@ -231,7 +235,7 @@ START_TEST(udev_double_resume)
libinput_resume(li);
libinput_event_destroy(event);
libinput_destroy(li);
libinput_unref(li);
udev_unref(udev);
}
END_TEST
@ -266,8 +270,9 @@ START_TEST(udev_suspend_resume)
udev = udev_new();
ck_assert(udev != NULL);
li = libinput_udev_create_for_seat(&simple_interface, NULL, udev, "seat0");
li = libinput_udev_create_context(&simple_interface, NULL, udev);
ck_assert(li != NULL);
ck_assert_int_eq(libinput_udev_assign_seat(li, "seat0"), 0);
fd = libinput_get_fd(li);
ck_assert_int_ge(fd, 0);
@ -289,7 +294,7 @@ START_TEST(udev_suspend_resume)
process_events_count_devices(li, &num_devices);
ck_assert_int_gt(num_devices, 0);
libinput_destroy(li);
libinput_unref(li);
udev_unref(udev);
}
END_TEST
@ -305,8 +310,9 @@ START_TEST(udev_device_sysname)
udev = udev_new();
ck_assert(udev != NULL);
li = libinput_udev_create_for_seat(&simple_interface, NULL, udev, "seat0");
li = libinput_udev_create_context(&simple_interface, NULL, udev);
ck_assert(li != NULL);
ck_assert_int_eq(libinput_udev_assign_seat(li, "seat0"), 0);
libinput_dispatch(li);
@ -322,7 +328,7 @@ START_TEST(udev_device_sysname)
libinput_event_destroy(ev);
}
libinput_destroy(li);
libinput_unref(li);
udev_unref(udev);
}
END_TEST
@ -342,8 +348,9 @@ START_TEST(udev_seat_recycle)
udev = udev_new();
ck_assert(udev != NULL);
li = libinput_udev_create_for_seat(&simple_interface, NULL, udev, "seat0");
li = libinput_udev_create_context(&simple_interface, NULL, udev);
ck_assert(li != NULL);
ck_assert_int_eq(libinput_udev_assign_seat(li, "seat0"), 0);
libinput_dispatch(li);
while ((ev = libinput_get_event(li))) {
@ -396,7 +403,7 @@ START_TEST(udev_seat_recycle)
ck_assert(found == 1);
libinput_destroy(li);
libinput_unref(li);
udev_unref(udev);
}
END_TEST

1
tools/.gitignore vendored
View file

@ -1 +1,2 @@
event-debug
event-gui

View file

@ -7,3 +7,12 @@ event_debug_SOURCES = event-debug.c
event_debug_LDADD = ../src/libinput.la $(LIBUDEV_LIBS)
event_debug_LDFLAGS = -static
event_debug_CFLAGS = $(LIBUDEV_CFLAGS)
if BUILD_EVENTGUI
noinst_PROGRAMS += event-gui
event_gui_SOURCES = event-gui.c
event_gui_LDADD = ../src/libinput.la $(CAIRO_LIBS) $(GTK_LIBS) $(LIBUDEV_LIBS)
event_gui_CFLAGS = $(CAIRO_CFLAGS) $(GTK_CFLAGS) $(LIBUDEV_CFLAGS)
event_gui_LDFLAGS = -static
endif

View file

@ -131,6 +131,15 @@ static const struct libinput_interface interface = {
.close_restricted = close_restricted,
};
static void
log_handler(struct libinput *li,
enum libinput_log_priority priority,
const char *format,
va_list args)
{
vprintf(format, args);
}
static int
open_udev(struct libinput **li)
{
@ -140,12 +149,23 @@ open_udev(struct libinput **li)
return 1;
}
*li = libinput_udev_create_for_seat(&interface, NULL, udev, seat);
*li = libinput_udev_create_context(&interface, NULL, udev);
if (!*li) {
fprintf(stderr, "Failed to initialize context from udev\n");
return 1;
}
if (verbose) {
libinput_log_set_handler(*li, log_handler);
libinput_log_set_priority(*li, LIBINPUT_LOG_PRIORITY_DEBUG);
}
if (libinput_udev_assign_seat(*li, seat)) {
fprintf(stderr, "Failed to set seat\n");
libinput_unref(*li);
return 1;
}
return 0;
}
@ -160,10 +180,15 @@ open_device(struct libinput **li, const char *path)
return 1;
}
if (verbose) {
libinput_log_set_handler(*li, log_handler);
libinput_log_set_priority(*li, LIBINPUT_LOG_PRIORITY_DEBUG);
}
device = libinput_path_add_device(*li, path);
if (!device) {
fprintf(stderr, "Failed to initialized device %s\n", path);
libinput_destroy(*li);
libinput_unref(*li);
return 1;
}
@ -259,13 +284,13 @@ static void
print_key_event(struct libinput_event *ev)
{
struct libinput_event_keyboard *k = libinput_event_get_keyboard_event(ev);
enum libinput_keyboard_key_state state;
enum libinput_key_state state;
print_event_time(libinput_event_keyboard_get_time(k));
state = libinput_event_keyboard_get_key_state(k);
printf("%d %s\n",
libinput_event_keyboard_get_key(k),
state == LIBINPUT_KEYBOARD_KEY_STATE_PRESSED ? "pressed" : "released");
state == LIBINPUT_KEY_STATE_PRESSED ? "pressed" : "released");
}
static void
@ -332,10 +357,10 @@ print_pointer_axis_event(struct libinput_event *ev)
double val;
switch (axis) {
case LIBINPUT_POINTER_AXIS_VERTICAL_SCROLL:
case LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL:
ax = "vscroll";
break;
case LIBINPUT_POINTER_AXIS_HORIZONTAL_SCROLL:
case LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL:
ax = "hscroll";
break;
default:
@ -574,15 +599,6 @@ mainloop(struct libinput *li)
close(fds[1].fd);
}
static void
log_handler(enum libinput_log_priority priority,
void *user_data,
const char *format,
va_list args)
{
vprintf(format, args);
}
int
main(int argc, char **argv)
{
@ -592,11 +608,6 @@ main(int argc, char **argv)
if (parse_args(argc, argv))
return 1;
if (verbose) {
libinput_log_set_handler(log_handler, NULL);
libinput_log_set_priority(LIBINPUT_LOG_PRIORITY_DEBUG);
}
if (mode == MODE_UDEV) {
if (open_udev(&li))
return 1;
@ -611,7 +622,7 @@ main(int argc, char **argv)
mainloop(li);
libinput_destroy(li);
libinput_unref(li);
if (udev)
udev_unref(udev);

474
tools/event-gui.c Normal file
View file

@ -0,0 +1,474 @@
/*
* Copyright © 2014 Red Hat, Inc.
*
* Permission to use, copy, modify, distribute, and sell this software and
* its documentation for any purpose is hereby granted without fee, provided
* that the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of the copyright holders not be used in
* advertising or publicity pertaining to distribution of the software
* without specific, written prior permission. The copyright holders make
* no representations about the suitability of this software for any
* purpose. It is provided "as is" without express or implied warranty.
*
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
* CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#define _GNU_SOURCE
#include <config.h>
#include <linux/input.h>
#include <cairo.h>
#include <errno.h>
#include <fcntl.h>
#include <getopt.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <gtk/gtk.h>
#include <glib.h>
#include <libinput.h>
#include <libinput-util.h>
#define clip(val_, min_, max_) min((max_), max((min_), (val_)))
struct touch {
int active;
int x, y;
};
struct window {
GtkWidget *win;
GtkWidget *area;
int width, height; /* of window */
/* sprite position */
double x, y;
/* abs position */
int absx, absy;
/* scroll bar positions */
int vx, vy;
int hx, hy;
/* touch positions */
struct touch touches[32];
/* l/m/r mouse buttons */
int l, m, r;
};
static int
error(const char *fmt, ...)
{
va_list args;
fprintf(stderr, "error: ");
va_start(args, fmt);
vfprintf(stderr, fmt, args);
va_end(args);
return EXIT_FAILURE;
}
static void
msg(const char *fmt, ...)
{
va_list args;
printf("info: ");
va_start(args, fmt);
vprintf(fmt, args);
va_end(args);
}
static void
usage(void)
{
printf("%s [path/to/device]\n", program_invocation_short_name);
}
static gboolean
draw(GtkWidget *widget, cairo_t *cr, gpointer data)
{
struct window *w = data;
struct touch *t;
cairo_set_source_rgb(cr, 1, 1, 1);
cairo_rectangle(cr, 0, 0, w->width, w->height);
cairo_fill(cr);
/* draw pointer sprite */
cairo_set_source_rgb(cr, 0, 0, 0);
cairo_save(cr);
cairo_move_to(cr, w->x, w->y);
cairo_rel_line_to(cr, 10, 15);
cairo_rel_line_to(cr, -10, 0);
cairo_rel_line_to(cr, 0, -15);
cairo_fill(cr);
cairo_restore(cr);
/* draw scroll bars */
cairo_set_source_rgb(cr, .4, .8, 0);
cairo_save(cr);
cairo_rectangle(cr, w->vx - 10, w->vy - 20, 20, 40);
cairo_rectangle(cr, w->hx - 20, w->hy - 10, 40, 20);
cairo_fill(cr);
cairo_restore(cr);
/* touch points */
cairo_set_source_rgb(cr, .8, .2, .2);
ARRAY_FOR_EACH(w->touches, t) {
cairo_save(cr);
cairo_arc(cr, t->x, t->y, 10, 0, 2 * M_PI);
cairo_fill(cr);
cairo_restore(cr);
}
/* abs position */
cairo_set_source_rgb(cr, .2, .4, .8);
cairo_save(cr);
cairo_move_to(cr, w->absx, w->absy);
cairo_arc(cr, 0, 0, 10, 0, 2 * M_PI);
cairo_fill(cr);
cairo_restore(cr);
/* lmr buttons */
cairo_save(cr);
if (w->l || w->m || w->r) {
cairo_set_source_rgb(cr, .2, .8, .8);
if (w->l)
cairo_rectangle(cr, w->width/2 - 100, w->height - 200, 70, 30);
if (w->m)
cairo_rectangle(cr, w->width/2 - 20, w->height - 200, 40, 30);
if (w->r)
cairo_rectangle(cr, w->width/2 + 30, w->height - 200, 70, 30);
cairo_fill(cr);
}
cairo_set_source_rgb(cr, 0, 0, 0);
cairo_rectangle(cr, w->width/2 - 100, w->height - 200, 70, 30);
cairo_rectangle(cr, w->width/2 - 20, w->height - 200, 40, 30);
cairo_rectangle(cr, w->width/2 + 30, w->height - 200, 70, 30);
cairo_stroke(cr);
cairo_restore(cr);
return TRUE;
}
static void
map_event_cb(GtkWidget *widget, GdkEvent *event, gpointer data)
{
struct window *w = data;
gtk_window_get_size(GTK_WINDOW(widget), &w->width, &w->height);
w->x = w->width/2;
w->y = w->height/2;
w->vx = w->width/2;
w->vy = w->height/2;
w->hx = w->width/2;
w->hy = w->height/2;
g_signal_connect(G_OBJECT(w->area), "draw", G_CALLBACK(draw), w);
gdk_window_set_cursor(gtk_widget_get_window(w->win),
gdk_cursor_new(GDK_BLANK_CURSOR));
}
static void
window_init(struct window *w)
{
memset(w, 0, sizeof(*w));
w->win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_widget_set_events(w->win, 0);
gtk_window_set_title(GTK_WINDOW(w->win), "libinput debugging tool");
gtk_window_set_default_size(GTK_WINDOW(w->win), 1024, 768);
gtk_window_maximize(GTK_WINDOW(w->win));
gtk_window_set_resizable(GTK_WINDOW(w->win), TRUE);
gtk_widget_realize(w->win);
g_signal_connect(G_OBJECT(w->win), "map-event", G_CALLBACK(map_event_cb), w);
g_signal_connect(G_OBJECT(w->win), "delete-event", G_CALLBACK(gtk_main_quit), NULL);
w->area = gtk_drawing_area_new();
gtk_widget_set_events(w->area, 0);
gtk_container_add(GTK_CONTAINER(w->win), w->area);
gtk_widget_show_all(w->win);
}
static void
handle_event_device_notify(struct libinput_event *ev)
{
struct libinput_device *dev = libinput_event_get_device(ev);
const char *type;
if (libinput_event_get_type(ev) == LIBINPUT_EVENT_DEVICE_ADDED)
type = "added";
else
type = "removed";
msg("%s %s\n", libinput_device_get_sysname(dev), type);
}
static void
handle_event_motion(struct libinput_event *ev, struct window *w)
{
struct libinput_event_pointer *p = libinput_event_get_pointer_event(ev);
double dx = libinput_event_pointer_get_dx(p),
dy = libinput_event_pointer_get_dy(p);
w->x += dx;
w->y += dy;
w->x = clip(w->x, 0.0, w->width);
w->y = clip(w->y, 0.0, w->height);
}
static void
handle_event_absmotion(struct libinput_event *ev, struct window *w)
{
struct libinput_event_pointer *p = libinput_event_get_pointer_event(ev);
double x = libinput_event_pointer_get_absolute_x(p),
y = libinput_event_pointer_get_absolute_y(p);
w->absx = clip((int)x, 0, w->width);
w->absy = clip((int)y, 0, w->height);
}
static void
handle_event_touch(struct libinput_event *ev, struct window *w)
{
struct libinput_event_touch *t = libinput_event_get_touch_event(ev);
int slot = libinput_event_touch_get_seat_slot(t);
struct touch *touch;
double x, y;
if (slot == -1 || slot >= ARRAY_LENGTH(w->touches))
return;
touch = &w->touches[slot];
if (libinput_event_get_type(ev) == LIBINPUT_EVENT_TOUCH_UP) {
touch->active = 0;
return;
}
x = libinput_event_touch_get_x(t),
y = libinput_event_touch_get_y(t);
touch->active = 1;
touch->x = (int)x;
touch->y = (int)y;
}
static void
handle_event_axis(struct libinput_event *ev, struct window *w)
{
struct libinput_event_pointer *p = libinput_event_get_pointer_event(ev);
enum libinput_pointer_axis axis = libinput_event_pointer_get_axis(p);
double v = libinput_event_pointer_get_axis_value(p);
switch (axis) {
case LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL:
w->vy += (int)v;
w->vy = clip(w->vy, 0, w->height);
break;
case LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL:
w->hx += (int)v;
w->hx = clip(w->hx, 0, w->width);
break;
default:
abort();
}
}
static int
handle_event_keyboard(struct libinput_event *ev, struct window *w)
{
struct libinput_event_keyboard *k = libinput_event_get_keyboard_event(ev);
if (libinput_event_keyboard_get_key(k) == KEY_ESC)
return 1;
return 0;
}
static void
handle_event_button(struct libinput_event *ev, struct window *w)
{
struct libinput_event_pointer *p = libinput_event_get_pointer_event(ev);
unsigned int button = libinput_event_pointer_get_button(p);
int is_press;
is_press = libinput_event_pointer_get_button_state(p) == LIBINPUT_BUTTON_STATE_PRESSED;
switch (button) {
case BTN_LEFT:
w->l = is_press;
break;
case BTN_RIGHT:
w->r = is_press;
break;
case BTN_MIDDLE:
w->m = is_press;
break;
}
}
static gboolean
handle_event_libinput(GIOChannel *source, GIOCondition condition, gpointer data)
{
struct libinput *li = data;
struct window *w = libinput_get_user_data(li);
struct libinput_event *ev;
libinput_dispatch(li);
while ((ev = libinput_get_event(li))) {
switch (libinput_event_get_type(ev)) {
case LIBINPUT_EVENT_NONE:
abort();
case LIBINPUT_EVENT_DEVICE_ADDED:
case LIBINPUT_EVENT_DEVICE_REMOVED:
handle_event_device_notify(ev);
break;
case LIBINPUT_EVENT_POINTER_MOTION:
handle_event_motion(ev, w);
break;
case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE:
handle_event_absmotion(ev, w);
break;
case LIBINPUT_EVENT_TOUCH_DOWN:
case LIBINPUT_EVENT_TOUCH_MOTION:
case LIBINPUT_EVENT_TOUCH_UP:
handle_event_touch(ev, w);
break;
case LIBINPUT_EVENT_POINTER_AXIS:
handle_event_axis(ev, w);
break;
case LIBINPUT_EVENT_TOUCH_CANCEL:
case LIBINPUT_EVENT_TOUCH_FRAME:
break;
case LIBINPUT_EVENT_POINTER_BUTTON:
handle_event_button(ev, w);
break;
case LIBINPUT_EVENT_KEYBOARD_KEY:
if (handle_event_keyboard(ev, w)) {
libinput_event_destroy(ev);
gtk_main_quit();
return FALSE;
}
break;
}
libinput_event_destroy(ev);
libinput_dispatch(li);
}
gtk_widget_queue_draw(w->area);
return TRUE;
}
static void
sockets_init(struct libinput *li)
{
GIOChannel *c = g_io_channel_unix_new(libinput_get_fd(li));
g_io_channel_set_encoding(c, NULL, NULL);
g_io_add_watch(c, G_IO_IN, handle_event_libinput, li);
}
static int
parse_opts(int argc, char *argv[])
{
while (1) {
static struct option long_options[] = {
{ "help", no_argument, 0, 'h' },
};
int option_index = 0;
int c;
c = getopt_long(argc, argv, "h", long_options,
&option_index);
if (c == -1)
break;
switch(c) {
case 'h':
usage();
return 0;
default:
usage();
return 1;
}
}
return 0;
}
static int
open_restricted(const char *path, int flags, void *user_data)
{
int fd = open(path, flags);
return fd < 0 ? -errno : fd;
}
static void
close_restricted(int fd, void *user_data)
{
close(fd);
}
const static struct libinput_interface interface = {
.open_restricted = open_restricted,
.close_restricted = close_restricted,
};
int
main(int argc, char *argv[])
{
struct window w;
struct libinput *li;
struct udev *udev;
gtk_init(&argc, &argv);
if (parse_opts(argc, argv) != 0)
return 1;
udev = udev_new();
if (!udev)
error("Failed to initialize udev\n");
li = libinput_udev_create_context(&interface, &w, udev);
if (!li || libinput_udev_assign_seat(li, "seat0") != 0)
error("Failed to initialize context from udev\n");
window_init(&w);
sockets_init(li);
gtk_main();
libinput_unref(li);
udev_unref(udev);
return 0;
}