[Libreoffice-commits] core.git: Branch 'libreoffice-6-2' - 3 commits - vcl/inc vcl/qt5 vcl/unx

Michael Stahl (via logerrit) logerrit at kemper.freedesktop.org
Wed May 22 11:45:09 UTC 2019


 vcl/inc/qt5/Qt5Instance.hxx      |    7 +
 vcl/qt5/Qt5FilePicker.cxx        |   12 ++
 vcl/qt5/Qt5Frame.cxx             |   28 +++---
 vcl/qt5/Qt5Instance.cxx          |  175 ++++++++++++++++++++++++++++++++++++---
 vcl/unx/kde5/KDE5SalInstance.cxx |   23 ++---
 vcl/unx/kde5/KDE5SalInstance.hxx |    8 -
 6 files changed, 208 insertions(+), 45 deletions(-)

New commits:
commit 5be0bd7ca8d8ed890f3a95680a8c7710c473dcdf
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Mon Feb 25 16:56:59 2019 +0100
Commit:     Thorsten Behrens <Thorsten.Behrens at CIB.de>
CommitDate: Wed May 22 13:44:47 2019 +0200

    tdf#119856 vcl: fix Qt warning Qt5Frame::SetModal()
    
    This prints a warning "Cannot create children for a parent that is in a
    different thread"; let's fix it before it causes another hard to debug
    crash.
    
    0  check_parent_thread(QObject*, QThreadData*, QThreadData*) (parent=parent at entry=0xe88ca0, parentThreadData=<optimized out>, currentThreadData=<optimized out>) at kernel/qobject.cpp:781
    1  check_parent_thread (currentThreadData=<optimized out>, parentThreadData=<optimized out>, parent=0xe88ca0) at kernel/qobject.cpp:822
    2  QObject::QObject(QObject*) (this=0x9ed2e80, parent=0xe88ca0) at kernel/qobject.cpp:810
    3  Adwaita::GenericData::GenericData(QObject*, QWidget*, int) () at /usr/lib64/qt5/plugins/styles/adwaita.so
    4  Adwaita::WidgetStateEngine::registerWidget(QWidget*, QFlags<Adwaita::AnimationMode>) () at /usr/lib64/qt5/plugins/styles/adwaita.so
    5  Adwaita::Animations::registerWidget(QWidget*) const () at /usr/lib64/qt5/plugins/styles/adwaita.so
    6  Adwaita::Style::polish(QWidget*) () at /usr/lib64/qt5/plugins/styles/adwaita.so
    7  QWidget::event(QEvent*) () at /lib64/libQt5Widgets.so.5
    8  Qt5Widget::event(QEvent*) (this=0x7321790, pEvent=0x7f90c27d3750) at vcl/qt5/Qt5Widget.cxx:416
    9  QApplicationPrivate::notify_helper(QObject*, QEvent*) () at /lib64/libQt5Widgets.so.5
    10 QApplication::notify(QObject*, QEvent*) () at /lib64/libQt5Widgets.so.5
    11 QCoreApplication::notifyInternal2(QObject*, QEvent*) (receiver=0x7321790, event=0x7f90c27d3750) at kernel/qcoreapplication.cpp:1047
    12 QWidget::ensurePolished() const () at /lib64/libQt5Widgets.so.5
    13 QWidget::setVisible(bool) () at /lib64/libQt5Widgets.so.5
    14 Qt5Frame::SetModal(bool) (this=0x9f411b0, bModal=true) at vcl/qt5/Qt5Frame.cxx:482
    
    Change-Id: Ib6b4d1ee859dfce650422a6c7860abf2eb2686f1
    Reviewed-on: https://gerrit.libreoffice.org/68356
    Tested-by: Jenkins
    Reviewed-by: Katarina Behrens <Katarina.Behrens at cib.de>
    (cherry picked from commit 69c46bf53363127033a83c019375170550308ae2)
    Reviewed-on: https://gerrit.libreoffice.org/72659
    Reviewed-by: Thorsten Behrens <Thorsten.Behrens at CIB.de>

