mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2026-01-08 11:40:15 +01:00
Merge branch 'master' into tablet-support
This commit is contained in:
commit
772d69751b
24 changed files with 584 additions and 157 deletions
|
|
@ -1,7 +1,7 @@
|
|||
AC_PREREQ([2.64])
|
||||
|
||||
m4_define([libinput_major_version], [0])
|
||||
m4_define([libinput_minor_version], [18])
|
||||
m4_define([libinput_minor_version], [19])
|
||||
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=12:3:2
|
||||
LIBINPUT_LT_VERSION=13:0:3
|
||||
AC_SUBST(LIBINPUT_LT_VERSION)
|
||||
|
||||
AM_SILENT_RULES([yes])
|
||||
|
|
|
|||
|
|
@ -12,10 +12,33 @@ physical movement or 10 millimeters, depending on the sensor. This
|
|||
affects pointer acceleration in libinput and interpretation of relative
|
||||
coordinates in callers.
|
||||
|
||||
libinput normalizes all relative input to a physical resolution of
|
||||
1000dpi, the same delta from two different devices thus represents the
|
||||
same physical movement of those two devices (within sensor error
|
||||
margins).
|
||||
libinput does partial normalization of relative input. For devices with a
|
||||
resolution of 1000dpi and higher, motion events are normalized to a default
|
||||
of 1000dpi before pointer acceleration is applied. As a result, devices with
|
||||
1000dpi and above feel the same.
|
||||
|
||||
Devices below 1000dpi are not normalized (normalization of a 1-device unit
|
||||
movement on a 400dpi mouse would cause a 2.5 pixel movement). Instead,
|
||||
libinput applies a dpi-dependent acceleration function. At low speeds, a
|
||||
1-device unit movement usually translates into a 1-pixel movements. As the
|
||||
movement speed increases, acceleration is applied - at high speeds a low-dpi
|
||||
device will roughly feel the same as a higher-dpi mouse.
|
||||
|
||||
This normalization only applies to accelerated coordinates, unaccelerated
|
||||
coordiantes are left in device-units. It is up to the caller to interpret
|
||||
those coordinates correctly.
|
||||
|
||||
@section Normalization of touchpad coordinates
|
||||
|
||||
Touchpads may have a different resolution for the horizontal and vertical
|
||||
axis. Interpreting coordinates from the touchpad without taking resolutino
|
||||
into account results in uneven motion.
|
||||
|
||||
libinput scales unaccelerated touchpad motion do the resolution of the
|
||||
touchpad's x axis, i.e. the unaccelerated value for the y axis is:
|
||||
y = (x / resolution_x) * resolution_y
|
||||
|
||||
@section Setting custom DPI settings
|
||||
|
||||
Devices usually do not advertise their resolution and libinput relies on
|
||||
the udev property <b>MOUSE_DPI</b> for this information. This property is usually
|
||||
|
|
|
|||
|
|
@ -91,6 +91,7 @@ static void
|
|||
tp_gesture_post_pointer_motion(struct tp_dispatch *tp, uint64_t time)
|
||||
{
|
||||
struct normalized_coords delta, unaccel;
|
||||
struct device_float_coords raw;
|
||||
|
||||
/* When a clickpad is clicked, combine motion of all active touches */
|
||||
if (tp->buttons.is_clickpad && tp->buttons.state)
|
||||
|
|
@ -101,8 +102,11 @@ tp_gesture_post_pointer_motion(struct tp_dispatch *tp, uint64_t time)
|
|||
delta = tp_filter_motion(tp, &unaccel, time);
|
||||
|
||||
if (!normalized_is_zero(delta) || !normalized_is_zero(unaccel)) {
|
||||
pointer_notify_motion(&tp->device->base, time,
|
||||
&delta, &unaccel);
|
||||
raw = tp_unnormalize_for_xaxis(tp, unaccel);
|
||||
pointer_notify_motion(&tp->device->base,
|
||||
time,
|
||||
&delta,
|
||||
&raw);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@
|
|||
* TP_MAGIC_SLOWDOWN in filter.c */
|
||||
#define DEFAULT_ACCEL_NUMERATOR 3000.0
|
||||
#define DEFAULT_HYSTERESIS_MARGIN_DENOMINATOR 700.0
|
||||
#define DEFAULT_TRACKPOINT_ACTIVITY_TIMEOUT 500 /* ms */
|
||||
#define DEFAULT_TRACKPOINT_ACTIVITY_TIMEOUT 300 /* ms */
|
||||
#define DEFAULT_KEYBOARD_ACTIVITY_TIMEOUT_1 200 /* ms */
|
||||
#define DEFAULT_KEYBOARD_ACTIVITY_TIMEOUT_2 500 /* ms */
|
||||
#define FAKE_FINGER_OVERFLOW (1 << 7)
|
||||
|
|
@ -211,6 +211,7 @@ tp_begin_touch(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time)
|
|||
t->state = TOUCH_BEGIN;
|
||||
t->millis = time;
|
||||
tp->nfingers_down++;
|
||||
t->palm.time = time;
|
||||
assert(tp->nfingers_down >= 1);
|
||||
}
|
||||
|
||||
|
|
@ -491,7 +492,6 @@ tp_palm_detect_dwt(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time)
|
|||
if (tp->dwt.keyboard_active &&
|
||||
t->state == TOUCH_BEGIN) {
|
||||
t->palm.state = PALM_TYPING;
|
||||
t->palm.time = time;
|
||||
t->palm.first = t->point;
|
||||
return 1;
|
||||
} else if (!tp->dwt.keyboard_active &&
|
||||
|
|
@ -515,6 +515,34 @@ tp_palm_detect_dwt(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
tp_palm_detect_trackpoint(struct tp_dispatch *tp,
|
||||
struct tp_touch *t,
|
||||
uint64_t time)
|
||||
{
|
||||
if (!tp->palm.monitor_trackpoint)
|
||||
return 0;
|
||||
|
||||
if (t->palm.state == PALM_NONE &&
|
||||
t->state == TOUCH_BEGIN &&
|
||||
tp->palm.trackpoint_active) {
|
||||
t->palm.state = PALM_TRACKPOINT;
|
||||
return 1;
|
||||
} else if (t->palm.state == PALM_TRACKPOINT &&
|
||||
t->state == TOUCH_UPDATE &&
|
||||
!tp->palm.trackpoint_active) {
|
||||
|
||||
if (t->palm.time == 0 ||
|
||||
t->palm.time > tp->palm.trackpoint_last_event_time) {
|
||||
t->palm.state = PALM_NONE;
|
||||
log_debug(tp_libinput_context(tp),
|
||||
"palm: touch released, timeout after trackpoint\n");
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
tp_palm_detect(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time)
|
||||
{
|
||||
|
|
@ -526,6 +554,9 @@ tp_palm_detect(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time)
|
|||
if (tp_palm_detect_dwt(tp, t, time))
|
||||
goto out;
|
||||
|
||||
if (tp_palm_detect_trackpoint(tp, t, time))
|
||||
goto out;
|
||||
|
||||
/* If labelled a touch as palm, we unlabel as palm when
|
||||
we move out of the palm edge zone within the timeout, provided
|
||||
the direction is within 45 degrees of the horizontal.
|
||||
|
|
@ -568,7 +599,8 @@ tp_palm_detect(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time)
|
|||
out:
|
||||
log_debug(tp_libinput_context(tp),
|
||||
"palm: palm detected (%s)\n",
|
||||
t->palm.state == PALM_EDGE ? "edge" : "typing");
|
||||
t->palm.state == PALM_EDGE ? "edge" :
|
||||
t->palm.state == PALM_TYPING ? "typing" : "trackpoint");
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -762,7 +794,7 @@ tp_post_events(struct tp_dispatch *tp, uint64_t time)
|
|||
filter_motion |= tp_post_button_events(tp, time);
|
||||
|
||||
if (filter_motion ||
|
||||
tp->sendevents.trackpoint_active ||
|
||||
tp->palm.trackpoint_active ||
|
||||
tp->dwt.keyboard_active) {
|
||||
tp_edge_scroll_stop_events(tp, time);
|
||||
tp_gesture_stop(tp, time);
|
||||
|
|
@ -812,12 +844,13 @@ tp_interface_process(struct evdev_dispatch *dispatch,
|
|||
static void
|
||||
tp_remove_sendevents(struct tp_dispatch *tp)
|
||||
{
|
||||
libinput_timer_cancel(&tp->sendevents.trackpoint_timer);
|
||||
libinput_timer_cancel(&tp->palm.trackpoint_timer);
|
||||
libinput_timer_cancel(&tp->dwt.keyboard_timer);
|
||||
|
||||
if (tp->buttons.trackpoint)
|
||||
if (tp->buttons.trackpoint &&
|
||||
tp->palm.monitor_trackpoint)
|
||||
libinput_device_remove_event_listener(
|
||||
&tp->sendevents.trackpoint_listener);
|
||||
&tp->palm.trackpoint_listener);
|
||||
|
||||
if (tp->dwt.keyboard)
|
||||
libinput_device_remove_event_listener(
|
||||
|
|
@ -928,7 +961,7 @@ tp_trackpoint_timeout(uint64_t now, void *data)
|
|||
struct tp_dispatch *tp = data;
|
||||
|
||||
tp_tap_resume(tp, now);
|
||||
tp->sendevents.trackpoint_active = false;
|
||||
tp->palm.trackpoint_active = false;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -941,14 +974,15 @@ tp_trackpoint_event(uint64_t time, struct libinput_event *event, void *data)
|
|||
if (event->type == LIBINPUT_EVENT_POINTER_BUTTON)
|
||||
return;
|
||||
|
||||
if (!tp->sendevents.trackpoint_active) {
|
||||
if (!tp->palm.trackpoint_active) {
|
||||
tp_edge_scroll_stop_events(tp, time);
|
||||
tp_gesture_stop(tp, time);
|
||||
tp_tap_suspend(tp, time);
|
||||
tp->sendevents.trackpoint_active = true;
|
||||
tp->palm.trackpoint_active = true;
|
||||
}
|
||||
|
||||
libinput_timer_set(&tp->sendevents.trackpoint_timer,
|
||||
tp->palm.trackpoint_last_event_time = time;
|
||||
libinput_timer_set(&tp->palm.trackpoint_timer,
|
||||
time + DEFAULT_TRACKPOINT_ACTIVITY_TIMEOUT);
|
||||
}
|
||||
|
||||
|
|
@ -1079,9 +1113,10 @@ tp_interface_device_added(struct evdev_device *device,
|
|||
/* Don't send any pending releases to the new trackpoint */
|
||||
tp->buttons.active_is_topbutton = false;
|
||||
tp->buttons.trackpoint = added_device;
|
||||
libinput_device_add_event_listener(&added_device->base,
|
||||
&tp->sendevents.trackpoint_listener,
|
||||
tp_trackpoint_event, tp);
|
||||
if (tp->palm.monitor_trackpoint)
|
||||
libinput_device_add_event_listener(&added_device->base,
|
||||
&tp->palm.trackpoint_listener,
|
||||
tp_trackpoint_event, tp);
|
||||
}
|
||||
|
||||
if (added_device->tags & EVDEV_TAG_KEYBOARD &&
|
||||
|
|
@ -1120,8 +1155,9 @@ tp_interface_device_removed(struct evdev_device *device,
|
|||
tp->buttons.active = 0;
|
||||
tp->buttons.active_is_topbutton = false;
|
||||
}
|
||||
libinput_device_remove_event_listener(
|
||||
&tp->sendevents.trackpoint_listener);
|
||||
if (tp->palm.monitor_trackpoint)
|
||||
libinput_device_remove_event_listener(
|
||||
&tp->palm.trackpoint_listener);
|
||||
tp->buttons.trackpoint = NULL;
|
||||
}
|
||||
|
||||
|
|
@ -1426,6 +1462,8 @@ tp_init_palmdetect(struct tp_dispatch *tp,
|
|||
tp->palm.left_edge = device->abs.absinfo_x->minimum + width * 0.05;
|
||||
tp->palm.vert_center = device->abs.absinfo_y->minimum + height/2;
|
||||
|
||||
tp->palm.monitor_trackpoint = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1433,7 +1471,7 @@ static int
|
|||
tp_init_sendevents(struct tp_dispatch *tp,
|
||||
struct evdev_device *device)
|
||||
{
|
||||
libinput_timer_init(&tp->sendevents.trackpoint_timer,
|
||||
libinput_timer_init(&tp->palm.trackpoint_timer,
|
||||
tp_libinput_context(tp),
|
||||
tp_trackpoint_timeout, tp);
|
||||
|
||||
|
|
|
|||
|
|
@ -64,6 +64,7 @@ enum touch_palm_state {
|
|||
PALM_NONE = 0,
|
||||
PALM_EDGE,
|
||||
PALM_TYPING,
|
||||
PALM_TRACKPOINT,
|
||||
};
|
||||
|
||||
enum button_event {
|
||||
|
|
@ -277,15 +278,17 @@ struct tp_dispatch {
|
|||
int32_t right_edge; /* in device coordinates */
|
||||
int32_t left_edge; /* in device coordinates */
|
||||
int32_t vert_center; /* in device coordinates */
|
||||
|
||||
bool trackpoint_active;
|
||||
struct libinput_event_listener trackpoint_listener;
|
||||
struct libinput_timer trackpoint_timer;
|
||||
uint64_t trackpoint_last_event_time;
|
||||
bool monitor_trackpoint;
|
||||
} palm;
|
||||
|
||||
struct {
|
||||
struct libinput_device_config_send_events config;
|
||||
enum libinput_config_send_events_mode current_mode;
|
||||
|
||||
bool trackpoint_active;
|
||||
struct libinput_event_listener trackpoint_listener;
|
||||
struct libinput_timer trackpoint_timer;
|
||||
} sendevents;
|
||||
|
||||
struct {
|
||||
|
|
@ -318,6 +321,21 @@ tp_normalize_delta(struct tp_dispatch *tp, struct device_float_coords delta)
|
|||
return normalized;
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes a dpi-normalized set of coordinates, returns a set of coordinates
|
||||
* in the x-axis' coordinate space.
|
||||
*/
|
||||
static inline struct device_float_coords
|
||||
tp_unnormalize_for_xaxis(struct tp_dispatch *tp, struct normalized_coords delta)
|
||||
{
|
||||
struct device_float_coords raw;
|
||||
|
||||
raw.x = delta.x / tp->accel.x_scale_coeff;
|
||||
raw.y = delta.y / tp->accel.x_scale_coeff; /* <--- not a typo */
|
||||
|
||||
return raw;
|
||||
}
|
||||
|
||||
struct normalized_coords
|
||||
tp_get_delta(struct tp_touch *t);
|
||||
|
||||
|
|
|
|||
27
src/evdev.c
27
src/evdev.c
|
|
@ -281,6 +281,7 @@ evdev_flush_pending_event(struct evdev_device *device, uint64_t time)
|
|||
struct libinput_seat *seat = base->seat;
|
||||
struct normalized_coords accel, unaccel;
|
||||
struct device_coords point;
|
||||
struct device_float_coords raw;
|
||||
|
||||
slot = device->mt.slot;
|
||||
|
||||
|
|
@ -289,6 +290,8 @@ evdev_flush_pending_event(struct evdev_device *device, uint64_t time)
|
|||
return;
|
||||
case EVDEV_RELATIVE_MOTION:
|
||||
normalize_delta(device, &device->rel, &unaccel);
|
||||
raw.x = device->rel.x;
|
||||
raw.y = device->rel.y;
|
||||
device->rel.x = 0;
|
||||
device->rel.y = 0;
|
||||
|
||||
|
|
@ -305,7 +308,7 @@ evdev_flush_pending_event(struct evdev_device *device, uint64_t time)
|
|||
if (normalized_is_zero(accel) && normalized_is_zero(unaccel))
|
||||
break;
|
||||
|
||||
pointer_notify_motion(base, time, &accel, &unaccel);
|
||||
pointer_notify_motion(base, time, &accel, &raw);
|
||||
break;
|
||||
case EVDEV_ABSOLUTE_MT_DOWN:
|
||||
if (!(device->seat_caps & EVDEV_DEVICE_TOUCH))
|
||||
|
|
@ -1408,7 +1411,8 @@ int
|
|||
evdev_device_init_pointer_acceleration(struct evdev_device *device,
|
||||
accel_profile_func_t profile)
|
||||
{
|
||||
device->pointer.filter = create_pointer_accelerator_filter(profile);
|
||||
device->pointer.filter = create_pointer_accelerator_filter(profile,
|
||||
device->dpi);
|
||||
if (!device->pointer.filter)
|
||||
return -1;
|
||||
|
||||
|
|
@ -1549,7 +1553,7 @@ evdev_read_model(struct evdev_device *device)
|
|||
}
|
||||
|
||||
/* Return 1 if the given resolutions have been set, or 0 otherwise */
|
||||
inline int
|
||||
static inline int
|
||||
evdev_fix_abs_resolution(struct evdev_device *device,
|
||||
unsigned int xcode,
|
||||
unsigned int ycode,
|
||||
|
|
@ -1825,6 +1829,19 @@ evdev_configure_mt_device(struct evdev_device *device)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
evdev_init_accel(struct evdev_device *device)
|
||||
{
|
||||
accel_profile_func_t profile;
|
||||
|
||||
if (device->dpi < DEFAULT_MOUSE_DPI)
|
||||
profile = pointer_accel_profile_linear_low_dpi;
|
||||
else
|
||||
profile = pointer_accel_profile_linear;
|
||||
|
||||
return evdev_device_init_pointer_acceleration(device, profile);
|
||||
}
|
||||
|
||||
static int
|
||||
evdev_configure_device(struct evdev_device *device)
|
||||
{
|
||||
|
|
@ -1936,9 +1953,7 @@ evdev_configure_device(struct evdev_device *device)
|
|||
udev_tags & EVDEV_UDEV_TAG_POINTINGSTICK) {
|
||||
if (libevdev_has_event_code(evdev, EV_REL, REL_X) &&
|
||||
libevdev_has_event_code(evdev, EV_REL, REL_Y) &&
|
||||
evdev_device_init_pointer_acceleration(
|
||||
device,
|
||||
pointer_accel_profile_linear) == -1)
|
||||
evdev_init_accel(device) == -1)
|
||||
return -1;
|
||||
|
||||
device->seat_caps |= EVDEV_DEVICE_POINTER;
|
||||
|
|
|
|||
10
src/evdev.h
10
src/evdev.h
|
|
@ -36,9 +36,6 @@
|
|||
#include "timer.h"
|
||||
#include "filter.h"
|
||||
|
||||
/* The HW DPI rate we normalize to before calculating pointer acceleration */
|
||||
#define DEFAULT_MOUSE_DPI 1000
|
||||
|
||||
/*
|
||||
* The constant (linear) acceleration factor we use to normalize trackpoint
|
||||
* deltas before calculating pointer acceleration.
|
||||
|
|
@ -284,13 +281,6 @@ struct evdev_device *
|
|||
evdev_device_create(struct libinput_seat *seat,
|
||||
struct udev_device *device);
|
||||
|
||||
int
|
||||
evdev_fix_abs_resolution(struct evdev_device *device,
|
||||
unsigned int xcode,
|
||||
unsigned int ycode,
|
||||
int yresolution,
|
||||
int xresolution);
|
||||
|
||||
int
|
||||
evdev_device_init_pointer_acceleration(struct evdev_device *device,
|
||||
accel_profile_func_t profile);
|
||||
|
|
|
|||
63
src/filter.c
63
src/filter.c
|
|
@ -111,6 +111,8 @@ struct pointer_accelerator {
|
|||
double threshold; /* units/ms */
|
||||
double accel; /* unitless factor */
|
||||
double incline; /* incline of the function */
|
||||
|
||||
double dpi_factor;
|
||||
};
|
||||
|
||||
static void
|
||||
|
|
@ -262,8 +264,16 @@ accelerator_filter(struct motion_filter *filter,
|
|||
double velocity; /* units/ms */
|
||||
double accel_value; /* unitless factor */
|
||||
struct normalized_coords accelerated;
|
||||
struct normalized_coords unnormalized;
|
||||
double dpi_factor = accel->dpi_factor;
|
||||
|
||||
feed_trackers(accel, unaccelerated, time);
|
||||
/* For low-dpi mice, use device units, everything else uses
|
||||
1000dpi normalized */
|
||||
dpi_factor = min(1.0, dpi_factor);
|
||||
unnormalized.x = unaccelerated->x * dpi_factor;
|
||||
unnormalized.y = unaccelerated->y * dpi_factor;
|
||||
|
||||
feed_trackers(accel, &unnormalized, time);
|
||||
velocity = calculate_velocity(accel, time);
|
||||
accel_value = calculate_acceleration(accel,
|
||||
data,
|
||||
|
|
@ -271,10 +281,10 @@ accelerator_filter(struct motion_filter *filter,
|
|||
accel->last_velocity,
|
||||
time);
|
||||
|
||||
accelerated.x = accel_value * unaccelerated->x;
|
||||
accelerated.y = accel_value * unaccelerated->y;
|
||||
accelerated.x = accel_value * unnormalized.x;
|
||||
accelerated.y = accel_value * unnormalized.y;
|
||||
|
||||
accel->last = *unaccelerated;
|
||||
accel->last = unnormalized;
|
||||
|
||||
accel->last_velocity = velocity;
|
||||
|
||||
|
|
@ -346,7 +356,8 @@ struct motion_filter_interface accelerator_interface = {
|
|||
};
|
||||
|
||||
struct motion_filter *
|
||||
create_pointer_accelerator_filter(accel_profile_func_t profile)
|
||||
create_pointer_accelerator_filter(accel_profile_func_t profile,
|
||||
int dpi)
|
||||
{
|
||||
struct pointer_accelerator *filter;
|
||||
|
||||
|
|
@ -369,13 +380,51 @@ create_pointer_accelerator_filter(accel_profile_func_t profile)
|
|||
filter->accel = DEFAULT_ACCELERATION;
|
||||
filter->incline = DEFAULT_INCLINE;
|
||||
|
||||
filter->dpi_factor = dpi/(double)DEFAULT_MOUSE_DPI;
|
||||
|
||||
return &filter->base;
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom acceleration function for mice < 1000dpi.
|
||||
* At slow motion, a single device unit causes a one-pixel movement.
|
||||
* The threshold/max accel depends on the DPI, the smaller the DPI the
|
||||
* earlier we accelerate and the higher the maximum acceleration is. Result:
|
||||
* at low speeds we get pixel-precision, at high speeds we get approx. the
|
||||
* same movement as a high-dpi mouse.
|
||||
*
|
||||
* Note: data fed to this function is in device units, not normalized.
|
||||
*/
|
||||
double
|
||||
pointer_accel_profile_linear_low_dpi(struct motion_filter *filter,
|
||||
void *data,
|
||||
double speed_in, /* in device units */
|
||||
uint64_t time)
|
||||
{
|
||||
struct pointer_accelerator *accel_filter =
|
||||
(struct pointer_accelerator *)filter;
|
||||
|
||||
double s1, s2;
|
||||
double max_accel = accel_filter->accel; /* unitless factor */
|
||||
const double threshold = accel_filter->threshold; /* units/ms */
|
||||
const double incline = accel_filter->incline;
|
||||
double factor;
|
||||
double dpi_factor = accel_filter->dpi_factor;
|
||||
|
||||
max_accel /= dpi_factor;
|
||||
|
||||
s1 = min(1, 0.3 + speed_in * 10);
|
||||
s2 = 1 + (speed_in - threshold * dpi_factor) * incline;
|
||||
|
||||
factor = min(max_accel, s2 > 1 ? s2 : s1);
|
||||
|
||||
return factor;
|
||||
}
|
||||
|
||||
double
|
||||
pointer_accel_profile_linear(struct motion_filter *filter,
|
||||
void *data,
|
||||
double speed_in,
|
||||
double speed_in, /* 1000-dpi normalized */
|
||||
uint64_t time)
|
||||
{
|
||||
struct pointer_accelerator *accel_filter =
|
||||
|
|
@ -387,7 +436,7 @@ pointer_accel_profile_linear(struct motion_filter *filter,
|
|||
const double incline = accel_filter->incline;
|
||||
double factor;
|
||||
|
||||
s1 = min(1, 0.3 + speed_in * 4);
|
||||
s1 = min(1, 0.3 + speed_in * 10);
|
||||
s2 = 1 + (speed_in - threshold) * incline;
|
||||
|
||||
factor = min(max_accel, s2 > 1 ? s2 : s1);
|
||||
|
|
|
|||
|
|
@ -58,13 +58,19 @@ typedef double (*accel_profile_func_t)(struct motion_filter *filter,
|
|||
uint64_t time);
|
||||
|
||||
struct motion_filter *
|
||||
create_pointer_accelerator_filter(accel_profile_func_t filter);
|
||||
create_pointer_accelerator_filter(accel_profile_func_t filter,
|
||||
int dpi);
|
||||
|
||||
/*
|
||||
* Pointer acceleration profiles.
|
||||
*/
|
||||
|
||||
double
|
||||
pointer_accel_profile_linear_low_dpi(struct motion_filter *filter,
|
||||
void *data,
|
||||
double speed_in,
|
||||
uint64_t time);
|
||||
double
|
||||
pointer_accel_profile_linear(struct motion_filter *filter,
|
||||
void *data,
|
||||
double speed_in,
|
||||
|
|
|
|||
|
|
@ -339,7 +339,7 @@ void
|
|||
pointer_notify_motion(struct libinput_device *device,
|
||||
uint64_t time,
|
||||
const struct normalized_coords *delta,
|
||||
const struct normalized_coords *unaccel);
|
||||
const struct device_float_coords *raw);
|
||||
|
||||
void
|
||||
pointer_notify_motion_absolute(struct libinput_device *device,
|
||||
|
|
|
|||
|
|
@ -37,6 +37,9 @@
|
|||
#define VENDOR_ID_APPLE 0x5ac
|
||||
#define VENDOR_ID_WACOM 0x56a
|
||||
|
||||
/* The HW DPI rate we normalize to before calculating pointer acceleration */
|
||||
#define DEFAULT_MOUSE_DPI 1000
|
||||
|
||||
void
|
||||
set_logging_enabled(int enabled);
|
||||
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ struct libinput_event_pointer {
|
|||
struct libinput_event base;
|
||||
uint32_t time;
|
||||
struct normalized_coords delta;
|
||||
struct normalized_coords delta_unaccel;
|
||||
struct device_float_coords delta_raw;
|
||||
struct device_coords absolute;
|
||||
struct discrete_coords discrete;
|
||||
uint32_t button;
|
||||
|
|
@ -364,7 +364,7 @@ libinput_event_pointer_get_dx_unaccelerated(
|
|||
0,
|
||||
LIBINPUT_EVENT_POINTER_MOTION);
|
||||
|
||||
return event->delta_unaccel.x;
|
||||
return event->delta_raw.x;
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT double
|
||||
|
|
@ -376,7 +376,7 @@ libinput_event_pointer_get_dy_unaccelerated(
|
|||
0,
|
||||
LIBINPUT_EVENT_POINTER_MOTION);
|
||||
|
||||
return event->delta_unaccel.y;
|
||||
return event->delta_raw.y;
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT double
|
||||
|
|
@ -1394,7 +1394,7 @@ void
|
|||
pointer_notify_motion(struct libinput_device *device,
|
||||
uint64_t time,
|
||||
const struct normalized_coords *delta,
|
||||
const struct normalized_coords *unaccel)
|
||||
const struct device_float_coords *raw)
|
||||
{
|
||||
struct libinput_event_pointer *motion_event;
|
||||
|
||||
|
|
@ -1408,7 +1408,7 @@ pointer_notify_motion(struct libinput_device *device,
|
|||
*motion_event = (struct libinput_event_pointer) {
|
||||
.time = time,
|
||||
.delta = *delta,
|
||||
.delta_unaccel = *unaccel,
|
||||
.delta_raw = *raw,
|
||||
};
|
||||
|
||||
post_device_event(device, time,
|
||||
|
|
|
|||
|
|
@ -582,8 +582,8 @@ libinput_event_pointer_get_time(struct libinput_event_pointer *event);
|
|||
* If a device employs pointer acceleration, the delta returned by this
|
||||
* function is the accelerated delta.
|
||||
*
|
||||
* Relative motion deltas are normalized to represent those of a device with
|
||||
* 1000dpi resolution. See @ref motion_normalization for more details.
|
||||
* Relative motion deltas are to be interpreted as pixel movement of a
|
||||
* standardized mouse. See @ref motion_normalization for more details.
|
||||
*
|
||||
* @note It is an application bug to call this function for events other than
|
||||
* @ref LIBINPUT_EVENT_POINTER_MOTION.
|
||||
|
|
@ -603,8 +603,8 @@ libinput_event_pointer_get_dx(struct libinput_event_pointer *event);
|
|||
* If a device employs pointer acceleration, the delta returned by this
|
||||
* function is the accelerated delta.
|
||||
*
|
||||
* Relative motion deltas are normalized to represent those of a device with
|
||||
* 1000dpi resolution. See @ref motion_normalization for more details.
|
||||
* Relative motion deltas are to be interpreted as pixel movement of a
|
||||
* standardized mouse. See @ref motion_normalization for more details.
|
||||
*
|
||||
* @note It is an application bug to call this function for events other than
|
||||
* @ref LIBINPUT_EVENT_POINTER_MOTION.
|
||||
|
|
@ -621,10 +621,11 @@ libinput_event_pointer_get_dy(struct libinput_event_pointer *event);
|
|||
* current event. For pointer events that are not of type @ref
|
||||
* LIBINPUT_EVENT_POINTER_MOTION, this function returns 0.
|
||||
*
|
||||
* Relative unaccelerated motion deltas are normalized to represent those of a
|
||||
* device with 1000dpi resolution. See @ref motion_normalization for more
|
||||
* details. Note that unaccelerated events are not equivalent to 'raw' events
|
||||
* as read from the device.
|
||||
* Relative unaccelerated motion deltas are raw device coordinates.
|
||||
* Note that these coordinates are subject to the device's native
|
||||
* resolution. Touchpad coordinates represent raw device coordinates in the
|
||||
* X resolution of the touchpad. See @ref motion_normalization for more
|
||||
* details.
|
||||
*
|
||||
* @note It is an application bug to call this function for events other than
|
||||
* @ref LIBINPUT_EVENT_POINTER_MOTION.
|
||||
|
|
@ -642,10 +643,11 @@ libinput_event_pointer_get_dx_unaccelerated(
|
|||
* current event. For pointer events that are not of type @ref
|
||||
* LIBINPUT_EVENT_POINTER_MOTION, this function returns 0.
|
||||
*
|
||||
* Relative unaccelerated motion deltas are normalized to represent those of a
|
||||
* device with 1000dpi resolution. See @ref motion_normalization for more
|
||||
* details. Note that unaccelerated events are not equivalent to 'raw' events
|
||||
* as read from the device.
|
||||
* Relative unaccelerated motion deltas are raw device coordinates.
|
||||
* Note that these coordinates are subject to the device's native
|
||||
* resolution. Touchpad coordinates represent raw device coordinates in the
|
||||
* X resolution of the touchpad. See @ref motion_normalization for more
|
||||
* details.
|
||||
*
|
||||
* @note It is an application bug to call this function for events other than
|
||||
* @ref LIBINPUT_EVENT_POINTER_MOTION.
|
||||
|
|
|
|||
|
|
@ -143,6 +143,7 @@ global:
|
|||
} LIBINPUT_0.14.0;
|
||||
|
||||
LIBINPUT_0.19.0 {
|
||||
global:
|
||||
libinput_device_config_tap_set_drag_lock_enabled;
|
||||
libinput_device_config_tap_get_drag_lock_enabled;
|
||||
libinput_device_config_tap_get_default_drag_lock_enabled;
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ liblitest_la_SOURCES = \
|
|||
litest-logitech-trackball.c \
|
||||
litest-mouse.c \
|
||||
litest-mouse-roccat.c \
|
||||
litest-mouse-low-dpi.c \
|
||||
litest-ms-surface-cover.c \
|
||||
litest-protocol-a-touch-screen.c \
|
||||
litest-qemu-usb-tablet.c \
|
||||
|
|
|
|||
|
|
@ -947,6 +947,65 @@ START_TEST(device_wheel_only)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(device_udev_tag_alps)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput_device *device = dev->libinput_device;
|
||||
struct udev_device *d;
|
||||
const char *prop;
|
||||
|
||||
d = libinput_device_get_udev_device(device);
|
||||
prop = udev_device_get_property_value(d,
|
||||
"LIBINPUT_MODEL_ALPS_TOUCHPAD");
|
||||
|
||||
if (strstr(libinput_device_get_name(device), "ALPS"))
|
||||
ck_assert_notnull(prop);
|
||||
else
|
||||
ck_assert(prop == NULL);
|
||||
|
||||
udev_device_unref(d);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(device_udev_tag_wacom)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput_device *device = dev->libinput_device;
|
||||
struct udev_device *d;
|
||||
const char *prop;
|
||||
|
||||
d = libinput_device_get_udev_device(device);
|
||||
prop = udev_device_get_property_value(d,
|
||||
"LIBINPUT_MODEL_WACOM_TOUCHPAD");
|
||||
|
||||
if (libevdev_get_id_vendor(dev->evdev) == VENDOR_ID_WACOM)
|
||||
ck_assert_notnull(prop);
|
||||
else
|
||||
ck_assert(prop == NULL);
|
||||
|
||||
udev_device_unref(d);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(device_udev_tag_apple)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput_device *device = dev->libinput_device;
|
||||
struct udev_device *d;
|
||||
const char *prop;
|
||||
|
||||
d = libinput_device_get_udev_device(device);
|
||||
prop = udev_device_get_property_value(d,
|
||||
"LIBINPUT_MODEL_WACOM_TOUCHPAD");
|
||||
|
||||
if (libevdev_get_id_vendor(dev->evdev) == VENDOR_ID_WACOM)
|
||||
ck_assert_notnull(prop);
|
||||
else
|
||||
ck_assert(prop == NULL);
|
||||
|
||||
udev_device_unref(d);
|
||||
}
|
||||
END_TEST
|
||||
void
|
||||
litest_setup_tests(void)
|
||||
{
|
||||
|
|
@ -989,4 +1048,8 @@ litest_setup_tests(void)
|
|||
litest_add_no_device("device:invalid devices", abs_mt_device_missing_res);
|
||||
|
||||
litest_add("device:wheel", device_wheel_only, LITEST_WHEEL, LITEST_RELATIVE|LITEST_ABSOLUTE|LITEST_TABLET);
|
||||
|
||||
litest_add("device:udev tags", device_udev_tag_alps, LITEST_TOUCHPAD, LITEST_ANY);
|
||||
litest_add("device:udev tags", device_udev_tag_wacom, LITEST_TOUCHPAD, LITEST_ANY);
|
||||
litest_add("device:udev tags", device_udev_tag_apple, LITEST_TOUCHPAD, LITEST_ANY);
|
||||
}
|
||||
|
|
|
|||
75
test/litest-mouse-low-dpi.c
Normal file
75
test/litest-mouse-low-dpi.c
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* Copyright © 2015 Red Hat, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "litest.h"
|
||||
#include "litest-int.h"
|
||||
|
||||
static void litest_mouse_setup(void)
|
||||
{
|
||||
struct litest_device *d = litest_create_device(LITEST_MOUSE_LOW_DPI);
|
||||
litest_set_current_device(d);
|
||||
}
|
||||
|
||||
static struct input_id input_id = {
|
||||
.bustype = 0x3,
|
||||
.vendor = 0x1,
|
||||
.product = 0x1,
|
||||
};
|
||||
|
||||
static int events[] = {
|
||||
EV_KEY, BTN_LEFT,
|
||||
EV_KEY, BTN_RIGHT,
|
||||
EV_KEY, BTN_MIDDLE,
|
||||
EV_REL, REL_X,
|
||||
EV_REL, REL_Y,
|
||||
EV_REL, REL_WHEEL,
|
||||
-1 , -1,
|
||||
};
|
||||
|
||||
static const char udev_rule[] =
|
||||
"ACTION==\"remove\", GOTO=\"touchpad_end\"\n"
|
||||
"KERNEL!=\"event*\", GOTO=\"touchpad_end\"\n"
|
||||
"ENV{ID_INPUT_TOUCHPAD}==\"\", GOTO=\"touchpad_end\"\n"
|
||||
"\n"
|
||||
"ATTRS{name}==\"litest Low DPI Mouse*\",\\\n"
|
||||
" ENV{MOUSE_DPI}=\"400@125\"\n"
|
||||
"\n"
|
||||
"LABEL=\"touchpad_end\"";
|
||||
|
||||
struct litest_test_device litest_mouse_low_dpi_device = {
|
||||
.type = LITEST_MOUSE_LOW_DPI,
|
||||
.features = LITEST_RELATIVE | LITEST_BUTTON | LITEST_WHEEL,
|
||||
.shortname = "low-dpi mouse",
|
||||
.setup = litest_mouse_setup,
|
||||
.interface = NULL,
|
||||
|
||||
.name = "Low DPI Mouse",
|
||||
.id = &input_id,
|
||||
.absinfo = NULL,
|
||||
.events = events,
|
||||
.udev_rule = udev_rule,
|
||||
};
|
||||
123
test/litest.c
123
test/litest.c
|
|
@ -44,6 +44,7 @@
|
|||
#include <sys/sendfile.h>
|
||||
#include <sys/timerfd.h>
|
||||
#include <sys/wait.h>
|
||||
#include <libudev.h>
|
||||
|
||||
#include "litest.h"
|
||||
#include "litest-int.h"
|
||||
|
|
@ -52,7 +53,7 @@
|
|||
#define UDEV_RULES_D "/run/udev/rules.d"
|
||||
#define UDEV_RULE_PREFIX "99-litest-"
|
||||
#define UDEV_HWDB_D "/etc/udev/hwdb.d"
|
||||
#define UDEV_COMMON_RULE_FILE UDEV_RULES_D "/91-litest-model-quirks.rules"
|
||||
#define UDEV_COMMON_RULE_FILE UDEV_RULES_D "/91-litest-model-quirks-REMOVEME.rules"
|
||||
#define UDEV_COMMON_HWDB_FILE UDEV_HWDB_D "/91-litest-model-quirks-REMOVEME.hwdb"
|
||||
|
||||
static int in_debugger = -1;
|
||||
|
|
@ -356,6 +357,7 @@ extern struct litest_test_device litest_ms_surface_cover_device;
|
|||
extern struct litest_test_device litest_logitech_trackball_device;
|
||||
extern struct litest_test_device litest_atmel_hover_device;
|
||||
extern struct litest_test_device litest_alps_dualpoint_device;
|
||||
extern struct litest_test_device litest_mouse_low_dpi_device;
|
||||
extern struct litest_test_device litest_waltop_tablet_device;
|
||||
|
||||
struct litest_test_device* devices[] = {
|
||||
|
|
@ -387,6 +389,7 @@ struct litest_test_device* devices[] = {
|
|||
&litest_logitech_trackball_device,
|
||||
&litest_atmel_hover_device,
|
||||
&litest_alps_dualpoint_device,
|
||||
&litest_mouse_low_dpi_device,
|
||||
&litest_waltop_tablet_device,
|
||||
NULL,
|
||||
};
|
||||
|
|
@ -933,16 +936,20 @@ litest_copy_file(const char *dest, const char *src, const char *header)
|
|||
static inline void
|
||||
litest_install_model_quirks(void)
|
||||
{
|
||||
litest_copy_file(UDEV_COMMON_RULE_FILE, LIBINPUT_UDEV_RULES_FILE, NULL);
|
||||
litest_copy_file(UDEV_COMMON_HWDB_FILE,
|
||||
LIBINPUT_UDEV_HWDB_FILE,
|
||||
const char *warning =
|
||||
"#################################################################\n"
|
||||
"# WARNING: REMOVE THIS FILE\n"
|
||||
"# This is the run-time hwdb file for the libinput test suite and\n"
|
||||
"# This is a run-time file for the libinput test suite and\n"
|
||||
"# should be removed on exit. If the test-suite is not currently \n"
|
||||
"# running, remove this file and update your hwdb: \n"
|
||||
"# sudo udevadm hwdb --update\n"
|
||||
"#################################################################\n\n");
|
||||
"#################################################################\n\n";
|
||||
litest_copy_file(UDEV_COMMON_RULE_FILE,
|
||||
LIBINPUT_UDEV_RULES_FILE,
|
||||
warning);
|
||||
litest_copy_file(UDEV_COMMON_HWDB_FILE,
|
||||
LIBINPUT_UDEV_HWDB_FILE,
|
||||
warning);
|
||||
}
|
||||
|
||||
static inline void
|
||||
|
|
@ -1083,32 +1090,6 @@ litest_restore_log_handler(struct libinput *libinput)
|
|||
libinput_log_set_handler(libinput, litest_log_handler);
|
||||
}
|
||||
|
||||
static inline void
|
||||
litest_wait_for_udev(int fd)
|
||||
{
|
||||
struct udev *udev;
|
||||
struct udev_device *device;
|
||||
struct stat st;
|
||||
int loop_count = 0;
|
||||
|
||||
litest_assert_int_ge(fstat(fd, &st), 0);
|
||||
|
||||
udev = udev_new();
|
||||
device = udev_device_new_from_devnum(udev, 'c', st.st_rdev);
|
||||
litest_assert_ptr_notnull(device);
|
||||
while (device && !udev_device_get_property_value(device, "ID_INPUT")) {
|
||||
loop_count++;
|
||||
litest_assert_int_lt(loop_count, 300);
|
||||
|
||||
udev_device_unref(device);
|
||||
msleep(2);
|
||||
device = udev_device_new_from_devnum(udev, 'c', st.st_rdev);
|
||||
}
|
||||
|
||||
udev_device_unref(device);
|
||||
udev_unref(udev);
|
||||
}
|
||||
|
||||
struct litest_device *
|
||||
litest_add_device_with_overrides(struct libinput *libinput,
|
||||
enum litest_device_type which,
|
||||
|
|
@ -1136,8 +1117,6 @@ litest_add_device_with_overrides(struct libinput *libinput,
|
|||
rc = libevdev_new_from_fd(fd, &d->evdev);
|
||||
litest_assert_int_eq(rc, 0);
|
||||
|
||||
litest_wait_for_udev(fd);
|
||||
|
||||
d->libinput = libinput;
|
||||
d->libinput_device = libinput_path_add_device(d->libinput, path);
|
||||
litest_assert(d->libinput_device != NULL);
|
||||
|
|
@ -1224,11 +1203,6 @@ litest_delete_device(struct litest_device *d)
|
|||
free(d->private);
|
||||
memset(d,0, sizeof(*d));
|
||||
free(d);
|
||||
|
||||
/* zzz so udev can catch up with things, so we don't accidentally open
|
||||
* an old device in the next test and then get all upset when things blow
|
||||
* up */
|
||||
msleep(10);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -1685,6 +1659,7 @@ litest_wait_for_event_of_type(struct libinput *li, ...)
|
|||
enum libinput_event_type types[32] = {LIBINPUT_EVENT_NONE};
|
||||
size_t ntypes = 0;
|
||||
enum libinput_event_type type;
|
||||
struct pollfd fds;
|
||||
|
||||
va_start(args, li);
|
||||
type = va_arg(args, int);
|
||||
|
|
@ -1696,12 +1671,16 @@ litest_wait_for_event_of_type(struct libinput *li, ...)
|
|||
}
|
||||
va_end(args);
|
||||
|
||||
fds.fd = libinput_get_fd(li);
|
||||
fds.events = POLLIN;
|
||||
fds.revents = 0;
|
||||
|
||||
while (1) {
|
||||
size_t i;
|
||||
struct libinput_event *event;
|
||||
|
||||
while ((type = libinput_next_event_type(li)) == LIBINPUT_EVENT_NONE) {
|
||||
msleep(10);
|
||||
poll(&fds, 1, -1);
|
||||
libinput_dispatch(li);
|
||||
}
|
||||
|
||||
|
|
@ -1858,11 +1837,11 @@ litest_assert_empty_queue(struct libinput *li)
|
|||
litest_assert(empty_queue);
|
||||
}
|
||||
|
||||
struct libevdev_uinput *
|
||||
litest_create_uinput_device_from_description(const char *name,
|
||||
const struct input_id *id,
|
||||
const struct input_absinfo *abs_info,
|
||||
const int *events)
|
||||
static struct libevdev_uinput *
|
||||
litest_create_uinput(const char *name,
|
||||
const struct input_id *id,
|
||||
const struct input_absinfo *abs_info,
|
||||
const int *events)
|
||||
{
|
||||
struct libevdev_uinput *uinput;
|
||||
struct libevdev *dev;
|
||||
|
|
@ -1950,6 +1929,58 @@ litest_create_uinput_device_from_description(const char *name,
|
|||
return uinput;
|
||||
}
|
||||
|
||||
struct libevdev_uinput *
|
||||
litest_create_uinput_device_from_description(const char *name,
|
||||
const struct input_id *id,
|
||||
const struct input_absinfo *abs_info,
|
||||
const int *events)
|
||||
{
|
||||
struct libevdev_uinput *uinput;
|
||||
const char *syspath;
|
||||
|
||||
struct udev *udev;
|
||||
struct udev_monitor *udev_monitor;
|
||||
struct udev_device *udev_device;
|
||||
const char *udev_action;
|
||||
const char *udev_syspath = NULL;
|
||||
|
||||
udev = udev_new();
|
||||
litest_assert_notnull(udev);
|
||||
udev_monitor = udev_monitor_new_from_netlink(udev, "udev");
|
||||
litest_assert_notnull(udev_monitor);
|
||||
udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "input",
|
||||
NULL);
|
||||
/* remove O_NONBLOCK */
|
||||
fcntl(udev_monitor_get_fd(udev_monitor), F_SETFL, 0);
|
||||
litest_assert_int_eq(udev_monitor_enable_receiving(udev_monitor),
|
||||
0);
|
||||
|
||||
uinput = litest_create_uinput(name, id, abs_info, events);
|
||||
|
||||
syspath = libevdev_uinput_get_syspath(uinput);
|
||||
|
||||
/* blocking, we don't want to continue until udev is ready */
|
||||
do {
|
||||
udev_device = udev_monitor_receive_device(udev_monitor);
|
||||
litest_assert_notnull(udev_device);
|
||||
udev_action = udev_device_get_action(udev_device);
|
||||
if (strcmp(udev_action, "add") != 0) {
|
||||
udev_device_unref(udev_device);
|
||||
continue;
|
||||
}
|
||||
|
||||
udev_syspath = udev_device_get_syspath(udev_device);
|
||||
} while (!udev_syspath || strcmp(udev_syspath, syspath) != 0);
|
||||
|
||||
litest_assert(udev_device_get_property_value(udev_device, "ID_INPUT"));
|
||||
|
||||
udev_device_unref(udev_device);
|
||||
udev_monitor_unref(udev_monitor);
|
||||
udev_unref(udev);
|
||||
|
||||
return uinput;
|
||||
}
|
||||
|
||||
static struct libevdev_uinput *
|
||||
litest_create_uinput_abs_device_v(const char *name,
|
||||
struct input_id *id,
|
||||
|
|
@ -2493,6 +2524,8 @@ main(int argc, char **argv)
|
|||
|
||||
list_init(&all_tests);
|
||||
|
||||
setenv("CK_DEFAULT_TIMEOUT", "10", 0);
|
||||
|
||||
mode = litest_parse_argv(argc, argv);
|
||||
if (mode == LITEST_MODE_ERROR)
|
||||
return EXIT_FAILURE;
|
||||
|
|
|
|||
|
|
@ -137,11 +137,12 @@ enum litest_device_type {
|
|||
LITEST_LOGITECH_TRACKBALL = -23,
|
||||
LITEST_ATMEL_HOVER = -24,
|
||||
LITEST_ALPS_DUALPOINT = -25,
|
||||
LITEST_WACOM_BAMBOO = -26,
|
||||
LITEST_WACOM_CINTIQ = -27,
|
||||
LITEST_WACOM_INTUOS = -28,
|
||||
LITEST_WACOM_ISDV4 = -29,
|
||||
LITEST_WALTOP = -30,
|
||||
LITEST_MOUSE_LOW_DPI = -26,
|
||||
LITEST_WACOM_BAMBOO = -27,
|
||||
LITEST_WACOM_CINTIQ = -28,
|
||||
LITEST_WACOM_INTUOS = -29,
|
||||
LITEST_WACOM_ISDV4 = -30,
|
||||
LITEST_WALTOP = -31,
|
||||
};
|
||||
|
||||
enum litest_device_feature {
|
||||
|
|
|
|||
|
|
@ -690,7 +690,7 @@ litest_setup_tests(void)
|
|||
|
||||
litest_add_no_device("misc:matrix", matrix_helpers);
|
||||
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:trackpoint accel parser", trackpoint_accel_parser);
|
||||
litest_add_no_device("misc:parser", dpi_parser);
|
||||
litest_add_no_device("misc:parser", wheel_click_parser);
|
||||
litest_add_no_device("misc:parser", trackpoint_accel_parser);
|
||||
}
|
||||
|
|
|
|||
133
test/pointer.c
133
test/pointer.c
|
|
@ -35,52 +35,26 @@
|
|||
#include "libinput-util.h"
|
||||
#include "litest.h"
|
||||
|
||||
static struct libinput_event_pointer *
|
||||
get_accelerated_motion_event(struct libinput *li)
|
||||
{
|
||||
struct libinput_event *event;
|
||||
struct libinput_event_pointer *ptrev;
|
||||
|
||||
while (1) {
|
||||
event = libinput_get_event(li);
|
||||
ptrev = litest_is_motion_event(event);
|
||||
|
||||
if (fabs(libinput_event_pointer_get_dx(ptrev)) < DBL_MIN &&
|
||||
fabs(libinput_event_pointer_get_dy(ptrev)) < DBL_MIN) {
|
||||
libinput_event_destroy(event);
|
||||
continue;
|
||||
}
|
||||
|
||||
return ptrev;
|
||||
}
|
||||
|
||||
litest_abort_msg("No accelerated pointer motion event found");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
test_relative_event(struct litest_device *dev, int dx, int dy)
|
||||
{
|
||||
struct libinput *li = dev->libinput;
|
||||
struct libinput_event_pointer *ptrev;
|
||||
struct libinput_event *event;
|
||||
double ev_dx, ev_dy;
|
||||
double expected_dir;
|
||||
double expected_length;
|
||||
double actual_dir;
|
||||
double actual_length;
|
||||
|
||||
/* Send two deltas, as the first one may be eaten up by an
|
||||
* acceleration filter. */
|
||||
litest_event(dev, EV_REL, REL_X, dx);
|
||||
litest_event(dev, EV_REL, REL_Y, dy);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
litest_event(dev, EV_REL, REL_X, dx);
|
||||
litest_event(dev, EV_REL, REL_Y, dy);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
|
||||
libinput_dispatch(li);
|
||||
|
||||
ptrev = get_accelerated_motion_event(li);
|
||||
event = libinput_get_event(li);
|
||||
ptrev = litest_is_motion_event(event);
|
||||
|
||||
expected_length = sqrt(4 * dx*dx + 4 * dy*dy);
|
||||
expected_dir = atan2(dx, dy);
|
||||
|
|
@ -97,7 +71,7 @@ test_relative_event(struct litest_device *dev, int dx, int dy)
|
|||
* indifference). */
|
||||
litest_assert(fabs(expected_dir - actual_dir) < M_PI_2);
|
||||
|
||||
libinput_event_destroy(libinput_event_pointer_get_base_event(ptrev));
|
||||
libinput_event_destroy(event);
|
||||
|
||||
litest_drain_events(dev->libinput);
|
||||
}
|
||||
|
|
@ -120,6 +94,13 @@ START_TEST(pointer_motion_relative)
|
|||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
|
||||
/* send a single event, the first movement
|
||||
is always decelerated by 0.3 */
|
||||
litest_event(dev, EV_REL, REL_X, 1);
|
||||
litest_event(dev, EV_REL, REL_Y, 0);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
libinput_dispatch(dev->libinput);
|
||||
|
||||
litest_drain_events(dev->libinput);
|
||||
|
||||
test_relative_event(dev, 1, 0);
|
||||
|
|
@ -134,6 +115,95 @@ START_TEST(pointer_motion_relative)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(pointer_motion_relative_zero)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
int i;
|
||||
|
||||
/* NOTE: this test does virtually nothing. The kernel should not
|
||||
* allow 0/0 events to be passed to userspace. If it ever happens,
|
||||
* let's hope this test fails if we do the wrong thing.
|
||||
*/
|
||||
litest_drain_events(li);
|
||||
|
||||
for (i = 0; i < 5; i++) {
|
||||
litest_event(dev, EV_REL, REL_X, 0);
|
||||
litest_event(dev, EV_REL, REL_Y, 0);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
libinput_dispatch(li);
|
||||
}
|
||||
litest_assert_empty_queue(li);
|
||||
|
||||
/* send a single event, the first movement
|
||||
is always decelerated by 0.3 */
|
||||
litest_event(dev, EV_REL, REL_X, 1);
|
||||
litest_event(dev, EV_REL, REL_Y, 0);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
libinput_dispatch(li);
|
||||
|
||||
libinput_event_destroy(libinput_get_event(li));
|
||||
litest_assert_empty_queue(li);
|
||||
|
||||
for (i = 0; i < 5; i++) {
|
||||
litest_event(dev, EV_REL, REL_X, 0);
|
||||
litest_event(dev, EV_REL, REL_Y, 0);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
libinput_dispatch(dev->libinput);
|
||||
}
|
||||
litest_assert_empty_queue(li);
|
||||
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(pointer_motion_relative_min_decel)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
struct libinput_event_pointer *ptrev;
|
||||
struct libinput_event *event;
|
||||
double evx, evy;
|
||||
int dx, dy;
|
||||
int cardinal = _i; /* ranged test */
|
||||
double len;
|
||||
|
||||
int deltas[8][2] = {
|
||||
/* N, NE, E, ... */
|
||||
{ 0, 1 },
|
||||
{ 1, 1 },
|
||||
{ 1, 0 },
|
||||
{ 1, -1 },
|
||||
{ 0, -1 },
|
||||
{ -1, -1 },
|
||||
{ -1, 0 },
|
||||
{ -1, 1 },
|
||||
};
|
||||
|
||||
litest_drain_events(dev->libinput);
|
||||
|
||||
dx = deltas[cardinal][0];
|
||||
dy = deltas[cardinal][1];
|
||||
|
||||
litest_event(dev, EV_REL, REL_X, dx);
|
||||
litest_event(dev, EV_REL, REL_Y, dy);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
libinput_dispatch(li);
|
||||
|
||||
event = libinput_get_event(li);
|
||||
ptrev = litest_is_motion_event(event);
|
||||
evx = libinput_event_pointer_get_dx(ptrev);
|
||||
evy = libinput_event_pointer_get_dy(ptrev);
|
||||
|
||||
ck_assert((evx == 0.0) == (dx == 0));
|
||||
ck_assert((evy == 0.0) == (dy == 0));
|
||||
|
||||
len = vector_length(evx, evy);
|
||||
ck_assert(fabs(len) >= 0.3);
|
||||
|
||||
libinput_event_destroy(event);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
static void
|
||||
test_absolute_event(struct litest_device *dev, double x, double y)
|
||||
{
|
||||
|
|
@ -1347,8 +1417,11 @@ void
|
|||
litest_setup_tests(void)
|
||||
{
|
||||
struct range axis_range = {ABS_X, ABS_Y + 1};
|
||||
struct range compass = {0, 7}; /* cardinal directions */
|
||||
|
||||
litest_add("pointer:motion", pointer_motion_relative, LITEST_RELATIVE, LITEST_ANY);
|
||||
litest_add_for_device("pointer:motion", pointer_motion_relative_zero, LITEST_MOUSE);
|
||||
litest_add_ranged("pointer:motion", pointer_motion_relative_min_decel, LITEST_RELATIVE, LITEST_ANY, &compass);
|
||||
litest_add("pointer:motion", pointer_motion_absolute, LITEST_ABSOLUTE, LITEST_ANY);
|
||||
litest_add("pointer:motion", pointer_motion_unaccel, LITEST_RELATIVE, LITEST_ANY);
|
||||
litest_add("pointer:button", pointer_button, LITEST_BUTTON, LITEST_CLICKPAD);
|
||||
|
|
|
|||
|
|
@ -168,6 +168,7 @@ usage(void)
|
|||
"--maxdx=<double> ... in motion mode only. Stop increasing dx at maxdx\n"
|
||||
"--steps=<double> ... in motion and delta modes only. Increase dx by step each round\n"
|
||||
"--speed=<double> ... accel speed [-1, 1], default 0\n"
|
||||
"--dpi=<int> ... device resolution in DPI (default: 1000)\n"
|
||||
"\n"
|
||||
"If extra arguments are present and mode is not given, mode defaults to 'sequence'\n"
|
||||
"and the arguments are interpreted as sequence of delta x coordinates\n"
|
||||
|
|
@ -191,17 +192,17 @@ main(int argc, char **argv)
|
|||
print_sequence = false;
|
||||
double custom_deltas[1024];
|
||||
double speed = 0.0;
|
||||
int dpi = 1000;
|
||||
|
||||
enum {
|
||||
OPT_MODE = 1,
|
||||
OPT_NEVENTS,
|
||||
OPT_MAXDX,
|
||||
OPT_STEP,
|
||||
OPT_SPEED,
|
||||
OPT_DPI,
|
||||
};
|
||||
|
||||
filter = create_pointer_accelerator_filter(pointer_accel_profile_linear);
|
||||
assert(filter != NULL);
|
||||
|
||||
while (1) {
|
||||
int c;
|
||||
int option_index = 0;
|
||||
|
|
@ -211,6 +212,7 @@ main(int argc, char **argv)
|
|||
{"maxdx", 1, 0, OPT_MAXDX },
|
||||
{"step", 1, 0, OPT_STEP },
|
||||
{"speed", 1, 0, OPT_SPEED },
|
||||
{"dpi", 1, 0, OPT_DPI },
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
|
|
@ -258,6 +260,9 @@ main(int argc, char **argv)
|
|||
case OPT_SPEED:
|
||||
speed = strtod(optarg, NULL);
|
||||
break;
|
||||
case OPT_DPI:
|
||||
dpi = strtod(optarg, NULL);
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
exit(1);
|
||||
|
|
@ -265,6 +270,9 @@ main(int argc, char **argv)
|
|||
}
|
||||
}
|
||||
|
||||
filter = create_pointer_accelerator_filter(pointer_accel_profile_linear,
|
||||
dpi);
|
||||
assert(filter != NULL);
|
||||
filter_set_speed(filter, speed);
|
||||
|
||||
if (!isatty(STDIN_FILENO)) {
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
ACTION!="add|change", GOTO="libinput_model_quirks_end"
|
||||
KERNEL!="event*", GOTO="libinput_model_quirks_end"
|
||||
|
||||
# Matches below are exclusive, if one matches we skip the rest
|
||||
# hwdb matches:
|
||||
#
|
||||
# libinput:touchpad:<modalias>
|
||||
|
|
|
|||
|
|
@ -1,3 +1,26 @@
|
|||
/*
|
||||
* Copyright © 2015 Red Hat, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue