git-svn-id: file:///srv/svn/repos/haiku/trunk/current@10695 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Stefano Ceccherini
2005-01-12 11:39:56 +00:00
parent d1d811ec70
commit 2ce1b3ecc2
+85 -62
View File
@@ -324,37 +324,38 @@ BMenuBar::StartMenuBar(int32 menuIndex, bool sticky, bool showMenu,
BRect *specialRect) BRect *specialRect)
{ {
BWindow *window = Window(); BWindow *window = Window();
if (!window) if (window == NULL)
debugger("MenuBar must be added to a window before it can be used."); debugger("MenuBar must be added to a window before it can be used.");
BAutolock lock(window); BAutolock lock(window);
if (lock.IsLocked()) { if (!lock.IsLocked())
fPrevFocusToken = -1; return;
fTracking = true;
window->MenusBeginning(); fPrevFocusToken = -1;
fTracking = true;
fMenuSem = create_sem(0, "window close sem"); window->MenusBeginning();
_set_menu_sem_(window, fMenuSem);
fMenuSem = create_sem(0, "window close sem");
fTrackingPID = spawn_thread(TrackTask, "menu_tracking", B_NORMAL_PRIORITY, NULL); _set_menu_sem_(window, fMenuSem);
if (fTrackingPID >= 0) {
menubar_data data; fTrackingPID = spawn_thread(TrackTask, "menu_tracking", B_NORMAL_PRIORITY, NULL);
data.menuBar = this; if (fTrackingPID >= 0) {
data.menuIndex = menuIndex; menubar_data data;
data.sticky = sticky; data.menuBar = this;
data.showMenu = showMenu; data.menuIndex = menuIndex;
data.useRect = specialRect != NULL; data.sticky = sticky;
if (data.useRect) data.showMenu = showMenu;
data.rect = *specialRect; data.useRect = specialRect != NULL;
if (data.useRect)
send_data(fTrackingPID, 0, &data, sizeof(data)); data.rect = *specialRect;
resume_thread(fTrackingPID);
send_data(fTrackingPID, 0, &data, sizeof(data));
} else { resume_thread(fTrackingPID);
_set_menu_sem_(window, B_NO_MORE_SEMS);
delete_sem(fMenuSem); } else {
} _set_menu_sem_(window, B_NO_MORE_SEMS);
delete_sem(fMenuSem);
} }
} }
@@ -397,43 +398,65 @@ BMenuBar::Track(int32 *action, int32 startIndex, bool showMenu)
// Cleanup // Cleanup
BMenuItem *resultItem = NULL; BMenuItem *resultItem = NULL;
BWindow *window = Window(); BWindow *window = Window();
if (window->LockWithTimeout(200000) == B_OK) { int localAction;
bool exitLoop = false;
do {
if (window->LockLooperWithTimeout(200000) < B_OK)
break;
BPoint where; BPoint where;
ulong buttons; ulong buttons;
do { GetMouse(&where, &buttons);
snooze(40000);
GetMouse(&where, &buttons);
BMenuItem *menuItem = HitTestItems(where, B_ORIGIN);
if (menuItem) {
SelectItem(menuItem);
BMenu *menu = menuItem->Submenu();
// TODO: Actually, this test shouldn't be needed, as
// all BMenuBar's BMenuItems are BMenus.
if (menu) {
if (IsStickyPrefOn())
menu->SetStickyMode(true);
do {
snooze(40000);
GetMouse(&where, &buttons);
// If we aren't over this BMenu anymore, exit the tracking loop.
BMenuItem *testItem = HitTestItems(where, B_ORIGIN);
if (testItem != NULL && testItem != menuItem)
break;
resultItem = menu->_track((int *)action, startIndex);
// "action" is "5" when the BMenu is closed.
} while (*action != 5);
}
SelectItem(NULL);
Invalidate();
}
} while (buttons != 0);
window->Unlock(); BMenuItem *menuItem = HitTestItems(where, B_ORIGIN);
} if (menuItem != NULL) {
SelectItem(menuItem);
BMenu *menu = menuItem->Submenu();
// TODO: Actually, this test shouldn't be needed, as
// all BMenuBar's BMenuItems are BMenus.
if (menu != NULL) {
if (IsStickyPrefOn())
menu->SetStickyMode(true);
do {
snooze(40000);
GetMouse(&where, &buttons);
// If we aren't over this BMenu anymore, exit the tracking loop.
BMenuItem *testItem = HitTestItems(where, B_ORIGIN);
if (testItem != NULL && testItem != menuItem)
break;
// No need to keep the window locked for the
// whole time, as BMenu::_track() does its own locking.
window->Unlock();
resultItem = menu->_track(&localAction, startIndex);
if (window->LockLooperWithTimeout(200000) < B_OK)
break;
// the returned action is "5" when the BMenu is closed.
} while (localAction != 5);
}
if (window->IsLocked()) {
SelectItem(NULL);
Invalidate();
}
}
if (window->IsLocked())
window->Unlock();
snooze(40000);
if (buttons == 0)
exitLoop = true;
} while (!exitLoop);
if (action != NULL)
*action = static_cast<int>(localAction);
if (resultItem != NULL) if (resultItem != NULL)
resultItem->Invoke(); resultItem->Invoke();
@@ -445,9 +468,9 @@ void
BMenuBar::StealFocus() BMenuBar::StealFocus()
{ {
BWindow *window = Window(); BWindow *window = Window();
if (window && window->Lock()) { if (window != NULL && window->Lock()) {
BView *focus = window->CurrentFocus(); BView *focus = window->CurrentFocus();
if (focus) if (focus != NULL)
fPrevFocusToken = _get_object_token_(focus); fPrevFocusToken = _get_object_token_(focus);
MakeFocus(); MakeFocus();
window->Unlock(); window->Unlock();
@@ -459,7 +482,7 @@ void
BMenuBar::RestoreFocus() BMenuBar::RestoreFocus()
{ {
BWindow *window = Window(); BWindow *window = Window();
if (window && window->Lock()) { if (window != NULL && window->Lock()) {
BHandler *handler = NULL; BHandler *handler = NULL;
if (BPrivate::gDefaultTokens.GetToken(fPrevFocusToken, B_HANDLER_TOKEN, if (BPrivate::gDefaultTokens.GetToken(fPrevFocusToken, B_HANDLER_TOKEN,
(void **)&handler, NULL) == B_OK) { (void **)&handler, NULL) == B_OK) {