[Libreoffice-commits] core.git: Branch 'private/jmux/scheduler-fixes' - 8 commits - basic/qa framework/source include/vcl sd/qa sw/source vcl/android vcl/headless vcl/inc vcl/osx vcl/qa vcl/README.scheduler vcl/source vcl/unx vcl/win

Jan-Marek Glogowski glogow at fbihome.de
Wed Oct 18 16:44:24 UTC 2017


Rebased ref, commits from common ancestor:
commit 9ee77a5836d563e5bc838ab04e68bf440ea10860
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Tue Oct 17 13:13:23 2017 +0200

    Implement processing of (all) current LO tasks
    
    Processing all current events is currently just implemented for
    LO user events and system events, which is inconsistent. This
    implements the same functionality in the scheduler to process all
    current LO tasks.
    
    Currently used by DoYield in the Mac and Windows backends.
    
    This also fixes the testTriggerIdleFromIdle test, as this now
    correctly wait-yields until the watchdog kicks in.
    
    Change-Id: Icab8671ceae724a96959fa092ad00bff20c919e1

diff --git a/include/vcl/scheduler.hxx b/include/vcl/scheduler.hxx
index ac429ed33b09..77396b90ae9c 100644
--- a/include/vcl/scheduler.hxx
+++ b/include/vcl/scheduler.hxx
@@ -43,16 +43,22 @@ class VCL_DLLPUBLIC Scheduler final
     static void Lock( sal_uInt32 nLockCount = 1 );
     static sal_uInt32 Unlock( bool bUnlockAll = false );
 
+    static bool ProcessSingleTask( sal_uInt64 nTime,
+                                   ImplSchedulerData ** const pLastDataPtr );
+
 public:
     static constexpr sal_uInt64 ImmediateTimeoutMs = 0;
     static constexpr sal_uInt64 InfiniteTimeoutMs  = SAL_MAX_UINT64;
 
     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();
+    /**
+     * Process one or all current pending tasks, ranked by priority
+     *
+     * @param bHandleAllCurrentEvents process one or all pending tasks
+     * @return true, if any task was processed
+     */
+    static bool       ProcessTaskScheduling( bool bHandleAllCurrentEvents );
     /**
      * Process all events until none is pending
      *
diff --git a/sd/qa/unit/misc-tests.cxx b/sd/qa/unit/misc-tests.cxx
index 60be08f83c09..64890b02129f 100644
--- a/sd/qa/unit/misc-tests.cxx
+++ b/sd/qa/unit/misc-tests.cxx
@@ -105,7 +105,7 @@ sd::DrawDocShellRef SdMiscTest::Load(const OUString& rURL, sal_Int32 nFormat)
     for (int i = 0; i < 1000; i++)
     {
         // Process all Tasks - slide sorter is created here
-        while (Scheduler::ProcessTaskScheduling());
+        Scheduler::ProcessEventsToIdle();
         if ((pSSVS = sd::slidesorter::SlideSorterViewShell::GetSlideSorter(pViewShell->GetViewShellBase())) != nullptr)
             break;
         osl::Thread::wait(std::chrono::milliseconds(100));
@@ -149,7 +149,7 @@ void SdMiscTest::testTdf96708()
 
     // Now wait for timers to trigger creation of auto-layout
     osl::Thread::wait(std::chrono::milliseconds(100));
-    Scheduler::ProcessTaskScheduling();
+    Scheduler::ProcessEventsToIdle();
 
     rSSController.GetClipboard().DoPaste();
     const sal_uInt16 nMasterPageCnt2 = xDocSh->GetDoc()->GetMasterSdPageCount(PageKind::Standard);
diff --git a/vcl/README.scheduler b/vcl/README.scheduler
index 80c14b032c54..ed44b66f5753 100644
--- a/vcl/README.scheduler
+++ b/vcl/README.scheduler
@@ -105,11 +105,8 @@ bool DoYield( bool bWait, bool bAllCurrent )
     if ( !bAllCurrent && bWasEvent )
         return true;
     bWasEvent = ProcessSystemEvents( bAllCurrent, &bWasSchedulerEvent ) || bWasEvent;
-    if ( !bWasSchedulerEvent && IsSchedulerEvent() )
-    {
-        ProcessSchedulerEvent()
-        bWasEvent = true;
-    }
+    if ( (!bWasSchedulerEvent || bAllCurrent) && IsSchedulerEvent() )
+        bWasEvent = ProcessSchedulerEvent( bAllCurrent ) || bWasEvent;
     if ( !bWasEvent && bWait )
     {
         WaitForSystemEvents();
@@ -118,6 +115,11 @@ bool DoYield( bool bWait, bool bAllCurrent )
     return bWasEvent;
 }
 
+Since the Scheduler works priority based, processing all current events
+might return before all current tasks are processed, if the next task
+has a higher priority then a current task, but was started after the
+current time!
+
 == General: main thread deferral ==
 
 Currently for Mac and Windows, we run main thread deferrals by disabling the
diff --git a/vcl/android/androidinst.cxx b/vcl/android/androidinst.cxx
index 3c181ace2ff6..13ce4f83061f 100644
--- a/vcl/android/androidinst.cxx
+++ b/vcl/android/androidinst.cxx
@@ -69,7 +69,7 @@ AndroidSalInstance::~AndroidSalInstance()
 bool AndroidSalInstance::AnyInput( VclInputFlags nType )
 {
     if( nType & VclInputFlags::TIMER )
-        return CheckTimeout( false );
+        return HandleTimeout( HandleTimeoutMode::CheckOnly );
 
     // Unfortunately there is no way to check for a specific type of
     // input being queued. That information is too hidden, sigh.
diff --git a/vcl/headless/svpinst.cxx b/vcl/headless/svpinst.cxx
index 44df78a7df60..478fcfd85c5e 100644
--- a/vcl/headless/svpinst.cxx
+++ b/vcl/headless/svpinst.cxx
@@ -164,7 +164,7 @@ void SvpSalInstance::Wakeup()
 #endif
 }
 
-bool SvpSalInstance::CheckTimeout( bool bExecuteTimers )
+bool SvpSalInstance::HandleTimeout( const HandleTimeoutMode eMode )
 {
     bool bRet = false;
     if( m_aTimeout.tv_sec ) // timer is started
@@ -174,7 +174,7 @@ bool SvpSalInstance::CheckTimeout( bool bExecuteTimers )
         if( aTimeOfDay >= m_aTimeout )
         {
             bRet = true;
-            if( bExecuteTimers )
+            if( eMode != HandleTimeoutMode::CheckOnly )
             {
                 // timed out, update timeout
                 m_aTimeout = aTimeOfDay;
@@ -183,9 +183,8 @@ bool SvpSalInstance::CheckTimeout( bool bExecuteTimers )
                 osl::Guard< comphelper::SolarMutex > aGuard( mpSalYieldMutex.get() );
 
                 // notify
-                ImplSVData* pSVData = ImplGetSVData();
-                if( pSVData->maSchedCtx.mpSalTimer )
-                    pSVData->maSchedCtx.mpSalTimer->CallCallback();
+                bRet = SalTimer::CallCallback(
+                    eMode == HandleTimeoutMode::ProcessAllCurrentTasks );
             }
         }
     }
@@ -269,7 +268,9 @@ bool SvpSalInstance::DoYield(bool bWait, bool bHandleAllCurrentEvents)
     if ( !bHandleAllCurrentEvents &&bEvent )
         return true;
 
-    bEvent = CheckTimeout() || bEvent;
+    bEvent = HandleTimeout( bHandleAllCurrentEvents
+         ? HandleTimeoutMode::ProcessAllCurrentTasks
+         : HandleTimeoutMode::ProcessSingleTask ) || bEvent;
 
     if (bWait && ! bEvent )
     {
@@ -330,7 +331,7 @@ void SvpSalInstance::DoReleaseYield( int nTimeoutMS )
 bool SvpSalInstance::AnyInput( VclInputFlags nType )
 {
     if( nType & VclInputFlags::TIMER )
-        return CheckTimeout( false );
+        return HandleTimeout( HandleTimeoutMode::CheckOnly );
     return false;
 }
 
diff --git a/vcl/inc/headless/svpinst.hxx b/vcl/inc/headless/svpinst.hxx
index ba80960326dc..17ee24cd8107 100644
--- a/vcl/inc/headless/svpinst.hxx
+++ b/vcl/inc/headless/svpinst.hxx
@@ -85,7 +85,7 @@ public:
     inline void             registerFrame( SalFrame* pFrame );
     inline void             deregisterFrame( SalFrame* pFrame );
 
-    bool                    CheckTimeout( bool bExecuteTimers = true );
+    bool                    HandleTimeout( HandleTimeoutMode eMode );
 
     // Frame
     virtual SalFrame*       CreateChildFrame( SystemParentData* pParent, SalFrameStyleFlags nStyle ) override;
diff --git a/vcl/inc/osx/saldata.hxx b/vcl/inc/osx/saldata.hxx
index 357a2df6a74b..fea6d4908ea2 100644
--- a/vcl/inc/osx/saldata.hxx
+++ b/vcl/inc/osx/saldata.hxx
@@ -62,7 +62,6 @@ class SystemFontList;
 class SalData
 {
 public:
-    SALTIMERPROC                                  mpTimerProc;      // timer callback proc
     AquaSalInstance                              *mpInstance;
     std::list<AquaSalFrame*>                      maPresentationFrames;  // list of frames in presentation mode
     SalObject                                    *mpFirstObject;    // pointer of first object window
diff --git a/vcl/inc/osx/saltimer.h b/vcl/inc/osx/saltimer.h
index a9934f280636..97c8db397e9c 100644
--- a/vcl/inc/osx/saltimer.h
+++ b/vcl/inc/osx/saltimer.h
@@ -47,7 +47,7 @@ class AquaSalTimer final : public SalTimer, protected VersionedEvent
     bool        m_bDirectTimeout;    ///< timeout can be processed directly
 
     void queueDispatchTimerEvent( bool bAtStart );
-    void callTimerCallback();
+    bool callTimerCallback( bool bHandleAllCurrentEvents );
 
 public:
     AquaSalTimer();
@@ -58,7 +58,7 @@ public:
 
     void handleStartTimerEvent( NSEvent* pEvent );
     bool handleDispatchTimerEvent( NSEvent* pEvent );
-    void handleTimerElapsed();
+    bool handleTimerElapsed( bool bHandleAllCurrentEvents );
     void handleWindowShouldClose();
 
     bool IsTimerElapsed() const;
diff --git a/vcl/inc/saltimer.hxx b/vcl/inc/saltimer.hxx
index 983e0771ee9b..9fde8de82071 100644
--- a/vcl/inc/saltimer.hxx
+++ b/vcl/inc/saltimer.hxx
@@ -22,8 +22,9 @@
 
 #include <sal/config.h>
 #include <vcl/dllapi.h>
-#include <salwtype.hxx>
-#include <iostream>
+#include <svdata.hxx>
+
+typedef bool (*SALTIMERPROC)( bool bHandleAllCurrentEvents );
 
 /*
  * note: there will be only a single instance of SalTimer
@@ -40,19 +41,32 @@ public:
     virtual ~SalTimer() COVERITY_NOEXCEPT_FALSE;
 
     // AutoRepeat and Restart
-    virtual void            Start( sal_uLong nMS ) = 0;
-    virtual void            Stop() = 0;
+    virtual void Start( sal_uLong nMS ) = 0;
+    virtual void Stop() = 0;
 
     // Callbacks (indepen in \sv\source\app\timer.cxx)
-    void            SetCallback( SALTIMERPROC pProc )
+    void SetCallback( SALTIMERPROC pProc )
     {
         m_pProc = pProc;
     }
 
-    void            CallCallback()
+    bool Timeout( bool bHandleAllCurrentEvents )
     {
+        bool bRet = false;
         if( m_pProc )
-            m_pProc();
+            bRet = m_pProc( bHandleAllCurrentEvents );
+        return bRet;
+    }
+
+    static bool CallCallback( bool bHandleAllCurrentEvents )
+    {
+        ImplSVData* pSVData = ImplGetSVData();
+        bool bRet = false;
+        assert( pSVData );
+        SalTimer *pTimer = pSVData->maSchedCtx.mpSalTimer;
+        if( pTimer )
+            bRet = pTimer->Timeout( bHandleAllCurrentEvents );
+        return bRet;
     }
 };
 
diff --git a/vcl/inc/salwtype.hxx b/vcl/inc/salwtype.hxx
index 1538c8e78a25..e4eca95dcfe8 100644
--- a/vcl/inc/salwtype.hxx
+++ b/vcl/inc/salwtype.hxx
@@ -215,7 +215,8 @@ struct SalQueryCharPositionEvent
 
 typedef bool (*SALFRAMEPROC)( vcl::Window* pInst, SalEvent nEvent, const void* pEvent );
 
-enum class SalObjEvent {
+enum class SalObjEvent
+{
     GetFocus           = 1,
     LoseFocus          = 2,
     ToTop              = 3
@@ -258,7 +259,12 @@ struct SalLongPressEvent
     long mnY;
 };
 
-typedef void (*SALTIMERPROC)();
+enum class HandleTimeoutMode
+{
+    CheckOnly,
+    ProcessSingleTask,
+    ProcessAllCurrentTasks
+};
 
 #endif // INCLUDED_VCL_INC_SALWTYPE_HXX
 
diff --git a/vcl/inc/unx/saldata.hxx b/vcl/inc/unx/saldata.hxx
index 6a7902dbf444..753f6ce8973b 100644
--- a/vcl/inc/unx/saldata.hxx
+++ b/vcl/inc/unx/saldata.hxx
@@ -72,8 +72,6 @@ public:
 
     SalXLib*        GetLib() const { return pXLib_; }
 
-    static void             Timeout();
-
     // X errors
     virtual void            ErrorTrapPush() override;
     virtual bool            ErrorTrapPop( bool bIgnoreError = true ) override;
diff --git a/vcl/inc/unx/saldisp.hxx b/vcl/inc/unx/saldisp.hxx
index 54799149e25c..e8d0f7b67bb9 100644
--- a/vcl/inc/unx/saldisp.hxx
+++ b/vcl/inc/unx/saldisp.hxx
@@ -179,7 +179,7 @@ public:
     virtual void    StartTimer( sal_uLong nMS );
     virtual void    StopTimer();
 
-    virtual bool    CheckTimeout( bool bExecuteTimers = true );
+    virtual bool    HandleTimeout( HandleTimeoutMode eMode );
 
     SalI18N_InputMethod* GetInputMethod() const { return m_pInputMethod; }
     Display*             GetDisplay() const { return m_pDisplay; }
diff --git a/vcl/inc/win/saltimer.h b/vcl/inc/win/saltimer.h
index 61d284d82ddb..ec6b8faebd7a 100644
--- a/vcl/inc/win/saltimer.h
+++ b/vcl/inc/win/saltimer.h
@@ -43,7 +43,7 @@ class WinSalTimer final : public SalTimer, protected VersionedEvent
     void ImplStart( sal_uIntPtr nMS );
     void ImplStop();
     bool ImplHandleTimerEvent( WPARAM aWPARAM );
-    void ImplHandleElapsedTimer();
+    bool ImplHandleElapsedTimer( bool bHandleAllCurrentEvents );
     bool ImplHandle_WM_TIMER( WPARAM aWPARAM );
 
 public:
diff --git a/vcl/osx/saldata.cxx b/vcl/osx/saldata.cxx
index a445e5cfb7ad..b35210bc6754 100644
--- a/vcl/osx/saldata.cxx
+++ b/vcl/osx/saldata.cxx
@@ -36,7 +36,6 @@ static void SAL_CALL releasePool( void* pPool )
 
 SalData::SalData()
 :
-    mpTimerProc( nullptr ),
     mpInstance( nullptr ),
     mpFirstObject( nullptr ),
     mpFirstVD( nullptr ),
diff --git a/vcl/osx/salframeview.mm b/vcl/osx/salframeview.mm
index c0d28fe4bc3f..5798f5b3e7a1 100644
--- a/vcl/osx/salframeview.mm
+++ b/vcl/osx/salframeview.mm
@@ -538,7 +538,7 @@ private:
         if ( bWasLiveResize != bIsLiveResize )
         {
             GetSalData()->mpInstance->mbIsLiveResize = bIsLiveResize;
-            Scheduler::ProcessTaskScheduling();
+            Scheduler::ProcessTaskScheduling( false );
         }
     }
 
diff --git a/vcl/osx/salinst.cxx b/vcl/osx/salinst.cxx
index 922046bcbfe8..8add64168bb3 100644
--- a/vcl/osx/salinst.cxx
+++ b/vcl/osx/salinst.cxx
@@ -603,11 +603,8 @@ SAL_WNODEPRECATED_DECLARATIONS_POP
         while( true );
 
         AquaSalTimer *pTimer = static_cast<AquaSalTimer*>( ImplGetSVData()->maSchedCtx.mpSalTimer );
-        if ( !mbTimerProcessed && pTimer && pTimer->IsDirectTimeout() )
-        {
-            pTimer->handleTimerElapsed();
-            bHadEvent = true;
-        }
+        if ( (!mbTimerProcessed || bHandleAllCurrentEvents) && pTimer && pTimer->IsDirectTimeout() )
+            bHadEvent = pTimer->handleTimerElapsed( bHandleAllCurrentEvents ) || bHadEvent;
 
         // if we had no event yet, wait for one if requested
         if( bWait && ! bHadEvent )
diff --git a/vcl/osx/salnstimer.mm b/vcl/osx/salnstimer.mm
index 9647bb6b87c1..b21e6a7e9695 100644
--- a/vcl/osx/salnstimer.mm
+++ b/vcl/osx/salnstimer.mm
@@ -32,7 +32,7 @@
     (void) pNSTimer;
     AquaSalTimer *pTimer = static_cast<AquaSalTimer*>( ImplGetSVData()->maSchedCtx.mpSalTimer );
     if (pTimer)
-        pTimer->handleTimerElapsed();
+        pTimer->handleTimerElapsed( false );
 }
 
 @end
diff --git a/vcl/osx/saltimer.cxx b/vcl/osx/saltimer.cxx
index af18ae7ea740..60bf9a67e5e1 100644
--- a/vcl/osx/saltimer.cxx
+++ b/vcl/osx/saltimer.cxx
@@ -90,7 +90,10 @@ void AquaSalTimer::Start( sal_uLong nMS )
     }
 
     if ( 0 == nMS && !pSalData->mpInstance->mbIsLiveResize )
-        queueDispatchTimerEvent( NO );
+    {
+        Stop();
+        m_bDirectTimeout = true;
+    }
     else
     {
         NSTimeInterval aTI = double(nMS) / 1000.0;
@@ -136,32 +139,33 @@ void AquaSalTimer::Stop()
     InvalidateEvent();
 }
 
-void AquaSalTimer::callTimerCallback()
+bool AquaSalTimer::callTimerCallback( bool bHandleAllCurrentEvents )
 {
-    ImplSVData* pSVData = ImplGetSVData();
     SolarMutexGuard aGuard;
     m_bDirectTimeout = false;
-    if( pSVData->maSchedCtx.mpSalTimer )
-        pSVData->maSchedCtx.mpSalTimer->CallCallback();
+    return SalTimer::CallCallback( bHandleAllCurrentEvents );
 }
 
-void AquaSalTimer::handleTimerElapsed()
+bool AquaSalTimer::handleTimerElapsed( bool bHandleAllCurrentEvent )
 {
+    bool bRet = false;
+
     if ( m_bDirectTimeout || GetSalData()->mpInstance->mbIsLiveResize )
     {
-        // Stop the timer, as it is just invalidated after the firing function
-        Stop();
-        callTimerCallback();
-    }
-    else
-        queueDispatchTimerEvent( YES );
+         // Stop the timer, as it is just invalidated after the firing function
+         Stop();
+         bRet = callTimerCallback( bHandleAllCurrentEvent );
+     }
+     else
+         queueDispatchTimerEvent( YES );
+    return bRet;
 }
 
 bool AquaSalTimer::handleDispatchTimerEvent( NSEvent *pEvent )
 {
     bool bIsValidEvent = IsValidEventVersion( [pEvent data1] );
     if ( bIsValidEvent )
-        callTimerCallback();
+        callTimerCallback( false );
     return bIsValidEvent;
 }
 
diff --git a/vcl/qa/cppunit/lifecycle.cxx b/vcl/qa/cppunit/lifecycle.cxx
index 26f8796a57ea..18160ccdb056 100644
--- a/vcl/qa/cppunit/lifecycle.cxx
+++ b/vcl/qa/cppunit/lifecycle.cxx
@@ -212,7 +212,7 @@ void LifecycleTest::testFocus()
     xWin->Show();
     xChild->GrabFocus();
     // process asynchronous ToTop
-    Scheduler::ProcessTaskScheduling();
+    Scheduler::ProcessTaskScheduling( false );
     // FIXME: really awful to test focus issues without showing windows.
     // CPPUNIT_ASSERT(xChild->HasFocus());
 }
diff --git a/vcl/qa/cppunit/timer.cxx b/vcl/qa/cppunit/timer.cxx
index 7b712bd76c04..a94d44cb7a15 100644
--- a/vcl/qa/cppunit/timer.cxx
+++ b/vcl/qa/cppunit/timer.cxx
@@ -402,8 +402,10 @@ public:
     {
         Start();
         if (mpOther)
+        {
             mpOther->Start();
-        Application::Yield();
+            Application::Yield();
+        }
         if (mpTriggered)
             *mpTriggered = true;
     }
diff --git a/vcl/source/app/scheduler.cxx b/vcl/source/app/scheduler.cxx
index 8fd26ec79a55..6c3059cedec1 100644
--- a/vcl/source/app/scheduler.cxx
+++ b/vcl/source/app/scheduler.cxx
@@ -236,7 +236,7 @@ void Scheduler::ImplStartTimer(sal_uInt64 nMS, bool bForce, sal_uInt64 nTime)
         rSchedCtx.mnTimerStart = 0;
         rSchedCtx.mnTimerPeriod = InfiniteTimeoutMs;
         rSchedCtx.mpSalTimer = pSVData->mpDefInst->CreateSalTimer();
-        rSchedCtx.mpSalTimer->SetCallback(Scheduler::CallbackTaskScheduling);
+        rSchedCtx.mpSalTimer->SetCallback( Scheduler::ProcessTaskScheduling );
     }
 
     assert(SAL_MAX_UINT64 - nMS >= nTime);
@@ -256,12 +256,6 @@ void Scheduler::ImplStartTimer(sal_uInt64 nMS, bool bForce, sal_uInt64 nTime)
     }
 }
 
-void Scheduler::CallbackTaskScheduling()
-{
-    // this function is for the saltimer callback
-    Scheduler::ProcessTaskScheduling();
-}
-
 static bool g_bDeterministicMode = false;
 
 void Scheduler::SetDeterministicMode(bool bDeterministic)
@@ -325,7 +319,8 @@ static inline ImplSchedulerData* DropSchedulerData(
     return pSchedulerDataNext;
 }
 
-bool Scheduler::ProcessTaskScheduling()
+bool Scheduler::ProcessSingleTask( const sal_uInt64 nTime,
+                                   ImplSchedulerData ** const pLastDataPtr )
 {
     ImplSVData *pSVData = ImplGetSVData();
     ImplSchedulerContext &rSchedCtx = pSVData->maSchedCtx;
@@ -336,25 +331,26 @@ bool Scheduler::ProcessTaskScheduling()
     if ( !rSchedCtx.mbActive || InfiniteTimeoutMs == rSchedCtx.mnTimerPeriod )
         return false;
 
-    sal_uInt64 nTime = tools::Time::GetSystemTicks();
     if ( nTime < rSchedCtx.mnTimerStart + rSchedCtx.mnTimerPeriod )
     {
-        SAL_WARN( "vcl.schedule", "we're too early - restart the timer!" );
+        SAL_WARN_IF( !pLastDataPtr,
+                     "vcl.schedule", "we're too early - restart the timer!" );
         UpdateSystemTimer( rSchedCtx,
                            rSchedCtx.mnTimerStart + rSchedCtx.mnTimerPeriod - nTime,
                            true, nTime );
         return false;
     }
 
-    ImplSchedulerData* pSchedulerData = nullptr;
+    ImplSchedulerData* pSchedulerData = rSchedCtx.mpFirstSchedulerData;
     ImplSchedulerData* pPrevSchedulerData = nullptr;
     ImplSchedulerData *pMostUrgent = nullptr;
     ImplSchedulerData *pPrevMostUrgent = nullptr;
     sal_uInt64         nMinPeriod = InfiniteTimeoutMs;
     sal_uInt64         nMostUrgentPeriod = InfiniteTimeoutMs;
     sal_uInt64         nReadyPeriod = InfiniteTimeoutMs;
+    bool               bAfterLastData = false;
+    bool               bInvokeMostUrgent = ( !pLastDataPtr || *pLastDataPtr );
 
-    pSchedulerData = rSchedCtx.mpFirstSchedulerData;
     while ( pSchedulerData )
     {
         const Timer *timer = dynamic_cast<Timer*>( pSchedulerData->mpTask );
@@ -386,6 +382,8 @@ bool Scheduler::ProcessTaskScheduling()
                     pSchedulerData->mpTask->mpSchedulerData = nullptr;
                 delete pSchedulerData;
             }
+            if ( pLastDataPtr && *pLastDataPtr == pSchedulerData )
+                bAfterLastData = true;
             pSchedulerData = pSchedulerDataNext;
             continue;
         }
@@ -404,11 +402,15 @@ bool Scheduler::ProcessTaskScheduling()
             pPrevMostUrgent = pPrevSchedulerData;
             pMostUrgent = pSchedulerData;
             nMostUrgentPeriod = nReadyPeriod;
+            if ( bAfterLastData || pMostUrgent->mnUpdateTime > nTime )
+                bInvokeMostUrgent = false;
         }
         else if ( nMinPeriod > nReadyPeriod )
             nMinPeriod = nReadyPeriod;
 
 next_entry:
+        if ( pLastDataPtr && *pLastDataPtr == pSchedulerData )
+            bAfterLastData = true;
         pPrevSchedulerData = pSchedulerData;
         pSchedulerData = pSchedulerData->mpNext;
     }
@@ -417,8 +419,19 @@ next_entry:
         SAL_INFO("vcl.schedule", "Calculated minimum timeout as " << nMinPeriod );
     UpdateSystemTimer( rSchedCtx, nMinPeriod, true, nTime );
 
-    if ( pMostUrgent )
+    if ( pMostUrgent && !bInvokeMostUrgent )
+    {
+        nReadyPeriod = pMostUrgent->mpTask->UpdateMinPeriod( nMinPeriod, nTime );
+        if ( nMinPeriod > nReadyPeriod )
+            nMinPeriod = nReadyPeriod;
+        UpdateSystemTimer( rSchedCtx, nMinPeriod, false, nTime );
+        pMostUrgent = nullptr;
+    }
+    else if ( pMostUrgent )
     {
+        if ( pLastDataPtr && *pLastDataPtr == pMostUrgent )
+            *pLastDataPtr = nullptr;
+
         SAL_INFO( "vcl.schedule", tools::Time::GetSystemTicks() << " "
                   << pMostUrgent << "  invoke-in  " << *pMostUrgent->mpTask );
 
@@ -460,6 +473,8 @@ next_entry:
             AppendSchedulerData( rSchedCtx, pSchedulerData );
             UpdateSystemTimer( rSchedCtx, ImmediateTimeoutMs, true,
                                tools::Time::GetSystemTicks() );
+            if ( pLastDataPtr && *pLastDataPtr && rSchedCtx.mpLastSchedulerData != *pLastDataPtr )
+                *pLastDataPtr = rSchedCtx.mpLastSchedulerData;
         }
         else
         {
@@ -484,6 +499,26 @@ next_entry:
     return !!pMostUrgent;
 }
 
+bool Scheduler::ProcessTaskScheduling( bool bHandleAllCurrentEvents )
+{
+    sal_uInt64 nTime = tools::Time::GetSystemTicks();
+    bool bWasEvent = false, bAnyEvent = false;
+    ImplSchedulerData *pLastData = ImplGetSVData()->maSchedCtx.mpLastSchedulerData;
+    ImplSchedulerData ** const pLastDataPtr = bHandleAllCurrentEvents ? &pLastData : nullptr;
+    SAL_INFO_IF( bHandleAllCurrentEvents, "vcl.schedule", tools::Time::GetSystemTicks()
+        << " process all current events - start" );
+    do
+    {
+        bWasEvent = ProcessSingleTask( nTime, pLastDataPtr );
+        if ( !bAnyEvent && bWasEvent )
+            bAnyEvent = bWasEvent;
+    }
+    while ( bWasEvent && bHandleAllCurrentEvents );
+    SAL_INFO_IF( bHandleAllCurrentEvents, "vcl.schedule", tools::Time::GetSystemTicks()
+        << " process all current events - done" );
+    return bAnyEvent;
+}
+
 void Task::StartTimer( sal_uInt64 nMS )
 {
     Scheduler::ImplStartTimer( nMS, false, tools::Time::GetSystemTicks() );
diff --git a/vcl/unx/generic/app/saldata.cxx b/vcl/unx/generic/app/saldata.cxx
index 4ad2c02db54f..39bab4f7368f 100644
--- a/vcl/unx/generic/app/saldata.cxx
+++ b/vcl/unx/generic/app/saldata.cxx
@@ -560,13 +560,6 @@ void X11SalData::XError( Display *pDisplay, XErrorEvent *pEvent )
     m_aXErrorHandlerStack.back().m_bWas = true;
 }
 
-void X11SalData::Timeout()
-{
-    ImplSVData* pSVData = ImplGetSVData();
-    if( pSVData->maSchedCtx.mpSalTimer )
-        pSVData->maSchedCtx.mpSalTimer->CallCallback();
-}
-
 struct YieldEntry
 {
     int         fd;         // file descriptor for reading
@@ -622,7 +615,7 @@ void SalXLib::Remove( int nFD )
     }
 }
 
-bool SalXLib::CheckTimeout( bool bExecuteTimers )
+bool SalXLib::HandleTimeout( HandleTimeoutMode eMode )
 {
     bool bRet = false;
     if( m_aTimeout.tv_sec ) // timer is started
@@ -632,7 +625,7 @@ bool SalXLib::CheckTimeout( bool bExecuteTimers )
         if( aTimeOfDay >= m_aTimeout )
         {
             bRet = true;
-            if( bExecuteTimers )
+            if( eMode != HandleTimeoutMode::CheckOnly )
             {
                 // timed out, update timeout
                 m_aTimeout = aTimeOfDay;
@@ -644,7 +637,7 @@ bool SalXLib::CheckTimeout( bool bExecuteTimers )
                 */
                 m_aTimeout += m_nTimeoutMS;
                 // notify
