Index: content/browser/renderer_host/input/wheel_event_queue.cc |
diff --git a/content/browser/renderer_host/input/wheel_event_queue.cc b/content/browser/renderer_host/input/wheel_event_queue.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..2d3131e7c053979ca4c041d6d0cbc0a26ac06c51 |
--- /dev/null |
+++ b/content/browser/renderer_host/input/wheel_event_queue.cc |
@@ -0,0 +1,111 @@ |
+ |
+// Copyright 2015 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "content/browser/renderer_host/input/wheel_event_queue.h" |
+ |
+#include "base/auto_reset.h" |
+#include "base/metrics/histogram.h" |
+ |
+namespace content { |
+ |
+WheelEventQueue::WheelEventQueue(WheelEventQueueClient* client, |
+ bool buffer_until_flush) |
+ : client_(client), |
+ buffer_until_flush_(buffer_until_flush), |
+ mouse_wheel_pending_(false), |
+ flushing_(false) {} |
+ |
+WheelEventQueue::~WheelEventQueue() {} |
+ |
+void WheelEventQueue::QueueEvent( |
+ const MouseWheelEventWithLatencyInfo& wheel_event) { |
+ if (mouse_wheel_pending_ || buffer_until_flush_) { |
+ // If there's already a mouse wheel event waiting to be sent to the |
+ // renderer, add the new deltas to that event. Not doing so (e.g., by |
+ // dropping the old event, as for mouse moves) results in very slow |
+ // scrolling on the Mac. |
+ DCHECK_IMPLIES(wheel_event.event.hasPreciseScrollingDeltas, |
+ wheel_event.event.canScroll); |
+ if (!coalesced_wheel_events_.empty() && |
+ coalesced_wheel_events_.back().CanCoalesceWith(wheel_event)) { |
+ coalesced_wheel_events_.back().CoalesceWith(wheel_event); |
+ TRACE_EVENT_INSTANT2("input", "InputRouterImpl::CoalescedWheelEvent", |
+ TRACE_EVENT_SCOPE_THREAD, "total_dx", |
+ coalesced_wheel_events_.back().event.deltaX, |
+ "total_dy", |
+ coalesced_wheel_events_.back().event.deltaY); |
+ } else { |
+ coalesced_wheel_events_.push_back(wheel_event); |
+ } |
+ if (buffer_until_flush_) |
+ client_->SetNeedsFlush(); |
+ return; |
+ } |
+ |
+ SendEvent(wheel_event); |
+} |
+ |
+void WheelEventQueue::ProcessWheelAck(InputEventAckState ack_result, |
+ const ui::LatencyInfo& latency) { |
+ DCHECK(mouse_wheel_pending_); |
+ // TODO(miletus): Add renderer side latency to each uncoalesced mouse |
+ // wheel event and add terminal component to each of them. |
+ current_wheel_event_.latency.AddNewLatencyFrom(latency); |
+ |
+ // Process the unhandled wheel event here before calling |SendEvent()| |
+ // since it will mutate current_wheel_event_. |
+ client_->OnWheelEventAck(current_wheel_event_, ack_result); |
+ |
+ // Mark the wheel event complete only after the ACKs have been handled above. |
+ // ACKing the event could cause another event to be enqueued, and that |
+ // event's sending should be deferred. |
+ mouse_wheel_pending_ = false; |
+ |
+ // Send the next (coalesced or synthetic) mouse wheel event. |
+ if (coalesced_wheel_events_.empty()) |
+ return; |
+ |
+ if (buffer_until_flush_ && !flushing_) { |
+ client_->SetNeedsFlush(); |
+ return; |
+ } |
+ |
+ MouseWheelEventWithLatencyInfo next_wheel_event = |
+ coalesced_wheel_events_.front(); |
+ coalesced_wheel_events_.pop_front(); |
+ SendEvent(next_wheel_event); |
+} |
+ |
+void WheelEventQueue::Flush() { |
+ if (!buffer_until_flush_) |
+ return; |
+ |
+ if (mouse_wheel_pending_) |
+ return; |
+ |
+ if (coalesced_wheel_events_.empty()) |
+ return; |
+ |
+ base::AutoReset<bool> flushing(&flushing_, false); |
+ MouseWheelEventWithLatencyInfo next_wheel_event = |
+ coalesced_wheel_events_.front(); |
+ coalesced_wheel_events_.pop_front(); |
+ SendEvent(next_wheel_event); |
+ DCHECK(mouse_wheel_pending_); |
+} |
+ |
+void WheelEventQueue::SendEvent( |
+ const MouseWheelEventWithLatencyInfo& wheel_event) { |
+ DCHECK(!mouse_wheel_pending_); |
+ mouse_wheel_pending_ = true; |
+ current_wheel_event_ = wheel_event; |
+ |
+ LOCAL_HISTOGRAM_COUNTS_100("Renderer.WheelQueueSize", |
+ coalesced_wheel_events_.size()); |
+ |
+ client_->SendWheelEventImmediately(wheel_event); |
+} |
+ |
+} // namespace content |