Flutter Engine
flutter::SmoothPointerDataDispatcher Class Reference

#include <pointer_data_dispatcher.h>

Inheritance diagram for flutter::SmoothPointerDataDispatcher:
flutter::DefaultPointerDataDispatcher flutter::PointerDataDispatcher

Public Member Functions

 SmoothPointerDataDispatcher (Delegate &delegate)
void DispatchPacket (std::unique_ptr< PointerDataPacket > packet, uint64_t trace_flow_id) override
 Signal that PlatformView has a packet to be dispatched. More...
virtual ~SmoothPointerDataDispatcher ()
- Public Member Functions inherited from flutter::DefaultPointerDataDispatcher
 DefaultPointerDataDispatcher (Delegate &delegate)
virtual ~DefaultPointerDataDispatcher ()
- Public Member Functions inherited from flutter::PointerDataDispatcher
virtual ~PointerDataDispatcher ()
 Default destructor. More...

Additional Inherited Members

- Protected Member Functions inherited from flutter::DefaultPointerDataDispatcher
 FML_DISALLOW_COPY_AND_ASSIGN (DefaultPointerDataDispatcher)
- Protected Attributes inherited from flutter::DefaultPointerDataDispatcher

Detailed Description

A dispatcher that may temporarily store and defer the last received PointerDataPacket if multiple packets are received in one VSYNC. The deferred packet will be sent in the next vsync in order to smooth out the events. This filters out irregular input events delivery to provide a smooth scroll on iPhone X/Xs.

It works as follows:

When DispatchPacket is called while a preivous pointer data dispatch is still in progress (its frame isn't finished yet), it means that an input event is delivered to us too fast. That potentially means a later event will be too late which could cause the missing of a frame. Hence we'll cache it in pending_packet_ for the next frame to smooth it out.

If the input event is sent to us regularly at the same rate of VSYNC (say at 60Hz), this would be identical to DefaultPointerDataDispatcher where runtime_controller_->DispatchPointerDataPacket is always called right away. That's because is_pointer_data_in_progress_ will always be false when DispatchPacket is called since it will be cleared by the end of a frame through ScheduleSecondaryVsyncCallback. This is the case for all Android/iOS devices before iPhone X/XS.

If the input event is irregular, but with a random latency of no more than one frame, this would guarantee that we'll miss at most 1 frame. Without this, we could miss half of the frames.

If the input event is delivered at a higher rate than that of VSYNC, this would at most add a latency of one event delivery. For example, if the input event is delivered at 120Hz (this is only true for iPad pro, not even iPhone X), this may delay the handling of an input event by 8ms.

The assumption of this solution is that the sampling itself is still regular. Only the event delivery is allowed to be irregular. So far this assumption seems to hold on all devices. If it's changed in the future, we'll need a different solution.

See also input_events_unittests.cc where we test all our claims above.

Definition at line 140 of file pointer_data_dispatcher.h.

Constructor & Destructor Documentation

◆ SmoothPointerDataDispatcher()

flutter::SmoothPointerDataDispatcher::SmoothPointerDataDispatcher ( Delegate delegate)

Definition at line 14 of file pointer_data_dispatcher.cc.

References ~SmoothPointerDataDispatcher().

15  : DefaultPointerDataDispatcher(delegate), weak_factory_(this) {}

◆ ~SmoothPointerDataDispatcher()

flutter::SmoothPointerDataDispatcher::~SmoothPointerDataDispatcher ( )

Member Function Documentation

◆ DispatchPacket()

void flutter::SmoothPointerDataDispatcher::DispatchPacket ( std::unique_ptr< PointerDataPacket packet,
uint64_t  trace_flow_id 

Signal that PlatformView has a packet to be dispatched.

[in]packetThe PointerDataPacket to be dispatched.
[in]trace_flow_idThe id for Animator::EnqueueTraceFlowId.

Reimplemented from flutter::DefaultPointerDataDispatcher.

Definition at line 26 of file pointer_data_dispatcher.cc.

References flutter::DefaultPointerDataDispatcher::delegate_, flutter::DefaultPointerDataDispatcher::DispatchPacket(), FML_DCHECK, flutter::PointerDataDispatcher::Delegate::ScheduleSecondaryVsyncCallback(), TRACE_EVENT0, and TRACE_FLOW_STEP.

28  {
29  TRACE_EVENT0("flutter", "SmoothPointerDataDispatcher::DispatchPacket");
30  TRACE_FLOW_STEP("flutter", "PointerEvent", trace_flow_id);
32  if (is_pointer_data_in_progress_) {
33  if (pending_packet_ != nullptr) {
34  DispatchPendingPacket();
35  }
36  pending_packet_ = std::move(packet);
37  pending_trace_flow_id_ = trace_flow_id;
38  } else {
39  FML_DCHECK(pending_packet_ == nullptr);
41  trace_flow_id);
42  }
43  is_pointer_data_in_progress_ = true;
44  ScheduleSecondaryVsyncCallback();
45 }
#define TRACE_EVENT0(category_group, name)
Definition: trace_event.h:90
#define TRACE_FLOW_STEP(category, name, id)
Definition: trace_event.h:133
#define FML_DCHECK(condition)
Definition: logging.h:86
void DispatchPacket(std::unique_ptr< PointerDataPacket > packet, uint64_t trace_flow_id) override
Signal that PlatformView has a packet to be dispatched.

The documentation for this class was generated from the following files: