office-gobmx/include/vcl/idle.hxx
Luboš Luňák d3b498cc47 invoke idle priority timers only when actually idle
The 'Idle' timers are misnamed. They are zero-timeout times, i.e.
they are invoked immediately after returning to the main loop.
But that does not necessarily mean they are invoked when idle,
there may be e.g. user input pending in the system event queue.
In fact, LO events are processed before system events, which means
that 'Idle' timers are normally processed before user input.

Besides being confused, this also leads to poor performance in some
cases, such as when using mouse wheel to zoom in a large document.
This results in several mouse wheel events, each of which will
result in adjusting the zoom and that causing a repaint. Repaints
are internally handled using a TaskPriority::REPAINT 'Idle',
and so what happens is zoom->repaint->zoom->repaint->zoom->repaint
instead of the more efficient zoom->zoom->zoom->repaint.

This change (besides trying to clarify the confusion in the docs)
delays invoking tasks with priorities TaskPriority::HIGH_IDLE
and lower if there is user input or repaint events in the OS queue.
That means that tasks using idle priorities actually will be invoked
only when idle (barring background threads etc.).

I'm reasonably certain this is a safe change, there's no guarantee
when exactly tasks will be invoked (e.g. other tasks with a higher
priority go first) and explicitly specifying such a priority means
asking for it.

I already implemented this once in 06d731428e,
and it was also again done in 87199d3829, but
apparently these have been removed. There was d348035a60
'Drop special idle handling' with the reasoning that 'Idles are just
instant timers'. Which strictly technically speaking is true due to
'Idle' being a misnomer, but the point is that some idles should be
actual idles and that's why they need to be handled specially.

Change-Id: I36c2b02a80ae7e1476b731f878d9b28aa87975f4
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/110538
Tested-by: Jenkins
Reviewed-by: Luboš Luňák <l.lunak@collabora.com>
2021-02-07 18:57:30 +01:00

70 lines
2.2 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#ifndef INCLUDED_VCL_IDLE_HXX
#define INCLUDED_VCL_IDLE_HXX
#include <vcl/timer.hxx>
/**
* 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
{
private:
// Delete all timeout specific functions, we don't want in an Idle
void SetTimeout( sal_uInt64 nTimeoutMs ) = delete;
sal_uInt64 GetTimeout() const = delete;
protected:
virtual sal_uInt64 UpdateMinPeriod( sal_uInt64 nTimeNow ) const override;
Idle( bool bAuto, const char *pDebugName );
public:
Idle( const char *pDebugName = nullptr );
virtual void Start() override;
};
/**
* An auto-idle is long running task processing small chunks of data, which
* is re-scheduled multiple times.
*
* Remember to stop the Idle when finished, as it would otherwise busy loop the CPU!
*
* It probably makes sense to re-implement ReadyForSchedule and UpdateMinPeriod,
* in case there is a quick check and it can otherwise sleep.
*/
class VCL_DLLPUBLIC AutoIdle : public Idle
{
public:
AutoIdle( const char *pDebugName );
};
#endif // INCLUDED_VCL_IDLE_HXX
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */