Source code

Revision control

Other Tools

1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
3
/* This Source Code Form is subject to the terms of the Mozilla Public
4
* License, v. 2.0. If a copy of the MPL was not distributed with this
5
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
#ifndef mozilla_layers_InputQueue_h
8
#define mozilla_layers_InputQueue_h
9
10
#include "APZUtils.h"
11
#include "DragTracker.h"
12
#include "InputData.h"
13
#include "mozilla/EventForwards.h"
14
#include "mozilla/layers/TouchCounter.h"
15
#include "mozilla/RefPtr.h"
16
#include "mozilla/UniquePtr.h"
17
#include "nsTArray.h"
18
19
namespace mozilla {
20
21
class InputData;
22
class MultiTouchInput;
23
class ScrollWheelInput;
24
25
namespace layers {
26
27
class AsyncPanZoomController;
28
class InputBlockState;
29
class CancelableBlockState;
30
class TouchBlockState;
31
class WheelBlockState;
32
class DragBlockState;
33
class PanGestureBlockState;
34
class KeyboardBlockState;
35
class AsyncDragMetrics;
36
class QueuedInput;
37
38
/**
39
* This class stores incoming input events, associated with "input blocks",
40
* until they are ready for handling.
41
*/
42
class InputQueue {
43
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(InputQueue)
44
45
public:
46
InputQueue();
47
48
/**
49
* Notifies the InputQueue of a new incoming input event. The APZC that the
50
* input event was targeted to should be provided in the |aTarget| parameter.
51
* See the documentation on APZCTreeManager::ReceiveInputEvent for info on
52
* return values from this function, including |aOutInputBlockId|.
53
*/
54
nsEventStatus ReceiveInputEvent(
55
const RefPtr<AsyncPanZoomController>& aTarget,
56
TargetConfirmationFlags aFlags, const InputData& aEvent,
57
uint64_t* aOutInputBlockId,
58
const Maybe<nsTArray<TouchBehaviorFlags>>& aTouchBehaviors = Nothing());
59
/**
60
* This function should be invoked to notify the InputQueue when web content
61
* decides whether or not it wants to cancel a block of events. The block
62
* id to which this applies should be provided in |aInputBlockId|.
63
*/
64
void ContentReceivedInputBlock(uint64_t aInputBlockId, bool aPreventDefault);
65
/**
66
* This function should be invoked to notify the InputQueue once the target
67
* APZC to handle an input block has been confirmed. In practice this should
68
* generally be decidable upon receipt of the input event, but in some cases
69
* we may need to query the layout engine to know for sure. The input block
70
* this applies to should be specified via the |aInputBlockId| parameter.
71
*/
72
void SetConfirmedTargetApzc(
73
uint64_t aInputBlockId,
74
const RefPtr<AsyncPanZoomController>& aTargetApzc);
75
/**
76
* This function is invoked to confirm that the drag block should be handled
77
* by the APZ.
78
*/
79
void ConfirmDragBlock(uint64_t aInputBlockId,
80
const RefPtr<AsyncPanZoomController>& aTargetApzc,
81
const AsyncDragMetrics& aDragMetrics);
82
/**
83
* This function should be invoked to notify the InputQueue of the touch-
84
* action properties for the different touch points in an input block. The
85
* input block this applies to should be specified by the |aInputBlockId|
86
* parameter. If touch-action is not enabled on the platform, this function
87
* does nothing and need not be called.
88
*/
89
void SetAllowedTouchBehavior(uint64_t aInputBlockId,
90
const nsTArray<TouchBehaviorFlags>& aBehaviors);
91
/**
92
* Adds a new touch block at the end of the input queue that has the same
93
* allowed touch behaviour flags as the the touch block currently being
94
* processed. This should only be called when processing of a touch block
95
* triggers the creation of a new touch block. Returns the input block id
96
* of the the newly-created block.
97
*/
98
uint64_t InjectNewTouchBlock(AsyncPanZoomController* aTarget);
99
/**
100
* Returns the pending input block at the head of the queue, if there is one.
101
* This may return null if there all input events have been processed.
102
*/
103
InputBlockState* GetCurrentBlock() const;
104
/*
105
* Returns the current pending input block as a specific kind of block. If
106
* GetCurrentBlock() returns null, these functions additionally check the
107
* mActiveXXXBlock field of the corresponding input type to see if there is
108
* a depleted but still active input block, and returns that if found. These
109
* functions may return null if no block is found.
110
*/
111
TouchBlockState* GetCurrentTouchBlock() const;
112
WheelBlockState* GetCurrentWheelBlock() const;
113
DragBlockState* GetCurrentDragBlock() const;
114
PanGestureBlockState* GetCurrentPanGestureBlock() const;
115
KeyboardBlockState* GetCurrentKeyboardBlock() const;
116
/**
117
* Returns true iff the pending block at the head of the queue is a touch
118
* block and is ready for handling.
119
*/
120
bool HasReadyTouchBlock() const;
121
/**
122
* If there is an active wheel transaction, returns the WheelBlockState
123
* representing the transaction. Otherwise, returns null. "Active" in this
124
* function name is the same kind of "active" as in mActiveWheelBlock - that
125
* is, new incoming wheel events will go into the "active" block.
126
*/
127
WheelBlockState* GetActiveWheelTransaction() const;
128
/**
129
* Remove all input blocks from the input queue.
130
*/
131
void Clear();
132
/**
133
* Whether the current pending block allows scroll handoff.
134
*/
135
bool AllowScrollHandoff() const;
136
/**
137
* If there is currently a drag in progress, return whether or not it was
138
* targeted at a scrollbar. If the drag was newly-created and doesn't know,
139
* use the provided |aOnScrollbar| to populate that information.
140
*/
141
bool IsDragOnScrollbar(bool aOnScrollbar);
142
143
private:
144
~InputQueue();
145
146
// RAII class for automatically running a timeout task that may
147
// need to be run immediately after an event has been queued.
148
class AutoRunImmediateTimeout final {
149
public:
150
explicit AutoRunImmediateTimeout(InputQueue* aQueue);
151
~AutoRunImmediateTimeout();
152
153
private:
154
InputQueue* mQueue;
155
};
156
157
TouchBlockState* StartNewTouchBlock(
158
const RefPtr<AsyncPanZoomController>& aTarget,
159
TargetConfirmationFlags aFlags, bool aCopyPropertiesFromCurrent);
160
161
/**
162
* If animations are present for the current pending input block, cancel
163
* them as soon as possible.
164
*/
165
void CancelAnimationsForNewBlock(InputBlockState* aBlock,
166
CancelAnimationFlags aExtraFlags = Default);
167
168
/**
169
* If we need to wait for a content response, schedule that now.
170
*/
171
void MaybeRequestContentResponse(
172
const RefPtr<AsyncPanZoomController>& aTarget,
173
CancelableBlockState* aBlock);
174
175
nsEventStatus ReceiveTouchInput(
176
const RefPtr<AsyncPanZoomController>& aTarget,
177
TargetConfirmationFlags aFlags, const MultiTouchInput& aEvent,
178
uint64_t* aOutInputBlockId,
179
const Maybe<nsTArray<TouchBehaviorFlags>>& aTouchBehaviors);
180
nsEventStatus ReceiveMouseInput(const RefPtr<AsyncPanZoomController>& aTarget,
181
TargetConfirmationFlags aFlags,
182
const MouseInput& aEvent,
183
uint64_t* aOutInputBlockId);
184
nsEventStatus ReceiveScrollWheelInput(
185
const RefPtr<AsyncPanZoomController>& aTarget,
186
TargetConfirmationFlags aFlags, const ScrollWheelInput& aEvent,
187
uint64_t* aOutInputBlockId);
188
nsEventStatus ReceivePanGestureInput(
189
const RefPtr<AsyncPanZoomController>& aTarget,
190
TargetConfirmationFlags aFlags, const PanGestureInput& aEvent,
191
uint64_t* aOutInputBlockId);
192
nsEventStatus ReceiveKeyboardInput(
193
const RefPtr<AsyncPanZoomController>& aTarget,
194
const KeyboardInput& aEvent, uint64_t* aOutInputBlockId);
195
196
/**
197
* Helper function that searches mQueuedInputs for the first block matching
198
* the given id, and returns it. If |aOutFirstInput| is non-null, it is
199
* populated with a pointer to the first input in mQueuedInputs that
200
* corresponds to the block, or null if no such input was found. Note that
201
* even if there are no inputs in mQueuedInputs, this function can return
202
* non-null if the block id provided matches one of the depleted-but-still-
203
* active blocks (mActiveTouchBlock, mActiveWheelBlock, etc.).
204
*/
205
InputBlockState* FindBlockForId(uint64_t aInputBlockId,
206
InputData** aOutFirstInput);
207
void ScheduleMainThreadTimeout(const RefPtr<AsyncPanZoomController>& aTarget,
208
CancelableBlockState* aBlock);
209
void MainThreadTimeout(uint64_t aInputBlockId);
210
void ProcessQueue();
211
bool CanDiscardBlock(InputBlockState* aBlock);
212
void UpdateActiveApzc(const RefPtr<AsyncPanZoomController>& aNewActive);
213
214
private:
215
// The queue of input events that have not yet been fully processed.
216
// This member must only be accessed on the controller/UI thread.
217
nsTArray<UniquePtr<QueuedInput>> mQueuedInputs;
218
219
// These are the most recently created blocks of each input type. They are
220
// "active" in the sense that new inputs of that type are associated with
221
// them. Note that these pointers may be null if no inputs of the type have
222
// arrived, or if the inputs for the type formed a complete block that was
223
// then discarded.
224
RefPtr<TouchBlockState> mActiveTouchBlock;
225
RefPtr<WheelBlockState> mActiveWheelBlock;
226
RefPtr<DragBlockState> mActiveDragBlock;
227
RefPtr<PanGestureBlockState> mActivePanGestureBlock;
228
RefPtr<KeyboardBlockState> mActiveKeyboardBlock;
229
230
// The APZC to which the last event was delivered
231
RefPtr<AsyncPanZoomController> mLastActiveApzc;
232
233
// Track touches so we know when to clear mLastActiveApzc
234
TouchCounter mTouchCounter;
235
236
// Track mouse inputs so we know if we're in a drag or not
237
DragTracker mDragTracker;
238
239
// Temporarily stores a timeout task that needs to be run as soon as
240
// as the event that triggered it has been queued.
241
RefPtr<Runnable> mImmediateTimeout;
242
};
243
244
} // namespace layers
245
} // namespace mozilla
246
247
#endif // mozilla_layers_InputQueue_h