From 4e338ac6df8ea2b43e459e6ce82efd099ac01cec Mon Sep 17 00:00:00 2001 From: Stefano Ceccherini Date: Thu, 17 Aug 2006 06:12:48 +0000 Subject: [PATCH] Started implementing menu keyboard navigation. Does only work for menubars because menu windows never get keyboard focus. Any idea how to solve this, since menu windows are B_AVOID_FOCUS both in beos and haiku? git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@18517 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/kits/interface/Menu.cpp | 82 ++++++++++++---------------------- src/kits/interface/MenuBar.cpp | 26 +++++++---- 2 files changed, 47 insertions(+), 61 deletions(-) diff --git a/src/kits/interface/Menu.cpp b/src/kits/interface/Menu.cpp index 70963718cd..f939d7caa5 100644 --- a/src/kits/interface/Menu.cpp +++ b/src/kits/interface/Menu.cpp @@ -781,68 +781,35 @@ BMenu::MessageReceived(BMessage *msg) void BMenu::KeyDown(const char *bytes, int32 numBytes) { + // TODO: Test how it works on beos and implement it correctly switch (bytes[0]) { - /*case B_UP_ARROW: - { - if (fSelected) { - fSelected->fSelected = false; - - if (fSelected == fItems.FirstItem()) - fSelected = static_cast(fItems.LastItem()); - else - fSelected = ItemAt(IndexOf(fSelected) - 1); - } else - fSelected = static_cast(fItems.LastItem()); - - fSelected->fSelected = true; - + case B_UP_ARROW: + if (fLayout == B_ITEMS_IN_COLUMN) + SelectNextItem(fSelected, false); break; - } + case B_DOWN_ARROW: - { - if (fSelected) { - fSelected->fSelected = false; - - if (fSelected == fItems.LastItem()) - fSelected = static_cast(fItems.FirstItem()); - else - fSelected = ItemAt(IndexOf(fSelected) + 1); - } else - fSelected = static_cast(fItems.FirstItem()); - - fSelected->fSelected = true; - + if (fLayout == B_ITEMS_IN_COLUMN) + SelectNextItem(fSelected, true); break; - } - case B_HOME: - { - if (fSelected) - fSelected->fSelected = false; - - fSelected = static_cast(fItems.FirstItem()); - fSelected->fSelected = true; + case B_LEFT_ARROW: + if (fLayout == B_ITEMS_IN_ROW) + SelectNextItem(fSelected, false); break; - } - case B_END: - { - if (fSelected) - fSelected->fSelected = false; - - fSelected = static_cast(fItems.LastItem()); - fSelected->fSelected = true; + case B_RIGHT_ARROW: + if (fLayout == B_ITEMS_IN_ROW) + SelectNextItem(fSelected, true); break; - } + case B_ENTER: case B_SPACE: - { if (fSelected) InvokeItem(fSelected); break; - } - */ + case B_ESCAPE: QuitTracking(); break; @@ -1330,6 +1297,7 @@ BMenu::_track(int *action, bigtime_t trackTime, long start) if (IsStickyMode()) submenu->SetStickyMode(true); BMenuItem *submenuItem = submenu->_track(&submenuAction, trackTime); + //submenu->Window()->Activate(); if (submenuAction == MENU_STATE_CLOSED) { item = submenuItem; fState = submenuAction; @@ -1910,9 +1878,7 @@ BMenu::Uninstall() void BMenu::SelectItem(BMenuItem *menuItem, uint32 showSubmenu, bool selectFirstItem) -{ - // TODO: make use of "selectFirstItem" - +{ // Avoid deselecting and then reselecting the same item // which would cause flickering if (menuItem != fSelected) { @@ -1930,8 +1896,10 @@ BMenu::SelectItem(BMenuItem *menuItem, uint32 showSubmenu, bool selectFirstItem) if (fSelected != NULL && showSubmenu == 0) { BMenu *subMenu = fSelected->Submenu(); - if (subMenu != NULL && subMenu->Window() == NULL) - subMenu->_show(); + if (subMenu != NULL && subMenu->Window() == NULL) { + subMenu->_show(selectFirstItem); + subMenu->Window()->Activate(); + } } } @@ -1958,6 +1926,13 @@ BMenu::SelectNextItem(BMenuItem *item, bool forward) BMenuItem * BMenu::NextItem(BMenuItem *item, bool forward) const { + if (item == NULL) { + if (forward) + return ItemAt(CountItems() - 1); + else + return ItemAt(0); + } + int32 index = fItems.IndexOf(item); if (forward) index++; @@ -2133,6 +2108,7 @@ BMenu::QuitTracking() if (BMenuBar *menuBar = dynamic_cast(this)) menuBar->RestoreFocus(); + fChosenItem = NULL; fState = MENU_STATE_CLOSED; } diff --git a/src/kits/interface/MenuBar.cpp b/src/kits/interface/MenuBar.cpp index 2985a8646e..1d20cec845 100644 --- a/src/kits/interface/MenuBar.cpp +++ b/src/kits/interface/MenuBar.cpp @@ -391,7 +391,14 @@ BMenuBar::Track(int32 *action, int32 startIndex, bool showMenu) // TODO: Cleanup, merge some "if" blocks if possible BMenuItem *resultItem = NULL; BWindow *window = Window(); - int localAction = fState = MENU_STATE_TRACKING; + fState = MENU_STATE_TRACKING; + + if (startIndex != -1) { + be_app->ObscureCursor(); + window->Lock(); + SelectItem(ItemAt(startIndex), 0, true); + window->Unlock(); + } while (true) { bigtime_t snoozeAmount = 40000; bool locked = window->Lock();//WithTimeout(200000) @@ -421,7 +428,7 @@ BMenuBar::Track(int32 *action, int32 startIndex, bool showMenu) } else { // Menu was already opened, close it and bail SelectItem(NULL); - localAction = MENU_STATE_CLOSED; + fState = MENU_STATE_CLOSED; resultItem = NULL; } } else { @@ -441,9 +448,14 @@ BMenuBar::Track(int32 *action, int32 startIndex, bool showMenu) snoozeAmount = 30000; if (IsStickyMode()) menu->SetStickyMode(true); + int localAction; resultItem = menu->_track(&localAction, system_time()); + //menu->Window()->Activate(); + if (localAction == MENU_STATE_CLOSED) + fState = MENU_STATE_CLOSED; } - } else if (menuItem == NULL && !IsStickyMode() && fState != MENU_STATE_TRACKING_SUBMENU) { + } else if (menuItem == NULL && !IsStickyMode() + && fState != MENU_STATE_TRACKING_SUBMENU) { SelectItem(NULL); fState = MENU_STATE_TRACKING; } @@ -451,10 +463,8 @@ BMenuBar::Track(int32 *action, int32 startIndex, bool showMenu) if (locked) window->Unlock(); - if (fState == MENU_STATE_CLOSED) - break; - - if (localAction == MENU_STATE_CLOSED || (buttons != 0 && IsStickyMode() && menuItem == NULL)) + if (fState == MENU_STATE_CLOSED + || (buttons != 0 && IsStickyMode() && menuItem == NULL)) break; else if (buttons == 0 && !IsStickyMode()) { // On an item without a submenu @@ -484,7 +494,7 @@ BMenuBar::Track(int32 *action, int32 startIndex, bool showMenu) DeleteMenuWindow(); if (action != NULL) - *action = static_cast(localAction); + *action = fState; return resultItem; }