[Libreoffice-commits] core.git: vcl/qt5

Jan-Marek Glogowski (via logerrit) logerrit at kemper.freedesktop.org
Wed Jun 5 11:23:22 UTC 2019


 vcl/qt5/Qt5Frame.cxx |   25 ++++++++++++++++---------
 1 file changed, 16 insertions(+), 9 deletions(-)

New commits:
commit e770bacc85a0eec96de77068d61b03f374b3cdec
Author:     Jan-Marek Glogowski <glogow at fbihome.de>
AuthorDate: Sun Jun 2 21:01:33 2019 +0000
Commit:     Jan-Marek Glogowski <glogow at fbihome.de>
CommitDate: Wed Jun 5 13:22:26 2019 +0200

    Qt5 workaround modal change after show bug
    
    The presentation minimizer dialog calls setVisible before execute.
    This results in the dialog being shown before setting the modality
    in execute. And this triggers a bug in the Qt / Xcb stack (gtk is
    fine because it directly uses XSendEvent to change the state).
    
    The result is an unmapped, modal dialog window: it's invisible and
    blocks the GUI. Qt believes it's show; isVisible() returns true.
    
    And my ~/.xsession-errors shows a "qt.qpa.xcb: QXcbConnection: XCB
    error: 3 (BadWindow) ... major code: 18 (ChangeProperty)" with an
    invalid resource id, according to 'xwininfo -tree -root'.
    You can find the window resource of the minimizer by its name in
    the full root tree and its unmapped state with 'xwininfo -id'.
    
    I originally thought of a Scheduler bug so enabled debug output
    for it. This is already responsible for a delay long enough to
    prevent the bug often. Same for doing an additional hide() and
    show() sequence. In the end I went with a fixed delay, but that
    is just a guess. In theory we could check the mapped state via
    Xlib in Qt's show event and manually map it using XMapWindow and
    the winId...
    
    I also noted that the minimizer leaks, as there are multiple new
    presenter resources after each show and hide...
    
    Change-Id: I2060918aa9c63d385ebb2ffee9e7a3e4196ea766
    Reviewed-on: https://gerrit.libreoffice.org/73462
    Tested-by: Jenkins
    Reviewed-by: Michael Weghorn <m.weghorn at posteo.de>
    Reviewed-by: Jan-Marek Glogowski <glogow at fbihome.de>

diff --git a/vcl/qt5/Qt5Frame.cxx b/vcl/qt5/Qt5Frame.cxx
index a9ffbf7756aa..ed8af3f1542d 100644
--- a/vcl/qt5/Qt5Frame.cxx
+++ b/vcl/qt5/Qt5Frame.cxx
@@ -34,6 +34,7 @@
 #include <QtCore/QMimeData>
 #include <QtCore/QPoint>
 #include <QtCore/QSize>
+#include <QtCore/QThread>
 #include <QtGui/QIcon>
 #include <QtGui/QWindow>
 #include <QtGui/QScreen>
@@ -507,21 +508,27 @@ void Qt5Frame::SetModal(bool bModal)
         auto* pSalInst(static_cast<Qt5Instance*>(GetSalData()->m_pInstance));
         assert(pSalInst);
         pSalInst->RunInMainThread([this, bModal]() {
-            bool wasVisible = windowHandle()->isVisible();
+
+            QWidget* const pChild = asChild();
+            const bool bWasVisible = pChild->isVisible();
 
             // modality change is only effective if the window is hidden
-            if (wasVisible)
+            if (bWasVisible)
             {
-                windowHandle()->hide();
+                pChild->hide();
+                if (QGuiApplication::platformName() == "xcb")
+                {
+                    SAL_WARN("vcl.qt5", "SetModal called after Show - apply delay");
+                    // give QXcbConnection some time to recover from unmap
+                    // ~/.xsession-errors => (BadWindow) (ChangeProperty)
+                    QThread::msleep(250);
+                }
             }
 
-            windowHandle()->setModality(bModal ? Qt::WindowModal : Qt::NonModal);
+            pChild->setWindowModality(bModal ? Qt::WindowModal : Qt::NonModal);
 
-            // and shown again if it was visible
-            if (wasVisible)
-            {
-                windowHandle()->show();
-            }
+            if (bWasVisible)
+                pChild->show();
         });
     }
 }


More information about the Libreoffice-commits mailing list