Ticket #7182: menu.diff
File menu.diff, 7.6 KB (added by , 13 years ago) |
---|
-
headers/private/interface/MenuPrivate.h
1 1 /* 2 * Copyright 2006-20 08, Haiku, Inc.2 * Copyright 2006-2011, Haiku, Inc. 3 3 * Distributed under the terms of the MIT License. 4 4 * 5 5 * Authors: … … 14 14 enum menu_states { 15 15 MENU_STATE_TRACKING = 0, 16 16 MENU_STATE_TRACKING_SUBMENU = 1, 17 MENU_STATE_KEY_TO_SUBMENU = 2, 18 MENU_STATE_KEY_LEAVE_SUBMENU = 3, 17 19 MENU_STATE_CLOSED = 5 18 20 }; 19 21 -
src/kits/interface/Menu.cpp
1 1 /* 2 * Copyright 2001-20 09, Haiku Inc. All rights reserved.2 * Copyright 2001-2011, Haiku Inc. All rights reserved. 3 3 * Distributed under the terms of the MIT license. 4 4 * 5 5 * Authors: … … 477 477 break; 478 478 479 479 case B_DOWN_ARROW: 480 { 481 BMenuBar* bar = dynamic_cast<BMenuBar*>(Supermenu()); 482 if (bar != NULL && fState == MENU_STATE_CLOSED) { 483 // tell MenuBar's _Track: 484 bar->fState = MENU_STATE_KEY_TO_SUBMENU; 485 } 486 } 480 487 if (fLayout == B_ITEMS_IN_COLUMN) 481 488 _SelectNextItem(fSelected, true); 482 489 break; … … 494 501 // another top level menu. 495 502 BMessenger msgr(Supermenu()); 496 503 msgr.SendMessage(Window()->CurrentMessage()); 497 } else 498 _QuitTracking(); 504 } else { 505 // tell _Track 506 fState = MENU_STATE_KEY_LEAVE_SUBMENU; 507 } 499 508 } 500 509 } 501 510 break; … … 505 514 _SelectNextItem(fSelected, true); 506 515 else { 507 516 if (fSelected && fSelected->Submenu()) { 508 fSelected->Submenu()->_SetStickyMode(true); 517 fSelected->Submenu()->_SetStickyMode(true); 509 518 // fix me: this shouldn't be needed but dynamic menus 510 519 // aren't getting it set correctly when keyboard 511 520 // navigating, which aborts the attach 521 fState = MENU_STATE_KEY_TO_SUBMENU; 512 522 _SelectItem(fSelected, true, true, true); 513 523 } else if (dynamic_cast<BMenuBar*>(Supermenu())) { 514 524 // if we have no submenu and we're an … … 539 549 case B_ENTER: 540 550 case B_SPACE: 541 551 if (fSelected) { 542 _InvokeItem(fSelected); 552 // preserve for exit handling 553 fChosenItem = fSelected; 543 554 _QuitTracking(false); 544 555 } 545 556 break; 546 557 547 558 case B_ESCAPE: 548 _QuitTracking(); 559 _SelectItem(NULL); 560 if (fState == MENU_STATE_CLOSED && dynamic_cast<BMenuBar*>(Supermenu())) { 561 // Keyboard may show menu without tracking it 562 BMessenger msgr(Supermenu()); 563 msgr.SendMessage(Window()->CurrentMessage()); 564 } else 565 _QuitTracking(false); 549 566 break; 550 567 551 568 default: … … 1580 1597 bigtime_t navigationAreaTime = 0; 1581 1598 1582 1599 fState = MENU_STATE_TRACKING; 1583 if (fSuper != NULL)1584 fSuper->fState = MENU_STATE_TRACKING_SUBMENU;1600 // we will use this for keyboard selection: 1601 fChosenItem = NULL; 1585 1602 1586 1603 BPoint location; 1587 1604 uint32 buttons = 0; … … 1608 1625 // The order of the checks is important 1609 1626 // to be able to handle overlapping menus: 1610 1627 // first we check if mouse is inside a submenu, 1611 // then if the m enuis inside this menu,1628 // then if the mouse is inside this menu, 1612 1629 // then if it's over a super menu. 1613 1630 bool overSub = _OverSubmenu(fSelected, screenLocation); 1614 1631 item = _HitTestItems(location, B_ORIGIN); 1615 if (overSub) { 1632 if (overSub || fState == MENU_STATE_KEY_TO_SUBMENU) { 1633 if (fState == MENU_STATE_TRACKING) { 1634 // not if from R.Arrow 1635 fState = MENU_STATE_TRACKING_SUBMENU; 1636 } 1616 1637 navAreaRectAbove = BRect(); 1617 1638 navAreaRectBelow = BRect(); 1618 1639 … … 1633 1654 if (submenuAction == MENU_STATE_CLOSED) { 1634 1655 item = submenuItem; 1635 1656 fState = MENU_STATE_CLOSED; 1636 } 1657 } else if (submenuAction == MENU_STATE_KEY_LEAVE_SUBMENU) { 1658 if (LockLooper()) { 1659 BMenuItem *temp = fSelected; 1660 // close the submenu: 1661 _SelectItem(NULL); 1662 // but reselect the item itself for user: 1663 _SelectItem(temp, false); 1664 UnlockLooper(); 1665 } 1666 // cancel key-nav state 1667 fState = MENU_STATE_TRACKING; 1668 } else 1669 fState = MENU_STATE_TRACKING; 1637 1670 if (!LockLooper()) 1638 1671 break; 1639 1672 } else if (item != NULL) { … … 1641 1674 navAreaRectBelow, selectedTime, navigationAreaTime); 1642 1675 if (!releasedOnce) 1643 1676 releasedOnce = true; 1644 } else if (_OverSuper(screenLocation) ) {1677 } else if (_OverSuper(screenLocation) && fSuper->fState != MENU_STATE_KEY_TO_SUBMENU) { 1645 1678 fState = MENU_STATE_TRACKING; 1646 1679 UnlockLooper(); 1647 1680 break; 1648 } else { 1681 } else if (fState == MENU_STATE_KEY_LEAVE_SUBMENU) { 1682 UnlockLooper(); 1683 break; 1684 } else if (fSuper == NULL || fSuper->fState != MENU_STATE_KEY_TO_SUBMENU) { 1649 1685 // Mouse pointer outside menu: 1650 1686 // If there's no other submenu opened, 1651 1687 // deselect the current selected item … … 1676 1712 uint32 newButtons = buttons; 1677 1713 1678 1714 // If user doesn't move the mouse, loop here, 1679 // so we don't interfer with keyboard menu navigation1715 // so we don't interfere with keyboard menu navigation 1680 1716 do { 1681 1717 snooze(snoozeAmount); 1682 1718 if (!LockLooper()) … … 1684 1720 GetMouse(&newLocation, &newButtons, true); 1685 1721 UnlockLooper(); 1686 1722 } while (newLocation == location && newButtons == buttons 1687 && !(item && item->Submenu() != NULL)); 1723 && !(item && item->Submenu() != NULL) 1724 && fState == MENU_STATE_TRACKING); 1688 1725 1689 1726 if (newLocation != location || newButtons != buttons) { 1690 1727 if (!releasedOnce && newButtons == 0 && buttons != 0) … … 1700 1737 1701 1738 if (action != NULL) 1702 1739 *action = fState; 1740 1741 // keyboard Enter will set this 1742 if (fChosenItem != NULL) 1743 item = fChosenItem; 1744 else if (fSelected == NULL) 1745 // needed to cover (rare) mouse/ESC combination 1746 item = NULL; 1703 1747 1704 1748 if (fSelected != NULL && LockLooper()) { 1705 1749 _SelectItem(NULL); 1706 1750 UnlockLooper(); 1707 1751 } 1708 1752 1709 1753 // delete the menu window recycled for all the child menus 1710 1754 _DeleteMenuWindow(); 1711 1755 … … 2829 2873 if (BMenuBar* menuBar = dynamic_cast<BMenuBar*>(this)) 2830 2874 menuBar->_RestoreFocus(); 2831 2875 2832 fChosenItem = NULL;2833 2876 fState = MENU_STATE_CLOSED; 2834 2877 2835 2878 // Close the whole menu hierarchy -
src/kits/interface/MenuBar.cpp
566 566 if (window->Lock()) { 567 567 if (startIndex != -1) { 568 568 be_app->ObscureCursor(); 569 _SelectItem(ItemAt(startIndex), true, true);569 _SelectItem(ItemAt(startIndex), true, false); 570 570 } 571 571 GetMouse(&where, &buttons); 572 572 window->Unlock(); … … 582 582 menuItem = ItemAt(0); 583 583 else 584 584 menuItem = _HitTestItems(where, B_ORIGIN); 585 if (_OverSubmenu(fSelected, ConvertToScreen(where))) { 585 if (_OverSubmenu(fSelected, ConvertToScreen(where)) 586 || fState == MENU_STATE_KEY_TO_SUBMENU) { 586 587 // call _Track() from the selected sub-menu when the mouse cursor 587 588 // is over its window 588 589 BMenu* menu = fSelected->Submenu(); … … 645 646 646 647 if (fState != MENU_STATE_CLOSED) { 647 648 // If user doesn't move the mouse, loop here, 648 // so we don't interfer with keyboard menu navigation649 // so we don't interfere with keyboard menu navigation 649 650 BPoint newLocation = where; 650 651 uint32 newButtons = buttons; 651 652 do { … … 654 655 break; 655 656 GetMouse(&newLocation, &newButtons, true); 656 657 UnlockLooper(); 657 } while (newLocation == where && newButtons == buttons); 658 } while (newLocation == where && newButtons == buttons 659 && fState == MENU_STATE_TRACKING); 658 660 659 661 where = newLocation; 660 662 buttons = newButtons;