widget/windows/winrt/MetroInput.h

branch
TOR_BUG_9701
changeset 15
b8a032363ba2
equal deleted inserted replaced
-1:000000000000 0:c1ca658520f1
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 } } }

mercurial