source: mainline/uspace/lib/ui/test/window.c@ 0d71fd6

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

Revert "Create UI controls based on UI object…"

This was a mistake. Controls need ui_resource object, which must be
(at least currently) specific to a window and cannot be obtained from
ui_t.

  • Property mode set to 100644
File size: 15.3 KB
Line 
1/*
2 * Copyright (c) 2020 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 <gfx/context.h>
30#include <gfx/coord.h>
31#include <io/kbd_event.h>
32#include <io/pos_event.h>
33#include <mem.h>
34#include <pcut/pcut.h>
35#include <stdbool.h>
36#include <ui/control.h>
37#include <ui/resource.h>
38#include <ui/ui.h>
39#include <ui/window.h>
40#include "../private/window.h"
41
42PCUT_INIT;
43
44PCUT_TEST_SUITE(window);
45
46static void test_window_close(ui_window_t *, void *);
47static void test_window_focus(ui_window_t *, void *);
48static void test_window_kbd(ui_window_t *, void *, kbd_event_t *);
49static errno_t test_window_paint(ui_window_t *, void *);
50static void test_window_pos(ui_window_t *, void *, pos_event_t *);
51static void test_window_unfocus(ui_window_t *, void *);
52
53static ui_window_cb_t test_window_cb = {
54 .close = test_window_close,
55 .focus = test_window_focus,
56 .kbd = test_window_kbd,
57 .paint = test_window_paint,
58 .pos = test_window_pos,
59 .unfocus = test_window_unfocus
60};
61
62static ui_window_cb_t dummy_window_cb = {
63};
64
65static errno_t test_ctl_paint(void *);
66static ui_evclaim_t test_ctl_pos_event(void *, pos_event_t *);
67
68static ui_control_ops_t test_ctl_ops = {
69 .paint = test_ctl_paint,
70 .pos_event = test_ctl_pos_event
71};
72
73typedef struct {
74 errno_t rc;
75 bool close;
76 bool focus;
77 bool kbd;
78 kbd_event_t kbd_event;
79 bool paint;
80 bool pos;
81 pos_event_t pos_event;
82 bool unfocus;
83} test_cb_resp_t;
84
85typedef struct {
86 errno_t rc;
87 ui_evclaim_t claim;
88 bool paint;
89 bool pos;
90 pos_event_t pos_event;
91} test_ctl_resp_t;
92
93/** Create and destroy window */
94PCUT_TEST(create_destroy)
95{
96 errno_t rc;
97 ui_t *ui = NULL;
98 ui_wnd_params_t params;
99 ui_window_t *window = NULL;
100
101 rc = ui_create_disp(NULL, &ui);
102 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
103
104 ui_wnd_params_init(&params);
105 params.caption = "Hello";
106
107 rc = ui_window_create(ui, &params, &window);
108 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
109 PCUT_ASSERT_NOT_NULL(window);
110
111 ui_window_destroy(window);
112 ui_destroy(ui);
113}
114
115/** ui_window_destroy() can take NULL argument (no-op) */
116PCUT_TEST(destroy_null)
117{
118 ui_window_destroy(NULL);
119}
120
121/** ui_window_add()/ui_window_remove() ... */
122PCUT_TEST(add_remove)
123{
124 errno_t rc;
125 ui_t *ui = NULL;
126 ui_wnd_params_t params;
127 ui_window_t *window = NULL;
128 ui_control_t *control = NULL;
129 test_ctl_resp_t resp;
130
131 rc = ui_create_disp(NULL, &ui);
132 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
133
134 ui_wnd_params_init(&params);
135 params.caption = "Hello";
136
137 rc = ui_window_create(ui, &params, &window);
138 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
139 PCUT_ASSERT_NOT_NULL(window);
140
141 rc = ui_control_new(&test_ctl_ops, &resp, &control);
142 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
143
144 /* Control not called since it hasn't been added yet */
145 resp.rc = ENOMEM;
146 resp.paint = false;
147 rc = ui_window_def_paint(window);
148 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
149 PCUT_ASSERT_FALSE(resp.paint);
150
151 ui_window_add(window, control);
152
153 /* Now paint request should be delivered to control */
154 resp.rc = EOK;
155 resp.paint = false;
156 rc = ui_window_def_paint(window);
157 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
158 PCUT_ASSERT_TRUE(resp.paint);
159
160 ui_window_remove(window, control);
161
162 /*
163 * After having removed the control the request should no longer
164 * be delivered to it.
165 */
166 resp.rc = ENOMEM;
167 resp.paint = false;
168 rc = ui_window_def_paint(window);
169 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
170 PCUT_ASSERT_FALSE(resp.paint);
171
172 ui_window_destroy(window);
173 ui_destroy(ui);
174}
175
176/** ui_window_get_res/gc/rect() return valid objects */
177PCUT_TEST(get_res_gc_rect)
178{
179 errno_t rc;
180 ui_t *ui = NULL;
181 ui_wnd_params_t params;
182 ui_window_t *window = NULL;
183 ui_resource_t *res;
184 gfx_context_t *gc;
185 gfx_rect_t rect;
186
187 rc = ui_create_disp(NULL, &ui);
188 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
189
190 ui_wnd_params_init(&params);
191 params.caption = "Hello";
192
193 rc = ui_window_create(ui, &params, &window);
194 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
195 PCUT_ASSERT_NOT_NULL(window);
196
197 res = ui_window_get_res(window);
198 PCUT_ASSERT_NOT_NULL(res);
199
200 gc = ui_window_get_gc(window);
201 PCUT_ASSERT_NOT_NULL(gc);
202
203 ui_window_get_app_rect(window, &rect);
204
205 ui_window_destroy(window);
206 ui_destroy(ui);
207}
208
209/** Test ui_window_paint() */
210PCUT_TEST(paint)
211{
212 errno_t rc;
213 ui_t *ui = NULL;
214 ui_wnd_params_t params;
215 ui_window_t *window = NULL;
216
217 rc = ui_create_disp(NULL, &ui);
218 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
219
220 ui_wnd_params_init(&params);
221 params.caption = "Hello";
222
223 rc = ui_window_create(ui, &params, &window);
224 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
225 PCUT_ASSERT_NOT_NULL(window);
226
227 ui_window_paint(window);
228
229 ui_window_destroy(window);
230 ui_destroy(ui);
231}
232
233/** Test ui_window_def_paint() */
234PCUT_TEST(def_paint)
235{
236 errno_t rc;
237 ui_t *ui = NULL;
238 ui_wnd_params_t params;
239 ui_window_t *window = NULL;
240 ui_control_t *control = NULL;
241 test_ctl_resp_t resp;
242
243 rc = ui_create_disp(NULL, &ui);
244 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
245
246 ui_wnd_params_init(&params);
247 params.caption = "Hello";
248
249 rc = ui_window_create(ui, &params, &window);
250 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
251 PCUT_ASSERT_NOT_NULL(window);
252
253 rc = ui_control_new(&test_ctl_ops, &resp, &control);
254 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
255
256 ui_window_add(window, control);
257
258 resp.rc = EOK;
259 resp.paint = false;
260 rc = ui_window_def_paint(window);
261 PCUT_ASSERT_ERRNO_VAL(resp.rc, rc);
262 PCUT_ASSERT_TRUE(resp.paint);
263
264 resp.rc = ENOMEM;
265 resp.paint = false;
266 rc = ui_window_def_paint(window);
267 PCUT_ASSERT_ERRNO_VAL(resp.rc, rc);
268 PCUT_ASSERT_TRUE(resp.paint);
269
270 PCUT_ASSERT_TRUE(resp.paint);
271
272 /* Need to remove first because we didn't implement the destructor */
273 ui_window_remove(window, control);
274
275 ui_window_destroy(window);
276 ui_destroy(ui);
277}
278
279/** ui_window_def_pos() delivers position event to control in window */
280PCUT_TEST(def_pos)
281{
282 errno_t rc;
283 ui_t *ui = NULL;
284 ui_wnd_params_t params;
285 ui_window_t *window = NULL;
286 ui_control_t *control = NULL;
287 test_ctl_resp_t resp;
288 pos_event_t event;
289
290 rc = ui_create_disp(NULL, &ui);
291 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
292
293 ui_wnd_params_init(&params);
294 params.caption = "Hello";
295
296 rc = ui_window_create(ui, &params, &window);
297 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
298
299 rc = ui_control_new(&test_ctl_ops, &resp, &control);
300 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
301
302 ui_window_add(window, control);
303
304 event.pos_id = 1;
305 event.type = POS_PRESS;
306 event.btn_num = 2;
307 event.hpos = 3;
308 event.vpos = 4;
309
310 resp.pos = false;
311 resp.claim = ui_claimed;
312
313 ui_window_def_pos(window, &event);
314
315 PCUT_ASSERT_TRUE(resp.pos);
316 PCUT_ASSERT_INT_EQUALS(event.pos_id, resp.pos_event.pos_id);
317 PCUT_ASSERT_INT_EQUALS(event.type, resp.pos_event.type);
318 PCUT_ASSERT_INT_EQUALS(event.btn_num, resp.pos_event.btn_num);
319 PCUT_ASSERT_INT_EQUALS(event.hpos, resp.pos_event.hpos);
320 PCUT_ASSERT_INT_EQUALS(event.vpos, resp.pos_event.vpos);
321
322 /* Need to remove first because we didn't implement the destructor */
323 ui_window_remove(window, control);
324
325 ui_window_destroy(window);
326 ui_destroy(ui);
327}
328
329/** ui_window_send_close() calls close callback set via ui_window_set_cb() */
330PCUT_TEST(send_close)
331{
332 errno_t rc;
333 ui_t *ui = NULL;
334 ui_wnd_params_t params;
335 ui_window_t *window = NULL;
336 test_cb_resp_t resp;
337
338 rc = ui_create_disp(NULL, &ui);
339 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
340
341 ui_wnd_params_init(&params);
342 params.caption = "Hello";
343
344 rc = ui_window_create(ui, &params, &window);
345 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
346 PCUT_ASSERT_NOT_NULL(window);
347
348 /* Close callback with no callbacks set */
349 ui_window_send_close(window);
350
351 /* Close callback with close callback not implemented */
352 ui_window_set_cb(window, &dummy_window_cb, NULL);
353 ui_window_send_close(window);
354
355 /* Close callback with real callback set */
356 resp.close = false;
357 ui_window_set_cb(window, &test_window_cb, &resp);
358 ui_window_send_close(window);
359 PCUT_ASSERT_TRUE(resp.close);
360
361 ui_window_destroy(window);
362 ui_destroy(ui);
363}
364
365/** ui_window_send_focus() calls focus callback set via ui_window_set_cb() */
366PCUT_TEST(send_focus)
367{
368 errno_t rc;
369 ui_t *ui = NULL;
370 ui_wnd_params_t params;
371 ui_window_t *window = NULL;
372 test_cb_resp_t resp;
373
374 rc = ui_create_disp(NULL, &ui);
375 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
376
377 ui_wnd_params_init(&params);
378 params.caption = "Hello";
379
380 rc = ui_window_create(ui, &params, &window);
381 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
382 PCUT_ASSERT_NOT_NULL(window);
383
384 /* Focus callback with no callbacks set */
385 ui_window_send_focus(window);
386
387 /* Focus callback with focus callback not implemented */
388 ui_window_set_cb(window, &dummy_window_cb, NULL);
389 ui_window_send_focus(window);
390
391 /* Focus callback with real callback set */
392 resp.focus = false;
393 ui_window_set_cb(window, &test_window_cb, &resp);
394 ui_window_send_focus(window);
395 PCUT_ASSERT_TRUE(resp.focus);
396
397 ui_window_destroy(window);
398 ui_destroy(ui);
399}
400
401/** ui_window_send_kbd() calls kbd callback set via ui_window_set_cb() */
402PCUT_TEST(send_kbd)
403{
404 errno_t rc;
405 ui_t *ui = NULL;
406 ui_wnd_params_t params;
407 ui_window_t *window = NULL;
408 kbd_event_t kbd_event;
409 test_cb_resp_t resp;
410
411 rc = ui_create_disp(NULL, &ui);
412 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
413
414 ui_wnd_params_init(&params);
415 params.caption = "Hello";
416
417 rc = ui_window_create(ui, &params, &window);
418 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
419 PCUT_ASSERT_NOT_NULL(window);
420
421 kbd_event.type = POS_PRESS;
422 kbd_event.key = KC_X;
423 kbd_event.mods = 0;
424 kbd_event.c = 'x';
425
426 /* Kbd callback with no callbacks set */
427 ui_window_send_kbd(window, &kbd_event);
428
429 /* Kbd callback with kbd callback not implemented */
430 ui_window_set_cb(window, &dummy_window_cb, NULL);
431 ui_window_send_kbd(window, &kbd_event);
432
433 /* Kbd callback with real callback set */
434 resp.kbd = false;
435 ui_window_set_cb(window, &test_window_cb, &resp);
436 ui_window_send_kbd(window, &kbd_event);
437 PCUT_ASSERT_TRUE(resp.kbd);
438 PCUT_ASSERT_EQUALS(kbd_event.type, resp.kbd_event.type);
439 PCUT_ASSERT_INT_EQUALS(kbd_event.key, resp.kbd_event.key);
440 PCUT_ASSERT_INT_EQUALS(kbd_event.mods, resp.kbd_event.mods);
441 PCUT_ASSERT_INT_EQUALS(kbd_event.c, resp.kbd_event.c);
442
443 ui_window_destroy(window);
444 ui_destroy(ui);
445}
446
447/** ui_window_send_paint() calls paint callback set via ui_window_set_cb() */
448PCUT_TEST(send_paint)
449{
450 errno_t rc;
451 ui_t *ui = NULL;
452 ui_wnd_params_t params;
453 ui_window_t *window = NULL;
454 test_cb_resp_t resp;
455
456 rc = ui_create_disp(NULL, &ui);
457 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
458
459 ui_wnd_params_init(&params);
460 params.caption = "Hello";
461
462 rc = ui_window_create(ui, &params, &window);
463 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
464 PCUT_ASSERT_NOT_NULL(window);
465
466 /* Paint callback with no callbacks set */
467 ui_window_send_paint(window);
468
469 /* Paint callback with paint callback not implemented */
470 ui_window_set_cb(window, &dummy_window_cb, NULL);
471 ui_window_send_paint(window);
472
473 /* Paint callback with real callback set */
474 resp.paint = false;
475 resp.rc = EOK;
476 ui_window_set_cb(window, &test_window_cb, &resp);
477 rc = ui_window_send_paint(window);
478 PCUT_ASSERT_ERRNO_VAL(resp.rc, rc);
479 PCUT_ASSERT_TRUE(resp.paint);
480
481 ui_window_destroy(window);
482 ui_destroy(ui);
483}
484
485/** ui_window_send_pos() calls pos callback set via ui_window_set_cb() */
486PCUT_TEST(send_pos)
487{
488 errno_t rc;
489 ui_t *ui = NULL;
490 ui_wnd_params_t params;
491 ui_window_t *window = NULL;
492 pos_event_t pos_event;
493 test_cb_resp_t resp;
494
495 rc = ui_create_disp(NULL, &ui);
496 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
497
498 ui_wnd_params_init(&params);
499 params.caption = "Hello";
500
501 rc = ui_window_create(ui, &params, &window);
502 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
503 PCUT_ASSERT_NOT_NULL(window);
504
505 pos_event.pos_id = 1;
506 pos_event.type = POS_PRESS;
507 pos_event.btn_num = 2;
508 pos_event.hpos = 3;
509 pos_event.vpos = 4;
510
511 /* Pos callback with no callbacks set */
512 ui_window_send_pos(window, &pos_event);
513
514 /* Pos callback with pos callback not implemented */
515 ui_window_set_cb(window, &dummy_window_cb, NULL);
516 ui_window_send_pos(window, &pos_event);
517
518 /* Pos callback with real callback set */
519 resp.pos = false;
520 ui_window_set_cb(window, &test_window_cb, &resp);
521 ui_window_send_pos(window, &pos_event);
522 PCUT_ASSERT_TRUE(resp.pos);
523 PCUT_ASSERT_INT_EQUALS(pos_event.pos_id, resp.pos_event.pos_id);
524 PCUT_ASSERT_EQUALS(pos_event.type, resp.pos_event.type);
525 PCUT_ASSERT_INT_EQUALS(pos_event.btn_num, resp.pos_event.btn_num);
526 PCUT_ASSERT_INT_EQUALS(pos_event.hpos, resp.pos_event.hpos);
527 PCUT_ASSERT_INT_EQUALS(pos_event.vpos, resp.pos_event.vpos);
528
529 ui_window_destroy(window);
530 ui_destroy(ui);
531}
532
533/** ui_window_send_unfocus() calls unfocus callback set via ui_window_set_cb() */
534PCUT_TEST(send_unfocus)
535{
536 errno_t rc;
537 ui_t *ui = NULL;
538 ui_wnd_params_t params;
539 ui_window_t *window = NULL;
540 test_cb_resp_t resp;
541
542 rc = ui_create_disp(NULL, &ui);
543 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
544
545 ui_wnd_params_init(&params);
546 params.caption = "Hello";
547
548 rc = ui_window_create(ui, &params, &window);
549 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
550 PCUT_ASSERT_NOT_NULL(window);
551
552 /* Unfocus callback with no callbacks set */
553 ui_window_send_unfocus(window);
554
555 /* Unfocus callback with unfocus callback not implemented */
556 ui_window_set_cb(window, &dummy_window_cb, NULL);
557 ui_window_send_unfocus(window);
558
559 /* Unfocus callback with real callback set */
560 resp.close = false;
561 ui_window_set_cb(window, &test_window_cb, &resp);
562 ui_window_send_unfocus(window);
563 PCUT_ASSERT_TRUE(resp.unfocus);
564
565 ui_window_destroy(window);
566 ui_destroy(ui);
567}
568
569static void test_window_close(ui_window_t *window, void *arg)
570{
571 test_cb_resp_t *resp = (test_cb_resp_t *) arg;
572
573 resp->close = true;
574}
575
576static void test_window_focus(ui_window_t *window, void *arg)
577{
578 test_cb_resp_t *resp = (test_cb_resp_t *) arg;
579
580 resp->focus = true;
581}
582
583static void test_window_kbd(ui_window_t *window, void *arg,
584 kbd_event_t *event)
585{
586 test_cb_resp_t *resp = (test_cb_resp_t *) arg;
587
588 resp->kbd = true;
589 resp->kbd_event = *event;
590}
591
592static errno_t test_window_paint(ui_window_t *window, void *arg)
593{
594 test_cb_resp_t *resp = (test_cb_resp_t *) arg;
595
596 resp->paint = true;
597 return resp->rc;
598}
599
600static void test_window_pos(ui_window_t *window, void *arg,
601 pos_event_t *event)
602{
603 test_cb_resp_t *resp = (test_cb_resp_t *) arg;
604
605 resp->pos = true;
606 resp->pos_event = *event;
607}
608
609static void test_window_unfocus(ui_window_t *window, void *arg)
610{
611 test_cb_resp_t *resp = (test_cb_resp_t *) arg;
612
613 resp->unfocus = true;
614}
615
616static errno_t test_ctl_paint(void *arg)
617{
618 test_ctl_resp_t *resp = (test_ctl_resp_t *) arg;
619
620 resp->paint = true;
621 return resp->rc;
622}
623
624static ui_evclaim_t test_ctl_pos_event(void *arg, pos_event_t *event)
625{
626 test_ctl_resp_t *resp = (test_ctl_resp_t *) arg;
627
628 resp->pos = true;
629 resp->pos_event = *event;
630
631 return resp->claim;
632}
633
634PCUT_EXPORT(window);
Note: See TracBrowser for help on using the repository browser.