[prev in list] [next in list] [prev in thread] [next in thread]
List: haiku-commits
Subject: [haiku-commits] Change in haiku[master]: Interface kit: rewrite menu logic by using input event
From: Gerrit <review () review ! haiku-os ! org>
Date: 2020-02-27 3:03:20
Message-ID: gerrit.1582772598000.Ia693570e9bf4cbea33cd7d71bd5e7249c089959f () review ! haiku-os ! org
[Download RAW message or body]
From X512 <danger_mail@list.ru>:
X512 has uploaded this change for review. ( https://review.haiku-os.org/c/haiku/+/2284 )
Change subject: Interface kit: rewrite menu logic by using input event
......................................................................
Interface kit: rewrite menu logic by using input event
WIP, DON'T MERGE
Keyboard navigation is implemented:
* Alt+Esc opens menu.
* Arrow keys are used to move to previous/next item and enter/leave submenu.
* Character key invoke or enter item with underlined character.
* Enter invoke menu, Esc leave current menu.
TODO:
* Fix mouse deadlock.
* Close menu when clicked outside.
* Fix sticky mode.
* Scroll menu on keyboard navigation.
* Fix freeze when dymanically building submenu
Change-Id: Ia693570e9bf4cbea33cd7d71bd5e7249c089959f
---
M headers/os/interface/Menu.h
M headers/private/interface/MenuPrivate.h
M src/kits/interface/Menu.cpp
M src/kits/interface/MenuBar.cpp
4 files changed, 243 insertions(+), 417 deletions(-)
git pull ssh://git.haiku-os.org:22/haiku refs/changes/84/2284/1
diff --git a/headers/os/interface/Menu.h b/headers/os/interface/Menu.h
index dcb8ab6..e465a33 100644
--- a/headers/os/interface/Menu.h
+++ b/headers/os/interface/Menu.h
@@ -17,6 +17,7 @@
namespace BPrivate {
+ class MenuTrackState;
class BMenuWindow;
class ExtraMenuData;
class TriggerList;
@@ -190,7 +191,7 @@
bool _Show(bool selectFirstItem = false,
bool keyDown = false);
void _Hide();
- BMenuItem* _Track(int* action, long start = -1);
+ BMenuItem* _Track(int32* action, int32 start = -1);
void _UpdateNavigationArea(BPoint position,
BRect& navAreaRectAbove,
@@ -281,7 +282,7 @@
static uint32 sCommandKey;
static uint32 sMenuKey;
- BMenuItem* fChosenItem;
+ BPrivate::MenuTrackState* fTrackState;
BList fItems;
BRect fPad;
BMenuItem* fSelected;
diff --git a/headers/private/interface/MenuPrivate.h b/headers/private/interface/MenuPrivate.h
index 4627b70..e819fc8 100644
--- a/headers/private/interface/MenuPrivate.h
+++ b/headers/private/interface/MenuPrivate.h
@@ -11,6 +11,7 @@
#include <Menu.h>
+#include <Locker.h>
enum menu_states {
@@ -21,6 +22,10 @@
MENU_STATE_CLOSED = 5
};
+enum menu_track_command {
+ MENU_TRACK_COMMAND_DONE = 0
+};
+
class BBitmap;
class BMenu;
@@ -78,6 +83,19 @@
};
+struct MenuTrackState {
+ thread_id trackThread;
+ BLocker locker;
+ bool quit;
+ BMenu* rootMenu;
+ BMenu* curMenu;
+ BMenuItem *invokedItem;
+ BRect navAreaRectAbove;
+ BRect navAreaRectBelow;
+ bigtime_t selectedTime;
+ bigtime_t navigationAreaTime;
+};
+
}; // namespace BPrivate
diff --git a/src/kits/interface/Menu.cpp b/src/kits/interface/Menu.cpp
index 079918b..288638d 100644
--- a/src/kits/interface/Menu.cpp
+++ b/src/kits/interface/Menu.cpp
@@ -39,6 +39,7 @@
#include <SystemCatalog.h>
#include <UnicodeChar.h>
#include <Window.h>
+#include <AutoLocker.h>
#include <AppServerLink.h>
#include <binary_compatibility/Interface.h>
@@ -226,7 +227,7 @@
BMenu::BMenu(const char* name, menu_layout layout)
:
BView(BRect(0, 0, 0, 0), name, 0, B_WILL_DRAW),
- fChosenItem(NULL),
+ fTrackState(NULL),
fPad(std::max(14.0f, be_plain_font->Size() + 2.0f), 2.0f, 20.0f, 0.0f),
fSelected(NULL),
fCachedMenuWindow(NULL),
@@ -261,7 +262,7 @@
BMenu::BMenu(const char* name, float width, float height)
:
BView(BRect(0.0f, 0.0f, 0.0f, 0.0f), name, 0, B_WILL_DRAW),
- fChosenItem(NULL),
+ fTrackState(NULL),
fPad(14.0f, 2.0f, 20.0f, 0.0f),
fSelected(NULL),
fCachedMenuWindow(NULL),
@@ -296,7 +297,7 @@
BMenu::BMenu(BMessage* archive)
:
BView(archive),
- fChosenItem(NULL),
+ fTrackState(NULL),
fPad(14.0f, 2.0f, 20.0f, 0.0f),
fSelected(NULL),
fCachedMenuWindow(NULL),
@@ -453,6 +454,10 @@
void
BMenu::MessageReceived(BMessage* message)
{
+ if (fTrackState == NULL) {
+ BView::MessageReceived(message);
+ return;
+ }
switch (message->what) {
case B_MOUSE_WHEEL_CHANGED:
{
@@ -479,6 +484,58 @@
break;
}
+ case B_MOUSE_DOWN:
+ if (fStickyMode) {
+ if (fSelected != NULL) {
+ _InvokeItem(fSelected);
+ }
+ _QuitTracking(false);
+ }
+ BView::MessageReceived(message);
+ break;
+ case B_MOUSE_UP:
+ if (!fStickyMode) {
+ if (fSelected != NULL) {
+ _InvokeItem(fSelected);
+ }
+ _QuitTracking(false);
+ }
+ BView::MessageReceived(message);
+ break;
+ case B_MOUSE_MOVED: {
+ BPoint where = B_ORIGIN;
+ int32 buttons = 0;
+ int32 transit = B_OUTSIDE_VIEW;
+
+ message->FindPoint("be:view_where", &where);
+ message->FindInt32("buttons", &buttons);
+ message->FindInt32("be:transit", &transit);
+
+ if (fTrackState == NULL) {
+ BView::MessageReceived(message);
+ return;
+ }
+
+ AutoLocker<BLocker> locker(fTrackState->locker);
+
+ BMenuItem *oldSelected = fSelected;
+ BMenuItem* item = _HitTestItems(where, B_ORIGIN);
+ if (item == NULL) {
+ if ((fSelected != NULL) && (fSelected->Submenu() == NULL)) {
+ _SelectItem(NULL);
+ }
+ } else {
+ _UpdateStateOpenSelect(item, where, fTrackState->navAreaRectAbove,
+ fTrackState->navAreaRectBelow, fTrackState->selectedTime, fTrackState->navigationAreaTime);
+ }
+
+ if (fSelected != oldSelected)
+ fTrackState->curMenu = this;
+
+ BView::MessageReceived(message);
+ break;
+ }
+
default:
BView::MessageReceived(message);
break;
@@ -490,63 +547,70 @@
BMenu::KeyDown(const char* bytes, int32 numBytes)
{
// TODO: Test how it works on BeOS R5 and implement this correctly
+
+ if (fTrackState == NULL)
+ return;
+
+ AutoLocker<BLocker> locker(fTrackState->locker);
+
+ if (fTrackState->curMenu != this) {
+ BMessenger messenger(fTrackState->curMenu);
+ messenger.SendMessage(Window()->CurrentMessage());
+ return;
+ }
switch (bytes[0]) {
case B_UP_ARROW:
- if (fLayout == B_ITEMS_IN_COLUMN)
+ if (fLayout == B_ITEMS_IN_COLUMN) {
_SelectNextItem(fSelected, false);
+ } else if (fLayout == B_ITEMS_IN_ROW || fLayout == B_ITEMS_IN_MATRIX) {
+ if (Supermenu() != NULL) {
+ _SelectItem(NULL);
+ fTrackState->curMenu = Supermenu();
+ } else {
+ _QuitTracking(false);
+ }
+ }
break;
case B_DOWN_ARROW:
- {
- BMenuBar* bar = dynamic_cast<BMenuBar*>(Supermenu());
- if (bar != NULL && fState == MENU_STATE_CLOSED) {
- // tell MenuBar's _Track:
- bar->fState = MENU_STATE_KEY_TO_SUBMENU;
- }
- if (fLayout == B_ITEMS_IN_COLUMN)
+ if (fLayout == B_ITEMS_IN_COLUMN) {
_SelectNextItem(fSelected, true);
- break;
- }
-
- case B_LEFT_ARROW:
- if (fLayout == B_ITEMS_IN_ROW)
- _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 messenger(Supermenu());
- messenger.SendMessage(Window()->CurrentMessage());
- } else {
- // tell _Track
- fState = MENU_STATE_KEY_LEAVE_SUBMENU;
+ } else if (fLayout == B_ITEMS_IN_ROW || fLayout == B_ITEMS_IN_MATRIX) {
+ if (fSelected != NULL) {
+ BMenu* subMenu = fSelected->Submenu();
+ if (subMenu != NULL && subMenu->LockLooper()) {
+ subMenu->_SelectNextItem(subMenu->fSelected, true);
+ subMenu->UnlockLooper();
+ fTrackState->curMenu = subMenu;
}
}
}
break;
+ case B_LEFT_ARROW:
+ if (fLayout == B_ITEMS_IN_ROW || fLayout == B_ITEMS_IN_MATRIX) {
+ _SelectNextItem(fSelected, false);
+ } else if (fLayout == B_ITEMS_IN_COLUMN) {
+ if (Supermenu() != NULL) {
+ _SelectItem(NULL);
+ fTrackState->curMenu = Supermenu();
+ } else {
+ _QuitTracking(false);
+ }
+ }
+ break;
+
case B_RIGHT_ARROW:
- if (fLayout == B_ITEMS_IN_ROW)
+ if (fLayout == B_ITEMS_IN_ROW || fLayout == B_ITEMS_IN_MATRIX) {
_SelectNextItem(fSelected, true);
- else {
- if (fSelected != NULL && fSelected->Submenu() != NULL) {
- fSelected->Submenu()->_SetStickyMode(true);
- // fix me: this shouldn't be needed but dynamic menus
- // aren't getting it set correctly when keyboard
- // navigating, which aborts the attach
- fState = MENU_STATE_KEY_TO_SUBMENU;
- _SelectItem(fSelected, true, 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 messenger(Supermenu());
- messenger.SendMessage(Window()->CurrentMessage());
+ } else if (fLayout == B_ITEMS_IN_COLUMN) {
+ if (fSelected != NULL) {
+ BMenu* subMenu = fSelected->Submenu();
+ if (subMenu != NULL && subMenu->LockLooper()) {
+ subMenu->_SelectNextItem(subMenu->fSelected, true);
+ subMenu->UnlockLooper();
+ fTrackState->curMenu = subMenu;
+ }
}
}
break;
@@ -569,21 +633,18 @@
case B_ENTER:
case B_SPACE:
if (fSelected != NULL) {
- fChosenItem = fSelected;
- // preserve for exit handling
+ _InvokeItem(fSelected);
_QuitTracking(false);
}
break;
case B_ESCAPE:
- _SelectItem(NULL);
- if (fState == MENU_STATE_CLOSED
- && dynamic_cast<BMenuBar*>(Supermenu())) {
- // Keyboard may show menu without tracking it
- BMessenger messenger(Supermenu());
- messenger.SendMessage(Window()->CurrentMessage());
- } else
+ if (Supermenu() != NULL) {
+ _SelectItem(NULL);
+ fTrackState->curMenu = Supermenu();
+ } else {
_QuitTracking(false);
+ }
break;
default:
@@ -595,8 +656,18 @@
if (item->fTriggerIndex < 0 || item->fTrigger != trigger)
continue;
- _InvokeItem(item);
- _QuitTracking(false);
+ if (item->Submenu()) {
+ _SelectItem(item, true, false, true);
+ BMenu* subMenu = fSelected->Submenu();
+ if (subMenu != NULL && subMenu->LockLooper()) {
+ subMenu->_SelectNextItem(subMenu->fSelected, true);
+ subMenu->UnlockLooper();
+ fTrackState->curMenu = subMenu;
+ }
+ } else {
+ _InvokeItem(item);
+ _QuitTracking(false);
+ }
break;
}
break;
@@ -1299,7 +1370,7 @@
menu_layout layout, bool resizeToFit)
:
BView(frame, name, resizingMode, flags),
- fChosenItem(NULL),
+ fTrackState(NULL),
fSelected(NULL),
fCachedMenuWindow(NULL),
fSuper(NULL),
@@ -1402,7 +1473,7 @@
_SetStickyMode(sticky);
- int action;
+ int32 action;
BMenuItem* menuItem = _Track(&action);
fExtraRect = NULL;
@@ -1550,6 +1621,7 @@
addAborted = _AddDynamicItems(keyDown);
if (addAborted) {
+ printf("addAborted\n");
if (ourWindow)
window->Quit();
else
@@ -1569,6 +1641,7 @@
// Menu didn't have the time to add its items: aborting...
if (fAttachAborted) {
+ printf("fAttachAborted\n");
window->DetachMenu();
// TODO: Probably not needed, we can just let _hide() quit the
// window.
@@ -1582,6 +1655,9 @@
_UpdateWindowViewSize(true);
window->Show();
+ if (Supermenu() != NULL)
+ fTrackState = Supermenu()->fTrackState;
+
if (selectFirstItem)
_SelectItem(ItemAt(0), false);
@@ -1602,6 +1678,8 @@
if (fSelected != NULL)
_SelectItem(NULL);
+ fTrackState = NULL;
+
window->Hide();
window->DetachMenu();
// we don't want to be deleted when the window is removed
@@ -1622,189 +1700,67 @@
// #pragma mark - mouse tracking
-const static bigtime_t kOpenSubmenuDelay = 0;
const static bigtime_t kNavigationAreaTimeout = 1000000;
BMenuItem*
-BMenu::_Track(int* action, long start)
+BMenu::_Track(int32* action, int32 start)
{
- // TODO: cleanup
+ if (fTrackState != NULL) {
+ printf("Track: already entered\n");
+ return NULL;
+ }
+ printf("+Track\n");
+ printf("sticky: %d\n", fStickyMode);
+ _SetStickyMode(true); // !!!
+ BPrivate::MenuTrackState trackState;
BMenuItem* item = NULL;
- BRect navAreaRectAbove;
- BRect navAreaRectBelow;
- bigtime_t selectedTime = system_time();
- bigtime_t navigationAreaTime = 0;
+ BMenuItem* startItem = ItemAt(start);
+ thread_id senderThread;
+ bool run = true;
- fState = MENU_STATE_TRACKING;
- fChosenItem = NULL;
- // we will use this for keyboard selection
+ fTrackState = &trackState;
+ fTrackState->trackThread = find_thread(NULL);
+ fTrackState->quit = false;
+ fTrackState->rootMenu = this;
+ fTrackState->curMenu = this;
+ fTrackState->invokedItem = NULL;
+ fTrackState->navAreaRectAbove = BRect();
+ fTrackState->navAreaRectBelow = BRect();
- BPoint location;
- uint32 buttons = 0;
if (LockLooper()) {
- GetMouse(&location, &buttons);
+ if (startItem != NULL)
+ _SelectItem(startItem, true, false, true);
+ else {
+ BPoint where;
+ GetMouse(&where, NULL);
+ _SelectItem(_HitTestItems(where, B_ORIGIN), true, false, true);
+ }
UnlockLooper();
}
-
- bool releasedOnce = buttons == 0;
- while (fState != MENU_STATE_CLOSED) {
- if (_CustomTrackingWantsToQuit())
+ while (run) {
+ int32 cmd = receive_data(&senderThread, NULL, 0);
+ switch (cmd) {
+ case MENU_TRACK_COMMAND_DONE:
+ run = false;
break;
-
- if (!LockLooper())
- break;
-
- BMenuWindow* window = static_cast<BMenuWindow*>(Window());
- BPoint screenLocation = ConvertToScreen(location);
- if (window->CheckForScrolling(screenLocation)) {
- UnlockLooper();
- continue;
- }
-
- // The order of the checks is important
- // to be able to handle overlapping menus:
- // first we check if mouse is inside a submenu,
- // then if the mouse is inside this menu,
- // then if it's over a super menu.
- if (_OverSubmenu(fSelected, screenLocation)
- || fState == MENU_STATE_KEY_TO_SUBMENU) {
- if (fState == MENU_STATE_TRACKING) {
- // not if from R.Arrow
- fState = MENU_STATE_TRACKING_SUBMENU;
- }
- navAreaRectAbove = BRect();
- navAreaRectBelow = BRect();
-
- // Since the submenu has its own looper,
- // we can unlock ours. Doing so also make sure
- // that our window gets any update message to
- // redraw itself
- UnlockLooper();
-
- // To prevent NULL access violation, ensure a menu has actually
- // been selected and that it has a submenu. Because keyboard and
- // mouse interactions set selected items differently, the menu
- // tracking thread needs to be careful in triggering the navigation
- // to the submenu.
- if (fSelected != NULL) {
- BMenu* submenu = fSelected->Submenu();
- int submenuAction = MENU_STATE_TRACKING;
- if (submenu != NULL) {
- submenu->_SetStickyMode(_IsStickyMode());
-
- // The following call blocks until the submenu
- // gives control back to us, either because the mouse
- // pointer goes out of the submenu's bounds, or because
- // the user closes the menu
- BMenuItem* submenuItem = submenu->_Track(&submenuAction);
- if (submenuAction == MENU_STATE_CLOSED) {
- item = submenuItem;
- fState = MENU_STATE_CLOSED;
- } else if (submenuAction == MENU_STATE_KEY_LEAVE_SUBMENU) {
- if (LockLooper()) {
- BMenuItem* temp = fSelected;
- // close the submenu:
- _SelectItem(NULL);
- // but reselect the item itself for user:
- _SelectItem(temp, false);
- UnlockLooper();
- }
- // cancel key-nav state
- fState = MENU_STATE_TRACKING;
- } else
- fState = MENU_STATE_TRACKING;
- }
- }
- if (!LockLooper())
- break;
- } else if ((item = _HitTestItems(location, B_ORIGIN)) != NULL) {
- _UpdateStateOpenSelect(item, location, navAreaRectAbove,
- navAreaRectBelow, selectedTime, navigationAreaTime);
- releasedOnce = true;
- } else if (_OverSuper(screenLocation)
- && fSuper->fState != MENU_STATE_KEY_TO_SUBMENU) {
- fState = MENU_STATE_TRACKING;
- UnlockLooper();
- break;
- } else if (fState == MENU_STATE_KEY_LEAVE_SUBMENU) {
- UnlockLooper();
- break;
- } else if (fSuper == NULL
- || fSuper->fState != MENU_STATE_KEY_TO_SUBMENU) {
- // Mouse pointer outside menu:
- // If there's no other submenu opened,
- // deselect the current selected item
- if (fSelected != NULL
- && (fSelected->Submenu() == NULL
- || fSelected->Submenu()->Window() == NULL)) {
- _SelectItem(NULL);
- fState = MENU_STATE_TRACKING;
- }
-
- if (fSuper != NULL) {
- // Give supermenu the chance to continue tracking
- *action = fState;
- UnlockLooper();
- return NULL;
- }
- }
-
- UnlockLooper();
-
- if (releasedOnce)
- _UpdateStateClose(item, location, buttons);
-
- if (fState != MENU_STATE_CLOSED) {
- bigtime_t snoozeAmount = 50000;
-
- BPoint newLocation = location;
- uint32 newButtons = buttons;
-
- // If user doesn't move the mouse, loop here,
- // so we don't interfere with keyboard menu navigation
- do {
- snooze(snoozeAmount);
- if (!LockLooper())
- break;
- GetMouse(&newLocation, &newButtons, true);
- UnlockLooper();
- } while (newLocation == location && newButtons == buttons
- && !(item != NULL && item->Submenu() != NULL
- && item->Submenu()->Window() == NULL)
- && fState == MENU_STATE_TRACKING);
-
- if (newLocation != location || newButtons != buttons) {
- if (!releasedOnce && newButtons == 0 && buttons != 0)
- releasedOnce = true;
- location = newLocation;
- buttons = newButtons;
- }
-
- if (releasedOnce)
- _UpdateStateClose(item, location, buttons);
}
}
- if (action != NULL)
- *action = fState;
+ item = fTrackState->invokedItem;
- // keyboard Enter will set this
- if (fChosenItem != NULL)
- item = fChosenItem;
- else if (fSelected == NULL) {
- // needed to cover (rare) mouse/ESC combination
- item = NULL;
- }
-
- if (fSelected != NULL && LockLooper()) {
+ if (LockLooper()) {
+ // hide submenus
_SelectItem(NULL);
UnlockLooper();
}
+ fTrackState = NULL;
+
// delete the menu window recycled for all the child menus
_DeleteMenuWindow();
+ printf("-Track\n");
return item;
}
@@ -1889,9 +1845,10 @@
BRect& navAreaRectAbove, BRect& navAreaRectBelow, bigtime_t& selectedTime,
bigtime_t& navigationAreaTime)
{
- if (fState == MENU_STATE_CLOSED)
+ if (fLayout != B_ITEMS_IN_COLUMN) {
+ _SelectItem(item, true);
return;
-
+ }
if (item != fSelected) {
if (navigationAreaTime == 0)
navigationAreaTime = system_time();
@@ -1954,8 +1911,7 @@
selectedTime = system_time();
navigationAreaTime = 0;
}
- } else if (fSelected->Submenu() != NULL &&
- system_time() - selectedTime > kOpenSubmenuDelay) {
+ } else if (fSelected->Submenu() != NULL) {
_SelectItem(fSelected, true);
if (!navAreaRectAbove.IsValid() && !navAreaRectBelow.IsValid()) {
@@ -1964,9 +1920,6 @@
navAreaRectBelow);
}
}
-
- if (fState != MENU_STATE_TRACKING)
- fState = MENU_STATE_TRACKING;
}
@@ -2378,7 +2331,7 @@
BPoint point;
if (superMenu->Layout() == B_ITEMS_IN_COLUMN)
- point = superItem->Frame().RightTop() + BPoint(1.0f, 1.0f);
+ point = superItem->Frame().RightTop() + BPoint(1.0f, 0.0f);
else
point = superItem->Frame().LeftBottom() + BPoint(1.0f, 1.0f);
@@ -2497,10 +2450,34 @@
if (!item->IsEnabled())
return;
+ // called from BWindow for shortcut handling
+ if (now) {
+ // Lock the root menu window before calling BMenuItem::Invoke()
+ BMenu* parent = this;
+ BMenu* rootMenu = NULL;
+ do {
+ rootMenu = parent;
+ parent = rootMenu->Supermenu();
+ } while (parent != NULL);
+
+ if (rootMenu->LockLooper()) {
+ item->Invoke();
+ rootMenu->UnlockLooper();
+ }
+ return;
+ }
+
+ {
+ if (fTrackState == NULL)
+ return;
+ AutoLocker<BLocker> locker(fTrackState->locker);
+ if (fTrackState->invokedItem != NULL)
+ return;
+ fTrackState->invokedItem = item;
+ }
+
// Do the "selected" animation
- // TODO: Doesn't work. This is supposed to highlight
- // and dehighlight the item, works on beos but not on haiku.
- if (!item->Submenu() && LockLooper()) {
+ if (LockLooper()) {
snooze(50000);
item->Select(true);
Window()->UpdateIfNeeded();
@@ -2515,19 +2492,6 @@
Window()->UpdateIfNeeded();
UnlockLooper();
}
-
- // Lock the root menu window before calling BMenuItem::Invoke()
- BMenu* parent = this;
- BMenu* rootMenu = NULL;
- do {
- rootMenu = parent;
- parent = rootMenu->Supermenu();
- } while (parent != NULL);
-
- if (rootMenu->LockLooper()) {
- item->Invoke();
- rootMenu->UnlockLooper();
- }
}
@@ -2680,6 +2644,7 @@
if (subMenu != NULL && subMenu->Window() == NULL) {
if (!subMenu->_Show(selectFirstItem, keyDown)) {
// something went wrong, deselect the item
+ printf("_SelectItem: can't show submenu\n");
fSelected->Select(false);
fSelected = NULL;
}
@@ -2698,7 +2663,7 @@
if (nextItem == NULL)
return false;
- _SelectItem(nextItem, dynamic_cast<BMenuBar*>(this) != NULL);
+ _SelectItem(nextItem, true, false, true);
if (LockLooper()) {
be_app->ObscureCursor();
@@ -3000,24 +2965,7 @@
bool
BMenu::_OkToProceed(BMenuItem* item, bool keyDown)
{
- BPoint where;
- uint32 buttons;
- GetMouse(&where, &buttons, false);
- bool stickyMode = _IsStickyMode();
- // Quit if user clicks the mouse button in sticky mode
- // or releases the mouse button in nonsticky mode
- // or moves the pointer over another item
- // TODO: I added the check for BMenuBar to solve a problem with Deskbar.
- // BeOS seems to do something similar. This could also be a bug in
- // Deskbar, though.
- if ((buttons != 0 && stickyMode)
- || ((dynamic_cast<BMenuBar*>(this) == NULL
- && (buttons == 0 && !stickyMode))
- || ((_HitTestItems(where) != item) && !keyDown))) {
- return false;
- }
-
- return true;
+ return true; /* !!! */
}
@@ -3037,27 +2985,11 @@
void
BMenu::_QuitTracking(bool onlyThis)
{
- _SelectItem(NULL);
- if (BMenuBar* menuBar = dynamic_cast<BMenuBar*>(this))
- menuBar->_RestoreFocus();
-
- fState = MENU_STATE_CLOSED;
-
- if (!onlyThis) {
- // Close the whole menu hierarchy
- if (Supermenu() != NULL)
- Supermenu()->fState = MENU_STATE_CLOSED;
-
- if (_IsStickyMode())
- _SetStickyMode(false);
-
- if (LockLooper()) {
- be_app->ShowCursor();
- UnlockLooper();
- }
- }
-
- _Hide();
+ if (fTrackState == NULL)
+ return;
+ AutoLocker<BLocker> locker(fTrackState->locker);
+ fTrackState->quit = true;
+ send_data(fTrackState->trackThread, MENU_TRACK_COMMAND_DONE, NULL, 0);
}
diff --git a/src/kits/interface/MenuBar.cpp b/src/kits/interface/MenuBar.cpp
index 791cbc4..81cae9d 100644
--- a/src/kits/interface/MenuBar.cpp
+++ b/src/kits/interface/MenuBar.cpp
@@ -173,6 +173,9 @@
void
BMenuBar::WindowActivated(bool state)
{
+ if (!state) {
+ BPrivate::MenuPrivate(this).QuitTracking(false);
+ }
BView::WindowActivated(state);
}
@@ -550,152 +553,24 @@
BMenuItem*
BMenuBar::_Track(int32* action, int32 startIndex, bool showMenu)
{
- // TODO: Cleanup, merge some "if" blocks if possible
BMenuItem* item = NULL;
- fState = MENU_STATE_TRACKING;
- fChosenItem = NULL;
- // we will use this for keyboard selection
- BPoint where;
- uint32 buttons;
- if (LockLooper()) {
- if (startIndex != -1) {
- be_app->ObscureCursor();
- _SelectItem(ItemAt(startIndex), true, false);
- }
- GetMouse(&where, &buttons);
- UnlockLooper();
- }
-
- while (fState != MENU_STATE_CLOSED) {
- bigtime_t snoozeAmount = 40000;
- if (!LockLooper())
- break;
-
- item = dynamic_cast<_BMCMenuBar_*>(this) != NULL ? ItemAt(0)
- : _HitTestItems(where, B_ORIGIN);
-
- if (_OverSubmenu(fSelected, ConvertToScreen(where))
- || fState == MENU_STATE_KEY_TO_SUBMENU) {
- // call _Track() from the selected sub-menu when the mouse cursor
- // is over its window
- BMenu* submenu = fSelected->Submenu();
- UnlockLooper();
- snoozeAmount = 30000;
- submenu->_SetStickyMode(_IsStickyMode());
- int localAction;
- fChosenItem = submenu->_Track(&localAction);
-
- // The mouse could have meen moved since the last time we
- // checked its position, or buttons might have been pressed.
- // Unfortunately our child menus don't tell
- // us the new position.
- // TODO: Maybe have a shared struct between all menus
- // where to store the current mouse position ?
- // (Or just use the BView mouse hooks)
- BPoint newWhere;
- if (LockLooper()) {
- GetMouse(&newWhere, &buttons);
- UnlockLooper();
- }
-
- // Needed to make BMenuField child menus "sticky"
- // (see ticket #953)
- if (localAction == MENU_STATE_CLOSED) {
- if (fExtraRect != NULL && fExtraRect->Contains(where)
- && point_distance(newWhere, where) < 9) {
- // 9 = 3 pixels ^ 2 (since point_distance() returns the
- // square of the distance)
- _SetStickyMode(true);
- fExtraRect = NULL;
- } else
- fState = MENU_STATE_CLOSED;
- }
- if (!LockLooper())
- break;
- } else if (item != NULL) {
- if (item->Submenu() != NULL && item != fSelected) {
- if (item->Submenu()->Window() == NULL) {
- // open the menu if it's not opened yet
- _SelectItem(item);
- } else {
- // Menu was already opened, close it and bail
- _SelectItem(NULL);
- fState = MENU_STATE_CLOSED;
- fChosenItem = NULL;
- }
- } else {
- // No submenu, just select the item
- _SelectItem(item);
- }
- } else if (item == NULL && fSelected != NULL
- && !_IsStickyMode() && Bounds().Contains(where)) {
- _SelectItem(NULL);
- fState = MENU_STATE_TRACKING;
- }
-
- UnlockLooper();
-
- if (fState != MENU_STATE_CLOSED) {
- BPoint newWhere = where;
- uint32 newButtons = buttons;
-
- do {
- // If user doesn't move the mouse or change buttons loop
- // here so that we don't interfere with keyboard menu
- // navigation
- snooze(snoozeAmount);
- if (!LockLooper())
- break;
-
- GetMouse(&newWhere, &newButtons);
- UnlockLooper();
- } while (newWhere == where && newButtons == buttons
- && fState == MENU_STATE_TRACKING);
-
- if (newButtons != 0 && _IsStickyMode()) {
- if (item == NULL || (item->Submenu() != NULL
- && item->Submenu()->Window() != NULL)) {
- // clicked outside the menu bar or on item with already
- // open sub menu
- fState = MENU_STATE_CLOSED;
- } else
- _SetStickyMode(false);
- } else if (newButtons == 0 && !_IsStickyMode()) {
- if ((fSelected != NULL && fSelected->Submenu() == NULL)
- || item == NULL) {
- // clicked on an item without a submenu or clicked and
- // released the mouse button outside the menu bar
- fChosenItem = fSelected;
- fState = MENU_STATE_CLOSED;
- } else
- _SetStickyMode(true);
- }
- where = newWhere;
- buttons = newButtons;
- }
- }
+ item = BMenu::_Track(action, startIndex);
if (LockLooper()) {
if (fSelected != NULL)
_SelectItem(NULL);
- if (fChosenItem != NULL)
- fChosenItem->Invoke();
+ if (item != NULL)
+ item->Invoke();
_RestoreFocus();
UnlockLooper();
}
- if (_IsStickyMode())
- _SetStickyMode(false);
-
_DeleteMenuWindow();
- if (action != NULL)
- *action = fState;
-
- return fChosenItem;
+ return item;
}
--
To view, visit https://review.haiku-os.org/c/haiku/+/2284
To unsubscribe, or for help writing mail filters, visit https://review.haiku-os.org/settings
Gerrit-Project: haiku
Gerrit-Branch: master
Gerrit-Change-Id: Ia693570e9bf4cbea33cd7d71bd5e7249c089959f
Gerrit-Change-Number: 2284
Gerrit-PatchSet: 1
Gerrit-Owner: X512 <danger_mail@list.ru>
Gerrit-MessageType: newchange
[Attachment #3 (text/html)]
<p>X512 has uploaded this change for <strong>review</strong>.</p><p><a \
href="https://review.haiku-os.org/c/haiku/+/2284">View Change</a></p><pre \
style="font-family: monospace,monospace; white-space: pre-wrap;">Interface kit: \
rewrite menu logic by using input event<br><br>WIP, DON'T MERGE<br><br>Keyboard \
navigation is implemented:<br> * Alt+Esc opens menu.<br> * Arrow keys are used to \
move to previous/next item and enter/leave submenu.<br> * Character key invoke or \
enter item with underlined character.<br> * Enter invoke menu, Esc leave current \
menu.<br><br>TODO:<br> * Fix mouse deadlock.<br> * Close menu when clicked \
outside.<br> * Fix sticky mode.<br> * Scroll menu on keyboard navigation.<br> * Fix \
freeze when dymanically building submenu<br><br>Change-Id: \
Ia693570e9bf4cbea33cd7d71bd5e7249c089959f<br>---<br>M \
headers/os/interface/Menu.h<br>M headers/private/interface/MenuPrivate.h<br>M \
src/kits/interface/Menu.cpp<br>M src/kits/interface/MenuBar.cpp<br>4 files changed, \
243 insertions(+), 417 deletions(-)<br><br></pre><pre style="font-family: \
monospace,monospace; white-space: pre-wrap;">git pull ssh://git.haiku-os.org:22/haiku \
refs/changes/84/2284/1</pre><pre style="font-family: monospace,monospace; \
white-space: pre-wrap;"><span>diff --git a/headers/os/interface/Menu.h \
b/headers/os/interface/Menu.h</span><br><span>index dcb8ab6..e465a33 \
100644</span><br><span>--- a/headers/os/interface/Menu.h</span><br><span>+++ \
b/headers/os/interface/Menu.h</span><br><span>@@ -17,6 +17,7 @@</span><br><span> \
</span><br><span> </span><br><span> namespace BPrivate {</span><br><span \
style="color: hsl(120, 100%, 40%);">+ class MenuTrackState;</span><br><span> class \
BMenuWindow;</span><br><span> class ExtraMenuData;</span><br><span> class \
TriggerList;</span><br><span>@@ -190,7 +191,7 @@</span><br><span> \
bool _Show(bool selectFirstItem = false,</span><br><span> bool keyDown = \
false);</span><br><span> void _Hide();</span><br><span style="color: hsl(0, \
100%, 40%);">- BMenuItem* _Track(int* action, long start = -1);</span><br><span \
style="color: hsl(120, 100%, 40%);">+ BMenuItem* _Track(int32* action, int32 \
start = -1);</span><br><span> </span><br><span> \
void _UpdateNavigationArea(BPoint position,</span><br><span> BRect& \
navAreaRectAbove,</span><br><span>@@ -281,7 +282,7 @@</span><br><span> \
static uint32 sCommandKey;</span><br><span> \
static uint32 sMenuKey;</span><br><span> </span><br><span style="color: hsl(0, \
100%, 40%);">- BMenuItem* fChosenItem;</span><br><span style="color: hsl(120, \
100%, 40%);">+ BPrivate::MenuTrackState* fTrackState;</span><br><span> \
BList fItems;</span><br><span> BRect fPad;</span><br><span> \
BMenuItem* fSelected;</span><br><span>diff --git \
a/headers/private/interface/MenuPrivate.h \
b/headers/private/interface/MenuPrivate.h</span><br><span>index 4627b70..e819fc8 \
100644</span><br><span>--- \
a/headers/private/interface/MenuPrivate.h</span><br><span>+++ \
b/headers/private/interface/MenuPrivate.h</span><br><span>@@ -11,6 +11,7 \
@@</span><br><span> </span><br><span> </span><br><span> #include \
<Menu.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include \
<Locker.h></span><br><span> </span><br><span> </span><br><span> enum \
menu_states {</span><br><span>@@ -21,6 +22,10 @@</span><br><span> MENU_STATE_CLOSED \
= 5</span><br><span> };</span><br><span> </span><br><span style="color: hsl(120, \
100%, 40%);">+enum menu_track_command {</span><br><span style="color: hsl(120, 100%, \
40%);">+ MENU_TRACK_COMMAND_DONE = 0</span><br><span style="color: hsl(120, 100%, \
40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> \
</span><br><span> class BBitmap;</span><br><span> class BMenu;</span><br><span>@@ \
-78,6 +83,19 @@</span><br><span> </span><br><span> };</span><br><span> \
</span><br><span style="color: hsl(120, 100%, 40%);">+struct MenuTrackState \
{</span><br><span style="color: hsl(120, 100%, 40%);">+ thread_id \
trackThread;</span><br><span style="color: hsl(120, 100%, 40%);">+ BLocker \
locker;</span><br><span style="color: hsl(120, 100%, 40%);">+ bool \
quit;</span><br><span style="color: hsl(120, 100%, 40%);">+ BMenu* \
rootMenu;</span><br><span style="color: hsl(120, 100%, 40%);">+ BMenu* \
curMenu;</span><br><span style="color: hsl(120, 100%, 40%);">+ BMenuItem \
*invokedItem;</span><br><span style="color: hsl(120, 100%, 40%);">+ BRect \
navAreaRectAbove;</span><br><span style="color: hsl(120, 100%, 40%);">+ BRect \
navAreaRectBelow;</span><br><span style="color: hsl(120, 100%, 40%);">+ bigtime_t \
selectedTime;</span><br><span style="color: hsl(120, 100%, 40%);">+ bigtime_t \
navigationAreaTime;</span><br><span style="color: hsl(120, 100%, \
40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> \
}; // namespace BPrivate</span><br><span> </span><br><span> </span><br><span>diff \
--git a/src/kits/interface/Menu.cpp \
b/src/kits/interface/Menu.cpp</span><br><span>index 079918b..288638d \
100644</span><br><span>--- a/src/kits/interface/Menu.cpp</span><br><span>+++ \
b/src/kits/interface/Menu.cpp</span><br><span>@@ -39,6 +39,7 @@</span><br><span> \
#include <SystemCatalog.h></span><br><span> #include \
<UnicodeChar.h></span><br><span> #include <Window.h></span><br><span \
style="color: hsl(120, 100%, 40%);">+#include <AutoLocker.h></span><br><span> \
</span><br><span> #include <AppServerLink.h></span><br><span> #include \
<binary_compatibility/Interface.h></span><br><span>@@ -226,7 +227,7 \
@@</span><br><span> BMenu::BMenu(const char* name, menu_layout \
layout)</span><br><span> :</span><br><span> BView(BRect(0, 0, 0, 0), name, 0, \
B_WILL_DRAW),</span><br><span style="color: hsl(0, 100%, \
40%);">- fChosenItem(NULL),</span><br><span style="color: hsl(120, 100%, \
40%);">+ fTrackState(NULL),</span><br><span> fPad(std::max(14.0f, \
be_plain_font->Size() + 2.0f), 2.0f, 20.0f, 0.0f),</span><br><span> \
fSelected(NULL),</span><br><span> fCachedMenuWindow(NULL),</span><br><span>@@ -261,7 \
+262,7 @@</span><br><span> BMenu::BMenu(const char* name, float width, float \
height)</span><br><span> :</span><br><span> BView(BRect(0.0f, 0.0f, 0.0f, 0.0f), \
name, 0, B_WILL_DRAW),</span><br><span style="color: hsl(0, 100%, \
40%);">- fChosenItem(NULL),</span><br><span style="color: hsl(120, 100%, \
40%);">+ fTrackState(NULL),</span><br><span> fPad(14.0f, 2.0f, 20.0f, \
0.0f),</span><br><span> fSelected(NULL),</span><br><span> \
fCachedMenuWindow(NULL),</span><br><span>@@ -296,7 +297,7 @@</span><br><span> \
BMenu::BMenu(BMessage* archive)</span><br><span> :</span><br><span> \
BView(archive),</span><br><span style="color: hsl(0, 100%, \
40%);">- fChosenItem(NULL),</span><br><span style="color: hsl(120, 100%, \
40%);">+ fTrackState(NULL),</span><br><span> fPad(14.0f, 2.0f, 20.0f, \
0.0f),</span><br><span> fSelected(NULL),</span><br><span> \
fCachedMenuWindow(NULL),</span><br><span>@@ -453,6 +454,10 @@</span><br><span> \
void</span><br><span> BMenu::MessageReceived(BMessage* message)</span><br><span> \
{</span><br><span style="color: hsl(120, 100%, 40%);">+ if (fTrackState == NULL) \
{</span><br><span style="color: hsl(120, 100%, \
40%);">+ BView::MessageReceived(message);</span><br><span style="color: hsl(120, \
100%, 40%);">+ return;</span><br><span style="color: hsl(120, 100%, \
40%);">+ }</span><br><span> switch (message->what) {</span><br><span> case \
B_MOUSE_WHEEL_CHANGED:</span><br><span> {</span><br><span>@@ -479,6 +484,58 \
@@</span><br><span> break;</span><br><span> }</span><br><span> </span><br><span \
style="color: hsl(120, 100%, 40%);">+ case B_MOUSE_DOWN:</span><br><span \
style="color: hsl(120, 100%, 40%);">+ if (fStickyMode) {</span><br><span \
style="color: hsl(120, 100%, 40%);">+ if (fSelected != NULL) {</span><br><span \
style="color: hsl(120, 100%, 40%);">+ _InvokeItem(fSelected);</span><br><span \
style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, \
100%, 40%);">+ _QuitTracking(false);</span><br><span style="color: hsl(120, 100%, \
40%);">+ }</span><br><span style="color: hsl(120, 100%, \
40%);">+ BView::MessageReceived(message);</span><br><span style="color: hsl(120, \
100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case \
B_MOUSE_UP:</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!fStickyMode) \
{</span><br><span style="color: hsl(120, 100%, 40%);">+ if (fSelected != NULL) \
{</span><br><span style="color: hsl(120, 100%, \
40%);">+ _InvokeItem(fSelected);</span><br><span style="color: hsl(120, 100%, \
40%);">+ }</span><br><span style="color: hsl(120, 100%, \
40%);">+ _QuitTracking(false);</span><br><span style="color: hsl(120, 100%, \
40%);">+ }</span><br><span style="color: hsl(120, 100%, \
40%);">+ BView::MessageReceived(message);</span><br><span style="color: hsl(120, \
100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case \
B_MOUSE_MOVED: {</span><br><span style="color: hsl(120, 100%, 40%);">+ BPoint where \
= B_ORIGIN;</span><br><span style="color: hsl(120, 100%, 40%);">+ int32 buttons = \
0;</span><br><span style="color: hsl(120, 100%, 40%);">+ int32 transit = \
B_OUTSIDE_VIEW;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span \
style="color: hsl(120, 100%, \
40%);">+ message->FindPoint("be:view_where", \
&where);</span><br><span style="color: hsl(120, 100%, \
40%);">+ message->FindInt32("buttons", &buttons);</span><br><span \
style="color: hsl(120, 100%, 40%);">+ message->FindInt32("be:transit", \
&transit);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span \
style="color: hsl(120, 100%, 40%);">+ if (fTrackState == NULL) {</span><br><span \
style="color: hsl(120, 100%, \
40%);">+ BView::MessageReceived(message);</span><br><span style="color: hsl(120, \
100%, 40%);">+ return;</span><br><span style="color: hsl(120, 100%, \
40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span \
style="color: hsl(120, 100%, 40%);">+ AutoLocker<BLocker> \
locker(fTrackState->locker);</span><br><span style="color: hsl(120, 100%, \
40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ BMenuItem \
*oldSelected = fSelected;</span><br><span style="color: hsl(120, 100%, \
40%);">+ BMenuItem* item = _HitTestItems(where, B_ORIGIN);</span><br><span \
style="color: hsl(120, 100%, 40%);">+ if (item == NULL) {</span><br><span \
style="color: hsl(120, 100%, 40%);">+ if ((fSelected != NULL) && \
(fSelected->Submenu() == NULL)) {</span><br><span style="color: hsl(120, 100%, \
40%);">+ _SelectItem(NULL);</span><br><span style="color: hsl(120, 100%, \
40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ } else \
{</span><br><span style="color: hsl(120, 100%, \
40%);">+ _UpdateStateOpenSelect(item, where, \
fTrackState->navAreaRectAbove,</span><br><span style="color: hsl(120, 100%, \
40%);">+ fTrackState->navAreaRectBelow, fTrackState->selectedTime, \
fTrackState->navigationAreaTime);</span><br><span style="color: hsl(120, 100%, \
40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span \
style="color: hsl(120, 100%, 40%);">+ if (fSelected != oldSelected)</span><br><span \
style="color: hsl(120, 100%, 40%);">+ fTrackState->curMenu = \
this;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span \
style="color: hsl(120, 100%, \
40%);">+ BView::MessageReceived(message);</span><br><span style="color: hsl(120, \
100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, \
40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> \
default:</span><br><span> BView::MessageReceived(message);</span><br><span> \
break;</span><br><span>@@ -490,63 +547,70 @@</span><br><span> BMenu::KeyDown(const \
char* bytes, int32 numBytes)</span><br><span> {</span><br><span> // TODO: Test how \
it works on BeOS R5 and implement this correctly</span><br><span style="color: \
hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if \
(fTrackState == NULL)</span><br><span style="color: hsl(120, 100%, \
40%);">+ return;</span><br><span style="color: hsl(120, 100%, \
40%);">+</span><br><span style="color: hsl(120, 100%, \
40%);">+ AutoLocker<BLocker> locker(fTrackState->locker);</span><br><span \
style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, \
40%);">+ if (fTrackState->curMenu != this) {</span><br><span style="color: \
hsl(120, 100%, 40%);">+ BMessenger \
messenger(fTrackState->curMenu);</span><br><span style="color: hsl(120, 100%, \
40%);">+ messenger.SendMessage(Window()->CurrentMessage());</span><br><span \
style="color: hsl(120, 100%, 40%);">+ return;</span><br><span style="color: hsl(120, \
100%, 40%);">+ }</span><br><span> switch (bytes[0]) {</span><br><span> case \
B_UP_ARROW:</span><br><span style="color: hsl(0, 100%, 40%);">- if (fLayout == \
B_ITEMS_IN_COLUMN)</span><br><span style="color: hsl(120, 100%, 40%);">+ if \
(fLayout == B_ITEMS_IN_COLUMN) {</span><br><span> _SelectNextItem(fSelected, \
false);</span><br><span style="color: hsl(120, 100%, 40%);">+ } else if (fLayout == \
B_ITEMS_IN_ROW || fLayout == B_ITEMS_IN_MATRIX) {</span><br><span style="color: \
hsl(120, 100%, 40%);">+ if (Supermenu() != NULL) {</span><br><span style="color: \
hsl(120, 100%, 40%);">+ _SelectItem(NULL);</span><br><span style="color: hsl(120, \
100%, 40%);">+ fTrackState->curMenu = Supermenu();</span><br><span \
style="color: hsl(120, 100%, 40%);">+ } else {</span><br><span style="color: \
hsl(120, 100%, 40%);">+ _QuitTracking(false);</span><br><span style="color: \
hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, \
40%);">+ }</span><br><span> break;</span><br><span> </span><br><span> case \
B_DOWN_ARROW:</span><br><span style="color: hsl(0, 100%, 40%);">- {</span><br><span \
style="color: hsl(0, 100%, 40%);">- BMenuBar* bar = \
dynamic_cast<BMenuBar*>(Supermenu());</span><br><span style="color: hsl(0, \
100%, 40%);">- if (bar != NULL && fState == MENU_STATE_CLOSED) \
{</span><br><span style="color: hsl(0, 100%, 40%);">- // tell MenuBar's \
_Track:</span><br><span style="color: hsl(0, 100%, 40%);">- bar->fState = \
MENU_STATE_KEY_TO_SUBMENU;</span><br><span style="color: hsl(0, 100%, \
40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- if (fLayout == \
B_ITEMS_IN_COLUMN)</span><br><span style="color: hsl(120, 100%, 40%);">+ if \
(fLayout == B_ITEMS_IN_COLUMN) {</span><br><span> _SelectNextItem(fSelected, \
true);</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span \
style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, \
40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- case \
B_LEFT_ARROW:</span><br><span style="color: hsl(0, 100%, 40%);">- if (fLayout == \
B_ITEMS_IN_ROW)</span><br><span style="color: hsl(0, 100%, \
<div style="display:none"> Gerrit-Project: haiku </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: \
Ia693570e9bf4cbea33cd7d71bd5e7249c089959f </div> <div style="display:none"> \
Gerrit-Change-Number: 2284 </div> <div style="display:none"> Gerrit-PatchSet: 1 \
</div> <div style="display:none"> Gerrit-Owner: X512 <danger_mail@list.ru> \
</div> <div style="display:none"> Gerrit-MessageType: newchange </div>
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic