14GHOST_DirectManipulationHelper::GHOST_DirectManipulationHelper(
16 Microsoft::WRL::ComPtr<IDirectManipulationManager> directManipulationManager,
17 Microsoft::WRL::ComPtr<IDirectManipulationUpdateManager> directManipulationUpdateManager,
18 Microsoft::WRL::ComPtr<IDirectManipulationViewport> directManipulationViewport,
19 Microsoft::WRL::ComPtr<GHOST_DirectManipulationViewportEventHandler>
20 directManipulationEventHandler,
21 DWORD directManipulationViewportHandlerCookie,
22 bool isScrollDirectionInverted)
24 scroll_direction_reg_key_(
nullptr),
25 scroll_direction_change_event_(
nullptr),
26 direct_manipulation_manager_(directManipulationManager),
27 direct_manipulation_update_manager_(directManipulationUpdateManager),
28 direct_manipulation_viewport_(directManipulationViewport),
29 direct_manipulation_event_handler_(directManipulationEventHandler),
30 direct_manipulation_viewport_handler_cookie_(directManipulationViewportHandlerCookie),
31 is_scroll_direction_inverted_(isScrollDirectionInverted)
37#define DM_CHECK_RESULT_AND_EXIT_EARLY(hr, failMessage) \
39 if (!SUCCEEDED(hr)) { \
40 GHOST_PRINT(failMessage); \
45 Microsoft::WRL::ComPtr<IDirectManipulationManager> directManipulationManager;
46 HRESULT hr = ::CoCreateInstance(CLSID_DirectManipulationManager,
49 IID_PPV_ARGS(&directManipulationManager));
53 Microsoft::WRL::ComPtr<IDirectManipulationUpdateManager> directManipulationUpdateManager;
54 hr = directManipulationManager->GetUpdateManager(IID_PPV_ARGS(&directManipulationUpdateManager));
57 Microsoft::WRL::ComPtr<IDirectManipulationViewport> directManipulationViewport;
58 hr = directManipulationManager->CreateViewport(
59 nullptr, hWnd, IID_PPV_ARGS(&directManipulationViewport));
62 DIRECTMANIPULATION_CONFIGURATION configuration =
63 DIRECTMANIPULATION_CONFIGURATION_INTERACTION |
64 DIRECTMANIPULATION_CONFIGURATION_TRANSLATION_X |
65 DIRECTMANIPULATION_CONFIGURATION_TRANSLATION_Y |
66 DIRECTMANIPULATION_CONFIGURATION_TRANSLATION_INERTIA |
67 DIRECTMANIPULATION_CONFIGURATION_SCALING;
69 hr = directManipulationViewport->ActivateConfiguration(configuration);
74 hr = directManipulationViewport->SetViewportOptions(
75 DIRECTMANIPULATION_VIEWPORT_OPTIONS_MANUALUPDATE);
80 Microsoft::WRL::ComPtr<GHOST_DirectManipulationViewportEventHandler>
81 directManipulationEventHandler =
82 Microsoft::WRL::Make<GHOST_DirectManipulationViewportEventHandler>(dpi);
83 DWORD directManipulationViewportHandlerCookie;
84 directManipulationViewport->AddEventHandler(
85 hWnd, directManipulationEventHandler.Get(), &directManipulationViewportHandlerCookie);
89 RECT rect = {0, 0, 10000, 10000};
90 hr = directManipulationViewport->SetViewportRect(&rect);
93 hr = directManipulationManager->Activate(hWnd);
96 hr = directManipulationViewport->Enable();
99 directManipulationEventHandler->resetViewport(directManipulationViewport.Get());
101 bool isScrollDirectionInverted = getScrollDirectionFromReg();
103 auto instance =
new GHOST_DirectManipulationHelper(hWnd,
104 directManipulationManager,
105 directManipulationUpdateManager,
106 directManipulationViewport,
107 directManipulationEventHandler,
108 directManipulationViewportHandlerCookie,
109 isScrollDirectionInverted);
111 instance->registerScrollDirectionChangeListener();
115#undef DM_CHECK_RESULT_AND_EXIT_EARLY
118bool GHOST_DirectManipulationHelper::getScrollDirectionFromReg()
120 DWORD scrollDirectionRegValue, pcbData;
121 HRESULT hr = HRESULT_FROM_WIN32(
122 RegGetValueW(HKEY_CURRENT_USER,
123 L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\PrecisionTouchPad\\",
127 &scrollDirectionRegValue,
129 if (!SUCCEEDED(hr)) {
130 GHOST_PRINT(
"Failed to get scroll direction from registry\n");
134 return scrollDirectionRegValue == 0;
137void GHOST_DirectManipulationHelper::registerScrollDirectionChangeListener()
140 if (!scroll_direction_reg_key_) {
141 HRESULT hr = HRESULT_FROM_WIN32(
142 RegOpenKeyExW(HKEY_CURRENT_USER,
143 L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\PrecisionTouchPad\\",
146 &scroll_direction_reg_key_));
147 if (!SUCCEEDED(hr)) {
148 GHOST_PRINT(
"Failed to open scroll direction registry key\n");
153 if (!scroll_direction_change_event_) {
154 scroll_direction_change_event_ = CreateEventW(
nullptr,
true,
false,
nullptr);
157 ResetEvent(scroll_direction_change_event_);
159 HRESULT hr = HRESULT_FROM_WIN32(RegNotifyChangeKeyValue(scroll_direction_reg_key_,
161 REG_NOTIFY_CHANGE_LAST_SET,
162 scroll_direction_change_event_,
164 if (!SUCCEEDED(hr)) {
165 GHOST_PRINT(
"Failed to register scroll direction change listener\n");
172 [[maybe_unused]] HRESULT hr = direct_manipulation_viewport_->SetContact(pointerId);
173 GHOST_ASSERT(SUCCEEDED(hr),
"Viewport set contact failed\n");
175 if (WaitForSingleObject(scroll_direction_change_event_, 0) == WAIT_OBJECT_0) {
176 is_scroll_direction_inverted_ = getScrollDirectionFromReg();
177 registerScrollDirectionChangeListener();
183 if (direct_manipulation_event_handler_->dm_status == DIRECTMANIPULATION_RUNNING ||
184 direct_manipulation_event_handler_->dm_status == DIRECTMANIPULATION_INERTIA)
186 [[maybe_unused]] HRESULT hr = direct_manipulation_update_manager_->Update(
nullptr);
187 GHOST_ASSERT(SUCCEEDED(hr),
"DirectManipulationUpdateManager update failed\n");
193 direct_manipulation_event_handler_->dpi = dpi;
199 result.isScrollDirectionInverted = is_scroll_direction_inverted_;
201 direct_manipulation_event_handler_->accumulated_values = {0, 0, 0};
208 hr = direct_manipulation_viewport_->Stop();
211 hr = direct_manipulation_viewport_->RemoveEventHandler(
212 direct_manipulation_viewport_handler_cookie_);
213 GHOST_ASSERT(SUCCEEDED(hr),
"Viewport remove event handler failed\n");
215 hr = direct_manipulation_viewport_->Abandon();
216 GHOST_ASSERT(SUCCEEDED(hr),
"Viewport abandon failed\n");
218 hr = direct_manipulation_manager_->Deactivate(h_wnd_);
219 GHOST_ASSERT(SUCCEEDED(hr),
"DirectManipulationManager deactivate failed\n");
221 if (scroll_direction_change_event_) {
222 CloseHandle(scroll_direction_change_event_);
223 scroll_direction_change_event_ =
nullptr;
225 if (scroll_direction_reg_key_) {
226 RegCloseKey(scroll_direction_reg_key_);
227 scroll_direction_reg_key_ =
nullptr;
233 : accumulated_values({0, 0, 0}), dpi(dpi), dm_status(DIRECTMANIPULATION_BUILDING)
238 IDirectManipulationViewport *viewport)
240 if (gesture_state != GESTURE_NONE) {
241 [[maybe_unused]] HRESULT hr = viewport->ZoomToRect(0.0f, 0.0f, 10000.0f, 10000.0f,
FALSE);
245 gesture_state = GESTURE_NONE;
253 IDirectManipulationViewport *viewport,
254 DIRECTMANIPULATION_STATUS current,
255 DIRECTMANIPULATION_STATUS previous)
259 if (current == previous) {
263 if (previous == DIRECTMANIPULATION_ENABLED || current == DIRECTMANIPULATION_READY ||
264 (previous == DIRECTMANIPULATION_INERTIA && current != DIRECTMANIPULATION_INERTIA))
273 IDirectManipulationViewport * )
280 IDirectManipulationViewport * , IDirectManipulationContent *content)
284 GHOST_ASSERT(SUCCEEDED(hr),
"DirectManipulationContent get transform failed\n");
286 const float device_scale_factor = dpi / 96.0f;
289 const float x =
transform[4] / device_scale_factor;
290 const float y =
transform[5] / device_scale_factor;
292 const float EPS = 3
e-5;
304 if (gesture_state == GESTURE_NONE) {
305 gesture_state = GESTURE_PAN;
310 if (gesture_state == GESTURE_PAN) {
312 gesture_state = GESTURE_PINCH;
324 switch (gesture_state) {
325 case GESTURE_PINCH: {
328 last_scale += dscale;
330 accumulated_values.scale += dscale;
340 accumulated_values.x += dx;
341 accumulated_values.y += dy;
#define GHOST_ASSERT(x, info)
#define DM_CHECK_RESULT_AND_EXIT_EARLY(hr, failMessage)
#define PINCH_SCALE_FACTOR
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
SIMD_FORCE_INLINE btVector3 transform(const btVector3 &point) const
void setDPI(uint16_t dpi)
~GHOST_DirectManipulationHelper()
void onPointerHitTest(UINT32 pointerId)
static GHOST_DirectManipulationHelper * create(HWND hWnd, uint16_t dpi)
GHOST_TTrackpadInfo getTrackpadInfo()
void resetViewport(IDirectManipulationViewport *viewport)
HRESULT STDMETHODCALLTYPE OnContentUpdated(IDirectManipulationViewport *viewport, IDirectManipulationContent *content) override
HRESULT STDMETHODCALLTYPE OnViewportUpdated(IDirectManipulationViewport *viewport) override
GHOST_DirectManipulationViewportEventHandler(uint16_t dpi)
HRESULT STDMETHODCALLTYPE OnViewportStatusChanged(IDirectManipulationViewport *viewport, DIRECTMANIPULATION_STATUS current, DIRECTMANIPULATION_STATUS previous) override
ccl_device_inline float2 fabs(const float2 a)