Changes in uspace/lib/ui/src/menubar.c [ec50d65e:d7f82635] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/ui/src/menubar.c
rec50d65e rd7f82635 1 1 /* 2 * Copyright (c) 202 4Jiri Svoboda2 * Copyright (c) 2021 Jiri Svoboda 3 3 * All rights reserved. 4 4 * … … 35 35 36 36 #include <adt/list.h> 37 #include <ctype.h>38 37 #include <errno.h> 39 38 #include <gfx/color.h> … … 46 45 #include <ui/control.h> 47 46 #include <ui/paint.h> 47 #include <ui/menu.h> 48 48 #include <ui/menubar.h> 49 #include <ui/menudd.h>50 #include <ui/wdecor.h>51 49 #include <ui/window.h> 52 50 #include "../private/menubar.h" 53 51 #include "../private/resource.h" 54 #include "../private/wdecor.h"55 #include "../private/window.h"56 52 57 53 enum { … … 64 60 static void ui_menu_bar_ctl_destroy(void *); 65 61 static errno_t ui_menu_bar_ctl_paint(void *); 66 static ui_evclaim_t ui_menu_bar_ctl_kbd_event(void *, kbd_event_t *);67 62 static ui_evclaim_t ui_menu_bar_ctl_pos_event(void *, pos_event_t *); 68 static void ui_menu_bar_activate_ev(ui_menu_bar_t *);69 static void ui_menu_bar_deactivate_ev(ui_menu_bar_t *);70 63 71 64 /** Menu bar control ops */ … … 73 66 .destroy = ui_menu_bar_ctl_destroy, 74 67 .paint = ui_menu_bar_ctl_paint, 75 .kbd_event = ui_menu_bar_ctl_kbd_event, 76 .pos_event = ui_menu_bar_ctl_pos_event 68 .pos_event = ui_menu_bar_ctl_pos_event, 77 69 }; 78 70 … … 101 93 mbar->ui = ui; 102 94 mbar->window = window; 103 list_initialize(&mbar->menudds); 104 105 if (window->mbar == NULL) 106 window->mbar = mbar; 107 95 list_initialize(&mbar->menus); 108 96 *rmbar = mbar; 109 97 return EOK; … … 116 104 void ui_menu_bar_destroy(ui_menu_bar_t *mbar) 117 105 { 118 ui_menu_ dd_t *mdd;106 ui_menu_t *menu; 119 107 120 108 if (mbar == NULL) 121 109 return; 122 110 123 if (mbar->window->mbar == mbar) 124 mbar->window->mbar = NULL; 125 126 /* Destroy menu drop-downs */ 127 mdd = ui_menu_dd_first(mbar); 128 while (mdd != NULL) { 129 ui_menu_dd_destroy(mdd); 130 mdd = ui_menu_dd_first(mbar); 111 /* Destroy menus */ 112 menu = ui_menu_first(mbar); 113 while (menu != NULL) { 114 ui_menu_destroy(menu); 115 menu = ui_menu_first(mbar); 131 116 } 132 117 … … 135 120 } 136 121 137 /** Set menu bar callbacks.138 *139 * @param mbar Menu bar140 * @param cb Callbacks141 * @param arg Callback argument142 */143 void ui_menu_bar_set_cb(ui_menu_bar_t *mbar, ui_menu_bar_cb_t *cb, void *arg)144 {145 mbar->cb = cb;146 mbar->arg = arg;147 }148 149 122 /** Get base control from menu bar. 150 123 * … … 175 148 { 176 149 ui_resource_t *res; 177 ui_text_fmt_t fmt;150 gfx_text_fmt_t fmt; 178 151 gfx_coord2_t pos; 179 152 gfx_coord2_t tpos; 180 153 gfx_rect_t rect; 181 154 gfx_color_t *bg_color; 182 ui_menu_ dd_t *mdd;155 ui_menu_t *menu; 183 156 const char *caption; 184 157 gfx_coord_t width; … … 209 182 pos = mbar->rect.p0; 210 183 211 ui_text_fmt_init(&fmt); 212 fmt.font = res->font; 184 gfx_text_fmt_init(&fmt); 213 185 fmt.halign = gfx_halign_left; 214 186 fmt.valign = gfx_valign_top; 215 187 216 m dd = ui_menu_dd_first(mbar);217 while (m dd!= NULL) {218 caption = ui_menu_ dd_caption(mdd);219 width = ui_text_width(res->font, caption) + 2 * hpad;188 menu = ui_menu_first(mbar); 189 while (menu != NULL) { 190 caption = ui_menu_caption(menu); 191 width = gfx_text_width(res->font, caption) + 2 * hpad; 220 192 tpos.x = pos.x + hpad; 221 193 tpos.y = pos.y + vpad; … … 225 197 rect.p1.y = mbar->rect.p1.y; 226 198 227 if (m dd== mbar->selected) {199 if (menu == mbar->selected) { 228 200 fmt.color = res->wnd_sel_text_color; 229 fmt.hgl_color = res->wnd_sel_text_hgl_color;230 201 bg_color = res->wnd_sel_text_bg_color; 231 202 } else { 232 203 fmt.color = res->wnd_text_color; 233 fmt.hgl_color = res->wnd_text_hgl_color;234 204 bg_color = res->wnd_face_color; 235 205 } … … 243 213 goto error; 244 214 245 rc = ui_paint_text(&tpos, &fmt, caption);215 rc = gfx_puttext(res->font, &tpos, &fmt, caption); 246 216 if (rc != EOK) 247 217 goto error; 248 218 249 219 pos.x += width; 250 m dd = ui_menu_dd_next(mdd);220 menu = ui_menu_next(menu); 251 221 } 252 222 … … 266 236 * 267 237 * @param mbar Menu bar 268 * @param mdd Menu drop-down to select (or deselect if selected) or @c NULL 269 * @param openup Open menu even if not currently open 270 * @param idev_id Input device ID associated with the selecting seat 271 */ 272 void ui_menu_bar_select(ui_menu_bar_t *mbar, ui_menu_dd_t *mdd, bool openup, 273 sysarg_t idev_id) 274 { 275 ui_menu_dd_t *old_mdd; 276 gfx_rect_t rect; 277 bool was_open; 278 279 old_mdd = mbar->selected; 280 281 mbar->selected = mdd; 282 283 /* Close previously open menu drop-down */ 284 if (old_mdd != NULL && ui_menu_dd_is_open(old_mdd)) { 285 was_open = true; 286 (void) ui_menu_dd_close(old_mdd); 287 } else { 288 was_open = false; 289 } 238 * @param rect Menu bar entry rectangle 239 * @param menu Menu to select (or deselect if selected) or @c NULL 240 */ 241 void ui_menu_bar_select(ui_menu_bar_t *mbar, gfx_rect_t *rect, 242 ui_menu_t *menu) 243 { 244 ui_menu_t *old_menu; 245 246 old_menu = mbar->selected; 247 248 if (mbar->selected != menu) 249 mbar->selected = menu; 250 else 251 mbar->selected = NULL; 252 253 /* Close previously open menu */ 254 if (old_menu != NULL) 255 (void) ui_menu_close(old_menu); 290 256 291 257 (void) ui_menu_bar_paint(mbar); 292 258 293 259 if (mbar->selected != NULL) { 294 ui_menu_bar_entry_rect(mbar, mbar->selected, &rect); 295 if (openup || was_open) { 296 /* 297 * Open the newly selected menu drop-down if either 298 * the old menu drop-down was open or @a openup was 299 * specified. 300 */ 301 (void) ui_menu_dd_open(mbar->selected, &rect, idev_id); 302 } 303 304 if (!mbar->active) 305 ui_menu_bar_activate_ev(mbar); 306 mbar->active = true; 307 } else { 308 if (mbar->active) 309 ui_menu_bar_deactivate_ev(mbar); 310 mbar->active = false; 311 } 312 } 313 314 /** Select first drop-down. 315 * 316 * @param mbar Menu bar 317 * @param openup @c true to open drop-down if it was not open 318 * @param idev_id Input device ID 319 */ 320 void ui_menu_bar_select_first(ui_menu_bar_t *mbar, bool openup, 321 sysarg_t idev_id) 322 { 323 ui_menu_dd_t *mdd; 324 325 mdd = ui_menu_dd_first(mbar); 326 ui_menu_bar_select(mbar, mdd, openup, idev_id); 327 } 328 329 /** Select last drop-down. 330 * 331 * @param mbar Menu bar 332 * @param openup @c true to open drop-down if it was not open 333 * @param idev_id Input device ID 334 */ 335 void ui_menu_bar_select_last(ui_menu_bar_t *mbar, bool openup, 336 sysarg_t idev_id) 337 { 338 ui_menu_dd_t *mdd; 339 340 mdd = ui_menu_dd_last(mbar); 341 ui_menu_bar_select(mbar, mdd, openup, idev_id); 342 } 343 344 /** Select system menu. 345 * 346 * @param mbar Menu bar 347 * @param openup @c true to open drop-down if it was not open 348 * @param idev_id Input device ID 349 */ 350 void ui_menu_bar_select_sysmenu(ui_menu_bar_t *mbar, bool openup, 351 sysarg_t idev_id) 352 { 353 ui_wdecor_sysmenu_hdl_set_active(mbar->window->wdecor, true); 354 355 if (openup) 356 ui_window_send_sysmenu(mbar->window, idev_id); 357 } 358 359 /** Move one entry left. 360 * 361 * If the selected menu is open, the newly selected menu will be open 362 * as well. If we are already at the first entry, we wrap around. 363 * 364 * @param mbar Menu bar 365 * @param idev_id Input device ID 366 */ 367 void ui_menu_bar_left(ui_menu_bar_t *mbar, sysarg_t idev_id) 368 { 369 ui_menu_dd_t *nmdd; 370 bool sel_sysmenu = false; 371 bool was_open; 372 373 if (mbar->selected == NULL) 374 return; 375 376 nmdd = ui_menu_dd_prev(mbar->selected); 377 if (nmdd == NULL) { 378 if ((mbar->window->wdecor->style & ui_wds_sysmenu_hdl) != 0) { 379 sel_sysmenu = true; 380 } else { 381 nmdd = ui_menu_dd_last(mbar); 382 } 383 } 384 385 was_open = mbar->selected != NULL && 386 ui_menu_dd_is_open(mbar->selected); 387 388 if (nmdd != mbar->selected) 389 ui_menu_bar_select(mbar, nmdd, false, idev_id); 390 391 /* 392 * Only open sysmenu *after* closing the previous menu, avoid 393 * having multiple popup windows at the same time. 394 */ 395 if (sel_sysmenu) 396 ui_menu_bar_select_sysmenu(mbar, was_open, idev_id); 397 } 398 399 /** Move one entry right. 400 * 401 * If the selected menu is open, the newly selected menu will be open 402 * as well. If we are already at the last entry, we wrap around. 403 * 404 * @param mbar Menu bar 405 * @param idev_id Input device ID 406 */ 407 void ui_menu_bar_right(ui_menu_bar_t *mbar, sysarg_t idev_id) 408 { 409 ui_menu_dd_t *nmdd; 410 bool sel_sysmenu = false; 411 bool was_open; 412 413 if (mbar->selected == NULL) 414 return; 415 416 nmdd = ui_menu_dd_next(mbar->selected); 417 if (nmdd == NULL) { 418 if ((mbar->window->wdecor->style & ui_wds_sysmenu_hdl) != 0) { 419 sel_sysmenu = true; 420 } else { 421 nmdd = ui_menu_dd_first(mbar); 422 } 423 } 424 425 was_open = mbar->selected != NULL && 426 ui_menu_dd_is_open(mbar->selected); 427 428 if (nmdd != mbar->selected) 429 ui_menu_bar_select(mbar, nmdd, false, idev_id); 430 431 /* 432 * Only open sysmenu *after* closing the previous menu, avoid 433 * having multiple popup windows at the same time. 434 */ 435 if (sel_sysmenu) 436 ui_menu_bar_select_sysmenu(mbar, was_open, idev_id); 437 } 438 439 /** Handle menu bar key press without modifiers. 440 * 441 * @param mbar Menu bar 442 * @param kbd_event Keyboard event 443 * @return @c ui_claimed iff the event is claimed 444 */ 445 ui_evclaim_t ui_menu_bar_key_press_unmod(ui_menu_bar_t *mbar, kbd_event_t *event) 446 { 447 gfx_rect_t rect; 448 449 if (event->key == KC_F10) { 450 ui_menu_bar_activate(mbar); 451 return ui_claimed; 452 } 453 454 if (!mbar->active) 455 return ui_unclaimed; 456 457 if (event->key == KC_ESCAPE) { 458 ui_menu_bar_deactivate(mbar); 459 return ui_claimed; 460 } 461 462 if (event->key == KC_LEFT) 463 ui_menu_bar_left(mbar, event->kbd_id); 464 465 if (event->key == KC_RIGHT) 466 ui_menu_bar_right(mbar, event->kbd_id); 467 468 if (event->key == KC_ENTER || event->key == KC_DOWN) { 469 if (mbar->selected != NULL && 470 !ui_menu_dd_is_open(mbar->selected)) { 471 ui_menu_bar_entry_rect(mbar, mbar->selected, 472 &rect); 473 ui_menu_dd_open(mbar->selected, &rect, event->kbd_id); 474 } 475 476 return ui_claimed; 477 } 478 479 if (event->c != '\0' && !ui_menu_dd_is_open(mbar->selected)) { 480 /* Check if it is an accelerator. */ 481 ui_menu_bar_press_accel(mbar, event->c, event->kbd_id); 482 } 483 484 return ui_claimed; 485 } 486 487 /** Handle menu bar keyboard event. 488 * 489 * @param mbar Menu bar 490 * @param kbd_event Keyboard event 491 * @return @c ui_claimed iff the event is claimed 492 */ 493 ui_evclaim_t ui_menu_bar_kbd_event(ui_menu_bar_t *mbar, kbd_event_t *event) 494 { 495 if ((event->mods & KM_ALT) != 0 && 496 (event->mods & (KM_CTRL | KM_SHIFT)) == 0 && event->c != '\0') { 497 /* Check if it is an accelerator. */ 498 ui_menu_bar_press_accel(mbar, event->c, event->kbd_id); 499 } 500 501 if (event->type == KEY_PRESS && (event->mods & 502 (KM_CTRL | KM_ALT | KM_SHIFT)) == 0) { 503 return ui_menu_bar_key_press_unmod(mbar, event); 504 } 505 506 if (mbar->active) 507 return ui_claimed; 508 509 return ui_unclaimed; 510 } 511 512 /** Accelerator key press. 513 * 514 * If @a c matches an accelerator key, open the respective menu. 515 * 516 * @param mbar Menu bar 517 * @param c Character 518 * @param kbd_id Keyboard ID 519 */ 520 void ui_menu_bar_press_accel(ui_menu_bar_t *mbar, char32_t c, sysarg_t kbd_id) 521 { 522 ui_menu_dd_t *mdd; 523 char32_t maccel; 524 525 mdd = ui_menu_dd_first(mbar); 526 while (mdd != NULL) { 527 maccel = ui_menu_dd_get_accel(mdd); 528 if ((char32_t)tolower(c) == maccel) { 529 ui_menu_bar_select(mbar, mdd, true, kbd_id); 530 return; 531 } 532 533 mdd = ui_menu_dd_next(mdd); 260 (void) ui_menu_open(mbar->selected, rect); 534 261 } 535 262 } … … 546 273 gfx_coord2_t pos; 547 274 gfx_rect_t rect; 548 ui_menu_ dd_t *mdd;275 ui_menu_t *menu; 549 276 const char *caption; 550 277 gfx_coord_t width; 551 278 gfx_coord_t hpad; 552 279 gfx_coord2_t ppos; 553 sysarg_t pos_id;554 280 555 281 res = ui_window_get_res(mbar->window); … … 565 291 566 292 pos = mbar->rect.p0; 567 pos_id = event->pos_id; 568 569 mdd = ui_menu_dd_first(mbar); 570 while (mdd != NULL) { 571 caption = ui_menu_dd_caption(mdd); 572 width = ui_text_width(res->font, caption) + 2 * hpad; 293 294 menu = ui_menu_first(mbar); 295 while (menu != NULL) { 296 caption = ui_menu_caption(menu); 297 width = gfx_text_width(res->font, caption) + 2 * hpad; 573 298 574 299 rect.p0 = pos; … … 579 304 if (event->type == POS_PRESS && 580 305 gfx_pix_inside_rect(&ppos, &rect)) { 581 mbar->active = true; 582 583 /* Open the menu, if not already open. */ 584 if (mdd != mbar->selected) 585 ui_menu_bar_select(mbar, mdd, true, pos_id); 586 306 ui_menu_bar_select(mbar, &rect, menu); 587 307 return ui_claimed; 588 308 } 589 309 590 310 pos.x += width; 591 m dd = ui_menu_dd_next(mdd);311 menu = ui_menu_next(menu); 592 312 } 593 313 594 314 return ui_unclaimed; 595 }596 597 /** Handle menu bar position event.598 *599 * @param mbar Menu bar600 * @param mdd Menu drop-down whose entry's rectangle is to be returned601 * @param rrect Place to store entry rectangle602 */603 void ui_menu_bar_entry_rect(ui_menu_bar_t *mbar, ui_menu_dd_t *mdd,604 gfx_rect_t *rrect)605 {606 ui_resource_t *res;607 gfx_coord2_t pos;608 gfx_rect_t rect;609 ui_menu_dd_t *cur;610 const char *caption;611 gfx_coord_t width;612 gfx_coord_t hpad;613 614 res = ui_window_get_res(mbar->window);615 616 if (res->textmode) {617 hpad = menubar_hpad_text;618 } else {619 hpad = menubar_hpad;620 }621 622 pos = mbar->rect.p0;623 624 cur = ui_menu_dd_first(mbar);625 while (cur != NULL) {626 caption = ui_menu_dd_caption(cur);627 width = ui_text_width(res->font, caption) + 2 * hpad;628 629 rect.p0 = pos;630 rect.p1.x = rect.p0.x + width;631 rect.p1.y = mbar->rect.p1.y;632 633 if (cur == mdd) {634 *rrect = rect;635 return;636 }637 638 pos.x += width;639 cur = ui_menu_dd_next(cur);640 }641 642 /* We should never get here */643 assert(false);644 }645 646 /** Activate menu bar.647 *648 * @param mbar Menu bar649 */650 void ui_menu_bar_activate(ui_menu_bar_t *mbar)651 {652 if (mbar->active)653 return;654 655 mbar->active = true;656 if (mbar->selected == NULL)657 mbar->selected = ui_menu_dd_first(mbar);658 659 (void) ui_menu_bar_paint(mbar);660 ui_menu_bar_activate_ev(mbar);661 }662 663 /** Deactivate menu bar.664 *665 * @param mbar Menu bar666 */667 void ui_menu_bar_deactivate(ui_menu_bar_t *mbar)668 {669 ui_menu_bar_select(mbar, NULL, false, 0);670 ui_menu_bar_deactivate_ev(mbar);671 315 } 672 316 … … 694 338 } 695 339 696 /** Handle menu bar control keyboardevent.340 /** Handle menu bar control position event. 697 341 * 698 342 * @param arg Argument (ui_menu_bar_t *) … … 700 344 * @return @c ui_claimed iff the event is claimed 701 345 */ 702 ui_evclaim_t ui_menu_bar_ctl_ kbd_event(void *arg, kbd_event_t *event)346 ui_evclaim_t ui_menu_bar_ctl_pos_event(void *arg, pos_event_t *event) 703 347 { 704 348 ui_menu_bar_t *mbar = (ui_menu_bar_t *) arg; 705 349 706 return ui_menu_bar_kbd_event(mbar, event);707 }708 709 /** Handle menu bar control position event.710 *711 * @param arg Argument (ui_menu_bar_t *)712 * @param pos_event Position event713 * @return @c ui_claimed iff the event is claimed714 */715 ui_evclaim_t ui_menu_bar_ctl_pos_event(void *arg, pos_event_t *event)716 {717 ui_menu_bar_t *mbar = (ui_menu_bar_t *) arg;718 719 350 return ui_menu_bar_pos_event(mbar, event); 720 351 } 721 352 722 /** Send menu bar activate event.723 *724 * @param mbar Menu bar725 */726 static void ui_menu_bar_activate_ev(ui_menu_bar_t *mbar)727 {728 if (mbar->cb != NULL && mbar->cb->activate != NULL)729 mbar->cb->activate(mbar, mbar->arg);730 }731 732 /** Send menu bar deactivate event.733 *734 * @param mbar Menu bar735 */736 static void ui_menu_bar_deactivate_ev(ui_menu_bar_t *mbar)737 {738 if (mbar->cb != NULL && mbar->cb->deactivate != NULL)739 mbar->cb->deactivate(mbar, mbar->arg);740 }741 742 353 /** @} 743 354 */
Note:
See TracChangeset
for help on using the changeset viewer.