Files
test2/intern/ghost/intern/GHOST_TrackpadWin32.h
Andrii Symkin e58b18888c GHOST: Add support for precision touchpad gestures on Windows
This patch adds support for precision touchpad gestures on Windows 8.1
and newer using Direct Manipulation API. Gestures work exactly like on
macOS, with full support for pan/pinch and inertia. This works by
creating a viewport with a fake scrollable which is reset after every
gesture and converts any changes to the content's transform into GHOST
trackpad events (as explained [here](https://bugzilla.mozilla.org/show_bug.cgi?id=890878)).
The code is based on the implementation from the [Chromium project](https://chromium.googlesource.com/chromium/src/+/refs/heads/master/content/browser/renderer_host/direct_manipulation_helper_win.cc).

Tested on Windows 10.

Fixes {T70754}, {T69264}.

Demo:{F8520272}

Reviewed By: nicholas_rishel

Differential Revision: https://developer.blender.org/D7660
2022-05-06 00:40:27 -07:00

139 lines
4.4 KiB
C++

/* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup GHOST
* Declaration of GHOST DirectManipulation classes.
*/
#pragma once
#ifndef WIN32
# error WIN32 only!
#endif // WIN32
#include "GHOST_Types.h"
#include <directmanipulation.h>
#include <wrl.h>
#define PINCH_SCALE_FACTOR 125.0f
typedef struct {
int32_t x, y, scale;
bool isScrollDirectionInverted;
} GHOST_TTrackpadInfo;
class GHOST_DirectManipulationHelper;
class GHOST_DirectManipulationViewportEventHandler
: public Microsoft::WRL::RuntimeClass<
Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::RuntimeClassType::ClassicCom>,
Microsoft::WRL::Implements<
Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::RuntimeClassType::ClassicCom>,
Microsoft::WRL::FtmBase,
IDirectManipulationViewportEventHandler>> {
public:
GHOST_DirectManipulationViewportEventHandler(uint16_t dpi);
/*
* Resets viewport and tracked touchpad state.
*/
void resetViewport(IDirectManipulationViewport *viewport);
/* DirectManipulation callbacks. */
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;
private:
enum { GESTURE_NONE, GESTURE_PAN, GESTURE_PINCH } gesture_state;
int32_t last_x, last_y, last_scale;
GHOST_TTrackpadInfo accumulated_values;
uint16_t dpi;
DIRECTMANIPULATION_STATUS dm_status;
friend class GHOST_DirectManipulationHelper;
};
class GHOST_DirectManipulationHelper {
public:
/*
* Creates a GHOST_DirectManipulationHelper for the provided window.
* \param hWnd: The window receiving DirectManipulation events.
* \param dpi: The current DPI.
* \return Pointer to the new GHOST_DirectManipulationHelper if created, nullptr if there was an
* error.
*/
static GHOST_DirectManipulationHelper *create(HWND hWnd, uint16_t dpi);
~GHOST_DirectManipulationHelper();
/*
* Drives the DirectManipulation context.
* DirectManipulation's intended use is to tie user input into DirectComposition's compositor
* scaling and translating. We are not using DirectComposition and therefore must drive
* DirectManipulation manually.
*/
void update();
/*
* Sets pointer in contact with the DirectManipulation context.
* \param pointerId: ID of the pointer in contact.
*/
void onPointerHitTest(UINT32 pointerId);
/*
* Updates DPI information for touchpad scaling.
* \param dpi: The new DPI.
*/
void setDPI(uint16_t dpi);
/*
* Retrieves trackpad input.
* \return The accumulated trackpad translation and scale since last call.
*/
GHOST_TTrackpadInfo getTrackpadInfo();
private:
GHOST_DirectManipulationHelper(
HWND hWnd,
Microsoft::WRL::ComPtr<IDirectManipulationManager> directManipulationManager,
Microsoft::WRL::ComPtr<IDirectManipulationUpdateManager> directManipulationUpdateManager,
Microsoft::WRL::ComPtr<IDirectManipulationViewport> directManipulationViewport,
Microsoft::WRL::ComPtr<GHOST_DirectManipulationViewportEventHandler>
directManipulationEventHandler,
DWORD directManipulationViewportHandlerCookie,
bool isScrollDirectionInverted);
/*
* Retrieves the scroll direction from the registry.
* \return True if scroll direction is inverted.
*/
static bool getScrollDirectionFromReg();
/*
* Registers listener for registry scroll direction entry changes.
*/
void registerScrollDirectionChangeListener();
HWND m_hWnd;
HKEY m_scrollDirectionRegKey;
HANDLE m_scrollDirectionChangeEvent;
Microsoft::WRL::ComPtr<IDirectManipulationManager> m_directManipulationManager;
Microsoft::WRL::ComPtr<IDirectManipulationUpdateManager> m_directManipulationUpdateManager;
Microsoft::WRL::ComPtr<IDirectManipulationViewport> m_directManipulationViewport;
Microsoft::WRL::ComPtr<GHOST_DirectManipulationViewportEventHandler>
m_directManipulationEventHandler;
DWORD m_directManipulationViewportHandlerCookie;
bool m_isScrollDirectionInverted;
};