mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2025-12-20 04:30:06 +01:00
filter: split the low-dpi acceleration into a separate file
Plenty of duplication there from the normal filter.c, but that also makes it less likely to break if we adjust the other one. Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
This commit is contained in:
parent
f61adfcf9b
commit
6135e1d878
3 changed files with 254 additions and 85 deletions
|
|
@ -152,6 +152,7 @@ dep_libinput_util = declare_dependency(link_with : libinput_util)
|
|||
src_libfilter = [
|
||||
'src/filter.c',
|
||||
'src/filter-flat.c',
|
||||
'src/filter-low-dpi.c',
|
||||
'src/filter-touchpad.c',
|
||||
'src/filter-touchpad-x230.c',
|
||||
'src/filter-tablet.c',
|
||||
|
|
|
|||
253
src/filter-low-dpi.c
Normal file
253
src/filter-low-dpi.c
Normal file
|
|
@ -0,0 +1,253 @@
|
|||
/*
|
||||
* Copyright © 2006-2009 Simon Thum
|
||||
* Copyright © 2012 Jonas Ådahl
|
||||
* Copyright © 2014-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 "config.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <limits.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "filter.h"
|
||||
#include "libinput-util.h"
|
||||
#include "filter-private.h"
|
||||
|
||||
/*
|
||||
* Default parameters for pointer acceleration profiles.
|
||||
*/
|
||||
|
||||
#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 */
|
||||
|
||||
#define NUM_POINTER_TRACKERS 16
|
||||
/**
|
||||
* 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 (units/us) */
|
||||
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/us */
|
||||
const double incline = accel_filter->incline;
|
||||
double dpi_factor = accel_filter->dpi/(double)DEFAULT_MOUSE_DPI;
|
||||
double factor; /* unitless */
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
static inline double
|
||||
calculate_acceleration_factor(struct pointer_accelerator *accel,
|
||||
const struct device_float_coords *unaccelerated,
|
||||
void *data,
|
||||
uint64_t time)
|
||||
{
|
||||
double velocity; /* units/us in device-native dpi*/
|
||||
double accel_factor;
|
||||
|
||||
feed_trackers(&accel->trackers, unaccelerated, time);
|
||||
velocity = calculate_velocity(&accel->trackers, time);
|
||||
accel_factor = calculate_acceleration_simpsons(&accel->base,
|
||||
accel->profile,
|
||||
data,
|
||||
velocity,
|
||||
accel->last_velocity,
|
||||
time);
|
||||
accel->last_velocity = velocity;
|
||||
|
||||
return accel_factor;
|
||||
}
|
||||
|
||||
static struct device_float_coords
|
||||
accelerator_filter_generic(struct motion_filter *filter,
|
||||
const struct device_float_coords *unaccelerated,
|
||||
void *data, uint64_t time)
|
||||
{
|
||||
struct pointer_accelerator *accel =
|
||||
(struct pointer_accelerator *) filter;
|
||||
double accel_value; /* unitless factor */
|
||||
struct device_float_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_unnormalized(struct motion_filter *filter,
|
||||
const struct device_float_coords *unaccelerated,
|
||||
void *data, uint64_t time)
|
||||
{
|
||||
struct device_float_coords accelerated;
|
||||
struct normalized_coords normalized;
|
||||
|
||||
/* Accelerate for device units and return device units */
|
||||
accelerated = accelerator_filter_generic(filter,
|
||||
unaccelerated,
|
||||
data,
|
||||
time);
|
||||
normalized.x = accelerated.x;
|
||||
normalized.y = accelerated.y;
|
||||
return normalized;
|
||||
}
|
||||
|
||||
static struct normalized_coords
|
||||
accelerator_filter_noop(struct motion_filter *filter,
|
||||
const struct device_float_coords *unaccelerated,
|
||||
void *data, uint64_t time)
|
||||
{
|
||||
struct pointer_accelerator *accel =
|
||||
(struct pointer_accelerator *) filter;
|
||||
|
||||
return normalize_for_dpi(unaccelerated, accel->dpi);
|
||||
}
|
||||
|
||||
static void
|
||||
accelerator_restart(struct motion_filter *filter,
|
||||
void *data,
|
||||
uint64_t time)
|
||||
{
|
||||
struct pointer_accelerator *accel =
|
||||
(struct pointer_accelerator *) filter;
|
||||
|
||||
reset_trackers(&accel->trackers, time);
|
||||
}
|
||||
|
||||
static void
|
||||
accelerator_destroy(struct motion_filter *filter)
|
||||
{
|
||||
struct pointer_accelerator *accel =
|
||||
(struct pointer_accelerator *) filter;
|
||||
|
||||
free_trackers(&accel->trackers);
|
||||
free(accel);
|
||||
}
|
||||
|
||||
static bool
|
||||
accelerator_set_speed(struct motion_filter *filter,
|
||||
double speed_adjustment)
|
||||
{
|
||||
struct pointer_accelerator *accel_filter =
|
||||
(struct pointer_accelerator *)filter;
|
||||
|
||||
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 -
|
||||
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_adjustment * 1.5;
|
||||
|
||||
/* higher speed -> faster to reach max */
|
||||
accel_filter->incline = DEFAULT_INCLINE + speed_adjustment * 0.75;
|
||||
|
||||
filter->speed_adjustment = speed_adjustment;
|
||||
return true;
|
||||
}
|
||||
|
||||
struct motion_filter_interface accelerator_interface_low_dpi = {
|
||||
.type = LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE,
|
||||
.filter = accelerator_filter_unnormalized,
|
||||
.filter_constant = accelerator_filter_noop,
|
||||
.restart = accelerator_restart,
|
||||
.destroy = accelerator_destroy,
|
||||
.set_speed = accelerator_set_speed,
|
||||
};
|
||||
|
||||
static struct pointer_accelerator *
|
||||
create_default_filter(int dpi)
|
||||
{
|
||||
struct pointer_accelerator *filter;
|
||||
|
||||
filter = zalloc(sizeof *filter);
|
||||
filter->last_velocity = 0.0;
|
||||
|
||||
init_trackers(&filter->trackers, NUM_POINTER_TRACKERS);
|
||||
|
||||
filter->threshold = DEFAULT_THRESHOLD;
|
||||
filter->accel = DEFAULT_ACCELERATION;
|
||||
filter->incline = DEFAULT_INCLINE;
|
||||
filter->dpi = dpi;
|
||||
|
||||
return filter;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
85
src/filter.c
85
src/filter.c
|
|
@ -401,24 +401,6 @@ accelerator_filter_pre_normalized(struct motion_filter *filter,
|
|||
return normalized;
|
||||
}
|
||||
|
||||
static struct normalized_coords
|
||||
accelerator_filter_unnormalized(struct motion_filter *filter,
|
||||
const struct device_float_coords *unaccelerated,
|
||||
void *data, uint64_t time)
|
||||
{
|
||||
struct device_float_coords accelerated;
|
||||
struct normalized_coords normalized;
|
||||
|
||||
/* Accelerate for device units and return device units */
|
||||
accelerated = accelerator_filter_generic(filter,
|
||||
unaccelerated,
|
||||
data,
|
||||
time);
|
||||
normalized.x = accelerated.x;
|
||||
normalized.y = accelerated.y;
|
||||
return normalized;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic filter that does nothing beyond converting from the device's
|
||||
* native dpi into normalized coordinates.
|
||||
|
|
@ -491,49 +473,6 @@ accelerator_set_speed(struct motion_filter *filter,
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 (units/us) */
|
||||
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/us */
|
||||
const double incline = accel_filter->incline;
|
||||
double dpi_factor = accel_filter->dpi/(double)DEFAULT_MOUSE_DPI;
|
||||
double factor; /* unitless */
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
double
|
||||
pointer_accel_profile_linear(struct motion_filter *filter,
|
||||
void *data,
|
||||
|
|
@ -651,27 +590,3 @@ create_pointer_accelerator_filter_linear(int dpi)
|
|||
|
||||
return &filter->base;
|
||||
}
|
||||
|
||||
struct motion_filter_interface accelerator_interface_low_dpi = {
|
||||
.type = LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE,
|
||||
.filter = accelerator_filter_unnormalized,
|
||||
.filter_constant = accelerator_filter_noop,
|
||||
.restart = accelerator_restart,
|
||||
.destroy = accelerator_destroy,
|
||||
.set_speed = 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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue