Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(73)

Side by Side Diff: content/browser/renderer_host/web_input_event_factory_win.cc

Issue 19776016: Add files. Does not compile yet! (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: gtk links, may not work correctly Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 /*
2 * Copyright (C) 2006-2009 Google Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 *
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
13 * distribution.
14 * * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #include "config.h"
32 #include "WebInputEventFactory.h"
33
34 #include "WebInputEvent.h"
35
36 #include <wtf/Assertions.h>
37
38 namespace WebKit {
39
40 static const unsigned long defaultScrollLinesPerWheelDelta = 3;
41 static const unsigned long defaultScrollCharsPerWheelDelta = 1;
42
43 // WebKeyboardEvent -----------------------------------------------------------
44
45 static bool isKeyDown(WPARAM wparam) { return GetKeyState(wparam) & 0x8000; }
46
47 static int getLocationModifier(WPARAM wparam, LPARAM lparam) {
48 int modifier = 0;
49 switch (wparam) {
50 case VK_RETURN:
51 if ((lparam >> 16) & KF_EXTENDED)
52 modifier = WebInputEvent::IsKeyPad;
53 break;
54 case VK_INSERT:
55 case VK_DELETE:
56 case VK_HOME:
57 case VK_END:
58 case VK_PRIOR:
59 case VK_NEXT:
60 case VK_UP:
61 case VK_DOWN:
62 case VK_LEFT:
63 case VK_RIGHT:
64 if (!((lparam >> 16) & KF_EXTENDED))
65 modifier = WebInputEvent::IsKeyPad;
66 break;
67 case VK_NUMLOCK:
68 case VK_NUMPAD0:
69 case VK_NUMPAD1:
70 case VK_NUMPAD2:
71 case VK_NUMPAD3:
72 case VK_NUMPAD4:
73 case VK_NUMPAD5:
74 case VK_NUMPAD6:
75 case VK_NUMPAD7:
76 case VK_NUMPAD8:
77 case VK_NUMPAD9:
78 case VK_DIVIDE:
79 case VK_MULTIPLY:
80 case VK_SUBTRACT:
81 case VK_ADD:
82 case VK_DECIMAL:
83 case VK_CLEAR:
84 modifier = WebInputEvent::IsKeyPad;
85 break;
86 case VK_SHIFT:
87 if (isKeyDown(VK_LSHIFT))
88 modifier = WebInputEvent::IsLeft;
89 else if (isKeyDown(VK_RSHIFT))
90 modifier = WebInputEvent::IsRight;
91 break;
92 case VK_CONTROL:
93 if (isKeyDown(VK_LCONTROL))
94 modifier = WebInputEvent::IsLeft;
95 else if (isKeyDown(VK_RCONTROL))
96 modifier = WebInputEvent::IsRight;
97 break;
98 case VK_MENU:
99 if (isKeyDown(VK_LMENU))
100 modifier = WebInputEvent::IsLeft;
101 else if (isKeyDown(VK_RMENU))
102 modifier = WebInputEvent::IsRight;
103 break;
104 case VK_LWIN:
105 modifier = WebInputEvent::IsLeft;
106 break;
107 case VK_RWIN:
108 modifier = WebInputEvent::IsRight;
109 break;
110 }
111
112 ASSERT(!modifier || modifier == WebInputEvent::IsKeyPad ||
113 modifier == WebInputEvent::IsLeft ||
114 modifier == WebInputEvent::IsRight);
115 return modifier;
116 }
117
118 // Loads the state for toggle keys into the event.
119 static void SetToggleKeyState(WebInputEvent* event) {
120 // Low bit set from GetKeyState indicates "toggled".
121 if (::GetKeyState(VK_NUMLOCK) & 1)
122 event->modifiers |= WebInputEvent::NumLockOn;
123 if (::GetKeyState(VK_CAPITAL) & 1)
124 event->modifiers |= WebInputEvent::CapsLockOn;
125 }
126
127 WebKeyboardEvent WebInputEventFactory::keyboardEvent(HWND hwnd,
128 UINT message,
129 WPARAM wparam,
130 LPARAM lparam) {
131 WebKeyboardEvent result;
132
133 // TODO(pkasting): http://b/1117926 Are we guaranteed that the message that
134 // GetMessageTime() refers to is the same one that we're passed in? Perhaps
135 // one of the construction parameters should be the time passed by the
136 // caller, who would know for sure.
137 result.timeStampSeconds = GetMessageTime() / 1000.0;
138
139 result.windowsKeyCode = static_cast<int>(wparam);
140 // Record the scan code (along with other context bits) for this key event.
141 result.nativeKeyCode = static_cast<int>(lparam);
142
143 switch (message) {
144 case WM_SYSKEYDOWN:
145 result.isSystemKey = true;
146 case WM_KEYDOWN:
147 result.type = WebInputEvent::RawKeyDown;
148 break;
149 case WM_SYSKEYUP:
150 result.isSystemKey = true;
151 case WM_KEYUP:
152 result.type = WebInputEvent::KeyUp;
153 break;
154 case WM_IME_CHAR:
155 result.type = WebInputEvent::Char;
156 break;
157 case WM_SYSCHAR:
158 result.isSystemKey = true;
159 result.type = WebInputEvent::Char;
160 case WM_CHAR:
161 result.type = WebInputEvent::Char;
162 break;
163 default:
164 ASSERT_NOT_REACHED();
165 }
166
167 if (result.type == WebInputEvent::Char ||
168 result.type == WebInputEvent::RawKeyDown) {
169 result.text[0] = result.windowsKeyCode;
170 result.unmodifiedText[0] = result.windowsKeyCode;
171 }
172 if (result.type != WebInputEvent::Char)
173 result.setKeyIdentifierFromWindowsKeyCode();
174
175 if (GetKeyState(VK_SHIFT) & 0x8000)
176 result.modifiers |= WebInputEvent::ShiftKey;
177 if (GetKeyState(VK_CONTROL) & 0x8000)
178 result.modifiers |= WebInputEvent::ControlKey;
179 if (GetKeyState(VK_MENU) & 0x8000)
180 result.modifiers |= WebInputEvent::AltKey;
181 // NOTE: There doesn't seem to be a way to query the mouse button state in
182 // this case.
183
184 if (LOWORD(lparam) > 1)
185 result.modifiers |= WebInputEvent::IsAutoRepeat;
186
187 result.modifiers |= getLocationModifier(wparam, lparam);
188
189 SetToggleKeyState(&result);
190 return result;
191 }
192
193 // WebMouseEvent --------------------------------------------------------------
194
195 static int gLastClickCount;
196 static double gLastClickTime;
197
198 static LPARAM GetRelativeCursorPos(HWND hwnd) {
199 POINT pos = {-1, -1};
200 GetCursorPos(&pos);
201 ScreenToClient(hwnd, &pos);
202 return MAKELPARAM(pos.x, pos.y);
203 }
204
205 void WebInputEventFactory::resetLastClickState() {
206 gLastClickTime = gLastClickCount = 0;
207 }
208
209 WebMouseEvent WebInputEventFactory::mouseEvent(HWND hwnd,
210 UINT message,
211 WPARAM wparam,
212 LPARAM lparam) {
213 WebMouseEvent result; //(WebInputEvent::Uninitialized());
214
215 switch (message) {
216 case WM_MOUSEMOVE:
217 result.type = WebInputEvent::MouseMove;
218 if (wparam & MK_LBUTTON)
219 result.button = WebMouseEvent::ButtonLeft;
220 else if (wparam & MK_MBUTTON)
221 result.button = WebMouseEvent::ButtonMiddle;
222 else if (wparam & MK_RBUTTON)
223 result.button = WebMouseEvent::ButtonRight;
224 else
225 result.button = WebMouseEvent::ButtonNone;
226 break;
227 case WM_MOUSELEAVE:
228 result.type = WebInputEvent::MouseLeave;
229 result.button = WebMouseEvent::ButtonNone;
230 // set the current mouse position (relative to the client area of the
231 // current window) since none is specified for this event
232 lparam = GetRelativeCursorPos(hwnd);
233 break;
234 case WM_LBUTTONDOWN:
235 case WM_LBUTTONDBLCLK:
236 result.type = WebInputEvent::MouseDown;
237 result.button = WebMouseEvent::ButtonLeft;
238 break;
239 case WM_MBUTTONDOWN:
240 case WM_MBUTTONDBLCLK:
241 result.type = WebInputEvent::MouseDown;
242 result.button = WebMouseEvent::ButtonMiddle;
243 break;
244 case WM_RBUTTONDOWN:
245 case WM_RBUTTONDBLCLK:
246 result.type = WebInputEvent::MouseDown;
247 result.button = WebMouseEvent::ButtonRight;
248 break;
249 case WM_LBUTTONUP:
250 result.type = WebInputEvent::MouseUp;
251 result.button = WebMouseEvent::ButtonLeft;
252 break;
253 case WM_MBUTTONUP:
254 result.type = WebInputEvent::MouseUp;
255 result.button = WebMouseEvent::ButtonMiddle;
256 break;
257 case WM_RBUTTONUP:
258 result.type = WebInputEvent::MouseUp;
259 result.button = WebMouseEvent::ButtonRight;
260 break;
261 default:
262 ASSERT_NOT_REACHED();
263 }
264
265 // TODO(pkasting): http://b/1117926 Are we guaranteed that the message that
266 // GetMessageTime() refers to is the same one that we're passed in? Perhaps
267 // one of the construction parameters should be the time passed by the
268 // caller, who would know for sure.
269 result.timeStampSeconds = GetMessageTime() / 1000.0;
270
271 // set position fields:
272
273 result.x = static_cast<short>(LOWORD(lparam));
274 result.y = static_cast<short>(HIWORD(lparam));
275 result.windowX = result.x;
276 result.windowY = result.y;
277
278 POINT globalPoint = {result.x, result.y};
279 ClientToScreen(hwnd, &globalPoint);
280
281 result.globalX = globalPoint.x;
282 result.globalY = globalPoint.y;
283
284 // calculate number of clicks:
285
286 // This differs slightly from the WebKit code in WebKit/win/WebView.cpp
287 // where their original code looks buggy.
288 static int lastClickPositionX;
289 static int lastClickPositionY;
290 static WebMouseEvent::Button lastClickButton = WebMouseEvent::ButtonLeft;
291
292 double currentTime = result.timeStampSeconds;
293 bool cancelPreviousClick =
294 (abs(lastClickPositionX - result.x) >
295 (GetSystemMetrics(SM_CXDOUBLECLK) / 2)) ||
296 (abs(lastClickPositionY - result.y) >
297 (GetSystemMetrics(SM_CYDOUBLECLK) / 2)) ||
298 ((currentTime - gLastClickTime) * 1000.0 > GetDoubleClickTime());
299
300 if (result.type == WebInputEvent::MouseDown) {
301 if (!cancelPreviousClick && (result.button == lastClickButton))
302 ++gLastClickCount;
303 else {
304 gLastClickCount = 1;
305 lastClickPositionX = result.x;
306 lastClickPositionY = result.y;
307 }
308 gLastClickTime = currentTime;
309 lastClickButton = result.button;
310 } else if (result.type == WebInputEvent::MouseMove ||
311 result.type == WebInputEvent::MouseLeave) {
312 if (cancelPreviousClick) {
313 gLastClickCount = 0;
314 lastClickPositionX = 0;
315 lastClickPositionY = 0;
316 gLastClickTime = 0;
317 }
318 }
319 result.clickCount = gLastClickCount;
320
321 // set modifiers:
322
323 if (wparam & MK_CONTROL)
324 result.modifiers |= WebInputEvent::ControlKey;
325 if (wparam & MK_SHIFT)
326 result.modifiers |= WebInputEvent::ShiftKey;
327 if (GetKeyState(VK_MENU) & 0x8000)
328 result.modifiers |= WebInputEvent::AltKey;
329 if (wparam & MK_LBUTTON)
330 result.modifiers |= WebInputEvent::LeftButtonDown;
331 if (wparam & MK_MBUTTON)
332 result.modifiers |= WebInputEvent::MiddleButtonDown;
333 if (wparam & MK_RBUTTON)
334 result.modifiers |= WebInputEvent::RightButtonDown;
335
336 SetToggleKeyState(&result);
337 return result;
338 }
339
340 // WebMouseWheelEvent ---------------------------------------------------------
341
342 WebMouseWheelEvent WebInputEventFactory::mouseWheelEvent(HWND hwnd,
343 UINT message,
344 WPARAM wparam,
345 LPARAM lparam) {
346 WebMouseWheelEvent result; //(WebInputEvent::Uninitialized());
347
348 result.type = WebInputEvent::MouseWheel;
349
350 // TODO(pkasting): http://b/1117926 Are we guaranteed that the message that
351 // GetMessageTime() refers to is the same one that we're passed in? Perhaps
352 // one of the construction parameters should be the time passed by the
353 // caller, who would know for sure.
354 result.timeStampSeconds = GetMessageTime() / 1000.0;
355
356 result.button = WebMouseEvent::ButtonNone;
357
358 // Get key state, coordinates, and wheel delta from event.
359 typedef SHORT(WINAPI * GetKeyStateFunction)(int key);
360 GetKeyStateFunction getKeyState;
361 UINT keyState;
362 float wheelDelta;
363 bool horizontalScroll = false;
364 if ((message == WM_VSCROLL) || (message == WM_HSCROLL)) {
365 // Synthesize mousewheel event from a scroll event. This is needed to
366 // simulate middle mouse scrolling in some laptops. Use GetAsyncKeyState
367 // for key state since we are synthesizing the input event.
368 getKeyState = GetAsyncKeyState;
369 keyState = 0;
370 if (getKeyState(VK_SHIFT))
371 keyState |= MK_SHIFT;
372 if (getKeyState(VK_CONTROL))
373 keyState |= MK_CONTROL;
374 // NOTE: There doesn't seem to be a way to query the mouse button state
375 // in this case.
376
377 POINT cursorPosition = {0};
378 GetCursorPos(&cursorPosition);
379 result.globalX = cursorPosition.x;
380 result.globalY = cursorPosition.y;
381
382 switch (LOWORD(wparam)) {
383 case SB_LINEUP: // == SB_LINELEFT
384 wheelDelta = WHEEL_DELTA;
385 break;
386 case SB_LINEDOWN: // == SB_LINERIGHT
387 wheelDelta = -WHEEL_DELTA;
388 break;
389 case SB_PAGEUP:
390 wheelDelta = 1;
391 result.scrollByPage = true;
392 break;
393 case SB_PAGEDOWN:
394 wheelDelta = -1;
395 result.scrollByPage = true;
396 break;
397 default: // We don't supoprt SB_THUMBPOSITION or SB_THUMBTRACK here.
398 wheelDelta = 0;
399 break;
400 }
401
402 if (message == WM_HSCROLL)
403 horizontalScroll = true;
404 } else {
405 // Non-synthesized event; we can just read data off the event.
406 getKeyState = GetKeyState;
407 keyState = GET_KEYSTATE_WPARAM(wparam);
408
409 result.globalX = static_cast<short>(LOWORD(lparam));
410 result.globalY = static_cast<short>(HIWORD(lparam));
411
412 wheelDelta = static_cast<float>(GET_WHEEL_DELTA_WPARAM(wparam));
413 if (message == WM_MOUSEHWHEEL) {
414 horizontalScroll = true;
415 wheelDelta = -wheelDelta; // Windows is <- -/+ ->, WebKit <- +/- ->.
416 }
417 }
418 if (keyState & MK_SHIFT)
419 horizontalScroll = true;
420
421 // Set modifiers based on key state.
422 if (keyState & MK_SHIFT)
423 result.modifiers |= WebInputEvent::ShiftKey;
424 if (keyState & MK_CONTROL)
425 result.modifiers |= WebInputEvent::ControlKey;
426 if (getKeyState(VK_MENU) & 0x8000)
427 result.modifiers |= WebInputEvent::AltKey;
428 if (keyState & MK_LBUTTON)
429 result.modifiers |= WebInputEvent::LeftButtonDown;
430 if (keyState & MK_MBUTTON)
431 result.modifiers |= WebInputEvent::MiddleButtonDown;
432 if (keyState & MK_RBUTTON)
433 result.modifiers |= WebInputEvent::RightButtonDown;
434
435 SetToggleKeyState(&result);
436
437 // Set coordinates by translating event coordinates from screen to client.
438 POINT clientPoint = {result.globalX, result.globalY};
439 MapWindowPoints(0, hwnd, &clientPoint, 1);
440 result.x = clientPoint.x;
441 result.y = clientPoint.y;
442 result.windowX = result.x;
443 result.windowY = result.y;
444
445 // Convert wheel delta amount to a number of pixels to scroll.
446 //
447 // How many pixels should we scroll per line? Gecko uses the height of the
448 // current line, which means scroll distance changes as you go through the
449 // page or go to different pages. IE 8 is ~60 px/line, although the value
450 // seems to vary slightly by page and zoom level. Also, IE defaults to
451 // smooth scrolling while Firefox doesn't, so it can get away with somewhat
452 // larger scroll values without feeling as jerky. Here we use 100 px per
453 // three lines (the default scroll amount is three lines per wheel tick).
454 // Even though we have smooth scrolling, we don't make this as large as IE
455 // because subjectively IE feels like it scrolls farther than you want while
456 // reading articles.
457 static const float scrollbarPixelsPerLine = 100.0f / 3.0f;
458 wheelDelta /= WHEEL_DELTA;
459 float scrollDelta = wheelDelta;
460 if (horizontalScroll) {
461 unsigned long scrollChars = defaultScrollCharsPerWheelDelta;
462 SystemParametersInfo(SPI_GETWHEELSCROLLCHARS, 0, &scrollChars, 0);
463 // TODO(pkasting): Should probably have a different multiplier
464 // scrollbarPixelsPerChar here.
465 scrollDelta *= static_cast<float>(scrollChars) * scrollbarPixelsPerLine;
466 } else {
467 unsigned long scrollLines = defaultScrollLinesPerWheelDelta;
468 SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &scrollLines, 0);
469 if (scrollLines == WHEEL_PAGESCROLL)
470 result.scrollByPage = true;
471 if (!result.scrollByPage)
472 scrollDelta *= static_cast<float>(scrollLines) * scrollbarPixelsPerLine;
473 }
474
475 // Set scroll amount based on above calculations. WebKit expects positive
476 // deltaY to mean "scroll up" and positive deltaX to mean "scroll left".
477 if (horizontalScroll) {
478 result.deltaX = scrollDelta;
479 result.wheelTicksX = wheelDelta;
480 } else {
481 result.deltaY = scrollDelta;
482 result.wheelTicksY = wheelDelta;
483 }
484
485 return result;
486 }
487
488 } // namespace WebKit
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698