diff --git a/vcl/qt5/Qt5Frame.cxx b/vcl/qt5/Qt5Frame.cxx
index 62d3808ba572..2c7dce84cd07 100644
--- a/vcl/qt5/Qt5Frame.cxx
+++ b/vcl/qt5/Qt5Frame.cxx
@@ -496,21 +496,25 @@ void Qt5Frame::SetModal(bool bModal)
 {
     if (isWindow())
     {
-        bool wasVisible = windowHandle()->isVisible();
+        auto* pSalInst(static_cast<Qt5Instance*>(GetSalData()->m_pInstance));
+        assert(pSalInst);
+        pSalInst->RunInMainThread([this, bModal]() {
+            bool wasVisible = windowHandle()->isVisible();
 
-        // modality change is only effective if the window is hidden
-        if (wasVisible)
-        {
-            windowHandle()->hide();
-        }
+            // modality change is only effective if the window is hidden
+            if (wasVisible)
+            {
+                windowHandle()->hide();
+            }
 
-        windowHandle()->setModality(bModal ? Qt::WindowModal : Qt::NonModal);
+            windowHandle()->setModality(bModal ? Qt::WindowModal : Qt::NonModal);
 
-        // and shown again if it was visible
-        if (wasVisible)
-        {
-            windowHandle()->show();
-        }
+            // and shown again if it was visible
+            if (wasVisible)
+            {
+                windowHandle()->show();
+            }
+        });
     }
 }
 
commit c6f2f4e86c60fcd23a4ee513ce63404d65806981
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Mon Feb 25 16:38:36 2019 +0100
Commit:     Thorsten Behrens <Thorsten.Behrens at CIB.de>
CommitDate: Wed May 22 13:44:41 2019 +0200

    tdf#119856 vcl: fix Qt5FilePicker destructor to run in main thread
    
    During QFileDialog dtor, QSocketNotifier::setEnabled(false) is called,
    but it doesn't do anything other than print a stupid warning and so it's
    still registered and later it receives events after it's dead.
    
    0   QSocketNotifier::setEnabled(bool) (this=this at entry=0x991c058, enable=enable at entry=false) at kernel/qsocketnotifier.cpp:240
    1   QInotifyFileSystemWatcherEngine::~QInotifyFileSystemWatcherEngine() (this=0x991c030, __in_chrg=<optimized out>) at io/qfilesystemwatcher_inotify.cpp:260
    2   QInotifyFileSystemWatcherEngine::~QInotifyFileSystemWatcherEngine() (this=0x991c030, __in_chrg=<optimized out>) at io/qfilesystemwatcher_inotify.cpp:258
    3   QObjectPrivate::deleteChildren() (this=this at entry=0x991c240) at kernel/qobject.cpp:1997
    4   QObject::~QObject() (this=<optimized out>, __in_chrg=<optimized out>) at kernel/qobject.cpp:1025
    5   QFileSystemWatcher::~QFileSystemWatcher() (this=0x9641b60, __in_chrg=<optimized out>) at io/qfilesystemwatcher.cpp:277
    6   QObjectPrivate::deleteChildren() (this=this at entry=0x2a30130) at kernel/qobject.cpp:1997
    7   QObject::~QObject() (this=<optimized out>, __in_chrg=<optimized out>) at kernel/qobject.cpp:1025
    8   QThread::~QThread() (this=0x2a079b8, __in_chrg=<optimized out>) at thread/qmutex.h:217
    9    () at /lib64/libQt5Widgets.so.5
    10  QScopedPointerDeleter<QObjectData>::cleanup(QObjectData*) (pointer=<optimized out>) at ../../include/QtCore/../../src/corelib/tools/qscopedpointer.h:52
    11  QScopedPointer<QObjectData, QScopedPointerDeleter<QObjectData> >::~QScopedPointer() (this=0x98aa4d8, __in_chrg=<optimized out>) at ../../include/QtCore/../../src/corelib/tools/qscopedpointer.h:107
    12  QObject::~QObject() (this=<optimized out>, __in_chrg=<optimized out>) at kernel/qobject.cpp:884
    13  QFileSystemModel::~QFileSystemModel() () at /lib64/libQt5Widgets.so.5
    14  QObjectPrivate::deleteChildren() (this=0x97bab00) at kernel/qobject.cpp:1997
    15  QWidget::~QWidget() () at /lib64/libQt5Widgets.so.5
    16  QFileDialog::~QFileDialog() () at /lib64/libQt5Widgets.so.5
    17  std::default_delete<QFileDialog>::operator()(QFileDialog*) const (this=0x9770f90, __ptr=0x926e970) at /usr/include/c++/8/bits/unique_ptr.h:81
    18  std::unique_ptr<QFileDialog, std::default_delete<QFileDialog> >::~unique_ptr() (this=0x9770f90, __in_chrg=<optimized out>) at /usr/include/c++/8/bits/unique_ptr.h:274
    19  Qt5FilePicker::~Qt5FilePicker() (this=0x9770ed0, __in_chrg=<optimized out>) at vcl/qt5/Qt5FilePicker.cxx:155
    
    Change-Id: Iddfa3d44de59e1760e20a389566d9e6815ab26f7
    Reviewed-on: https://gerrit.libreoffice.org/68355
    Tested-by: Jenkins
    Reviewed-by: Katarina Behrens <Katarina.Behrens at cib.de>
    (cherry picked from commit 621bebd8640feeb5f8e15fafac1425cb18bd28e4)
    Reviewed-on: https://gerrit.libreoffice.org/72658
    Reviewed-by: Thorsten Behrens <Thorsten.Behrens at CIB.de>

diff --git a/vcl/qt5/Qt5FilePicker.cxx b/vcl/qt5/Qt5FilePicker.cxx
index 9df730351bca..282723ff12fb 100644
--- a/vcl/qt5/Qt5FilePicker.cxx
+++ b/vcl/qt5/Qt5FilePicker.cxx
@@ -23,6 +23,7 @@
 #include <Qt5Frame.hxx>
 #include <Qt5Tools.hxx>
 #include <Qt5Widget.hxx>
+#include <Qt5Instance.hxx>
 
 #include <com/sun/star/lang/DisposedException.hpp>
 #include <com/sun/star/lang/IllegalArgumentException.hpp>
@@ -167,7 +168,16 @@ Qt5FilePicker::Qt5FilePicker(QFileDialog::FileMode eMode, bool bShowFileExtensio
             SLOT(updateAutomaticFileExtension()));
 }
 
-Qt5FilePicker::~Qt5FilePicker() {}
+Qt5FilePicker::~Qt5FilePicker()
+{
+    auto* pSalInst(static_cast<Qt5Instance*>(GetSalData()->m_pInstance));
+    assert(pSalInst);
+    pSalInst->RunInMainThread([this]() {
+        // must delete it in main thread, otherwise
+        // QSocketNotifier::setEnabled() will crash us
+        m_pFileDialog.reset();
+    });
+}
 
 void SAL_CALL
 Qt5FilePicker::addFilePickerListener(const uno::Reference<XFilePickerListener>& xListener)
