[Libreoffice-commits] core.git: Branch 'private/jmux/scheduler-fixes' - 2 commits - sw/inc sw/source vcl/inc vcl/source vcl/unx

Jan-Marek Glogowski glogow at fbihome.de
Fri Oct 6 09:26:43 UTC 2017


Rebased ref, commits from common ancestor:
commit 8f52f12771f2ef1a9395737975fcda26df8b1866
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
    
    Change-Id: Ia17be032ae39dc4c7bfa44cadd22d85a1b9c4fbd

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 >& );
 };
commit ea4c2a8af7ef3668456e0608b57a3445d29d41c4
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Fri Oct 6 11:00:19 2017 +0200

    Don't schedule the Idle job for busy documents
    
    This refactors DocumentTimerManager to export the busy status
    independent of the Idle function. This way it can be ignored in
    the Scheduler while the document is busy,
    
    Change-Id: Icec2075d3338ad8dd4440678eb0570d7fe887778

diff --git a/sw/inc/IDocumentTimerAccess.hxx b/sw/inc/IDocumentTimerAccess.hxx
index 717728f83c99..6efe1a114963 100644
--- a/sw/inc/IDocumentTimerAccess.hxx
+++ b/sw/inc/IDocumentTimerAccess.hxx
@@ -55,6 +55,11 @@ public:
     */
     virtual void StartBackgroundJobs() = 0;
 
+    /**
+     * Is the document ready to be processed?
+     */
+    virtual bool IsDocIdle() const = 0;
+
 protected:
     virtual ~IDocumentTimerAccess() {};
 };
diff --git a/sw/source/core/doc/DocumentTimerManager.cxx b/sw/source/core/doc/DocumentTimerManager.cxx
index ec4874ea9ecc..4da834ffbcbb 100644
--- a/sw/source/core/doc/DocumentTimerManager.cxx
+++ b/sw/source/core/doc/DocumentTimerManager.cxx
@@ -80,27 +80,16 @@ void DocumentTimerManager::StartBackgroundJobs()
         maDocIdle.Start();
 }
 
-IMPL_LINK( DocumentTimerManager, DoIdleJobs, Timer*, pIdle, void )
+DocumentTimerManager::IdleJob DocumentTimerManager::GetNextIdleJob() const
 {
-#ifdef TIMELOG
-    static ::rtl::Logfile* pModLogFile = 0;
-    if( !pModLogFile )
-        pModLogFile = new ::rtl::Logfile( "First DoIdleJobs" );
-#endif
-
     SwRootFrame* pTmpRoot = m_rDoc.getIDocumentLayoutAccess().GetCurrentLayout();
     if( pTmpRoot &&
         !SfxProgress::GetActiveProgress( m_rDoc.GetDocShell() ) )
     {
         SwViewShell* pShell(m_rDoc.getIDocumentLayoutAccess().GetCurrentViewShell());
         for(SwViewShell& rSh : pShell->GetRingContainer())
-        {
             if( rSh.ActionPend() )
-            {
-                pIdle->Start();
-                return;
-            }
-        }
+                return IdleJob::Busy;
 
         if( pTmpRoot->IsNeedGrammarCheck() )
         {
@@ -109,59 +98,93 @@ IMPL_LINK( DocumentTimerManager, DoIdleJobs, Timer*, pIdle, void )
             SvtLinguConfig().GetProperty( OUString(
                         UPN_IS_GRAMMAR_AUTO ) ) >>= bIsAutoGrammar;
 
-            if (bIsOnlineSpell && bIsAutoGrammar)
-                StartGrammarChecking( m_rDoc );
+            if( bIsOnlineSpell && bIsAutoGrammar )
+                return IdleJob::Grammar;
         }
-        std::set<SwRootFrame*> aAllLayouts = m_rDoc.GetAllLayouts();
-        std::set<SwRootFrame*>::iterator pLayIter = aAllLayouts.begin();
-        for ( ;pLayIter != aAllLayouts.end();++pLayIter )
+
+        for ( auto pLayout : m_rDoc.GetAllLayouts() )
         {
-            if ((*pLayIter)->IsIdleFormat())
-            {
-                (*pLayIter)->GetCurrShell()->LayoutIdle();
-                // Defer the remaining work.
-                pIdle->Start();
-                return;
-            }
+            if( pLayout->IsIdleFormat() )
+                return IdleJob::Layout;
         }
 
         SwFieldUpdateFlags nFieldUpdFlag = m_rDoc.GetDocumentSettingManager().getFieldUpdateFlags(true);
         if( ( AUTOUPD_FIELD_ONLY == nFieldUpdFlag
-                    || AUTOUPD_FIELD_AND_CHARTS == nFieldUpdFlag ) &&
-                m_rDoc.getIDocumentFieldsAccess().GetUpdateFields().IsFieldsDirty()
-                // If we switch the field name the Fields are not updated.
-                // So the "background update" should always be carried out
-                /* && !pStartSh->GetViewOptions()->IsFieldName()*/ )
+                    || AUTOUPD_FIELD_AND_CHARTS == nFieldUpdFlag )
+                && m_rDoc.getIDocumentFieldsAccess().GetUpdateFields().IsFieldsDirty() )
         {
-            if ( m_rDoc.getIDocumentFieldsAccess().GetUpdateFields().IsInUpdateFields() ||
-                      m_rDoc.getIDocumentFieldsAccess().IsExpFieldsLocked() )
+            if( m_rDoc.getIDocumentFieldsAccess().GetUpdateFields().IsInUpdateFields()
+                    || m_rDoc.getIDocumentFieldsAccess().IsExpFieldsLocked() )
+                return IdleJob::Busy;
+            return IdleJob::Fields;
+        }
+    }
+
+    return IdleJob::None;
+}
+
+IMPL_LINK( DocumentTimerManager, DoIdleJobs, Timer*, pIdle, void )
+{
+#ifdef TIMELOG
+    static ::rtl::Logfile* pModLogFile = 0;
+    if( !pModLogFile )
+        pModLogFile = new ::rtl::Logfile( "First DoIdleJobs" );
+#endif
+
+    IdleJob eJob = GetNextIdleJob();
+
+    switch ( eJob )
+    {
+    case IdleJob::Grammar:
+        StartGrammarChecking( m_rDoc );
+        break;
+
+    case IdleJob::Layout:
+        for ( auto pLayout : m_rDoc.GetAllLayouts() )
+            if( pLayout->IsIdleFormat() )
             {
-                pIdle->Start();
-                return;
+                pLayout->GetCurrShell()->LayoutIdle();
+                break;
             }
+         break;
 
-            //  Action brackets!
-            m_rDoc.getIDocumentFieldsAccess().GetUpdateFields().SetInUpdateFields( true );
+    case IdleJob::Fields:
+    {
+        SwViewShell* pShell( m_rDoc.getIDocumentLayoutAccess().GetCurrentViewShell() );
+        SwRootFrame* pTmpRoot = m_rDoc.getIDocumentLayoutAccess().GetCurrentLayout();
 
-            pTmpRoot->StartAllAction();
+        //  Action brackets!
+        m_rDoc.getIDocumentFieldsAccess().GetUpdateFields().SetInUpdateFields( true );
 
-            // no jump on update of fields #i85168#
-            const bool bOldLockView = pShell->IsViewLocked();
-            pShell->LockView( true );
+        pTmpRoot->StartAllAction();
 
-            m_rDoc.getIDocumentFieldsAccess().GetSysFieldType( SwFieldIds::Chapter )->ModifyNotification( nullptr, nullptr );    // ChapterField
-            m_rDoc.getIDocumentFieldsAccess().UpdateExpFields( nullptr, false );      // Updates ExpressionFields
-            m_rDoc.getIDocumentFieldsAccess().UpdateTableFields(nullptr);                // Tables
-            m_rDoc.getIDocumentFieldsAccess().UpdateRefFields();                // References
+        // no jump on update of fields #i85168#
+        const bool bOldLockView = pShell->IsViewLocked();
+        pShell->LockView( true );
 
-            pTmpRoot->EndAllAction();
+        m_rDoc.getIDocumentFieldsAccess().GetSysFieldType( SwFieldIds::Chapter )->ModifyNotification( nullptr, nullptr );  // ChapterField
+        m_rDoc.getIDocumentFieldsAccess().UpdateExpFields( nullptr, false );  // Updates ExpressionFields
+        m_rDoc.getIDocumentFieldsAccess().UpdateTableFields(nullptr);  // Tables
+        m_rDoc.getIDocumentFieldsAccess().UpdateRefFields();  // References
 
-            pShell->LockView( bOldLockView );
+        pTmpRoot->EndAllAction();
 
-            m_rDoc.getIDocumentFieldsAccess().GetUpdateFields().SetInUpdateFields( false );
-            m_rDoc.getIDocumentFieldsAccess().GetUpdateFields().SetFieldsDirty( false );
-        }
+        pShell->LockView( bOldLockView );
+
+        m_rDoc.getIDocumentFieldsAccess().GetUpdateFields().SetInUpdateFields( false );
+        m_rDoc.getIDocumentFieldsAccess().GetUpdateFields().SetFieldsDirty( false );
+        break;
     }
+
+    case IdleJob::Busy:
+        break;
+    case IdleJob::None:
+        break;
+    }
+
+    if ( IdleJob::None != eJob )
+        pIdle->Start();
+
 #ifdef TIMELOG
     if( pModLogFile && 1 != (long)pModLogFile )
         delete pModLogFile, static_cast<long&>(pModLogFile) = 1;
