blob: 4c438a227fa81ba7275292ace3ded439cd45f1a5 [file] [log] [blame]
Alexandros Frantzis5d6acf82017-12-04 15:34:03 +02001/*
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
Alexandros Frantzis21808582017-12-13 13:27:55 +020031#include "shared/timespec-util.h"
Alexandros Frantzis5d6acf82017-12-04 15:34:03 +020032#include "weston-test-client-helper.h"
33
Alexandros Frantzis21808582017-12-13 13:27:55 +020034static const struct timespec t0 = { .tv_sec = 0, .tv_nsec = 100000000 };
35static const struct timespec t1 = { .tv_sec = 1, .tv_nsec = 1000001 };
36static const struct timespec t2 = { .tv_sec = 2, .tv_nsec = 2000001 };
37
38static void
39send_motion(struct client *client, const struct timespec *time, int x, int y)
40{
41 uint32_t tv_sec_hi, tv_sec_lo, tv_nsec;
42
43 timespec_to_proto(time, &tv_sec_hi, &tv_sec_lo, &tv_nsec);
44 weston_test_move_pointer(client->test->weston_test, tv_sec_hi, tv_sec_lo,
45 tv_nsec, x, y);
46 client_roundtrip(client);
47}
48
49static void
50send_button(struct client *client, const struct timespec *time,
51 uint32_t button, uint32_t state)
52{
53 uint32_t tv_sec_hi, tv_sec_lo, tv_nsec;
54
55 timespec_to_proto(time, &tv_sec_hi, &tv_sec_lo, &tv_nsec);
56 weston_test_send_button(client->test->weston_test, tv_sec_hi, tv_sec_lo,
57 tv_nsec, button, state);
58 client_roundtrip(client);
59}
60
Alexandros Frantzis5d6acf82017-12-04 15:34:03 +020061static void
Alexandros Frantzisb0341ae2017-12-18 12:16:55 +020062send_axis(struct client *client, const struct timespec *time, uint32_t axis,
63 double value)
64{
65 uint32_t tv_sec_hi, tv_sec_lo, tv_nsec;
66
67 timespec_to_proto(time, &tv_sec_hi, &tv_sec_lo, &tv_nsec);
68 weston_test_send_axis(client->test->weston_test, tv_sec_hi, tv_sec_lo,
69 tv_nsec, axis, wl_fixed_from_double(value));
70 client_roundtrip(client);
71}
72
73static void
Alexandros Frantzis5d6acf82017-12-04 15:34:03 +020074check_pointer(struct client *client, int x, int y)
75{
76 int sx, sy;
77
78 /* check that the client got the global pointer update */
79 assert(client->test->pointer_x == x);
80 assert(client->test->pointer_y == y);
81
82 /* Does global pointer map onto the surface? */
83 if (surface_contains(client->surface, x, y)) {
84 /* check that the surface has the pointer focus */
85 assert(client->input->pointer->focus == client->surface);
86
87 /*
88 * check that the local surface pointer maps
89 * to the global pointer.
90 */
91 sx = client->input->pointer->x + client->surface->x;
92 sy = client->input->pointer->y + client->surface->y;
93 assert(sx == x);
94 assert(sy == y);
95 } else {
96 /*
97 * The global pointer does not map onto surface. So
98 * check that it doesn't have the pointer focus.
99 */
100 assert(client->input->pointer->focus == NULL);
101 }
102}
103
104static void
105check_pointer_move(struct client *client, int x, int y)
106{
Alexandros Frantzis21808582017-12-13 13:27:55 +0200107 send_motion(client, &t0, x, y);
Alexandros Frantzis5d6acf82017-12-04 15:34:03 +0200108 check_pointer(client, x, y);
109}
110
Alexandros Frantzis903e4452017-12-04 15:34:04 +0200111static struct client *
112create_client_with_pointer_focus(int x, int y, int w, int h)
113{
114 struct client *cl = create_client_and_test_surface(x, y, w, h);
115 assert(cl);
116 /* Move the pointer inside the surface to ensure that the surface
117 * has the pointer focus. */
118 check_pointer_move(cl, x, y);
119 return cl;
120}
121
Alexandros Frantzis5d6acf82017-12-04 15:34:03 +0200122TEST(test_pointer_top_left)
123{
124 struct client *client;
125 int x, y;
126
127 client = create_client_and_test_surface(46, 76, 111, 134);
128 assert(client);
129
130 /* move pointer outside top left */
131 x = client->surface->x - 1;
132 y = client->surface->y - 1;
133 assert(!surface_contains(client->surface, x, y));
134 check_pointer_move(client, x, y);
135
136 /* move pointer on top left */
137 x += 1; y += 1;
138 assert(surface_contains(client->surface, x, y));
139 check_pointer_move(client, x, y);
140
141 /* move pointer outside top left */
142 x -= 1; y -= 1;
143 assert(!surface_contains(client->surface, x, y));
144 check_pointer_move(client, x, y);
145}
146
147TEST(test_pointer_bottom_left)
148{
149 struct client *client;
150 int x, y;
151
152 client = create_client_and_test_surface(99, 100, 100, 98);
153 assert(client);
154
155 /* move pointer outside bottom left */
156 x = client->surface->x - 1;
157 y = client->surface->y + client->surface->height;
158 assert(!surface_contains(client->surface, x, y));
159 check_pointer_move(client, x, y);
160
161 /* move pointer on bottom left */
162 x += 1; y -= 1;
163 assert(surface_contains(client->surface, x, y));
164 check_pointer_move(client, x, y);
165
166 /* move pointer outside bottom left */
167 x -= 1; y += 1;
168 assert(!surface_contains(client->surface, x, y));
169 check_pointer_move(client, x, y);
170}
171
172TEST(test_pointer_top_right)
173{
174 struct client *client;
175 int x, y;
176
177 client = create_client_and_test_surface(48, 100, 67, 100);
178 assert(client);
179
180 /* move pointer outside top right */
181 x = client->surface->x + client->surface->width;
182 y = client->surface->y - 1;
183 assert(!surface_contains(client->surface, x, y));
184 check_pointer_move(client, x, y);
185
186 /* move pointer on top right */
187 x -= 1; y += 1;
188 assert(surface_contains(client->surface, x, y));
189 check_pointer_move(client, x, y);
190
191 /* move pointer outside top right */
192 x += 1; y -= 1;
193 assert(!surface_contains(client->surface, x, y));
194 check_pointer_move(client, x, y);
195}
196
197TEST(test_pointer_bottom_right)
198{
199 struct client *client;
200 int x, y;
201
202 client = create_client_and_test_surface(100, 123, 100, 69);
203 assert(client);
204
205 /* move pointer outside bottom right */
206 x = client->surface->x + client->surface->width;
207 y = client->surface->y + client->surface->height;
208 assert(!surface_contains(client->surface, x, y));
209 check_pointer_move(client, x, y);
210
211 /* move pointer on bottom right */
212 x -= 1; y -= 1;
213 assert(surface_contains(client->surface, x, y));
214 check_pointer_move(client, x, y);
215
216 /* move pointer outside bottom right */
217 x += 1; y += 1;
218 assert(!surface_contains(client->surface, x, y));
219 check_pointer_move(client, x, y);
220}
221
222TEST(test_pointer_top_center)
223{
224 struct client *client;
225 int x, y;
226
227 client = create_client_and_test_surface(100, 201, 100, 50);
228 assert(client);
229
230 /* move pointer outside top center */
231 x = client->surface->x + client->surface->width/2;
232 y = client->surface->y - 1;
233 assert(!surface_contains(client->surface, x, y));
234 check_pointer_move(client, x, y);
235
236 /* move pointer on top center */
237 y += 1;
238 assert(surface_contains(client->surface, x, y));
239 check_pointer_move(client, x, y);
240
241 /* move pointer outside top center */
242 y -= 1;
243 assert(!surface_contains(client->surface, x, y));
244 check_pointer_move(client, x, y);
245}
246
247TEST(test_pointer_bottom_center)
248{
249 struct client *client;
250 int x, y;
251
252 client = create_client_and_test_surface(100, 45, 67, 100);
253 assert(client);
254
255 /* move pointer outside bottom center */
256 x = client->surface->x + client->surface->width/2;
257 y = client->surface->y + client->surface->height;
258 assert(!surface_contains(client->surface, x, y));
259 check_pointer_move(client, x, y);
260
261 /* move pointer on bottom center */
262 y -= 1;
263 assert(surface_contains(client->surface, x, y));
264 check_pointer_move(client, x, y);
265
266 /* move pointer outside bottom center */
267 y += 1;
268 assert(!surface_contains(client->surface, x, y));
269 check_pointer_move(client, x, y);
270}
271
272TEST(test_pointer_left_center)
273{
274 struct client *client;
275 int x, y;
276
277 client = create_client_and_test_surface(167, 45, 78, 100);
278 assert(client);
279
280 /* move pointer outside left center */
281 x = client->surface->x - 1;
282 y = client->surface->y + client->surface->height/2;
283 assert(!surface_contains(client->surface, x, y));
284 check_pointer_move(client, x, y);
285
286 /* move pointer on left center */
287 x += 1;
288 assert(surface_contains(client->surface, x, y));
289 check_pointer_move(client, x, y);
290
291 /* move pointer outside left center */
292 x -= 1;
293 assert(!surface_contains(client->surface, x, y));
294 check_pointer_move(client, x, y);
295}
296
297TEST(test_pointer_right_center)
298{
299 struct client *client;
300 int x, y;
301
302 client = create_client_and_test_surface(110, 37, 100, 46);
303 assert(client);
304
305 /* move pointer outside right center */
306 x = client->surface->x + client->surface->width;
307 y = client->surface->y + client->surface->height/2;
308 assert(!surface_contains(client->surface, x, y));
309 check_pointer_move(client, x, y);
310
311 /* move pointer on right center */
312 x -= 1;
313 assert(surface_contains(client->surface, x, y));
314 check_pointer_move(client, x, y);
315
316 /* move pointer outside right center */
317 x += 1;
318 assert(!surface_contains(client->surface, x, y));
319 check_pointer_move(client, x, y);
320}
321
322TEST(test_pointer_surface_move)
323{
324 struct client *client;
325
326 client = create_client_and_test_surface(100, 100, 100, 100);
327 assert(client);
328
329 /* move pointer outside of client */
330 assert(!surface_contains(client->surface, 50, 50));
331 check_pointer_move(client, 50, 50);
332
333 /* move client center to pointer */
334 move_client(client, 0, 0);
335 assert(surface_contains(client->surface, 50, 50));
336 check_pointer(client, 50, 50);
337}
338
Alexandros Frantzis903e4452017-12-04 15:34:04 +0200339TEST(pointer_motion_events)
Alexandros Frantzis5d6acf82017-12-04 15:34:03 +0200340{
Alexandros Frantzis903e4452017-12-04 15:34:04 +0200341 struct client *client = create_client_with_pointer_focus(100, 100,
342 100, 100);
343 struct pointer *pointer = client->input->pointer;
Alexandros Frantzis5d6acf82017-12-04 15:34:03 +0200344
Alexandros Frantzis21808582017-12-13 13:27:55 +0200345 send_motion(client, &t1, 150, 150);
Alexandros Frantzis5d6acf82017-12-04 15:34:03 +0200346 assert(pointer->x == 50);
347 assert(pointer->y == 50);
Alexandros Frantzis21808582017-12-13 13:27:55 +0200348 assert(pointer->motion_time_msec == timespec_to_msec(&t1));
Alexandros Frantzis903e4452017-12-04 15:34:04 +0200349}
350
351TEST(pointer_button_events)
352{
353 struct client *client = create_client_with_pointer_focus(100, 100,
354 100, 100);
355 struct pointer *pointer = client->input->pointer;
356
357 assert(pointer->button == 0);
358 assert(pointer->state == 0);
Alexandros Frantzis5d6acf82017-12-04 15:34:03 +0200359
Alexandros Frantzis21808582017-12-13 13:27:55 +0200360 send_button(client, &t1, BTN_LEFT, WL_POINTER_BUTTON_STATE_PRESSED);
Alexandros Frantzis5d6acf82017-12-04 15:34:03 +0200361 assert(pointer->button == BTN_LEFT);
362 assert(pointer->state == WL_POINTER_BUTTON_STATE_PRESSED);
Alexandros Frantzis21808582017-12-13 13:27:55 +0200363 assert(pointer->button_time_msec == timespec_to_msec(&t1));
Alexandros Frantzis5d6acf82017-12-04 15:34:03 +0200364
Alexandros Frantzis21808582017-12-13 13:27:55 +0200365 send_button(client, &t2, BTN_LEFT, WL_POINTER_BUTTON_STATE_RELEASED);
Alexandros Frantzis5d6acf82017-12-04 15:34:03 +0200366 assert(pointer->button == BTN_LEFT);
367 assert(pointer->state == WL_POINTER_BUTTON_STATE_RELEASED);
Alexandros Frantzis21808582017-12-13 13:27:55 +0200368 assert(pointer->button_time_msec == timespec_to_msec(&t2));
Alexandros Frantzis5d6acf82017-12-04 15:34:03 +0200369}
Alexandros Frantzisb0341ae2017-12-18 12:16:55 +0200370
371TEST(pointer_axis_events)
372{
373 struct client *client = create_client_with_pointer_focus(100, 100,
374 100, 100);
375 struct pointer *pointer = client->input->pointer;
376
377 send_axis(client, &t1, 1, 1.0);
378 assert(pointer->axis == 1);
379 assert(pointer->axis_value == 1.0);
380 assert(pointer->axis_time_msec == timespec_to_msec(&t1));
381
382 send_axis(client, &t2, 2, 0.0);
383 assert(pointer->axis == 2);
384 assert(pointer->axis_stop_time_msec == timespec_to_msec(&t2));
385}