commit 5ad697fd5912cabf6fe645e15c85a86ceca3a158
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Fri Feb 22 19:19:27 2019 +0100
Commit:     Thorsten Behrens <Thorsten.Behrens at CIB.de>
CommitDate: Wed May 22 13:44:32 2019 +0200

    tdf#119856 vcl: Qt5/KDE5 RunInMainThread
    
    The problem with the current approach of transferring calls to the main
    thread with Q_EMIT signals is that if the code that should run in the
    main thread needs SolarMutex, then the non-main-thread must use
    SolarMutexReleaser - but then the main thread will run not only the call
    that is needed right now, but will potentially process all pending
    events, and the other thread hasn't prepared for that.
    
    We need the inter-thread feature of Qt::BlockingQueuedConnection and the
    non-queued feature of Qt::DirectConnection, but this combination doesn't
    appear to exist.
    
    So the SolarMutexReleaser needs to go - but then the main thread does
    need SolarMutex for some things, and hence we need to trick it into
    believing it has SolarMutex with the m_bNoYieldLock hack.
    
    Then it becomes apparent that the main thread may be blocked on either
    Qt events, which is fine, or on the SalYieldMutex's m_aMutex, which will
    never be released now.
    
    So the main thread must never block on m_aMutex; the alternative is to
    use the same approach as the osx code (and, in a somewhat different
    form, the svp code), and add some condition variables on which the main
    thread can block if it fails to acquire the m_aMutex immediately.
    
    It's even possible to do this in a somewhat generic way with lambdas.
    
    This does appear to work, but it makes the Q_EMIT approach entirely
    untenable, because now the main thread will be blocked on the condition
    variable and the non-main-thread will be blocked until the Qt event is
    processed.
    
    Reviewed-on: https://gerrit.libreoffice.org/68232
    Tested-by: Jenkins
    Reviewed-by: Katarina Behrens <Katarina.Behrens at cib.de>
    (cherry picked from commit 265caa4381c048c346c907b017561ab0fe0367ff)
    
    Change-Id: I6480a6b909d5ec8814b2ff10dbefb0f3686a83c7
    Reviewed-on: https://gerrit.libreoffice.org/72657
    Tested-by: Jenkins
    Reviewed-by: Thorsten Behrens <Thorsten.Behrens at CIB.de>

diff --git a/vcl/inc/qt5/Qt5Instance.hxx b/vcl/inc/qt5/Qt5Instance.hxx
index cece484b0316..fc40d89e6075 100644
--- a/vcl/inc/qt5/Qt5Instance.hxx
+++ b/vcl/inc/qt5/Qt5Instance.hxx
@@ -27,6 +27,8 @@
 
 #include <QtCore/QObject>
 
+#include <functional>
+
 class QApplication;
 class SalYieldMutex;
 class SalFrame;
@@ -51,16 +53,19 @@ public:
 private Q_SLOTS:
     bool ImplYield(bool bWait, bool bHandleAllCurrentEvents);
     static void deleteObjectLater(QObject* pObject);
+    void ImplRunInMain();
 
 Q_SIGNALS:
     bool ImplYieldSignal(bool bWait, bool bHandleAllCurrentEvents);
-    std::unique_ptr<SalMenu> createMenuSignal(bool, Menu*);
+    void ImplRunInMainSignal();
     void deleteObjectLaterSignal(QObject* pObject);
 
 public:
     explicit Qt5Instance(bool bUseCairo = false);
     virtual ~Qt5Instance() override;
 
+    void RunInMainThread(std::function<void()> func);
+
     virtual SalFrame* CreateFrame(SalFrame* pParent, SalFrameStyleFlags nStyle) override;
     virtual SalFrame* CreateChildFrame(SystemParentData* pParent,
                                        SalFrameStyleFlags nStyle) override;
diff --git a/vcl/qt5/Qt5Instance.cxx b/vcl/qt5/Qt5Instance.cxx
index 58f93fea73c6..c383f8600108 100644
--- a/vcl/qt5/Qt5Instance.cxx
+++ b/vcl/qt5/Qt5Instance.cxx
@@ -43,13 +43,165 @@
 #include <QtWidgets/QWidget>
 
 #include <vclpluginapi.h>
+#include <tools/debug.hxx>
+#include <comphelper/flagguard.hxx>
 #include <sal/log.hxx>
 #include <osl/process.h>
 
 #include <headless/svpbmp.hxx>
 