diff --git a/sw/source/core/doc/SwDocIdle.cxx b/sw/source/core/doc/SwDocIdle.cxx
index 9461807943d8..5987274a6b3d 100644
--- a/sw/source/core/doc/SwDocIdle.cxx
+++ b/sw/source/core/doc/SwDocIdle.cxx
@@ -24,6 +24,7 @@
 #include <vcl/scheduler.hxx>
 
 #include "SwDocIdle.hxx"
+#include "IDocumentTimerAccess.hxx"
 
 namespace sw
 {
@@ -31,12 +32,17 @@ namespace sw
 sal_uInt64 SwDocIdle::UpdateMinPeriod( sal_uInt64 /* nMinPeriod */, sal_uInt64 /* nTimeNow */ ) const
 {
     bool bReadyForSchedule = true;
+
     SwView* pView = m_rDoc.GetDocShell() ? m_rDoc.GetDocShell()->GetView() : nullptr;
     if( pView )
     {
         SwWrtShell& rWrtShell = pView->GetWrtShell();
         bReadyForSchedule = rWrtShell.GetViewOptions()->IsIdle();
     }
+
+    if( bReadyForSchedule && !m_rDoc.getIDocumentTimerAccess().IsDocIdle() )
+        bReadyForSchedule = false;
+
     return bReadyForSchedule
         ? Scheduler::ImmediateTimeoutMs : Scheduler::InfiniteTimeoutMs;
 }
diff --git a/sw/source/core/inc/DocumentTimerManager.hxx b/sw/source/core/inc/DocumentTimerManager.hxx
index 698762ab087e..d8c1a76b2a14 100644
--- a/sw/source/core/inc/DocumentTimerManager.hxx
+++ b/sw/source/core/inc/DocumentTimerManager.hxx
@@ -34,8 +34,17 @@ namespace sw
 class DocumentTimerManager : public IDocumentTimerAccess
 {
 public:
+    enum class IdleJob
+    {
+        None, ///< document has no idle jobs to do
+        Busy, ///< document is busy and idle jobs are postponed
+        Grammar,
+        Layout,
+        Fields,
+    };
 
     DocumentTimerManager( SwDoc& i_rSwdoc );
+    virtual ~DocumentTimerManager() override;
 
     void StartIdling() override;
 
@@ -47,15 +56,16 @@ public:
 
     void StartBackgroundJobs() override;
 
-    DECL_LINK( DoIdleJobs, Timer *, void );
-
-    virtual ~DocumentTimerManager() override;
+    bool IsDocIdle() const override;
 
 private:
-
     DocumentTimerManager(DocumentTimerManager const&) = delete;
     DocumentTimerManager& operator=(DocumentTimerManager const&) = delete;
 
+    DECL_LINK( DoIdleJobs, Timer *, void );
+
+    IdleJob GetNextIdleJob() const;
+
     SwDoc& m_rDoc;
 
     bool mbStartIdleTimer; //< idle timer mode start/stop
@@ -63,6 +73,11 @@ private:
     SwDocIdle maDocIdle;
 };
 
+inline bool DocumentTimerManager::IsDocIdle() const
+{
+    return( GetNextIdleJob() != IdleJob::Busy );
+}
+
 }
 
 #endif


More information about the Libreoffice-commits mailing list