Bumping manifests a=b2g-bump
[gecko.git] / widget / windows / nsWindowBase.cpp
blob4f0ae928e5319773f0ba5cc10f1ed55866053d63
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 "nsGkAtoms.h"
10 #include "WinUtils.h"
11 #include "npapi.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;
20 bool
21 nsWindowBase::DispatchPluginEvent(const MSG& aMsg)
23 if (!PluginHasFocus()) {
24 return false;
26 WidgetPluginEvent pluginEvent(true, NS_PLUGIN_INPUT_EVENT, this);
27 nsIntPoint point(0, 0);
28 InitEvent(pluginEvent, &point);
29 NPEvent npEvent;
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);
38 // static
39 bool
40 nsWindowBase::InitTouchInjection()
42 if (!sTouchInjectInitialized) {
43 // Initialize touch injection on the first call
44 HMODULE hMod = LoadLibraryW(kUser32LibName);
45 if (!hMod) {
46 return false;
49 InitializeTouchInjectionPtr func =
50 (InitializeTouchInjectionPtr)GetProcAddress(hMod, "InitializeTouchInjection");
51 if (!func) {
52 WinUtils::Log("InitializeTouchInjection not available.");
53 return false;
56 if (!func(TOUCH_INJECT_MAX_POINTS, TOUCH_FEEDBACK_DEFAULT)) {
57 WinUtils::Log("InitializeTouchInjection failure. GetLastError=%d", GetLastError());
58 return false;
61 sInjectTouchFuncPtr =
62 (InjectTouchInputPtr)GetProcAddress(hMod, "InjectTouchInput");
63 if (!sInjectTouchFuncPtr) {
64 WinUtils::Log("InjectTouchInput not available.");
65 return false;
67 sTouchInjectInitialized = true;
69 return true;
72 bool
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.");
79 return false;
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());
103 return false;
105 return true;
108 nsresult
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
125 // from 0.0 to 1.0.
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
132 if (info) {
133 POINTER_FLAGS flags = POINTER_FLAG_UPDATE;
134 if (hover) {
135 flags |= POINTER_FLAG_INRANGE;
136 } else if (contact) {
137 flags |= POINTER_FLAG_INCONTACT|POINTER_FLAG_INRANGE;
138 } else if (remove) {
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);
145 if (cancel) {
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;
163 if (contact) {
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;
173 // static
174 PLDHashOperator
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);
182 nsresult
183 nsWindowBase::ClearNativeTouchSequence()
185 if (!sTouchInjectInitialized) {
186 return NS_OK;
189 // cancel all input points
190 mActivePointers.Enumerate(CancelTouchPoints, (void*)this);
192 nsBaseWidget::ClearNativeTouchSequence();
194 return NS_OK;
197 bool
198 nsWindowBase::DispatchCommandEvent(uint32_t aEventCommand)
200 nsCOMPtr<nsIAtom> command;
201 switch (aEventCommand) {
202 case APPCOMMAND_BROWSER_BACKWARD:
203 command = nsGkAtoms::Back;
204 break;
205 case APPCOMMAND_BROWSER_FORWARD:
206 command = nsGkAtoms::Forward;
207 break;
208 case APPCOMMAND_BROWSER_REFRESH:
209 command = nsGkAtoms::Reload;
210 break;
211 case APPCOMMAND_BROWSER_STOP:
212 command = nsGkAtoms::Stop;
213 break;
214 case APPCOMMAND_BROWSER_SEARCH:
215 command = nsGkAtoms::Search;
216 break;
217 case APPCOMMAND_BROWSER_FAVORITES:
218 command = nsGkAtoms::Bookmarks;
219 break;
220 case APPCOMMAND_BROWSER_HOME:
221 command = nsGkAtoms::Home;
222 break;
223 case APPCOMMAND_CLOSE:
224 command = nsGkAtoms::Close;
225 break;
226 case APPCOMMAND_FIND:
227 command = nsGkAtoms::Find;
228 break;
229 case APPCOMMAND_HELP:
230 command = nsGkAtoms::Help;
231 break;
232 case APPCOMMAND_NEW:
233 command = nsGkAtoms::New;
234 break;
235 case APPCOMMAND_OPEN:
236 command = nsGkAtoms::Open;
237 break;
238 case APPCOMMAND_PRINT:
239 command = nsGkAtoms::Print;
240 break;
241 case APPCOMMAND_SAVE:
242 command = nsGkAtoms::Save;
243 break;
244 case APPCOMMAND_FORWARD_MAIL:
245 command = nsGkAtoms::ForwardMail;
246 break;
247 case APPCOMMAND_REPLY_TO_MAIL:
248 command = nsGkAtoms::ReplyToMail;
249 break;
250 case APPCOMMAND_SEND_MAIL:
251 command = nsGkAtoms::SendMail;
252 break;
253 default:
254 return false;
256 WidgetCommandEvent event(true, nsGkAtoms::onAppCommand, command, this);
258 InitEvent(event);
259 return DispatchWindowEvent(&event);
262 bool
263 nsWindowBase::HandleAppCommandMsg(WPARAM aWParam,
264 LPARAM aLParam,
265 LRESULT *aRetValue)
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.
271 switch (appCommand)
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:
283 case APPCOMMAND_NEW:
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
295 *aRetValue = 1;
296 return true;
298 break;
300 // Use content command for following commands:
301 case APPCOMMAND_COPY:
302 contentCommandMessage = NS_CONTENT_COMMAND_COPY;
303 break;
304 case APPCOMMAND_CUT:
305 contentCommandMessage = NS_CONTENT_COMMAND_CUT;
306 break;
307 case APPCOMMAND_PASTE:
308 contentCommandMessage = NS_CONTENT_COMMAND_PASTE;
309 break;
310 case APPCOMMAND_REDO:
311 contentCommandMessage = NS_CONTENT_COMMAND_REDO;
312 break;
313 case APPCOMMAND_UNDO:
314 contentCommandMessage = NS_CONTENT_COMMAND_UNDO;
315 break;
318 if (contentCommandMessage) {
319 WidgetContentCommandEvent contentCommand(true, contentCommandMessage,
320 this);
321 DispatchWindowEvent(&contentCommand);
322 // tell the driver that we handled the event
323 *aRetValue = 1;
324 return true;
327 // default = false - tell the driver that the event was not handled
328 return false;