1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
|
// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_INPUT_MOUSE_WHEEL_EVENT_QUEUE_H_
#define COMPONENTS_INPUT_MOUSE_WHEEL_EVENT_QUEUE_H_
#include <memory>
#include "base/component_export.h"
#include "base/containers/circular_deque.h"
#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "components/input/dispatch_to_renderer_callback.h"
#include "components/input/event_with_latency_info.h"
#include "third_party/blink/public/common/input/web_input_event.h"
#include "third_party/blink/public/mojom/input/input_event_result.mojom-shared.h"
namespace input {
class QueuedWebMouseWheelEvent;
// Interface with which MouseWheelEventQueue can forward mouse wheel events,
// and dispatch mouse wheel event responses.
class COMPONENT_EXPORT(INPUT) MouseWheelEventQueueClient {
public:
using MouseWheelEventHandledCallback = base::OnceCallback<void(
const MouseWheelEventWithLatencyInfo& ack_event,
blink::mojom::InputEventResultSource ack_source,
blink::mojom::InputEventResultState ack_result)>;
virtual ~MouseWheelEventQueueClient() = default;
virtual void SendMouseWheelEventImmediately(
const MouseWheelEventWithLatencyInfo& event,
MouseWheelEventHandledCallback callback,
DispatchToRendererCallback& dispatch_callback) = 0;
virtual void OnMouseWheelEventAck(
const MouseWheelEventWithLatencyInfo& event,
blink::mojom::InputEventResultSource ack_source,
blink::mojom::InputEventResultState ack_result) = 0;
virtual void ForwardGestureEventWithLatencyInfo(
const blink::WebGestureEvent& event,
const ui::LatencyInfo& latency_info) = 0;
virtual bool IsWheelScrollInProgress() = 0;
virtual bool IsAutoscrollInProgress() = 0;
};
// A queue for throttling and coalescing mouse wheel events. This class tracks
// wheel events sent to the renderer and receives their ACKs. If the ACK
// reports the event went unconsumed by the renderer, this class will generate
// a sequence of gesture scroll events.
//
// Within a sequence, wheel events are initially forwarded using a blocking
// dispatch. This means that further wheel events are queued and scroll event
// generation will wait (i.e. block) until the in-flight wheel event is ACKed.
// Once a wheel event goes unconsumed, and scrolling begins, dispatch of
// subsequent wheel events becomes non-blocking. This means the wheel event
// will be ACKed by the browser immediately after being dispatched. This will
// cause scroll events to follow the wheel immediately and new wheel events
// will be dispatched immediately rather than queueing.
class COMPONENT_EXPORT(INPUT) MouseWheelEventQueue {
public:
// The |client| must outlive the MouseWheelEventQueue.
// |IsWheelScrollInProgress| indicates whether mouse wheel events should
// generate Scroll[Begin|Update|End] on unhandled acknowledge events.
MouseWheelEventQueue(MouseWheelEventQueueClient* client);
MouseWheelEventQueue(const MouseWheelEventQueue&) = delete;
MouseWheelEventQueue& operator=(const MouseWheelEventQueue&) = delete;
~MouseWheelEventQueue();
// Adds an event to the queue. The event may be coalesced with previously
// queued events (e.g. consecutive mouse-wheel events can be coalesced into a
// single mouse-wheel event). The event may also be immediately forwarded to
// the renderer (e.g. when there are no other queued mouse-wheel event).
void QueueEvent(const MouseWheelEventWithLatencyInfo& event,
DispatchToRendererCallback& dispatch_callback);
// When GestureScrollBegin is received, and it is a different source
// than mouse wheels terminate the current GestureScroll if there is one.
// When Gesture{ScrollEnd,FlingStart} is received, resume generating
// gestures.
void OnGestureScrollEvent(
const GestureEventWithLatencyInfo& gesture_event);
[[nodiscard]] bool has_pending() const {
return !wheel_queue_.empty() || event_sent_for_gesture_ack_;
}
size_t queued_size() const { return wheel_queue_.size(); }
bool event_in_flight() const {
return event_sent_for_gesture_ack_ != nullptr;
}
private:
// Notifies the queue that a mouse wheel event has been processed by the
// renderer.
void ProcessMouseWheelAck(
const MouseWheelEventWithLatencyInfo& ack_event,
blink::mojom::InputEventResultSource ack_source,
blink::mojom::InputEventResultState ack_result);
void TryForwardNextEventToRenderer();
void SendScrollEnd(blink::WebGestureEvent update_event, bool synthetic);
void SendScrollBegin(const blink::WebGestureEvent& gesture_update,
bool synthetic);
// True if gesture scroll events can be generated for the wheel event sent for
// ack.
bool CanGenerateGestureScroll(
blink::mojom::InputEventResultState ack_result) const;
raw_ptr<MouseWheelEventQueueClient> client_;
base::circular_deque<std::unique_ptr<QueuedWebMouseWheelEvent>> wheel_queue_;
std::unique_ptr<QueuedWebMouseWheelEvent> event_sent_for_gesture_ack_;
// True if the ack for the first wheel event in a scroll sequence is not
// consumed. This lets us to send the rest of the wheel events in the sequence
// as non-blocking.
bool send_wheel_events_async_;
blink::WebGestureDevice scrolling_device_;
};
} // namespace input
#endif // COMPONENTS_INPUT_MOUSE_WHEEL_EVENT_QUEUE_H_
|