mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2026-01-12 01:00:19 +01:00
Merge branch 'filter-us-ms-cleanup'
This commit is contained in:
commit
f976619ebd
16 changed files with 15334 additions and 129 deletions
|
|
@ -18,6 +18,7 @@ header_files = \
|
|||
$(srcdir)/normalization-of-relative-motion.dox \
|
||||
$(srcdir)/palm-detection.dox \
|
||||
$(srcdir)/page-hierarchy.dox \
|
||||
$(srcdir)/pointer-acceleration.dox \
|
||||
$(srcdir)/reporting-bugs.dox \
|
||||
$(srcdir)/scrolling.dox \
|
||||
$(srcdir)/seats.dox \
|
||||
|
|
@ -39,6 +40,10 @@ diagram_files = \
|
|||
$(srcdir)/svg/edge-scrolling.svg \
|
||||
$(srcdir)/svg/palm-detection.svg \
|
||||
$(srcdir)/svg/pinch-gestures.svg \
|
||||
$(srcdir)/svg/ptraccel-linear.svg \
|
||||
$(srcdir)/svg/ptraccel-low-dpi.svg \
|
||||
$(srcdir)/svg/ptraccel-touchpad.svg \
|
||||
$(srcdir)/svg/ptraccel-trackpoint.svg \
|
||||
$(srcdir)/svg/swipe-gestures.svg \
|
||||
$(srcdir)/svg/tap-n-drag.svg \
|
||||
$(srcdir)/svg/thumb-detection.svg \
|
||||
|
|
|
|||
|
|
@ -31,5 +31,6 @@
|
|||
|
||||
- @subpage test-suite
|
||||
- @subpage tools
|
||||
- @subpage pointer-acceleration
|
||||
|
||||
*/
|
||||
|
|
|
|||
110
doc/pointer-acceleration.dox
Normal file
110
doc/pointer-acceleration.dox
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
/**
|
||||
@page pointer-acceleration Pointer acceleration
|
||||
|
||||
libinput uses device-specific pointer acceleration methods, with the default
|
||||
being the @ref ptraccel-linear. The methods share common properties, such as
|
||||
@ref ptraccel-velocity.
|
||||
|
||||
This page explains the high-level concepts used in the code. It aims to
|
||||
provide an overview for developers and is not necessarily useful for
|
||||
users.
|
||||
|
||||
@section ptraccel-velocity Velocity calculation
|
||||
|
||||
The device's speed of movement is measured across multiple input events
|
||||
through so-called "trackers". Each event prepends a the tracker item, each
|
||||
subsequent tracker contains the delta of that item to the current position,
|
||||
the timestamp of the event that created it and the cardinal direction of the
|
||||
movement at the time. If a device moves into the same direction, the
|
||||
velocity is calculated across multiple trackers. For example, if a device
|
||||
moves steadily for 10 events to the left, the velocity is calculated across
|
||||
all 10 events.
|
||||
|
||||
Whenever the movement changes direction or significantly changes speed, the
|
||||
velocity is calculated from the direction/speed change only. For example, if
|
||||
a device moves steadily for 8 events to the left and then 2 events to the
|
||||
right, the velocity is only that of the last 2 events.
|
||||
|
||||
An extra time limit prevents events that are too old to factor into the
|
||||
velocity calculation. For example, if a device moves steadily for 5 events
|
||||
to the left, then pauses, then moves again for 5 events to the left, only
|
||||
the last 5 events are used for velocity calculation.
|
||||
|
||||
The velocity is then used to calculate the acceleration factor
|
||||
|
||||
@section ptraccel-factor Acceleration factor
|
||||
|
||||
The acceleration factor is the final outcome of the pointer acceleration
|
||||
calculations. It is a unitless factor that is applied to the current delta,
|
||||
a factor of 2 doubles the delta (i.e. speeds up the movement), a factor of
|
||||
less than 1 reduces the delta (i.e. slows the movement).
|
||||
|
||||
Any factor less than 1 requires the user to move the device further to move
|
||||
the visible pointer. This is called deceleration and enables high precision
|
||||
target selection through subpixel movements. libinput's current maximum
|
||||
deceleration factor is 0.3 (i.e. slow down to 30% of the pointer speed).
|
||||
|
||||
A factor higher than 1 moves the pointer further than the physical device
|
||||
moves. This is acceleration and allows a user to cross the screen quickly
|
||||
but effectively skips pixels. libinput's current maximum acceleration factor
|
||||
is 3.5.
|
||||
|
||||
@section ptraccel-linear Linear pointer acceleration
|
||||
|
||||
The linear pointer acceleration method is the default for most pointer
|
||||
devices. It provides deceleration at very slow movements, a 1:1 mapping for
|
||||
regular movements and a linear increase to the maximum acceleration factor
|
||||
for fast movements.
|
||||
|
||||
Linear pointer acceleration applies to devices with above 1000dpi resolution
|
||||
and after @ref motion_normalization is applied.
|
||||
|
||||
@image html ptraccel-linear.svg "Linear pointer acceleration"
|
||||
|
||||
The image above shows the linear pointer acceleration settings at various
|
||||
speeds. The line for 0.0 is the default acceleration curve, speed settings
|
||||
above 0.0 accelerate sooner, faster and to a higher maximum acceleration.
|
||||
Speed settings below 0 delay when acceleration kicks in, how soon the
|
||||
maximum acceleration is reached and the maximum acceleration factor.
|
||||
|
||||
Extremely low speed settings provide no acceleration and additionally
|
||||
decelerate all movement by a constant factor.
|
||||
|
||||
@section ptraccel-low-dpi Pointer acceleration for low-dpi devices
|
||||
|
||||
Low-dpi devices are those with a physical resolution of less than 1000 dots
|
||||
per inch (dpi). The pointer acceleration is adjusted to provide roughly the
|
||||
same feel for all devices at normal to high speeds. At slow speeds, the
|
||||
pointer acceleration works on device-units rather than normalized
|
||||
coordinates (see @ref motion_normalization).
|
||||
|
||||
@image html ptraccel-low-dpi.svg "Pointer acceleration for low-dpi devices"
|
||||
|
||||
The image above shows the default pointer acceleration curve for a speed of
|
||||
0.0 at different DPI settings. A device with low DPI has the acceleration
|
||||
applied sooner and with a stronger acceleration factor.
|
||||
|
||||
@section ptraccel-touchpad Pointer acceleration on touchpads
|
||||
|
||||
Touchpad pointer acceleration uses the @ref ptraccel-linear profile, with a
|
||||
constant deceleration factor applied. The user expectation of how much a
|
||||
pointer should move in response to finger movement is different to that of a
|
||||
mouse device, hence the constant deceleration factor.
|
||||
|
||||
@image html ptraccel-touchpad.svg "Pointer acceleration curve for touchpads"
|
||||
|
||||
The image above shows the touchpad acceleration profile in comparison to the
|
||||
@ref ptraccel-linear. The shape of the curve is identical but vertically squashed.
|
||||
|
||||
@section ptraccel-trackpoint Pointer acceleration on trackpoints
|
||||
|
||||
Trackpoint pointer acceleration uses the @ref ptraccel-low-dpi profile, with a
|
||||
constant deceleration factor taking the place of the DPI settings.
|
||||
|
||||
@image html ptraccel-trackpoint.svg "Pointer acceleration curves for trackpoints"
|
||||
|
||||
The image above shows the trackpoint acceleration profile in comparison to the
|
||||
@ref ptraccel-linear. The constant acceleration factor, usually applied by
|
||||
udev, shapes the acceleration profile.
|
||||
|
||||
*/
|
||||
5486
doc/svg/ptraccel-linear.svg
Normal file
5486
doc/svg/ptraccel-linear.svg
Normal file
File diff suppressed because it is too large
Load diff
|
After Width: | Height: | Size: 550 KiB |
3748
doc/svg/ptraccel-low-dpi.svg
Normal file
3748
doc/svg/ptraccel-low-dpi.svg
Normal file
File diff suppressed because it is too large
Load diff
|
After Width: | Height: | Size: 377 KiB |
1723
doc/svg/ptraccel-touchpad.svg
Normal file
1723
doc/svg/ptraccel-touchpad.svg
Normal file
File diff suppressed because it is too large
Load diff
|
After Width: | Height: | Size: 171 KiB |
3689
doc/svg/ptraccel-trackpoint.svg
Normal file
3689
doc/svg/ptraccel-trackpoint.svg
Normal file
File diff suppressed because it is too large
Load diff
|
After Width: | Height: | Size: 371 KiB |
|
|
@ -1510,7 +1510,7 @@ static int
|
|||
tp_init_accel(struct tp_dispatch *tp, double diagonal)
|
||||
{
|
||||
int res_x, res_y;
|
||||
accel_profile_func_t profile;
|
||||
struct motion_filter *filter;
|
||||
|
||||
res_x = tp->device->abs.absinfo_x->resolution;
|
||||
res_y = tp->device->abs.absinfo_y->resolution;
|
||||
|
|
@ -1526,14 +1526,14 @@ tp_init_accel(struct tp_dispatch *tp, double diagonal)
|
|||
tp->accel.y_scale_coeff = (DEFAULT_MOUSE_DPI/25.4) / res_y;
|
||||
|
||||
if (tp->device->model_flags & EVDEV_MODEL_LENOVO_X230)
|
||||
profile = touchpad_lenovo_x230_accel_profile;
|
||||
filter = create_pointer_accelerator_filter_lenovo_x230(tp->device->dpi);
|
||||
else
|
||||
profile = touchpad_accel_profile_linear;
|
||||
filter = create_pointer_accelerator_filter_touchpad(tp->device->dpi);
|
||||
|
||||
if (evdev_device_init_pointer_acceleration(tp->device, profile) == -1)
|
||||
if (!filter)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
return evdev_device_init_pointer_acceleration(tp->device, filter);
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
|
|
|
|||
22
src/evdev.c
22
src/evdev.c
|
|
@ -1408,12 +1408,9 @@ evdev_accel_config_get_default_speed(struct libinput_device *device)
|
|||
|
||||
int
|
||||
evdev_device_init_pointer_acceleration(struct evdev_device *device,
|
||||
accel_profile_func_t profile)
|
||||
struct motion_filter *filter)
|
||||
{
|
||||
device->pointer.filter = create_pointer_accelerator_filter(profile,
|
||||
device->dpi);
|
||||
if (!device->pointer.filter)
|
||||
return -1;
|
||||
device->pointer.filter = filter;
|
||||
|
||||
device->pointer.config.available = evdev_accel_config_available;
|
||||
device->pointer.config.set_speed = evdev_accel_config_set_speed;
|
||||
|
|
@ -1862,14 +1859,19 @@ evdev_configure_mt_device(struct evdev_device *device)
|
|||
static inline int
|
||||
evdev_init_accel(struct evdev_device *device)
|
||||
{
|
||||
accel_profile_func_t profile;
|
||||
struct motion_filter *filter;
|
||||
|
||||
if (device->dpi < DEFAULT_MOUSE_DPI)
|
||||
profile = pointer_accel_profile_linear_low_dpi;
|
||||
if (device->tags & EVDEV_TAG_TRACKPOINT)
|
||||
filter = create_pointer_accelerator_filter_trackpoint(device->dpi);
|
||||
else if (device->dpi < DEFAULT_MOUSE_DPI)
|
||||
filter = create_pointer_accelerator_filter_linear_low_dpi(device->dpi);
|
||||
else
|
||||
profile = pointer_accel_profile_linear;
|
||||
filter = create_pointer_accelerator_filter_linear(device->dpi);
|
||||
|
||||
return evdev_device_init_pointer_acceleration(device, profile);
|
||||
if (!filter)
|
||||
return -1;
|
||||
|
||||
return evdev_device_init_pointer_acceleration(device, filter);
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
|
|||
|
|
@ -281,7 +281,7 @@ evdev_device_create(struct libinput_seat *seat,
|
|||
|
||||
int
|
||||
evdev_device_init_pointer_acceleration(struct evdev_device *device,
|
||||
accel_profile_func_t profile);
|
||||
struct motion_filter *filter);
|
||||
|
||||
struct evdev_dispatch *
|
||||
evdev_touchpad_create(struct evdev_device *device);
|
||||
|
|
|
|||
|
|
@ -38,11 +38,11 @@ struct motion_filter_interface {
|
|||
uint64_t time);
|
||||
void (*destroy)(struct motion_filter *filter);
|
||||
bool (*set_speed)(struct motion_filter *filter,
|
||||
double speed);
|
||||
double speed_adjustment);
|
||||
};
|
||||
|
||||
struct motion_filter {
|
||||
double speed; /* normalized [-1, 1] */
|
||||
double speed_adjustment; /* normalized [-1, 1] */
|
||||
struct motion_filter_interface *interface;
|
||||
};
|
||||
|
||||
|
|
|
|||
512
src/filter.c
512
src/filter.c
|
|
@ -36,6 +36,20 @@
|
|||
#include "libinput-util.h"
|
||||
#include "filter-private.h"
|
||||
|
||||
/* Convert speed/velocity from units/us to units/ms */
|
||||
static inline double
|
||||
v_us2ms(double units_per_us)
|
||||
{
|
||||
return units_per_us * 1000.0;
|
||||
}
|
||||
|
||||
/* Convert speed/velocity from units/ms to units/us */
|
||||
static inline double
|
||||
v_ms2us(double units_per_ms)
|
||||
{
|
||||
return units_per_ms/1000.0;
|
||||
}
|
||||
|
||||
struct normalized_coords
|
||||
filter_dispatch(struct motion_filter *filter,
|
||||
const struct normalized_coords *unaccelerated,
|
||||
|
|
@ -62,31 +76,36 @@ filter_destroy(struct motion_filter *filter)
|
|||
|
||||
bool
|
||||
filter_set_speed(struct motion_filter *filter,
|
||||
double speed)
|
||||
double speed_adjustment)
|
||||
{
|
||||
return filter->interface->set_speed(filter, speed);
|
||||
return filter->interface->set_speed(filter, speed_adjustment);
|
||||
}
|
||||
|
||||
double
|
||||
filter_get_speed(struct motion_filter *filter)
|
||||
{
|
||||
return filter->speed;
|
||||
return filter->speed_adjustment;
|
||||
}
|
||||
|
||||
/*
|
||||
* Default parameters for pointer acceleration profiles.
|
||||
*/
|
||||
|
||||
#define DEFAULT_THRESHOLD 0.4 /* in units/ms */
|
||||
#define MINIMUM_THRESHOLD 0.2 /* in units/ms */
|
||||
#define DEFAULT_THRESHOLD v_ms2us(0.4) /* in units/us */
|
||||
#define MINIMUM_THRESHOLD v_ms2us(0.2) /* in units/us */
|
||||
#define DEFAULT_ACCELERATION 2.0 /* unitless factor */
|
||||
#define DEFAULT_INCLINE 1.1 /* unitless factor */
|
||||
|
||||
/* for the Lenovo x230 custom accel. do not touch */
|
||||
#define X230_THRESHOLD v_ms2us(0.4) /* in units/us */
|
||||
#define X230_ACCELERATION 2.0 /* unitless factor */
|
||||
#define X230_INCLINE 1.1 /* unitless factor */
|
||||
|
||||
/*
|
||||
* Pointer acceleration filter constants
|
||||
*/
|
||||
|
||||
#define MAX_VELOCITY_DIFF 1 /* units/ms */
|
||||
#define MAX_VELOCITY_DIFF v_ms2us(1) /* units/us */
|
||||
#define MOTION_TIMEOUT ms2us(1000)
|
||||
#define NUM_POINTER_TRACKERS 16
|
||||
|
||||
|
|
@ -96,20 +115,18 @@ struct pointer_tracker {
|
|||
int dir;
|
||||
};
|
||||
|
||||
struct pointer_accelerator;
|
||||
struct pointer_accelerator {
|
||||
struct motion_filter base;
|
||||
|
||||
accel_profile_func_t profile;
|
||||
|
||||
double velocity; /* units/ms */
|
||||
double last_velocity; /* units/ms */
|
||||
struct normalized_coords last;
|
||||
double velocity; /* units/us */
|
||||
double last_velocity; /* units/us */
|
||||
|
||||
struct pointer_tracker *trackers;
|
||||
int cur_tracker;
|
||||
|
||||
double threshold; /* units/ms */
|
||||
double threshold; /* units/us */
|
||||
double accel; /* unitless factor */
|
||||
double incline; /* incline of the function */
|
||||
|
||||
|
|
@ -151,7 +168,7 @@ static double
|
|||
calculate_tracker_velocity(struct pointer_tracker *tracker, uint64_t time)
|
||||
{
|
||||
double tdelta = time - tracker->time + 1;
|
||||
return normalized_length(tracker->delta) / tdelta * 1000.0; /* units/ms */
|
||||
return normalized_length(tracker->delta) / tdelta; /* units/us */
|
||||
}
|
||||
|
||||
static inline double
|
||||
|
|
@ -221,7 +238,7 @@ calculate_velocity(struct pointer_accelerator *accel, uint64_t time)
|
|||
}
|
||||
}
|
||||
|
||||
return result; /* units/ms */
|
||||
return result; /* units/us */
|
||||
}
|
||||
|
||||
static double
|
||||
|
|
@ -254,14 +271,55 @@ calculate_acceleration(struct pointer_accelerator *accel,
|
|||
return factor; /* unitless factor */
|
||||
}
|
||||
|
||||
static inline double
|
||||
calculate_acceleration_factor(struct pointer_accelerator *accel,
|
||||
const struct normalized_coords *unaccelerated,
|
||||
void *data,
|
||||
uint64_t time)
|
||||
{
|
||||
double velocity; /* units/us */
|
||||
double accel_factor;
|
||||
|
||||
feed_trackers(accel, unaccelerated, time);
|
||||
velocity = calculate_velocity(accel, time);
|
||||
accel_factor = calculate_acceleration(accel,
|
||||
data,
|
||||
velocity,
|
||||
accel->last_velocity,
|
||||
time);
|
||||
accel->last_velocity = velocity;
|
||||
|
||||
return accel_factor;
|
||||
}
|
||||
|
||||
static struct normalized_coords
|
||||
accelerator_filter(struct motion_filter *filter,
|
||||
const struct normalized_coords *unaccelerated,
|
||||
void *data, uint64_t time /* in us */)
|
||||
void *data, uint64_t time)
|
||||
{
|
||||
struct pointer_accelerator *accel =
|
||||
(struct pointer_accelerator *) filter;
|
||||
double accel_value; /* unitless factor */
|
||||
struct normalized_coords accelerated;
|
||||
|
||||
accel_value = calculate_acceleration_factor(accel,
|
||||
unaccelerated,
|
||||
data,
|
||||
time);
|
||||
|
||||
accelerated.x = accel_value * unaccelerated->x;
|
||||
accelerated.y = accel_value * unaccelerated->y;
|
||||
|
||||
return accelerated;
|
||||
}
|
||||
|
||||
static struct normalized_coords
|
||||
accelerator_filter_low_dpi(struct motion_filter *filter,
|
||||
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;
|
||||
struct normalized_coords unnormalized;
|
||||
|
|
@ -273,21 +331,70 @@ accelerator_filter(struct motion_filter *filter,
|
|||
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,
|
||||
velocity,
|
||||
accel->last_velocity,
|
||||
time);
|
||||
accel_value = calculate_acceleration_factor(accel,
|
||||
&unnormalized,
|
||||
data,
|
||||
time);
|
||||
|
||||
accelerated.x = accel_value * unnormalized.x;
|
||||
accelerated.y = accel_value * unnormalized.y;
|
||||
|
||||
accel->last = unnormalized;
|
||||
return accelerated;
|
||||
}
|
||||
|
||||
static struct normalized_coords
|
||||
accelerator_filter_trackpoint(struct motion_filter *filter,
|
||||
const struct normalized_coords *unaccelerated,
|
||||
void *data, uint64_t time)
|
||||
{
|
||||
struct pointer_accelerator *accel =
|
||||
(struct pointer_accelerator *) filter;
|
||||
double accel_value; /* unitless factor */
|
||||
struct normalized_coords accelerated;
|
||||
struct normalized_coords unnormalized;
|
||||
double dpi_factor = accel->dpi_factor;
|
||||
|
||||
/* trackpoints with a dpi factor have a const accel set, remove that
|
||||
* and restore device units. The accel profile takes const accel
|
||||
* into account */
|
||||
dpi_factor = min(1.0, dpi_factor);
|
||||
unnormalized.x = unaccelerated->x * dpi_factor;
|
||||
unnormalized.y = unaccelerated->y * dpi_factor;
|
||||
|
||||
accel_value = calculate_acceleration_factor(accel,
|
||||
&unnormalized,
|
||||
data,
|
||||
time);
|
||||
|
||||
accelerated.x = accel_value * unnormalized.x;
|
||||
accelerated.y = accel_value * unnormalized.y;
|
||||
|
||||
return accelerated;
|
||||
}
|
||||
|
||||
static struct normalized_coords
|
||||
accelerator_filter_x230(struct motion_filter *filter,
|
||||
const struct normalized_coords *unaccelerated,
|
||||
void *data, uint64_t time)
|
||||
{
|
||||
struct pointer_accelerator *accel =
|
||||
(struct pointer_accelerator *) filter;
|
||||
double accel_factor; /* unitless factor */
|
||||
struct normalized_coords accelerated;
|
||||
double velocity; /* units/us */
|
||||
|
||||
feed_trackers(accel, unaccelerated, time);
|
||||
velocity = calculate_velocity(accel, time);
|
||||
accel_factor = calculate_acceleration(accel,
|
||||
data,
|
||||
velocity,
|
||||
accel->last_velocity,
|
||||
time);
|
||||
accel->last_velocity = velocity;
|
||||
|
||||
accelerated.x = accel_factor * unaccelerated->x;
|
||||
accelerated.y = accel_factor * unaccelerated->y;
|
||||
|
||||
return accelerated;
|
||||
}
|
||||
|
||||
|
|
@ -326,65 +433,32 @@ accelerator_destroy(struct motion_filter *filter)
|
|||
|
||||
static bool
|
||||
accelerator_set_speed(struct motion_filter *filter,
|
||||
double speed)
|
||||
double speed_adjustment)
|
||||
{
|
||||
struct pointer_accelerator *accel_filter =
|
||||
(struct pointer_accelerator *)filter;
|
||||
|
||||
assert(speed >= -1.0 && speed <= 1.0);
|
||||
assert(speed_adjustment >= -1.0 && speed_adjustment <= 1.0);
|
||||
|
||||
/* Note: the numbers below are nothing but trial-and-error magic,
|
||||
don't read more into them other than "they mostly worked ok" */
|
||||
|
||||
/* delay when accel kicks in */
|
||||
accel_filter->threshold = DEFAULT_THRESHOLD - speed / 4.0;
|
||||
accel_filter->threshold = DEFAULT_THRESHOLD -
|
||||
v_ms2us(0.25) * speed_adjustment;
|
||||
if (accel_filter->threshold < MINIMUM_THRESHOLD)
|
||||
accel_filter->threshold = MINIMUM_THRESHOLD;
|
||||
|
||||
/* adjust max accel factor */
|
||||
accel_filter->accel = DEFAULT_ACCELERATION + speed * 1.5;
|
||||
accel_filter->accel = DEFAULT_ACCELERATION + speed_adjustment * 1.5;
|
||||
|
||||
/* higher speed -> faster to reach max */
|
||||
accel_filter->incline = DEFAULT_INCLINE + speed * 0.75;
|
||||
accel_filter->incline = DEFAULT_INCLINE + speed_adjustment * 0.75;
|
||||
|
||||
filter->speed = speed;
|
||||
filter->speed_adjustment = speed_adjustment;
|
||||
return true;
|
||||
}
|
||||
|
||||
struct motion_filter_interface accelerator_interface = {
|
||||
accelerator_filter,
|
||||
accelerator_restart,
|
||||
accelerator_destroy,
|
||||
accelerator_set_speed,
|
||||
};
|
||||
|
||||
struct motion_filter *
|
||||
create_pointer_accelerator_filter(accel_profile_func_t profile,
|
||||
int dpi)
|
||||
{
|
||||
struct pointer_accelerator *filter;
|
||||
|
||||
filter = zalloc(sizeof *filter);
|
||||
if (filter == NULL)
|
||||
return NULL;
|
||||
|
||||
filter->base.interface = &accelerator_interface;
|
||||
|
||||
filter->profile = profile;
|
||||
filter->last_velocity = 0.0;
|
||||
filter->last.x = 0;
|
||||
filter->last.y = 0;
|
||||
|
||||
filter->trackers =
|
||||
calloc(NUM_POINTER_TRACKERS, sizeof *filter->trackers);
|
||||
filter->cur_tracker = 0;
|
||||
|
||||
filter->threshold = DEFAULT_THRESHOLD;
|
||||
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.
|
||||
|
|
@ -398,25 +472,32 @@ create_pointer_accelerator_filter(accel_profile_func_t profile,
|
|||
double
|
||||
pointer_accel_profile_linear_low_dpi(struct motion_filter *filter,
|
||||
void *data,
|
||||
double speed_in, /* in device units (units/ms) */
|
||||
uint64_t time /* in us */)
|
||||
double speed_in, /* in device units (units/us) */
|
||||
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 */
|
||||
double threshold = accel_filter->threshold; /* units/us */
|
||||
const double incline = accel_filter->incline;
|
||||
double factor;
|
||||
double factor; /* unitless */
|
||||
double dpi_factor = accel_filter->dpi_factor;
|
||||
|
||||
/* dpi_factor is always < 1.0, increase max_accel, reduce
|
||||
the threshold so it kicks in earlier */
|
||||
max_accel /= dpi_factor;
|
||||
threshold *= dpi_factor;
|
||||
|
||||
s1 = min(1, 0.3 + speed_in * 10.0);
|
||||
s2 = 1 + (speed_in - threshold * dpi_factor) * incline;
|
||||
/* see pointer_accel_profile_linear for a long description */
|
||||
if (v_us2ms(speed_in) < 0.07)
|
||||
factor = 10 * v_us2ms(speed_in) + 0.3;
|
||||
else if (speed_in < threshold)
|
||||
factor = 1;
|
||||
else
|
||||
factor = incline * v_us2ms(speed_in - threshold) + 1;
|
||||
|
||||
factor = min(max_accel, s2 > 1 ? s2 : s1);
|
||||
factor = min(max_accel, factor);
|
||||
|
||||
return factor;
|
||||
}
|
||||
|
|
@ -425,54 +506,104 @@ double
|
|||
pointer_accel_profile_linear(struct motion_filter *filter,
|
||||
void *data,
|
||||
double speed_in, /* 1000-dpi normalized */
|
||||
uint64_t time /* in us */)
|
||||
uint64_t time)
|
||||
{
|
||||
struct pointer_accelerator *accel_filter =
|
||||
(struct pointer_accelerator *)filter;
|
||||
|
||||
double s1, s2;
|
||||
const double max_accel = accel_filter->accel; /* unitless factor */
|
||||
const double threshold = accel_filter->threshold; /* units/ms */
|
||||
const double threshold = accel_filter->threshold; /* units/us */
|
||||
const double incline = accel_filter->incline;
|
||||
double factor;
|
||||
double factor; /* unitless */
|
||||
|
||||
s1 = min(1, 0.3 + speed_in * 10);
|
||||
s2 = 1 + (speed_in - threshold) * incline;
|
||||
/*
|
||||
Our acceleration function calculates a factor to accelerate input
|
||||
deltas with. The function is a double incline with a plateau,
|
||||
with a rough shape like this:
|
||||
|
||||
factor = min(max_accel, s2 > 1 ? s2 : s1);
|
||||
accel
|
||||
factor
|
||||
^
|
||||
| /
|
||||
| _____/
|
||||
| /
|
||||
|/
|
||||
+-------------> speed in
|
||||
|
||||
The two inclines are linear functions in the form
|
||||
y = ax + b
|
||||
where y is speed_out
|
||||
x is speed_in
|
||||
a is the incline of acceleration
|
||||
b is minimum acceleration factor
|
||||
|
||||
for speeds up to 0.07 u/ms, we decelerate, down to 30% of input
|
||||
speed.
|
||||
hence 1 = a * 0.07 + 0.3
|
||||
0.3 = a * 0.00 + 0.3 => a := 10
|
||||
deceleration function is thus:
|
||||
y = 10x + 0.3
|
||||
|
||||
Note:
|
||||
* 0.07u/ms as threshold is a result of trial-and-error and
|
||||
has no other intrinsic meaning.
|
||||
* 0.3 is chosen simply because it is above the Nyquist frequency
|
||||
for subpixel motion within a pixel.
|
||||
*/
|
||||
if (v_us2ms(speed_in) < 0.07) {
|
||||
factor = 10 * v_us2ms(speed_in) + 0.3;
|
||||
/* up to the threshold, we keep factor 1, i.e. 1:1 movement */
|
||||
} else if (speed_in < threshold) {
|
||||
factor = 1;
|
||||
|
||||
} else {
|
||||
/* Acceleration function above the threshold:
|
||||
y = ax' + b
|
||||
where T is threshold
|
||||
x is speed_in
|
||||
x' is speed
|
||||
and
|
||||
y(T) == 1
|
||||
hence 1 = ax' + 1
|
||||
=> x' := (x - T)
|
||||
*/
|
||||
factor = incline * v_us2ms(speed_in - threshold) + 1;
|
||||
}
|
||||
|
||||
/* Cap at the maximum acceleration factor */
|
||||
factor = min(max_accel, factor);
|
||||
|
||||
return factor;
|
||||
}
|
||||
|
||||
double
|
||||
touchpad_accel_profile_linear(struct motion_filter *filter,
|
||||
void *data,
|
||||
double speed_in,
|
||||
uint64_t time /* in us */)
|
||||
void *data,
|
||||
double speed_in, /* units/us */
|
||||
uint64_t time)
|
||||
{
|
||||
/* Once normalized, touchpads see the same
|
||||
acceleration as mice. that is technically correct but
|
||||
subjectively wrong, we expect a touchpad to be a lot
|
||||
slower than a mouse. Apply a magic factor here and proceed
|
||||
as normal. */
|
||||
const double TP_MAGIC_SLOWDOWN = 0.4;
|
||||
double speed_out;
|
||||
const double TP_MAGIC_SLOWDOWN = 0.4; /* unitless */
|
||||
double factor; /* unitless */
|
||||
|
||||
speed_in *= TP_MAGIC_SLOWDOWN;
|
||||
|
||||
speed_out = pointer_accel_profile_linear(filter, data, speed_in, time);
|
||||
factor = pointer_accel_profile_linear(filter, data, speed_in, time);
|
||||
|
||||
return speed_out * TP_MAGIC_SLOWDOWN;
|
||||
return factor * TP_MAGIC_SLOWDOWN;
|
||||
}
|
||||
|
||||
double
|
||||
touchpad_lenovo_x230_accel_profile(struct motion_filter *filter,
|
||||
void *data,
|
||||
double speed_in,
|
||||
uint64_t time /* in us */)
|
||||
uint64_t time)
|
||||
{
|
||||
/* Keep the magic factor from touchpad_accel_profile_linear. */
|
||||
const double TP_MAGIC_SLOWDOWN = 0.4;
|
||||
const double TP_MAGIC_SLOWDOWN = 0.4; /* unitless */
|
||||
|
||||
/* Those touchpads presents an actual lower resolution that what is
|
||||
* advertised. We see some jumps from the cursor due to the big steps
|
||||
|
|
@ -480,24 +611,207 @@ touchpad_lenovo_x230_accel_profile(struct motion_filter *filter,
|
|||
* Apply a factor to minimize those jumps at low speed, and try
|
||||
* keeping the same feeling as regular touchpads at high speed.
|
||||
* It still feels slower but it is usable at least */
|
||||
const double TP_MAGIC_LOW_RES_FACTOR = 4.0;
|
||||
double speed_out;
|
||||
const double TP_MAGIC_LOW_RES_FACTOR = 4.0; /* unitless */
|
||||
double factor; /* unitless */
|
||||
struct pointer_accelerator *accel_filter =
|
||||
(struct pointer_accelerator *)filter;
|
||||
|
||||
double s1, s2;
|
||||
double f1, f2; /* unitless */
|
||||
const double max_accel = accel_filter->accel *
|
||||
TP_MAGIC_LOW_RES_FACTOR; /* unitless factor */
|
||||
const double threshold = accel_filter->threshold /
|
||||
TP_MAGIC_LOW_RES_FACTOR; /* units/ms */
|
||||
TP_MAGIC_LOW_RES_FACTOR; /* units/us */
|
||||
const double incline = accel_filter->incline * TP_MAGIC_LOW_RES_FACTOR;
|
||||
|
||||
/* Note: the magic values in this function are obtained by
|
||||
* trial-and-error. No other meaning should be interpreted.
|
||||
* The calculation is a compressed form of
|
||||
* pointer_accel_profile_linear(), look at the git history of that
|
||||
* function for an explaination of what the min/max/etc. does.
|
||||
*/
|
||||
speed_in *= TP_MAGIC_SLOWDOWN / TP_MAGIC_LOW_RES_FACTOR;
|
||||
|
||||
s1 = min(1, speed_in * 5);
|
||||
s2 = 1 + (speed_in - threshold) * incline;
|
||||
f1 = min(1, v_us2ms(speed_in) * 5);
|
||||
f2 = 1 + (v_us2ms(speed_in) - v_us2ms(threshold)) * incline;
|
||||
|
||||
speed_out = min(max_accel, s2 > 1 ? s2 : s1);
|
||||
factor = min(max_accel, f2 > 1 ? f2 : f1);
|
||||
|
||||
return speed_out * TP_MAGIC_SLOWDOWN / TP_MAGIC_LOW_RES_FACTOR;
|
||||
return factor * TP_MAGIC_SLOWDOWN / TP_MAGIC_LOW_RES_FACTOR;
|
||||
}
|
||||
|
||||
double
|
||||
trackpoint_accel_profile(struct motion_filter *filter,
|
||||
void *data,
|
||||
double speed_in, /* 1000-dpi normalized */
|
||||
uint64_t time)
|
||||
{
|
||||
struct pointer_accelerator *accel_filter =
|
||||
(struct pointer_accelerator *)filter;
|
||||
double max_accel = accel_filter->accel; /* unitless factor */
|
||||
double threshold = accel_filter->threshold; /* units/ms */
|
||||
const double incline = accel_filter->incline;
|
||||
double factor;
|
||||
double dpi_factor = accel_filter->dpi_factor;
|
||||
|
||||
/* dpi_factor is always < 1.0, increase max_accel, reduce
|
||||
the threshold so it kicks in earlier */
|
||||
max_accel /= dpi_factor;
|
||||
threshold *= dpi_factor;
|
||||
|
||||
/* see pointer_accel_profile_linear for a long description */
|
||||
if (v_us2ms(speed_in) < 0.07)
|
||||
factor = 10 * v_us2ms(speed_in) + 0.3;
|
||||
else if (speed_in < threshold)
|
||||
factor = 1;
|
||||
else
|
||||
factor = incline * v_us2ms(speed_in - threshold) + 1;
|
||||
|
||||
factor = min(max_accel, factor);
|
||||
|
||||
return factor;
|
||||
}
|
||||
|
||||
struct motion_filter_interface accelerator_interface = {
|
||||
accelerator_filter,
|
||||
accelerator_restart,
|
||||
accelerator_destroy,
|
||||
accelerator_set_speed,
|
||||
};
|
||||
|
||||
static struct pointer_accelerator *
|
||||
create_default_filter(int dpi)
|
||||
{
|
||||
struct pointer_accelerator *filter;
|
||||
|
||||
filter = zalloc(sizeof *filter);
|
||||
if (filter == NULL)
|
||||
return NULL;
|
||||
|
||||
filter->last_velocity = 0.0;
|
||||
|
||||
filter->trackers =
|
||||
calloc(NUM_POINTER_TRACKERS, sizeof *filter->trackers);
|
||||
filter->cur_tracker = 0;
|
||||
|
||||
filter->threshold = DEFAULT_THRESHOLD;
|
||||
filter->accel = DEFAULT_ACCELERATION;
|
||||
filter->incline = DEFAULT_INCLINE;
|
||||
|
||||
filter->dpi_factor = dpi/(double)DEFAULT_MOUSE_DPI;
|
||||
|
||||
return filter;
|
||||
}
|
||||
|
||||
struct motion_filter *
|
||||
create_pointer_accelerator_filter_linear(int dpi)
|
||||
{
|
||||
struct pointer_accelerator *filter;
|
||||
|
||||
filter = create_default_filter(dpi);
|
||||
if (!filter)
|
||||
return NULL;
|
||||
|
||||
filter->base.interface = &accelerator_interface;
|
||||
filter->profile = pointer_accel_profile_linear;
|
||||
|
||||
return &filter->base;
|
||||
}
|
||||
|
||||
struct motion_filter_interface accelerator_interface_low_dpi = {
|
||||
accelerator_filter_low_dpi,
|
||||
accelerator_restart,
|
||||
accelerator_destroy,
|
||||
accelerator_set_speed,
|
||||
};
|
||||
|
||||
struct motion_filter *
|
||||
create_pointer_accelerator_filter_linear_low_dpi(int dpi)
|
||||
{
|
||||
struct pointer_accelerator *filter;
|
||||
|
||||
filter = create_default_filter(dpi);
|
||||
if (!filter)
|
||||
return NULL;
|
||||
|
||||
filter->base.interface = &accelerator_interface_low_dpi;
|
||||
filter->profile = pointer_accel_profile_linear_low_dpi;
|
||||
|
||||
return &filter->base;
|
||||
}
|
||||
|
||||
struct motion_filter *
|
||||
create_pointer_accelerator_filter_touchpad(int dpi)
|
||||
{
|
||||
struct pointer_accelerator *filter;
|
||||
|
||||
filter = create_default_filter(dpi);
|
||||
if (!filter)
|
||||
return NULL;
|
||||
|
||||
filter->base.interface = &accelerator_interface;
|
||||
filter->profile = touchpad_accel_profile_linear;
|
||||
|
||||
return &filter->base;
|
||||
}
|
||||
|
||||
struct motion_filter_interface accelerator_interface_x230 = {
|
||||
accelerator_filter_x230,
|
||||
accelerator_restart,
|
||||
accelerator_destroy,
|
||||
accelerator_set_speed,
|
||||
};
|
||||
|
||||
/* The Lenovo x230 has a bad touchpad. This accel method has been
|
||||
* trial-and-error'd, any changes to it will require re-testing everything.
|
||||
* Don't touch this.
|
||||
*/
|
||||
struct motion_filter *
|
||||
create_pointer_accelerator_filter_lenovo_x230(int dpi)
|
||||
{
|
||||
struct pointer_accelerator *filter;
|
||||
|
||||
filter = zalloc(sizeof *filter);
|
||||
if (filter == NULL)
|
||||
return NULL;
|
||||
|
||||
filter->base.interface = &accelerator_interface_x230;
|
||||
filter->profile = touchpad_lenovo_x230_accel_profile;
|
||||
filter->last_velocity = 0.0;
|
||||
|
||||
filter->trackers =
|
||||
calloc(NUM_POINTER_TRACKERS, sizeof *filter->trackers);
|
||||
filter->cur_tracker = 0;
|
||||
|
||||
filter->threshold = X230_THRESHOLD;
|
||||
filter->accel = X230_ACCELERATION; /* unitless factor */
|
||||
filter->incline = X230_INCLINE; /* incline of the acceleration function */
|
||||
|
||||
filter->dpi_factor = 1; /* unused for this accel method */
|
||||
|
||||
return &filter->base;
|
||||
}
|
||||
|
||||
struct motion_filter_interface accelerator_interface_trackpoint = {
|
||||
accelerator_filter_trackpoint,
|
||||
accelerator_restart,
|
||||
accelerator_destroy,
|
||||
accelerator_set_speed,
|
||||
};
|
||||
|
||||
struct motion_filter *
|
||||
create_pointer_accelerator_filter_trackpoint(int dpi)
|
||||
{
|
||||
struct pointer_accelerator *filter;
|
||||
|
||||
filter = create_default_filter(dpi);
|
||||
if (!filter)
|
||||
return NULL;
|
||||
|
||||
filter->base.interface = &accelerator_interface_trackpoint;
|
||||
filter->profile = trackpoint_accel_profile;
|
||||
filter->threshold = DEFAULT_THRESHOLD;
|
||||
filter->accel = DEFAULT_ACCELERATION;
|
||||
filter->incline = DEFAULT_INCLINE;
|
||||
|
||||
return &filter->base;
|
||||
}
|
||||
|
|
|
|||
22
src/filter.h
22
src/filter.h
|
|
@ -57,9 +57,22 @@ typedef double (*accel_profile_func_t)(struct motion_filter *filter,
|
|||
double velocity,
|
||||
uint64_t time);
|
||||
|
||||
/* Pointer acceleration types */
|
||||
|
||||
struct motion_filter *
|
||||
create_pointer_accelerator_filter(accel_profile_func_t filter,
|
||||
int dpi);
|
||||
create_pointer_accelerator_filter_linear(int dpi);
|
||||
|
||||
struct motion_filter *
|
||||
create_pointer_accelerator_filter_linear_low_dpi(int dpi);
|
||||
|
||||
struct motion_filter *
|
||||
create_pointer_accelerator_filter_touchpad(int dpi);
|
||||
|
||||
struct motion_filter *
|
||||
create_pointer_accelerator_filter_lenovo_x230(int dpi);
|
||||
|
||||
struct motion_filter *
|
||||
create_pointer_accelerator_filter_trackpoint(int dpi);
|
||||
|
||||
/*
|
||||
* Pointer acceleration profiles.
|
||||
|
|
@ -85,4 +98,9 @@ touchpad_lenovo_x230_accel_profile(struct motion_filter *filter,
|
|||
void *data,
|
||||
double speed_in,
|
||||
uint64_t time);
|
||||
double
|
||||
trackpoint_accel_profile(struct motion_filter *filter,
|
||||
void *data,
|
||||
double speed_in,
|
||||
uint64_t time);
|
||||
#endif /* FILTER_H */
|
||||
|
|
|
|||
|
|
@ -39,3 +39,5 @@ event_gui_LDADD = ../src/libinput.la libshared.la $(CAIRO_LIBS) $(GTK_LIBS) $(LI
|
|||
event_gui_CFLAGS = $(CAIRO_CFLAGS) $(GTK_CFLAGS) $(LIBUDEV_CFLAGS)
|
||||
event_gui_LDFLAGS = -no-install
|
||||
endif
|
||||
|
||||
EXTRA_DIST = make-ptraccel-graphs.sh
|
||||
|
|
|
|||
79
tools/make-ptraccel-graphs.sh
Executable file
79
tools/make-ptraccel-graphs.sh
Executable file
|
|
@ -0,0 +1,79 @@
|
|||
#!/bin/bash
|
||||
|
||||
tool=`dirname $0`/ptraccel-debug
|
||||
gnuplot=/usr/bin/gnuplot
|
||||
|
||||
outfile="ptraccel-linear"
|
||||
for speed in -1 -0.75 -0.5 -0.25 0 0.5 1; do
|
||||
$tool --mode=accel --dpi=1000 --filter=linear --speed=$speed > $outfile-$speed.gnuplot
|
||||
done
|
||||
$gnuplot <<EOF
|
||||
set terminal svg enhanced background rgb 'white'
|
||||
set output "$outfile.svg"
|
||||
set xlabel "speed in units/us"
|
||||
set ylabel "accel factor"
|
||||
set style data lines
|
||||
set yrange [0:3]
|
||||
set xrange [0:0.003]
|
||||
plot "$outfile--1.gnuplot" using 1:2 title "-1.0", \
|
||||
"$outfile--0.75.gnuplot" using 1:2 title "-0.75", \
|
||||
"$outfile--0.5.gnuplot" using 1:2 title "-0.5", \
|
||||
"$outfile--0.25.gnuplot" using 1:2 title "-0.25", \
|
||||
"$outfile-0.gnuplot" using 1:2 title "0.0", \
|
||||
"$outfile-0.5.gnuplot" using 1:2 title "0.5", \
|
||||
"$outfile-1.gnuplot" using 1:2 title "1.0"
|
||||
EOF
|
||||
|
||||
outfile="ptraccel-low-dpi"
|
||||
for dpi in 200 400 800 1000; do
|
||||
$tool --mode=accel --dpi=$dpi --filter=low-dpi > $outfile-$dpi.gnuplot
|
||||
done
|
||||
|
||||
$gnuplot <<EOF
|
||||
set terminal svg enhanced background rgb 'white'
|
||||
set output "$outfile.svg"
|
||||
set xlabel "speed in units/us"
|
||||
set ylabel "accel factor"
|
||||
set style data lines
|
||||
set yrange [0:5]
|
||||
set xrange [0:0.003]
|
||||
plot "$outfile-200.gnuplot" using 1:2 title "200dpi", \
|
||||
"$outfile-400.gnuplot" using 1:2 title "400dpi", \
|
||||
"$outfile-800.gnuplot" using 1:2 title "800dpi", \
|
||||
"$outfile-1000.gnuplot" using 1:2 title "1000dpi"
|
||||
EOF
|
||||
|
||||
outfile="ptraccel-touchpad"
|
||||
$tool --mode=accel --dpi=1000 --filter=linear > $outfile-mouse.gnuplot
|
||||
$tool --mode=accel --dpi=1000 --filter=touchpad > $outfile-touchpad.gnuplot
|
||||
$gnuplot <<EOF
|
||||
set terminal svg enhanced background rgb 'white'
|
||||
set output "$outfile.svg"
|
||||
set xlabel "speed in units/us"
|
||||
set ylabel "accel factor"
|
||||
set style data lines
|
||||
set yrange [0:3]
|
||||
set xrange [0:0.003]
|
||||
plot "$outfile-mouse.gnuplot" using 1:2 title "linear (mouse)", \
|
||||
"$outfile-touchpad.gnuplot" using 1:2 title "touchpad"
|
||||
EOF
|
||||
|
||||
outfile="ptraccel-trackpoint"
|
||||
$tool --mode=accel --dpi=1000 --filter=linear > $outfile-mouse.gnuplot
|
||||
for constaccel in 1 2 3; do
|
||||
dpi=$((1000/$constaccel))
|
||||
$tool --mode=accel --dpi=$dpi --filter=trackpoint > $outfile-trackpoint-$constaccel.gnuplot
|
||||
done
|
||||
$gnuplot <<EOF
|
||||
set terminal svg enhanced background rgb 'white'
|
||||
set output "$outfile.svg"
|
||||
set xlabel "speed in units/us"
|
||||
set ylabel "accel factor"
|
||||
set style data lines
|
||||
set yrange [0:5]
|
||||
set xrange [0:0.003]
|
||||
plot "$outfile-mouse.gnuplot" using 1:2 title "linear (mouse)", \
|
||||
"$outfile-trackpoint-1.gnuplot" using 1:2 title "const accel 1", \
|
||||
"$outfile-trackpoint-2.gnuplot" using 1:2 title "const accel 2", \
|
||||
"$outfile-trackpoint-3.gnuplot" using 1:2 title "const accel 3"
|
||||
EOF
|
||||
|
|
@ -138,7 +138,7 @@ print_ptraccel_sequence(struct motion_filter *filter,
|
|||
}
|
||||
|
||||
static void
|
||||
print_accel_func(struct motion_filter *filter)
|
||||
print_accel_func(struct motion_filter *filter, accel_profile_func_t profile)
|
||||
{
|
||||
double vel;
|
||||
|
||||
|
|
@ -147,12 +147,9 @@ print_accel_func(struct motion_filter *filter)
|
|||
printf("# set ylabel \"raw accel factor\"\n");
|
||||
printf("# set style data lines\n");
|
||||
printf("# plot \"gnuplot.data\" using 1:2\n");
|
||||
for (vel = 0.0; vel < 3.0; vel += .0001) {
|
||||
double result = pointer_accel_profile_linear(filter,
|
||||
NULL,
|
||||
vel,
|
||||
0 /* time */);
|
||||
printf("%.4f\t%.4f\n", vel, result);
|
||||
for (vel = 0.0; vel < 0.003; vel += 0.0000001) {
|
||||
double result = profile(filter, NULL, vel, 0 /* time */);
|
||||
printf("%.8f\t%.4f\n", vel, result);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -171,6 +168,12 @@ usage(void)
|
|||
"--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"
|
||||
"--filter=<linear|low-dpi|touchpad|x230|trackpoint> \n"
|
||||
" linear ... the default motion filter\n"
|
||||
" low-dpi ... low-dpi filter, use --dpi with this argument\n"
|
||||
" touchpad ... the touchpad motion filter\n"
|
||||
" x230 ... custom filter for the Lenovo x230 touchpad\n"
|
||||
" trackpoint... trackpoint motion filter\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"
|
||||
|
|
@ -195,6 +198,8 @@ main(int argc, char **argv)
|
|||
double custom_deltas[1024];
|
||||
double speed = 0.0;
|
||||
int dpi = 1000;
|
||||
const char *filter_type = "linear";
|
||||
accel_profile_func_t profile = NULL;
|
||||
|
||||
enum {
|
||||
OPT_MODE = 1,
|
||||
|
|
@ -203,6 +208,7 @@ main(int argc, char **argv)
|
|||
OPT_STEP,
|
||||
OPT_SPEED,
|
||||
OPT_DPI,
|
||||
OPT_FILTER,
|
||||
};
|
||||
|
||||
while (1) {
|
||||
|
|
@ -215,6 +221,7 @@ main(int argc, char **argv)
|
|||
{"step", 1, 0, OPT_STEP },
|
||||
{"speed", 1, 0, OPT_SPEED },
|
||||
{"dpi", 1, 0, OPT_DPI },
|
||||
{"filter", 1, 0, OPT_FILTER},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
|
|
@ -265,6 +272,9 @@ main(int argc, char **argv)
|
|||
case OPT_DPI:
|
||||
dpi = strtod(optarg, NULL);
|
||||
break;
|
||||
case OPT_FILTER:
|
||||
filter_type = optarg;
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
exit(1);
|
||||
|
|
@ -272,8 +282,26 @@ main(int argc, char **argv)
|
|||
}
|
||||
}
|
||||
|
||||
filter = create_pointer_accelerator_filter(pointer_accel_profile_linear,
|
||||
dpi);
|
||||
if (streq(filter_type, "linear")) {
|
||||
filter = create_pointer_accelerator_filter_linear(dpi);
|
||||
profile = pointer_accel_profile_linear;
|
||||
} else if (streq(filter_type, "low-dpi")) {
|
||||
filter = create_pointer_accelerator_filter_linear_low_dpi(dpi);
|
||||
profile = pointer_accel_profile_linear_low_dpi;
|
||||
} else if (streq(filter_type, "touchpad")) {
|
||||
filter = create_pointer_accelerator_filter_touchpad(dpi);
|
||||
profile = touchpad_accel_profile_linear;
|
||||
} else if (streq(filter_type, "x230")) {
|
||||
filter = create_pointer_accelerator_filter_lenovo_x230(dpi);
|
||||
profile = touchpad_lenovo_x230_accel_profile;
|
||||
} else if (streq(filter_type, "trackpoint")) {
|
||||
filter = create_pointer_accelerator_filter_trackpoint(dpi);
|
||||
profile = trackpoint_accel_profile;
|
||||
} else {
|
||||
fprintf(stderr, "Invalid filter type %s\n", filter_type);
|
||||
return 1;
|
||||
}
|
||||
|
||||
assert(filter != NULL);
|
||||
filter_set_speed(filter, speed);
|
||||
|
||||
|
|
@ -297,7 +325,7 @@ main(int argc, char **argv)
|
|||
}
|
||||
|
||||
if (print_accel)
|
||||
print_accel_func(filter);
|
||||
print_accel_func(filter, profile);
|
||||
else if (print_delta)
|
||||
print_ptraccel_deltas(filter, step);
|
||||
else if (print_motion)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue