diff --git a/widget/windows/winrt/MetroInput.cpp b/widget/windows/winrt/MetroInput.cpp index 87a7c2cb835..cfea55c0b53 100644 --- a/widget/windows/winrt/MetroInput.cpp +++ b/widget/windows/winrt/MetroInput.cpp @@ -14,7 +14,6 @@ #include "UIABridgePrivate.h" #include "MetroAppShell.h" #include "mozilla/MouseEvents.h" -#include "mozilla/TouchEvents.h" #include "mozilla/Preferences.h" // for Preferences #include "WinUtils.h" #include "nsIPresShell.h" @@ -22,7 +21,6 @@ // System headers (alphabetical) #include // ABI::Window::UI::Core namespace -#include // ABI::Window::UI::Input namespace //#define DEBUG_INPUT @@ -238,20 +236,6 @@ namespace { aData->mChanged = false; return PL_DHASH_NEXT; } - - // Helper for making sure event ptrs get freed. - class AutoDeleteEvent - { - public: - AutoDeleteEvent(WidgetGUIEvent* aPtr) : - mPtr(aPtr) {} - ~AutoDeleteEvent() { - if (mPtr) { - delete mPtr; - } - } - WidgetGUIEvent* mPtr; - }; } namespace mozilla { @@ -540,19 +524,19 @@ MetroInput::OnPointerPressed(UI::Core::ICoreWindow* aSender, LogFunction(); #endif - WRL::ComPtr currentPoint; + UI::Input::IPointerPoint* currentPoint; WRL::ComPtr device; Devices::Input::PointerDeviceType deviceType; - aArgs->get_CurrentPoint(currentPoint.GetAddressOf()); + aArgs->get_CurrentPoint(¤tPoint); currentPoint->get_PointerDevice(device.GetAddressOf()); device->get_PointerDeviceType(&deviceType); // For mouse and pen input, simply call our helper function if (deviceType != Devices::Input::PointerDeviceType::PointerDeviceType_Touch) { - OnPointerNonTouch(currentPoint.Get()); - mGestureRecognizer->ProcessDownEvent(currentPoint.Get()); + OnPointerNonTouch(currentPoint); + mGestureRecognizer->ProcessDownEvent(currentPoint); return S_OK; } @@ -562,7 +546,7 @@ MetroInput::OnPointerPressed(UI::Core::ICoreWindow* aSender, // Create the new touch point and add it to our event. uint32_t pointerId; currentPoint->get_PointerId(&pointerId); - nsRefPtr touch = CreateDOMTouch(currentPoint.Get()); + nsRefPtr touch = CreateDOMTouch(currentPoint); touch->mChanged = true; mTouches.Put(pointerId, touch); @@ -582,25 +566,31 @@ MetroInput::OnPointerPressed(UI::Core::ICoreWindow* aSender, } InitTouchEventTouchList(touchEvent); - DispatchAsyncTouchEvent(touchEvent); + DispatchAsyncTouchEvent(new TouchEventQueueEntry(touchEvent, currentPoint)); - if (ShouldDeliverInputToRecognizer()) { - mGestureRecognizer->ProcessDownEvent(currentPoint.Get()); - } return S_OK; } void -MetroInput::AddPointerMoveDataToRecognizer(UI::Core::IPointerEventArgs* aArgs) +MetroInput::AddPointerMoveDataToRecognizer(IPointerEventArgs* aArgs) { if (ShouldDeliverInputToRecognizer()) { - WRL::ComPtr> - pointerPoints; + WRL::ComPtr pointerPoints; aArgs->GetIntermediatePoints(pointerPoints.GetAddressOf()); mGestureRecognizer->ProcessMoveEvents(pointerPoints.Get()); } } +void +MetroInput::DeliverNextQueuedNoMoveTouch() { + nsAutoPtr queueEntry = + static_cast(mInputEventQueue.PopFront()); + + if (ShouldDeliverInputToRecognizer()) { + mGestureRecognizer->ProcessMoveEvents(queueEntry->GetPointerPoints()); + } +} + // This event is raised when the user moves the mouse, moves a pen that is // in contact with the surface, or moves a finger that is in contact with // a touch screen. @@ -644,12 +634,19 @@ MetroInput::OnPointerMoved(UI::Core::ICoreWindow* aSender, return S_OK; } - AddPointerMoveDataToRecognizer(aArgs); + PointerPointVector* pointerPoints; + aArgs->GetIntermediatePoints(&pointerPoints); // If the point hasn't moved, filter it out per the spec. Pres shell does // this as well, but we need to know when our first touchmove is going to // get delivered so we can check the result. if (!HasPointMoved(touch, currentPoint.Get())) { + // Even when the pointer has not moved, the gesture recognizer requires it. + // Doing it asynchronously to keep the event's order. + mInputEventQueue.Push(new TouchEventQueueEntry(nullptr, pointerPoints)); + nsCOMPtr runnable = + NS_NewRunnableMethod(this, &MetroInput::DeliverNextQueuedNoMoveTouch); + NS_DispatchToCurrentThread(runnable); return S_OK; } @@ -661,7 +658,8 @@ MetroInput::OnPointerMoved(UI::Core::ICoreWindow* aSender, WidgetTouchEvent* touchEvent = new WidgetTouchEvent(true, NS_TOUCH_MOVE, mWidget.Get()); InitTouchEventTouchList(touchEvent); - DispatchAsyncTouchEvent(touchEvent); + + DispatchAsyncTouchEvent(new TouchEventQueueEntry(touchEvent, pointerPoints)); return S_OK; } @@ -676,19 +674,19 @@ MetroInput::OnPointerReleased(UI::Core::ICoreWindow* aSender, LogFunction(); #endif - WRL::ComPtr currentPoint; + UI::Input::IPointerPoint* currentPoint; WRL::ComPtr device; Devices::Input::PointerDeviceType deviceType; - aArgs->get_CurrentPoint(currentPoint.GetAddressOf()); + aArgs->get_CurrentPoint(¤tPoint); currentPoint->get_PointerDevice(device.GetAddressOf()); device->get_PointerDeviceType(&deviceType); // For mouse and pen input, simply call our helper function if (deviceType != Devices::Input::PointerDeviceType::PointerDeviceType_Touch) { - OnPointerNonTouch(currentPoint.Get()); - mGestureRecognizer->ProcessUpEvent(currentPoint.Get()); + OnPointerNonTouch(currentPoint); + mGestureRecognizer->ProcessUpEvent(currentPoint); return S_OK; } @@ -705,7 +703,7 @@ MetroInput::OnPointerReleased(UI::Core::ICoreWindow* aSender, WidgetTouchEvent* touchEvent = new WidgetTouchEvent(true, NS_TOUCH_MOVE, mWidget.Get()); InitTouchEventTouchList(touchEvent); - DispatchAsyncTouchEvent(touchEvent); + DispatchAsyncTouchEvent(new TouchEventQueueEntry(touchEvent, (IPointerPoint*)nullptr)); } // Remove this touch point from our map. Eventually all touch points are @@ -716,12 +714,8 @@ MetroInput::OnPointerReleased(UI::Core::ICoreWindow* aSender, // touchend events only have a single touch; the touch that has been removed WidgetTouchEvent* touchEvent = new WidgetTouchEvent(true, NS_TOUCH_END, mWidget.Get()); - touchEvent->touches.AppendElement(CreateDOMTouch(currentPoint.Get())); - DispatchAsyncTouchEvent(touchEvent); - - if (ShouldDeliverInputToRecognizer()) { - mGestureRecognizer->ProcessUpEvent(currentPoint.Get()); - } + touchEvent->touches.AppendElement(CreateDOMTouch(currentPoint)); + DispatchAsyncTouchEvent(new TouchEventQueueEntry(touchEvent, currentPoint)); return S_OK; } @@ -1136,12 +1130,13 @@ MetroInput::DeliverNextQueuedEventIgnoreStatus() } void -MetroInput::DispatchAsyncTouchEvent(WidgetTouchEvent* aEvent) +MetroInput::DispatchAsyncTouchEvent(TouchEventQueueEntry* queueEntry) { - aEvent->time = ::GetMessageTime(); + WidgetTouchEvent* event = queueEntry->GetEvent(); + event->time = ::GetMessageTime(); mModifierKeyState.Update(); - mModifierKeyState.InitInputEvent(*aEvent); - mInputEventQueue.Push(aEvent); + mModifierKeyState.InitInputEvent(*event); + mInputEventQueue.Push(queueEntry); nsCOMPtr runnable = NS_NewRunnableMethod(this, &MetroInput::DeliverNextQueuedTouchEvent); NS_DispatchToCurrentThread(runnable); @@ -1352,11 +1347,12 @@ MetroInput::DeliverNextQueuedTouchEvent() */ nsEventStatus status = nsEventStatus_eIgnore; - WidgetTouchEvent* event = - static_cast(mInputEventQueue.PopFront()); - MOZ_ASSERT(event); + nsAutoPtr queueEntry = + static_cast(mInputEventQueue.PopFront()); + + WidgetTouchEvent* event = queueEntry->GetEvent(); - AutoDeleteEvent wrap(event); + MOZ_ASSERT(event); // Test for non-apz vs. apz target. To do this we only use the first touch // point since that will be the input batch target. Cache this for touch events @@ -1387,6 +1383,25 @@ MetroInput::DeliverNextQueuedTouchEvent() mCancelable = false; } } + } + + if (ShouldDeliverInputToRecognizer()) { + switch (event->message) { + case NS_TOUCH_START: + mGestureRecognizer->ProcessDownEvent(queueEntry->GetPointerPoint()); + break; + case NS_TOUCH_END: + mGestureRecognizer->ProcessUpEvent(queueEntry->GetPointerPoint()); + break; + case NS_TOUCH_MOVE: + if (queueEntry->GetPointerPoints()) { + mGestureRecognizer->ProcessMoveEvents(queueEntry->GetPointerPoints()); + } + break; + } + } + + if (mNonApzTargetForTouch) { return; } diff --git a/widget/windows/winrt/MetroInput.h b/widget/windows/winrt/MetroInput.h index 8705059ef62..592ca5311ce 100644 --- a/widget/windows/winrt/MetroInput.h +++ b/widget/windows/winrt/MetroInput.h @@ -8,15 +8,17 @@ // 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 "nsHashKeys.h" // type of key for mTouches #include "mozilla/EventForwards.h" #include "mozilla/layers/APZCTreeManager.h" +#include "mozilla/TouchEvents.h" +#include "mozwrlbase.h" // System headers (alphabetical) #include // EventRegistrationToken #include // uint32_t +#include // ABI::Window::UI::Input namespace #include // Microsoft::WRL::ComPtr class #include // Microsoft::WRL::InspectableClass macro @@ -68,6 +70,41 @@ namespace mozilla { namespace widget { namespace winrt { +class TouchEventQueueEntry { +private: + typedef ABI::Windows::UI::Input::IPointerPoint IPointerPoint; + typedef ABI::Windows::UI::Input::PointerPoint PointerPoint; + typedef ABI::Windows::Foundation::Collections::IVector PointerPointVector; + + Microsoft::WRL::ComPtr mPointerPoints; + Microsoft::WRL::ComPtr mPointerPoint; + nsAutoPtr mTouchEvent; + +public: + TouchEventQueueEntry(WidgetTouchEvent* aTouchEvent, IPointerPoint* aPointerPoint) + : mTouchEvent(aTouchEvent), mPointerPoint(aPointerPoint) + { + } + + TouchEventQueueEntry(WidgetTouchEvent* aTouchEvent, PointerPointVector* aPointerPoints) + : mTouchEvent(aTouchEvent), mPointerPoints(aPointerPoints) + { + } + + IPointerPoint* GetPointerPoint() { + return mPointerPoint.Get(); + } + + PointerPointVector* GetPointerPoints() { + return mPointerPoints.Get(); + } + + WidgetTouchEvent* GetEvent() { + return mTouchEvent; + } +}; + + class MetroInput : public Microsoft::WRL::RuntimeClass { InspectableClass(L"MetroInput", BaseTrust); @@ -79,9 +116,6 @@ private: // 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 \ @@ -103,6 +137,11 @@ private: typedef ABI::Windows::UI::Input::IRightTappedEventArgs IRightTappedEventArgs; typedef ABI::Windows::UI::Input::ITappedEventArgs ITappedEventArgs; typedef ABI::Windows::UI::Input::ManipulationDelta ManipulationDelta; + typedef ABI::Windows::UI::Input::PointerPoint PointerPoint; + + // Foundation + typedef ABI::Windows::Foundation::Point Point; + typedef ABI::Windows::Foundation::Collections::IVector PointerPointVector; typedef mozilla::layers::ScrollableLayerGuid ScrollableLayerGuid; @@ -283,11 +322,12 @@ private: // Async event dispatching void DispatchAsyncEventIgnoreStatus(WidgetInputEvent* aEvent); - void DispatchAsyncTouchEvent(WidgetTouchEvent* aEvent); + void DispatchAsyncTouchEvent(TouchEventQueueEntry* queueEntry); // Async event callbacks void DeliverNextQueuedEventIgnoreStatus(); void DeliverNextQueuedTouchEvent(); + void DeliverNextQueuedNoMoveTouch(); void HandleFirstTouchStartEvent(WidgetTouchEvent* aEvent); void HandleFirstTouchMoveEvent(WidgetTouchEvent* aEvent);