vcl: re-introduce idle handling.
The idea here is that we should process 'idle' events - like re-paint
after we have processed any OS messages - such as key/mouse input,
window re-size events etc.
The previous approach wasn't achieving this - it was processing a single
idle event each time around the main-loop iteration; urk.
Lubos implemented something -like- this, the vestiges of it need cleaning
up and removing in: 06d731428ef6cf93c7333e8228bfb6088853b52f but it was
disabled (most likely because it broke gtk in tdf#91727, which was itself
broken by using silly values for timeouts in the scheduler (now fixed))
Tested on Windows, gtk, kde4, unx-generic.
Change-Id: I7756bca874779c00f72b372cacb7745d0f189f66
Reviewed-on: https://gerrit.libreoffice.org/20158
Reviewed-by: Michael Meeks <michael.meeks@collabora.com>
Tested-by: Michael Meeks <michael.meeks@collabora.com>
diff --git a/include/vcl/scheduler.hxx b/include/vcl/scheduler.hxx
index be9df9e..5771f3a 100644
--- a/include/vcl/scheduler.hxx
+++ b/include/vcl/scheduler.hxx
@@ -94,7 +94,7 @@
// Process one pending Timer with highhest priority
static void CallbackTaskScheduling( bool ignore );
/// Calculate minimum timeout - and return its value.
static sal_uInt64 CalculateMinimumTimeout();
static sal_uInt64 CalculateMinimumTimeout( bool &bHasActiveIdles );
/// Process one pending task ahead of time with highhest priority.
static void ProcessTaskScheduling( bool bTimer );
};
diff --git a/vcl/source/app/idle.cxx b/vcl/source/app/idle.cxx
index 5ce5361..bba2d05 100644
--- a/vcl/source/app/idle.cxx
+++ b/vcl/source/app/idle.cxx
@@ -48,10 +48,7 @@
bool Idle::ReadyForSchedule( bool bTimer ) const
{
// tdf#91727 - We need to re-work this to allow only UI idle handlers
// and not timeouts to be processed in some limited scenarios
(void)bTimer;
return true; // !bTimer
return !bTimer;
}
sal_uInt64 Idle::UpdateMinPeriod( sal_uInt64 nMinPeriod, sal_uInt64 /* nTime */ ) const
diff --git a/vcl/source/app/scheduler.cxx b/vcl/source/app/scheduler.cxx
index b5e64e2..743de91 100644
--- a/vcl/source/app/scheduler.cxx
+++ b/vcl/source/app/scheduler.cxx
@@ -153,7 +153,7 @@
{
// this function is for the saltimer callback
(void)ignore;
Scheduler::ProcessTaskScheduling( true );
Scheduler::ProcessTaskScheduling( false );
}
void Scheduler::ProcessTaskScheduling( bool bTimerOnly )
@@ -168,7 +168,7 @@
}
}
sal_uInt64 Scheduler::CalculateMinimumTimeout()
sal_uInt64 Scheduler::CalculateMinimumTimeout( bool &bHasActiveIdles )
{
// process all pending Tasks
// if bTimer True, only handle timer
@@ -181,13 +181,11 @@
pSchedulerData = pSVData->mpFirstSchedulerData;
while ( pSchedulerData )
{
if( pSchedulerData->mbInScheduler )
{
pPrevSchedulerData = pSchedulerData;
pSchedulerData = pSchedulerData->mpNext;
}
ImplSchedulerData *pNext = pSchedulerData->mpNext;
// Should Task be released from scheduling?
else if ( pSchedulerData->mbDelete )
if ( !pSchedulerData->mbInScheduler &&
pSchedulerData->mbDelete )
{
if ( pPrevSchedulerData )
pPrevSchedulerData->mpNext = pSchedulerData->mpNext;
@@ -195,19 +193,24 @@
pSVData->mpFirstSchedulerData = pSchedulerData->mpNext;
if ( pSchedulerData->mpScheduler )
pSchedulerData->mpScheduler->mpSchedulerData = nullptr;
ImplSchedulerData* pTempSchedulerData = pSchedulerData;
pSchedulerData = pSchedulerData->mpNext;
delete pTempSchedulerData;
pNext = pSchedulerData->mpNext;
delete pSchedulerData;
}
else
{
nMinPeriod = pSchedulerData->mpScheduler->UpdateMinPeriod( nMinPeriod, nTime );
if (!pSchedulerData->mbInScheduler)
{
if ( pSchedulerData->mpScheduler->ReadyForSchedule( true ) )
nMinPeriod = pSchedulerData->mpScheduler->UpdateMinPeriod( nMinPeriod, nTime );
else
bHasActiveIdles = true;
}
pPrevSchedulerData = pSchedulerData;
pSchedulerData = pSchedulerData->mpNext;
}
pSchedulerData = pNext;
}
// delete clock if no more timers available
// delete clock if no more timers available,
if ( !pSVData->mpFirstSchedulerData )
{
if ( pSVData->mpSalTimer )
diff --git a/vcl/source/app/svapp.cxx b/vcl/source/app/svapp.cxx
index 734b5de..808e743 100644
--- a/vcl/source/app/svapp.cxx
+++ b/vcl/source/app/svapp.cxx
@@ -477,18 +477,25 @@
{
ImplSVData* pSVData = ImplGetSVData();
bool bHasActiveIdles = false;
sal_uInt64 nMinTimeout = 0;
if (nReleased == 0) // else thread doesn't have SolarMutex so avoid race
nMinTimeout = Scheduler::CalculateMinimumTimeout();
nMinTimeout = Scheduler::CalculateMinimumTimeout(bHasActiveIdles);
// FIXME: should use returned value as param to DoYield
(void)nMinTimeout;
// If we have idles, don't wait for the timeout; check for events
// and come back as quick as possible.
if (bHasActiveIdles)
i_bWait = false;
// TODO: there's a data race here on WNT only because ImplYield may be
// called without SolarMutex; if we can get rid of LazyDelete (with VclPtr)
// then the only remaining use of mnDispatchLevel is in OSX specific code
// so that would effectively eliminate the race on WNT
pSVData->maAppData.mnDispatchLevel++;
// do not wait for events if application was already quit; in that
// case only dispatch events already available
// do not wait for events either if the app decided that it is too busy for timers