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

Side by Side Diff: content/browser/renderer_host/input/web_input_event_builders_win.cc

Issue 19676008: Import windows WebInputEvent factory to content (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: remove dead code, fix namespace for aurawin 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
OLDNEW
(Empty)
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "content/browser/renderer_host/input/web_input_event_builders_win.h"
6
7 #include "base/logging.h"
8
9 using WebKit::WebInputEvent;
10 using WebKit::WebKeyboardEvent;
11 using WebKit::WebMouseEvent;
12 using WebKit::WebMouseWheelEvent;
13
14 namespace content {
15
16 static const unsigned long kDefaultScrollLinesPerWheelDelta = 3;
17 static const unsigned long kDefaultScrollCharsPerWheelDelta = 1;
18
19 static bool IsKeyDown(WPARAM wparam) {
20 return (GetKeyState(wparam) & 0x8000) != 0;
21 }
22
23 static int GetLocationModifier(WPARAM wparam, LPARAM lparam) {
24 int modifier = 0;
25 switch (wparam) {
26 case VK_RETURN:
27 if ((lparam >> 16) & KF_EXTENDED)
28 modifier = WebInputEvent::IsKeyPad;
29 break;
30 case VK_INSERT:
31 case VK_DELETE:
32 case VK_HOME:
33 case VK_END:
34 case VK_PRIOR:
35 case VK_NEXT:
36 case VK_UP:
37 case VK_DOWN:
38 case VK_LEFT:
39 case VK_RIGHT:
40 if (!((lparam >> 16) & KF_EXTENDED))
41 modifier = WebInputEvent::IsKeyPad;
42 break;
43 case VK_NUMLOCK:
44 case VK_NUMPAD0:
45 case VK_NUMPAD1:
46 case VK_NUMPAD2:
47 case VK_NUMPAD3:
48 case VK_NUMPAD4:
49 case VK_NUMPAD5:
50 case VK_NUMPAD6:
51 case VK_NUMPAD7:
52 case VK_NUMPAD8:
53 case VK_NUMPAD9:
54 case VK_DIVIDE:
55 case VK_MULTIPLY:
56 case VK_SUBTRACT:
57 case VK_ADD:
58 case VK_DECIMAL:
59 case VK_CLEAR:
60 modifier = WebInputEvent::IsKeyPad;
61 break;
62 case VK_SHIFT:
63 if (IsKeyDown(VK_LSHIFT))
64 modifier = WebInputEvent::IsLeft;
65 else if (IsKeyDown(VK_RSHIFT))
66 modifier = WebInputEvent::IsRight;
67 break;
68 case VK_CONTROL:
69 if (IsKeyDown(VK_LCONTROL))
70 modifier = WebInputEvent::IsLeft;
71 else if (IsKeyDown(VK_RCONTROL))
72 modifier = WebInputEvent::IsRight;
73 break;
74 case VK_MENU:
75 if (IsKeyDown(VK_LMENU))
76 modifier = WebInputEvent::IsLeft;
77 else if (IsKeyDown(VK_RMENU))
78 modifier = WebInputEvent::IsRight;
79 break;
80 case VK_LWIN:
81 modifier = WebInputEvent::IsLeft;
82 break;
83 case VK_RWIN:
84 modifier = WebInputEvent::IsRight;
85 break;
86 }
87
88 DCHECK(!modifier
89 || modifier == WebInputEvent::IsKeyPad
90 || modifier == WebInputEvent::IsLeft
91 || modifier == WebInputEvent::IsRight);
92 return modifier;
93 }
94
95 // Loads the state for toggle keys into the event.
96 static void SetToggleKeyState(WebInputEvent* event) {
97 // Low bit set from GetKeyState indicates "toggled".
98 if (::GetKeyState(VK_NUMLOCK) & 1)
99 event->modifiers |= WebInputEvent::NumLockOn;
100 if (::GetKeyState(VK_CAPITAL) & 1)
101 event->modifiers |= WebInputEvent::CapsLockOn;
102 }
103
104 WebKeyboardEvent WebKeyboardEventBuilder::Build(HWND hwnd, UINT message,
105 WPARAM wparam, LPARAM lparam) {
106 WebKeyboardEvent result;
107
108 // TODO(pkasting): http://b/1117926 Are we guaranteed that the message that
109 // GetMessageTime() refers to is the same one that we're passed in? Perhaps
110 // one of the construction parameters should be the time passed by the
111 // caller, who would know for sure.
112 result.timeStampSeconds = ::GetMessageTime() / 1000.0;
113
114 result.windowsKeyCode = static_cast<int>(wparam);
115 // Record the scan code (along with other context bits) for this key event.
116 result.nativeKeyCode = static_cast<int>(lparam);
117
118 switch (message) {
119 case WM_SYSKEYDOWN:
120 result.isSystemKey = true;
121 case WM_KEYDOWN:
122 result.type = WebInputEvent::RawKeyDown;
123 break;
124 case WM_SYSKEYUP:
125 result.isSystemKey = true;
126 case WM_KEYUP:
127 result.type = WebInputEvent::KeyUp;
128 break;
129 case WM_IME_CHAR:
130 result.type = WebInputEvent::Char;
131 break;
132 case WM_SYSCHAR:
133 result.isSystemKey = true;
134 result.type = WebInputEvent::Char;
135 case WM_CHAR:
136 result.type = WebInputEvent::Char;
137 break;
138 default:
139 NOTREACHED();
140 }
141
142 if (result.type == WebInputEvent::Char
143 || result.type == WebInputEvent::RawKeyDown) {
144 result.text[0] = result.windowsKeyCode;
145 result.unmodifiedText[0] = result.windowsKeyCode;
146 }
147 if (result.type != WebInputEvent::Char)
148 result.setKeyIdentifierFromWindowsKeyCode();
149
150 if (::GetKeyState(VK_SHIFT) & 0x8000)
151 result.modifiers |= WebInputEvent::ShiftKey;
152 if (::GetKeyState(VK_CONTROL) & 0x8000)
153 result.modifiers |= WebInputEvent::ControlKey;
154 if (::GetKeyState(VK_MENU) & 0x8000)
155 result.modifiers |= WebInputEvent::AltKey;
156 // NOTE: There doesn't seem to be a way to query the mouse button state in
157 // this case.
158
159 if (LOWORD(lparam) > 1)
160 result.modifiers |= WebInputEvent::IsAutoRepeat;
161
162 result.modifiers |= GetLocationModifier(wparam, lparam);
163
164 SetToggleKeyState(&result);
165 return result;
166 }
167
168 // WebMouseEvent --------------------------------------------------------------
169
170 static int g_last_click_count = 0;
171 static double g_last_click_time = 0;
172
173 static LPARAM GetRelativeCursorPos(HWND hwnd) {
174 POINT pos = {-1, -1};
175 GetCursorPos(&pos);
176 ScreenToClient(hwnd, &pos);
177 return MAKELPARAM(pos.x, pos.y);
178 }
179
180 WebMouseEvent WebMouseEventBuilder::Build(HWND hwnd, UINT message,
181 WPARAM wparam, LPARAM lparam) {
182 WebMouseEvent result;
183
184 switch (message) {
185 case WM_MOUSEMOVE:
186 result.type = WebInputEvent::MouseMove;
187 if (wparam & MK_LBUTTON)
188 result.button = WebMouseEvent::ButtonLeft;
189 else if (wparam & MK_MBUTTON)
190 result.button = WebMouseEvent::ButtonMiddle;
191 else if (wparam & MK_RBUTTON)
192 result.button = WebMouseEvent::ButtonRight;
193 else
194 result.button = WebMouseEvent::ButtonNone;
195 break;
196 case WM_MOUSELEAVE:
197 result.type = WebInputEvent::MouseLeave;
198 result.button = WebMouseEvent::ButtonNone;
199 // set the current mouse position (relative to the client area of the
200 // current window) since none is specified for this event
201 lparam = GetRelativeCursorPos(hwnd);
202 break;
203 case WM_LBUTTONDOWN:
204 case WM_LBUTTONDBLCLK:
205 result.type = WebInputEvent::MouseDown;
206 result.button = WebMouseEvent::ButtonLeft;
207 break;
208 case WM_MBUTTONDOWN:
209 case WM_MBUTTONDBLCLK:
210 result.type = WebInputEvent::MouseDown;
211 result.button = WebMouseEvent::ButtonMiddle;
212 break;
213 case WM_RBUTTONDOWN:
214 case WM_RBUTTONDBLCLK:
215 result.type = WebInputEvent::MouseDown;
216 result.button = WebMouseEvent::ButtonRight;
217 break;
218 case WM_LBUTTONUP:
219 result.type = WebInputEvent::MouseUp;
220 result.button = WebMouseEvent::ButtonLeft;
221 break;
222 case WM_MBUTTONUP:
223 result.type = WebInputEvent::MouseUp;
224 result.button = WebMouseEvent::ButtonMiddle;
225 break;
226 case WM_RBUTTONUP:
227 result.type = WebInputEvent::MouseUp;
228 result.button = WebMouseEvent::ButtonRight;
229 break;
230 default:
231 NOTREACHED();
232 }
233
234 // TODO(pkasting): http://b/1117926 Are we guaranteed that the message that
235 // GetMessageTime() refers to is the same one that we're passed in? Perhaps
236 // one of the construction parameters should be the time passed by the
237 // caller, who would know for sure.
238 result.timeStampSeconds = ::GetMessageTime() / 1000.0;
239
240 // set position fields:
241
242 result.x = static_cast<short>(LOWORD(lparam));
243 result.y = static_cast<short>(HIWORD(lparam));
244 result.windowX = result.x;
245 result.windowY = result.y;
246
247 POINT global_point = { result.x, result.y };
248 ClientToScreen(hwnd, &global_point);
249
250 result.globalX = global_point.x;
251 result.globalY = global_point.y;
252
253 // calculate number of clicks:
254
255 // This differs slightly from the WebKit code in WebKit/win/WebView.cpp
256 // where their original code looks buggy.
257 static int last_click_position_x;
258 static int last_click_position_Y;
259 static WebMouseEvent::Button last_click_button = WebMouseEvent::ButtonLeft;
260
261 double current_time = result.timeStampSeconds;
262 bool cancel_previous_click =
263 (abs(last_click_position_x - result.x) >
264 (::GetSystemMetrics(SM_CXDOUBLECLK) / 2))
265 || (abs(last_click_position_x - result.y) >
266 (::GetSystemMetrics(SM_CYDOUBLECLK) / 2))
267 || ((current_time - g_last_click_time) * 1000.0 > ::GetDoubleClickTime());
268
269 if (result.type == WebInputEvent::MouseDown) {
270 if (!cancel_previous_click && (result.button == last_click_button)) {
271 ++g_last_click_count;
272 } else {
273 g_last_click_count = 1;
274 last_click_position_x = result.x;
275 last_click_position_x = result.y;
276 }
277 g_last_click_time = current_time;
278 last_click_button = result.button;
279 } else if (result.type == WebInputEvent::MouseMove
280 || result.type == WebInputEvent::MouseLeave) {
281 if (cancel_previous_click) {
282 g_last_click_count = 0;
283 last_click_position_x = 0;
284 last_click_position_x = 0;
285 g_last_click_time = 0;
286 }
287 }
288 result.clickCount = g_last_click_count;
289
290 // set modifiers:
291
292 if (wparam & MK_CONTROL)
293 result.modifiers |= WebInputEvent::ControlKey;
294 if (wparam & MK_SHIFT)
295 result.modifiers |= WebInputEvent::ShiftKey;
296 if (::GetKeyState(VK_MENU) & 0x8000)
297 result.modifiers |= WebInputEvent::AltKey;
298 if (wparam & MK_LBUTTON)
299 result.modifiers |= WebInputEvent::LeftButtonDown;
300 if (wparam & MK_MBUTTON)
301 result.modifiers |= WebInputEvent::MiddleButtonDown;
302 if (wparam & MK_RBUTTON)
303 result.modifiers |= WebInputEvent::RightButtonDown;
304
305 SetToggleKeyState(&result);
306 return result;
307 }
308
309 // WebMouseWheelEvent ---------------------------------------------------------
310
311 WebMouseWheelEvent
312 WebMouseWheelEventBuilder::Build(HWND hwnd, UINT message,
313 WPARAM wparam, LPARAM lparam) {
314 WebMouseWheelEvent result;
315
316 result.type = WebInputEvent::MouseWheel;
317
318 // TODO(pkasting): http://b/1117926 Are we guaranteed that the message that
319 // GetMessageTime() refers to is the same one that we're passed in? Perhaps
320 // one of the construction parameters should be the time passed by the
321 // caller, who would know for sure.
322 result.timeStampSeconds = ::GetMessageTime() / 1000.0;
323
324 result.button = WebMouseEvent::ButtonNone;
325
326 // Get key state, coordinates, and wheel delta from event.
327 typedef SHORT (WINAPI *GetKeyStateFunction)(int key);
328 GetKeyStateFunction get_key_state_func;
329 UINT key_state;
330 float wheel_delta;
331 bool horizontal_scroll = false;
332 if ((message == WM_VSCROLL) || (message == WM_HSCROLL)) {
333 // Synthesize mousewheel event from a scroll event. This is needed to
334 // simulate middle mouse scrolling in some laptops. Use GetAsyncKeyState
335 // for key state since we are synthesizing the input event.
336 get_key_state_func = GetAsyncKeyState;
337 key_state = 0;
338 if (get_key_state_func(VK_SHIFT))
339 key_state |= MK_SHIFT;
340 if (get_key_state_func(VK_CONTROL))
341 key_state |= MK_CONTROL;
342 // NOTE: There doesn't seem to be a way to query the mouse button state
343 // in this case.
344
345 POINT cursor_position = {0};
346 GetCursorPos(&cursor_position);
347 result.globalX = cursor_position.x;
348 result.globalY = cursor_position.y;
349
350 switch (LOWORD(wparam)) {
351 case SB_LINEUP: // == SB_LINELEFT
352 wheel_delta = WHEEL_DELTA;
353 break;
354 case SB_LINEDOWN: // == SB_LINERIGHT
355 wheel_delta = -WHEEL_DELTA;
356 break;
357 case SB_PAGEUP:
358 wheel_delta = 1;
359 result.scrollByPage = true;
360 break;
361 case SB_PAGEDOWN:
362 wheel_delta = -1;
363 result.scrollByPage = true;
364 break;
365 default: // We don't supoprt SB_THUMBPOSITION or SB_THUMBTRACK here.
366 wheel_delta = 0;
367 break;
368 }
369
370 if (message == WM_HSCROLL)
371 horizontal_scroll = true;
372 } else {
373 // Non-synthesized event; we can just read data off the event.
374 get_key_state_func = ::GetKeyState;
375 key_state = GET_KEYSTATE_WPARAM(wparam);
376
377 result.globalX = static_cast<short>(LOWORD(lparam));
378 result.globalY = static_cast<short>(HIWORD(lparam));
379
380 wheel_delta = static_cast<float>(GET_WHEEL_DELTA_WPARAM(wparam));
381 if (message == WM_MOUSEHWHEEL) {
382 horizontal_scroll = true;
383 wheel_delta = -wheel_delta; // Windows is <- -/+ ->, WebKit <- +/- ->.
384 }
385 }
386 if (key_state & MK_SHIFT)
387 horizontal_scroll = true;
388
389 // Set modifiers based on key state.
390 if (key_state & MK_SHIFT)
391 result.modifiers |= WebInputEvent::ShiftKey;
392 if (key_state & MK_CONTROL)
393 result.modifiers |= WebInputEvent::ControlKey;
394 if (get_key_state_func(VK_MENU) & 0x8000)
395 result.modifiers |= WebInputEvent::AltKey;
396 if (key_state & MK_LBUTTON)
397 result.modifiers |= WebInputEvent::LeftButtonDown;
398 if (key_state & MK_MBUTTON)
399 result.modifiers |= WebInputEvent::MiddleButtonDown;
400 if (key_state & MK_RBUTTON)
401 result.modifiers |= WebInputEvent::RightButtonDown;
402
403 SetToggleKeyState(&result);
404
405 // Set coordinates by translating event coordinates from screen to client.
406 POINT client_point = { result.globalX, result.globalY };
407 MapWindowPoints(0, hwnd, &client_point, 1);
408 result.x = client_point.x;
409 result.y = client_point.y;
410 result.windowX = result.x;
411 result.windowY = result.y;
412
413 // Convert wheel delta amount to a number of pixels to scroll.
414 //
415 // How many pixels should we scroll per line? Gecko uses the height of the
416 // current line, which means scroll distance changes as you go through the
417 // page or go to different pages. IE 8 is ~60 px/line, although the value
418 // seems to vary slightly by page and zoom level. Also, IE defaults to
419 // smooth scrolling while Firefox doesn't, so it can get away with somewhat
420 // larger scroll values without feeling as jerky. Here we use 100 px per
421 // three lines (the default scroll amount is three lines per wheel tick).
422 // Even though we have smooth scrolling, we don't make this as large as IE
423 // because subjectively IE feels like it scrolls farther than you want while
424 // reading articles.
425 static const float kScrollbarPixelsPerLine = 100.0f / 3.0f;
426 wheel_delta /= WHEEL_DELTA;
427 float scroll_delta = wheel_delta * kScrollbarPixelsPerLine;
428 if (horizontal_scroll) {
429 unsigned long scroll_chars = kDefaultScrollCharsPerWheelDelta;
430 SystemParametersInfo(SPI_GETWHEELSCROLLCHARS, 0, &scroll_chars, 0);
431 // TODO(pkasting): Should probably have a different multiplier
432 // scrollbarPixelsPerChar here.
433 scroll_delta *= static_cast<float>(scroll_chars);
434 } else {
435 unsigned long scroll_lines = kDefaultScrollLinesPerWheelDelta;
436 SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &scroll_lines, 0);
437 if (scroll_lines == WHEEL_PAGESCROLL)
438 result.scrollByPage = true;
439 if (!result.scrollByPage)
440 scroll_delta *= static_cast<float>(scroll_lines);
441 }
442
443 // Set scroll amount based on above calculations. WebKit expects positive
444 // deltaY to mean "scroll up" and positive deltaX to mean "scroll left".
445 if (horizontal_scroll) {
446 result.deltaX = scroll_delta;
447 result.wheelTicksX = wheel_delta;
448 } else {
449 result.deltaY = scroll_delta;
450 result.wheelTicksY = wheel_delta;
451 }
452
453 return result;
454 }
455
456 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698