Backed out changeset 2450366cf7ca (bug 1891629) for causing win msix mochitest failures
[gecko.git] / widget / windows / DirectManipulationOwner.cpp
blob569dd4e18997b4ed6d0731398172d7255935c74e
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"
7 #include "nsWindow.h"
8 #include "WinModifierKeyState.h"
9 #include "InputData.h"
10 #include "mozilla/StaticPrefs_apz.h"
11 #include "mozilla/SwipeTracker.h"
12 #include "mozilla/TimeStamp.h"
13 #include "mozilla/VsyncDispatcher.h"
15 #include "directmanipulation.h"
17 namespace mozilla {
18 namespace widget {
20 class DManipEventHandler : public IDirectManipulationViewportEventHandler,
21 public IDirectManipulationInteractionEventHandler {
22 public:
23 typedef mozilla::LayoutDeviceIntRect LayoutDeviceIntRect;
25 friend class DirectManipulationOwner;
27 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DManipEventHandler)
29 STDMETHODIMP QueryInterface(REFIID, void**) override;
31 friend class DirectManipulationOwner;
33 explicit DManipEventHandler(nsWindow* aWindow,
34 DirectManipulationOwner* aOwner,
35 const LayoutDeviceIntRect& aBounds);
37 HRESULT STDMETHODCALLTYPE OnViewportStatusChanged(
38 IDirectManipulationViewport* viewport, DIRECTMANIPULATION_STATUS current,
39 DIRECTMANIPULATION_STATUS previous) override;
41 HRESULT STDMETHODCALLTYPE
42 OnViewportUpdated(IDirectManipulationViewport* viewport) override;
44 HRESULT STDMETHODCALLTYPE
45 OnContentUpdated(IDirectManipulationViewport* viewport,
46 IDirectManipulationContent* content) override;
48 HRESULT STDMETHODCALLTYPE
49 OnInteraction(IDirectManipulationViewport2* viewport,
50 DIRECTMANIPULATION_INTERACTION_TYPE interaction) override;
52 void Update();
54 class VObserver final : public mozilla::VsyncObserver {
55 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DManipEventHandler::VObserver,
56 override)
58 public:
59 void NotifyVsync(const mozilla::VsyncEvent& aVsync) override {
60 if (mOwner) {
61 mOwner->Update();
64 explicit VObserver(DManipEventHandler* aOwner) : mOwner(aOwner) {}
66 void ClearOwner() { mOwner = nullptr; }
68 private:
69 virtual ~VObserver() {}
70 DManipEventHandler* mOwner;
73 enum class State { eNone, ePanning, eInertia, ePinching };
74 void TransitionToState(State aNewState);
76 enum class Phase { eStart, eMiddle, eEnd };
77 // Return value indicates if we sent an event or not and hence if we should
78 // update mLastScale. (We only want to send pinch events if the computed
79 // deltaY for the corresponding WidgetWheelEvent would be non-zero.)
80 bool SendPinch(Phase aPhase, float aScale);
81 void SendPan(Phase aPhase, float x, float y, bool aIsInertia);
82 static void SendPanCommon(nsWindow* aWindow, Phase aPhase,
83 ScreenPoint aPosition, double aDeltaX,
84 double aDeltaY, Modifiers aMods, bool aIsInertia);
86 static void SynthesizeNativeTouchpadPan(
87 nsWindow* aWindow, nsIWidget::TouchpadGesturePhase aEventPhase,
88 LayoutDeviceIntPoint aPoint, double aDeltaX, double aDeltaY,
89 int32_t aModifierFlags);
91 private:
92 virtual ~DManipEventHandler() = default;
94 nsWindow* mWindow;
95 DirectManipulationOwner* mOwner;
96 RefPtr<VObserver> mObserver;
97 float mLastScale;
98 float mLastXOffset;
99 float mLastYOffset;
100 LayoutDeviceIntRect mBounds;
101 bool mShouldSendPanStart;
102 bool mShouldSendPinchStart;
103 State mState = State::eNone;
106 DManipEventHandler::DManipEventHandler(nsWindow* aWindow,
107 DirectManipulationOwner* aOwner,
108 const LayoutDeviceIntRect& aBounds)
109 : mWindow(aWindow),
110 mOwner(aOwner),
111 mLastScale(1.f),
112 mLastXOffset(0.f),
113 mLastYOffset(0.f),
114 mBounds(aBounds),
115 mShouldSendPanStart(false),
116 mShouldSendPinchStart(false) {}
118 STDMETHODIMP
119 DManipEventHandler::QueryInterface(REFIID iid, void** ppv) {
120 const IID IID_IDirectManipulationViewportEventHandler =
121 __uuidof(IDirectManipulationViewportEventHandler);
122 const IID IID_IDirectManipulationInteractionEventHandler =
123 __uuidof(IDirectManipulationInteractionEventHandler);
125 if ((IID_IUnknown == iid) ||
126 (IID_IDirectManipulationViewportEventHandler == iid)) {
127 *ppv = static_cast<IDirectManipulationViewportEventHandler*>(this);
128 AddRef();
129 return S_OK;
131 if (IID_IDirectManipulationInteractionEventHandler == iid) {
132 *ppv = static_cast<IDirectManipulationInteractionEventHandler*>(this);
133 AddRef();
134 return S_OK;
137 return E_NOINTERFACE;
140 HRESULT
141 DManipEventHandler::OnViewportStatusChanged(
142 IDirectManipulationViewport* viewport, DIRECTMANIPULATION_STATUS current,
143 DIRECTMANIPULATION_STATUS previous) {
144 if (current == previous) {
145 return S_OK;
148 if (current == DIRECTMANIPULATION_INERTIA) {
149 if (previous != DIRECTMANIPULATION_RUNNING || mState != State::ePanning) {
150 // xxx transition to none?
151 return S_OK;
154 TransitionToState(State::eInertia);
157 if (current == DIRECTMANIPULATION_RUNNING) {
158 // INERTIA -> RUNNING, should start a new sequence.
159 if (previous == DIRECTMANIPULATION_INERTIA) {
160 TransitionToState(State::eNone);
164 if (current != DIRECTMANIPULATION_ENABLED &&
165 current != DIRECTMANIPULATION_READY) {
166 return S_OK;
169 // A session has ended, reset the transform.
170 if (mLastScale != 1.f || mLastXOffset != 0.f || mLastYOffset != 0.f) {
171 HRESULT hr =
172 viewport->ZoomToRect(0, 0, mBounds.width, mBounds.height, false);
173 if (!SUCCEEDED(hr)) {
174 NS_WARNING("ZoomToRect failed");
177 mLastScale = 1.f;
178 mLastXOffset = 0.f;
179 mLastYOffset = 0.f;
181 TransitionToState(State::eNone);
183 return S_OK;
186 HRESULT
187 DManipEventHandler::OnViewportUpdated(IDirectManipulationViewport* viewport) {
188 return S_OK;
191 void DManipEventHandler::TransitionToState(State aNewState) {
192 if (mState == aNewState) {
193 return;
196 State prevState = mState;
197 mState = aNewState;
199 // End the previous sequence.
200 switch (prevState) {
201 case State::ePanning: {
202 // ePanning -> *: PanEnd
203 SendPan(Phase::eEnd, 0.f, 0.f, false);
204 break;
206 case State::eInertia: {
207 // eInertia -> *: MomentumEnd
208 SendPan(Phase::eEnd, 0.f, 0.f, true);
209 break;
211 case State::ePinching: {
212 MOZ_ASSERT(aNewState == State::eNone);
213 // ePinching -> eNone: PinchEnd. ePinching should only transition to
214 // eNone.
215 // Only send a pinch end if we sent a pinch start.
216 if (!mShouldSendPinchStart) {
217 SendPinch(Phase::eEnd, 0.f);
219 mShouldSendPinchStart = false;
220 break;
222 case State::eNone: {
223 // eNone -> *: no cleanup is needed.
224 break;
226 default:
227 MOZ_ASSERT(false);
230 // Start the new sequence.
231 switch (aNewState) {
232 case State::ePanning: {
233 // eInertia, eNone -> ePanning: PanStart.
234 // We're being called from OnContentUpdated, it has the coords we need to
235 // pass to SendPan(Phase::eStart), so set mShouldSendPanStart and when we
236 // return OnContentUpdated will check it and call SendPan(Phase::eStart).
237 mShouldSendPanStart = true;
238 break;
240 case State::eInertia: {
241 // Only ePanning can transition to eInertia.
242 MOZ_ASSERT(prevState == State::ePanning);
243 SendPan(Phase::eStart, 0.f, 0.f, true);
244 break;
246 case State::ePinching: {
247 // * -> ePinching: PinchStart.
248 // Pinch gesture may begin with some scroll events.
249 // We're being called from OnContentUpdated, it has the scale we need to
250 // pass to SendPinch(Phase::eStart), so set mShouldSendPinchStart and when
251 // we return OnContentUpdated will check it and call
252 // SendPinch(Phase::eStart).
253 mShouldSendPinchStart = true;
254 break;
256 case State::eNone: {
257 // * -> eNone: only cleanup is needed.
258 break;
260 default:
261 MOZ_ASSERT(false);
265 HRESULT
266 DManipEventHandler::OnContentUpdated(IDirectManipulationViewport* viewport,
267 IDirectManipulationContent* content) {
268 float transform[6];
269 HRESULT hr = content->GetContentTransform(transform, ARRAYSIZE(transform));
270 if (!SUCCEEDED(hr)) {
271 NS_WARNING("GetContentTransform failed");
272 return S_OK;
275 float scale = transform[0];
276 float xoffset = transform[4];
277 float yoffset = transform[5];
279 // Not different from last time.
280 if (FuzzyEqualsMultiplicative(scale, mLastScale) && xoffset == mLastXOffset &&
281 yoffset == mLastYOffset) {
282 return S_OK;
285 // Consider this is a Scroll when scale factor equals 1.0.
286 if (FuzzyEqualsMultiplicative(scale, 1.f)) {
287 if (mState == State::eNone) {
288 TransitionToState(State::ePanning);
290 } else {
291 // Pinch gesture may begin with some scroll events.
292 TransitionToState(State::ePinching);
295 if (mState == State::ePanning || mState == State::eInertia) {
296 // Accumulate the offset (by not updating mLastX/YOffset) until we have at
297 // least one pixel.
298 float dx = std::abs(mLastXOffset - xoffset);
299 float dy = std::abs(mLastYOffset - yoffset);
300 if (dx < 1.f && dy < 1.f) {
301 return S_OK;
305 bool updateLastScale = true;
306 if (mState == State::ePanning) {
307 if (mShouldSendPanStart) {
308 SendPan(Phase::eStart, mLastXOffset - xoffset, mLastYOffset - yoffset,
309 false);
310 mShouldSendPanStart = false;
311 } else {
312 SendPan(Phase::eMiddle, mLastXOffset - xoffset, mLastYOffset - yoffset,
313 false);
315 } else if (mState == State::eInertia) {
316 SendPan(Phase::eMiddle, mLastXOffset - xoffset, mLastYOffset - yoffset,
317 true);
318 } else if (mState == State::ePinching) {
319 if (mShouldSendPinchStart) {
320 updateLastScale = SendPinch(Phase::eStart, scale);
321 // Only clear mShouldSendPinchStart if we actually sent the event
322 // (updateLastScale tells us if we sent an event).
323 if (updateLastScale) {
324 mShouldSendPinchStart = false;
326 } else {
327 updateLastScale = SendPinch(Phase::eMiddle, scale);
331 if (updateLastScale) {
332 mLastScale = scale;
334 mLastXOffset = xoffset;
335 mLastYOffset = yoffset;
337 return S_OK;
340 HRESULT
341 DManipEventHandler::OnInteraction(
342 IDirectManipulationViewport2* viewport,
343 DIRECTMANIPULATION_INTERACTION_TYPE interaction) {
344 if (interaction == DIRECTMANIPULATION_INTERACTION_BEGIN) {
345 if (!mObserver) {
346 mObserver = new VObserver(this);
349 gfxWindowsPlatform::GetPlatform()
350 ->GetGlobalVsyncDispatcher()
351 ->AddMainThreadObserver(mObserver);
354 if (mObserver && interaction == DIRECTMANIPULATION_INTERACTION_END) {
355 gfxWindowsPlatform::GetPlatform()
356 ->GetGlobalVsyncDispatcher()
357 ->RemoveMainThreadObserver(mObserver);
360 return S_OK;
363 void DManipEventHandler::Update() {
364 if (mOwner) {
365 mOwner->Update();
369 void DirectManipulationOwner::Update() {
370 if (mDmUpdateManager) {
371 mDmUpdateManager->Update(nullptr);
375 DirectManipulationOwner::DirectManipulationOwner(nsWindow* aWindow)
376 : mWindow(aWindow) {}
378 DirectManipulationOwner::~DirectManipulationOwner() { Destroy(); }
380 bool DManipEventHandler::SendPinch(Phase aPhase, float aScale) {
381 if (!mWindow) {
382 return false;
385 if (aScale == mLastScale && aPhase != Phase::eEnd) {
386 return false;
389 PinchGestureInput::PinchGestureType pinchGestureType =
390 PinchGestureInput::PINCHGESTURE_SCALE;
391 switch (aPhase) {
392 case Phase::eStart:
393 pinchGestureType = PinchGestureInput::PINCHGESTURE_START;
394 break;
395 case Phase::eMiddle:
396 pinchGestureType = PinchGestureInput::PINCHGESTURE_SCALE;
397 break;
398 case Phase::eEnd:
399 pinchGestureType = PinchGestureInput::PINCHGESTURE_END;
400 break;
401 default:
402 MOZ_ASSERT_UNREACHABLE("handle all enum values");
405 TimeStamp eventTimeStamp = TimeStamp::Now();
407 ModifierKeyState modifierKeyState;
408 Modifiers mods = modifierKeyState.GetModifiers();
410 ExternalPoint screenOffset = ViewAs<ExternalPixel>(
411 mWindow->WidgetToScreenOffset(),
412 PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent);
414 POINT cursor_pos;
415 ::GetCursorPos(&cursor_pos);
416 HWND wnd = static_cast<HWND>(mWindow->GetNativeData(NS_NATIVE_WINDOW));
417 ::ScreenToClient(wnd, &cursor_pos);
418 ScreenPoint position = {(float)cursor_pos.x, (float)cursor_pos.y};
420 PinchGestureInput event{pinchGestureType,
421 PinchGestureInput::TRACKPAD,
422 eventTimeStamp,
423 screenOffset,
424 position,
425 100.0 * ((aPhase == Phase::eEnd) ? 1.f : aScale),
426 100.0 * ((aPhase == Phase::eEnd) ? 1.f : mLastScale),
427 mods};
429 if (!event.SetLineOrPageDeltaY(mWindow)) {
430 return false;
433 mWindow->SendAnAPZEvent(event);
435 return true;
438 void DManipEventHandler::SendPan(Phase aPhase, float x, float y,
439 bool aIsInertia) {
440 if (!mWindow) {
441 return;
444 ModifierKeyState modifierKeyState;
445 Modifiers mods = modifierKeyState.GetModifiers();
447 POINT cursor_pos;
448 ::GetCursorPos(&cursor_pos);
449 HWND wnd = static_cast<HWND>(mWindow->GetNativeData(NS_NATIVE_WINDOW));
450 ::ScreenToClient(wnd, &cursor_pos);
451 ScreenPoint position = {(float)cursor_pos.x, (float)cursor_pos.y};
453 SendPanCommon(mWindow, aPhase, position, x, y, mods, aIsInertia);
456 /* static */
457 void DManipEventHandler::SendPanCommon(nsWindow* aWindow, Phase aPhase,
458 ScreenPoint aPosition, double aDeltaX,
459 double aDeltaY, Modifiers aMods,
460 bool aIsInertia) {
461 if (!aWindow) {
462 return;
465 PanGestureInput::PanGestureType panGestureType =
466 PanGestureInput::PANGESTURE_PAN;
467 if (aIsInertia) {
468 switch (aPhase) {
469 case Phase::eStart:
470 panGestureType = PanGestureInput::PANGESTURE_MOMENTUMSTART;
471 break;
472 case Phase::eMiddle:
473 panGestureType = PanGestureInput::PANGESTURE_MOMENTUMPAN;
474 break;
475 case Phase::eEnd:
476 panGestureType = PanGestureInput::PANGESTURE_MOMENTUMEND;
477 break;
478 default:
479 MOZ_ASSERT_UNREACHABLE("handle all enum values");
481 } else {
482 switch (aPhase) {
483 case Phase::eStart:
484 panGestureType = PanGestureInput::PANGESTURE_START;
485 break;
486 case Phase::eMiddle:
487 panGestureType = PanGestureInput::PANGESTURE_PAN;
488 break;
489 case Phase::eEnd:
490 panGestureType = PanGestureInput::PANGESTURE_END;
491 break;
492 default:
493 MOZ_ASSERT_UNREACHABLE("handle all enum values");
497 TimeStamp eventTimeStamp = TimeStamp::Now();
499 PanGestureInput event{panGestureType, eventTimeStamp, aPosition,
500 ScreenPoint(aDeltaX, aDeltaY), aMods};
502 aWindow->SendAnAPZEvent(event);
505 void DirectManipulationOwner::Init(const LayoutDeviceIntRect& aBounds) {
506 HRESULT hr = CoCreateInstance(
507 CLSID_DirectManipulationManager, nullptr, CLSCTX_INPROC_SERVER,
508 IID_IDirectManipulationManager, getter_AddRefs(mDmManager));
509 if (!SUCCEEDED(hr)) {
510 NS_WARNING("CoCreateInstance(CLSID_DirectManipulationManager failed");
511 mDmManager = nullptr;
512 return;
515 hr = mDmManager->GetUpdateManager(IID_IDirectManipulationUpdateManager,
516 getter_AddRefs(mDmUpdateManager));
517 if (!SUCCEEDED(hr)) {
518 NS_WARNING("GetUpdateManager failed");
519 mDmManager = nullptr;
520 mDmUpdateManager = nullptr;
521 return;
524 HWND wnd = static_cast<HWND>(mWindow->GetNativeData(NS_NATIVE_WINDOW));
526 hr = mDmManager->CreateViewport(nullptr, wnd, IID_IDirectManipulationViewport,
527 getter_AddRefs(mDmViewport));
528 if (!SUCCEEDED(hr)) {
529 NS_WARNING("CreateViewport failed");
530 mDmManager = nullptr;
531 mDmUpdateManager = nullptr;
532 mDmViewport = nullptr;
533 return;
536 DIRECTMANIPULATION_CONFIGURATION configuration =
537 DIRECTMANIPULATION_CONFIGURATION_INTERACTION |
538 DIRECTMANIPULATION_CONFIGURATION_TRANSLATION_X |
539 DIRECTMANIPULATION_CONFIGURATION_TRANSLATION_Y |
540 DIRECTMANIPULATION_CONFIGURATION_TRANSLATION_INERTIA |
541 DIRECTMANIPULATION_CONFIGURATION_RAILS_X |
542 DIRECTMANIPULATION_CONFIGURATION_RAILS_Y;
543 if (StaticPrefs::apz_allow_zooming()) {
544 configuration |= DIRECTMANIPULATION_CONFIGURATION_SCALING;
547 hr = mDmViewport->ActivateConfiguration(configuration);
548 if (!SUCCEEDED(hr)) {
549 NS_WARNING("ActivateConfiguration failed");
550 mDmManager = nullptr;
551 mDmUpdateManager = nullptr;
552 mDmViewport = nullptr;
553 return;
556 hr = mDmViewport->SetViewportOptions(
557 DIRECTMANIPULATION_VIEWPORT_OPTIONS_MANUALUPDATE);
558 if (!SUCCEEDED(hr)) {
559 NS_WARNING("SetViewportOptions failed");
560 mDmManager = nullptr;
561 mDmUpdateManager = nullptr;
562 mDmViewport = nullptr;
563 return;
566 mDmHandler = new DManipEventHandler(mWindow, this, aBounds);
568 hr = mDmViewport->AddEventHandler(wnd, mDmHandler.get(),
569 &mDmViewportHandlerCookie);
570 if (!SUCCEEDED(hr)) {
571 NS_WARNING("AddEventHandler failed");
572 mDmManager = nullptr;
573 mDmUpdateManager = nullptr;
574 mDmViewport = nullptr;
575 mDmHandler = nullptr;
576 return;
579 RECT rect = {0, 0, aBounds.Width(), aBounds.Height()};
580 hr = mDmViewport->SetViewportRect(&rect);
581 if (!SUCCEEDED(hr)) {
582 NS_WARNING("SetViewportRect failed");
583 mDmManager = nullptr;
584 mDmUpdateManager = nullptr;
585 mDmViewport = nullptr;
586 mDmHandler = nullptr;
587 return;
590 hr = mDmManager->Activate(wnd);
591 if (!SUCCEEDED(hr)) {
592 NS_WARNING("manager Activate failed");
593 mDmManager = nullptr;
594 mDmUpdateManager = nullptr;
595 mDmViewport = nullptr;
596 mDmHandler = nullptr;
597 return;
600 hr = mDmViewport->Enable();
601 if (!SUCCEEDED(hr)) {
602 NS_WARNING("mDmViewport->Enable failed");
603 mDmManager = nullptr;
604 mDmUpdateManager = nullptr;
605 mDmViewport = nullptr;
606 mDmHandler = nullptr;
607 return;
610 hr = mDmUpdateManager->Update(nullptr);
611 if (!SUCCEEDED(hr)) {
612 NS_WARNING("mDmUpdateManager->Update failed");
613 mDmManager = nullptr;
614 mDmUpdateManager = nullptr;
615 mDmViewport = nullptr;
616 mDmHandler = nullptr;
617 return;
621 void DirectManipulationOwner::ResizeViewport(
622 const LayoutDeviceIntRect& aBounds) {
623 if (mDmHandler) {
624 mDmHandler->mBounds = aBounds;
627 if (mDmViewport) {
628 RECT rect = {0, 0, aBounds.Width(), aBounds.Height()};
629 HRESULT hr = mDmViewport->SetViewportRect(&rect);
630 if (!SUCCEEDED(hr)) {
631 NS_WARNING("SetViewportRect failed");
636 void DirectManipulationOwner::Destroy() {
637 if (mDmHandler) {
638 mDmHandler->mWindow = nullptr;
639 mDmHandler->mOwner = nullptr;
640 if (mDmHandler->mObserver) {
641 gfxWindowsPlatform::GetPlatform()
642 ->GetGlobalVsyncDispatcher()
643 ->RemoveMainThreadObserver(mDmHandler->mObserver);
644 mDmHandler->mObserver->ClearOwner();
645 mDmHandler->mObserver = nullptr;
649 HRESULT hr;
650 if (mDmViewport) {
651 hr = mDmViewport->Stop();
652 if (!SUCCEEDED(hr)) {
653 NS_WARNING("mDmViewport->Stop() failed");
656 hr = mDmViewport->Disable();
657 if (!SUCCEEDED(hr)) {
658 NS_WARNING("mDmViewport->Disable() failed");
661 hr = mDmViewport->RemoveEventHandler(mDmViewportHandlerCookie);
662 if (!SUCCEEDED(hr)) {
663 NS_WARNING("mDmViewport->RemoveEventHandler() failed");
666 hr = mDmViewport->Abandon();
667 if (!SUCCEEDED(hr)) {
668 NS_WARNING("mDmViewport->Abandon() failed");
672 if (mWindow) {
673 HWND wnd = static_cast<HWND>(mWindow->GetNativeData(NS_NATIVE_WINDOW));
675 if (mDmManager) {
676 hr = mDmManager->Deactivate(wnd);
677 if (!SUCCEEDED(hr)) {
678 NS_WARNING("mDmManager->Deactivate() failed");
683 mDmHandler = nullptr;
684 mDmViewport = nullptr;
685 mDmUpdateManager = nullptr;
686 mDmManager = nullptr;
687 mWindow = nullptr;
690 void DirectManipulationOwner::SetContact(UINT aContactId) {
691 if (mDmViewport) {
692 mDmViewport->SetContact(aContactId);
696 /*static */ void DirectManipulationOwner::SynthesizeNativeTouchpadPan(
697 nsWindow* aWindow, nsIWidget::TouchpadGesturePhase aEventPhase,
698 LayoutDeviceIntPoint aPoint, double aDeltaX, double aDeltaY,
699 int32_t aModifierFlags) {
700 DManipEventHandler::SynthesizeNativeTouchpadPan(
701 aWindow, aEventPhase, aPoint, aDeltaX, aDeltaY, aModifierFlags);
704 /*static */ void DManipEventHandler::SynthesizeNativeTouchpadPan(
705 nsWindow* aWindow, nsIWidget::TouchpadGesturePhase aEventPhase,
706 LayoutDeviceIntPoint aPoint, double aDeltaX, double aDeltaY,
707 int32_t aModifierFlags) {
708 ScreenPoint position = {(float)aPoint.x, (float)aPoint.y};
709 Phase phase = Phase::eStart;
710 if (aEventPhase == nsIWidget::PHASE_UPDATE) {
711 phase = Phase::eMiddle;
714 if (aEventPhase == nsIWidget::PHASE_END) {
715 phase = Phase::eEnd;
717 SendPanCommon(aWindow, phase, position, aDeltaX, aDeltaY, aModifierFlags,
718 /* aIsInertia = */ false);
721 } // namespace widget
722 } // namespace mozilla