hopefully improved menu tracking. Among other things, this fixes bug 461
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@17204 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -2,10 +2,10 @@
|
|||||||
#define __MENU_PRIVATE_H
|
#define __MENU_PRIVATE_H
|
||||||
|
|
||||||
|
|
||||||
enum menu_actions {
|
enum menu_states {
|
||||||
MENU_ACT_NONE = 0,
|
MENU_STATE_TRACKING = 0,
|
||||||
MENU_ACT_SUBMENU = 1,
|
MENU_STATE_TRACKING_SUBMENU = 1,
|
||||||
MENU_ACT_CLOSE = 5
|
MENU_STATE_CLOSED = 5
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+52
-62
@@ -236,47 +236,21 @@ BMenu::Archive(BMessage *data, bool deep) const
|
|||||||
{
|
{
|
||||||
status_t err = BView::Archive(data, deep);
|
status_t err = BView::Archive(data, deep);
|
||||||
|
|
||||||
if (err < B_OK)
|
if (err == B_OK && Layout() != B_ITEMS_IN_ROW)
|
||||||
return err;
|
|
||||||
|
|
||||||
if (Layout() != B_ITEMS_IN_ROW) {
|
|
||||||
err = data->AddInt32("_layout", Layout());
|
err = data->AddInt32("_layout", Layout());
|
||||||
|
if (err == B_OK)
|
||||||
if (err < B_OK)
|
err = data->AddBool("_rsize_to_fit", fResizeToFit);
|
||||||
return err;
|
if (err == B_OK)
|
||||||
}
|
err = data->AddBool("_disable", !IsEnabled());
|
||||||
|
if (err == B_OK)
|
||||||
err = data->AddBool("_rsize_to_fit", fResizeToFit);
|
err = data->AddBool("_radio", IsRadioMode());
|
||||||
|
if (err == B_OK)
|
||||||
if (err < B_OK)
|
err = data->AddBool("_trig_disabled", AreTriggersEnabled());
|
||||||
return err;
|
if (err == B_OK)
|
||||||
|
err = data->AddBool("_dyn_label", fDynamicName);
|
||||||
err = data->AddBool("_disable", !IsEnabled());
|
if (err == B_OK)
|
||||||
|
err = data->AddFloat("_maxwidth", fMaxContentWidth);
|
||||||
if (err < B_OK)
|
if (err == B_OK && deep) {
|
||||||
return err;
|
|
||||||
|
|
||||||
err = data->AddBool("_radio", IsRadioMode());
|
|
||||||
|
|
||||||
if (err < B_OK)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
err = data->AddBool("_trig_disabled", AreTriggersEnabled());
|
|
||||||
|
|
||||||
if (err < B_OK)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
err = data->AddBool("_dyn_label", fDynamicName);
|
|
||||||
|
|
||||||
if (err < B_OK)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
err = data->AddFloat("_maxwidth", fMaxContentWidth);
|
|
||||||
|
|
||||||
if (err < B_OK)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
if (deep) {
|
|
||||||
// TODO store items and rects
|
// TODO store items and rects
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1129,7 +1103,7 @@ BMenu::_show(bool selectFirstItem)
|
|||||||
|
|
||||||
UpdateWindowViewSize();
|
UpdateWindowViewSize();
|
||||||
window->Show();
|
window->Show();
|
||||||
|
|
||||||
if (selectFirstItem)
|
if (selectFirstItem)
|
||||||
SelectItem(ItemAt(0));
|
SelectItem(ItemAt(0));
|
||||||
|
|
||||||
@@ -1175,9 +1149,17 @@ BMenu::_track(int *action, bigtime_t trackTime, long start)
|
|||||||
bigtime_t openTime = system_time();
|
bigtime_t openTime = system_time();
|
||||||
bigtime_t closeTime = openTime;
|
bigtime_t closeTime = openTime;
|
||||||
|
|
||||||
fState = MENU_ACT_NONE;
|
fState = MENU_STATE_TRACKING;
|
||||||
|
if (fSuper != NULL)
|
||||||
|
fSuper->fState = MENU_STATE_TRACKING_SUBMENU;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
|
if (fExtraMenuData != NULL && fExtraMenuData->trackingHook != NULL
|
||||||
|
&& fExtraMenuData->trackingState != NULL) {
|
||||||
|
bool result = fExtraMenuData->trackingHook(this, fExtraMenuData->trackingState);
|
||||||
|
//printf("tracking hook returned %s\n", result ? "true" : "false");
|
||||||
|
}
|
||||||
|
|
||||||
bool locked = LockLooper();
|
bool locked = LockLooper();
|
||||||
if (!locked)
|
if (!locked)
|
||||||
break;
|
break;
|
||||||
@@ -1190,37 +1172,35 @@ BMenu::_track(int *action, bigtime_t trackTime, long start)
|
|||||||
BPoint screenLocation = ConvertToScreen(location);
|
BPoint screenLocation = ConvertToScreen(location);
|
||||||
item = HitTestItems(location, B_ORIGIN);
|
item = HitTestItems(location, B_ORIGIN);
|
||||||
if (item != NULL) {
|
if (item != NULL) {
|
||||||
if (item != fSelected
|
if (item != fSelected && system_time() > closeTime + kHysteresis) {
|
||||||
&& (fState != MENU_ACT_SUBMENU || system_time() > closeTime + kHysteresis)) {
|
|
||||||
SelectItem(item, -1);
|
SelectItem(item, -1);
|
||||||
openTime = system_time();
|
openTime = system_time();
|
||||||
fState = MENU_ACT_NONE;
|
|
||||||
snoozeAmount = 20000;
|
|
||||||
} else if (system_time() > kHysteresis + openTime && item->Submenu() != NULL
|
} else if (system_time() > kHysteresis + openTime && item->Submenu() != NULL
|
||||||
&& item->Submenu()->Window() == NULL) {
|
&& item->Submenu()->Window() == NULL) {
|
||||||
// Open the submenu if it's not opened yet, but only if
|
// Open the submenu if it's not opened yet, but only if
|
||||||
// the mouse pointer stayed over there for some time
|
// the mouse pointer stayed over there for some time
|
||||||
// (hysteresis)
|
// (hysteresis)
|
||||||
SelectItem(item);
|
SelectItem(item);
|
||||||
fState = MENU_ACT_SUBMENU;
|
|
||||||
closeTime = system_time();
|
closeTime = system_time();
|
||||||
}
|
}
|
||||||
|
fState = MENU_STATE_TRACKING;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Track the submenu
|
// Track the submenu
|
||||||
if (fSelected != NULL && OverSubmenu(fSelected, screenLocation)) {
|
if (fSelected != NULL && OverSubmenu(fSelected, screenLocation)) {
|
||||||
UnlockLooper();
|
UnlockLooper();
|
||||||
locked = false;
|
locked = false;
|
||||||
int submenuAction = MENU_ACT_NONE;
|
int submenuAction = MENU_STATE_TRACKING;
|
||||||
|
BMenu *submenu = fSelected->Submenu();
|
||||||
if (IsStickyMode())
|
if (IsStickyMode())
|
||||||
fSelected->Submenu()->SetStickyMode(true);
|
submenu->SetStickyMode(true);
|
||||||
BMenuItem *submenuItem = fSelected->Submenu()->_track(&submenuAction, trackTime);
|
BMenuItem *submenuItem = submenu->_track(&submenuAction, trackTime);
|
||||||
if (submenuAction == MENU_ACT_CLOSE) {
|
if (submenuAction == MENU_STATE_CLOSED) {
|
||||||
item = submenuItem;
|
item = submenuItem;
|
||||||
fState = submenuAction;
|
fState = submenuAction;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
locked = LockLooper();
|
locked = LockLooper();
|
||||||
if (!locked)
|
if (!locked)
|
||||||
break;
|
break;
|
||||||
@@ -1228,29 +1208,38 @@ BMenu::_track(int *action, bigtime_t trackTime, long start)
|
|||||||
|
|
||||||
if (item == NULL) {
|
if (item == NULL) {
|
||||||
if (OverSuper(screenLocation)) {
|
if (OverSuper(screenLocation)) {
|
||||||
fState = MENU_ACT_NONE;
|
fState = MENU_STATE_TRACKING;
|
||||||
UnlockLooper();
|
UnlockLooper();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fSelected != NULL && !OverSubmenu(fSelected, screenLocation)
|
if (fSelected != NULL && !OverSubmenu(fSelected, screenLocation)
|
||||||
&& (fState != MENU_ACT_SUBMENU || system_time() > closeTime + kHysteresis)) {
|
&& system_time() > closeTime + kHysteresis
|
||||||
|
&& fState != MENU_STATE_TRACKING_SUBMENU) {
|
||||||
SelectItem(NULL);
|
SelectItem(NULL);
|
||||||
fState = MENU_ACT_NONE;
|
fState = MENU_STATE_TRACKING;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fSuper != NULL) {
|
||||||
|
if (locked)
|
||||||
|
UnlockLooper();
|
||||||
|
*action = fState;
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (locked)
|
if (locked)
|
||||||
UnlockLooper();
|
UnlockLooper();
|
||||||
|
|
||||||
if (buttons != 0 && IsStickyMode()) {
|
if (buttons != 0 && IsStickyMode()) {
|
||||||
fState = MENU_ACT_CLOSE;
|
fState = MENU_STATE_CLOSED;
|
||||||
break;
|
break;
|
||||||
} else if (buttons == 0 && !IsStickyMode()) {
|
} else if (buttons == 0 && !IsStickyMode()) {
|
||||||
if (system_time() < trackTime + 1000000
|
if (system_time() < trackTime + 1000000
|
||||||
|| (fExtraRect != NULL && fExtraRect->Contains(location)))
|
|| (fExtraRect != NULL && fExtraRect->Contains(location)))
|
||||||
SetStickyMode(true);
|
SetStickyMode(true);
|
||||||
else {
|
else {
|
||||||
fState = MENU_ACT_CLOSE;
|
fState = MENU_STATE_CLOSED;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1261,7 +1250,7 @@ BMenu::_track(int *action, bigtime_t trackTime, long start)
|
|||||||
if (action != NULL)
|
if (action != NULL)
|
||||||
*action = fState;
|
*action = fState;
|
||||||
|
|
||||||
if (LockLooper()) {
|
if (fSelected != NULL && LockLooper()) {
|
||||||
SelectItem(NULL);
|
SelectItem(NULL);
|
||||||
UnlockLooper();
|
UnlockLooper();
|
||||||
}
|
}
|
||||||
@@ -1918,7 +1907,8 @@ BMenu::UpdateWindowViewSize(bool upWind)
|
|||||||
window->ResizeTo(Bounds().Width() + 2, Bounds().Height() + 2);
|
window->ResizeTo(Bounds().Width() + 2, Bounds().Height() + 2);
|
||||||
else {
|
else {
|
||||||
CacheFontInfo();
|
CacheFontInfo();
|
||||||
window->ResizeTo(StringWidth(kEmptyMenuLabel) + 5, fFontHeight + 6);
|
window->ResizeTo(StringWidth(kEmptyMenuLabel) + fPad.left + fPad.right,
|
||||||
|
fFontHeight + fPad.top + fPad.bottom);
|
||||||
}
|
}
|
||||||
window->MoveTo(frame.LeftTop());
|
window->MoveTo(frame.LeftTop());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -378,16 +378,16 @@ BMenuBar::Track(int32 *action, int32 startIndex, bool showMenu)
|
|||||||
// TODO: Cleanup, merge some "if" blocks if possible
|
// TODO: Cleanup, merge some "if" blocks if possible
|
||||||
BMenuItem *resultItem = NULL;
|
BMenuItem *resultItem = NULL;
|
||||||
BWindow *window = Window();
|
BWindow *window = Window();
|
||||||
int localAction = MENU_ACT_NONE;
|
int localAction = MENU_STATE_TRACKING;
|
||||||
while (true) {
|
while (true) {
|
||||||
bigtime_t snoozeAmount = 30000;
|
bigtime_t snoozeAmount = 40000;
|
||||||
bool locked = window->Lock();//WithTimeout(200000)
|
bool locked = window->Lock();//WithTimeout(200000)
|
||||||
if (!locked)
|
if (!locked)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
BPoint where;
|
BPoint where;
|
||||||
ulong buttons;
|
ulong buttons;
|
||||||
GetMouse(&where, &buttons);
|
GetMouse(&where, &buttons, true);
|
||||||
BMenuItem *menuItem = HitTestItems(where, B_ORIGIN);
|
BMenuItem *menuItem = HitTestItems(where, B_ORIGIN);
|
||||||
if (menuItem != NULL) {
|
if (menuItem != NULL) {
|
||||||
// Select item if:
|
// Select item if:
|
||||||
@@ -406,7 +406,7 @@ BMenuBar::Track(int32 *action, int32 startIndex, bool showMenu)
|
|||||||
} else {
|
} else {
|
||||||
// Menu was already opened, close it and bail
|
// Menu was already opened, close it and bail
|
||||||
SelectItem(NULL);
|
SelectItem(NULL);
|
||||||
localAction = MENU_ACT_CLOSE;
|
localAction = MENU_STATE_CLOSED;
|
||||||
resultItem = NULL;
|
resultItem = NULL;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -423,18 +423,20 @@ BMenuBar::Track(int32 *action, int32 startIndex, bool showMenu)
|
|||||||
if (menu != NULL) {
|
if (menu != NULL) {
|
||||||
window->Unlock();
|
window->Unlock();
|
||||||
locked = false;
|
locked = false;
|
||||||
snoozeAmount = 0;
|
snoozeAmount = 30000;
|
||||||
if (IsStickyMode())
|
if (IsStickyMode())
|
||||||
menu->SetStickyMode(true);
|
menu->SetStickyMode(true);
|
||||||
resultItem = menu->_track(&localAction, system_time());
|
resultItem = menu->_track(&localAction, system_time());
|
||||||
}
|
}
|
||||||
} else if (menuItem == NULL && !IsStickyMode())
|
} else if (menuItem == NULL && !IsStickyMode()) {
|
||||||
SelectItem(NULL);
|
SelectItem(NULL);
|
||||||
|
fState = MENU_STATE_TRACKING;
|
||||||
|
}
|
||||||
|
|
||||||
if (locked)
|
if (locked)
|
||||||
window->Unlock();
|
window->Unlock();
|
||||||
|
|
||||||
if (localAction == MENU_ACT_CLOSE || (buttons != 0 && IsStickyMode() && menuItem == NULL))
|
if (localAction == MENU_STATE_CLOSED || (buttons != 0 && IsStickyMode() && menuItem == NULL))
|
||||||
break;
|
break;
|
||||||
else if (buttons == 0 && !IsStickyMode()) {
|
else if (buttons == 0 && !IsStickyMode()) {
|
||||||
// On an item without a submenu
|
// On an item without a submenu
|
||||||
@@ -446,7 +448,7 @@ BMenuBar::Track(int32 *action, int32 startIndex, bool showMenu)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (snoozeAmount > 0)
|
if (snoozeAmount > 0)
|
||||||
snooze(snoozeAmount);
|
snooze(snoozeAmount);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (window->Lock()) {
|
if (window->Lock()) {
|
||||||
|
|||||||
Reference in New Issue
Block a user