Bug 1630912. Create the necessary direct manipulation objects. r=aklotz

Differential Revision: https://phabricator.services.mozilla.com/D71305
This commit is contained in:
Timothy Nikkel 2020-05-08 23:19:58 +00:00
Родитель 1dcfcb4957
Коммит 3cd8209b42
6 изменённых файлов: 426 добавлений и 0 удалений

Просмотреть файл

@ -582,6 +582,11 @@
value: @IS_NOT_NIGHTLY_BUILD@
mirror: always
- name: apz.windows.use_direct_manipulation
type: RelaxedAtomicBool
value: false
mirror: always
- name: apz.x_skate_highmem_adjust
type: AtomicFloat
value: 0.0f

Просмотреть файл

@ -0,0 +1,292 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "DirectManipulationOwner.h"
#include "nsWindow.h"
// Direct Manipulation is only defined for Win8 and newer.
#if defined(_WIN32_WINNT)
# undef _WIN32_WINNT
# define _WIN32_WINNT _WIN32_WINNT_WIN8
#endif // defined(_WIN32_WINNT)
#if defined(NTDDI_VERSION)
# undef NTDDI_VERSION
# define NTDDI_VERSION NTDDI_WIN8
#endif // defined(NTDDI_VERSION)
#include "directmanipulation.h"
namespace mozilla {
namespace widget {
class DManipEventHandler : public IDirectManipulationViewportEventHandler,
public IDirectManipulationInteractionEventHandler {
public:
friend class DirectManipulationOwner;
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DManipEventHandler)
STDMETHODIMP QueryInterface(REFIID, void**) override;
explicit DManipEventHandler(nsWindow* aWindow,
DirectManipulationOwner* aOwner)
: mWindow(aWindow), mOwner(aOwner) {}
HRESULT STDMETHODCALLTYPE OnViewportStatusChanged(
IDirectManipulationViewport* viewport, DIRECTMANIPULATION_STATUS current,
DIRECTMANIPULATION_STATUS previous) override;
HRESULT STDMETHODCALLTYPE
OnViewportUpdated(IDirectManipulationViewport* viewport) override;
HRESULT STDMETHODCALLTYPE
OnContentUpdated(IDirectManipulationViewport* viewport,
IDirectManipulationContent* content) override;
HRESULT STDMETHODCALLTYPE
OnInteraction(IDirectManipulationViewport2* viewport,
DIRECTMANIPULATION_INTERACTION_TYPE interaction) override;
private:
virtual ~DManipEventHandler() = default;
nsWindow* mWindow;
DirectManipulationOwner* mOwner;
};
STDMETHODIMP
DManipEventHandler::QueryInterface(REFIID iid, void** ppv) {
const IID IID_IDirectManipulationViewportEventHandler =
__uuidof(IDirectManipulationViewportEventHandler);
const IID IID_IDirectManipulationInteractionEventHandler =
__uuidof(IDirectManipulationInteractionEventHandler);
if ((IID_IUnknown == iid) ||
(IID_IDirectManipulationViewportEventHandler == iid)) {
*ppv = static_cast<IDirectManipulationViewportEventHandler*>(this);
AddRef();
return S_OK;
}
if (IID_IDirectManipulationInteractionEventHandler == iid) {
*ppv = static_cast<IDirectManipulationInteractionEventHandler*>(this);
AddRef();
return S_OK;
}
return E_NOINTERFACE;
}
HRESULT
DManipEventHandler::OnViewportStatusChanged(
IDirectManipulationViewport* viewport, DIRECTMANIPULATION_STATUS current,
DIRECTMANIPULATION_STATUS previous) {
return S_OK;
}
HRESULT
DManipEventHandler::OnViewportUpdated(IDirectManipulationViewport* viewport) {
return S_OK;
}
HRESULT
DManipEventHandler::OnContentUpdated(IDirectManipulationViewport* viewport,
IDirectManipulationContent* content) {
return S_OK;
}
HRESULT
DManipEventHandler::OnInteraction(
IDirectManipulationViewport2* viewport,
DIRECTMANIPULATION_INTERACTION_TYPE interaction) {
return S_OK;
}
DirectManipulationOwner::DirectManipulationOwner(nsWindow* aWindow)
: mWindow(aWindow) {}
DirectManipulationOwner::~DirectManipulationOwner() { Destroy(); }
void DirectManipulationOwner::Init(const LayoutDeviceIntRect& aBounds) {
HRESULT hr = CoCreateInstance(
CLSID_DirectManipulationManager, nullptr, CLSCTX_INPROC_SERVER,
IID_IDirectManipulationManager, getter_AddRefs(mDmManager));
if (!SUCCEEDED(hr)) {
NS_WARNING("CoCreateInstance(CLSID_DirectManipulationManager failed");
mDmManager = nullptr;
return;
}
hr = mDmManager->GetUpdateManager(IID_IDirectManipulationUpdateManager,
getter_AddRefs(mDmUpdateManager));
if (!SUCCEEDED(hr)) {
NS_WARNING("GetUpdateManager failed");
mDmManager = nullptr;
mDmUpdateManager = nullptr;
return;
}
HWND wnd = static_cast<HWND>(mWindow->GetNativeData(NS_NATIVE_WINDOW));
hr = mDmManager->CreateViewport(nullptr, wnd, IID_IDirectManipulationViewport,
getter_AddRefs(mDmViewport));
if (!SUCCEEDED(hr)) {
NS_WARNING("CreateViewport failed");
mDmManager = nullptr;
mDmUpdateManager = nullptr;
mDmViewport = nullptr;
return;
}
DIRECTMANIPULATION_CONFIGURATION configuration =
DIRECTMANIPULATION_CONFIGURATION_INTERACTION |
DIRECTMANIPULATION_CONFIGURATION_TRANSLATION_X |
DIRECTMANIPULATION_CONFIGURATION_TRANSLATION_Y |
DIRECTMANIPULATION_CONFIGURATION_TRANSLATION_INERTIA |
DIRECTMANIPULATION_CONFIGURATION_RAILS_X |
DIRECTMANIPULATION_CONFIGURATION_RAILS_Y;
if (StaticPrefs::apz_allow_zooming()) {
configuration |= DIRECTMANIPULATION_CONFIGURATION_SCALING;
}
hr = mDmViewport->ActivateConfiguration(configuration);
if (!SUCCEEDED(hr)) {
NS_WARNING("ActivateConfiguration failed");
mDmManager = nullptr;
mDmUpdateManager = nullptr;
mDmViewport = nullptr;
return;
}
hr = mDmViewport->SetViewportOptions(
DIRECTMANIPULATION_VIEWPORT_OPTIONS_MANUALUPDATE);
if (!SUCCEEDED(hr)) {
NS_WARNING("SetViewportOptions failed");
mDmManager = nullptr;
mDmUpdateManager = nullptr;
mDmViewport = nullptr;
return;
}
mDmHandler = new DManipEventHandler(mWindow, this);
hr = mDmViewport->AddEventHandler(wnd, mDmHandler.get(),
&mDmViewportHandlerCookie);
if (!SUCCEEDED(hr)) {
NS_WARNING("AddEventHandler failed");
mDmManager = nullptr;
mDmUpdateManager = nullptr;
mDmViewport = nullptr;
mDmHandler = nullptr;
return;
}
RECT rect = {0, 0, aBounds.Width(), aBounds.Height()};
hr = mDmViewport->SetViewportRect(&rect);
if (!SUCCEEDED(hr)) {
NS_WARNING("SetViewportRect failed");
mDmManager = nullptr;
mDmUpdateManager = nullptr;
mDmViewport = nullptr;
mDmHandler = nullptr;
return;
}
hr = mDmManager->Activate(wnd);
if (!SUCCEEDED(hr)) {
NS_WARNING("manager Activate failed");
mDmManager = nullptr;
mDmUpdateManager = nullptr;
mDmViewport = nullptr;
mDmHandler = nullptr;
return;
}
hr = mDmViewport->Enable();
if (!SUCCEEDED(hr)) {
NS_WARNING("mDmViewport->Enable failed");
mDmManager = nullptr;
mDmUpdateManager = nullptr;
mDmViewport = nullptr;
mDmHandler = nullptr;
return;
}
hr = mDmUpdateManager->Update(nullptr);
if (!SUCCEEDED(hr)) {
NS_WARNING("mDmUpdateManager->Update failed");
mDmManager = nullptr;
mDmUpdateManager = nullptr;
mDmViewport = nullptr;
mDmHandler = nullptr;
return;
}
}
void DirectManipulationOwner::ResizeViewport(
const LayoutDeviceIntRect& aBounds) {
if (mDmViewport) {
RECT rect = {0, 0, aBounds.Width(), aBounds.Height()};
HRESULT hr = mDmViewport->SetViewportRect(&rect);
if (!SUCCEEDED(hr)) {
NS_WARNING("SetViewportRect failed");
}
}
}
void DirectManipulationOwner::Destroy() {
if (mDmHandler) {
mDmHandler->mWindow = nullptr;
mDmHandler->mOwner = nullptr;
}
HRESULT hr;
if (mDmViewport) {
hr = mDmViewport->Stop();
if (!SUCCEEDED(hr)) {
NS_WARNING("mDmViewport->Stop() failed");
}
hr = mDmViewport->Disable();
if (!SUCCEEDED(hr)) {
NS_WARNING("mDmViewport->Disable() failed");
}
hr = mDmViewport->RemoveEventHandler(mDmViewportHandlerCookie);
if (!SUCCEEDED(hr)) {
NS_WARNING("mDmViewport->RemoveEventHandler() failed");
}
hr = mDmViewport->Abandon();
if (!SUCCEEDED(hr)) {
NS_WARNING("mDmViewport->Abandon() failed");
}
}
if (mWindow) {
HWND wnd = static_cast<HWND>(mWindow->GetNativeData(NS_NATIVE_WINDOW));
if (mDmManager) {
hr = mDmManager->Deactivate(wnd);
if (!SUCCEEDED(hr)) {
NS_WARNING("mDmManager->Deactivate() failed");
}
}
}
mDmHandler = nullptr;
mDmViewport = nullptr;
mDmUpdateManager = nullptr;
mDmManager = nullptr;
mWindow = nullptr;
}
void DirectManipulationOwner::SetContact(UINT aContactId) {
if (mDmViewport) {
mDmViewport->SetContact(aContactId);
}
}
} // namespace widget
} // namespace mozilla

