Menus make a better use of windows: when a child menu is opened, it asks the parent for a window, which is then cached for every other child for that parent menu. This avoids multiple creation/deletion of BWindows in a row. This also makes menus much nicer to use in qemu (together with the slight change in locking in BMenuBar (Lock() instead of LockWithTimeout))
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15939 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
+50
-19
@@ -1030,18 +1030,36 @@ BMenu::InitData(BMessage *data)
|
|||||||
bool
|
bool
|
||||||
BMenu::_show(bool selectFirstItem)
|
BMenu::_show(bool selectFirstItem)
|
||||||
{
|
{
|
||||||
// Menu windows get the BMenu's handler name
|
// See if the supermenu has a cached menuwindow,
|
||||||
fCachedMenuWindow = new BMenuWindow(Name());
|
// and use that one if possible.
|
||||||
fCachedMenuWindow->ChildAt(0)->AddChild(this);
|
BMenuWindow *window = NULL;
|
||||||
|
if (fSuper != NULL)
|
||||||
|
window = fSuper->MenuWindow();
|
||||||
|
|
||||||
|
// Otherwise, create a new one
|
||||||
|
// Actually, I think this can only happen for
|
||||||
|
// "stand alone" BPopUpMenus (i.e. not within a BMenuField)
|
||||||
|
if (window == NULL) {
|
||||||
|
// Menu windows get the BMenu's handler name
|
||||||
|
window = new BMenuWindow(Name());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (window == NULL)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!window->IsLocked())
|
||||||
|
window->Lock();
|
||||||
|
|
||||||
|
window->ChildAt(0)->AddChild(this);
|
||||||
|
|
||||||
// We're doing this here because ConvertToScreen() needs:
|
|
||||||
// 1. The BView to be attached (see the above line).
|
|
||||||
// 2. The looper locked or not running (the Show() call below starts the looper)
|
|
||||||
if (fSuper != NULL)
|
if (fSuper != NULL)
|
||||||
fSuperbounds = fSuper->ConvertToScreen(fSuper->Bounds());
|
fSuperbounds = fSuper->ConvertToScreen(fSuper->Bounds());
|
||||||
|
|
||||||
UpdateWindowViewSize();
|
UpdateWindowViewSize();
|
||||||
fCachedMenuWindow->Show();
|
window->Show();
|
||||||
|
|
||||||
|
if (window->IsLocked())
|
||||||
|
window->Unlock();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -1052,18 +1070,23 @@ BMenu::_hide()
|
|||||||
{
|
{
|
||||||
if (!LockLooper())
|
if (!LockLooper())
|
||||||
return;
|
return;
|
||||||
if (fCachedMenuWindow == NULL) {
|
|
||||||
|
BMenuWindow *menuWindow = fSuper ? fSuper->fCachedMenuWindow : NULL;
|
||||||
|
BMenuWindow *window = static_cast<BMenuWindow *>(Window());
|
||||||
|
if (window == NULL) {
|
||||||
// Huh? What did happen here? - we're trying to be on the safe side
|
// Huh? What did happen here? - we're trying to be on the safe side
|
||||||
UnlockLooper();
|
UnlockLooper();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
fCachedMenuWindow->Hide();
|
window->Hide();
|
||||||
fCachedMenuWindow->ChildAt(0)->RemoveChild(this);
|
window->ChildAt(0)->RemoveChild(this);
|
||||||
// we don't want to be deleted when the window is removed
|
// we don't want to be deleted when the window is removed
|
||||||
|
|
||||||
fCachedMenuWindow->Quit();
|
// Only quit if the window isn't cached. The cached menu window
|
||||||
fCachedMenuWindow = NULL;
|
// will be deleted at the end of BMenu::_track().
|
||||||
|
if (menuWindow != window)
|
||||||
|
window->Quit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1128,7 +1151,10 @@ BMenu::_track(int *action, long start)
|
|||||||
SelectItem(NULL);
|
SelectItem(NULL);
|
||||||
UnlockLooper();
|
UnlockLooper();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// delete the menu window recycled for all the child menus
|
||||||
|
DeleteMenuWindow();
|
||||||
|
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1506,9 +1532,15 @@ BMenu::OverSubmenu(BMenuItem *item, BPoint loc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BMenuWindow *
|
BMenuWindow *
|
||||||
BMenu::MenuWindow()
|
BMenu::MenuWindow()
|
||||||
{
|
{
|
||||||
|
if (fCachedMenuWindow == NULL) {
|
||||||
|
char windowName[64];
|
||||||
|
snprintf(windowName, 64, "%s cached menuwindow\n", Name());
|
||||||
|
fCachedMenuWindow = new BMenuWindow(windowName);
|
||||||
|
}
|
||||||
|
|
||||||
return fCachedMenuWindow;
|
return fCachedMenuWindow;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1736,14 +1768,13 @@ BMenu::ChooseTrigger(const char *title, BList *chars)
|
|||||||
void
|
void
|
||||||
BMenu::UpdateWindowViewSize(bool upWind)
|
BMenu::UpdateWindowViewSize(bool upWind)
|
||||||
{
|
{
|
||||||
ASSERT(fCachedMenuWindow != NULL);
|
BWindow *window = Window();
|
||||||
|
|
||||||
bool scroll;
|
bool scroll;
|
||||||
BRect frame = CalcFrame(ScreenLocation(), &scroll);
|
BRect frame = CalcFrame(ScreenLocation(), &scroll);
|
||||||
ResizeTo(frame.Width(), frame.Height());
|
ResizeTo(frame.Width(), frame.Height());
|
||||||
|
|
||||||
fCachedMenuWindow->ResizeTo(Bounds().Width() + 2, Bounds().Height() + 2);
|
window->ResizeTo(Bounds().Width() + 2, Bounds().Height() + 2);
|
||||||
fCachedMenuWindow->MoveTo(frame.LeftTop());
|
window->MoveTo(frame.LeftTop());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// Copyright (c) 2001-2005, Haiku, Inc.
|
// Copyright (c) 2001-2005, Haiku, Inc.
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
@@ -400,7 +400,7 @@ BMenuBar::Track(int32 *action, int32 startIndex, bool showMenu)
|
|||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
bigtime_t snoozeAmount = 30000;
|
bigtime_t snoozeAmount = 30000;
|
||||||
if (window->LockWithTimeout(200000) < B_OK)
|
if (!window->Lock())//WithTimeout(200000) < B_OK)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
BPoint where;
|
BPoint where;
|
||||||
@@ -426,7 +426,7 @@ BMenuBar::Track(int32 *action, int32 startIndex, bool showMenu)
|
|||||||
menu->SetStickyMode(true);
|
menu->SetStickyMode(true);
|
||||||
snoozeAmount = 0;
|
snoozeAmount = 0;
|
||||||
resultItem = menu->_track(&localAction);
|
resultItem = menu->_track(&localAction);
|
||||||
if (window->LockWithTimeout(200000) < B_OK)
|
if (!window->Lock())//WithTimeout(200000) < B_OK)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -448,6 +448,8 @@ BMenuBar::Track(int32 *action, int32 startIndex, bool showMenu)
|
|||||||
window->Unlock();
|
window->Unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DeleteMenuWindow();
|
||||||
|
|
||||||
if (action != NULL)
|
if (action != NULL)
|
||||||
*action = static_cast<int32>(localAction);
|
*action = static_cast<int32>(localAction);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user