VCL expect correct frame size for native menubars
... and renove the wrong framesize hack in the Qt backend
This wastes a few additional pixels in the frame backing store,
actually covered by the real native menu bar, to get rid of all
the hacks and eventually fix quite a bunch of bugs in Qt (and
maybe other backends).
This seems to work correct with Qt using either QPainter or Cairo
as the painting backend. It's much simpler then my previous failed
attempts to fix the Qt related bugs. I would like to convert every
implementation to my interpretation of the API (at least I now
documented the API). It looks like Win and Mac will just work,
because Win has no native menu bar and Mac uses a global menu,
so always returns the size of 0. And Gtk also seems to work, if
it also lies about the menu bar size being zero. That just seems
consequent, if the frame size is reduced by the menubar size.
This fixes at least:
tdf#64438 - Dockable panels in LibreOffice not dockable using KDE
Works.
tdf#130893 - XWindow::SetPosSize resizing based on
XWindow::GetPosSize shrinks the window
The document macro from tdf#130841 now doesn't resize the window.
This is just fixed for Qt.
tdf#134704 - KDE5 - unable to dock sidebar by dragging frame
not fixed, because the sidebar window is now a dialog, which is
not dockable. FWIW the same has happend the Navigator (F5), which
also renders it non-dockable. No idea, if this is intentional.
tdf#137471 - CMIS dialog advances beyond lower right corner of the
screen
So commit 3f8d3fd4649ef09e86c735617383a4bda0425540 ("tdf#137471 Qt
return frame pos + client area size") was really not enought as a
fix (at least it didn't break anything). The whole parent-based
repositioning is wrong and it really depends on the correct frame
size, so I'm keeping this as fixed by this patch.
Change-Id: I7faeace61b456c2b0f42c7a826f58018b70d46ae
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/135082
Tested-by: Jenkins
Reviewed-by: Jan-Marek Glogowski <glogow@fbihome.de>
diff --git a/include/vcl/menu.hxx b/include/vcl/menu.hxx
index 54df7ee..538cc4c 100644
--- a/include/vcl/menu.hxx
+++ b/include/vcl/menu.hxx
@@ -179,6 +179,8 @@ protected:
SAL_DLLPRIVATE void ImplFillLayoutData() const;
SAL_DLLPRIVATE SalMenu* ImplGetSalMenu() { return mpSalMenu.get(); }
// convenience function; just returns the SalMenu*, if HasNativeMenuBar() is true
SAL_DLLPRIVATE SalMenu* GetNativeMenuBar();
SAL_DLLPRIVATE OUString ImplGetHelpText( sal_uInt16 nItemId ) const;
// returns native check and option menu symbol height in rCheckHeight and rRadioHeight
diff --git a/vcl/inc/osx/salmenu.h b/vcl/inc/osx/salmenu.h
index 597180c..274d1ec 100644
--- a/vcl/inc/osx/salmenu.h
+++ b/vcl/inc/osx/salmenu.h
@@ -55,7 +55,7 @@ public:
AquaSalMenu( bool bMenuBar );
virtual ~AquaSalMenu() override;
virtual bool VisibleMenuBar() override;
virtual bool HasNativeMenuBar() override;
virtual void InsertItem( SalMenuItem* pSalMenuItem, unsigned nPos ) override;
virtual void RemoveItem( unsigned nPos ) override;
diff --git a/vcl/inc/qt5/QtFrame.hxx b/vcl/inc/qt5/QtFrame.hxx
index 963572ca..40954f6 100644
--- a/vcl/inc/qt5/QtFrame.hxx
+++ b/vcl/inc/qt5/QtFrame.hxx
@@ -131,7 +131,6 @@ class VCLPLUG_QT_PUBLIC QtFrame : public QObject, public SalFrame
bool isMinimized() const;
bool isMaximized() const;
void SetWindowStateImpl(Qt::WindowStates eState);
int menuBarOffset() const;
void fixICCCMwindowGroup();
@@ -146,6 +145,8 @@ public:
QtMainWindow* GetTopLevelWindow() const { return m_pTopLevel; }
QWidget* asChild() const;
qreal devicePixelRatioF() const;
QPoint mapToParent(const QPoint&) const;
QPoint mapFromParent(const QPoint&) const;
void Damage(sal_Int32 nExtentsX, sal_Int32 nExtentsY, sal_Int32 nExtentsWidth,
sal_Int32 nExtentsHeight) const;
diff --git a/vcl/inc/qt5/QtMenu.hxx b/vcl/inc/qt5/QtMenu.hxx
index a1b7768..6bb0dbc 100644
--- a/vcl/inc/qt5/QtMenu.hxx
+++ b/vcl/inc/qt5/QtMenu.hxx
@@ -69,14 +69,15 @@ private:
public:
QtMenu(bool bMenuBar);
virtual bool VisibleMenuBar() override; // must return TRUE to actually DISPLAY native menu bars
virtual bool HasNativeMenuBar() override;
virtual int GetMenuBarHeight() const override;
virtual void ShowMenuBar(bool bVisible) override;
virtual void InsertItem(SalMenuItem* pSalMenuItem, unsigned nPos) override;
virtual void RemoveItem(unsigned nPos) override;
virtual void SetSubMenu(SalMenuItem* pSalMenuItem, SalMenu* pSubMenu, unsigned nPos) override;
virtual void SetFrame(const SalFrame* pFrame) override;
const QtFrame* GetFrame() const;
virtual void ShowMenuBar(bool bVisible) override;
virtual bool ShowNativePopupMenu(FloatingWindow* pWin, const tools::Rectangle& rRect,
FloatWinPopupFlags nFlags) override;
QtMenu* GetTopLevel();
@@ -95,7 +96,6 @@ public:
virtual bool AddMenuBarButton(const SalMenuButtonItem&) override;
virtual void RemoveMenuBarButton(sal_uInt16 nId) override;
virtual tools::Rectangle GetMenuBarButtonRectPixel(sal_uInt16 nId, SalFrame*) override;
virtual int GetMenuBarHeight() const override;
void SetMenu(Menu* pMenu) { mpVCLMenu = pMenu; }
Menu* GetMenu() { return mpVCLMenu; }
diff --git a/vcl/inc/qt5/QtPainter.hxx b/vcl/inc/qt5/QtPainter.hxx
index 9702a19..755a51f60 100644
--- a/vcl/inc/qt5/QtPainter.hxx
+++ b/vcl/inc/qt5/QtPainter.hxx
@@ -34,34 +34,26 @@ class QtPainter final : public QPainter
public:
QtPainter(QtGraphicsBackend& rGraphics, bool bPrepareBrush = false,
sal_uInt8 nTransparency = 255);
~QtPainter()
{
if (m_rGraphics.m_pFrame && !m_aRegion.isEmpty())
m_rGraphics.m_pFrame->GetQWidget()->update(m_aRegion);
}
~QtPainter();
void update(int nx, int ny, int nw, int nh)
{
if (m_rGraphics.m_pFrame)
m_aRegion += scaledQRect({ nx, ny, nw, nh }, 1 / m_rGraphics.devicePixelRatioF());
m_aRegion += QRect(nx, ny, nw, nh);
}
void update(const QRect& rRect)
{
if (m_rGraphics.m_pFrame)
m_aRegion += scaledQRect(rRect, 1 / m_rGraphics.devicePixelRatioF());
m_aRegion += rRect;
}
void update(const QRectF& rRectF)
{
if (m_rGraphics.m_pFrame)
update(scaledQRect(rRectF.toAlignedRect(), 1 / m_rGraphics.devicePixelRatioF()));
}
void update(const QRectF& rRectF) { update(rRectF.toAlignedRect()); }
void update()
{
if (m_rGraphics.m_pFrame)
m_aRegion += m_rGraphics.m_pFrame->GetQWidget()->rect();
m_aRegion += m_rGraphics.m_pFrame->GetQWidget()->geometry();
}
};
diff --git a/vcl/inc/qt5/QtTools.hxx b/vcl/inc/qt5/QtTools.hxx
index 534fe74..669b5bef 100644
--- a/vcl/inc/qt5/QtTools.hxx
+++ b/vcl/inc/qt5/QtTools.hxx
@@ -69,6 +69,11 @@ inline QRect scaledQRect(const QRect& rRect, const qreal fScale)
ceil(rRect.height() * fScale));
}
inline QSize scaledQSize(const QSize& rSize, const qreal fScale)
{
return QSize(ceil(rSize.width() * fScale), ceil(rSize.height() * fScale));
}
inline tools::Rectangle toRectangle(const QRect& rRect)
{
return tools::Rectangle(rRect.left(), rRect.top(), rRect.right(), rRect.bottom());
diff --git a/vcl/inc/salmenu.hxx b/vcl/inc/salmenu.hxx
index 79254d9..25a022b 100644
--- a/vcl/inc/salmenu.hxx
+++ b/vcl/inc/salmenu.hxx
@@ -59,9 +59,18 @@ class VCL_PLUGIN_PUBLIC SalMenu
public:
virtual ~SalMenu();
virtual bool VisibleMenuBar() = 0; // must return true to actually DISPLAY native menu bars
// otherwise only menu messages are processed (eg, OLE on Windows)
virtual void ShowMenuBar( bool ) {}
/**
* Return true, if the implementation supports a native menu bar
* (or wants to suppress LO's menu bar, like on Mac).
*
* You might need to implement the matching SalFrame::SetMenu.
**/
virtual bool HasNativeMenuBar() = 0;
/** Return the height of the native menu bar. Must return 0, if it's hidden. */
virtual int GetMenuBarHeight() const;
/** Change visibility of the native menu bar. */
virtual void ShowMenuBar(bool);
virtual void InsertItem( SalMenuItem* pSalMenuItem, unsigned nPos ) = 0;
virtual void RemoveItem( unsigned nPos ) = 0;
virtual void SetSubMenu( SalMenuItem* pSalMenuItem, SalMenu* pSubMenu, unsigned nPos ) = 0;
@@ -90,8 +99,6 @@ public:
// but rectangle cannot be determined
virtual tools::Rectangle GetMenuBarButtonRectPixel( sal_uInt16 i_nItemId, SalFrame* i_pReferenceFrame );
virtual int GetMenuBarHeight() const;
virtual void ApplyPersona();
};
diff --git a/vcl/inc/unx/gtk/gtksalmenu.hxx b/vcl/inc/unx/gtk/gtksalmenu.hxx
index 85c0f5d..ec1e123 100644
--- a/vcl/inc/unx/gtk/gtksalmenu.hxx
+++ b/vcl/inc/unx/gtk/gtksalmenu.hxx
@@ -71,8 +71,8 @@ public:
GtkSalMenu( bool bMenuBar );
virtual ~GtkSalMenu() override;
virtual bool VisibleMenuBar() override; // must return TRUE to actually DISPLAY native menu bars
// otherwise only menu messages are processed (eg, OLE on Windows)
virtual bool HasNativeMenuBar() override;
virtual void ShowMenuBar(bool bVisible) override;
virtual void InsertItem( SalMenuItem* pSalMenuItem, unsigned nPos ) override;
virtual void RemoveItem( unsigned nPos ) override;
@@ -112,7 +112,6 @@ public:
static void Activate(const gchar* pMenuCommand);
static void Deactivate(const gchar* pMenuCommand);
void EnableUnity(bool bEnable);
virtual void ShowMenuBar( bool bVisible ) override;
bool PrepUpdate() const;
virtual void Update() override; // Update this menu only.
// Update full menu hierarchy from this menu.
@@ -139,7 +138,6 @@ public:
virtual tools::Rectangle GetMenuBarButtonRectPixel( sal_uInt16 i_nItemId, SalFrame* i_pReferenceFrame ) override;
virtual bool CanGetFocus() const override;
virtual bool TakeFocus() override;
virtual int GetMenuBarHeight() const override;
virtual void ApplyPersona() override;
};
diff --git a/vcl/inc/win/salmenu.h b/vcl/inc/win/salmenu.h
index 7058d9c..96dc275 100644
--- a/vcl/inc/win/salmenu.h
+++ b/vcl/inc/win/salmenu.h
@@ -28,8 +28,7 @@ class WinSalMenu : public SalMenu
public:
WinSalMenu();
virtual ~WinSalMenu() override;
virtual bool VisibleMenuBar() override; // must return TRUE to actually DISPLAY native menu bars
// otherwise only menu messages are processed (eg, OLE on Windows)
virtual bool HasNativeMenuBar() override;
virtual void InsertItem( SalMenuItem* pSalMenuItem, unsigned nPos ) override;
virtual void RemoveItem( unsigned nPos ) override;
diff --git a/vcl/osx/salmenu.cxx b/vcl/osx/salmenu.cxx
index c35e748..60cafca 100644
--- a/vcl/osx/salmenu.cxx
+++ b/vcl/osx/salmenu.cxx
@@ -448,7 +448,7 @@ void AquaSalMenu::removeFallbackMenuItem( NSMenuItem* pOldItem )
}
}
bool AquaSalMenu::VisibleMenuBar()
bool AquaSalMenu::HasNativeMenuBar()
{
return true;
}
diff --git a/vcl/qt5/QtFrame.cxx b/vcl/qt5/QtFrame.cxx
index 9ccfd8e..3a240b2 100644
--- a/vcl/qt5/QtFrame.cxx
+++ b/vcl/qt5/QtFrame.cxx
@@ -249,8 +249,16 @@ QtFrame::~QtFrame()
void QtFrame::Damage(sal_Int32 nExtentsX, sal_Int32 nExtentsY, sal_Int32 nExtentsWidth,
sal_Int32 nExtentsHeight) const
{
m_pQWidget->update(scaledQRect(QRect(nExtentsX, nExtentsY, nExtentsWidth, nExtentsHeight),
1 / devicePixelRatioF()));
QRect aParentUpdateRect(scaledQRect(QRect(nExtentsX, nExtentsY, nExtentsWidth, nExtentsHeight),
1 / devicePixelRatioF()));
if (!m_pTopLevel)
m_pQWidget->update(aParentUpdateRect);
else
{
QRect aIntersectedRect(aParentUpdateRect.intersected(m_pQWidget->geometry()));
if (!aIntersectedRect.isEmpty())
m_pQWidget->update(aIntersectedRect.translated(-m_pQWidget->geometry().topLeft()));
}
}
SalGraphics* QtFrame::AcquireGraphics()
@@ -264,7 +272,7 @@ SalGraphics* QtFrame::AcquireGraphics()
{
if (!m_pSvpGraphics)
{
QSize aSize = m_pQWidget->size() * devicePixelRatioF();
QSize aSize = asChild()->size() * devicePixelRatioF();
m_pSvpGraphics.reset(new QtSvpGraphics(this));
m_pSurface.reset(
cairo_image_surface_create(CAIRO_FORMAT_ARGB32, aSize.width(), aSize.height()));
@@ -281,7 +289,7 @@ SalGraphics* QtFrame::AcquireGraphics()
{
m_pQtGraphics.reset(new QtGraphics(this));
m_pQImage.reset(
new QImage(m_pQWidget->size() * devicePixelRatioF(), Qt_DefaultFormat32));
new QImage(asChild()->size() * devicePixelRatioF(), Qt_DefaultFormat32));
m_pQImage->fill(Qt::transparent);
m_pQtGraphics->ChangeQImage(m_pQImage.get());
}
@@ -447,32 +455,25 @@ void QtFrame::SetMaxClientSize(tools::Long nWidth, tools::Long nHeight)
}
}
int QtFrame::menuBarOffset() const
{
QtMainWindow* pTopLevel = m_pParent->GetTopLevelWindow();
if (pTopLevel && pTopLevel->menuBar() && pTopLevel->menuBar()->isVisible())
return round(pTopLevel->menuBar()->geometry().height() * devicePixelRatioF());
return 0;
}
void QtFrame::SetDefaultPos()
{
if (!m_bDefaultPos)
return;
// center on parent
QWidget* const pChildWin = asChild()->window();
QPoint aPos;
// center on parent or screen
if (m_pParent)
{
const qreal fRatio = devicePixelRatioF();
QWidget* const pParentWin = m_pParent->asChild()->window();
QWidget* const pChildWin = asChild()->window();
QPoint aPos = (pParentWin->rect().center() - pChildWin->rect().center()) * fRatio;
aPos.ry() -= menuBarOffset();
SetPosSize(aPos.x(), aPos.y(), 0, 0, SAL_FRAME_POSSIZE_X | SAL_FRAME_POSSIZE_Y);
assert(!m_bDefaultPos);
aPos = (pParentWin->rect().center() - pChildWin->rect().center()) * devicePixelRatioF();
}
else
m_bDefaultPos = false;
aPos = windowHandle()->screen()->availableGeometry().center() - pChildWin->rect().center();
SetPosSize(aPos.x(), aPos.y(), 0, 0, SAL_FRAME_POSSIZE_X | SAL_FRAME_POSSIZE_Y);
assert(!m_bDefaultPos);
}
Size QtFrame::CalcDefaultSize()
@@ -566,10 +567,11 @@ void QtFrame::SetPosSize(tools::Long nX, tools::Long nY, tools::Long nWidth, too
{
const SalFrameGeometry& aParentGeometry = m_pParent->maGeometry;
if (QGuiApplication::isRightToLeft())
nX = aParentGeometry.x() + aParentGeometry.width() - nX - maGeometry.width() - 1;
nX = aParentGeometry.x() + aParentGeometry.width() - nX - maGeometry.width()
- aParentGeometry.rightDecoration() - 1;
else
nX += aParentGeometry.x();
nY += aParentGeometry.y() + menuBarOffset();
nX += aParentGeometry.x() + aParentGeometry.leftDecoration();
nY += aParentGeometry.y() + aParentGeometry.topDecoration();
}
if (!(nFlags & SAL_FRAME_POSSIZE_X))
@@ -587,8 +589,8 @@ void QtFrame::SetPosSize(tools::Long nX, tools::Long nY, tools::Long nWidth, too
void QtFrame::GetClientSize(tools::Long& rWidth, tools::Long& rHeight)
{
rWidth = round(m_pQWidget->width() * devicePixelRatioF());
rHeight = round(m_pQWidget->height() * devicePixelRatioF());
rWidth = maGeometry.width();
rHeight = maGeometry.height();
}
void QtFrame::GetWorkArea(tools::Rectangle& rRect)
@@ -1510,4 +1512,14 @@ void QtFrame::handleDragLeave()
m_bInDrag = false;
}
QPoint QtFrame::mapToParent(const QPoint& rPos) const
{
return m_pTopLevel ? m_pQWidget->mapToParent(rPos) : rPos;
}
QPoint QtFrame::mapFromParent(const QPoint& rPos) const
{
return m_pTopLevel ? m_pQWidget->mapFromParent(rPos) : rPos;
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qt5/QtMenu.cxx b/vcl/qt5/QtMenu.cxx
index ccd2eb4..5a4d3e8 100644
--- a/vcl/qt5/QtMenu.cxx
+++ b/vcl/qt5/QtMenu.cxx
@@ -59,7 +59,7 @@ QtMenu::QtMenu(bool bMenuBar)
{
}
bool QtMenu::VisibleMenuBar() { return true; }
bool QtMenu::HasNativeMenuBar() { return true; }
void QtMenu::InsertMenuItem(QtMenuItem* pSalMenuItem, unsigned nPos)
{
@@ -845,8 +845,7 @@ int QtMenu::GetMenuBarHeight() const
{
if (!validateQMenuBar() || !mpQMenuBar->isVisible())
return 0;
return mpQMenuBar->height();
return mpQMenuBar->height() * mpFrame->devicePixelRatioF();
}
QtMenuItem::QtMenuItem(const SalItemParams* pItemData)
diff --git a/vcl/qt5/QtPainter.cxx b/vcl/qt5/QtPainter.cxx
index fc0057e..a4c83bb 100644
--- a/vcl/qt5/QtPainter.cxx
+++ b/vcl/qt5/QtPainter.cxx
@@ -56,3 +56,23 @@ QtPainter::QtPainter(QtGraphicsBackend& rGraphics, bool bPrepareBrush, sal_uInt8
setCompositionMode(rGraphics.m_eCompositionMode);
setRenderHint(QPainter::Antialiasing, m_rGraphics.getAntiAlias());
}
QtPainter::~QtPainter()
{
if (!m_rGraphics.m_pFrame || m_aRegion.isEmpty())
return;
QWidget* pWidget = m_rGraphics.m_pFrame->GetQWidget();
QRect aParentUpdateRect(
scaledQRect(m_aRegion.boundingRect(), 1 / m_rGraphics.devicePixelRatioF()));
if (!m_rGraphics.m_pFrame->GetTopLevelWindow())
pWidget->update(m_aRegion);
else
{
QRect aIntersectedRect(aParentUpdateRect.intersected(pWidget->geometry()));
if (!aIntersectedRect.isEmpty())
pWidget->update(aIntersectedRect.translated(-pWidget->geometry().topLeft()));
}
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qt5/QtWidget.cxx b/vcl/qt5/QtWidget.cxx
index e26e1e3..ead9979 100644
--- a/vcl/qt5/QtWidget.cxx
+++ b/vcl/qt5/QtWidget.cxx
@@ -82,18 +82,21 @@ void QtWidget::paintEvent(QPaintEvent* pEvent)
aImage = *m_rFrame.m_pQImage;
const qreal fRatio = m_rFrame.devicePixelRatioF();
assert(aImage.size() == scaledQSize(m_rFrame.asChild()->size(), fRatio));
aImage.setDevicePixelRatio(fRatio);
QRectF source(pEvent->rect().topLeft() * fRatio, pEvent->rect().size() * fRatio);
p.drawImage(pEvent->rect(), aImage, source);
QPoint aPos = m_rFrame.mapToParent(pEvent->rect().topLeft());
QRectF source(aPos * fRatio, scaledQSize(pEvent->rect().size(), fRatio));
p.drawImage(pEvent->rect().topLeft(), aImage, source);
}
void QtWidget::resizeEvent(QResizeEvent* pEvent)
void QtWidget::resizeEvent(QResizeEvent*)
{
// this uses the actual frame size for the double buffering backing store.
// while children get a resize event before their parents, the size of the
// frame / window is already updated at this point.
const qreal fRatio = m_rFrame.devicePixelRatioF();
const int nWidth = ceil(pEvent->size().width() * fRatio);
const int nHeight = ceil(pEvent->size().height() * fRatio);
m_rFrame.maGeometry.setSize({ nWidth, nHeight });
const int nWidth = ceil(m_rFrame.asChild()->size().width() * fRatio);
const int nHeight = ceil(m_rFrame.asChild()->size().height() * fRatio);
if (m_rFrame.m_bUseCairo)
{
@@ -128,6 +131,13 @@ void QtWidget::resizeEvent(QResizeEvent* pEvent)
}
}
const QRect aQtFrameGeometry = m_rFrame.asChild()->frameGeometry();
const QRect aQtGeometry = m_rFrame.asChild()->geometry();
m_rFrame.maGeometry.setLeftDecoration(aQtGeometry.left() - aQtFrameGeometry.left());
m_rFrame.maGeometry.setTopDecoration(aQtGeometry.top() - aQtFrameGeometry.top());
m_rFrame.maGeometry.setRightDecoration(aQtFrameGeometry.right() - aQtGeometry.right());
m_rFrame.maGeometry.setBottomDecoration(aQtFrameGeometry.bottom() - aQtGeometry.bottom());
m_rFrame.maGeometry.setSize({ nWidth, nHeight });
m_rFrame.CallCallback(SalEvent::Resize, nullptr);
}
@@ -142,7 +152,7 @@ void QtWidget::fillSalAbstractMouseEvent(const QtFrame& rFrame, const QInputEven
SalAbstractMouseEvent& aSalEvent)
{
const qreal fRatio = rFrame.devicePixelRatioF();
const Point aPos = toPoint(rPos * fRatio);
const Point aPos = toPoint(rFrame.mapToParent(rPos) * fRatio);
aSalEvent.mnX = QGuiApplication::isLeftToRight() ? aPos.X() : round(nWidth * fRatio) - aPos.X();
aSalEvent.mnY = aPos.Y();
@@ -205,7 +215,7 @@ void QtWidget::mouseMoveEvent(QMouseEvent* pEvent)
void QtWidget::handleMouseEnterLeaveEvents(const QtFrame& rFrame, QEvent* pQEvent)
{
const qreal fRatio = rFrame.devicePixelRatioF();
const QWidget* pWidget = rFrame.GetQWidget();
const QWidget* pWidget = rFrame.asChild();
const Point aPos = toPoint(pWidget->mapFromGlobal(QCursor::pos()) * fRatio);
SalMouseEvent aEvent;
diff --git a/vcl/source/app/salvtables.cxx b/vcl/source/app/salvtables.cxx
index 40c0442..0cca56b 100644
--- a/vcl/source/app/salvtables.cxx
+++ b/vcl/source/app/salvtables.cxx
@@ -235,6 +235,8 @@ tools::Rectangle SalMenu::GetMenuBarButtonRectPixel(sal_uInt16, SalFrame*)
int SalMenu::GetMenuBarHeight() const { return 0; }
void SalMenu::ShowMenuBar(bool) {}
void SalMenu::ApplyPersona() {}
SalMenuItem::~SalMenuItem() {}
diff --git a/vcl/source/window/menu.cxx b/vcl/source/window/menu.cxx
index 5fb4c2c..bd24431 100644
--- a/vcl/source/window/menu.cxx
+++ b/vcl/source/window/menu.cxx
@@ -2207,6 +2207,11 @@ void Menu::ImplFillLayoutData() const
}
}
SalMenu* Menu::GetNativeMenuBar()
{
return mpSalMenu && mpSalMenu->HasNativeMenuBar() ? mpSalMenu.get() : nullptr;
}
tools::Rectangle Menu::GetCharacterBounds( sal_uInt16 nItemID, tools::Long nIndex ) const
{
tools::Long nItemIndex = -1;
@@ -2440,26 +2445,16 @@ void MenuBar::SetDisplayable( bool bDisplayable )
VclPtr<vcl::Window> MenuBar::ImplCreate(vcl::Window* pParent, vcl::Window* pWindow, MenuBar* pMenu)
{
// can't this be a static_cast? is there a real possibility, the pWindow is not the MenuBarWindow or nullptr?
VclPtr<MenuBarWindow> pMenuBarWindow = dynamic_cast<MenuBarWindow*>(pWindow);
if (!pMenuBarWindow)
{
pWindow = pMenuBarWindow = VclPtr<MenuBarWindow>::Create( pParent );
}
pMenuBarWindow = VclPtr<MenuBarWindow>::Create(pParent);
pMenu->pStartedFrom = nullptr;
pMenu->pWindow = pWindow;
pMenu->pWindow = pMenuBarWindow;
pMenuBarWindow->SetMenu(pMenu);
tools::Long nHeight = pWindow ? pMenu->ImplCalcSize(pWindow).Height() : 0;
// depending on the native implementation or the displayable flag
// the menubar windows is suppressed (ie, height=0)
if (!pMenu->IsDisplayable() || (pMenu->ImplGetSalMenu() && pMenu->ImplGetSalMenu()->VisibleMenuBar()))
{
nHeight = 0;
}
pMenuBarWindow->SetHeight(nHeight);
return pWindow;
return pMenuBarWindow;
}
void MenuBar::ImplDestroy( MenuBar* pMenu, bool bDelete )
@@ -2486,7 +2481,7 @@ bool MenuBar::ImplHandleKeyEvent( const KeyEvent& rKEvent )
// No keyboard processing when system handles the menu.
SalMenu *pNativeMenu = ImplGetSalMenu();
if (pNativeMenu && pNativeMenu->VisibleMenuBar())
if (pNativeMenu && pNativeMenu->HasNativeMenuBar())
{
// Except when the event is the F6 cycle pane event and we can put our
// focus into it (i.e. the gtk3 menubar case but not the mac/unity case
diff --git a/vcl/source/window/menubarwindow.cxx b/vcl/source/window/menubarwindow.cxx
index 0109bb5..552034b 100644
--- a/vcl/source/window/menubarwindow.cxx
+++ b/vcl/source/window/menubarwindow.cxx
@@ -167,34 +167,43 @@ void MenuBarWindow::dispose()
Window::dispose();
}
void MenuBarWindow::SetMenu( MenuBar* pMen )
void MenuBarWindow::SetMenu(MenuBar* pMenu)
{
m_pMenu = pMen;
if (pMenu == m_pMenu)
return;
m_pMenu = pMenu;
KillActivePopup();
m_nHighlightedItem = ITEMPOS_INVALID;
if (pMen)
if (!pMenu)
{
m_aCloseBtn->ShowItem(ToolBoxItemId(IID_DOCUMENTCLOSE), pMen->HasCloseButton());
m_aCloseBtn->Show(pMen->HasCloseButton() || !m_aAddButtons.empty());
m_aFloatBtn->Show(pMen->HasFloatButton());
m_aHideBtn->Show(pMen->HasHideButton());
LayoutChanged();
return;
}
Invalidate();
SalMenu* pSalMenu = pMenu->ImplGetSalMenu();
const bool bHasNativeMenuBar = pSalMenu && pSalMenu->HasNativeMenuBar();
// show and connect native menubar
if( m_pMenu && m_pMenu->ImplGetSalMenu() )
// no menubar window drawing needed in case of a native menu bar
SetPaintTransparent(bHasNativeMenuBar);
m_aCloseBtn->ShowItem(ToolBoxItemId(IID_DOCUMENTCLOSE), !bHasNativeMenuBar && pMenu->HasCloseButton());
m_aCloseBtn->Show(!bHasNativeMenuBar && (pMenu->HasCloseButton() || !m_aAddButtons.empty()));
m_aFloatBtn->Show(!bHasNativeMenuBar && pMenu->HasFloatButton());
m_aHideBtn->Show(!bHasNativeMenuBar && pMenu->HasHideButton());
// connect native popup menu / menubar and show it
if (pSalMenu)
{
if( m_pMenu->ImplGetSalMenu()->VisibleMenuBar() )
ImplGetFrame()->SetMenu( m_pMenu->ImplGetSalMenu() );
m_pMenu->ImplGetSalMenu()->SetFrame( ImplGetFrame() );
m_pMenu->ImplGetSalMenu()->ShowMenuBar(true);
SalFrame* pFrame = ImplGetFrame();
assert(pFrame);
if (bHasNativeMenuBar)
pFrame->SetMenu(pSalMenu);
pSalMenu->SetFrame(pFrame);
if (bHasNativeMenuBar)
pSalMenu->ShowMenuBar(true);
}
}
void MenuBarWindow::SetHeight(tools::Long nHeight)
{
setPosSizePixel(0, 0, 0, nHeight, PosSizeFlags::Height);
LayoutChanged();
}
void MenuBarWindow::ShowButtons( bool bClose, bool bFloat, bool bHide )
@@ -724,10 +733,8 @@ bool MenuBarWindow::HandleKeyEvent( const KeyEvent& rKEvent, bool bFromMenu )
}
// no key events if native menus
if (m_pMenu->ImplGetSalMenu() && m_pMenu->ImplGetSalMenu()->VisibleMenuBar())
{
if (m_pMenu->GetNativeMenuBar())
return false;
}
if ( nCode == KEY_MENU && !rKEvent.GetKeyCode().IsShift() ) // only F10, not Shift-F10
{
@@ -862,7 +869,7 @@ void MenuBarWindow::Paint(vcl::RenderContext& rRenderContext, const tools::Recta
Size aOutputSize = GetOutputSizePixel();
// no VCL paint if native menus
if (m_pMenu->ImplGetSalMenu() && m_pMenu->ImplGetSalMenu()->VisibleMenuBar())
if (m_pMenu->GetNativeMenuBar())
return;
// Make sure that all actual rendering happens in one go to avoid flicker.
@@ -1004,22 +1011,24 @@ void MenuBarWindow::LayoutChanged()
ApplySettings(*GetOutDev());
// if the font was changed.
tools::Long nHeight = m_pMenu->ImplCalcSize(this).Height();
// depending on the native implementation or the displayable flag
// the menubar windows is suppressed (ie, height=0)
if (!static_cast<MenuBar*>(m_pMenu.get())->IsDisplayable() ||
(m_pMenu->ImplGetSalMenu() && m_pMenu->ImplGetSalMenu()->VisibleMenuBar()))
{
nHeight = 0;
}
tools::Long nHeight = 0;
const bool bHasNativeMenuBar = m_pMenu->GetNativeMenuBar();
if (bHasNativeMenuBar)
nHeight = m_pMenu->ImplGetSalMenu()->GetMenuBarHeight();
else if (static_cast<MenuBar*>(m_pMenu.get())->IsDisplayable())
nHeight = m_pMenu->ImplCalcSize(this).Height();
setPosSizePixel(0, 0, 0, nHeight, PosSizeFlags::Height);
GetParent()->Resize();
Invalidate();
Resize();
m_pMenu->ImplKillLayoutData();
if (!bHasNativeMenuBar)
{
Invalidate();
Resize();
m_pMenu->ImplKillLayoutData();
}
}
void MenuBarWindow::ApplySettings(vcl::RenderContext& rRenderContext)
@@ -1210,8 +1219,8 @@ bool MenuBarWindow::CanGetFocus() const
this relies on MenuBar::ImplCreate setting the height of the menubar
to 0 in this case
*/
SalMenu *pNativeMenu = m_pMenu ? m_pMenu->ImplGetSalMenu() : nullptr;
if (pNativeMenu && pNativeMenu->VisibleMenuBar())
SalMenu *pNativeMenu = m_pMenu ? m_pMenu->GetNativeMenuBar() : nullptr;
if (pNativeMenu)
return pNativeMenu->CanGetFocus();
return GetSizePixel().Height() > 0;
}
diff --git a/vcl/source/window/menubarwindow.hxx b/vcl/source/window/menubarwindow.hxx
index cc7963a..0a90747 100644
--- a/vcl/source/window/menubarwindow.hxx
+++ b/vcl/source/window/menubarwindow.hxx
@@ -120,7 +120,6 @@ public:
virtual void RequestHelp( const HelpEvent& rHEvt ) override;
void SetMenu(MenuBar* pMenu);
void SetHeight(tools::Long nHeight);
void KillActivePopup();
void PopupClosed(Menu const * pMenu);
sal_uInt16 GetHighlightedItem() const { return m_nHighlightedItem; }
diff --git a/vcl/unx/gtk3/gtksalmenu.cxx b/vcl/unx/gtk3/gtksalmenu.cxx
index bcae159..22261c6 100644
--- a/vcl/unx/gtk3/gtksalmenu.cxx
+++ b/vcl/unx/gtk3/gtksalmenu.cxx
@@ -653,7 +653,7 @@ GtkSalMenu::~GtkSalMenu()
mpFrame->SetMenu(nullptr);
}
bool GtkSalMenu::VisibleMenuBar()
bool GtkSalMenu::HasNativeMenuBar()
{
return mbMenuBar && (bUnityMode || mpMenuBarContainerWidget);
}
@@ -1618,11 +1618,6 @@ void GtkSalMenu::GetSystemMenuData( SystemMenuData* )
{
}
int GtkSalMenu::GetMenuBarHeight() const
{
return mpMenuBarWidget ? gtk_widget_get_allocated_height(mpMenuBarWidget) : 0;
}
/*
* GtkSalMenuItem
*/
diff --git a/vcl/win/window/salmenu.cxx b/vcl/win/window/salmenu.cxx
index 91a1528..4b07f23 100644
--- a/vcl/win/window/salmenu.cxx
+++ b/vcl/win/window/salmenu.cxx
@@ -115,7 +115,7 @@ WinSalMenu::~WinSalMenu()
::DestroyMenu( mhMenu );
}
bool WinSalMenu::VisibleMenuBar()
bool WinSalMenu::HasNativeMenuBar()
{
// The Win32 implementation never shows a native
// menubar. Thus, native menus are only visible