* Allowed Go() to also work if it was not called from within a window - this

prevented ProcessController from showing its menus.
* Minor cleanup.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@17587 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2006-05-25 13:20:15 +00:00
parent 20914efdcf
commit 6d27f962bd
+39 -48
View File
@@ -7,6 +7,7 @@
* Stefano Ceccherini ([email protected]) * Stefano Ceccherini ([email protected])
*/ */
#include <Application.h> #include <Application.h>
#include <Looper.h> #include <Looper.h>
#include <MenuItem.h> #include <MenuItem.h>
@@ -14,28 +15,26 @@
#include <Window.h> #include <Window.h>
struct popup_menu_data struct popup_menu_data {
{
BPopUpMenu *object; BPopUpMenu *object;
BWindow *window; BWindow *window;
BMenuItem *selected; BMenuItem *selected;
BPoint where; BPoint where;
BRect rect; BRect rect;
bool async; bool async;
bool autoInvoke; bool autoInvoke;
bool startOpened; bool startOpened;
bool useRect; bool useRect;
sem_id lock; sem_id lock;
}; };
BPopUpMenu::BPopUpMenu(const char *title, bool radioMode, bool autoRename, BPopUpMenu::BPopUpMenu(const char *title, bool radioMode, bool autoRename,
menu_layout layout) menu_layout layout)
: : BMenu(title, layout),
BMenu(title, layout),
fUseWhere(false), fUseWhere(false),
fAutoDestruct(false), fAutoDestruct(false),
fTrackThread(-1) fTrackThread(-1)
@@ -49,8 +48,7 @@ BPopUpMenu::BPopUpMenu(const char *title, bool radioMode, bool autoRename,
BPopUpMenu::BPopUpMenu(BMessage *archive) BPopUpMenu::BPopUpMenu(BMessage *archive)
: : BMenu(archive),
BMenu(archive),
fUseWhere(false), fUseWhere(false),
fAutoDestruct(false), fAutoDestruct(false),
fTrackThread(-1) fTrackThread(-1)
@@ -86,9 +84,9 @@ BPopUpMenu::Instantiate(BMessage *data)
BMenuItem * BMenuItem *
BPopUpMenu::Go(BPoint where, bool delivers_message, bool open_anyway, bool async) BPopUpMenu::Go(BPoint where, bool deliversMessage, bool openAnyway, bool async)
{ {
return _go(where, delivers_message, open_anyway, NULL, async); return _go(where, deliversMessage, openAnyway, NULL, async);
} }
@@ -232,7 +230,7 @@ BPopUpMenu::ScreenLocation()
{ {
if (fUseWhere) if (fUseWhere)
return fWhere; return fWhere;
BMenuItem *superItem = Superitem(); BMenuItem *superItem = Superitem();
BMenu *superMenu = Supermenu(); BMenu *superMenu = Supermenu();
BMenuItem *selectedItem = FindItem(superItem->Label()); BMenuItem *selectedItem = FindItem(superItem->Label());
@@ -247,8 +245,7 @@ BPopUpMenu::ScreenLocation()
} }
// #pragma mark - // #pragma mark - private methods
// private methods
void BPopUpMenu::_ReservedPopUpMenu1() {} void BPopUpMenu::_ReservedPopUpMenu1() {}
@@ -276,25 +273,22 @@ BPopUpMenu::_go(BPoint where, bool autoInvoke, bool startOpened,
} }
BMenuItem *selected = NULL; BMenuItem *selected = NULL;
// Can't use Window(), as the BPopUpMenu isn't attached // Can't use Window(), as the BPopUpMenu isn't attached
BLooper *looper = BLooper::LooperForThread(find_thread(NULL)); BLooper *looper = BLooper::LooperForThread(find_thread(NULL));
BWindow *window = dynamic_cast<BWindow *>(looper); BWindow *window = dynamic_cast<BWindow *>(looper);
if (window == NULL)
return NULL;
popup_menu_data *data = new popup_menu_data; popup_menu_data *data = new popup_menu_data;
sem_id sem = create_sem(0, "window close lock"); sem_id sem = create_sem(0, "window close lock");
data->window = window; data->window = window;
// Asynchronous menu: we set the BWindow menu's semaphore // Asynchronous menu: we set the BWindow menu's semaphore
// and let BWindow block when needed // and let BWindow block when needed
if (async) { if (async && window != NULL) {
_set_menu_sem_(window, sem); _set_menu_sem_(window, sem);
} }
data->object = this; data->object = this;
data->autoInvoke = autoInvoke; data->autoInvoke = autoInvoke;
data->useRect = _specialRect != NULL; data->useRect = _specialRect != NULL;
@@ -305,16 +299,16 @@ BPopUpMenu::_go(BPoint where, bool autoInvoke, bool startOpened,
data->startOpened = startOpened; data->startOpened = startOpened;
data->selected = selected; data->selected = selected;
data->lock = sem; data->lock = sem;
// Spawn the tracking thread // Spawn the tracking thread
fTrackThread = spawn_thread(entry, "popup", B_NORMAL_PRIORITY, data); fTrackThread = spawn_thread(entry, "popup", B_NORMAL_PRIORITY, data);
if (fTrackThread >= 0) if (fTrackThread >= 0)
resume_thread(fTrackThread); resume_thread(fTrackThread);
else { else {
// Something went wrong. Cleanup and return NULL // Something went wrong. Cleanup and return NULL
delete_sem(sem); delete_sem(sem);
if (async) if (async && window != NULL)
_set_menu_sem_(window, B_BAD_SEM_ID); _set_menu_sem_(window, B_BAD_SEM_ID);
delete data; delete data;
return NULL; return NULL;
@@ -327,21 +321,19 @@ BPopUpMenu::_go(BPoint where, bool autoInvoke, bool startOpened,
// TODO: usually it's not a good idea to check for a particular error // TODO: usually it's not a good idea to check for a particular error
// code. Though here we just want to wait till the semaphore is deleted // code. Though here we just want to wait till the semaphore is deleted
// (it will return B_BAD_SEM_ID in that case), not provide locking or whatever. // (it will return B_BAD_SEM_ID in that case), not provide locking or whatever.
while (acquire_sem_etc(sem, 1, B_TIMEOUT, 50000) != B_BAD_SEM_ID) while (acquire_sem_etc(sem, 1, B_TIMEOUT, 50000) != B_BAD_SEM_ID) {
window->UpdateIfNeeded(); window->UpdateIfNeeded();
}
} }
status_t unused; status_t unused;
while (wait_for_thread(fTrackThread, &unused) == B_INTERRUPTED) while (wait_for_thread(fTrackThread, &unused) == B_INTERRUPTED)
; ;
selected = data->selected;
delete data;
selected = data->selected;
delete data;
} }
return selected; return selected;
} }
@@ -355,53 +347,52 @@ BPopUpMenu::entry(void *arg)
BRect *rect = NULL; BRect *rect = NULL;
bool autoInvoke = data->autoInvoke; bool autoInvoke = data->autoInvoke;
bool startOpened = data->startOpened; bool startOpened = data->startOpened;
if (data->useRect) if (data->useRect)
rect = &data->rect; rect = &data->rect;
data->selected = menu->start_track(where, autoInvoke, startOpened, rect); data->selected = menu->start_track(where, autoInvoke, startOpened, rect);
// Reset the window menu semaphore // Reset the window menu semaphore
if (data->async && data->window) if (data->async && data->window)
_set_menu_sem_(data->window, B_BAD_SEM_ID); _set_menu_sem_(data->window, B_BAD_SEM_ID);
delete_sem(data->lock); delete_sem(data->lock);
// Commit suicide if needed // Commit suicide if needed
if (menu->fAutoDestruct) if (menu->fAutoDestruct)
delete menu; delete menu;
if (data->async) if (data->async)
delete data; delete data;
return 0; return 0;
} }
BMenuItem * BMenuItem *
BPopUpMenu::start_track(BPoint where, bool autoInvoke, BPopUpMenu::start_track(BPoint where, bool autoInvoke,
bool startOpened, BRect *_specialRect) bool startOpened, BRect *_specialRect)
{ {
fWhere = where; fWhere = where;
// I know, this doesn't look senseful, but don't be fooled, // I know, this doesn't look senseful, but don't be fooled,
// fUseWhere is used in ScreenLocation(), which is a virtual // fUseWhere is used in ScreenLocation(), which is a virtual
// called by BMenu::Track() // called by BMenu::Track()
fUseWhere = true; fUseWhere = true;
// Show the menu's window // Show the menu's window
Show(); Show();
// Wait some time then track the menu // Wait some time then track the menu
snooze(50000); snooze(50000);
BMenuItem *result = Track(startOpened, _specialRect); BMenuItem *result = Track(startOpened, _specialRect);
if (result != NULL && autoInvoke) if (result != NULL && autoInvoke)
result->Invoke(); result->Invoke();
fUseWhere = false; fUseWhere = false;
Hide(); Hide();
be_app->ShowCursor(); be_app->ShowCursor();
fTrackThread = -1; fTrackThread = -1;