[Libreoffice-commits] core.git: vcl/inc vcl/source vcl/unx

Jan-Marek Glogowski glogow at fbihome.de
Fri Oct 6 13:05:30 UTC 2017


 vcl/inc/unx/gendisp.hxx             |    2 -
 vcl/inc/unx/saldisp.hxx             |    2 -
 vcl/source/app/salusereventlist.cxx |    1 
 vcl/unx/generic/app/gendisp.cxx     |    4 +-
 vcl/unx/generic/app/salinst.cxx     |    3 +
 vcl/unx/kde4/KDESalDisplay.cxx      |    3 -
 vcl/unx/kde4/KDEXLib.cxx            |   62 ++++++++++++++++++++++++++----------
 vcl/unx/kde4/KDEXLib.hxx            |   19 ++++++-----
 8 files changed, 64 insertions(+), 32 deletions(-)

New commits:
commit 0d24dd25e6f506b5f9128d70d7eb21f0bb4dde89
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Thu Oct 5 18:19:32 2017 +0200

    KDE update system loop integration
    
    This updates the system loop integration to be on par with the
    other backends. This includes:
    
    1. Process LO user events before other LO events
    2. Correctly handle elapsed QTimer events
    3. Don't wait-yield in the main thread from a non-main thread
    
    Change-Id: Ia17be032ae39dc4c7bfa44cadd22d85a1b9c4fbd
    Reviewed-on: https://gerrit.libreoffice.org/43198
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Jan-Marek Glogowski <glogow at fbihome.de>

diff --git a/vcl/inc/unx/gendisp.hxx b/vcl/inc/unx/gendisp.hxx
index 5c8f5113c300..2d5bc12fcadf 100644
--- a/vcl/inc/unx/gendisp.hxx
+++ b/vcl/inc/unx/gendisp.hxx
@@ -47,7 +47,7 @@ public:
 
     void SendInternalEvent( SalFrame* pFrame, void* pData, SalEvent nEvent = SalEvent::UserEvent );
     void CancelInternalEvent( SalFrame* pFrame, void* pData, SalEvent nEvent );
-    bool DispatchInternalEvent();
+    bool DispatchInternalEvent( bool bHandleAllCurrentEvent = false );
 
     bool     MouseCaptured( const SalFrame *pFrameData ) const
                         { return m_pCapture == pFrameData; }
diff --git a/vcl/inc/unx/saldisp.hxx b/vcl/inc/unx/saldisp.hxx
index 8f96e03630b0..54799149e25c 100644
--- a/vcl/inc/unx/saldisp.hxx
+++ b/vcl/inc/unx/saldisp.hxx
@@ -179,7 +179,7 @@ public:
     virtual void    StartTimer( sal_uLong nMS );
     virtual void    StopTimer();
 
-    bool            CheckTimeout( bool bExecuteTimers = true );
+    virtual bool    CheckTimeout( bool bExecuteTimers = true );
 
     SalI18N_InputMethod* GetInputMethod() const { return m_pInputMethod; }
     Display*             GetDisplay() const { return m_pDisplay; }
