widget/windows/winrt/MetroInput.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/widget/windows/winrt/MetroInput.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,304 @@
     1.4 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +#pragma once
    1.10 +
    1.11 +// Moz headers (alphabetical)
    1.12 +#include "keyboardlayout.h"   // mModifierKeyState
    1.13 +#include "nsBaseHashtable.h"  // mTouches
    1.14 +#include "nsHashKeys.h"       // type of key for mTouches
    1.15 +#include "mozwrlbase.h"
    1.16 +#include "nsDeque.h"
    1.17 +#include "mozilla/EventForwards.h"
    1.18 +#include "mozilla/layers/APZCTreeManager.h"
    1.19 +
    1.20 +// System headers (alphabetical)
    1.21 +#include <EventToken.h>     // EventRegistrationToken
    1.22 +#include <stdint.h>         // uint32_t
    1.23 +#include <wrl\client.h>     // Microsoft::WRL::ComPtr class
    1.24 +#include <wrl\implements.h> // Microsoft::WRL::InspectableClass macro
    1.25 +
    1.26 +// Moz forward declarations
    1.27 +class MetroWidget;
    1.28 +struct nsIntPoint;
    1.29 +
    1.30 +namespace mozilla {
    1.31 +namespace dom {
    1.32 +class Touch;
    1.33 +}
    1.34 +}
    1.35 +
    1.36 +// Windows forward declarations
    1.37 +namespace ABI {
    1.38 +  namespace Windows {
    1.39 +    namespace Devices {
    1.40 +      namespace Input {
    1.41 +        enum PointerDeviceType;
    1.42 +      }
    1.43 +    };
    1.44 +    namespace Foundation {
    1.45 +      struct Point;
    1.46 +    };
    1.47 +    namespace UI {
    1.48 +      namespace Core {
    1.49 +        struct ICoreWindow;
    1.50 +        struct IAcceleratorKeyEventArgs;
    1.51 +        struct IKeyEventArgs;
    1.52 +        struct IPointerEventArgs;
    1.53 +      };
    1.54 +      namespace Input {
    1.55 +        struct IEdgeGesture;
    1.56 +        struct IEdgeGestureEventArgs;
    1.57 +        struct IGestureRecognizer;
    1.58 +        struct IManipulationCompletedEventArgs;
    1.59 +        struct IManipulationStartedEventArgs;
    1.60 +        struct IManipulationUpdatedEventArgs;
    1.61 +        struct IPointerPoint;
    1.62 +        struct IRightTappedEventArgs;
    1.63 +        struct ITappedEventArgs;
    1.64 +        struct ManipulationDelta;
    1.65 +      };
    1.66 +    };
    1.67 +  };
    1.68 +};
    1.69 +
    1.70 +namespace mozilla {
    1.71 +namespace widget {
    1.72 +namespace winrt {
    1.73 +
    1.74 +class MetroInput : public Microsoft::WRL::RuntimeClass<IInspectable>
    1.75 +{
    1.76 +  InspectableClass(L"MetroInput", BaseTrust);
    1.77 +
    1.78 +private:
    1.79 +  typedef mozilla::layers::AllowedTouchBehavior AllowedTouchBehavior;
    1.80 +  typedef uint32_t TouchBehaviorFlags;
    1.81 +
    1.82 +  // Devices
    1.83 +  typedef ABI::Windows::Devices::Input::PointerDeviceType PointerDeviceType;
    1.84 +
    1.85 +  // Foundation
    1.86 +  typedef ABI::Windows::Foundation::Point Point;
    1.87 +
    1.88 +  // UI::Core
    1.89 +  typedef ABI::Windows::UI::Core::ICoreWindow ICoreWindow;
    1.90 +  typedef ABI::Windows::UI::Core::IAcceleratorKeyEventArgs \
    1.91 +                                  IAcceleratorKeyEventArgs;
    1.92 +  typedef ABI::Windows::UI::Core::IKeyEventArgs IKeyEventArgs;
    1.93 +  typedef ABI::Windows::UI::Core::IPointerEventArgs IPointerEventArgs;
    1.94 +
    1.95 +  // UI::Input
    1.96 +  typedef ABI::Windows::UI::Input::IEdgeGesture IEdgeGesture;
    1.97 +  typedef ABI::Windows::UI::Input::IEdgeGestureEventArgs IEdgeGestureEventArgs;
    1.98 +  typedef ABI::Windows::UI::Input::IGestureRecognizer IGestureRecognizer;
    1.99 +  typedef ABI::Windows::UI::Input::IManipulationCompletedEventArgs \
   1.100 +                                   IManipulationCompletedEventArgs;
   1.101 +  typedef ABI::Windows::UI::Input::IManipulationStartedEventArgs \
   1.102 +                                   IManipulationStartedEventArgs;
   1.103 +  typedef ABI::Windows::UI::Input::IManipulationUpdatedEventArgs \
   1.104 +                                   IManipulationUpdatedEventArgs;
   1.105 +  typedef ABI::Windows::UI::Input::IPointerPoint IPointerPoint;
   1.106 +  typedef ABI::Windows::UI::Input::IRightTappedEventArgs IRightTappedEventArgs;
   1.107 +  typedef ABI::Windows::UI::Input::ITappedEventArgs ITappedEventArgs;
   1.108 +  typedef ABI::Windows::UI::Input::ManipulationDelta ManipulationDelta;
   1.109 +
   1.110 +  typedef mozilla::layers::ScrollableLayerGuid ScrollableLayerGuid;
   1.111 +
   1.112 +public:
   1.113 +  MetroInput(MetroWidget* aWidget,
   1.114 +             ICoreWindow* aWindow);
   1.115 +  virtual ~MetroInput();
   1.116 +
   1.117 +  // These input events are received from our window. These are basic
   1.118 +  // pointer and keyboard press events. MetroInput responds to them
   1.119 +  // by sending gecko events and forwarding these input events to its
   1.120 +  // GestureRecognizer to be processed into more complex input events
   1.121 +  // (tap, rightTap, rotate, etc)
   1.122 +  HRESULT OnPointerPressed(ICoreWindow* aSender,
   1.123 +                           IPointerEventArgs* aArgs);
   1.124 +  HRESULT OnPointerReleased(ICoreWindow* aSender,
   1.125 +                            IPointerEventArgs* aArgs);
   1.126 +  HRESULT OnPointerMoved(ICoreWindow* aSender,
   1.127 +                         IPointerEventArgs* aArgs);
   1.128 +  HRESULT OnPointerEntered(ICoreWindow* aSender,
   1.129 +                           IPointerEventArgs* aArgs);
   1.130 +  HRESULT OnPointerExited(ICoreWindow* aSender,
   1.131 +                          IPointerEventArgs* aArgs);
   1.132 +
   1.133 +  // The Edge gesture event is special.  It does not come from our window
   1.134 +  // or from our GestureRecognizer.
   1.135 +  HRESULT OnEdgeGestureStarted(IEdgeGesture* aSender,
   1.136 +                               IEdgeGestureEventArgs* aArgs);
   1.137 +  HRESULT OnEdgeGestureCanceled(IEdgeGesture* aSender,
   1.138 +                                IEdgeGestureEventArgs* aArgs);
   1.139 +  HRESULT OnEdgeGestureCompleted(IEdgeGesture* aSender,
   1.140 +                                 IEdgeGestureEventArgs* aArgs);
   1.141 +
   1.142 +  // Swipe gesture callback from the GestureRecognizer.
   1.143 +  HRESULT OnManipulationCompleted(IGestureRecognizer* aSender,
   1.144 +                                  IManipulationCompletedEventArgs* aArgs);
   1.145 +
   1.146 +  // Tap gesture callback from the GestureRecognizer.
   1.147 +  HRESULT OnTapped(IGestureRecognizer* aSender, ITappedEventArgs* aArgs);
   1.148 +  HRESULT OnRightTapped(IGestureRecognizer* aSender,
   1.149 +                        IRightTappedEventArgs* aArgs);
   1.150 +
   1.151 +  void HandleTap(const Point& aPoint, unsigned int aTapCount);
   1.152 +  void HandleLongTap(const Point& aPoint);
   1.153 +
   1.154 +  static bool IsInputModeImprecise();
   1.155 +
   1.156 +private:
   1.157 +  Microsoft::WRL::ComPtr<ICoreWindow> mWindow;
   1.158 +  Microsoft::WRL::ComPtr<MetroWidget> mWidget;
   1.159 +  Microsoft::WRL::ComPtr<IGestureRecognizer> mGestureRecognizer;
   1.160 +
   1.161 +  ModifierKeyState mModifierKeyState;
   1.162 +
   1.163 +  // Tracking input level
   1.164 +  enum InputPrecisionLevel {
   1.165 +    LEVEL_PRECISE,
   1.166 +    LEVEL_IMPRECISE
   1.167 +  };
   1.168 +  static InputPrecisionLevel sCurrentInputLevel;
   1.169 +  void UpdateInputLevel(InputPrecisionLevel aInputLevel);
   1.170 +
   1.171 +  // Initialization/Uninitialization helpers
   1.172 +  void RegisterInputEvents();
   1.173 +  void UnregisterInputEvents();
   1.174 +
   1.175 +  // Hit testing for apz content
   1.176 +  bool mNonApzTargetForTouch;
   1.177 +  bool HitTestChrome(const LayoutDeviceIntPoint& pt);
   1.178 +
   1.179 +  // Event processing helpers.  See function definitions for more info.
   1.180 +  bool TransformRefPoint(const Point& aPosition,
   1.181 +                         LayoutDeviceIntPoint& aRefPointOut);
   1.182 +  void TransformTouchEvent(WidgetTouchEvent* aEvent);
   1.183 +  void OnPointerNonTouch(IPointerPoint* aPoint);
   1.184 +  void AddPointerMoveDataToRecognizer(IPointerEventArgs* aArgs);
   1.185 +  void InitGeckoMouseEventFromPointerPoint(WidgetMouseEvent* aEvent,
   1.186 +                                           IPointerPoint* aPoint);
   1.187 +  void ProcessManipulationDelta(ManipulationDelta const& aDelta,
   1.188 +                                Point const& aPosition,
   1.189 +                                uint32_t aMagEventType,
   1.190 +                                uint32_t aRotEventType);
   1.191 +  uint16_t ProcessInputTypeForGesture(IEdgeGestureEventArgs* aArgs);
   1.192 +  bool ShouldDeliverInputToRecognizer();
   1.193 +
   1.194 +  // Returns array of allowed touch behaviors  for touch points of given TouchEvent.
   1.195 +  // Note: event argument should be transformed via apzc before supplying to this method.
   1.196 +  void GetAllowedTouchBehavior(WidgetTouchEvent* aTransformedEvent, nsTArray<TouchBehaviorFlags>& aOutBehaviors);
   1.197 +
   1.198 +  // Checks whether any touch behavior is allowed.
   1.199 +  bool IsTouchBehaviorForbidden(const nsTArray<TouchBehaviorFlags>& aTouchBehaviors);
   1.200 +
   1.201 +  // The W3C spec states that "whether preventDefault has been called" should
   1.202 +  // be tracked on a per-touchpoint basis, but it also states that touchstart
   1.203 +  // and touchmove events can contain multiple changed points.  At the time of
   1.204 +  // this writing, W3C touch events are in the process of being abandoned in
   1.205 +  // favor of W3C pointer events, so it is unlikely that this ambiguity will
   1.206 +  // be resolved.  Additionally, nsPresShell tracks "whether preventDefault
   1.207 +  // has been called" on a per-touch-session basis.  We will follow a similar
   1.208 +  // approach here.
   1.209 +  //
   1.210 +  // Specifically:
   1.211 +  //   If preventDefault is called on the FIRST touchstart event of a touch
   1.212 +  //   session, then no default actions associated with any touchstart,
   1.213 +  //   touchmove, or touchend events will be taken.  This means that no
   1.214 +  //   mousedowns, mousemoves, mouseups, clicks, swipes, rotations,
   1.215 +  //   magnifications, etc will be dispatched during this touch session;
   1.216 +  //   only touchstart, touchmove, and touchend.
   1.217 +  //
   1.218 +  //   If preventDefault is called on the FIRST touchmove event of a touch
   1.219 +  //   session, then no default actions associated with the _touchmove_ events
   1.220 +  //   will be dispatched.  However, it is still possible that additional
   1.221 +  //   events will be generated based on the touchstart and touchend events.
   1.222 +  //   For example, a set of mousemove, mousedown, and mouseup events might
   1.223 +  //   be sent if a tap is detected.
   1.224 +  bool mContentConsumingTouch;
   1.225 +  bool mApzConsumingTouch;
   1.226 +  bool mCancelable;
   1.227 +  bool mRecognizerWantsEvents;
   1.228 +
   1.229 +  nsTArray<uint32_t> mCanceledIds;
   1.230 +
   1.231 +  // In the old Win32 way of doing things, we would receive a WM_TOUCH event
   1.232 +  // that told us the state of every touchpoint on the touch surface.  If
   1.233 +  // multiple touchpoints had moved since the last update we would learn
   1.234 +  // about all their movement simultaneously.
   1.235 +  //
   1.236 +  // In the new WinRT way of doing things, we receive a separate
   1.237 +  // PointerPressed/PointerMoved/PointerReleased event for each touchpoint
   1.238 +  // that has changed.
   1.239 +  //
   1.240 +  // When we learn of touch input, we dispatch gecko events in response.
   1.241 +  // With the new WinRT way of doing things, we would end up sending many
   1.242 +  // more gecko events than we would using the Win32 mechanism.  E.g.,
   1.243 +  // for 5 active touchpoints, we would be sending 5 times as many gecko
   1.244 +  // events.  This caused performance to visibly degrade on modestly-powered
   1.245 +  // machines.  In response, we no longer send touch events immediately
   1.246 +  // upon receiving PointerPressed or PointerMoved.  Instead, we store
   1.247 +  // the updated touchpoint info and record the fact that the touchpoint
   1.248 +  // has changed.  If ever we try to update a touchpoint has already
   1.249 +  // changed, we dispatch a touch event containing all the changed touches.
   1.250 +  void InitTouchEventTouchList(WidgetTouchEvent* aEvent);
   1.251 +  nsBaseHashtable<nsUint32HashKey,
   1.252 +                  nsRefPtr<mozilla::dom::Touch>,
   1.253 +                  nsRefPtr<mozilla::dom::Touch> > mTouches;
   1.254 +
   1.255 +  // These registration tokens are set when we register ourselves to receive
   1.256 +  // events from our window.  We must hold on to them for the entire duration
   1.257 +  // that we want to receive these events.  When we are done, we must
   1.258 +  // unregister ourself with the window using these tokens.
   1.259 +  EventRegistrationToken mTokenPointerPressed;
   1.260 +  EventRegistrationToken mTokenPointerReleased;
   1.261 +  EventRegistrationToken mTokenPointerMoved;
   1.262 +  EventRegistrationToken mTokenPointerEntered;
   1.263 +  EventRegistrationToken mTokenPointerExited;
   1.264 +
   1.265 +  // When we register ourselves to handle edge gestures, we receive a
   1.266 +  // token. To we unregister ourselves, we must use the token we received.
   1.267 +  EventRegistrationToken mTokenEdgeStarted;
   1.268 +  EventRegistrationToken mTokenEdgeCanceled;
   1.269 +  EventRegistrationToken mTokenEdgeCompleted;
   1.270 +
   1.271 +  // These registration tokens are set when we register ourselves to receive
   1.272 +  // events from our GestureRecognizer.  It's probably not a huge deal if we
   1.273 +  // don't unregister ourselves with our GestureRecognizer before destroying
   1.274 +  // the GestureRecognizer, but it can't hurt.
   1.275 +  EventRegistrationToken mTokenManipulationCompleted;
   1.276 +  EventRegistrationToken mTokenTapped;
   1.277 +  EventRegistrationToken mTokenRightTapped;
   1.278 +
   1.279 +  // Due to a limitation added in 8.1 the ui thread can't re-enter the main
   1.280 +  // native event dispatcher in MetroAppShell. So all events delivered to us
   1.281 +  // on the ui thread via a native event dispatch call get bounced through
   1.282 +  // the gecko thread event queue using runnables. Most events can be sent
   1.283 +  // async without the need to see the status result. Those that do have
   1.284 +  // specialty callbacks. Note any event that arrives to us on the ui thread
   1.285 +  // that originates from another thread is safe to send sync.
   1.286 +
   1.287 +  // Async event dispatching
   1.288 +  void DispatchAsyncEventIgnoreStatus(WidgetInputEvent* aEvent);
   1.289 +  void DispatchAsyncTouchEvent(WidgetTouchEvent* aEvent);
   1.290 +
   1.291 +  // Async event callbacks
   1.292 +  void DeliverNextQueuedEventIgnoreStatus();
   1.293 +  void DeliverNextQueuedTouchEvent();
   1.294 +
   1.295 +  void HandleFirstTouchStartEvent(WidgetTouchEvent* aEvent);
   1.296 +  void HandleFirstTouchMoveEvent(WidgetTouchEvent* aEvent);
   1.297 +
   1.298 +  // Sync event dispatching
   1.299 +  void DispatchEventIgnoreStatus(WidgetGUIEvent* aEvent);
   1.300 +  void DispatchTouchCancel(WidgetTouchEvent* aEvent);
   1.301 +
   1.302 +  nsDeque mInputEventQueue;
   1.303 +  mozilla::layers::ScrollableLayerGuid mTargetAPZCGuid;
   1.304 +  static nsEventStatus sThrowawayStatus;
   1.305 +};
   1.306 +
   1.307 +} } }

mercurial