BMenu: Submenu opening direction follows parent opening direction

Fixes #4859
Change-Id: I8e89afc3ad982d899428e3038fed354a78d04981
This commit is contained in:
David Murphy 2018-07-16 03:42:01 -04:00 committed by waddlesplash
parent 0da0829bbc
commit e3f7fe948d
1 changed files with 23 additions and 8 deletions

View File

@ -86,10 +86,16 @@ public:
menu_tracking_hook trackingHook;
void* trackingState;
ExtraMenuData(menu_tracking_hook func, void* state)
// Used to track when the menu would be drawn offscreen and instead gets
// shifted back on the screen towards the left. This information
// allows us to draw submenus in the same direction as their parents.
bool frameShiftedLeft;
ExtraMenuData()
{
trackingHook = func;
trackingState = state;
trackingHook = NULL;
trackingState = NULL;
frameShiftedLeft = false;
}
};
@ -1443,8 +1449,8 @@ BMenu::DrawBackground(BRect updateRect)
void
BMenu::SetTrackingHook(menu_tracking_hook func, void* state)
{
delete fExtraMenuData;
fExtraMenuData = new (nothrow) BPrivate::ExtraMenuData(func, state);
fExtraMenuData->trackingHook = func;
fExtraMenuData->trackingState = state;
}
@ -1465,6 +1471,8 @@ BMenu::_InitData(BMessage* archive)
font.SetSize(sMenuInfo.font_size);
SetFont(&font, B_FONT_FAMILY_AND_STYLE | B_FONT_SIZE);
fExtraMenuData = new (nothrow) BPrivate::ExtraMenuData();
fLayoutData = new LayoutData;
fLayoutData->lastResizingMode = ResizingMode();
@ -2387,6 +2395,9 @@ BMenu::_CalcFrame(BPoint where, bool* scrollOn)
BMenu* superMenu = Supermenu();
BMenuItem* superItem = Superitem();
// Reset frame shifted state since this menu is being redrawn
fExtraMenuData->frameShiftedLeft = false;
// TODO: Horrible hack:
// When added to a BMenuField, a BPopUpMenu is the child of
// a _BMCMenuBar_ to "fake" the menu hierarchy
@ -2401,19 +2412,23 @@ BMenu::_CalcFrame(BPoint where, bool* scrollOn)
bool scroll = false;
if (superMenu == NULL || superItem == NULL || inMenuField) {
// just move the window on screen
if (frame.bottom > screenFrame.bottom)
frame.OffsetBy(0, screenFrame.bottom - frame.bottom);
else if (frame.top < screenFrame.top)
frame.OffsetBy(0, -frame.top);
if (frame.right > screenFrame.right)
if (frame.right > screenFrame.right) {
frame.OffsetBy(screenFrame.right - frame.right, 0);
fExtraMenuData->frameShiftedLeft = true;
}
else if (frame.left < screenFrame.left)
frame.OffsetBy(-frame.left, 0);
} else if (superMenu->Layout() == B_ITEMS_IN_COLUMN) {
if (frame.right > screenFrame.right)
if (frame.right > screenFrame.right
|| superMenu->fExtraMenuData->frameShiftedLeft) {
frame.OffsetBy(-superItem->Frame().Width() - frame.Width() - 2, 0);
fExtraMenuData->frameShiftedLeft = true;
}
if (frame.left < 0)
frame.OffsetBy(-frame.left + 6, 0);