BMenu: Inform parent menu when modifier keys change
BMenuWindow: Move submenus over recursively if layout changes. Fixes #15782 Change-Id: I70e67c3514a3b850f5b5893170b9a34a9176363e Reviewed-on: https://review.haiku-os.org/c/haiku/+/2324 Haiku-Format: Haiku-format Bot <[email protected]> Reviewed-by: John Scipione <[email protected]> Tested-by: Commit checker robot <[email protected]>
This commit is contained in:
@@ -499,6 +499,13 @@ BMenu::MessageReceived(BMessage* message)
|
||||
break;
|
||||
}
|
||||
|
||||
case B_MODIFIERS_CHANGED:
|
||||
if (fSuper != NULL && fSuper->fState != MENU_STATE_CLOSED) {
|
||||
// inform parent to update its modifier keys and relayout
|
||||
BMessenger(fSuper).SendMessage(Window()->CurrentMessage());
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
BView::MessageReceived(message);
|
||||
break;
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <Debug.h>
|
||||
#include <Menu.h>
|
||||
#include <MenuItem.h>
|
||||
#include <Screen.h>
|
||||
|
||||
#include <MenuPrivate.h>
|
||||
#include <WindowPrivate.h>
|
||||
@@ -41,6 +42,11 @@ public:
|
||||
virtual void AttachedToWindow();
|
||||
virtual void DetachedFromWindow();
|
||||
virtual void Draw(BRect updateRect);
|
||||
virtual void LayoutChanged();
|
||||
|
||||
void MoveSubmenusOver(BMenu* menu,
|
||||
BRect menuFrame,
|
||||
BRect screenFrame);
|
||||
|
||||
private:
|
||||
friend class BMenuWindow;
|
||||
@@ -228,6 +234,91 @@ BMenuFrame::Draw(BRect updateRect)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BMenuFrame::LayoutChanged()
|
||||
{
|
||||
if (fMenu == NULL || Window() == NULL)
|
||||
return BView::LayoutChanged();
|
||||
|
||||
// shift child menus over recursively
|
||||
MoveSubmenusOver(fMenu, fMenu->ConvertToScreen(fMenu->Frame()),
|
||||
(BScreen(fMenu->Window())).Frame());
|
||||
|
||||
BView::LayoutChanged();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BMenuFrame::MoveSubmenusOver(BMenu* menu, BRect menuFrame, BRect screenFrame)
|
||||
{
|
||||
if (menu == NULL)
|
||||
return;
|
||||
|
||||
BMenu* submenu;
|
||||
BMenuWindow* submenuWindow;
|
||||
BPoint submenuLoc;
|
||||
BRect submenuFrame;
|
||||
|
||||
int32 itemCount = menu->CountItems();
|
||||
for (int32 index = 0; index < itemCount; index++) {
|
||||
submenu = menu->SubmenuAt(index);
|
||||
if (submenu == NULL || submenu->Window() == NULL)
|
||||
continue; // not an open submenu, next
|
||||
|
||||
submenuWindow = dynamic_cast<BMenuWindow*>(submenu->Window());
|
||||
if (submenuWindow == NULL)
|
||||
break; // submenu window was not a BMenuWindow, strange if true
|
||||
|
||||
// found an open submenu, get submenu frame
|
||||
if (submenu->LockLooper()) {
|
||||
// need to lock looper because we're in a different thread
|
||||
submenuFrame = submenu->Frame();
|
||||
submenu->ConvertToScreen(&submenuFrame);
|
||||
submenu->UnlockLooper();
|
||||
} else {
|
||||
// give up
|
||||
break;
|
||||
}
|
||||
|
||||
// get submenu loc and convert it to screen coords using menu
|
||||
if (menu->LockLooper()) {
|
||||
// check if submenu should be displayed right or left of menu
|
||||
BRect superFrame = submenu->Superitem()->Frame();
|
||||
if (submenuFrame.right < menuFrame.right)
|
||||
submenuLoc = superFrame.LeftTop() - BPoint(submenuFrame.Width() + 1, -1);
|
||||
else
|
||||
submenuLoc = superFrame.RightTop() + BPoint(1, 1);
|
||||
|
||||
menu->ConvertToScreen(&submenuLoc);
|
||||
submenuFrame.OffsetTo(submenuLoc);
|
||||
menu->UnlockLooper();
|
||||
} else {
|
||||
// give up
|
||||
break;
|
||||
}
|
||||
|
||||
// move submenu frame into screen bounds vertically
|
||||
if (submenuFrame.Height() < screenFrame.Height()) {
|
||||
if (submenuFrame.bottom >= screenFrame.bottom)
|
||||
submenuLoc.y -= (submenuFrame.bottom - screenFrame.bottom);
|
||||
else if (submenuFrame.top <= screenFrame.top)
|
||||
submenuLoc.y += (screenFrame.top - submenuFrame.top);
|
||||
} else {
|
||||
// put menu at top of screen, turn on the scroll arrows
|
||||
submenuLoc.y = 0;
|
||||
}
|
||||
|
||||
// move submenu window into place
|
||||
submenuWindow->MoveTo(submenuLoc);
|
||||
|
||||
// recurse through submenu's submenus
|
||||
MoveSubmenusOver(submenu, submenuFrame, screenFrame);
|
||||
|
||||
// we're done with this menu
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
Reference in New Issue
Block a user