Просмотреть файл

@ -0,0 +1,46 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef DirectManipulationOwner_h__
#define DirectManipulationOwner_h__
#include "Units.h"
#include "WinDef.h"
class nsWindow;
class IDirectManipulationManager;
class IDirectManipulationUpdateManager;
class IDirectManipulationViewport;
namespace mozilla {
namespace widget {
class DManipEventHandler;
class DirectManipulationOwner {
public:
typedef mozilla::LayoutDeviceIntRect LayoutDeviceIntRect;
explicit DirectManipulationOwner(nsWindow* aWindow);
~DirectManipulationOwner();
void Init(const LayoutDeviceIntRect& aBounds);
void ResizeViewport(const LayoutDeviceIntRect& aBounds);
void Destroy();
void SetContact(UINT aContactId);
private:
nsWindow* mWindow;
DWORD mDmViewportHandlerCookie;
RefPtr<IDirectManipulationManager> mDmManager;
RefPtr<IDirectManipulationUpdateManager> mDmUpdateManager;
RefPtr<IDirectManipulationViewport> mDmViewport;
RefPtr<DManipEventHandler> mDmHandler;
};
} // namespace widget
} // namespace mozilla
#endif // #ifndef DirectManipulationOwner_h__

Просмотреть файл

@ -106,6 +106,11 @@ SOURCES += [
'WinMouseScrollHandler.cpp',
]
# These files redefine the winsdk api version macro and we don't want it to leak to other files.
SOURCES += [
'DirectManipulationOwner.cpp',
]
# Needs INITGUID and we don't allow INITGUID in unified sources since bug 970429.
SOURCES += [
'InputDeviceUtils.cpp',

Просмотреть файл

@ -65,6 +65,7 @@
#include "mozilla/MiscEvents.h"
#include "mozilla/MouseEvents.h"
#include "mozilla/TouchEvents.h"
#include "mozilla/TimeStamp.h"
#include "mozilla/ipc/MessageChannel.h"
#include <algorithm>
@ -212,6 +213,9 @@
#include "mozilla/Telemetry.h"
#include "mozilla/plugins/PluginProcessParent.h"
#include "mozilla/webrender/WebRenderAPI.h"
#include "mozilla/layers/IAPZCTreeManager.h"
#include "DirectManipulationOwner.h"
using namespace mozilla;
using namespace mozilla::dom;
@ -712,6 +716,47 @@ static bool ShouldCacheTitleBarInfo(nsWindowType aWindowType,
!nsUXThemeData::sTitlebarInfoPopulatedAero);
}
void nsWindow::RecreateDirectManipulationIfNeeded() {
DestroyDirectManipulation();
if (mWindowType != eWindowType_toplevel && mWindowType != eWindowType_popup) {
return;
}
if (!StaticPrefs::apz_windows_use_direct_manipulation() ||
StaticPrefs::apz_windows_force_disable_direct_manipulation()) {
return;
}
if (!IsWin10OrLater()) {
// Chrome source said the Windows Direct Manipulation implementation had
// important bugs until Windows 10 (although IE on Windows 8.1 seems to use
// Direct Manipulation).
return;
}
mDmOwner = MakeUnique<DirectManipulationOwner>(this);
LayoutDeviceIntRect bounds(mBounds.X(), mBounds.Y(), mBounds.Width(),
GetHeight(mBounds.Height()));
mDmOwner->Init(bounds);
}
void nsWindow::ResizeDirectManipulationViewport() {
if (mDmOwner) {
LayoutDeviceIntRect bounds(mBounds.X(), mBounds.Y(), mBounds.Width(),
GetHeight(mBounds.Height()));
mDmOwner->ResizeViewport(bounds);
}
}
void nsWindow::DestroyDirectManipulation() {
if (mDmOwner) {
mDmOwner->Destroy();
mDmOwner.reset();
}
}
// Create the proper widget
nsresult nsWindow::Create(nsIWidget* aParent, nsNativeWidget aNativeParent,
const LayoutDeviceIntRect& aRect,
@ -915,6 +960,9 @@ nsresult nsWindow::Create(nsIWidget* aParent, nsNativeWidget aNativeParent,
::PostMessage(mWnd, MOZ_WM_STARTA11Y, 0, 0);
}
}
RecreateDirectManipulationIfNeeded();
return NS_OK;
}
@ -932,6 +980,8 @@ void nsWindow::Destroy() {
// deleted.
nsCOMPtr<nsIWidget> kungFuDeathGrip(this);
DestroyDirectManipulation();
/**
* On windows the LayerManagerOGL destructor wants the widget to be around for
* cleanup. It also would like to have the HWND intact, so we nullptr it here.
@ -1227,6 +1277,7 @@ void nsWindow::SetParent(nsIWidget* aNewParent) {
if (mWnd) {
// If we have no parent, SetParent should return the desktop.
VERIFY(::SetParent(mWnd, nullptr));
RecreateDirectManipulationIfNeeded();
}
}
@ -1241,6 +1292,7 @@ void nsWindow::ReparentNativeWidget(nsIWidget* aNewParent) {
NS_ASSERTION(newParent, "Parent widget has a null native window handle");
if (newParent && mWnd) {
::SetParent(mWnd, newParent);
RecreateDirectManipulationIfNeeded();
}
}
@ -1818,6 +1870,8 @@ void nsWindow::Move(double aX, double aY) {
}
SetThemeRegion();
ResizeDirectManipulationViewport();
}
NotifyRollupGeometryChange();
}
@ -1864,6 +1918,8 @@ void nsWindow::Resize(double aWidth, double aHeight, bool aRepaint) {
ChangedDPI();
}
SetThemeRegion();
ResizeDirectManipulationViewport();
}
if (aRepaint) Invalidate();
@ -1922,6 +1978,8 @@ void nsWindow::Resize(double aX, double aY, double aWidth, double aHeight,
SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
}
SetThemeRegion();
ResizeDirectManipulationViewport();
}
if (aRepaint) Invalidate();
@ -3502,6 +3560,7 @@ void nsWindow::SetNativeData(uint32_t aDataType, uintptr_t aVal) {
? mWnd
: WinUtils::GetTopLevelHWND(mWnd);
SetChildStyleAndParent(childHwnd, parentHwnd);
RecreateDirectManipulationIfNeeded();
break;
}
default:
@ -5611,6 +5670,17 @@ bool nsWindow::ProcessMessage(UINT msg, WPARAM& wParam, LPARAM& lParam,
}
break;
case DM_POINTERHITTEST:
if (mDmOwner) {
UINT contactId = GET_POINTERID_WPARAM(wParam);
POINTER_INPUT_TYPE pointerType;
if (mPointerEvents.GetPointerType(contactId, &pointerType) &&
pointerType == PT_TOUCHPAD) {
mDmOwner->SetContact(contactId);
}
}
break;
case WM_LBUTTONDBLCLK:
result = DispatchMouseEvent(eMouseDoubleClick, wParam, lParam, false,
MouseButton::eLeft, MOUSE_INPUT_SOURCE());

Просмотреть файл

@ -30,6 +30,7 @@
#include "mozilla/TimeStamp.h"
#include "mozilla/webrender/WebRenderTypes.h"
#include "mozilla/dom/MouseEventBinding.h"
#include "mozilla/UniquePtr.h"
#include "nsMargin.h"
#include "nsRegionFwd.h"
@ -62,6 +63,7 @@ namespace widget {
class NativeKey;
class InProcessWinCompositorWidget;
struct MSGResult;
class DirectManipulationOwner;
} // namespace widget
} // namespace mozilla
@ -564,6 +566,10 @@ class nsWindow final : public nsWindowBase {
void CreateCompositor() override;
void RequestFxrOutput();
void RecreateDirectManipulationIfNeeded();
void ResizeDirectManipulationViewport();
void DestroyDirectManipulation();
protected:
nsCOMPtr<nsIWidget> mParent;
nsIntSize mLastSize;
@ -728,6 +734,8 @@ class nsWindow final : public nsWindowBase {
// When true, used to indicate an async call to RequestFxrOutput to the GPU
// process after the Compositor is created
bool mRequestFxrOutputPending;
mozilla::UniquePtr<mozilla::widget::DirectManipulationOwner> mDmOwner;
};
#endif // Window_h__