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
This commit is contained in:
parent
5591ec214e
commit
4e338ac6df
@ -781,68 +781,35 @@ BMenu::MessageReceived(BMessage *msg)
|
|||||||
void
|
void
|
||||||
BMenu::KeyDown(const char *bytes, int32 numBytes)
|
BMenu::KeyDown(const char *bytes, int32 numBytes)
|
||||||
{
|
{
|
||||||
|
// TODO: Test how it works on beos and implement it correctly
|
||||||
switch (bytes[0]) {
|
switch (bytes[0]) {
|
||||||
/*case B_UP_ARROW:
|
case B_UP_ARROW:
|
||||||
{
|
if (fLayout == B_ITEMS_IN_COLUMN)
|
||||||
if (fSelected) {
|
SelectNextItem(fSelected, false);
|
||||||
fSelected->fSelected = false;
|
|
||||||
|
|
||||||
if (fSelected == fItems.FirstItem())
|
|
||||||
fSelected = static_cast<BMenuItem *>(fItems.LastItem());
|
|
||||||
else
|
|
||||||
fSelected = ItemAt(IndexOf(fSelected) - 1);
|
|
||||||
} else
|
|
||||||
fSelected = static_cast<BMenuItem *>(fItems.LastItem());
|
|
||||||
|
|
||||||
fSelected->fSelected = true;
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
case B_DOWN_ARROW:
|
case B_DOWN_ARROW:
|
||||||
{
|
if (fLayout == B_ITEMS_IN_COLUMN)
|
||||||
if (fSelected) {
|
SelectNextItem(fSelected, true);
|
||||||
fSelected->fSelected = false;
|
|
||||||
|
|
||||||
if (fSelected == fItems.LastItem())
|
|
||||||
fSelected = static_cast<BMenuItem *>(fItems.FirstItem());
|
|
||||||
else
|
|
||||||
fSelected = ItemAt(IndexOf(fSelected) + 1);
|
|
||||||
} else
|
|
||||||
fSelected = static_cast<BMenuItem *>(fItems.FirstItem());
|
|
||||||
|
|
||||||
fSelected->fSelected = true;
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
case B_HOME:
|
|
||||||
{
|
|
||||||
if (fSelected)
|
|
||||||
fSelected->fSelected = false;
|
|
||||||
|
|
||||||
fSelected = static_cast<BMenuItem *>(fItems.FirstItem());
|
|
||||||
fSelected->fSelected = true;
|
|
||||||
|
|
||||||
|
case B_LEFT_ARROW:
|
||||||
|
if (fLayout == B_ITEMS_IN_ROW)
|
||||||
|
SelectNextItem(fSelected, false);
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
case B_END:
|
|
||||||
{
|
|
||||||
if (fSelected)
|
|
||||||
fSelected->fSelected = false;
|
|
||||||
|
|
||||||
fSelected = static_cast<BMenuItem *>(fItems.LastItem());
|
|
||||||
fSelected->fSelected = true;
|
|
||||||
|
|
||||||
|
case B_RIGHT_ARROW:
|
||||||
|
if (fLayout == B_ITEMS_IN_ROW)
|
||||||
|
SelectNextItem(fSelected, true);
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
case B_ENTER:
|
case B_ENTER:
|
||||||
case B_SPACE:
|
case B_SPACE:
|
||||||
{
|
|
||||||
if (fSelected)
|
if (fSelected)
|
||||||
InvokeItem(fSelected);
|
InvokeItem(fSelected);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
*/
|
|
||||||
case B_ESCAPE:
|
case B_ESCAPE:
|
||||||
QuitTracking();
|
QuitTracking();
|
||||||
break;
|
break;
|
||||||
@ -1330,6 +1297,7 @@ BMenu::_track(int *action, bigtime_t trackTime, long start)
|
|||||||
if (IsStickyMode())
|
if (IsStickyMode())
|
||||||
submenu->SetStickyMode(true);
|
submenu->SetStickyMode(true);
|
||||||
BMenuItem *submenuItem = submenu->_track(&submenuAction, trackTime);
|
BMenuItem *submenuItem = submenu->_track(&submenuAction, trackTime);
|
||||||
|
//submenu->Window()->Activate();
|
||||||
if (submenuAction == MENU_STATE_CLOSED) {
|
if (submenuAction == MENU_STATE_CLOSED) {
|
||||||
item = submenuItem;
|
item = submenuItem;
|
||||||
fState = submenuAction;
|
fState = submenuAction;
|
||||||
@ -1910,9 +1878,7 @@ BMenu::Uninstall()
|
|||||||
|
|
||||||
void
|
void
|
||||||
BMenu::SelectItem(BMenuItem *menuItem, uint32 showSubmenu, bool selectFirstItem)
|
BMenu::SelectItem(BMenuItem *menuItem, uint32 showSubmenu, bool selectFirstItem)
|
||||||
{
|
{
|
||||||
// TODO: make use of "selectFirstItem"
|
|
||||||
|
|
||||||
// Avoid deselecting and then reselecting the same item
|
// Avoid deselecting and then reselecting the same item
|
||||||
// which would cause flickering
|
// which would cause flickering
|
||||||
if (menuItem != fSelected) {
|
if (menuItem != fSelected) {
|
||||||
@ -1930,8 +1896,10 @@ BMenu::SelectItem(BMenuItem *menuItem, uint32 showSubmenu, bool selectFirstItem)
|
|||||||
|
|
||||||
if (fSelected != NULL && showSubmenu == 0) {
|
if (fSelected != NULL && showSubmenu == 0) {
|
||||||
BMenu *subMenu = fSelected->Submenu();
|
BMenu *subMenu = fSelected->Submenu();
|
||||||
if (subMenu != NULL && subMenu->Window() == NULL)
|
if (subMenu != NULL && subMenu->Window() == NULL) {
|
||||||
subMenu->_show();
|
subMenu->_show(selectFirstItem);
|
||||||
|
subMenu->Window()->Activate();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1958,6 +1926,13 @@ 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 (forward)
|
||||||
|
return ItemAt(CountItems() - 1);
|
||||||
|
else
|
||||||
|
return ItemAt(0);
|
||||||
|
}
|
||||||
|
|
||||||
int32 index = fItems.IndexOf(item);
|
int32 index = fItems.IndexOf(item);
|
||||||
if (forward)
|
if (forward)
|
||||||
index++;
|
index++;
|
||||||
@ -2133,6 +2108,7 @@ BMenu::QuitTracking()
|
|||||||
if (BMenuBar *menuBar = dynamic_cast<BMenuBar *>(this))
|
if (BMenuBar *menuBar = dynamic_cast<BMenuBar *>(this))
|
||||||
menuBar->RestoreFocus();
|
menuBar->RestoreFocus();
|
||||||
|
|
||||||
|
fChosenItem = NULL;
|
||||||
fState = MENU_STATE_CLOSED;
|
fState = MENU_STATE_CLOSED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -391,7 +391,14 @@ BMenuBar::Track(int32 *action, int32 startIndex, bool showMenu)
|
|||||||
// TODO: Cleanup, merge some "if" blocks if possible
|
// TODO: Cleanup, merge some "if" blocks if possible
|
||||||
BMenuItem *resultItem = NULL;
|
BMenuItem *resultItem = NULL;
|
||||||
BWindow *window = Window();
|
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) {
|
while (true) {
|
||||||
bigtime_t snoozeAmount = 40000;
|
bigtime_t snoozeAmount = 40000;
|
||||||
bool locked = window->Lock();//WithTimeout(200000)
|
bool locked = window->Lock();//WithTimeout(200000)
|
||||||
@ -421,7 +428,7 @@ BMenuBar::Track(int32 *action, int32 startIndex, bool showMenu)
|
|||||||
} else {
|
} else {
|
||||||
// Menu was already opened, close it and bail
|
// Menu was already opened, close it and bail
|
||||||
SelectItem(NULL);
|
SelectItem(NULL);
|
||||||
localAction = MENU_STATE_CLOSED;
|
fState = MENU_STATE_CLOSED;
|
||||||
resultItem = NULL;
|
resultItem = NULL;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -441,9 +448,14 @@ BMenuBar::Track(int32 *action, int32 startIndex, bool showMenu)
|
|||||||
snoozeAmount = 30000;
|
snoozeAmount = 30000;
|
||||||
if (IsStickyMode())
|
if (IsStickyMode())
|
||||||
menu->SetStickyMode(true);
|
menu->SetStickyMode(true);
|
||||||
|
int localAction;
|
||||||
resultItem = menu->_track(&localAction, system_time());
|
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);
|
SelectItem(NULL);
|
||||||
fState = MENU_STATE_TRACKING;
|
fState = MENU_STATE_TRACKING;
|
||||||
}
|
}
|
||||||
@ -451,10 +463,8 @@ BMenuBar::Track(int32 *action, int32 startIndex, bool showMenu)
|
|||||||
if (locked)
|
if (locked)
|
||||||
window->Unlock();
|
window->Unlock();
|
||||||
|
|
||||||
if (fState == MENU_STATE_CLOSED)
|
if (fState == MENU_STATE_CLOSED
|
||||||
break;
|
|| (buttons != 0 && IsStickyMode() && menuItem == NULL))
|
||||||
|
|
||||||
if (localAction == MENU_STATE_CLOSED || (buttons != 0 && IsStickyMode() && menuItem == NULL))
|
|
||||||
break;
|
break;
|
||||||
else if (buttons == 0 && !IsStickyMode()) {
|
else if (buttons == 0 && !IsStickyMode()) {
|
||||||
// On an item without a submenu
|
// On an item without a submenu
|
||||||
@ -484,7 +494,7 @@ BMenuBar::Track(int32 *action, int32 startIndex, bool showMenu)
|
|||||||
DeleteMenuWindow();
|
DeleteMenuWindow();
|
||||||
|
|
||||||
if (action != NULL)
|
if (action != NULL)
|
||||||
*action = static_cast<int32>(localAction);
|
*action = fState;
|
||||||
|
|
||||||
return resultItem;
|
return resultItem;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user