diff options
-rw-r--r-- | include/vcl/idle.hxx | 84 | ||||
-rw-r--r-- | include/vcl/timer.hxx | 45 | ||||
-rw-r--r-- | vcl/inc/svdata.hxx | 3 | ||||
-rw-r--r-- | vcl/inc/window.h | 1 | ||||
-rw-r--r-- | vcl/source/app/idle.cxx | 218 | ||||
-rw-r--r-- | vcl/source/app/svapp.cxx | 3 | ||||
-rw-r--r-- | vcl/source/app/timer.cxx | 98 |
7 files changed, 311 insertions, 141 deletions
diff --git a/include/vcl/idle.hxx b/include/vcl/idle.hxx new file mode 100644 index 000000000000..9da841490f2f --- /dev/null +++ b/include/vcl/idle.hxx @@ -0,0 +1,84 @@ +/* -*- 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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_VCL_IDLE_HXX +#define INCLUDED_VCL_IDLE_HXX + +#include <tools/link.hxx> +#include <tools/solar.h> +#include <vcl/dllapi.h> + +struct ImplIdleData; +struct ImplSVData; + +enum class IdlePriority { + VCL_IDLE_PRIORITY_HIGHEST = 0, // -> 0ms + VCL_IDLE_PRIORITY_HIGH = 1, // -> 1ms + VCL_IDLE_PRIORITY_REPAINT = 2, // -> 30ms + VCL_IDLE_PRIORITY_RESIZE = 3, // -> 50ms + VCL_IDLE_PRIORITY_MEDIUM = 4, // -> 50ms + VCL_IDLE_PRIORITY_LOW = 5, // -> 100ms + VCL_IDLE_PRIORITY_LOWER = 6, // -> 200ms + VCL_IDLE_PRIORITY_LOWEST = 7 // -> 400ms +}; + + +// To port from Timer -> Idle switch class name, +// s/Timeout/DoIdle/ etc. and select priority +class VCL_DLLPUBLIC Idle +{ +protected: + ImplIdleData* mpIdleData; + IdlePriority mePriority; + bool mbActive; + Link maIdleHdl; + + friend struct ImplIdleData; + +public: + Idle(); + Idle( const Idle& rIdle ); + virtual ~Idle(); + + void SetPriority( IdlePriority ePriority ) { mePriority = ePriority; } + IdlePriority GetPriority() const { return mePriority; } + + /// Make it possible to associate a callback with this idle handler + /// of course, you can also sub-class and override 'DoIdle' + void SetIdleHdl( const Link& rLink ) { maIdleHdl = rLink; } + const Link& GetIdleHdl() const { return maIdleHdl; } + + virtual void DoIdle(); + + void Start(); + void Stop(); + + bool IsActive() const { return mbActive; } + + Idle& operator=( const Idle& rIdle ); + static void ImplDeInitIdle(); + static void ImplIdleCallbackProc(); + + /// Process all pending idle tasks ahead of time in priority order. + static void ProcessAllIdleHandlers(); +}; + +#endif // INCLUDED_VCL_IDLE_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/vcl/timer.hxx b/include/vcl/timer.hxx index d93e7c01cdac..d2302275cff9 100644 --- a/include/vcl/timer.hxx +++ b/include/vcl/timer.hxx @@ -35,7 +35,6 @@ protected: sal_uLong mnTimeout; bool mbActive; bool mbAuto; - bool mbIdle; Link maTimeoutHdl; friend struct ImplTimerData; @@ -63,12 +62,7 @@ public: /// @internal static void ImplDeInitTimer(); - /// @internal - /// @p idle - allow also idle timers - static void ImplTimerCallbackProc( bool idle ); - - /// Process all pending idle tasks ahead of time in priority order. - static void ProcessAllIdleHandlers(); + static void ImplTimerCallbackProc(); }; /// An auto-timer is a multi-shot timer re-emitting itself at @@ -81,43 +75,6 @@ public: AutoTimer& operator=( const AutoTimer& rTimer ); }; - -enum IdlePriority { - VCL_IDLE_PRIORITY_HIGHEST, // -> 0ms - VCL_IDLE_PRIORITY_HIGH, // -> 1ms - VCL_IDLE_PRIORITY_REPAINT, // -> 30ms - VCL_IDLE_PRIORITY_RESIZE, // -> 50ms - VCL_IDLE_PRIORITY_MEDIUM, // -> 50ms - VCL_IDLE_PRIORITY_LOW, // -> 100ms - VCL_IDLE_PRIORITY_LOWER, // -> 200ms - VCL_IDLE_PRIORITY_LOWEST // -> 400ms -}; - - -// To port from Timer -> Idle switch class name, -// s/Timeout/DoIdle/ etc. and select priority -class VCL_DLLPUBLIC Idle : public Timer -{ - public: - Idle(); - Idle( IdlePriority ePriority ); - virtual ~Idle(); - - void SetPriority( IdlePriority ePriority ); - - /// Make it possible to associate a callback with this idle handler - /// of course, you can also sub-class and override 'DoIdle' - void SetIdleHdl( const Link& rLink ) { SetTimeoutHdl( rLink ); } - const Link& GetIdleHdl() const { return GetTimeoutHdl(); } - - void Start() { Timer::Start(); } - void Stop() { Timer::Stop(); } - - void DoIdle(); - - virtual void Timeout() SAL_OVERRIDE { DoIdle(); } -}; - #endif // INCLUDED_VCL_TIMER_HXX /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/inc/svdata.hxx b/vcl/inc/svdata.hxx index dd76b8578e95..fc49591f5a40 100644 --- a/vcl/inc/svdata.hxx +++ b/vcl/inc/svdata.hxx @@ -48,6 +48,7 @@ #include <config_version.h> struct ImplTimerData; +struct ImplIdleData; struct ImplConfigData; class ImplDirectFontSubstitution; struct ImplHotKey; @@ -65,6 +66,7 @@ class AllSettings; class NotifyEvent; class Timer; class AutoTimer; +class Idle; class Help; class ImageList; class Image; @@ -310,6 +312,7 @@ struct ImplSVData sal_uLong mnThreadCount; // is VCL MultiThread enabled ImplConfigData* mpFirstConfigData; // pointer to the first config block ImplTimerData* mpFirstTimerData; // list of all running timers + ImplIdleData* mpFirstIdleData; // list of all running idles SalTimer* mpSalTimer; // interface to sal event loop/timers SalI18NImeStatus* mpImeStatus; // interface to ime status window SalSystem* mpSalSystem; // SalSystem interface diff --git a/vcl/inc/window.h b/vcl/inc/window.h index 92e94a2b62f2..31c5dff7f4ea 100644 --- a/vcl/inc/window.h +++ b/vcl/inc/window.h @@ -33,6 +33,7 @@ #include <vcl/pointr.hxx> #include <vcl/salnativewidgets.hxx> #include <vcl/timer.hxx> +#include <vcl/idle.hxx> #include <vcl/vclevent.hxx> #include <vector> diff --git a/vcl/source/app/idle.cxx b/vcl/source/app/idle.cxx new file mode 100644 index 000000000000..bf715fb1e5bc --- /dev/null +++ b/vcl/source/app/idle.cxx @@ -0,0 +1,218 @@ +/* -*- 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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <vcl/svapp.hxx> +#include <vcl/idle.hxx> + +#include <svdata.hxx> +#include <salinst.hxx> + +struct ImplIdleData +{ + ImplIdleData* mpNext; // Pointer to the next Instance + Idle* mpIdle; // Pointer to VCL Idle instance + bool mbDelete; // Was Idle deleted during Update()? + bool mbInIdle; // Are we in a idle handler? + + void Invoke() + { + if (mbDelete || mbInIdle ) + return; + + mbDelete = true; + mpIdle->mbActive = false; + + // invoke it + mbInIdle = true; + mpIdle->DoIdle(); + mbInIdle = false; + } + + static ImplIdleData *GetFirstIdle() + { + ImplSVData* pSVData = ImplGetSVData(); + ImplIdleData *pMostUrgent = NULL; + + for ( ImplIdleData *p = pSVData->mpFirstIdleData; p; p = p->mpNext ) + { + if ( !p->mpIdle || p->mbDelete ) + continue; + if (!pMostUrgent) + pMostUrgent = p; + else + { + // Find the highest priority one somehow. + if ( p->mpIdle->GetPriority() < pMostUrgent->mpIdle->GetPriority() ) + pMostUrgent = p; + } + } + + return pMostUrgent; + } +}; + +void Idle::ImplDeInitIdle() +{ + ImplSVData* pSVData = ImplGetSVData(); + ImplIdleData* pIdleData = pSVData->mpFirstIdleData; + + if ( pIdleData ) + { + do + { + ImplIdleData* pTempIdleData = pIdleData; + if ( pIdleData->mpIdle ) + { + pIdleData->mpIdle->mbActive = false; + pIdleData->mpIdle->mpIdleData = NULL; + } + pIdleData = pIdleData->mpNext; + delete pTempIdleData; + } + while ( pIdleData ); + + pSVData->mpFirstIdleData = NULL; + } +} + +void Idle::ProcessAllIdleHandlers() +{ + // process all pending Idle + ImplIdleData* pIdleData; + ImplIdleData* pPrevIdleData; + while (pIdleData = ImplIdleData::GetFirstIdle()) + { + pIdleData->Invoke(); + } + + pIdleData = pSVData->mpFirstIdleData; + while ( pIdleData ) + { + // Was timer destroyed in the meantime? + if ( pIdleData->mbDelete ) + { + if ( pPrevIdleData ) + pPrevIdleData->mpNext = pIdleData->mpNext; + else + pSVData->mpFirstIdleData = pIdleData->mpNext; + if ( pIdleData->mpIdle ) + pIdleData->mpIdle->mpIdleData = NULL; + ImplIdleData* pTempIdleData = pIdleData; + pIdleData = pIdleData->mpNext; + delete pTempIdleData; + } + else + { + pPrevIdleData = pIdleData; + pIdleData = pIdleData->mpNext; + } + } +} + +void Idle::DoIdle() +{ + maIdleHdl.Call( this ); +} + +void Idle::Start() +{ + mbActive = true; + + ImplSVData* pSVData = ImplGetSVData(); + if ( !mpIdleData ) + { + // insert timer and start + mpIdleData = new ImplIdleData; + mpIdleData->mpIdle = this; + mpIdleData->mbDelete = false; + mpIdleData->mbInIdle = false; + + // insert last due to SFX! + ImplIdleData* pPrev = NULL; + ImplIdleData* pData = pSVData->mpFirstIdleData; + while ( pData ) + { + pPrev = pData; + pData = pData->mpNext; + } + mpIdleData->mpNext = NULL; + if ( pPrev ) + pPrev->mpNext = mpIdleData; + else + pSVData->mpFirstIdleData = mpIdleData; + } + else if( !mpIdleData->mpIdle ) // TODO: remove when guilty found + { + OSL_FAIL( "Idle::Start() on a destroyed Idle!" ); + } + else + { + mpIdleData->mbDelete = false; + } +} + +void Idle::Stop() +{ + mbActive = false; + + if ( mpIdleData ) + mpIdleData->mbDelete = true; +} + +Idle& Idle::operator=( const Idle& rIdle ) +{ + if ( IsActive() ) + Stop(); + + mbActive = false; + mePriority = rIdle.mePriority; + maIdleHdl = rIdle.maIdleHdl; + + if ( rIdle.IsActive() ) + Start(); + + return *this; +} + +Idle::Idle(): + mpIdleData(NULL), + mePriority(VCL_IDLE_PRIORITY_HIGH), + mbActive(false) +{ +} + +Idle::Idle( const Idle& rIdle ): + mpIdleData(NULL), + mePriority(rIdle.mePriority), + mbActive(false), + maIdleHdl(rIdle.maIdleHdl) +{ + if ( rIdle.IsActive() ) + Start(); +} + +Idle::~Idle() +{ + if ( mpIdleData ) + { + mpIdleData->mbDelete = true; + mpIdleData->mpIdle = NULL; + } +} +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/source/app/svapp.cxx b/vcl/source/app/svapp.cxx index 3fd670202e5a..3b6b16142cb2 100644 --- a/vcl/source/app/svapp.cxx +++ b/vcl/source/app/svapp.cxx @@ -45,6 +45,7 @@ #include "vcl/cvtgrf.hxx" #include "vcl/unowrap.hxx" #include "vcl/timer.hxx" +#include "vcl/idle.hxx" #include "vcl/unohelp.hxx" #include "vcl/lazydelete.hxx" @@ -349,7 +350,7 @@ inline void ImplYield( bool i_bWait, bool i_bAllEvents ) } //Process all idles - Timer::Timer::ProcessAllIdleHandlers(); + Idle::Idle::ProcessAllIdleHandlers(); pSVData->maAppData.mnDispatchLevel++; // do not wait for events if application was already quit; in that diff --git a/vcl/source/app/timer.cxx b/vcl/source/app/timer.cxx index 88b6188d54e9..9ea7c40f9a3a 100644 --- a/vcl/source/app/timer.cxx +++ b/vcl/source/app/timer.cxx @@ -59,27 +59,6 @@ struct ImplTimerData { return mnUpdateTime + mpTimer->mnTimeout; } - static ImplTimerData *GetFirstIdle() - { - ImplSVData* pSVData = ImplGetSVData(); - ImplTimerData *pMostUrgent = NULL; - - for ( ImplTimerData *p = pSVData->mpFirstTimerData; p; p = p->mpNext ) - { - if ( !p->mpTimer || p->mbDelete || !p->mpTimer->mbIdle ) - continue; - if (!pMostUrgent) - pMostUrgent = p; - else - { - // Find the highest priority one somehow. - if ( p->GetDeadline() < pMostUrgent->GetDeadline() ) - pMostUrgent = p; - } - } - - return pMostUrgent; - } }; void Timer::ImplDeInitTimer() @@ -151,7 +130,7 @@ void Timer::ImplTimerCallbackProc( bool idle ) // If the timer is not new, was not deleted, and if it is not in the timeout handler, then // call the handler as soon as the time is up. if ( (pTimerData->mnTimerUpdate < pSVData->mnTimerUpdate) && - !pTimerData->mbDelete && !pTimerData->mbInTimeout && !pTimerData->mpTimer->mbIdle) + !pTimerData->mbDelete && !pTimerData->mbInTimeout) { // time has expired if ( pTimerData->GetDeadline() <= nTime ) @@ -231,23 +210,11 @@ void Timer::ImplTimerCallbackProc( bool idle ) pSVData->mbNotAllTimerCalled = false; } -void Timer::ProcessAllIdleHandlers() -{ - // process all pending Idle timers - ImplTimerData* pTimerData; - while (pTimerData = - ImplTimerData::GetFirstIdle()) - { - pTimerData->Invoke(); - } -} - Timer::Timer(): mpTimerData(NULL), mnTimeout(1), mbActive(false), - mbAuto(false), - mbIdle(false) + mbAuto(false) { } @@ -256,7 +223,6 @@ Timer::Timer( const Timer& rTimer ): mnTimeout(rTimer.mnTimeout), mbActive(false), mbAuto(false), - mbIdle(false), maTimeoutHdl(rTimer.maTimeoutHdl) { if ( rTimer.IsActive() ) @@ -382,64 +348,4 @@ AutoTimer& AutoTimer::operator=( const AutoTimer& rTimer ) Timer::operator=( rTimer ); return *this; } - -Idle::Idle() - : Timer() -{ - mbIdle = true; - SetPriority(VCL_IDLE_PRIORITY_LOWEST); -} - -Idle::Idle( IdlePriority ePriority ) - : Timer() -{ - mbIdle = true; - SetPriority( ePriority ); -} - -void Idle::SetPriority( IdlePriority ePriority ) -{ - sal_uLong nTimeoutMS = 0; - - // Ultimately this will just be a sort key in a work queue. - switch (ePriority) { - case VCL_IDLE_PRIORITY_HIGHEST: - nTimeoutMS = 0; - break; - case VCL_IDLE_PRIORITY_HIGH: - nTimeoutMS = 1; - break; - case VCL_IDLE_PRIORITY_REPAINT: - nTimeoutMS = 30; - break; - case VCL_IDLE_PRIORITY_RESIZE: - nTimeoutMS = 50; - break; - case VCL_IDLE_PRIORITY_MEDIUM: - nTimeoutMS = 50; - break; - case VCL_IDLE_PRIORITY_LOW: - nTimeoutMS = 100; - break; - case VCL_IDLE_PRIORITY_LOWER: - nTimeoutMS = 200; - break; - case VCL_IDLE_PRIORITY_LOWEST: - default: - nTimeoutMS = 400; - break; - } - SetTimeout( nTimeoutMS ); -} - -void Idle::DoIdle() -{ - maTimeoutHdl.Call( this ); -} - - -Idle::~Idle() -{ -} - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |