flutter_flutter/shell/common/vsync_waiter.h
liyuqian 9675ca2f6b
Reland "Smooth out iOS irregular input events delivery (#12280)" (#12385)
This reverts commit c2879cae2ee3707ad07af1118bf4862dc1d82bb7.

Additionally, we fix https://github.com/flutter/flutter/issues/40863 by adding a secondary VSYNC callback.

Unit tests are updated to provide VSYNC mocking and check the fix of https://github.com/flutter/flutter/issues/40863.

The root cause of having https://github.com/flutter/flutter/issues/40863 is the false assumption that each input event must trigger a new frame. That was true in the framework PR https://github.com/flutter/flutter/pull/36616 because the input events there are all scrolling move events. When the PR was ported to the engine, we can no longer distinguish different types of events, and tap events may no longer trigger a new frame.

Therefore, this PR directly hooks into the `VsyncWaiter` and uses its (newly added) secondary callback to dispatch the pending input event.
2019-09-30 11:25:50 -07:00

72 lines
2.3 KiB
C++

// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef FLUTTER_SHELL_COMMON_VSYNC_WAITER_H_
#define FLUTTER_SHELL_COMMON_VSYNC_WAITER_H_
#include <functional>
#include <memory>
#include <mutex>
#include "flutter/common/task_runners.h"
#include "flutter/fml/synchronization/thread_annotations.h"
#include "flutter/fml/time/time_point.h"
namespace flutter {
/// Abstract Base Class that represents a platform specific mechanism for
/// getting callbacks when a vsync event happens.
class VsyncWaiter : public std::enable_shared_from_this<VsyncWaiter> {
public:
using Callback = std::function<void(fml::TimePoint frame_start_time,
fml::TimePoint frame_target_time)>;
virtual ~VsyncWaiter();
void AsyncWaitForVsync(Callback callback);
/// Add a secondary callback for the next vsync.
///
/// See also |PointerDataDispatcher::ScheduleSecondaryVsyncCallback|.
void ScheduleSecondaryCallback(fml::closure callback);
static constexpr float kUnknownRefreshRateFPS = 0.0;
// Get the display's maximum refresh rate in the unit of frame per second.
// Return kUnknownRefreshRateFPS if the refresh rate is unknown.
virtual float GetDisplayRefreshRate() const;
protected:
// On some backends, the |FireCallback| needs to be made from a static C
// method.
friend class VsyncWaiterAndroid;
friend class VsyncWaiterEmbedder;
const TaskRunners task_runners_;
VsyncWaiter(TaskRunners task_runners);
// Implementations are meant to override this method and arm their vsync
// latches when in response to this invocation. On vsync, they are meant to
// invoke the |FireCallback| method once (and only once) with the appropriate
// arguments. This method should not block the current thread.
virtual void AwaitVSync() = 0;
void FireCallback(fml::TimePoint frame_start_time,
fml::TimePoint frame_target_time);
private:
std::mutex callback_mutex_;
Callback callback_ FML_GUARDED_BY(callback_mutex_);
std::mutex secondary_callback_mutex_;
fml::closure secondary_callback_ FML_GUARDED_BY(callback_mutex_);
FML_DISALLOW_COPY_AND_ASSIGN(VsyncWaiter);
};
} // namespace flutter
#endif // FLUTTER_SHELL_COMMON_VSYNC_WAITER_H_