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