source: mainline/uspace/lib/ui/test/menubar.c@ 95658c9

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

Create menu windows in the correct seat

Add a mechanism to set the seat of a new display window, UI window,
UI popup - input device ID. This is set to the ID of the device which
activated the menu (mouse, keyboard). The display server determines
the correct seat from there.

This makes sure clicking outside closes the correct pop-up window.

  • Property mode set to 100644
File size: 9.1 KB
Line 
1/*
2 * Copyright (c) 2023 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/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>
37#include <ui/window.h>
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
50 rc = ui_menu_bar_create(NULL, NULL, &mbar);
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
70 rc = ui_menu_bar_create(NULL, NULL, &mbar);
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;
84 ui_t *ui = NULL;
85 ui_window_t *window = NULL;
86 ui_wnd_params_t params;
87 ui_menu_bar_t *mbar = NULL;
88 gfx_rect_t rect;
89
90 rc = ui_create_disp(NULL, &ui);
91 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
92
93 ui_wnd_params_init(&params);
94 params.caption = "Hello";
95
96 rc = ui_window_create(ui, &params, &window);
97 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
98 PCUT_ASSERT_NOT_NULL(window);
99
100 rc = ui_menu_bar_create(ui, window, &mbar);
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);
116 ui_window_destroy(window);
117 ui_destroy(ui);
118}
119
120/** Paint menu bar */
121PCUT_TEST(paint)
122{
123 ui_t *ui = NULL;
124 ui_window_t *window = NULL;
125 ui_wnd_params_t params;
126 ui_menu_bar_t *mbar = NULL;
127 errno_t rc;
128
129 rc = ui_create_disp(NULL, &ui);
130 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
131
132 ui_wnd_params_init(&params);
133 params.caption = "Hello";
134
135 rc = ui_window_create(ui, &params, &window);
136 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
137 PCUT_ASSERT_NOT_NULL(window);
138
139 rc = ui_menu_bar_create(ui, window, &mbar);
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);
147 ui_window_destroy(window);
148 ui_destroy(ui);
149}
150
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_F10;
190 event.mods = 0;
191 claimed = ui_menu_bar_kbd_event(mbar, &event);
192 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
193 PCUT_ASSERT_EQUALS(ui_claimed, claimed);
194
195 ui_menu_bar_destroy(mbar);
196 ui_window_destroy(window);
197 ui_destroy(ui);
198}
199
200/** ui_menu_bar_press_accel() opens the corresponding menu */
201PCUT_TEST(press_accel)
202{
203 ui_t *ui = NULL;
204 ui_window_t *window = NULL;
205 ui_wnd_params_t params;
206 ui_menu_bar_t *mbar = NULL;
207 ui_menu_t *menu = NULL;
208 gfx_rect_t rect;
209 errno_t rc;
210
211 rc = ui_create_disp(NULL, &ui);
212 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
213
214 ui_wnd_params_init(&params);
215 params.caption = "Hello";
216
217 rc = ui_window_create(ui, &params, &window);
218 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
219 PCUT_ASSERT_NOT_NULL(window);
220
221 rc = ui_menu_bar_create(ui, window, &mbar);
222 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
223 PCUT_ASSERT_NOT_NULL(mbar);
224
225 rect.p0.x = 0;
226 rect.p0.y = 0;
227 rect.p1.x = 50;
228 rect.p1.y = 25;
229 ui_menu_bar_set_rect(mbar, &rect);
230
231 rc = ui_menu_create(mbar, "~T~est", &menu);
232 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
233 PCUT_ASSERT_NOT_NULL(menu);
234
235 PCUT_ASSERT_FALSE(ui_menu_is_open(menu));
236
237 ui_menu_bar_press_accel(mbar, 't', 0);
238
239 PCUT_ASSERT_TRUE(ui_menu_is_open(menu));
240
241 ui_menu_bar_destroy(mbar);
242 ui_window_destroy(window);
243 ui_destroy(ui);
244}
245
246/** Press event on menu bar entry selects menu */
247PCUT_TEST(pos_event_select)
248{
249 ui_t *ui = NULL;
250 ui_window_t *window = NULL;
251 ui_wnd_params_t params;
252 ui_menu_bar_t *mbar = NULL;
253 ui_menu_t *menu = NULL;
254 ui_evclaim_t claimed;
255 pos_event_t event;
256 gfx_rect_t rect;
257 errno_t rc;
258
259 rc = ui_create_disp(NULL, &ui);
260 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
261
262 ui_wnd_params_init(&params);
263 params.caption = "Hello";
264
265 rc = ui_window_create(ui, &params, &window);
266 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
267 PCUT_ASSERT_NOT_NULL(window);
268
269 rc = ui_menu_bar_create(ui, window, &mbar);
270 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
271 PCUT_ASSERT_NOT_NULL(mbar);
272
273 rect.p0.x = 0;
274 rect.p0.y = 0;
275 rect.p1.x = 50;
276 rect.p1.y = 25;
277 ui_menu_bar_set_rect(mbar, &rect);
278
279 rc = ui_menu_create(mbar, "Test", &menu);
280 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
281 PCUT_ASSERT_NOT_NULL(menu);
282
283 event.type = POS_PRESS;
284 event.hpos = 4;
285 event.vpos = 4;
286 claimed = ui_menu_bar_pos_event(mbar, &event);
287 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
288 PCUT_ASSERT_EQUALS(ui_claimed, claimed);
289
290 /* Clicking the menu bar entry should select menu */
291 PCUT_ASSERT_EQUALS(menu, mbar->selected);
292
293 ui_menu_bar_destroy(mbar);
294 ui_window_destroy(window);
295 ui_destroy(ui);
296}
297
298/** Calling ui_menu_bar_select() with another menu selects it */
299PCUT_TEST(select_different)
300{
301 ui_t *ui = NULL;
302 ui_window_t *window = NULL;
303 ui_wnd_params_t params;
304 ui_menu_bar_t *mbar = NULL;
305 ui_menu_t *menu1 = NULL;
306 ui_menu_t *menu2 = NULL;
307 errno_t rc;
308
309 rc = ui_create_disp(NULL, &ui);
310 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
311
312 ui_wnd_params_init(&params);
313 params.caption = "Hello";
314
315 rc = ui_window_create(ui, &params, &window);
316 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
317 PCUT_ASSERT_NOT_NULL(window);
318
319 rc = ui_menu_bar_create(ui, window, &mbar);
320 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
321 PCUT_ASSERT_NOT_NULL(mbar);
322
323 rc = ui_menu_create(mbar, "Test 1", &menu1);
324 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
325 PCUT_ASSERT_NOT_NULL(menu1);
326
327 rc = ui_menu_create(mbar, "Test 2", &menu2);
328 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
329 PCUT_ASSERT_NOT_NULL(menu2);
330
331 ui_menu_bar_select(mbar, menu1, true, 0);
332 PCUT_ASSERT_EQUALS(menu1, mbar->selected);
333
334 /* Selecting different menu should select it */
335 ui_menu_bar_select(mbar, menu2, true, 0);
336 PCUT_ASSERT_EQUALS(menu2, mbar->selected);
337
338 ui_menu_bar_destroy(mbar);
339 ui_window_destroy(window);
340 ui_destroy(ui);
341}
342
343/** ui_menu_bar_activate() activates/deactivates menu bar */
344PCUT_TEST(activate_deactivate)
345{
346 ui_t *ui = NULL;
347 ui_window_t *window = NULL;
348 ui_wnd_params_t params;
349 ui_menu_bar_t *mbar = NULL;
350 ui_menu_t *menu = NULL;
351 errno_t rc;
352
353 rc = ui_create_disp(NULL, &ui);
354 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
355
356 ui_wnd_params_init(&params);
357 params.caption = "Hello";
358
359 rc = ui_window_create(ui, &params, &window);
360 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
361 PCUT_ASSERT_NOT_NULL(window);
362
363 rc = ui_menu_bar_create(ui, window, &mbar);
364 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
365 PCUT_ASSERT_NOT_NULL(mbar);
366
367 rc = ui_menu_create(mbar, "Test", &menu);
368 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
369 PCUT_ASSERT_NOT_NULL(menu);
370
371 ui_menu_bar_activate(mbar);
372 PCUT_ASSERT_EQUALS(menu, mbar->selected);
373
374 ui_menu_bar_deactivate(mbar);
375 PCUT_ASSERT_NULL(mbar->selected);
376
377 ui_menu_bar_destroy(mbar);
378 ui_window_destroy(window);
379 ui_destroy(ui);
380}
381
382PCUT_EXPORT(menubar);
Note: See TracBrowser for help on using the repository browser.