diff options
-rw-r--r-- | include/vcl/idle.hxx | 4 | ||||
-rw-r--r-- | include/vcl/task.hxx | 1 | ||||
-rw-r--r-- | vcl/README.scheduler | 15 | ||||
-rw-r--r-- | vcl/source/app/scheduler.cxx | 11 |
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() << " " |