mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
305 lines
12 KiB
C++
305 lines
12 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
#pragma once
|
|
|
|
// Moz headers (alphabetical)
|
|
#include "keyboardlayout.h" // mModifierKeyState
|
|
#include "nsBaseHashtable.h" // mTouches
|
|
#include "nsHashKeys.h" // type of key for mTouches
|
|
#include "mozwrlbase.h"
|
|
#include "nsDeque.h"
|
|
#include "mozilla/EventForwards.h"
|
|
#include "mozilla/layers/APZCTreeManager.h"
|
|
|
|
// System headers (alphabetical)
|
|
#include <EventToken.h> // EventRegistrationToken
|
|
#include <stdint.h> // uint32_t
|
|
#include <wrl\client.h> // Microsoft::WRL::ComPtr class
|
|
#include <wrl\implements.h> // Microsoft::WRL::InspectableClass macro
|
|
|
|
// Moz forward declarations
|
|
class MetroWidget;
|
|
struct nsIntPoint;
|
|
|
|
namespace mozilla {
|
|
namespace dom {
|
|
class Touch;
|
|
}
|
|
}
|
|
|
|
// Windows forward declarations
|
|
namespace ABI {
|
|
namespace Windows {
|
|
namespace Devices {
|
|
namespace Input {
|
|
enum PointerDeviceType;
|
|
}
|
|
};
|
|
namespace Foundation {
|
|
struct Point;
|
|
};
|
|
namespace UI {
|
|
namespace Core {
|
|
struct ICoreWindow;
|
|
struct IAcceleratorKeyEventArgs;
|
|
struct IKeyEventArgs;
|
|
struct IPointerEventArgs;
|
|
};
|
|
namespace Input {
|
|
struct IEdgeGesture;
|
|
struct IEdgeGestureEventArgs;
|
|
struct IGestureRecognizer;
|
|
struct IManipulationCompletedEventArgs;
|
|
struct IManipulationStartedEventArgs;
|
|
struct IManipulationUpdatedEventArgs;
|
|
struct IPointerPoint;
|
|
struct IRightTappedEventArgs;
|
|
struct ITappedEventArgs;
|
|
struct ManipulationDelta;
|
|
};
|
|
};
|
|
};
|
|
};
|
|
|
|
namespace mozilla {
|
|
namespace widget {
|
|
namespace winrt {
|
|
|
|
class MetroInput : public Microsoft::WRL::RuntimeClass<IInspectable>
|
|
{
|
|
InspectableClass(L"MetroInput", BaseTrust);
|
|
|
|
private:
|
|
typedef mozilla::layers::AllowedTouchBehavior AllowedTouchBehavior;
|
|
typedef uint32_t TouchBehaviorFlags;
|
|
|
|
// Devices
|
|
typedef ABI::Windows::Devices::Input::PointerDeviceType PointerDeviceType;
|
|
|
|
// Foundation
|
|
typedef ABI::Windows::Foundation::Point Point;
|
|
|
|
// UI::Core
|
|
typedef ABI::Windows::UI::Core::ICoreWindow ICoreWindow;
|
|
typedef ABI::Windows::UI::Core::IAcceleratorKeyEventArgs \
|
|
IAcceleratorKeyEventArgs;
|
|
typedef ABI::Windows::UI::Core::IKeyEventArgs IKeyEventArgs;
|
|
typedef ABI::Windows::UI::Core::IPointerEventArgs IPointerEventArgs;
|
|
|
|
// UI::Input
|
|
typedef ABI::Windows::UI::Input::IEdgeGesture IEdgeGesture;
|
|
typedef ABI::Windows::UI::Input::IEdgeGestureEventArgs IEdgeGestureEventArgs;
|
|
typedef ABI::Windows::UI::Input::IGestureRecognizer IGestureRecognizer;
|
|
typedef ABI::Windows::UI::Input::IManipulationCompletedEventArgs \
|
|
IManipulationCompletedEventArgs;
|
|
typedef ABI::Windows::UI::Input::IManipulationStartedEventArgs \
|
|
IManipulationStartedEventArgs;
|
|
typedef ABI::Windows::UI::Input::IManipulationUpdatedEventArgs \
|
|
IManipulationUpdatedEventArgs;
|
|
typedef ABI::Windows::UI::Input::IPointerPoint IPointerPoint;
|
|
typedef ABI::Windows::UI::Input::IRightTappedEventArgs IRightTappedEventArgs;
|
|
typedef ABI::Windows::UI::Input::ITappedEventArgs ITappedEventArgs;
|
|
typedef ABI::Windows::UI::Input::ManipulationDelta ManipulationDelta;
|
|
|
|
typedef mozilla::layers::ScrollableLayerGuid ScrollableLayerGuid;
|
|
|
|
public:
|
|
MetroInput(MetroWidget* aWidget,
|
|
ICoreWindow* aWindow);
|
|
virtual ~MetroInput();
|
|
|
|
// These input events are received from our window. These are basic
|
|
// pointer and keyboard press events. MetroInput responds to them
|
|
// by sending gecko events and forwarding these input events to its
|
|
// GestureRecognizer to be processed into more complex input events
|
|
// (tap, rightTap, rotate, etc)
|
|
HRESULT OnPointerPressed(ICoreWindow* aSender,
|
|
IPointerEventArgs* aArgs);
|
|
HRESULT OnPointerReleased(ICoreWindow* aSender,
|
|
IPointerEventArgs* aArgs);
|
|
HRESULT OnPointerMoved(ICoreWindow* aSender,
|
|
IPointerEventArgs* aArgs);
|
|
HRESULT OnPointerEntered(ICoreWindow* aSender,
|
|
IPointerEventArgs* aArgs);
|
|
HRESULT OnPointerExited(ICoreWindow* aSender,
|
|
IPointerEventArgs* aArgs);
|
|
|
|
// The Edge gesture event is special. It does not come from our window
|
|
// or from our GestureRecognizer.
|
|
HRESULT OnEdgeGestureStarted(IEdgeGesture* aSender,
|
|
IEdgeGestureEventArgs* aArgs);
|
|
HRESULT OnEdgeGestureCanceled(IEdgeGesture* aSender,
|
|
IEdgeGestureEventArgs* aArgs);
|
|
HRESULT OnEdgeGestureCompleted(IEdgeGesture* aSender,
|
|
IEdgeGestureEventArgs* aArgs);
|
|
|
|
// Swipe gesture callback from the GestureRecognizer.
|
|
HRESULT OnManipulationCompleted(IGestureRecognizer* aSender,
|
|
IManipulationCompletedEventArgs* aArgs);
|
|
|
|
// Tap gesture callback from the GestureRecognizer.
|
|
HRESULT OnTapped(IGestureRecognizer* aSender, ITappedEventArgs* aArgs);
|
|
HRESULT OnRightTapped(IGestureRecognizer* aSender,
|
|
IRightTappedEventArgs* aArgs);
|
|
|
|
void HandleTap(const Point& aPoint, unsigned int aTapCount);
|
|
void HandleLongTap(const Point& aPoint);
|
|
|
|
static bool IsInputModeImprecise();
|
|
|
|
private:
|
|
Microsoft::WRL::ComPtr<ICoreWindow> mWindow;
|
|
Microsoft::WRL::ComPtr<MetroWidget> mWidget;
|
|
Microsoft::WRL::ComPtr<IGestureRecognizer> mGestureRecognizer;
|
|
|
|
ModifierKeyState mModifierKeyState;
|
|
|
|
// Tracking input level
|
|
enum InputPrecisionLevel {
|
|
LEVEL_PRECISE,
|
|
LEVEL_IMPRECISE
|
|
};
|
|
static InputPrecisionLevel sCurrentInputLevel;
|
|
void UpdateInputLevel(InputPrecisionLevel aInputLevel);
|
|
|
|
// Initialization/Uninitialization helpers
|
|
void RegisterInputEvents();
|
|
void UnregisterInputEvents();
|
|
|
|
// Hit testing for apz content
|
|
bool mNonApzTargetForTouch;
|
|
bool HitTestChrome(const LayoutDeviceIntPoint& pt);
|
|
|
|
// Event processing helpers. See function definitions for more info.
|
|
bool TransformRefPoint(const Point& aPosition,
|
|
LayoutDeviceIntPoint& aRefPointOut);
|
|
void TransformTouchEvent(WidgetTouchEvent* aEvent);
|
|
void OnPointerNonTouch(IPointerPoint* aPoint);
|
|
void AddPointerMoveDataToRecognizer(IPointerEventArgs* aArgs);
|
|
void InitGeckoMouseEventFromPointerPoint(WidgetMouseEvent* aEvent,
|
|
IPointerPoint* aPoint);
|
|
void ProcessManipulationDelta(ManipulationDelta const& aDelta,
|
|
Point const& aPosition,
|
|
uint32_t aMagEventType,
|
|
uint32_t aRotEventType);
|
|
uint16_t ProcessInputTypeForGesture(IEdgeGestureEventArgs* aArgs);
|
|
bool ShouldDeliverInputToRecognizer();
|
|
|
|
// Returns array of allowed touch behaviors for touch points of given TouchEvent.
|
|
// Note: event argument should be transformed via apzc before supplying to this method.
|
|
void GetAllowedTouchBehavior(WidgetTouchEvent* aTransformedEvent, nsTArray<TouchBehaviorFlags>& aOutBehaviors);
|
|
|
|
// Checks whether any touch behavior is allowed.
|
|
bool IsTouchBehaviorForbidden(const nsTArray<TouchBehaviorFlags>& aTouchBehaviors);
|
|
|
|
// The W3C spec states that "whether preventDefault has been called" should
|
|
// be tracked on a per-touchpoint basis, but it also states that touchstart
|
|
// and touchmove events can contain multiple changed points. At the time of
|
|
// this writing, W3C touch events are in the process of being abandoned in
|
|
// favor of W3C pointer events, so it is unlikely that this ambiguity will
|
|
// be resolved. Additionally, nsPresShell tracks "whether preventDefault
|
|
// has been called" on a per-touch-session basis. We will follow a similar
|
|
// approach here.
|
|
//
|
|
// Specifically:
|
|
// If preventDefault is called on the FIRST touchstart event of a touch
|
|
// session, then no default actions associated with any touchstart,
|
|
// touchmove, or touchend events will be taken. This means that no
|
|
// mousedowns, mousemoves, mouseups, clicks, swipes, rotations,
|
|
// magnifications, etc will be dispatched during this touch session;
|
|
// only touchstart, touchmove, and touchend.
|
|
//
|
|
// If preventDefault is called on the FIRST touchmove event of a touch
|
|
// session, then no default actions associated with the _touchmove_ events
|
|
// will be dispatched. However, it is still possible that additional
|
|
// events will be generated based on the touchstart and touchend events.
|
|
// For example, a set of mousemove, mousedown, and mouseup events might
|
|
// be sent if a tap is detected.
|
|
bool mContentConsumingTouch;
|
|
bool mApzConsumingTouch;
|
|
bool mCancelable;
|
|
bool mRecognizerWantsEvents;
|
|
|
|
nsTArray<uint32_t> mCanceledIds;
|
|
|
|
// In the old Win32 way of doing things, we would receive a WM_TOUCH event
|
|
// that told us the state of every touchpoint on the touch surface. If
|
|
// multiple touchpoints had moved since the last update we would learn
|
|
// about all their movement simultaneously.
|
|
//
|
|
// In the new WinRT way of doing things, we receive a separate
|
|
// PointerPressed/PointerMoved/PointerReleased event for each touchpoint
|
|
// that has changed.
|
|
//
|
|
// When we learn of touch input, we dispatch gecko events in response.
|
|
// With the new WinRT way of doing things, we would end up sending many
|
|
// more gecko events than we would using the Win32 mechanism. E.g.,
|
|
// for 5 active touchpoints, we would be sending 5 times as many gecko
|
|
// events. This caused performance to visibly degrade on modestly-powered
|
|
// machines. In response, we no longer send touch events immediately
|
|
// upon receiving PointerPressed or PointerMoved. Instead, we store
|
|
// the updated touchpoint info and record the fact that the touchpoint
|
|
// has changed. If ever we try to update a touchpoint has already
|
|
// changed, we dispatch a touch event containing all the changed touches.
|
|
void InitTouchEventTouchList(WidgetTouchEvent* aEvent);
|
|
nsBaseHashtable<nsUint32HashKey,
|
|
nsRefPtr<mozilla::dom::Touch>,
|
|
nsRefPtr<mozilla::dom::Touch> > mTouches;
|
|
|
|
// These registration tokens are set when we register ourselves to receive
|
|
// events from our window. We must hold on to them for the entire duration
|
|
// that we want to receive these events. When we are done, we must
|
|
// unregister ourself with the window using these tokens.
|
|
EventRegistrationToken mTokenPointerPressed;
|
|
EventRegistrationToken mTokenPointerReleased;
|
|
EventRegistrationToken mTokenPointerMoved;
|
|
EventRegistrationToken mTokenPointerEntered;
|
|
EventRegistrationToken mTokenPointerExited;
|
|
|
|
// When we register ourselves to handle edge gestures, we receive a
|
|
// token. To we unregister ourselves, we must use the token we received.
|
|
EventRegistrationToken mTokenEdgeStarted;
|
|
EventRegistrationToken mTokenEdgeCanceled;
|
|
EventRegistrationToken mTokenEdgeCompleted;
|
|
|
|
// These registration tokens are set when we register ourselves to receive
|
|
// events from our GestureRecognizer. It's probably not a huge deal if we
|
|
// don't unregister ourselves with our GestureRecognizer before destroying
|
|
// the GestureRecognizer, but it can't hurt.
|
|
EventRegistrationToken mTokenManipulationCompleted;
|
|
EventRegistrationToken mTokenTapped;
|
|
EventRegistrationToken mTokenRightTapped;
|
|
|
|
// Due to a limitation added in 8.1 the ui thread can't re-enter the main
|
|
// native event dispatcher in MetroAppShell. So all events delivered to us
|
|
// on the ui thread via a native event dispatch call get bounced through
|
|
// the gecko thread event queue using runnables. Most events can be sent
|
|
// async without the need to see the status result. Those that do have
|
|
// specialty callbacks. Note any event that arrives to us on the ui thread
|
|
// that originates from another thread is safe to send sync.
|
|
|
|
// Async event dispatching
|
|
void DispatchAsyncEventIgnoreStatus(WidgetInputEvent* aEvent);
|
|
void DispatchAsyncTouchEvent(WidgetTouchEvent* aEvent);
|
|
|
|
// Async event callbacks
|
|
void DeliverNextQueuedEventIgnoreStatus();
|
|
void DeliverNextQueuedTouchEvent();
|
|
|
|
void HandleFirstTouchStartEvent(WidgetTouchEvent* aEvent);
|
|
void HandleFirstTouchMoveEvent(WidgetTouchEvent* aEvent);
|
|
|
|
// Sync event dispatching
|
|
void DispatchEventIgnoreStatus(WidgetGUIEvent* aEvent);
|
|
void DispatchTouchCancel(WidgetTouchEvent* aEvent);
|
|
|
|
nsDeque mInputEventQueue;
|
|
mozilla::layers::ScrollableLayerGuid mTargetAPZCGuid;
|
|
static nsEventStatus sThrowawayStatus;
|
|
};
|
|
|
|
} } }
|