1 /*
2 * Copyright © 2006-2009 Simon Thum
3 * Copyright © 2012 Jonas Ådahl
4 * Copyright © 2014-2015 Red Hat, Inc.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the next
14 * paragraph) shall be included in all copies or substantial portions of the
15 * Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 * DEALINGS IN THE SOFTWARE.
24 */
25
26 #include "config.h"
27
28 #include <assert.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <stdint.h>
32
33 #include "filter.h"
34 #include "libinput-util.h"
35 #include "filter-private.h"
36
37 #define TP_MAGIC_SLOWDOWN_FLAT 0.2968
38
39 struct touchpad_accelerator_flat {
40 struct motion_filter base;
41
42 double factor;
43 int dpi;
44 };
45
46 static struct normalized_coords
accelerator_filter_touchpad_flat(struct motion_filter * filter,const struct device_float_coords * unaccelerated,void * data,uint64_t time)47 accelerator_filter_touchpad_flat(struct motion_filter *filter,
48 const struct device_float_coords *unaccelerated,
49 void *data, uint64_t time)
50 {
51 struct touchpad_accelerator_flat *accel =
52 (struct touchpad_accelerator_flat *)filter;
53 double factor; /* unitless factor */
54 struct normalized_coords normalized;
55
56 /* You want flat acceleration, you get flat acceleration for the
57 * device */
58 factor = accel->factor;
59 normalized = normalize_for_dpi(unaccelerated, accel->dpi);
60 normalized.x = TP_MAGIC_SLOWDOWN_FLAT * factor * normalized.x;
61 normalized.y = TP_MAGIC_SLOWDOWN_FLAT * factor * normalized.y;
62
63 return normalized;
64 }
65
66 static struct normalized_coords
accelerator_filter_noop_touchpad_flat(struct motion_filter * filter,const struct device_float_coords * unaccelerated,void * data,uint64_t time)67 accelerator_filter_noop_touchpad_flat(struct motion_filter *filter,
68 const struct device_float_coords *unaccelerated,
69 void *data, uint64_t time)
70 {
71 /* We map the unaccelerated flat filter to have the same behavior as
72 * the "accelerated" flat filter.
73 * The filter by definition is flat, i.e. it does not actually
74 * apply any acceleration (merely a constant factor) and we can assume
75 * that a user wants all mouse movement to have the same speed, mapped
76 * 1:1 to the input speed.
77 *
78 * Thus we apply the same factor to our non-accelerated motion - this way
79 * things like gestures end up having the same movement as
80 * pointer motion.
81 */
82 return accelerator_filter_touchpad_flat(filter, unaccelerated, data, time);
83 }
84
85 static bool
accelerator_set_speed_touchpad_flat(struct motion_filter * filter,double speed_adjustment)86 accelerator_set_speed_touchpad_flat(struct motion_filter *filter,
87 double speed_adjustment)
88 {
89 struct touchpad_accelerator_flat *accel_filter =
90 (struct touchpad_accelerator_flat *)filter;
91
92 assert(speed_adjustment >= -1.0 && speed_adjustment <= 1.0);
93
94 accel_filter->factor = max(0.005, 1 + speed_adjustment);
95 filter->speed_adjustment = speed_adjustment;
96
97 return true;
98 }
99
100 static void
accelerator_destroy_touchpad_flat(struct motion_filter * filter)101 accelerator_destroy_touchpad_flat(struct motion_filter *filter)
102 {
103 struct touchpad_accelerator_flat *accel =
104 (struct touchpad_accelerator_flat *) filter;
105
106 free(accel);
107 }
108
109 static const struct motion_filter_interface accelerator_interface_touchpad_flat = {
110 .type = LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT,
111 .filter = accelerator_filter_touchpad_flat,
112 .filter_constant = accelerator_filter_noop_touchpad_flat,
113 .filter_scroll = accelerator_filter_noop_touchpad_flat,
114 .restart = NULL,
115 .destroy = accelerator_destroy_touchpad_flat,
116 .set_speed = accelerator_set_speed_touchpad_flat,
117 };
118
119 struct motion_filter *
create_pointer_accelerator_filter_touchpad_flat(int dpi)120 create_pointer_accelerator_filter_touchpad_flat(int dpi)
121 {
122 struct touchpad_accelerator_flat *filter;
123
124 filter = zalloc(sizeof *filter);
125 filter->base.interface = &accelerator_interface_touchpad_flat;
126 filter->dpi = dpi;
127
128 return &filter->base;
129 }
130