source: mainline/uspace/srv/hid/display/test/display.c@ 5d62130

ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 5d62130 was 5d62130, checked in by Jiri Svoboda <jiri@…>, 3 years ago

Taskbar should be always on top

We add support for topmost windows and make the taskbar window topmost.

  • Property mode set to 100644
File size: 14.1 KB
Line 
1/*
2 * Copyright (c) 2022 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#include "../wmclient.h"
39
40PCUT_INIT;
41
42PCUT_TEST_SUITE(display);
43
44static void test_ds_ev_pending(void *);
45
46static ds_client_cb_t test_ds_client_cb = {
47 .ev_pending = test_ds_ev_pending
48};
49
50static void test_ds_wmev_pending(void *);
51
52static ds_wmclient_cb_t test_ds_wmclient_cb = {
53 .ev_pending = test_ds_wmev_pending
54};
55
56static void test_ds_ev_pending(void *arg)
57{
58 bool *called_cb = (bool *) arg;
59 *called_cb = true;
60}
61
62static void test_ds_wmev_pending(void *arg)
63{
64 bool *called_cb = (bool *) arg;
65 *called_cb = true;
66}
67
68/** Display creation and destruction. */
69PCUT_TEST(display_create_destroy)
70{
71 ds_display_t *disp;
72 errno_t rc;
73
74 rc = ds_display_create(NULL, df_none, &disp);
75 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
76
77 ds_display_destroy(disp);
78}
79
80/** Basic client operation. */
81PCUT_TEST(display_client)
82{
83 ds_display_t *disp;
84 ds_client_t *client;
85 ds_client_t *c0, *c1;
86 errno_t rc;
87
88 rc = ds_display_create(NULL, df_none, &disp);
89 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
90
91 rc = ds_client_create(disp, &test_ds_client_cb, NULL, &client);
92 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
93
94 c0 = ds_display_first_client(disp);
95 PCUT_ASSERT_EQUALS(c0, client);
96
97 c1 = ds_display_next_client(c0);
98 PCUT_ASSERT_NULL(c1);
99
100 ds_client_destroy(client);
101 ds_display_destroy(disp);
102}
103
104/** Basic WM client operation. */
105PCUT_TEST(display_wmclient)
106{
107 ds_display_t *disp;
108 ds_wmclient_t *wmclient;
109 ds_wmclient_t *c0, *c1;
110 errno_t rc;
111
112 rc = ds_display_create(NULL, df_none, &disp);
113 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
114
115 rc = ds_wmclient_create(disp, &test_ds_wmclient_cb, NULL, &wmclient);
116 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
117
118 c0 = ds_display_first_wmclient(disp);
119 PCUT_ASSERT_EQUALS(c0, wmclient);
120
121 c1 = ds_display_next_wmclient(c0);
122 PCUT_ASSERT_NULL(c1);
123
124 ds_wmclient_destroy(wmclient);
125 ds_display_destroy(disp);
126}
127
128/** Test ds_display_find_window(). */
129PCUT_TEST(display_find_window)
130{
131 ds_display_t *disp;
132 ds_client_t *client;
133 ds_seat_t *seat;
134 ds_window_t *w0;
135 ds_window_t *w1;
136 ds_window_t *wnd;
137 display_wnd_params_t params;
138 bool called_cb = false;
139 errno_t rc;
140
141 rc = ds_display_create(NULL, df_none, &disp);
142 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
143
144 rc = ds_client_create(disp, &test_ds_client_cb, &called_cb, &client);
145 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
146
147 rc = ds_seat_create(disp, &seat);
148 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
149
150 display_wnd_params_init(&params);
151 params.rect.p0.x = params.rect.p0.y = 0;
152 params.rect.p1.x = params.rect.p1.y = 1;
153
154 rc = ds_window_create(client, &params, &w1);
155 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
156
157 rc = ds_window_create(client, &params, &w0);
158 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
159
160 wnd = ds_display_first_window(disp);
161 PCUT_ASSERT_EQUALS(w0, wnd);
162
163 wnd = ds_display_next_window(wnd);
164 PCUT_ASSERT_EQUALS(w1, wnd);
165
166 wnd = ds_display_next_window(wnd);
167 PCUT_ASSERT_NULL(wnd);
168
169 wnd = ds_display_last_window(disp);
170 PCUT_ASSERT_EQUALS(w1, wnd);
171
172 wnd = ds_display_prev_window(wnd);
173 PCUT_ASSERT_EQUALS(w0, wnd);
174
175 wnd = ds_display_prev_window(wnd);
176 PCUT_ASSERT_NULL(wnd);
177
178 wnd = ds_display_find_window(disp, w0->id);
179 PCUT_ASSERT_EQUALS(w0, wnd);
180
181 wnd = ds_display_find_window(disp, w1->id);
182 PCUT_ASSERT_EQUALS(w1, wnd);
183
184 wnd = ds_display_find_window(disp, 0);
185 PCUT_ASSERT_NULL(wnd);
186
187 wnd = ds_display_find_window(disp, w0->id + 1);
188 PCUT_ASSERT_NULL(wnd);
189
190 ds_window_destroy(w0);
191 ds_window_destroy(w1);
192 ds_seat_destroy(seat);
193 ds_client_destroy(client);
194 ds_display_destroy(disp);
195}
196
197/** Test ds_display_enlist_window() */
198PCUT_TEST(display_enlist_window)
199{
200 ds_display_t *disp;
201 ds_client_t *client;
202 ds_seat_t *seat;
203 ds_window_t *w0;
204 ds_window_t *w1;
205 ds_window_t *w2;
206 ds_window_t *w3;
207 ds_window_t *w;
208 display_wnd_params_t params;
209 bool called_cb = false;
210 errno_t rc;
211
212 rc = ds_display_create(NULL, df_none, &disp);
213 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
214
215 rc = ds_client_create(disp, &test_ds_client_cb, &called_cb, &client);
216 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
217
218 rc = ds_seat_create(disp, &seat);
219 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
220
221 display_wnd_params_init(&params);
222 params.rect.p0.x = params.rect.p0.y = 0;
223 params.rect.p1.x = params.rect.p1.y = 100;
224
225 /* Regular windows */
226
227 rc = ds_window_create(client, &params, &w0);
228 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
229
230 rc = ds_window_create(client, &params, &w1);
231 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
232
233 /* Topmost windows */
234
235 params.flags |= wndf_topmost;
236
237 rc = ds_window_create(client, &params, &w2);
238 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
239
240 rc = ds_window_create(client, &params, &w3);
241 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
242
243 /* Delist w1 and w2 */
244 list_remove(&w1->ldwindows);
245 list_remove(&w2->ldwindows);
246
247 /* Enlist the windows back and check their order */
248 ds_display_enlist_window(disp, w1);
249 ds_display_enlist_window(disp, w2);
250
251 w = ds_display_first_window(disp);
252 PCUT_ASSERT_EQUALS(w2, w);
253 w = ds_display_next_window(w);
254 PCUT_ASSERT_EQUALS(w3, w);
255 w = ds_display_next_window(w);
256 PCUT_ASSERT_EQUALS(w1, w);
257 w = ds_display_next_window(w);
258 PCUT_ASSERT_EQUALS(w0, w);
259 w = ds_display_next_window(w);
260 PCUT_ASSERT_EQUALS(NULL, w);
261
262 ds_window_destroy(w0);
263 ds_window_destroy(w1);
264 ds_window_destroy(w2);
265 ds_window_destroy(w3);
266 ds_seat_destroy(seat);
267 ds_client_destroy(client);
268 ds_display_destroy(disp);
269}
270
271/** Test ds_display_window_to_top() */
272PCUT_TEST(display_window_to_top)
273{
274 ds_display_t *disp;
275 ds_client_t *client;
276 ds_seat_t *seat;
277 ds_window_t *w0;
278 ds_window_t *w1;
279 display_wnd_params_t params;
280 bool called_cb = false;
281 errno_t rc;
282
283 rc = ds_display_create(NULL, df_none, &disp);
284 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
285
286 rc = ds_client_create(disp, &test_ds_client_cb, &called_cb, &client);
287 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
288
289 rc = ds_seat_create(disp, &seat);
290 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
291
292 display_wnd_params_init(&params);
293 params.rect.p0.x = params.rect.p0.y = 0;
294 params.rect.p1.x = params.rect.p1.y = 100;
295
296 rc = ds_window_create(client, &params, &w0);
297 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
298
299 rc = ds_window_create(client, &params, &w1);
300 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
301
302 PCUT_ASSERT_EQUALS(w1, ds_display_first_window(disp));
303 ds_display_window_to_top(w0);
304 PCUT_ASSERT_EQUALS(w0, ds_display_first_window(disp));
305
306 ds_window_destroy(w0);
307 ds_window_destroy(w1);
308 ds_seat_destroy(seat);
309 ds_client_destroy(client);
310 ds_display_destroy(disp);
311}
312
313/** Test ds_display_window_by_pos(). */
314PCUT_TEST(display_window_by_pos)
315{
316 ds_display_t *disp;
317 ds_client_t *client;
318 ds_seat_t *seat;
319 ds_window_t *w0;
320 ds_window_t *w1;
321 ds_window_t *wnd;
322 display_wnd_params_t params;
323 gfx_coord2_t pos;
324 bool called_cb = false;
325 errno_t rc;
326
327 rc = ds_display_create(NULL, df_none, &disp);
328 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
329
330 rc = ds_client_create(disp, &test_ds_client_cb, &called_cb, &client);
331 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
332
333 rc = ds_seat_create(disp, &seat);
334 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
335
336 display_wnd_params_init(&params);
337 params.rect.p0.x = params.rect.p0.y = 0;
338 params.rect.p1.x = params.rect.p1.y = 100;
339
340 rc = ds_window_create(client, &params, &w0);
341 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
342
343 rc = ds_window_create(client, &params, &w1);
344 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
345
346 w0->dpos.x = 10;
347 w0->dpos.y = 10;
348
349 w1->dpos.x = 400;
350 w1->dpos.y = 400;
351
352 pos.x = 10;
353 pos.y = 10;
354 wnd = ds_display_window_by_pos(disp, &pos);
355 PCUT_ASSERT_EQUALS(w0, wnd);
356
357 pos.x = 400;
358 pos.y = 400;
359 wnd = ds_display_window_by_pos(disp, &pos);
360 PCUT_ASSERT_EQUALS(w1, wnd);
361
362 ds_window_destroy(w0);
363 ds_window_destroy(w1);
364 ds_seat_destroy(seat);
365 ds_client_destroy(client);
366 ds_display_destroy(disp);
367}
368
369/** Basic seat operation. */
370PCUT_TEST(display_seat)
371{
372 ds_display_t *disp;
373 ds_seat_t *seat;
374 ds_seat_t *s0, *s1;
375 errno_t rc;
376
377 rc = ds_display_create(NULL, df_none, &disp);
378 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
379
380 rc = ds_seat_create(disp, &seat);
381 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
382
383 s0 = ds_display_first_seat(disp);
384 PCUT_ASSERT_EQUALS(s0, seat);
385
386 s1 = ds_display_next_seat(s0);
387 PCUT_ASSERT_NULL(s1);
388
389 ds_seat_destroy(seat);
390 ds_display_destroy(disp);
391}
392
393/** ds_display_seat_by_idev() returns the correct seat. */
394PCUT_TEST(display_seat_by_idev)
395{
396 // XXX TODO
397}
398
399/** Test ds_display_post_kbd_event() delivers event to client callback.
400 */
401PCUT_TEST(display_post_kbd_event)
402{
403 ds_display_t *disp;
404 ds_seat_t *seat;
405 ds_client_t *client;
406 ds_window_t *wnd;
407 display_wnd_params_t params;
408 kbd_event_t event;
409 bool called_cb = false;
410 errno_t rc;
411
412 rc = ds_display_create(NULL, df_none, &disp);
413 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
414
415 rc = ds_seat_create(disp, &seat);
416 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
417
418 rc = ds_client_create(disp, &test_ds_client_cb, &called_cb, &client);
419 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
420
421 display_wnd_params_init(&params);
422 params.rect.p0.x = params.rect.p0.y = 0;
423 params.rect.p1.x = params.rect.p1.y = 1;
424
425 rc = ds_window_create(client, &params, &wnd);
426 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
427
428 ds_seat_set_focus(seat, wnd);
429
430 event.type = KEY_PRESS;
431 event.key = KC_ENTER;
432 event.mods = 0;
433 event.c = L'\0';
434
435 called_cb = false;
436
437 rc = ds_display_post_kbd_event(disp, &event);
438 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
439 PCUT_ASSERT_TRUE(called_cb);
440
441 ds_window_destroy(wnd);
442 ds_client_destroy(client);
443 ds_seat_destroy(seat);
444 ds_display_destroy(disp);
445}
446
447/** Test ds_display_post_kbd_event() with Alt-Tab switches focus.
448 */
449PCUT_TEST(display_post_kbd_event_alt_tab)
450{
451 ds_display_t *disp;
452 ds_seat_t *seat;
453 ds_client_t *client;
454 ds_window_t *w0, *w1;
455 display_wnd_params_t params;
456 kbd_event_t event;
457 bool called_cb = false;
458 errno_t rc;
459
460 rc = ds_display_create(NULL, df_none, &disp);
461 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
462
463 rc = ds_seat_create(disp, &seat);
464 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
465
466 rc = ds_client_create(disp, &test_ds_client_cb, &called_cb, &client);
467 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
468
469 display_wnd_params_init(&params);
470 params.rect.p0.x = params.rect.p0.y = 0;
471 params.rect.p1.x = params.rect.p1.y = 1;
472
473 rc = ds_window_create(client, &params, &w0);
474 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
475
476 rc = ds_window_create(client, &params, &w1);
477 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
478
479 ds_seat_set_focus(seat, w0);
480
481 event.type = KEY_PRESS;
482 event.key = KC_TAB;
483 event.mods = KM_ALT;
484 event.c = L'\0';
485
486 called_cb = false;
487
488 rc = ds_display_post_kbd_event(disp, &event);
489 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
490
491 /* Got gocus/unfocus events */
492 PCUT_ASSERT_TRUE(called_cb);
493
494 /* Next window should be focused */
495 PCUT_ASSERT_EQUALS(w1, seat->focus);
496
497 called_cb = false;
498
499 rc = ds_display_post_kbd_event(disp, &event);
500 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
501
502 /* Got gocus/unfocus events */
503 PCUT_ASSERT_TRUE(called_cb);
504
505 /* Focus should be back to the first window */
506 PCUT_ASSERT_EQUALS(w0, seat->focus);
507
508 ds_window_destroy(w0);
509 ds_window_destroy(w1);
510 ds_client_destroy(client);
511 ds_seat_destroy(seat);
512 ds_display_destroy(disp);
513}
514
515/** Test ds_display_post_ptd_event() with click on window switches focus
516 */
517PCUT_TEST(display_post_ptd_event_wnd_switch)
518{
519 ds_display_t *disp;
520 ds_seat_t *seat;
521 ds_client_t *client;
522 ds_window_t *w0, *w1;
523 display_wnd_params_t params;
524 ptd_event_t event;
525 bool called_cb = false;
526 errno_t rc;
527
528 rc = ds_display_create(NULL, df_none, &disp);
529 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
530
531 rc = ds_seat_create(disp, &seat);
532 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
533
534 rc = ds_client_create(disp, &test_ds_client_cb, &called_cb, &client);
535 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
536
537 /*
538 * For PTD_MOVE to work we need to set display dimensions (as pointer
539 * move is clipped to the display rectangle. Here we do it directly
540 * instead of adding a display device.
541 */
542 disp->rect.p0.x = 0;
543 disp->rect.p0.y = 0;
544 disp->rect.p1.x = 500;
545 disp->rect.p1.y = 500;
546
547 display_wnd_params_init(&params);
548 params.rect.p0.x = params.rect.p0.y = 0;
549 params.rect.p1.x = params.rect.p1.y = 1;
550
551 rc = ds_window_create(client, &params, &w0);
552 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
553
554 rc = ds_window_create(client, &params, &w1);
555 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
556
557 w0->dpos.x = 10;
558 w0->dpos.y = 10;
559
560 w1->dpos.x = 400;
561 w1->dpos.y = 400;
562
563 ds_seat_set_focus(seat, w0);
564
565 event.type = PTD_MOVE;
566 event.dmove.x = 400;
567 event.dmove.y = 400;
568 rc = ds_display_post_ptd_event(disp, &event);
569 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
570
571 event.type = PTD_PRESS;
572 event.btn_num = 1;
573 rc = ds_display_post_ptd_event(disp, &event);
574 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
575
576 PCUT_ASSERT_EQUALS(w1, seat->focus);
577
578 event.type = PTD_RELEASE;
579 event.btn_num = 1;
580 rc = ds_display_post_ptd_event(disp, &event);
581 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
582
583 event.type = PTD_MOVE;
584 event.dmove.x = -400 + 10;
585 event.dmove.y = -400 + 10;
586 rc = ds_display_post_ptd_event(disp, &event);
587 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
588
589 event.type = PTD_PRESS;
590 event.btn_num = 1;
591 rc = ds_display_post_ptd_event(disp, &event);
592 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
593
594 PCUT_ASSERT_EQUALS(w0, seat->focus);
595
596 ds_window_destroy(w0);
597 ds_window_destroy(w1);
598 ds_client_destroy(client);
599 ds_seat_destroy(seat);
600 ds_display_destroy(disp);
601}
602
603PCUT_EXPORT(display);
Note: See TracBrowser for help on using the repository browser.