widget/windows/winrt/MetroInput.h

Thu, 15 Jan 2015 15:59:08 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 15 Jan 2015 15:59:08 +0100
branch
TOR_BUG_9701
changeset 10
ac0c01689b40
permissions
-rw-r--r--

Implement a real Private Browsing Mode condition by changing the API/ABI;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

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

mercurial