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:
Stefano Ceccherini
2006-01-13 17:47:35 +00:00
parent cf97e60972
commit 201381d6ab
2 changed files with 55 additions and 22 deletions
+50 -19
View File
@@ -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());
} }
+5 -3
View File
@@ -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);