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"
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::DispatchCommandEvent(uint32_t aEventCommand
)
200 nsCOMPtr
<nsIAtom
> command
;
201 switch (aEventCommand
) {
202 case APPCOMMAND_BROWSER_BACKWARD
:
203 command
= nsGkAtoms::Back
;
205 case APPCOMMAND_BROWSER_FORWARD
:
206 command
= nsGkAtoms::Forward
;
208 case APPCOMMAND_BROWSER_REFRESH
:
209 command
= nsGkAtoms::Reload
;
211 case APPCOMMAND_BROWSER_STOP
:
212 command
= nsGkAtoms::Stop
;
214 case APPCOMMAND_BROWSER_SEARCH
:
215 command
= nsGkAtoms::Search
;
217 case APPCOMMAND_BROWSER_FAVORITES
:
218 command
= nsGkAtoms::Bookmarks
;
220 case APPCOMMAND_BROWSER_HOME
:
221 command
= nsGkAtoms::Home
;
223 case APPCOMMAND_CLOSE
:
224 command
= nsGkAtoms::Close
;
226 case APPCOMMAND_FIND
:
227 command
= nsGkAtoms::Find
;
229 case APPCOMMAND_HELP
:
230 command
= nsGkAtoms::Help
;
233 command
= nsGkAtoms::New
;
235 case APPCOMMAND_OPEN
:
236 command
= nsGkAtoms::Open
;
238 case APPCOMMAND_PRINT
:
239 command
= nsGkAtoms::Print
;
241 case APPCOMMAND_SAVE
:
242 command
= nsGkAtoms::Save
;
244 case APPCOMMAND_FORWARD_MAIL
:
245 command
= nsGkAtoms::ForwardMail
;
247 case APPCOMMAND_REPLY_TO_MAIL
:
248 command
= nsGkAtoms::ReplyToMail
;
250 case APPCOMMAND_SEND_MAIL
:
251 command
= nsGkAtoms::SendMail
;
256 WidgetCommandEvent
event(true, nsGkAtoms::onAppCommand
, command
, this);
259 return DispatchWindowEvent(&event
);
263 nsWindowBase::HandleAppCommandMsg(WPARAM aWParam
,
267 uint32_t appCommand
= GET_APPCOMMAND_LPARAM(aLParam
);
268 uint32_t contentCommandMessage
= NS_EVENT_NULL
;
269 // XXX After we implement KeyboardEvent.key, we should dispatch the
270 // key event if (GET_DEVICE_LPARAM(lParam) == FAPPCOMMAND_KEY) is.
273 case APPCOMMAND_BROWSER_BACKWARD
:
274 case APPCOMMAND_BROWSER_FORWARD
:
275 case APPCOMMAND_BROWSER_REFRESH
:
276 case APPCOMMAND_BROWSER_STOP
:
277 case APPCOMMAND_BROWSER_SEARCH
:
278 case APPCOMMAND_BROWSER_FAVORITES
:
279 case APPCOMMAND_BROWSER_HOME
:
280 case APPCOMMAND_CLOSE
:
281 case APPCOMMAND_FIND
:
282 case APPCOMMAND_HELP
:
284 case APPCOMMAND_OPEN
:
285 case APPCOMMAND_PRINT
:
286 case APPCOMMAND_SAVE
:
287 case APPCOMMAND_FORWARD_MAIL
:
288 case APPCOMMAND_REPLY_TO_MAIL
:
289 case APPCOMMAND_SEND_MAIL
:
290 // We shouldn't consume the message always because if we don't handle
291 // the message, the sender (typically, utility of keyboard or mouse)
292 // may send other key messages which indicate well known shortcut key.
293 if (DispatchCommandEvent(appCommand
)) {
294 // tell the driver that we handled the event
300 // Use content command for following commands:
301 case APPCOMMAND_COPY
:
302 contentCommandMessage
= NS_CONTENT_COMMAND_COPY
;
305 contentCommandMessage
= NS_CONTENT_COMMAND_CUT
;
307 case APPCOMMAND_PASTE
:
308 contentCommandMessage
= NS_CONTENT_COMMAND_PASTE
;
310 case APPCOMMAND_REDO
:
311 contentCommandMessage
= NS_CONTENT_COMMAND_REDO
;
313 case APPCOMMAND_UNDO
:
314 contentCommandMessage
= NS_CONTENT_COMMAND_UNDO
;
318 if (contentCommandMessage
) {
319 WidgetContentCommandEvent
contentCommand(true, contentCommandMessage
,
321 DispatchWindowEvent(&contentCommand
);
322 // tell the driver that we handled the event
327 // default = false - tell the driver that the event was not handled