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

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

Configurable display double-buffering

On by default (since turning off creates flicker in the absence of
front-to-back rendering). This is the quick and dirty way: display
server renders locally to a bitmap (using mem GC) and renders the
bitmap when ready.

The more sophisticated way would be to implement buffering in the
display device. That would require, however, enhancing the protocols
to communicate frame boundaries.

  • Property mode set to 100644
File size: 13.3 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 <stdio.h>
33#include <str.h>
34
35#include "../client.h"
36#include "../display.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 printf("test_ds_ev_pending\n");
53 *called_cb = true;
54
55}
56
57/** Client creation and destruction. */
58PCUT_TEST(client_create_destroy)
59{
60 ds_display_t *disp;
61 ds_client_t *client;
62 errno_t rc;
63
64 rc = ds_display_create(NULL, df_none, &disp);
65 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
66
67 rc = ds_client_create(disp, &test_ds_client_cb, NULL, &client);
68 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
69
70 ds_client_destroy(client);
71 ds_display_destroy(disp);
72}
73
74/** Test ds_client_find_window().
75 *
76 * ds_client_add_window() and ds_client_remove_window() are indirectly
77 * tested too as part of creating and destroying the window
78 */
79PCUT_TEST(client_find_window)
80{
81 ds_display_t *disp;
82 ds_client_t *client;
83 ds_window_t *w0;
84 ds_window_t *w1;
85 ds_window_t *wnd;
86 display_wnd_params_t params;
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, NULL, &client);
93 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
94
95 display_wnd_params_init(&params);
96 params.rect.p0.x = params.rect.p0.y = 0;
97 params.rect.p1.x = params.rect.p1.y = 1;
98
99 rc = ds_window_create(client, &params, &w0);
100 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
101
102 rc = ds_window_create(client, &params, &w1);
103 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
104
105 wnd = ds_client_find_window(client, w0->id);
106 PCUT_ASSERT_EQUALS(w0, wnd);
107
108 wnd = ds_client_find_window(client, w1->id);
109 PCUT_ASSERT_EQUALS(w1, wnd);
110
111 wnd = ds_client_find_window(client, 0);
112 PCUT_ASSERT_NULL(wnd);
113
114 wnd = ds_client_find_window(client, w1->id + 1);
115 PCUT_ASSERT_NULL(wnd);
116
117 ds_window_destroy(w0);
118 ds_window_destroy(w1);
119 ds_client_destroy(client);
120 ds_display_destroy(disp);
121}
122
123/** Test ds_client_first_window() / ds_client_next_window. */
124PCUT_TEST(client_first_next_window)
125{
126 ds_display_t *disp;
127 ds_client_t *client;
128 ds_window_t *w0;
129 ds_window_t *w1;
130 ds_window_t *wnd;
131 display_wnd_params_t params;
132 errno_t rc;
133
134 rc = ds_display_create(NULL, df_none, &disp);
135 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
136
137 rc = ds_client_create(disp, &test_ds_client_cb, NULL, &client);
138 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
139
140 display_wnd_params_init(&params);
141 params.rect.p0.x = params.rect.p0.y = 0;
142 params.rect.p1.x = params.rect.p1.y = 1;
143
144 rc = ds_window_create(client, &params, &w0);
145 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
146
147 rc = ds_window_create(client, &params, &w1);
148 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
149
150 wnd = ds_client_first_window(client);
151 PCUT_ASSERT_EQUALS(w0, wnd);
152
153 wnd = ds_client_next_window(w0);
154 PCUT_ASSERT_EQUALS(w1, wnd);
155
156 wnd = ds_client_next_window(w1);
157 PCUT_ASSERT_NULL(wnd);
158
159 ds_window_destroy(w0);
160 ds_window_destroy(w1);
161 ds_client_destroy(client);
162 ds_display_destroy(disp);
163}
164
165/** Test ds_client_get_event(), ds_client_post_close_event(). */
166PCUT_TEST(client_get_post_close_event)
167{
168 ds_display_t *disp;
169 ds_client_t *client;
170 ds_window_t *wnd;
171 display_wnd_params_t params;
172 ds_window_t *rwindow;
173 display_wnd_ev_t revent;
174 bool called_cb = NULL;
175 errno_t rc;
176
177 rc = ds_display_create(NULL, df_none, &disp);
178 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
179
180 rc = ds_client_create(disp, &test_ds_client_cb, &called_cb, &client);
181 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
182
183 display_wnd_params_init(&params);
184 params.rect.p0.x = params.rect.p0.y = 0;
185 params.rect.p1.x = params.rect.p1.y = 1;
186
187 rc = ds_window_create(client, &params, &wnd);
188 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
189
190 PCUT_ASSERT_FALSE(called_cb);
191
192 rc = ds_client_get_event(client, &rwindow, &revent);
193 PCUT_ASSERT_ERRNO_VAL(ENOENT, rc);
194
195 rc = ds_client_post_close_event(client, wnd);
196 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
197 PCUT_ASSERT_TRUE(called_cb);
198
199 rc = ds_client_get_event(client, &rwindow, &revent);
200 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
201 PCUT_ASSERT_EQUALS(wnd, rwindow);
202 PCUT_ASSERT_EQUALS(wev_close, revent.etype);
203
204 rc = ds_client_get_event(client, &rwindow, &revent);
205 PCUT_ASSERT_ERRNO_VAL(ENOENT, rc);
206
207 ds_window_destroy(wnd);
208 ds_client_destroy(client);
209 ds_display_destroy(disp);
210}
211
212/** Test ds_client_get_event(), ds_client_post_focus_event(). */
213PCUT_TEST(client_get_post_focus_event)
214{
215 ds_display_t *disp;
216 ds_client_t *client;
217 ds_window_t *wnd;
218 display_wnd_params_t params;
219 ds_window_t *rwindow;
220 display_wnd_ev_t revent;
221 bool called_cb = NULL;
222 errno_t rc;
223
224 rc = ds_display_create(NULL, df_none, &disp);
225 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
226
227 rc = ds_client_create(disp, &test_ds_client_cb, &called_cb, &client);
228 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
229
230 display_wnd_params_init(&params);
231 params.rect.p0.x = params.rect.p0.y = 0;
232 params.rect.p1.x = params.rect.p1.y = 1;
233
234 rc = ds_window_create(client, &params, &wnd);
235 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
236
237 PCUT_ASSERT_FALSE(called_cb);
238
239 rc = ds_client_get_event(client, &rwindow, &revent);
240 PCUT_ASSERT_ERRNO_VAL(ENOENT, rc);
241
242 rc = ds_client_post_focus_event(client, wnd);
243 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
244 PCUT_ASSERT_TRUE(called_cb);
245
246 rc = ds_client_get_event(client, &rwindow, &revent);
247 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
248 PCUT_ASSERT_EQUALS(wnd, rwindow);
249 PCUT_ASSERT_EQUALS(wev_focus, revent.etype);
250
251 rc = ds_client_get_event(client, &rwindow, &revent);
252 PCUT_ASSERT_ERRNO_VAL(ENOENT, rc);
253
254 ds_window_destroy(wnd);
255 ds_client_destroy(client);
256 ds_display_destroy(disp);
257}
258
259/** Test ds_client_get_event(), ds_client_post_kbd_event(). */
260PCUT_TEST(client_get_post_kbd_event)
261{
262 ds_display_t *disp;
263 ds_client_t *client;
264 ds_window_t *wnd;
265 display_wnd_params_t params;
266 kbd_event_t event;
267 ds_window_t *rwindow;
268 display_wnd_ev_t revent;
269 bool called_cb = NULL;
270 errno_t rc;
271
272 rc = ds_display_create(NULL, df_none, &disp);
273 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
274
275 rc = ds_client_create(disp, &test_ds_client_cb, &called_cb, &client);
276 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
277
278 display_wnd_params_init(&params);
279 params.rect.p0.x = params.rect.p0.y = 0;
280 params.rect.p1.x = params.rect.p1.y = 1;
281
282 rc = ds_window_create(client, &params, &wnd);
283 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
284
285 event.type = KEY_PRESS;
286 event.key = KC_ENTER;
287 event.mods = 0;
288 event.c = L'\0';
289
290 PCUT_ASSERT_FALSE(called_cb);
291
292 rc = ds_client_get_event(client, &rwindow, &revent);
293 PCUT_ASSERT_ERRNO_VAL(ENOENT, rc);
294
295 rc = ds_client_post_kbd_event(client, wnd, &event);
296 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
297 PCUT_ASSERT_TRUE(called_cb);
298
299 rc = ds_client_get_event(client, &rwindow, &revent);
300 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
301 PCUT_ASSERT_EQUALS(wnd, rwindow);
302 PCUT_ASSERT_EQUALS(wev_kbd, revent.etype);
303 PCUT_ASSERT_EQUALS(event.type, revent.ev.kbd.type);
304 PCUT_ASSERT_EQUALS(event.key, revent.ev.kbd.key);
305 PCUT_ASSERT_EQUALS(event.mods, revent.ev.kbd.mods);
306 PCUT_ASSERT_EQUALS(event.c, revent.ev.kbd.c);
307
308 rc = ds_client_get_event(client, &rwindow, &revent);
309 PCUT_ASSERT_ERRNO_VAL(ENOENT, rc);
310
311 ds_window_destroy(wnd);
312 ds_client_destroy(client);
313 ds_display_destroy(disp);
314}
315
316/** Test ds_client_get_event(), ds_client_post_pos_event(). */
317PCUT_TEST(client_get_post_pos_event)
318{
319 ds_display_t *disp;
320 ds_client_t *client;
321 ds_window_t *wnd;
322 display_wnd_params_t params;
323 pos_event_t event;
324 ds_window_t *rwindow;
325 display_wnd_ev_t revent;
326 bool called_cb = NULL;
327 errno_t rc;
328
329 rc = ds_display_create(NULL, df_none, &disp);
330 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
331
332 rc = ds_client_create(disp, &test_ds_client_cb, &called_cb, &client);
333 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
334
335 display_wnd_params_init(&params);
336 params.rect.p0.x = params.rect.p0.y = 0;
337 params.rect.p1.x = params.rect.p1.y = 1;
338
339 rc = ds_window_create(client, &params, &wnd);
340 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
341
342 event.type = POS_PRESS;
343 event.hpos = 1;
344 event.vpos = 2;
345
346 PCUT_ASSERT_FALSE(called_cb);
347
348 rc = ds_client_get_event(client, &rwindow, &revent);
349 PCUT_ASSERT_ERRNO_VAL(ENOENT, rc);
350
351 rc = ds_client_post_pos_event(client, wnd, &event);
352 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
353 PCUT_ASSERT_TRUE(called_cb);
354
355 rc = ds_client_get_event(client, &rwindow, &revent);
356 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
357 PCUT_ASSERT_EQUALS(wnd, rwindow);
358 PCUT_ASSERT_EQUALS(wev_pos, revent.etype);
359 PCUT_ASSERT_EQUALS(event.type, revent.ev.pos.type);
360 PCUT_ASSERT_EQUALS(event.hpos, revent.ev.pos.hpos);
361 PCUT_ASSERT_EQUALS(event.vpos, revent.ev.pos.vpos);
362
363 rc = ds_client_get_event(client, &rwindow, &revent);
364 PCUT_ASSERT_ERRNO_VAL(ENOENT, rc);
365
366 ds_window_destroy(wnd);
367 ds_client_destroy(client);
368 ds_display_destroy(disp);
369}
370
371/** Test ds_client_get_event(), ds_client_post_resize_event(). */
372PCUT_TEST(client_get_post_resize_event)
373{
374 ds_display_t *disp;
375 ds_client_t *client;
376 ds_window_t *wnd;
377 display_wnd_params_t params;
378 gfx_rect_t rect;
379 ds_window_t *rwindow;
380 display_wnd_ev_t revent;
381 bool called_cb = NULL;
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 display_wnd_params_init(&params);
391 params.rect.p0.x = params.rect.p0.y = 0;
392 params.rect.p1.x = params.rect.p1.y = 1;
393
394 rc = ds_window_create(client, &params, &wnd);
395 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
396
397 rect.p0.x = 1;
398 rect.p0.y = 2;
399 rect.p1.x = 3;
400 rect.p1.y = 4;
401
402 PCUT_ASSERT_FALSE(called_cb);
403
404 rc = ds_client_get_event(client, &rwindow, &revent);
405 PCUT_ASSERT_ERRNO_VAL(ENOENT, rc);
406
407 rc = ds_client_post_resize_event(client, wnd, &rect);
408 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
409 PCUT_ASSERT_TRUE(called_cb);
410
411 rc = ds_client_get_event(client, &rwindow, &revent);
412 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
413 PCUT_ASSERT_EQUALS(wnd, rwindow);
414 PCUT_ASSERT_EQUALS(wev_resize, revent.etype);
415 PCUT_ASSERT_EQUALS(rect.p0.x, revent.ev.resize.rect.p0.x);
416 PCUT_ASSERT_EQUALS(rect.p0.y, revent.ev.resize.rect.p0.y);
417 PCUT_ASSERT_EQUALS(rect.p1.x, revent.ev.resize.rect.p1.x);
418 PCUT_ASSERT_EQUALS(rect.p1.y, revent.ev.resize.rect.p1.y);
419
420 rc = ds_client_get_event(client, &rwindow, &revent);
421 PCUT_ASSERT_ERRNO_VAL(ENOENT, rc);
422
423 ds_window_destroy(wnd);
424 ds_client_destroy(client);
425 ds_display_destroy(disp);
426}
427
428/** Test ds_client_get_event(), ds_client_post_unfocus_event(). */
429PCUT_TEST(client_get_post_unfocus_event)
430{
431 ds_display_t *disp;
432 ds_client_t *client;
433 ds_window_t *wnd;
434 display_wnd_params_t params;
435 ds_window_t *rwindow;
436 display_wnd_ev_t revent;
437 bool called_cb = NULL;
438 errno_t rc;
439
440 rc = ds_display_create(NULL, df_none, &disp);
441 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
442
443 rc = ds_client_create(disp, &test_ds_client_cb, &called_cb, &client);
444 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
445
446 display_wnd_params_init(&params);
447 params.rect.p0.x = params.rect.p0.y = 0;
448 params.rect.p1.x = params.rect.p1.y = 1;
449
450 rc = ds_window_create(client, &params, &wnd);
451 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
452
453 PCUT_ASSERT_FALSE(called_cb);
454
455 rc = ds_client_get_event(client, &rwindow, &revent);
456 PCUT_ASSERT_ERRNO_VAL(ENOENT, rc);
457
458 rc = ds_client_post_unfocus_event(client, wnd);
459 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
460 PCUT_ASSERT_TRUE(called_cb);
461
462 rc = ds_client_get_event(client, &rwindow, &revent);
463 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
464 PCUT_ASSERT_EQUALS(wnd, rwindow);
465 PCUT_ASSERT_EQUALS(wev_unfocus, revent.etype);
466
467 rc = ds_client_get_event(client, &rwindow, &revent);
468 PCUT_ASSERT_ERRNO_VAL(ENOENT, rc);
469
470 ds_window_destroy(wnd);
471 ds_client_destroy(client);
472 ds_display_destroy(disp);
473}
474
475/** Test client being destroyed while still having a window.
476 *
477 * This can happen if client forgets to destroy window or if the client
478 * is disconnected (or terminated).
479 */
480PCUT_TEST(client_leftover_window)
481{
482 ds_display_t *disp;
483 ds_client_t *client;
484 ds_window_t *wnd;
485 display_wnd_params_t params;
486 errno_t rc;
487
488 rc = ds_display_create(NULL, df_none, &disp);
489 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
490
491 rc = ds_client_create(disp, NULL, NULL, &client);
492 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
493
494 display_wnd_params_init(&params);
495 params.rect.p0.x = params.rect.p0.y = 0;
496 params.rect.p1.x = params.rect.p1.y = 1;
497
498 rc = ds_window_create(client, &params, &wnd);
499 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
500
501 ds_client_destroy(client);
502 ds_display_destroy(disp);
503}
504
505PCUT_EXPORT(client);
Note: See TracBrowser for help on using the repository browser.