|
1 /* -*- Mode: C++; tab-width: 4; 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 #pragma once |
|
7 |
|
8 // Moz headers (alphabetical) |
|
9 #include "keyboardlayout.h" // mModifierKeyState |
|
10 #include "nsBaseHashtable.h" // mTouches |
|
11 #include "nsHashKeys.h" // type of key for mTouches |
|
12 #include "mozwrlbase.h" |
|
13 #include "nsDeque.h" |
|
14 #include "mozilla/EventForwards.h" |
|
15 #include "mozilla/layers/APZCTreeManager.h" |
|
16 |
|
17 // System headers (alphabetical) |
|
18 #include <EventToken.h> // EventRegistrationToken |
|
19 #include <stdint.h> // uint32_t |
|
20 #include <wrl\client.h> // Microsoft::WRL::ComPtr class |
|
21 #include <wrl\implements.h> // Microsoft::WRL::InspectableClass macro |
|
22 |
|
23 // Moz forward declarations |
|
24 class MetroWidget; |
|
25 struct nsIntPoint; |
|
26 |
|
27 namespace mozilla { |
|
28 namespace dom { |
|
29 class Touch; |
|
30 } |
|
31 } |
|
32 |
|
33 // Windows forward declarations |
|
34 namespace ABI { |
|
35 namespace Windows { |
|
36 namespace Devices { |
|
37 namespace Input { |
|
38 enum PointerDeviceType; |
|
39 } |
|
40 }; |
|
41 namespace Foundation { |
|
42 struct Point; |
|
43 }; |
|
44 namespace UI { |
|
45 namespace Core { |
|
46 struct ICoreWindow; |
|
47 struct IAcceleratorKeyEventArgs; |
|
48 struct IKeyEventArgs; |
|
49 struct IPointerEventArgs; |
|
50 }; |
|
51 namespace Input { |
|
52 struct IEdgeGesture; |
|
53 struct IEdgeGestureEventArgs; |
|
54 struct IGestureRecognizer; |
|
55 struct IManipulationCompletedEventArgs; |
|
56 struct IManipulationStartedEventArgs; |
|
57 struct IManipulationUpdatedEventArgs; |
|
58 struct IPointerPoint; |
|
59 struct IRightTappedEventArgs; |
|
60 struct ITappedEventArgs; |
|
61 struct ManipulationDelta; |
|
62 }; |
|
63 }; |
|
64 }; |
|
65 }; |
|
66 |
|
67 namespace mozilla { |
|
68 namespace widget { |
|
69 namespace winrt { |
|
70 |
|
71 class MetroInput : public Microsoft::WRL::RuntimeClass<IInspectable> |
|
72 { |
|
73 InspectableClass(L"MetroInput", BaseTrust); |
|
74 |
|
75 private: |
|
76 typedef mozilla::layers::AllowedTouchBehavior AllowedTouchBehavior; |
|
77 typedef uint32_t TouchBehaviorFlags; |
|
78 |
|
79 // Devices |
|
80 typedef ABI::Windows::Devices::Input::PointerDeviceType PointerDeviceType; |
|
81 |
|
82 // Foundation |
|
83 typedef ABI::Windows::Foundation::Point Point; |
|
84 |
|
85 // UI::Core |
|
86 typedef ABI::Windows::UI::Core::ICoreWindow ICoreWindow; |
|
87 typedef ABI::Windows::UI::Core::IAcceleratorKeyEventArgs \ |
|
88 IAcceleratorKeyEventArgs; |
|
89 typedef ABI::Windows::UI::Core::IKeyEventArgs IKeyEventArgs; |
|
90 typedef ABI::Windows::UI::Core::IPointerEventArgs IPointerEventArgs; |
|
91 |
|
92 // UI::Input |
|
93 typedef ABI::Windows::UI::Input::IEdgeGesture IEdgeGesture; |
|
94 typedef ABI::Windows::UI::Input::IEdgeGestureEventArgs IEdgeGestureEventArgs; |
|
95 typedef ABI::Windows::UI::Input::IGestureRecognizer IGestureRecognizer; |
|
96 typedef ABI::Windows::UI::Input::IManipulationCompletedEventArgs \ |
|
97 IManipulationCompletedEventArgs; |
|
98 typedef ABI::Windows::UI::Input::IManipulationStartedEventArgs \ |
|
99 IManipulationStartedEventArgs; |
|
100 typedef ABI::Windows::UI::Input::IManipulationUpdatedEventArgs \ |
|
101 IManipulationUpdatedEventArgs; |
|
102 typedef ABI::Windows::UI::Input::IPointerPoint IPointerPoint; |
|
103 typedef ABI::Windows::UI::Input::IRightTappedEventArgs IRightTappedEventArgs; |
|
104 typedef ABI::Windows::UI::Input::ITappedEventArgs ITappedEventArgs; |
|
105 typedef ABI::Windows::UI::Input::ManipulationDelta ManipulationDelta; |
|
106 |
|
107 typedef mozilla::layers::ScrollableLayerGuid ScrollableLayerGuid; |
|
108 |
|
109 public: |
|
110 MetroInput(MetroWidget* aWidget, |
|
111 ICoreWindow* aWindow); |
|
112 virtual ~MetroInput(); |
|
113 |
|
114 // These input events are received from our window. These are basic |
|
115 // pointer and keyboard press events. MetroInput responds to them |
|
116 // by sending gecko events and forwarding these input events to its |
|
117 // GestureRecognizer to be processed into more complex input events |
|
118 // (tap, rightTap, rotate, etc) |
|
119 HRESULT OnPointerPressed(ICoreWindow* aSender, |
|
120 IPointerEventArgs* aArgs); |
|
121 HRESULT OnPointerReleased(ICoreWindow* aSender, |
|
122 IPointerEventArgs* aArgs); |
|
123 HRESULT OnPointerMoved(ICoreWindow* aSender, |
|
124 IPointerEventArgs* aArgs); |
|
125 HRESULT OnPointerEntered(ICoreWindow* aSender, |
|
126 IPointerEventArgs* aArgs); |
|
127 HRESULT OnPointerExited(ICoreWindow* aSender, |
|
128 IPointerEventArgs* aArgs); |
|
129 |
|
130 // The Edge gesture event is special. It does not come from our window |
|
131 // or from our GestureRecognizer. |
|
132 HRESULT OnEdgeGestureStarted(IEdgeGesture* aSender, |
|
133 IEdgeGestureEventArgs* aArgs); |
|
134 HRESULT OnEdgeGestureCanceled(IEdgeGesture* aSender, |
|
135 IEdgeGestureEventArgs* aArgs); |
|
136 HRESULT OnEdgeGestureCompleted(IEdgeGesture* aSender, |
|
137 IEdgeGestureEventArgs* aArgs); |
|
138 |
|
139 // Swipe gesture callback from the GestureRecognizer. |
|
140 HRESULT OnManipulationCompleted(IGestureRecognizer* aSender, |
|
141 IManipulationCompletedEventArgs* aArgs); |
|
142 |
|
143 // Tap gesture callback from the GestureRecognizer. |
|
144 HRESULT OnTapped(IGestureRecognizer* aSender, ITappedEventArgs* aArgs); |
|
145 HRESULT OnRightTapped(IGestureRecognizer* aSender, |
|
146 IRightTappedEventArgs* aArgs); |
|
147 |
|
148 void HandleTap(const Point& aPoint, unsigned int aTapCount); |
|
149 void HandleLongTap(const Point& aPoint); |
|
150 |
|
151 static bool IsInputModeImprecise(); |
|
152 |
|
153 private: |
|
154 Microsoft::WRL::ComPtr<ICoreWindow> mWindow; |
|
155 Microsoft::WRL::ComPtr<MetroWidget> mWidget; |
|
156 Microsoft::WRL::ComPtr<IGestureRecognizer> mGestureRecognizer; |
|
157 |
|
158 ModifierKeyState mModifierKeyState; |
|
159 |
|
160 // Tracking input level |
|
161 enum InputPrecisionLevel { |
|
162 LEVEL_PRECISE, |
|
163 LEVEL_IMPRECISE |
|
164 }; |
|
165 static InputPrecisionLevel sCurrentInputLevel; |
|
166 void UpdateInputLevel(InputPrecisionLevel aInputLevel); |
|
167 |
|
168 // Initialization/Uninitialization helpers |
|
169 void RegisterInputEvents(); |
|
170 void UnregisterInputEvents(); |
|
171 |
|
172 // Hit testing for apz content |
|
173 bool mNonApzTargetForTouch; |
|
174 bool HitTestChrome(const LayoutDeviceIntPoint& pt); |
|
175 |
|
176 // Event processing helpers. See function definitions for more info. |
|
177 bool TransformRefPoint(const Point& aPosition, |
|
178 LayoutDeviceIntPoint& aRefPointOut); |
|
179 void TransformTouchEvent(WidgetTouchEvent* aEvent); |
|
180 void OnPointerNonTouch(IPointerPoint* aPoint); |
|
181 void AddPointerMoveDataToRecognizer(IPointerEventArgs* aArgs); |
|
182 void InitGeckoMouseEventFromPointerPoint(WidgetMouseEvent* aEvent, |
|
183 IPointerPoint* aPoint); |
|
184 void ProcessManipulationDelta(ManipulationDelta const& aDelta, |
|
185 Point const& aPosition, |
|
186 uint32_t aMagEventType, |
|
187 uint32_t aRotEventType); |
|
188 uint16_t ProcessInputTypeForGesture(IEdgeGestureEventArgs* aArgs); |
|
189 bool ShouldDeliverInputToRecognizer(); |
|
190 |
|
191 // Returns array of allowed touch behaviors for touch points of given TouchEvent. |
|
192 // Note: event argument should be transformed via apzc before supplying to this method. |
|
193 void GetAllowedTouchBehavior(WidgetTouchEvent* aTransformedEvent, nsTArray<TouchBehaviorFlags>& aOutBehaviors); |
|
194 |
|
195 // Checks whether any touch behavior is allowed. |
|
196 bool IsTouchBehaviorForbidden(const nsTArray<TouchBehaviorFlags>& aTouchBehaviors); |
|
197 |
|
198 // The W3C spec states that "whether preventDefault has been called" should |
|
199 // be tracked on a per-touchpoint basis, but it also states that touchstart |
|
200 // and touchmove events can contain multiple changed points. At the time of |
|
201 // this writing, W3C touch events are in the process of being abandoned in |
|
202 // favor of W3C pointer events, so it is unlikely that this ambiguity will |
|
203 // be resolved. Additionally, nsPresShell tracks "whether preventDefault |
|
204 // has been called" on a per-touch-session basis. We will follow a similar |
|
205 // approach here. |
|
206 // |
|
207 // Specifically: |
|
208 // If preventDefault is called on the FIRST touchstart event of a touch |
|
209 // session, then no default actions associated with any touchstart, |
|
210 // touchmove, or touchend events will be taken. This means that no |
|
211 // mousedowns, mousemoves, mouseups, clicks, swipes, rotations, |
|
212 // magnifications, etc will be dispatched during this touch session; |
|
213 // only touchstart, touchmove, and touchend. |
|
214 // |
|
215 // If preventDefault is called on the FIRST touchmove event of a touch |
|
216 // session, then no default actions associated with the _touchmove_ events |
|
217 // will be dispatched. However, it is still possible that additional |
|
218 // events will be generated based on the touchstart and touchend events. |
|
219 // For example, a set of mousemove, mousedown, and mouseup events might |
|
220 // be sent if a tap is detected. |
|
221 bool mContentConsumingTouch; |
|
222 bool mApzConsumingTouch; |
|
223 bool mCancelable; |
|
224 bool mRecognizerWantsEvents; |
|
225 |
|
226 nsTArray<uint32_t> mCanceledIds; |
|
227 |
|
228 // In the old Win32 way of doing things, we would receive a WM_TOUCH event |
|
229 // that told us the state of every touchpoint on the touch surface. If |
|
230 // multiple touchpoints had moved since the last update we would learn |
|
231 // about all their movement simultaneously. |
|
232 // |
|
233 // In the new WinRT way of doing things, we receive a separate |
|
234 // PointerPressed/PointerMoved/PointerReleased event for each touchpoint |
|
235 // that has changed. |
|
236 // |
|
237 // When we learn of touch input, we dispatch gecko events in response. |
|
238 // With the new WinRT way of doing things, we would end up sending many |
|
239 // more gecko events than we would using the Win32 mechanism. E.g., |
|
240 // for 5 active touchpoints, we would be sending 5 times as many gecko |
|
241 // events. This caused performance to visibly degrade on modestly-powered |
|
242 // machines. In response, we no longer send touch events immediately |
|
243 // upon receiving PointerPressed or PointerMoved. Instead, we store |
|
244 // the updated touchpoint info and record the fact that the touchpoint |
|
245 // has changed. If ever we try to update a touchpoint has already |
|
246 // changed, we dispatch a touch event containing all the changed touches. |
|
247 void InitTouchEventTouchList(WidgetTouchEvent* aEvent); |
|
248 nsBaseHashtable<nsUint32HashKey, |
|
249 nsRefPtr<mozilla::dom::Touch>, |
|
250 nsRefPtr<mozilla::dom::Touch> > mTouches; |
|
251 |
|
252 // These registration tokens are set when we register ourselves to receive |
|
253 // events from our window. We must hold on to them for the entire duration |
|
254 // that we want to receive these events. When we are done, we must |
|
255 // unregister ourself with the window using these tokens. |
|
256 EventRegistrationToken mTokenPointerPressed; |
|
257 EventRegistrationToken mTokenPointerReleased; |
|
258 EventRegistrationToken mTokenPointerMoved; |
|
259 EventRegistrationToken mTokenPointerEntered; |
|
260 EventRegistrationToken mTokenPointerExited; |
|
261 |
|
262 // When we register ourselves to handle edge gestures, we receive a |
|
263 // token. To we unregister ourselves, we must use the token we received. |
|
264 EventRegistrationToken mTokenEdgeStarted; |
|
265 EventRegistrationToken mTokenEdgeCanceled; |
|
266 EventRegistrationToken mTokenEdgeCompleted; |
|
267 |
|
268 // These registration tokens are set when we register ourselves to receive |
|
269 // events from our GestureRecognizer. It's probably not a huge deal if we |
|
270 // don't unregister ourselves with our GestureRecognizer before destroying |
|
271 // the GestureRecognizer, but it can't hurt. |
|
272 EventRegistrationToken mTokenManipulationCompleted; |
|
273 EventRegistrationToken mTokenTapped; |
|
274 EventRegistrationToken mTokenRightTapped; |
|
275 |
|
276 // Due to a limitation added in 8.1 the ui thread can't re-enter the main |
|
277 // native event dispatcher in MetroAppShell. So all events delivered to us |
|
278 // on the ui thread via a native event dispatch call get bounced through |
|
279 // the gecko thread event queue using runnables. Most events can be sent |
|
280 // async without the need to see the status result. Those that do have |
|
281 // specialty callbacks. Note any event that arrives to us on the ui thread |
|
282 // that originates from another thread is safe to send sync. |
|
283 |
|
284 // Async event dispatching |
|
285 void DispatchAsyncEventIgnoreStatus(WidgetInputEvent* aEvent); |
|
286 void DispatchAsyncTouchEvent(WidgetTouchEvent* aEvent); |
|
287 |
|
288 // Async event callbacks |
|
289 void DeliverNextQueuedEventIgnoreStatus(); |
|
290 void DeliverNextQueuedTouchEvent(); |
|
291 |
|
292 void HandleFirstTouchStartEvent(WidgetTouchEvent* aEvent); |
|
293 void HandleFirstTouchMoveEvent(WidgetTouchEvent* aEvent); |
|
294 |
|
295 // Sync event dispatching |
|
296 void DispatchEventIgnoreStatus(WidgetGUIEvent* aEvent); |
|
297 void DispatchTouchCancel(WidgetTouchEvent* aEvent); |
|
298 |
|
299 nsDeque mInputEventQueue; |
|
300 mozilla::layers::ScrollableLayerGuid mTargetAPZCGuid; |
|
301 static nsEventStatus sThrowawayStatus; |
|
302 }; |
|
303 |
|
304 } } } |