1 /*
2 * Copyright © 2016 Red Hat, Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 */
23
24 #include <config.h>
25
26 #include <check.h>
27 #include <errno.h>
28 #include <fcntl.h>
29 #include <libinput.h>
30 #include <unistd.h>
31
32 #include "libinput-util.h"
33 #include "litest.h"
34
START_TEST(trackball_rotation_config_defaults)35 START_TEST(trackball_rotation_config_defaults)
36 {
37 struct litest_device *dev = litest_current_device();
38 struct libinput_device *device = dev->libinput_device;
39 int angle;
40
41 ck_assert(libinput_device_config_rotation_is_available(device));
42
43 angle = libinput_device_config_rotation_get_angle(device);
44 ck_assert_int_eq(angle, 0);
45 angle = libinput_device_config_rotation_get_default_angle(device);
46 ck_assert_int_eq(angle, 0);
47 }
48 END_TEST
49
START_TEST(trackball_rotation_config_invalid_range)50 START_TEST(trackball_rotation_config_invalid_range)
51 {
52 struct litest_device *dev = litest_current_device();
53 struct libinput_device *device = dev->libinput_device;
54 enum libinput_config_status status;
55
56 status = libinput_device_config_rotation_set_angle(device, 360);
57 ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_INVALID);
58 status = libinput_device_config_rotation_set_angle(device, 361);
59 ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_INVALID);
60 status = libinput_device_config_rotation_set_angle(device, -1);
61 ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_INVALID);
62 }
63 END_TEST
64
START_TEST(trackball_rotation_config_no_rotation)65 START_TEST(trackball_rotation_config_no_rotation)
66 {
67 struct litest_device *dev = litest_current_device();
68 struct libinput_device *device = dev->libinput_device;
69 enum libinput_config_status status;
70 int angle;
71
72 ck_assert(!libinput_device_config_rotation_is_available(device));
73
74 angle = libinput_device_config_rotation_get_angle(device);
75 ck_assert_int_eq(angle, 0);
76 angle = libinput_device_config_rotation_get_default_angle(device);
77 ck_assert_int_eq(angle, 0);
78
79 /* 0 always succeeds */
80 status = libinput_device_config_rotation_set_angle(device, 0);
81 ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
82
83 for (angle = 1; angle < 360; angle++) {
84 if (angle % 90 == 0)
85 continue;
86 status = libinput_device_config_rotation_set_angle(device,
87 angle);
88 ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_UNSUPPORTED);
89 }
90 }
91 END_TEST
92
START_TEST(trackball_rotation_config_right_angle)93 START_TEST(trackball_rotation_config_right_angle)
94 {
95 struct litest_device *dev = litest_current_device();
96 struct libinput_device *device = dev->libinput_device;
97 enum libinput_config_status status;
98 int angle;
99
100 ck_assert(libinput_device_config_rotation_is_available(device));
101
102 for (angle = 0; angle < 360; angle += 90) {
103 status = libinput_device_config_rotation_set_angle(device,
104 angle);
105 ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
106 }
107 }
108 END_TEST
109
START_TEST(trackball_rotation_config_odd_angle)110 START_TEST(trackball_rotation_config_odd_angle)
111 {
112 struct litest_device *dev = litest_current_device();
113 struct libinput_device *device = dev->libinput_device;
114 enum libinput_config_status status;
115 int angle;
116
117 ck_assert(libinput_device_config_rotation_is_available(device));
118
119 for (angle = 0; angle < 360; angle++) {
120 if (angle % 90 == 0)
121 continue;
122 status = libinput_device_config_rotation_set_angle(device,
123 angle);
124 ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_INVALID);
125 }
126 }
127 END_TEST
128
START_TEST(trackball_rotation_x)129 START_TEST(trackball_rotation_x)
130 {
131 struct litest_device *dev = litest_current_device();
132 struct libinput *li = dev->libinput;
133 struct libinput_device *device = dev->libinput_device;
134 struct libinput_event *event;
135 struct libinput_event_pointer *ptrev;
136 int angle;
137 double dx, dy;
138
139 litest_drain_events(li);
140
141 for (angle = 0; angle < 360; angle++) {
142 libinput_device_config_rotation_set_angle(device, angle);
143
144 litest_event(dev, EV_REL, REL_X, 1);
145 litest_event(dev, EV_SYN, SYN_REPORT, 0);
146 libinput_dispatch(li);
147
148 event = libinput_get_event(li);
149 ptrev = litest_is_motion_event(event);
150
151 /* Test unaccelerated because pointer accel may mangle the
152 other coords */
153 dx = libinput_event_pointer_get_dx_unaccelerated(ptrev);
154 dy = libinput_event_pointer_get_dy_unaccelerated(ptrev);
155
156 switch (angle) {
157 case 0:
158 ck_assert_double_eq(dx, 1.0);
159 ck_assert_double_eq(dy, 0.0);
160 break;
161 case 90:
162 ck_assert_double_eq(dx, 0.0);
163 ck_assert_double_eq(dy, 1.0);
164 break;
165 case 180:
166 ck_assert_double_eq(dx, -1.0);
167 ck_assert_double_eq(dy, 0.0);
168 break;
169 case 270:
170 ck_assert_double_eq(dx, 0.0);
171 ck_assert_double_eq(dy, -1.0);
172 break;
173 }
174 libinput_event_destroy(event);
175 }
176 }
177 END_TEST
178
START_TEST(trackball_rotation_y)179 START_TEST(trackball_rotation_y)
180 {
181 struct litest_device *dev = litest_current_device();
182 struct libinput *li = dev->libinput;
183 struct libinput_device *device = dev->libinput_device;
184 struct libinput_event *event;
185 struct libinput_event_pointer *ptrev;
186 int angle;
187 double dx, dy;
188
189 litest_drain_events(li);
190
191 for (angle = 0; angle < 360; angle++) {
192 libinput_device_config_rotation_set_angle(device, angle);
193
194 litest_event(dev, EV_REL, REL_Y, 1);
195 litest_event(dev, EV_SYN, SYN_REPORT, 0);
196 libinput_dispatch(li);
197
198 event = libinput_get_event(li);
199 ptrev = litest_is_motion_event(event);
200
201 /* Test unaccelerated because pointer accel may mangle the
202 other coords */
203 dx = libinput_event_pointer_get_dx_unaccelerated(ptrev);
204 dy = libinput_event_pointer_get_dy_unaccelerated(ptrev);
205
206 switch (angle) {
207 case 0:
208 ck_assert_double_eq(dx, 0.0);
209 ck_assert_double_eq(dy, 1.0);
210 break;
211 case 90:
212 ck_assert_double_eq(dx, -1.0);
213 ck_assert_double_eq(dy, 0.0);
214 break;
215 case 180:
216 ck_assert_double_eq(dx, 0.0);
217 ck_assert_double_eq(dy, -1.0);
218 break;
219 case 270:
220 ck_assert_double_eq(dx, 1.0);
221 ck_assert_double_eq(dy, 0.0);
222 break;
223 }
224 libinput_event_destroy(event);
225 }
226 }
227 END_TEST
228
START_TEST(trackball_rotation_accel)229 START_TEST(trackball_rotation_accel)
230 {
231 struct litest_device *dev = litest_current_device();
232 struct libinput *li = dev->libinput;
233 struct libinput_device *device = dev->libinput_device;
234 struct libinput_event *event;
235 struct libinput_event_pointer *ptrev;
236 double dx, dy;
237
238 litest_drain_events(li);
239
240 /* Pointer accel mangles the coordinates, so we only test one angle
241 * and rely on the unaccelerated tests above to warn us when
242 * something's off */
243 libinput_device_config_rotation_set_angle(device, 90);
244
245 litest_event(dev, EV_REL, REL_Y, 1);
246 litest_event(dev, EV_REL, REL_X, 1);
247 litest_event(dev, EV_SYN, SYN_REPORT, 0);
248 libinput_dispatch(li);
249
250 event = libinput_get_event(li);
251 ptrev = litest_is_motion_event(event);
252
253 dx = libinput_event_pointer_get_dx(ptrev);
254 dy = libinput_event_pointer_get_dy(ptrev);
255
256 ck_assert_double_lt(dx, 0.0);
257 ck_assert_double_gt(dy, 0.0);
258 libinput_event_destroy(event);
259 }
260 END_TEST
261
TEST_COLLECTION(trackball)262 TEST_COLLECTION(trackball)
263 {
264 litest_add(trackball_rotation_config_defaults, LITEST_TRACKBALL, LITEST_ANY);
265 litest_add(trackball_rotation_config_invalid_range, LITEST_TRACKBALL, LITEST_ANY);
266 litest_add(trackball_rotation_config_no_rotation, LITEST_ANY, LITEST_TRACKBALL);
267 litest_add(trackball_rotation_config_right_angle, LITEST_TRACKBALL, LITEST_ANY);
268 litest_add(trackball_rotation_config_odd_angle, LITEST_TRACKBALL, LITEST_ANY);
269 litest_add(trackball_rotation_x, LITEST_TRACKBALL, LITEST_ANY);
270 litest_add(trackball_rotation_y, LITEST_TRACKBALL, LITEST_ANY);
271 litest_add(trackball_rotation_accel, LITEST_TRACKBALL, LITEST_ANY);
272 }
273