Bug 1761003 [wpt PR 33324] - Add comment pointing to followup bug, and fix typos...
[gecko.git] / widget / windows / DirectManipulationOwner.cpp
blobbd8c530c8ddfb43ae0287705154d94b11438009a
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 bool NotifyVsync(const mozilla::VsyncEvent& aVsync) override {
76 if (mOwner) {
77 mOwner->Update();
79 return true;
81 explicit VObserver(DManipEventHandler* aOwner) : mOwner(aOwner) {}
83 void ClearOwner() { mOwner = nullptr; }
85 private:
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);
108 private:
109 virtual ~DManipEventHandler() = default;
111 nsWindow* mWindow;
112 DirectManipulationOwner* mOwner;
113 RefPtr<VObserver> mObserver;
114 float mLastScale;
115 float mLastXOffset;
116 float mLastYOffset;
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)
126 : mWindow(aWindow),
127 mOwner(aOwner),
128 mLastScale(1.f),
129 mLastXOffset(0.f),
130 mLastYOffset(0.f),
131 mBounds(aBounds),
132 mShouldSendPanStart(false),
133 mShouldSendPinchStart(false) {}
135 STDMETHODIMP
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);
145 AddRef();
146 return S_OK;
148 if (IID_IDirectManipulationInteractionEventHandler == iid) {
149 *ppv = static_cast<IDirectManipulationInteractionEventHandler*>(this);
150 AddRef();
151 return S_OK;
154 return E_NOINTERFACE;
157 HRESULT
158 DManipEventHandler::OnViewportStatusChanged(
159 IDirectManipulationViewport* viewport, DIRECTMANIPULATION_STATUS current,
160 DIRECTMANIPULATION_STATUS previous) {
161 if (current == previous) {
162 return S_OK;
165 if (current == DIRECTMANIPULATION_INERTIA) {
166 if (previous != DIRECTMANIPULATION_RUNNING || mState != State::ePanning) {
167 // xxx transition to none?
168 return S_OK;
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) {
183 return S_OK;
186 // A session has ended, reset the transform.
187 if (mLastScale != 1.f || mLastXOffset != 0.f || mLastYOffset != 0.f) {
188 HRESULT hr =
189 viewport->ZoomToRect(0, 0, mBounds.width, mBounds.height, false);
190 if (!SUCCEEDED(hr)) {
191 NS_WARNING("ZoomToRect failed");
194 mLastScale = 1.f;
195 mLastXOffset = 0.f;
196 mLastYOffset = 0.f;
198 TransitionToState(State::eNone);
200 return S_OK;
203 HRESULT
204 DManipEventHandler::OnViewportUpdated(IDirectManipulationViewport* viewport) {
205 return S_OK;
208 void DManipEventHandler::TransitionToState(State aNewState) {
209 if (mState == aNewState) {
210 return;
213 State prevState = mState;
214 mState = aNewState;
216 // End the previous sequence.
217 switch (prevState) {
218 case State::ePanning: {
219 // ePanning -> *: PanEnd
220 SendPan(Phase::eEnd, 0.f, 0.f, false);
221 break;
223 case State::eInertia: {
224 // eInertia -> *: MomentumEnd
225 SendPan(Phase::eEnd, 0.f, 0.f, true);
226 break;
228 case State::ePinching: {
229 MOZ_ASSERT(aNewState == State::eNone);
230 // ePinching -> eNone: PinchEnd. ePinching should only transition to
231 // eNone.
232 // Only send a pinch end if we sent a pinch start.
233 if (!mShouldSendPinchStart) {
234 SendPinch(Phase::eEnd, 0.f);
236 mShouldSendPinchStart = false;
237 break;
239 case State::eNone: {
240 // eNone -> *: no cleanup is needed.
241 break;
243 default:
244 MOZ_ASSERT(false);
247 // Start the new sequence.
248 switch (aNewState) {
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;
255 break;
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);
261 break;
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;
271 break;
273 case State::eNone: {
274 // * -> eNone: only cleanup is needed.
275 break;
277 default:
278 MOZ_ASSERT(false);
282 HRESULT
283 DManipEventHandler::OnContentUpdated(IDirectManipulationViewport* viewport,
284 IDirectManipulationContent* content) {
285 float transform[6];
286 HRESULT hr = content->GetContentTransform(transform, ARRAYSIZE(transform));
287 if (!SUCCEEDED(hr)) {
288 NS_WARNING("GetContentTransform failed");
289 return S_OK;
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) {
299 return S_OK;
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);
307 } else {
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
314 // least one pixel.
315 float dx = std::abs(mLastXOffset - xoffset);
316 float dy = std::abs(mLastYOffset - yoffset);
317 if (dx < 1.f && dy < 1.f) {
318 return S_OK;
322 bool updateLastScale = true;
323 if (mState == State::ePanning) {
324 if (mShouldSendPanStart) {
325 SendPan(Phase::eStart, mLastXOffset - xoffset, mLastYOffset - yoffset,
326 false);
327 mShouldSendPanStart = false;
328 } else {
329 SendPan(Phase::eMiddle, mLastXOffset - xoffset, mLastYOffset - yoffset,
330 false);
332 } else if (mState == State::eInertia) {
333 SendPan(Phase::eMiddle, mLastXOffset - xoffset, mLastYOffset - yoffset,
334 true);
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;
343 } else {
344 updateLastScale = SendPinch(Phase::eMiddle, scale);
348 if (updateLastScale) {
349 mLastScale = scale;
351 mLastXOffset = xoffset;
352 mLastYOffset = yoffset;
354 return S_OK;
357 HRESULT
358 DManipEventHandler::OnInteraction(
359 IDirectManipulationViewport2* viewport,
360 DIRECTMANIPULATION_INTERACTION_TYPE interaction) {
361 if (interaction == DIRECTMANIPULATION_INTERACTION_BEGIN) {
362 if (!mObserver) {
363 mObserver = new VObserver(this);
366 gfxWindowsPlatform::GetPlatform()->GetHardwareVsync()->AddGenericObserver(
367 mObserver);
370 if (mObserver && interaction == DIRECTMANIPULATION_INTERACTION_END) {
371 gfxWindowsPlatform::GetPlatform()
372 ->GetHardwareVsync()
373 ->RemoveGenericObserver(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 ->GetHardwareVsync()
685 ->RemoveGenericObserver(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