| Index: ui/events/blink/input_handler_proxy.cc
|
| diff --git a/ui/events/blink/input_handler_proxy.cc b/ui/events/blink/input_handler_proxy.cc
|
| index 40d1415d9e9ec0a9493b194486da549f9aed5a8c..ae52f930a7bb120dafa969c6e244855a4024e0e6 100644
|
| --- a/ui/events/blink/input_handler_proxy.cc
|
| +++ b/ui/events/blink/input_handler_proxy.cc
|
| @@ -12,13 +12,18 @@
|
| #include "base/command_line.h"
|
| #include "base/location.h"
|
| #include "base/logging.h"
|
| +#include "base/memory/ptr_util.h"
|
| #include "base/metrics/histogram_macros.h"
|
| #include "base/single_thread_task_runner.h"
|
| #include "base/threading/thread_task_runner_handle.h"
|
| +#include "base/time/default_tick_clock.h"
|
| #include "base/trace_event/trace_event.h"
|
| #include "cc/input/main_thread_scrolling_reason.h"
|
| #include "third_party/WebKit/public/platform/WebInputEvent.h"
|
| +#include "ui/events/blink/blink_event_util.h"
|
| +#include "ui/events/blink/compositor_thread_event_queue.h"
|
| #include "ui/events/blink/did_overscroll_params.h"
|
| +#include "ui/events/blink/event_with_callback.h"
|
| #include "ui/events/blink/input_handler_proxy_client.h"
|
| #include "ui/events/blink/input_scroll_elasticity_controller.h"
|
| #include "ui/events/blink/web_input_event_traits.h"
|
| @@ -62,6 +67,8 @@ const double kMinBoostTouchScrollSpeedSquare = 150 * 150.;
|
| // slightly increased value to accomodate small IPC message delays.
|
| const double kFlingBoostTimeoutDelaySeconds = 0.05;
|
|
|
| +const size_t kTenSeconds = 10 * 1000 * 1000;
|
| +
|
| gfx::Vector2dF ToClientScrollIncrement(const WebFloatSize& increment) {
|
| return gfx::Vector2dF(-increment.width, -increment.height);
|
| }
|
| @@ -242,7 +249,9 @@ InputHandlerProxy::InputHandlerProxy(cc::InputHandler* input_handler,
|
| smooth_scroll_enabled_(false),
|
| uma_latency_reporting_enabled_(base::TimeTicks::IsHighResolution()),
|
| touch_start_result_(kEventDispositionUndefined),
|
| - current_overscroll_params_(nullptr) {
|
| + current_overscroll_params_(nullptr),
|
| + has_ongoing_compositor_scroll_pinch_(false),
|
| + tick_clock_(base::MakeUnique<base::DefaultTickClock>()) {
|
| DCHECK(client);
|
| input_handler_->BindToClient(this);
|
| cc::ScrollElasticityHelper* scroll_elasticity_helper =
|
| @@ -251,6 +260,10 @@ InputHandlerProxy::InputHandlerProxy(cc::InputHandler* input_handler,
|
| scroll_elasticity_controller_.reset(
|
| new InputScrollElasticityController(scroll_elasticity_helper));
|
| }
|
| + compositor_event_queue_ =
|
| + base::FeatureList::IsEnabled(features::kVsyncAlignedInputEvents)
|
| + ? base::MakeUnique<CompositorThreadEventQueue>()
|
| + : nullptr;
|
| }
|
|
|
| InputHandlerProxy::~InputHandlerProxy() {}
|
| @@ -275,15 +288,102 @@ void InputHandlerProxy::HandleInputEventWithLatencyInfo(
|
| TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT,
|
| "step", "HandleInputEventImpl");
|
|
|
| - ui::LatencyInfo monitored_latency_info = latency_info;
|
| + std::unique_ptr<EventWithCallback> event_with_callback =
|
| + base::MakeUnique<EventWithCallback>(std::move(event), latency_info,
|
| + tick_clock_->NowTicks(), callback);
|
| +
|
| + // Note: Other input can race ahead of gesture input as they don't have to go
|
| + // through the queue, but we believe it's OK to do so.
|
| + if (!compositor_event_queue_ ||
|
| + !IsGestureScollOrPinch(event_with_callback->event().type)) {
|
| + DispatchSingleInputEvent(std::move(event_with_callback),
|
| + tick_clock_->NowTicks());
|
| + return;
|
| + }
|
| +
|
| + if (has_ongoing_compositor_scroll_pinch_) {
|
| + bool needs_animate_input = compositor_event_queue_->empty();
|
| + compositor_event_queue_->Queue(std::move(event_with_callback),
|
| + tick_clock_->NowTicks());
|
| + if (needs_animate_input)
|
| + input_handler_->SetNeedsAnimateInput();
|
| + return;
|
| + }
|
| +
|
| + // We have to dispatch the event to know whether the gesture sequence will be
|
| + // handled by the compositor or not.
|
| + DispatchSingleInputEvent(std::move(event_with_callback),
|
| + tick_clock_->NowTicks());
|
| +}
|
| +
|
| +void InputHandlerProxy::DispatchSingleInputEvent(
|
| + std::unique_ptr<EventWithCallback> event_with_callback,
|
| + const base::TimeTicks now) {
|
| + if (compositor_event_queue_ &&
|
| + IsGestureScollOrPinch(event_with_callback->event().type)) {
|
| + // Report the coalesced count only for continuous events to avoid the noise
|
| + // from non-continuous events.
|
| + if (IsContinuousGestureEvent(event_with_callback->event().type)) {
|
| + UMA_HISTOGRAM_CUSTOM_COUNTS(
|
| + "Event.CompositorThreadEventQueue.Continuous.HeadQueueingTime",
|
| + (now - event_with_callback->creation_timestamp()).InMicroseconds(), 1,
|
| + kTenSeconds, 50);
|
| +
|
| + UMA_HISTOGRAM_CUSTOM_COUNTS(
|
| + "Event.CompositorThreadEventQueue.Continuous.TailQueueingTime",
|
| + (now - event_with_callback->last_coalesced_timestamp())
|
| + .InMicroseconds(),
|
| + 1, kTenSeconds, 50);
|
| +
|
| + UMA_HISTOGRAM_COUNTS_1000(
|
| + "Event.CompositorThreadEventQueue.CoalescedCount",
|
| + static_cast<int>(event_with_callback->coalesced_count()));
|
| + } else {
|
| + UMA_HISTOGRAM_CUSTOM_COUNTS(
|
| + "Event.CompositorThreadEventQueue.NonContinuous.QueueingTime",
|
| + (now - event_with_callback->creation_timestamp()).InMicroseconds(), 1,
|
| + kTenSeconds, 50);
|
| + }
|
| + }
|
| +
|
| + ui::LatencyInfo monitored_latency_info = event_with_callback->latency_info();
|
| std::unique_ptr<cc::SwapPromiseMonitor> latency_info_swap_promise_monitor =
|
| input_handler_->CreateLatencyInfoSwapPromiseMonitor(
|
| &monitored_latency_info);
|
|
|
| current_overscroll_params_.reset();
|
| - InputHandlerProxy::EventDisposition disposition = HandleInputEvent(*event);
|
| - callback.Run(disposition, std::move(event), monitored_latency_info,
|
| - std::move(current_overscroll_params_));
|
| + InputHandlerProxy::EventDisposition disposition =
|
| + HandleInputEvent(event_with_callback->event());
|
| +
|
| + switch (event_with_callback->event().type) {
|
| + case blink::WebGestureEvent::GestureScrollBegin:
|
| + case blink::WebGestureEvent::GesturePinchBegin:
|
| + case blink::WebGestureEvent::GestureScrollUpdate:
|
| + case blink::WebGestureEvent::GesturePinchUpdate:
|
| + has_ongoing_compositor_scroll_pinch_ = disposition == DID_HANDLE;
|
| + break;
|
| +
|
| + case blink::WebGestureEvent::GestureScrollEnd:
|
| + case blink::WebGestureEvent::GesturePinchEnd:
|
| + has_ongoing_compositor_scroll_pinch_ = false;
|
| + break;
|
| + default:
|
| + break;
|
| + }
|
| +
|
| + // Will run callback for every original events.
|
| + event_with_callback->RunCallbacks(disposition, monitored_latency_info,
|
| + std::move(current_overscroll_params_));
|
| +}
|
| +
|
| +void InputHandlerProxy::DispatchQueuedInputEvents() {
|
| + if (!compositor_event_queue_)
|
| + return;
|
| +
|
| + // Calling |NowTicks()| is expensive so we only want to do it once.
|
| + base::TimeTicks now = tick_clock_->NowTicks();
|
| + while (!compositor_event_queue_->empty())
|
| + DispatchSingleInputEvent(compositor_event_queue_->Pop(), now);
|
| }
|
|
|
| InputHandlerProxy::EventDisposition InputHandlerProxy::HandleInputEvent(
|
| @@ -1138,6 +1238,10 @@ void InputHandlerProxy::UpdateRootLayerStateForSynchronousInputHandler(
|
| }
|
| }
|
|
|
| +void InputHandlerProxy::DeliverInputForBeginFrame() {
|
| + DispatchQueuedInputEvents();
|
| +}
|
| +
|
| void InputHandlerProxy::SetOnlySynchronouslyAnimateRootFlings(
|
| SynchronousInputHandler* synchronous_input_handler) {
|
| allow_root_animate_ = !synchronous_input_handler;
|
| @@ -1422,4 +1526,9 @@ void InputHandlerProxy::HandleScrollElasticityOverscroll(
|
| scroll_result));
|
| }
|
|
|
| +void InputHandlerProxy::SetTickClockForTesting(
|
| + std::unique_ptr<base::TickClock> tick_clock) {
|
| + tick_clock_ = std::move(tick_clock);
|
| +}
|
| +
|
| } // namespace ui
|
|
|