[Libreoffice-commits] core.git: Branch 'feature/new-vcl-scheduler' - 297 commits - accessibility/inc accessibility/source avmedia/source basctl/source basic/source chart2/source comphelper/source compilerplugins/clang config_host/config_graphite.h.in config_host.mk.in configure.ac connectivity/source cppcanvas/source cppuhelper/source cui/source cui/uiconfig dbaccess/source dbaccess/uiconfig dbaccess/UIConfig_dbapp.mk desktop/qa desktop/source download.lst drawinglayer/source editeng/source extensions/source external/curl external/harfbuzz external/icu external/jpeg-turbo external/libzmf external/poppler extras/source filter/source forms/source formula/source formula/uiconfig fpicker/source framework/inc framework/source .gitignore helpcompiler/source helpcontent2 i18npool/source i18nutil/source icon-themes/breeze_dark icon-themes/breeze_svg idlc/source include/comphelper include/connectivity include/cppcanvas include/dbaccess include/editeng include/framework include/oox include/rtl include/sal include/sax include/sfx2 include/svl include/svtools include/svx include/tools include/unotools include/vcl jvmfwk/distributions linguistic/source lotuswordpro/source mysqlc/source offapi/com officecfg/registry oox/source package/source reportdesign/inc reportdesign/source RepositoryExternal.mk sal/osl sal/qa sax/source scaddins/source sc/inc sc/Library_scfilt.mk sc/qa scripting/source sc/source sdext/source sd/qa sd/source sfx2/classification sfx2/source shell/source slideshow/source solenv/bin solenv/gbuild solenv/gdb solenv/Module_solenv.mk solenv/qa starmath/inc starmath/source stoc/source svgio/source svl/Library_svl.mk svl/source svtools/source svx/AllLangResTarget_svx.mk svx/qa svx/source svx/uiconfig svx/UIConfig_svx.mk sw/inc sw/qa sw/source sw/uiconfig sysui/desktop toolkit/source ucb/qa ucb/source unodevtools/source unotools/Library_utl.mk unotools/source unoxml/source vbahelper/source vcl/headless vcl/inc vcl/null vcl/opengl vcl/osx vcl/qa vcl/quartz vcl/README.scheduler vcl/README.vars vcl/source vcl/unx vcl/win vcl/workben wizards/source writerfilter/source writerperfect/Library_wpftcalc.mk writerperfect/Library_wpftdraw.mk writerperfect/Library_wpftwriter.mk xmloff/source xmlsecurity/inc xmlsecurity/Library_xmlsecurity.mk xmlsecurity/qa xmlsecurity/source
Jan-Marek Glogowski
glogow at fbihome.de
Thu Nov 3 16:12:14 UTC 2016
Rebased ref, commits from common ancestor:
commit 4d170198eaba05448bf5db47d4e07e2bba853069
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date: Wed Nov 2 12:33:51 2016 +0100
Temporary workaround for AppIcon recursion @quikee
Change-Id: I6d39d719ad0afb593fec15c9213cc5906c711cbc
diff --git a/vcl/unx/generic/window/salframe.cxx b/vcl/unx/generic/window/salframe.cxx
index 9f3f6f6..65a1d85 100644
--- a/vcl/unx/generic/window/salframe.cxx
+++ b/vcl/unx/generic/window/salframe.cxx
@@ -250,6 +250,7 @@ static bool lcl_SelectAppIconPixmap( SalDisplay *pDisplay, SalX11Screen nXScreen
sal_uInt16 nIcon, sal_uInt16 iconSize,
Pixmap& icon_pixmap, Pixmap& icon_mask, NetWmIconData& netwm_icon)
{
+ return true;
if( ! ImplGetResMgr() )
return false;
commit 60c0ae120dc7b77e6c73a74337ed0bafa53790e3
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date: Wed Nov 2 16:47:29 2016 +0100
Add VCL AutoTimer::Stop() test
Ensure we can stop a timer inside Invoke().
Change-Id: I6162b32b8d1cab8a017abc112feb4b31a9600d17
diff --git a/vcl/qa/cppunit/timer.cxx b/vcl/qa/cppunit/timer.cxx
index 8fe634d..fe171db 100644
--- a/vcl/qa/cppunit/timer.cxx
+++ b/vcl/qa/cppunit/timer.cxx
@@ -64,6 +64,7 @@ public:
void testAutoTimer();
void testMultiAutoTimers();
#endif
+ void testAutoTimerStop();
void testRecursiveTimer();
void testSlowTimerCallback();
void testInvokedDisposed();
@@ -79,6 +80,7 @@ public:
CPPUNIT_TEST(testAutoTimer);
CPPUNIT_TEST(testMultiAutoTimers);
#endif
+ CPPUNIT_TEST(testAutoTimerStop);
CPPUNIT_TEST(testRecursiveTimer);
CPPUNIT_TEST(testSlowTimerCallback);
CPPUNIT_TEST(testInvokedDisposed);
@@ -181,17 +183,23 @@ void TimerTest::testDurations()
class AutoTimerCount : public AutoTimer
{
sal_Int32 &mrCount;
+ const sal_Int32 mnMaxCount;
+
public:
- AutoTimerCount( sal_uLong nMS, sal_Int32 &rCount ) :
- AutoTimer(), mrCount( rCount )
+ AutoTimerCount( sal_uLong nMS, sal_Int32 &rCount,
+ const sal_Int32 nMaxCount = -1 )
+ : AutoTimer(), mrCount( rCount ), mnMaxCount( nMaxCount )
{
SetTimeout( nMS );
Start();
mrCount = 0;
}
+
virtual void Invoke() override
{
- mrCount++;
+ ++mrCount;
+ if ( mrCount == mnMaxCount )
+ Stop();
}
};
@@ -297,6 +305,17 @@ void TimerTest::testMultiAutoTimers()
}
#endif // TEST_TIMERPRECISION
+void TimerTest::testAutoTimerStop()
+{
+ sal_Int32 nProcessCount = 0, nTimerCount = 0;
+ const sal_Int32 nMaxCount = 100;
+ AutoTimerCount aAutoTimer( 0, nTimerCount, nMaxCount );
+ while ( Scheduler::ProcessTaskScheduling( IdleRunPolicy::IDLE_VIA_LOOP ) )
+ ++nProcessCount;
+ CPPUNIT_ASSERT_EQUAL( nProcessCount, nMaxCount );
+ CPPUNIT_ASSERT_EQUAL( nTimerCount, nMaxCount );
+}
+
class YieldTimer : public Timer
{
commit 4ab482dfb0492b9b76824d9c505937e1d803c269
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date: Wed Nov 2 16:43:02 2016 +0100
A sensible timer handling for Calc input
There is no need to destroy and recreate the timer object.
Simply stop and start the timer as required.
Change-Id: I2885fef8bdb90c379dc2e9b9caf986d250face5c
diff --git a/sc/source/ui/app/inputhdl.cxx b/sc/source/ui/app/inputhdl.cxx
index e0712c4..47585b9 100644
--- a/sc/source/ui/app/inputhdl.cxx
+++ b/sc/source/ui/app/inputhdl.cxx
@@ -644,6 +644,10 @@ ScInputHandler::ScInputHandler()
pActiveViewSh = nullptr;
// Bindings (only still used for Invalidate) are retrieved if needed on demand
+
+ pDelayTimer = new Timer( "ScInputHandlerDelay timer" );
+ pDelayTimer->SetTimeout( 500 ); // 500 ms delay
+ pDelayTimer->SetTimeoutHdl( LINK( this, ScInputHandler, DelayTimer ) );
}
ScInputHandler::~ScInputHandler()
@@ -3714,36 +3718,23 @@ void ScInputHandler::NotifyChange( const ScInputHdlState* pState,
{
if ( !pInputWin->IsEnabled())
{
+ pDelayTimer->Stop();
pInputWin->Enable();
- if(pDelayTimer )
- {
- DELETEZ( pDelayTimer );
- }
}
}
else if(pScMod->IsRefDialogOpen())
{ // Because every document has its own InputWin,
// we should start Timer again, because the input line may
// still be active
- if ( !pDelayTimer )
- {
- pDelayTimer = new Timer("Restart ScInputHandlerDelay timer");
- pDelayTimer->SetTimeout( 500 ); // 500 ms delay
- pDelayTimer->SetTimeoutHdl( LINK( this, ScInputHandler, DelayTimer ) );
+ if ( !pDelayTimer->IsActive() )
pDelayTimer->Start();
- }
}
}
}
else // !pState || !pActiveViewSh
{
- if ( !pDelayTimer )
- {
- pDelayTimer = new Timer("ScInputHandlerDelay timer");
- pDelayTimer->SetTimeout( 500 ); // 500 ms delay
- pDelayTimer->SetTimeoutHdl( LINK( this, ScInputHandler, DelayTimer ) );
+ if ( !pDelayTimer->IsActive() )
pDelayTimer->Start();
- }
}
HideTip();
@@ -3759,50 +3750,42 @@ void ScInputHandler::UpdateCellAdjust( SvxCellHorJustify eJust )
void ScInputHandler::ResetDelayTimer()
{
- if(pDelayTimer!=nullptr)
+ if( pDelayTimer->IsActive() )
{
- DELETEZ( pDelayTimer );
-
- if ( pInputWin)
- {
+ pDelayTimer->Stop();
+ if ( pInputWin )
pInputWin->Enable();
- }
}
}
-IMPL_LINK( ScInputHandler, DelayTimer, Timer*, pTimer, void )
+IMPL_LINK_NOARG( ScInputHandler, DelayTimer, Timer*, void )
{
- if ( pTimer == pDelayTimer )
+ if ( nullptr == pLastState || SC_MOD()->IsFormulaMode() || SC_MOD()->IsRefDialogOpen())
{
- DELETEZ( pDelayTimer );
-
- if ( nullptr == pLastState || SC_MOD()->IsFormulaMode() || SC_MOD()->IsRefDialogOpen())
+ //! New method at ScModule to query if function autopilot is open
+ SfxViewFrame* pViewFrm = SfxViewFrame::Current();
+ if ( pViewFrm && pViewFrm->GetChildWindow( SID_OPENDLG_FUNCTION ) )
{
- //! New method at ScModule to query if function autopilot is open
- SfxViewFrame* pViewFrm = SfxViewFrame::Current();
- if ( pViewFrm && pViewFrm->GetChildWindow( SID_OPENDLG_FUNCTION ) )
+ if ( pInputWin)
{
- if ( pInputWin)
- {
- pInputWin->EnableButtons( false );
- pInputWin->Disable();
- }
+ pInputWin->EnableButtons( false );
+ pInputWin->Disable();
}
- else if ( !bFormulaMode ) // Keep formula e.g. for help
- {
- bInOwnChange = true; // disable ModifyHdl (reset below)
-
- pActiveViewSh = nullptr;
- pEngine->SetText( EMPTY_OUSTRING );
- if ( pInputWin )
- {
- pInputWin->SetPosString( EMPTY_OUSTRING );
- pInputWin->SetTextString( EMPTY_OUSTRING );
- pInputWin->Disable();
- }
+ }
+ else if ( !bFormulaMode ) // Keep formula e.g. for help
+ {
+ bInOwnChange = true; // disable ModifyHdl (reset below)
- bInOwnChange = false;
+ pActiveViewSh = nullptr;
+ pEngine->SetText( EMPTY_OUSTRING );
+ if ( pInputWin )
+ {
+ pInputWin->SetPosString( EMPTY_OUSTRING );
+ pInputWin->SetTextString( EMPTY_OUSTRING );
+ pInputWin->Disable();
}
+
+ bInOwnChange = false;
}
}
}
commit d61ed41357318e7feadac4e8508b4ce28f0c75c7
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date: Tue Nov 1 09:32:55 2016 +0100
Revert "sfx2: ensure that no timers are running...
... after SfxApplication dies"
Also adds two asserts to check the VCL DeInit status in the
scheduler Init and DeInit functions.
This reverts commit 2e29a518b04250b5f9cc9d0d77da3df076834d60.
Change-Id: I447b520f8a54634e98deb70579efee47588fe28c
diff --git a/sfx2/source/appl/appinit.cxx b/sfx2/source/appl/appinit.cxx
index 592420e..a23ba7e 100644
--- a/sfx2/source/appl/appinit.cxx
+++ b/sfx2/source/appl/appinit.cxx
@@ -46,7 +46,6 @@
#include <cppuhelper/supportsservice.hxx>
#include <vcl/edit.hxx>
-#include <vcl/scheduler.hxx>
#include <sfx2/unoctitm.hxx>
#include "app.hrc"
@@ -106,10 +105,6 @@ void SAL_CALL SfxTerminateListener_Impl::notifyTermination( const EventObject& a
SolarMutexGuard aGuard;
utl::ConfigManager::storeConfigItems();
- // Timers may access the SfxApplication and are only deleted in
- // Application::Quit(), which is asynchronous (PostUserEvent) - disable!
- Scheduler::ImplDeInitScheduler();
-
SfxApplication* pApp = SfxGetpApp();
pApp->Broadcast( SfxHint( SFX_HINT_DEINITIALIZING ) );
pApp->Get_Impl()->pAppDispatch->ReleaseAll();
diff --git a/vcl/source/app/scheduler.cxx b/vcl/source/app/scheduler.cxx
index 5f41396c..5de64e7 100644
--- a/vcl/source/app/scheduler.cxx
+++ b/vcl/source/app/scheduler.cxx
@@ -127,6 +127,7 @@ void Scheduler::SetDeletionFlags()
bool Scheduler::ImplInitScheduler()
{
ImplSVData *pSVData = ImplGetSVData();
+ assert( !pSVData->mbDeInit );
pSVData->mpFreeListMutex = new ::osl::Mutex();
if ( nullptr == pSVData->mpFreeListMutex )
@@ -150,6 +151,7 @@ bool Scheduler::ImplInitScheduler()
void Scheduler::ImplDeInitScheduler()
{
ImplSVData *pSVData = ImplGetSVData();
+ assert( pSVData->mbDeInit );
if (pSVData->mpSalTimer) pSVData->mpSalTimer->Stop();
DELETEZ( pSVData->mpSalTimer );
commit b24e00e233016cbbd16ae1d6c6682a5d69464fa7
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date: Mon Oct 31 22:50:21 2016 +0100
KDE4 change scheduler timer to be single-shot
Change-Id: I21a0a62bd0cd122e0da676579d2b2a93264acdd8
diff --git a/vcl/unx/kde4/KDEXLib.cxx b/vcl/unx/kde4/KDEXLib.cxx
index 13bc8e9..47fba56 100644
--- a/vcl/unx/kde4/KDEXLib.cxx
+++ b/vcl/unx/kde4/KDEXLib.cxx
@@ -58,6 +58,7 @@ KDEXLib::KDEXLib() :
// the timer has to use a Qt::QueuedConnection, otherwise the nested event
// loop will detect the blocking timer and drop it from the polling
// freezing LO X11 processing.
+ timeoutTimer.setSingleShot( true );
connect( &timeoutTimer, SIGNAL( timeout()), this, SLOT( timeoutActivated()), Qt::QueuedConnection );
connect( &userEventTimer, SIGNAL( timeout()), this, SLOT( userEventActivated()), Qt::QueuedConnection );
commit 96d451d7827a211f30971b820d5a0c728817de38
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date: Sun Oct 30 14:30:57 2016 +0000
Add VCL scheduler mp-sc locking: invoke+stop
AKA multiple producers - single consumer.
While a task is invoked, prevent
1. freeing the invoked Scheduler object
2. detaching ImplSchedulerData from the Scheduler object
This effectively blocks inside the Dispose function until Invoke
has finished.
For self-deleting objects, you have to explicitly call the Dispose
function with the DisposePolicy::IgnoreInvoke.
Change-Id: I6d23561e4069d0e541751e70554a04901c1d17d7
diff --git a/drawinglayer/source/primitive2d/textlayoutdevice.cxx b/drawinglayer/source/primitive2d/textlayoutdevice.cxx
index 3c64903..1750362 100644
--- a/drawinglayer/source/primitive2d/textlayoutdevice.cxx
+++ b/drawinglayer/source/primitive2d/textlayoutdevice.cxx
@@ -91,6 +91,8 @@ namespace
void ImpTimedRefDev::Invoke()
{
+ // deleting ourself, so explicitly dispose, ignoring bInScheduler state!
+ this->Dispose( DisposePolicy::IGNORE_INVOKE );
// for obvious reasons, do not call anything after this
mrOwnerOfMe.reset();
}
diff --git a/include/vcl/scheduler.hxx b/include/vcl/scheduler.hxx
index 806d555..62efb21 100644
--- a/include/vcl/scheduler.hxx
+++ b/include/vcl/scheduler.hxx
@@ -35,7 +35,8 @@ enum class SchedulerPriority
REPAINT, ///< All repaint events should go in here
POST_PAINT, ///< Everything running directly after painting
DEFAULT_IDLE, ///< Default idle priority
- LOWEST ///< Low, very idle cleanup tasks
+ LOWEST, ///< Low, very idle cleanup tasks
+ DISPOSED ///< Internal priority for desposed tasks
};
enum class IdleRunPolicy
@@ -44,6 +45,12 @@ enum class IdleRunPolicy
IDLE_VIA_LOOP ///< Return indicates processed events, so they are processed in a loop
};
+enum class DisposePolicy
+{
+ WAIT_INVOKE, ///< Wait for Invoke() to finish, if invoked
+ IGNORE_INVOKE ///< Dispose object ignoring Invoke() state (for self-deleting objects)
+};
+
class VCL_DLLPUBLIC Scheduler
{
friend struct ImplSchedulerData;
@@ -75,7 +82,7 @@ public:
virtual ~Scheduler();
Scheduler& operator=( const Scheduler& rScheduler );
- void SetPriority(SchedulerPriority ePriority) { mePriority = ePriority; }
+ void SetPriority(SchedulerPriority ePriority);
SchedulerPriority GetPriority() const { return mePriority; }
void SetDebugName( const sal_Char *pDebugName ) { mpDebugName = pDebugName; }
@@ -86,8 +93,25 @@ public:
virtual void Start();
void Stop();
-
- inline bool IsActive() const;
+ /**
+ * Dispose will clean up the Scheduler object
+ *
+ * It'll wait until the object is no longer invoked.
+ *
+ * Also call Dispose(), if Invoke() depends on any resources you're going
+ * to destroy.
+ *
+ * If you have a self-deleting object, i.e. an object composed or inherited
+ * from Scheduler, which you delete inside it's Invoke() function, you must
+ * explicitly Dispose() the invoked Scheduler object using the
+ * DisposePolicy::IGNORE_INVOKE policy, otherwise the Schedulers destructor
+ * will deadlock waiting for Invoke() to finish!
+ *
+ * @param ePolicy Optionally ignore the Schedulers Invoke() state.
+ */
+ void Dispose( DisposePolicy ePolicy = DisposePolicy::WAIT_INVOKE );
+
+ bool IsActive() const;
static bool ImplInitScheduler();
static void ImplDeInitScheduler();
@@ -109,11 +133,6 @@ public:
static bool GetDeterministicMode();
};
-inline bool Scheduler::IsActive() const
-{
- return nullptr != mpSchedulerData;
-}
-
template< typename charT, typename traits >
inline std::basic_ostream<charT, traits> & operator <<(
std::basic_ostream<charT, traits> & stream, const Scheduler& scheduler )
diff --git a/sd/source/core/drawdoc4.cxx b/sd/source/core/drawdoc4.cxx
index 72d6889..532cee4 100644
--- a/sd/source/core/drawdoc4.cxx
+++ b/sd/source/core/drawdoc4.cxx
@@ -864,6 +864,8 @@ IMPL_LINK_NOARG(SdDrawDocument, OnlineSpellingHdl, Idle *, void)
// Initial spelling has finished
mbInitialOnlineSpellingEnabled = false;
+ // deleting ourself, so explicitly dispose, ignoring bInScheduler state!
+ mpOnlineSpellingIdle->Dispose( DisposePolicy::IGNORE_INVOKE );
// Stop search
StopOnlineSpelling();
diff --git a/sd/source/ui/view/ViewShellImplementation.cxx b/sd/source/ui/view/ViewShellImplementation.cxx
index 87f03b9..4451451 100644
--- a/sd/source/ui/view/ViewShellImplementation.cxx
+++ b/sd/source/ui/view/ViewShellImplementation.cxx
@@ -358,6 +358,8 @@ IMPL_LINK_NOARG(ViewShell::Implementation::ToolBarManagerLock, TimeoutCallback,
}
else
{
+ // deleting ourself, so explicitly dispose, ignoring bInScheduler state!
+ maTimer.Dispose( DisposePolicy::IGNORE_INVOKE );
mpSelf.reset();
}
}
diff --git a/sfx2/source/appl/appcfg.cxx b/sfx2/source/appl/appcfg.cxx
index c7283b2..0f09535 100644
--- a/sfx2/source/appl/appcfg.cxx
+++ b/sfx2/source/appl/appcfg.cxx
@@ -137,6 +137,8 @@ IMPL_LINK(SfxEventAsyncer_Impl, IdleHdl, Idle*, pAsyncIdle, void)
SfxGetpApp()->Broadcast( aHint );
if ( xRef.Is() )
xRef->Broadcast( aHint );
+ // deleting ourself, so explicitly dispose, ignoring bInScheduler state!
+ pAsyncIdle->Dispose( DisposePolicy::IGNORE_INVOKE );
delete this;
}
diff --git a/sfx2/source/control/itemdel.cxx b/sfx2/source/control/itemdel.cxx
index c94d362..32ead9d 100644
--- a/sfx2/source/control/itemdel.cxx
+++ b/sfx2/source/control/itemdel.cxx
@@ -68,6 +68,8 @@ SfxItemDisruptor_Impl::~SfxItemDisruptor_Impl()
IMPL_LINK_NOARG(SfxItemDisruptor_Impl, Delete, Idle*, void)
{
+ // deleting ourself, so explicitly dispose, ignoring bInScheduler state!
+ m_Idle.Dispose( DisposePolicy::IGNORE_INVOKE );
delete this;
}
diff --git a/vcl/inc/svdata.hxx b/vcl/inc/svdata.hxx
index 8fb13cf..64c0c8d 100644
--- a/vcl/inc/svdata.hxx
+++ b/vcl/inc/svdata.hxx
@@ -99,16 +99,16 @@ namespace osl
class Mutex;
}
+typedef std::vector<Link<VclWindowEvent&,bool> > SVAppKeyListeners;
+typedef std::pair<VclPtr<vcl::Window>, ImplPostEventData *> ImplPostEventPair;
+typedef void* oslCondition;
+
class LocaleConfigurationListener : public utl::ConfigurationListener
{
public:
virtual void ConfigurationChanged( utl::ConfigurationBroadcaster*, sal_uInt32 ) override;
};
-typedef std::vector<Link<VclWindowEvent&,bool> > SVAppKeyListeners;
-
-typedef std::pair<VclPtr<vcl::Window>, ImplPostEventData *> ImplPostEventPair;
-
struct ImplSVAppData
{
enum ImeStatusWindowMode
@@ -332,6 +332,8 @@ struct ImplSVData
SalTimer* mpSalTimer = nullptr; // interface to sal event loop/timers
osl::Mutex* mpAppendMutex = nullptr;
osl::Mutex* mpFreeListMutex = nullptr;
+ osl::Mutex* mpInvokeMutex = nullptr;
+ oslCondition maInvokeCondition = nullptr;
SalI18NImeStatus* mpImeStatus = nullptr; // interface to ime status window
SalSystem* mpSalSystem = nullptr; // SalSystem interface
diff --git a/vcl/qa/cppunit/timer.cxx b/vcl/qa/cppunit/timer.cxx
index 8506f77..8fe634d 100644
--- a/vcl/qa/cppunit/timer.cxx
+++ b/vcl/qa/cppunit/timer.cxx
@@ -66,6 +66,7 @@ public:
#endif
void testRecursiveTimer();
void testSlowTimerCallback();
+ void testInvokedDisposed();
CPPUNIT_TEST_SUITE(TimerTest);
CPPUNIT_TEST(testIdle);
@@ -80,6 +81,7 @@ public:
#endif
CPPUNIT_TEST(testRecursiveTimer);
CPPUNIT_TEST(testSlowTimerCallback);
+ CPPUNIT_TEST(testInvokedDisposed);
CPPUNIT_TEST_SUITE_END();
};
@@ -354,6 +356,31 @@ void TimerTest::testSlowTimerCallback()
Application::Yield();
}
+
+class InvokedDisposedIdle : public Idle
+{
+public:
+ InvokedDisposedIdle() : Idle()
+ {
+ Start();
+ }
+
+ virtual void Invoke() override
+ {
+ // Invoked event is blocked, so nothing to do
+ CPPUNIT_ASSERT( !Scheduler::ProcessTaskScheduling( IdleRunPolicy::IDLE_VIA_LOOP ) );
+ // Without explicit Dispose() => deadlock
+ Dispose( DisposePolicy::IGNORE_INVOKE );
+ delete this;
+ }
+};
+
+void TimerTest::testInvokedDisposed()
+{
+ new InvokedDisposedIdle();
+ Scheduler::ProcessAllPendingEvents();
+}
+
CPPUNIT_TEST_SUITE_REGISTRATION(TimerTest);
CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/vcl/source/app/scheduler.cxx b/vcl/source/app/scheduler.cxx
index d912236..5f41396c 100644
--- a/vcl/source/app/scheduler.cxx
+++ b/vcl/source/app/scheduler.cxx
@@ -24,6 +24,7 @@
#include <svdata.hxx>
#include <salinst.hxx>
#include <osl/mutex.hxx>
+#include <osl/conditn.h>
/**
@@ -61,26 +62,66 @@ void ImplSchedulerData::Invoke()
{
DBG_TESTSOLARMUTEX();
- assert( mpScheduler && !mbInScheduler );
- if ( !mpScheduler || mbInScheduler )
+ if ( mbInScheduler )
+ {
+ assert( mbInScheduler && !mpScheduler );
return;
+ }
- Scheduler *sched = mpScheduler;
+ ImplSVData *pSVData = ImplGetSVData();
+ Scheduler *sched;
+ {
+ osl::MutexGuard aImplGuard( pSVData->mpInvokeMutex );
+ if ( !mpScheduler )
+ return;
+ mbInScheduler = true;
+ // SetDeletionFlags will set mpScheduler == nullptr for single-shot tasks
+ sched = mpScheduler;
+ }
- // prepare Scheduler Object for deletion after handling
- mpScheduler->SetDeletionFlags();
+ sched->SetDeletionFlags();
- // invoke it
- mbInScheduler = true;
sched->Invoke();
+ // Invoke() can delete the sched(uler) object, so it might be invalid now;
+ // e.g. see SfxItemDisruptor_Impl::Delete
+
mbInScheduler = false;
+
+ // notify all waiting / nested threads to check their mbInScheduler
+ osl_setCondition( pSVData->maInvokeCondition );
+}
+
+bool Scheduler::IsActive() const
+{
+ ImplSVData *pSVData = ImplGetSVData();
+ return ( !pSVData->mbDeInit && nullptr != mpSchedulerData &&
+ this == mpSchedulerData->mpScheduler );
+}
+
+void Scheduler::SetPriority( SchedulerPriority ePriority )
+{
+ assert( SchedulerPriority::DISPOSED != ePriority );
+ assert( SchedulerPriority::DISPOSED != mePriority );
+ if ( SchedulerPriority::DISPOSED != mePriority &&
+ SchedulerPriority::DISPOSED != ePriority )
+ {
+ mePriority = ePriority;
+ if ( IsActive() )
+ ImplGetSVData()->mbNeedsReschedule = true;
+ }
}
void Scheduler::SetDeletionFlags()
{
assert( mpSchedulerData );
- mpSchedulerData->mpScheduler = nullptr;
- mpSchedulerData = nullptr;
+ ImplSVData *pSVData = ImplGetSVData();
+ if ( !pSVData->mbDeInit )
+ {
+ osl::MutexGuard aImplGuard( pSVData->mpInvokeMutex );
+ mpSchedulerData->mpScheduler = nullptr;
+ }
+ else
+ mpSchedulerData->mpScheduler = nullptr;
}
bool Scheduler::ImplInitScheduler()
@@ -95,6 +136,14 @@ bool Scheduler::ImplInitScheduler()
if ( nullptr == pSVData->mpAppendMutex )
return false;
+ pSVData->mpInvokeMutex = new ::osl::Mutex();
+ if ( nullptr == pSVData->mpInvokeMutex )
+ return false;
+
+ pSVData->maInvokeCondition = osl_createCondition();
+ if ( nullptr == pSVData->maInvokeCondition )
+ return false;
+
return true;
}
@@ -109,13 +158,16 @@ void Scheduler::ImplDeInitScheduler()
DELETEZ( pSVData->mpFreeListMutex );
if ( pSVData->mpAppendMutex ) pSVData->mpAppendMutex->acquire();
DELETEZ( pSVData->mpAppendMutex );
+ if ( pSVData->mpInvokeMutex ) pSVData->mpInvokeMutex->acquire();
+ DELETEZ( pSVData->mpInvokeMutex );
+
+ osl_destroyCondition( pSVData->maInvokeCondition );
+ pSVData->maInvokeCondition = nullptr;
// Free active tasks
ImplSchedulerData *pSchedulerData = pSVData->mpFirstSchedulerData;
while ( pSchedulerData )
{
- if ( pSchedulerData->mpScheduler )
- pSchedulerData->mpScheduler->mpSchedulerData = nullptr;
ImplSchedulerData* pNextSchedulerData = pSchedulerData->mpNext;
delete pSchedulerData;
pSchedulerData = pNextSchedulerData;
@@ -407,35 +459,36 @@ next_entry:
void Scheduler::Start()
{
ImplSVData *const pSVData = ImplGetSVData();
- if (pSVData->mbDeInit)
+ if (pSVData->mbDeInit || SchedulerPriority::DISPOSED == mePriority)
return;
if ( mpSchedulerData && mpSchedulerData->mpNext )
- Scheduler::SetDeletionFlags();
- assert( !mpSchedulerData );
- if ( !mpSchedulerData )
+ SetDeletionFlags();
+ if ( !IsActive() )
{
// Try fetching free Scheduler object from list
- bool bNewObject = false;
+ ImplSchedulerData *pNewData = nullptr;
{
osl::MutexGuard aImplGuard( pSVData->mpFreeListMutex );
if ( pSVData->mpFreeSchedulerData )
{
- mpSchedulerData = pSVData->mpFreeSchedulerData;
- pSVData->mpFreeSchedulerData = mpSchedulerData->mpNext;
+ pNewData = pSVData->mpFreeSchedulerData;
+ pSVData->mpFreeSchedulerData = pNewData->mpNext;
}
- else
- bNewObject = true;
}
- if ( bNewObject )
- mpSchedulerData = new ImplSchedulerData;
- mpSchedulerData->mpScheduler = this;
- mpSchedulerData->mbInScheduler = false;
- mpSchedulerData->mpNext = nullptr;
+ if ( !pNewData )
+ pNewData = new ImplSchedulerData;
+ pNewData->mpScheduler = this;
+ pNewData->mbInScheduler = false;
+ pNewData->mpNext = nullptr;
// insert last due to SFX!
{
osl::MutexGuard aImplGuard( pSVData->mpAppendMutex );
+ if ( IsActive() )
+ SetDeletionFlags();
+
+ mpSchedulerData = pNewData;
if ( pSVData->mpFirstSchedulerData == nullptr )
{
assert( pSVData->mpLastSchedulerData == nullptr );
@@ -456,19 +509,65 @@ void Scheduler::Start()
SAL_INFO( "vcl.schedule", tools::Time::GetSystemTicks()
<< " " << mpSchedulerData << " restarted " << *this );
- assert( mpSchedulerData->mpScheduler == this );
- mpSchedulerData->mnUpdateTime = tools::Time::GetSystemTicks();
- pSVData->mbNeedsReschedule = true;
+ // Have we lost a race with an other caller?
+ if( mpSchedulerData->mpScheduler == this )
+ {
+ mpSchedulerData->mnUpdateTime = tools::Time::GetSystemTicks();
+ pSVData->mbNeedsReschedule = true;
+ }
}
void Scheduler::Stop()
{
- if ( !mpSchedulerData )
+ if ( !IsActive() )
return;
SAL_INFO( "vcl.schedule", tools::Time::GetSystemTicks()
- << " " << mpSchedulerData << " stopped " << *this );
+ << " " << mpSchedulerData << " stopped " << *this );
Scheduler::SetDeletionFlags();
- assert( !mpSchedulerData );
+}
+
+void Scheduler::Dispose( DisposePolicy ePolicy )
+{
+ mePriority = SchedulerPriority::DISPOSED;
+ if ( !mpSchedulerData )
+ return;
+ const ImplSVData *pSVData = ImplGetSVData();
+ if ( pSVData->mbDeInit )
+ {
+ mpSchedulerData = nullptr;
+ return;
+ }
+ const bool bUseLocks = (DisposePolicy::WAIT_INVOKE == ePolicy);
+ if ( bUseLocks )
+ {
+ pSVData->mpInvokeMutex->acquire();
+ if ( mpSchedulerData->mbInScheduler )
+ {
+ // Don't free invoking events
+ while ( true )
+ {
+ pSVData->mpInvokeMutex->release();
+ osl_waitCondition( pSVData->maInvokeCondition, nullptr );
+ pSVData->mpInvokeMutex->acquire();
+ if ( !mpSchedulerData->mbInScheduler )
+ break;
+ else
+ osl_resetCondition( pSVData->maInvokeCondition );
+ }
+ }
+ }
+ if ( pSVData->mbDeInit )
+ return;
+
+ SAL_INFO( "vcl.schedule", tools::Time::GetSystemTicks()
+ << " " << mpSchedulerData << " disposed " << *this );
+ if ( mpSchedulerData )
+ {
+ mpSchedulerData->mpScheduler = nullptr;
+ mpSchedulerData = nullptr;
+ }
+ if ( bUseLocks )
+ pSVData->mpInvokeMutex->release();
}
Scheduler& Scheduler::operator=( const Scheduler& rScheduler )
@@ -502,8 +601,7 @@ Scheduler::Scheduler( const Scheduler& rScheduler ):
Scheduler::~Scheduler()
{
- if ( mpSchedulerData )
- mpSchedulerData->mpScheduler = nullptr;
+ Dispose();
}
const char *ImplSchedulerData::GetDebugName() const
commit 2078fe90e8eb965de06d692ffc5298e57cbf684e
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date: Sun Oct 30 00:03:34 2016 +0200
Add VCL scheduler mp-sc locking: add+rm
AKA multiple producers - single consumer.
While the consumer can process any task in the list, a producer
is just allowed to append a task (like a queue).
This patch implements protective locks for two situations:
* when changing the last element
* when changing the list of freed scheduler objects
Change-Id: Ibd398f660618cf351feb5ca5b0645f30327b48cd
diff --git a/include/vcl/scheduler.hxx b/include/vcl/scheduler.hxx
index cf031e9..806d555 100644
--- a/include/vcl/scheduler.hxx
+++ b/include/vcl/scheduler.hxx
@@ -73,6 +73,7 @@ public:
Scheduler( const sal_Char *pDebugName );
Scheduler( const Scheduler& rScheduler );
virtual ~Scheduler();
+ Scheduler& operator=( const Scheduler& rScheduler );
void SetPriority(SchedulerPriority ePriority) { mePriority = ePriority; }
SchedulerPriority GetPriority() const { return mePriority; }
@@ -88,7 +89,7 @@ public:
inline bool IsActive() const;
- Scheduler& operator=( const Scheduler& rScheduler );
+ static bool ImplInitScheduler();
static void ImplDeInitScheduler();
/// Process one pending Timer with highhest priority
diff --git a/vcl/inc/svdata.hxx b/vcl/inc/svdata.hxx
index 72a091e..8fb13cf 100644
--- a/vcl/inc/svdata.hxx
+++ b/vcl/inc/svdata.hxx
@@ -65,11 +65,6 @@ class Image;
class PopupMenu;
class Application;
class OutputDevice;
-namespace vcl
-{
- class CommandInfoProvider;
- class Window;
-}
class SystemWindow;
class WorkWindow;
class Dialog;
@@ -90,7 +85,19 @@ class SalData;
class OpenGLContext;
class SvFileStream;
-namespace vcl { class DisplayConnectionDispatch; class SettingsConfigItem; class DeleteOnDeinitBase; }
+namespace vcl
+{
+ class DisplayConnectionDispatch;
+ class SettingsConfigItem;
+ class DeleteOnDeinitBase;
+ class CommandInfoProvider;
+ class Window;
+}
+
+namespace osl
+{
+ class Mutex;
+}
class LocaleConfigurationListener : public utl::ConfigurationListener
{
@@ -316,12 +323,15 @@ struct ImplSVData
bool mbDeInit = false; // Is VCL deinitializing
ImplSchedulerData* mpFirstSchedulerData = nullptr; // list of all running tasks
+ ImplSchedulerData* mpLastSchedulerData = nullptr; // last item of the mpFirstSchedulerData list
ImplSchedulerData* mpFreeSchedulerData = nullptr; // list of all deleted tasks for reuse
bool mbNeedsReschedule = false; // was the list of tasks changed?
bool mbTaskRemoved = false; // was a task removed
sal_uInt64 mnTimerPeriod = 0; // current timer period / sleep time
sal_uInt64 mnLastUpdate = 0; // last scheduler time
SalTimer* mpSalTimer = nullptr; // interface to sal event loop/timers
+ osl::Mutex* mpAppendMutex = nullptr;
+ osl::Mutex* mpFreeListMutex = nullptr;
SalI18NImeStatus* mpImeStatus = nullptr; // interface to ime status window
SalSystem* mpSalSystem = nullptr; // SalSystem interface
diff --git a/vcl/source/app/scheduler.cxx b/vcl/source/app/scheduler.cxx
index 745c827..d912236 100644
--- a/vcl/source/app/scheduler.cxx
+++ b/vcl/source/app/scheduler.cxx
@@ -19,11 +19,12 @@
#include <svdata.hxx>
#include <tools/time.hxx>
-#include <vcl/scheduler.hxx>
+#include <vcl/idle.hxx>
#include <saltimer.hxx>
#include <svdata.hxx>
#include <salinst.hxx>
-#include <vcl/idle.hxx>
+#include <osl/mutex.hxx>
+
/**
* clang won't compile this in the Timer.hxx header, even with a class Idle
@@ -82,13 +83,32 @@ void Scheduler::SetDeletionFlags()
mpSchedulerData = nullptr;
}
+bool Scheduler::ImplInitScheduler()
+{
+ ImplSVData *pSVData = ImplGetSVData();
+
+ pSVData->mpFreeListMutex = new ::osl::Mutex();
+ if ( nullptr == pSVData->mpFreeListMutex )
+ return false;
+
+ pSVData->mpAppendMutex = new ::osl::Mutex();
+ if ( nullptr == pSVData->mpAppendMutex )
+ return false;
+
+ return true;
+}
+
void Scheduler::ImplDeInitScheduler()
{
- ImplSVData* pSVData = ImplGetSVData();
- if (pSVData->mpSalTimer)
- {
- pSVData->mpSalTimer->Stop();
- }
+ ImplSVData *pSVData = ImplGetSVData();
+
+ if (pSVData->mpSalTimer) pSVData->mpSalTimer->Stop();
+ DELETEZ( pSVData->mpSalTimer );
+
+ if ( pSVData->mpFreeListMutex ) pSVData->mpFreeListMutex->acquire();
+ DELETEZ( pSVData->mpFreeListMutex );
+ if ( pSVData->mpAppendMutex ) pSVData->mpAppendMutex->acquire();
+ DELETEZ( pSVData->mpAppendMutex );
// Free active tasks
ImplSchedulerData *pSchedulerData = pSVData->mpFirstSchedulerData;
@@ -114,9 +134,6 @@ void Scheduler::ImplDeInitScheduler()
pSVData->mpFirstSchedulerData = nullptr;
pSVData->mpFreeSchedulerData = nullptr;
pSVData->mnTimerPeriod = 0;
-
- delete pSVData->mpSalTimer;
- pSVData->mpSalTimer = nullptr;
}
/**
@@ -206,9 +223,11 @@ bool Scheduler::ProcessTaskScheduling( IdleRunPolicy eIdleRunPolicy )
return false;
pSVData->mbNeedsReschedule = false;
- ImplSchedulerData* pSchedulerData = pSVData->mpFirstSchedulerData;
- ImplSchedulerData* pPrevSchedulerData = nullptr;
+ ImplSchedulerData *pSchedulerData = pSVData->mpFirstSchedulerData;
+ ImplSchedulerData *pPrevSchedulerData = nullptr;
ImplSchedulerData *pPrevMostUrgent = nullptr;
+ ImplSchedulerData *pFirstFreedSchedulerData = nullptr;
+ ImplSchedulerData *pLastFreedSchedulerData = nullptr;
ImplSchedulerData *pMostUrgent = nullptr;
sal_uInt64 nMinPeriod = InfiniteTimeoutMs;
bool bIsNestedCall = false;
@@ -240,13 +259,35 @@ bool Scheduler::ProcessTaskScheduling( IdleRunPolicy eIdleRunPolicy )
// Can this task be removed from scheduling?
if ( !pSchedulerData->mpScheduler )
{
+ // last element can be changed by Start(), so needs protection
+ bool bIsLastElement = nullptr == pSchedulerData->mpNext;
+ if ( bIsLastElement )
+ pSVData->mpAppendMutex->acquire();
ImplSchedulerData* pNextSchedulerData = pSchedulerData->mpNext;
+ // if Start() has appended a task, while we waited for the mutex,
+ // we're not the last anymore, so release the mutex
+ if ( bIsLastElement && pNextSchedulerData )
+ {
+ pSVData->mpAppendMutex->release();
+ bIsLastElement = false;
+ }
+
if ( pPrevSchedulerData )
pPrevSchedulerData->mpNext = pNextSchedulerData;
else
pSVData->mpFirstSchedulerData = pNextSchedulerData;
- pSchedulerData->mpNext = pSVData->mpFreeSchedulerData;
- pSVData->mpFreeSchedulerData = pSchedulerData;
+
+ if ( bIsLastElement )
+ {
+ pSVData->mpLastSchedulerData = pPrevSchedulerData;
+ // critical section passed - release the mutex
+ pSVData->mpAppendMutex->release();
+ }
+
+ if ( !pLastFreedSchedulerData )
+ pLastFreedSchedulerData = pSchedulerData;
+ pSchedulerData->mpNext = pFirstFreedSchedulerData;
+ pFirstFreedSchedulerData = pSchedulerData;
pSchedulerData = pNextSchedulerData;
pSVData->mbTaskRemoved = true;
continue;
@@ -275,6 +316,14 @@ next_entry:
assert( !pSchedulerData );
+ // Prepend freed scheduler data objects
+ if ( pFirstFreedSchedulerData )
+ {
+ osl::MutexGuard aImplGuard( pSVData->mpFreeListMutex );
+ pLastFreedSchedulerData->mpNext = pSVData->mpFreeSchedulerData;
+ pSVData->mpFreeSchedulerData = pFirstFreedSchedulerData;
+ }
+
// We just have to handle removed tasks for nested calls
if ( !bIsNestedCall )
pSVData->mbTaskRemoved = false;
@@ -299,15 +348,16 @@ next_entry:
}
// do some simple round-robin scheduling
- // nothing to do, if we're already the last element
if ( pMostUrgent->mpScheduler )
{
pMostUrgent->mnUpdateTime = nTime;
UpdateMinPeriod( pMostUrgent, nTime, nMinPeriod );
+ // nothing to do, if we're already the last element
if ( pMostUrgent->mpNext )
{
- // see ^^^^^
+ // if a nested call has removed items, pPrevMostUrgent is
+ // wrong, so we have to find the correct pPrevMostUrgent
if ( pSVData->mbTaskRemoved )
{
pPrevMostUrgent = pSVData->mpFirstSchedulerData;
@@ -324,14 +374,11 @@ next_entry:
pPrevMostUrgent->mpNext = pMostUrgent->mpNext;
else
pSVData->mpFirstSchedulerData = pMostUrgent->mpNext;
- // Invoke() might have changed the task list - find new end
- while ( pPrevSchedulerData->mpNext )
- {
- pPrevSchedulerData = pPrevSchedulerData->mpNext;
- UpdateMinPeriod( pPrevSchedulerData, nTime, nMinPeriod );
- }
- pPrevSchedulerData->mpNext = pMostUrgent;
+
pMostUrgent->mpNext = nullptr;
+ osl::MutexGuard aImplGuard( pSVData->mpAppendMutex );
+ pSVData->mpLastSchedulerData->mpNext = pMostUrgent;
+ pSVData->mpLastSchedulerData = pMostUrgent;
}
}
}
@@ -363,34 +410,45 @@ void Scheduler::Start()
if (pSVData->mbDeInit)
return;
- DBG_TESTSOLARMUTEX();
-
if ( mpSchedulerData && mpSchedulerData->mpNext )
Scheduler::SetDeletionFlags();
+ assert( !mpSchedulerData );
if ( !mpSchedulerData )
{
- // insert Scheduler
- if ( pSVData->mpFreeSchedulerData )
+ // Try fetching free Scheduler object from list
+ bool bNewObject = false;
{
- mpSchedulerData = pSVData->mpFreeSchedulerData;
- pSVData->mpFreeSchedulerData = mpSchedulerData->mpNext;
+ osl::MutexGuard aImplGuard( pSVData->mpFreeListMutex );
+ if ( pSVData->mpFreeSchedulerData )
+ {
+ mpSchedulerData = pSVData->mpFreeSchedulerData;
+ pSVData->mpFreeSchedulerData = mpSchedulerData->mpNext;
+ }
+ else
+ bNewObject = true;
}
- else
+ if ( bNewObject )
mpSchedulerData = new ImplSchedulerData;
mpSchedulerData->mpScheduler = this;
mpSchedulerData->mbInScheduler = false;
- mpSchedulerData->mpNext = nullptr;
+ mpSchedulerData->mpNext = nullptr;
// insert last due to SFX!
- ImplSchedulerData* pData = pSVData->mpFirstSchedulerData;
- if ( pData )
{
- while ( pData->mpNext )
- pData = pData->mpNext;
- pData->mpNext = mpSchedulerData;
+ osl::MutexGuard aImplGuard( pSVData->mpAppendMutex );
+ if ( pSVData->mpFirstSchedulerData == nullptr )
+ {
+ assert( pSVData->mpLastSchedulerData == nullptr );
+ pSVData->mpFirstSchedulerData = mpSchedulerData;
+ pSVData->mpLastSchedulerData = mpSchedulerData;
+ }
+ else
+ {
+ assert( pSVData->mpLastSchedulerData != nullptr );
+ pSVData->mpLastSchedulerData->mpNext = mpSchedulerData;
+ pSVData->mpLastSchedulerData = mpSchedulerData;
+ }
}
- else
- pSVData->mpFirstSchedulerData = mpSchedulerData;
SAL_INFO( "vcl.schedule", tools::Time::GetSystemTicks()
<< " " << mpSchedulerData << " added " << *this );
}
diff --git a/vcl/source/app/svmain.cxx b/vcl/source/app/svmain.cxx
index 2012764b..c963bf5 100644
--- a/vcl/source/app/svmain.cxx
+++ b/vcl/source/app/svmain.cxx
@@ -291,6 +291,9 @@ bool InitVCL()
if ( !pSVData->mpDefInst )
return false;
+ if( !Scheduler::ImplInitScheduler() )
+ return false;
+
// Desktop Environment context (to be able to get value of "system.desktop-environment" as soon as possible)
css::uno::setCurrentContext(
new DesktopEnvironmentContext( css::uno::getCurrentContext() ) );
commit 8562ff19e3bc9441ee8a8e6de896a9fc0e4edb43
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date: Sun Oct 30 10:45:02 2016 +0100
Fix rate-limiting of the GUI layouting
Before starting the layout timer, check its activity, so we don't
reset the timer with every start.
Change-Id: I5355a117866e863a652f4d70862c2786fbc4b935
diff --git a/framework/source/layoutmanager/layoutmanager.cxx b/framework/source/layoutmanager/layoutmanager.cxx
index c41edf8..e93262b 100644
--- a/framework/source/layoutmanager/layoutmanager.cxx
+++ b/framework/source/layoutmanager/layoutmanager.cxx
@@ -144,6 +144,7 @@ LayoutManager::LayoutManager( const Reference< XComponentContext >& xContext ) :
}
m_aAsyncLayoutTimer.SetTimeout( 50 );
+ m_aAsyncLayoutTimer.SetPriority( SchedulerPriority::HIGH_IDLE );
m_aAsyncLayoutTimer.SetTimeoutHdl( LINK( this, LayoutManager, AsyncLayoutHdl ) );
m_aAsyncLayoutTimer.SetDebugName( "framework::LayoutManager m_aAsyncLayoutTimer" );
@@ -233,13 +234,17 @@ void LayoutManager::implts_lock()
{
SolarMutexGuard g;
++m_nLockCount;
+ m_aAsyncLayoutTimer.Stop();
}
bool LayoutManager::implts_unlock()
{
SolarMutexGuard g;
m_nLockCount = std::max( m_nLockCount-1, static_cast<sal_Int32>(0) );
- return ( m_nLockCount == 0 );
+ bool bCanLayout = ( m_nLockCount == 0 );
+ if ( bCanLayout && m_bMustDoLayout && !m_aAsyncLayoutTimer.IsActive() )
+ m_aAsyncLayoutTimer.Start();
+ return bCanLayout;
}
void LayoutManager::implts_reset( bool bAttached )
@@ -2277,9 +2282,9 @@ throw (RuntimeException, std::exception)
// conform to documentation: unlock with lock count == 0 means force a layout
SolarMutexClearableGuard aWriteLock;
- if ( bDoLayout )
- m_aAsyncLayoutTimer.Stop();
- aWriteLock.clear();
+ if ( bDoLayout )
+ m_aAsyncLayoutTimer.Stop();
+ aWriteLock.clear();
Any a( nLockCount );
implts_notifyListeners( frame::LayoutManagerEvents::UNLOCK, a );
@@ -2681,11 +2686,7 @@ throw( uno::RuntimeException, std::exception )
// application modules need this. So we have to check if this is the first
// call after the async layout time expired.
m_bMustDoLayout = true;
- if ( !m_aAsyncLayoutTimer.IsActive() )
- {
- m_aAsyncLayoutTimer.Invoke();
- }
- if ( m_nLockCount == 0 )
+ if ( m_nLockCount == 0 && !m_aAsyncLayoutTimer.IsActive() )
m_aAsyncLayoutTimer.Start();
}
else if ( m_xFrame.is() && aEvent.Source == m_xFrame->getContainerWindow() )
@@ -2756,7 +2757,6 @@ void SAL_CALL LayoutManager::windowHidden( const lang::EventObject& aEvent ) thr
IMPL_LINK_NOARG(LayoutManager, AsyncLayoutHdl, Timer *, void)
{
SolarMutexClearableGuard aReadLock;
- m_aAsyncLayoutTimer.Stop();
if( !m_xContainerWindow.is() )
return;
commit 283988047fb844bc784e5b4f1139a913b66dd50e
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date: Sun Oct 30 02:02:10 2016 +0100
Just wait for the Yield mutex in the timer callback
Probably this instantly deadlocks, but it's worth a shot ;-)
Change-Id: Ib46eb6dbf57f29c85ffdbd6492922020f7785d30
diff --git a/vcl/win/app/saltimer.cxx b/vcl/win/app/saltimer.cxx
index 2288c52..8cb0072 100644
--- a/vcl/win/app/saltimer.cxx
+++ b/vcl/win/app/saltimer.cxx
@@ -163,15 +163,9 @@ void EmitTimerCallback()
if ( nullptr == pSalData->mnTimerId )
return;
- // Try to acquire the mutex. If we don't get the mutex then we
- // try this a short time later again.
- if (ImplSalYieldMutexTryToAcquire())
- {
- pSVData->mpSalTimer->CallCallback();
- ImplSalYieldMutexRelease();
- }
- else
- ImplSalStartTimer( 10 );
+ ImplSalYieldMutexAcquireWithWait();
+ pSVData->mpSalTimer->CallCallback();
+ ImplSalYieldMutexRelease();
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit d33ed55b5e329f75f2415f70a20e1ef49dcd9de4
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date: Sun Oct 30 00:14:18 2016 +0000
Simplify Windows system timer / LO event handling
The system timer is supposed to have the following constraints:
1. There is just one system timer, which drives LO event loop
2. The timer has to run in the main window thread
3. Messages are processed in order, so there is no real need for
calling SendMessageW instead of PostMessageW
4. LO event loop is supposed to be processed in the main window
thread with the Solar mutex acquired
5. The system timer is a single-shot timer
In the end this removes duplicated code and simplifies it.
Drop the 16bit MAX duration limit, as CreateTimerQueueTimer uses
a DWORD for the DueTime parameter, which is always UINT32.
CreateTimerQueueTimer already sets the period to 0, which makes it
a one-shot timer, but there is also the WT_EXECUTEONLYONCE, which
enforces the Period parameter to be 0.
Change-Id: I549142394334bdc098f053b42f222b23cf4fcecd
diff --git a/vcl/inc/win/saldata.hxx b/vcl/inc/win/saldata.hxx
index fa65c56..7b94032 100644
--- a/vcl/inc/win/saldata.hxx
+++ b/vcl/inc/win/saldata.hxx
@@ -80,10 +80,6 @@ public:
long* mpDitherDiff; // Dither mapping table
BYTE* mpDitherLow; // Dither mapping table
BYTE* mpDitherHigh; // Dither mapping table
- sal_uLong mnTimerMS; // Current Time (in MS) of the Timer
- sal_uLong mnTimerOrgMS; // Current Original Time (in MS)
- DWORD mnNextTimerTime;
- DWORD mnLastEventTime;
HANDLE mnTimerId; ///< Windows timer id
HHOOK mhSalObjMsgHook; // hook to get interesting msg for SalObject
HWND mhWantLeaveMsg; // window handle, that want a MOUSELEAVE message
@@ -206,7 +202,7 @@ int ImplSalWICompareAscii( const wchar_t* pStr1, const char* pStr2 );
// wParam == bWait; lParam == 0
#define SAL_MSG_THREADYIELD (WM_USER+111)
// wParam == 0; lParam == nMS
-#define SAL_MSG_STARTTIMER (WM_USER+113)
+#define SAL_MSG_DEFERREDSTARTTIMER (WM_USER+113)
// wParam == nFrameStyle; lParam == pParent; lResult == pFrame
#define SAL_MSG_CREATEFRAME (WM_USER+114)
// wParam == 0; lParam == 0
@@ -258,8 +254,6 @@ int ImplSalWICompareAscii( const wchar_t* pStr1, const char* pStr2 );
#define SAL_MSG_SETINPUTCONTEXT (WM_USER+144)
// wParam == nFlags; lParam == 0
#define SAL_MSG_ENDEXTTEXTINPUT (WM_USER+145)
-// DEFERREDTIMER-Message; wparam = 0, lParam == time
-#define SAL_MSG_DEFERREDTIMER (WM_USER+146)
// SysChild-ToTop; wParam = 0; lParam = 0
#define SALOBJ_MSG_TOTOP (WM_USER+160)
@@ -269,7 +263,7 @@ int ImplSalWICompareAscii( const wchar_t* pStr1, const char* pStr2 );
// Call the Timer's callback from the main thread
#define SAL_MSG_TIMER_CALLBACK (WM_USER+162)
// Stop the timer from the main thread; wParam = 0, lParam = 0
-#define SAL_MSG_STOPTIMER (WM_USER+163)
+#define SAL_MSG_DEFERREDSTOPTIMER (WM_USER+163)
inline void SetWindowPtr( HWND hWnd, WinSalFrame* pThis )
{
diff --git a/vcl/inc/win/salinst.h b/vcl/inc/win/salinst.h
index d4ca2a6..112aff3 100644
--- a/vcl/inc/win/salinst.h
+++ b/vcl/inc/win/salinst.h
@@ -82,7 +82,7 @@ public:
SalFrame* ImplSalCreateFrame( WinSalInstance* pInst, HWND hWndParent, SalFrameStyleFlags nSalFrameStyle );
SalObject* ImplSalCreateObject( WinSalInstance* pInst, WinSalFrame* pParent );
HWND ImplSalReCreateHWND( HWND hWndParent, HWND oldhWnd, bool bAsChild );
-void ImplSalStartTimer( sal_uIntPtr nMS, bool bMutex = false );
+void ImplSalStartTimer( sal_uIntPtr nMS );
void ImplSalStopTimer();
#endif // INCLUDED_VCL_INC_WIN_SALINST_H
diff --git a/vcl/win/app/salinst.cxx b/vcl/win/app/salinst.cxx
index 35cd5b6..44c7cc6 100644
--- a/vcl/win/app/salinst.cxx
+++ b/vcl/win/app/salinst.cxx
@@ -331,10 +331,6 @@ SalData::SalData()
mpDitherDiff = nullptr; // Dither mapping table
mpDitherLow = nullptr; // Dither mapping table
mpDitherHigh = nullptr; // Dither mapping table
- mnTimerMS = 0; // Current Time (in MS) of the Timer
- mnTimerOrgMS = 0; // Current Original Time (in MS)
- mnNextTimerTime = 0;
- mnLastEventTime = 0;
mnTimerId = nullptr; // windows timer id
mhSalObjMsgHook = nullptr; // hook to get interesting msg for SalObject
mhWantLeaveMsg = nullptr; // window handle, that want a MOUSELEAVE message
@@ -673,11 +669,18 @@ LRESULT CALLBACK SalComWndProc( HWND, UINT nMsg, WPARAM wParam, LPARAM lParam, i
ImplSalYield( (bool)wParam, (bool)lParam );
rDef = FALSE;
break;
- case SAL_MSG_STARTTIMER:
- ImplSalStartTimer( (sal_uLong) lParam );
+ case SAL_MSG_DEFERREDSTARTTIMER:
+ {
+ sal_uLong nTime = GetTickCount();
+ if ( nTime < (sal_uLong) lParam )
+ nTime = (sal_uLong) lParam - nTime;
+ else
+ nTime = 0;
+ ImplSalStartTimer( nTime );
rDef = FALSE;
break;
- case SAL_MSG_STOPTIMER:
+ }
+ case SAL_MSG_DEFERREDSTOPTIMER:
ImplSalStopTimer();
rDef = FALSE;
break;
@@ -725,23 +728,12 @@ LRESULT CALLBACK SalComWndProc( HWND, UINT nMsg, WPARAM wParam, LPARAM lParam, i
ReleaseDC( reinterpret_cast<HWND>(wParam), reinterpret_cast<HDC>(lParam) );
rDef = FALSE;
break;
- case SAL_MSG_DEFERREDTIMER:
- EmitTimerCallback();
- break;
case SAL_MSG_TIMER_CALLBACK:
- EmitTimerCallback();
MSG aMsg;
- while (PeekMessageW(&aMsg, nullptr, SAL_MSG_TIMER_CALLBACK, SAL_MSG_TIMER_CALLBACK, PM_REMOVE))
- {
- // nothing; just remove all the SAL_MSG_TIMER_CALLBACKs that
- // accumulated in the queue during the EmitTimerCallback(),
- // otherwise it happens with short timeouts and long callbacks
- // that no other events will ever be processed, as the queue
- // is full of SAL_MSG_TIMER_CALLBACKs.
- // It is impossible to limit the amount of them being emitted
- // in the first place, as they are emitted asynchronously, but
- // here we are already fully synchronized.
- }
+ while ( PeekMessageW(&aMsg, nullptr, SAL_MSG_TIMER_CALLBACK,
+ SAL_MSG_TIMER_CALLBACK, PM_REMOVE) )
+ assert( "Multiple timer messages in queue" );
+ EmitTimerCallback();
break;
}
@@ -859,24 +851,6 @@ bool WinSalInstance::AnyInput( VclInputFlags nType )
return false;
}
-void SalTimer::Start( sal_uLong nMS )
-{
- // to switch to Main-Thread
- SalData* pSalData = GetSalData();
- if ( pSalData->mpFirstInstance )
- {
- if ( pSalData->mnAppThreadId != GetCurrentThreadId() )
- {
- BOOL const ret = PostMessageW(pSalData->mpFirstInstance->mhComWnd, SAL_MSG_STARTTIMER, 0, (LPARAM)nMS);
- SAL_WARN_IF(0 == ret, "vcl", "ERROR: PostMessage() failed!");
- }
- else
- SendMessageW( pSalData->mpFirstInstance->mhComWnd, SAL_MSG_STARTTIMER, 0, (LPARAM)nMS );
- }
- else
- ImplSalStartTimer( nMS );
-}
-
SalFrame* WinSalInstance::CreateChildFrame( SystemParentData* pSystemParentData, SalFrameStyleFlags nSalFrameStyle )
{
// to switch to Main-Thread
diff --git a/vcl/win/app/saltimer.cxx b/vcl/win/app/saltimer.cxx
index 6887dce..2288c52 100644
--- a/vcl/win/app/saltimer.cxx
+++ b/vcl/win/app/saltimer.cxx
@@ -26,9 +26,6 @@
#include <sehandler.hxx>
#endif
-// maximum period
-#define MAX_SYSPERIOD 65533
-
void CALLBACK SalTimerProc(PVOID pParameter, BOOLEAN bTimerOrWaitFired);
// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms687003%28v=vs.85%29.aspx
@@ -41,64 +38,55 @@ void CALLBACK SalTimerProc(PVOID pParameter, BOOLEAN bTimerOrWaitFired);
void ImplSalStopTimer()
{
SalData *const pSalData = GetSalData();
+ assert( pSalData->mnAppThreadId == GetCurrentThreadId() );
+
HANDLE hTimer = pSalData->mnTimerId;
if (hTimer)
{
- pSalData->mnTimerId = nullptr; // reset so it doesn't restart
+ pSalData->mnTimerId = nullptr;
DeleteTimerQueueTimer(nullptr, hTimer, INVALID_HANDLE_VALUE);
- pSalData->mnNextTimerTime = 0;
- }
- MSG aMsg;
- // this needs to run on the main thread
- while (PeekMessageW(&aMsg, nullptr, SAL_MSG_TIMER_CALLBACK, SAL_MSG_TIMER_CALLBACK, PM_REMOVE))
- {
- // just remove all the SAL_MSG_TIMER_CALLBACKs
- // when the application end, this SAL_MSG_TIMER_CALLBACK start the timer again
- // and then crashed in "SalTimerProc" when the object "SalData" was deleted
+
+ // remove all pending SAL_MSG_TIMER_CALLBACK messages
+ MSG aMsg;
+ int nMsgCount = 0;
+ while ( PeekMessageW(&aMsg, nullptr, SAL_MSG_TIMER_CALLBACK,
+ SAL_MSG_TIMER_CALLBACK, PM_REMOVE) )
+ nMsgCount++;
+ assert( nMsgCount <= 1 );
}
}
-void ImplSalStartTimer( sal_uLong nMS, bool bMutex )
+void ImplSalStartTimer( sal_uLong nMS )
{
SalData* pSalData = GetSalData();
+ assert( pSalData->mnAppThreadId == GetCurrentThreadId() );
- // Remember the time of the timer
- pSalData->mnTimerMS = nMS;
- if (!bMutex)
- pSalData->mnTimerOrgMS = nMS;
-
- // duration has to fit into Window's sal_uInt16
- if (nMS > MAX_SYSPERIOD)
- nMS = MAX_SYSPERIOD;
+ // DueTime parameter is a DWORD, which is always an unsigned 32bit
+ if (nMS > SAL_MAX_UINT32)
+ nMS = SAL_MAX_UINT32;
// cannot change a one-shot timer, so delete it and create new one
- if (pSalData->mnTimerId)
- {
- DeleteTimerQueueTimer(nullptr, pSalData->mnTimerId, INVALID_HANDLE_VALUE);
- pSalData->mnTimerId = nullptr;
- }
- CreateTimerQueueTimer(&pSalData->mnTimerId, nullptr, SalTimerProc, nullptr, nMS, 0, WT_EXECUTEINTIMERTHREAD);
-
- pSalData->mnNextTimerTime = pSalData->mnLastEventTime + nMS;
+ ImplSalStopTimer();
+ // probably WT_EXECUTEONLYONCE is not needed, but it enforces Period to be
+ // 0 and should not hurt; also see
+ // https://www.microsoft.com/msj/0499/pooling/pooling.aspx
+ CreateTimerQueueTimer(&pSalData->mnTimerId, nullptr, SalTimerProc, nullptr,
+ nMS, 0, WT_EXECUTEINTIMERTHREAD | WT_EXECUTEONLYONCE);
}
WinSalTimer::~WinSalTimer()
{
+ Stop();
}
void WinSalTimer::Start( sal_uLong nMS )
{
- // switch to main thread
SalData* pSalData = GetSalData();
- if ( pSalData->mpFirstInstance )
+ if ( pSalData->mpFirstInstance && pSalData->mnAppThreadId != GetCurrentThreadId() )
{
- if ( pSalData->mnAppThreadId != GetCurrentThreadId() )
- {
- BOOL const ret = PostMessageW(pSalData->mpFirstInstance->mhComWnd, SAL_MSG_STARTTIMER, 0, (LPARAM)nMS);
- SAL_WARN_IF(0 == ret, "vcl", "ERROR: PostMessage() failed!");
- }
- else
- SendMessageW( pSalData->mpFirstInstance->mhComWnd, SAL_MSG_STARTTIMER, 0, (LPARAM)nMS );
+ BOOL const ret = PostMessageW(pSalData->mpFirstInstance->mhComWnd,
+ SAL_MSG_DEFERREDSTARTTIMER, 0, (LPARAM)GetTickCount() + nMS);
+ SAL_WARN_IF(0 == ret, "vcl", "ERROR: PostMessage() failed!");
}
else
ImplSalStartTimer( nMS );
@@ -107,9 +95,14 @@ void WinSalTimer::Start( sal_uLong nMS )
void WinSalTimer::Stop()
{
SalData* pSalData = GetSalData();
-
- assert(pSalData->mpFirstInstance);
- SendMessageW(pSalData->mpFirstInstance->mhComWnd, SAL_MSG_STOPTIMER, 0, 0);
+ if ( pSalData->mpFirstInstance && pSalData->mnAppThreadId != GetCurrentThreadId() )
+ {
+ BOOL const ret = PostMessageW(pSalData->mpFirstInstance->mhComWnd,
+ SAL_MSG_DEFERREDSTOPTIMER, 0, 0);
+ SAL_WARN_IF(0 == ret, "vcl", "ERROR: PostMessage() failed!");
+ }
+ else
+ ImplSalStopTimer();
}
/** This gets invoked from a Timer Queue thread.
@@ -135,7 +128,8 @@ void CALLBACK SalTimerProc(PVOID, BOOLEAN)
// always post message when the timer fires, we will remove the ones
// that happened during execution of the callback later directly from
// the message queue
- BOOL const ret = PostMessageW(pSalData->mpFirstInstance->mhComWnd, SAL_MSG_TIMER_CALLBACK, 0, 0);
+ BOOL const ret = PostMessageW(pSalData->mpFirstInstance->mhComWnd,
+ SAL_MSG_TIMER_CALLBACK, 0, 0);
#if OSL_DEBUG_LEVEL > 0
if (0 == ret) // SEH prevents using SAL_WARN here?
fputs("ERROR: PostMessage() failed!", stderr);
@@ -159,30 +153,25 @@ call then happens when the main thread gets SAL_MSG_TIMER_CALLBACK.
*/
void EmitTimerCallback()
{
- SalData* pSalData = GetSalData();
- ImplSVData* pSVData = ImplGetSVData();
-
// Test for MouseLeave
SalTestMouseLeave();
+ ImplSVData *pSVData = ImplGetSVData();
+ if ( ! pSVData->mpSalTimer )
+ return;
+ SalData *pSalData = GetSalData();
+ if ( nullptr == pSalData->mnTimerId )
+ return;
+
// Try to acquire the mutex. If we don't get the mutex then we
// try this a short time later again.
- if (pSVData->mpSalTimer && ImplSalYieldMutexTryToAcquire())
+ if (ImplSalYieldMutexTryToAcquire())
{
pSVData->mpSalTimer->CallCallback();
ImplSalYieldMutexRelease();
-
- // Run the timer again if it was started before, and also
- // Run the timer in the correct time, if we started this
- // with a small timeout, because we didn't get the mutex
- // - but not if mnTimerId is 0, which is set by ImplSalStopTimer()
- if (pSalData->mnTimerId)
- ImplSalStartTimer(pSalData->mnTimerOrgMS);
}
else
- {
- ImplSalStartTimer(10, true);
- }
+ ImplSalStartTimer( 10 );
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/win/window/salframe.cxx b/vcl/win/window/salframe.cxx
index 3a79e18..2ca26f1 100644
--- a/vcl/win/window/salframe.cxx
+++ b/vcl/win/window/salframe.cxx
@@ -5492,8 +5492,6 @@ LRESULT CALLBACK SalFrameWndProc( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lP
return 0;
}
- bool bCheckTimers = false;
-
switch( nMsg )
{
case WM_MOUSEMOVE:
@@ -5630,11 +5628,11 @@ LRESULT CALLBACK SalFrameWndProc( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lP
rDef = FALSE;
break;
case WM_PAINT:
- bCheckTimers = ImplHandlePaintMsg( hWnd );
+ ImplHandlePaintMsg( hWnd );
rDef = FALSE;
break;
case SAL_MSG_DEFERREDPAINT:
- bCheckTimers = ImplHandleDeferredPaintMsg( hWnd, reinterpret_cast<RECT*>(wParam) );
+ ImplHandleDeferredPaintMsg( hWnd, reinterpret_cast<RECT*>(wParam) );
rDef = FALSE;
break;
@@ -5855,24 +5853,6 @@ LRESULT CALLBACK SalFrameWndProc( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lP
break;
}
- if( bCheckTimers )
- {
- SalData* pSalData = GetSalData();
- if( pSalData->mnNextTimerTime )
- {
- DWORD nCurTime = GetTickCount();
- if( pSalData->mnNextTimerTime < nCurTime )
- {
- MSG aMsg;
- if( ! PeekMessageW( &aMsg, nullptr, WM_PAINT, WM_PAINT, PM_NOREMOVE | PM_NOYIELD ) )
- {
- BOOL const ret = PostMessageW(pSalData->mpFirstInstance->mhComWnd, SAL_MSG_DEFERREDTIMER, 0, nCurTime);
- SAL_WARN_IF(0 == ret, "vcl", "ERROR: PostMessage() failed!");
- }
- }
- }
- }
-
return nRet;
}
commit 75a3e023fc4ead19696a0db7f7c9ca1a380d67ad
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date: Sat Oct 29 12:00:08 2016 +0200
Unify deferred message handling
Moves the common code into ProcessOrDeferMessage.
All callers (try to) aquire the mutex before getting the
WinSalFrame pointer, except for ImplHandleDeferredPaintMsg.
This was probably an oversight, so this reverses the order in this
function, so the GetWindowPtr is now always protected by the Solar
mutex.
Change-Id: Icb8f34f7e8716f0faa90a95903b1681f7489aed2
diff --git a/vcl/win/window/salframe.cxx b/vcl/win/window/salframe.cxx
index 38894ed..3a79e18 100644
--- a/vcl/win/window/salframe.cxx
+++ b/vcl/win/window/salframe.cxx
@@ -3701,47 +3701,82 @@ long ImplHandleSalObjSysCharMsg( HWND hWnd, WPARAM wParam, LPARAM lParam )
return nRet;
}
-enum class DeferredPaint
+enum class DeferPolicy
{
- IsDeferred,
- IsInitial
+ Blocked,
+ Allowed
};
-static BOOL ImplHandleDeferredPaintMsg( HWND hWnd, RECT* pRect,
- DeferredPaint eProcessed = DeferredPaint::IsDeferred )
+// Remember to release the solar mutex on success!
+static inline WinSalFrame* ProcessOrDeferMessage( HWND hWnd, INT nMsg, WPARAM pWParam = 0,
+ DeferPolicy eCanDefer = DeferPolicy::Allowed )
{
- bool bGotMutex = false;
+ bool bFailedCondition = FALSE, bGotMutex = FALSE;
+ WinSalFrame* pFrame = nullptr;
- WinSalFrame* pFrame = GetWindowPtr( hWnd );
- if ( pFrame )
+ if ( DeferPolicy::Blocked == eCanDefer )
+ assert( (DeferPolicy::Blocked == eCanDefer) && (nMsg == 0) && (pWParam == 0) );
+ else
+ assert( (DeferPolicy::Allowed == eCanDefer) && (nMsg != 0) );
+
+ if ( DeferPolicy::Blocked == eCanDefer )
{
- if ( ImplSalYieldMutexTryToAcquire() )
- bGotMutex = true;
+ ImplSalYieldMutexAcquireWithWait();
+ bGotMutex = TRUE;
+ }
+ else if ( !(bGotMutex = ImplSalYieldMutexTryToAcquire()) )
+ bFailedCondition = TRUE;
+
+ if ( !bFailedCondition )
+ {
+ pFrame = GetWindowPtr( hWnd );
+ bFailedCondition = pFrame == nullptr;
+ }
+ if ( bFailedCondition )
+ {
if ( bGotMutex )
- {
- SalPaintEvent aPEvt( pRect->left, pRect->top, pRect->right-pRect->left, pRect->bottom-pRect->top );
- pFrame->CallCallback( SalEvent::Paint, &aPEvt );
ImplSalYieldMutexRelease();
- if ( DeferredPaint::IsDeferred == eProcessed )
- delete pRect;
- }
- else
+ if ( DeferPolicy::Allowed == eCanDefer )
{
- RECT* pMsgRect;
- if ( DeferredPaint::IsInitial == eProcessed )
- {
- pMsgRect = new RECT;
- CopyRect( pMsgRect, pRect );
- }
- else
- pMsgRect = pRect;
- BOOL const ret = PostMessageW(hWnd, SAL_MSG_DEFERREDPAINT, reinterpret_cast<WPARAM>(pMsgRect), 0);
+ BOOL const ret = PostMessageW(hWnd, nMsg, pWParam, 0);
SAL_WARN_IF(0 == ret, "vcl", "ERROR: PostMessage() failed!");
}
}
- return bGotMutex;
+ return pFrame;
+}
+
+enum class DeferredState
+{
+ IsDeferred,
+ IsInitial
+};
+
+static bool ImplHandleDeferredPaintMsg( HWND hWnd, RECT* pRect,
+ DeferredState eProcessed = DeferredState::IsDeferred )
+{
+ RECT* pMsgRect;
+ if ( DeferredState::IsInitial == eProcessed )
+ {
+ pMsgRect = new RECT;
+ CopyRect( pMsgRect, pRect );
+ }
+ else
+ pMsgRect = pRect;
+
+ WinSalFrame* pFrame = ProcessOrDeferMessage( hWnd, SAL_MSG_DEFERREDPAINT,
+ reinterpret_cast<WPARAM>(pMsgRect) );
+ if ( pFrame )
+ {
+ SalPaintEvent aPEvt( pRect->left, pRect->top, pRect->right-pRect->left, pRect->bottom-pRect->top );
+ pFrame->CallCallback( SalEvent::Paint, &aPEvt );
+ ImplSalYieldMutexRelease();
+ if ( DeferredState::IsDeferred == eProcessed )
+ delete pRect;
+ }
+
+ return (pFrame != nullptr);
}
static bool ImplHandlePaintMsg( HWND hWnd )
@@ -3783,11 +3818,11 @@ static bool ImplHandlePaintMsg( HWND hWnd )
if ( bHasPaintRegion )
{
bPaintSuccessful = ImplHandleDeferredPaintMsg(
- hWnd, &aUpdateRect, DeferredPaint::IsInitial );
+ hWnd, &aUpdateRect, DeferredState::IsInitial );
EndPaint( hWnd, &aPs );
}
else // if there is nothing to paint, the paint is successful
- bPaintSuccessful = true
+ bPaintSuccessful = true;
}
return bPaintSuccessful;
@@ -3900,9 +3935,7 @@ static void ImplCallClosePopupsHdl( HWND hWnd )
static void ImplHandleMoveMsg( HWND hWnd )
{
- if ( ImplSalYieldMutexTryToAcquire() )
- {
- WinSalFrame* pFrame = GetWindowPtr( hWnd );
+ WinSalFrame* pFrame = ProcessOrDeferMessage( hWnd, SAL_MSG_DEFERREDMOVE );
if ( pFrame )
{
UpdateFrameGeometry( hWnd, pFrame );
@@ -3927,39 +3960,24 @@ static void ImplHandleMoveMsg( HWND hWnd )
//#93851 if we call this handler, VCL floating windows are not updated correctly
ImplCallMoveHdl( hWnd );
+ ImplSalYieldMutexRelease();
}
-
- ImplSalYieldMutexRelease();
- }
- else
- {
- BOOL const ret = PostMessageW( hWnd, SAL_MSG_DEFERREDMOVE, 0, 0 );
- SAL_WARN_IF(0 == ret, "vcl", "ERROR: PostMessage() failed!");
- }
}
static void ImplCallSizeHdl( HWND hWnd )
{
// as Windows can send these messages also, we have to use
// the Solar semaphore
- if ( ImplSalYieldMutexTryToAcquire() )
- {
- WinSalFrame* pFrame = GetWindowPtr( hWnd );
+ WinSalFrame* pFrame = ProcessOrDeferMessage( hWnd, SAL_MSG_DEFERREDCALLSIZE );
if ( pFrame )
{
pFrame->CallCallback( SalEvent::Resize, nullptr );
// to avoid double Paints by VCL and SAL
if ( IsWindowVisible( hWnd ) && !pFrame->mbInShow )
UpdateWindow( hWnd );
- }
- ImplSalYieldMutexRelease();
- }
- else
- {
- BOOL const ret = PostMessageW( hWnd, SAL_MSG_DEFERREDCALLSIZE, 0, 0 );
- SAL_WARN_IF(0 == ret, "vcl", "ERROR: PostMessage() failed!");
- }
+ ImplSalYieldMutexRelease();
+ }
}
static void ImplHandleSizeMsg( HWND hWnd, WPARAM wParam, LPARAM lParam )
@@ -3983,12 +4001,13 @@ static void ImplHandleSizeMsg( HWND hWnd, WPARAM wParam, LPARAM lParam )
static void ImplHandleFocusMsg( HWND hWnd )
{
- if ( ImplSalYieldMutexTryToAcquire() )
+ WinSalFrame* pFrame = ProcessOrDeferMessage( hWnd, SAL_MSG_DEFERREDSETFOCUS );
+ if ( pFrame )
{
- WinSalFrame* pFrame = GetWindowPtr( hWnd );
- if ( pFrame && !WinSalFrame::mbInReparent )
+ if ( !WinSalFrame::mbInReparent )
{
- if ( ::GetFocus() == hWnd )
+ bool bGotFocus = ::GetFocus() == hWnd;
+ if ( bGotFocus )
{
if ( IsWindowVisible( hWnd ) && !pFrame->mbInShow )
UpdateWindow( hWnd );
@@ -4002,53 +4021,32 @@ static void ImplHandleFocusMsg( HWND hWnd )
pFrame->mbAtCursorIME = (nImeProps & IME_PROP_AT_CARET) != 0;
pFrame->mbHandleIME = !pFrame->mbSpezIME;
}
-
- pFrame->CallCallback( SalEvent::GetFocus, nullptr );
- }
- else
- {
- pFrame->CallCallback( SalEvent::LoseFocus, nullptr );
}
+ pFrame->CallCallback( bGotFocus ? SalEvent::GetFocus : SalEvent::LoseFocus, nullptr );
}
-
ImplSalYieldMutexRelease();
}
- else
- {
- BOOL const ret = PostMessageW( hWnd, SAL_MSG_DEFERREDSETFOCUS, 0, 0 );
- SAL_WARN_IF(0 == ret, "vcl", "ERROR: PostMessage() failed!");
- }
}
static void ImplHandleCloseMsg( HWND hWnd )
{
- if ( ImplSalYieldMutexTryToAcquire() )
- {
- WinSalFrame* pFrame = GetWindowPtr( hWnd );
+ WinSalFrame* pFrame = ProcessOrDeferMessage( hWnd, WM_CLOSE );
if ( pFrame )
{
pFrame->CallCallback( SalEvent::Close, nullptr );
+ ImplSalYieldMutexRelease();
}
-
- ImplSalYieldMutexRelease();
- }
- else
- {
- BOOL const ret = PostMessageW( hWnd, WM_CLOSE, 0, 0 );
- SAL_WARN_IF(0 == ret, "vcl", "ERROR: PostMessage() failed!");
- }
}
static long ImplHandleShutDownMsg( HWND hWnd )
{
- ImplSalYieldMutexAcquireWithWait();
- long nRet = 0;
- WinSalFrame* pFrame = GetWindowPtr( hWnd );
+ long nRet = 0;
+ WinSalFrame* pFrame = ProcessOrDeferMessage( hWnd, 0, 0, DeferPolicy::Blocked );
if ( pFrame )
{
nRet = pFrame->CallCallback( SalEvent::Shutdown, nullptr );
+ ImplSalYieldMutexRelease();
}
- ImplSalYieldMutexRelease();
return nRet;
}
@@ -4083,9 +4081,7 @@ static void ImplHandleSettingsChangeMsg( HWND hWnd, UINT nMsg,
if ( WM_SYSCOLORCHANGE == nMsg && GetSalData()->mhDitherPal )
ImplUpdateSysColorEntries();
- ImplSalYieldMutexAcquireWithWait();
-
- WinSalFrame* pFrame = GetWindowPtr( hWnd );
+ WinSalFrame* pFrame = ProcessOrDeferMessage( hWnd, 0, 0, DeferPolicy::Blocked );
if ( pFrame )
{
if ( (nMsg == WM_DISPLAYCHANGE) || (nMsg == WM_WININICHANGE) )
@@ -4095,20 +4091,18 @@ static void ImplHandleSettingsChangeMsg( HWND hWnd, UINT nMsg,
}
pFrame->CallCallback( nSalEvent, nullptr );
+ ImplSalYieldMutexRelease();
}
-
- ImplSalYieldMutexRelease();
}
static void ImplHandleUserEvent( HWND hWnd, LPARAM lParam )
{
- ImplSalYieldMutexAcquireWithWait();
- WinSalFrame* pFrame = GetWindowPtr( hWnd );
+ WinSalFrame* pFrame = ProcessOrDeferMessage( hWnd, 0, 0, DeferPolicy::Blocked );
if ( pFrame )
{
pFrame->CallCallback( SalEvent::UserEvent, reinterpret_cast<void*>(lParam) );
+ ImplSalYieldMutexRelease();
}
- ImplSalYieldMutexRelease();
}
static void ImplHandleForcePalette( HWND hWnd )
@@ -4117,14 +4111,7 @@ static void ImplHandleForcePalette( HWND hWnd )
HPALETTE hPal = pSalData->mhDitherPal;
if ( hPal )
{
- if ( !ImplSalYieldMutexTryToAcquire() )
- {
- BOOL const ret = PostMessageW( hWnd, SAL_MSG_FORCEPALETTE, 0, 0 );
- SAL_WARN_IF(0 == ret, "vcl", "ERROR: PostMessage() failed!");
- return;
- }
-
- WinSalFrame* pFrame = GetWindowPtr( hWnd );
+ WinSalFrame* pFrame = ProcessOrDeferMessage( hWnd, SAL_MSG_FORCEPALETTE );
if ( pFrame && pFrame->mpGraphics )
{
WinSalGraphics* pGraphics = pFrame->mpGraphics;
@@ -4139,8 +4126,8 @@ static void ImplHandleForcePalette( HWND hWnd )
}
}
}
-
- ImplSalYieldMutexRelease();
+ if ( pFrame )
+ ImplSalYieldMutexRelease();
}
}
commit 85e5b279202ce63c1bd5c44d5e06d59068ce528b
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date: Sat Oct 29 02:36:46 2016 +0200
Change SAL_MSG_DEFERREDTIMER to unique number
When introduced in commit 0bf4645736af9f3a8d8b91b2a9c0af3ec5404cf9,
SAL_MSG_POSTTIMER got the same id then SALOBJ_MSG_DEFERREDFOCUS just
a few lines below, so change the id from 161 to the consecutive
SAL_MSG_* id 146.
Change-Id: I14ec79d18d7ddb84b4c33bcfddd6352890441581
diff --git a/vcl/inc/win/saldata.hxx b/vcl/inc/win/saldata.hxx
index 13f52b0..fa65c56 100644
--- a/vcl/inc/win/saldata.hxx
+++ b/vcl/inc/win/saldata.hxx
@@ -259,7 +259,7 @@ int ImplSalWICompareAscii( const wchar_t* pStr1, const char* pStr2 );
// wParam == nFlags; lParam == 0
#define SAL_MSG_ENDEXTTEXTINPUT (WM_USER+145)
// DEFERREDTIMER-Message; wparam = 0, lParam == time
-#define SAL_MSG_DEFERREDTIMER (WM_USER+161)
+#define SAL_MSG_DEFERREDTIMER (WM_USER+146)
// SysChild-ToTop; wParam = 0; lParam = 0
#define SALOBJ_MSG_TOTOP (WM_USER+160)
commit 642f558d8b3352faf6afeb6204bc7610b23714cb
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date: Sat Oct 29 02:29:43 2016 +0200
Rename POST messages to DEFERRED
POST indicates a message is processed after the original message.
While this is semantically correct, these messages are used to defer
the processing of a message AKA postponed, until we acquire the
Yield mutex in the main thread.
While at it rename POSTFOCUS to DEFERREDSETFOCUS, as this defers
the WM_SETFOCUS message.
Change-Id: I66669e1a1ad807049232476414ac9e2fd4e5cb47
diff --git a/vcl/inc/win/saldata.hxx b/vcl/inc/win/saldata.hxx
index fc82e13..13f52b0 100644
--- a/vcl/inc/win/saldata.hxx
+++ b/vcl/inc/win/saldata.hxx
@@ -233,17 +233,17 @@ int ImplSalWICompareAscii( const wchar_t* pStr1, const char* pStr2 );
// NULL-Message, should not be processed
#define SAL_MSG_DUMMY (WM_USER+132)
// wParam == 0; lParam == 0
-#define SAL_MSG_POSTFOCUS (WM_USER+133)
+#define SAL_MSG_DEFERREDSETFOCUS (WM_USER+133)
// wParam == wParam; lParam == lParam
-#define SAL_MSG_POSTQUERYNEWPAL (WM_USER+134)
+#define SAL_MSG_DEFERREDQUERYNEWPAL (WM_USER+134)
// wParam == wParam; lParam == lParam
-#define SAL_MSG_POSTPALCHANGED (WM_USER+135)
+#define SAL_MSG_DEFERREDPALCHANGED (WM_USER+135)
// wParam == wParam; lParam == lParam
-#define SAL_MSG_POSTMOVE (WM_USER+136)
+#define SAL_MSG_DEFERREDMOVE (WM_USER+136)
// wParam == wParam; lParam == lParam
-#define SAL_MSG_POSTCALLSIZE (WM_USER+137)
+#define SAL_MSG_DEFERREDCALLSIZE (WM_USER+137)
// wParam == pRECT; lParam == 0
-#define SAL_MSG_POSTPAINT (WM_USER+138)
+#define SAL_MSG_DEFERREDPAINT (WM_USER+138)
// wParam == 0; lParam == pFrame; lResult 0
#define SAL_MSG_FORCEPALETTE (WM_USER+139)
// wParam == 0; lParam == 0
@@ -258,13 +258,13 @@ int ImplSalWICompareAscii( const wchar_t* pStr1, const char* pStr2 );
#define SAL_MSG_SETINPUTCONTEXT (WM_USER+144)
// wParam == nFlags; lParam == 0
#define SAL_MSG_ENDEXTTEXTINPUT (WM_USER+145)
-// POSTTIMER-Message; wparam = 0, lParam == time
-#define SAL_MSG_POSTTIMER (WM_USER+161)
+// DEFERREDTIMER-Message; wparam = 0, lParam == time
+#define SAL_MSG_DEFERREDTIMER (WM_USER+161)
// SysChild-ToTop; wParam = 0; lParam = 0
#define SALOBJ_MSG_TOTOP (WM_USER+160)
-// POSTFOCUS-Message; wParam == bFocus; lParam == 0
-#define SALOBJ_MSG_POSTFOCUS (WM_USER+161)
+// DEFERREDFOCUS-Message; wParam == bFocus; lParam == 0
+#define SALOBJ_MSG_DEFERREDFOCUS (WM_USER+161)
// Call the Timer's callback from the main thread
#define SAL_MSG_TIMER_CALLBACK (WM_USER+162)
diff --git a/vcl/win/app/salinst.cxx b/vcl/win/app/salinst.cxx
index 34d1f50..35cd5b6 100644
--- a/vcl/win/app/salinst.cxx
+++ b/vcl/win/app/salinst.cxx
@@ -725,7 +725,7 @@ LRESULT CALLBACK SalComWndProc( HWND, UINT nMsg, WPARAM wParam, LPARAM lParam, i
ReleaseDC( reinterpret_cast<HWND>(wParam), reinterpret_cast<HDC>(lParam) );
rDef = FALSE;
break;
- case SAL_MSG_POSTTIMER:
+ case SAL_MSG_DEFERREDTIMER:
EmitTimerCallback();
break;
case SAL_MSG_TIMER_CALLBACK:
@@ -826,7 +826,7 @@ bool WinSalInstance::AnyInput( VclInputFlags nType )
PM_NOREMOVE | PM_NOYIELD ) )
return true;
- if ( PeekMessageW( &aMsg, nullptr, SAL_MSG_POSTCALLSIZE, SAL_MSG_POSTCALLSIZE,
+ if ( PeekMessageW( &aMsg, nullptr, SAL_MSG_DEFERREDCALLSIZE, SAL_MSG_DEFERREDCALLSIZE,
PM_NOREMOVE | PM_NOYIELD ) )
return true;
@@ -834,7 +834,7 @@ bool WinSalInstance::AnyInput( VclInputFlags nType )
PM_NOREMOVE | PM_NOYIELD ) )
return true;
- if ( PeekMessageW( &aMsg, nullptr, SAL_MSG_POSTMOVE, SAL_MSG_POSTMOVE,
+ if ( PeekMessageW( &aMsg, nullptr, SAL_MSG_DEFERREDMOVE, SAL_MSG_DEFERREDMOVE,
PM_NOREMOVE | PM_NOYIELD ) )
return true;
}
diff --git a/vcl/win/window/salframe.cxx b/vcl/win/window/salframe.cxx
index f5dac2d..38894ed 100644
--- a/vcl/win/window/salframe.cxx
+++ b/vcl/win/window/salframe.cxx
@@ -3701,14 +3701,14 @@ long ImplHandleSalObjSysCharMsg( HWND hWnd, WPARAM wParam, LPARAM lParam )
return nRet;
}
-enum class PostPaint
+enum class DeferredPaint
{
- IsPosted,
+ IsDeferred,
IsInitial
};
-static bool ImplHandlePostPaintMsg( HWND hWnd, RECT* pRect,
- PostPaint eProcessed = PostPaint::IsPosted )
+static BOOL ImplHandleDeferredPaintMsg( HWND hWnd, RECT* pRect,
+ DeferredPaint eProcessed = DeferredPaint::IsDeferred )
{
bool bGotMutex = false;
@@ -3723,20 +3723,20 @@ static bool ImplHandlePostPaintMsg( HWND hWnd, RECT* pRect,
SalPaintEvent aPEvt( pRect->left, pRect->top, pRect->right-pRect->left, pRect->bottom-pRect->top );
pFrame->CallCallback( SalEvent::Paint, &aPEvt );
ImplSalYieldMutexRelease();
- if ( PostPaint::IsIsPosted == eProcessed )
+ if ( DeferredPaint::IsDeferred == eProcessed )
delete pRect;
}
else
{
RECT* pMsgRect;
- if ( PostPaint::IsInitial == eProcessed )
+ if ( DeferredPaint::IsInitial == eProcessed )
{
pMsgRect = new RECT;
CopyRect( pMsgRect, pRect );
}
else
pMsgRect = pRect;
- BOOL const ret = PostMessageW(hWnd, SAL_MSG_POSTPAINT, reinterpret_cast<WPARAM>(pMsgRect), 0);
+ BOOL const ret = PostMessageW(hWnd, SAL_MSG_DEFERREDPAINT, reinterpret_cast<WPARAM>(pMsgRect), 0);
SAL_WARN_IF(0 == ret, "vcl", "ERROR: PostMessage() failed!");
}
}
@@ -3782,8 +3782,8 @@ static bool ImplHandlePaintMsg( HWND hWnd )
// try painting
if ( bHasPaintRegion )
{
- bPaintSuccessful = ImplHandlePostPaintMsg( hWnd, &aUpdateRect,
- PostPaint::IsInitial );
+ bPaintSuccessful = ImplHandleDeferredPaintMsg(
+ hWnd, &aUpdateRect, DeferredPaint::IsInitial );
EndPaint( hWnd, &aPs );
}
else // if there is nothing to paint, the paint is successful
@@ -3933,7 +3933,7 @@ static void ImplHandleMoveMsg( HWND hWnd )
}
else
{
- BOOL const ret = PostMessageW( hWnd, SAL_MSG_POSTMOVE, 0, 0 );
+ BOOL const ret = PostMessageW( hWnd, SAL_MSG_DEFERREDMOVE, 0, 0 );
SAL_WARN_IF(0 == ret, "vcl", "ERROR: PostMessage() failed!");
}
}
@@ -3957,7 +3957,7 @@ static void ImplCallSizeHdl( HWND hWnd )
}
else
{
- BOOL const ret = PostMessageW( hWnd, SAL_MSG_POSTCALLSIZE, 0, 0 );
+ BOOL const ret = PostMessageW( hWnd, SAL_MSG_DEFERREDCALLSIZE, 0, 0 );
SAL_WARN_IF(0 == ret, "vcl", "ERROR: PostMessage() failed!");
}
}
@@ -4015,7 +4015,7 @@ static void ImplHandleFocusMsg( HWND hWnd )
}
else
{
- BOOL const ret = PostMessageW( hWnd, SAL_MSG_POSTFOCUS, 0, 0 );
+ BOOL const ret = PostMessageW( hWnd, SAL_MSG_DEFERREDSETFOCUS, 0, 0 );
SAL_WARN_IF(0 == ret, "vcl", "ERROR: PostMessage() failed!");
}
}
@@ -4156,7 +4156,7 @@ static LRESULT ImplHandlePalette( bool bFrame, HWND hWnd, UINT nMsg,
if ( pSalData->mbInPalChange )
return 0;
- if ( (nMsg == WM_PALETTECHANGED) || (nMsg == SAL_MSG_POSTPALCHANGED) )
+ if ( (nMsg == WM_PALETTECHANGED) || (nMsg == SAL_MSG_DEFERREDPALCHANGED) )
{
if ( reinterpret_cast<HWND>(wParam) == hWnd )
return 0;
@@ -4171,12 +4171,12 @@ static LRESULT ImplHandlePalette( bool bFrame, HWND hWnd, UINT nMsg,
bReleaseMutex = TRUE;
else if ( nMsg == WM_QUERYNEWPALETTE )
{
- BOOL const ret = PostMessageW(hWnd, SAL_MSG_POSTQUERYNEWPAL, wParam, lParam);
+ BOOL const ret = PostMessageW(hWnd, SAL_MSG_DEFERREDQUERYNEWPAL, wParam, lParam);
SAL_WARN_IF(0 == ret, "vcl", "ERROR: PostMessage() failed!");
}
else /* ( nMsg == WM_PALETTECHANGED ) */
{
- BOOL const ret = PostMessageW(hWnd, SAL_MSG_POSTPALCHANGED, wParam, lParam);
+ BOOL const ret = PostMessageW(hWnd, SAL_MSG_DEFERREDPALCHANGED, wParam, lParam);
SAL_WARN_IF(0 == ret, "vcl", "ERROR: PostMessage() failed!");
}
}
@@ -5620,7 +5620,7 @@ LRESULT CALLBACK SalFrameWndProc( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lP
break;
case WM_MOVE:
- case SAL_MSG_POSTMOVE:
+ case SAL_MSG_DEFERREDMOVE:
ImplHandleMoveMsg( hWnd );
rDef = FALSE;
break;
@@ -5628,7 +5628,7 @@ LRESULT CALLBACK SalFrameWndProc( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lP
ImplHandleSizeMsg( hWnd, wParam, lParam );
rDef = FALSE;
break;
- case SAL_MSG_POSTCALLSIZE:
+ case SAL_MSG_DEFERREDCALLSIZE:
ImplCallSizeHdl( hWnd );
rDef = FALSE;
break;
@@ -5646,8 +5646,8 @@ LRESULT CALLBACK SalFrameWndProc( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lP
bCheckTimers = ImplHandlePaintMsg( hWnd );
rDef = FALSE;
break;
- case SAL_MSG_POSTPAINT:
- bCheckTimers = ImplHandlePostPaintMsg( hWnd, reinterpret_cast<RECT*>(wParam) );
+ case SAL_MSG_DEFERREDPAINT:
+ bCheckTimers = ImplHandleDeferredPaintMsg( hWnd, reinterpret_cast<RECT*>(wParam) );
rDef = FALSE;
break;
@@ -5657,7 +5657,7 @@ LRESULT CALLBACK SalFrameWndProc( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lP
break;
case WM_QUERYNEWPALETTE:
- case SAL_MSG_POSTQUERYNEWPAL:
+ case SAL_MSG_DEFERREDQUERYNEWPAL:
nRet = ImplHandlePalette( true, hWnd, nMsg, wParam, lParam, rDef );
break;
@@ -5706,7 +5706,7 @@ LRESULT CALLBACK SalFrameWndProc( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lP
DestroyCaret();
SAL_FALLTHROUGH;
case WM_SETFOCUS:
- case SAL_MSG_POSTFOCUS:
+ case SAL_MSG_DEFERREDSETFOCUS:
ImplHandleFocusMsg( hWnd );
rDef = FALSE;
break;
@@ -5879,7 +5879,7 @@ LRESULT CALLBACK SalFrameWndProc( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lP
MSG aMsg;
if( ! PeekMessageW( &aMsg, nullptr, WM_PAINT, WM_PAINT, PM_NOREMOVE | PM_NOYIELD ) )
{
- BOOL const ret = PostMessageW(pSalData->mpFirstInstance->mhComWnd, SAL_MSG_POSTTIMER, 0, nCurTime);
+ BOOL const ret = PostMessageW(pSalData->mpFirstInstance->mhComWnd, SAL_MSG_DEFERREDTIMER, 0, nCurTime);
SAL_WARN_IF(0 == ret, "vcl", "ERROR: PostMessage() failed!");
}
}
@@ -5923,7 +5923,7 @@ bool ImplHandleGlobalMsg( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam, LR
// handle all messages concerning all frames so they get processed only once
// Must work for Unicode and none Unicode
bool bResult = FALSE;
- if ( (nMsg == WM_PALETTECHANGED) || (nMsg == SAL_MSG_POSTPALCHANGED) )
+ if ( (nMsg == WM_PALETTECHANGED) || (nMsg == SAL_MSG_DEFERREDPALCHANGED) )
{
int bDef = TRUE;
rlResult = ImplHandlePalette( false, hWnd, nMsg, wParam, lParam, bDef );
diff --git a/vcl/win/window/salobj.cxx b/vcl/win/window/salobj.cxx
index f21dfb7..17c32c6 100644
--- a/vcl/win/window/salobj.cxx
+++ b/vcl/win/window/salobj.cxx
@@ -113,7 +113,7 @@ LRESULT CALLBACK SalSysMsgProc( int nCode, WPARAM wParam, LPARAM lParam )
}
else
{
- BOOL const ret = PostMessageW(pObject->mhWnd, SALOBJ_MSG_POSTFOCUS, 0, 0);
+ BOOL const ret = PostMessageW(pObject->mhWnd, SALOBJ_MSG_DEFERREDFOCUS, 0, 0);
SAL_WARN_IF(0 == ret, "vcl", "ERROR: PostMessage() failed!");
}
}
@@ -133,7 +133,7 @@ LRESULT CALLBACK SalSysMsgProc( int nCode, WPARAM wParam, LPARAM lParam )
}
else
{
- BOOL const ret = PostMessageW(pObject->mhWnd, SALOBJ_MSG_POSTFOCUS, 0, 0);
+ BOOL const ret = PostMessageW(pObject->mhWnd, SALOBJ_MSG_DEFERREDFOCUS, 0, 0);
SAL_WARN_IF(0 == ret, "vcl", "ERROR: PostMessage() failed!");
}
}
@@ -320,7 +320,7 @@ LRESULT CALLBACK SalSysObjWndProc( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM l
}
break;
- case SALOBJ_MSG_POSTFOCUS:
+ case SALOBJ_MSG_DEFERREDFOCUS:
if ( ImplSalYieldMutexTryToAcquire() )
{
pSysObj = GetSalObjWindowPtr( hWnd );
@@ -335,7 +335,7 @@ LRESULT CALLBACK SalSysObjWndProc( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM l
}
else
{
- BOOL const ret = PostMessageW(hWnd, SALOBJ_MSG_POSTFOCUS, 0, 0);
+ BOOL const ret = PostMessageW(hWnd, SALOBJ_MSG_DEFERREDFOCUS, 0, 0);
SAL_WARN_IF(0 == ret, "vcl", "ERROR: PostMessage() failed!");
}
rDef = FALSE;
commit 71c15eeb114333a68bbda675812ccf35b0b848a4
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date: Sat Oct 29 02:11:32 2016 +0200
Cleanup paint message handling
Makes PAINT handling function use the POSTPAINT handling
function and unifies the locking behaviour, so we now check
the frame before trying to aquire the lock in both functions.
Change-Id: Ia6bac6e24d95e680830c5405f0ab34cbed6e9688
diff --git a/vcl/win/window/salframe.cxx b/vcl/win/window/salframe.cxx
index 8257ec0..f5dac2d 100644
--- a/vcl/win/window/salframe.cxx
+++ b/vcl/win/window/salframe.cxx
@@ -3701,93 +3701,96 @@ long ImplHandleSalObjSysCharMsg( HWND hWnd, WPARAM wParam, LPARAM lParam )
return nRet;
}
-static bool ImplHandlePaintMsg( HWND hWnd )
+enum class PostPaint
{
- bool bMutex = FALSE;
- if ( ImplSalYieldMutexTryToAcquire() )
- bMutex = TRUE;
+ IsPosted,
+ IsInitial
+};
- // if we don't get the mutex, we can also change the clip region,
- // because other threads doesn't use the mutex from the main
- // thread --> see AcquireGraphics()
+static bool ImplHandlePostPaintMsg( HWND hWnd, RECT* pRect,
+ PostPaint eProcessed = PostPaint::IsPosted )
+{
+ bool bGotMutex = false;
WinSalFrame* pFrame = GetWindowPtr( hWnd );
if ( pFrame )
{
- // clip-region must be reset, as we do not get a proper
- // bounding-rectangle otherwise
- if ( pFrame->mpGraphics && pFrame->mpGraphics->getRegion() )
- SelectClipRgn( pFrame->mpGraphics->getHDC(), nullptr );
+ if ( ImplSalYieldMutexTryToAcquire() )
+ bGotMutex = true;
- // according to Window-Documentation one shall check first if
- // there really is a paint-region
- if ( GetUpdateRect( hWnd, nullptr, FALSE ) )
+ if ( bGotMutex )
{
- // Call BeginPaint/EndPaint to query the rect and send
- // this Notofication to rect
- RECT aUpdateRect;
- PAINTSTRUCT aPs;
- BeginPaint( hWnd, &aPs );
- CopyRect( &aUpdateRect, &aPs.rcPaint );
-
- // Paint
- // reset ClipRegion
- if ( pFrame->mpGraphics && pFrame->mpGraphics->getRegion() )
- {
- SelectClipRgn( pFrame->mpGraphics->getHDC(),
- pFrame->mpGraphics->getRegion() );
- }
-
- if ( bMutex )
- {
- SalPaintEvent aPEvt( aUpdateRect.left, aUpdateRect.top, aUpdateRect.right-aUpdateRect.left, aUpdateRect.bottom-aUpdateRect.top, pFrame->mbPresentation );
- pFrame->CallCallback( SalEvent::Paint, &aPEvt );
- }
- else
- {
- RECT* pRect = new RECT;
- CopyRect( pRect, &aUpdateRect );
- BOOL const ret = PostMessageW(hWnd, SAL_MSG_POSTPAINT, reinterpret_cast<WPARAM>(pRect), 0);
- SAL_WARN_IF(0 == ret, "vcl", "ERROR: PostMessage() failed!");
- }
- EndPaint( hWnd, &aPs );
+ SalPaintEvent aPEvt( pRect->left, pRect->top, pRect->right-pRect->left, pRect->bottom-pRect->top );
+ pFrame->CallCallback( SalEvent::Paint, &aPEvt );
+ ImplSalYieldMutexRelease();
+ if ( PostPaint::IsIsPosted == eProcessed )
+ delete pRect;
}
else
{
- // reset ClipRegion
- if ( pFrame->mpGraphics && pFrame->mpGraphics->getRegion() )
+ RECT* pMsgRect;
+ if ( PostPaint::IsInitial == eProcessed )
{
- SelectClipRgn( pFrame->mpGraphics->getHDC(),
- pFrame->mpGraphics->getRegion() );
+ pMsgRect = new RECT;
+ CopyRect( pMsgRect, pRect );
}
+ else
+ pMsgRect = pRect;
+ BOOL const ret = PostMessageW(hWnd, SAL_MSG_POSTPAINT, reinterpret_cast<WPARAM>(pMsgRect), 0);
+ SAL_WARN_IF(0 == ret, "vcl", "ERROR: PostMessage() failed!");
}
}
- if ( bMutex )
- ImplSalYieldMutexRelease();
-
- return bMutex;
+ return bGotMutex;
}
-static void ImplHandlePaintMsg2( HWND hWnd, RECT* pRect )
+static bool ImplHandlePaintMsg( HWND hWnd )
{
- // Paint
- if ( ImplSalYieldMutexTryToAcquire() )
+ bool bPaintSuccessful = false;
+
+ // even without the Yield mutex, we can still change the clip region,
+ // because other threads don't use the Yield mutex
+ // --> see AcquireGraphics()
+
+ WinSalFrame* pFrame = GetWindowPtr( hWnd );
+ if ( pFrame )
{
- WinSalFrame* pFrame = GetWindowPtr( hWnd );
- if ( pFrame )
+ // clip region must be set, as we don't get a proper
+ // bounding rectangle otherwise
+ bool bHasClipRegion = pFrame->mpGraphics && pFrame->mpGraphics->getRegion();
+ if ( bHasClipRegion )
+ SelectClipRgn( pFrame->mpGraphics->getHDC(), nullptr );
+
+ // according to Windows documentation one shall check first if
+ // there really is a paint-region
+ RECT aUpdateRect;
+ PAINTSTRUCT aPs;
+ bool bHasPaintRegion = GetUpdateRect( hWnd, nullptr, FALSE );
+ if ( bHasPaintRegion )
{
- SalPaintEvent aPEvt( pRect->left, pRect->top, pRect->right-pRect->left, pRect->bottom-pRect->top );
- pFrame->CallCallback( SalEvent::Paint, &aPEvt );
+ // call BeginPaint/EndPaint to query the paint rect and use
+ // this infomation in the (deferred) paint
+ BeginPaint( hWnd, &aPs );
+ CopyRect( &aUpdateRect, &aPs.rcPaint );
}
- ImplSalYieldMutexRelease();
- delete pRect;
- }
- else
- {
- BOOL const ret = PostMessageW(hWnd, SAL_MSG_POSTPAINT, reinterpret_cast<WPARAM>(pRect), 0);
- SAL_WARN_IF(0 == ret, "vcl", "ERROR: PostMessage() failed!");
+
+ // reset clip region
+ if ( bHasClipRegion )
+ SelectClipRgn( pFrame->mpGraphics->getHDC(),
+ pFrame->mpGraphics->getRegion() );
+
+ // try painting
+ if ( bHasPaintRegion )
+ {
+ bPaintSuccessful = ImplHandlePostPaintMsg( hWnd, &aUpdateRect,
+ PostPaint::IsInitial );
+ EndPaint( hWnd, &aPs );
+ }
+ else // if there is nothing to paint, the paint is successful
+ bPaintSuccessful = true
}
+
+ return bPaintSuccessful;
}
static void SetMaximizedFrameGeometry( HWND hWnd, WinSalFrame* pFrame, RECT* pParentRect )
@@ -5644,8 +5647,7 @@ LRESULT CALLBACK SalFrameWndProc( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lP
rDef = FALSE;
break;
case SAL_MSG_POSTPAINT:
- ImplHandlePaintMsg2( hWnd, reinterpret_cast<RECT*>(wParam) );
- bCheckTimers = true;
+ bCheckTimers = ImplHandlePostPaintMsg( hWnd, reinterpret_cast<RECT*>(wParam) );
rDef = FALSE;
break;
commit 2cd6a751a0f35ddf5ad71938e1ea9c70230a54dc
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date: Sun Oct 23 14:01:45 2016 +0200
Reduce <vcl/scheduler.hxx> header scope
This includes <vcl/timer.hx> and <vcl/idle.hxx>.
Change-Id: Ia1d042db670bdd20ce82b45d8cd41bc0d2f56d5f
diff --git a/cui/source/dialogs/cuigrfflt.cxx b/cui/source/dialogs/cuigrfflt.cxx
index c6928c2..bd417e8 100644
--- a/cui/source/dialogs/cuigrfflt.cxx
+++ b/cui/source/dialogs/cuigrfflt.cxx
@@ -19,6 +19,7 @@
#include <vcl/builderfactory.hxx>
#include <vcl/msgbox.hxx>
+#include <vcl/animate.hxx>
#include <sfx2/viewfrm.hxx>
#include <sfx2/viewsh.hxx>
#include <sfx2/objsh.hxx>
diff --git a/cui/source/dialogs/screenshotannotationdlg.cxx b/cui/source/dialogs/screenshotannotationdlg.cxx
index cd0591d..42d6445 100644
--- a/cui/source/dialogs/screenshotannotationdlg.cxx
+++ b/cui/source/dialogs/screenshotannotationdlg.cxx
@@ -31,6 +31,7 @@
#include <comphelper/random.hxx>
#include <vcl/pngwrite.hxx>
#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <tools/stream.hxx>
#include <tools/urlobj.hxx>
#include <vcl/fixed.hxx>
#include <vcl/svapp.hxx>
diff --git a/dbaccess/source/ui/inc/sqledit.hxx b/dbaccess/source/ui/inc/sqledit.hxx
index 4150b22..110d08b 100644
--- a/dbaccess/source/ui/inc/sqledit.hxx
+++ b/dbaccess/source/ui/inc/sqledit.hxx
@@ -25,6 +25,7 @@
#include <svtools/editsyntaxhighlighter.hxx>
#include <svl/lstner.hxx>
#include <svtools/colorcfg.hxx>
+#include <vcl/timer.hxx>
namespace com { namespace sun { namespace star { namespace beans {
class XMultiPropertySet;
diff --git a/editeng/source/items/paraitem.cxx b/editeng/source/items/paraitem.cxx
index 26bb5d0..2f45af5 100644
--- a/editeng/source/items/paraitem.cxx
+++ b/editeng/source/items/paraitem.cxx
@@ -25,6 +25,7 @@
#include <unotools/syslocale.hxx>
#include <comphelper/types.hxx>
#include <tools/mapunit.hxx>
+#include <tools/stream.hxx>
#include <svl/itempool.hxx>
#include <svl/memberid.hrc>
#include <editeng/editrids.hrc>
diff --git a/extensions/source/scanner/sane.hxx b/extensions/source/scanner/sane.hxx
index 327410e..99b2338 100644
--- a/extensions/source/scanner/sane.hxx
+++ b/extensions/source/scanner/sane.hxx
@@ -22,6 +22,7 @@
#include <osl/thread.h>
#include <osl/module.h>
#include <vcl/bitmap.hxx>
+#include <tools/stream.hxx>
#include <sane/sane.h>
#include <scanner.hxx>
diff --git a/filter/source/graphicfilter/egif/egif.cxx b/filter/source/graphicfilter/egif/egif.cxx
index 29a75ab..3d1d6f4 100644
--- a/filter/source/graphicfilter/egif/egif.cxx
+++ b/filter/source/graphicfilter/egif/egif.cxx
@@ -24,6 +24,7 @@
#include <vcl/window.hxx>
#include <svl/solar.hrc>
#include <vcl/fltcall.hxx>
+#include <vcl/animate.hxx>
#include <vcl/FilterConfigItem.hxx>
#include "giflzwc.hxx"
#include <memory>
diff --git a/filter/source/graphicfilter/etiff/etiff.cxx b/filter/source/graphicfilter/etiff/etiff.cxx
index ed955cf..b4711f4 100644
--- a/filter/source/graphicfilter/etiff/etiff.cxx
+++ b/filter/source/graphicfilter/etiff/etiff.cxx
@@ -24,6 +24,7 @@
#include <vcl/bitmapaccess.hxx>
#include <svl/solar.hrc>
#include <vcl/fltcall.hxx>
+#include <vcl/animate.hxx>
#include <vcl/FilterConfigItem.hxx>
#define NewSubfileType 254
diff --git a/forms/source/component/clickableimage.cxx b/forms/source/component/clickableimage.cxx
index 54f0963..4dc031c 100644
--- a/forms/source/component/clickableimage.cxx
+++ b/forms/source/component/clickableimage.cxx
@@ -36,6 +36,7 @@
#include <tools/urlobj.hxx>
#include <tools/debug.hxx>
#include <vcl/svapp.hxx>
+#include <vcl/graph.hxx>
#include <sfx2/docfile.hxx>
#include <sfx2/objsh.hxx>
#include <osl/mutex.hxx>
diff --git a/framework/source/uielement/togglebuttontoolbarcontroller.cxx b/framework/source/uielement/togglebuttontoolbarcontroller.cxx
index c0a19ff..c066be9 100644
--- a/framework/source/uielement/togglebuttontoolbarcontroller.cxx
+++ b/framework/source/uielement/togglebuttontoolbarcontroller.cxx
@@ -40,6 +40,8 @@
#include <vcl/bitmap.hxx>
#include <vcl/graphicfilter.hxx>
#include <vcl/toolbox.hxx>
+#include <vcl/menu.hxx>
+#include <vcl/combobox.hxx>
#include <svtools/miscopt.hxx>
using namespace ::com::sun::star;
diff --git a/include/svtools/grfmgr.hxx b/include/svtools/grfmgr.hxx
index 75fb774..118ae27 100644
--- a/include/svtools/grfmgr.hxx
+++ b/include/svtools/grfmgr.hxx
@@ -76,6 +76,7 @@ class SvStream;
class BitmapWriteAccess;
class GraphicCache;
class VirtualDevice;
+class Timer;
struct GrfSimpleCacheObj;
struct ImplTileInfo;
diff --git a/include/vcl/graph.hxx b/include/vcl/graph.hxx
index 31df428..3a2146f 100644
--- a/include/vcl/graph.hxx
+++ b/include/vcl/graph.hxx
@@ -26,7 +26,6 @@
#include <rtl/ustring.hxx>
#include <vcl/bitmap.hxx>
#include <vcl/bitmapex.hxx>
-#include <vcl/animate.hxx>
#include <vcl/gdimtf.hxx>
#include <vcl/gfxlink.hxx>
#include <com/sun/star/uno/Reference.hxx>
@@ -45,6 +44,7 @@ enum class GraphicType
namespace com { namespace sun { namespace star { namespace graphic { class XGraphic;} } } }
namespace vcl { class Font; }
+class Animation;
class GfxLink;
class ImpGraphic;
class OutputDevice;
diff --git a/include/vcl/graphicfilter.hxx b/include/vcl/graphicfilter.hxx
index 2623498..2ceafa1 100644
--- a/include/vcl/graphicfilter.hxx
+++ b/include/vcl/graphicfilter.hxx
@@ -23,7 +23,6 @@
#include <tools/gen.hxx>
#include <tools/urlobj.hxx>
#include <vcl/dllapi.h>
-#include <vcl/field.hxx>
#include <vcl/graph.hxx>
#include <o3tl/typed_flags_set.hxx>
diff --git a/include/vcl/metaact.hxx b/include/vcl/metaact.hxx
index c7a26cd..7ce273c 100644
--- a/include/vcl/metaact.hxx
+++ b/include/vcl/metaact.hxx
@@ -29,7 +29,6 @@
#include <vcl/bitmap.hxx>
#include <vcl/bitmapex.hxx>
#include <vcl/region.hxx>
-#include <vcl/graph.hxx>
#include <vcl/outdev.hxx>
#include <vcl/gdimtf.hxx>
#include <vcl/gfxlink.hxx>
diff --git a/include/vcl/outdev.hxx b/include/vcl/outdev.hxx
index 6b396fa..8e25dc4 100644
--- a/include/vcl/outdev.hxx
... etc. - the rest is truncated
More information about the Libreoffice-commits
mailing list