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;
|
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:
|
default:
|
||||||
BView::MessageReceived(message);
|
BView::MessageReceived(message);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
#include <Debug.h>
|
#include <Debug.h>
|
||||||
#include <Menu.h>
|
#include <Menu.h>
|
||||||
#include <MenuItem.h>
|
#include <MenuItem.h>
|
||||||
|
#include <Screen.h>
|
||||||
|
|
||||||
#include <MenuPrivate.h>
|
#include <MenuPrivate.h>
|
||||||
#include <WindowPrivate.h>
|
#include <WindowPrivate.h>
|
||||||
@@ -41,6 +42,11 @@ public:
|
|||||||
virtual void AttachedToWindow();
|
virtual void AttachedToWindow();
|
||||||
virtual void DetachedFromWindow();
|
virtual void DetachedFromWindow();
|
||||||
virtual void Draw(BRect updateRect);
|
virtual void Draw(BRect updateRect);
|
||||||
|
virtual void LayoutChanged();
|
||||||
|
|
||||||
|
void MoveSubmenusOver(BMenu* menu,
|
||||||
|
BRect menuFrame,
|
||||||
|
BRect screenFrame);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class BMenuWindow;
|
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 -
|
// #pragma mark -
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user