source: mainline/uspace/srv/hid/display/test/seat.c@ 0da03df

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

Distinguish between focus switching and evacuation

It's the same thing if there are at least two windows. With just
one window, switching focus should do nothing. Evacuation should
lead to no window being focused. (Fixes crash when pressing
Alt-Shift/Ctrl-Shift with just one window left).

  • Property mode set to 100644
File size: 12.7 KB
Line 
1/*
2 * Copyright (c) 2019 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_focus(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_focus(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/** Switch focus when another window is available. */
185PCUT_TEST(switch_focus_two_windows)
186{
187 ds_display_t *disp;
188 ds_client_t *client;
189 ds_seat_t *seat;
190 ds_window_t *w0;
191 ds_window_t *w1;
192 display_wnd_params_t params;
193 bool called_cb = false;
194 errno_t rc;
195
196 rc = ds_display_create(NULL, df_none, &disp);
197 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
198
199 rc = ds_client_create(disp, &test_ds_client_cb, &called_cb, &client);
200 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
201
202 rc = ds_seat_create(disp, &seat);
203 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
204
205 display_wnd_params_init(&params);
206 params.rect.p0.x = params.rect.p0.y = 0;
207 params.rect.p1.x = params.rect.p1.y = 1;
208
209 rc = ds_window_create(client, &params, &w1);
210 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
211
212 rc = ds_window_create(client, &params, &w0);
213 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
214
215 ds_seat_set_focus(seat, w1);
216 PCUT_ASSERT_EQUALS(w1, seat->focus);
217 PCUT_ASSERT_TRUE(called_cb);
218 called_cb = false;
219
220 ds_seat_switch_focus(seat);
221 PCUT_ASSERT_EQUALS(w0, seat->focus);
222 PCUT_ASSERT_TRUE(called_cb);
223
224 ds_window_destroy(w0);
225 ds_window_destroy(w1);
226 ds_seat_destroy(seat);
227 ds_client_destroy(client);
228 ds_display_destroy(disp);
229}
230
231/** Switch focus with just one existing window.
232 *
233 * After switching the focus should remain with the same window.
234 */
235PCUT_TEST(switch_focus_one_window)
236{
237 ds_display_t *disp;
238 ds_client_t *client;
239 ds_seat_t *seat;
240 ds_window_t *wnd;
241 display_wnd_params_t params;
242 bool called_cb = false;
243 errno_t rc;
244
245 rc = ds_display_create(NULL, df_none, &disp);
246 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
247
248 rc = ds_client_create(disp, &test_ds_client_cb, &called_cb, &client);
249 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
250
251 rc = ds_seat_create(disp, &seat);
252 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
253
254 display_wnd_params_init(&params);
255 params.rect.p0.x = params.rect.p0.y = 0;
256 params.rect.p1.x = params.rect.p1.y = 1;
257
258 rc = ds_window_create(client, &params, &wnd);
259 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
260
261 ds_seat_set_focus(seat, wnd);
262 PCUT_ASSERT_EQUALS(wnd, seat->focus);
263 PCUT_ASSERT_TRUE(called_cb);
264 called_cb = false;
265
266 ds_seat_switch_focus(seat);
267 PCUT_ASSERT_EQUALS(wnd, seat->focus);
268 PCUT_ASSERT_FALSE(called_cb);
269
270 ds_window_destroy(wnd);
271 ds_seat_destroy(seat);
272 ds_client_destroy(client);
273 ds_display_destroy(disp);
274}
275
276/** Test ds_seat_post_kbd_event() with Alt-Tab switches focus */
277PCUT_TEST(post_kbd_event_alt_tab)
278{
279 ds_display_t *disp;
280 ds_client_t *client;
281 ds_seat_t *seat;
282 ds_window_t *w0;
283 ds_window_t *w1;
284 display_wnd_params_t params;
285 bool called_cb = false;
286 kbd_event_t event;
287 errno_t rc;
288
289 rc = ds_display_create(NULL, df_none, &disp);
290 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
291
292 rc = ds_client_create(disp, &test_ds_client_cb, &called_cb, &client);
293 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
294
295 rc = ds_seat_create(disp, &seat);
296 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
297
298 display_wnd_params_init(&params);
299 params.rect.p0.x = params.rect.p0.y = 0;
300 params.rect.p1.x = params.rect.p1.y = 1;
301
302 rc = ds_window_create(client, &params, &w1);
303 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
304
305 rc = ds_window_create(client, &params, &w0);
306 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
307
308 ds_seat_set_focus(seat, w1);
309 PCUT_ASSERT_EQUALS(w1, seat->focus);
310 PCUT_ASSERT_TRUE(called_cb);
311 called_cb = false;
312
313 event.type = KEY_PRESS;
314 event.mods = KM_ALT;
315 event.key = KC_TAB;
316 rc = ds_seat_post_kbd_event(seat, &event);
317 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
318 PCUT_ASSERT_EQUALS(w0, seat->focus);
319 PCUT_ASSERT_TRUE(called_cb);
320
321 ds_window_destroy(w0);
322 ds_window_destroy(w1);
323 ds_seat_destroy(seat);
324 ds_client_destroy(client);
325 ds_display_destroy(disp);
326}
327
328/** Test ds_seat_post_kbd_event() with regular key press delivers to client queue */
329PCUT_TEST(post_kbd_event_regular)
330{
331 ds_display_t *disp;
332 ds_client_t *client;
333 ds_seat_t *seat;
334 ds_window_t *wnd;
335 display_wnd_params_t params;
336 kbd_event_t event;
337 ds_window_t *rwindow;
338 display_wnd_ev_t revent;
339 bool called_cb = false;
340 errno_t rc;
341
342 rc = ds_display_create(NULL, df_none, &disp);
343 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
344
345 rc = ds_client_create(disp, &test_ds_client_cb, &called_cb, &client);
346 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
347
348 rc = ds_seat_create(disp, &seat);
349 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
350
351 display_wnd_params_init(&params);
352 params.rect.p0.x = params.rect.p0.y = 0;
353 params.rect.p1.x = params.rect.p1.y = 1;
354
355 rc = ds_window_create(client, &params, &wnd);
356 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
357
358 ds_seat_set_focus(seat, wnd);
359 PCUT_ASSERT_EQUALS(wnd, seat->focus);
360
361 PCUT_ASSERT_TRUE(called_cb);
362 rc = ds_client_get_event(client, &rwindow, &revent);
363 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
364 called_cb = false;
365
366 event.type = KEY_PRESS;
367 event.key = KC_ENTER;
368 event.mods = 0;
369 event.c = L'\0';
370
371 rc = ds_client_get_event(client, &rwindow, &revent);
372 PCUT_ASSERT_ERRNO_VAL(ENOENT, rc);
373
374 rc = ds_seat_post_kbd_event(seat, &event);
375 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
376 PCUT_ASSERT_TRUE(called_cb);
377
378 rc = ds_client_get_event(client, &rwindow, &revent);
379 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
380 PCUT_ASSERT_EQUALS(wnd, rwindow);
381 PCUT_ASSERT_EQUALS(wev_kbd, revent.etype);
382 PCUT_ASSERT_EQUALS(event.type, revent.ev.kbd.type);
383 PCUT_ASSERT_EQUALS(event.key, revent.ev.kbd.key);
384 PCUT_ASSERT_EQUALS(event.mods, revent.ev.kbd.mods);
385 PCUT_ASSERT_EQUALS(event.c, revent.ev.kbd.c);
386
387 rc = ds_client_get_event(client, &rwindow, &revent);
388 PCUT_ASSERT_ERRNO_VAL(ENOENT, rc);
389
390 ds_window_destroy(wnd);
391 ds_seat_destroy(seat);
392 ds_client_destroy(client);
393 ds_display_destroy(disp);
394}
395
396/** Test ds_seat_post_ptd_event() with click on window switches focus
397 */
398PCUT_TEST(post_ptd_event_wnd_switch)
399{
400 ds_display_t *disp;
401 ds_seat_t *seat;
402 ds_client_t *client;
403 ds_window_t *w0, *w1;
404 display_wnd_params_t params;
405 ptd_event_t event;
406 bool called_cb = false;
407 errno_t rc;
408
409 rc = ds_display_create(NULL, df_none, &disp);
410 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
411
412 rc = ds_seat_create(disp, &seat);
413 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
414
415 rc = ds_client_create(disp, &test_ds_client_cb, &called_cb, &client);
416 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
417
418 /* Set up display size to allow the pointer a range of movement */
419 disp->rect.p1.x = 500;
420 disp->rect.p1.y = 500;
421
422 display_wnd_params_init(&params);
423 params.rect.p0.x = params.rect.p0.y = 0;
424 params.rect.p1.x = params.rect.p1.y = 1;
425
426 rc = ds_window_create(client, &params, &w0);
427 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
428
429 rc = ds_window_create(client, &params, &w1);
430 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
431
432 w0->dpos.x = 10;
433 w0->dpos.y = 10;
434
435 w1->dpos.x = 400;
436 w1->dpos.y = 400;
437
438 PCUT_ASSERT_FALSE(called_cb);
439
440 ds_seat_set_focus(seat, w0);
441
442 event.type = PTD_MOVE;
443 event.dmove.x = 400;
444 event.dmove.y = 400;
445 rc = ds_seat_post_ptd_event(seat, &event);
446 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
447
448 PCUT_ASSERT_TRUE(called_cb);
449 called_cb = false;
450
451 event.type = PTD_PRESS;
452 event.btn_num = 1;
453 rc = ds_seat_post_ptd_event(seat, &event);
454 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
455 PCUT_ASSERT_TRUE(called_cb);
456 called_cb = false;
457
458 PCUT_ASSERT_EQUALS(w1, seat->focus);
459
460 event.type = PTD_MOVE;
461 event.dmove.x = -400 + 10;
462 event.dmove.y = -400 + 10;
463 rc = ds_seat_post_ptd_event(seat, &event);
464 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
465 PCUT_ASSERT_TRUE(called_cb);
466 called_cb = false;
467
468 event.type = PTD_PRESS;
469 event.btn_num = 1;
470 rc = ds_seat_post_ptd_event(seat, &event);
471 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
472 PCUT_ASSERT_TRUE(called_cb);
473 called_cb = false;
474
475 PCUT_ASSERT_EQUALS(w0, seat->focus);
476
477 ds_window_destroy(w0);
478 ds_window_destroy(w1);
479 ds_client_destroy(client);
480 ds_seat_destroy(seat);
481 ds_display_destroy(disp);
482}
483
484/** Test ds_seat_post_pos_event() */
485PCUT_TEST(post_pos_event)
486{
487 // XXX
488}
489
490/** Set WM cursor */
491PCUT_TEST(set_wm_cursor)
492{
493 ds_display_t *disp;
494 ds_client_t *client;
495 ds_seat_t *seat;
496 bool called_cb = false;
497 errno_t rc;
498
499 rc = ds_display_create(NULL, df_none, &disp);
500 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
501
502 rc = ds_client_create(disp, &test_ds_client_cb, &called_cb, &client);
503 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
504
505 rc = ds_seat_create(disp, &seat);
506 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
507
508 ds_seat_set_wm_cursor(seat, disp->cursor[dcurs_size_ud]);
509 ds_seat_set_wm_cursor(seat, NULL);
510
511 ds_seat_destroy(seat);
512 ds_client_destroy(client);
513 ds_display_destroy(disp);
514}
515
516PCUT_EXPORT(seat);
Note: See TracBrowser for help on using the repository browser.