big improvements for menus. The tracking is in many ways on par with r5, except for a few things, like diagonal movement and that grandparent bug

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@17095 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Stefano Ceccherini
2006-04-11 20:20:41 +00:00
parent 6ac6b512a0
commit 2191a09a93
3 changed files with 43 additions and 26 deletions
+1 -1
View File
@@ -188,7 +188,7 @@ virtual void _ReservedMenu6();
void InitData(BMessage *data = NULL); void InitData(BMessage *data = NULL);
bool _show(bool selectFirstItem = false); bool _show(bool selectFirstItem = false);
void _hide(); void _hide();
BMenuItem *_track(int *action, long start = -1); BMenuItem *_track(int *action, bigtime_t trackTime, long start = -1);
bool _AddItem(BMenuItem *item, int32 index); bool _AddItem(BMenuItem *item, int32 index);
bool RemoveItems(int32 index, bool RemoveItems(int32 index,
int32 count, int32 count,
+13 -5
View File
@@ -975,7 +975,7 @@ BMenu::Track(bool openAnyway, BRect *clickToOpenRect)
} }
int action; int action;
BMenuItem *menuItem = _track(&action, -1); BMenuItem *menuItem = _track(&action, system_time());
SetStickyMode(false); SetStickyMode(false);
fExtraRect = NULL; fExtraRect = NULL;
@@ -1136,7 +1136,7 @@ BMenu::_hide()
BMenuItem * BMenuItem *
BMenu::_track(int *action, long start) BMenu::_track(int *action, bigtime_t trackTime, long start)
{ {
// TODO: cleanup // TODO: cleanup
ulong buttons; ulong buttons;
@@ -1186,7 +1186,7 @@ BMenu::_track(int *action, long start)
UnlockLooper(); UnlockLooper();
locked = false; locked = false;
int submenuAction = MENU_ACT_NONE; int submenuAction = MENU_ACT_NONE;
BMenuItem *submenuItem = fSelected->Submenu()->_track(&submenuAction); BMenuItem *submenuItem = fSelected->Submenu()->_track(&submenuAction, startTime);
if (submenuAction == MENU_ACT_CLOSE) { if (submenuAction == MENU_ACT_CLOSE) {
item = submenuItem; item = submenuItem;
localAction = submenuAction; localAction = submenuAction;
@@ -1202,8 +1202,8 @@ BMenu::_track(int *action, long start)
if (buttons != 0 && IsStickyMode()) { if (buttons != 0 && IsStickyMode()) {
localAction = MENU_ACT_CLOSE; localAction = MENU_ACT_CLOSE;
break; break;
} else if (buttons == 0) { } else if (buttons == 0 && !IsStickyMode()) {
if (IsStickyPrefOn()) if (IsStickyPrefOn() && system_time() < trackTime + 2000000)
SetStickyMode(true); SetStickyMode(true);
else { else {
localAction = MENU_ACT_CLOSE; localAction = MENU_ACT_CLOSE;
@@ -1220,6 +1220,9 @@ BMenu::_track(int *action, long start)
UnlockLooper(); UnlockLooper();
} }
if (IsStickyMode())
SetStickyMode(false);
// delete the menu window recycled for all the child menus // delete the menu window recycled for all the child menus
DeleteMenuWindow(); DeleteMenuWindow();
@@ -1785,6 +1788,11 @@ void
BMenu::SetStickyMode(bool on) BMenu::SetStickyMode(bool on)
{ {
fStickyMode = on; fStickyMode = on;
// If we are switching to sticky mode, propagate the status
// back to the super menu
if (on && fSuper != NULL)
fSuper->SetStickyMode(on);
} }
+20 -11
View File
@@ -377,15 +377,15 @@ BMenuBar::TrackTask(void *arg)
BMenuItem * BMenuItem *
BMenuBar::Track(int32 *action, int32 startIndex, bool showMenu) BMenuBar::Track(int32 *action, int32 startIndex, bool showMenu)
{ {
// TODO: This function is very incomplete and just partially working: // TODO: Cleanup, merge some "if" blocks if possible
// For example, it doesn't respect the "sticky mode" setting.
BMenuItem *resultItem = NULL; BMenuItem *resultItem = NULL;
BWindow *window = Window(); BWindow *window = Window();
int localAction = MENU_ACT_NONE; int localAction = MENU_ACT_NONE;
bigtime_t startTime = system_time();
while (true) { while (true) {
bigtime_t snoozeAmount = 30000; bigtime_t snoozeAmount = 30000;
if (!window->Lock())//WithTimeout(200000) < B_OK) bool locked = window->Lock();//WithTimeout(200000)
if (!locked)
break; break;
BPoint where; BPoint where;
@@ -393,6 +393,11 @@ BMenuBar::Track(int32 *action, int32 startIndex, bool showMenu)
GetMouse(&where, &buttons); GetMouse(&where, &buttons);
BMenuItem *menuItem = HitTestItems(where, B_ORIGIN); BMenuItem *menuItem = HitTestItems(where, B_ORIGIN);
if (menuItem != NULL && menuItem != fSelected) { if (menuItem != NULL && menuItem != fSelected) {
// Select item if:
// - clicked in sticky mode
// - nonsticky mode,
// - no previous selection
if (fSelected == NULL || !IsStickyMode() || buttons != 0) {
// only select the item // only select the item
SelectItem(menuItem, -1); SelectItem(menuItem, -1);
if (menuItem->Submenu() != NULL if (menuItem->Submenu() != NULL
@@ -401,6 +406,7 @@ BMenuBar::Track(int32 *action, int32 startIndex, bool showMenu)
SelectItem(menuItem); SelectItem(menuItem);
} }
} }
}
if (fSelected != NULL && OverSubmenu(fSelected, ConvertToScreen(where))) { if (fSelected != NULL && OverSubmenu(fSelected, ConvertToScreen(where))) {
// call _track() from the selected sub-menu when the mouse cursor // call _track() from the selected sub-menu when the mouse cursor
@@ -408,20 +414,22 @@ BMenuBar::Track(int32 *action, int32 startIndex, bool showMenu)
BMenu *menu = fSelected->Submenu(); BMenu *menu = fSelected->Submenu();
if (menu != NULL) { if (menu != NULL) {
window->Unlock(); window->Unlock();
locked = false;
snoozeAmount = 0; snoozeAmount = 0;
resultItem = menu->_track(&localAction); resultItem = menu->_track(&localAction, startTime);
if (!window->Lock())//WithTimeout(200000) < B_OK)
break;
} }
} else if (menuItem == NULL && !fLastBounds->Contains(where)) } else if (menuItem == NULL && !IsStickyMode())
SelectItem(NULL); SelectItem(NULL);
if (locked)
window->Unlock(); window->Unlock();
if (localAction == MENU_ACT_CLOSE || (buttons != 0 && IsStickyMode())) if (localAction == MENU_ACT_CLOSE || (buttons != 0 && IsStickyMode() && menuItem == NULL))
break; break;
else if (buttons == 0) { else if (buttons == 0 && !IsStickyMode()) {
if (IsStickyPrefOn()) // Don't switch to sticky mode if user kept the mouse pressed for too long
// TODO: Delay could be smaller, but then it wouldn't be noticeable on QEMU on my machine
if (IsStickyPrefOn() && system_time() < startTime + 2000000)
SetStickyMode(true); SetStickyMode(true);
else else
break; break;
@@ -444,6 +452,7 @@ BMenuBar::Track(int32 *action, int32 startIndex, bool showMenu)
if (IsStickyMode()) if (IsStickyMode())
SetStickyMode(false); SetStickyMode(false);
DeleteMenuWindow(); DeleteMenuWindow();
if (action != NULL) if (action != NULL)