Bug 1779627 - Migrate toolkit/components/mozintl/mozIntl.jsm to esm; r=nordzilla
[gecko.git] / widget / windows / DirectManipulationOwner.cpp
blob64d379bf6cad625e27a2943253704b7b11077f06
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 #if !defined(__MINGW32__) && !defined(__MINGW64__)
17 // Direct Manipulation is only defined for Win8 and newer.
18 # if defined(_WIN32_WINNT)
19 # undef _WIN32_WINNT
20 # define _WIN32_WINNT _WIN32_WINNT_WIN8
21 # endif // defined(_WIN32_WINNT)
22 # if defined(NTDDI_VERSION)
23 # undef NTDDI_VERSION
24 # define NTDDI_VERSION NTDDI_WIN8
25 # endif // defined(NTDDI_VERSION)
27 # include "directmanipulation.h"
29 #endif // !defined(__MINGW32__) && !defined(__MINGW64__)
31 namespace mozilla {
32 namespace widget {
34 #if !defined(__MINGW32__) && !defined(__MINGW64__)
36 class DManipEventHandler : public IDirectManipulationViewportEventHandler,
37 public IDirectManipulationInteractionEventHandler {
38 public:
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;
68 void Update();
70 class VObserver final : public mozilla::VsyncObserver {
71 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DManipEventHandler::VObserver,
72 override)
74 public:
75 void NotifyVsync(const mozilla::VsyncEvent& aVsync) override {
76 if (mOwner) {
77 mOwner->Update();
80 explicit VObserver(DManipEventHandler* aOwner) : mOwner(aOwner) {}
82 void ClearOwner() { mOwner = nullptr; }
84 private:
85 virtual ~VObserver() {}
86 DManipEventHandler* mOwner;
89 enum class State { eNone, ePanning, eInertia, ePinching };
90 void TransitionToState(State aNewState);
92 enum class Phase { eStart, eMiddle, eEnd };
93 // Return value indicates if we sent an event or not and hence if we should
94 // update mLastScale. (We only want to send pinch events if the computed
95 // deltaY for the corresponding WidgetWheelEvent would be non-zero.)
96 bool SendPinch(Phase aPhase, float aScale);
97 void SendPan(Phase aPhase, float x, float y, bool aIsInertia);
98 static void SendPanCommon(nsWindow* aWindow, Phase aPhase,
99 ScreenPoint aPosition, double aDeltaX,
100 double aDeltaY, Modifiers aMods, bool aIsInertia);
102 static void SynthesizeNativeTouchpadPan(
103 nsWindow* aWindow, nsIWidget::TouchpadGesturePhase aEventPhase,
104 LayoutDeviceIntPoint aPoint, double aDeltaX, double aDeltaY,
105 int32_t aModifierFlags);
107 private:
108 virtual ~DManipEventHandler() = default;
110 nsWindow* mWindow;
111 DirectManipulationOwner* mOwner;
112 RefPtr<VObserver> mObserver;
113 float mLastScale;
114 float mLastXOffset;
115 float mLastYOffset;
116 LayoutDeviceIntRect mBounds;
117 bool mShouldSendPanStart;
118 bool mShouldSendPinchStart;
119 State mState = State::eNone;
122 DManipEventHandler::DManipEventHandler(nsWindow* aWindow,
123 DirectManipulationOwner* aOwner,
124 const LayoutDeviceIntRect& aBounds)
125 : mWindow(aWindow),
126 mOwner(aOwner),
127 mLastScale(1.f),
128 mLastXOffset(0.f),
129 mLastYOffset(0.f),
130 mBounds(aBounds),
131 mShouldSendPanStart(false),
132 mShouldSendPinchStart(false) {}
134 STDMETHODIMP
135 DManipEventHandler::QueryInterface(REFIID iid, void** ppv) {
136 const IID IID_IDirectManipulationViewportEventHandler =
137 __uuidof(IDirectManipulationViewportEventHandler);
138 const IID IID_IDirectManipulationInteractionEventHandler =
139 __uuidof(IDirectManipulationInteractionEventHandler);
141 if ((IID_IUnknown == iid) ||
142 (IID_IDirectManipulationViewportEventHandler == iid)) {
143 *ppv = static_cast<IDirectManipulationViewportEventHandler*>(this);
144 AddRef();
145 return S_OK;
147 if (IID_IDirectManipulationInteractionEventHandler == iid) {
148 *ppv = static_cast<IDirectManipulationInteractionEventHandler*>(this);
149 AddRef();
150 return S_OK;
153 return E_NOINTERFACE;
156 HRESULT
157 DManipEventHandler::OnViewportStatusChanged(
158 IDirectManipulationViewport* viewport, DIRECTMANIPULATION_STATUS current,
159 DIRECTMANIPULATION_STATUS previous) {
160 if (current == previous) {
161 return S_OK;
164 if (current == DIRECTMANIPULATION_INERTIA) {
165 if (previous != DIRECTMANIPULATION_RUNNING || mState != State::ePanning) {
166 // xxx transition to none?
167 return S_OK;
170 TransitionToState(State::eInertia);
173 if (current == DIRECTMANIPULATION_RUNNING) {
174 // INERTIA -> RUNNING, should start a new sequence.
175 if (previous == DIRECTMANIPULATION_INERTIA) {
176 TransitionToState(State::eNone);
180 if (current != DIRECTMANIPULATION_ENABLED &&
181 current != DIRECTMANIPULATION_READY) {
182 return S_OK;
185 // A session has ended, reset the transform.
186 if (mLastScale != 1.f || mLastXOffset != 0.f || mLastYOffset != 0.f) {
187 HRESULT hr =
188 viewport->ZoomToRect(0, 0, mBounds.width, mBounds.height, false);
189 if (!SUCCEEDED(hr)) {
190 NS_WARNING("ZoomToRect failed");
193 mLastScale = 1.f;
194 mLastXOffset = 0.f;
195 mLastYOffset = 0.f;
197 TransitionToState(State::eNone);
199 return S_OK;
202 HRESULT
203 DManipEventHandler::OnViewportUpdated(IDirectManipulationViewport* viewport) {
204 return S_OK;
207 void DManipEventHandler::TransitionToState(State aNewState) {
208 if (mState == aNewState) {
209 return;
212 State prevState = mState;
213 mState = aNewState;
215 // End the previous sequence.
216 switch (prevState) {
217 case State::ePanning: {
218 // ePanning -> *: PanEnd
219 SendPan(Phase::eEnd, 0.f, 0.f, false);
220 break;
222 case State::eInertia: {
223 // eInertia -> *: MomentumEnd
224 SendPan(Phase::eEnd, 0.f, 0.f, true);
225 break;
227 case State::ePinching: {
228 MOZ_ASSERT(aNewState == State::eNone);
229 // ePinching -> eNone: PinchEnd. ePinching should only transition to
230 // eNone.
231 // Only send a pinch end if we sent a pinch start.
232 if (!mShouldSendPinchStart) {
233 SendPinch(Phase::eEnd, 0.f);
235 mShouldSendPinchStart = false;
236 break;
238 case State::eNone: {
239 // eNone -> *: no cleanup is needed.
240 break;
242 default:
243 MOZ_ASSERT(false);
246 // Start the new sequence.
247 switch (aNewState) {
248 case State::ePanning: {
249 // eInertia, eNone -> ePanning: PanStart.
250 // We're being called from OnContentUpdated, it has the coords we need to
251 // pass to SendPan(Phase::eStart), so set mShouldSendPanStart and when we
252 // return OnContentUpdated will check it and call SendPan(Phase::eStart).
253 mShouldSendPanStart = true;
254 break;
256 case State::eInertia: {
257 // Only ePanning can transition to eInertia.
258 MOZ_ASSERT(prevState == State::ePanning);
259 SendPan(Phase::eStart, 0.f, 0.f, true);
260 break;
262 case State::ePinching: {
263 // * -> ePinching: PinchStart.
264 // Pinch gesture may begin with some scroll events.
265 // We're being called from OnContentUpdated, it has the scale we need to
266 // pass to SendPinch(Phase::eStart), so set mShouldSendPinchStart and when
267 // we return OnContentUpdated will check it and call
268 // SendPinch(Phase::eStart).
269 mShouldSendPinchStart = true;
270 break;
272 case State::eNone: {
273 // * -> eNone: only cleanup is needed.
274 break;
276 default:
277 MOZ_ASSERT(false);
281 HRESULT
282 DManipEventHandler::OnContentUpdated(IDirectManipulationViewport* viewport,
283 IDirectManipulationContent* content) {
284 float transform[6];
285 HRESULT hr = content->GetContentTransform(transform, ARRAYSIZE(transform));
286 if (!SUCCEEDED(hr)) {
287 NS_WARNING("GetContentTransform failed");
288 return S_OK;
291 float scale = transform[0];
292 float xoffset = transform[4];
293 float yoffset = transform[5];
295 // Not different from last time.
296 if (FuzzyEqualsMultiplicative(scale, mLastScale) && xoffset == mLastXOffset &&
297 yoffset == mLastYOffset) {
298 return S_OK;
301 // Consider this is a Scroll when scale factor equals 1.0.
302 if (FuzzyEqualsMultiplicative(scale, 1.f)) {
303 if (mState == State::eNone) {
304 TransitionToState(State::ePanning);
306 } else {
307 // Pinch gesture may begin with some scroll events.
308 TransitionToState(State::ePinching);
311 if (mState == State::ePanning || mState == State::eInertia) {
312 // Accumulate the offset (by not updating mLastX/YOffset) until we have at
313 // least one pixel.
314 float dx = std::abs(mLastXOffset - xoffset);
315 float dy = std::abs(mLastYOffset - yoffset);
316 if (dx < 1.f && dy < 1.f) {
317 return S_OK;
321 bool updateLastScale = true;
322 if (mState == State::ePanning) {
323 if (mShouldSendPanStart) {
324 SendPan(Phase::eStart, mLastXOffset - xoffset, mLastYOffset - yoffset,
325 false);
326 mShouldSendPanStart = false;
327 } else {
328 SendPan(Phase::eMiddle, mLastXOffset - xoffset, mLastYOffset - yoffset,
329 false);
331 } else if (mState == State::eInertia) {
332 SendPan(Phase::eMiddle, mLastXOffset - xoffset, mLastYOffset - yoffset,
333 true);
334 } else if (mState == State::ePinching) {
335 if (mShouldSendPinchStart) {
336 updateLastScale = SendPinch(Phase::eStart, scale);
337 // Only clear mShouldSendPinchStart if we actually sent the event
338 // (updateLastScale tells us if we sent an event).
339 if (updateLastScale) {
340 mShouldSendPinchStart = false;
342 } else {
343 updateLastScale = SendPinch(Phase::eMiddle, scale);
347 if (updateLastScale) {
348 mLastScale = scale;
350 mLastXOffset = xoffset;
351 mLastYOffset = yoffset;
353 return S_OK;
356 HRESULT
357 DManipEventHandler::OnInteraction(
358 IDirectManipulationViewport2* viewport,
359 DIRECTMANIPULATION_INTERACTION_TYPE interaction) {
360 if (interaction == DIRECTMANIPULATION_INTERACTION_BEGIN) {
361 if (!mObserver) {
362 mObserver = new VObserver(this);
365 gfxWindowsPlatform::GetPlatform()
366 ->GetGlobalVsyncDispatcher()
367 ->AddMainThreadObserver(mObserver);
370 if (mObserver && interaction == DIRECTMANIPULATION_INTERACTION_END) {
371 gfxWindowsPlatform::GetPlatform()
372 ->GetGlobalVsyncDispatcher()
373 ->RemoveMainThreadObserver(mObserver);
376 return S_OK;
379 void DManipEventHandler::Update() {
380 if (mOwner) {
381 mOwner->Update();
385 #endif // !defined(__MINGW32__) && !defined(__MINGW64__)
387 void DirectManipulationOwner::Update() {
388 #if !defined(__MINGW32__) && !defined(__MINGW64__)
389 if (mDmUpdateManager) {
390 mDmUpdateManager->Update(nullptr);
392 #endif
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) {
403 if (!mWindow) {
404 return false;
407 if (aScale == mLastScale && aPhase != Phase::eEnd) {
408 return false;
411 PinchGestureInput::PinchGestureType pinchGestureType =
412 PinchGestureInput::PINCHGESTURE_SCALE;
413 switch (aPhase) {
414 case Phase::eStart:
415 pinchGestureType = PinchGestureInput::PINCHGESTURE_START;
416 break;
417 case Phase::eMiddle:
418 pinchGestureType = PinchGestureInput::PINCHGESTURE_SCALE;
419 break;
420 case Phase::eEnd:
421 pinchGestureType = PinchGestureInput::PINCHGESTURE_END;
422 break;
423 default:
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);
437 POINT cursor_pos;
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,
445 eventIntervalTime,
446 eventTimeStamp,
447 screenOffset,
448 position,
449 100.0 * ((aPhase == Phase::eEnd) ? 1.f : aScale),
450 100.0 * ((aPhase == Phase::eEnd) ? 1.f : mLastScale),
451 mods};
453 if (!event.SetLineOrPageDeltaY(mWindow)) {
454 return false;
457 mWindow->SendAnAPZEvent(event);
459 return true;
462 void DManipEventHandler::SendPan(Phase aPhase, float x, float y,
463 bool aIsInertia) {
464 if (!mWindow) {
465 return;
468 ModifierKeyState modifierKeyState;
469 Modifiers mods = modifierKeyState.GetModifiers();
471 POINT cursor_pos;
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);
480 /* static */
481 void DManipEventHandler::SendPanCommon(nsWindow* aWindow, Phase aPhase,
482 ScreenPoint aPosition, double aDeltaX,
483 double aDeltaY, Modifiers aMods,
484 bool aIsInertia) {
485 if (!aWindow) {
486 return;
489 PanGestureInput::PanGestureType panGestureType =
490 PanGestureInput::PANGESTURE_PAN;
491 if (aIsInertia) {
492 switch (aPhase) {
493 case Phase::eStart:
494 panGestureType = PanGestureInput::PANGESTURE_MOMENTUMSTART;
495 break;
496 case Phase::eMiddle:
497 panGestureType = PanGestureInput::PANGESTURE_MOMENTUMPAN;
498 break;
499 case Phase::eEnd:
500 panGestureType = PanGestureInput::PANGESTURE_MOMENTUMEND;
501 break;
502 default:
503 MOZ_ASSERT_UNREACHABLE("handle all enum values");
505 } else {
506 switch (aPhase) {
507 case Phase::eStart:
508 panGestureType = PanGestureInput::PANGESTURE_START;
509 break;
510 case Phase::eMiddle:
511 panGestureType = PanGestureInput::PANGESTURE_PAN;
512 break;
513 case Phase::eEnd:
514 panGestureType = PanGestureInput::PANGESTURE_END;
515 break;
516 default:
517 MOZ_ASSERT_UNREACHABLE("handle all enum values");
521 PRIntervalTime eventIntervalTime = PR_IntervalNow();
522 TimeStamp eventTimeStamp = TimeStamp::Now();
524 PanGestureInput event{panGestureType,
525 eventIntervalTime,
526 eventTimeStamp,
527 aPosition,
528 ScreenPoint(aDeltaX, aDeltaY),
529 aMods};
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;
550 return;
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;
559 return;
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;
571 return;
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;
591 return;
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;
601 return;
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;
614 return;
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;
625 return;
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;
635 return;
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;
645 return;
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;
655 return;
657 #endif // !defined(__MINGW32__) && !defined(__MINGW64__)
660 void DirectManipulationOwner::ResizeViewport(
661 const LayoutDeviceIntRect& aBounds) {
662 #if !defined(__MINGW32__) && !defined(__MINGW64__)
663 if (mDmHandler) {
664 mDmHandler->mBounds = aBounds;
667 if (mDmViewport) {
668 RECT rect = {0, 0, aBounds.Width(), aBounds.Height()};
669 HRESULT hr = mDmViewport->SetViewportRect(&rect);
670 if (!SUCCEEDED(hr)) {
671 NS_WARNING("SetViewportRect failed");
674 #endif
677 void DirectManipulationOwner::Destroy() {
678 #if !defined(__MINGW32__) && !defined(__MINGW64__)
679 if (mDmHandler) {
680 mDmHandler->mWindow = nullptr;
681 mDmHandler->mOwner = nullptr;
682 if (mDmHandler->mObserver) {
683 gfxWindowsPlatform::GetPlatform()
684 ->GetGlobalVsyncDispatcher()
685 ->RemoveMainThreadObserver(mDmHandler->mObserver);
686 mDmHandler->mObserver->ClearOwner();
687 mDmHandler->mObserver = nullptr;
691 HRESULT hr;
692 if (mDmViewport) {
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");
714 if (mWindow) {
715 HWND wnd = static_cast<HWND>(mWindow->GetNativeData(NS_NATIVE_WINDOW));
717 if (mDmManager) {
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__)
730 mWindow = nullptr;
733 void DirectManipulationOwner::SetContact(UINT aContactId) {
734 #if !defined(__MINGW32__) && !defined(__MINGW64__)
735 if (mDmViewport) {
736 mDmViewport->SetContact(aContactId);
738 #endif
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);
748 #endif
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) {
763 phase = Phase::eEnd;
765 SendPanCommon(aWindow, phase, position, aDeltaX, aDeltaY, aModifierFlags,
766 /* aIsInertia = */ false);
768 #endif
770 } // namespace widget
771 } // namespace mozilla