source: mainline/uspace/lib/ui/test/menubar.c@ 5de852c

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

Coordinate keyboard event delivery between application and UI framework

If an application sets its own keyboard event handler, it needs to call
ui_window_def_kbd() to deliver events to the window's UI control tree.
Menubar should be able to capture these events so that they are not
accidentally acted upon by the application keyboard handler.

  • Property mode set to 100644
File size: 9.1 KB
RevLine 
[95a9cbc]1/*
[59768c7]2 * Copyright (c) 2022 Jiri Svoboda
[95a9cbc]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/coord.h>
30#include <mem.h>
31#include <pcut/pcut.h>
32#include <stdbool.h>
33#include <ui/control.h>
34#include <ui/menu.h>
35#include <ui/menubar.h>
36#include <ui/ui.h>
[c68c18b9]37#include <ui/window.h>
[95a9cbc]38#include "../private/menubar.h"
39
40PCUT_INIT;
41
42PCUT_TEST_SUITE(menubar);
43
44/** Create and destroy menu bar */
45PCUT_TEST(create_destroy)
46{
47 ui_menu_bar_t *mbar = NULL;
48 errno_t rc;
49
[3c8c580]50 rc = ui_menu_bar_create(NULL, NULL, &mbar);
[95a9cbc]51 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
52 PCUT_ASSERT_NOT_NULL(mbar);
53
54 ui_menu_bar_destroy(mbar);
55}
56
57/** ui_menu_bar_destroy() can take NULL argument (no-op) */
58PCUT_TEST(destroy_null)
59{
60 ui_menu_bar_destroy(NULL);
61}
62
63/** ui_menu_bar_ctl() returns control that has a working virtual destructor */
64PCUT_TEST(ctl)
65{
66 ui_menu_bar_t *mbar = NULL;
67 ui_control_t *control;
68 errno_t rc;
69
[3c8c580]70 rc = ui_menu_bar_create(NULL, NULL, &mbar);
[95a9cbc]71 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
72 PCUT_ASSERT_NOT_NULL(mbar);
73
74 control = ui_menu_bar_ctl(mbar);
75 PCUT_ASSERT_NOT_NULL(control);
76
77 ui_control_destroy(control);
78}
79
80/** Set menu bar rectangle sets internal field */
81PCUT_TEST(set_rect)
82{
83 errno_t rc;
[c68c18b9]84 ui_t *ui = NULL;
85 ui_window_t *window = NULL;
86 ui_wnd_params_t params;
[95a9cbc]87 ui_menu_bar_t *mbar = NULL;
88 gfx_rect_t rect;
89
[c68c18b9]90 rc = ui_create_disp(NULL, &ui);
[95a9cbc]91 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
92
[c68c18b9]93 ui_wnd_params_init(&params);
94 params.caption = "Hello";
[95a9cbc]95
[c68c18b9]96 rc = ui_window_create(ui, &params, &window);
[95a9cbc]97 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
[c68c18b9]98 PCUT_ASSERT_NOT_NULL(window);
[95a9cbc]99
[c68c18b9]100 rc = ui_menu_bar_create(ui, window, &mbar);
[95a9cbc]101 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
102 PCUT_ASSERT_NOT_NULL(mbar);
103
104 rect.p0.x = 1;
105 rect.p0.y = 2;
106 rect.p1.x = 3;
107 rect.p1.y = 4;
108
109 ui_menu_bar_set_rect(mbar, &rect);
110 PCUT_ASSERT_INT_EQUALS(rect.p0.x, mbar->rect.p0.x);
111 PCUT_ASSERT_INT_EQUALS(rect.p0.y, mbar->rect.p0.y);
112 PCUT_ASSERT_INT_EQUALS(rect.p1.x, mbar->rect.p1.x);
113 PCUT_ASSERT_INT_EQUALS(rect.p1.y, mbar->rect.p1.y);
114
115 ui_menu_bar_destroy(mbar);
[c68c18b9]116 ui_window_destroy(window);
117 ui_destroy(ui);
[95a9cbc]118}
119
120/** Paint menu bar */
121PCUT_TEST(paint)
122{
[c68c18b9]123 ui_t *ui = NULL;
124 ui_window_t *window = NULL;
125 ui_wnd_params_t params;
[95a9cbc]126 ui_menu_bar_t *mbar = NULL;
127 errno_t rc;
128
[c68c18b9]129 rc = ui_create_disp(NULL, &ui);
[95a9cbc]130 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
131
[c68c18b9]132 ui_wnd_params_init(&params);
133 params.caption = "Hello";
[95a9cbc]134
[c68c18b9]135 rc = ui_window_create(ui, &params, &window);
[95a9cbc]136 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
[c68c18b9]137 PCUT_ASSERT_NOT_NULL(window);
[95a9cbc]138
[c68c18b9]139 rc = ui_menu_bar_create(ui, window, &mbar);
[95a9cbc]140 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
141 PCUT_ASSERT_NOT_NULL(mbar);
142
143 rc = ui_menu_bar_paint(mbar);
144 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
145
146 ui_menu_bar_destroy(mbar);
[c68c18b9]147 ui_window_destroy(window);
148 ui_destroy(ui);
[95a9cbc]149}
150
[59768c7]151/** Deliver menu bar keyboard event */
152PCUT_TEST(kbd_event)
153{
154 ui_t *ui = NULL;
155 ui_window_t *window = NULL;
156 ui_wnd_params_t params;
157 ui_menu_bar_t *mbar = NULL;
158 ui_menu_t *menu = NULL;
159 ui_evclaim_t claimed;
160 kbd_event_t event;
161 gfx_rect_t rect;
162 errno_t rc;
163
164 rc = ui_create_disp(NULL, &ui);
165 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
166
167 ui_wnd_params_init(&params);
168 params.caption = "Hello";
169
170 rc = ui_window_create(ui, &params, &window);
171 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
172 PCUT_ASSERT_NOT_NULL(window);
173
174 rc = ui_menu_bar_create(ui, window, &mbar);
175 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
176 PCUT_ASSERT_NOT_NULL(mbar);
177
178 rect.p0.x = 0;
179 rect.p0.y = 0;
180 rect.p1.x = 50;
181 rect.p1.y = 25;
182 ui_menu_bar_set_rect(mbar, &rect);
183
184 rc = ui_menu_create(mbar, "Test", &menu);
185 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
186 PCUT_ASSERT_NOT_NULL(menu);
187
188 event.type = KEY_PRESS;
189 event.key = KC_ESCAPE;
[5de852c]190 claimed = ui_menu_bar_kbd_event(mbar, &event);
[59768c7]191 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
192 PCUT_ASSERT_EQUALS(ui_claimed, claimed);
193
194 ui_menu_bar_destroy(mbar);
195 ui_window_destroy(window);
196 ui_destroy(ui);
197}
198
[95a9cbc]199/** Press event on menu bar entry selects menu */
200PCUT_TEST(pos_event_select)
201{
[3c8c580]202 ui_t *ui = NULL;
[c68c18b9]203 ui_window_t *window = NULL;
204 ui_wnd_params_t params;
[95a9cbc]205 ui_menu_bar_t *mbar = NULL;
206 ui_menu_t *menu = NULL;
207 ui_evclaim_t claimed;
208 pos_event_t event;
209 gfx_rect_t rect;
210 errno_t rc;
211
[3c8c580]212 rc = ui_create_disp(NULL, &ui);
213 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
214
[c68c18b9]215 ui_wnd_params_init(&params);
216 params.caption = "Hello";
217
218 rc = ui_window_create(ui, &params, &window);
[95a9cbc]219 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
[c68c18b9]220 PCUT_ASSERT_NOT_NULL(window);
[95a9cbc]221
[c68c18b9]222 rc = ui_menu_bar_create(ui, window, &mbar);
[95a9cbc]223 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
224 PCUT_ASSERT_NOT_NULL(mbar);
225
226 rect.p0.x = 0;
227 rect.p0.y = 0;
228 rect.p1.x = 50;
229 rect.p1.y = 25;
230 ui_menu_bar_set_rect(mbar, &rect);
231
232 rc = ui_menu_create(mbar, "Test", &menu);
233 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
234 PCUT_ASSERT_NOT_NULL(menu);
235
236 event.type = POS_PRESS;
237 event.hpos = 4;
238 event.vpos = 4;
239 claimed = ui_menu_bar_pos_event(mbar, &event);
240 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
241 PCUT_ASSERT_EQUALS(ui_claimed, claimed);
242
243 /* Clicking the menu bar entry should select menu */
244 PCUT_ASSERT_EQUALS(menu, mbar->selected);
245
246 ui_menu_bar_destroy(mbar);
[c68c18b9]247 ui_window_destroy(window);
[3c8c580]248 ui_destroy(ui);
[95a9cbc]249}
250
[3c8c580]251/** Calling ui_menu_bar_select() with the same menu twice deselects it */
252PCUT_TEST(select_same)
[95a9cbc]253{
[3c8c580]254 ui_t *ui = NULL;
[c68c18b9]255 ui_window_t *window = NULL;
256 ui_wnd_params_t params;
[95a9cbc]257 ui_menu_bar_t *mbar = NULL;
258 ui_menu_t *menu = NULL;
259 errno_t rc;
260
[3c8c580]261 rc = ui_create_disp(NULL, &ui);
[95a9cbc]262 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
263
[c68c18b9]264 ui_wnd_params_init(&params);
265 params.caption = "Hello";
266
267 rc = ui_window_create(ui, &params, &window);
[95a9cbc]268 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
[c68c18b9]269 PCUT_ASSERT_NOT_NULL(window);
[95a9cbc]270
[c68c18b9]271 rc = ui_menu_bar_create(ui, window, &mbar);
[95a9cbc]272 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
273 PCUT_ASSERT_NOT_NULL(mbar);
274
275 rc = ui_menu_create(mbar, "Test", &menu);
276 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
277 PCUT_ASSERT_NOT_NULL(menu);
278
[59768c7]279 ui_menu_bar_select(mbar, menu, true);
[95a9cbc]280 PCUT_ASSERT_EQUALS(menu, mbar->selected);
281
282 /* Selecting again should unselect the menu */
[59768c7]283 ui_menu_bar_select(mbar, menu, true);
[95a9cbc]284 PCUT_ASSERT_NULL(mbar->selected);
285
286 ui_menu_bar_destroy(mbar);
[c68c18b9]287 ui_window_destroy(window);
[3c8c580]288 ui_destroy(ui);
[95a9cbc]289}
290
291/** Calling ui_menu_bar_select() with another menu selects it */
292PCUT_TEST(select_different)
293{
[3c8c580]294 ui_t *ui = NULL;
[c68c18b9]295 ui_window_t *window = NULL;
296 ui_wnd_params_t params;
[95a9cbc]297 ui_menu_bar_t *mbar = NULL;
298 ui_menu_t *menu1 = NULL;
299 ui_menu_t *menu2 = NULL;
300 errno_t rc;
301
[3c8c580]302 rc = ui_create_disp(NULL, &ui);
303 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
304
[c68c18b9]305 ui_wnd_params_init(&params);
306 params.caption = "Hello";
307
308 rc = ui_window_create(ui, &params, &window);
[95a9cbc]309 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
[c68c18b9]310 PCUT_ASSERT_NOT_NULL(window);
[95a9cbc]311
[c68c18b9]312 rc = ui_menu_bar_create(ui, window, &mbar);
[95a9cbc]313 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
314 PCUT_ASSERT_NOT_NULL(mbar);
315
316 rc = ui_menu_create(mbar, "Test 1", &menu1);
317 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
318 PCUT_ASSERT_NOT_NULL(menu1);
319
320 rc = ui_menu_create(mbar, "Test 2", &menu2);
321 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
322 PCUT_ASSERT_NOT_NULL(menu2);
323
[59768c7]324 ui_menu_bar_select(mbar, menu1, true);
[95a9cbc]325 PCUT_ASSERT_EQUALS(menu1, mbar->selected);
326
327 /* Selecting different menu should select it */
[59768c7]328 ui_menu_bar_select(mbar, menu2, true);
[95a9cbc]329 PCUT_ASSERT_EQUALS(menu2, mbar->selected);
330
331 ui_menu_bar_destroy(mbar);
[c68c18b9]332 ui_window_destroy(window);
[3c8c580]333 ui_destroy(ui);
[95a9cbc]334}
335
[59768c7]336/** ui_menu_bar_activate() activates/deactivates menu bar */
337PCUT_TEST(activate_deactivate)
338{
339 ui_t *ui = NULL;
340 ui_window_t *window = NULL;
341 ui_wnd_params_t params;
342 ui_menu_bar_t *mbar = NULL;
343 ui_menu_t *menu = NULL;
344 errno_t rc;
345
346 rc = ui_create_disp(NULL, &ui);
347 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
348
349 ui_wnd_params_init(&params);
350 params.caption = "Hello";
351
352 rc = ui_window_create(ui, &params, &window);
353 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
354 PCUT_ASSERT_NOT_NULL(window);
355
356 rc = ui_menu_bar_create(ui, window, &mbar);
357 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
358 PCUT_ASSERT_NOT_NULL(mbar);
359
360 rc = ui_menu_create(mbar, "Test", &menu);
361 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
362 PCUT_ASSERT_NOT_NULL(menu);
363
364 ui_menu_bar_activate(mbar);
365 PCUT_ASSERT_EQUALS(menu, mbar->selected);
366
367 ui_menu_bar_deactivate(mbar);
368 PCUT_ASSERT_NULL(mbar->selected);
369
370 ui_menu_bar_destroy(mbar);
371 ui_window_destroy(window);
372 ui_destroy(ui);
373}
374
[95a9cbc]375PCUT_EXPORT(menubar);
Note: See TracBrowser for help on using the repository browser.