[Libreoffice-commits] core.git: Branch 'feature/new-vcl-scheduler' - 282 commits - android/mobile-config.py avmedia/source basctl/source basic/qa bin/convwatch.py bin/test-hid-vs-ui.py bin/upload_symbols.py chart2/source comphelper/source compilerplugins/clang config_host/config_options_calc.h.in config_host.mk.in configure.ac connectivity/source cppcanvas/source cppu/Library_cppu.mk cppu/source cui/source cui/uiconfig dbaccess/inc dbaccess/Library_dbu.mk dbaccess/source dbaccess/uiconfig dbaccess/UIConfig_dbapp.mk dbaccess/UIConfig_dbbrowser.mk dbaccess/UIConfig_dbtdata.mk dbaccess/util desktop/CppunitTest_desktop_app.mk desktop/qa desktop/source drawinglayer/source editeng/source extensions/source external/icu external/liblangtag external/libxmlsec external/libzmf external/nss extras/source filter/source forms/source formula/source framework/inc framework/source helpcontent2 icon-themes/breeze icon-themes/breeze_dark icon-themes/breeze_svg idl/inc idl/source include/comphelper include/editeng i nclude/filter include/formula include/oox include/opencl include/rsc include/sal include/sfx2 include/svl include/svtools include/svx include/toolkit include/tools include/tubes include/ucbhelper include/unotools include/vbahelper include/vcl include/xmloff Library_merged.mk librelogo/source mysqlc/source odk/examples officecfg/registry oox/source opencl/source postprocess/Rdb_services.mk pyuno/demo pyuno/source qadevOOo/tests reportdesign/source RepositoryExternal.mk Repository.mk rsc/inc rsc/source sal/osl scaddins/source sc/AllLangResTarget_sc.mk sc/inc sc/Library_sc.mk scp2/AutoInstall.mk scp2/InstallScript_setup_osl.mk sc/qa scripting/source sc/sdi sc/source sc/uiconfig sc/UIConfig_scalc.mk sdext/source sd/inc sd/Library_sd.mk sd/qa sd/README sd/source sfx2/qa sfx2/source slideshow/Library_OGLTrans.mk slideshow/source solenv/bin solenv/CustomTarget_gbuildtesttools.mk solenv/Executable_gbuildtojson.mk solenv/gbuild solenv/gbuildtojson solenv/gdb solenv/Module_solenv.mk solenv/Py thonTest_solenv_python.mk solenv/qa sot/source starmath/inc starmath/source stoc/Library_javavm.mk stoc/source svgio/inc svgio/source svl/Library_svl.mk svl/qa svl/source svtools/source svx/inc svx/source sw/CppunitTest_sw_ww8export2.mk sw/inc sw/Module_sw.mk sw/qa sw/source sysui/desktop TEMPLATE.SOURCECODE.HEADER test/source toolkit/source tools/source tubes/qa tubes/source ucbhelper/source ucb/qa ucb/source uitest/calc_tests uitest/demo_ui uitest/impress_tests uitest/libreoffice uitest/math_tests uitest/test_main.py uitest/uitest uitest/writer_tests UnoControls/inc UnoControls/source unotest/source unotools/source uui/source vbahelper/source vcl/headless vcl/inc vcl/Library_vcl.mk vcl/opengl vcl/osx vcl/qa vcl/quartz vcl/README.scheduler vcl/source vcl/unx vcl/win writerfilter/source xmlhelp/source xmloff/source xmlsecurity/inc xmlsecurity/qa xmlsecurity/source

Jan-Marek Glogowski glogow at fbihome.de
Fri Oct 28 10:16:00 UTC 2016


Rebased ref, commits from common ancestor:
commit b87a70dc3aa1719d9836314d2aef145016c0af07
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Fri Oct 28 11:05:18 2016 +0200

    Add VCL scheduler documentation
    
    Change-Id: Id2476e39272f5e253c5edfce59e84b0e2902db82

diff --git a/vcl/README.scheduler b/vcl/README.scheduler
new file mode 100644
index 0000000..b99fe8f
--- /dev/null
+++ b/vcl/README.scheduler
@@ -0,0 +1,74 @@
+= Introduction =
+
+The VCL scheduler handles LOs primary event queue.
+It is simple by design, currently just a single-linked list, and has the following behaviour:
+
+B.1. Tasks are scheduled just priority based
+B.2. Implicitly cooperative AKA non-preemptive
+B.3. It's not "fair" in any way (a consequence of B.2)
+B.4. Tasks are handled round-robin (per priority)
+B.5. Higher priorities have lower values
+B.6. A small set of priorities instead of an flexible value AKA int
+
+There are some consequences due to this design.
+
+C.1. Higher priorority tasks starve lower priority tasks
+     As long as a higher task is available, lower tasks are never run!
+     See Anti-pattern.
+
+C.2. Tasks should be split into sensible blocks
+     If this can't really be done, process pending tasks by calling Application::Reschedule(). Or use a thread.
+
+C.3. This is not an OS scheduler
+     There is no real way to "fix" B.2. and B.3. If you need to do an preemptive task, use a thread!
+     OS schedulers need to be "fair". There are complex approaches, like RCU, priority inversion, priority inheritance, etc. to fix C.1., but most aren't useable in userspace (there even is a userspace RCU library, FWIW).
+
+
+= Anti-pattern: Dependencies via (fine grained) priorities =
+
+"Idle 1" should run before "Idle 2", therefore give "Idle 1" a higher priority then "Idle 2".
+This just works correct for low frequency idles, but otherwise always breaks!
+
+If you have some longer work - even if it can be split by into schedulable, smaller blocks - you normally don't want to schedule it with a non-default priority, as it starves all lower priority tasks. Even if a block was processed in "Idle 1", it is scheduled with the same (higher) priority again. Changing the "Idle" to a "Timer" also won't work, as this breaks the dependency.
+
+What is needed is task based dependency handling, so if "Task 1" is done, it has to start "Task 2" and if "Task 1" is started again, it has to stop "Task 2". This currently has to be done by the implementor, but this feature can be added to the scheduler reasonably.
+
+
+= TODOs and ideas =
+
+== Task dependencies AKA children ==
+
+Every task can have a list of children / a child.
+
+ * When a task is stopped, the children are started.
+ * When a task is started, the children are stopped.
+
+This should be easy to implement.
+
+== Per priority time-sorted queues ==
+
+This would result in O(1) scheduler. It was used in the Linux kernel for some time (search Ingo Molinars O(1) scheduler). This can be a scheduling optimization, which would prevent walking longer event list. But probably the management overhead would be too large, as we have many one-shot events.
+
+To find the next task the scheduler just walks the (constant) list of priority queues and schedules the first ready event of any queue.
+
+The downside of this approach: Insert / Start / Reschedule(for "auto" tasks) now need O(log(n)) to find the position in the queue.
+
+== Always process all (higher priority) pending events ==
+
+Currently Application::Reschedule() processes a single event or "all" events, with "all" defined as "100" events in most backends. This already is "ignored" by the KDE4 backend, as Qt defines its ProcessPendingEvents() as always processing all pending events (there are ways to skip event classes, but no easy but one hard way to process just a single event).
+
+== Convert Scheduler from single-linked list to queue ==
+
+Keep a pointer to the last list element to speed up adding new events.
+This is a prerequisite to implement I.2 of the "Thread-safe scheduler".
+
+== Thread-safe scheduler ==
+
+We already have crashes, where LO adds new events to the scheduler without holding the SolarMutex.
+Instead of using the global lock, use extra locking to allow threads to add events to the main queue.
+
+I.1. Use an extra list for new events. The new event list is appended to the scheduler list and accounted at two points: 1. the start of a normal scheduler run and 2. after invoking an event.
+I.2. The scheduler just needs the list lock, if it handles the last item, as new events are always appended. No special list handling is needed in this case. As a consequence the list has to become a queue with a last item, as unlocked walk outside the scheduler will not be thread-safe.
+
+Stopping and invoking would also need locking, but the main task of walking the list is safe without the lock.
+
commit 45e528eaf49bd65afe34952d569d213323de25ef
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Wed Sep 14 18:17:18 2016 +0200

    Don't poll busy documents via idle task
    
    Creates a very busy idle-loop, for non-task work like mail merge.
    
    Change-Id: If7be82e4675008f23e6f4f6be5c40df40a231a8b

diff --git a/sw/source/core/doc/DocumentTimerManager.cxx b/sw/source/core/doc/DocumentTimerManager.cxx
index 4a0176b..a7c5d23 100644
--- a/sw/source/core/doc/DocumentTimerManager.cxx
+++ b/sw/source/core/doc/DocumentTimerManager.cxx
@@ -40,47 +40,50 @@ namespace sw
 DocumentTimerManager::DocumentTimerManager( SwDoc& i_rSwdoc ) : m_rDoc( i_rSwdoc ),
                                                                 mbStartIdleTimer( false ),
                                                                 mIdleBlockCount( 0 ),
-                                                                maIdle("DocumentTimerManagerIdleTimer")
+                                                                maDocIdleTimer("DocumentTimerManagerIdleTimer")
 {
-    maIdle.SetPriority( SchedulerPriority::LOWEST );
-    maIdle.SetIdleHdl( LINK( this, DocumentTimerManager, DoIdleJobs) );
-    maIdle.SetDebugName( "sw::DocumentTimerManager maIdle" );
+    maDocIdleTimer.SetPriority( SchedulerPriority::LOWEST );
+    maDocIdleTimer.SetTimeoutHdl( LINK( this, DocumentTimerManager, DoIdleJobs) );
+    maDocIdleTimer.SetDebugName( "sw::DocumentTimerManager maDocIdleTimer" );
 }
 
 void DocumentTimerManager::StartIdling()
 {
     mbStartIdleTimer = true;
     if( !mIdleBlockCount )
-        maIdle.Start();
+    {
+        maDocIdleTimer.SetTimeout( 0 );
+        maDocIdleTimer.Start();
+    }
 }
 
 void DocumentTimerManager::StopIdling()
 {
     mbStartIdleTimer = false;
-    maIdle.Stop();
+    maDocIdleTimer.Stop();
 }
 
 void DocumentTimerManager::BlockIdling()
 {
-    maIdle.Stop();
+    maDocIdleTimer.Stop();
     ++mIdleBlockCount;
 }
 
 void DocumentTimerManager::UnblockIdling()
 {
     --mIdleBlockCount;
-    if( !mIdleBlockCount && mbStartIdleTimer && !maIdle.IsActive() )
-        maIdle.Start();
+    if( !mIdleBlockCount && mbStartIdleTimer && !maDocIdleTimer.IsActive() )
+        maDocIdleTimer.Start();
 }
 
 void DocumentTimerManager::StartBackgroundJobs()
 {
     // Trigger DoIdleJobs(), asynchronously.
-    if (!maIdle.IsActive()) //fdo#73165 if the timer is already running don't restart from 0
-        maIdle.Start();
+    if (!maDocIdleTimer.IsActive()) //fdo#73165 if the timer is already running don't restart from 0
+        maDocIdleTimer.Start();
 }
 
-IMPL_LINK( DocumentTimerManager, DoIdleJobs, Idle*, pIdle, void )
+IMPL_LINK( DocumentTimerManager, DoIdleJobs, Timer*, pTimer, void )
 {
 #ifdef TIMELOG
     static ::rtl::Logfile* pModLogFile = 0;
@@ -97,7 +100,8 @@ IMPL_LINK( DocumentTimerManager, DoIdleJobs, Idle*, pIdle, void )
         {
             if( rSh.ActionPend() )
             {
-                pIdle->Start();
+                pTimer->SetTimeout( 2000 );
+                pTimer->Start();
                 return;
             }
         }
@@ -121,7 +125,8 @@ IMPL_LINK( DocumentTimerManager, DoIdleJobs, Idle*, pIdle, void )
                 (*pLayIter)->GetCurrShell()->LayoutIdle();
 
                 // Defer the remaining work.
-                pIdle->Start();
+                pTimer->SetTimeout( 2000 );
+                pTimer->Start();
                 return;
             }
         }
@@ -137,7 +142,8 @@ IMPL_LINK( DocumentTimerManager, DoIdleJobs, Idle*, pIdle, void )
             if ( m_rDoc.getIDocumentFieldsAccess().GetUpdateFields().IsInUpdateFields() ||
                  m_rDoc.getIDocumentFieldsAccess().IsExpFieldsLocked() )
             {
-                pIdle->Start();
+                pTimer->SetTimeout( 2000 );
+                pTimer->Start();
                 return;
             }
 
diff --git a/sw/source/core/inc/DocumentTimerManager.hxx b/sw/source/core/inc/DocumentTimerManager.hxx
index b857519..17fa950 100644
--- a/sw/source/core/inc/DocumentTimerManager.hxx
+++ b/sw/source/core/inc/DocumentTimerManager.hxx
@@ -48,7 +48,7 @@ public:
     void StartBackgroundJobs() override;
 
     // Our own 'IdleTimer' calls the following method
-    DECL_LINK( DoIdleJobs, Idle *, void );
+    DECL_LINK( DoIdleJobs, Timer *, void );
 
     virtual ~DocumentTimerManager() override;
 
@@ -61,7 +61,7 @@ private:
 
     bool mbStartIdleTimer; //< idle timer mode start/stop
     sal_Int32 mIdleBlockCount;
-    Idle  maIdle;
+    Timer maDocIdleTimer;
 };
 
 }
commit 9470f7bea3fb2a5a36ea05df68ea9b892a88dd16
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Sun Jul 31 16:35:49 2016 +0200

    Don't update document stats for non-idle views
    
    This functionality should be merged into the DocumentTimerManager,
    which itself should run the different document idle tasks via
    seperate jobs instead of a single idle, if they don't depend on
    each other.
    
    As a workaround, this checks for the idle status of the view and
    won't run on busy documents.
    
    The idle is also changed to a timer, which sleeps for busy views.
    
    Change-Id: I185137ed3423ecaae0f7edb39018d26c4244d359

diff --git a/include/vcl/idle.hxx b/include/vcl/idle.hxx
index 5b359f2..b2834d4 100644
--- a/include/vcl/idle.hxx
+++ b/include/vcl/idle.hxx
@@ -60,6 +60,21 @@ inline void Idle::SetIdleHdl( const Link<Idle*, void> &rLink )
         reinterpret_cast< Link<Timer*, void>::Stub* >( rLink.GetFunction()) ) );
 }
 
+/**
+ * An auto-idle is long running task processing small chunks of data, which
+ * is re-scheduled multiple times.
+ *
+ * Remember to stop the Idle when finished, as it would otherwise busy loop the CPU!
+ *
+ * It probably makes sense to re-implement ReadyForSchedule and UpdateMinPeriod,
+ * in case there is a quick check and it can otherwise sleep.
+ */
+class VCL_DLLPUBLIC AutoIdle : public Idle
+{
+public:
+    AutoIdle( const sal_Char *pDebugName = nullptr );
+};
+
 #endif // INCLUDED_VCL_IDLE_HXX
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/doc/DocumentStatisticsManager.cxx b/sw/source/core/doc/DocumentStatisticsManager.cxx
index 96a31a0..9099937 100644
--- a/sw/source/core/doc/DocumentStatisticsManager.cxx
+++ b/sw/source/core/doc/DocumentStatisticsManager.cxx
@@ -34,6 +34,8 @@
 #include <vector>
 #include <viewsh.hxx>
 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
+#include <wrtsh.hxx>
+#include <viewopt.hxx>
 
 using namespace ::com::sun::star;
 
@@ -73,9 +75,8 @@ DocumentStatisticsManager::DocumentStatisticsManager( SwDoc& i_rSwdoc ) : m_rDoc
                                                                           mpDocStat( new SwDocStat ),
                                                                           mbInitialized( false )
 {
-    maStatsUpdateTimer.SetTimeout( 1 );
-    maStatsUpdateTimer.SetPriority( SchedulerPriority::LOWEST );
     maStatsUpdateTimer.SetTimeoutHdl( LINK( this, DocumentStatisticsManager, DoIdleStatsUpdate ) );
+    maStatsUpdateTimer.SetPriority( SchedulerPriority::DEFAULT_IDLE );
     maStatsUpdateTimer.SetDebugName( "sw::DocumentStatisticsManager maStatsUpdateTimer" );
 }
 
@@ -120,14 +121,15 @@ void DocumentStatisticsManager::UpdateDocStat( bool bCompleteAsync, bool bFields
     {
         if (!bCompleteAsync)
         {
+            maStatsUpdateTimer.Stop();
             while (IncrementalDocStatCalculate(
                         std::numeric_limits<long>::max(), bFields)) {}
-            maStatsUpdateTimer.Stop();
         }
-        else if (IncrementalDocStatCalculate(5000, bFields))
-            maStatsUpdateTimer.Start();
         else
-            maStatsUpdateTimer.Stop();
+        {
+            if (!maStatsUpdateTimer.IsActive() && IncrementalDocStatCalculate(5000, bFields))
+                maStatsUpdateTimer.Start();
+        }
     }
 }
 
@@ -234,12 +236,23 @@ bool DocumentStatisticsManager::IncrementalDocStatCalculate(long nChars, bool bF
 
 IMPL_LINK( DocumentStatisticsManager, DoIdleStatsUpdate, Timer *, pTimer, void )
 {
-    (void)pTimer;
-    if (IncrementalDocStatCalculate(32000))
-        maStatsUpdateTimer.Start();
-
+    (void) pTimer;
     SwView* pView = m_rDoc.GetDocShell() ? m_rDoc.GetDocShell()->GetView() : nullptr;
     if( pView )
+    {
+        SwWrtShell& rWrtShell = pView->GetWrtShell();
+        if (!rWrtShell.GetViewOptions()->IsIdle())
+        {
+            maStatsUpdateTimer.SetTimeout( 1000 );
+            return;
+        }
+    }
+    maStatsUpdateTimer.SetTimeout( 0 );
+
+    if (!IncrementalDocStatCalculate(32000))
+        maStatsUpdateTimer.Stop();
+
+    if( pView )
         pView->UpdateDocStats();
 }
 
diff --git a/sw/source/core/inc/DocumentStatisticsManager.hxx b/sw/source/core/inc/DocumentStatisticsManager.hxx
index b21e8ec..f67d6ce 100644
--- a/sw/source/core/inc/DocumentStatisticsManager.hxx
+++ b/sw/source/core/inc/DocumentStatisticsManager.hxx
@@ -20,11 +20,10 @@
 #define INCLUDED_SW_SOURCE_CORE_INC_DOCUMENTSTATISTICSMANAGER_HXX
 
 #include <IDocumentStatistics.hxx>
-#include <vcl/timer.hxx>
+#include <vcl/idle.hxx>
 
 class SwDoc;
 struct SwDocStat;
-class Timer;
 
 namespace sw {
 
@@ -62,9 +61,9 @@ private:
     DECL_LINK( DoIdleStatsUpdate, Timer *, void );
 
 
-    SwDocStat       *mpDocStat;          //< Statistics information.
-    bool            mbInitialized;       // allow first time update
-    Timer       maStatsUpdateTimer;      //< Timer for asynchronous stats calculation
+    SwDocStat       *mpDocStat;          //< Statistics information
+    bool             mbInitialized;      //< allow first time update
+    AutoTimer        maStatsUpdateTimer; //< Timer for asynchronous stats calculation
 };
 
 }
diff --git a/vcl/source/app/idle.cxx b/vcl/source/app/idle.cxx
index 66bf0bf..f2c6264 100644
--- a/vcl/source/app/idle.cxx
+++ b/vcl/source/app/idle.cxx
@@ -58,4 +58,10 @@ void Idle::UpdateMinPeriod( const sal_uInt64 /* nTime */, sal_uInt64 &nMinPeriod
     nMinPeriod = ImmediateTimeoutMs; // don't wait
 }
 
+AutoIdle::AutoIdle( const sal_Char *pDebugName )
+    : Idle( pDebugName )
+{
+    mbAuto = true;
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit c2e7df7c39a1f7f1f6280fbbaec32607d1b905e5
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Sun Oct 23 14:17:44 2016 +0200

    Change layout timer to an high idle...
    
    ... so it will run before the next paint.
    
    This also changes the paint from the main resize handler to be
    scheduled instead of invoked, as resize triggers the layout task,
    which has no chance to run before the invoked paint.
    
    Change-Id: I0794b714f40cf8eb295148f413313e233fdf3673

diff --git a/framework/inc/services/layoutmanager.hxx b/framework/inc/services/layoutmanager.hxx
index 7a895cc..4cb2b62 100644
--- a/framework/inc/services/layoutmanager.hxx
+++ b/framework/inc/services/layoutmanager.hxx
@@ -179,7 +179,7 @@ namespace framework
                     const css::uno::Reference< css::uno::XComponentContext > &rComponentContext );
 
         protected:
-            DECL_LINK(AsyncLayoutHdl, Timer *, void);
+            DECL_LINK(AsyncLayoutHdl, Idle *, void);
 
         private:
 
@@ -290,7 +290,7 @@ namespace framework
             css::uno::Reference< css::container::XNameAccess >             m_xPersistentWindowStateSupplier;
             GlobalSettings*                                                m_pGlobalSettings;
             OUString                                                       m_aModuleIdentifier;
-            Timer                                                          m_aAsyncLayoutTimer;
+            Idle                                                           m_aAsyncLayoutIdle;
             ::cppu::OMultiTypeInterfaceContainerHelper                     m_aListenerContainer; // container for ALL Listener
             ToolbarLayoutManager*                                          m_pToolbarManager;
             css::uno::Reference< css::ui::XUIConfigurationListener >       m_xToolbarManager;
diff --git a/framework/source/layoutmanager/layoutmanager.cxx b/framework/source/layoutmanager/layoutmanager.cxx
index 90e2b1b..2602045 100644
--- a/framework/source/layoutmanager/layoutmanager.cxx
+++ b/framework/source/layoutmanager/layoutmanager.cxx
@@ -143,9 +143,9 @@ LayoutManager::LayoutManager( const Reference< XComponentContext >& xContext ) :
         m_xToolbarManager.set( static_cast< OWeakObject* >( m_pToolbarManager ), uno::UNO_QUERY );
     }
 
-    m_aAsyncLayoutTimer.SetTimeout( 50 );
-    m_aAsyncLayoutTimer.SetTimeoutHdl( LINK( this, LayoutManager, AsyncLayoutHdl ) );
-    m_aAsyncLayoutTimer.SetDebugName( "framework::LayoutManager m_aAsyncLayoutTimer" );
+    m_aAsyncLayoutIdle.SetPriority( SchedulerPriority::HIGH_IDLE );
+    m_aAsyncLayoutIdle.SetIdleHdl( LINK( this, LayoutManager, AsyncLayoutHdl ) );
+    m_aAsyncLayoutIdle.SetDebugName( "framework::LayoutManager m_aAsyncLayoutIdle" );
 
     registerProperty( LAYOUTMANAGER_PROPNAME_ASCII_AUTOMATICTOOLBARS, LAYOUTMANAGER_PROPHANDLE_AUTOMATICTOOLBARS, css::beans::PropertyAttribute::TRANSIENT, &m_bAutomaticToolbars, cppu::UnoType<decltype(m_bAutomaticToolbars)>::get() );
     registerProperty( LAYOUTMANAGER_PROPNAME_ASCII_HIDECURRENTUI, LAYOUTMANAGER_PROPHANDLE_HIDECURRENTUI, beans::PropertyAttribute::TRANSIENT, &m_bHideCurrentUI, cppu::UnoType<decltype(m_bHideCurrentUI)>::get() );
@@ -157,7 +157,7 @@ LayoutManager::LayoutManager( const Reference< XComponentContext >& xContext ) :
 
 LayoutManager::~LayoutManager()
 {
-    m_aAsyncLayoutTimer.Stop();
+    m_aAsyncLayoutIdle.Stop();
     setDockingAreaAcceptor(nullptr);
     delete m_pGlobalSettings;
 }
@@ -233,13 +233,17 @@ void LayoutManager::implts_lock()
 {
     SolarMutexGuard g;
     ++m_nLockCount;
+    m_aAsyncLayoutIdle.Stop();
 }
 
 bool LayoutManager::implts_unlock()
 {
     SolarMutexGuard g;
     m_nLockCount = std::max( m_nLockCount-1, static_cast<sal_Int32>(0) );
-    return ( m_nLockCount == 0 );
+    bool bCanLayout = ( m_nLockCount == 0 );
+    if ( bCanLayout && m_bMustDoLayout )
+        m_aAsyncLayoutIdle.Start();
+    return bCanLayout;
 }
 
 void LayoutManager::implts_reset( bool bAttached )
@@ -1282,7 +1286,7 @@ throw ( RuntimeException, std::exception )
 
     // IMPORTANT: Be sure to stop layout timer if don't have a docking area acceptor!
     if ( !xDockingAreaAcceptor.is() )
-        m_aAsyncLayoutTimer.Stop();
+        m_aAsyncLayoutIdle.Stop();
 
     bool bAutomaticToolbars( m_bAutomaticToolbars );
     std::vector< Reference< awt::XWindow > > oldDockingAreaWindows;
@@ -1290,7 +1294,7 @@ throw ( RuntimeException, std::exception )
     ToolbarLayoutManager* pToolbarManager = m_pToolbarManager;
 
     if ( !xDockingAreaAcceptor.is() )
-        m_aAsyncLayoutTimer.Stop();
+        m_aAsyncLayoutIdle.Stop();
 
     // Remove listener from old docking area acceptor
     if ( m_xDockingAreaAcceptor.is() )
@@ -2277,9 +2281,9 @@ throw (RuntimeException, std::exception)
     // conform to documentation: unlock with lock count == 0 means force a layout
 
     SolarMutexClearableGuard aWriteLock;
-        if ( bDoLayout )
-                m_aAsyncLayoutTimer.Stop();
-        aWriteLock.clear();
+    if ( bDoLayout )
+        m_aAsyncLayoutIdle.Stop();
+    aWriteLock.clear();
 
     Any a( nLockCount );
     implts_notifyListeners( frame::LayoutManagerEvents::UNLOCK, a );
@@ -2681,12 +2685,8 @@ throw( uno::RuntimeException, std::exception )
         // application modules need this. So we have to check if this is the first
         // call after the async layout time expired.
         m_bMustDoLayout = true;
-        if ( !m_aAsyncLayoutTimer.IsActive() )
-        {
-            m_aAsyncLayoutTimer.Invoke();
-        }
         if ( m_nLockCount == 0 )
-            m_aAsyncLayoutTimer.Start();
+            m_aAsyncLayoutIdle.Start();
     }
     else if ( m_xFrame.is() && aEvent.Source == m_xFrame->getContainerWindow() )
     {
@@ -2753,10 +2753,9 @@ void SAL_CALL LayoutManager::windowHidden( const lang::EventObject& aEvent ) thr
     }
 }
 
-IMPL_LINK_NOARG(LayoutManager, AsyncLayoutHdl, Timer *, void)
+IMPL_LINK_NOARG(LayoutManager, AsyncLayoutHdl, Idle *, void)
 {
     SolarMutexClearableGuard aReadLock;
-    m_aAsyncLayoutTimer.Stop();
 
     if( !m_xContainerWindow.is() )
         return;
diff --git a/vcl/source/window/paint.cxx b/vcl/source/window/paint.cxx
index 308b971..e900df3 100644
--- a/vcl/source/window/paint.cxx
+++ b/vcl/source/window/paint.cxx
@@ -664,11 +664,8 @@ IMPL_LINK_NOARG(Window, ImplHandleResizeTimerHdl, Idle *, void)
     if( mpWindowImpl->mbReallyVisible )
     {
         ImplCallResize();
-        if( mpWindowImpl->mpFrameData->maPaintIdle.IsActive() )
-        {
-            mpWindowImpl->mpFrameData->maPaintIdle.Stop();
-            mpWindowImpl->mpFrameData->maPaintIdle.Invoke( nullptr );
-        }
+        if( !mpWindowImpl->mpFrameData->maPaintIdle.IsActive() )
+            mpWindowImpl->mpFrameData->maPaintIdle.Start();
     }
 }
 
commit 5efc9ff2df2d1d24b3b2aba563bb91806bdb7d66
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Fri Oct 21 12:58:19 2016 +0200

    KDE4 clang-lo:staticmethods
    
    Change-Id: I4899a30f97f8433fd4d20b7d65cb3fbb6a06103f

diff --git a/vcl/unx/kde4/KDEXLib.hxx b/vcl/unx/kde4/KDEXLib.hxx
index 5bcc6b1..e97b20f 100644
--- a/vcl/unx/kde4/KDEXLib.hxx
+++ b/vcl/unx/kde4/KDEXLib.hxx
@@ -62,11 +62,11 @@ class KDEXLib : public QObject, public SalXLib
 
     private Q_SLOTS:
         void socketNotifierActivated( int fd );
-        void timeoutActivated();
+        static void timeoutActivated();
         void userEventActivated();
         void startTimeoutTimer();
         void startUserEventTimer();
-        bool processYield( bool bWait, bool bHandleAllCurrentEvents );
+        static bool processYield( bool bWait, bool bHandleAllCurrentEvents );
     Q_SIGNALS:
         void startTimeoutTimerSignal();
         void startUserEventTimerSignal();
commit 556783247352c0e32922359e106c9ff41b357c99
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Fri Oct 14 16:05:58 2016 +0200

    Correctly handle nested task processing calls
    
    If ProcessTaskScheduling is called to process tasks while inside
    Invoke(), the assumptions about the list pointers in the parent
    call will be void.
    
    There would be two possible solutions:
      1. Nested calls are forbidden to change the list, except for
         adding tasks.
      2. The parent call must be informed of the changes and update
         the pointers.
    
    Since we want to be able to remove processed tasks in nested calls,
    we go with option 2, which has a slight overhead but won't exhaust
    memory, because it can't release processed tasks.
    
    Change-Id: I7a3910a9a4677988dff1d5a7648a67d66fb41056

diff --git a/vcl/inc/svdata.hxx b/vcl/inc/svdata.hxx
index 27c4cfc..02ffdc1 100644
--- a/vcl/inc/svdata.hxx
+++ b/vcl/inc/svdata.hxx
@@ -318,6 +318,7 @@ struct ImplSVData
     ImplSchedulerData*      mpFirstSchedulerData = nullptr; // list of all running tasks
     ImplSchedulerData*      mpFreeSchedulerData = nullptr;  // list of all deleted tasks for reuse
     bool                    mbNeedsReschedule = false;      // was the list of tasks changed?
+    bool                    mbTaskRemoved = false;          // was a task removed
     sal_uInt64              mnTimerPeriod = 0;              // current timer period / sleep time
     sal_uInt64              mnLastUpdate = 0;               // last scheduler time
     SalTimer*               mpSalTimer = nullptr;           // interface to sal event loop/timers
diff --git a/vcl/source/app/scheduler.cxx b/vcl/source/app/scheduler.cxx
index 73a7451..66f72b6 100644
--- a/vcl/source/app/scheduler.cxx
+++ b/vcl/source/app/scheduler.cxx
@@ -209,6 +209,7 @@ bool Scheduler::ProcessTaskScheduling( IdleRunPolicy eIdleRunPolicy )
     ImplSchedulerData *pPrevMostUrgent = nullptr;
     ImplSchedulerData *pMostUrgent = nullptr;
     sal_uInt64         nMinPeriod = InfiniteTimeoutMs;
+    bool               bIsNestedCall = false;
 
     DBG_TESTSOLARMUTEX();
 
@@ -226,7 +227,10 @@ bool Scheduler::ProcessTaskScheduling( IdleRunPolicy eIdleRunPolicy )
 
         // Skip invoked task
         if ( pSchedulerData->mbInScheduler )
+        {
+            bIsNestedCall = true;
             goto next_entry;
+        }
 
         // Can this task be removed from scheduling?
         if ( !pSchedulerData->mpScheduler )
@@ -239,6 +243,7 @@ bool Scheduler::ProcessTaskScheduling( IdleRunPolicy eIdleRunPolicy )
             pSchedulerData->mpNext = pSVData->mpFreeSchedulerData;
             pSVData->mpFreeSchedulerData = pSchedulerData;
             pSchedulerData = pNextSchedulerData;
+            pSVData->mbTaskRemoved = true;
             continue;
         }
 
@@ -265,6 +270,10 @@ next_entry:
 
     assert( !pSchedulerData );
 
+    // We just have to handle removed tasks for nested calls
+    if ( !bIsNestedCall )
+        pSVData->mbTaskRemoved = false;
+
     if ( pMostUrgent )
     {
         assert( pPrevMostUrgent != pMostUrgent );
@@ -276,6 +285,14 @@ next_entry:
         SAL_INFO_IF( !pMostUrgent->mpScheduler, "vcl.schedule",
             tools::Time::GetSystemTicks() << " " << pMostUrgent << "  tag-rm" );
 
+        // If there were some tasks removed, our list pointers may be invalid,
+        // except pMostUrgent, which is protected by mbInScheduler
+        if ( pSVData->mbTaskRemoved )
+        {
+            nMinPeriod = ImmediateTimeoutMs;
+            pPrevSchedulerData = pMostUrgent;
+        }
+
         // do some simple round-robin scheduling
         // nothing to do, if we're already the last element
         if ( pMostUrgent->mpScheduler )
@@ -285,6 +302,19 @@ next_entry:
 
             if ( pMostUrgent->mpNext )
             {
+                // see ^^^^^
+                if ( pSVData->mbTaskRemoved )
+                {
+                    pPrevMostUrgent = pSVData->mpFirstSchedulerData;
+                    if ( pPrevMostUrgent != pMostUrgent )
+                    {
+                        while ( pPrevMostUrgent && pPrevMostUrgent->mpNext != pMostUrgent )
+                            pPrevMostUrgent = pPrevMostUrgent->mpNext;
+                        assert( pPrevMostUrgent );
+                    }
+                    else
+                        pPrevMostUrgent = nullptr;
+                }
                 if ( pPrevMostUrgent )
                     pPrevMostUrgent->mpNext = pMostUrgent->mpNext;
                 else
commit 0970fba856b755fee0d1c980c84525ff93dc6b19
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Tue Sep 13 11:03:08 2016 +0200

    Round-robin invoked auto tasks
    
    Add some simple round-robin to the task processing, so equal
    priority (auto) tasks won't always be scheduled, if there are
    multiple tasks with the same priority.
    
    Change-Id: If84496bff68aec42d0fa63c2b7e05c3202f67b2c

diff --git a/vcl/source/app/scheduler.cxx b/vcl/source/app/scheduler.cxx
index 48cda62..73a7451 100644
--- a/vcl/source/app/scheduler.cxx
+++ b/vcl/source/app/scheduler.cxx
@@ -64,9 +64,6 @@ void ImplSchedulerData::Invoke()
     if ( !mpScheduler || mbInScheduler )
         return;
 
-    // tdf#92036 Reset the period to avoid re-firing immediately.
-    mpScheduler->mpSchedulerData->mnUpdateTime = tools::Time::GetSystemTicks();
-
     Scheduler *sched = mpScheduler;
 
     // prepare Scheduler Object for deletion after handling
@@ -209,6 +206,7 @@ bool Scheduler::ProcessTaskScheduling( IdleRunPolicy eIdleRunPolicy )
 
     ImplSchedulerData* pSchedulerData = pSVData->mpFirstSchedulerData;
     ImplSchedulerData* pPrevSchedulerData = nullptr;
+    ImplSchedulerData *pPrevMostUrgent = nullptr;
     ImplSchedulerData *pMostUrgent = nullptr;
     sal_uInt64         nMinPeriod = InfiniteTimeoutMs;
 
@@ -256,6 +254,7 @@ bool Scheduler::ProcessTaskScheduling( IdleRunPolicy eIdleRunPolicy )
             // Just account previous most urgent tasks
             if ( pMostUrgent )
                 UpdateMinPeriod( pMostUrgent, nTime, nMinPeriod );
+            pPrevMostUrgent = pPrevSchedulerData;
             pMostUrgent = pSchedulerData;
         }
 
@@ -277,10 +276,28 @@ next_entry:
         SAL_INFO_IF( !pMostUrgent->mpScheduler, "vcl.schedule",
             tools::Time::GetSystemTicks() << " " << pMostUrgent << "  tag-rm" );
 
+        // do some simple round-robin scheduling
+        // nothing to do, if we're already the last element
         if ( pMostUrgent->mpScheduler )
         {
             pMostUrgent->mnUpdateTime = nTime;
             UpdateMinPeriod( pMostUrgent, nTime, nMinPeriod );
+
+            if ( pMostUrgent->mpNext )
+            {
+                if ( pPrevMostUrgent )
+                    pPrevMostUrgent->mpNext = pMostUrgent->mpNext;
+                else
+                    pSVData->mpFirstSchedulerData = pMostUrgent->mpNext;
+                // Invoke() might have changed the task list - find new end
+                while ( pPrevSchedulerData->mpNext )
+                {
+                    pPrevSchedulerData = pPrevSchedulerData->mpNext;
+                    UpdateMinPeriod( pPrevSchedulerData, nTime, nMinPeriod );
+                }
+                pPrevSchedulerData->mpNext = pMostUrgent;
+                pMostUrgent->mpNext = nullptr;
+            }
         }
     }
 
@@ -306,12 +323,12 @@ void Scheduler::Start()
 {
     ImplSVData *const pSVData = ImplGetSVData();
     if (pSVData->mbDeInit)
-    {
         return;
-    }
 
     DBG_TESTSOLARMUTEX();
 
+    if ( mpSchedulerData && mpSchedulerData->mpNext )
+        Scheduler::SetDeletionFlags();
     if ( !mpSchedulerData )
     {
         // insert Scheduler
@@ -324,26 +341,21 @@ void Scheduler::Start()
             mpSchedulerData = new ImplSchedulerData;
         mpSchedulerData->mpScheduler   = this;
         mpSchedulerData->mbInScheduler = false;
+        mpSchedulerData->mpNext = nullptr;
 
         // insert last due to SFX!
-        ImplSchedulerData* pPrev = nullptr;
         ImplSchedulerData* pData = pSVData->mpFirstSchedulerData;
-        while ( pData )
+        if ( pData )
         {
-            pPrev = pData;
-            pData = pData->mpNext;
+            while ( pData->mpNext )
+                pData = pData->mpNext;
+            pData->mpNext = mpSchedulerData;
         }
-        mpSchedulerData->mpNext = nullptr;
-        if ( pPrev )
-            pPrev->mpNext = mpSchedulerData;
         else
             pSVData->mpFirstSchedulerData = mpSchedulerData;
         SAL_INFO( "vcl.schedule", tools::Time::GetSystemTicks()
              << " " << mpSchedulerData <<  "  added      " << *this );
     }
-    else
-        SAL_INFO( "vcl.schedule", tools::Time::GetSystemTicks() << " " << mpSchedulerData
-             <<  "  restarted  " << (int) mePriority << " " << mpDebugName );
 
     assert( mpSchedulerData->mpScheduler == this );
     mpSchedulerData->mnUpdateTime = tools::Time::GetSystemTicks();
diff --git a/vcl/source/app/svapp.cxx b/vcl/source/app/svapp.cxx
index 4a6d491..e4309bb 100644
--- a/vcl/source/app/svapp.cxx
+++ b/vcl/source/app/svapp.cxx
@@ -476,7 +476,7 @@ inline bool ImplYield(bool i_bWait, bool i_bAllEvents, sal_uLong const nReleased
     ImplSVData* pSVData = ImplGetSVData();
 
     SAL_INFO("vcl.schedule", "Enter ImplYield: " << (i_bWait ? "wait" : "no wait") <<
-             ": " << (i_bAllEvents ? "all events" : "one event") << ": " << nReleased);
+             " / " << (i_bAllEvents ? "all events" : "one event") << " / " << nReleased);
 
     if ( i_bWait && Scheduler::HasPendingEvents() )
         i_bWait = false;
diff --git a/vcl/source/app/timer.cxx b/vcl/source/app/timer.cxx
index 54f6f52..f0265c2 100644
--- a/vcl/source/app/timer.cxx
+++ b/vcl/source/app/timer.cxx
@@ -77,7 +77,7 @@ void Timer::SetTimeout( sal_uInt64 nNewTimeout )
     // If timer is active, then renew clock.
     if ( IsActive() )
     {
-        Scheduler::ImplStartTimer(mnTimeout);
+        Start();
     }
 }
 
commit 4ff411ff5e6310af94008eaff9d2287997cb56cd
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Wed Aug 10 12:33:21 2016 +0200

    Readd SAL_INFOs to dump the Scheduler handling
    
    Debug area name is still "vcl.schedule".
    
    Also adds some std::basic_ostream output formaters for Scheduler,
    Timer and Idle classes.
    
    Change-Id: Ia1eab69e76671bd33ce3324c5eb058e4e00dfdd2

diff --git a/include/vcl/scheduler.hxx b/include/vcl/scheduler.hxx
index c1581eb..cf031e9 100644
--- a/include/vcl/scheduler.hxx
+++ b/include/vcl/scheduler.hxx
@@ -21,6 +21,7 @@
 #define INCLUDED_VCL_SCHEDULER_HXX
 
 #include <vcl/dllapi.h>
+#include <ostream>
 
 struct ImplSchedulerData;
 struct ImplSVData;
@@ -54,7 +55,7 @@ private:
     static inline bool HasPendingEvents( const ImplSVData* pSVData, const sal_uInt64 nTime );
 
 protected:
-    ImplSchedulerData*  mpSchedulerData;    /// Pointer to element in scheduler list
+    ImplSchedulerData  *mpSchedulerData;    /// Pointer to element in scheduler list
     const sal_Char     *mpDebugName;        /// Useful for debugging
     SchedulerPriority   mePriority;         /// Scheduler priority
 
@@ -77,7 +78,7 @@ public:
     SchedulerPriority GetPriority() const { return mePriority; }
 
     void            SetDebugName( const sal_Char *pDebugName ) { mpDebugName = pDebugName; }
-    const char     *GetDebugName() const { return mpDebugName; }
+    const sal_Char* GetDebugName() const { return mpDebugName; }
 
     // Call handler
     virtual void    Invoke() = 0;
@@ -112,6 +113,18 @@ inline bool Scheduler::IsActive() const
     return nullptr != mpSchedulerData;
 }
 
+template< typename charT, typename traits >
+inline std::basic_ostream<charT, traits> & operator <<(
+    std::basic_ostream<charT, traits> & stream, const Scheduler& scheduler )
+{
+    stream << scheduler.IsActive() << " " << (int) scheduler.GetPriority();
+    const sal_Char *name = scheduler.GetDebugName();
+    if( nullptr == name )
+        return stream << " (nullptr)";
+    else
+        return stream << " " << name;
+}
+
 #endif // INCLUDED_VCL_SCHEDULER_HXX
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/app/scheduler.cxx b/vcl/source/app/scheduler.cxx
index bddd44c..48cda62 100644
--- a/vcl/source/app/scheduler.cxx
+++ b/vcl/source/app/scheduler.cxx
@@ -23,6 +23,38 @@
 #include <saltimer.hxx>
 #include <svdata.hxx>
 #include <salinst.hxx>
+#include <vcl/idle.hxx>
+
+/**
+ * clang won't compile this in the Timer.hxx header, even with a class Idle
+ * forward definition, due to the incomplete Idle type in the template.
+ * Currently the code is just used in the Scheduler, so we keep it local.
+ *
+ * @see http://clang.llvm.org/compatibility.html#undep_incomplete
+ */
+template< typename charT, typename traits >
+inline std::basic_ostream<charT, traits> & operator <<(
+    std::basic_ostream<charT, traits> & stream, const Timer& timer )
+{
+    bool bIsIdle = (dynamic_cast<const Idle*>( &timer ) != nullptr);
+    stream << (bIsIdle ? "Idle " : "Timer")
+           << " a: " << timer.IsActive() << " p: " << (int) timer.GetPriority();
+    const sal_Char *name = timer.GetDebugName();
+    if ( nullptr == name )
+        stream << " (nullptr)";
+    else
+        stream << " " << name;
+    if ( !bIsIdle )
+        stream << " " << timer.GetTimeout() << "ms";
+    return stream;
+}
+
+template< typename charT, typename traits >
+inline std::basic_ostream<charT, traits> & operator <<(
+    std::basic_ostream<charT, traits> & stream, const Idle& idle )
+{
+    return stream << static_cast<const Timer*>( &idle );
+}
 
 void ImplSchedulerData::Invoke()
 {
@@ -182,8 +214,18 @@ bool Scheduler::ProcessTaskScheduling( IdleRunPolicy eIdleRunPolicy )
 
     DBG_TESTSOLARMUTEX();
 
+    SAL_INFO( "vcl.schedule", "==========  Start  ==========" );
+
     while ( pSchedulerData )
     {
+        const Timer *timer = dynamic_cast<Timer*>( pSchedulerData->mpScheduler );
+        if ( timer )
+            SAL_INFO( "vcl.schedule", pSchedulerData->mbInScheduler << " " << *timer );
+        else if ( pSchedulerData->mpScheduler )
+            SAL_INFO( "vcl.schedule", pSchedulerData->mbInScheduler << " " << *pSchedulerData->mpScheduler );
+        else
+            SAL_INFO( "vcl.schedule", pSchedulerData->mbInScheduler << " (to be deleted)" );
+
         // Skip invoked task
         if ( pSchedulerData->mbInScheduler )
             goto next_entry;
@@ -226,7 +268,14 @@ next_entry:
 
     if ( pMostUrgent )
     {
+        assert( pPrevMostUrgent != pMostUrgent );
+        assert( !pPrevMostUrgent || (pPrevMostUrgent->mpNext == pMostUrgent) );
+
+        SAL_INFO( "vcl.schedule", tools::Time::GetSystemTicks() << " "
+            << pMostUrgent << "  invoke     " << *pMostUrgent->mpScheduler );
         pMostUrgent->Invoke();
+        SAL_INFO_IF( !pMostUrgent->mpScheduler, "vcl.schedule",
+            tools::Time::GetSystemTicks() << " " << pMostUrgent << "  tag-rm" );
 
         if ( pMostUrgent->mpScheduler )
         {
@@ -239,11 +288,14 @@ next_entry:
             && ((eIdleRunPolicy == IdleRunPolicy::IDLE_VIA_TIMER)
                 || (nMinPeriod > ImmediateTimeoutMs)) )
     {
+        SAL_INFO( "vcl.schedule", "Scheduler sleep timeout: " << nMinPeriod );
         ImplStartTimer( nMinPeriod, true );
     }
     else if ( pSVData->mpSalTimer )
         pSVData->mpSalTimer->Stop();
 
+    SAL_INFO( "vcl.schedule", "==========   End   ==========" );
+
     pSVData->mnTimerPeriod = nMinPeriod;
     pSVData->mnLastUpdate = nTime;
 
@@ -286,7 +338,12 @@ void Scheduler::Start()
             pPrev->mpNext = mpSchedulerData;
         else
             pSVData->mpFirstSchedulerData = mpSchedulerData;
+        SAL_INFO( "vcl.schedule", tools::Time::GetSystemTicks()
+             << " " << mpSchedulerData <<  "  added      " << *this );
     }
+    else
+        SAL_INFO( "vcl.schedule", tools::Time::GetSystemTicks() << " " << mpSchedulerData
+             <<  "  restarted  " << (int) mePriority << " " << mpDebugName );
 
     assert( mpSchedulerData->mpScheduler == this );
     mpSchedulerData->mnUpdateTime = tools::Time::GetSystemTicks();
@@ -297,6 +354,8 @@ void Scheduler::Stop()
 {
     if ( !mpSchedulerData )
         return;
+    SAL_INFO( "vcl.schedule", tools::Time::GetSystemTicks()
+          << " " << mpSchedulerData << "  stopped    " << *this );
     Scheduler::SetDeletionFlags();
     assert( !mpSchedulerData );
 }
diff --git a/vcl/source/app/timer.cxx b/vcl/source/app/timer.cxx
index 8e02235..54f6f52 100644
--- a/vcl/source/app/timer.cxx
+++ b/vcl/source/app/timer.cxx
@@ -19,6 +19,7 @@
 
 #include <tools/time.hxx>
 #include <vcl/timer.hxx>
+#include <vcl/idle.hxx>
 #include "saltimer.hxx"
 
 void Timer::SetDeletionFlags()
commit 4ea7bf43358c2dd976ceddec3ef022e916441739
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Wed Sep 14 15:33:54 2016 +0200

    Run Idle tasks immediatly
    
    There is really no reason to wait a millisecond for an idle.
    
    Change-Id: I7665d5f2e7d6ba3e01290a692bbc8e42c36b9986

diff --git a/include/vcl/scheduler.hxx b/include/vcl/scheduler.hxx
index 3d4fde6..c1581eb 100644
--- a/include/vcl/scheduler.hxx
+++ b/include/vcl/scheduler.hxx
@@ -37,6 +37,12 @@ enum class SchedulerPriority
     LOWEST         ///< Low, very idle cleanup tasks
 };
 
+enum class IdleRunPolicy
+{
+    IDLE_VIA_TIMER,  ///< Idles are scheduled via immediate timers (ImmediateTimeoutMs)
+    IDLE_VIA_LOOP    ///< Return indicates processed events, so they are processed in a loop
+};
+
 class VCL_DLLPUBLIC Scheduler
 {
     friend struct ImplSchedulerData;
@@ -52,7 +58,7 @@ protected:
     const sal_Char     *mpDebugName;        /// Useful for debugging
     SchedulerPriority   mePriority;         /// Scheduler priority
 
-    static const SAL_CONSTEXPR sal_uInt64 ImmediateTimeoutMs = 1;
+    static const SAL_CONSTEXPR sal_uInt64 ImmediateTimeoutMs = 0;
     static const SAL_CONSTEXPR sal_uInt64 InfiniteTimeoutMs  = SAL_MAX_UINT64;
 
     static void ImplStartTimer(sal_uInt64 nMS, bool bForce = false);
@@ -82,12 +88,13 @@ public:
     inline bool     IsActive() const;
 
     Scheduler&      operator=( const Scheduler& rScheduler );
-    static void ImplDeInitScheduler();
+    static void     ImplDeInitScheduler();
 
     /// Process one pending Timer with highhest priority
     static void       CallbackTaskScheduling();
     /// Process one pending task ahead of time with highest priority.
-    static bool       ProcessTaskScheduling();
+    static bool       ProcessTaskScheduling( IdleRunPolicy eIdleRunPolicy
+                          = IdleRunPolicy::IDLE_VIA_TIMER );
     /// Process all events until we are idle
     static void       ProcessAllPendingEvents();
     /// Are there any pending tasks in the LO task queue?
diff --git a/vcl/source/app/scheduler.cxx b/vcl/source/app/scheduler.cxx
index 603e1f0..bddd44c 100644
--- a/vcl/source/app/scheduler.cxx
+++ b/vcl/source/app/scheduler.cxx
@@ -119,9 +119,6 @@ void Scheduler::ImplStartTimer( sal_uInt64 nMS, bool bForce )
         pSVData->mpSalTimer->SetCallback(Scheduler::CallbackTaskScheduling);
     }
 
-    if ( !nMS )
-        nMS = 1;
-
     // Only if smaller timeout, to avoid skipping.
     if (nMS < pSVData->mnTimerPeriod || (bForce && nMS != pSVData->mnTimerPeriod) )
     {
@@ -168,10 +165,9 @@ inline void Scheduler::UpdateMinPeriod( ImplSchedulerData *pSchedulerData,
 {
     if ( nMinPeriod > ImmediateTimeoutMs )
         pSchedulerData->mpScheduler->UpdateMinPeriod( nTime, nMinPeriod );
-    assert( nMinPeriod >= ImmediateTimeoutMs );
 }
 
-bool Scheduler::ProcessTaskScheduling()
+bool Scheduler::ProcessTaskScheduling( IdleRunPolicy eIdleRunPolicy )
 {
     ImplSVData*        pSVData = ImplGetSVData();
     sal_uInt64         nTime = tools::Time::GetSystemTicks();
@@ -239,8 +235,12 @@ next_entry:
         }
     }
 
-    if ( nMinPeriod != InfiniteTimeoutMs )
+    if ( nMinPeriod != InfiniteTimeoutMs
+            && ((eIdleRunPolicy == IdleRunPolicy::IDLE_VIA_TIMER)
+                || (nMinPeriod > ImmediateTimeoutMs)) )
+    {
         ImplStartTimer( nMinPeriod, true );
+    }
     else if ( pSVData->mpSalTimer )
         pSVData->mpSalTimer->Stop();
 
diff --git a/vcl/source/app/svapp.cxx b/vcl/source/app/svapp.cxx
index 8fc7821..4a6d491 100644
--- a/vcl/source/app/svapp.cxx
+++ b/vcl/source/app/svapp.cxx
@@ -54,6 +54,7 @@
 #if HAVE_FEATURE_OPENGL
 #include <vcl/opengl/OpenGLWrapper.hxx>
 #endif
+#include <saltimer.hxx>
 
 #include "salinst.hxx"
 #include "salframe.hxx"
@@ -528,16 +529,33 @@ void Application::Reschedule( bool i_bAllEvents )
 
 void Scheduler::ProcessAllPendingEvents()
 {
-    int nSanity = 1000;
-    while( Scheduler::ProcessTaskScheduling() ||
-           ImplYield(false, true, 0) )
+    int nSanity = 1;
+    while( Scheduler::ProcessTaskScheduling( IdleRunPolicy::IDLE_VIA_LOOP )
+        || ImplYield( false, true, 0 ) )
     {
-        if (nSanity-- < 0)
+        if (0 == ++nSanity % 1000)
         {
-            SAL_WARN("vcl.schedule", "Unexpected volume of events to process");
-            break;
+            SAL_WARN("vcl.schedule", "ProcessAllPendingEvents: " << nSanity);
+        }
+    }
+#if OSL_DEBUG_LEVEL > 0
+    ImplSchedulerData* pSchedulerData = ImplGetSVData()->mpFirstSchedulerData;
+    bool bAnyIdle = false;
+    while ( pSchedulerData )
+    {
+        if ( pSchedulerData->mpScheduler && !pSchedulerData->mbInScheduler )
+        {
+            Idle *pIdle = dynamic_cast<Idle*>( pSchedulerData->mpScheduler );
+            if ( pIdle )
+            {
+                bAnyIdle = true;
+                SAL_WARN( "vcl.schedule",  "Unprocessed Idle: " << pSchedulerData->GetDebugName() );
+            }
         }
+        pSchedulerData = pSchedulerData->mpNext;
     }
+    assert( !bAnyIdle );
+#endif
 }
 
 void Application::Yield()
commit 7046da2c25cfd28948552f60d3c34aeb9936c42c
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Wed Sep 14 13:48:02 2016 +0200

    Change Idle to be a Timer subclass
    
    Drops a lot of duplicated code and reflects the Scheduler
    handling of "Idle"s in the source code.
    
    Change-Id: I847592e92e86d15ab1cab168bf0e667322e48048

diff --git a/basctl/source/basicide/baside2b.cxx b/basctl/source/basicide/baside2b.cxx
index e7de865..9af89c6 100644
--- a/basctl/source/basicide/baside2b.cxx
+++ b/basctl/source/basicide/baside2b.cxx
@@ -1325,7 +1325,7 @@ void EditorWindow::DestroyProgress()
 void EditorWindow::ForceSyntaxTimeout()
 {
     aSyntaxIdle.Stop();
-    aSyntaxIdle.GetIdleHdl().Call(&aSyntaxIdle);
+    aSyntaxIdle.Invoke();
 }
 
 // BreakPointWindow
diff --git a/editeng/source/editeng/impedit5.cxx b/editeng/source/editeng/impedit5.cxx
index e091a14..66dae9b 100644
--- a/editeng/source/editeng/impedit5.cxx
+++ b/editeng/source/editeng/impedit5.cxx
@@ -810,7 +810,7 @@ void IdleFormattter::ForceTimeout()
     if ( IsActive() )
     {
         Stop();
-        ((Link<Idle *, void>&)GetIdleHdl()).Call( this );
+        Invoke();
     }
 }
 
diff --git a/framework/source/layoutmanager/layoutmanager.cxx b/framework/source/layoutmanager/layoutmanager.cxx
index bc00a7c..90e2b1b 100644
--- a/framework/source/layoutmanager/layoutmanager.cxx
+++ b/framework/source/layoutmanager/layoutmanager.cxx
@@ -2683,8 +2683,7 @@ throw( uno::RuntimeException, std::exception )
         m_bMustDoLayout = true;
         if ( !m_aAsyncLayoutTimer.IsActive() )
         {
-            const Link<Timer *, void>& aLink = m_aAsyncLayoutTimer.GetTimeoutHdl();
-            aLink.Call( &m_aAsyncLayoutTimer );
+            m_aAsyncLayoutTimer.Invoke();
         }
         if ( m_nLockCount == 0 )
             m_aAsyncLayoutTimer.Start();
diff --git a/include/tools/link.hxx b/include/tools/link.hxx
index 8b65be4..de76c25 100644
--- a/include/tools/link.hxx
+++ b/include/tools/link.hxx
@@ -102,6 +102,7 @@ public:
     { return function_ == other.function_ && instance_ == other.instance_; };
 
     void *GetInstance() const { return instance_; }
+    Stub* GetFunction() const { return function_; }
 
 private:
     Stub * function_;
diff --git a/include/vcl/idle.hxx b/include/vcl/idle.hxx
index 6ddb3ab..5b359f2 100644
--- a/include/vcl/idle.hxx
+++ b/include/vcl/idle.hxx
@@ -20,31 +20,46 @@
 #ifndef INCLUDED_VCL_IDLE_HXX
 #define INCLUDED_VCL_IDLE_HXX
 
-#include <tools/link.hxx>
-#include <vcl/scheduler.hxx>
+#include <vcl/timer.hxx>
 
-class VCL_DLLPUBLIC Idle : public Scheduler
+/**
+ * An idle is a low priority timer to be scheduled immediately.
+ *
+ * Therefore the timeout is set to ImmediateTimeoutMs and the initial,
+ * priority is DEFAULT_IDLE.
+ *
+ * It's - more or less - just a convenience class.
+ */
+class VCL_DLLPUBLIC Idle : public Timer
 {
-protected:
-    Link<Idle *, void> maIdleHdl;          // Callback Link
+private:
+    // Delete all timeout specific functions, we don't want in an Idle
+    void          SetTimeout( sal_uInt64 nTimeoutMs ) = delete;
+    sal_uInt64    GetTimeout() const = delete;
 
+protected:
     virtual bool ReadyForSchedule( const sal_uInt64 nTime ) const override;
     virtual void UpdateMinPeriod( const sal_uInt64 nTime, sal_uInt64 &nMinPeriod ) const override;
 
 public:
     Idle( const sal_Char *pDebugName = nullptr );
-    Idle( const Idle& rIdle );
 
-    virtual void    Start() override;
+    virtual void  Start() override;
 
-    /// Make it possible to associate a callback with this idle handler
-    /// of course, you can also sub-class and override 'Invoke'
-    void            SetIdleHdl( const Link<Idle *, void>& rLink ) { maIdleHdl = rLink; }
-    const Link<Idle *, void>& GetIdleHdl() const { return maIdleHdl; }
-    virtual void Invoke() override;
-    Idle&           operator=( const Idle& rIdle );
+    /**
+     * Convenience function for more readable code
+     *
+     * TODO: actually rename it and it's instances to SetInvokeHandler
+     */
+    inline void   SetIdleHdl( const Link<Idle *, void>& rLink );
 };
 
+inline void Idle::SetIdleHdl( const Link<Idle*, void> &rLink )
+{
+    SetInvokeHandler( Link<Timer*, void>( rLink.GetInstance(),
+        reinterpret_cast< Link<Timer*, void>::Stub* >( rLink.GetFunction()) ) );
+}
+
 #endif // INCLUDED_VCL_IDLE_HXX
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/include/vcl/timer.hxx b/include/vcl/timer.hxx
index 4f7e3d8..2cfa96a 100644
--- a/include/vcl/timer.hxx
+++ b/include/vcl/timer.hxx
@@ -26,9 +26,9 @@
 class VCL_DLLPUBLIC Timer : public Scheduler
 {
 protected:
-    Link<Timer *, void> maTimeoutHdl;          // Callback Link
-    sal_uInt64      mnTimeout;
-    bool            mbAuto;
+    Link<Timer *, void> maInvokeHandler;   ///< Callback Link
+    sal_uInt64          mnTimeout;
+    bool                mbAuto;
 
     virtual void SetDeletionFlags() override;
 
@@ -37,29 +37,45 @@ protected:
 
 public:
     Timer( const sal_Char *pDebugName = nullptr );
-    Timer( const Timer& rTimer );
 
-    /// Make it possible to associate a callback with this timer handler
-    /// of course, you can also sub-class and override 'Invoke'
-    void            SetTimeoutHdl( const Link<Timer *, void>& rLink ) { maTimeoutHdl = rLink; }
-    const Link<Timer *, void>& GetTimeoutHdl() const { return maTimeoutHdl; }
+    /**
+     * Calls the maInvokeHandler with the parameter this.
+     */
+    virtual void    Invoke() override;
+    /**
+     * Calls the maInvokeHandler with the parameter.
+     *
+     * Convenience Invoke function, mainly used to call with nullptr.
+     *
+     * @param arg parameter for the Link::Call function
+     */
+    void            Invoke( Timer *arg );
+    void            SetInvokeHandler( const Link<Timer *, void>& rLink ) { maInvokeHandler = rLink; }
+    bool            HasInvokeHandler() const { return maInvokeHandler.IsSet(); };
+
+    /**
+     * Convenience function for more readable code
+     *
+     * TODO: actually use SetInvokeHandler and drop it
+     */
+    inline void     SetTimeoutHdl( const Link<Timer *, void>& rLink );
+
     void            SetTimeout( sal_uInt64 nTimeoutMs );
     sal_uInt64      GetTimeout() const { return mnTimeout; }
-    virtual void    Invoke() override;
-    void            Timeout() { Invoke(); }
-    Timer&          operator=( const Timer& rTimer );
     virtual void    Start() override;
 };
 
+inline void Timer::SetTimeoutHdl( const Link<Timer *, void>& rLink )
+{
+    SetInvokeHandler( rLink );
+}
+
 /// An auto-timer is a multi-shot timer re-emitting itself at
 /// interval until destroyed.
 class VCL_DLLPUBLIC AutoTimer : public Timer
 {
 public:
-                    AutoTimer();
-                    AutoTimer( const AutoTimer& rTimer );
-
-    AutoTimer&      operator=( const AutoTimer& rTimer );
+    AutoTimer( const sal_Char *pDebugName = nullptr );
 };
 
 #endif // INCLUDED_VCL_TIMER_HXX
diff --git a/sc/source/core/tool/refreshtimer.cxx b/sc/source/core/tool/refreshtimer.cxx
index cb83c4c..954c132 100644
--- a/sc/source/core/tool/refreshtimer.cxx
+++ b/sc/source/core/tool/refreshtimer.cxx
@@ -120,7 +120,7 @@ void ScRefreshTimer::Invoke()
     {
         // now we COULD make the call in another thread ...
         ::osl::MutexGuard aGuard( (*ppControl)->GetMutex() );
-        maTimeoutHdl.Call( this );
+        Timer::Invoke();
         // restart from now on, don't execute immediately again if timed out
         // a second time during refresh
         if ( IsActive() )
diff --git a/solenv/gdb/libreoffice/vcl.py b/solenv/gdb/libreoffice/vcl.py
index 76ca27c..c7b4bf3 100644
--- a/solenv/gdb/libreoffice/vcl.py
+++ b/solenv/gdb/libreoffice/vcl.py
@@ -27,10 +27,11 @@ class ImplSchedulerDataPrinter(object):
     def as_string(self, gdbobj):
         if gdbobj['mpScheduler']:
             sched = gdbobj['mpScheduler'].dereference()
-            if gdbobj['mpScheduler'].dynamic_cast( self.timer_type_ptr ):
-                sched_type = "Timer"
-            elif gdbobj['mpScheduler'].dynamic_cast( self.idle_type_ptr ):
+            timer = gdbobj['mpScheduler'].dynamic_cast( self.timer_type_ptr )
+            if gdbobj['mpScheduler'].dynamic_cast( self.idle_type_ptr ):
                 sched_type = "Idle"
+            elif timer:
+                sched_type = "Timer"
             else:
                 assert sched_type, "Scheduler object neither Timer nor Idle"
             res = "{:7s}{:10s}".format( sched_type, str(sched['mePriority']) )
@@ -39,6 +40,12 @@ class ImplSchedulerDataPrinter(object):
                 res = "{}   (scheduler debug name not set) ({})".format(res, str(sched.dynamic_type))
             else:
                 res = "{} '{}' ({})".format(res, str(name.string()), str(sched.dynamic_type))
+            val_type = gdb.lookup_type(str( sched.dynamic_type )).pointer()
+            timer = gdbobj['mpScheduler'].cast( val_type )
+            if (sched_type == "Timer"):
+                res = "{}: {}ms".format(res, timer['mnTimeout'])
+            else:
+                assert 0 == timer['mnTimeout'], "Idle with timeout == {}".format( timer['mnTimeout'] )
             return res
         else:
             return "(no scheduler - to be deleted)"
diff --git a/vcl/source/app/idle.cxx b/vcl/source/app/idle.cxx
index 433027b..66bf0bf 100644
--- a/vcl/source/app/idle.cxx
+++ b/vcl/source/app/idle.cxx
@@ -20,31 +20,15 @@
 #include <vcl/idle.hxx>
 #include "saltimer.hxx"
 
-void Idle::Invoke()
-{
-    maIdleHdl.Call( this );
-}
-
-Idle& Idle::operator=( const Idle& rIdle )
-{
-    Scheduler::operator=(rIdle);
-    maIdleHdl = rIdle.maIdleHdl;
-    return *this;
-}
-
-Idle::Idle( const sal_Char *pDebugName ) : Scheduler( pDebugName )
+Idle::Idle( const sal_Char *pDebugName )
+    : Timer( pDebugName )
 {
     mePriority = SchedulerPriority::DEFAULT_IDLE;
 }
 
-Idle::Idle( const Idle& rIdle ) : Scheduler(rIdle)
-{
-    maIdleHdl = rIdle.maIdleHdl;
-}
-
 void Idle::Start()
 {
-    Scheduler::Start();
+    Timer::Start();
 
     sal_uInt64 nPeriod = Scheduler::ImmediateTimeoutMs;
     if (Scheduler::GetDeterministicMode())
diff --git a/vcl/source/app/timer.cxx b/vcl/source/app/timer.cxx
index 8a30fe1..8e02235 100644
--- a/vcl/source/app/timer.cxx
+++ b/vcl/source/app/timer.cxx
@@ -46,25 +46,22 @@ void Timer::UpdateMinPeriod( const sal_uInt64 nTime, sal_uInt64 &nMinPeriod ) co
     }
 }
 
-Timer::Timer(const sal_Char *pDebugName) :
-    Scheduler(pDebugName),
-    mnTimeout(ImmediateTimeoutMs),
-    mbAuto(false)
+Timer::Timer(const sal_Char *pDebugName)
+    : Scheduler( pDebugName )
+    , mnTimeout( ImmediateTimeoutMs )
+    , mbAuto( false )
 {
     mePriority = SchedulerPriority::DEFAULT;
 }
 
-Timer::Timer( const Timer& rTimer ) :
-    Scheduler(rTimer),
-    mnTimeout(rTimer.mnTimeout),
-    mbAuto(rTimer.mbAuto)
+void Timer::Invoke()
 {
-    maTimeoutHdl = rTimer.maTimeoutHdl;
+    maInvokeHandler.Call( this );
 }
 
-void Timer::Invoke()
+void Timer::Invoke( Timer *arg )
 {
-    maTimeoutHdl.Call( this );
+    maInvokeHandler.Call( arg );
 }
 
 void Timer::Start()
@@ -83,28 +80,10 @@ void Timer::SetTimeout( sal_uInt64 nNewTimeout )
     }
 }
 
-Timer& Timer::operator=( const Timer& rTimer )
-{
-    Scheduler::operator=(rTimer);
-    maTimeoutHdl = rTimer.maTimeoutHdl;
-    mnTimeout = rTimer.mnTimeout;
-    mbAuto = rTimer.mbAuto;
-    return *this;
-}
-
-AutoTimer::AutoTimer()
+AutoTimer::AutoTimer( const sal_Char *pDebugName )
+    : Timer( pDebugName )
 {
     mbAuto = true;
 }
 
-AutoTimer::AutoTimer( const AutoTimer& rTimer ) : Timer( rTimer )
-{
-    mbAuto = true;
-}
-
-AutoTimer& AutoTimer::operator=( const AutoTimer& rTimer )
-{
-    Timer::operator=( rTimer );
-    return *this;
-}
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/control/edit.cxx b/vcl/source/control/edit.cxx
index 2fc1650..88f663e 100644
--- a/vcl/source/control/edit.cxx
+++ b/vcl/source/control/edit.cxx
@@ -1901,7 +1901,7 @@ void Edit::LoseFocus()
     {
         //notify an update latest when the focus is lost
         mpUpdateDataTimer->Stop();
-        mpUpdateDataTimer->Timeout();
+        mpUpdateDataTimer->Invoke();
     }
 
     if ( !mpSubEdit )
diff --git a/vcl/source/edit/textdata.cxx b/vcl/source/edit/textdata.cxx
index c732314..02378b2 100644
--- a/vcl/source/edit/textdata.cxx
+++ b/vcl/source/edit/textdata.cxx
@@ -293,7 +293,7 @@ void IdleFormatter::DoIdleFormat( TextView* pV, sal_uInt16 nMaxRestarts )
     if ( mnRestarts > nMaxRestarts )
     {
         mnRestarts = 0;
-        ((Link<Idle *, void>&)GetIdleHdl()).Call( this );
+        Invoke();
     }
     else
     {
@@ -307,7 +307,7 @@ void IdleFormatter::ForceTimeout()
     {
         Stop();
         mnRestarts = 0;
-        ((Link<Idle *, void>&)GetIdleHdl()).Call( this );
+        Invoke();
     }
 }
 
diff --git a/vcl/source/window/paint.cxx b/vcl/source/window/paint.cxx
index 7639a0e..308b971 100644
--- a/vcl/source/window/paint.cxx
+++ b/vcl/source/window/paint.cxx
@@ -667,7 +667,7 @@ IMPL_LINK_NOARG(Window, ImplHandleResizeTimerHdl, Idle *, void)
         if( mpWindowImpl->mpFrameData->maPaintIdle.IsActive() )
         {
             mpWindowImpl->mpFrameData->maPaintIdle.Stop();
-            mpWindowImpl->mpFrameData->maPaintIdle.GetIdleHdl().Call( nullptr );
+            mpWindowImpl->mpFrameData->maPaintIdle.Invoke( nullptr );
         }
     }
 }
diff --git a/vcl/source/window/window.cxx b/vcl/source/window/window.cxx
index 2c97ee5..7164899 100644
--- a/vcl/source/window/window.cxx
+++ b/vcl/source/window/window.cxx
@@ -2388,7 +2388,7 @@ Size Window::GetSizePixel() const
     {
         VclPtr<vcl::Window> xWindow( const_cast<Window*>(this) );
         mpWindowImpl->mpFrameData->maResizeIdle.Stop();
-        mpWindowImpl->mpFrameData->maResizeIdle.GetIdleHdl().Call( nullptr );
+        mpWindowImpl->mpFrameData->maResizeIdle.Invoke( nullptr );
         if( xWindow->IsDisposed() )
             return Size(0,0);
     }
commit 15d5002436c73e120f9f2fd0355a1e7141452d9a
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Mon Sep 12 18:24:14 2016 +0200

    Handle all main loop and task events
    
    Change-Id: I75ed5a38b0e24966dafcfdd2ea4cb8afc93a8a0c

diff --git a/vcl/source/app/svapp.cxx b/vcl/source/app/svapp.cxx
index bf6efe3..8fc7821 100644
--- a/vcl/source/app/svapp.cxx
+++ b/vcl/source/app/svapp.cxx
@@ -502,7 +502,14 @@ inline bool ImplYield(bool i_bWait, bool i_bAllEvents, sal_uLong const nReleased
     if (nReleased == 0) // tdf#99383 don't run stuff from ReAcquireSolarMutex
     {
         // Process all Tasks
-        bProcessedEvent = Scheduler::ProcessTaskScheduling() || bProcessedEvent;
+        do
+        {
+            bool bScheduledEevent = Scheduler::ProcessTaskScheduling();
+            bProcessedEvent |= bScheduledEevent;
+            if (!bScheduledEevent)
+                break;
+        }
+        while ( i_bAllEvents );
     }
 
     // flush lazy deleted objects
commit 85c0d50733d0efe1df2ea30ad34b5109986500b8
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Wed Aug 10 12:00:53 2016 +0200

    Reorganize Scheduler priority classes
    
    This is based on glibs classification of tasks, but while glib uses
    an int for more fine grained priority, we stay with our enum.
    
    1. Timers start with DEFAULT priority, which directly corresponds
       with the previous HIGH priority
    2. Idles start with DEFAULT_IDLE priority instead of the previous
       HIGH priority, so idle default becomes "really run when idle".
    
    As RESIZE and REPAINT are special, and the DEFAULTS are set, there
    is just one primary decision for the programmer: should my idle
    run before paint (AKA HIGH_IDLE)?
    
    If we really need a more fine-grained classification, we can add it
    later, or also switch to a real int. As a result, this drops many
    classifications from the code and drastically changes behaviour,
    AKA a mail merge from KDE is now as fast as Gtk+ again.
    
    Change-Id: I498a73fd02d5fb6f5d7e9f742f3bce972de9b1f9

diff --git a/avmedia/source/framework/mediacontrol.cxx b/avmedia/source/framework/mediacontrol.cxx
index 872abab..32d5154 100644
--- a/avmedia/source/framework/mediacontrol.cxx
+++ b/avmedia/source/framework/mediacontrol.cxx
@@ -114,7 +114,7 @@ MediaControl::MediaControl( vcl::Window* pParent, MediaControlStyle eControlStyl
         mpZoomToolBox->SetPaintTransparent( true );
     }
 
-    maIdle.SetPriority( SchedulerPriority::LOW );
+    maIdle.SetPriority( SchedulerPriority::HIGH_IDLE );
     maIdle.SetIdleHdl( LINK( this, MediaControl, implTimeoutHdl ) );
     maIdle.Start();
 }
diff --git a/avmedia/source/framework/soundhandler.cxx b/avmedia/source/framework/soundhandler.cxx
index 753fddc..ece9df4 100644
--- a/avmedia/source/framework/soundhandler.cxx
+++ b/avmedia/source/framework/soundhandler.cxx
@@ -221,7 +221,7 @@ void SAL_CALL SoundHandler::dispatchWithNotification(const css::util::URL&
         // Count this request and initialize self-holder against dying by uno ref count ...
         m_xSelfHold.set(static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY);
         m_xPlayer->start();
-        m_aUpdateIdle.SetPriority( SchedulerPriority::LOWER );
+        m_aUpdateIdle.SetPriority( SchedulerPriority::HIGH_IDLE );
         m_aUpdateIdle.Start();
     }
     catch( css::uno::Exception& e )
diff --git a/avmedia/source/opengl/oglplayer.cxx b/avmedia/source/opengl/oglplayer.cxx
index 50fdf4c..4991758 100644
--- a/avmedia/source/opengl/oglplayer.cxx
+++ b/avmedia/source/opengl/oglplayer.cxx
@@ -123,7 +123,7 @@ bool OGLPlayer::create( const OUString& rURL )
 
     // Set timer
     m_aTimer.SetTimeout(8); // is 125fps enough for anyone ?
-    m_aTimer.SetPriority(SchedulerPriority::LOW);
+    m_aTimer.SetPriority(SchedulerPriority::HIGH_IDLE);
     m_aTimer.SetTimeoutHdl(LINK(this,OGLPlayer,TimerHandler));
 
     return true;
diff --git a/basctl/source/basicide/baside2b.cxx b/basctl/source/basicide/baside2b.cxx
index 33fbf52..e7de865 100644
--- a/basctl/source/basicide/baside2b.cxx
+++ b/basctl/source/basicide/baside2b.cxx
@@ -961,7 +961,6 @@ void EditorWindow::CreateEditEngine()
 
     ImplSetFont();
 
-    aSyntaxIdle.SetPriority( SchedulerPriority::LOWER );
     aSyntaxIdle.SetIdleHdl( LINK( this, EditorWindow, SyntaxTimerHdl ) );
 
     bool bWasDoSyntaxHighlight = bDoSyntaxHighlight;
