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/. */
7 * WinPointerEvents - Helper functions to retrieve PointerEvent's attributes
11 #include "nsWindowDefs.h"
12 #include "WinPointerEvents.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
=
28 WinPointerEvents::WinPointerEvents() { InitLibrary(); }
30 /* Load and shutdown */
31 void WinPointerEvents::InitLibrary() {
32 MOZ_ASSERT(XRE_IsParentProcess());
34 // Return if we already initialized the PointerEvent related interfaces
37 sLibraryHandle
= ::LoadLibraryW(kPointerLibraryName
);
38 MOZ_ASSERT(sLibraryHandle
, "cannot load pointer library");
41 (GetPointerTypePtr
)GetProcAddress(sLibraryHandle
, "GetPointerType");
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;
57 bool WinPointerEvents::ShouldHandleWinPointerMessages(UINT aMsg
,
59 MOZ_ASSERT(aMsg
== WM_POINTERDOWN
|| aMsg
== WM_POINTERUP
||
60 aMsg
== WM_POINTERUPDATE
|| aMsg
== WM_POINTERLEAVE
);
61 if (!sLibraryHandle
) {
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
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");
74 return (pointerType
== PT_PEN
);
77 bool WinPointerEvents::GetPointerType(uint32_t aPointerId
,
78 POINTER_INPUT_TYPE
* aPointerType
) {
79 if (!getPointerType
) {
82 return getPointerType(aPointerId
, aPointerType
);
86 WinPointerEvents::GetPointerType(uint32_t aPointerId
) {
87 POINTER_INPUT_TYPE pointerType
= PT_POINTER
;
88 Unused
<< GetPointerType(aPointerId
, &pointerType
);
92 bool WinPointerEvents::GetPointerInfo(uint32_t aPointerId
,
93 POINTER_INFO
* aPointerInfo
) {
94 if (!getPointerInfo
) {
97 return getPointerInfo(aPointerId
, aPointerInfo
);
100 bool WinPointerEvents::GetPointerPenInfo(uint32_t aPointerId
,
101 POINTER_PEN_INFO
* aPenInfo
) {
102 if (!getPointerPenInfo
) {
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
,
123 if (!sLibraryHandle
||
124 MOUSE_INPUT_SOURCE() != dom::MouseEvent_Binding::MOZ_SOURCE_PEN
||
125 ShouldFirePointerEventByWinPointerMessages()) {
132 return &mPenPointerDownInfo
;
136 return &mPenPointerDownInfo
;
138 return &mPenPointerUpdateInfo
;
145 void WinPointerEvents::ConvertAndCachePointerInfo(UINT aMsg
, WPARAM aWParam
) {
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.
155 ConvertAndCachePointerInfo(aWParam
, &mPenPointerDownInfo
);
158 ConvertAndCachePointerInfo(aWParam
, &mPenPointerUpInfo
);
160 case WM_POINTERUPDATE
:
161 ConvertAndCachePointerInfo(aWParam
, &mPenPointerUpdateInfo
);
168 void WinPointerEvents::ConvertAndCachePointerInfo(WPARAM aWParam
,
169 WinPointerInfo
* aInfo
) {
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;