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

View File

@ -1030,18 +1030,36 @@ BMenu::InitData(BMessage *data)
bool
BMenu::_show(bool selectFirstItem)
{
// Menu windows get the BMenu's handler name
fCachedMenuWindow = new BMenuWindow(Name());
fCachedMenuWindow->ChildAt(0)->AddChild(this);
// See if the supermenu has a cached menuwindow,
// and use that one if possible.
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)
fSuperbounds = fSuper->ConvertToScreen(fSuper->Bounds());
UpdateWindowViewSize();
fCachedMenuWindow->Show();
window->Show();
if (window->IsLocked())
window->Unlock();
return true;
}
@ -1052,18 +1070,23 @@ BMenu::_hide()
{
if (!LockLooper())
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
UnlockLooper();
return;
}
fCachedMenuWindow->Hide();
fCachedMenuWindow->ChildAt(0)->RemoveChild(this);
window->Hide();
window->ChildAt(0)->RemoveChild(this);
// we don't want to be deleted when the window is removed
fCachedMenuWindow->Quit();
fCachedMenuWindow = NULL;
// Only quit if the window isn't cached. The cached menu window
// 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);
UnlockLooper();
}
// delete the menu window recycled for all the child menus
DeleteMenuWindow();
return item;
}
@ -1506,9 +1532,15 @@ BMenu::OverSubmenu(BMenuItem *item, BPoint loc)
}
BMenuWindow *
BMenuWindow *
BMenu::MenuWindow()
{
if (fCachedMenuWindow == NULL) {
char windowName[64];
snprintf(windowName, 64, "%s cached menuwindow\n", Name());
fCachedMenuWindow = new BMenuWindow(windowName);
}
return fCachedMenuWindow;
}
@ -1736,14 +1768,13 @@ BMenu::ChooseTrigger(const char *title, BList *chars)
void
BMenu::UpdateWindowViewSize(bool upWind)
{
ASSERT(fCachedMenuWindow != NULL);
BWindow *window = Window();
bool scroll;
BRect frame = CalcFrame(ScreenLocation(), &scroll);
ResizeTo(frame.Width(), frame.Height());
fCachedMenuWindow->ResizeTo(Bounds().Width() + 2, Bounds().Height() + 2);
fCachedMenuWindow->MoveTo(frame.LeftTop());
window->ResizeTo(Bounds().Width() + 2, Bounds().Height() + 2);
window->MoveTo(frame.LeftTop());
}

View File

@ -1,4 +1,4 @@
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Copyright (c) 2001-2005, Haiku, Inc.
//
// 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) {
bigtime_t snoozeAmount = 30000;
if (window->LockWithTimeout(200000) < B_OK)
if (!window->Lock())//WithTimeout(200000) < B_OK)
break;
BPoint where;
@ -426,7 +426,7 @@ BMenuBar::Track(int32 *action, int32 startIndex, bool showMenu)
menu->SetStickyMode(true);
snoozeAmount = 0;
resultItem = menu->_track(&localAction);
if (window->LockWithTimeout(200000) < B_OK)
if (!window->Lock())//WithTimeout(200000) < B_OK)
break;
}
}
@ -448,6 +448,8 @@ BMenuBar::Track(int32 *action, int32 startIndex, bool showMenu)
window->Unlock();
}
DeleteMenuWindow();
if (action != NULL)
*action = static_cast<int32>(localAction);