diff options
author | Jan-Marek Glogowski <glogow@fbihome.de> | 2021-10-31 02:33:46 +0200 |
---|---|---|
committer | Jan-Marek Glogowski <glogow@fbihome.de> | 2021-10-31 21:04:33 +0100 |
commit | b00a68a8e19370e106cd76258a3c1825f43613ee (patch) | |
tree | 7dc47d21ca3f2401c6b29bde91492053f222b4e8 /vcl/qt5 | |
parent | e4abf879f4a24258bcc560eb58ca78b147768d46 (diff) |
tdf#145363 Qt reparent modal dialogs on show
Simply said, one can't have two modal dialogs open at the same
parent in Qt. All modal windows must open as a stack, each
parented to the previous one. This is kind of logical.
Unexpectedly Qt totally breaks, if you open two modal dialogs on
the same window. This happens, because the existing paragraph
style dialog and the "sub" "list style" dialog are both children
of their Writer window.
I'm not sure the additionally introduced QWidget-based parent
handling is strictly needed. It seems Ok.
So for every visibility and modality change, we reparent the
Qt widget, either on top of the modal stack or restore the
original LO-based parent. The LO hierachy is never changed!
Change-Id: Id209c9aa67774440089dc50a6648ac293950087a
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/124500
Tested-by: Jenkins
Reviewed-by: Jan-Marek Glogowski <glogow@fbihome.de>
Diffstat (limited to 'vcl/qt5')
-rw-r--r-- | vcl/qt5/QtFrame.cxx | 80 | ||||
-rw-r--r-- | vcl/qt5/QtWidget.cxx | 6 |
2 files changed, 76 insertions, 10 deletions
diff --git a/vcl/qt5/QtFrame.cxx b/vcl/qt5/QtFrame.cxx index 73bdad874552..1ae4016d589d 100644 --- a/vcl/qt5/QtFrame.cxx +++ b/vcl/qt5/QtFrame.cxx @@ -417,24 +417,71 @@ void QtFrame::DrawMenuBar() { /* not needed */} void QtFrame::SetExtendedFrameStyle(SalExtStyle /*nExtStyle*/) { /* not needed */} +void QtFrame::modalReparent(bool bVisible) +{ +#ifndef NDEBUG + auto* pSalInst(static_cast<QtInstance*>(GetSalData()->m_pInstance)); + assert(pSalInst); + assert(pSalInst->IsMainThread()); + assert(!asChild()->isVisible()); + assert(asChild()->isModal()); +#endif + + if (!bVisible) + { + m_pQWidget->setParent(m_pParent ? m_pParent->asChild() : nullptr, + m_pQWidget->windowFlags()); + return; + } + + if (!QGuiApplication::modalWindow()) + return; + + QtInstance* pInst = static_cast<QtInstance*>(GetSalData()->m_pInstance); + for (auto* pFrame : pInst->getFrames()) + { + QWidget* pQWidget = static_cast<QtFrame*>(pFrame)->asChild(); + if (pQWidget->windowHandle() == QGuiApplication::modalWindow()) + { + m_pQWidget->setParent(pQWidget, m_pQWidget->windowFlags()); + break; + } + } +} + void QtFrame::Show(bool bVisible, bool bNoActivate) { assert(m_pQWidget); if (bVisible == asChild()->isVisible()) return; + auto* pSalInst(static_cast<QtInstance*>(GetSalData()->m_pInstance)); + assert(pSalInst); + + if (!bVisible) // hide + { + pSalInst->RunInMainThread([this]() { + asChild()->hide(); + if (m_pQWidget->isModal()) + modalReparent(false); + }); + return; + } + + // show SetDefaultSize(); SetDefaultPos(); - auto* pSalInst(static_cast<QtInstance*>(GetSalData()->m_pInstance)); - assert(pSalInst); - pSalInst->RunInMainThread([this, bVisible, bNoActivate]() { - asChild()->setVisible(bVisible); - asChild()->raise(); + pSalInst->RunInMainThread([this, bNoActivate]() { + QWidget* const pChild = asChild(); + if (m_pQWidget->isModal()) + modalReparent(true); + pChild->show(); + pChild->raise(); if (!bNoActivate && !isPopup()) { - asChild()->activateWindow(); - asChild()->setFocus(); + pChild->activateWindow(); + pChild->setFocus(); } }); } @@ -610,7 +657,7 @@ SalFrame* QtFrame::GetParent() const { return m_pParent; } void QtFrame::SetModal(bool bModal) { - if (!isWindow()) + if (!isWindow() || asChild()->isModal() == bModal) return; auto* pSalInst(static_cast<QtInstance*>(GetSalData()->m_pInstance)); @@ -622,12 +669,20 @@ void QtFrame::SetModal(bool bModal) // modality change is only effective if the window is hidden if (bWasVisible) + { pChild->hide(); + if (!bModal) + modalReparent(false); + } pChild->setWindowModality(bModal ? Qt::WindowModal : Qt::NonModal); if (bWasVisible) + { + if (bModal) + modalReparent(true); pChild->show(); + } }); } @@ -1180,7 +1235,14 @@ void QtFrame::SimulateKeyPress(sal_uInt16 nKeyCode) SAL_WARN("vcl.qt", "missing simulate keypress " << nKeyCode); } -void QtFrame::SetParent(SalFrame* pNewParent) { m_pParent = static_cast<QtFrame*>(pNewParent); } +void QtFrame::SetParent(SalFrame* pNewParent) +{ + if (m_pParent == pNewParent) + return; + m_pParent = static_cast<QtFrame*>(pNewParent); + if (!m_pTopLevel) + m_pQWidget->setParent(m_pParent->asChild(), m_pQWidget->windowFlags()); +} void QtFrame::SetPluginParent(SystemParentData* /*pNewParent*/) { diff --git a/vcl/qt5/QtWidget.cxx b/vcl/qt5/QtWidget.cxx index 44952f9318b0..85bcd814b03a 100644 --- a/vcl/qt5/QtWidget.cxx +++ b/vcl/qt5/QtWidget.cxx @@ -23,6 +23,7 @@ #include <QtFrame.hxx> #include <QtGraphics.hxx> #include <QtInstance.hxx> +#include <QtMainWindow.hxx> #include <QtSvpGraphics.hxx> #include <QtTransferable.hxx> #include <QtTools.hxx> @@ -616,7 +617,10 @@ void QtWidget::focusOutEvent(QFocusEvent*) } QtWidget::QtWidget(QtFrame& rFrame, Qt::WindowFlags f) - : QWidget(Q_NULLPTR, f) + : QWidget(!rFrame.GetTopLevelWindow() && rFrame.GetParent() + ? static_cast<QtFrame*>(rFrame.GetParent())->asChild() + : Q_NULLPTR, + f) , m_rFrame(rFrame) , m_bNonEmptyIMPreeditSeen(false) , m_nDeltaX(0) |