Bug 1777519 [wpt PR 34660] - Avoid OSError from --kill-safari stat'ing random paths...
[gecko.git] / widget / windows / DirectManipulationOwner.cpp
blob3bda193d3aa65b45a83b19bb362af3ea21e222d4
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 // Direct Manipulation is only defined for Win8 and newer.
16 #if defined(_WIN32_WINNT)
17 # undef _WIN32_WINNT
18 # define _WIN32_WINNT _WIN32_WINNT_WIN8
19 #endif // defined(_WIN32_WINNT)
20 #if defined(NTDDI_VERSION)
21 # undef NTDDI_VERSION
22 # define NTDDI_VERSION NTDDI_WIN8
23 #endif // defined(NTDDI_VERSION)
25 #include "directmanipulation.h"
27 namespace mozilla {
28 namespace widget {
30 class DManipEventHandler : public IDirectManipulationViewportEventHandler,
31 public IDirectManipulationInteractionEventHandler {
32 public:
33 typedef mozilla::LayoutDeviceIntRect LayoutDeviceIntRect;
35 friend class DirectManipulationOwner;
37 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DManipEventHandler)
39 STDMETHODIMP QueryInterface(REFIID, void**) override;
41 friend class DirectManipulationOwner;
43 explicit DManipEventHandler(nsWindow* aWindow,
44 DirectManipulationOwner* aOwner,
45 const LayoutDeviceIntRect& aBounds);
47 HRESULT STDMETHODCALLTYPE OnViewportStatusChanged(
48 IDirectManipulationViewport* viewport, DIRECTMANIPULATION_STATUS current,
49 DIRECTMANIPULATION_STATUS previous) override;
51 HRESULT STDMETHODCALLTYPE
52 OnViewportUpdated(IDirectManipulationViewport* viewport) override;
54 HRESULT STDMETHODCALLTYPE
55 OnContentUpdated(IDirectManipulationViewport* viewport,
56 IDirectManipulationContent* content) override;
58 HRESULT STDMETHODCALLTYPE
59 OnInteraction(IDirectManipulationViewport2* viewport,
60 DIRECTMANIPULATION_INTERACTION_TYPE interaction) override;
62 void Update();
64 class VObserver final : public mozilla::VsyncObserver {
65 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DManipEventHandler::VObserver,
66 override)
68 public:
69 void NotifyVsync(const mozilla::VsyncEvent& aVsync) override {
70 if (mOwner) {
71 mOwner->Update();
74 explicit VObserver(DManipEventHandler* aOwner) : mOwner(aOwner) {}
76 void ClearOwner() { mOwner = nullptr; }
78 private:
79 virtual ~VObserver() {}
80 DManipEventHandler* mOwner;
83 enum class State { eNone, ePanning, eInertia, ePinching };
84 void TransitionToState(State aNewState);
86 enum class Phase { eStart, eMiddle, eEnd };
87 // Return value indicates if we sent an event or not and hence if we should
88 // update mLastScale. (We only want to send pinch events if the computed
89 // deltaY for the corresponding WidgetWheelEvent would be non-zero.)
90 bool SendPinch(Phase aPhase, float aScale);
91 void SendPan(Phase aPhase, float x, float y, bool aIsInertia);
92 static void SendPanCommon(nsWindow* aWindow, Phase aPhase,
93 ScreenPoint aPosition, double aDeltaX,
94 double aDeltaY, Modifiers aMods, bool aIsInertia);
96 static void SynthesizeNativeTouchpadPan(
97 nsWindow* aWindow, nsIWidget::TouchpadGesturePhase aEventPhase,
98 LayoutDeviceIntPoint aPoint, double aDeltaX, double aDeltaY,
99 int32_t aModifierFlags);
101 private:
102 virtual ~DManipEventHandler() = default;
104 nsWindow* mWindow;
105 DirectManipulationOwner* mOwner;
106 RefPtr<VObserver> mObserver;
107 float mLastScale;
108 float mLastXOffset;
109 float mLastYOffset;
110 LayoutDeviceIntRect mBounds;
111 bool mShouldSendPanStart;
112 bool mShouldSendPinchStart;
113 State mState = State::eNone;
116 DManipEventHandler::DManipEventHandler(nsWindow* aWindow,
117 DirectManipulationOwner* aOwner,
118 const LayoutDeviceIntRect& aBounds)
119 : mWindow(aWindow),
120 mOwner(aOwner),
121 mLastScale(1.f),
122 mLastXOffset(0.f),
123 mLastYOffset(0.f),
124 mBounds(aBounds),
125 mShouldSendPanStart(false),
126 mShouldSendPinchStart(false) {}
128 STDMETHODIMP
129 DManipEventHandler::QueryInterface(REFIID iid, void** ppv) {
130 const IID IID_IDirectManipulationViewportEventHandler =
131 __uuidof(IDirectManipulationViewportEventHandler);
132 const IID IID_IDirectManipulationInteractionEventHandler =
133 __uuidof(IDirectManipulationInteractionEventHandler);
135 if ((IID_IUnknown == iid) ||
136 (IID_IDirectManipulationViewportEventHandler == iid)) {
137 *ppv = static_cast<IDirectManipulationViewportEventHandler*>(this);
138 AddRef();
139 return S_OK;
141 if (IID_IDirectManipulationInteractionEventHandler == iid) {
142 *ppv = static_cast<IDirectManipulationInteractionEventHandler*>(this);
143 AddRef();
144 return S_OK;
147 return E_NOINTERFACE;
150 HRESULT
151 DManipEventHandler::OnViewportStatusChanged(
152 IDirectManipulationViewport* viewport, DIRECTMANIPULATION_STATUS current,
153 DIRECTMANIPULATION_STATUS previous) {
154 if (current == previous) {
155 return S_OK;
158 if (current == DIRECTMANIPULATION_INERTIA) {
159 if (previous != DIRECTMANIPULATION_RUNNING || mState != State::ePanning) {
160 // xxx transition to none?
161 return S_OK;
164 TransitionToState(State::eInertia);
167 if (current == DIRECTMANIPULATION_RUNNING) {
168 // INERTIA -> RUNNING, should start a new sequence.
169 if (previous == DIRECTMANIPULATION_INERTIA) {
170 TransitionToState(State::eNone);
174 if (current != DIRECTMANIPULATION_ENABLED &&
175 current != DIRECTMANIPULATION_READY) {
176 return S_OK;
179 // A session has ended, reset the transform.
180 if (mLastScale != 1.f || mLastXOffset != 0.f || mLastYOffset != 0.f) {
181 HRESULT hr =
182 viewport->ZoomToRect(0, 0, mBounds.width, mBounds.height, false);
183 if (!SUCCEEDED(hr)) {
184 NS_WARNING("ZoomToRect failed");
187 mLastScale = 1.f;
188 mLastXOffset = 0.f;
189 mLastYOffset = 0.f;
191 TransitionToState(State::eNone);
193 return S_OK;
196 HRESULT
197 DManipEventHandler::OnViewportUpdated(IDirectManipulationViewport* viewport) {
198 return S_OK;
201 void DManipEventHandler::TransitionToState(State aNewState) {
202 if (mState == aNewState) {
203 return;
206 State prevState = mState;
207 mState = aNewState;
209 // End the previous sequence.
210 switch (prevState) {
211 case State::ePanning: {
212 // ePanning -> *: PanEnd
213 SendPan(Phase::eEnd, 0.f, 0.f, false);
214 break;
216 case State::eInertia: {
217 // eInertia -> *: MomentumEnd
218 SendPan(Phase::eEnd, 0.f, 0.f, true);
219 break;
221 case State::ePinching: {
222 MOZ_ASSERT(aNewState == State::eNone);
223 // ePinching -> eNone: PinchEnd. ePinching should only transition to
224 // eNone.
225 // Only send a pinch end if we sent a pinch start.
226 if (!mShouldSendPinchStart) {
227 SendPinch(Phase::eEnd, 0.f);
229 mShouldSendPinchStart = false;
230 break;
232 case State::eNone: {
233 // eNone -> *: no cleanup is needed.
234 break;
236 default:
237 MOZ_ASSERT(false);
240 // Start the new sequence.
241 switch (aNewState) {
242 case State::ePanning: {
243 // eInertia, eNone -> ePanning: PanStart.
244 // We're being called from OnContentUpdated, it has the coords we need to
245 // pass to SendPan(Phase::eStart), so set mShouldSendPanStart and when we
246 // return OnContentUpdated will check it and call SendPan(Phase::eStart).
247 mShouldSendPanStart = true;
248 break;
250 case State::eInertia: {
251 // Only ePanning can transition to eInertia.
252 MOZ_ASSERT(prevState == State::ePanning);
253 SendPan(Phase::eStart, 0.f, 0.f, true);
254 break;
256 case State::ePinching: {
257 // * -> ePinching: PinchStart.
258 // Pinch gesture may begin with some scroll events.
259 // We're being called from OnContentUpdated, it has the scale we need to
260 // pass to SendPinch(Phase::eStart), so set mShouldSendPinchStart and when
261 // we return OnContentUpdated will check it and call
262 // SendPinch(Phase::eStart).
263 mShouldSendPinchStart = true;
264 break;
266 case State::eNone: {
267 // * -> eNone: only cleanup is needed.
268 break;
270 default:
271 MOZ_ASSERT(false);
275 HRESULT
276 DManipEventHandler::OnContentUpdated(IDirectManipulationViewport* viewport,
277 IDirectManipulationContent* content) {
278 float transform[6];
279 HRESULT hr = content->GetContentTransform(transform, ARRAYSIZE(transform));
280 if (!SUCCEEDED(hr)) {
281 NS_WARNING("GetContentTransform failed");
282 return S_OK;
285 float scale = transform[0];
286 float xoffset = transform[4];
287 float yoffset = transform[5];
289 // Not different from last time.
290 if (FuzzyEqualsMultiplicative(scale, mLastScale) && xoffset == mLastXOffset &&
291 yoffset == mLastYOffset) {
292 return S_OK;
295 // Consider this is a Scroll when scale factor equals 1.0.
296 if (FuzzyEqualsMultiplicative(scale, 1.f)) {
297 if (mState == State::eNone) {
298 TransitionToState(State::ePanning);
300 } else {
301 // Pinch gesture may begin with some scroll events.
302 TransitionToState(State::ePinching);
305 if (mState == State::ePanning || mState == State::eInertia) {
306 // Accumulate the offset (by not updating mLastX/YOffset) until we have at
307 // least one pixel.
308 float dx = std::abs(mLastXOffset - xoffset);
309 float dy = std::abs(mLastYOffset - yoffset);
310 if (dx < 1.f && dy < 1.f) {
311 return S_OK;
315 bool updateLastScale = true;
316 if (mState == State::ePanning) {
317 if (mShouldSendPanStart) {
318 SendPan(Phase::eStart, mLastXOffset - xoffset, mLastYOffset - yoffset,
319 false);
320 mShouldSendPanStart = false;
321 } else {
322 SendPan(Phase::eMiddle, mLastXOffset - xoffset, mLastYOffset - yoffset,
323 false);
325 } else if (mState == State::eInertia) {
326 SendPan(Phase::eMiddle, mLastXOffset - xoffset, mLastYOffset - yoffset,
327 true);
328 } else if (mState == State::ePinching) {
329 if (mShouldSendPinchStart) {
330 updateLastScale = SendPinch(Phase::eStart, scale);
331 // Only clear mShouldSendPinchStart if we actually sent the event
332 // (updateLastScale tells us if we sent an event).
333 if (updateLastScale) {
334 mShouldSendPinchStart = false;
336 } else {
337 updateLastScale = SendPinch(Phase::eMiddle, scale);
341 if (updateLastScale) {
342 mLastScale = scale;
344 mLastXOffset = xoffset;
345 mLastYOffset = yoffset;
347 return S_OK;
350 HRESULT
351 DManipEventHandler::OnInteraction(
352 IDirectManipulationViewport2* viewport,
353 DIRECTMANIPULATION_INTERACTION_TYPE interaction) {
354 if (interaction == DIRECTMANIPULATION_INTERACTION_BEGIN) {
355 if (!mObserver) {
356 mObserver = new VObserver(this);
359 gfxWindowsPlatform::GetPlatform()
360 ->GetGlobalVsyncDispatcher()
361 ->AddMainThreadObserver(mObserver);
364 if (mObserver && interaction == DIRECTMANIPULATION_INTERACTION_END) {
365 gfxWindowsPlatform::GetPlatform()
366 ->GetGlobalVsyncDispatcher()
367 ->RemoveMainThreadObserver(mObserver);
370 return S_OK;
373 void DManipEventHandler::Update() {
374 if (mOwner) {
375 mOwner->Update();
379 void DirectManipulationOwner::Update() {
380 if (mDmUpdateManager) {
381 mDmUpdateManager->Update(nullptr);
385 DirectManipulationOwner::DirectManipulationOwner(nsWindow* aWindow)
386 : mWindow(aWindow) {}
388 DirectManipulationOwner::~DirectManipulationOwner() { Destroy(); }
390 bool DManipEventHandler::SendPinch(Phase aPhase, float aScale) {
391 if (!mWindow) {
392 return false;
395 if (aScale == mLastScale && aPhase != Phase::eEnd) {
396 return false;
399 PinchGestureInput::PinchGestureType pinchGestureType =
400 PinchGestureInput::PINCHGESTURE_SCALE;
401 switch (aPhase) {
402 case Phase::eStart:
403 pinchGestureType = PinchGestureInput::PINCHGESTURE_START;
404 break;
405 case Phase::eMiddle:
406 pinchGestureType = PinchGestureInput::PINCHGESTURE_SCALE;
407 break;
408 case Phase::eEnd:
409 pinchGestureType = PinchGestureInput::PINCHGESTURE_END;
410 break;
411 default:
412 MOZ_ASSERT_UNREACHABLE("handle all enum values");
415 TimeStamp eventTimeStamp = TimeStamp::Now();
417 ModifierKeyState modifierKeyState;
418 Modifiers mods = modifierKeyState.GetModifiers();
420 ExternalPoint screenOffset = ViewAs<ExternalPixel>(
421 mWindow->WidgetToScreenOffset(),
422 PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent);
424 POINT cursor_pos;
425 ::GetCursorPos(&cursor_pos);
426 HWND wnd = static_cast<HWND>(mWindow->GetNativeData(NS_NATIVE_WINDOW));
427 ::ScreenToClient(wnd, &cursor_pos);
428 ScreenPoint position = {(float)cursor_pos.x, (float)cursor_pos.y};
430 PinchGestureInput event{pinchGestureType,
431 PinchGestureInput::TRACKPAD,
432 eventTimeStamp,
433 screenOffset,
434 position,
435 100.0 * ((aPhase == Phase::eEnd) ? 1.f : aScale),
436 100.0 * ((aPhase == Phase::eEnd) ? 1.f : mLastScale),
437 mods};
439 if (!event.SetLineOrPageDeltaY(mWindow)) {
440 return false;
443 mWindow->SendAnAPZEvent(event);
445 return true;
448 void DManipEventHandler::SendPan(Phase aPhase, float x, float y,
449 bool aIsInertia) {
450 if (!mWindow) {
451 return;
454 ModifierKeyState modifierKeyState;
455 Modifiers mods = modifierKeyState.GetModifiers();
457 POINT cursor_pos;
458 ::GetCursorPos(&cursor_pos);
459 HWND wnd = static_cast<HWND>(mWindow->GetNativeData(NS_NATIVE_WINDOW));
460 ::ScreenToClient(wnd, &cursor_pos);
461 ScreenPoint position = {(float)cursor_pos.x, (float)cursor_pos.y};
463 SendPanCommon(mWindow, aPhase, position, x, y, mods, aIsInertia);
466 /* static */
467 void DManipEventHandler::SendPanCommon(nsWindow* aWindow, Phase aPhase,
468 ScreenPoint aPosition, double aDeltaX,
469 double aDeltaY, Modifiers aMods,
470 bool aIsInertia) {
471 if (!aWindow) {
472 return;
475 PanGestureInput::PanGestureType panGestureType =
476 PanGestureInput::PANGESTURE_PAN;
477 if (aIsInertia) {
478 switch (aPhase) {
479 case Phase::eStart:
480 panGestureType = PanGestureInput::PANGESTURE_MOMENTUMSTART;
481 break;
482 case Phase::eMiddle:
483 panGestureType = PanGestureInput::PANGESTURE_MOMENTUMPAN;
484 break;
485 case Phase::eEnd:
486 panGestureType = PanGestureInput::PANGESTURE_MOMENTUMEND;
487 break;
488 default:
489 MOZ_ASSERT_UNREACHABLE("handle all enum values");
491 } else {
492 switch (aPhase) {
493 case Phase::eStart:
494 panGestureType = PanGestureInput::PANGESTURE_START;
495 break;
496 case Phase::eMiddle:
497 panGestureType = PanGestureInput::PANGESTURE_PAN;
498 break;
499 case Phase::eEnd:
500 panGestureType = PanGestureInput::PANGESTURE_END;
501 break;
502 default:
503 MOZ_ASSERT_UNREACHABLE("handle all enum values");
507 TimeStamp eventTimeStamp = TimeStamp::Now();
509 PanGestureInput event{panGestureType, eventTimeStamp, aPosition,
510 ScreenPoint(aDeltaX, aDeltaY), aMods};
512 aWindow->SendAnAPZEvent(event);
515 void DirectManipulationOwner::Init(const LayoutDeviceIntRect& aBounds) {
516 HRESULT hr = CoCreateInstance(
517 CLSID_DirectManipulationManager, nullptr, CLSCTX_INPROC_SERVER,
518 IID_IDirectManipulationManager, getter_AddRefs(mDmManager));
519 if (!SUCCEEDED(hr)) {
520 NS_WARNING("CoCreateInstance(CLSID_DirectManipulationManager failed");
521 mDmManager = nullptr;
522 return;
525 hr = mDmManager->GetUpdateManager(IID_IDirectManipulationUpdateManager,
526 getter_AddRefs(mDmUpdateManager));
527 if (!SUCCEEDED(hr)) {
528 NS_WARNING("GetUpdateManager failed");
529 mDmManager = nullptr;
530 mDmUpdateManager = nullptr;
531 return;
534 HWND wnd = static_cast<HWND>(mWindow->GetNativeData(NS_NATIVE_WINDOW));
536 hr = mDmManager->CreateViewport(nullptr, wnd, IID_IDirectManipulationViewport,
537 getter_AddRefs(mDmViewport));
538 if (!SUCCEEDED(hr)) {
539 NS_WARNING("CreateViewport failed");
540 mDmManager = nullptr;
541 mDmUpdateManager = nullptr;
542 mDmViewport = nullptr;
543 return;
546 DIRECTMANIPULATION_CONFIGURATION configuration =
547 DIRECTMANIPULATION_CONFIGURATION_INTERACTION |
548 DIRECTMANIPULATION_CONFIGURATION_TRANSLATION_X |
549 DIRECTMANIPULATION_CONFIGURATION_TRANSLATION_Y |
550 DIRECTMANIPULATION_CONFIGURATION_TRANSLATION_INERTIA |
551 DIRECTMANIPULATION_CONFIGURATION_RAILS_X |
552 DIRECTMANIPULATION_CONFIGURATION_RAILS_Y;
553 if (StaticPrefs::apz_allow_zooming()) {
554 configuration |= DIRECTMANIPULATION_CONFIGURATION_SCALING;
557 hr = mDmViewport->ActivateConfiguration(configuration);
558 if (!SUCCEEDED(hr)) {
559 NS_WARNING("ActivateConfiguration failed");
560 mDmManager = nullptr;
561 mDmUpdateManager = nullptr;
562 mDmViewport = nullptr;
563 return;
566 hr = mDmViewport->SetViewportOptions(
567 DIRECTMANIPULATION_VIEWPORT_OPTIONS_MANUALUPDATE);
568 if (!SUCCEEDED(hr)) {
569 NS_WARNING("SetViewportOptions failed");
570 mDmManager = nullptr;
571 mDmUpdateManager = nullptr;
572 mDmViewport = nullptr;
573 return;
576 mDmHandler = new DManipEventHandler(mWindow, this, aBounds);
578 hr = mDmViewport->AddEventHandler(wnd, mDmHandler.get(),
579 &mDmViewportHandlerCookie);
580 if (!SUCCEEDED(hr)) {
581 NS_WARNING("AddEventHandler failed");
582 mDmManager = nullptr;
583 mDmUpdateManager = nullptr;
584 mDmViewport = nullptr;
585 mDmHandler = nullptr;
586 return;
589 RECT rect = {0, 0, aBounds.Width(), aBounds.Height()};
590 hr = mDmViewport->SetViewportRect(&rect);
591 if (!SUCCEEDED(hr)) {
592 NS_WARNING("SetViewportRect failed");
593 mDmManager = nullptr;
594 mDmUpdateManager = nullptr;
595 mDmViewport = nullptr;
596 mDmHandler = nullptr;
597 return;
600 hr = mDmManager->Activate(wnd);
601 if (!SUCCEEDED(hr)) {
602 NS_WARNING("manager Activate failed");
603 mDmManager = nullptr;
604 mDmUpdateManager = nullptr;
605 mDmViewport = nullptr;
606 mDmHandler = nullptr;
607 return;
610 hr = mDmViewport->Enable();
611 if (!SUCCEEDED(hr)) {
612 NS_WARNING("mDmViewport->Enable failed");
613 mDmManager = nullptr;
614 mDmUpdateManager = nullptr;
615 mDmViewport = nullptr;
616 mDmHandler = nullptr;
617 return;
620 hr = mDmUpdateManager->Update(nullptr);
621 if (!SUCCEEDED(hr)) {
622 NS_WARNING("mDmUpdateManager->Update failed");
623 mDmManager = nullptr;
624 mDmUpdateManager = nullptr;
625 mDmViewport = nullptr;
626 mDmHandler = nullptr;
627 return;
631 void DirectManipulationOwner::ResizeViewport(
632 const LayoutDeviceIntRect& aBounds) {
633 if (mDmHandler) {
634 mDmHandler->mBounds = aBounds;
637 if (mDmViewport) {
638 RECT rect = {0, 0, aBounds.Width(), aBounds.Height()};
639 HRESULT hr = mDmViewport->SetViewportRect(&rect);
640 if (!SUCCEEDED(hr)) {
641 NS_WARNING("SetViewportRect failed");
646 void DirectManipulationOwner::Destroy() {
647 if (mDmHandler) {
648 mDmHandler->mWindow = nullptr;
649 mDmHandler->mOwner = nullptr;
650 if (mDmHandler->mObserver) {
651 gfxWindowsPlatform::GetPlatform()
652 ->GetGlobalVsyncDispatcher()
653 ->RemoveMainThreadObserver(mDmHandler->mObserver);
654 mDmHandler->mObserver->ClearOwner();
655 mDmHandler->mObserver = nullptr;
659 HRESULT hr;
660 if (mDmViewport) {
661 hr = mDmViewport->Stop();
662 if (!SUCCEEDED(hr)) {
663 NS_WARNING("mDmViewport->Stop() failed");
666 hr = mDmViewport->Disable();
667 if (!SUCCEEDED(hr)) {
668 NS_WARNING("mDmViewport->Disable() failed");
671 hr = mDmViewport->RemoveEventHandler(mDmViewportHandlerCookie);
672 if (!SUCCEEDED(hr)) {
673 NS_WARNING("mDmViewport->RemoveEventHandler() failed");
676 hr = mDmViewport->Abandon();
677 if (!SUCCEEDED(hr)) {
678 NS_WARNING("mDmViewport->Abandon() failed");
682 if (mWindow) {
683 HWND wnd = static_cast<HWND>(mWindow->GetNativeData(NS_NATIVE_WINDOW));
685 if (mDmManager) {
686 hr = mDmManager->Deactivate(wnd);
687 if (!SUCCEEDED(hr)) {
688 NS_WARNING("mDmManager->Deactivate() failed");
693 mDmHandler = nullptr;
694 mDmViewport = nullptr;
695 mDmUpdateManager = nullptr;
696 mDmManager = nullptr;
697 mWindow = nullptr;
700 void DirectManipulationOwner::SetContact(UINT aContactId) {
701 if (mDmViewport) {
702 mDmViewport->SetContact(aContactId);
706 /*static */ void DirectManipulationOwner::SynthesizeNativeTouchpadPan(
707 nsWindow* aWindow, nsIWidget::TouchpadGesturePhase aEventPhase,
708 LayoutDeviceIntPoint aPoint, double aDeltaX, double aDeltaY,
709 int32_t aModifierFlags) {
710 DManipEventHandler::SynthesizeNativeTouchpadPan(
711 aWindow, aEventPhase, aPoint, aDeltaX, aDeltaY, aModifierFlags);
714 /*static */ void DManipEventHandler::SynthesizeNativeTouchpadPan(
715 nsWindow* aWindow, nsIWidget::TouchpadGesturePhase aEventPhase,
716 LayoutDeviceIntPoint aPoint, double aDeltaX, double aDeltaY,
717 int32_t aModifierFlags) {
718 ScreenPoint position = {(float)aPoint.x, (float)aPoint.y};
719 Phase phase = Phase::eStart;
720 if (aEventPhase == nsIWidget::PHASE_UPDATE) {
721 phase = Phase::eMiddle;
724 if (aEventPhase == nsIWidget::PHASE_END) {
725 phase = Phase::eEnd;
727 SendPanCommon(aWindow, phase, position, aDeltaX, aDeltaY, aModifierFlags,
728 /* aIsInertia = */ false);
731 } // namespace widget
732 } // namespace mozilla