Chromium Code Reviews| 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 18baa4cf33d4dd8cbcc16699b89b28e4d6451d49..fa8ac9246b1b7ecbce65bbf67b808edec9480e3f 100644 |
| --- a/ui/events/blink/input_handler_proxy.cc |
| +++ b/ui/events/blink/input_handler_proxy.cc |
| @@ -12,13 +12,17 @@ |
| #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/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 +66,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); |
| } |
| @@ -223,6 +229,9 @@ cc::InputHandler::ScrollInputType GestureScrollInputType( |
| namespace ui { |
| +std::unique_ptr<base::TimeTicks> InputHandlerProxy::testing_timestamp_now_ = |
| + nullptr; |
| + |
| InputHandlerProxy::InputHandlerProxy(cc::InputHandler* input_handler, |
| InputHandlerProxyClient* client) |
| : client_(client), |
| @@ -242,7 +251,10 @@ 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), |
| + compositor_event_queue_enabled_( |
| + base::FeatureList::IsEnabled(features::kVsyncAlignedInputEvents)) { |
| DCHECK(client); |
| input_handler_->BindToClient(this); |
| cc::ScrollElasticityHelper* scroll_elasticity_helper = |
| @@ -251,6 +263,9 @@ InputHandlerProxy::InputHandlerProxy(cc::InputHandler* input_handler, |
| scroll_elasticity_controller_.reset( |
| new InputScrollElasticityController(scroll_elasticity_helper)); |
| } |
| + if (compositor_event_queue_enabled_) { |
| + event_queue_ = base::MakeUnique<CompositorThreadEventQueue>(); |
|
dtapuska
2016/11/09 21:28:05
no scope brackets
chongz
2016/11/11 21:52:04
Done.
|
| + } |
| } |
| InputHandlerProxy::~InputHandlerProxy() {} |
| @@ -275,15 +290,99 @@ 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, |
| + callback); |
| + |
| + if (!compositor_event_queue_enabled_ || |
| + !IsGestureScollOrPinch(event_with_callback->event().type)) { |
| + DispatchSingleInputEvent(std::move(event_with_callback)); |
| + return; |
| + } |
| + |
| + if (has_ongoing_compositor_scroll_pinch_) { |
| + bool needs_animate_input = event_queue_->empty(); |
| + event_queue_->Queue(std::move(event_with_callback)); |
| + 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)); |
| +} |
| + |
| +void InputHandlerProxy::DispatchSingleInputEvent( |
| + std::unique_ptr<EventWithCallback> event_with_callback) { |
| + if (compositor_event_queue_enabled_ && |
| + IsGestureScollOrPinch(event_with_callback->event().type)) { |
| + // Report the coalesced count only for continuous events to avoid the noise |
| + // from non-continuous events. |
| + base::TimeTicks now = testing_timestamp_now_ ? *testing_timestamp_now_ |
| + : base::TimeTicks::Now(); |
| + if (IsContinuousGestureEvent(event_with_callback->event().type)) { |
| + UMA_HISTOGRAM_CUSTOM_COUNTS( |
| + "Event.CompositorThreadEventQueue.Continuous.HeadQueueingTime", |
| + (now - event_with_callback->creationTimestamp()).InMicroseconds(), 1, |
| + kTenSeconds, 50); |
| + |
| + UMA_HISTOGRAM_CUSTOM_COUNTS( |
| + "Event.CompositorThreadEventQueue.Continuous.TailQueueingTime", |
| + (now - event_with_callback->lastCoalescedTimestamp()) |
| + .InMicroseconds(), |
| + 1, kTenSeconds, 50); |
| + |
| + UMA_HISTOGRAM_COUNTS_1000( |
| + "Event.CompositorThreadEventQueue.CoalescedCount", |
| + static_cast<int>(event_with_callback->coalescedCount())); |
| + } else { |
| + UMA_HISTOGRAM_CUSTOM_COUNTS( |
| + "Event.CompositorThreadEventQueue.NonContinuous.QueueingTime", |
| + (now - event_with_callback->creationTimestamp()).InMicroseconds(), 1, |
| + kTenSeconds, 50); |
| + } |
| + } |
| + |
| + ui::LatencyInfo monitored_latency_info = event_with_callback->latencyInfo(); |
| 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: |
| + has_ongoing_compositor_scroll_pinch_ = disposition == DID_HANDLE; |
| + break; |
| + |
| + case blink::WebGestureEvent::GestureScrollUpdate: |
|
dtapuska
2016/11/09 21:28:05
Can this be combined with the above cases?
chongz
2016/11/11 21:52:04
Done.
|
| + 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_enabled_) |
| + return; |
| + |
| + while (!event_queue_->empty()) |
| + DispatchSingleInputEvent(event_queue_->Pop()); |
| } |
| InputHandlerProxy::EventDisposition InputHandlerProxy::HandleInputEvent( |
| @@ -1138,6 +1237,10 @@ void InputHandlerProxy::UpdateRootLayerStateForSynchronousInputHandler( |
| } |
| } |
| +void InputHandlerProxy::DeliverInputForBeginFrame() { |
| + DispatchQueuedInputEvents(); |
| +} |
| + |
| void InputHandlerProxy::SetOnlySynchronouslyAnimateRootFlings( |
| SynchronousInputHandler* synchronous_input_handler) { |
| allow_root_animate_ = !synchronous_input_handler; |