Changes in uspace/lib/ui/src/menubar.c [d7f82635:ec50d65e] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/ui/src/menubar.c
rd7f82635 rec50d65e 1 1 /* 2 * Copyright (c) 202 1Jiri Svoboda2 * Copyright (c) 2024 Jiri Svoboda 3 3 * All rights reserved. 4 4 * … … 35 35 36 36 #include <adt/list.h> 37 #include <ctype.h> 37 38 #include <errno.h> 38 39 #include <gfx/color.h> … … 45 46 #include <ui/control.h> 46 47 #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> 49 51 #include <ui/window.h> 50 52 #include "../private/menubar.h" 51 53 #include "../private/resource.h" 54 #include "../private/wdecor.h" 55 #include "../private/window.h" 52 56 53 57 enum { … … 60 64 static void ui_menu_bar_ctl_destroy(void *); 61 65 static errno_t ui_menu_bar_ctl_paint(void *); 66 static ui_evclaim_t ui_menu_bar_ctl_kbd_event(void *, kbd_event_t *); 62 67 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 *); 63 70 64 71 /** Menu bar control ops */ … … 66 73 .destroy = ui_menu_bar_ctl_destroy, 67 74 .paint = ui_menu_bar_ctl_paint, 68 .pos_event = ui_menu_bar_ctl_pos_event, 75 .kbd_event = ui_menu_bar_ctl_kbd_event, 76 .pos_event = ui_menu_bar_ctl_pos_event 69 77 }; 70 78 … … 93 101 mbar->ui = ui; 94 102 mbar->window = window; 95 list_initialize(&mbar->menus); 103 list_initialize(&mbar->menudds); 104 105 if (window->mbar == NULL) 106 window->mbar = mbar; 107 96 108 *rmbar = mbar; 97 109 return EOK; … … 104 116 void ui_menu_bar_destroy(ui_menu_bar_t *mbar) 105 117 { 106 ui_menu_ t *menu;118 ui_menu_dd_t *mdd; 107 119 108 120 if (mbar == NULL) 109 121 return; 110 122 111 /* Destroy menus */ 112 menu = ui_menu_first(mbar); 113 while (menu != NULL) { 114 ui_menu_destroy(menu); 115 menu = ui_menu_first(mbar); 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); 116 131 } 117 132 … … 120 135 } 121 136 137 /** Set menu bar callbacks. 138 * 139 * @param mbar Menu bar 140 * @param cb Callbacks 141 * @param arg Callback argument 142 */ 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 122 149 /** Get base control from menu bar. 123 150 * … … 148 175 { 149 176 ui_resource_t *res; 150 gfx_text_fmt_t fmt;177 ui_text_fmt_t fmt; 151 178 gfx_coord2_t pos; 152 179 gfx_coord2_t tpos; 153 180 gfx_rect_t rect; 154 181 gfx_color_t *bg_color; 155 ui_menu_ t *menu;182 ui_menu_dd_t *mdd; 156 183 const char *caption; 157 184 gfx_coord_t width; … … 182 209 pos = mbar->rect.p0; 183 210 184 gfx_text_fmt_init(&fmt); 211 ui_text_fmt_init(&fmt); 212 fmt.font = res->font; 185 213 fmt.halign = gfx_halign_left; 186 214 fmt.valign = gfx_valign_top; 187 215 188 m enu = ui_menu_first(mbar);189 while (m enu!= NULL) {190 caption = ui_menu_ caption(menu);191 width = gfx_text_width(res->font, caption) + 2 * hpad;216 mdd = ui_menu_dd_first(mbar); 217 while (mdd != NULL) { 218 caption = ui_menu_dd_caption(mdd); 219 width = ui_text_width(res->font, caption) + 2 * hpad; 192 220 tpos.x = pos.x + hpad; 193 221 tpos.y = pos.y + vpad; … … 197 225 rect.p1.y = mbar->rect.p1.y; 198 226 199 if (m enu== mbar->selected) {227 if (mdd == mbar->selected) { 200 228 fmt.color = res->wnd_sel_text_color; 229 fmt.hgl_color = res->wnd_sel_text_hgl_color; 201 230 bg_color = res->wnd_sel_text_bg_color; 202 231 } else { 203 232 fmt.color = res->wnd_text_color; 233 fmt.hgl_color = res->wnd_text_hgl_color; 204 234 bg_color = res->wnd_face_color; 205 235 } … … 213 243 goto error; 214 244 215 rc = gfx_puttext(res->font,&tpos, &fmt, caption);245 rc = ui_paint_text(&tpos, &fmt, caption); 216 246 if (rc != EOK) 217 247 goto error; 218 248 219 249 pos.x += width; 220 m enu = ui_menu_next(menu);250 mdd = ui_menu_dd_next(mdd); 221 251 } 222 252 … … 236 266 * 237 267 * @param mbar Menu bar 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); 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 } 256 290 257 291 (void) ui_menu_bar_paint(mbar); 258 292 259 293 if (mbar->selected != NULL) { 260 (void) ui_menu_open(mbar->selected, rect); 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); 261 534 } 262 535 } … … 273 546 gfx_coord2_t pos; 274 547 gfx_rect_t rect; 275 ui_menu_ t *menu;548 ui_menu_dd_t *mdd; 276 549 const char *caption; 277 550 gfx_coord_t width; 278 551 gfx_coord_t hpad; 279 552 gfx_coord2_t ppos; 553 sysarg_t pos_id; 280 554 281 555 res = ui_window_get_res(mbar->window); … … 291 565 292 566 pos = mbar->rect.p0; 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; 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; 298 573 299 574 rect.p0 = pos; … … 304 579 if (event->type == POS_PRESS && 305 580 gfx_pix_inside_rect(&ppos, &rect)) { 306 ui_menu_bar_select(mbar, &rect, menu); 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 307 587 return ui_claimed; 308 588 } 309 589 310 590 pos.x += width; 311 m enu = ui_menu_next(menu);591 mdd = ui_menu_dd_next(mdd); 312 592 } 313 593 314 594 return ui_unclaimed; 595 } 596 597 /** Handle menu bar position event. 598 * 599 * @param mbar Menu bar 600 * @param mdd Menu drop-down whose entry's rectangle is to be returned 601 * @param rrect Place to store entry rectangle 602 */ 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 bar 649 */ 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 bar 666 */ 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); 315 671 } 316 672 … … 338 694 } 339 695 340 /** Handle menu bar control positionevent.696 /** Handle menu bar control keyboard event. 341 697 * 342 698 * @param arg Argument (ui_menu_bar_t *) … … 344 700 * @return @c ui_claimed iff the event is claimed 345 701 */ 702 ui_evclaim_t ui_menu_bar_ctl_kbd_event(void *arg, kbd_event_t *event) 703 { 704 ui_menu_bar_t *mbar = (ui_menu_bar_t *) arg; 705 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 event 713 * @return @c ui_claimed iff the event is claimed 714 */ 346 715 ui_evclaim_t ui_menu_bar_ctl_pos_event(void *arg, pos_event_t *event) 347 716 { … … 351 720 } 352 721 722 /** Send menu bar activate event. 723 * 724 * @param mbar Menu bar 725 */ 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 bar 735 */ 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 353 742 /** @} 354 743 */
Note:
See TracChangeset
for help on using the changeset viewer.