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 struct pointer_accelerator_flat {
38 	struct motion_filter base;
39 
40 	double factor;
41 	int dpi;
42 };
43 
44 static struct normalized_coords
accelerator_filter_flat(struct motion_filter *filter, const struct device_float_coords *unaccelerated, void *data, uint64_t time)45 accelerator_filter_flat(struct motion_filter *filter,
46 			const struct device_float_coords *unaccelerated,
47 			void *data, uint64_t time)
48 {
49 	struct pointer_accelerator_flat *accel_filter =
50 		(struct pointer_accelerator_flat *)filter;
51 	double factor; /* unitless factor */
52 	struct normalized_coords accelerated;
53 
54 	/* You want flat acceleration, you get flat acceleration for the
55 	 * device */
56 	factor = accel_filter->factor;
57 	accelerated.x = factor * unaccelerated->x;
58 	accelerated.y = factor * unaccelerated->y;
59 
60 	return accelerated;
61 }
62 
63 static struct normalized_coords
accelerator_filter_noop_flat(struct motion_filter *filter, const struct device_float_coords *unaccelerated, void *data, uint64_t time)64 accelerator_filter_noop_flat(struct motion_filter *filter,
65 			     const struct device_float_coords *unaccelerated,
66 			     void *data, uint64_t time)
67 {
68 	/* We map the unaccelerated flat filter to have the same behavior as
69 	 * the "accelerated" flat filter.
70 	 * The filter by definition is flat, i.e. it does not actually
71 	 * apply any acceleration (merely a constant factor) and we can assume
72 	 * that a user wants all mouse movement to have the same speed, mapped
73 	 * 1:1 to the input speed.
74 	 *
75 	 * Thus we apply the same factor to our non-accelerated motion - this way
76 	 * things like button scrolling end up having the same movement as
77 	 * pointer motion.
78 	 */
79 	return accelerator_filter_flat(filter, unaccelerated, data, time);
80 }
81 
82 static bool
accelerator_set_speed_flat(struct motion_filter *filter, double speed_adjustment)83 accelerator_set_speed_flat(struct motion_filter *filter,
84 			   double speed_adjustment)
85 {
86 	struct pointer_accelerator_flat *accel_filter =
87 		(struct pointer_accelerator_flat *)filter;
88 
89 	assert(speed_adjustment >= -1.0 && speed_adjustment <= 1.0);
90 
91 	/* Speed range is 0-200% of the nominal speed, with 0 mapping to the
92 	 * nominal speed. Anything above 200 is pointless, we're already
93 	 * skipping over ever second pixel at 200% speed.
94 	 */
95 
96 	accel_filter->factor = max(0.005, 1 + speed_adjustment);
97 	filter->speed_adjustment = speed_adjustment;
98 
99 	return true;
100 }
101 
102 static void
accelerator_destroy_flat(struct motion_filter *filter)103 accelerator_destroy_flat(struct motion_filter *filter)
104 {
105 	struct pointer_accelerator_flat *accel =
106 		(struct pointer_accelerator_flat *) filter;
107 
108 	free(accel);
109 }
110 
111 static const struct motion_filter_interface accelerator_interface_flat = {
112 	.type = LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT,
113 	.filter = accelerator_filter_flat,
114 	.filter_constant = accelerator_filter_noop_flat,
115 	.filter_scroll = accelerator_filter_noop_flat,
116 	.restart = NULL,
117 	.destroy = accelerator_destroy_flat,
118 	.set_speed = accelerator_set_speed_flat,
119 };
120 
121 struct motion_filter *
create_pointer_accelerator_filter_flat(int dpi)122 create_pointer_accelerator_filter_flat(int dpi)
123 {
124 	struct pointer_accelerator_flat *filter;
125 
126 	filter = zalloc(sizeof *filter);
127 	filter->base.interface = &accelerator_interface_flat;
128 	filter->dpi = dpi;
129 
130 	return &filter->base;
131 }
132