1 /* -*- Mode: C++; tab-width: 4; 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 #include "nsWindowBase.h"
8 #include "mozilla/MiscEvents.h"
9 #include "KeyboardLayout.h"
13 using namespace mozilla
;
14 using namespace mozilla::widget
;
16 static const wchar_t kUser32LibName
[] = L
"user32.dll";
17 bool nsWindowBase::sTouchInjectInitialized
= false;
18 InjectTouchInputPtr
nsWindowBase::sInjectTouchFuncPtr
;
21 nsWindowBase::DispatchPluginEvent(const MSG
& aMsg
)
23 if (!PluginHasFocus()) {
26 WidgetPluginEvent
pluginEvent(true, NS_PLUGIN_INPUT_EVENT
, this);
27 nsIntPoint
point(0, 0);
28 InitEvent(pluginEvent
, &point
);
30 npEvent
.event
= aMsg
.message
;
31 npEvent
.wParam
= aMsg
.wParam
;
32 npEvent
.lParam
= aMsg
.lParam
;
33 pluginEvent
.mPluginEvent
.Copy(npEvent
);
34 pluginEvent
.retargetToFocusedDocument
= true;
35 return DispatchWindowEvent(&pluginEvent
);
40 nsWindowBase::InitTouchInjection()
42 if (!sTouchInjectInitialized
) {
43 // Initialize touch injection on the first call
44 HMODULE hMod
= LoadLibraryW(kUser32LibName
);
49 InitializeTouchInjectionPtr func
=
50 (InitializeTouchInjectionPtr
)GetProcAddress(hMod
, "InitializeTouchInjection");
52 WinUtils::Log("InitializeTouchInjection not available.");
56 if (!func(TOUCH_INJECT_MAX_POINTS
, TOUCH_FEEDBACK_DEFAULT
)) {
57 WinUtils::Log("InitializeTouchInjection failure. GetLastError=%d", GetLastError());
62 (InjectTouchInputPtr
)GetProcAddress(hMod
, "InjectTouchInput");
63 if (!sInjectTouchFuncPtr
) {
64 WinUtils::Log("InjectTouchInput not available.");
67 sTouchInjectInitialized
= true;
73 nsWindowBase::InjectTouchPoint(uint32_t aId
, nsIntPoint
& aPointerScreenPoint
,
74 POINTER_FLAGS aFlags
, uint32_t aPressure
,
75 uint32_t aOrientation
)
77 if (aId
> TOUCH_INJECT_MAX_POINTS
) {
78 WinUtils::Log("Pointer ID exceeds maximum. See TOUCH_INJECT_MAX_POINTS.");
82 POINTER_TOUCH_INFO info
;
83 memset(&info
, 0, sizeof(POINTER_TOUCH_INFO
));
85 info
.touchFlags
= TOUCH_FLAG_NONE
;
86 info
.touchMask
= TOUCH_MASK_CONTACTAREA
|TOUCH_MASK_ORIENTATION
|TOUCH_MASK_PRESSURE
;
87 info
.pressure
= aPressure
;
88 info
.orientation
= aOrientation
;
90 info
.pointerInfo
.pointerFlags
= aFlags
;
91 info
.pointerInfo
.pointerType
= PT_TOUCH
;
92 info
.pointerInfo
.pointerId
= aId
;
93 info
.pointerInfo
.ptPixelLocation
.x
= WinUtils::LogToPhys(aPointerScreenPoint
.x
);
94 info
.pointerInfo
.ptPixelLocation
.y
= WinUtils::LogToPhys(aPointerScreenPoint
.y
);
96 info
.rcContact
.top
= info
.pointerInfo
.ptPixelLocation
.y
- 2;
97 info
.rcContact
.bottom
= info
.pointerInfo
.ptPixelLocation
.y
+ 2;
98 info
.rcContact
.left
= info
.pointerInfo
.ptPixelLocation
.x
- 2;
99 info
.rcContact
.right
= info
.pointerInfo
.ptPixelLocation
.x
+ 2;
101 if (!sInjectTouchFuncPtr(1, &info
)) {
102 WinUtils::Log("InjectTouchInput failure. GetLastError=%d", GetLastError());
109 nsWindowBase::SynthesizeNativeTouchPoint(uint32_t aPointerId
,
110 nsIWidget::TouchPointerState aPointerState
,
111 nsIntPoint aPointerScreenPoint
,
112 double aPointerPressure
,
113 uint32_t aPointerOrientation
)
115 if (!InitTouchInjection()) {
116 return NS_ERROR_NOT_IMPLEMENTED
;
119 bool hover
= aPointerState
& TOUCH_HOVER
;
120 bool contact
= aPointerState
& TOUCH_CONTACT
;
121 bool remove
= aPointerState
& TOUCH_REMOVE
;
122 bool cancel
= aPointerState
& TOUCH_CANCEL
;
124 // win api expects a value from 0 to 1024. aPointerPressure is a value
126 uint32_t pressure
= (uint32_t)ceil(aPointerPressure
* 1024);
128 // If we already know about this pointer id get it's record
129 PointerInfo
* info
= mActivePointers
.Get(aPointerId
);
131 // We know about this pointer, send an update
133 POINTER_FLAGS flags
= POINTER_FLAG_UPDATE
;
135 flags
|= POINTER_FLAG_INRANGE
;
136 } else if (contact
) {
137 flags
|= POINTER_FLAG_INCONTACT
|POINTER_FLAG_INRANGE
;
139 flags
= POINTER_FLAG_UP
;
140 // Remove the pointer from our tracking list. This is nsAutPtr wrapped,
141 // so shouldn't leak.
142 mActivePointers
.Remove(aPointerId
);
146 flags
|= POINTER_FLAG_CANCELED
;
149 return !InjectTouchPoint(aPointerId
, aPointerScreenPoint
, flags
,
150 pressure
, aPointerOrientation
) ?
151 NS_ERROR_UNEXPECTED
: NS_OK
;
154 // Missing init state, error out
155 if (remove
|| cancel
) {
156 return NS_ERROR_INVALID_ARG
;
159 // Create a new pointer
160 info
= new PointerInfo(aPointerId
, aPointerScreenPoint
);
162 POINTER_FLAGS flags
= POINTER_FLAG_INRANGE
;
164 flags
|= POINTER_FLAG_INCONTACT
|POINTER_FLAG_DOWN
;
167 mActivePointers
.Put(aPointerId
, info
);
168 return !InjectTouchPoint(aPointerId
, aPointerScreenPoint
, flags
,
169 pressure
, aPointerOrientation
) ?
170 NS_ERROR_UNEXPECTED
: NS_OK
;
175 nsWindowBase::CancelTouchPoints(const unsigned int& aPointerId
, nsAutoPtr
<PointerInfo
>& aInfo
, void* aUserArg
)
177 nsWindowBase
* self
= static_cast<nsWindowBase
*>(aUserArg
);
178 self
->InjectTouchPoint(aInfo
.get()->mPointerId
, aInfo
.get()->mPosition
, POINTER_FLAG_CANCELED
);
179 return (PLDHashOperator
)(PL_DHASH_NEXT
|PL_DHASH_REMOVE
);
183 nsWindowBase::ClearNativeTouchSequence()
185 if (!sTouchInjectInitialized
) {
189 // cancel all input points
190 mActivePointers
.Enumerate(CancelTouchPoints
, (void*)this);
192 nsBaseWidget::ClearNativeTouchSequence();
198 nsWindowBase::HandleAppCommandMsg(const MSG
& aAppCommandMsg
,
201 ModifierKeyState modKeyState
;
202 NativeKey
nativeKey(this, aAppCommandMsg
, modKeyState
);
203 bool consumed
= nativeKey
.HandleAppCommandMessage();
204 *aRetValue
= consumed
? 1 : 0;