source: mainline/uspace/srv/hid/display/test/display.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@…>, 6 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: 10.2 KB
RevLine 
[c8cf261]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
[3434233]29#include <disp_srv.h>
[6af4b4f]30#include <errno.h>
31#include <pcut/pcut.h>
32#include <stdio.h>
33#include <str.h>
[c8cf261]34
[b3c185b6]35#include "../client.h"
[6af4b4f]36#include "../display.h"
[cf32dbd]37#include "../seat.h"
[b2d1df3]38#include "../window.h"
[c8cf261]39
[6af4b4f]40PCUT_INIT;
[c8cf261]41
[6af4b4f]42PCUT_TEST_SUITE(display);
[c8cf261]43
[be15256]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_ev_pending(void *arg)
51{
[b2d1df3]52 bool *called_cb = (bool *) arg;
[be15256]53 printf("test_ds_ev_pending\n");
[b2d1df3]54 *called_cb = true;
55}
[be15256]56
[6af4b4f]57/** Display creation and destruction. */
[bef51cf]58PCUT_TEST(display_create_destroy)
[6af4b4f]59{
60 ds_display_t *disp;
61 errno_t rc;
[c8cf261]62
[8aef01c]63 rc = ds_display_create(NULL, df_none, &disp);
[6af4b4f]64 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
65
66 ds_display_destroy(disp);
67}
68
[b3c185b6]69/** Basic client operation. */
70PCUT_TEST(display_client)
[bef51cf]71{
72 ds_display_t *disp;
[b3c185b6]73 ds_client_t *client;
74 ds_client_t *c0, *c1;
[bef51cf]75 errno_t rc;
76
[8aef01c]77 rc = ds_display_create(NULL, df_none, &disp);
[bef51cf]78 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
79
[be15256]80 rc = ds_client_create(disp, &test_ds_client_cb, NULL, &client);
[bef51cf]81 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
82
[b3c185b6]83 c0 = ds_display_first_client(disp);
84 PCUT_ASSERT_EQUALS(c0, client);
[bef51cf]85
[b3c185b6]86 c1 = ds_display_next_client(c0);
87 PCUT_ASSERT_NULL(c1);
[bef51cf]88
[b3c185b6]89 ds_client_destroy(client);
[bef51cf]90 ds_display_destroy(disp);
91}
92
[b2d1df3]93/** Test ds_display_find_window(). */
94PCUT_TEST(display_find_window)
95{
96 ds_display_t *disp;
97 ds_client_t *client;
98 ds_window_t *w0;
99 ds_window_t *w1;
100 ds_window_t *wnd;
[3434233]101 display_wnd_params_t params;
[b2d1df3]102 errno_t rc;
103
[8aef01c]104 rc = ds_display_create(NULL, df_none, &disp);
[b2d1df3]105 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
106
107 rc = ds_client_create(disp, &test_ds_client_cb, NULL, &client);
108 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
109
[3434233]110 display_wnd_params_init(&params);
111 params.rect.p0.x = params.rect.p0.y = 0;
112 params.rect.p1.x = params.rect.p1.y = 1;
113
114 rc = ds_window_create(client, &params, &w1);
[b2d1df3]115 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
116
[3434233]117 rc = ds_window_create(client, &params, &w0);
[b2d1df3]118 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
119
[bd1f9a6d]120 wnd = ds_display_first_window(disp);
121 PCUT_ASSERT_EQUALS(w0, wnd);
122
123 wnd = ds_display_next_window(wnd);
124 PCUT_ASSERT_EQUALS(w1, wnd);
125
126 wnd = ds_display_next_window(wnd);
127 PCUT_ASSERT_NULL(wnd);
128
[2012fe0]129 wnd = ds_display_last_window(disp);
130 PCUT_ASSERT_EQUALS(w1, wnd);
131
132 wnd = ds_display_prev_window(wnd);
133 PCUT_ASSERT_EQUALS(w0, wnd);
134
135 wnd = ds_display_prev_window(wnd);
136 PCUT_ASSERT_NULL(wnd);
137
[b2d1df3]138 wnd = ds_display_find_window(disp, w0->id);
139 PCUT_ASSERT_EQUALS(w0, wnd);
140
141 wnd = ds_display_find_window(disp, w1->id);
142 PCUT_ASSERT_EQUALS(w1, wnd);
143
144 wnd = ds_display_find_window(disp, 0);
145 PCUT_ASSERT_NULL(wnd);
146
[bd1f9a6d]147 wnd = ds_display_find_window(disp, w0->id + 1);
[b2d1df3]148 PCUT_ASSERT_NULL(wnd);
149
[648e2ac]150 ds_window_destroy(w0);
151 ds_window_destroy(w1);
[b2d1df3]152 ds_client_destroy(client);
153 ds_display_destroy(disp);
154}
155
[24cf391a]156/** Test ds_display_window_by_pos(). */
157PCUT_TEST(display_window_by_pos)
158{
159 ds_display_t *disp;
160 ds_client_t *client;
161 ds_window_t *w0;
162 ds_window_t *w1;
163 ds_window_t *wnd;
[3434233]164 display_wnd_params_t params;
[24cf391a]165 gfx_coord2_t pos;
166 errno_t rc;
167
[8aef01c]168 rc = ds_display_create(NULL, df_none, &disp);
[24cf391a]169 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
170
171 rc = ds_client_create(disp, &test_ds_client_cb, NULL, &client);
172 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
173
[3434233]174 display_wnd_params_init(&params);
175 params.rect.p0.x = params.rect.p0.y = 0;
176 params.rect.p1.x = params.rect.p1.y = 100;
177
178 rc = ds_window_create(client, &params, &w0);
[24cf391a]179 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
180
[3434233]181 rc = ds_window_create(client, &params, &w1);
[24cf391a]182 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
183
184 w0->dpos.x = 10;
185 w0->dpos.y = 10;
186
187 w1->dpos.x = 400;
188 w1->dpos.y = 400;
189
190 pos.x = 10;
191 pos.y = 10;
192 wnd = ds_display_window_by_pos(disp, &pos);
193 PCUT_ASSERT_EQUALS(w0, wnd);
194
195 pos.x = 400;
196 pos.y = 400;
197 wnd = ds_display_window_by_pos(disp, &pos);
198 PCUT_ASSERT_EQUALS(w1, wnd);
199
200 ds_window_destroy(w0);
201 ds_window_destroy(w1);
202 ds_client_destroy(client);
203 ds_display_destroy(disp);
204}
205
[cf32dbd]206/** Basic seat operation. */
207PCUT_TEST(display_seat)
208{
209 ds_display_t *disp;
210 ds_seat_t *seat;
211 ds_seat_t *s0, *s1;
212 errno_t rc;
213
[8aef01c]214 rc = ds_display_create(NULL, df_none, &disp);
[cf32dbd]215 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
216
217 rc = ds_seat_create(disp, &seat);
218 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
219
220 s0 = ds_display_first_seat(disp);
221 PCUT_ASSERT_EQUALS(s0, seat);
222
223 s1 = ds_display_next_seat(s0);
224 PCUT_ASSERT_NULL(s1);
225
226 ds_seat_destroy(seat);
227 ds_display_destroy(disp);
228}
229
[24cf391a]230/** Test ds_display_post_kbd_event() delivers event to client callback.
231 */
[b2d1df3]232PCUT_TEST(display_post_kbd_event)
233{
234 ds_display_t *disp;
[cf32dbd]235 ds_seat_t *seat;
[b2d1df3]236 ds_client_t *client;
237 ds_window_t *wnd;
[3434233]238 display_wnd_params_t params;
[b2d1df3]239 kbd_event_t event;
[24cf391a]240 bool called_cb = false;
[b2d1df3]241 errno_t rc;
242
[8aef01c]243 rc = ds_display_create(NULL, df_none, &disp);
[b2d1df3]244 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
245
[cf32dbd]246 rc = ds_seat_create(disp, &seat);
247 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
248
[b2d1df3]249 rc = ds_client_create(disp, &test_ds_client_cb, &called_cb, &client);
250 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
251
[3434233]252 display_wnd_params_init(&params);
253 params.rect.p0.x = params.rect.p0.y = 0;
254 params.rect.p1.x = params.rect.p1.y = 1;
255
256 rc = ds_window_create(client, &params, &wnd);
[b2d1df3]257 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
258
[94635b30]259 ds_seat_set_focus(seat, wnd);
260
[b2d1df3]261 event.type = KEY_PRESS;
262 event.key = KC_ENTER;
263 event.mods = 0;
264 event.c = L'\0';
265
[0e6e77f]266 called_cb = false;
[b2d1df3]267
268 rc = ds_display_post_kbd_event(disp, &event);
269 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
270 PCUT_ASSERT_TRUE(called_cb);
271
[648e2ac]272 ds_window_destroy(wnd);
[b2d1df3]273 ds_client_destroy(client);
[cf32dbd]274 ds_seat_destroy(seat);
[b2d1df3]275 ds_display_destroy(disp);
276}
277
[24cf391a]278/** Test ds_display_post_kbd_event() with Alt-Tab switches focus.
279 */
280PCUT_TEST(display_post_kbd_event_alt_tab)
281{
282 ds_display_t *disp;
283 ds_seat_t *seat;
284 ds_client_t *client;
285 ds_window_t *w0, *w1;
[3434233]286 display_wnd_params_t params;
[24cf391a]287 kbd_event_t event;
288 bool called_cb = false;
289 errno_t rc;
290
[8aef01c]291 rc = ds_display_create(NULL, df_none, &disp);
[24cf391a]292 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
293
294 rc = ds_seat_create(disp, &seat);
295 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
296
297 rc = ds_client_create(disp, &test_ds_client_cb, &called_cb, &client);
298 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
299
[3434233]300 display_wnd_params_init(&params);
301 params.rect.p0.x = params.rect.p0.y = 0;
302 params.rect.p1.x = params.rect.p1.y = 1;
303
304 rc = ds_window_create(client, &params, &w0);
[24cf391a]305 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
306
[3434233]307 rc = ds_window_create(client, &params, &w1);
[24cf391a]308 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
309
310 ds_seat_set_focus(seat, w0);
311
312 event.type = KEY_PRESS;
313 event.key = KC_TAB;
314 event.mods = KM_ALT;
315 event.c = L'\0';
316
[0e6e77f]317 called_cb = false;
[24cf391a]318
319 rc = ds_display_post_kbd_event(disp, &event);
320 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
[0e6e77f]321
322 /* Got gocus/unfocus events */
323 PCUT_ASSERT_TRUE(called_cb);
[24cf391a]324
325 /* Next window should be focused */
326 PCUT_ASSERT_EQUALS(w1, seat->focus);
327
[0e6e77f]328 called_cb = false;
329
[24cf391a]330 rc = ds_display_post_kbd_event(disp, &event);
331 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
[0e6e77f]332
333 /* Got gocus/unfocus events */
334 PCUT_ASSERT_TRUE(called_cb);
[24cf391a]335
336 /* Focus should be back to the first window */
337 PCUT_ASSERT_EQUALS(w0, seat->focus);
338
339 ds_window_destroy(w0);
340 ds_window_destroy(w1);
341 ds_client_destroy(client);
342 ds_seat_destroy(seat);
343 ds_display_destroy(disp);
344}
345
[4fbdc3d]346/** Test ds_display_post_ptd_event() with click on window switches focus
[24cf391a]347 */
[4fbdc3d]348PCUT_TEST(display_post_ptd_event_wnd_switch)
[24cf391a]349{
350 ds_display_t *disp;
351 ds_seat_t *seat;
352 ds_client_t *client;
353 ds_window_t *w0, *w1;
[3434233]354 display_wnd_params_t params;
[4fbdc3d]355 ptd_event_t event;
[24cf391a]356 bool called_cb = false;
357 errno_t rc;
358
[8aef01c]359 rc = ds_display_create(NULL, df_none, &disp);
[24cf391a]360 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
361
362 rc = ds_seat_create(disp, &seat);
363 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
364
365 rc = ds_client_create(disp, &test_ds_client_cb, &called_cb, &client);
366 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
367
[0e6e77f]368 /*
369 * For PTD_MOVE to work we need to set display dimensions (as pointer
370 * move is clipped to the display rectangle. Here we do it directly
371 * instead of adding a display device.
372 */
373 disp->rect.p0.x = 0;
374 disp->rect.p0.y = 0;
375 disp->rect.p1.x = 500;
376 disp->rect.p1.y = 500;
377
[3434233]378 display_wnd_params_init(&params);
379 params.rect.p0.x = params.rect.p0.y = 0;
380 params.rect.p1.x = params.rect.p1.y = 1;
381
382 rc = ds_window_create(client, &params, &w0);
[24cf391a]383 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
384
[3434233]385 rc = ds_window_create(client, &params, &w1);
[24cf391a]386 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
387
388 w0->dpos.x = 10;
389 w0->dpos.y = 10;
390
391 w1->dpos.x = 400;
392 w1->dpos.y = 400;
393
[4fbdc3d]394 ds_seat_set_focus(seat, w0);
[24cf391a]395
[4fbdc3d]396 event.type = PTD_MOVE;
397 event.dmove.x = 400;
398 event.dmove.y = 400;
399 rc = ds_display_post_ptd_event(disp, &event);
400 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
[24cf391a]401
[4fbdc3d]402 event.type = PTD_PRESS;
403 event.btn_num = 1;
404 rc = ds_display_post_ptd_event(disp, &event);
[24cf391a]405 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
406
407 PCUT_ASSERT_EQUALS(w1, seat->focus);
408
[f5191b4]409 event.type = PTD_RELEASE;
410 event.btn_num = 1;
411 rc = ds_display_post_ptd_event(disp, &event);
412 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
413
[4fbdc3d]414 event.type = PTD_MOVE;
[a40ae0d]415 event.dmove.x = -400 + 10;
416 event.dmove.y = -400 + 10;
[4fbdc3d]417 rc = ds_display_post_ptd_event(disp, &event);
418 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
419
420 event.type = PTD_PRESS;
421 event.btn_num = 1;
422 rc = ds_display_post_ptd_event(disp, &event);
[24cf391a]423 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
424
425 PCUT_ASSERT_EQUALS(w0, seat->focus);
426
427 ds_window_destroy(w0);
428 ds_window_destroy(w1);
429 ds_client_destroy(client);
430 ds_seat_destroy(seat);
431 ds_display_destroy(disp);
432}
433
[6af4b4f]434PCUT_EXPORT(display);
Note: See TracBrowser for help on using the repository browser.