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:
parent
cf97e60972
commit
201381d6ab
@ -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());
|
||||
}
|
||||
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user