-----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iEYEABECAAYFAlURAX0ACgkQ4jt+cLRn8L9oeQCfUkFNZCSYwEGiuBQfx6wgGfBD
 vWgAoLiQ7zVV5Vko9NE4Lu4hPkt7UQ21
 =LvzY
 -----END PGP SIGNATURE-----

Merge tag '0.13.0' into tablet-support
This commit is contained in:
Peter Hutterer 2015-04-07 07:52:43 +10:00
commit 29ba32b330
13 changed files with 227 additions and 196 deletions

View file

@ -1,7 +1,7 @@
AC_PREREQ([2.64])
m4_define([libinput_major_version], [0])
m4_define([libinput_minor_version], [12])
m4_define([libinput_minor_version], [13])
m4_define([libinput_micro_version], [0])
m4_define([libinput_version],
[libinput_major_version.libinput_minor_version.libinput_micro_version])
@ -31,7 +31,7 @@ AM_INIT_AUTOMAKE([1.11 foreign no-dist-gzip dist-xz])
# b) If interfaces have been changed or added, but binary compatibility has
# been preserved, change to C+1:0:A+1
# c) If the interface is the same as the previous version, change to C:R+1:A
LIBINPUT_LT_VERSION=10:0:0
LIBINPUT_LT_VERSION=10:1:0
AC_SUBST(LIBINPUT_LT_VERSION)
AM_SILENT_RULES([yes])

View file

@ -57,11 +57,6 @@ See @ref motion_normalization for details.
<dd>The angle in degrees for each click on a mouse wheel. See
libinput_pointer_get_axis_source() for details.
</dd>
<dt>TOUCHPAD_RESOLUTION</dt>
<dd>The x and y resolution in units/mm for a touchpad. This value is only
used if the touchpad kernel driver does not supply a valid resolution. It
is only used on touchpad devices. The format is two unsigned integer values
separated by a literal 'x', e.g. "42x129".</dd>
</dl>
Below is an example udev rule to assign "seat1" to a device from vendor

View file