+#include <mutex>
+#include <condition_variable>
+
+/// TODO: not much Qt5 specific here? could be generalised, esp. for OSX...
+/// this subclass allows for the transfer of a closure for running on the main
+/// thread, to handle all the thread affine stuff in Qt5; the SolarMutex is
+/// "loaned" to the main thread for the execution of the closure.
+/// @note it doesn't work to just use "emit" and signals/slots to move calls to
+/// the main thread, because the other thread has the SolarMutex; the other
+/// thread (typically) cannot release SolarMutex, because then the main thread
+/// will handle all sorts of events and whatnot; this design ensures that the
+/// main thread only runs the passed closure (unless the closure releases
+/// SolarMutex itself, which should probably be avoided).
+class Qt5YieldMutex : public SalYieldMutex
+{
+public:
+    /// flag only accessed on main thread:
+    /// main thread has "borrowed" SolarMutex from another thread
+    bool m_bNoYieldLock = false;
+    /// members for communication from non-main thread to main thread
+    std::mutex m_RunInMainMutex;
+    std::condition_variable m_InMainCondition;
+    bool m_isWakeUpMain = false;
+    std::function<void()> m_Closure; ///< code for main thread to run
+    /// members for communication from main thread to non-main thread
+    std::condition_variable m_ResultCondition;
+    bool m_isResultReady = false;
+
+    virtual bool IsCurrentThread() const override;
+    virtual void doAcquire(sal_uInt32 nLockCount) override;
+    virtual sal_uInt32 doRelease(bool const bUnlockAll) override;
+};
+
+bool Qt5YieldMutex::IsCurrentThread() const
+{
+    auto const* pSalInst(static_cast<Qt5Instance const*>(GetSalData()->m_pInstance));
+    assert(pSalInst);
+    if (pSalInst->IsMainThread() && m_bNoYieldLock)
+    {
+        return true; // main thread has borrowed SolarMutex
+    }
+    return SalYieldMutex::IsCurrentThread();
+}
+
+void Qt5YieldMutex::doAcquire(sal_uInt32 nLockCount)
+{
+    auto const* pSalInst(static_cast<Qt5Instance const*>(GetSalData()->m_pInstance));
+    assert(pSalInst);
+    if (!pSalInst->IsMainThread())
+    {
+        SalYieldMutex::doAcquire(nLockCount);
+        return;
+    }
+    if (m_bNoYieldLock)
+    {
+        return; // special case for main thread: borrowed from other thread
+    }
+    do // main thread acquire...
+    {
+        std::function<void()> func; // copy of closure on thread stack
+        {
+            std::unique_lock<std::mutex> g(m_RunInMainMutex);
+            if (m_aMutex.tryToAcquire())
+            {
+                // if there's a closure, the other thread holds m_aMutex
+                assert(!m_Closure);
+                m_isWakeUpMain = false;
+                --nLockCount; // have acquired once!
+                ++m_nCount;
+                break;
+            }
+            m_InMainCondition.wait(g, [this]() { return m_isWakeUpMain; });
+            m_isWakeUpMain = false;
+            std::swap(func, m_Closure);
+        }
+        if (func)
+        {
+            assert(!m_bNoYieldLock);
+            m_bNoYieldLock = true; // execute closure with borrowed SolarMutex
+            func();
+            m_bNoYieldLock = false;
+            std::unique_lock<std::mutex> g(m_RunInMainMutex);
+            assert(!m_isResultReady);
+            m_isResultReady = true;
+            m_ResultCondition.notify_all(); // unblock other thread
+        }
+    } while (true);
+    SalYieldMutex::doAcquire(nLockCount);
+}
+
+sal_uInt32 Qt5YieldMutex::doRelease(bool const bUnlockAll)
+{
+    auto const* pSalInst(static_cast<Qt5Instance const*>(GetSalData()->m_pInstance));
+    assert(pSalInst);
+    if (pSalInst->IsMainThread() && m_bNoYieldLock)
+    {
+        return 1; // dummy value
+    }
+
+    std::unique_lock<std::mutex> g(m_RunInMainMutex);
+    // read m_nCount before doRelease (it's guarded by m_aMutex)
+    bool const isReleased(bUnlockAll || m_nCount == 1);
+    sal_uInt32 nCount = SalYieldMutex::doRelease(bUnlockAll);
+    if (isReleased && !pSalInst->IsMainThread())
+    {
+        m_isWakeUpMain = true;
+        m_InMainCondition.notify_all(); // unblock main thread
+    }
+    return nCount;
+}
+
+// this could be abstracted to be independent of Qt5 by passing in the
+// event-trigger as another function parameter...
+// it could also be a template of the return type, then it could return the
+// result of func... but then how to handle the result in doAcquire?
+void Qt5Instance::RunInMainThread(std::function<void()> func)
+{
+    DBG_TESTSOLARMUTEX();
+    if (IsMainThread())
+    {
+        func();
+        return;
+    }
+
+    Qt5YieldMutex* const pMutex(static_cast<Qt5YieldMutex*>(GetYieldMutex()));
+    {
+        std::unique_lock<std::mutex> g(pMutex->m_RunInMainMutex);
+        assert(!pMutex->m_Closure);
+        pMutex->m_Closure = func;
+        // unblock main thread in case it is blocked on condition
+        pMutex->m_isWakeUpMain = true;
+        pMutex->m_InMainCondition.notify_all();
+    }
+    // wake up main thread in case it is blocked on event queue
+    // TriggerUserEventProcessing() appears to be insufficient in case the
+    // main thread does QEventLoop::WaitForMoreEvents
+    Q_EMIT ImplRunInMainSignal();
+    {
+        std::unique_lock<std::mutex> g(pMutex->m_RunInMainMutex);
+        pMutex->m_ResultCondition.wait(g, [pMutex]() { return pMutex->m_isResultReady; });
+        pMutex->m_isResultReady = false;
+    }
+}
+
+void Qt5Instance::ImplRunInMain()
+{
+    SolarMutexGuard g; // trigger the dispatch code in Qt5YieldMutex::doAcquire
+    (void)this; // suppress unhelpful [loplugin:staticmethods]; can't be static
+}
+
 Qt5Instance::Qt5Instance(bool bUseCairo)
