source: mainline/uspace/srv/hid/display/test/client.c@ d7f82635

serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since d7f82635 was 9e84d2c, checked in by jxsvoboda <5887334+jxsvoboda@…>, 4 years ago

Popup windows event delivery is special

Popup windows don't get focus, yet they still receive events.

  • Property mode set to 100644
File size: 15.3 KB
Line 
1/*
2 * Copyright (c) 2021 Jiri Svoboda
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <disp_srv.h>
30#include <errno.h>
31#include <pcut/pcut.h>
32#include <str.h>
33
34#include "../client.h"
35#include "../display.h"
36#include "../seat.h"
37#include "../window.h"
38
39PCUT_INIT;
40
41PCUT_TEST_SUITE(client);
42
43static void test_ds_ev_pending(void *);
44
45static ds_client_cb_t test_ds_client_cb = {
46 .ev_pending = test_ds_ev_pending
47};
48
49static void test_ds_ev_pending(void *arg)
50{
51 bool *called_cb = (bool *) arg;
52 *called_cb = true;
53}
54
55/** Client creation and destruction. */
56PCUT_TEST(client_create_destroy)
57{
58 ds_display_t *disp;
59 ds_client_t *client;
60 errno_t rc;
61
62 rc = ds_display_create(NULL, df_none, &disp);
63 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
64
65 rc = ds_client_create(disp, &test_ds_client_cb, NULL, &client);
66 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
67
68 ds_client_destroy(client);
69 ds_display_destroy(disp);
70}
71
72/** Test ds_client_find_window().
73 *
74 * ds_client_add_window() and ds_client_remove_window() are indirectly
75 * tested too as part of creating and destroying the window
76 */
77PCUT_TEST(client_find_window)
78{
79 ds_display_t *disp;
80 ds_client_t *client;
81 ds_seat_t *seat;
82 ds_window_t *w0;
83 ds_window_t *w1;
84 ds_window_t *wnd;
85 display_wnd_params_t params;
86 bool called_cb = NULL;
87 errno_t rc;
88
89 rc = ds_display_create(NULL, df_none, &disp);
90 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
91
92 rc = ds_client_create(disp, &test_ds_client_cb, &called_cb, &client);
93 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
94
95 rc = ds_seat_create(disp, &seat);
96 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
97
98 display_wnd_params_init(&params);
99 params.rect.p0.x = params.rect.p0.y = 0;
100 params.rect.p1.x = params.rect.p1.y = 1;
101
102 rc = ds_window_create(client, &params, &w0);
103 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
104
105 rc = ds_window_create(client, &params, &w1);
106 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
107
108 wnd = ds_client_find_window(client, w0->id);
109 PCUT_ASSERT_EQUALS(w0, wnd);
110
111 wnd = ds_client_find_window(client, w1->id);
112 PCUT_ASSERT_EQUALS(w1, wnd);
113
114 wnd = ds_client_find_window(client, 0);
115 PCUT_ASSERT_NULL(wnd);
116
117 wnd = ds_client_find_window(client, w1->id + 1);
118 PCUT_ASSERT_NULL(wnd);
119
120 ds_window_destroy(w0);
121 ds_window_destroy(w1);
122 ds_seat_destroy(seat);
123 ds_client_destroy(client);
124 ds_display_destroy(disp);
125}
126
127/** Test ds_client_first_window() / ds_client_next_window. */
128PCUT_TEST(client_first_next_window)
129{
130 ds_display_t *disp;
131 ds_client_t *client;
132 ds_seat_t *seat;
133 ds_window_t *w0;
134 ds_window_t *w1;
135 ds_window_t *wnd;
136 display_wnd_params_t params;
137 bool called_cb = NULL;
138 errno_t rc;
139
140 rc = ds_display_create(NULL, df_none, &disp);
141 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
142
143 rc = ds_client_create(disp, &test_ds_client_cb, &called_cb, &client);
144 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
145
146 rc = ds_seat_create(disp, &seat);
147 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
148
149 display_wnd_params_init(&params);
150 params.rect.p0.x = params.rect.p0.y = 0;
151 params.rect.p1.x = params.rect.p1.y = 1;
152
153 rc = ds_window_create(client, &params, &w0);
154 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
155
156 rc = ds_window_create(client, &params, &w1);
157 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
158
159 wnd = ds_client_first_window(client);
160 PCUT_ASSERT_EQUALS(w0, wnd);
161
162 wnd = ds_client_next_window(w0);
163 PCUT_ASSERT_EQUALS(w1, wnd);
164
165 wnd = ds_client_next_window(w1);
166 PCUT_ASSERT_NULL(wnd);
167
168 ds_window_destroy(w0);
169 ds_window_destroy(w1);
170 ds_seat_destroy(seat);
171 ds_client_destroy(client);
172 ds_display_destroy(disp);
173}
174
175/** Test ds_client_get_event(), ds_client_post_close_event(). */
176PCUT_TEST(client_get_post_close_event)
177{
178 ds_display_t *disp;
179 ds_client_t *client;
180 ds_seat_t *seat;
181 ds_window_t *wnd;
182 display_wnd_params_t params;
183 ds_window_t *rwindow;
184 display_wnd_ev_t revent;
185 bool called_cb = NULL;
186 errno_t rc;
187
188 rc = ds_display_create(NULL, df_none, &disp);
189 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
190
191 rc = ds_client_create(disp, &test_ds_client_cb, &called_cb, &client);
192 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
193
194 rc = ds_seat_create(disp, &seat);
195 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
196
197 display_wnd_params_init(&params);
198 params.rect.p0.x = params.rect.p0.y = 0;
199 params.rect.p1.x = params.rect.p1.y = 1;
200
201 rc = ds_window_create(client, &params, &wnd);
202 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
203
204 /* New window gets focused event */
205 PCUT_ASSERT_TRUE(called_cb);
206
207 rc = ds_client_get_event(client, &rwindow, &revent);
208 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
209
210 called_cb = false;
211
212 rc = ds_client_get_event(client, &rwindow, &revent);
213 PCUT_ASSERT_ERRNO_VAL(ENOENT, rc);
214
215 rc = ds_client_post_close_event(client, wnd);
216 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
217 PCUT_ASSERT_TRUE(called_cb);
218
219 rc = ds_client_get_event(client, &rwindow, &revent);
220 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
221 PCUT_ASSERT_EQUALS(wnd, rwindow);
222 PCUT_ASSERT_EQUALS(wev_close, revent.etype);
223
224 rc = ds_client_get_event(client, &rwindow, &revent);
225 PCUT_ASSERT_ERRNO_VAL(ENOENT, rc);
226
227 ds_window_destroy(wnd);
228 ds_seat_destroy(seat);
229 ds_client_destroy(client);
230 ds_display_destroy(disp);
231}
232
233/** Test ds_client_get_event(), ds_client_post_focus_event(). */
234PCUT_TEST(client_get_post_focus_event)
235{
236 ds_display_t *disp;
237 ds_client_t *client;
238 ds_seat_t *seat;
239 ds_window_t *wnd;
240 display_wnd_params_t params;
241 ds_window_t *rwindow;
242 display_wnd_ev_t revent;
243 bool called_cb = NULL;
244 errno_t rc;
245
246 rc = ds_display_create(NULL, df_none, &disp);
247 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
248
249 rc = ds_client_create(disp, &test_ds_client_cb, &called_cb, &client);
250 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
251
252 rc = ds_seat_create(disp, &seat);
253 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
254
255 display_wnd_params_init(&params);
256 params.rect.p0.x = params.rect.p0.y = 0;
257 params.rect.p1.x = params.rect.p1.y = 1;
258
259 rc = ds_window_create(client, &params, &wnd);
260 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
261
262 /* New window gets focused event */
263 PCUT_ASSERT_TRUE(called_cb);
264
265 rc = ds_client_get_event(client, &rwindow, &revent);
266 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
267
268 called_cb = false;
269
270 rc = ds_client_get_event(client, &rwindow, &revent);
271 PCUT_ASSERT_ERRNO_VAL(ENOENT, rc);
272
273 rc = ds_client_post_focus_event(client, wnd);
274 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
275 PCUT_ASSERT_TRUE(called_cb);
276
277 rc = ds_client_get_event(client, &rwindow, &revent);
278 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
279 PCUT_ASSERT_EQUALS(wnd, rwindow);
280 PCUT_ASSERT_EQUALS(wev_focus, revent.etype);
281
282 rc = ds_client_get_event(client, &rwindow, &revent);
283 PCUT_ASSERT_ERRNO_VAL(ENOENT, rc);
284
285 ds_window_destroy(wnd);
286 ds_seat_destroy(seat);
287 ds_client_destroy(client);
288 ds_display_destroy(disp);
289}
290
291/** Test ds_client_get_event(), ds_client_post_kbd_event(). */
292PCUT_TEST(client_get_post_kbd_event)
293{
294 ds_display_t *disp;
295 ds_client_t *client;
296 ds_seat_t *seat;
297 ds_window_t *wnd;
298 display_wnd_params_t params;
299 kbd_event_t event;
300 ds_window_t *rwindow;
301 display_wnd_ev_t revent;
302 bool called_cb = NULL;
303 errno_t rc;
304
305 rc = ds_display_create(NULL, df_none, &disp);
306 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
307
308 rc = ds_client_create(disp, &test_ds_client_cb, &called_cb, &client);
309 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
310
311 rc = ds_seat_create(disp, &seat);
312 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
313
314 display_wnd_params_init(&params);
315 params.rect.p0.x = params.rect.p0.y = 0;
316 params.rect.p1.x = params.rect.p1.y = 1;
317
318 rc = ds_window_create(client, &params, &wnd);
319 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
320
321 /* New window gets focused event */
322 PCUT_ASSERT_TRUE(called_cb);
323
324 rc = ds_client_get_event(client, &rwindow, &revent);
325 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
326
327 called_cb = false;
328
329 rc = ds_client_get_event(client, &rwindow, &revent);
330 PCUT_ASSERT_ERRNO_VAL(ENOENT, rc);
331
332 event.type = KEY_PRESS;
333 event.key = KC_ENTER;
334 event.mods = 0;
335 event.c = L'\0';
336
337 rc = ds_client_post_kbd_event(client, wnd, &event);
338 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
339 PCUT_ASSERT_TRUE(called_cb);
340
341 rc = ds_client_get_event(client, &rwindow, &revent);
342 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
343 PCUT_ASSERT_EQUALS(wnd, rwindow);
344 PCUT_ASSERT_EQUALS(wev_kbd, revent.etype);
345 PCUT_ASSERT_EQUALS(event.type, revent.ev.kbd.type);
346 PCUT_ASSERT_EQUALS(event.key, revent.ev.kbd.key);
347 PCUT_ASSERT_EQUALS(event.mods, revent.ev.kbd.mods);
348 PCUT_ASSERT_EQUALS(event.c, revent.ev.kbd.c);
349
350 rc = ds_client_get_event(client, &rwindow, &revent);
351 PCUT_ASSERT_ERRNO_VAL(ENOENT, rc);
352
353 ds_window_destroy(wnd);
354 ds_seat_destroy(seat);
355 ds_client_destroy(client);
356 ds_display_destroy(disp);
357}
358
359/** Test ds_client_get_event(), ds_client_post_pos_event(). */
360PCUT_TEST(client_get_post_pos_event)
361{
362 ds_display_t *disp;
363 ds_client_t *client;
364 ds_seat_t *seat;
365 ds_window_t *wnd;
366 display_wnd_params_t params;
367 pos_event_t event;
368 ds_window_t *rwindow;
369 display_wnd_ev_t revent;
370 bool called_cb = NULL;
371 errno_t rc;
372
373 rc = ds_display_create(NULL, df_none, &disp);
374 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
375
376 rc = ds_client_create(disp, &test_ds_client_cb, &called_cb, &client);
377 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
378
379 rc = ds_seat_create(disp, &seat);
380 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
381
382 display_wnd_params_init(&params);
383 params.rect.p0.x = params.rect.p0.y = 0;
384 params.rect.p1.x = params.rect.p1.y = 1;
385
386 rc = ds_window_create(client, &params, &wnd);
387 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
388
389 /* New window gets focused event */
390 PCUT_ASSERT_TRUE(called_cb);
391
392 rc = ds_client_get_event(client, &rwindow, &revent);
393 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
394
395 called_cb = false;
396
397 PCUT_ASSERT_FALSE(called_cb);
398
399 rc = ds_client_get_event(client, &rwindow, &revent);
400 PCUT_ASSERT_ERRNO_VAL(ENOENT, rc);
401
402 event.type = POS_PRESS;
403 event.hpos = 1;
404 event.vpos = 2;
405
406 rc = ds_client_post_pos_event(client, wnd, &event);
407 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
408 PCUT_ASSERT_TRUE(called_cb);
409
410 rc = ds_client_get_event(client, &rwindow, &revent);
411 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
412 PCUT_ASSERT_EQUALS(wnd, rwindow);
413 PCUT_ASSERT_EQUALS(wev_pos, revent.etype);
414 PCUT_ASSERT_EQUALS(event.type, revent.ev.pos.type);
415 PCUT_ASSERT_EQUALS(event.hpos, revent.ev.pos.hpos);
416 PCUT_ASSERT_EQUALS(event.vpos, revent.ev.pos.vpos);
417
418 rc = ds_client_get_event(client, &rwindow, &revent);
419 PCUT_ASSERT_ERRNO_VAL(ENOENT, rc);
420
421 ds_window_destroy(wnd);
422 ds_seat_destroy(seat);
423 ds_client_destroy(client);
424 ds_display_destroy(disp);
425}
426
427/** Test ds_client_get_event(), ds_client_post_resize_event(). */
428PCUT_TEST(client_get_post_resize_event)
429{
430 ds_display_t *disp;
431 ds_client_t *client;
432 ds_seat_t *seat;
433 ds_window_t *wnd;
434 display_wnd_params_t params;
435 gfx_rect_t rect;
436 ds_window_t *rwindow;
437 display_wnd_ev_t revent;
438 bool called_cb = NULL;
439 errno_t rc;
440
441 rc = ds_display_create(NULL, df_none, &disp);
442 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
443
444 rc = ds_client_create(disp, &test_ds_client_cb, &called_cb, &client);
445 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
446
447 rc = ds_seat_create(disp, &seat);
448 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
449
450 display_wnd_params_init(&params);
451 params.rect.p0.x = params.rect.p0.y = 0;
452 params.rect.p1.x = params.rect.p1.y = 1;
453
454 rc = ds_window_create(client, &params, &wnd);
455 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
456
457 /* New window gets focused event */
458 PCUT_ASSERT_TRUE(called_cb);
459
460 rc = ds_client_get_event(client, &rwindow, &revent);
461 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
462
463 called_cb = false;
464
465 PCUT_ASSERT_FALSE(called_cb);
466
467 rc = ds_client_get_event(client, &rwindow, &revent);
468 PCUT_ASSERT_ERRNO_VAL(ENOENT, rc);
469
470 rect.p0.x = 1;
471 rect.p0.y = 2;
472 rect.p1.x = 3;
473 rect.p1.y = 4;
474
475 rc = ds_client_post_resize_event(client, wnd, &rect);
476 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
477 PCUT_ASSERT_TRUE(called_cb);
478
479 rc = ds_client_get_event(client, &rwindow, &revent);
480 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
481 PCUT_ASSERT_EQUALS(wnd, rwindow);
482 PCUT_ASSERT_EQUALS(wev_resize, revent.etype);
483 PCUT_ASSERT_EQUALS(rect.p0.x, revent.ev.resize.rect.p0.x);
484 PCUT_ASSERT_EQUALS(rect.p0.y, revent.ev.resize.rect.p0.y);
485 PCUT_ASSERT_EQUALS(rect.p1.x, revent.ev.resize.rect.p1.x);
486 PCUT_ASSERT_EQUALS(rect.p1.y, revent.ev.resize.rect.p1.y);
487
488 rc = ds_client_get_event(client, &rwindow, &revent);
489 PCUT_ASSERT_ERRNO_VAL(ENOENT, rc);
490
491 ds_window_destroy(wnd);
492 ds_seat_destroy(seat);
493 ds_client_destroy(client);
494 ds_display_destroy(disp);
495}
496
497/** Test ds_client_get_event(), ds_client_post_unfocus_event(). */
498PCUT_TEST(client_get_post_unfocus_event)
499{
500 ds_display_t *disp;
501 ds_client_t *client;
502 ds_seat_t *seat;
503 ds_window_t *wnd;
504 display_wnd_params_t params;
505 ds_window_t *rwindow;
506 display_wnd_ev_t revent;
507 bool called_cb = NULL;
508 errno_t rc;
509
510 rc = ds_display_create(NULL, df_none, &disp);
511 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
512
513 rc = ds_client_create(disp, &test_ds_client_cb, &called_cb, &client);
514 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
515
516 rc = ds_seat_create(disp, &seat);
517 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
518
519 display_wnd_params_init(&params);
520 params.rect.p0.x = params.rect.p0.y = 0;
521 params.rect.p1.x = params.rect.p1.y = 1;
522
523 rc = ds_window_create(client, &params, &wnd);
524 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
525
526 /* New window gets focused event */
527 PCUT_ASSERT_TRUE(called_cb);
528
529 rc = ds_client_get_event(client, &rwindow, &revent);
530 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
531
532 called_cb = false;
533
534 rc = ds_client_get_event(client, &rwindow, &revent);
535 PCUT_ASSERT_ERRNO_VAL(ENOENT, rc);
536
537 rc = ds_client_post_unfocus_event(client, wnd);
538 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
539 PCUT_ASSERT_TRUE(called_cb);
540
541 rc = ds_client_get_event(client, &rwindow, &revent);
542 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
543 PCUT_ASSERT_EQUALS(wnd, rwindow);
544 PCUT_ASSERT_EQUALS(wev_unfocus, revent.etype);
545
546 rc = ds_client_get_event(client, &rwindow, &revent);
547 PCUT_ASSERT_ERRNO_VAL(ENOENT, rc);
548
549 ds_window_destroy(wnd);
550 ds_seat_destroy(seat);
551 ds_client_destroy(client);
552 ds_display_destroy(disp);
553}
554
555/** Test client being destroyed while still having a window.
556 *
557 * This can happen if client forgets to destroy window or if the client
558 * is disconnected (or terminated).
559 */
560PCUT_TEST(client_leftover_window)
561{
562 ds_display_t *disp;
563 ds_client_t *client;
564 ds_seat_t *seat;
565 ds_window_t *wnd;
566 display_wnd_params_t params;
567 errno_t rc;
568
569 rc = ds_display_create(NULL, df_none, &disp);
570 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
571
572 rc = ds_client_create(disp, NULL, NULL, &client);
573 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
574
575 rc = ds_seat_create(disp, &seat);
576 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
577
578 display_wnd_params_init(&params);
579 params.rect.p0.x = params.rect.p0.y = 0;
580 params.rect.p1.x = params.rect.p1.y = 1;
581
582 rc = ds_window_create(client, &params, &wnd);
583 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
584
585 ds_seat_destroy(seat);
586 ds_client_destroy(client);
587 ds_display_destroy(disp);
588}
589
590PCUT_EXPORT(client);
Note: See TracBrowser for help on using the repository browser.