tests: add test_seat_release() for symmetry
[platform/upstream/weston.git] / tests / pointer-test.c
1 /*
2  * Copyright © 2012 Intel Corporation
3  * Copyright © 2013 Collabora, Ltd.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining
6  * a copy of this software and associated documentation files (the
7  * "Software"), to deal in the Software without restriction, including
8  * without limitation the rights to use, copy, modify, merge, publish,
9  * distribute, sublicense, and/or sell copies of the Software, and to
10  * permit persons to whom the Software is furnished to do so, subject to
11  * the following conditions:
12  *
13  * The above copyright notice and this permission notice (including the
14  * next paragraph) shall be included in all copies or substantial
15  * portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20  * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
21  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
22  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24  * SOFTWARE.
25  */
26
27 #include "config.h"
28
29 #include <linux/input.h>
30
31 #include "input-timestamps-helper.h"
32 #include "shared/timespec-util.h"
33 #include "weston-test-client-helper.h"
34
35 static const struct timespec t0 = { .tv_sec = 0, .tv_nsec = 100000000 };
36 static const struct timespec t1 = { .tv_sec = 1, .tv_nsec = 1000001 };
37 static const struct timespec t2 = { .tv_sec = 2, .tv_nsec = 2000001 };
38 static const struct timespec t_other = { .tv_sec = 123, .tv_nsec = 456 };
39
40 static void
41 send_motion(struct client *client, const struct timespec *time, int x, int y)
42 {
43         uint32_t tv_sec_hi, tv_sec_lo, tv_nsec;
44
45         timespec_to_proto(time, &tv_sec_hi, &tv_sec_lo, &tv_nsec);
46         weston_test_move_pointer(client->test->weston_test, tv_sec_hi, tv_sec_lo,
47                                  tv_nsec, x, y);
48         client_roundtrip(client);
49 }
50
51 static void
52 send_button(struct client *client, const struct timespec *time,
53             uint32_t button, uint32_t state)
54 {
55         uint32_t tv_sec_hi, tv_sec_lo, tv_nsec;
56
57         timespec_to_proto(time, &tv_sec_hi, &tv_sec_lo, &tv_nsec);
58         weston_test_send_button(client->test->weston_test, tv_sec_hi, tv_sec_lo,
59                                 tv_nsec, button, state);
60         client_roundtrip(client);
61 }
62
63 static void
64 send_axis(struct client *client, const struct timespec *time, uint32_t axis,
65           double value)
66 {
67         uint32_t tv_sec_hi, tv_sec_lo, tv_nsec;
68
69         timespec_to_proto(time, &tv_sec_hi, &tv_sec_lo, &tv_nsec);
70         weston_test_send_axis(client->test->weston_test, tv_sec_hi, tv_sec_lo,
71                               tv_nsec, axis, wl_fixed_from_double(value));
72         client_roundtrip(client);
73 }
74
75 static void
76 check_pointer(struct client *client, int x, int y)
77 {
78         int sx, sy;
79
80         /* check that the client got the global pointer update */
81         assert(client->test->pointer_x == x);
82         assert(client->test->pointer_y == y);
83
84         /* Does global pointer map onto the surface? */
85         if (surface_contains(client->surface, x, y)) {
86                 /* check that the surface has the pointer focus */
87                 assert(client->input->pointer->focus == client->surface);
88
89                 /*
90                  * check that the local surface pointer maps
91                  * to the global pointer.
92                  */
93                 sx = client->input->pointer->x + client->surface->x;
94                 sy = client->input->pointer->y + client->surface->y;
95                 assert(sx == x);
96                 assert(sy == y);
97         } else {
98                 /*
99                  * The global pointer does not map onto surface.  So
100                  * check that it doesn't have the pointer focus.
101                  */
102                 assert(client->input->pointer->focus == NULL);
103         }
104 }
105
106 static void
107 check_pointer_move(struct client *client, int x, int y)
108 {
109         send_motion(client, &t0, x, y);
110         check_pointer(client, x, y);
111 }
112
113 static struct client *
114 create_client_with_pointer_focus(int x, int y, int w, int h)
115 {
116         struct client *cl = create_client_and_test_surface(x, y, w, h);
117         assert(cl);
118         /* Move the pointer inside the surface to ensure that the surface
119          * has the pointer focus. */
120         check_pointer_move(cl, x, y);
121         return cl;
122 }
123
124 TEST(test_pointer_top_left)
125 {
126         struct client *client;
127         int x, y;
128
129         client = create_client_and_test_surface(46, 76, 111, 134);
130         assert(client);
131
132         /* move pointer outside top left */
133         x = client->surface->x - 1;
134         y = client->surface->y - 1;
135         assert(!surface_contains(client->surface, x, y));
136         check_pointer_move(client, x, y);
137
138         /* move pointer on top left */
139         x += 1; y += 1;
140         assert(surface_contains(client->surface, x, y));
141         check_pointer_move(client, x, y);
142
143         /* move pointer outside top left */
144         x -= 1; y -= 1;
145         assert(!surface_contains(client->surface, x, y));
146         check_pointer_move(client, x, y);
147 }
148
149 TEST(test_pointer_bottom_left)
150 {
151         struct client *client;
152         int x, y;
153
154         client = create_client_and_test_surface(99, 100, 100, 98);
155         assert(client);
156
157         /* move pointer outside bottom left */
158         x = client->surface->x - 1;
159         y = client->surface->y + client->surface->height;
160         assert(!surface_contains(client->surface, x, y));
161         check_pointer_move(client, x, y);
162
163         /* move pointer on bottom left */
164         x += 1; y -= 1;
165         assert(surface_contains(client->surface, x, y));
166         check_pointer_move(client, x, y);
167
168         /* move pointer outside bottom left */
169         x -= 1; y += 1;
170         assert(!surface_contains(client->surface, x, y));
171         check_pointer_move(client, x, y);
172 }
173
174 TEST(test_pointer_top_right)
175 {
176         struct client *client;
177         int x, y;
178
179         client = create_client_and_test_surface(48, 100, 67, 100);
180         assert(client);
181
182         /* move pointer outside top right */
183         x = client->surface->x + client->surface->width;
184         y = client->surface->y - 1;
185         assert(!surface_contains(client->surface, x, y));
186         check_pointer_move(client, x, y);
187
188         /* move pointer on top right */
189         x -= 1; y += 1;
190         assert(surface_contains(client->surface, x, y));
191         check_pointer_move(client, x, y);
192
193         /* move pointer outside top right */
194         x += 1; y -= 1;
195         assert(!surface_contains(client->surface, x, y));
196         check_pointer_move(client, x, y);
197 }
198
199 TEST(test_pointer_bottom_right)
200 {
201         struct client *client;
202         int x, y;
203
204         client = create_client_and_test_surface(100, 123, 100, 69);
205         assert(client);
206
207         /* move pointer outside bottom right */
208         x = client->surface->x + client->surface->width;
209         y = client->surface->y + client->surface->height;
210         assert(!surface_contains(client->surface, x, y));
211         check_pointer_move(client, x, y);
212
213         /* move pointer on bottom right */
214         x -= 1; y -= 1;
215         assert(surface_contains(client->surface, x, y));
216         check_pointer_move(client, x, y);
217
218         /* move pointer outside bottom right */
219         x += 1; y += 1;
220         assert(!surface_contains(client->surface, x, y));
221         check_pointer_move(client, x, y);
222 }
223
224 TEST(test_pointer_top_center)
225 {
226         struct client *client;
227         int x, y;
228
229         client = create_client_and_test_surface(100, 201, 100, 50);
230         assert(client);
231
232         /* move pointer outside top center */
233         x = client->surface->x + client->surface->width/2;
234         y = client->surface->y - 1;
235         assert(!surface_contains(client->surface, x, y));
236         check_pointer_move(client, x, y);
237
238         /* move pointer on top center */
239         y += 1;
240         assert(surface_contains(client->surface, x, y));
241         check_pointer_move(client, x, y);
242
243         /* move pointer outside top center */
244         y -= 1;
245         assert(!surface_contains(client->surface, x, y));
246         check_pointer_move(client, x, y);
247 }
248
249 TEST(test_pointer_bottom_center)
250 {
251         struct client *client;
252         int x, y;
253
254         client = create_client_and_test_surface(100, 45, 67, 100);
255         assert(client);
256
257         /* move pointer outside bottom center */
258         x = client->surface->x + client->surface->width/2;
259         y = client->surface->y + client->surface->height;
260         assert(!surface_contains(client->surface, x, y));
261         check_pointer_move(client, x, y);
262
263         /* move pointer on bottom center */
264         y -= 1;
265         assert(surface_contains(client->surface, x, y));
266         check_pointer_move(client, x, y);
267
268         /* move pointer outside bottom center */
269         y += 1;
270         assert(!surface_contains(client->surface, x, y));
271         check_pointer_move(client, x, y);
272 }
273
274 TEST(test_pointer_left_center)
275 {
276         struct client *client;
277         int x, y;
278
279         client = create_client_and_test_surface(167, 45, 78, 100);
280         assert(client);
281
282         /* move pointer outside left center */
283         x = client->surface->x - 1;
284         y = client->surface->y + client->surface->height/2;
285         assert(!surface_contains(client->surface, x, y));
286         check_pointer_move(client, x, y);
287
288         /* move pointer on left center */
289         x += 1;
290         assert(surface_contains(client->surface, x, y));
291         check_pointer_move(client, x, y);
292
293         /* move pointer outside left center */
294         x -= 1;
295         assert(!surface_contains(client->surface, x, y));
296         check_pointer_move(client, x, y);
297 }
298
299 TEST(test_pointer_right_center)
300 {
301         struct client *client;
302         int x, y;
303
304         client = create_client_and_test_surface(110, 37, 100, 46);
305         assert(client);
306
307         /* move pointer outside right center */
308         x = client->surface->x + client->surface->width;
309         y = client->surface->y + client->surface->height/2;
310         assert(!surface_contains(client->surface, x, y));
311         check_pointer_move(client, x, y);
312
313         /* move pointer on right center */
314         x -= 1;
315         assert(surface_contains(client->surface, x, y));
316         check_pointer_move(client, x, y);
317
318         /* move pointer outside right center */
319         x += 1;
320         assert(!surface_contains(client->surface, x, y));
321         check_pointer_move(client, x, y);
322 }
323
324 TEST(test_pointer_surface_move)
325 {
326         struct client *client;
327
328         client = create_client_and_test_surface(100, 100, 100, 100);
329         assert(client);
330
331         /* move pointer outside of client */
332         assert(!surface_contains(client->surface, 50, 50));
333         check_pointer_move(client, 50, 50);
334
335         /* move client center to pointer */
336         move_client(client, 0, 0);
337         assert(surface_contains(client->surface, 50, 50));
338         check_pointer(client, 50, 50);
339 }
340
341 TEST(pointer_motion_events)
342 {
343         struct client *client = create_client_with_pointer_focus(100, 100,
344                                                                  100, 100);
345         struct pointer *pointer = client->input->pointer;
346         struct input_timestamps *input_ts =
347                 input_timestamps_create_for_pointer(client);
348
349         send_motion(client, &t1, 150, 150);
350         assert(pointer->x == 50);
351         assert(pointer->y == 50);
352         assert(pointer->motion_time_msec == timespec_to_msec(&t1));
353         assert(timespec_eq(&pointer->motion_time_timespec, &t1));
354
355         input_timestamps_destroy(input_ts);
356 }
357
358 TEST(pointer_button_events)
359 {
360         struct client *client = create_client_with_pointer_focus(100, 100,
361                                                                  100, 100);
362         struct pointer *pointer = client->input->pointer;
363         struct input_timestamps *input_ts =
364                 input_timestamps_create_for_pointer(client);
365
366         assert(pointer->button == 0);
367         assert(pointer->state == 0);
368
369         send_button(client, &t1, BTN_LEFT, WL_POINTER_BUTTON_STATE_PRESSED);
370         assert(pointer->button == BTN_LEFT);
371         assert(pointer->state == WL_POINTER_BUTTON_STATE_PRESSED);
372         assert(pointer->button_time_msec == timespec_to_msec(&t1));
373         assert(timespec_eq(&pointer->button_time_timespec, &t1));
374
375         send_button(client, &t2, BTN_LEFT, WL_POINTER_BUTTON_STATE_RELEASED);
376         assert(pointer->button == BTN_LEFT);
377         assert(pointer->state == WL_POINTER_BUTTON_STATE_RELEASED);
378         assert(pointer->button_time_msec == timespec_to_msec(&t2));
379         assert(timespec_eq(&pointer->button_time_timespec, &t2));
380
381         input_timestamps_destroy(input_ts);
382 }
383
384 TEST(pointer_axis_events)
385 {
386         struct client *client = create_client_with_pointer_focus(100, 100,
387                                                                  100, 100);
388         struct pointer *pointer = client->input->pointer;
389         struct input_timestamps *input_ts =
390                 input_timestamps_create_for_pointer(client);
391
392         send_axis(client, &t1, 1, 1.0);
393         assert(pointer->axis == 1);
394         assert(pointer->axis_value == 1.0);
395         assert(pointer->axis_time_msec == timespec_to_msec(&t1));
396         assert(timespec_eq(&pointer->axis_time_timespec, &t1));
397
398         send_axis(client, &t2, 2, 0.0);
399         assert(pointer->axis == 2);
400         assert(pointer->axis_stop_time_msec == timespec_to_msec(&t2));
401         assert(timespec_eq(&pointer->axis_stop_time_timespec, &t2));
402
403         input_timestamps_destroy(input_ts);
404 }
405
406 TEST(pointer_timestamps_stop_after_input_timestamps_object_is_destroyed)
407 {
408         struct client *client = create_client_with_pointer_focus(100, 100,
409                                                                  100, 100);
410         struct pointer *pointer = client->input->pointer;
411         struct input_timestamps *input_ts =
412                 input_timestamps_create_for_pointer(client);
413
414         send_button(client, &t1, BTN_LEFT, WL_POINTER_BUTTON_STATE_PRESSED);
415         assert(pointer->button == BTN_LEFT);
416         assert(pointer->state == WL_POINTER_BUTTON_STATE_PRESSED);
417         assert(pointer->button_time_msec == timespec_to_msec(&t1));
418         assert(timespec_eq(&pointer->button_time_timespec, &t1));
419
420         input_timestamps_destroy(input_ts);
421
422         send_button(client, &t2, BTN_LEFT, WL_POINTER_BUTTON_STATE_RELEASED);
423         assert(pointer->button == BTN_LEFT);
424         assert(pointer->state == WL_POINTER_BUTTON_STATE_RELEASED);
425         assert(pointer->button_time_msec == timespec_to_msec(&t2));
426         assert(timespec_is_zero(&pointer->button_time_timespec));
427 }
428
429 TEST(pointer_timestamps_stop_after_client_releases_wl_pointer)
430 {
431         struct client *client = create_client_with_pointer_focus(100, 100,
432                                                                  100, 100);
433         struct pointer *pointer = client->input->pointer;
434         struct input_timestamps *input_ts =
435                 input_timestamps_create_for_pointer(client);
436
437         send_motion(client, &t1, 150, 150);
438         assert(pointer->x == 50);
439         assert(pointer->y == 50);
440         assert(pointer->motion_time_msec == timespec_to_msec(&t1));
441         assert(timespec_eq(&pointer->motion_time_timespec, &t1));
442
443         wl_pointer_release(client->input->pointer->wl_pointer);
444
445         /* Set input_timestamp to an arbitrary value (different from t1, t2
446          * and 0) and check that it is not changed by sending the event.
447          * This is preferred over just checking for 0, since 0 is used
448          * internally for resetting the timestamp after handling an input
449          * event and checking for it here may lead to false negatives. */
450         pointer->input_timestamp = t_other;
451         send_motion(client, &t2, 175, 175);
452         assert(timespec_eq(&pointer->input_timestamp, &t_other));
453
454         input_timestamps_destroy(input_ts);
455 }