-    : SalGenericInstance(o3tl::make_unique<SalYieldMutex>())
+    : SalGenericInstance(std::make_unique<Qt5YieldMutex>())
     , m_postUserEventId(-1)
     , m_bUseCairo(bUseCairo)
 {
@@ -65,8 +217,8 @@ Qt5Instance::Qt5Instance(bool bUseCairo)
     // is processed before the thread emitting the signal continues
     connect(this, SIGNAL(ImplYieldSignal(bool, bool)), this, SLOT(ImplYield(bool, bool)),
             Qt::BlockingQueuedConnection);
-    connect(this, &Qt5Instance::createMenuSignal, this, &Qt5Instance::CreateMenu,
-            Qt::BlockingQueuedConnection);
+    connect(this, &Qt5Instance::ImplRunInMainSignal, this, &Qt5Instance::ImplRunInMain,
+            Qt::QueuedConnection); // no Blocking!
 
     // this one needs to be queued non-blocking
     // in order to have this event arriving to correct event processing loop
@@ -144,15 +296,14 @@ Qt5Instance::CreateVirtualDevice(SalGraphics* pGraphics, long& nDX, long& nDY, D
 
 std::unique_ptr<SalMenu> Qt5Instance::CreateMenu(bool bMenuBar, Menu* pVCLMenu)
 {
-    if (qApp->thread() != QThread::currentThread())
-    {
-        SolarMutexReleaser aReleaser;
-        return Q_EMIT createMenuSignal(bMenuBar, pVCLMenu);
-    }
-
-    Qt5Menu* pSalMenu = new Qt5Menu(bMenuBar);
-    pSalMenu->SetMenu(pVCLMenu);
-    return std::unique_ptr<SalMenu>(pSalMenu);
+    std::unique_ptr<SalMenu> pRet;
+    RunInMainThread([&pRet, bMenuBar, pVCLMenu]() {
+        Qt5Menu* pSalMenu = new Qt5Menu(bMenuBar);
+        pRet.reset(pSalMenu);
+        pSalMenu->SetMenu(pVCLMenu);
+    });
+    assert(pRet);
+    return pRet;
 }
 
 std::unique_ptr<SalMenuItem> Qt5Instance::CreateMenuItem(const SalItemParams& rItemData)
diff --git a/vcl/unx/kde5/KDE5SalInstance.cxx b/vcl/unx/kde5/KDE5SalInstance.cxx
index 32998cdb36e3..565140cbcf4c 100644
--- a/vcl/unx/kde5/KDE5SalInstance.cxx
+++ b/vcl/unx/kde5/KDE5SalInstance.cxx
@@ -46,21 +46,16 @@ KDE5SalInstance::KDE5SalInstance()
     pSVData->maAppData.mxToolkitName = OUString("kde5");
 
     KDE5SalData::initNWF();
-
-    connect(this, &KDE5SalInstance::createFrameSignal, this, &KDE5SalInstance::CreateFrame,
-            Qt::BlockingQueuedConnection);
-    connect(this, &KDE5SalInstance::createFilePickerSignal, this,
-            &KDE5SalInstance::createFilePicker, Qt::BlockingQueuedConnection);
 }
 
 SalFrame* KDE5SalInstance::CreateFrame(SalFrame* pParent, SalFrameStyleFlags nState)
 {
-    if (!IsMainThread())
-    {
-        SolarMutexReleaser aReleaser;
-        return Q_EMIT createFrameSignal(pParent, nState);
-    }
-    return new KDE5SalFrame(static_cast<KDE5SalFrame*>(pParent), nState, true);
+    SalFrame* pRet(nullptr);
+    RunInMainThread(std::function([&pRet, pParent, nState]() {
+        pRet = new KDE5SalFrame(static_cast<KDE5SalFrame*>(pParent), nState, true);
+    }));
+    assert(pRet);
+    return pRet;
 }
 
 uno::Reference<ui::dialogs::XFilePicker2>
@@ -68,7 +63,11 @@ KDE5SalInstance::createFilePicker(const uno::Reference<uno::XComponentContext>&
 {
     if (!IsMainThread())
     {
-        return Q_EMIT createFilePickerSignal(xMSF);
+        uno::Reference<ui::dialogs::XFilePicker2> xRet;
+        RunInMainThread(
+            std::function([&xRet, this, xMSF]() { xRet = this->createFilePicker(xMSF); }));
+        assert(xRet);
+        return xRet;
     }
 
     // In order to insert custom controls, KDE5FilePicker currently relies on KFileWidget
diff --git a/vcl/unx/kde5/KDE5SalInstance.hxx b/vcl/unx/kde5/KDE5SalInstance.hxx
index 3cca255f9b2c..5980ea4699cc 100644
--- a/vcl/unx/kde5/KDE5SalInstance.hxx
+++ b/vcl/unx/kde5/KDE5SalInstance.hxx
@@ -42,13 +42,7 @@ public:
 
     virtual bool IsMainThread() const override;
 
-Q_SIGNALS:
-    SalFrame* createFrameSignal(SalFrame* pParent, SalFrameStyleFlags nStyle);
-
-    css::uno::Reference<css::ui::dialogs::XFilePicker2>
-    createFilePickerSignal(const css::uno::Reference<css::uno::XComponentContext>&);
-
-private Q_SLOTS:
+private:
     virtual SalFrame* CreateFrame(SalFrame* pParent, SalFrameStyleFlags nStyle) override;
 
     virtual css::uno::Reference<css::ui::dialogs::XFilePicker2>


More information about the Libreoffice-commits mailing list