Merged (parts of, for now) patches from Rene Gollent and

Christof Lutteroth, which improve menu keyboard navigation. Sorry for 
the delay, I had these patches sitting on my hard drive for a while. At 
least now you can open a menu with ALT + ESC, navigate it with the arrow keys,
and invoke an item.
Various issues still exist, including: menubars don't get the keydown 
messages, and if you keep the mouse over the menu while navigating
with the keyboard, nothing will happen. 


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@23339 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Stefano Ceccherini
2008-01-10 14:06:11 +00:00
parent 67abb56fcd
commit 85e661dbf0
+55 -11
View File
@@ -1,10 +1,11 @@
/* /*
* Copyright 2001-2007, Haiku, Inc. * Copyright 2001-2008, Haiku, Inc.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
* *
* Authors: * Authors:
* Marc Flerackers ([email protected]) * Marc Flerackers ([email protected])
* Stefano Ceccherini ([email protected]) * Stefano Ceccherini ([email protected])
* Rene Gollent ([email protected])
*/ */
#include <new> #include <new>
@@ -19,6 +20,7 @@
#include <Menu.h> #include <Menu.h>
#include <MenuBar.h> #include <MenuBar.h>
#include <MenuItem.h> #include <MenuItem.h>
#include <Messenger.h>
#include <Path.h> #include <Path.h>
#include <PropertyInfo.h> #include <PropertyInfo.h>
#include <Screen.h> #include <Screen.h>
@@ -831,11 +833,36 @@ BMenu::KeyDown(const char *bytes, int32 numBytes)
case B_LEFT_ARROW: case B_LEFT_ARROW:
if (fLayout == B_ITEMS_IN_ROW) if (fLayout == B_ITEMS_IN_ROW)
_SelectNextItem(fSelected, false); _SelectNextItem(fSelected, false);
else {
// this case has to be handled a bit specially.
BMenuItem *item = Superitem();
if (item) {
if (dynamic_cast<BMenuBar *>(Supermenu())) {
// if we're at the top menu below the menu bar, pass the keypress to
// the menu bar so we can move to another top level menu
BMessenger msgr(Supermenu());
msgr.SendMessage(Window()->CurrentMessage());
} else
Supermenu()->_SelectItem(item, false, false);
}
}
break; break;
case B_RIGHT_ARROW: case B_RIGHT_ARROW:
if (fLayout == B_ITEMS_IN_ROW) if (fLayout == B_ITEMS_IN_ROW)
_SelectNextItem(fSelected, true); _SelectNextItem(fSelected, true);
else {
if (fSelected && fSelected->Submenu()) {
_SelectItem(fSelected, true, true);
} else if (dynamic_cast<BMenuBar *>(Supermenu())) {
// if we have no submenu and we're an
// item in the top menu below the menubar,
// pass the keypress to the menubar
// so you can use the keypress to switch menus.
BMessenger msgr(Supermenu());
msgr.SendMessage(Window()->CurrentMessage());
}
}
break; break;
case B_ENTER: case B_ENTER:
@@ -2121,11 +2148,14 @@ BMenu::_SelectItem(BMenuItem* menuItem, bool showSubmenu, bool selectFirstItem)
bool bool
BMenu::_SelectNextItem(BMenuItem *item, bool forward) BMenu::_SelectNextItem(BMenuItem *item, bool forward)
{ {
if (CountItems() == 0) // cannot select next item in an empty menu
return false;
BMenuItem *nextItem = _NextItem(item, forward); BMenuItem *nextItem = _NextItem(item, forward);
if (nextItem == NULL) if (nextItem == NULL)
return false; return false;
_SelectItem(nextItem); _SelectItem(nextItem, false);
return true; return true;
} }
@@ -2133,21 +2163,34 @@ BMenu::_SelectNextItem(BMenuItem *item, bool forward)
BMenuItem * BMenuItem *
BMenu::_NextItem(BMenuItem *item, bool forward) const BMenu::_NextItem(BMenuItem *item, bool forward) const
{ {
if (item == NULL) { /*if (item == NULL) {
if (forward) if (forward)
return ItemAt(CountItems() - 1); return ItemAt(CountItems() - 1);
return ItemAt(0); return ItemAt(0);
} }
*/
// go to next item, and skip over disabled items such as separators
int32 index = fItems.IndexOf(item);
if (index < 0)
index = 0;
int32 index = fItems.IndexOf(item); int32 startIndex = index;
if (forward) do {
index++; if (forward)
else index++;
index--; else
index--;
if (index < 0 || index >= fItems.CountItems()) // cycle through menu items
return NULL; if (index < 0)
index = CountItems() - 1;
else if(index >= fItems.CountItems())
index = 0;
} while (!ItemAt(index)->IsEnabled() && index != startIndex);
if (index == startIndex) // we are back where we started and no item was enabled
return false;
return ItemAt(index); return ItemAt(index);
} }
@@ -2343,6 +2386,7 @@ BMenu::QuitTracking()
fChosenItem = NULL; fChosenItem = NULL;
fState = MENU_STATE_CLOSED; fState = MENU_STATE_CLOSED;
_Hide();
} }