diff --git a/basctl/source/dlged/dlged.cxx b/basctl/source/dlged/dlged.cxx
index 09fb336..8ca7500 100644
--- a/basctl/source/dlged/dlged.cxx
+++ b/basctl/source/dlged/dlged.cxx
@@ -218,7 +218,6 @@ DlgEditor::DlgEditor (
     m_ClipboardDataFlavorsResource[1].HumanPresentableName = "Dialog 8.0" ;
     m_ClipboardDataFlavorsResource[1].DataType =             cppu::UnoType<Sequence< sal_Int8 >>::get();
 
-    aMarkIdle.SetPriority(SchedulerPriority::LOW);
     aMarkIdle.SetIdleHdl( LINK( this, DlgEditor, MarkTimeout ) );
 
     rWindow.SetMapMode( MapMode( MapUnit::Map100thMM ) );
diff --git a/cui/source/options/optjava.cxx b/cui/source/options/optjava.cxx
index c8bb0cb..8d28ac8 100644
--- a/cui/source/options/optjava.cxx
+++ b/cui/source/options/optjava.cxx
@@ -186,7 +186,6 @@ SvxJavaOptionsPage::SvxJavaOptionsPage( vcl::Window* pParent, const SfxItemSet&
     m_pParameterBtn->SetClickHdl( LINK( this, SvxJavaOptionsPage, ParameterHdl_Impl ) );
     m_pClassPathBtn->SetClickHdl( LINK( this, SvxJavaOptionsPage, ClassPathHdl_Impl ) );
     m_aResetIdle.SetIdleHdl( LINK( this, SvxJavaOptionsPage, ResetHdl_Impl ) );
-    m_aResetIdle.SetPriority(SchedulerPriority::LOWER);
 
     m_pExpertConfigBtn->SetClickHdl( LINK( this, SvxJavaOptionsPage, ExpertConfigHdl_Impl) );
     if (!officecfg::Office::Common::Security::EnableExpertConfiguration::get())
diff --git a/cui/source/tabpages/macroass.cxx b/cui/source/tabpages/macroass.cxx
index af0c0bd..7a73d76 100644
--- a/cui/source/tabpages/macroass.cxx
+++ b/cui/source/tabpages/macroass.cxx
@@ -138,7 +138,7 @@ SfxMacroTabPage::SfxMacroTabPage(vcl::Window* pParent, const Reference< XFrame >
     mpImpl.reset(new SfxMacroTabPage_Impl);
 
     mpImpl->maFillGroupIdle.SetIdleHdl( LINK( this, SfxMacroTabPage, TimeOut_Impl ) );
-    mpImpl->maFillGroupIdle.SetPriority( SchedulerPriority::HIGHEST );
+    mpImpl->maFillGroupIdle.SetPriority( SchedulerPriority::HIGH_IDLE );
     mpImpl->maFillGroupIdle.SetDebugName( "SfxMacroTabPage maFillGroupIdle" );
 
     mpImpl->sStrEvent = get<FixedText>("eventft")->GetText();
diff --git a/dbaccess/source/ui/querydesign/JoinTableView.cxx b/dbaccess/source/ui/querydesign/JoinTableView.cxx
index 52d2de8..07e2bb4 100644
--- a/dbaccess/source/ui/querydesign/JoinTableView.cxx
+++ b/dbaccess/source/ui/querydesign/JoinTableView.cxx
@@ -1063,7 +1063,7 @@ void OJoinTableView::ScrollWhileDragging()
     // resetting timer, if still necessary
     if (bNeedScrollTimer)
     {
-        m_aDragScrollIdle.SetPriority(SchedulerPriority::LOW);
+        m_aDragScrollIdle.SetPriority( SchedulerPriority::HIGH_IDLE );
         m_aDragScrollIdle.Start();
     }
 
diff --git a/desktop/source/deployment/gui/dp_gui_dialog2.cxx b/desktop/source/deployment/gui/dp_gui_dialog2.cxx
index 4c6cd32..c08ba96 100644
--- a/desktop/source/deployment/gui/dp_gui_dialog2.cxx
+++ b/desktop/source/deployment/gui/dp_gui_dialog2.cxx
@@ -1204,7 +1204,6 @@ UpdateRequiredDialog::UpdateRequiredDialog(vcl::Window *pParent, TheExtensionMan
     m_pUpdateBtn->Enable( false );
     m_pCloseBtn->GrabFocus();
 
-    m_aIdle.SetPriority( SchedulerPriority::LOWEST );
     m_aIdle.SetIdleHdl( LINK( this, UpdateRequiredDialog, TimeOutHdl ) );
 }
 
diff --git a/formula/source/ui/dlg/formula.cxx b/formula/source/ui/dlg/formula.cxx
index 4947a36..a1a4af8 100644
--- a/formula/source/ui/dlg/formula.cxx
+++ b/formula/source/ui/dlg/formula.cxx
@@ -1802,7 +1802,6 @@ OUString FormulaDlg::GetMeText() const
 void FormulaDlg::Update()
 {
     m_pImpl->Update();
-    m_pImpl->aIdle.SetPriority(SchedulerPriority::LOWER);
     m_pImpl->aIdle.SetIdleHdl(LINK( this, FormulaDlg, UpdateFocusHdl));
     m_pImpl->aIdle.Start();
 }
diff --git a/formula/source/ui/dlg/funcutl.cxx b/formula/source/ui/dlg/funcutl.cxx
index 1fc5a9e9..8f3ae4f 100644
--- a/formula/source/ui/dlg/funcutl.cxx
+++ b/formula/source/ui/dlg/funcutl.cxx
@@ -409,7 +409,6 @@ RefEdit::RefEdit( vcl::Window* _pParent, vcl::Window* pShrinkModeLabel, WinBits
     , pLabelWidget(pShrinkModeLabel)
 {
     aIdle.SetIdleHdl( LINK( this, RefEdit, UpdateHdl ) );
-    aIdle.SetPriority( SchedulerPriority::LOW );
 }
 
 VCL_BUILDER_DECL_FACTORY(RefEdit)
@@ -478,7 +477,6 @@ void RefEdit::SetReferences( IControlReferenceHandler* pDlg, vcl::Window* pLabel
     if( pDlg )
     {
         aIdle.SetIdleHdl( LINK( this, RefEdit, UpdateHdl ) );
-        aIdle.SetPriority( SchedulerPriority::LOW );
     }
     else
     {
diff --git a/include/vcl/scheduler.hxx b/include/vcl/scheduler.hxx
index 69684b3..3d4fde6 100644
--- a/include/vcl/scheduler.hxx
+++ b/include/vcl/scheduler.hxx
@@ -25,17 +25,16 @@
 struct ImplSchedulerData;
 struct ImplSVData;
 
-enum class SchedulerPriority {
-    HIGHEST      = 0,
-    HIGH         = 1,
-    RESIZE       = 2,
-    REPAINT      = 3,
-    MEDIUM       = 3,
-    POST_PAINT   = 4,
-    DEFAULT_IDLE = 5,
-    LOW          = 6,
-    LOWER        = 7,
-    LOWEST       = 8
+enum class SchedulerPriority
+{
+    HIGHEST,       ///< These events should run very fast!
+    DEFAULT,       ///< Default priority used, e.g. the default timer priority
+    HIGH_IDLE,     ///< Important idle events to be run before processing drawing events
+    RESIZE,        ///< Resize runs before repaint, so we won't paint twice
+    REPAINT,       ///< All repaint events should go in here
+    POST_PAINT,    ///< Everything running directly after painting
+    DEFAULT_IDLE,  ///< Default idle priority
+    LOWEST         ///< Low, very idle cleanup tasks
 };
 
 class VCL_DLLPUBLIC Scheduler
diff --git a/reportdesign/source/ui/report/DesignView.cxx b/reportdesign/source/ui/report/DesignView.cxx
index 6b21aec..4ae321e 100644
--- a/reportdesign/source/ui/report/DesignView.cxx
+++ b/reportdesign/source/ui/report/DesignView.cxx
@@ -117,7 +117,6 @@ ODesignView::ODesignView(   vcl::Window* pParent,
     m_aSplitWin->SetAlign(WindowAlign::Left);
     m_aSplitWin->Show();
 
-    m_aMarkIdle.SetPriority( SchedulerPriority::LOW );
     m_aMarkIdle.SetIdleHdl( LINK( this, ODesignView, MarkTimeout ) );
 }
 
diff --git a/sc/source/core/data/documen2.cxx b/sc/source/core/data/documen2.cxx
index 389611d..ca96bb2 100644
--- a/sc/source/core/data/documen2.cxx
+++ b/sc/source/core/data/documen2.cxx
@@ -249,7 +249,6 @@ ScDocument::ScDocument( ScDocumentMode eMode, SfxObjectShell* pDocShell ) :
     SetLanguage( ScGlobal::eLnge, ScGlobal::eLnge, ScGlobal::eLnge );
 
     aTrackIdle.SetIdleHdl( LINK( this, ScDocument, TrackTimeHdl ) );
-    aTrackIdle.SetPriority( SchedulerPriority::LOW );
 }
 
 sfx2::LinkManager* ScDocument::GetLinkManager()
diff --git a/sc/source/ui/app/scmod.cxx b/sc/source/ui/app/scmod.cxx
index 27e850f..dabceb4 100644
--- a/sc/source/ui/app/scmod.cxx
+++ b/sc/source/ui/app/scmod.cxx
@@ -178,7 +178,6 @@ ScModule::ScModule( SfxObjectFactory* pFact ) :
                                         ERRCODE_AREA_APP2-1,
                                         GetResMgr() );
 
-    aSpellIdle.SetPriority(SchedulerPriority::LOWER);
     aSpellIdle.SetIdleHdl( LINK( this, ScModule, SpellTimerHdl ) );
     aSpellIdle.SetDebugName( "sc::ScModule aSpellIdle" );
 
diff --git a/sc/source/ui/docshell/autostyl.cxx b/sc/source/ui/docshell/autostyl.cxx
index 3888dbc..5a59827 100644
--- a/sc/source/ui/docshell/autostyl.cxx
+++ b/sc/source/ui/docshell/autostyl.cxx
@@ -65,7 +65,7 @@ ScAutoStyleList::ScAutoStyleList(ScDocShell* pShell)
 {
     aTimer.SetTimeoutHdl( LINK( this, ScAutoStyleList, TimerHdl ) );
     aInitIdle.SetIdleHdl( LINK( this, ScAutoStyleList, InitHdl ) );
-    aInitIdle.SetPriority( SchedulerPriority::HIGHEST );
+    aInitIdle.SetPriority( SchedulerPriority::HIGH_IDLE );
 }
 
 ScAutoStyleList::~ScAutoStyleList()
diff --git a/sc/source/ui/miscdlgs/acredlin.cxx b/sc/source/ui/miscdlgs/acredlin.cxx
index 2bbcb8c..5c93ef3 100644
--- a/sc/source/ui/miscdlgs/acredlin.cxx
+++ b/sc/source/ui/miscdlgs/acredlin.cxx
@@ -108,13 +108,11 @@ ScAcceptChgDlg::ScAcceptChgDlg(SfxBindings* pB, SfxChildWindow* pCW, vcl::Window
     m_pAcceptChgCtr = VclPtr<SvxAcceptChgCtr>::Create(get_content_area(), this);
     nAcceptCount=0;
     nRejectCount=0;
-    aReOpenIdle.SetPriority(SchedulerPriority::MEDIUM);
     aReOpenIdle.SetIdleHdl(LINK( this, ScAcceptChgDlg, ReOpenTimerHdl ));
 
     pTPFilter=m_pAcceptChgCtr->GetFilterPage();
     pTPView=m_pAcceptChgCtr->GetViewPage();
     pTheView=pTPView->GetTableControl();
-    aSelectionIdle.SetPriority(SchedulerPriority::LOW);
     aSelectionIdle.SetIdleHdl(LINK( this, ScAcceptChgDlg, UpdateSelectionHdl ));
     aSelectionIdle.SetDebugName( "ScAcceptChgDlg  aSelectionIdle" );
 
diff --git a/sc/source/ui/miscdlgs/anyrefdg.cxx b/sc/source/ui/miscdlgs/anyrefdg.cxx
index 512af1b..c027dc0 100644
--- a/sc/source/ui/miscdlgs/anyrefdg.cxx
+++ b/sc/source/ui/miscdlgs/anyrefdg.cxx
@@ -765,7 +765,6 @@ ScRefHandler::ScRefHandler( vcl::Window &rWindow, SfxBindings* pB, bool bBindRef
         pActiveWin(nullptr)
 {
     m_aHelper.SetWindow(m_rWindow.get());
-    aIdle.SetPriority(SchedulerPriority::LOWER);
     aIdle.SetIdleHdl(LINK( this, ScRefHandler, UpdateFocusHdl));
 
     if( bBindRef ) EnterRefMode();
diff --git a/sc/source/ui/miscdlgs/conflictsdlg.cxx b/sc/source/ui/miscdlgs/conflictsdlg.cxx
index 578efed..73f740c 100644
--- a/sc/source/ui/miscdlgs/conflictsdlg.cxx
+++ b/sc/source/ui/miscdlgs/conflictsdlg.cxx
@@ -421,7 +421,6 @@ ScConflictsDlg::ScConflictsDlg( vcl::Window* pParent, ScViewData* pViewData, ScD
     m_pLbConflicts->SetSelectionMode( SelectionMode::Multiple );
     m_pLbConflicts->SetHighlightRange();
 
-    maSelectionIdle.SetPriority( SchedulerPriority::LOW );
     maSelectionIdle.SetIdleHdl( LINK( this, ScConflictsDlg, UpdateSelectionHdl ) );
     maSelectionIdle.SetDebugName( "ScConflictsDlg maSelectionIdle" );
 
diff --git a/sd/source/ui/dlg/filedlg.cxx b/sd/source/ui/dlg/filedlg.cxx
index b06c780..ad78df5 100644
--- a/sd/source/ui/dlg/filedlg.cxx
+++ b/sd/source/ui/dlg/filedlg.cxx
@@ -129,7 +129,6 @@ IMPL_LINK_NOARG(SdFileDialog_Imp, PlayMusicHdl, void*, void)
             {
                 mxPlayer.set( avmedia::MediaWindow::createPlayer( aUrl, "" ), css::uno::UNO_QUERY_THROW );
                 mxPlayer->start();
-                maUpdateIdle.SetPriority( SchedulerPriority::LOW );
                 maUpdateIdle.Start();
             }
             catch (const css::uno::Exception&)
diff --git a/sd/source/ui/framework/module/ShellStackGuard.cxx b/sd/source/ui/framework/module/ShellStackGuard.cxx
index cf4fe2d..37bcde4 100644
--- a/sd/source/ui/framework/module/ShellStackGuard.cxx
+++ b/sd/source/ui/framework/module/ShellStackGuard.cxx
@@ -72,7 +72,6 @@ ShellStackGuard::ShellStackGuard (Reference<frame::XController>& rxController)
 
         // Prepare the printer polling.
         maPrinterPollingIdle.SetIdleHdl(LINK(this,ShellStackGuard,TimeoutHandler));
-        maPrinterPollingIdle.SetPriority(SchedulerPriority::LOWER);
     }
 }
 
diff --git a/sd/source/ui/view/sdview.cxx b/sd/source/ui/view/sdview.cxx
index 014a67d..43a039f 100644
--- a/sd/source/ui/view/sdview.cxx
+++ b/sd/source/ui/view/sdview.cxx
@@ -143,9 +143,7 @@ View::View(SdDrawDocument& rDrawDoc, OutputDevice* pOutDev,
 
     // Timer for delayed drop (has to be for MAC)
     maDropErrorIdle.SetIdleHdl( LINK(this, View, DropErrorHdl) );
-    maDropErrorIdle.SetPriority(SchedulerPriority::MEDIUM);
     maDropInsertFileIdle.SetIdleHdl( LINK(this, View, DropInsertFileHdl) );
-    maDropInsertFileIdle.SetPriority(SchedulerPriority::MEDIUM);
 }
 
 void View::ImplClearDrawDropMarker()
diff --git a/sfx2/source/appl/appcfg.cxx b/sfx2/source/appl/appcfg.cxx
index c170a65..c7283b2 100644
--- a/sfx2/source/appl/appcfg.cxx
+++ b/sfx2/source/appl/appcfg.cxx
@@ -110,7 +110,7 @@ SfxEventAsyncer_Impl::SfxEventAsyncer_Impl( const SfxEventHint& rHint )
         StartListening( *rHint.GetObjShell() );
     pIdle = new Idle("SfxEventASyncer");
     pIdle->SetIdleHdl( LINK(this, SfxEventAsyncer_Impl, IdleHdl) );
-    pIdle->SetPriority( SchedulerPriority::HIGHEST );
+    pIdle->SetPriority( SchedulerPriority::HIGH_IDLE );
     pIdle->SetDebugName( "sfx::SfxEventAsyncer_Impl pIdle" );
     pIdle->Start();
 }
diff --git a/sfx2/source/appl/newhelp.cxx b/sfx2/source/appl/newhelp.cxx
index 9735cb2..e1a1a94 100644
--- a/sfx2/source/appl/newhelp.cxx
+++ b/sfx2/source/appl/newhelp.cxx
@@ -553,7 +553,6 @@ IndexTabPage_Impl::IndexTabPage_Impl(vcl::Window* pParent, SfxHelpIndexWindow_Im
     m_pOpenBtn->SetClickHdl( LINK( this, IndexTabPage_Impl, OpenHdl ) );
     Link<Timer *, void> aTimeoutLink = LINK( this, IndexTabPage_Impl, TimeoutHdl );
     aFactoryIdle.SetIdleHdl( LINK(this, IndexTabPage_Impl, IdleHdl ));
-    aFactoryIdle.SetPriority(SchedulerPriority::LOWER);
     aKeywordTimer.SetTimeoutHdl( aTimeoutLink );
 }
 
@@ -1433,7 +1432,6 @@ SfxHelpIndexWindow_Impl::SfxHelpIndexWindow_Impl(SfxHelpWindow_Impl* _pParent)
     nMinWidth = ( m_pActiveLB->GetSizePixel().Width() / 2 );
 
     aIdle.SetIdleHdl( LINK( this, SfxHelpIndexWindow_Impl, InitHdl ) );
-    aIdle.SetPriority( SchedulerPriority::LOWER );
     aIdle.Start();
 
     Show();
diff --git a/sfx2/source/control/dispatch.cxx b/sfx2/source/control/dispatch.cxx
index 0b10e0a..c625e29 100644
--- a/sfx2/source/control/dispatch.cxx
+++ b/sfx2/source/control/dispatch.cxx
@@ -449,7 +449,7 @@ void SfxDispatcher::Construct_Impl( SfxDispatcher* pParent )
 
     xImp->xPoster = new SfxHintPoster(aGenLink);
 
-    xImp->aIdle.SetPriority(SchedulerPriority::MEDIUM);
+    xImp->aIdle.SetPriority(SchedulerPriority::HIGH_IDLE );
     xImp->aIdle.SetIdleHdl( LINK(this, SfxDispatcher, EventHdl_Impl ) );
     xImp->aIdle.SetDebugName( "sfx::SfxDispatcher_Impl aIdle" );
 }
@@ -586,8 +586,6 @@ void SfxDispatcher::Pop(SfxShell& rShell, SfxDispatcherPopFlags nMode)
     if(!pSfxApp->IsDowning() && !xImp->aToDoStack.empty())
     {
         // No immediate update is requested
-        xImp->aIdle.SetPriority(SchedulerPriority::MEDIUM);
-        xImp->aIdle.SetIdleHdl( LINK(this, SfxDispatcher, EventHdl_Impl ) );
         xImp->aIdle.Start();
     }
     else
@@ -789,8 +787,6 @@ void SfxDispatcher::DoActivate_Impl(bool bMDI)
     if(!xImp->aToDoStack.empty())
     {
         // No immediate update is requested
-        xImp->aIdle.SetPriority(SchedulerPriority::MEDIUM);
-        xImp->aIdle.SetIdleHdl( LINK(this, SfxDispatcher, EventHdl_Impl ) );
         xImp->aIdle.Start();
     }
 }
diff --git a/svtools/source/contnr/imivctl1.cxx b/svtools/source/contnr/imivctl1.cxx
index a61cd40..60fbd54 100644
--- a/svtools/source/contnr/imivctl1.cxx
+++ b/svtools/source/contnr/imivctl1.cxx
@@ -143,7 +143,7 @@ SvxIconChoiceCtrl_Impl::SvxIconChoiceCtrl_Impl(
     aEditIdle.SetIdleHdl(LINK(this,SvxIconChoiceCtrl_Impl,EditTimeoutHdl));
     aEditIdle.SetDebugName( "svtools::SvxIconChoiceCtrl_Impl aEditIdle" );
 
-    aAutoArrangeIdle.SetPriority( SchedulerPriority::LOW );
+    aAutoArrangeIdle.SetPriority( SchedulerPriority::HIGH_IDLE );
     aAutoArrangeIdle.SetIdleHdl(LINK(this,SvxIconChoiceCtrl_Impl,AutoArrangeHdl));
     aAutoArrangeIdle.SetDebugName( "svtools::SvxIconChoiceCtrl_Impl aAutoArrangeIdle" );
 
@@ -151,11 +151,11 @@ SvxIconChoiceCtrl_Impl::SvxIconChoiceCtrl_Impl(
     aCallSelectHdlIdle.SetIdleHdl( LINK(this,SvxIconChoiceCtrl_Impl,CallSelectHdlHdl));
     aCallSelectHdlIdle.SetDebugName( "svtools::SvxIconChoiceCtrl_Impl aCallSelectHdlIdle" );
 
-    aDocRectChangedIdle.SetPriority( SchedulerPriority::MEDIUM );
+    aDocRectChangedIdle.SetPriority( SchedulerPriority::HIGH_IDLE );
     aDocRectChangedIdle.SetIdleHdl(LINK(this,SvxIconChoiceCtrl_Impl,DocRectChangedHdl));
     aDocRectChangedIdle.SetDebugName( "svtools::SvxIconChoiceCtrl_Impl aDocRectChangedIdle" );
 
-    aVisRectChangedIdle.SetPriority( SchedulerPriority::MEDIUM );
+    aVisRectChangedIdle.SetPriority( SchedulerPriority::HIGH_IDLE );
     aVisRectChangedIdle.SetIdleHdl(LINK(this,SvxIconChoiceCtrl_Impl,VisRectChangedHdl));
     aVisRectChangedIdle.SetDebugName( "svtools::SvxIconChoiceCtrl_Impl aVisRectChangedIdle" );
 
diff --git a/svtools/source/contnr/svimpbox.cxx b/svtools/source/contnr/svimpbox.cxx
index b535552..beab485 100644
--- a/svtools/source/contnr/svimpbox.cxx
+++ b/svtools/source/contnr/svimpbox.cxx
@@ -89,7 +89,7 @@ SvImpLBox::SvImpLBox( SvTreeListBox* pLBView, SvTreeList* pLBTree, WinBits nWinS
     nNodeBmpWidth       = 0;
 
     bAsyncBeginDrag     = false;
-    aAsyncBeginDragIdle.SetPriority( SchedulerPriority::HIGHEST );
+    aAsyncBeginDragIdle.SetPriority( SchedulerPriority::HIGH_IDLE );
     aAsyncBeginDragIdle.SetIdleHdl( LINK(this,SvImpLBox,BeginDragHdl));
     // button animation in listbox
     pActiveButton = nullptr;
diff --git a/svx/source/dialog/_contdlg.cxx b/svx/source/dialog/_contdlg.cxx
index fe877794..e70718c 100644
--- a/svx/source/dialog/_contdlg.cxx
+++ b/svx/source/dialog/_contdlg.cxx
@@ -286,7 +286,6 @@ SvxSuperContourDlg::SvxSuperContourDlg(SfxBindings *_pBindings, SfxChildWindow *
 
     Resize();
 
-    aUpdateIdle.SetPriority( SchedulerPriority::LOW );
     aUpdateIdle.SetIdleHdl( LINK( this, SvxSuperContourDlg, UpdateHdl ) );
 
     aCreateIdle.SetPriority( SchedulerPriority::RESIZE );
diff --git a/svx/source/dialog/imapdlg.cxx b/svx/source/dialog/imapdlg.cxx
index 8afc2c1..6586f7a 100644
--- a/svx/source/dialog/imapdlg.cxx
+++ b/svx/source/dialog/imapdlg.cxx
@@ -203,7 +203,6 @@ SvxIMapDlg::SvxIMapDlg(SfxBindings *_pBindings, SfxChildWindow *pCW, vcl::Window
     m_pCbbTarget->Disable();
     pOwnData->bExecState = false;
 
-    pOwnData->aIdle.SetPriority( SchedulerPriority::LOW );
     pOwnData->aIdle.SetIdleHdl( LINK( this, SvxIMapDlg, UpdateHdl ) );
 
     m_pTbxIMapDlg1->EnableItem( mnActiveId, false );
diff --git a/svx/source/sdr/contact/objectcontactofpageview.cxx b/svx/source/sdr/contact/objectcontactofpageview.cxx
index efeaad6..57fdc7e 100644
--- a/svx/source/sdr/contact/objectcontactofpageview.cxx
+++ b/svx/source/sdr/contact/objectcontactofpageview.cxx
@@ -61,7 +61,7 @@ namespace sdr
             setPreviewRenderer(((SdrPaintView&)rPageWindow.GetPageView().GetView()).IsPreviewRenderer());
 
             // init timer
-            SetPriority(SchedulerPriority::HIGH);
+            SetPriority(SchedulerPriority::HIGH_IDLE);
             Stop();
         }
 
diff --git a/svx/source/sdr/contact/viewobjectcontactofpageobj.cxx b/svx/source/sdr/contact/viewobjectcontactofpageobj.cxx
index 4827c3d..dc274cd 100644
--- a/svx/source/sdr/contact/viewobjectcontactofpageobj.cxx
+++ b/svx/source/sdr/contact/viewobjectcontactofpageobj.cxx
@@ -84,7 +84,7 @@ PagePrimitiveExtractor::PagePrimitiveExtractor(
     setPreviewRenderer(true);
 
     // init timer
-    SetPriority(SchedulerPriority::HIGH);
+    SetPriority(SchedulerPriority::HIGH_IDLE);
     Stop();
 }
 
diff --git a/svx/source/sdr/event/eventhandler.cxx b/svx/source/sdr/event/eventhandler.cxx
index 4f3c6ba..283aa86 100644
--- a/svx/source/sdr/event/eventhandler.cxx
+++ b/svx/source/sdr/event/eventhandler.cxx
@@ -83,7 +83,7 @@ namespace sdr
 
         TimerEventHandler::TimerEventHandler()
         {
-            SetPriority(SchedulerPriority::HIGH);
+            SetPriority(SchedulerPriority::HIGH_IDLE);
             Stop();
         }
 
diff --git a/svx/source/svdraw/svdibrow.cxx b/svx/source/svdraw/svdibrow.cxx
index 44ab835..7247be0 100644
--- a/svx/source/svdraw/svdibrow.cxx
+++ b/svx/source/svdraw/svdibrow.cxx
@@ -1101,7 +1101,7 @@ void SdrItemBrowser::SetDirty()
 {
     if (!bDirty) {
         bDirty = true;
-        aIdle.SetPriority(SchedulerPriority::HIGH);
+        aIdle.SetPriority(SchedulerPriority::HIGH_IDLE);
         aIdle.Start();
     }
 }
diff --git a/svx/source/tbxctrls/grafctrl.cxx b/svx/source/tbxctrls/grafctrl.cxx
index 22cc918..c07f10d 100644
--- a/svx/source/tbxctrls/grafctrl.cxx
+++ b/svx/source/tbxctrls/grafctrl.cxx
@@ -121,7 +121,6 @@ ImplGrafMetricField::ImplGrafMetricField( vcl::Window* pParent, const OUString&
         SetSpinSize( 1 );
     }
 
-    maIdle.SetPriority( SchedulerPriority::LOW );
     maIdle.SetIdleHdl( LINK( this, ImplGrafMetricField, ImplModifyHdl ) );
 }
 
diff --git a/sw/source/uibase/docvw/srcedtw.cxx b/sw/source/uibase/docvw/srcedtw.cxx
index 1e7da99..783b2b2 100644
--- a/sw/source/uibase/docvw/srcedtw.cxx
+++ b/sw/source/uibase/docvw/srcedtw.cxx
@@ -535,7 +535,6 @@ void SwSrcEditWindow::CreateTextEngine()
     m_pOutWin->SetFont( aFont );
     m_pTextEngine->SetFont( aFont );
 
-    m_aSyntaxIdle.SetPriority( SchedulerPriority::LOWER );
     m_aSyntaxIdle.SetIdleHdl( LINK( this, SwSrcEditWindow, SyntaxTimerHdl ) );
 
     m_pTextEngine->EnableUndo( true );
diff --git a/sw/source/uibase/utlui/unotools.cxx b/sw/source/uibase/utlui/unotools.cxx
index 4a89a65..6b9bf20 100644
--- a/sw/source/uibase/utlui/unotools.cxx
+++ b/sw/source/uibase/utlui/unotools.cxx
@@ -84,7 +84,7 @@ SwOneExampleFrame::SwOneExampleFrame( vcl::Window& rWin,
 
     // the controller is asynchronously set
     aLoadedIdle.SetIdleHdl(LINK(this, SwOneExampleFrame, TimeoutHdl));
-    aLoadedIdle.SetPriority(SchedulerPriority::HIGH);
+    aLoadedIdle.SetPriority(SchedulerPriority::HIGH_IDLE);
 
     CreateControl();
 
diff --git a/vcl/osx/salinst.cxx b/vcl/osx/salinst.cxx
index 33a2fb4..3fcdcc8 100644
--- a/vcl/osx/salinst.cxx
+++ b/vcl/osx/salinst.cxx
@@ -105,7 +105,6 @@ void AquaSalInstance::delayedSettingsChanged( bool bInvalidate )
 {
     osl::Guard< comphelper::SolarMutex > aGuard( *mpSalYieldMutex );
     AquaDelayedSettingsChanged* pIdle = new AquaDelayedSettingsChanged( bInvalidate );
-    pIdle->SetPriority( SchedulerPriority::MEDIUM );
     pIdle->Start();
 }
 
diff --git a/vcl/source/app/idle.cxx b/vcl/source/app/idle.cxx
index b5d92ad..433027b 100644
--- a/vcl/source/app/idle.cxx
+++ b/vcl/source/app/idle.cxx
@@ -34,6 +34,7 @@ Idle& Idle::operator=( const Idle& rIdle )
 
 Idle::Idle( const sal_Char *pDebugName ) : Scheduler( pDebugName )
 {
+    mePriority = SchedulerPriority::DEFAULT_IDLE;
 }
 
 Idle::Idle( const Idle& rIdle ) : Scheduler(rIdle)
@@ -50,8 +51,7 @@ void Idle::Start()
     {
         switch (mePriority)
         {
-            case SchedulerPriority::LOW:
-            case SchedulerPriority::LOWER:
+            case SchedulerPriority::DEFAULT_IDLE:
             case SchedulerPriority::LOWEST:
                 nPeriod = Scheduler::InfiniteTimeoutMs;
                 break;
@@ -71,7 +71,7 @@ bool Idle::ReadyForSchedule( const sal_uInt64 /* nTime */ ) const
 
 void Idle::UpdateMinPeriod( const sal_uInt64 /* nTime */, sal_uInt64 &nMinPeriod ) const
 {
-    nMinPeriod = ImmediateTimeoutMs;
+    nMinPeriod = ImmediateTimeoutMs; // don't wait
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/app/scheduler.cxx b/vcl/source/app/scheduler.cxx
index 5ac32b7..603e1f0 100644
--- a/vcl/source/app/scheduler.cxx
+++ b/vcl/source/app/scheduler.cxx
@@ -317,7 +317,7 @@ Scheduler& Scheduler::operator=( const Scheduler& rScheduler )
 Scheduler::Scheduler(const sal_Char *pDebugName):
     mpSchedulerData(nullptr),
     mpDebugName(pDebugName),
-    mePriority(SchedulerPriority::HIGH)
+    mePriority(SchedulerPriority::DEFAULT)
 {
 }
 
diff --git a/vcl/source/app/svapp.cxx b/vcl/source/app/svapp.cxx
index 3e954c3..bf6efe3 100644
--- a/vcl/source/app/svapp.cxx
+++ b/vcl/source/app/svapp.cxx
@@ -459,7 +459,7 @@ void Application::Execute()
         pSVData->maAppData.mnEventTestLimit = 50;
         pSVData->maAppData.mpEventTestingIdle = new Idle("eventtesting");
         pSVData->maAppData.mpEventTestingIdle->SetIdleHdl(LINK(&(pSVData->maAppData), ImplSVAppData, VclEventTestingHdl));
-        pSVData->maAppData.mpEventTestingIdle->SetPriority(SchedulerPriority::MEDIUM);
+        pSVData->maAppData.mpEventTestingIdle->SetPriority(SchedulerPriority::HIGH_IDLE);
         pSVData->maAppData.mpEventTestInput = new SvFileStream("eventtesting", StreamMode::READ);
         pSVData->maAppData.mpEventTestingIdle->Start();
     }
diff --git a/vcl/source/app/timer.cxx b/vcl/source/app/timer.cxx
index fb5d382..8a30fe1 100644
--- a/vcl/source/app/timer.cxx
+++ b/vcl/source/app/timer.cxx
@@ -51,7 +51,7 @@ Timer::Timer(const sal_Char *pDebugName) :
     mnTimeout(ImmediateTimeoutMs),
     mbAuto(false)
 {
-    mePriority = SchedulerPriority::HIGHEST;
+    mePriority = SchedulerPriority::DEFAULT;
 }
 
 Timer::Timer( const Timer& rTimer ) :
diff --git a/vcl/source/edit/textdata.cxx b/vcl/source/edit/textdata.cxx
index 5a3b15c..c732314 100644
--- a/vcl/source/edit/textdata.cxx
+++ b/vcl/source/edit/textdata.cxx
@@ -275,7 +275,7 @@ IdleFormatter::IdleFormatter()
 {
     mpView = nullptr;
     mnRestarts = 0;
-    SetPriority(SchedulerPriority::HIGH);
+    SetPriority(SchedulerPriority::HIGH_IDLE);
 }
 
 IdleFormatter::~IdleFormatter()
diff --git a/vcl/source/window/dockmgr.cxx b/vcl/source/window/dockmgr.cxx
index 560b6d4..6a6f3b2 100644
--- a/vcl/source/window/dockmgr.cxx
+++ b/vcl/source/window/dockmgr.cxx
@@ -88,11 +88,11 @@ ImplDockFloatWin2::ImplDockFloatWin2( vcl::Window* pParent, WinBits nWinBits,
     SetBackground( GetSettings().GetStyleSettings().GetFaceColor() );
 
     maDockIdle.SetIdleHdl( LINK( this, ImplDockFloatWin2, DockTimerHdl ) );
-    maDockIdle.SetPriority( SchedulerPriority::MEDIUM );
+    maDockIdle.SetPriority( SchedulerPriority::HIGH_IDLE );
     maDockIdle.SetDebugName( "vcl::ImplDockFloatWin2 maDockIdle" );
 
     maEndDockIdle.SetIdleHdl( LINK( this, ImplDockFloatWin2, EndDockTimerHdl ) );
-    maEndDockIdle.SetPriority( SchedulerPriority::MEDIUM );
+    maEndDockIdle.SetPriority( SchedulerPriority::HIGH_IDLE );
     maEndDockIdle.SetDebugName( "vcl::ImplDockFloatWin2 maEndDockIdle" );
 }
 
diff --git a/vcl/source/window/dockwin.cxx b/vcl/source/window/dockwin.cxx
index 50fee16..b1cbe25 100644
--- a/vcl/source/window/dockwin.cxx
+++ b/vcl/source/window/dockwin.cxx
@@ -103,7 +103,7 @@ ImplDockFloatWin::ImplDockFloatWin( vcl::Window* pParent, WinBits nWinBits,
     SetBackground();
 
     maDockIdle.SetIdleHdl( LINK( this, ImplDockFloatWin, DockTimerHdl ) );
-    maDockIdle.SetPriority( SchedulerPriority::MEDIUM );
+    maDockIdle.SetPriority( SchedulerPriority::HIGH_IDLE );
     maDockIdle.SetDebugName( "vcl::ImplDockFloatWin maDockIdle" );
 }
 
commit 873506c201eb4e1cbe24fa046ce2282a44fc5b68
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Tue Sep 13 12:20:45 2016 +0200

    Don't wait in Yield with pending events
    
    This re-introduces some functionality of commit
      87199d3829257420429057336283c55be6ae7481
    
    Change-Id: Ie88c2945acb066e312bab7d0f5b2f3b525fa1c4c

diff --git a/include/vcl/scheduler.hxx b/include/vcl/scheduler.hxx
index 66348fa..69684b3 100644
--- a/include/vcl/scheduler.hxx
+++ b/include/vcl/scheduler.hxx
@@ -23,6 +23,7 @@
 #include <vcl/dllapi.h>
 
 struct ImplSchedulerData;
+struct ImplSVData;
 
 enum class SchedulerPriority {
     HIGHEST      = 0,
@@ -45,6 +46,8 @@ private:
     static inline void UpdateMinPeriod( ImplSchedulerData *pSchedulerData,
                                         const sal_uInt64 nTime, sal_uInt64 &nMinPeriod );
 
+    static inline bool HasPendingEvents( const ImplSVData* pSVData, const sal_uInt64 nTime );
+
 protected:
     ImplSchedulerData*  mpSchedulerData;    /// Pointer to element in scheduler list
     const sal_Char     *mpDebugName;        /// Useful for debugging
@@ -88,6 +91,8 @@ public:
     static bool       ProcessTaskScheduling();
     /// Process all events until we are idle
     static void       ProcessAllPendingEvents();
+    /// Are there any pending tasks in the LO task queue?
+    static bool       HasPendingEvents();
 
     /// Control the deterministic mode.  In this mode, two subsequent runs of
     /// LibreOffice fire about the same amount idles.
diff --git a/vcl/source/app/scheduler.cxx b/vcl/source/app/scheduler.cxx
index 0ce90ed..5ac32b7 100644
--- a/vcl/source/app/scheduler.cxx
+++ b/vcl/source/app/scheduler.cxx
@@ -150,6 +150,19 @@ bool Scheduler::GetDeterministicMode()
     return g_bDeterministicMode;
 }
 
+inline bool Scheduler::HasPendingEvents( const ImplSVData* pSVData, const sal_uInt64 nTime )
+{
+   return ( pSVData->mbNeedsReschedule || ((pSVData->mnTimerPeriod != InfiniteTimeoutMs)
+       && (nTime >= pSVData->mnLastUpdate + pSVData->mnTimerPeriod)) );
+}
+
+bool Scheduler::HasPendingEvents()
+{
+    ImplSVData*  pSVData = ImplGetSVData();
+    sal_uInt64   nTime = tools::Time::GetSystemTicks();
+    return HasPendingEvents( pSVData, nTime );
+}
+
 inline void Scheduler::UpdateMinPeriod( ImplSchedulerData *pSchedulerData,
                                         const sal_uInt64 nTime, sal_uInt64 &nMinPeriod )
 {
@@ -162,8 +175,7 @@ bool Scheduler::ProcessTaskScheduling()
 {
     ImplSVData*        pSVData = ImplGetSVData();
     sal_uInt64         nTime = tools::Time::GetSystemTicks();
-    if (!pSVData->mbNeedsReschedule &&
-            (nTime < pSVData->mnLastUpdate + pSVData->mnTimerPeriod) )
+    if ( !HasPendingEvents( pSVData, nTime ) )
         return false;
     pSVData->mbNeedsReschedule = false;
 
diff --git a/vcl/source/app/svapp.cxx b/vcl/source/app/svapp.cxx
index 28b2c96..3e954c3 100644
--- a/vcl/source/app/svapp.cxx
+++ b/vcl/source/app/svapp.cxx
@@ -477,6 +477,9 @@ inline bool ImplYield(bool i_bWait, bool i_bAllEvents, sal_uLong const nReleased
     SAL_INFO("vcl.schedule", "Enter ImplYield: " << (i_bWait ? "wait" : "no wait") <<
              ": " << (i_bAllEvents ? "all events" : "one event") << ": " << nReleased);
 
+    if ( i_bWait && Scheduler::HasPendingEvents() )
+        i_bWait = false;
+
     // TODO: there's a data race here on WNT only because ImplYield may be
     // called without SolarMutex; if we can get rid of LazyDelete (with VclPtr)
     // then the only remaining use of mnDispatchLevel is in OSX specific code
commit 6296419a8c4f227cf117b99744f044a9ff24d75a
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Sun Jul 31 17:31:07 2016 +0200

    Just schedule tasks, if timeout has ellapsed
    
    As the native main loop wakes up on new events and not just by
    timer timeouts, make sure there is really an ellapsed event.
    
    Probably we should just schedule events via the system timeout.
    At least this will prevent expensive re-scheduling.
    
    Change-Id: I248c9b8acb7df026295d10f256871b9fc8d39c07

diff --git a/vcl/inc/svdata.hxx b/vcl/inc/svdata.hxx
index 173c166..27c4cfc 100644
--- a/vcl/inc/svdata.hxx
+++ b/vcl/inc/svdata.hxx
@@ -314,13 +314,17 @@ struct ImplSVData
     Application*            mpApp = nullptr;                // pApp
     VclPtr<WorkWindow>      mpDefaultWin;                   // Default-Window
     bool                    mbDeInit = false;               // Is VCL deinitializing
+
     ImplSchedulerData*      mpFirstSchedulerData = nullptr; // list of all running tasks
     ImplSchedulerData*      mpFreeSchedulerData = nullptr;  // list of all deleted tasks for reuse
+    bool                    mbNeedsReschedule = false;      // was the list of tasks changed?
+    sal_uInt64              mnTimerPeriod = 0;              // current timer period / sleep time
+    sal_uInt64              mnLastUpdate = 0;               // last scheduler time
     SalTimer*               mpSalTimer = nullptr;           // interface to sal event loop/timers
+
     SalI18NImeStatus*       mpImeStatus = nullptr;          // interface to ime status window
     SalSystem*              mpSalSystem = nullptr;          // SalSystem interface
     ResMgr*                 mpResMgr = nullptr;             // SV-Resource-Manager
-    sal_uInt64              mnTimerPeriod = 0;              // current timer period
     ImplSVAppData           maAppData;                      // indepen data for class Application
     ImplSVGDIData           maGDIData;                      // indepen data for Output classes
     ImplSVWinData           maWinData;                      // indepen data for Windows classes
diff --git a/vcl/source/app/scheduler.cxx b/vcl/source/app/scheduler.cxx
index 231258c..0ce90ed 100644
--- a/vcl/source/app/scheduler.cxx
+++ b/vcl/source/app/scheduler.cxx
@@ -133,6 +133,8 @@ void Scheduler::ImplStartTimer( sal_uInt64 nMS, bool bForce )
 void Scheduler::CallbackTaskScheduling()
 {
     // this function is for the saltimer callback
+    ImplSVData* pSVData = ImplGetSVData();
+    pSVData->mbNeedsReschedule = true;
     Scheduler::ProcessTaskScheduling();
 }
 
@@ -159,11 +161,15 @@ inline void Scheduler::UpdateMinPeriod( ImplSchedulerData *pSchedulerData,
 bool Scheduler::ProcessTaskScheduling()
 {
     ImplSVData*        pSVData = ImplGetSVData();
+    sal_uInt64         nTime = tools::Time::GetSystemTicks();
+    if (!pSVData->mbNeedsReschedule &&
+            (nTime < pSVData->mnLastUpdate + pSVData->mnTimerPeriod) )
+        return false;
+    pSVData->mbNeedsReschedule = false;
+
     ImplSchedulerData* pSchedulerData = pSVData->mpFirstSchedulerData;
     ImplSchedulerData* pPrevSchedulerData = nullptr;
     ImplSchedulerData *pMostUrgent = nullptr;
-
-    sal_uInt64         nTime = tools::Time::GetSystemTicks();
     sal_uInt64         nMinPeriod = InfiniteTimeoutMs;
 
     DBG_TESTSOLARMUTEX();
@@ -227,6 +233,7 @@ next_entry:
         pSVData->mpSalTimer->Stop();
 
     pSVData->mnTimerPeriod = nMinPeriod;
+    pSVData->mnLastUpdate = nTime;
 
     return pMostUrgent != nullptr;
 }
@@ -268,7 +275,10 @@ void Scheduler::Start()
         else
             pSVData->mpFirstSchedulerData = mpSchedulerData;
     }
-    mpSchedulerData->mnUpdateTime  = tools::Time::GetSystemTicks();
+
+    assert( mpSchedulerData->mpScheduler == this );
+    mpSchedulerData->mnUpdateTime = tools::Time::GetSystemTicks();
+    pSVData->mbNeedsReschedule = true;
 }
 
 void Scheduler::Stop()
commit e73d4165dd95cc6aae0bf52ba89a3575581d8da8
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Mon Sep 12 17:03:29 2016 +0200

    Drop special idle handling
    
    Idles are just instant, mainly low-priority timers.
    So we'll just schedule by priority.
    
    This basically also reverts the following commit:
    
      commit 06d731428ef6cf93c7333e8228bfb6088853b52f
    
    Change-Id: I446eaea0077f45a5b7daa0aa06dcb80010ac0bd5

diff --git a/desktop/qa/desktop_lib/test_desktop_lib.cxx b/desktop/qa/desktop_lib/test_desktop_lib.cxx
index 11c8db4..a1d4046 100644
--- a/desktop/qa/desktop_lib/test_desktop_lib.cxx
+++ b/desktop/qa/desktop_lib/test_desktop_lib.cxx
@@ -387,7 +387,7 @@ void DesktopLOKTest::testSearchCalc()
         {"SearchItem.Command", uno::makeAny(static_cast<sal_uInt16>(SvxSearchCmd::FIND_ALL))},
     }));
     comphelper::dispatchCommand(".uno:ExecuteSearch", aPropertyValues);
-    Scheduler::ProcessEventsToIdle();
+    Scheduler::ProcessAllPendingEvents();
 
     std::vector<OString> aSelections;
     sal_Int32 nIndex = 0;
@@ -421,7 +421,7 @@ void DesktopLOKTest::testSearchAllNotificationsCalc()
         {"SearchItem.Command", uno::makeAny(static_cast<sal_uInt16>(SvxSearchCmd::FIND_ALL))},
     }));
     comphelper::dispatchCommand(".uno:ExecuteSearch", aPropertyValues);
-    Scheduler::ProcessEventsToIdle();
+    Scheduler::ProcessAllPendingEvents();
 
     // This was 1, make sure that we get no notifications about selection changes during search.
     CPPUNIT_ASSERT_EQUAL(0, m_nSelectionBeforeSearchResult);
@@ -691,7 +691,7 @@ void DesktopLOKTest::testCommandResult()
     // the condition var.
     m_aCommandResultCondition.reset();
     pDocument->pClass->postUnoCommand(pDocument, ".uno:Bold", nullptr, true);
-    Scheduler::ProcessEventsToIdle();
+    Scheduler::ProcessAllPendingEvents();
     m_aCommandResultCondition.wait(aTimeValue);
 
     CPPUNIT_ASSERT(m_aCommandResult.isEmpty());
@@ -701,7 +701,7 @@ void DesktopLOKTest::testCommandResult()
 
     m_aCommandResultCondition.reset();
     pDocument->pClass->postUnoCommand(pDocument, ".uno:Bold", nullptr, true);
-    Scheduler::ProcessEventsToIdle();
+    Scheduler::ProcessAllPendingEvents();
     m_aCommandResultCondition.wait(aTimeValue);
 
     boost::property_tree::ptree aTree;
@@ -724,7 +724,7 @@ void DesktopLOKTest::testWriterComments()
     TimeValue aTimeValue = {2 , 0}; // 2 seconds max
     m_aCommandResultCondition.reset();
     pDocument->pClass->postUnoCommand(pDocument, ".uno:InsertAnnotation", nullptr, true);
-    Scheduler::ProcessEventsToIdle();
+    Scheduler::ProcessAllPendingEvents();
     m_aCommandResultCondition.wait(aTimeValue);
     CPPUNIT_ASSERT(!m_aCommandResult.isEmpty());
     xToolkit->reschedule();

... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list