source: mainline/uspace/srv/hid/display/test/seat.c@ 98735eb

serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 98735eb 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: 13.8 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(seat);
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/** Set focus. */
56PCUT_TEST(set_focus)
57{
58 ds_display_t *disp;
59 ds_client_t *client;
60 ds_seat_t *seat;
61 ds_window_t *wnd;
62 display_wnd_params_t params;
63 bool called_cb = false;
64 errno_t rc;
65
66 rc = ds_display_create(NULL, df_none, &disp);
67 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
68
69 rc = ds_client_create(disp, &test_ds_client_cb, &called_cb, &client);
70 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
71
72 rc = ds_seat_create(disp, &seat);
73 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
74
75 display_wnd_params_init(&params);
76 params.rect.p0.x = params.rect.p0.y = 0;
77 params.rect.p1.x = params.rect.p1.y = 1;
78
79 rc = ds_window_create(client, &params, &wnd);
80 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
81
82 ds_seat_set_focus(seat, wnd);
83 PCUT_ASSERT_EQUALS(wnd, seat->focus);
84 PCUT_ASSERT_TRUE(called_cb);
85
86 ds_window_destroy(wnd);
87 ds_seat_destroy(seat);
88 ds_client_destroy(client);
89 ds_display_destroy(disp);
90}
91
92/** Evacuate focus when another window is available. */
93PCUT_TEST(evac_focus_two_windows)
94{
95 ds_display_t *disp;
96 ds_client_t *client;
97 ds_seat_t *seat;
98 ds_window_t *w0;
99 ds_window_t *w1;
100 display_wnd_params_t params;
101 bool called_cb = false;
102 errno_t rc;
103
104 rc = ds_display_create(NULL, df_none, &disp);
105 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
106
107 rc = ds_client_create(disp, &test_ds_client_cb, &called_cb, &client);
108 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
109
110 rc = ds_seat_create(disp, &seat);
111 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
112
113 display_wnd_params_init(&params);
114 params.rect.p0.x = params.rect.p0.y = 0;
115 params.rect.p1.x = params.rect.p1.y = 1;
116
117 rc = ds_window_create(client, &params, &w1);
118 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
119
120 rc = ds_window_create(client, &params, &w0);
121 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
122
123 ds_seat_set_focus(seat, w1);
124 PCUT_ASSERT_EQUALS(w1, seat->focus);
125 PCUT_ASSERT_TRUE(called_cb);
126 called_cb = false;
127
128 ds_seat_evac_wnd_refs(seat, w1);
129 PCUT_ASSERT_EQUALS(w0, seat->focus);
130 PCUT_ASSERT_TRUE(called_cb);
131
132 ds_window_destroy(w0);
133 ds_window_destroy(w1);
134 ds_seat_destroy(seat);
135 ds_client_destroy(client);
136 ds_display_destroy(disp);
137}
138
139/** Evacuate focus from the only existing window.
140 *
141 * After evacuating no window should be focused
142 */
143PCUT_TEST(evac_focus_one_window)
144{
145 ds_display_t *disp;
146 ds_client_t *client;
147 ds_seat_t *seat;
148 ds_window_t *wnd;
149 display_wnd_params_t params;
150 bool called_cb = false;
151 errno_t rc;
152
153 rc = ds_display_create(NULL, df_none, &disp);
154 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
155
156 rc = ds_client_create(disp, &test_ds_client_cb, &called_cb, &client);
157 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
158
159 rc = ds_seat_create(disp, &seat);
160 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
161
162 display_wnd_params_init(&params);
163 params.rect.p0.x = params.rect.p0.y = 0;
164 params.rect.p1.x = params.rect.p1.y = 1;
165
166 rc = ds_window_create(client, &params, &wnd);
167 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
168
169 ds_seat_set_focus(seat, wnd);
170 PCUT_ASSERT_EQUALS(wnd, seat->focus);
171 PCUT_ASSERT_TRUE(called_cb);
172 called_cb = false;
173
174 ds_seat_evac_wnd_refs(seat, wnd);
175 PCUT_ASSERT_NULL(seat->focus);
176 PCUT_ASSERT_TRUE(called_cb);
177
178 ds_window_destroy(wnd);
179 ds_seat_destroy(seat);
180 ds_client_destroy(client);
181 ds_display_destroy(disp);
182}
183
184/** Evacuate popup reference from window.
185 *
186 * After evacuating no window should be set as the popup
187 */
188PCUT_TEST(evac_popup)
189{
190 ds_display_t *disp;
191 ds_client_t *client;
192 ds_seat_t *seat;
193 ds_window_t *wnd;
194 display_wnd_params_t params;
195 bool called_cb = false;
196 errno_t rc;
197
198 rc = ds_display_create(NULL, df_none, &disp);
199 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
200
201 rc = ds_client_create(disp, &test_ds_client_cb, &called_cb, &client);
202 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
203
204 rc = ds_seat_create(disp, &seat);
205 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
206
207 display_wnd_params_init(&params);
208 params.rect.p0.x = params.rect.p0.y = 0;
209 params.rect.p1.x = params.rect.p1.y = 1;
210 params.flags |= wndf_popup;
211
212 rc = ds_window_create(client, &params, &wnd);
213 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
214
215 PCUT_ASSERT_EQUALS(wnd, seat->popup);
216
217 ds_seat_evac_wnd_refs(seat, wnd);
218 PCUT_ASSERT_NULL(seat->popup);
219
220 ds_window_destroy(wnd);
221 ds_seat_destroy(seat);
222 ds_client_destroy(client);
223 ds_display_destroy(disp);
224}
225
226/** Switch focus when another window is available. */
227PCUT_TEST(switch_focus_two_windows)
228{
229 ds_display_t *disp;
230 ds_client_t *client;
231 ds_seat_t *seat;
232 ds_window_t *w0;
233 ds_window_t *w1;
234 display_wnd_params_t params;
235 bool called_cb = false;
236 errno_t rc;
237
238 rc = ds_display_create(NULL, df_none, &disp);
239 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
240
241 rc = ds_client_create(disp, &test_ds_client_cb, &called_cb, &client);
242 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
243
244 rc = ds_seat_create(disp, &seat);
245 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
246
247 display_wnd_params_init(&params);
248 params.rect.p0.x = params.rect.p0.y = 0;
249 params.rect.p1.x = params.rect.p1.y = 1;
250
251 rc = ds_window_create(client, &params, &w1);
252 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
253
254 rc = ds_window_create(client, &params, &w0);
255 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
256
257 ds_seat_set_focus(seat, w1);
258 PCUT_ASSERT_EQUALS(w1, seat->focus);
259 PCUT_ASSERT_TRUE(called_cb);
260 called_cb = false;
261
262 ds_seat_switch_focus(seat);
263 PCUT_ASSERT_EQUALS(w0, seat->focus);
264 PCUT_ASSERT_TRUE(called_cb);
265
266 ds_window_destroy(w0);
267 ds_window_destroy(w1);
268 ds_seat_destroy(seat);
269 ds_client_destroy(client);
270 ds_display_destroy(disp);
271}
272
273/** Switch focus with just one existing window.
274 *
275 * After switching the focus should remain with the same window.
276 */
277PCUT_TEST(switch_focus_one_window)
278{
279 ds_display_t *disp;
280 ds_client_t *client;
281 ds_seat_t *seat;
282 ds_window_t *wnd;
283 display_wnd_params_t params;
284 bool called_cb = false;
285 errno_t rc;
286
287 rc = ds_display_create(NULL, df_none, &disp);
288 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
289
290 rc = ds_client_create(disp, &test_ds_client_cb, &called_cb, &client);
291 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
292
293 rc = ds_seat_create(disp, &seat);
294 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
295
296 display_wnd_params_init(&params);
297 params.rect.p0.x = params.rect.p0.y = 0;
298 params.rect.p1.x = params.rect.p1.y = 1;
299
300 rc = ds_window_create(client, &params, &wnd);
301 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
302
303 ds_seat_set_focus(seat, wnd);
304 PCUT_ASSERT_EQUALS(wnd, seat->focus);
305 PCUT_ASSERT_TRUE(called_cb);
306 called_cb = false;
307
308 ds_seat_switch_focus(seat);
309 PCUT_ASSERT_EQUALS(wnd, seat->focus);
310 PCUT_ASSERT_FALSE(called_cb);
311
312 ds_window_destroy(wnd);
313 ds_seat_destroy(seat);
314 ds_client_destroy(client);
315 ds_display_destroy(disp);
316}
317
318/** Test ds_seat_post_kbd_event() with Alt-Tab switches focus */
319PCUT_TEST(post_kbd_event_alt_tab)
320{
321 ds_display_t *disp;
322 ds_client_t *client;
323 ds_seat_t *seat;
324 ds_window_t *w0;
325 ds_window_t *w1;
326 display_wnd_params_t params;
327 bool called_cb = false;
328 kbd_event_t event;
329 errno_t rc;
330
331 rc = ds_display_create(NULL, df_none, &disp);
332 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
333
334 rc = ds_client_create(disp, &test_ds_client_cb, &called_cb, &client);
335 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
336
337 rc = ds_seat_create(disp, &seat);
338 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
339
340 display_wnd_params_init(&params);
341 params.rect.p0.x = params.rect.p0.y = 0;
342 params.rect.p1.x = params.rect.p1.y = 1;
343
344 rc = ds_window_create(client, &params, &w1);
345 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
346
347 rc = ds_window_create(client, &params, &w0);
348 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
349
350 ds_seat_set_focus(seat, w1);
351 PCUT_ASSERT_EQUALS(w1, seat->focus);
352 PCUT_ASSERT_TRUE(called_cb);
353 called_cb = false;
354
355 event.type = KEY_PRESS;
356 event.mods = KM_ALT;
357 event.key = KC_TAB;
358 rc = ds_seat_post_kbd_event(seat, &event);
359 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
360 PCUT_ASSERT_EQUALS(w0, seat->focus);
361 PCUT_ASSERT_TRUE(called_cb);
362
363 ds_window_destroy(w0);
364 ds_window_destroy(w1);
365 ds_seat_destroy(seat);
366 ds_client_destroy(client);
367 ds_display_destroy(disp);
368}
369
370/** Test ds_seat_post_kbd_event() with regular key press delivers to client queue */
371PCUT_TEST(post_kbd_event_regular)
372{
373 ds_display_t *disp;
374 ds_client_t *client;
375 ds_seat_t *seat;
376 ds_window_t *wnd;
377 display_wnd_params_t params;
378 kbd_event_t event;
379 ds_window_t *rwindow;
380 display_wnd_ev_t revent;
381 bool called_cb = false;
382 errno_t rc;
383
384 rc = ds_display_create(NULL, df_none, &disp);
385 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
386
387 rc = ds_client_create(disp, &test_ds_client_cb, &called_cb, &client);
388 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
389
390 rc = ds_seat_create(disp, &seat);
391 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
392
393 display_wnd_params_init(&params);
394 params.rect.p0.x = params.rect.p0.y = 0;
395 params.rect.p1.x = params.rect.p1.y = 1;
396
397 rc = ds_window_create(client, &params, &wnd);
398 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
399
400 ds_seat_set_focus(seat, wnd);
401 PCUT_ASSERT_EQUALS(wnd, seat->focus);
402
403 PCUT_ASSERT_TRUE(called_cb);
404 rc = ds_client_get_event(client, &rwindow, &revent);
405 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
406 called_cb = false;
407
408 event.type = KEY_PRESS;
409 event.key = KC_ENTER;
410 event.mods = 0;
411 event.c = L'\0';
412
413 rc = ds_client_get_event(client, &rwindow, &revent);
414 PCUT_ASSERT_ERRNO_VAL(ENOENT, rc);
415
416 rc = ds_seat_post_kbd_event(seat, &event);
417 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
418 PCUT_ASSERT_TRUE(called_cb);
419
420 rc = ds_client_get_event(client, &rwindow, &revent);
421 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
422 PCUT_ASSERT_EQUALS(wnd, rwindow);
423 PCUT_ASSERT_EQUALS(wev_kbd, revent.etype);
424 PCUT_ASSERT_EQUALS(event.type, revent.ev.kbd.type);
425 PCUT_ASSERT_EQUALS(event.key, revent.ev.kbd.key);
426 PCUT_ASSERT_EQUALS(event.mods, revent.ev.kbd.mods);
427 PCUT_ASSERT_EQUALS(event.c, revent.ev.kbd.c);
428
429 rc = ds_client_get_event(client, &rwindow, &revent);
430 PCUT_ASSERT_ERRNO_VAL(ENOENT, rc);
431
432 ds_window_destroy(wnd);
433 ds_seat_destroy(seat);
434 ds_client_destroy(client);
435 ds_display_destroy(disp);
436}
437
438/** Test ds_seat_post_ptd_event() with click on window switches focus
439 */
440PCUT_TEST(post_ptd_event_wnd_switch)
441{
442 ds_display_t *disp;
443 ds_seat_t *seat;
444 ds_client_t *client;
445 ds_window_t *w0, *w1;
446 display_wnd_params_t params;
447 ptd_event_t event;
448 bool called_cb = false;
449 errno_t rc;
450
451 rc = ds_display_create(NULL, df_none, &disp);
452 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
453
454 rc = ds_seat_create(disp, &seat);
455 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
456
457 rc = ds_client_create(disp, &test_ds_client_cb, &called_cb, &client);
458 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
459
460 /* Set up display size to allow the pointer a range of movement */
461 disp->rect.p1.x = 500;
462 disp->rect.p1.y = 500;
463
464 display_wnd_params_init(&params);
465 params.rect.p0.x = params.rect.p0.y = 0;
466 params.rect.p1.x = params.rect.p1.y = 1;
467
468 rc = ds_window_create(client, &params, &w0);
469 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
470
471 rc = ds_window_create(client, &params, &w1);
472 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
473
474 w0->dpos.x = 10;
475 w0->dpos.y = 10;
476
477 w1->dpos.x = 400;
478 w1->dpos.y = 400;
479
480 /* New window gets focused event */
481 PCUT_ASSERT_TRUE(called_cb);
482
483 called_cb = false;
484
485 ds_seat_set_focus(seat, w0);
486
487 event.type = PTD_MOVE;
488 event.dmove.x = 400;
489 event.dmove.y = 400;
490 rc = ds_seat_post_ptd_event(seat, &event);
491 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
492
493 PCUT_ASSERT_TRUE(called_cb);
494 called_cb = false;
495
496 event.type = PTD_PRESS;
497 event.btn_num = 1;
498 rc = ds_seat_post_ptd_event(seat, &event);
499 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
500 PCUT_ASSERT_TRUE(called_cb);
501 called_cb = false;
502
503 PCUT_ASSERT_EQUALS(w1, seat->focus);
504
505 event.type = PTD_MOVE;
506 event.dmove.x = -400 + 10;
507 event.dmove.y = -400 + 10;
508 rc = ds_seat_post_ptd_event(seat, &event);
509 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
510 PCUT_ASSERT_TRUE(called_cb);
511 called_cb = false;
512
513 event.type = PTD_PRESS;
514 event.btn_num = 1;
515 rc = ds_seat_post_ptd_event(seat, &event);
516 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
517 PCUT_ASSERT_TRUE(called_cb);
518 called_cb = false;
519
520 PCUT_ASSERT_EQUALS(w0, seat->focus);
521
522 ds_window_destroy(w0);
523 ds_window_destroy(w1);
524 ds_client_destroy(client);
525 ds_seat_destroy(seat);
526 ds_display_destroy(disp);
527}
528
529/** Test ds_seat_post_pos_event() */
530PCUT_TEST(post_pos_event)
531{
532 // XXX
533}
534
535/** Set WM cursor */
536PCUT_TEST(set_wm_cursor)
537{
538 ds_display_t *disp;
539 ds_client_t *client;
540 ds_seat_t *seat;
541 bool called_cb = false;
542 errno_t rc;
543
544 rc = ds_display_create(NULL, df_none, &disp);
545 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
546
547 rc = ds_client_create(disp, &test_ds_client_cb, &called_cb, &client);
548 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
549
550 rc = ds_seat_create(disp, &seat);
551 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
552
553 ds_seat_set_wm_cursor(seat, disp->cursor[dcurs_size_ud]);
554 ds_seat_set_wm_cursor(seat, NULL);
555
556 ds_seat_destroy(seat);
557 ds_client_destroy(client);
558 ds_display_destroy(disp);
559}
560
561PCUT_EXPORT(seat);
Note: See TracBrowser for help on using the repository browser.