diff --git a/vcl/source/app/salusereventlist.cxx b/vcl/source/app/salusereventlist.cxx
index 6384d8805be4..8f9d76ed313f 100644
--- a/vcl/source/app/salusereventlist.cxx
+++ b/vcl/source/app/salusereventlist.cxx
@@ -51,6 +51,7 @@ bool SalUserEventList::DispatchUserEvents( bool bHandleAllCurrentEvents )
 
     {
         osl::MutexGuard aGuard( m_aUserEventsMutex );
+        assert( m_aProcessingUserEvents.empty() );
         if( ! m_aUserEvents.empty() )
         {
             if( bHandleAllCurrentEvents )
diff --git a/vcl/unx/generic/app/gendisp.cxx b/vcl/unx/generic/app/gendisp.cxx
index 1be8606602e0..c83283a7b0e0 100644
--- a/vcl/unx/generic/app/gendisp.cxx
+++ b/vcl/unx/generic/app/gendisp.cxx
@@ -47,9 +47,9 @@ void SalGenericDisplay::emitDisplayChanged()
         pAnyFrame->CallCallback( SalEvent::DisplayChanged, nullptr );
 }
 
-bool SalGenericDisplay::DispatchInternalEvent()
+bool SalGenericDisplay::DispatchInternalEvent( bool bHandleAllCurrentEvent )
 {
-    return DispatchUserEvents( false );
+    return DispatchUserEvents( bHandleAllCurrentEvent );
 }
 
 void SalGenericDisplay::SendInternalEvent( SalFrame* pFrame, void* pData, SalEvent nEvent )
diff --git a/vcl/unx/generic/app/salinst.cxx b/vcl/unx/generic/app/salinst.cxx
index abd29a78c077..0d30e1d17a99 100644
--- a/vcl/unx/generic/app/salinst.cxx
+++ b/vcl/unx/generic/app/salinst.cxx
@@ -147,7 +147,8 @@ bool X11SalInstance::AnyInput(VclInputFlags nType)
 
     if( (nType & VclInputFlags::TIMER) && (mpXLib && mpXLib->CheckTimeout(false)) )
         bRet = true;
-    else if (XPending(pDisplay) )
+
+    if( !bRet && XPending(pDisplay) )
     {
         PredicateReturn aInput;
         XEvent          aEvent;
diff --git a/vcl/unx/kde4/KDESalDisplay.cxx b/vcl/unx/kde4/KDESalDisplay.cxx
index 8a2422a3918d..14a753e1c0a1 100644
--- a/vcl/unx/kde4/KDESalDisplay.cxx
+++ b/vcl/unx/kde4/KDESalDisplay.cxx
@@ -47,9 +47,6 @@ SalKDEDisplay::~SalKDEDisplay()
 
 void SalKDEDisplay::Yield()
 {
-    if( DispatchInternalEvent() )
-        return;
-
     // Prevent blocking from Drag'n'Drop events, which may have already have processed the event
     if (XEventsQueued( pDisp_, QueuedAfterReading ) == 0)
         return;
diff --git a/vcl/unx/kde4/KDEXLib.cxx b/vcl/unx/kde4/KDEXLib.cxx
index f047ed9fce65..43e055a2c0bb 100644
--- a/vcl/unx/kde4/KDEXLib.cxx
+++ b/vcl/unx/kde4/KDEXLib.cxx
@@ -53,6 +53,7 @@ KDEXLib::KDEXLib() :
     m_nFakeCmdLineArgs( 0 ),
     m_isGlibEventLoopType(false), m_allowKdeDialogs(false),
     m_timerEventId( -1 ), m_postUserEventId( -1 )
+    , m_bTimedOut( false )
 {
     m_timerEventId = QEvent::registerEventType();
     m_postUserEventId = QEvent::registerEventType();
@@ -269,22 +270,24 @@ void KDEXLib::socketNotifierActivated( int fd )
 
 bool KDEXLib::Yield( bool bWait, bool bHandleAllCurrentEvents )
 {
+    bool bWasEvent = false;
     if( !m_isGlibEventLoopType )
     {
-        bool wasEvent = false;
         if( qApp->thread() == QThread::currentThread())
         {
             // even if we use the LO event loop, still process Qt's events,
             // otherwise they can remain unhandled for quite a long while
-            wasEvent = processYield( false, bHandleAllCurrentEvents );
+            bWasEvent = processYield( false, bHandleAllCurrentEvents );
         }
-        return SalXLib::Yield(bWait, bHandleAllCurrentEvents) || wasEvent;
+        return SalXLib::Yield(bWait, bHandleAllCurrentEvents) || bWasEvent;
     }
     // if we are the main thread (which is where the event processing is done),
     // good, just do it
     if( qApp->thread() == QThread::currentThread())
     {
-        return processYield( bWait, bHandleAllCurrentEvents );
+        bWasEvent = processYield( bWait, bHandleAllCurrentEvents );
+        if ( bWasEvent )
+            m_aWaitingYieldCond.set();
     }
     else
     {
@@ -292,23 +295,40 @@ bool KDEXLib::Yield( bool bWait, bool bHandleAllCurrentEvents )
         // release the yield lock to prevent deadlock with the main thread
         // (it's ok to release it here, since even normal processYield() would
         // temporarily do it while checking for new events)
-        SolarMutexReleaser aReleaser;
-        return Q_EMIT processYieldSignal( bWait, bHandleAllCurrentEvents );
+        {
+            SolarMutexReleaser aReleaser;
+            bWasEvent = Q_EMIT processYieldSignal( false, bHandleAllCurrentEvents );
+        }
+        if ( !bWasEvent && bWait )
+        {
+            m_aWaitingYieldCond.reset();
+            SolarMutexReleaser aReleaser;
+            m_aWaitingYieldCond.wait();
+            bWasEvent = true;
+        }
     }
+    return bWasEvent;
 }
 
-/**
- * Quoting the Qt docs: [QAbstractEventDispatcher::processEvents] processes
- * pending events that match flags until there are no more events to process.
- */
-bool KDEXLib::processYield( bool bWait, bool )
+bool KDEXLib::processYield( bool bWait, bool bHandleAllCurrentEvents )
 {
-    QAbstractEventDispatcher* dispatcher = QAbstractEventDispatcher::instance( qApp->thread());
     bool wasEvent = false;
-    if ( bWait )
+    if ( m_isGlibEventLoopType )
+    {
+        wasEvent = SalKDEDisplay::self()->DispatchInternalEvent( bHandleAllCurrentEvents );
+        if ( !bHandleAllCurrentEvents && wasEvent )
+            return true;
+    }
+
+    /**
+     * Quoting the Qt docs: [QAbstractEventDispatcher::processEvents] processes
+     * pending events that match flags until there are no more events to process.
+     */
+    QAbstractEventDispatcher* dispatcher = QAbstractEventDispatcher::instance( qApp->thread());
+    if ( bWait && !wasEvent )
         wasEvent = dispatcher->processEvents( QEventLoop::WaitForMoreEvents );
     else
-        wasEvent = dispatcher->processEvents( QEventLoop::AllEvents );
+        wasEvent = dispatcher->processEvents( QEventLoop::AllEvents ) || wasEvent;
     return wasEvent;
 }
 
@@ -336,18 +356,28 @@ void KDEXLib::StopTimer()
     timeoutTimer.stop();
 }
 
+bool KDEXLib::CheckTimeout( bool bExecuteTimers )
+{
+    if( !m_isGlibEventLoopType )
+        return SalXLib::CheckTimeout( bExecuteTimers );
+    assert( !bExecuteTimers );
+    return m_bTimedOut;
+}
+
 void KDEXLib::timeoutActivated()
 {
     // don't potentially wait in timeout, as QTimer is non-recursive
+    m_bTimedOut = true;
     QApplication::postEvent(this, new QEvent(QEvent::Type( m_timerEventId )));
 }
 
 void KDEXLib::customEvent(QEvent* e)
 {
     if( e->type() == m_timerEventId )
+    {
+        m_bTimedOut = false;
         X11SalData::Timeout();
-    else if( e->type() == m_postUserEventId )
-        SalKDEDisplay::self()->DispatchInternalEvent();
+    }
 }
 
 void KDEXLib::Wakeup()
diff --git a/vcl/unx/kde4/KDEXLib.hxx b/vcl/unx/kde4/KDEXLib.hxx
index 4c06104b4c59..452aae8b3286 100644
--- a/vcl/unx/kde4/KDEXLib.hxx
+++ b/vcl/unx/kde4/KDEXLib.hxx
@@ -30,13 +30,14 @@
 #include <QtCore/QTimer>
 
 #include <unx/salinst.h>
+#include <osl/conditn.hxx>
 
 class VCLKDEApplication;
 
 class KDEXLib : public QObject, public SalXLib
 {
     Q_OBJECT
-    private:
+
         bool m_bStartupDone;
         std::unique_ptr<VCLKDEApplication> m_pApplication;
         std::unique_ptr<char*[]> m_pFreeCmdLineArgs;
@@ -56,23 +57,24 @@ class KDEXLib : public QObject, public SalXLib
         bool m_allowKdeDialogs;
         int m_timerEventId;
         int m_postUserEventId;
+    osl::Condition m_aWaitingYieldCond;
+    bool m_bTimedOut;
 
-    private:
-        void setupEventLoop();
+    void setupEventLoop();
 
-    private Q_SLOTS:
+private Q_SLOTS:
         void socketNotifierActivated( int fd );
         void timeoutActivated();
         void startTimeoutTimer();
-        static bool processYield( bool bWait, bool bHandleAllCurrentEvents );
+        bool processYield( bool bWait, bool bHandleAllCurrentEvents );
 
-    Q_SIGNALS:
+Q_SIGNALS:
         void startTimeoutTimerSignal();
         bool processYieldSignal( bool bWait, bool bHandleAllCurrentEvents );
         css::uno::Reference< css::ui::dialogs::XFilePicker2 >
             createFilePickerSignal( const css::uno::Reference< css::uno::XComponentContext >& );
 
-    public:
+public:
         KDEXLib();
         virtual ~KDEXLib() override;
 
@@ -82,6 +84,7 @@ class KDEXLib : public QObject, public SalXLib
         virtual void Remove( int fd ) override;
         virtual void StartTimer( sal_uLong nMS ) override;
         virtual void StopTimer() override;
+        virtual bool CheckTimeout( bool bExecuteTimers = true ) override;
         virtual void Wakeup() override;
         void TriggerUserEventProcessing();
 
@@ -90,7 +93,7 @@ class KDEXLib : public QObject, public SalXLib
 
         virtual void customEvent(QEvent* e) override;
 
-    public Q_SLOTS:
+public Q_SLOTS:
         css::uno::Reference< css::ui::dialogs::XFilePicker2 >
             createFilePicker( const css::uno::Reference< css::uno::XComponentContext >& );
 };


More information about the Libreoffice-commits mailing list