summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/vcl/idle.hxx4
-rw-r--r--include/vcl/task.hxx1
-rw-r--r--vcl/README.scheduler15
-rw-r--r--vcl/source/app/scheduler.cxx11
4 files changed, 31 insertions, 0 deletions
diff --git a/include/vcl/idle.hxx b/include/vcl/idle.hxx
index ebbeb160cf41..78fcaae817b9 100644
--- a/include/vcl/idle.hxx
+++ b/include/vcl/idle.hxx
@@ -26,6 +26,10 @@
* An idle is a timer to be scheduled immediately.
*
* It's - more or less - just a convenience class.
+ *
+ * Note: Despite the name, the timer is not necessarily invoked when idle.
+ * Use an idle priority such as TaskPriority::DEFAULT_IDLE to actually
+ * invoke the timer only when idle.
*/
class VCL_DLLPUBLIC Idle : public Timer
{
diff --git a/include/vcl/task.hxx b/include/vcl/task.hxx
index d8adae7eff0b..e95aa5bc460a 100644
--- a/include/vcl/task.hxx
+++ b/include/vcl/task.hxx
@@ -28,6 +28,7 @@ enum class TaskPriority
{
HIGHEST, ///< These events should run very fast!
DEFAULT, ///< Default priority used, e.g. the default timer priority
+ // Input from the OS event queue is processed before HIGH_IDLE tasks.
HIGH_IDLE, ///< Important idle events to be run before processing drawing events
RESIZE, ///< Resize runs before repaint, so we won't paint twice
REPAINT, ///< All repaint events should go in here
diff --git a/vcl/README.scheduler b/vcl/README.scheduler
index 263fe329bc3d..38e17d8cedef 100644
--- a/vcl/README.scheduler
+++ b/vcl/README.scheduler
@@ -74,6 +74,21 @@ non-scheduler code, so it was converted to a non-recursive
std::mutex.
+= Idle processing =
+
+Confusingly, there are 2 concepts that are called 'idle':
+
+* Instant (zero timeout) tasks, represented e.g. by the Idle class. This is
+a misnomer, as these tasks are processed after returning to the main loop.
+This is not necessarily when LO is idle, in fact such tasks may be invoked
+while there is input in the OS event queue pending.
+(TODO: This case should be fixed by renaming.)
+
+* Low priority tasks, represented by priorities TaskPriority::HIGH_IDLE and lower.
+In addition to being invoked only when there is no task with a higher priority,
+pending input in the OS event queue also takes precedence.
+
+
= Lifecycle / thread-safety of Scheduler-based objects =
A scheduler object it thread-safe in the way, that it can be associated to
diff --git a/vcl/source/app/scheduler.cxx b/vcl/source/app/scheduler.cxx
index b325f9238a7d..57b8176521f7 100644
--- a/vcl/source/app/scheduler.cxx
+++ b/vcl/source/app/scheduler.cxx
@@ -430,6 +430,17 @@ bool Scheduler::ProcessTaskScheduling()
<< " of " << nTasks << " tasks" );
UpdateSystemTimer( rSchedCtx, nMinPeriod, true, nTime );
+ // Delay invoking tasks with idle priorities as long as there are user input or repaint events
+ // in the OS event queue. This will often effectively compress such events and repaint only
+ // once at the end, improving performance in cases such as repeated zooming with a complex document.
+ if ( pMostUrgent && pMostUrgent->mePriority >= TaskPriority::HIGH_IDLE
+ && Application::AnyInput( VclInputFlags::MOUSE | VclInputFlags::KEYBOARD | VclInputFlags::PAINT ))
+ {
+ SAL_INFO( "vcl.schedule", tools::Time::GetSystemTicks()
+ << " idle priority task " << pMostUrgent << " delayed, system events pending" );
+ pMostUrgent = nullptr;
+ }
+
if ( pMostUrgent )
{
SAL_INFO( "vcl.schedule", tools::Time::GetSystemTicks() << " "