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