| 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
|
|
|