Change calibration into a configuration option
[platform/upstream/libinput.git] / test / touch.c
1 /*
2  * Copyright © 2013 Red Hat, Inc.
3  *
4  * Permission to use, copy, modify, distribute, and sell this software and
5  * its documentation for any purpose is hereby granted without fee, provided
6  * that the above copyright notice appear in all copies and that both that
7  * copyright notice and this permission notice appear in supporting
8  * documentation, and that the name of the copyright holders not be used in
9  * advertising or publicity pertaining to distribution of the software
10  * without specific, written prior permission.  The copyright holders make
11  * no representations about the suitability of this software for any
12  * purpose.  It is provided "as is" without express or implied warranty.
13  *
14  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
15  * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
16  * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
17  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
18  * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
19  * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
20  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21  */
22
23 #include <config.h>
24
25 #include <check.h>
26 #include <errno.h>
27 #include <fcntl.h>
28 #include <libinput.h>
29 #include <libevdev/libevdev.h>
30 #include <unistd.h>
31
32 #include "libinput-util.h"
33 #include "litest.h"
34
35 START_TEST(touch_frame_events)
36 {
37         struct litest_device *dev = litest_current_device();
38         struct libinput *li = dev->libinput;
39         struct libinput_event *event;
40         int have_frame_event = 0;
41
42         litest_drain_events(dev->libinput);
43
44         litest_touch_down(dev, 0, 10, 10);
45         libinput_dispatch(li);
46
47         while ((event = libinput_get_event(li))) {
48                 if (libinput_event_get_type(event) == LIBINPUT_EVENT_TOUCH_FRAME)
49                         have_frame_event++;
50                 libinput_event_destroy(event);
51         }
52         ck_assert_int_eq(have_frame_event, 1);
53
54         litest_touch_down(dev, 1, 10, 10);
55         libinput_dispatch(li);
56
57         while ((event = libinput_get_event(li))) {
58                 if (libinput_event_get_type(event) == LIBINPUT_EVENT_TOUCH_FRAME)
59                         have_frame_event++;
60                 libinput_event_destroy(event);
61         }
62         ck_assert_int_eq(have_frame_event, 2);
63 }
64 END_TEST
65
66 START_TEST(touch_abs_transform)
67 {
68         struct litest_device *dev;
69         struct libinput *libinput;
70         struct libinput_event *ev;
71         struct libinput_event_touch *tev;
72         double fx, fy;
73         bool tested = false;
74
75         struct input_absinfo abs[] = {
76                 { ABS_X, 0, 32767, 75, 0, 10 },
77                 { ABS_Y, 0, 32767, 129, 0, 9 },
78                 { ABS_MT_POSITION_X, 0, 32767, 0, 0, 10 },
79                 { ABS_MT_POSITION_Y, 0, 32767, 0, 0, 9 },
80                 { .value = -1 },
81         };
82
83         dev = litest_create_device_with_overrides(LITEST_WACOM_TOUCH,
84                                                   "litest Highres touch device",
85                                                   NULL, abs, NULL);
86
87         libinput = dev->libinput;
88
89         litest_touch_down(dev, 0, 100, 100);
90
91         libinput_dispatch(libinput);
92
93         while ((ev = libinput_get_event(libinput))) {
94                 if (libinput_event_get_type(ev) != LIBINPUT_EVENT_TOUCH_DOWN) {
95                         libinput_event_destroy(ev);
96                         continue;
97                 }
98
99                 tev = libinput_event_get_touch_event(ev);
100                 fx = libinput_event_touch_get_x_transformed(tev, 1920);
101                 ck_assert_int_eq(fx, 1919.0);
102                 fy = libinput_event_touch_get_y_transformed(tev, 720);
103                 ck_assert_int_eq(fy, 719.0);
104
105                 tested = true;
106
107                 libinput_event_destroy(ev);
108         }
109
110         ck_assert(tested);
111
112         litest_delete_device(dev);
113 }
114 END_TEST
115
116 START_TEST(touch_many_slots)
117 {
118         struct libinput *libinput;
119         struct litest_device *dev;
120         struct libinput_event *ev;
121         int slot;
122         const int num_tps = 100;
123         int slot_count = 0;
124         enum libinput_event_type type;
125
126         struct input_absinfo abs[] = {
127                 { ABS_MT_SLOT, 0, num_tps - 1, 0, 0, 0 },
128                 { .value = -1 },
129         };
130
131         dev = litest_create_device_with_overrides(LITEST_WACOM_TOUCH,
132                                                   "litest Multi-touch device",
133                                                   NULL, abs, NULL);
134         libinput = dev->libinput;
135
136         for (slot = 0; slot < num_tps; ++slot)
137                 litest_touch_down(dev, slot, 0, 0);
138         for (slot = 0; slot < num_tps; ++slot)
139                 litest_touch_up(dev, slot);
140
141         libinput_dispatch(libinput);
142         while ((ev = libinput_get_event(libinput))) {
143                 type = libinput_event_get_type(ev);
144
145                 if (type == LIBINPUT_EVENT_TOUCH_DOWN)
146                         slot_count++;
147                 else if (type == LIBINPUT_EVENT_TOUCH_UP)
148                         break;
149
150                 libinput_event_destroy(ev);
151                 libinput_dispatch(libinput);
152         }
153
154         ck_assert_notnull(ev);
155         ck_assert_int_gt(slot_count, 0);
156
157         libinput_dispatch(libinput);
158         do {
159                 type = libinput_event_get_type(ev);
160                 ck_assert_int_ne(type, LIBINPUT_EVENT_TOUCH_DOWN);
161                 if (type == LIBINPUT_EVENT_TOUCH_UP)
162                         slot_count--;
163
164                 libinput_event_destroy(ev);
165                 libinput_dispatch(libinput);
166         } while ((ev = libinput_get_event(libinput)));
167
168         ck_assert_int_eq(slot_count, 0);
169
170         litest_delete_device(dev);
171 }
172 END_TEST
173
174 START_TEST(touch_double_touch_down_up)
175 {
176         struct libinput *libinput;
177         struct litest_device *dev;
178         struct libinput_event *ev;
179         bool got_down = false;
180         bool got_up = false;
181
182         dev = litest_current_device();
183         libinput = dev->libinput;
184
185         litest_touch_down(dev, 0, 0, 0);
186         litest_touch_down(dev, 0, 0, 0);
187         litest_touch_up(dev, 0);
188         litest_touch_up(dev, 0);
189
190         libinput_dispatch(libinput);
191
192         while ((ev = libinput_get_event(libinput))) {
193                 switch (libinput_event_get_type(ev)) {
194                 case LIBINPUT_EVENT_TOUCH_DOWN:
195                         ck_assert(!got_down);
196                         got_down = true;
197                         break;
198                 case LIBINPUT_EVENT_TOUCH_UP:
199                         ck_assert(got_down);
200                         ck_assert(!got_up);
201                         got_up = true;
202                         break;
203                 default:
204                         break;
205                 }
206
207                 libinput_event_destroy(ev);
208                 libinput_dispatch(libinput);
209         }
210
211         ck_assert(got_down);
212         ck_assert(got_up);
213 }
214 END_TEST
215
216 START_TEST(touch_calibration_scale)
217 {
218         struct libinput *li;
219         struct litest_device *dev;
220         struct libinput_event *ev;
221         struct libinput_event_touch *tev;
222         float matrix[6] = {
223                 1, 0, 0,
224                 0, 1, 0
225         };
226
227         float calibration;
228         double x, y;
229         const int width = 640, height = 480;
230
231         dev = litest_current_device();
232         li = dev->libinput;
233
234         for (calibration = 0.1; calibration < 1; calibration += 0.1) {
235                 libinput_device_config_calibration_set_matrix(dev->libinput_device,
236                                                               matrix);
237                 litest_drain_events(li);
238
239                 litest_touch_down(dev, 0, 100, 100);
240                 litest_touch_up(dev, 0);
241
242                 litest_wait_for_event(li);
243                 ev = libinput_get_event(li);
244                 ck_assert_int_eq(libinput_event_get_type(ev),
245                                  LIBINPUT_EVENT_TOUCH_DOWN);
246                 tev = libinput_event_get_touch_event(ev);
247
248                 x = libinput_event_touch_get_x_transformed(tev, width);
249                 y = libinput_event_touch_get_y_transformed(tev, height);
250
251                 ck_assert_int_eq(round(x), round(width * matrix[0]));
252                 ck_assert_int_eq(round(y), round(height * matrix[4]));
253
254                 libinput_event_destroy(ev);
255                 litest_drain_events(li);
256
257                 matrix[0] = calibration;
258                 matrix[4] = 1 - calibration;
259         }
260 }
261 END_TEST
262
263 START_TEST(touch_calibration_rotation)
264 {
265         struct libinput *li;
266         struct litest_device *dev;
267         struct libinput_event *ev;
268         struct libinput_event_touch *tev;
269         float matrix[6];
270         int i;
271         double x, y;
272         int width = 1024, height = 480;
273
274         dev = litest_current_device();
275         li = dev->libinput;
276
277         for (i = 0; i < 4; i++) {
278                 float angle = i * M_PI/2;
279
280                 /* [ cos -sin  tx ]
281                    [ sin  cos  ty ]
282                    [  0    0   1  ] */
283                 matrix[0] = cos(angle);
284                 matrix[1] = -sin(angle);
285                 matrix[3] = sin(angle);
286                 matrix[4] = cos(angle);
287
288                 switch(i) {
289                 case 0: /* 0 deg */
290                         matrix[2] = 0;
291                         matrix[5] = 0;
292                         break;
293                 case 1: /* 90 deg cw */
294                         matrix[2] = 1;
295                         matrix[5] = 0;
296                         break;
297                 case 2: /* 180 deg cw */
298                         matrix[2] = 1;
299                         matrix[5] = 1;
300                         break;
301                 case 3: /* 270 deg cw */
302                         matrix[2] = 0;
303                         matrix[5] = 1;
304                         break;
305                 }
306
307                 libinput_device_config_calibration_set_matrix(dev->libinput_device,
308                                                               matrix);
309                 litest_drain_events(li);
310
311                 litest_touch_down(dev, 0, 80, 20);
312                 litest_touch_up(dev, 0);
313                 litest_wait_for_event(li);
314                 ev = libinput_get_event(li);
315                 ck_assert_int_eq(libinput_event_get_type(ev),
316                                  LIBINPUT_EVENT_TOUCH_DOWN);
317                 tev = libinput_event_get_touch_event(ev);
318
319                 x = libinput_event_touch_get_x_transformed(tev, width);
320                 y = libinput_event_touch_get_y_transformed(tev, height);
321
322                 /* rounding errors... */
323 #define almost_equal(a_, b_) \
324                 { ck_assert_int_ge((a_) + 0.5, (b_) - 1); \
325                   ck_assert_int_le((a_) + 0.5, (b_) + 1); }
326                 switch(i) {
327                 case 0: /* 0 deg */
328                         almost_equal(x, width * 0.8);
329                         almost_equal(y, height * 0.2);
330                         break;
331                 case 1: /* 90 deg cw */
332                         almost_equal(x, width * 0.8);
333                         almost_equal(y, height * 0.8);
334                         break;
335                 case 2: /* 180 deg cw */
336                         almost_equal(x, width * 0.2);
337                         almost_equal(y, height * 0.8);
338                         break;
339                 case 3: /* 270 deg cw */
340                         almost_equal(x, width * 0.2);
341                         almost_equal(y, height * 0.2);
342                         break;
343                 }
344 #undef almost_equal
345
346
347                 libinput_event_destroy(ev);
348                 litest_drain_events(li);
349         }
350 }
351 END_TEST
352
353 START_TEST(touch_calibration_translation)
354 {
355         struct libinput *li;
356         struct litest_device *dev;
357         struct libinput_event *ev;
358         struct libinput_event_touch *tev;
359         float matrix[6] = {
360                 1, 0, 0,
361                 0, 1, 0
362         };
363
364         float translate;
365         double x, y;
366         const int width = 640, height = 480;
367
368         dev = litest_current_device();
369         li = dev->libinput;
370
371         /* translating from 0 up to 1 device width/height */
372         for (translate = 0.1; translate <= 1; translate += 0.1) {
373                 libinput_device_config_calibration_set_matrix(dev->libinput_device,
374                                                               matrix);
375                 litest_drain_events(li);
376
377                 litest_touch_down(dev, 0, 100, 100);
378                 litest_touch_up(dev, 0);
379
380                 litest_wait_for_event(li);
381                 ev = libinput_get_event(li);
382                 ck_assert_int_eq(libinput_event_get_type(ev),
383                                  LIBINPUT_EVENT_TOUCH_DOWN);
384                 tev = libinput_event_get_touch_event(ev);
385
386                 x = libinput_event_touch_get_x_transformed(tev, width);
387                 y = libinput_event_touch_get_y_transformed(tev, height);
388
389                 /* sigh. rounding errors */
390                 ck_assert_int_ge(round(x), width + round(width * matrix[2]) - 1);
391                 ck_assert_int_ge(round(y), height + round(height * matrix[5]) - 1);
392                 ck_assert_int_le(round(x), width + round(width * matrix[2]) + 1);
393                 ck_assert_int_le(round(y), height + round(height * matrix[5]) + 1);
394
395                 libinput_event_destroy(ev);
396                 litest_drain_events(li);
397
398                 matrix[2] = translate;
399                 matrix[5] = 1 - translate;
400         }
401 }
402 END_TEST
403
404 int
405 main(int argc, char **argv)
406 {
407         litest_add("touch:frame", touch_frame_events, LITEST_TOUCH, LITEST_ANY);
408         litest_add_no_device("touch:abs-transform", touch_abs_transform);
409         litest_add_no_device("touch:many-slots", touch_many_slots);
410         litest_add("touch:double-touch-down-up", touch_double_touch_down_up, LITEST_TOUCH, LITEST_ANY);
411         litest_add("touch:calibration", touch_calibration_scale, LITEST_TOUCH, LITEST_TOUCHPAD);
412         litest_add("touch:calibration", touch_calibration_scale, LITEST_SINGLE_TOUCH, LITEST_TOUCHPAD);
413         litest_add("touch:calibration", touch_calibration_rotation, LITEST_TOUCH, LITEST_TOUCHPAD);
414         litest_add("touch:calibration", touch_calibration_rotation, LITEST_SINGLE_TOUCH, LITEST_TOUCHPAD);
415         litest_add("touch:calibration", touch_calibration_translation, LITEST_TOUCH, LITEST_TOUCHPAD);
416         litest_add("touch:calibration", touch_calibration_translation, LITEST_SINGLE_TOUCH, LITEST_TOUCHPAD);
417
418         return litest_run(argc, argv);
419 }