| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| #include "config.h" |
| |
| #include <assert.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <stdint.h> |
| |
| #include "filter.h" |
| #include "libinput-util.h" |
| #include "filter-private.h" |
| |
| |
| |
| |
| |
| #define DEFAULT_THRESHOLD v_ms2us(0.4) |
| #define MINIMUM_THRESHOLD v_ms2us(0.2) |
| #define DEFAULT_ACCELERATION 2.0 |
| #define DEFAULT_INCLINE 1.1 |
| |
| struct pointer_accelerator_low_dpi { |
| struct motion_filter base; |
| |
| accel_profile_func_t profile; |
| |
| double velocity; |
| double last_velocity; |
| |
| struct pointer_trackers trackers; |
| |
| double threshold; |
| double accel; |
| double incline; |
| |
| int dpi; |
| }; |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| double |
| pointer_accel_profile_linear_low_dpi(struct motion_filter *filter, |
| void *data, |
| double speed_in, |
| uint64_t time) |
| { |
| struct pointer_accelerator_low_dpi *accel_filter = |
| (struct pointer_accelerator_low_dpi *)filter; |
| |
| double max_accel = accel_filter->accel; |
| double threshold = accel_filter->threshold; |
| const double incline = accel_filter->incline; |
| double dpi_factor = accel_filter->dpi/(double)DEFAULT_MOUSE_DPI; |
| double factor; |
| |
| |
| |
| max_accel /= dpi_factor; |
| threshold *= dpi_factor; |
| |
| |
| 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_low_dpi *accel, |
| const struct device_float_coords *unaccelerated, |
| void *data, |
| uint64_t time) |
| { |
| double velocity; |
| double accel_factor; |
| |
| trackers_feed(&accel->trackers, unaccelerated, time); |
| velocity = trackers_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_low_dpi *accel = |
| (struct pointer_accelerator_low_dpi *) filter; |
| double accel_value; |
| 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; |
| |
| |
| 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_low_dpi *accel = |
| (struct pointer_accelerator_low_dpi *) filter; |
| |
| return normalize_for_dpi(unaccelerated, accel->dpi); |
| } |
| |
| static void |
| accelerator_restart(struct motion_filter *filter, |
| void *data, |
| uint64_t time) |
| { |
| struct pointer_accelerator_low_dpi *accel = |
| (struct pointer_accelerator_low_dpi *) filter; |
| |
| trackers_reset(&accel->trackers, time); |
| } |
| |
| static void |
| accelerator_destroy(struct motion_filter *filter) |
| { |
| struct pointer_accelerator_low_dpi *accel = |
| (struct pointer_accelerator_low_dpi *) filter; |
| |
| trackers_free(&accel->trackers); |
| free(accel); |
| } |
| |
| static bool |
| accelerator_set_speed(struct motion_filter *filter, |
| double speed_adjustment) |
| { |
| struct pointer_accelerator_low_dpi *accel_filter = |
| (struct pointer_accelerator_low_dpi *)filter; |
| |
| assert(speed_adjustment >= -1.0 && speed_adjustment <= 1.0); |
| |
| |
| |
| |
| |
| accel_filter->threshold = DEFAULT_THRESHOLD - |
| v_ms2us(0.25) * speed_adjustment; |
| if (accel_filter->threshold < MINIMUM_THRESHOLD) |
| accel_filter->threshold = MINIMUM_THRESHOLD; |
| |
| |
| accel_filter->accel = DEFAULT_ACCELERATION + speed_adjustment * 1.5; |
| |
| |
| 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_low_dpi * |
| create_default_filter(int dpi, bool use_velocity_averaging) |
| { |
| struct pointer_accelerator_low_dpi *filter; |
| |
| filter = zalloc(sizeof *filter); |
| filter->last_velocity = 0.0; |
| |
| trackers_init(&filter->trackers, use_velocity_averaging ? 16 : 2); |
| |
| 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, bool use_velocity_averaging) |
| { |
| struct pointer_accelerator_low_dpi *filter; |
| |
| filter = create_default_filter(dpi, use_velocity_averaging); |
| if (!filter) |
| return NULL; |
| |
| filter->base.interface = &accelerator_interface_low_dpi; |
| filter->profile = pointer_accel_profile_linear_low_dpi; |
| |
| return &filter->base; |
| } |