-                X11SalData::Timeout();
+                bRet = SalTimer::CallCallback( eMode == HandleTimeoutMode::ProcessAllCurrentTasks );
             }
         }
     }
@@ -655,10 +648,7 @@ bool
 SalXLib::Yield( bool bWait, bool bHandleAllCurrentEvents )
 {
     // check for timeouts here if you want to make screenshots
-    static char* p_prioritize_timer = getenv ("SAL_HIGHPRIORITY_REPAINT");
     bool bHandledEvent = false;
-    if (p_prioritize_timer != nullptr)
-        bHandledEvent = CheckTimeout();
 
     const int nMaxEvents = bHandleAllCurrentEvents ? 100 : 1;
 
@@ -724,8 +714,9 @@ SalXLib::Yield( bool bWait, bool bHandleAllCurrentEvents )
     }
 
     // usually handle timeouts here (as in 5.2)
-    if (p_prioritize_timer == nullptr)
-        bHandledEvent = CheckTimeout() || bHandledEvent;
+    bHandledEvent = HandleTimeout( bHandleAllCurrentEvents
+                  ? HandleTimeoutMode::ProcessAllCurrentTasks
+                  : HandleTimeoutMode::ProcessSingleTask ) || bHandledEvent;
 
     // handle wakeup events.
     if ((nFound > 0) && FD_ISSET(m_pTimeoutFDS[0], &ReadFDS))
diff --git a/vcl/unx/generic/app/salinst.cxx b/vcl/unx/generic/app/salinst.cxx
index 0d30e1d17a99..b1615b052e94 100644
--- a/vcl/unx/generic/app/salinst.cxx
+++ b/vcl/unx/generic/app/salinst.cxx
@@ -145,7 +145,8 @@ bool X11SalInstance::AnyInput(VclInputFlags nType)
     Display *pDisplay  = vcl_sal::getSalDisplay(pData)->GetDisplay();
     bool bRet = false;
 
-    if( (nType & VclInputFlags::TIMER) && (mpXLib && mpXLib->CheckTimeout(false)) )
+    if( (nType & VclInputFlags::TIMER)
+            && mpXLib && mpXLib->HandleTimeout( HandleTimeoutMode::CheckOnly ) )
         bRet = true;
 
     if( !bRet && XPending(pDisplay) )
diff --git a/vcl/unx/gtk/gtkdata.cxx b/vcl/unx/gtk/gtkdata.cxx
index 97541eed22c1..6f849f212eaa 100644
--- a/vcl/unx/gtk/gtkdata.cxx
+++ b/vcl/unx/gtk/gtkdata.cxx
@@ -728,9 +728,7 @@ extern "C" {
 
         sal_gtk_timeout_defer( pTSource );
 
-        ImplSVData* pSVData = ImplGetSVData();
-        if( pSVData->maSchedCtx.mpSalTimer )
-            pSVData->maSchedCtx.mpSalTimer->CallCallback();
+        SalTimer::CallCallback( false );
 
         return G_SOURCE_REMOVE;
     }
diff --git a/vcl/unx/gtk3/gtk3gtkdata.cxx b/vcl/unx/gtk3/gtk3gtkdata.cxx
index f4d41a53d2c0..bf69882d181f 100644
--- a/vcl/unx/gtk3/gtk3gtkdata.cxx
+++ b/vcl/unx/gtk3/gtk3gtkdata.cxx
@@ -693,9 +693,7 @@ extern "C" {
 
         sal_gtk_timeout_defer( pTSource );
 
-        ImplSVData* pSVData = ImplGetSVData();
-        if( pSVData->maSchedCtx.mpSalTimer )
-            pSVData->maSchedCtx.mpSalTimer->CallCallback();
+        SalTimer::CallCallback( false );
 
         return G_SOURCE_REMOVE;
     }
diff --git a/vcl/unx/kde4/KDEXLib.cxx b/vcl/unx/kde4/KDEXLib.cxx
index 43e055a2c0bb..8be84f99a925 100644
--- a/vcl/unx/kde4/KDEXLib.cxx
+++ b/vcl/unx/kde4/KDEXLib.cxx
@@ -42,6 +42,8 @@
 
 #include "KDESalDisplay.hxx"
 
+#include <saltimer.hxx>
+
 #if KDE4_HAVE_GLIB
 #include "KDE4FilePicker.hxx"
 #include "tst_exclude_socket_notifiers.moc"
@@ -356,11 +358,11 @@ void KDEXLib::StopTimer()
     timeoutTimer.stop();
 }
 
-bool KDEXLib::CheckTimeout( bool bExecuteTimers )
+bool KDEXLib::HandleTimeout( HandleTimeoutMode eMode )
 {
     if( !m_isGlibEventLoopType )
-        return SalXLib::CheckTimeout( bExecuteTimers );
-    assert( !bExecuteTimers );
+        return SalXLib::HandleTimeout( eMode );
+    assert( eMode == HandleTimeoutMode::CheckOnly );
     return m_bTimedOut;
 }
 
@@ -376,7 +378,7 @@ void KDEXLib::customEvent(QEvent* e)
     if( e->type() == m_timerEventId )
     {
         m_bTimedOut = false;
-        X11SalData::Timeout();
+        SalTimer::CallCallback( false );
     }
 }
 
diff --git a/vcl/unx/kde4/KDEXLib.hxx b/vcl/unx/kde4/KDEXLib.hxx
index 452aae8b3286..e2d6d6b024fb 100644
--- a/vcl/unx/kde4/KDEXLib.hxx
+++ b/vcl/unx/kde4/KDEXLib.hxx
@@ -84,7 +84,7 @@ public:
         virtual void Remove( int fd ) override;
         virtual void StartTimer( sal_uLong nMS ) override;
         virtual void StopTimer() override;
-        virtual bool CheckTimeout( bool bExecuteTimers = true ) override;
+        virtual bool HandleTimeout( HandleTimeoutMode eMode ) override;
         virtual void Wakeup() override;
         void TriggerUserEventProcessing();
 
diff --git a/vcl/win/app/salinst.cxx b/vcl/win/app/salinst.cxx
index f2a998ee78e7..ceb3651b4353 100644
--- a/vcl/win/app/salinst.cxx
+++ b/vcl/win/app/salinst.cxx
@@ -512,11 +512,8 @@ bool ImplSalYield( bool bWait, bool bHandleAllCurrentEvents )
     // event loop with timeout messages.
     // We ensure we never handle more then one timeout per call.
     // This way we'll always process a normal system message.
-    if ( !bWasTimeoutMsg && pTimer && pTimer->IsDirectTimeout() )
-    {
-        pTimer->ImplHandleElapsedTimer();
-        bWasMsg = true;
-    }
+    if ( (!bWasTimeoutMsg || bHandleAllCurrentEvents) && pTimer && pTimer->IsDirectTimeout() )
+        bWasMsg = pTimer->ImplHandleElapsedTimer( bHandleAllCurrentEvents ) || bWasMsg;
 
     if ( bHandleAllCurrentEvents )
         nLastTicks = nCurTicks;
diff --git a/vcl/win/app/saltimer.cxx b/vcl/win/app/saltimer.cxx
index 9c67e841956e..2098e757d953 100644
--- a/vcl/win/app/saltimer.cxx
+++ b/vcl/win/app/saltimer.cxx
@@ -147,15 +147,16 @@ void CALLBACK SalTimerProc(PVOID data, BOOLEAN)
     }
 }
 
-void WinSalTimer::ImplHandleElapsedTimer()
+bool WinSalTimer::ImplHandleElapsedTimer( bool bHandleAllCurrentEvents )
 {
     // Test for MouseLeave
     SalTestMouseLeave();
 
     m_bDirectTimeout = false;
     ImplSalYieldMutexAcquireWithWait();
-    CallCallback();
+    bool bRet = Timeout( bHandleAllCurrentEvents );
     ImplSalYieldMutexRelease();
+    return bRet;
 }
 
 bool WinSalTimer::ImplHandleTimerEvent( const WPARAM aWPARAM )
@@ -163,9 +164,7 @@ bool WinSalTimer::ImplHandleTimerEvent( const WPARAM aWPARAM )
     assert( aWPARAM <= SAL_MAX_INT32 );
     if ( !IsValidEventVersion( static_cast<sal_Int32>( aWPARAM ) ) )
         return false;
-
-    ImplHandleElapsedTimer();
-    return true;
+    return ImplHandleElapsedTimer( false );
 }
 
 void WinSalTimer::SetForceRealTimer( const bool bVal )
@@ -185,9 +184,7 @@ bool WinSalTimer::ImplHandle_WM_TIMER( const WPARAM aWPARAM )
     assert( m_aWmTimerId == aWPARAM );
     if ( !(m_aWmTimerId == aWPARAM && m_bDirectTimeout && m_bForceRealTimer) )
         return false;
-
-    ImplHandleElapsedTimer();
-    return true;
+    return ImplHandleElapsedTimer( false );
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit 337e90fb59eb5c828f356d22f5ed2d80493b625f
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Mon Oct 16 17:04:24 2017 +0200

    WIN scheduler cleanup and refactoring
    
    Replace a lot of duplicated case code with macros.
    Some minor constifications of function parameters.
    
    I restrained from shorten the SAL_MSG_* via preprocessor concat,
    so a grep will still find the whole names.
    
    Change-Id: If1f2477fc8817b4ae7816e807154e35004bb4da9

diff --git a/vcl/inc/osx/salinst.h b/vcl/inc/osx/salinst.h
index 01e50af77b99..a80af4fb5ee7 100644
--- a/vcl/inc/osx/salinst.h
+++ b/vcl/inc/osx/salinst.h
@@ -63,6 +63,8 @@ public:
 
 class AquaSalInstance : public SalInstance, public SalUserEventList
 {
+    friend class AquaSalFrame;
+
     bool RunInMainYield( bool bHandleAllCurrentEvents );
 
     virtual void TriggerUserEventProcessing() override;
@@ -81,7 +83,6 @@ public:
 
     static std::list<const ApplicationEvent*> aAppEventList;
 
-public:
     AquaSalInstance();
     virtual ~AquaSalInstance() override;
 
@@ -136,9 +137,6 @@ public:
     // this is needed to avoid duplicate open events through a) command line and b) NSApp's openFile
     static bool isOnCommandLine( const OUString& );
 
-public:
-    friend class AquaSalFrame;
-
     void delayedSettingsChanged( bool bInvalidate );
 
     // Is this the NSAppThread?
diff --git a/vcl/inc/win/saldata.hxx b/vcl/inc/win/saldata.hxx
index 0f3e05b8f31a..659fd68f7dda 100644
--- a/vcl/inc/win/saldata.hxx
+++ b/vcl/inc/win/saldata.hxx
@@ -180,8 +180,8 @@ bool ImplHandleSalObjSysCharMsg( HWND hWnd, WPARAM wParam, LPARAM lParam );
 bool ImplHandleGlobalMsg( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam, LRESULT& rlResult );
 
 WinSalObject* ImplFindSalObject( HWND hWndChild );
-bool ImplSalPreDispatchMsg( MSG* pMsg );
-void ImplSalPostDispatchMsg( MSG* pMsg, LRESULT nDispatchResult );
+bool ImplSalPreDispatchMsg( const MSG* pMsg );
+void ImplSalPostDispatchMsg( const MSG* pMsg );
 
 void ImplSalLogFontToFontW( HDC hDC, const LOGFONTW& rLogFont, vcl::Font& rFont );
 
diff --git a/vcl/inc/win/saltimer.h b/vcl/inc/win/saltimer.h
index b7d1a1e0d0f1..61d284d82ddb 100644
--- a/vcl/inc/win/saltimer.h
+++ b/vcl/inc/win/saltimer.h
@@ -25,7 +25,7 @@
 class WinSalTimer final : public SalTimer, protected VersionedEvent
 {
     // for access to Impl* functions
-    friend LRESULT CALLBACK SalComWndProc( HWND, UINT nMsg, WPARAM wParam, LPARAM lParam, int& rDef );
+    friend LRESULT CALLBACK SalComWndProc( HWND, UINT nMsg, WPARAM wParam, LPARAM lParam, bool& rDef );
     // for access to GetNextVersionedEvent
     friend void CALLBACK SalTimerProc( PVOID data, BOOLEAN );
     // for access to ImplHandleElapsedTimer
diff --git a/vcl/osx/vclnsapp.mm b/vcl/osx/vclnsapp.mm
index 4dd8ceac8169..23b22c360eeb 100644
--- a/vcl/osx/vclnsapp.mm
+++ b/vcl/osx/vclnsapp.mm
@@ -66,7 +66,7 @@ SAL_WNODEPRECATED_DECLARATIONS_PUSH
     NSEvent* pEvent = [NSEvent otherEventWithType: NSApplicationDefined
                                location: NSZeroPoint
                                modifierFlags: 0
-                               timestamp: 0
+                               timestamp: [[NSProcessInfo processInfo] systemUptime]
                                windowNumber: 0
                                context: nil
                                subtype: AquaSalInstance::AppExecuteSVMain
diff --git a/vcl/win/app/salinst.cxx b/vcl/win/app/salinst.cxx
index 5fcca5cde5b4..f2a998ee78e7 100644
--- a/vcl/win/app/salinst.cxx
+++ b/vcl/win/app/salinst.cxx
@@ -569,124 +569,108 @@ bool WinSalInstance::DoYield(bool bWait, bool bHandleAllCurrentEvents)
     return bDidWork;
 }
 
-LRESULT CALLBACK SalComWndProc( HWND, UINT nMsg, WPARAM wParam, LPARAM lParam, int& rDef )
+#define CASE_NOYIELDLOCK( salmsg, function ) \
+    case salmsg: \
+        assert( !pInst->mbNoYieldLock ); \
+        pInst->mbNoYieldLock = true; \
+        function; \
+        pInst->mbNoYieldLock = false; \
+        break;
+
+#define CASE_NOYIELDLOCK_RESULT( salmsg, function ) \
+    case salmsg: \
+        assert( !pInst->mbNoYieldLock ); \
+        pInst->mbNoYieldLock = true; \
+        nRet = reinterpret_cast<LRESULT>( function ); \
+        pInst->mbNoYieldLock = false; \
+        break;
+
+LRESULT CALLBACK SalComWndProc( HWND, UINT nMsg, WPARAM wParam, LPARAM lParam, bool& rDef )
 {
     LRESULT nRet = 0;
     WinSalInstance *pInst = GetSalData()->mpInstance;
+    WinSalTimer *const pTimer = static_cast<WinSalTimer*>( ImplGetSVData()->maSchedCtx.mpSalTimer );
 
     switch ( nMsg )
     {
         case SAL_MSG_THREADYIELD:
             assert( !(bool)wParam );
-            nRet = static_cast<LRESULT>(ImplSalYield( false, (bool)lParam ));
-            rDef = FALSE;
+            nRet = static_cast<LRESULT>(ImplSalYield(
+                false, static_cast<bool>( lParam ) ));
             break;
+
         case SAL_MSG_STARTTIMER:
         {
             sal_uInt64 nTime = tools::Time::GetSystemTicks();
-            if ( nTime < (sal_uInt64) lParam )
-                nTime = (sal_uInt64) lParam - nTime;
+            if ( nTime < static_cast<sal_uInt64>( lParam ) )
+                nTime = static_cast<sal_uInt64>( lParam ) - nTime;
             else
                 nTime = 0;
-            static_cast<WinSalTimer*>(ImplGetSVData()->maSchedCtx.mpSalTimer)->ImplStart( nTime );
-            rDef = FALSE;
+            assert( pTimer != nullptr );
+            pTimer->ImplStart( nTime );
             break;
         }
+
         case SAL_MSG_STOPTIMER:
-            static_cast<WinSalTimer*>(ImplGetSVData()->maSchedCtx.mpSalTimer)->ImplStop();
-            break;
-        case SAL_MSG_CREATEFRAME:
-            assert( !pInst->mbNoYieldLock );
-            pInst->mbNoYieldLock = true;
-            nRet = reinterpret_cast<LRESULT>(ImplSalCreateFrame( GetSalData()->mpInstance, reinterpret_cast<HWND>(lParam), (SalFrameStyleFlags)wParam ));
-            pInst->mbNoYieldLock = false;
-            rDef = FALSE;
-            break;
-        case SAL_MSG_RECREATEHWND:
-            assert( !pInst->mbNoYieldLock );
-            pInst->mbNoYieldLock = true;
-            nRet = reinterpret_cast<LRESULT>(ImplSalReCreateHWND( reinterpret_cast<HWND>(wParam), reinterpret_cast<HWND>(lParam), false ));
-            pInst->mbNoYieldLock = false;
-            rDef = FALSE;
-            break;
-        case SAL_MSG_RECREATECHILDHWND:
-            assert( !pInst->mbNoYieldLock );
-            pInst->mbNoYieldLock = true;
-            nRet = reinterpret_cast<LRESULT>(ImplSalReCreateHWND( reinterpret_cast<HWND>(wParam), reinterpret_cast<HWND>(lParam), true ));
-            pInst->mbNoYieldLock = false;
-            rDef = FALSE;
-            break;
-        case SAL_MSG_DESTROYFRAME:
-            assert( !pInst->mbNoYieldLock );
-            pInst->mbNoYieldLock = true;
-            delete reinterpret_cast<SalFrame*>(lParam);
-            pInst->mbNoYieldLock = false;
-            rDef = FALSE;
+            assert( pTimer != nullptr );
+            pTimer->ImplStop();
             break;
+
+        CASE_NOYIELDLOCK_RESULT( SAL_MSG_CREATEFRAME, ImplSalCreateFrame( GetSalData()->mpInstance,
+            reinterpret_cast<HWND>(lParam), static_cast<SalFrameStyleFlags>(wParam)) )
+        CASE_NOYIELDLOCK_RESULT( SAL_MSG_RECREATEHWND, ImplSalReCreateHWND(
+            reinterpret_cast<HWND>(wParam), reinterpret_cast<HWND>(lParam), false) )
+        CASE_NOYIELDLOCK_RESULT( SAL_MSG_RECREATECHILDHWND, ImplSalReCreateHWND(
+            reinterpret_cast<HWND>(wParam), reinterpret_cast<HWND>(lParam), true) )
+        CASE_NOYIELDLOCK( SAL_MSG_DESTROYFRAME, delete reinterpret_cast<SalFrame*>(lParam) )
+
         case SAL_MSG_DESTROYHWND:
-            //We only destroy the native window here. We do NOT destroy the SalFrame contained
-            //in the structure (GetWindowPtr()).
+            // We only destroy the native window here. We do NOT destroy the SalFrame contained
+            // in the structure (GetWindowPtr()).
             if (DestroyWindow(reinterpret_cast<HWND>(lParam)) == 0)
             {
                 OSL_FAIL("DestroyWindow failed!");
-                //Failure: We remove the SalFrame from the window structure. So we avoid that
+                // Failure: We remove the SalFrame from the window structure. So we avoid that
                 // the window structure may contain an invalid pointer, once the SalFrame is deleted.
-               SetWindowPtr(reinterpret_cast<HWND>(lParam), nullptr);
+                SetWindowPtr(reinterpret_cast<HWND>(lParam), nullptr);
             }
-            rDef = FALSE;
-            break;
-        case SAL_MSG_CREATEOBJECT:
-            assert( !pInst->mbNoYieldLock );
-            pInst->mbNoYieldLock = true;
-            nRet = reinterpret_cast<LRESULT>(ImplSalCreateObject( GetSalData()->mpInstance, reinterpret_cast<WinSalFrame*>(lParam) ));
-            pInst->mbNoYieldLock = false;
-            rDef = FALSE;
-            break;
-        case SAL_MSG_DESTROYOBJECT:
-            assert( !pInst->mbNoYieldLock );
-            pInst->mbNoYieldLock = true;
-            delete reinterpret_cast<SalObject*>(lParam);
-            pInst->mbNoYieldLock = false;
-            rDef = FALSE;
-            break;
-        case SAL_MSG_GETDC:
-            assert( !pInst->mbNoYieldLock );
-            pInst->mbNoYieldLock = true;
-            nRet = reinterpret_cast<LRESULT>(GetDCEx( reinterpret_cast<HWND>(wParam), nullptr, DCX_CACHE ));
-            pInst->mbNoYieldLock = false;
-            rDef = FALSE;
-            break;
-        case SAL_MSG_RELEASEDC:
-            assert( !pInst->mbNoYieldLock );
-            pInst->mbNoYieldLock = true;
-            ReleaseDC( reinterpret_cast<HWND>(wParam), reinterpret_cast<HDC>(lParam) );
-            pInst->mbNoYieldLock = false;
-            rDef = FALSE;
             break;
+
+        CASE_NOYIELDLOCK_RESULT( SAL_MSG_CREATEOBJECT, ImplSalCreateObject(
+            GetSalData()->mpInstance, reinterpret_cast<WinSalFrame*>(lParam)) )
+        CASE_NOYIELDLOCK( SAL_MSG_DESTROYOBJECT, delete reinterpret_cast<SalObject*>(lParam) )
+        CASE_NOYIELDLOCK_RESULT( SAL_MSG_GETDC, GetDCEx(
+            reinterpret_cast<HWND>(wParam), nullptr, DCX_CACHE) )
+        CASE_NOYIELDLOCK( SAL_MSG_RELEASEDC, ReleaseDC(
+            reinterpret_cast<HWND>(wParam), reinterpret_cast<HDC>(lParam)) )
+
         case SAL_MSG_TIMER_CALLBACK:
-        {
-            WinSalTimer *const pTimer = static_cast<WinSalTimer*>( ImplGetSVData()->maSchedCtx.mpSalTimer );
             assert( pTimer != nullptr );
             nRet = static_cast<LRESULT>( pTimer->ImplHandleTimerEvent( wParam ) );
-            nDef = FALSE;
             break;
-        }
+
         case WM_TIMER:
-        {
-            WinSalTimer *const pTimer = static_cast<WinSalTimer*>( ImplGetSVData()->maSchedCtx.mpSalTimer );
             assert( pTimer != nullptr );
             nRet = static_cast<LRESULT>( pTimer->ImplHandle_WM_TIMER( wParam ) );
-            nDef = FALSE;
             break;
-        }
+
+        case SAL_MSG_DUMMY:
+            break;
+
+        default:
+            rDef = TRUE;
+            break;
     }
 
     return nRet;
 }
 
+#undef CASE_NOYIELDLOCK
+#undef CASE_NOYIELDLOCK_RESULT
+
 LRESULT CALLBACK SalComWndProcW( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam )
 {
-    int bDef = TRUE;
+    bool bDef = FALSE;
     LRESULT nRet = 0;
     __try
     {
diff --git a/vcl/win/window/salobj.cxx b/vcl/win/window/salobj.cxx
index 172f61e923d3..75e406c33f61 100644
--- a/vcl/win/window/salobj.cxx
+++ b/vcl/win/window/salobj.cxx
@@ -145,7 +145,7 @@ LRESULT CALLBACK SalSysMsgProc( int nCode, WPARAM wParam, LPARAM lParam )
     return CallNextHookEx( pSalData->mhSalObjMsgHook, nCode, wParam, lParam );
 }
 
-bool ImplSalPreDispatchMsg( MSG* pMsg )
+bool ImplSalPreDispatchMsg( const MSG* pMsg )
 {
     // Used for Unicode and none Unicode
     SalData*        pSalData = GetSalData();
@@ -231,10 +231,10 @@ bool ImplSalPreDispatchMsg( MSG* pMsg )
     return FALSE;
 }
 
-void ImplSalPostDispatchMsg( MSG* pMsg, LRESULT /* nDispatchResult */ )
+void ImplSalPostDispatchMsg( const MSG* pMsg )
 {
     // Used for Unicode and none Unicode
-    SalData*        pSalData = GetSalData();
+    SalData *pSalData = GetSalData();
 
     if ( (pMsg->message == WM_KEYDOWN) || (pMsg->message == WM_KEYUP) )
     {
commit cf2cc439af9e0949af6397462d0b3178ac797db3
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Wed Oct 18 17:00:53 2017 +0200

    OSX implement direct timeout processing
    
    Basically works in the same way then in the Windows backend.
    
    Change-Id: If48e2b55f037563839a5e716830ce75ed78381e4

diff --git a/vcl/inc/osx/salinst.h b/vcl/inc/osx/salinst.h
index 272cfc722d64..01e50af77b99 100644
--- a/vcl/inc/osx/salinst.h
+++ b/vcl/inc/osx/salinst.h
@@ -77,6 +77,7 @@ public:
     osl::Condition                          maWaitingYieldCond;
     bool                                    mbIsLiveResize;
     bool                                    mbNoYieldLock;
+    bool                                    mbTimerProcessed;
 
     static std::list<const ApplicationEvent*> aAppEventList;
 
diff --git a/vcl/inc/osx/saltimer.h b/vcl/inc/osx/saltimer.h
index c860ad5cbdda..a9934f280636 100644
--- a/vcl/inc/osx/saltimer.h
+++ b/vcl/inc/osx/saltimer.h
@@ -44,6 +44,7 @@ public:
 class AquaSalTimer final : public SalTimer, protected VersionedEvent
 {
     NSTimer    *m_pRunningTimer;
+    bool        m_bDirectTimeout;    ///< timeout can be processed directly
 
     void queueDispatchTimerEvent( bool bAtStart );
     void callTimerCallback();
@@ -56,13 +57,19 @@ public:
     void Stop() override;
 
     void handleStartTimerEvent( NSEvent* pEvent );
-    void handleDispatchTimerEvent( NSEvent* pEvent );
+    bool handleDispatchTimerEvent( NSEvent* pEvent );
     void handleTimerElapsed();
     void handleWindowShouldClose();
 
     bool IsTimerElapsed() const;
+    inline bool IsDirectTimeout() const;
 };
 
+inline bool AquaSalTimer::IsDirectTimeout() const
+{
+    return m_bDirectTimeout;
+}
+
 #endif // INCLUDED_VCL_INC_OSX_SALTIMER_H
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/osx/salinst.cxx b/vcl/osx/salinst.cxx
index d475f30275b0..922046bcbfe8 100644
--- a/vcl/osx/salinst.cxx
+++ b/vcl/osx/salinst.cxx
@@ -379,6 +379,7 @@ AquaSalInstance::AquaSalInstance()
     : mnActivePrintJobs( 0 )
     , mbIsLiveResize( false )
     , mbNoYieldLock( false )
+    , mbTimerProcessed( false )
 {
     mpSalYieldMutex = new SalYieldMutex;
     mpSalYieldMutex->acquire();
@@ -452,9 +453,12 @@ void AquaSalInstance::handleAppDefinedEvent( NSEvent* pEvent )
         break;
     }
     case DispatchTimerEvent:
-        if ( pTimer )
-            pTimer->handleDispatchTimerEvent( pEvent );
+    {
+        AquaSalInstance *pInst = GetSalData()->mpInstance;
+        if ( pTimer && pInst )
+            pInst->mbTimerProcessed = pTimer->handleDispatchTimerEvent( pEvent );
         break;
+    }
 #if !HAVE_FEATURE_MACOSX_SANDBOX
     case AppleRemoteControlEvent: // Defined in <apple_remote/RemoteMainController.h>
     {
@@ -570,6 +574,8 @@ bool AquaSalInstance::DoYield(bool bWait, bool bHandleAllCurrentEvents)
         // handle available events
         NSEvent* pEvent = nil;
         NSTimeInterval now = [[NSProcessInfo processInfo] systemUptime];
+        mbTimerProcessed = false;
+
         do
         {
             SolarMutexReleaser aReleaser;
@@ -596,6 +602,13 @@ SAL_WNODEPRECATED_DECLARATIONS_POP
         }
         while( true );
 
+        AquaSalTimer *pTimer = static_cast<AquaSalTimer*>( ImplGetSVData()->maSchedCtx.mpSalTimer );
+        if ( !mbTimerProcessed && pTimer && pTimer->IsDirectTimeout() )
+        {
+            pTimer->handleTimerElapsed();
+            bHadEvent = true;
+        }
+
         // if we had no event yet, wait for one if requested
         if( bWait && ! bHadEvent )
         {
diff --git a/vcl/osx/saltimer.cxx b/vcl/osx/saltimer.cxx
index 34d46f08728a..af18ae7ea740 100644
--- a/vcl/osx/saltimer.cxx
+++ b/vcl/osx/saltimer.cxx
@@ -74,6 +74,7 @@ SAL_WNODEPRECATED_DECLARATIONS_POP
 void AquaSalTimer::queueDispatchTimerEvent( bool bAtStart )
 {
     Stop();
+    m_bDirectTimeout = true;
     ImplNSAppPostEvent( AquaSalInstance::DispatchTimerEvent,
                         bAtStart, GetNextEventVersion() );
 }
@@ -139,13 +140,14 @@ void AquaSalTimer::callTimerCallback()
 {
     ImplSVData* pSVData = ImplGetSVData();
     SolarMutexGuard aGuard;
+    m_bDirectTimeout = false;
     if( pSVData->maSchedCtx.mpSalTimer )
         pSVData->maSchedCtx.mpSalTimer->CallCallback();
 }
 
 void AquaSalTimer::handleTimerElapsed()
 {
-    if ( GetSalData()->mpInstance->mbIsLiveResize )
+    if ( m_bDirectTimeout || GetSalData()->mpInstance->mbIsLiveResize )
     {
         // Stop the timer, as it is just invalidated after the firing function
         Stop();
@@ -155,10 +157,12 @@ void AquaSalTimer::handleTimerElapsed()
         queueDispatchTimerEvent( YES );
 }
 
-void AquaSalTimer::handleDispatchTimerEvent( NSEvent *pEvent )
+bool AquaSalTimer::handleDispatchTimerEvent( NSEvent *pEvent )
 {
-    if ( IsValidEventVersion( [pEvent data1] ) )
+    bool bIsValidEvent = IsValidEventVersion( [pEvent data1] );
+    if ( bIsValidEvent )
         callTimerCallback();
+    return bIsValidEvent;
 }
 
 void AquaSalTimer::handleStartTimerEvent( NSEvent* pEvent )
@@ -177,8 +181,8 @@ void AquaSalTimer::handleStartTimerEvent( NSEvent* pEvent )
 
 bool AquaSalTimer::IsTimerElapsed() const
 {
-    assert( !(ExistsValidEvent() && m_pRunningTimer) );
-    if ( ExistsValidEvent() )
+    assert( !((ExistsValidEvent() || m_bDirectTimeout) && m_pRunningTimer) );
+    if ( ExistsValidEvent() || m_bDirectTimeout )
         return true;
     if ( !m_pRunningTimer )
         return false;
commit ac8d05a0f8bf9dc275833068461c6b714fb70ea7
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Mon Oct 16 16:59:45 2017 +0200

    WIN guarantee direct timeout handling
    
    The code did acccount processing of an invaild timeout system
    message as a valid timeout event.
    
    Change-Id: I3c31f8b9cec592631b4089411163dadecffde816

diff --git a/vcl/README.scheduler b/vcl/README.scheduler
index 17648ae3b439..80c14b032c54 100644
--- a/vcl/README.scheduler
+++ b/vcl/README.scheduler
@@ -89,6 +89,35 @@ can be added to the scheduler reasonably.
 
 = Implementation details =
 
+== General: event priority for DoYield ==
+
+There are three types of events, with different priority:
+
+1. LO user events
+2. System events
+3. LO Scheduler event
+
+They should be processed according to the following code:
+
+bool DoYield( bool bWait, bool bAllCurrent )
+{
+    bool bWasEvent = ProcessUserEvents( bAllCurrent );
+    if ( !bAllCurrent && bWasEvent )
+        return true;
+    bWasEvent = ProcessSystemEvents( bAllCurrent, &bWasSchedulerEvent ) || bWasEvent;
+    if ( !bWasSchedulerEvent && IsSchedulerEvent() )
+    {
+        ProcessSchedulerEvent()
+        bWasEvent = true;
+    }
+    if ( !bWasEvent && bWait )
+    {
+        WaitForSystemEvents();
+        bWasEvent = true;
+    }
+    return bWasEvent;
+}
+
 == General: main thread deferral ==
 
 Currently for Mac and Windows, we run main thread deferrals by disabling the
diff --git a/vcl/inc/win/saltimer.h b/vcl/inc/win/saltimer.h
index d762b51b6716..b7d1a1e0d0f1 100644
--- a/vcl/inc/win/saltimer.h
+++ b/vcl/inc/win/saltimer.h
@@ -42,9 +42,9 @@ class WinSalTimer final : public SalTimer, protected VersionedEvent
 
     void ImplStart( sal_uIntPtr nMS );
     void ImplStop();
-    void ImplHandleTimerEvent( WPARAM aWPARAM );
+    bool ImplHandleTimerEvent( WPARAM aWPARAM );
     void ImplHandleElapsedTimer();
-    void ImplHandle_WM_TIMER( WPARAM aWPARAM );
+    bool ImplHandle_WM_TIMER( WPARAM aWPARAM );
 
 public:
     WinSalTimer();
diff --git a/vcl/win/app/salinst.cxx b/vcl/win/app/salinst.cxx
index d1fc8adb6272..5fcca5cde5b4 100644
--- a/vcl/win/app/salinst.cxx
+++ b/vcl/win/app/salinst.cxx
@@ -459,17 +459,15 @@ void WinSalInstance::AcquireYieldMutex( sal_uInt32 nCount )
     mpSalYieldMutex->acquire( nCount );
 }
 
-static void ImplSalDispatchMessage( MSG* pMsg )
+static LRESULT ImplSalDispatchMessage( const MSG* pMsg )
 {
     SalData* pSalData = GetSalData();
-    if ( pSalData->mpFirstObject )
-    {
-        if ( ImplSalPreDispatchMsg( pMsg ) )
-            return;
-    }
+    if ( pSalData->mpFirstObject && ImplSalPreDispatchMsg( pMsg ) )
+        return 0;
     LRESULT lResult = DispatchMessageW( pMsg );
     if ( pSalData->mpFirstObject )
-        ImplSalPostDispatchMsg( pMsg, lResult );
+        ImplSalPostDispatchMsg( pMsg );
+    return lResult;
 }
 
 bool ImplSalYield( bool bWait, bool bHandleAllCurrentEvents )
@@ -491,10 +489,13 @@ bool ImplSalYield( bool bWait, bool bHandleAllCurrentEvents )
         if ( bOneEvent )
         {
             bWasMsg = true;
-            if ( !bWasTimeoutMsg )
-                bWasTimeoutMsg = (SAL_MSG_TIMER_CALLBACK == aMsg.message);
             TranslateMessage( &aMsg );
-            ImplSalDispatchMessage( &aMsg );
+            LRESULT nRet = ImplSalDispatchMessage( &aMsg );
+
+            if ( !bWasTimeoutMsg )
+                bWasTimeoutMsg = (SAL_MSG_TIMER_CALLBACK == aMsg.message)
+                    && static_cast<bool>( nRet );
+
             if ( bHandleAllCurrentEvents
                     && !bHadNewerEvent && aMsg.time > nCurTicks
                     && (nLastTicks <= nCurTicks || aMsg.time < nLastTicks) )
@@ -666,14 +667,16 @@ LRESULT CALLBACK SalComWndProc( HWND, UINT nMsg, WPARAM wParam, LPARAM lParam, i
         {
             WinSalTimer *const pTimer = static_cast<WinSalTimer*>( ImplGetSVData()->maSchedCtx.mpSalTimer );
             assert( pTimer != nullptr );
-            pTimer->ImplHandleTimerEvent( wParam );
+            nRet = static_cast<LRESULT>( pTimer->ImplHandleTimerEvent( wParam ) );
+            nDef = FALSE;
             break;
         }
         case WM_TIMER:
         {
             WinSalTimer *const pTimer = static_cast<WinSalTimer*>( ImplGetSVData()->maSchedCtx.mpSalTimer );
             assert( pTimer != nullptr );
-            pTimer->ImplHandle_WM_TIMER( wParam );
+            nRet = static_cast<LRESULT>( pTimer->ImplHandle_WM_TIMER( wParam ) );
+            nDef = FALSE;
             break;
         }
     }
diff --git a/vcl/win/app/saltimer.cxx b/vcl/win/app/saltimer.cxx
index 9d20c70bdb5a..9c67e841956e 100644
--- a/vcl/win/app/saltimer.cxx
+++ b/vcl/win/app/saltimer.cxx
@@ -158,13 +158,14 @@ void WinSalTimer::ImplHandleElapsedTimer()
     ImplSalYieldMutexRelease();
 }
 
-void WinSalTimer::ImplHandleTimerEvent( const WPARAM aWPARAM )
+bool WinSalTimer::ImplHandleTimerEvent( const WPARAM aWPARAM )
 {
     assert( aWPARAM <= SAL_MAX_INT32 );
     if ( !IsValidEventVersion( static_cast<sal_Int32>( aWPARAM ) ) )
-        return;
+        return false;
 
     ImplHandleElapsedTimer();
+    return true;
 }
 
 void WinSalTimer::SetForceRealTimer( const bool bVal )
@@ -179,11 +180,14 @@ void WinSalTimer::SetForceRealTimer( const bool bVal )
         Start( 0 );
 }
 
-void WinSalTimer::ImplHandle_WM_TIMER( const WPARAM aWPARAM )
+bool WinSalTimer::ImplHandle_WM_TIMER( const WPARAM aWPARAM )
 {
     assert( m_aWmTimerId == aWPARAM );
-    if ( m_aWmTimerId == aWPARAM && m_bDirectTimeout && m_bForceRealTimer )
-        ImplHandleElapsedTimer();
+    if ( !(m_aWmTimerId == aWPARAM && m_bDirectTimeout && m_bForceRealTimer) )
+        return false;
+
+    ImplHandleElapsedTimer();
+    return true;
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit 907253a02d4570b0dc2b0b6466d8a34fd1a9a328
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Mon Oct 16 19:03:59 2017 +0200

    tdf#105062 prevent AutoRecovery DB deadlock
    
    AutoRecovery document event notification - at least for Firebird
    DB files - needs the SolarMutex for getLocation().
    
    If I place the SolarMutex inside the CacheLockGuard I get a the
    css::uno::RuntimeException from CacheLockGuard::lock.
    
    Change-Id: I3341a80ecf144d29e0a68de6695d1ca6a7241c60

diff --git a/framework/source/services/autorecovery.cxx b/framework/source/services/autorecovery.cxx
index d1b106592d4e..53f02f4e3d5f 100644
--- a/framework/source/services/autorecovery.cxx
+++ b/framework/source/services/autorecovery.cxx
@@ -2606,6 +2606,7 @@ void AutoRecovery::implts_updateDocumentUsedForSavingState(const css::uno::Refer
 
 void AutoRecovery::implts_markDocumentAsSaved(const css::uno::Reference< css::frame::XModel >& xDocument)
 {
+    SolarMutexGuard aSolarGuard;
     CacheLockGuard aCacheLock(this, cppu::WeakComponentImplHelperBase::rBHelper.rMutex, m_nDocCacheLock, LOCK_FOR_CACHE_USE);
 
     AutoRecovery::TDocumentInfo aInfo;
commit 18548028c3ff7a4f4dce3ddc6a8151446cfda81b
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Wed Oct 18 14:54:20 2017 +0200

    Prefer ACE over Jet ODBC Excel drivers in VB tests
    
    The Jet drivers are deprectated and unsupported.
    
    From commit 66b3970c946bd25647484ea1ac2c2e62bd9fb7b4 I guess a
    Windows 10 64bit doesn't provide any, but don't know.
    
    Essentially commit 66b3970c946bd25647484ea1ac2c2e62bd9fb7b4,
    is reverted, as it also removed the ole_dfltObjDflMethod.vb test.
    
    Change-Id: I2dfc525c7cdf7ceb7f46521905933f9ce67aa2e6

diff --git a/basic/qa/cppunit/test_vba.cxx b/basic/qa/cppunit/test_vba.cxx
index d153a1d62f82..13d897a01894 100644
--- a/basic/qa/cppunit/test_vba.cxx
+++ b/basic/qa/cppunit/test_vba.cxx
@@ -30,13 +30,17 @@ namespace
         public:
         VBATest() : BootstrapFixture(true, false) {}
         void testMiscVBAFunctions();
+#ifdef _WIN32
         void testMiscOLEStuff();
+#endif
         // Adds code needed to register the test suite
         CPPUNIT_TEST_SUITE(VBATest);
 
         // Declares the method as a test to call
         CPPUNIT_TEST(testMiscVBAFunctions);
+#ifdef _WIN32
         CPPUNIT_TEST(testMiscOLEStuff);
+#endif
 
         // End of test suite definition
         CPPUNIT_TEST_SUITE_END();
@@ -175,16 +179,11 @@ void VBATest::testMiscVBAFunctions()
     }
 }
 
-void VBATest::testMiscOLEStuff()
-{
 // Not much point even trying to run except on Windows.
 // (Without Excel doesn't really do anything anyway,
-// see "so skip test" below.)
-
-// Since some time, on a properly updated Windows 10, this works
-// only with a 64-bit LibreOffice
-
-#if defined(_WIN64)
+#ifdef _WIN32
+void VBATest::testMiscOLEStuff()
+{
     // test if we have the necessary runtime environment
     // to run the OLE tests.
     uno::Reference< lang::XMultiServiceFactory > xOLEFactory;
@@ -203,27 +202,45 @@ void VBATest::testMiscOLEStuff()
         bOk = xADODB.is();
     }
     if ( !bOk )
-        return; // can't do anything, skip test
+        return; // can't do anything without OLE, so skip test
 
+    // search for the ODBC Excel drivers
     const int nBufSize = 1024 * 4;
     wchar_t sBuf[nBufSize];
-    SQLGetInstalledDriversW( sBuf, nBufSize, nullptr );
+    if( !SQLGetInstalledDriversW( sBuf, nBufSize, nullptr ) )
+        return;
+
+    const wchar_t *aExcelDriverNameList[]
+    {
+        L"Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb)",
+        L"Microsoft Excel Driver (*.xls)"
+    };
+    const unsigned MAX_DRV = SAL_N_ELEMENTS( aExcelDriverNameList );
+    bool bFoundDrivers[ MAX_DRV ] = { false, };
 
     const wchar_t *pODBCDriverName = sBuf;
-    bool bFound = false;
-    for (; wcslen( pODBCDriverName ) != 0; pODBCDriverName += wcslen( pODBCDriverName ) + 1 ) {
-        if( wcscmp( pODBCDriverName, L"Microsoft Excel Driver (*.xls)" ) == 0 ||
-            wcscmp( pODBCDriverName, L"Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb)" ) == 0 ) {
-            bFound = true;
+    for (; wcslen( pODBCDriverName ) != 0; pODBCDriverName += wcslen( pODBCDriverName ) + 1 )
+    {
+        for ( unsigned i = 0; i < MAX_DRV; ++i )
+            if ( !bFoundDrivers[ i ] && wcscmp( pODBCDriverName, aExcelDriverNameList[ i ] ) == 0 )
+                bFoundDrivers[ i ] = true;
+    }
+
+    pODBCDriverName = nullptr;
+    for ( unsigned i = 0; i < MAX_DRV; ++i )
+        if ( bFoundDrivers[ i ] )
+        {
+            pODBCDriverName = aExcelDriverNameList[ i ];
             break;
         }
-    }
-    if ( !bFound )
-        return; // can't find ODBC driver needed test, so skip test
+
+    if ( !pODBCDriverName )
+        return; // can't find any ODBC driver needed for the test, so skip it
 
     const char* macroSource[] = {
         "ole_ObjAssignNoDflt.vb",
         "ole_ObjAssignToNothing.vb",
+        "ole_dfltObjDflMethod.vb",
     };
 
     OUString sMacroPathURL = m_directories.getURLFromSrc("/basic/qa/vba_tests/");
@@ -251,11 +268,8 @@ void VBATest::testMiscOLEStuff()
         CPPUNIT_ASSERT_MESSAGE("No return variable huh?", pReturn.get() != nullptr );
         CPPUNIT_ASSERT_EQUAL_MESSAGE("Result not as expected", OUString("OK"), pReturn->GetOUString() );
     }
-#else
-    // Avoid "this method is empty and should be removed" warning
-    (void) 42;
-#endif
 }
+#endif
 
   // Put the test suite in the registry
   CPPUNIT_TEST_SUITE_REGISTRATION(VBATest);
diff --git a/basic/qa/vba_tests/ole_dfltObjDflMethod.vb b/basic/qa/vba_tests/ole_dfltObjDflMethod.vb
new file mode 100644
index 000000000000..9ac50d9b5f9e
--- /dev/null
+++ b/basic/qa/vba_tests/ole_dfltObjDflMethod.vb
@@ -0,0 +1,24 @@
+Option VBASupport 1
+Option Explicit
+
+Rem Test accessing an object that has default object member
+Rem which in turn has a default member that is a method
+Function doUnitTest(TestData As String, Driver as String) As String
+doUnitTest = "Begin"
+Dim modifiedTimout As Long
+Dim cnn1 As New ADODB.Connection
+Dim rst1 As New ADODB.Recordset
+Dim conStr As String
+cnn1.Open "Provider=Microsoft.Jet.OLEDB.4.0;" & _
+"Data Source=" & TestData & ";" & _
+"Extended Properties=""Excel 8.0;HDR=Yes"";"
+rst1.Open "SELECT * FROM [Sheet1$];", cnn1, adOpenStatic, adLockReadOnly
+Dim val
+val = rst1("FirstName")
+If val = "Paddy" Then
+    doUnitTest = "OK"
+Else
+    doUnitTest = "Failed, expected 'Paddy' got " & val
+End If
+
+End Function
commit a1f93eee75450c3ab6bc623bfad4f850260b86d0
Author: Szymon Kłos <szymon.klos at collabora.com>
Date:   Wed Oct 18 18:15:29 2017 +0200

    tdf#107224 use correct bg for notebookbar
    
    Change-Id: I26093cb9cf0170aa9ba4ccfc8c8556c2e78086b3
    Reviewed-on: https://gerrit.libreoffice.org/43515
    Reviewed-by: Szymon Kłos <szymon.klos at collabora.com>
    Tested-by: Szymon Kłos <szymon.klos at collabora.com>

diff --git a/vcl/source/control/notebookbar.cxx b/vcl/source/control/notebookbar.cxx
index dc47f66d82b1..ee3e05ab3852 100644
--- a/vcl/source/control/notebookbar.cxx
+++ b/vcl/source/control/notebookbar.cxx
@@ -173,7 +173,7 @@ void NotebookBar::UpdateBackground()
     if (!aPersona.IsEmpty())
         SetBackground(Wallpaper(aPersona));
     else
-        SetBackground(rStyleSettings.GetMenuBarColor());
+        SetBackground(rStyleSettings.GetDialogColor());
 
     Invalidate(tools::Rectangle(Point(0,0), GetSizePixel()));
 }
commit 2874a31e4830c2e899a057530e9799bbae456d79
Author: Muhammet Kara <muhammet.kara at pardus.org.tr>
Date:   Sun Oct 15 14:33:41 2017 +0000

    Fix spacing
    
    and use the hungarian prefix 's' for the string.
    
    Inconsistent spacing introduced with:
    2b5b8fd39c93166d9e6e696c010482413b155f78
    
    Change-Id: Ieee55f51ec6c87b087365f7460097d5cc997a261
    Reviewed-on: https://gerrit.libreoffice.org/43405
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Muhammet Kara <muhammet.kara at pardus.org.tr>

diff --git a/sw/source/ui/vba/vbarow.cxx b/sw/source/ui/vba/vbarow.cxx
index 088ecfbfaa53..2255ce34c1a5 100644
--- a/sw/source/ui/vba/vbarow.cxx
+++ b/sw/source/ui/vba/vbarow.cxx
@@ -82,16 +82,16 @@ SwVbaRow::Select( )
 
 void SwVbaRow::SelectRow( const uno::Reference< frame::XModel >& xModel, const uno::Reference< text::XTextTable >& xTextTable, sal_Int32 nStartRow, sal_Int32 nEndRow )
 {
-    OUString aRangeName = "A" + OUString::number(nStartRow + 1);
+    OUString sRangeName = "A" + OUString::number(nStartRow + 1);
     SwVbaTableHelper aTableHelper( xTextTable );
     sal_Int32 nColCount = aTableHelper.getTabColumnsCount( nEndRow );
     // FIXME: the column count > 26
     //sal_Char cCol = 'A' + nColCount - 1;
     OUString sCol = SwVbaTableHelper::getColumnStr( nColCount - 1);
-    aRangeName += ":" +sCol + OUString::number(nEndRow + 1);
+    sRangeName += ":" + sCol + OUString::number(nEndRow + 1);
 
     uno::Reference< table::XCellRange > xCellRange( xTextTable, uno::UNO_QUERY_THROW );
-    uno::Reference< table::XCellRange > xSelRange = xCellRange->getCellRangeByName( aRangeName );
+    uno::Reference< table::XCellRange > xSelRange = xCellRange->getCellRangeByName( sRangeName );
 
     uno::Reference< view::XSelectionSupplier > xSelection( xModel->getCurrentController(), uno::UNO_QUERY_THROW );
     xSelection->select( uno::makeAny( xSelRange ) );


More information about the Libreoffice-commits mailing list