Bug 1861709 replace AudioCallbackDriver::ThreadRunning() assertions that mean to...
[gecko.git] / widget / windows / WinPointerEvents.cpp
blob57e19a0c4b01d350e745e71b7ddbe0b017c7ab70
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 /*
7 * WinPointerEvents - Helper functions to retrieve PointerEvent's attributes
8 */
10 #include "nscore.h"
11 #include "nsWindowDefs.h"
12 #include "WinPointerEvents.h"
13 #include "WinUtils.h"
14 #include "mozilla/MouseEvents.h"
15 #include "mozilla/StaticPrefs_dom.h"
16 #include "mozilla/dom/MouseEventBinding.h"
18 using namespace mozilla;
19 using namespace mozilla::widget;
21 const wchar_t WinPointerEvents::kPointerLibraryName[] = L"user32.dll";
22 HMODULE WinPointerEvents::sLibraryHandle = nullptr;
23 WinPointerEvents::GetPointerTypePtr WinPointerEvents::getPointerType = nullptr;
24 WinPointerEvents::GetPointerInfoPtr WinPointerEvents::getPointerInfo = nullptr;
25 WinPointerEvents::GetPointerPenInfoPtr WinPointerEvents::getPointerPenInfo =
26 nullptr;
28 WinPointerEvents::WinPointerEvents() { InitLibrary(); }
30 /* Load and shutdown */
31 void WinPointerEvents::InitLibrary() {
32 MOZ_ASSERT(XRE_IsParentProcess());
33 if (getPointerType) {
34 // Return if we already initialized the PointerEvent related interfaces
35 return;
37 sLibraryHandle = ::LoadLibraryW(kPointerLibraryName);
38 MOZ_ASSERT(sLibraryHandle, "cannot load pointer library");
39 if (sLibraryHandle) {
40 getPointerType =
41 (GetPointerTypePtr)GetProcAddress(sLibraryHandle, "GetPointerType");
42 getPointerInfo =
43 (GetPointerInfoPtr)GetProcAddress(sLibraryHandle, "GetPointerInfo");
44 getPointerPenInfo = (GetPointerPenInfoPtr)GetProcAddress(
45 sLibraryHandle, "GetPointerPenInfo");
48 if (!getPointerType || !getPointerInfo || !getPointerPenInfo) {
49 MOZ_ASSERT(false, "get PointerEvent interfaces failed");
50 getPointerType = nullptr;
51 getPointerInfo = nullptr;
52 getPointerPenInfo = nullptr;
53 return;
57 bool WinPointerEvents::ShouldHandleWinPointerMessages(UINT aMsg,
58 WPARAM aWParam) {
59 MOZ_ASSERT(aMsg == WM_POINTERDOWN || aMsg == WM_POINTERUP ||
60 aMsg == WM_POINTERUPDATE || aMsg == WM_POINTERLEAVE);
61 if (!sLibraryHandle) {
62 return false;
65 // We only handle WM_POINTER* when the input source is pen. This is because
66 // we need some information (e.g. tiltX, tiltY) which can't be retrieved by
67 // WM_*BUTTONDOWN.
68 uint32_t pointerId = GetPointerId(aWParam);
69 POINTER_INPUT_TYPE pointerType = PT_POINTER;
70 if (!GetPointerType(pointerId, &pointerType)) {
71 MOZ_ASSERT(false, "cannot find PointerType");
72 return false;
74 return (pointerType == PT_PEN);
77 bool WinPointerEvents::GetPointerType(uint32_t aPointerId,
78 POINTER_INPUT_TYPE* aPointerType) {
79 if (!getPointerType) {
80 return false;
82 return getPointerType(aPointerId, aPointerType);
85 POINTER_INPUT_TYPE
86 WinPointerEvents::GetPointerType(uint32_t aPointerId) {
87 POINTER_INPUT_TYPE pointerType = PT_POINTER;
88 Unused << GetPointerType(aPointerId, &pointerType);
89 return pointerType;
92 bool WinPointerEvents::GetPointerInfo(uint32_t aPointerId,
93 POINTER_INFO* aPointerInfo) {
94 if (!getPointerInfo) {
95 return false;
97 return getPointerInfo(aPointerId, aPointerInfo);
100 bool WinPointerEvents::GetPointerPenInfo(uint32_t aPointerId,
101 POINTER_PEN_INFO* aPenInfo) {
102 if (!getPointerPenInfo) {
103 return false;
105 return getPointerPenInfo(aPointerId, aPenInfo);
108 bool WinPointerEvents::ShouldRollupOnPointerEvent(UINT aMsg, WPARAM aWParam) {
109 MOZ_ASSERT(aMsg == WM_POINTERDOWN);
110 // Only roll up popups when we handling WM_POINTER* to fire Gecko
111 // WidgetMouseEvent and suppress Windows WM_*BUTTONDOWN.
112 return ShouldHandleWinPointerMessages(aMsg, aWParam) &&
113 ShouldFirePointerEventByWinPointerMessages();
116 bool WinPointerEvents::ShouldFirePointerEventByWinPointerMessages() {
117 MOZ_ASSERT(sLibraryHandle);
118 return StaticPrefs::dom_w3c_pointer_events_dispatch_by_pointer_messages();
121 WinPointerInfo* WinPointerEvents::GetCachedPointerInfo(UINT aMsg,
122 WPARAM aWParam) {
123 if (!sLibraryHandle ||
124 MOUSE_INPUT_SOURCE() != dom::MouseEvent_Binding::MOZ_SOURCE_PEN ||
125 ShouldFirePointerEventByWinPointerMessages()) {
126 return nullptr;
128 switch (aMsg) {
129 case WM_LBUTTONDOWN:
130 case WM_MBUTTONDOWN:
131 case WM_RBUTTONDOWN:
132 return &mPenPointerDownInfo;
133 case WM_LBUTTONUP:
134 case WM_MBUTTONUP:
135 case WM_RBUTTONUP:
136 return &mPenPointerDownInfo;
137 case WM_MOUSEMOVE:
138 return &mPenPointerUpdateInfo;
139 default:
140 MOZ_ASSERT(false);
142 return nullptr;
145 void WinPointerEvents::ConvertAndCachePointerInfo(UINT aMsg, WPARAM aWParam) {
146 MOZ_ASSERT(
147 !StaticPrefs::dom_w3c_pointer_events_dispatch_by_pointer_messages());
148 // Windows doesn't support chorded buttons for pen, so we can simply keep the
149 // latest information from pen generated pointer messages and use them when
150 // handling mouse messages. Used different pointer info for pointerdown,
151 // pointerupdate, and pointerup because Windows doesn't always interleave
152 // pointer messages and mouse messages.
153 switch (aMsg) {
154 case WM_POINTERDOWN:
155 ConvertAndCachePointerInfo(aWParam, &mPenPointerDownInfo);
156 break;
157 case WM_POINTERUP:
158 ConvertAndCachePointerInfo(aWParam, &mPenPointerUpInfo);
159 break;
160 case WM_POINTERUPDATE:
161 ConvertAndCachePointerInfo(aWParam, &mPenPointerUpdateInfo);
162 break;
163 default:
164 break;
168 void WinPointerEvents::ConvertAndCachePointerInfo(WPARAM aWParam,
169 WinPointerInfo* aInfo) {
170 MOZ_ASSERT(
171 !StaticPrefs::dom_w3c_pointer_events_dispatch_by_pointer_messages());
172 aInfo->pointerId = GetPointerId(aWParam);
173 MOZ_ASSERT(GetPointerType(aInfo->pointerId) == PT_PEN);
174 POINTER_PEN_INFO penInfo;
175 GetPointerPenInfo(aInfo->pointerId, &penInfo);
176 aInfo->tiltX = penInfo.tiltX;
177 aInfo->tiltY = penInfo.tiltY;
178 // Windows defines the pen pressure is normalized to a range between 0 and
179 // 1024. Convert it to float.
180 aInfo->mPressure = penInfo.pressure ? (float)penInfo.pressure / 1024 : 0;