source: mainline/uspace/lib/ui/src/menubar.c@ 4030072

ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 4030072 was 1543d4c, checked in by Jiri Svoboda <jiri@…>, 21 months ago

Properly close drop-down menu on second menu-bar entry click

Note that this does not work in console due to current limitations
in libui's window emulation.

  • Property mode set to 100644
File size: 15.7 KB
RevLine 
[214aefb]1/*
[5d380b6]2 * Copyright (c) 2023 Jiri Svoboda
[214aefb]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/** @addtogroup libui
30 * @{
31 */
32/**
33 * @file Menu bar
34 */
35
36#include <adt/list.h>
[61643c8]37#include <ctype.h>
[214aefb]38#include <errno.h>
39#include <gfx/color.h>
40#include <gfx/context.h>
41#include <gfx/render.h>
42#include <gfx/text.h>
43#include <io/pos_event.h>
44#include <stdlib.h>
45#include <str.h>
46#include <ui/control.h>
47#include <ui/paint.h>
48#include <ui/menubar.h>
[46bd63c9]49#include <ui/menudd.h>
[8d1bcd7]50#include <ui/wdecor.h>
[c68c18b9]51#include <ui/window.h>
[214aefb]52#include "../private/menubar.h"
53#include "../private/resource.h"
[8d1bcd7]54#include "../private/wdecor.h"
55#include "../private/window.h"
[214aefb]56
57enum {
58 menubar_hpad = 4,
59 menubar_vpad = 4,
60 menubar_hpad_text = 1,
61 menubar_vpad_text = 0
62};
63
64static void ui_menu_bar_ctl_destroy(void *);
65static errno_t ui_menu_bar_ctl_paint(void *);
[59768c7]66static ui_evclaim_t ui_menu_bar_ctl_kbd_event(void *, kbd_event_t *);
[214aefb]67static ui_evclaim_t ui_menu_bar_ctl_pos_event(void *, pos_event_t *);
68
69/** Menu bar control ops */
70ui_control_ops_t ui_menu_bar_ops = {
71 .destroy = ui_menu_bar_ctl_destroy,
72 .paint = ui_menu_bar_ctl_paint,
[59768c7]73 .kbd_event = ui_menu_bar_ctl_kbd_event,
74 .pos_event = ui_menu_bar_ctl_pos_event
[214aefb]75};
76
77/** Create new menu bar.
78 *
[3c8c580]79 * @param ui UI
[c68c18b9]80 * @param window Window that will contain the menu bar
[214aefb]81 * @param rmbar Place to store pointer to new menu bar
82 * @return EOK on success, ENOMEM if out of memory
83 */
[c68c18b9]84errno_t ui_menu_bar_create(ui_t *ui, ui_window_t *window, ui_menu_bar_t **rmbar)
[214aefb]85{
86 ui_menu_bar_t *mbar;
87 errno_t rc;
88
89 mbar = calloc(1, sizeof(ui_menu_bar_t));
90 if (mbar == NULL)
91 return ENOMEM;
92
93 rc = ui_control_new(&ui_menu_bar_ops, (void *) mbar, &mbar->control);
94 if (rc != EOK) {
95 free(mbar);
96 return rc;
97 }
98
[3c8c580]99 mbar->ui = ui;
[c68c18b9]100 mbar->window = window;
[46bd63c9]101 list_initialize(&mbar->menudds);
[8d1bcd7]102
103 if (window->mbar == NULL)
104 window->mbar = mbar;
105
[214aefb]106 *rmbar = mbar;
107 return EOK;
108}
109
110/** Destroy menu bar
111 *
112 * @param mbar Menu bar or @c NULL
113 */
114void ui_menu_bar_destroy(ui_menu_bar_t *mbar)
115{
[46bd63c9]116 ui_menu_dd_t *mdd;
[214aefb]117
118 if (mbar == NULL)
119 return;
120
[8d1bcd7]121 if (mbar->window->mbar == mbar)
122 mbar->window->mbar = NULL;
123
[46bd63c9]124 /* Destroy menu drop-downs */
125 mdd = ui_menu_dd_first(mbar);
126 while (mdd != NULL) {
127 ui_menu_dd_destroy(mdd);
128 mdd = ui_menu_dd_first(mbar);
[214aefb]129 }
130
131 ui_control_delete(mbar->control);
132 free(mbar);
133}
134
135/** Get base control from menu bar.
136 *
137 * @param mbar Menu bar
138 * @return Control
139 */
140ui_control_t *ui_menu_bar_ctl(ui_menu_bar_t *mbar)
141{
142 return mbar->control;
143}
144
145/** Set menu bar rectangle.
146 *
147 * @param mbar Menu bar
148 * @param rect New menu bar rectangle
149 */
150void ui_menu_bar_set_rect(ui_menu_bar_t *mbar, gfx_rect_t *rect)
151{
152 mbar->rect = *rect;
153}
154
155/** Paint menu bar.
156 *
157 * @param mbar Menu bar
158 * @return EOK on success or an error code
159 */
160errno_t ui_menu_bar_paint(ui_menu_bar_t *mbar)
161{
[c68c18b9]162 ui_resource_t *res;
[ca2680d]163 ui_text_fmt_t fmt;
[214aefb]164 gfx_coord2_t pos;
165 gfx_coord2_t tpos;
166 gfx_rect_t rect;
167 gfx_color_t *bg_color;
[46bd63c9]168 ui_menu_dd_t *mdd;
[214aefb]169 const char *caption;
170 gfx_coord_t width;
171 gfx_coord_t hpad;
172 gfx_coord_t vpad;
173 errno_t rc;
174
[c68c18b9]175 res = ui_window_get_res(mbar->window);
176
[214aefb]177 /* Paint menu bar background */
178
[c68c18b9]179 rc = gfx_set_color(res->gc, res->wnd_face_color);
[214aefb]180 if (rc != EOK)
181 goto error;
182
[c68c18b9]183 rc = gfx_fill_rect(res->gc, &mbar->rect);
[214aefb]184 if (rc != EOK)
185 goto error;
186
[c68c18b9]187 if (res->textmode) {
[214aefb]188 hpad = menubar_hpad_text;
189 vpad = menubar_vpad_text;
190 } else {
191 hpad = menubar_hpad;
192 vpad = menubar_vpad;
193 }
194
195 pos = mbar->rect.p0;
196
[ca2680d]197 ui_text_fmt_init(&fmt);
[4583015]198 fmt.font = res->font;
[214aefb]199 fmt.halign = gfx_halign_left;
200 fmt.valign = gfx_valign_top;
201
[46bd63c9]202 mdd = ui_menu_dd_first(mbar);
203 while (mdd != NULL) {
204 caption = ui_menu_dd_caption(mdd);
[ca2680d]205 width = ui_text_width(res->font, caption) + 2 * hpad;
[214aefb]206 tpos.x = pos.x + hpad;
207 tpos.y = pos.y + vpad;
208
209 rect.p0 = pos;
210 rect.p1.x = rect.p0.x + width;
211 rect.p1.y = mbar->rect.p1.y;
212
[46bd63c9]213 if (mdd == mbar->selected) {
[c68c18b9]214 fmt.color = res->wnd_sel_text_color;
[ca2680d]215 fmt.hgl_color = res->wnd_sel_text_hgl_color;
[c68c18b9]216 bg_color = res->wnd_sel_text_bg_color;
[214aefb]217 } else {
[c68c18b9]218 fmt.color = res->wnd_text_color;
[ca2680d]219 fmt.hgl_color = res->wnd_text_hgl_color;
[c68c18b9]220 bg_color = res->wnd_face_color;
[214aefb]221 }
222
[c68c18b9]223 rc = gfx_set_color(res->gc, bg_color);
[214aefb]224 if (rc != EOK)
225 goto error;
226
[c68c18b9]227 rc = gfx_fill_rect(res->gc, &rect);
[214aefb]228 if (rc != EOK)
229 goto error;
230
[ca2680d]231 rc = ui_paint_text(&tpos, &fmt, caption);
[214aefb]232 if (rc != EOK)
233 goto error;
234
235 pos.x += width;
[46bd63c9]236 mdd = ui_menu_dd_next(mdd);
[214aefb]237 }
238
[c68c18b9]239 rc = gfx_update(res->gc);
[214aefb]240 if (rc != EOK)
241 goto error;
242
243 return EOK;
244error:
245 return rc;
246}
247
248/** Select or deselect menu from menu bar.
249 *
250 * Select @a menu. If @a menu is @c NULL or it is already selected,
251 * then select none.
252 *
253 * @param mbar Menu bar
[46bd63c9]254 * @param mdd Menu drop-down to select (or deselect if selected) or @c NULL
[59768c7]255 * @param openup Open menu even if not currently open
[5d380b6]256 * @param idev_id Input device ID associated with the selecting seat
[214aefb]257 */
[46bd63c9]258void ui_menu_bar_select(ui_menu_bar_t *mbar, ui_menu_dd_t *mdd, bool openup,
[5d380b6]259 sysarg_t idev_id)
[214aefb]260{
[46bd63c9]261 ui_menu_dd_t *old_mdd;
[59768c7]262 gfx_rect_t rect;
263 bool was_open;
[214aefb]264
[46bd63c9]265 old_mdd = mbar->selected;
[214aefb]266
[46bd63c9]267 mbar->selected = mdd;
[214aefb]268
[46bd63c9]269 /* Close previously open menu drop-down */
270 if (old_mdd != NULL && ui_menu_dd_is_open(old_mdd)) {
[59768c7]271 was_open = true;
[46bd63c9]272 (void) ui_menu_dd_close(old_mdd);
[59768c7]273 } else {
274 was_open = false;
275 }
[214aefb]276
277 (void) ui_menu_bar_paint(mbar);
278
279 if (mbar->selected != NULL) {
[59768c7]280 ui_menu_bar_entry_rect(mbar, mbar->selected, &rect);
281 if (openup || was_open) {
282 /*
[46bd63c9]283 * Open the newly selected menu drop-down if either
284 * the old menu drop-down was open or @a openup was
[59768c7]285 * specified.
286 */
[46bd63c9]287 (void) ui_menu_dd_open(mbar->selected, &rect, idev_id);
[59768c7]288 }
[8d1bcd7]289
290 mbar->active = true;
291 } else {
292 mbar->active = false;
[214aefb]293 }
294}
295
[4034954c]296/** Select first drop-down.
297 *
298 * @param mbar Menu bar
299 * @param openup @c true to open drop-down if it was not open
300 * @param idev_id Input device ID
301 */
[8d1bcd7]302void ui_menu_bar_select_first(ui_menu_bar_t *mbar, bool openup,
303 sysarg_t idev_id)
304{
305 ui_menu_dd_t *mdd;
306
307 mdd = ui_menu_dd_first(mbar);
308 ui_menu_bar_select(mbar, mdd, openup, idev_id);
309}
310
[4034954c]311/** Select last drop-down.
312 *
313 * @param mbar Menu bar
314 * @param openup @c true to open drop-down if it was not open
315 * @param idev_id Input device ID
316 */
[8d1bcd7]317void ui_menu_bar_select_last(ui_menu_bar_t *mbar, bool openup,
318 sysarg_t idev_id)
319{
320 ui_menu_dd_t *mdd;
321
322 mdd = ui_menu_dd_last(mbar);
323 ui_menu_bar_select(mbar, mdd, openup, idev_id);
324}
325
[4034954c]326/** Select system menu.
327 *
328 * @param mbar Menu bar
329 * @param openup @c true to open drop-down if it was not open
330 * @param idev_id Input device ID
331 */
332void ui_menu_bar_select_sysmenu(ui_menu_bar_t *mbar, bool openup,
333 sysarg_t idev_id)
[8d1bcd7]334{
335 ui_wdecor_sysmenu_hdl_set_active(mbar->window->wdecor, true);
336
[4034954c]337 if (openup)
[8d1bcd7]338 ui_window_send_sysmenu(mbar->window, idev_id);
339}
340
[59768c7]341/** Move one entry left.
342 *
343 * If the selected menu is open, the newly selected menu will be open
344 * as well. If we are already at the first entry, we wrap around.
345 *
346 * @param mbar Menu bar
[5d380b6]347 * @param idev_id Input device ID
[59768c7]348 */
[5d380b6]349void ui_menu_bar_left(ui_menu_bar_t *mbar, sysarg_t idev_id)
[59768c7]350{
[46bd63c9]351 ui_menu_dd_t *nmdd;
[4034954c]352 bool sel_sysmenu = false;
353 bool was_open;
[59768c7]354
355 if (mbar->selected == NULL)
356 return;
357
[46bd63c9]358 nmdd = ui_menu_dd_prev(mbar->selected);
[8d1bcd7]359 if (nmdd == NULL) {
360 if ((mbar->window->wdecor->style & ui_wds_sysmenu_hdl) != 0) {
[4034954c]361 sel_sysmenu = true;
[8d1bcd7]362 } else {
363 nmdd = ui_menu_dd_last(mbar);
364 }
365 }
[59768c7]366
[4034954c]367 was_open = mbar->selected != NULL &&
368 ui_menu_dd_is_open(mbar->selected);
369
[46bd63c9]370 if (nmdd != mbar->selected)
371 ui_menu_bar_select(mbar, nmdd, false, idev_id);
[4034954c]372
373 /*
374 * Only open sysmenu *after* closing the previous menu, avoid
375 * having multiple popup windows at the same time.
376 */
377 if (sel_sysmenu)
378 ui_menu_bar_select_sysmenu(mbar, was_open, idev_id);
[59768c7]379}
380
381/** Move one entry right.
382 *
383 * If the selected menu is open, the newly selected menu will be open
384 * as well. If we are already at the last entry, we wrap around.
385 *
386 * @param mbar Menu bar
[5d380b6]387 * @param idev_id Input device ID
[59768c7]388 */
[5d380b6]389void ui_menu_bar_right(ui_menu_bar_t *mbar, sysarg_t idev_id)
[59768c7]390{
[46bd63c9]391 ui_menu_dd_t *nmdd;
[4034954c]392 bool sel_sysmenu = false;
393 bool was_open;
[59768c7]394
395 if (mbar->selected == NULL)
396 return;
397
[46bd63c9]398 nmdd = ui_menu_dd_next(mbar->selected);
[8d1bcd7]399 if (nmdd == NULL) {
400 if ((mbar->window->wdecor->style & ui_wds_sysmenu_hdl) != 0) {
[4034954c]401 sel_sysmenu = true;
[8d1bcd7]402 } else {
403 nmdd = ui_menu_dd_first(mbar);
404 }
405 }
[59768c7]406
[4034954c]407 was_open = mbar->selected != NULL &&
408 ui_menu_dd_is_open(mbar->selected);
409
[46bd63c9]410 if (nmdd != mbar->selected)
411 ui_menu_bar_select(mbar, nmdd, false, idev_id);
[4034954c]412
413 /*
414 * Only open sysmenu *after* closing the previous menu, avoid
415 * having multiple popup windows at the same time.
416 */
417 if (sel_sysmenu)
418 ui_menu_bar_select_sysmenu(mbar, was_open, idev_id);
[59768c7]419}
420
421/** Handle menu bar key press without modifiers.
422 *
423 * @param mbar Menu bar
424 * @param kbd_event Keyboard event
425 * @return @c ui_claimed iff the event is claimed
426 */
427ui_evclaim_t ui_menu_bar_key_press_unmod(ui_menu_bar_t *mbar, kbd_event_t *event)
428{
429 gfx_rect_t rect;
430
431 if (event->key == KC_F10) {
432 ui_menu_bar_activate(mbar);
433 return ui_claimed;
434 }
435
436 if (!mbar->active)
437 return ui_unclaimed;
438
439 if (event->key == KC_ESCAPE) {
440 ui_menu_bar_deactivate(mbar);
441 return ui_claimed;
442 }
443
444 if (event->key == KC_LEFT)
[5d380b6]445 ui_menu_bar_left(mbar, event->kbd_id);
[59768c7]446
447 if (event->key == KC_RIGHT)
[5d380b6]448 ui_menu_bar_right(mbar, event->kbd_id);
[59768c7]449
450 if (event->key == KC_ENTER || event->key == KC_DOWN) {
[46bd63c9]451 if (mbar->selected != NULL &&
452 !ui_menu_dd_is_open(mbar->selected)) {
[59768c7]453 ui_menu_bar_entry_rect(mbar, mbar->selected,
454 &rect);
[46bd63c9]455 ui_menu_dd_open(mbar->selected, &rect, event->kbd_id);
[59768c7]456 }
457
458 return ui_claimed;
459 }
460
[46bd63c9]461 if (event->c != '\0' && !ui_menu_dd_is_open(mbar->selected)) {
[96c6a00]462 /* Check if it is an accelerator. */
[5d380b6]463 ui_menu_bar_press_accel(mbar, event->c, event->kbd_id);
[96c6a00]464 }
465
[59768c7]466 return ui_claimed;
467}
468
469/** Handle menu bar keyboard event.
470 *
471 * @param mbar Menu bar
472 * @param kbd_event Keyboard event
473 * @return @c ui_claimed iff the event is claimed
474 */
475ui_evclaim_t ui_menu_bar_kbd_event(ui_menu_bar_t *mbar, kbd_event_t *event)
476{
[b3b48f4]477 if ((event->mods & KM_ALT) != 0 &&
478 (event->mods & (KM_CTRL | KM_SHIFT)) == 0 && event->c != '\0') {
479 /* Check if it is an accelerator. */
[5d380b6]480 ui_menu_bar_press_accel(mbar, event->c, event->kbd_id);
[b3b48f4]481 }
482
[59768c7]483 if (event->type == KEY_PRESS && (event->mods &
484 (KM_CTRL | KM_ALT | KM_SHIFT)) == 0) {
[5de852c]485 return ui_menu_bar_key_press_unmod(mbar, event);
[59768c7]486 }
487
[5de852c]488 if (mbar->active)
489 return ui_claimed;
490
491 return ui_unclaimed;
[59768c7]492}
493
[b3b48f4]494/** Accelerator key press.
495 *
496 * If @a c matches an accelerator key, open the respective menu.
497 *
498 * @param mbar Menu bar
499 * @param c Character
[5d380b6]500 * @param kbd_id Keyboard ID
[b3b48f4]501 */
[5d380b6]502void ui_menu_bar_press_accel(ui_menu_bar_t *mbar, char32_t c, sysarg_t kbd_id)
[b3b48f4]503{
[46bd63c9]504 ui_menu_dd_t *mdd;
[b3b48f4]505 char32_t maccel;
506
[46bd63c9]507 mdd = ui_menu_dd_first(mbar);
508 while (mdd != NULL) {
509 maccel = ui_menu_dd_get_accel(mdd);
[61643c8]510 if ((char32_t)tolower(c) == maccel) {
[46bd63c9]511 ui_menu_bar_select(mbar, mdd, true, kbd_id);
[b3b48f4]512 return;
513 }
514
[46bd63c9]515 mdd = ui_menu_dd_next(mdd);
[b3b48f4]516 }
517}
518
[214aefb]519/** Handle menu bar position event.
520 *
521 * @param mbar Menu bar
[0262f16c]522 * @param pos_event Position event
[214aefb]523 * @return @c ui_claimed iff the event is claimed
524 */
[0262f16c]525ui_evclaim_t ui_menu_bar_pos_event(ui_menu_bar_t *mbar, pos_event_t *event)
[214aefb]526{
[c68c18b9]527 ui_resource_t *res;
[214aefb]528 gfx_coord2_t pos;
529 gfx_rect_t rect;
[46bd63c9]530 ui_menu_dd_t *mdd;
[214aefb]531 const char *caption;
532 gfx_coord_t width;
533 gfx_coord_t hpad;
[0262f16c]534 gfx_coord2_t ppos;
[5d380b6]535 sysarg_t pos_id;
[0262f16c]536
[c68c18b9]537 res = ui_window_get_res(mbar->window);
538
[0262f16c]539 ppos.x = event->hpos;
540 ppos.y = event->vpos;
[214aefb]541
[c68c18b9]542 if (res->textmode) {
[214aefb]543 hpad = menubar_hpad_text;
544 } else {
545 hpad = menubar_hpad;
546 }
547
548 pos = mbar->rect.p0;
[5d380b6]549 pos_id = event->pos_id;
[214aefb]550
[46bd63c9]551 mdd = ui_menu_dd_first(mbar);
552 while (mdd != NULL) {
553 caption = ui_menu_dd_caption(mdd);
[ca2680d]554 width = ui_text_width(res->font, caption) + 2 * hpad;
[214aefb]555
556 rect.p0 = pos;
557 rect.p1.x = rect.p0.x + width;
558 rect.p1.y = mbar->rect.p1.y;
559
560 /* Check if press is inside menu bar entry */
[0262f16c]561 if (event->type == POS_PRESS &&
562 gfx_pix_inside_rect(&ppos, &rect)) {
[59768c7]563 mbar->active = true;
[96c6a00]564
[1543d4c]565 /* Open the menu, if not already open. */
566 if (mdd != mbar->selected)
[46bd63c9]567 ui_menu_bar_select(mbar, mdd, true, pos_id);
[96c6a00]568
[214aefb]569 return ui_claimed;
570 }
571
572 pos.x += width;
[46bd63c9]573 mdd = ui_menu_dd_next(mdd);
[214aefb]574 }
575
576 return ui_unclaimed;
577}
578
[59768c7]579/** Handle menu bar position event.
580 *
581 * @param mbar Menu bar
[46bd63c9]582 * @param mdd Menu drop-down whose entry's rectangle is to be returned
[59768c7]583 * @param rrect Place to store entry rectangle
584 */
[46bd63c9]585void ui_menu_bar_entry_rect(ui_menu_bar_t *mbar, ui_menu_dd_t *mdd,
[59768c7]586 gfx_rect_t *rrect)
587{
588 ui_resource_t *res;
589 gfx_coord2_t pos;
590 gfx_rect_t rect;
[46bd63c9]591 ui_menu_dd_t *cur;
[59768c7]592 const char *caption;
593 gfx_coord_t width;
594 gfx_coord_t hpad;
595
596 res = ui_window_get_res(mbar->window);
597
598 if (res->textmode) {
599 hpad = menubar_hpad_text;
600 } else {
601 hpad = menubar_hpad;
602 }
603
604 pos = mbar->rect.p0;
605
[46bd63c9]606 cur = ui_menu_dd_first(mbar);
[59768c7]607 while (cur != NULL) {
[46bd63c9]608 caption = ui_menu_dd_caption(cur);
[ca2680d]609 width = ui_text_width(res->font, caption) + 2 * hpad;
[59768c7]610
611 rect.p0 = pos;
612 rect.p1.x = rect.p0.x + width;
613 rect.p1.y = mbar->rect.p1.y;
614
[46bd63c9]615 if (cur == mdd) {
[59768c7]616 *rrect = rect;
617 return;
618 }
619
620 pos.x += width;
[46bd63c9]621 cur = ui_menu_dd_next(cur);
[59768c7]622 }
623
624 /* We should never get here */
625 assert(false);
626}
627
628/** Activate menu bar.
629 *
630 * @param mbar Menu bar
631 */
632void ui_menu_bar_activate(ui_menu_bar_t *mbar)
633{
634 if (mbar->active)
635 return;
636
637 mbar->active = true;
638 if (mbar->selected == NULL)
[46bd63c9]639 mbar->selected = ui_menu_dd_first(mbar);
[59768c7]640
641 (void) ui_menu_bar_paint(mbar);
642}
643
[8d1bcd7]644/** Deactivate menu bar.
645 *
646 * @param mbar Menu bar
647 */
[59768c7]648void ui_menu_bar_deactivate(ui_menu_bar_t *mbar)
649{
[5d380b6]650 ui_menu_bar_select(mbar, NULL, false, 0);
[59768c7]651}
652
[214aefb]653/** Destroy menu bar control.
654 *
655 * @param arg Argument (ui_menu_bar_t *)
656 */
657void ui_menu_bar_ctl_destroy(void *arg)
658{
659 ui_menu_bar_t *mbar = (ui_menu_bar_t *) arg;
660
661 ui_menu_bar_destroy(mbar);
662}
663
664/** Paint menu bar control.
665 *
666 * @param arg Argument (ui_menu_bar_t *)
667 * @return EOK on success or an error code
668 */
669errno_t ui_menu_bar_ctl_paint(void *arg)
670{
671 ui_menu_bar_t *mbar = (ui_menu_bar_t *) arg;
672
673 return ui_menu_bar_paint(mbar);
674}
675
[59768c7]676/** Handle menu bar control keyboard event.
677 *
678 * @param arg Argument (ui_menu_bar_t *)
679 * @param pos_event Position event
680 * @return @c ui_claimed iff the event is claimed
681 */
682ui_evclaim_t ui_menu_bar_ctl_kbd_event(void *arg, kbd_event_t *event)
683{
684 ui_menu_bar_t *mbar = (ui_menu_bar_t *) arg;
685
686 return ui_menu_bar_kbd_event(mbar, event);
687}
688
[214aefb]689/** Handle menu bar control position event.
690 *
691 * @param arg Argument (ui_menu_bar_t *)
692 * @param pos_event Position event
693 * @return @c ui_claimed iff the event is claimed
694 */
695ui_evclaim_t ui_menu_bar_ctl_pos_event(void *arg, pos_event_t *event)
696{
697 ui_menu_bar_t *mbar = (ui_menu_bar_t *) arg;
698
699 return ui_menu_bar_pos_event(mbar, event);
700}
701
702/** @}
703 */
Note: See TracBrowser for help on using the repository browser.