Rebased ref, commits from common ancestor: commit 5146a9bbbe394851a2fc1f56196a76df540ff03c Author: Jan-Marek Glogowski <glo...@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 5bb4ef1e062ab7b90f8550ebe93ca9730513c772 Author: Jan-Marek Glogowski <glo...@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 b2da514bd88342a92d5aa0e6bb98c347909b0601 Author: Jan-Marek Glogowski <glo...@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 806ed4e81e2f11135cd6d8c056035d8a56bcf754 Author: Jan-Marek Glogowski <glo...@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 327abc3433c220bf549ad305a17a1cc4e1dbc44f Author: Jan-Marek Glogowski <glo...@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 5db82a6cb4d0cde2577ac6ebb12052cb7750f551 Author: Jan-Marek Glogowski <glo...@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..6baa98e8ff8d 100644 --- a/basic/qa/cppunit/test_vba.cxx +++ b/basic/qa/cppunit/test_vba.cxx @@ -36,7 +36,9 @@ namespace // 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 +177,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 +200,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 +266,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); commit 331016f82a709d80c70143435db18753a78a23f6 Author: Caolán McNamara <caol...@redhat.com> Date: Wed Oct 18 11:15:00 2017 +0100 return early on failure Change-Id: Id96ba954d3056cf982701090cf84ab4b1793b40b Reviewed-on: https://gerrit.libreoffice.org/43489 Tested-by: Jenkins <c...@libreoffice.org> Reviewed-by: Caolán McNamara <caol...@redhat.com> Tested-by: Caolán McNamara <caol...@redhat.com> diff --git a/svx/source/accessibility/AccessibleShape.cxx b/svx/source/accessibility/AccessibleShape.cxx index 86cc8ba732d1..ecf4c478774f 100644 --- a/svx/source/accessibility/AccessibleShape.cxx +++ b/svx/source/accessibility/AccessibleShape.cxx @@ -405,67 +405,66 @@ uno::Reference<XAccessibleStateSet> SAL_CALL AccessibleShape::getAccessibleStateSet() { ::osl::MutexGuard aGuard (maMutex); - Reference<XAccessibleStateSet> xStateSet; - bool bDisposed = IsDisposed(); - - if (bDisposed) + if (IsDisposed()) { // Return a minimal state set that only contains the DEFUNC state. - xStateSet = AccessibleContextBase::getAccessibleStateSet (); + return AccessibleContextBase::getAccessibleStateSet (); } - else - { - ::utl::AccessibleStateSetHelper* pStateSet = - static_cast< ::utl::AccessibleStateSetHelper*>(mxStateSet.get()); - if (pStateSet != nullptr) + ::utl::AccessibleStateSetHelper* pStateSet = + static_cast<::utl::AccessibleStateSetHelper*>(mxStateSet.get()); + + if (!pStateSet) + return Reference<XAccessibleStateSet>(); + + // Merge current FOCUSED state from edit engine. + if (mpText) + { + if (mpText->HaveFocus()) + pStateSet->AddState (AccessibleStateType::FOCUSED); + else + pStateSet->RemoveState (AccessibleStateType::FOCUSED); + } + //Just when the document is not read-only,set states EDITABLE,RESIZABLE,MOVEABLE + css::uno::Reference<XAccessible> xTempAcc = getAccessibleParent(); + if( xTempAcc.is() ) + { + css::uno::Reference<XAccessibleContext> + xTempAccContext = xTempAcc->getAccessibleContext(); + if( xTempAccContext.is() ) { - // Merge current FOCUSED state from edit engine. - if (mpText != nullptr) + css::uno::Reference<XAccessibleStateSet> rState = + xTempAccContext->getAccessibleStateSet(); + if (rState.is()) { - if (mpText->HaveFocus()) - pStateSet->AddState (AccessibleStateType::FOCUSED); - else - pStateSet->RemoveState (AccessibleStateType::FOCUSED); - } - //Just when the document is not read-only,set states EDITABLE,RESIZABLE,MOVEABLE - css::uno::Reference<XAccessible> xTempAcc = getAccessibleParent(); - if( xTempAcc.is() ) - { - css::uno::Reference<XAccessibleContext> - xTempAccContext = xTempAcc->getAccessibleContext(); - if( xTempAccContext.is() ) + css::uno::Sequence<short> aStates = rState->getStates(); + int count = aStates.getLength(); + for( int iIndex = 0;iIndex < count;iIndex++ ) { - css::uno::Reference<XAccessibleStateSet> rState = - xTempAccContext->getAccessibleStateSet(); - if( rState.is() ) { - css::uno::Sequence<short> aStates = rState->getStates(); - int count = aStates.getLength(); - for( int iIndex = 0;iIndex < count;iIndex++ ) - { - if( aStates[iIndex] == AccessibleStateType::EDITABLE ) - { - pStateSet->AddState (AccessibleStateType::EDITABLE); - pStateSet->AddState (AccessibleStateType::RESIZABLE); - pStateSet->AddState (AccessibleStateType::MOVEABLE); - break; - } - } + if( aStates[iIndex] == AccessibleStateType::EDITABLE ) + { + pStateSet->AddState (AccessibleStateType::EDITABLE); + pStateSet->AddState (AccessibleStateType::RESIZABLE); + pStateSet->AddState (AccessibleStateType::MOVEABLE); + break; } } } - // Create a copy of the state set that may be modified by the - // caller without affecting the current state set. - xStateSet.set( new ::utl::AccessibleStateSetHelper (*pStateSet)); } } - if (!bDisposed && xStateSet.is() && mpParent && mpParent->IsDocumentSelAll()) + + // Create a copy of the state set that may be modified by the + // caller without affecting the current state set. + Reference<XAccessibleStateSet> xStateSet(new ::utl::AccessibleStateSetHelper(*pStateSet)); + + if (mpParent && mpParent->IsDocumentSelAll()) { - ::utl::AccessibleStateSetHelper* pStateSet = - static_cast< ::utl::AccessibleStateSetHelper*>(xStateSet.get()); - pStateSet->AddState (AccessibleStateType::SELECTED); + ::utl::AccessibleStateSetHelper* pCopyStateSet = + static_cast<::utl::AccessibleStateSetHelper*>(xStateSet.get()); + pCopyStateSet->AddState (AccessibleStateType::SELECTED); } + return xStateSet; } commit e7cab93ebbccfc02e84c9385b8c53832784ef47c Author: Caolán McNamara <caol...@redhat.com> Date: Wed Oct 18 15:51:14 2017 +0100 ofz+ubsan: signed integer overflow in unused variable Change-Id: Ie95ddfdb002fdb5b6670bb155d2dd0089b719fca diff --git a/sw/source/filter/ww8/ww8scan.cxx b/sw/source/filter/ww8/ww8scan.cxx index d02cb762ed78..402319bce5cb 100644 --- a/sw/source/filter/ww8/ww8scan.cxx +++ b/sw/source/filter/ww8/ww8scan.cxx @@ -7159,9 +7159,6 @@ WW8PLCF_HdFt::WW8PLCF_HdFt( SvStream* pSt, WW8Fib& rFib, WW8Dop const & rDop ) for( sal_uInt8 nI = 0x1; nI <= 0x20; nI <<= 1 ) if( nI & rDop.grpfIhdt ) // bit set? nIdxOffset++; - - nTextOfs = rFib.m_ccpText + rFib.m_ccpFootnote; // size of the main text - // and from the footnotes } bool WW8PLCF_HdFt::GetTextPos(sal_uInt8 grpfIhdt, sal_uInt8 nWhich, WW8_CP& rStart, diff --git a/sw/source/filter/ww8/ww8scan.hxx b/sw/source/filter/ww8/ww8scan.hxx index d43335928fb7..ba0f1e9efecf 100644 --- a/sw/source/filter/ww8/ww8scan.hxx +++ b/sw/source/filter/ww8/ww8scan.hxx @@ -1844,7 +1844,6 @@ class WW8PLCF_HdFt { private: WW8PLCF aPLCF; - long nTextOfs; short nIdxOffset; public: commit 93c34fea480275343896ef25289a2b41ce19b114 Author: Andrea Gelmini <andrea.gelm...@gelma.net> Date: Wed Oct 18 12:57:27 2017 +0200 Fix typo Change-Id: Ie29a05fec90c0d81b4a0399505b0a6761dfdef69 Reviewed-on: https://gerrit.libreoffice.org/43463 Reviewed-by: Julien Nabet <serval2...@yahoo.fr> Tested-by: Julien Nabet <serval2...@yahoo.fr> diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx b/writerfilter/source/dmapper/DomainMapper_Impl.cxx index 545a003bb3e3..6870e5ff335c 100644 --- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx +++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx @@ -1186,7 +1186,7 @@ void DomainMapper_Impl::finishParagraph( const PropertyMapPtr& pPropertyMap ) { // Workaround to make sure char props of the field are not lost. // Not relevant for editeng-based comments. - // Nor revelent for fields inside a TOC field. + // Not relevant for fields inside a TOC field. OUString const sMarker("X"); xCursor = xTextAppend->getText()->createTextCursor(); if (xCursor.is()) commit abaf2e3b856356d68b104c6aa0d17d6937d980b4 Author: Noel Grandin <noel.gran...@collabora.co.uk> Date: Wed Oct 18 16:26:14 2017 +0200 rename some fields in preparation for const-method detection Change-Id: Iecf7102892d664ded799615ce1a848a538dcfcef diff --git a/compilerplugins/clang/constparams.cxx b/compilerplugins/clang/constparams.cxx index 87a00ec488c3..ca30048f9b1c 100644 --- a/compilerplugins/clang/constparams.cxx +++ b/compilerplugins/clang/constparams.cxx @@ -8,7 +8,6 @@ */ #include <algorithm> -#include <set> #include <string> #include <unordered_set> #include <unordered_map> @@ -60,8 +59,8 @@ public: TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); - for (const ParmVarDecl *pParmVarDecl : interestingSet) { - if (cannotBeConstSet.find(pParmVarDecl) == cannotBeConstSet.end()) { + for (const ParmVarDecl *pParmVarDecl : interestingParamSet) { + if (paramCannotBeConstSet.find(pParmVarDecl) == paramCannotBeConstSet.end()) { auto functionDecl = parmToFunction[pParmVarDecl]; auto canonicalDecl = functionDecl->getCanonicalDecl(); if (ignoredFunctions_.find(canonicalDecl) @@ -174,10 +173,10 @@ private: bool checkIfCanBeConst(const Stmt*, const ParmVarDecl*); bool isPointerOrReferenceToConst(const QualType& qt); - std::unordered_set<const ParmVarDecl*> interestingSet; + std::unordered_set<const ParmVarDecl*> interestingParamSet; std::unordered_map<const ParmVarDecl*, const FunctionDecl*> parmToFunction; - std::unordered_set<const ParmVarDecl*> cannotBeConstSet; - std::set<FunctionDecl const *> ignoredFunctions_; + std::unordered_set<const ParmVarDecl*> paramCannotBeConstSet; + std::unordered_set<FunctionDecl const *> ignoredFunctions_; Expr const * callee_ = nullptr; }; @@ -257,7 +256,7 @@ bool ConstParams::VisitFunctionDecl(const FunctionDecl * functionDecl) // ignore things with template params if (pParmVarDecl->getType()->isInstantiationDependentType()) continue; - interestingSet.insert(pParmVarDecl); + interestingParamSet.insert(pParmVarDecl); parmToFunction[pParmVarDecl] = functionDecl; } @@ -278,10 +277,10 @@ bool ConstParams::VisitDeclRefExpr( const DeclRefExpr* declRefExpr ) return true; } // no need to check again if we have already eliminated this one - if (cannotBeConstSet.find(parmVarDecl) != cannotBeConstSet.end()) + if (paramCannotBeConstSet.find(parmVarDecl) != paramCannotBeConstSet.end()) return true; if (!checkIfCanBeConst(declRefExpr, parmVarDecl)) - cannotBeConstSet.insert(parmVarDecl); + paramCannotBeConstSet.insert(parmVarDecl); return true; } commit d9575e72de6ad54e6680d00e795e380df2c82264 Author: Noel Grandin <noel.gran...@collabora.co.uk> Date: Wed Oct 18 16:21:45 2017 +0200 loplugin:manualrefcount this is the code I used to find naked acquire/release stuff No need to run it all the time, so leave it in store Change-Id: I9ac4a6f5db7cd4cbb1b63698340425eed7cb8713 diff --git a/compilerplugins/clang/store/manualrefcount.cxx b/compilerplugins/clang/store/manualrefcount.cxx new file mode 100644 index 000000000000..c8085904fede --- /dev/null +++ b/compilerplugins/clang/store/manualrefcount.cxx @@ -0,0 +1,323 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <cassert> +#include <string> +#include <iostream> +#include <fstream> +#include <set> + +#include <clang/AST/CXXInheritance.h> +#include "compat.hxx" +#include "plugin.hxx" +#include "check.hxx" + +/** + Look for calls to the ref-counting methods acquire()/release(), which should only be called by classes like rtl::Reference. +*/ + +namespace { + +class ManualRefCount: + public RecursiveASTVisitor<ManualRefCount>, public loplugin::Plugin +{ +public: + explicit ManualRefCount(InstantiationData const & data): Plugin(data) {} + + virtual void run() override + { + StringRef fn( compiler.getSourceManager().getFileEntryForID( + compiler.getSourceManager().getMainFileID())->getName() ); + + // old code, no point in updating + if (loplugin::isSamePathname(fn, SRCDIR "/store/source/store.cxx")) + return; + +// TODO ----------------------------- + if (loplugin::isSamePathname(fn, SRCDIR "/registry/source/registry.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/registry/source/regimpl.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/registry/source/reflread.cxx")) + return; + // TODO MenuAttributes::CreateAttribute + if (loplugin::isSamePathname(fn, SRCDIR "/framework/source/fwe/xml/menuconfiguration.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/sw/source/uibase/app/apphdl.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/dbaccess/source/core/dataaccess/ModelImpl.cxx")) + return; + // need a better replacement for vcl::EventPoster + if (loplugin::isSamePathname(fn, SRCDIR "/svtools/source/misc/acceleratorexecute.cxx")) + return; + // PostUserEvent stuff + if (loplugin::isSamePathname(fn, SRCDIR "/toolkit/source/awt/vclxwindow.cxx")) + return; + // playing games with pointers passed into combobox entries + if (loplugin::isSamePathname(fn, SRCDIR "/cui/source/customize/cfgutil.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/cui/source/customize/cfg.cxx")) + return; +// END TODO ----------------------------- + + // can't fix these without breaking stable ABI + if (fn.startswith(SRCDIR "/sal/")) + return; + if (fn.startswith(SRCDIR "/salhelper/")) + return; + if (fn.startswith(SRCDIR "/cppu/")) + return; + if (fn.startswith(SRCDIR "/cppuhelper/")) + return; + if (fn.startswith(SRCDIR "/bridges/")) + return; + + // lots of magic here + if (fn.startswith(SRCDIR "/stoc/")) + return; + if (fn.startswith(SRCDIR "/testtools/")) + return; + + // mutex games + if (loplugin::isSamePathname(fn, SRCDIR "/vcl/source/app/scheduler.cxx")) + return; + // opengl games + if (loplugin::isSamePathname(fn, SRCDIR "/vcl/source/app/svdata.cxx")) + return; + + // passing the pointer through PostUserEvent + if (loplugin::isSamePathname(fn, SRCDIR "/avmedia/source/gstreamer/gstplayer.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/svx/source/form/fmscriptingenv.cxx")) + return; + + // thread games + if (loplugin::isSamePathname(fn, SRCDIR "/io/source/stm/opump.cxx")) + return; + + // ??? no idea what this code is up to + if (loplugin::isSamePathname(fn, SRCDIR "/extensions/source/scanner/scanunx.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/stoc/source/invocation_adapterfactory/iafactory.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/fpicker/source/office/asyncfilepicker.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/forms/source/component/FormComponent.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/ucb/source/ucp/file/bc.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/ucb/source/ucp/file/filprp.cxx")) + return; + // calling release() ? + if (loplugin::isSamePathname(fn, SRCDIR "/toolkit/source/helper/accessibilityclient.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/svtools/source/misc/svtaccessiblefactory.cxx")) + return; + + // implementing css::uno::XInterface + if (loplugin::isSamePathname(fn, SRCDIR "/sd/source/ui/animations/motionpathtag.cxx")) + return; + // UNO factory methods + if (fn.startswith(SRCDIR "/comphelper/")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/linguistic/source/convdiclist.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/linguistic/source/dlistimp.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/linguistic/source/gciterator.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/linguistic/source/lngsvcmgr.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/linguistic/source/lngopt.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/vcl/unx/generic/gdi/gcach_xpeer.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/dbaccess/source/ui/dlg/dbwizsetup.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/dbaccess/source/ui/dlg/dbwizsetup.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/lingucomponent/source/hyphenator/hyphen/hyphenimp.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/lingucomponent/source/spellcheck/spell/sspellimp.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/lingucomponent/source/thesaurus/libnth/nthesimp.cxx")) + return; + + + // some kind of complicated listener nonsense + if (loplugin::isSamePathname(fn, SRCDIR "/sd/source/ui/framework/tools/FrameworkHelper.cxx")) + return; + // more listener nonsense + if (loplugin::isSamePathname(fn, SRCDIR "/sw/source/uibase/uno/unomailmerge.cxx")) + return; + // playing games with it's listener list + if (loplugin::isSamePathname(fn, SRCDIR "/sc/source/ui/unoobj/cellsuno.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/sc/source/ui/unoobj/chart2uno.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/sc/source/ui/unoobj/dapiuno.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/sc/source/ui/unoobj/datauno.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/sc/source/ui/unoobj/linkuno.cxx")) + return; + // PostUserEvent + if (loplugin::isSamePathname(fn, SRCDIR "/sc/source/ui/vba/vbaeventshelper.cxx")) + return; + // thread holding itself + if (loplugin::isSamePathname(fn, SRCDIR "/forms/source/component/EventThread.cxx")) + return; + + + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + + bool shouldVisitTemplateInstantiations () const { return true; } + + bool VisitCXXMemberCallExpr(const CXXMemberCallExpr *); + bool TraverseCXXRecordDecl(CXXRecordDecl *); + bool TraverseCXXMethodDecl(CXXMethodDecl *); + bool TraverseFunctionDecl(FunctionDecl *); + bool TraverseCXXConstructorDecl(CXXConstructorDecl *); + bool TraverseCXXDestructorDecl(CXXDestructorDecl *); + bool TraverseCXXConversionDecl(CXXConversionDecl *); + bool TraverseClassTemplateSpecializationDecl(ClassTemplateSpecializationDecl *); + bool TraverseLinkageSpecDecl(LinkageSpecDecl *); +private: + bool ignoreCallerClass(CXXRecordDecl*); +}; + +bool ManualRefCount::TraverseCXXMethodDecl(CXXMethodDecl* cxxMethodDecl) +{ + if (ignoreCallerClass(cxxMethodDecl->getParent())) + return true; + // disambiguating forwarding methods for XInterface subclasses + if (cxxMethodDecl->getIdentifier() && (cxxMethodDecl->getName() == "acquire" || cxxMethodDecl->getName() == "release")) + return true; + return RecursiveASTVisitor::TraverseCXXMethodDecl(cxxMethodDecl); +} + +bool ManualRefCount::TraverseFunctionDecl(FunctionDecl* functionDecl) +{ + auto tc = loplugin::DeclCheck(functionDecl); + if (tc.Function("make_shared_from_UNO").Namespace("comphelper").GlobalNamespace()) + return true; + return RecursiveASTVisitor::TraverseFunctionDecl(functionDecl); +} + +bool ManualRefCount::TraverseCXXConstructorDecl(CXXConstructorDecl* cxxMethodDecl) +{ + if (ignoreCallerClass(cxxMethodDecl->getParent())) + return true; + return RecursiveASTVisitor::TraverseCXXMethodDecl(cxxMethodDecl); +} + +bool ManualRefCount::TraverseCXXDestructorDecl(CXXDestructorDecl*) +{ + // just ignore destructors, tons of places like to call acquire() on themselves in their destructor + // supposedly to prevent recursively calling the destructor + return true; +} +bool ManualRefCount::TraverseCXXConversionDecl(CXXConversionDecl* cxxMethodDecl) +{ + if (ignoreCallerClass(cxxMethodDecl->getParent())) + return true; + return RecursiveASTVisitor::TraverseCXXMethodDecl(cxxMethodDecl); +} +bool ManualRefCount::TraverseCXXRecordDecl(CXXRecordDecl* cxxRecordDecl) +{ + if (ignoreCallerClass(cxxRecordDecl)) + return true; + return RecursiveASTVisitor::TraverseCXXRecordDecl(cxxRecordDecl); +} + +bool ManualRefCount::TraverseClassTemplateSpecializationDecl(ClassTemplateSpecializationDecl* templateDecl) +{ + if (ignoreCallerClass(templateDecl)) + return true; + return RecursiveASTVisitor::TraverseClassTemplateSpecializationDecl(templateDecl); +} + +bool ManualRefCount::TraverseLinkageSpecDecl(LinkageSpecDecl *) +{ + // ignore methods inside "extern ""C""" blocks, these are normally UNO constructors, which + // are required to raise the reference count before returning + return true; +} + +bool ManualRefCount::ignoreCallerClass(CXXRecordDecl* cxxRecordDecl) +{ + auto tc = loplugin::TypeCheck(cxxRecordDecl); + return + tc.Class("Reference").Namespace("rtl").GlobalNamespace() + || tc.Class("cow_wrapper").Namespace("o3tl").GlobalNamespace() + || tc.Class("Reference").Namespace("uno").Namespace("star").Namespace("sun").Namespace("com").GlobalNamespace() + || tc.Class("ShareGuard").Namespace("framework").GlobalNamespace() + || tc.Class("ControlModelLock").Namespace("frm").GlobalNamespace() + || tc.Struct("ReleaseFunc").Namespace("detail").Namespace("comphelper").GlobalNamespace() + // TODO no idea what this is up to + || tc.Class("SfxModelSubComponent").GlobalNamespace() + || tc.Class("OSubComponent").Namespace("mysqlc").Namespace("connectivity").GlobalNamespace() + || tc.Class("OSubComponent").Namespace("connectivity").GlobalNamespace() + // TODO do we really need this? + || tc.Class("ShareableMutex").Namespace("framework").GlobalNamespace() + || tc.Class("ObservableThread").GlobalNamespace() + ; +} + +bool ManualRefCount::VisitCXXMemberCallExpr(const CXXMemberCallExpr* cxxMemberCallExpr) +{ + if (ignoreLocation(cxxMemberCallExpr)) + return true; + if (isInUnoIncludeFile(compiler.getSourceManager().getSpellingLoc(cxxMemberCallExpr->getLocStart()))) + return true; + + // first, use some heuristics to find the right kind of acquire()/release() calls + CXXMethodDecl const * calleeMethodDecl = cxxMemberCallExpr->getMethodDecl(); + if (!calleeMethodDecl || !calleeMethodDecl->getIdentifier()) + return true; + if (calleeMethodDecl->getName() != "acquire" && calleeMethodDecl->getName() != "release") + return true; + if (calleeMethodDecl->getNumParams() != 0) + return true; + // std::unique_ptr::release() and similar methods + if (calleeMethodDecl->getName() == "release" && loplugin::TypeCheck(calleeMethodDecl->getReturnType()).Pointer()) + return true; + + // these are OK + auto calleeRecordTC = loplugin::TypeCheck(calleeMethodDecl->getParent()); + if (calleeRecordTC.Struct("ResourceHolder").Namespace("store").GlobalNamespace()) + return true; + if (calleeRecordTC.Class("Module").Namespace("osl").GlobalNamespace()) + return true; + if (calleeRecordTC.Class("Mutex").Namespace("osl").GlobalNamespace()) + return true; + if (calleeRecordTC.Class("multi_type_vector").Namespace("mdds").GlobalNamespace()) + return true; + +// while (calleeMethodDecl->size_overridden_methods() > 0) +// calleeMethodDecl = *calleeMethodDecl->begin_overridden_methods(); +// auto tc2 = loplugin::TypeCheck(calleeMethodDecl->getParent()); +// if (tc2.Class("XInterface").Namespace("uno").Namespace("star").Namespace("sun").Namespace("com").GlobalNamespace()) +// return true; + +std::cout << calleeMethodDecl->getParent()->getQualifiedNameAsString() << std::endl; + report( + DiagnosticsEngine::Warning, "call to acquire/release", + cxxMemberCallExpr->getLocStart()) + << cxxMemberCallExpr->getSourceRange(); + return true; +} + + +loplugin::Plugin::Registration< ManualRefCount > X("manualrefcount", true); + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ commit d5b971f94245b32e8e1a884d0076ca4f1696d09a Author: Noel Grandin <noel.gran...@collabora.co.uk> Date: Wed Oct 18 13:43:07 2017 +0200 use rtl::Reference in forms instead of manual reference counting Change-Id: I5bad5b7b83049f5c018a1f2d5bbc37f03727c3ce Reviewed-on: https://gerrit.libreoffice.org/43497 Tested-by: Jenkins <c...@libreoffice.org> Reviewed-by: Noel Grandin <noel.gran...@collabora.co.uk> diff --git a/forms/source/richtext/richtextcontrol.cxx b/forms/source/richtext/richtextcontrol.cxx index fcf1c7ee3d79..ab662fa1d078 100644 --- a/forms/source/richtext/richtextcontrol.cxx +++ b/forms/source/richtext/richtextcontrol.cxx @@ -180,15 +180,12 @@ namespace frm // create the peer Reference< XControlModel > xModel( getModel() ); - ORichTextPeer* pPeer = ORichTextPeer::Create( xModel, pParentWin, getWinBits( xModel ) ); + rtl::Reference<ORichTextPeer> pPeer = ORichTextPeer::Create( xModel, pParentWin, getWinBits( xModel ) ); DBG_ASSERT( pPeer, "ORichTextControl::createPeer: invalid peer returned!" ); if ( pPeer ) { - // by definition, the returned component is acquired once - pPeer->release(); - // announce the peer to the base class - setPeer( pPeer ); + setPeer( pPeer.get() ); // initialize ourself (and thus the peer) with the model properties updateFromModel(); @@ -254,7 +251,7 @@ namespace frm } // ORichTextPeer - ORichTextPeer* ORichTextPeer::Create( const Reference< XControlModel >& _rxModel, vcl::Window* _pParentWindow, WinBits _nStyle ) + rtl::Reference<ORichTextPeer> ORichTextPeer::Create( const Reference< XControlModel >& _rxModel, vcl::Window* _pParentWindow, WinBits _nStyle ) { DBG_TESTSOLARMUTEX(); @@ -265,14 +262,13 @@ namespace frm return nullptr; // the peer itself - ORichTextPeer* pPeer = new ORichTextPeer; - pPeer->acquire(); // by definition, the returned object is acquired once + rtl::Reference<ORichTextPeer> pPeer(new ORichTextPeer); // the VCL control for the peer - VclPtrInstance<RichTextControl> pRichTextControl( pEngine, _pParentWindow, _nStyle, nullptr, pPeer ); + VclPtrInstance<RichTextControl> pRichTextControl( pEngine, _pParentWindow, _nStyle, nullptr, pPeer.get() ); // some knittings - pRichTextControl->SetComponentInterface( pPeer ); + pRichTextControl->SetComponentInterface( pPeer.get() ); // outta here return pPeer; diff --git a/forms/source/richtext/richtextcontrol.hxx b/forms/source/richtext/richtextcontrol.hxx index e19d68b08d8e..c48fa618da62 100644 --- a/forms/source/richtext/richtextcontrol.hxx +++ b/forms/source/richtext/richtextcontrol.hxx @@ -86,10 +86,8 @@ namespace frm public: /** factory method - @return - a new ORichTextPeer instance, which has been acquired once! */ - static ORichTextPeer* Create( + static rtl::Reference<ORichTextPeer> Create( const css::uno::Reference< css::awt::XControlModel >& _rxModel, vcl::Window* _pParentWindow, WinBits _nStyle diff --git a/forms/source/solar/component/navbarcontrol.cxx b/forms/source/solar/component/navbarcontrol.cxx index e6aca3a50d95..01b798808720 100644 --- a/forms/source/solar/component/navbarcontrol.cxx +++ b/forms/source/solar/component/navbarcontrol.cxx @@ -131,13 +131,11 @@ namespace frm } // create the peer - ONavigationBarPeer* pPeer = ONavigationBarPeer::Create( m_xContext, pParentWin, getModel() ); + rtl::Reference<ONavigationBarPeer> pPeer = ONavigationBarPeer::Create( m_xContext, pParentWin, getModel() ); assert(pPeer && "ONavigationBarControl::createPeer: invalid peer returned!"); - // by definition, the returned component is acquired once - pPeer->release(); // announce the peer to the base class - setPeer( pPeer ); + setPeer( pPeer.get() ); // initialize ourself (and thus the peer) with the model properties updateFromModel(); @@ -198,14 +196,13 @@ namespace frm // ONavigationBarPeer - ONavigationBarPeer* ONavigationBarPeer::Create( const Reference< XComponentContext >& _rxORB, + rtl::Reference<ONavigationBarPeer> ONavigationBarPeer::Create( const Reference< XComponentContext >& _rxORB, vcl::Window* _pParentWindow, const Reference< XControlModel >& _rxModel ) { DBG_TESTSOLARMUTEX(); // the peer itself - ONavigationBarPeer* pPeer = new ONavigationBarPeer( _rxORB ); - pPeer->acquire(); // by definition, the returned object is acquired once + rtl::Reference<ONavigationBarPeer> pPeer(new ONavigationBarPeer( _rxORB )); // the VCL control for the peer Reference< XModel > xContextDocument( getXModel( _rxModel ) ); @@ -220,8 +217,8 @@ namespace frm ); // some knittings - pNavBar->setDispatcher( pPeer ); - pNavBar->SetComponentInterface( pPeer ); + pNavBar->setDispatcher( pPeer.get() ); + pNavBar->SetComponentInterface( pPeer.get() ); // we want a faster repeating rate for the slots in this // toolbox diff --git a/forms/source/solar/component/navbarcontrol.hxx b/forms/source/solar/component/navbarcontrol.hxx index 22ebb3046b2b..4f2463e652e5 100644 --- a/forms/source/solar/component/navbarcontrol.hxx +++ b/forms/source/solar/component/navbarcontrol.hxx @@ -78,10 +78,8 @@ namespace frm { public: /** factory method - @return - a new ONavigationBarPeer instance, which has been acquired once! */ - static ONavigationBarPeer* Create( + static rtl::Reference<ONavigationBarPeer> Create( const css::uno::Reference< css::uno::XComponentContext >& _rxORB, vcl::Window* _pParentWindow, const css::uno::Reference< css::awt::XControlModel >& _rxModel commit e149c4f3dcd08b9331dbbecf31c200d4d3bb02b5 Author: Gulsah Kose <gulsah.1...@gmail.com> Date: Tue Oct 17 15:09:37 2017 +0300 tdf#112808 Disable "Edit Region" command while cursor in an index. Change-Id: Icefa1e42831ad0ba7a9f5346545adac0033ce3e0 Signed-off-by: Gulsah Kose <gulsah.1...@gmail.com> Reviewed-on: https://gerrit.libreoffice.org/43456 Tested-by: Jenkins <c...@libreoffice.org> Reviewed-by: Samuel Mehrbrodt <samuel.mehrbr...@cib.de> diff --git a/sw/source/uibase/shells/basesh.cxx b/sw/source/uibase/shells/basesh.cxx index 8dbfd4e91cc8..c053715bd4ad 100644 --- a/sw/source/uibase/shells/basesh.cxx +++ b/sw/source/uibase/shells/basesh.cxx @@ -1398,8 +1398,12 @@ void SwBaseShell::GetState( SfxItemSet &rSet ) break; case FN_EDIT_CURRENT_REGION: - if( !rSh.GetCurrSection() ) + //tdf#112808 if cursor is in an index, don't show the edit section. + if( !rSh.GetCurrSection() || + rSh.GetCurrSection()->GetType() != CONTENT_SECTION ) + { rSet.DisableItem(nWhich); + } break; case FN_INSERT_REGION: commit 087a90e27b7219e8c1aaa880b39376c94a0dcaae Author: Thorsten Behrens <thorsten.behr...@cib.de> Date: Wed Oct 18 14:23:37 2017 +0200 gpg4libre fix tdf#113190 don't show expired/invalid keys Change-Id: I30485bc97d3d287bd867b50398927eabe018914b Reviewed-on: https://gerrit.libreoffice.org/43502 Reviewed-by: Eike Rathke <er...@redhat.com> Reviewed-by: Thorsten Behrens <thorsten.behr...@cib.de> Tested-by: Thorsten Behrens <thorsten.behr...@cib.de> diff --git a/xmlsecurity/source/gpg/SecurityEnvironment.cxx b/xmlsecurity/source/gpg/SecurityEnvironment.cxx index c3cd90565fe2..2392bf0c8031 100644 --- a/xmlsecurity/source/gpg/SecurityEnvironment.cxx +++ b/xmlsecurity/source/gpg/SecurityEnvironment.cxx @@ -76,7 +76,7 @@ Sequence< Reference < XCertificate > > SecurityEnvironmentGpg::getCertificatesIm GpgME::Key k = m_ctx->nextKey(err); if (err) break; - if (!k.isInvalid()) { + if (!k.isRevoked() && !k.isExpired() && !k.isDisabled() && !k.isInvalid()) { // We can't create CertificateImpl here as CertificateImpl::setCertificate uses GpgME API // which interrupts our key listing here. So first get the keys from GpgME, then create the CertificateImpls keyList.push_back(k); commit 7b00829e27b0a26e9fa8d06bb651134f03a466e9 Author: Thorsten Behrens <thorsten.behr...@cib.de> Date: Wed Oct 18 12:48:55 2017 +0200 gpg4libre - tdf#113188 add option for minimal PGPKeyPacket Change-Id: I660e68074616f6953e6527e40ec22276ce8ef2fb Reviewed-on: https://gerrit.libreoffice.org/43492 Reviewed-by: Thorsten Behrens <thorsten.behr...@cib.de> Tested-by: Thorsten Behrens <thorsten.behr...@cib.de> diff --git a/external/gpgme/UnpackedTarball_gpgme.mk b/external/gpgme/UnpackedTarball_gpgme.mk index ca9fd79feaab..15259971f798 100644 --- a/external/gpgme/UnpackedTarball_gpgme.mk +++ b/external/gpgme/UnpackedTarball_gpgme.mk @@ -16,5 +16,6 @@ $(eval $(call gb_UnpackedTarball_set_patchlevel,gpgme,0)) $(eval $(call gb_UnpackedTarball_add_patches,gpgme, \ external/gpgme/find-libgpg-error-libassuan.patch \ external/gpgme/fix-autoconf-macros.patch \ + external/gpgme/add-minimal-keyexport.patch \ )) # vim: set noet sw=4 ts=4: diff --git a/external/gpgme/add-minimal-keyexport.patch b/external/gpgme/add-minimal-keyexport.patch new file mode 100644 index 000000000000..abaeb15897fc --- /dev/null +++ b/external/gpgme/add-minimal-keyexport.patch @@ -0,0 +1,68 @@ +--- lang/cpp/src/context.h.bak 2017-10-18 12:28:00.898945587 +0200 ++++ lang/cpp/src/context.h 2017-10-18 12:28:35.794832395 +0200 +@@ -178,10 +178,10 @@ + // Key Export + // + +- GpgME::Error exportPublicKeys(const char *pattern, Data &keyData); +- GpgME::Error exportPublicKeys(const char *pattern[], Data &keyData); +- GpgME::Error startPublicKeyExport(const char *pattern, Data &keyData); +- GpgME::Error startPublicKeyExport(const char *pattern[], Data &keyData); ++ GpgME::Error exportPublicKeys(const char *pattern, Data &keyData, bool minimal=false); ++ GpgME::Error exportPublicKeys(const char *pattern[], Data &keyData, bool minimal=false); ++ GpgME::Error startPublicKeyExport(const char *pattern, Data &keyData, bool minimal=false); ++ GpgME::Error startPublicKeyExport(const char *pattern[], Data &keyData, bool minimal=false); + + // + // Key Import +--- lang/cpp/src/context.cpp.bak 2017-10-18 12:27:50.830978224 +0200 ++++ lang/cpp/src/context.cpp 2017-10-18 12:30:13.278515603 +0200 +@@ -557,14 +557,14 @@ + } + } + +-Error Context::exportPublicKeys(const char *pattern, Data &keyData) ++Error Context::exportPublicKeys(const char *pattern, Data &keyData, bool minimal) + { + d->lastop = Private::Export; + Data::Private *const dp = keyData.impl(); +- return Error(d->lasterr = gpgme_op_export(d->ctx, pattern, 0, dp ? dp->data : 0)); ++ return Error(d->lasterr = gpgme_op_export(d->ctx, pattern, minimal ? GPGME_EXPORT_MODE_MINIMAL : 0, dp ? dp->data : 0)); + } + +-Error Context::exportPublicKeys(const char *patterns[], Data &keyData) ++Error Context::exportPublicKeys(const char *patterns[], Data &keyData, bool minimal) + { + d->lastop = Private::Export; + #ifndef HAVE_GPGME_EXT_KEYLIST_MODE_EXTERNAL_NONBROKEN +@@ -574,17 +574,17 @@ + } + #endif + Data::Private *const dp = keyData.impl(); +- return Error(d->lasterr = gpgme_op_export_ext(d->ctx, patterns, 0, dp ? dp->data : 0)); ++ return Error(d->lasterr = gpgme_op_export_ext(d->ctx, patterns, minimal ? GPGME_EXPORT_MODE_MINIMAL : 0, dp ? dp->data : 0)); + } + +-Error Context::startPublicKeyExport(const char *pattern, Data &keyData) ++Error Context::startPublicKeyExport(const char *pattern, Data &keyData, bool minimal) + { + d->lastop = Private::Export; + Data::Private *const dp = keyData.impl(); +- return Error(d->lasterr = gpgme_op_export_start(d->ctx, pattern, 0, dp ? dp->data : 0)); ++ return Error(d->lasterr = gpgme_op_export_start(d->ctx, pattern, minimal ? GPGME_EXPORT_MODE_MINIMAL : 0, dp ? dp->data : 0)); + } + +-Error Context::startPublicKeyExport(const char *patterns[], Data &keyData) ++Error Context::startPublicKeyExport(const char *patterns[], Data &keyData, bool minimal) + { + d->lastop = Private::Export; + #ifndef HAVE_GPGME_EXT_KEYLIST_MODE_EXTERNAL_NONBROKEN +@@ -594,7 +594,7 @@ + } + #endif + Data::Private *const dp = keyData.impl(); +- return Error(d->lasterr = gpgme_op_export_ext_start(d->ctx, patterns, 0, dp ? dp->data : 0)); ++ return Error(d->lasterr = gpgme_op_export_ext_start(d->ctx, patterns, minimal ? GPGME_EXPORT_MODE_MINIMAL : 0, dp ? dp->data : 0)); + } + + ImportResult Context::importKeys(const Data &data) diff --git a/officecfg/registry/schema/org/openoffice/Office/Common.xcs b/officecfg/registry/schema/org/openoffice/Office/Common.xcs index 118700782343..01651dabe8f5 100644 --- a/officecfg/registry/schema/org/openoffice/Office/Common.xcs +++ b/officecfg/registry/schema/org/openoffice/Office/Common.xcs @@ -2460,6 +2460,19 @@ </info> <value>true</value> </prop> + <group oor:name="OpenPGP"> + <info> + <desc>Contains security settings regarding the GnuPG/OpenPGP backend.</desc> + </info> + <prop oor:name="MinimalKeyExport" oor:type="xs:boolean" oor:nillable="false"> + <info> + <desc>Determines if the PGPKeyPacket element on signed ... etc. - the rest is truncated
_______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits