* 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:
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user