1 /* -*- Mode: C++; tab-width: 2; 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/. */
6 #include "DirectManipulationOwner.h"
8 #include "WinModifierKeyState.h"
10 #include "mozilla/StaticPrefs_apz.h"
11 #include "mozilla/SwipeTracker.h"
12 #include "mozilla/TimeStamp.h"
13 #include "mozilla/VsyncDispatcher.h"
15 #if !defined(__MINGW32__) && !defined(__MINGW64__)
17 // Direct Manipulation is only defined for Win8 and newer.
18 # if defined(_WIN32_WINNT)
20 # define _WIN32_WINNT _WIN32_WINNT_WIN8
21 # endif // defined(_WIN32_WINNT)
22 # if defined(NTDDI_VERSION)
24 # define NTDDI_VERSION NTDDI_WIN8
25 # endif // defined(NTDDI_VERSION)
27 # include "directmanipulation.h"
29 #endif // !defined(__MINGW32__) && !defined(__MINGW64__)
34 #if !defined(__MINGW32__) && !defined(__MINGW64__)
36 class DManipEventHandler
: public IDirectManipulationViewportEventHandler
,
37 public IDirectManipulationInteractionEventHandler
{
39 typedef mozilla::LayoutDeviceIntRect LayoutDeviceIntRect
;
41 friend class DirectManipulationOwner
;
43 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DManipEventHandler
)
45 STDMETHODIMP
QueryInterface(REFIID
, void**) override
;
47 friend class DirectManipulationOwner
;
49 explicit DManipEventHandler(nsWindow
* aWindow
,
50 DirectManipulationOwner
* aOwner
,
51 const LayoutDeviceIntRect
& aBounds
);
53 HRESULT STDMETHODCALLTYPE
OnViewportStatusChanged(
54 IDirectManipulationViewport
* viewport
, DIRECTMANIPULATION_STATUS current
,
55 DIRECTMANIPULATION_STATUS previous
) override
;
57 HRESULT STDMETHODCALLTYPE
58 OnViewportUpdated(IDirectManipulationViewport
* viewport
) override
;
60 HRESULT STDMETHODCALLTYPE
61 OnContentUpdated(IDirectManipulationViewport
* viewport
,
62 IDirectManipulationContent
* content
) override
;
64 HRESULT STDMETHODCALLTYPE
65 OnInteraction(IDirectManipulationViewport2
* viewport
,
66 DIRECTMANIPULATION_INTERACTION_TYPE interaction
) override
;
70 class VObserver final
: public mozilla::VsyncObserver
{
71 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DManipEventHandler::VObserver
,
75 bool NotifyVsync(const mozilla::VsyncEvent
& aVsync
) override
{
81 explicit VObserver(DManipEventHandler
* aOwner
) : mOwner(aOwner
) {}
83 void ClearOwner() { mOwner
= nullptr; }
86 virtual ~VObserver() {}
87 DManipEventHandler
* mOwner
;
90 enum class State
{ eNone
, ePanning
, eInertia
, ePinching
};
91 void TransitionToState(State aNewState
);
93 enum class Phase
{ eStart
, eMiddle
, eEnd
};
94 // Return value indicates if we sent an event or not and hence if we should
95 // update mLastScale. (We only want to send pinch events if the computed
96 // deltaY for the corresponding WidgetWheelEvent would be non-zero.)
97 bool SendPinch(Phase aPhase
, float aScale
);
98 void SendPan(Phase aPhase
, float x
, float y
, bool aIsInertia
);
99 static void SendPanCommon(nsWindow
* aWindow
, Phase aPhase
,
100 ScreenPoint aPosition
, double aDeltaX
,
101 double aDeltaY
, Modifiers aMods
, bool aIsInertia
);
103 static void SynthesizeNativeTouchpadPan(
104 nsWindow
* aWindow
, nsIWidget::TouchpadGesturePhase aEventPhase
,
105 LayoutDeviceIntPoint aPoint
, double aDeltaX
, double aDeltaY
,
106 int32_t aModifierFlags
);
109 virtual ~DManipEventHandler() = default;
112 DirectManipulationOwner
* mOwner
;
113 RefPtr
<VObserver
> mObserver
;
117 LayoutDeviceIntRect mBounds
;
118 bool mShouldSendPanStart
;
119 bool mShouldSendPinchStart
;
120 State mState
= State::eNone
;
123 DManipEventHandler::DManipEventHandler(nsWindow
* aWindow
,
124 DirectManipulationOwner
* aOwner
,
125 const LayoutDeviceIntRect
& aBounds
)
132 mShouldSendPanStart(false),
133 mShouldSendPinchStart(false) {}
136 DManipEventHandler::QueryInterface(REFIID iid
, void** ppv
) {
137 const IID IID_IDirectManipulationViewportEventHandler
=
138 __uuidof(IDirectManipulationViewportEventHandler
);
139 const IID IID_IDirectManipulationInteractionEventHandler
=
140 __uuidof(IDirectManipulationInteractionEventHandler
);
142 if ((IID_IUnknown
== iid
) ||
143 (IID_IDirectManipulationViewportEventHandler
== iid
)) {
144 *ppv
= static_cast<IDirectManipulationViewportEventHandler
*>(this);
148 if (IID_IDirectManipulationInteractionEventHandler
== iid
) {
149 *ppv
= static_cast<IDirectManipulationInteractionEventHandler
*>(this);
154 return E_NOINTERFACE
;
158 DManipEventHandler::OnViewportStatusChanged(
159 IDirectManipulationViewport
* viewport
, DIRECTMANIPULATION_STATUS current
,
160 DIRECTMANIPULATION_STATUS previous
) {
161 if (current
== previous
) {
165 if (current
== DIRECTMANIPULATION_INERTIA
) {
166 if (previous
!= DIRECTMANIPULATION_RUNNING
|| mState
!= State::ePanning
) {
167 // xxx transition to none?
171 TransitionToState(State::eInertia
);
174 if (current
== DIRECTMANIPULATION_RUNNING
) {
175 // INERTIA -> RUNNING, should start a new sequence.
176 if (previous
== DIRECTMANIPULATION_INERTIA
) {
177 TransitionToState(State::eNone
);
181 if (current
!= DIRECTMANIPULATION_ENABLED
&&
182 current
!= DIRECTMANIPULATION_READY
) {
186 // A session has ended, reset the transform.
187 if (mLastScale
!= 1.f
|| mLastXOffset
!= 0.f
|| mLastYOffset
!= 0.f
) {
189 viewport
->ZoomToRect(0, 0, mBounds
.width
, mBounds
.height
, false);
190 if (!SUCCEEDED(hr
)) {
191 NS_WARNING("ZoomToRect failed");
198 TransitionToState(State::eNone
);
204 DManipEventHandler::OnViewportUpdated(IDirectManipulationViewport
* viewport
) {
208 void DManipEventHandler::TransitionToState(State aNewState
) {
209 if (mState
== aNewState
) {
213 State prevState
= mState
;
216 // End the previous sequence.
218 case State::ePanning
: {
219 // ePanning -> *: PanEnd
220 SendPan(Phase::eEnd
, 0.f
, 0.f
, false);
223 case State::eInertia
: {
224 // eInertia -> *: MomentumEnd
225 SendPan(Phase::eEnd
, 0.f
, 0.f
, true);
228 case State::ePinching
: {
229 MOZ_ASSERT(aNewState
== State::eNone
);
230 // ePinching -> eNone: PinchEnd. ePinching should only transition to
232 // Only send a pinch end if we sent a pinch start.
233 if (!mShouldSendPinchStart
) {
234 SendPinch(Phase::eEnd
, 0.f
);
236 mShouldSendPinchStart
= false;
240 // eNone -> *: no cleanup is needed.
247 // Start the new sequence.
249 case State::ePanning
: {
250 // eInertia, eNone -> ePanning: PanStart.
251 // We're being called from OnContentUpdated, it has the coords we need to
252 // pass to SendPan(Phase::eStart), so set mShouldSendPanStart and when we
253 // return OnContentUpdated will check it and call SendPan(Phase::eStart).
254 mShouldSendPanStart
= true;
257 case State::eInertia
: {
258 // Only ePanning can transition to eInertia.
259 MOZ_ASSERT(prevState
== State::ePanning
);
260 SendPan(Phase::eStart
, 0.f
, 0.f
, true);
263 case State::ePinching
: {
264 // * -> ePinching: PinchStart.
265 // Pinch gesture may begin with some scroll events.
266 // We're being called from OnContentUpdated, it has the scale we need to
267 // pass to SendPinch(Phase::eStart), so set mShouldSendPinchStart and when
268 // we return OnContentUpdated will check it and call
269 // SendPinch(Phase::eStart).
270 mShouldSendPinchStart
= true;
274 // * -> eNone: only cleanup is needed.
283 DManipEventHandler::OnContentUpdated(IDirectManipulationViewport
* viewport
,
284 IDirectManipulationContent
* content
) {
286 HRESULT hr
= content
->GetContentTransform(transform
, ARRAYSIZE(transform
));
287 if (!SUCCEEDED(hr
)) {
288 NS_WARNING("GetContentTransform failed");
292 float scale
= transform
[0];
293 float xoffset
= transform
[4];
294 float yoffset
= transform
[5];
296 // Not different from last time.
297 if (FuzzyEqualsMultiplicative(scale
, mLastScale
) && xoffset
== mLastXOffset
&&
298 yoffset
== mLastYOffset
) {
302 // Consider this is a Scroll when scale factor equals 1.0.
303 if (FuzzyEqualsMultiplicative(scale
, 1.f
)) {
304 if (mState
== State::eNone
) {
305 TransitionToState(State::ePanning
);
308 // Pinch gesture may begin with some scroll events.
309 TransitionToState(State::ePinching
);
312 if (mState
== State::ePanning
|| mState
== State::eInertia
) {
313 // Accumulate the offset (by not updating mLastX/YOffset) until we have at
315 float dx
= std::abs(mLastXOffset
- xoffset
);
316 float dy
= std::abs(mLastYOffset
- yoffset
);
317 if (dx
< 1.f
&& dy
< 1.f
) {
322 bool updateLastScale
= true;
323 if (mState
== State::ePanning
) {
324 if (mShouldSendPanStart
) {
325 SendPan(Phase::eStart
, mLastXOffset
- xoffset
, mLastYOffset
- yoffset
,
327 mShouldSendPanStart
= false;
329 SendPan(Phase::eMiddle
, mLastXOffset
- xoffset
, mLastYOffset
- yoffset
,
332 } else if (mState
== State::eInertia
) {
333 SendPan(Phase::eMiddle
, mLastXOffset
- xoffset
, mLastYOffset
- yoffset
,
335 } else if (mState
== State::ePinching
) {
336 if (mShouldSendPinchStart
) {
337 updateLastScale
= SendPinch(Phase::eStart
, scale
);
338 // Only clear mShouldSendPinchStart if we actually sent the event
339 // (updateLastScale tells us if we sent an event).
340 if (updateLastScale
) {
341 mShouldSendPinchStart
= false;
344 updateLastScale
= SendPinch(Phase::eMiddle
, scale
);
348 if (updateLastScale
) {
351 mLastXOffset
= xoffset
;
352 mLastYOffset
= yoffset
;
358 DManipEventHandler::OnInteraction(
359 IDirectManipulationViewport2
* viewport
,
360 DIRECTMANIPULATION_INTERACTION_TYPE interaction
) {
361 if (interaction
== DIRECTMANIPULATION_INTERACTION_BEGIN
) {
363 mObserver
= new VObserver(this);
366 gfxWindowsPlatform::GetPlatform()->GetHardwareVsync()->AddGenericObserver(
370 if (mObserver
&& interaction
== DIRECTMANIPULATION_INTERACTION_END
) {
371 gfxWindowsPlatform::GetPlatform()
373 ->RemoveGenericObserver(mObserver
);
379 void DManipEventHandler::Update() {
385 #endif // !defined(__MINGW32__) && !defined(__MINGW64__)
387 void DirectManipulationOwner::Update() {
388 #if !defined(__MINGW32__) && !defined(__MINGW64__)
389 if (mDmUpdateManager
) {
390 mDmUpdateManager
->Update(nullptr);
395 DirectManipulationOwner::DirectManipulationOwner(nsWindow
* aWindow
)
396 : mWindow(aWindow
) {}
398 DirectManipulationOwner::~DirectManipulationOwner() { Destroy(); }
400 #if !defined(__MINGW32__) && !defined(__MINGW64__)
402 bool DManipEventHandler::SendPinch(Phase aPhase
, float aScale
) {
407 if (aScale
== mLastScale
&& aPhase
!= Phase::eEnd
) {
411 PinchGestureInput::PinchGestureType pinchGestureType
=
412 PinchGestureInput::PINCHGESTURE_SCALE
;
415 pinchGestureType
= PinchGestureInput::PINCHGESTURE_START
;
418 pinchGestureType
= PinchGestureInput::PINCHGESTURE_SCALE
;
421 pinchGestureType
= PinchGestureInput::PINCHGESTURE_END
;
424 MOZ_ASSERT_UNREACHABLE("handle all enum values");
427 PRIntervalTime eventIntervalTime
= PR_IntervalNow();
428 TimeStamp eventTimeStamp
= TimeStamp::Now();
430 ModifierKeyState modifierKeyState
;
431 Modifiers mods
= modifierKeyState
.GetModifiers();
433 ExternalPoint screenOffset
= ViewAs
<ExternalPixel
>(
434 mWindow
->WidgetToScreenOffset(),
435 PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent
);
438 ::GetCursorPos(&cursor_pos
);
439 HWND wnd
= static_cast<HWND
>(mWindow
->GetNativeData(NS_NATIVE_WINDOW
));
440 ::ScreenToClient(wnd
, &cursor_pos
);
441 ScreenPoint position
= {(float)cursor_pos
.x
, (float)cursor_pos
.y
};
443 PinchGestureInput event
{pinchGestureType
,
444 PinchGestureInput::TRACKPAD
,
449 100.0 * ((aPhase
== Phase::eEnd
) ? 1.f
: aScale
),
450 100.0 * ((aPhase
== Phase::eEnd
) ? 1.f
: mLastScale
),
453 if (!event
.SetLineOrPageDeltaY(mWindow
)) {
457 mWindow
->SendAnAPZEvent(event
);
462 void DManipEventHandler::SendPan(Phase aPhase
, float x
, float y
,
468 ModifierKeyState modifierKeyState
;
469 Modifiers mods
= modifierKeyState
.GetModifiers();
472 ::GetCursorPos(&cursor_pos
);
473 HWND wnd
= static_cast<HWND
>(mWindow
->GetNativeData(NS_NATIVE_WINDOW
));
474 ::ScreenToClient(wnd
, &cursor_pos
);
475 ScreenPoint position
= {(float)cursor_pos
.x
, (float)cursor_pos
.y
};
477 SendPanCommon(mWindow
, aPhase
, position
, x
, y
, mods
, aIsInertia
);
481 void DManipEventHandler::SendPanCommon(nsWindow
* aWindow
, Phase aPhase
,
482 ScreenPoint aPosition
, double aDeltaX
,
483 double aDeltaY
, Modifiers aMods
,
489 PanGestureInput::PanGestureType panGestureType
=
490 PanGestureInput::PANGESTURE_PAN
;
494 panGestureType
= PanGestureInput::PANGESTURE_MOMENTUMSTART
;
497 panGestureType
= PanGestureInput::PANGESTURE_MOMENTUMPAN
;
500 panGestureType
= PanGestureInput::PANGESTURE_MOMENTUMEND
;
503 MOZ_ASSERT_UNREACHABLE("handle all enum values");
508 panGestureType
= PanGestureInput::PANGESTURE_START
;
511 panGestureType
= PanGestureInput::PANGESTURE_PAN
;
514 panGestureType
= PanGestureInput::PANGESTURE_END
;
517 MOZ_ASSERT_UNREACHABLE("handle all enum values");
521 PRIntervalTime eventIntervalTime
= PR_IntervalNow();
522 TimeStamp eventTimeStamp
= TimeStamp::Now();
524 PanGestureInput event
{panGestureType
,
528 ScreenPoint(aDeltaX
, aDeltaY
),
531 // This `SendPanCommon` gets called only if the Windows setting, "Drag two
532 // fingers to scroll" option, is enabled (or it gets called in tests), so we
533 // don't need to explicitly check whether the option is enabled or not here.
534 event
.mRequiresContentResponseIfCannotScrollHorizontallyInStartDirection
=
535 SwipeTracker::CanTriggerSwipe(event
);
537 aWindow
->SendAnAPZEvent(event
);
540 #endif // !defined(__MINGW32__) && !defined(__MINGW64__)
542 void DirectManipulationOwner::Init(const LayoutDeviceIntRect
& aBounds
) {
543 #if !defined(__MINGW32__) && !defined(__MINGW64__)
544 HRESULT hr
= CoCreateInstance(
545 CLSID_DirectManipulationManager
, nullptr, CLSCTX_INPROC_SERVER
,
546 IID_IDirectManipulationManager
, getter_AddRefs(mDmManager
));
547 if (!SUCCEEDED(hr
)) {
548 NS_WARNING("CoCreateInstance(CLSID_DirectManipulationManager failed");
549 mDmManager
= nullptr;
553 hr
= mDmManager
->GetUpdateManager(IID_IDirectManipulationUpdateManager
,
554 getter_AddRefs(mDmUpdateManager
));
555 if (!SUCCEEDED(hr
)) {
556 NS_WARNING("GetUpdateManager failed");
557 mDmManager
= nullptr;
558 mDmUpdateManager
= nullptr;
562 HWND wnd
= static_cast<HWND
>(mWindow
->GetNativeData(NS_NATIVE_WINDOW
));
564 hr
= mDmManager
->CreateViewport(nullptr, wnd
, IID_IDirectManipulationViewport
,
565 getter_AddRefs(mDmViewport
));
566 if (!SUCCEEDED(hr
)) {
567 NS_WARNING("CreateViewport failed");
568 mDmManager
= nullptr;
569 mDmUpdateManager
= nullptr;
570 mDmViewport
= nullptr;
574 DIRECTMANIPULATION_CONFIGURATION configuration
=
575 DIRECTMANIPULATION_CONFIGURATION_INTERACTION
|
576 DIRECTMANIPULATION_CONFIGURATION_TRANSLATION_X
|
577 DIRECTMANIPULATION_CONFIGURATION_TRANSLATION_Y
|
578 DIRECTMANIPULATION_CONFIGURATION_TRANSLATION_INERTIA
|
579 DIRECTMANIPULATION_CONFIGURATION_RAILS_X
|
580 DIRECTMANIPULATION_CONFIGURATION_RAILS_Y
;
581 if (StaticPrefs::apz_allow_zooming()) {
582 configuration
|= DIRECTMANIPULATION_CONFIGURATION_SCALING
;
585 hr
= mDmViewport
->ActivateConfiguration(configuration
);
586 if (!SUCCEEDED(hr
)) {
587 NS_WARNING("ActivateConfiguration failed");
588 mDmManager
= nullptr;
589 mDmUpdateManager
= nullptr;
590 mDmViewport
= nullptr;
594 hr
= mDmViewport
->SetViewportOptions(
595 DIRECTMANIPULATION_VIEWPORT_OPTIONS_MANUALUPDATE
);
596 if (!SUCCEEDED(hr
)) {
597 NS_WARNING("SetViewportOptions failed");
598 mDmManager
= nullptr;
599 mDmUpdateManager
= nullptr;
600 mDmViewport
= nullptr;
604 mDmHandler
= new DManipEventHandler(mWindow
, this, aBounds
);
606 hr
= mDmViewport
->AddEventHandler(wnd
, mDmHandler
.get(),
607 &mDmViewportHandlerCookie
);
608 if (!SUCCEEDED(hr
)) {
609 NS_WARNING("AddEventHandler failed");
610 mDmManager
= nullptr;
611 mDmUpdateManager
= nullptr;
612 mDmViewport
= nullptr;
613 mDmHandler
= nullptr;
617 RECT rect
= {0, 0, aBounds
.Width(), aBounds
.Height()};
618 hr
= mDmViewport
->SetViewportRect(&rect
);
619 if (!SUCCEEDED(hr
)) {
620 NS_WARNING("SetViewportRect failed");
621 mDmManager
= nullptr;
622 mDmUpdateManager
= nullptr;
623 mDmViewport
= nullptr;
624 mDmHandler
= nullptr;
628 hr
= mDmManager
->Activate(wnd
);
629 if (!SUCCEEDED(hr
)) {
630 NS_WARNING("manager Activate failed");
631 mDmManager
= nullptr;
632 mDmUpdateManager
= nullptr;
633 mDmViewport
= nullptr;
634 mDmHandler
= nullptr;
638 hr
= mDmViewport
->Enable();
639 if (!SUCCEEDED(hr
)) {
640 NS_WARNING("mDmViewport->Enable failed");
641 mDmManager
= nullptr;
642 mDmUpdateManager
= nullptr;
643 mDmViewport
= nullptr;
644 mDmHandler
= nullptr;
648 hr
= mDmUpdateManager
->Update(nullptr);
649 if (!SUCCEEDED(hr
)) {
650 NS_WARNING("mDmUpdateManager->Update failed");
651 mDmManager
= nullptr;
652 mDmUpdateManager
= nullptr;
653 mDmViewport
= nullptr;
654 mDmHandler
= nullptr;
657 #endif // !defined(__MINGW32__) && !defined(__MINGW64__)
660 void DirectManipulationOwner::ResizeViewport(
661 const LayoutDeviceIntRect
& aBounds
) {
662 #if !defined(__MINGW32__) && !defined(__MINGW64__)
664 mDmHandler
->mBounds
= aBounds
;
668 RECT rect
= {0, 0, aBounds
.Width(), aBounds
.Height()};
669 HRESULT hr
= mDmViewport
->SetViewportRect(&rect
);
670 if (!SUCCEEDED(hr
)) {
671 NS_WARNING("SetViewportRect failed");
677 void DirectManipulationOwner::Destroy() {
678 #if !defined(__MINGW32__) && !defined(__MINGW64__)
680 mDmHandler
->mWindow
= nullptr;
681 mDmHandler
->mOwner
= nullptr;
682 if (mDmHandler
->mObserver
) {
683 gfxWindowsPlatform::GetPlatform()
685 ->RemoveGenericObserver(mDmHandler
->mObserver
);
686 mDmHandler
->mObserver
->ClearOwner();
687 mDmHandler
->mObserver
= nullptr;
693 hr
= mDmViewport
->Stop();
694 if (!SUCCEEDED(hr
)) {
695 NS_WARNING("mDmViewport->Stop() failed");
698 hr
= mDmViewport
->Disable();
699 if (!SUCCEEDED(hr
)) {
700 NS_WARNING("mDmViewport->Disable() failed");
703 hr
= mDmViewport
->RemoveEventHandler(mDmViewportHandlerCookie
);
704 if (!SUCCEEDED(hr
)) {
705 NS_WARNING("mDmViewport->RemoveEventHandler() failed");
708 hr
= mDmViewport
->Abandon();
709 if (!SUCCEEDED(hr
)) {
710 NS_WARNING("mDmViewport->Abandon() failed");
715 HWND wnd
= static_cast<HWND
>(mWindow
->GetNativeData(NS_NATIVE_WINDOW
));
718 hr
= mDmManager
->Deactivate(wnd
);
719 if (!SUCCEEDED(hr
)) {
720 NS_WARNING("mDmManager->Deactivate() failed");
725 mDmHandler
= nullptr;
726 mDmViewport
= nullptr;
727 mDmUpdateManager
= nullptr;
728 mDmManager
= nullptr;
729 #endif // !defined(__MINGW32__) && !defined(__MINGW64__)
733 void DirectManipulationOwner::SetContact(UINT aContactId
) {
734 #if !defined(__MINGW32__) && !defined(__MINGW64__)
736 mDmViewport
->SetContact(aContactId
);
741 /*static */ void DirectManipulationOwner::SynthesizeNativeTouchpadPan(
742 nsWindow
* aWindow
, nsIWidget::TouchpadGesturePhase aEventPhase
,
743 LayoutDeviceIntPoint aPoint
, double aDeltaX
, double aDeltaY
,
744 int32_t aModifierFlags
) {
745 #if !defined(__MINGW32__) && !defined(__MINGW64__)
746 DManipEventHandler::SynthesizeNativeTouchpadPan(
747 aWindow
, aEventPhase
, aPoint
, aDeltaX
, aDeltaY
, aModifierFlags
);
751 #if !defined(__MINGW32__) && !defined(__MINGW64__)
752 /*static */ void DManipEventHandler::SynthesizeNativeTouchpadPan(
753 nsWindow
* aWindow
, nsIWidget::TouchpadGesturePhase aEventPhase
,
754 LayoutDeviceIntPoint aPoint
, double aDeltaX
, double aDeltaY
,
755 int32_t aModifierFlags
) {
756 ScreenPoint position
= {(float)aPoint
.x
, (float)aPoint
.y
};
757 Phase phase
= Phase::eStart
;
758 if (aEventPhase
== nsIWidget::PHASE_UPDATE
) {
759 phase
= Phase::eMiddle
;
762 if (aEventPhase
== nsIWidget::PHASE_END
) {
765 SendPanCommon(aWindow
, phase
, position
, aDeltaX
, aDeltaY
, aModifierFlags
,
766 /* aIsInertia = */ false);
770 } // namespace widget
771 } // namespace mozilla