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:
+55
-11
@@ -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--;
|
||||||
|
|
||||||
|
// cycle through menu items
|
||||||
|
if (index < 0)
|
||||||
|
index = CountItems() - 1;
|
||||||
|
else if(index >= fItems.CountItems())
|
||||||
|
index = 0;
|
||||||
|
} while (!ItemAt(index)->IsEnabled() && index != startIndex);
|
||||||
|
|
||||||
if (index < 0 || index >= fItems.CountItems())
|
if (index == startIndex) // we are back where we started and no item was enabled
|
||||||
return NULL;
|
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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user