diff --git a/headers/os/interface/Menu.h b/headers/os/interface/Menu.h index 99af9b3bf7..b01079c994 100644 --- a/headers/os/interface/Menu.h +++ b/headers/os/interface/Menu.h @@ -236,6 +236,8 @@ virtual void _ReservedMenu6(); void RedrawAfterSticky(BRect bounds); bool OkToProceed(BMenuItem *); + void QuitTracking(); + status_t ParseMsg(BMessage *msg, int32 *sindex, BMessage *spec, int32 *form, const char **prop, BMenu **tmenu, BMenuItem **titem, int32 *user_data, diff --git a/src/kits/interface/Menu.cpp b/src/kits/interface/Menu.cpp index e2c93f6774..55ac7fff11 100644 --- a/src/kits/interface/Menu.cpp +++ b/src/kits/interface/Menu.cpp @@ -317,6 +317,7 @@ BMenu::AddItem(BMenuItem *item, int32 index) if (!_AddItem(item, index)) return false; + InvalidateLayout(); if (LockLooper()) { if (!Window()->IsHidden()) { LayoutItems(index); @@ -432,8 +433,9 @@ BMenu::AddList(BList *list, int32 index) if (!_AddItem(item, index + i)) break; } - } + } + InvalidateLayout(); if (locked && Window() != NULL && !Window()->IsHidden()) { // Make sure we update the layout if needed. LayoutItems(index); @@ -1020,6 +1022,7 @@ BMenu::Show() void BMenu::Show(bool selectFirst) { + Install(NULL); _show(selectFirst); } @@ -1028,6 +1031,7 @@ void BMenu::Hide() { _hide(); + Uninstall(); } @@ -1302,19 +1306,19 @@ BMenu::_track(int *action, bigtime_t trackTime, long start) if (locked) UnlockLooper(); - if (buttons != 0 && IsStickyMode()) { + if (buttons != 0 && IsStickyMode()) fState = MENU_STATE_CLOSED; - break; - } else if (buttons == 0 && !IsStickyMode()) { + else if (buttons == 0 && !IsStickyMode()) { if (system_time() < trackTime + 1000000 || (fExtraRect != NULL && fExtraRect->Contains(location))) SetStickyMode(true); - else { + else fState = MENU_STATE_CLOSED; - break; - } } + if (fState == MENU_STATE_CLOSED) + break; + snooze(snoozeAmount); } @@ -1358,10 +1362,6 @@ BMenu::_AddItem(BMenuItem *item, int32 index) item->SetSuper(this); - // TODO: Sometimes the menu layout isn't invalidated correctly, - // So we force a rebuild of the whole menu layout. Remove this! - InvalidateLayout(); - return true; } @@ -2061,6 +2061,14 @@ BMenu::OkToProceed(BMenuItem* item) } +void +BMenu::QuitTracking() +{ + fState = MENU_STATE_CLOSED; + +} + + status_t BMenu::ParseMsg(BMessage *msg, int32 *sindex, BMessage *spec, int32 *form, const char **prop, BMenu **tmenu, diff --git a/src/kits/interface/MenuBar.cpp b/src/kits/interface/MenuBar.cpp index 29f92290f4..2403790a10 100644 --- a/src/kits/interface/MenuBar.cpp +++ b/src/kits/interface/MenuBar.cpp @@ -390,7 +390,7 @@ BMenuBar::Track(int32 *action, int32 startIndex, bool showMenu) // TODO: Cleanup, merge some "if" blocks if possible BMenuItem *resultItem = NULL; BWindow *window = Window(); - int localAction = MENU_STATE_TRACKING; + int localAction = fState = MENU_STATE_TRACKING; while (true) { bigtime_t snoozeAmount = 40000; bool locked = window->Lock();//WithTimeout(200000) @@ -461,6 +461,9 @@ BMenuBar::Track(int32 *action, int32 startIndex, bool showMenu) SetStickyMode(true); } + if (fState == MENU_STATE_CLOSED) + break; + if (snoozeAmount > 0) snooze(snoozeAmount); } diff --git a/src/kits/interface/Window.cpp b/src/kits/interface/Window.cpp index 93f08c1ca0..4368142f32 100644 --- a/src/kits/interface/Window.cpp +++ b/src/kits/interface/Window.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -317,6 +318,10 @@ BWindow::~BWindow() { Lock(); + if (BMenu *menu = dynamic_cast(fFocus)) { + menu->QuitTracking(); + } + // Wait if a menu is still tracking if (fMenuSem > 0) { while (acquire_sem(fMenuSem) == B_INTERRUPTED) @@ -904,6 +909,11 @@ FrameMoved(origin); case B_MOUSE_DOWN: { + // Close an eventually opened menu. + if (BMenu *menu = dynamic_cast(fFocus)) { + menu->QuitTracking(); + } + if (BView *view = dynamic_cast(target)) { BPoint where; msg->FindPoint("be:view_where", &where); @@ -1544,7 +1554,8 @@ BWindow::FindView(BPoint point) const } -BView *BWindow::CurrentFocus() const +BView * +BWindow::CurrentFocus() const { return fFocus; }