forked from amazingfate/loongoffice
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 06d731428ef6cf93c7333e8228b, and it was also again done in 87199d3829257420429057336283, but apparently these have been removed. There was d348035a60361a1b9ba9e '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>
106 lines
3.9 KiB
C++
106 lines
3.9 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_TASK_HXX
|
|
#define INCLUDED_VCL_TASK_HXX
|
|
|
|
#include <vcl/dllapi.h>
|
|
|
|
struct ImplSchedulerData;
|
|
|
|
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
|
|
POST_PAINT, ///< Everything running directly after painting
|
|
DEFAULT_IDLE, ///< Default idle priority
|
|
LOWEST ///< Low, very idle cleanup tasks
|
|
};
|
|
|
|
#define PRIO_COUNT (static_cast<int>(TaskPriority::LOWEST) + 1)
|
|
|
|
class VCL_DLLPUBLIC Task
|
|
{
|
|
friend class Scheduler;
|
|
friend struct ImplSchedulerData;
|
|
|
|
ImplSchedulerData *mpSchedulerData; ///< Pointer to the element in scheduler list
|
|
const char *mpDebugName; ///< Useful for debugging
|
|
TaskPriority mePriority; ///< Task priority
|
|
bool mbActive; ///< Currently in the scheduler
|
|
bool mbStatic; ///< Is a static object
|
|
|
|
protected:
|
|
static void StartTimer( sal_uInt64 nMS );
|
|
|
|
const ImplSchedulerData* GetSchedulerData() const { return mpSchedulerData; }
|
|
|
|
virtual void SetDeletionFlags();
|
|
|
|
/**
|
|
* How long (in MS) until the Task is ready to be dispatched?
|
|
*
|
|
* Simply return Scheduler::ImmediateTimeoutMs if you're ready, like an
|
|
* Idle. If you have to return Scheduler::InfiniteTimeoutMs, you probably
|
|
* need another mechanism to wake up the Scheduler or rely on other
|
|
* Tasks to be scheduled, or simply use a polling Timer.
|
|
*
|
|
* @param nTimeNow the current time
|
|
* @return the sleep time of the Task to become ready
|
|
*/
|
|
virtual sal_uInt64 UpdateMinPeriod( sal_uInt64 nTimeNow ) const = 0;
|
|
|
|
public:
|
|
Task( const char *pDebugName );
|
|
Task( const Task& rTask );
|
|
virtual ~Task() COVERITY_NOEXCEPT_FALSE;
|
|
Task& operator=( const Task& rTask );
|
|
|
|
void SetPriority(TaskPriority ePriority);
|
|
TaskPriority GetPriority() const { return mePriority; }
|
|
|
|
void SetDebugName( const char *pDebugName ) { mpDebugName = pDebugName; }
|
|
const char *GetDebugName() const { return mpDebugName; }
|
|
|
|
// Call handler
|
|
virtual void Invoke() = 0;
|
|
|
|
virtual void Start();
|
|
void Stop();
|
|
|
|
bool IsActive() const { return mbActive; }
|
|
|
|
/**
|
|
* This function must be called for static tasks, so the Task destructor
|
|
* ignores the scheduler mutex, as it may not be available anymore.
|
|
* The cleanup is still correct, as it has already happened in
|
|
* DeInitScheduler call well before the static destructor calls.
|
|
*/
|
|
void SetStatic() { mbStatic = true; }
|
|
bool IsStatic() const { return mbStatic; }
|
|
};
|
|
|
|
#endif // INCLUDED_VCL_TASK_HXX
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|