@ -64,21 +64,27 @@ tp_filter_motion(struct tp_dispatch *tp,
double *dx_unaccel, double *dy_unaccel,
uint64_t time)
{
struct motion_params motion;
struct normalized_coords unaccelerated;
struct normalized_coords accelerated;
motion.dx = *dx;
motion.dy = *dy;
unaccelerated.x = *dx;
unaccelerated.y = *dy;
if (unaccelerated.x != 0.0 || unaccelerated.y != 0.0)
accelerated = filter_dispatch(tp->device->pointer.filter,
&unaccelerated,
tp,
time);
else
accelerated = unaccelerated;
if (dx_unaccel)
*dx_unaccel = motion.dx;
*dx_unaccel = unaccelerated.x;
if (dy_unaccel)
*dy_unaccel = motion.dy;
*dy_unaccel = unaccelerated.y;
if (motion.dx != 0.0 || motion.dy != 0.0)
filter_dispatch(tp->device->pointer.filter, &motion, tp, time);
*dx = motion.dx;
*dy = motion.dy;
*dx = accelerated.x;
*dy = accelerated.y;
}
static inline void
@ -967,22 +973,6 @@ tp_init_accel(struct tp_dispatch *tp, double diagonal)
res_x = tp->device->abs.absinfo_x->resolution;
res_y = tp->device->abs.absinfo_y->resolution;
/* Mac touchpads seem to all be the same size (except the most
* recent ones)
* http://www.moshi.com/trackpad-protector-trackguard-macbook-pro#silver
*/
if (tp->model == MODEL_UNIBODY_MACBOOK && tp->device->abs.fake_resolution) {
const struct input_absinfo *abs;
int width, height;
abs = tp->device->abs.absinfo_x;
width = abs->maximum - abs->minimum;
abs = tp->device->abs.absinfo_y;
height = abs->maximum - abs->minimum;
res_x = width/104.4;
res_y = height/75.4;
}
/*
* Not all touchpads report the same amount of units/mm (resolution).
* Normalize motion events to the default mouse DPI as base
@ -1134,32 +1124,6 @@ tp_init_sendevents(struct tp_dispatch *tp,
return 0;
}
static void
tp_fix_resolution(struct tp_dispatch *tp, struct evdev_device *device)
{
struct libinput *libinput = device->base.seat->libinput;
const char *prop;
unsigned int resx, resy;
prop = udev_device_get_property_value(device->udev_device,
"TOUCHPAD_RESOLUTION");
if (!prop)
return;
if (parse_touchpad_resolution_property(prop, &resx, &resy) == -1) {
log_error(libinput,
"Touchpad resolution property set for '%s', but invalid.\n",
device->devname);
return;
}
if (evdev_fix_abs_resolution(device,
tp->has_mt ? ABS_MT_POSITION_X : ABS_X,
tp->has_mt ? ABS_MT_POSITION_Y : ABS_Y,
resx, resy))
device->abs.fake_resolution = 0;
}
static int
tp_init(struct tp_dispatch *tp,
struct evdev_device *device)
@ -1173,8 +1137,6 @@ tp_init(struct tp_dispatch *tp,
if (tp_init_slots(tp, device) != 0)
return -1;
tp_fix_resolution(tp, device);
width = abs(device->abs.absinfo_x->maximum -
device->abs.absinfo_x->minimum);
height = abs(device->abs.absinfo_y->maximum -

View file

@ -238,7 +238,6 @@ static void
evdev_flush_pending_event(struct evdev_device *device, uint64_t time)
{
struct libinput *libinput = device->base.seat->libinput;
struct motion_params motion;
int slot;
int seat_slot;
struct libinput_device *base = &device->base;
@ -267,11 +266,7 @@ evdev_flush_pending_event(struct evdev_device *device, uint64_t time)
}
/* Apply pointer acceleration. */
motion.dx = unaccel.x;
motion.dy = unaccel.y;
filter_dispatch(device->pointer.filter, &motion, device, time);
accel.x = motion.dx;
accel.y = motion.dy;
accel = filter_dispatch(device->pointer.filter, &unaccel, device, time);
if (accel.x == 0.0 && accel.y == 0.0 &&
unaccel.x == 0.0 && unaccel.y == 0.0) {
@ -1458,10 +1453,32 @@ evdev_fix_android_mt(struct evdev_device *device)
libevdev_get_abs_info(evdev, ABS_MT_POSITION_Y));
}
static inline int
evdev_check_min_max(struct evdev_device *device, unsigned int code)
{
struct libevdev *evdev = device->evdev;
const struct input_absinfo *absinfo;
if (!libevdev_has_event_code(evdev, EV_ABS, code))
return 0;
absinfo = libevdev_get_abs_info(evdev, code);
if (absinfo->minimum == absinfo->maximum) {
log_bug_kernel(device->base.seat->libinput,
"Device '%s' has min == max on %s\n",
device->devname,
libevdev_event_code_get_name(EV_ABS, code));
return -1;
}
return 0;
}
static int
evdev_reject_device(struct evdev_device *device)
{
struct libevdev *evdev = device->evdev;
unsigned int code;
if (libevdev_has_event_code(evdev, EV_ABS, ABS_X) ^
libevdev_has_event_code(evdev, EV_ABS, ABS_Y))
@ -1471,6 +1488,18 @@ evdev_reject_device(struct evdev_device *device)
libevdev_has_event_code(evdev, EV_ABS, ABS_MT_POSITION_Y))
return -1;
for (code = 0; code < ABS_CNT; code++) {
switch (code) {
case ABS_MISC:
case ABS_MT_SLOT:
case ABS_MT_TOOL_TYPE:
break;
default:
if (evdev_check_min_max(device, code) == -1)
return -1;
}
}
return 0;
}

View file

@ -28,9 +28,10 @@
#include "filter.h"
struct motion_filter_interface {
void (*filter)(struct motion_filter *filter,
struct motion_params *motion,
void *data, uint64_t time);
struct normalized_coords (*filter)(
struct motion_filter *filter,
const struct normalized_coords *unaccelerated,
void *data, uint64_t time);
void (*destroy)(struct motion_filter *filter);
bool (*set_speed)(struct motion_filter *filter,
double speed);

View file

@ -33,12 +33,12 @@
#include "libinput-util.h"
#include "filter-private.h"
void
struct normalized_coords
filter_dispatch(struct motion_filter *filter,
struct motion_params *motion,
const struct normalized_coords *unaccelerated,
void *data, uint64_t time)
{
filter->interface->filter(filter, motion, data, time);
return filter->interface->filter(filter, unaccelerated, data, time);
}
void
@ -80,8 +80,7 @@ filter_get_speed(struct motion_filter *filter)
#define NUM_POINTER_TRACKERS 16
struct pointer_tracker {
double dx; /* delta to most recent event, in device units */
double dy; /* delta to most recent event, in device units */
struct normalized_coords delta; /* delta to most recent event */
uint64_t time; /* ms */
int dir;
};
@ -94,8 +93,7 @@ struct pointer_accelerator {
double velocity; /* units/ms */
double last_velocity; /* units/ms */
int last_dx; /* device units */
int last_dy; /* device units */
struct normalized_coords last;
struct pointer_tracker *trackers;
int cur_tracker;
@ -107,24 +105,24 @@ struct pointer_accelerator {
static void
feed_trackers(struct pointer_accelerator *accel,
double dx, double dy,
const struct normalized_coords *delta,
uint64_t time)
{
int i, current;
struct pointer_tracker *trackers = accel->trackers;
for (i = 0; i < NUM_POINTER_TRACKERS; i++) {
trackers[i].dx += dx;
trackers[i].dy += dy;
trackers[i].delta.x += delta->x;
trackers[i].delta.y += delta->y;
}
current = (accel->cur_tracker + 1) % NUM_POINTER_TRACKERS;
accel->cur_tracker = current;
trackers[current].dx = 0.0;
trackers[current].dy = 0.0;
trackers[current].delta.x = 0.0;
trackers[current].delta.y = 0.0;
trackers[current].time = time;
trackers[current].dir = vector_get_direction(dx, dy);
trackers[current].dir = vector_get_direction(delta->x, delta->y);
}
static struct pointer_tracker *
@ -139,14 +137,11 @@ tracker_by_offset(struct pointer_accelerator *accel, unsigned int offset)
static double
calculate_tracker_velocity(struct pointer_tracker *tracker, uint64_t time)
{
double dx;
double dy;
double distance;
double tdelta = time - tracker->time + 1;
dx = tracker->dx;
dy = tracker->dy;
distance = sqrt(dx*dx + dy*dy);
return distance / (double)(time - tracker->time); /* units/ms */
distance = hypot(tracker->delta.x, tracker->delta.y);
return distance / tdelta; /* units/ms */
}
static double
@ -220,27 +215,29 @@ calculate_acceleration(struct pointer_accelerator *accel,
return factor; /* unitless factor */
}
static void
static struct normalized_coords
accelerator_filter(struct motion_filter *filter,
struct motion_params *motion,
const struct normalized_coords *unaccelerated,
void *data, uint64_t time)
{
struct pointer_accelerator *accel =
(struct pointer_accelerator *) filter;
double velocity; /* units/ms */
double accel_value; /* unitless factor */
struct normalized_coords accelerated;
feed_trackers(accel, motion->dx, motion->dy, time);
feed_trackers(accel, unaccelerated, time);
velocity = calculate_velocity(accel, time);
accel_value = calculate_acceleration(accel, data, velocity, time);
motion->dx = accel_value * motion->dx;
motion->dy = accel_value * motion->dy;
accelerated.x = accel_value * unaccelerated->x;
accelerated.y = accel_value * unaccelerated->y;
accel->last_dx = motion->dx;
accel->last_dy = motion->dy;
accel->last = *unaccelerated;
accel->last_velocity = velocity;
return accelerated;
}
static void
@ -294,8 +291,8 @@ create_pointer_accelerator_filter(accel_profile_func_t profile)
filter->profile = profile;
filter->last_velocity = 0.0;
filter->last_dx = 0;
filter->last_dy = 0;
filter->last.x = 0;
filter->last.y = 0;
filter->trackers =
calloc(NUM_POINTER_TRACKERS, sizeof *filter->trackers);

View file

@ -28,15 +28,13 @@
#include <stdbool.h>
#include <stdint.h>
struct motion_params {
double dx, dy; /* in units/ms @ DEFAULT_MOUSE_DPI resolution */
};
#include "libinput-private.h"
struct motion_filter;
void
struct normalized_coords
filter_dispatch(struct motion_filter *filter,
struct motion_params *motion,
const struct normalized_coords *unaccelerated,
void *data, uint64_t time);
void
filter_destroy(struct motion_filter *filter);

View file

@ -201,33 +201,3 @@ parse_mouse_wheel_click_angle_property(const char *prop)
return angle;
}
/**
* Helper function to parse the TOUCHPAD_RESOLUTION property from udev.
* Property is of the form
* TOUCHPAD_RESOLUTION=<integer>x<integer>
* With both integer values in device units per mm.
* @param prop The value of the udev property (without the
* TOUCHPAD_RESOLUTION=)
* @return
*/
int
parse_touchpad_resolution_property(const char *prop,
unsigned int *res_x,
unsigned int *res_y)
{
int nconverted = 0;
unsigned int rx, ry;
nconverted = sscanf(prop, "%ux%u", &rx, &ry);
if (nconverted != 2 || rx == 0 || ry == 0)
return -1;
if (rx > 1000 || ry > 1000 || /* yeah, right... */
rx < 10 || ry < 10) /* what is this? the 90s? */
return -1;
*res_x = rx;
*res_y = ry;
return 0;
}

View file

@ -135,28 +135,28 @@ enum directions {
};
static inline int
vector_get_direction(int dx, int dy)
vector_get_direction(double dx, double dy)
{
int dir = UNDEFINED_DIRECTION;
int d1, d2;
double r;
if (abs(dx) < 2 && abs(dy) < 2) {
if (dx > 0 && dy > 0)
if (fabs(dx) < 2.0 && fabs(dy) < 2.0) {
if (dx > 0.0 && dy > 0.0)
dir = S | SE | E;
else if (dx > 0 && dy < 0)
else if (dx > 0.0 && dy < 0.0)
dir = N | NE | E;
else if (dx < 0 && dy > 0)
else if (dx < 0.0 && dy > 0.0)
dir = S | SW | W;
else if (dx < 0 && dy < 0)
else if (dx < 0.0 && dy < 0.0)
dir = N | NW | W;
else if (dx > 0)
else if (dx > 0.0)
dir = NE | E | SE;
else if (dx < 0)
else if (dx < 0.0)
dir = NW | W | SW;
else if (dy > 0)
else if (dy > 0.0)
dir = SE | S | SW;
else if (dy < 0)
else if (dy < 0.0)
dir = NE | N | NW;
} else {
/* Calculate r within the interval [0 to 8)
@ -323,8 +323,5 @@ enum ratelimit_state ratelimit_test(struct ratelimit *r);
int parse_mouse_dpi_property(const char *prop);
int parse_mouse_wheel_click_angle_property(const char *prop);
int parse_touchpad_resolution_property(const char *prop,
unsigned int *res_x,
unsigned int *res_y);
#endif /* LIBINPUT_UTIL_H */

View file

@ -814,6 +814,86 @@ START_TEST(abs_mt_device_no_absx)
}
END_TEST
START_TEST(abs_device_no_range)
{
struct libevdev_uinput *uinput;
struct libinput *li;
struct libinput_device *device;
int code;
/* set x/y so libinput doesn't just reject for missing axes */
struct input_absinfo absinfo[] = {
{ ABS_X, 0, 10, 0, 0, 0 },
{ ABS_Y, 0, 10, 0, 0, 0 },
{ -1, 0, 0, 0, 0, 0 },
{ -1, -1, -1, -1, -1, -1 }
};
li = litest_create_context();
litest_disable_log_handler(li);
for (code = 0; code < ABS_MT_SLOT; code++) {
if (code == ABS_MISC)
continue;
absinfo[2].value = code;
uinput = litest_create_uinput_abs_device("test device", NULL,
absinfo,
EV_KEY, BTN_LEFT,
EV_KEY, BTN_RIGHT,
-1);
device = libinput_path_add_device(li,
libevdev_uinput_get_devnode(uinput));
ck_assert(device == NULL);
libevdev_uinput_destroy(uinput);
}
litest_restore_log_handler(li);
libinput_unref(li);
}
END_TEST
START_TEST(abs_mt_device_no_range)
{
struct libevdev_uinput *uinput;
struct libinput *li;
struct libinput_device *device;
int code;
/* set x/y so libinput doesn't just reject for missing axes */
struct input_absinfo absinfo[] = {
{ ABS_X, 0, 10, 0, 0, 0 },
{ ABS_Y, 0, 10, 0, 0, 0 },
{ ABS_MT_SLOT, 0, 10, 0, 0, 0 },
{ ABS_MT_TRACKING_ID, 0, 255, 0, 0, 0 },
{ ABS_MT_POSITION_X, 0, 10, 0, 0, 0 },
{ ABS_MT_POSITION_Y, 0, 10, 0, 0, 0 },
{ -1, 0, 0, 0, 0, 0 },
{ -1, -1, -1, -1, -1, -1 }
};
li = litest_create_context();
litest_disable_log_handler(li);
for (code = ABS_MT_SLOT + 1; code < ABS_CNT; code++) {
if (code == ABS_MT_TOOL_TYPE ||
code == ABS_MT_TRACKING_ID) /* kernel overrides it */
continue;
absinfo[6].value = code;
uinput = litest_create_uinput_abs_device("test device", NULL,
absinfo,
EV_KEY, BTN_LEFT,
EV_KEY, BTN_RIGHT,
-1);
device = libinput_path_add_device(li,
libevdev_uinput_get_devnode(uinput));
ck_assert(device == NULL);
libevdev_uinput_destroy(uinput);
}
litest_restore_log_handler(li);
libinput_unref(li);
}
END_TEST
int main (int argc, char **argv)
{
litest_add("device:sendevents", device_sendevents_config, LITEST_ANY, LITEST_TOUCHPAD|LITEST_TABLET);
@ -847,6 +927,8 @@ int main (int argc, char **argv)
litest_add_no_device("device:invalid devices", abs_device_no_absy);
litest_add_no_device("device:invalid devices", abs_mt_device_no_absx);
litest_add_no_device("device:invalid devices", abs_mt_device_no_absy);
litest_add_no_device("device:invalid devices", abs_device_no_range);
litest_add_no_device("device:invalid devices", abs_mt_device_no_range);
return litest_run(argc, argv);
}

View file

@ -595,54 +595,6 @@ START_TEST(wheel_click_parser)
}
END_TEST
struct res_parser_test {
const char *value;
int retvalue;
int rx, ry;
};
START_TEST(touchpad_resolution_parser)
{
struct res_parser_test tests[] = {
{ "43x85", 0, 43, 85},
{ "242x428", 0, 242, 428 },
{ "1x1", -1, 0, 0},
{ "abcd", -1, 0, 0},
{ "", -1, 0, 0 },
{ "x", -1, 0, 0 },
{ "23x", -1, 0, 0 },
{ "x58", -1, 0, 0 },
{ "1x1", -1, 0, 0 },
{ "9x9", -1, 0, 0 },
{ "-34x-19", -1, 0, 0 },
{ "-34x19", -1, 0, 0 },
{ "34x-19", -1, 0, 0 },
{ NULL, 0, 0, 0 }
};
struct res_parser_test *test = tests;
int rc;
unsigned int rx, ry;
while (test->value != NULL) {
rx = 0xab;
ry = 0xcd;
rc = parse_touchpad_resolution_property(test->value, &rx, &ry);
ck_assert_int_eq(rc, test->retvalue);
if (rc == 0) {
ck_assert_int_eq(rx, test->rx);
ck_assert_int_eq(ry, test->ry);
} else {
ck_assert_int_eq(rx, 0xab);
ck_assert_int_eq(ry, 0xcd);
}
test++;
}
}
END_TEST
int main (int argc, char **argv) {
litest_add_no_device("events:conversion", event_conversion_device_notify);
litest_add_for_device("events:conversion", event_conversion_pointer, LITEST_MOUSE);
@ -659,7 +611,6 @@ int main (int argc, char **argv) {
litest_add_no_device("misc:ratelimit", ratelimit_helpers);
litest_add_no_device("misc:dpi parser", dpi_parser);
litest_add_no_device("misc:wheel click parser", wheel_click_parser);
litest_add_no_device("misc:touchpad resolution parser", touchpad_resolution_parser);
return litest_run(argc, argv);
}

View file

@ -812,6 +812,48 @@ START_TEST(pointer_accel_defaults_absolute)
}
END_TEST
START_TEST(pointer_accel_direction_change)
{
struct litest_device *dev = litest_current_device();
struct libinput *li = dev->libinput;
struct libinput_event *event;
struct libinput_event_pointer *pev;
int i;
double delta;
double max_accel;
litest_drain_events(li);
for (i = 0; i < 10; i++) {
litest_event(dev, EV_REL, REL_X, -1);
litest_event(dev, EV_SYN, SYN_REPORT, 0);
}
litest_event(dev, EV_REL, REL_X, 1);
litest_event(dev, EV_SYN, SYN_REPORT, 0);
libinput_dispatch(li);
litest_wait_for_event_of_type(li,
LIBINPUT_EVENT_POINTER_MOTION,
-1);
event = libinput_get_event(li);
do {
pev = libinput_event_get_pointer_event(event);
delta = libinput_event_pointer_get_dx(pev);
ck_assert(delta <= 0.0);
max_accel = delta;
libinput_event_destroy(event);
event = libinput_get_event(li);
} while (libinput_next_event_type(li) != LIBINPUT_EVENT_NONE);
pev = libinput_event_get_pointer_event(event);
delta = libinput_event_pointer_get_dx(pev);
ck_assert(delta > 0.0);
ck_assert(delta < -max_accel);
libinput_event_destroy(event);
}
END_TEST
int main (int argc, char **argv) {
litest_add("pointer:motion", pointer_motion_relative, LITEST_RELATIVE, LITEST_ANY);
@ -837,6 +879,7 @@ int main (int argc, char **argv) {
litest_add("pointer:accel", pointer_accel_defaults, LITEST_RELATIVE, LITEST_ANY);
litest_add("pointer:accel", pointer_accel_invalid, LITEST_RELATIVE, LITEST_ANY);
litest_add("pointer:accel", pointer_accel_defaults_absolute, LITEST_ABSOLUTE, LITEST_ANY);
litest_add("pointer:accel", pointer_accel_direction_change, LITEST_RELATIVE, LITEST_ANY);
return litest_run(argc, argv);
}

View file

@ -172,6 +172,8 @@ static void
map_event_cb(GtkWidget *widget, GdkEvent *event, gpointer data)
{
struct window *w = data;
GdkDisplay *display;
GdkWindow *window;
gtk_window_get_size(GTK_WINDOW(widget), &w->width, &w->height);
@ -185,8 +187,12 @@ map_event_cb(GtkWidget *widget, GdkEvent *event, gpointer data)
g_signal_connect(G_OBJECT(w->area), "draw", G_CALLBACK(draw), w);
window = gdk_event_get_window(event);
display = gdk_window_get_display(window);
gdk_window_set_cursor(gtk_widget_get_window(w->win),
gdk_cursor_new(GDK_BLANK_CURSOR));
gdk_cursor_new_for_display(display,
GDK_BLANK_CURSOR));
}
static void