[Libreoffice-commits] core.git: Branch 'libreoffice-7-3' - vcl/inc vcl/qt5
vcl/inc/qt5/QtObject.hxx | 25 ++ vcl/qt5/QtObject.cxx | 65 ++- 2 files changed, 57 insertions(+), 33 deletions(-) New commits: commit 70e497f786dad6bda3aa593c07c778b06381c0e4 Author: Jan-Marek Glogowski AuthorDate: Tue May 24 11:34:59 2022 +0200 Commit: Michael Weghorn CommitDate: Wed May 25 16:25:34 2022 +0200 tdf#148864 Qt switch QtObjectWindow to QWidget ... and therefore rename it to QtObjectWidget Replacement of the QWidget with QWindow originally happened in commit 56b19f9a814ae5a39ed760ee542d715493cd0bf3 ("tdf#121247, tdf#121266 KDE5: Add basic support for OpenGL"), but that unfortunately has a very sparce commit message with no reason for this change. Then the code was further complicated in commit 25edbded9946801effd117b9c46de0f8b4bc5632 ("tdf#125517 Qt5 implement a minimal Qt5ObjectWindow") and a few follow up fixes to restore input and focus handling. But appearingly all this QWindow handling isn't necessary and just returning to a QWidget based class fixes the problems with the video overlay (AKA QWidget::winId()) and video playback for good. The OpenGL Impress transition (Fade) mentioned in the original tdf#121266 bug still works. This also adds the previously missing SolarMutexGuard to all the overridden QtObjectWidget functions, which call the SalObject's Callback function. I accidently triggered a DBG_TESTSOLARMUTEX crashing Impress while debugging this. Change-Id: Ia22cabfd4f3585dc7fa3f9f18a913c5bd1987dd8 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/134864 Reviewed-by: Michael Weghorn Tested-by: Jenkins (cherry picked from commit 4366e0605214260e55a937173b0c2e02225dc843) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/134903 Reviewed-by: Ilmari Lauhakangas diff --git a/vcl/inc/qt5/QtObject.hxx b/vcl/inc/qt5/QtObject.hxx index 328946e4388e..bc5a8e584b8f 100644 --- a/vcl/inc/qt5/QtObject.hxx +++ b/vcl/inc/qt5/QtObject.hxx @@ -24,10 +24,11 @@ #include #include -#include +#include class QtFrame; -class QWidget; +class QtObjectWidget; +class QWindow; class QtObject final : public QObject, public SalObject { @@ -35,17 +36,18 @@ class QtObject final : public QObject, public SalObject SystemEnvData m_aSystemData; QtFrame* m_pParent; -QWidget* m_pQWidget; // main widget, container -QWindow* m_pQWindow; // contained window, used for opengl rendering +QtObjectWidget* m_pQWidget; QRegion m_pRegion; +bool m_bForwardKey; public: QtObject(QtFrame* pParent, bool bShow); ~QtObject() override; QtFrame* frame() const { return m_pParent; } -QWidget* widget() const { return m_pQWidget; } -QWindow* windowHandle() const { return m_pQWindow; } +inline QWidget* widget() const; +QWindow* windowHandle() const; +bool forwardKey() const { return m_bForwardKey; } virtual void ResetClipRegion() override; virtual void BeginSetClipRegion(sal_uInt32 nRects) override; @@ -60,22 +62,25 @@ public: virtual void SetForwardKey(bool bEnable) override; virtual const SystemEnvData* GetSystemData() const override { return _aSystemData; } + +virtual void Reparent(SalFrame* pFrame) override; }; -class QtObjectWindow final : public QWindow +class QtObjectWidget final : public QWidget { QtObject& m_rParent; -bool event(QEvent*) override; void focusInEvent(QFocusEvent*) override; void focusOutEvent(QFocusEvent*) override; void mousePressEvent(QMouseEvent*) override; void mouseReleaseEvent(QMouseEvent*) override; -// keyPressEvent(QKeyEvent*) is handled via event(QEvent*); see comment in QtWidget::event +void keyPressEvent(QKeyEvent*) override; void keyReleaseEvent(QKeyEvent*) override; public: -explicit QtObjectWindow(QtObject& rParent); +explicit QtObjectWidget(QtObject& rParent); }; +QWidget* QtObject::widget() const { return m_pQWidget; } + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/qt5/QtObject.cxx b/vcl/qt5/QtObject.cxx index 569586a0dc98..fbdc8e9b625e 100644 --- a/vcl/qt5/QtObject.cxx +++ b/vcl/qt5/QtObject.cxx @@ -24,20 +24,18 @@ #include #include +#include +#include QtObject::QtObject(QtFrame* pParent, bool bShow) : m_pParent(pParent) , m_pQWidget(nullptr) -, m_pQWindow(nullptr) +, m_bForwardKey(false) { if (!m_pParent || !pParent->GetQWidget()) return; -m_pQWindow = new QtObjectWindow(*this); -m_pQWidget = QWidget::createWindowContainer(m_pQWindow, pParent->GetQWidget()); -m_pQWidget->setAttribute(Qt::WA_NoSystemBackground); -connect(m_pQWidget, ::destroyed, this, [this]() { m_pQWidget = nullptr; }); - +m_pQWidget = new QtObjectWidget(*this); if (bShow) m_pQWidget->show(); @@ -53,6 +51,11 @@ QtObject::~QtObject()
[Libreoffice-commits] core.git: Branch 'libreoffice-7-3' - vcl/inc vcl/qt5
vcl/inc/qt5/QtInstance.hxx |6 ++ vcl/inc/qt5/QtWidget.hxx |1 + vcl/qt5/QtInstance.cxx |7 +++ vcl/qt5/QtWidget.cxx | 20 4 files changed, 30 insertions(+), 4 deletions(-) New commits: commit 06c51d61e4a16057f945effe85b1ff9457f8cffb Author: Jan-Marek Glogowski AuthorDate: Thu Apr 21 10:56:42 2022 +0200 Commit: Jan-Marek Glogowski CommitDate: Thu Apr 21 18:57:05 2022 +0200 tdf#148699 Qt track the active / shown popup I have no idea, if there can be multiple active popups in LO in some way. There can be multiple FloatingWindow and gtk does count them in m_nFloats... There is a whole lot going on in gtk3 related to isFloatGrabWindow(), with "funny" comments like: // FIXME: find out who the hell steals the focus from our frame So this goes with some "optimistic" approach: there is just one active popup, so we can track it in QtInstance. It WFM... Change-Id: I9778587696e1ad9e641dba4f102e2e921266eee6 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133249 Tested-by: Jenkins Reviewed-by: Michael Weghorn (cherry picked from commit 347622a98f512dae709f938a85498dcdcf9f225a) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133260 Reviewed-by: Jan-Marek Glogowski diff --git a/vcl/inc/qt5/QtInstance.hxx b/vcl/inc/qt5/QtInstance.hxx index 9a9853a7a2ce..fd111bb22abe 100644 --- a/vcl/inc/qt5/QtInstance.hxx +++ b/vcl/inc/qt5/QtInstance.hxx @@ -35,6 +35,7 @@ #include "QtFilePicker.hxx" +class QtFrame; class QtTimer; class QApplication; @@ -67,6 +68,8 @@ class VCLPLUG_QT_PUBLIC QtInstance : public QObject, Timer m_aUpdateStyleTimer; bool m_bUpdateFonts; +QtFrame* m_pActivePopup; + DECL_DLLPRIVATE_LINK(updateStyleHdl, Timer*, void); void AfterAppInit() override; @@ -172,6 +175,9 @@ public: void UpdateStyle(bool bFontsChanged); void* CreateGStreamerSink(const SystemChildWindow*) override; + +QtFrame* activePopup() const { return m_pActivePopup; } +void setActivePopup(QtFrame*); }; /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/inc/qt5/QtWidget.hxx b/vcl/inc/qt5/QtWidget.hxx index 4a40589b16ba..8f7f6cc319e1 100644 --- a/vcl/inc/qt5/QtWidget.hxx +++ b/vcl/inc/qt5/QtWidget.hxx @@ -73,6 +73,7 @@ class QtWidget : public QWidget virtual void paintEvent(QPaintEvent*) override; virtual void resizeEvent(QResizeEvent*) override; virtual void showEvent(QShowEvent*) override; +virtual void hideEvent(QHideEvent*) override; virtual void wheelEvent(QWheelEvent*) override; virtual void closeEvent(QCloseEvent*) override; virtual void changeEvent(QEvent*) override; diff --git a/vcl/qt5/QtInstance.cxx b/vcl/qt5/QtInstance.cxx index d252109e122a..247001443020 100644 --- a/vcl/qt5/QtInstance.cxx +++ b/vcl/qt5/QtInstance.cxx @@ -223,6 +223,7 @@ QtInstance::QtInstance(std::unique_ptr& pQApp, bool bUseCairo) , m_pQApplication(std::move(pQApp)) , m_aUpdateStyleTimer("vcl::qt5 m_aUpdateStyleTimer") , m_bUpdateFonts(false) +, m_pActivePopup(nullptr) { ImplSVData* pSVData = ImplGetSVData(); const OUString sToolkit = "qt" + OUString::number(QT_VERSION_MAJOR); @@ -722,6 +723,12 @@ std::unique_ptr QtInstance::CreateQApplication(int& nArgc, char** return pQApp; } +void QtInstance::setActivePopup(QtFrame* pFrame) +{ +assert(!pFrame || pFrame->isPopup()); +m_pActivePopup = pFrame; +} + extern "C" { VCLPLUG_QT_PUBLIC SalInstance* create_SalInstance() { diff --git a/vcl/qt5/QtWidget.cxx b/vcl/qt5/QtWidget.cxx index 5f07974600e8..8c545fd13377 100644 --- a/vcl/qt5/QtWidget.cxx +++ b/vcl/qt5/QtWidget.cxx @@ -317,9 +317,21 @@ void QtWidget::showEvent(QShowEvent*) // sequence from QtFrame::SetModal, if the frame was already set visible, // resulting in a hidden / unmapped window SalPaintEvent aPaintEvt(0, 0, aSize.width(), aSize.height()); +if (m_rFrame.isPopup()) +{ +auto* pQtInst(static_cast(GetSalData()->m_pInstance)); +pQtInst->setActivePopup(_rFrame); +} m_rFrame.CallCallback(SalEvent::Paint, ); } +void QtWidget::hideEvent(QHideEvent*) +{ +auto* pQtInst(static_cast(GetSalData()->m_pInstance)); +if (m_rFrame.isPopup() && pQtInst->activePopup() == _rFrame) +pQtInst->setActivePopup(nullptr); +} + void QtWidget::closeEvent(QCloseEvent* /*pEvent*/) { m_rFrame.CallCallback(SalEvent::Close, nullptr); @@ -627,11 +639,11 @@ bool QtWidget::handleEvent(QtFrame& rFrame, QWidget& rWidget, QEvent* pEvent) } else if (pEvent->type() == QEvent::ToolTip) { -// Qt's POV on focus is wrong for our fake popup windows, so check LO's state. +// Qt's POV on the active popup is wrong due to our fake popup, so check LO's state. // Otherwise Qt will continue handling ToolTip events from the "parent" window. -const vcl::Window* pFocusWin =
[Libreoffice-commits] core.git: Branch 'libreoffice-7-3' - vcl/inc vcl/qt5
vcl/inc/qt5/QtWidget.hxx |7 +++ vcl/qt5/QtWidget.cxx | 35 +++ 2 files changed, 42 insertions(+) New commits: commit 00f9671624e676f34c9039d7b0b0ebba6034f05c Author: Jan-Marek Glogowski AuthorDate: Tue Apr 19 16:03:56 2022 +0200 Commit: Michael Weghorn CommitDate: Thu Apr 21 11:31:13 2022 +0200 tdf#140463 Qt handle mouse enter+leave events Currently just implemented for the QtWidget, but still as a static function, so it may be used for QtObject at some point too. But there is no (mouse) enter or leave event function in QWindow, so no way to handle these there. And since we can't modify the returned QWidget from QWidget::createWindowContainer, the only way would be to expand the static QtWidget::handleEvent used by QtObjectWindow::event ... if it's actually needed at some point. Includes squashed commit 5d56255c22c79b72c1cedb48cfe0a200f89bdc66 ("qt6: Fix build (QtWidget::enterEvent)"). Change-Id: If9009e5dfca508acd1e702df1a17eb8ad7c29690 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133190 Tested-by: Jenkins Reviewed-by: Jan-Marek Glogowski (cherry picked from commit dc886bc6de2c0061a840bea2426663c3be2ecd26) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133149 Reviewed-by: Michael Weghorn diff --git a/vcl/inc/qt5/QtWidget.hxx b/vcl/inc/qt5/QtWidget.hxx index 878c8b1229ce..4a40589b16ba 100644 --- a/vcl/inc/qt5/QtWidget.hxx +++ b/vcl/inc/qt5/QtWidget.hxx @@ -51,6 +51,7 @@ class QtWidget : public QWidget static void commitText(QtFrame&, const QString& aText); static bool handleKeyEvent(QtFrame&, const QWidget&, QKeyEvent*, const ButtonKeyState); static void handleMouseButtonEvent(const QtFrame&, const QMouseEvent*, const ButtonKeyState); +static void handleMouseEnterLeaveEvents(const QtFrame&, QEvent*); static void fillSalAbstractMouseEvent(const QtFrame& rFrame, const QInputEvent* pQEvent, const QPoint& rPos, Qt::MouseButtons eButtons, int nWidth, SalAbstractMouseEvent& aSalEvent); @@ -75,6 +76,12 @@ class QtWidget : public QWidget virtual void wheelEvent(QWheelEvent*) override; virtual void closeEvent(QCloseEvent*) override; virtual void changeEvent(QEvent*) override; +virtual void leaveEvent(QEvent*) override; +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) +virtual void enterEvent(QEnterEvent*) override; +#else +virtual void enterEvent(QEvent*) override; +#endif void inputMethodEvent(QInputMethodEvent*) override; QVariant inputMethodQuery(Qt::InputMethodQuery) const override; diff --git a/vcl/qt5/QtWidget.cxx b/vcl/qt5/QtWidget.cxx index 017249b05434..5f07974600e8 100644 --- a/vcl/qt5/QtWidget.cxx +++ b/vcl/qt5/QtWidget.cxx @@ -208,6 +208,41 @@ void QtWidget::mouseMoveEvent(QMouseEvent* pEvent) pEvent->accept(); } +void QtWidget::handleMouseEnterLeaveEvents(const QtFrame& rFrame, QEvent* pQEvent) +{ +const qreal fRatio = rFrame.devicePixelRatioF(); +const QWidget* pWidget = rFrame.GetQWidget(); +const Point aPos = toPoint(pWidget->mapFromGlobal(QCursor::pos()) * fRatio); + +SalMouseEvent aEvent; +aEvent.mnX += QGuiApplication::isLeftToRight() ? aPos.X() : round(pWidget->width() * fRatio) - aPos.X(); +aEvent.mnY = aPos.Y(); +aEvent.mnTime = 0; +aEvent.mnButton = 0; +aEvent.mnCode = GetKeyModCode(QGuiApplication::keyboardModifiers()) +| GetMouseModCode(QGuiApplication::mouseButtons()); + +SalEvent nEventType; +if (pQEvent->type() == QEvent::Enter) +nEventType = SalEvent::MouseMove; +else +nEventType = SalEvent::MouseLeave; +rFrame.CallCallback(nEventType, ); +pQEvent->accept(); +} + +void QtWidget::leaveEvent(QEvent* pEvent) { handleMouseEnterLeaveEvents(m_rFrame, pEvent); } + +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) +void QtWidget::enterEvent(QEnterEvent* pEvent) +#else +void QtWidget::enterEvent(QEvent* pEvent) +#endif +{ +handleMouseEnterLeaveEvents(m_rFrame, pEvent); +} + void QtWidget::wheelEvent(QWheelEvent* pEvent) { SalWheelMouseEvent aEvent;
[Libreoffice-commits] core.git: Branch 'libreoffice-7-3' - vcl/inc vcl/qt5
vcl/inc/qt5/QtFrame.hxx |3 +++ vcl/inc/qt5/QtWidget.hxx |2 +- vcl/qt5/QtFrame.cxx |8 +++- vcl/qt5/QtWidget.cxx | 19 ++- 4 files changed, 29 insertions(+), 3 deletions(-) New commits: commit 7fc871299080427587307932c505d3ae93d6a357 Author: Jan-Marek Glogowski AuthorDate: Tue Apr 12 00:29:56 2022 +0200 Commit: Jan-Marek Glogowski CommitDate: Wed Apr 13 22:31:30 2022 +0200 tdf#148115 Qt handle tooltips via event loop Instead of calling QToolTip::showText directly from LO, this defers showing the tooltip to the QEvent processing, which takes the tooltip timeouts into account. So tooltips are shown with a slight delay, therefore they happen less fast on mouse move, reducing / avoiding artifacts of fast changing windows. This unfortunately comes with yet an other hack in the area of our fake popup windows... New handling is based on the code of the Qt Tool Tips example. Change-Id: I42634ad36dd12171c30f52f07a02a88d3c48a718 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/132841 Reviewed-by: Michael Weghorn Tested-by: Jenkins (cherry picked from commit af6dd54d53eee0d0de1164bff0a77c6b433b3935) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/132864 Reviewed-by: Jan-Marek Glogowski diff --git a/vcl/inc/qt5/QtFrame.hxx b/vcl/inc/qt5/QtFrame.hxx index 5ffaacf3ad94..23a4fd9887f1 100644 --- a/vcl/inc/qt5/QtFrame.hxx +++ b/vcl/inc/qt5/QtFrame.hxx @@ -111,6 +111,9 @@ class VCLPLUG_QT_PUBLIC QtFrame : public QObject, public SalFrame LanguageType m_nInputLanguage; +OUString m_aTooltipText; +QRect m_aTooltipArea; + void SetDefaultPos(); Size CalcDefaultSize(); void SetDefaultSize(); diff --git a/vcl/inc/qt5/QtWidget.hxx b/vcl/inc/qt5/QtWidget.hxx index 575cef11014f..878c8b1229ce 100644 --- a/vcl/inc/qt5/QtWidget.hxx +++ b/vcl/inc/qt5/QtWidget.hxx @@ -87,7 +87,7 @@ public: void endExtTextInput(); void fakeResize(); -static bool handleEvent(QtFrame&, const QWidget&, QEvent*); +static bool handleEvent(QtFrame&, QWidget&, QEvent*); // key events might be propagated further down => call base on false static inline bool handleKeyReleaseEvent(QtFrame&, const QWidget&, QKeyEvent*); // mouse events are always accepted diff --git a/vcl/qt5/QtFrame.cxx b/vcl/qt5/QtFrame.cxx index c78417b3070a..f6f4b6c2611d 100644 --- a/vcl/qt5/QtFrame.cxx +++ b/vcl/qt5/QtFrame.cxx @@ -175,7 +175,12 @@ QtFrame::QtFrame(QtFrame* pParent, SalFrameStyleFlags nStyle, bool bUseCairo) m_pTopLevel->setFocusProxy(m_pQWidget); } else +{ m_pQWidget = new QtWidget(*this, aWinFlags); +// from Qt's POV the popup window doesn't have the input focus, so we must force tooltips... +if (isPopup()) +m_pQWidget->setAttribute(Qt::WA_AlwaysShowToolTips); +} QWindow* pChildWindow = windowHandle(); connect(pChildWindow, ::screenChanged, this, ::screenChanged); @@ -855,7 +860,8 @@ bool QtFrame::ShowTooltip(const OUString& rText, const tools::Rectangle& rHelpAr QRect aHelpArea(toQRect(rHelpArea)); if (QGuiApplication::isRightToLeft()) aHelpArea.moveLeft(maGeometry.nWidth - aHelpArea.width() - aHelpArea.left() - 1); -QToolTip::showText(QCursor::pos(), toQString(rText), m_pQWidget, aHelpArea); +m_aTooltipText = rText; +m_aTooltipArea = aHelpArea; return true; } diff --git a/vcl/qt5/QtWidget.cxx b/vcl/qt5/QtWidget.cxx index 1fe2ce9a7159..017249b05434 100644 --- a/vcl/qt5/QtWidget.cxx +++ b/vcl/qt5/QtWidget.cxx @@ -42,6 +42,7 @@ #include #include #include +#include #include #include @@ -562,7 +563,7 @@ bool QtWidget::handleKeyEvent(QtFrame& rFrame, const QWidget& rWidget, QKeyEvent return bStopProcessingKey; } -bool QtWidget::handleEvent(QtFrame& rFrame, const QWidget& rWidget, QEvent* pEvent) +bool QtWidget::handleEvent(QtFrame& rFrame, QWidget& rWidget, QEvent* pEvent) { if (pEvent->type() == QEvent::ShortcutOverride) { @@ -589,6 +590,22 @@ bool QtWidget::handleEvent(QtFrame& rFrame, const QWidget& rWidget, QEvent* pEve ButtonKeyState::Pressed)) return true; } +else if (pEvent->type() == QEvent::ToolTip) +{ +// Qt's POV on focus is wrong for our fake popup windows, so check LO's state. +// Otherwise Qt will continue handling ToolTip events from the "parent" window. +const vcl::Window* pFocusWin = Application::GetFocusWindow(); +if (!rFrame.m_aTooltipText.isEmpty() && pFocusWin +&& pFocusWin->GetFrameWindow() == rFrame.GetWindow()) +QToolTip::showText(QCursor::pos(), toQString(rFrame.m_aTooltipText), , + rFrame.m_aTooltipArea); +else +{ +QToolTip::hideText(); +pEvent->ignore(); +} +return true; +}
[Libreoffice-commits] core.git: Branch 'libreoffice-7-3' - vcl/inc vcl/qt5
vcl/inc/qt5/QtMenu.hxx |1 - vcl/qt5/QtMenu.cxx |8 +--- 2 files changed, 5 insertions(+), 4 deletions(-) New commits: commit 664ea7545a62e1329eb1761caea25b7f31cafa7a Author: Jan-Marek Glogowski AuthorDate: Wed Apr 6 16:42:24 2022 +0200 Commit: Jan-Marek Glogowski CommitDate: Tue Apr 12 20:18:41 2022 +0200 tdf#148491 Qt reconnect the QMenuBar close button When the QMenuBar of a QMainWindow is replaced, an existing corner widget is preserved / transferred, but its connections are still severed; a bit unexpected... The documentation for QMenuBar::setCornerWidget is not really clear what is happening, but the code has this nice comment: "// Reparent corner widgets before we delete the old menu". At least there is no need to explicitly delete the button. Still we must reconnect an existing button on each SetFrame. Regression from commit 9c4ef8ce3183e27ca174475cf4a8d15cc0368f60 ("tdf#145954 Qt unshare QMenubar usage"). This includes commit 4a537cf77affc4f1f2e2e5be9ff0b1ff11724509 ("Qt drop unused QtMenu::mpCloseButton"). Change-Id: I13c31734e665b78231a08cd76ca6305122e08879 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/132836 Tested-by: Jenkins Reviewed-by: Michael Weghorn (cherry picked from commit f751417b77e6573a0c639778e76ec943449f4573) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/132894 Reviewed-by: Jan-Marek Glogowski diff --git a/vcl/inc/qt5/QtMenu.hxx b/vcl/inc/qt5/QtMenu.hxx index f39be7e8d506..11f3f00c5aa6 100644 --- a/vcl/inc/qt5/QtMenu.hxx +++ b/vcl/inc/qt5/QtMenu.hxx @@ -49,7 +49,6 @@ private: std::unique_ptr mpOwnedQMenu; // pointer to QMenu owned by the corresponding QtMenuItem or self (-> mpOwnedQMenu) QMenu* mpQMenu; -QPushButton* mpCloseButton; void DoFullMenuUpdate(Menu* pMenuBar); static void NativeItemText(OUString& rItemText); diff --git a/vcl/qt5/QtMenu.cxx b/vcl/qt5/QtMenu.cxx index 44873ce3384d..9400f5e129bf 100644 --- a/vcl/qt5/QtMenu.cxx +++ b/vcl/qt5/QtMenu.cxx @@ -40,7 +40,6 @@ QtMenu::QtMenu(bool bMenuBar) , mbMenuBar(bMenuBar) , mpQMenuBar(nullptr) , mpQMenu(nullptr) -, mpCloseButton(nullptr) { } @@ -431,7 +430,9 @@ void QtMenu::SetFrame(const SalFrame* pFrame) mpQMenuBar = new QMenuBar(); pMainWindow->setMenuBar(mpQMenuBar); -mpCloseButton = nullptr; +QPushButton* pButton = static_cast(mpQMenuBar->cornerWidget(Qt::TopRightCorner)); +if (pButton) +connect(pButton, ::clicked, this, ::slotCloseDocument); mpQMenu = nullptr; DoFullMenuUpdate(mpVCLMenu); @@ -650,6 +651,8 @@ void QtMenu::ShowCloseButton(bool bShow) return; QPushButton* pButton = static_cast(mpQMenuBar->cornerWidget(Qt::TopRightCorner)); +if (!pButton && !bShow) +return; if (!pButton) { QIcon aIcon; @@ -665,7 +668,6 @@ void QtMenu::ShowCloseButton(bool bShow) pButton->setToolTip(toQString(VclResId(SV_HELPTEXT_CLOSEDOCUMENT))); mpQMenuBar->setCornerWidget(pButton, Qt::TopRightCorner); connect(pButton, ::clicked, this, ::slotCloseDocument); -mpCloseButton = pButton; } if (bShow)
[Libreoffice-commits] core.git: Branch 'libreoffice-7-3' - vcl/inc vcl/qt5
vcl/inc/qt5/QtFrame.hxx |6 +- vcl/inc/qt5/QtWidget.hxx |1 + vcl/qt5/QtFrame.cxx | 21 ++--- vcl/qt5/QtWidget.cxx |6 ++ 4 files changed, 26 insertions(+), 8 deletions(-) New commits: commit 76de12a19bd90c0ed0d7a6a85502d3dccdbeba4e Author: Jan-Marek Glogowski AuthorDate: Thu Apr 7 01:07:43 2022 +0200 Commit: Jan-Marek Glogowski CommitDate: Fri Apr 8 19:48:56 2022 +0200 tdf#141578 Qt handle QtFrame screen changes LO doesn't provide any way to notify screen changes / scaling factors of a window and in fact doesn't really handle scaling factors in VCL. The QWidget doesn't receive a resize event, because it's size doesn't change, just the scaling factor. So we trigger a faked resize on QWindow::screenChanged signal. Change-Id: I6928c4c62d1c0995c70fea0088cff17849bcd1d4 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/132650 Reviewed-by: Michael Weghorn Tested-by: Jenkins (cherry picked from commit 881cfbf77567194f5016a961d1c3db869734d68b) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/132740 Reviewed-by: Jan-Marek Glogowski diff --git a/vcl/inc/qt5/QtFrame.hxx b/vcl/inc/qt5/QtFrame.hxx index 59ec093a2ed6..5ffaacf3ad94 100644 --- a/vcl/inc/qt5/QtFrame.hxx +++ b/vcl/inc/qt5/QtFrame.hxx @@ -25,6 +25,7 @@ #include #include "QtTools.hxx" +#include "QtWidget.hxx" #include #include @@ -70,7 +71,7 @@ class VCLPLUG_QT_PUBLIC QtFrame : public QObject, public SalFrame friend class QtWidget; -QWidget* m_pQWidget; +QtWidget* m_pQWidget; QtMainWindow* m_pTopLevel; const bool m_bUseCairo; @@ -134,6 +135,9 @@ class VCLPLUG_QT_PUBLIC QtFrame : public QObject, public SalFrame void fixICCCMwindowGroup(); +private Q_SLOTS: +void screenChanged(QScreen*); + public: QtFrame(QtFrame* pParent, SalFrameStyleFlags nSalFrameStyle, bool bUseCairo); virtual ~QtFrame() override; diff --git a/vcl/inc/qt5/QtWidget.hxx b/vcl/inc/qt5/QtWidget.hxx index e2a22d3c9f18..575cef11014f 100644 --- a/vcl/inc/qt5/QtWidget.hxx +++ b/vcl/inc/qt5/QtWidget.hxx @@ -85,6 +85,7 @@ public: QtFrame& frame() const { return m_rFrame; } void endExtTextInput(); +void fakeResize(); static bool handleEvent(QtFrame&, const QWidget&, QEvent*); // key events might be propagated further down => call base on false diff --git a/vcl/qt5/QtFrame.cxx b/vcl/qt5/QtFrame.cxx index bcd95494dabd..c78417b3070a 100644 --- a/vcl/qt5/QtFrame.cxx +++ b/vcl/qt5/QtFrame.cxx @@ -30,7 +30,6 @@ #include #include #include -#include #include #include @@ -178,10 +177,12 @@ QtFrame::QtFrame(QtFrame* pParent, SalFrameStyleFlags nStyle, bool bUseCairo) else m_pQWidget = new QtWidget(*this, aWinFlags); +QWindow* pChildWindow = windowHandle(); +connect(pChildWindow, ::screenChanged, this, ::screenChanged); + if (pParent && !(pParent->m_nStyle & SalFrameStyleFlags::PLUG)) { -QWindow* pParentWindow = pParent->GetQWidget()->window()->windowHandle(); -QWindow* pChildWindow = asChild()->window()->windowHandle(); +QWindow* pParentWindow = pParent->windowHandle(); if (pParentWindow && pChildWindow && (pParentWindow != pChildWindow)) pChildWindow->setTransientParent(pParentWindow); } @@ -193,6 +194,8 @@ QtFrame::QtFrame(QtFrame* pParent, SalFrameStyleFlags nStyle, bool bUseCairo) fixICCCMwindowGroup(); } +void QtFrame::screenChanged(QScreen*) { m_pQWidget->fakeResize(); } + void QtFrame::FillSystemEnvData(SystemEnvData& rData, sal_IntPtr pWindow, QWidget* pWidget) { if (QGuiApplication::platformName() == "wayland") @@ -343,7 +346,12 @@ bool QtFrame::PostEvent(std::unique_ptr pData) return true; } -QWidget* QtFrame::asChild() const { return m_pTopLevel ? m_pTopLevel : m_pQWidget; } +QWidget* QtFrame::asChild() const +{ +if (m_pTopLevel) +return m_pTopLevel; +return m_pQWidget; +} qreal QtFrame::devicePixelRatioF() const { return asChild()->devicePixelRatioF(); } @@ -864,9 +872,8 @@ void QtFrame::SetInputContext(SalInputContext* pContext) void QtFrame::EndExtTextInput(EndExtTextInputFlags /*nFlags*/) { -QtWidget* pQtWidget = static_cast(m_pQWidget); -if (pQtWidget) -pQtWidget->endExtTextInput(); +if (m_pQWidget) +m_pQWidget->endExtTextInput(); } OUString QtFrame::GetKeyName(sal_uInt16 nKeyCode) diff --git a/vcl/qt5/QtWidget.cxx b/vcl/qt5/QtWidget.cxx index ab8bf2dc0017..1fe2ce9a7159 100644 --- a/vcl/qt5/QtWidget.cxx +++ b/vcl/qt5/QtWidget.cxx @@ -135,6 +135,12 @@ void QtWidget::resizeEvent(QResizeEvent* pEvent) m_rFrame.CallCallback(SalEvent::Resize, nullptr); } +void QtWidget::fakeResize() +{ +QResizeEvent aEvent(size(), QSize()); +resizeEvent(); +} + void QtWidget::fillSalAbstractMouseEvent(const QtFrame& rFrame, const QInputEvent* pQEvent,
[Libreoffice-commits] core.git: Branch 'libreoffice-7-3' - vcl/inc vcl/qt5
vcl/inc/qt5/QtWidget.hxx |3 +++ vcl/qt5/QtFrame.cxx |5 +++-- vcl/qt5/QtWidget.cxx | 18 +- 3 files changed, 19 insertions(+), 7 deletions(-) New commits: commit a174fe91987160c0d57099d0aaf49dcc8e036f5b Author: Jan-Marek Glogowski AuthorDate: Wed Apr 6 18:59:10 2022 +0200 Commit: Jan-Marek Glogowski CommitDate: Fri Apr 8 08:19:42 2022 +0200 tdf#143135 Qt break recursive IM QueryCursorRect To reproduce the Impress crash, you need an IM, e.g. fcitx / ibus. This is triggered by having an active input, like double-clicking one of a presentations text fields, then leaving the window and switching back to it. This results in a stack exhaustion in a few seconds. The backtrace is basically: QWidget::setFocus QtFrame::ToTop sd::Window::GrabFocus ImplHandleExtTextInputPos QtWidget::inputMethodQuery QInputMethod::cursorRectangle QWidget::setFocus QApplication::setActiveWindow QtInstance::DoYield main I scratched my head over the longer backtrace for while, but there seems to be no good way to prevent this from LO's POV. The only alternative from the Qt VCL plugin is QtFrame::ToTop. That code is less ugly (no mutable or cached result), but QtWidget:: inputMethodQuery is earlier in the backtrace. Change-Id: Ief3a8e44bca295cc676e75050d52d70a1da98a88 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/132643 Tested-by: Jenkins Reviewed-by: Michael Weghorn Reviewed-by: Jan-Marek Glogowski (cherry picked from commit e81385277c091dabb1f6542a94229d7dcc77289b) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/132612 diff --git a/vcl/inc/qt5/QtWidget.hxx b/vcl/inc/qt5/QtWidget.hxx index 801cd290ff88..e2a22d3c9f18 100644 --- a/vcl/inc/qt5/QtWidget.hxx +++ b/vcl/inc/qt5/QtWidget.hxx @@ -19,6 +19,7 @@ #pragma once +#include #include #include @@ -36,6 +37,8 @@ class QtWidget : public QWidget QtFrame& m_rFrame; bool m_bNonEmptyIMPreeditSeen; +mutable bool m_bInInputMethodQueryCursorRectangle; +mutable QRect m_aImCursorRectangle; int m_nDeltaX; int m_nDeltaY; diff --git a/vcl/qt5/QtFrame.cxx b/vcl/qt5/QtFrame.cxx index ad9c03d0bfa1..bcd95494dabd 100644 --- a/vcl/qt5/QtFrame.cxx +++ b/vcl/qt5/QtFrame.cxx @@ -795,8 +795,9 @@ void QtFrame::ToTop(SalFrameToTop nFlags) pWidget->activateWindow(); else if ((nFlags & SalFrameToTop::GrabFocus) || (nFlags & SalFrameToTop::GrabFocusOnly)) { -pWidget->activateWindow(); -pWidget->setFocus(); +if (!(nFlags & SalFrameToTop::GrabFocusOnly)) +pWidget->activateWindow(); +pWidget->setFocus(Qt::OtherFocusReason); } } diff --git a/vcl/qt5/QtWidget.cxx b/vcl/qt5/QtWidget.cxx index 86431a3488b1..ab8bf2dc0017 100644 --- a/vcl/qt5/QtWidget.cxx +++ b/vcl/qt5/QtWidget.cxx @@ -623,6 +623,7 @@ QtWidget::QtWidget(QtFrame& rFrame, Qt::WindowFlags f) : QWidget(Q_NULLPTR, f) , m_rFrame(rFrame) , m_bNonEmptyIMPreeditSeen(false) +, m_bInInputMethodQueryCursorRectangle(false) , m_nDeltaX(0) , m_nDeltaY(0) { @@ -796,11 +797,18 @@ QVariant QtWidget::inputMethodQuery(Qt::InputMethodQuery property) const } case Qt::ImCursorRectangle: { -const qreal fRatio = m_rFrame.devicePixelRatioF(); -SalExtTextInputPosEvent aPosEvent; -m_rFrame.CallCallback(SalEvent::ExtTextInputPos, ); -return QVariant(QRect(aPosEvent.mnX / fRatio, aPosEvent.mnY / fRatio, - aPosEvent.mnWidth / fRatio, aPosEvent.mnHeight / fRatio)); +if (!m_bInInputMethodQueryCursorRectangle) +{ +m_bInInputMethodQueryCursorRectangle = true; +SalExtTextInputPosEvent aPosEvent; +m_rFrame.CallCallback(SalEvent::ExtTextInputPos, ); +const qreal fRatio = m_rFrame.devicePixelRatioF(); +m_aImCursorRectangle.setRect(aPosEvent.mnX / fRatio, aPosEvent.mnY / fRatio, + aPosEvent.mnWidth / fRatio, + aPosEvent.mnHeight / fRatio); +m_bInInputMethodQueryCursorRectangle = false; +} +return QVariant(m_aImCursorRectangle); } case Qt::ImAnchorPosition: {
[Libreoffice-commits] core.git: Branch 'libreoffice-7-3' - vcl/inc vcl/qt5
vcl/inc/qt5/QtTransferable.hxx |2 +- vcl/qt5/QtTransferable.cxx | 25 + 2 files changed, 18 insertions(+), 9 deletions(-) New commits: commit b60e4b4ba11c726cbbc45f0747d8fc4d3da0ed74 Author: Michael Weghorn AuthorDate: Wed Apr 6 13:51:59 2022 +0200 Commit: Michael Weghorn CommitDate: Thu Apr 7 07:21:58 2022 +0200 tdf#147285 qt: Prefer "text/plain;charset=utf-8" over "text/plain" If there were no data for MIME type "text/plain;charset=utf-16" in the clipboard, but "text/plain" was provided, it was previously assumed that this would be encoded in the locale's encoding, and corresponding conversion using that encoding happened to provide "text/plain;charset=utf-16" ourselves. "text/plain;charset=utf-8" data was simply ignored, but using it (if present) and preferring it over "text/plain" is more reliable (and e.g. avoids incorrect paste of Chinese characters from Firefox into Impress when using the qt5/qt6/kf5 VCL plugins on Wayland), so use it if present. Rename the "m_bConvertFromLocale" member to better fit the new meaning. (An alternative solution to adding our own handling for "text/plain;charset=utf-8" and making assumptions for the encoding of "text/plain" data would be to let Qt handle this and just call `QMimeData::text()` for the `m_bProvideUTF16FromOtherEncoding=true` case in `QtTransferable::getTransferData`. Since qtbase commit 589a01ff6b1eacf81e74a5fc4801572135214f43 ("QMimeData: Prefer UTF-8 when multiple charsets are available", contained in Qt >= 5.13), that one handles MIME type "text/plain;charset=utf-8" in addition to "text/plain".) [1] https://code.qt.io/cgit/qt/qtbase.git/commit/?id=589a01ff6b1eacf81e74a5fc4801572135214f43 Change-Id: I89f33216bf6be02a347d245b2359273af2eb530a Reviewed-on: https://gerrit.libreoffice.org/c/core/+/132631 Reviewed-by: Jan-Marek Glogowski Tested-by: Jenkins (cherry picked from commit 5b3227fac58dcbd588e2389e205679cd77842bac) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/132607 Reviewed-by: Adolfo Jayme Barrientos diff --git a/vcl/inc/qt5/QtTransferable.hxx b/vcl/inc/qt5/QtTransferable.hxx index f2997089c037..5f1533dd5968 100644 --- a/vcl/inc/qt5/QtTransferable.hxx +++ b/vcl/inc/qt5/QtTransferable.hxx @@ -35,7 +35,7 @@ class QtTransferable : public cppu::WeakImplHelper m_aMimeTypeSeq; public: diff --git a/vcl/qt5/QtTransferable.cxx b/vcl/qt5/QtTransferable.cxx index a2483b4b5f3a..1ab07dbb6224 100644 --- a/vcl/qt5/QtTransferable.cxx +++ b/vcl/qt5/QtTransferable.cxx @@ -42,7 +42,7 @@ static bool lcl_textMimeInfo(const OUString& rMimeString, bool& bHaveNoCharset, QtTransferable::QtTransferable(const QMimeData* pMimeData) : m_pMimeData(pMimeData) -, m_bConvertFromLocale(false) +, m_bProvideUTF16FromOtherEncoding(false) { assert(pMimeData); } @@ -62,7 +62,7 @@ css::uno::Sequence SAL_CALL QtTransferable::getTr QStringList aFormatList(m_pMimeData->formats()); // we might add the UTF-16 mime text variant later const int nMimeTypeSeqSize = aFormatList.size() + 1; -bool bHaveNoCharset = false, bHaveUTF16 = false; +bool bHaveNoCharset = false, bHaveUTF16 = false, bHaveUTF8 = false; css::uno::Sequence aMimeTypeSeq(nMimeTypeSeqSize); auto pMimeTypeSeq = aMimeTypeSeq.getArray(); @@ -85,6 +85,7 @@ css::uno::Sequence SAL_CALL QtTransferable::getTr { bHaveNoCharset |= bIsNoCharset; bHaveUTF16 |= bIsUTF16; +bHaveUTF8 |= bIsUTF8; if (bIsUTF16) aFlavor.DataType = cppu::UnoType::get(); else @@ -99,8 +100,8 @@ css::uno::Sequence SAL_CALL QtTransferable::getTr nMimeTypeCount++; } -m_bConvertFromLocale = bHaveNoCharset && !bHaveUTF16; -if (m_bConvertFromLocale) +m_bProvideUTF16FromOtherEncoding = (bHaveNoCharset || bHaveUTF8) && !bHaveUTF16; +if (m_bProvideUTF16FromOtherEncoding) { aFlavor.MimeType = "text/plain;charset=utf-16"; aFlavor.DataType = cppu::UnoType::get(); @@ -133,11 +134,19 @@ css::uno::Any SAL_CALL QtTransferable::getTransferData(const css::datatransfer:: if (rFlavor.MimeType == "text/plain;charset=utf-16") { OUString aString; -if (m_bConvertFromLocale) +if (m_bProvideUTF16FromOtherEncoding) { -QByteArray aByteData(m_pMimeData->data(QStringLiteral("text/plain"))); -aString = OUString(reinterpret_cast(aByteData.data()), aByteData.size(), - osl_getThreadTextEncoding()); +if (m_pMimeData->hasFormat("text/plain;charset=utf-8")) +{ +QByteArray aByteData(m_pMimeData->data(QStringLiteral("text/plain;charset=utf-8"))); +aString = OUString::fromUtf8(reinterpret_cast(aByteData.data())); +} +
[Libreoffice-commits] core.git: Branch 'libreoffice-7-3' - vcl/inc vcl/qt5
vcl/inc/qt5/QtMenu.hxx |2 +- vcl/qt5/QtMenu.cxx | 38 -- 2 files changed, 21 insertions(+), 19 deletions(-) New commits: commit 45d7a65f3d3dadcd71807a290fc11ff546aa5ba7 Author: Jan-Marek Glogowski AuthorDate: Tue Apr 5 16:49:38 2022 +0200 Commit: Jan-Marek Glogowski CommitDate: Wed Apr 6 15:16:47 2022 +0200 tdf#145954 Qt unshare QMenubar usage The Qt code was sharing the menu bar from the top level frame, but LO expects independent menu bars per SetFrame calls. So instead of showing the new bar and then hiding the old one, this was always show and hiding the same menu bar, resulting in a hidden menu bar. As a result of unsharing, LO now must check that its menu bar pointer is still valid for usage. The QMainWindows takes ownership when a QMenuBar is assigned and destroy old ones. Change-Id: I2c6b12199a1e17a5d9f88686a4b27b1413beda47 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/132581 Tested-by: Jenkins Reviewed-by: Jan-Marek Glogowski (cherry picked from commit 9c4ef8ce3183e27ca174475cf4a8d15cc0368f60) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/132604 Reviewed-by: Michael Weghorn diff --git a/vcl/inc/qt5/QtMenu.hxx b/vcl/inc/qt5/QtMenu.hxx index 55275ae6e099..f39be7e8d506 100644 --- a/vcl/inc/qt5/QtMenu.hxx +++ b/vcl/inc/qt5/QtMenu.hxx @@ -50,7 +50,6 @@ private: // pointer to QMenu owned by the corresponding QtMenuItem or self (-> mpOwnedQMenu) QMenu* mpQMenu; QPushButton* mpCloseButton; -QMetaObject::Connection maCloseButtonConnection; void DoFullMenuUpdate(Menu* pMenuBar); static void NativeItemText(OUString& rItemText); @@ -60,6 +59,7 @@ private: void ReinitializeActionGroup(unsigned nPos); void ResetAllActionGroups(); void UpdateActionGroupItem(const QtMenuItem* pSalMenuItem); +bool validateQMenuBar(); public: QtMenu(bool bMenuBar); diff --git a/vcl/qt5/QtMenu.cxx b/vcl/qt5/QtMenu.cxx index c6224b137665..44873ce3384d 100644 --- a/vcl/qt5/QtMenu.cxx +++ b/vcl/qt5/QtMenu.cxx @@ -59,7 +59,7 @@ void QtMenu::InsertMenuItem(QtMenuItem* pSalMenuItem, unsigned nPos) if (mbMenuBar) { // top-level menu -if (mpQMenuBar) +if (validateQMenuBar()) { QMenu* pQMenu = new QMenu(toQString(aText), nullptr); pSalMenuItem->mpMenu.reset(pQMenu); @@ -428,20 +428,10 @@ void QtMenu::SetFrame(const SalFrame* pFrame) if (!pMainWindow) return; -mpQMenuBar = pMainWindow->menuBar(); -if (mpQMenuBar) -{ -mpQMenuBar->clear(); -QPushButton* pButton -= static_cast(mpQMenuBar->cornerWidget(Qt::TopRightCorner)); -if (pButton && ((mpCloseButton != pButton) || !maCloseButtonConnection)) -{ -maCloseButtonConnection -= connect(pButton, ::clicked, this, ::slotCloseDocument); -mpCloseButton = pButton; -} -} +mpQMenuBar = new QMenuBar(); +pMainWindow->setMenuBar(mpQMenuBar); +mpCloseButton = nullptr; mpQMenu = nullptr; DoFullMenuUpdate(mpVCLMenu); @@ -565,9 +555,22 @@ QtMenu* QtMenu::GetTopLevel() return pMenu; } +bool QtMenu::validateQMenuBar() +{ +if (!mpQMenuBar) +return false; +assert(mpFrame); +QtMainWindow* pMainWindow = mpFrame->GetTopLevelWindow(); +assert(pMainWindow); +const bool bValid = mpQMenuBar == pMainWindow->menuBar(); +if (!bValid) +mpQMenuBar = nullptr; +return bValid; +} + void QtMenu::ShowMenuBar(bool bVisible) { -if (mpQMenuBar) +if (validateQMenuBar()) mpQMenuBar->setVisible(bVisible); } @@ -643,7 +646,7 @@ void QtMenu::slotCloseDocument() void QtMenu::ShowCloseButton(bool bShow) { -if (!mpQMenuBar) +if (!validateQMenuBar()) return; QPushButton* pButton = static_cast(mpQMenuBar->cornerWidget(Qt::TopRightCorner)); @@ -661,8 +664,7 @@ void QtMenu::ShowCloseButton(bool bShow) pButton->setFocusPolicy(Qt::NoFocus); pButton->setToolTip(toQString(VclResId(SV_HELPTEXT_CLOSEDOCUMENT))); mpQMenuBar->setCornerWidget(pButton, Qt::TopRightCorner); -maCloseButtonConnection -= connect(pButton, ::clicked, this, ::slotCloseDocument); +connect(pButton, ::clicked, this, ::slotCloseDocument); mpCloseButton = pButton; }
[Libreoffice-commits] core.git: Branch 'libreoffice-7-3' - vcl/inc vcl/qt5
vcl/inc/qt5/QtFrame.hxx |1 vcl/qt5/QtFrame.cxx | 73 +++- vcl/qt5/QtWidget.cxx|8 + 3 files changed, 15 insertions(+), 67 deletions(-) New commits: commit c309ddb6d9cd61f3024ffeee33fce1a0e173d9cc Author: Jan-Marek Glogowski AuthorDate: Mon Apr 4 18:02:28 2022 +0200 Commit: Michael Weghorn CommitDate: Wed Apr 6 14:49:52 2022 +0200 tdf#144585 Qt fix Wayland LO fake popups So Michael Weghorn was somehow reminded of an abandoned commit from me ("Qt5 rework parent handling") archived in https://gerrit.libreoffice.org/c/core/+/73463. The bug introducing the new QWidget parenting, tdf#145363, was resolved in a better way by explicitly setting parents for the modal dialogs, so LO doesn't break Qt anymore. The actual problem is, that an additional modal dialog needs to be stacked to the previous modal dialog; no "parallel" modal dialogs are allowed, which my original fix tried to enforce by reparenting. Then there is the problem with Qt::Popup's focus grabbing on show, which breaks LO's editable ComboBox. So LO's popup / FLOAT windows are mapped to Qt::ToolTip, which are automatically advertised as tooltips via accessibility. For X11 / xcb, Qt:Window with the Qt::BypassWindowManagerHint works well enough as an alternative, but WASM and Wayland don't seem to implement it correctly, so this just handles popups as Qt::ToolTip on all platforms. This reverts commit b00a68a8e19370e106cd76258a3c1825f43613ee ("tdf#145363 Qt reparent modal dialogs on show"). In addition the popup widgets are switched back to Qt::ToolTip. Change-Id: If726771b4e9cc3f639f21cf502b3ec5985873643 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/132526 Reviewed-by: Jan-Marek Glogowski Reviewed-by: Michael Weghorn Tested-by: Jenkins (cherry picked from commit fbf739198aa7f02975d531521c6525073783c7f1) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/132625 diff --git a/vcl/inc/qt5/QtFrame.hxx b/vcl/inc/qt5/QtFrame.hxx index dbf54079313d..59ec093a2ed6 100644 --- a/vcl/inc/qt5/QtFrame.hxx +++ b/vcl/inc/qt5/QtFrame.hxx @@ -133,7 +133,6 @@ class VCLPLUG_QT_PUBLIC QtFrame : public QObject, public SalFrame int menuBarOffset() const; void fixICCCMwindowGroup(); -void modalReparent(bool bVisible); public: QtFrame(QtFrame* pParent, SalFrameStyleFlags nSalFrameStyle, bool bUseCairo); diff --git a/vcl/qt5/QtFrame.cxx b/vcl/qt5/QtFrame.cxx index 10b7e46909c5..ad9c03d0bfa1 100644 --- a/vcl/qt5/QtFrame.cxx +++ b/vcl/qt5/QtFrame.cxx @@ -149,11 +149,14 @@ QtFrame::QtFrame(QtFrame* pParent, SalFrameStyleFlags nStyle, bool bUseCairo) aWinFlags = Qt::Tool | Qt::FramelessWindowHint; else if (nStyle & SalFrameStyleFlags::TOOLTIP) aWinFlags = Qt::ToolTip; -// Can't use Qt::Popup, because it grabs the input focus and generates -// a focus-out event, reaching the combo box. This used to map to -// Qt::ToolTip, which doesn't feel that correct... +// Can't use Qt::Popup, because it grabs the input focus and generates a focus-out event, +// instantly auto-closing the LO's editable ComboBox popup. +// On X11, the alternative Qt::Window | Qt::FramelessWindowHint | Qt::BypassWindowManagerHint +// seems to work well enough, but at least on Wayland and WASM, this results in problems. +// So while using Qt::ToolTip, the popups are wrongly advertised via accessibility, at least +// the GUI seems to work on all platforms... what a mess. else if (isPopup()) -aWinFlags = Qt::Window | Qt::FramelessWindowHint | Qt::BypassWindowManagerHint; +aWinFlags = Qt::ToolTip | Qt::FramelessWindowHint; else if (nStyle & SalFrameStyleFlags::TOOLWINDOW) aWinFlags = Qt::Tool; // top level windows can't be transient in Qt, so make them dialogs, if they have a parent. At least @@ -168,7 +171,7 @@ QtFrame::QtFrame(QtFrame* pParent, SalFrameStyleFlags nStyle, bool bUseCairo) if (aWinFlags == Qt::Window) { m_pTopLevel = new QtMainWindow(*this, aWinFlags); -m_pQWidget = new QtWidget(*this, aWinFlags); +m_pQWidget = new QtWidget(*this); m_pTopLevel->setCentralWidget(m_pQWidget); m_pTopLevel->setFocusProxy(m_pQWidget); } @@ -417,38 +420,6 @@ void QtFrame::DrawMenuBar() { /* not needed */} void QtFrame::SetExtendedFrameStyle(SalExtStyle /*nExtStyle*/) { /* not needed */} -void QtFrame::modalReparent(bool bVisible) -{ -#ifndef NDEBUG -auto* pSalInst(static_cast(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() :
[Libreoffice-commits] core.git: Branch 'libreoffice-7-3' - vcl/inc vcl/qt5
vcl/inc/qt5/QtInstance.hxx |8 vcl/qt5/QtInstance.cxx | 36 2 files changed, 44 insertions(+) New commits: commit e49d774fd2bb5ddf35a47368f36980d5e0d32ad3 Author: Jan-Marek Glogowski AuthorDate: Sun Jan 16 10:14:47 2022 +0100 Commit: Caolán McNamara CommitDate: Sun Jan 16 18:22:44 2022 +0100 Qt notify LO of many QScreen related events LO just has a single display event, SalEvent::DisplayChanged, Qt has a multitude. So this will generate multiple LO notifications. I don't see any reasonable way to prevent that. Doesn't seem a problem here. Change-Id: I2f11e53765869a4ca292a1d337347e4e7470e3c2 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/128474 Tested-by: Jenkins Reviewed-by: Jan-Marek Glogowski (cherry picked from commit ced4cde59eb51e4364daf69520a184b55c2c54db) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/128434 Tested-by: Caolán McNamara Reviewed-by: Caolán McNamara diff --git a/vcl/inc/qt5/QtInstance.hxx b/vcl/inc/qt5/QtInstance.hxx index 009b9ae8c312..9a9853a7a2ce 100644 --- a/vcl/inc/qt5/QtInstance.hxx +++ b/vcl/inc/qt5/QtInstance.hxx @@ -75,6 +75,12 @@ private Q_SLOTS: static void deleteObjectLater(QObject* pObject); static void localeChanged(); +void orientationChanged(Qt::ScreenOrientation); +void primaryScreenChanged(QScreen*); +void screenAdded(QScreen*); +void screenRemoved(QScreen*); +void virtualGeometryChanged(const QRect&); + Q_SIGNALS: bool ImplYieldSignal(bool bWait, bool bHandleAllCurrentEvents); void deleteObjectLaterSignal(QObject* pObject); @@ -86,6 +92,8 @@ protected: bool useCairo() const { return m_bUseCairo; } // encodes cairo usage and Qt platform name into the ToolkitName OUString constructToolkitID(std::u16string_view sTKname); +void connectQScreenSignals(const QScreen*); +void notifyDisplayChanged(); public: explicit QtInstance(std::unique_ptr& pQApp, bool bUseCairo = false); diff --git a/vcl/qt5/QtInstance.cxx b/vcl/qt5/QtInstance.cxx index 29a7d0e4ddf7..d252109e122a 100644 --- a/vcl/qt5/QtInstance.cxx +++ b/vcl/qt5/QtInstance.cxx @@ -40,6 +40,7 @@ #include #include +#include #include #include @@ -248,6 +249,12 @@ QtInstance::QtInstance(std::unique_ptr& pQApp, bool bUseCairo) connect(QGuiApplication::inputMethod(), ::localeChanged, this, ::localeChanged); +for (const QScreen* pCurScreen : QApplication::screens()) +connectQScreenSignals(pCurScreen); +connect(qApp, ::primaryScreenChanged, this, ::primaryScreenChanged); +connect(qApp, ::screenAdded, this, ::screenAdded); +connect(qApp, ::screenRemoved, this, ::screenRemoved); + #ifndef EMSCRIPTEN m_bSupportsOpenGL = true; #endif @@ -602,6 +609,35 @@ void* QtInstance::CreateGStreamerSink(const SystemChildWindow* pWindow) #endif } +void QtInstance::connectQScreenSignals(const QScreen* pScreen) +{ +connect(pScreen, ::orientationChanged, this, ::orientationChanged); +connect(pScreen, ::virtualGeometryChanged, this, ::virtualGeometryChanged); +} + +void QtInstance::notifyDisplayChanged() +{ +SolarMutexGuard aGuard; +SalFrame* pAnyFrame = anyFrame(); +if (pAnyFrame) +pAnyFrame->CallCallback(SalEvent::DisplayChanged, nullptr); +} + +void QtInstance::orientationChanged(Qt::ScreenOrientation) { notifyDisplayChanged(); } + +void QtInstance::primaryScreenChanged(QScreen*) { notifyDisplayChanged(); } + +void QtInstance::screenAdded(QScreen* pScreen) +{ +connectQScreenSignals(pScreen); +if (QApplication::screens().size() == 1) +notifyDisplayChanged(); +} + +void QtInstance::screenRemoved(QScreen*) { notifyDisplayChanged(); } + +void QtInstance::virtualGeometryChanged(const QRect&) { notifyDisplayChanged(); } + void QtInstance::AllocFakeCmdlineArgs(std::unique_ptr& rFakeArgv, std::unique_ptr& rFakeArgc, std::vector& rFakeArgvFreeable)
[Libreoffice-commits] core.git: Branch 'libreoffice-7-3' - vcl/inc vcl/qt5
vcl/inc/qt5/QtFrame.hxx |1 + vcl/qt5/QtFrame.cxx | 20 ++-- 2 files changed, 15 insertions(+), 6 deletions(-) New commits: commit 4d30c63bd0652c75cda9c57ef21c4cfe65df184f Author: Jan-Marek Glogowski AuthorDate: Mon Dec 20 13:32:52 2021 +0100 Commit: Adolfo Jayme Barrientos CommitDate: Wed Dec 22 05:01:00 2021 +0100 tdf#131467 Qt set default position on first resize Setting the position in Show() is too late, because LO will try to set the mouse pointer to the default button, if configured. That obviously needs the window position. And also take the menubar offset into account. Change-Id: Ia280539c082ff6f675966869fb6643a41a17d696 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/127154 Tested-by: Jenkins Reviewed-by: Jan-Marek Glogowski (cherry picked from commit ca28826a087245686d7fca3ffc8ca1f03307924d) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/127185 Reviewed-by: Adolfo Jayme Barrientos diff --git a/vcl/inc/qt5/QtFrame.hxx b/vcl/inc/qt5/QtFrame.hxx index c3c9cdb9f309..dbf54079313d 100644 --- a/vcl/inc/qt5/QtFrame.hxx +++ b/vcl/inc/qt5/QtFrame.hxx @@ -130,6 +130,7 @@ 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(); void modalReparent(bool bVisible); diff --git a/vcl/qt5/QtFrame.cxx b/vcl/qt5/QtFrame.cxx index 5772e7e87251..7b24103908e9 100644 --- a/vcl/qt5/QtFrame.cxx +++ b/vcl/qt5/QtFrame.cxx @@ -470,7 +470,6 @@ void QtFrame::Show(bool bVisible, bool bNoActivate) // show SetDefaultSize(); -SetDefaultPos(); pSalInst->RunInMainThread([this, bNoActivate]() { QWidget* const pChild = asChild(); @@ -504,6 +503,14 @@ 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) @@ -516,6 +523,7 @@ void QtFrame::SetDefaultPos() 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); } @@ -604,7 +612,11 @@ void QtFrame::SetPosSize(tools::Long nX, tools::Long nY, tools::Long nWidth, too } if (!(nFlags & (SAL_FRAME_POSSIZE_X | SAL_FRAME_POSSIZE_Y))) +{ +if (nFlags & (SAL_FRAME_POSSIZE_WIDTH | SAL_FRAME_POSSIZE_HEIGHT)) +SetDefaultPos(); return; +} if (m_pParent) { @@ -613,11 +625,7 @@ void QtFrame::SetPosSize(tools::Long nX, tools::Long nY, tools::Long nWidth, too nX = aParentGeometry.nX + aParentGeometry.nWidth - nX - maGeometry.nWidth - 1; else nX += aParentGeometry.nX; -nY += aParentGeometry.nY; - -QtMainWindow* pTopLevel = m_pParent->GetTopLevelWindow(); -if (pTopLevel && pTopLevel->menuBar() && pTopLevel->menuBar()->isVisible()) -nY += round(pTopLevel->menuBar()->geometry().height() * devicePixelRatioF()); +nY += aParentGeometry.nY + menuBarOffset(); } if (!(nFlags & SAL_FRAME_POSSIZE_X))