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

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: 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;
171 static double g_last_click_time;
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 void ResetLastClickState() {
181 g_last_click_time = g_last_click_count = 0;
182 }
183
184 WebMouseEvent WebMouseEventBuilder::Build(HWND hwnd, UINT message,
185 WPARAM wparam, LPARAM lparam) {
186 WebMouseEvent result;
187
188 switch (message) {
189 case WM_MOUSEMOVE:
190 result.type = WebInputEvent::MouseMove;
191 if (wparam & MK_LBUTTON)
192 result.button = WebMouseEvent::ButtonLeft;
193 else if (wparam & MK_MBUTTON)
194 result.button = WebMouseEvent::ButtonMiddle;
195 else if (wparam & MK_RBUTTON)
196 result.button = WebMouseEvent::ButtonRight;
197 else
198 result.button = WebMouseEvent::ButtonNone;
199 break;
200 case WM_MOUSELEAVE:
201 result.type = WebInputEvent::MouseLeave;
202 result.button = WebMouseEvent::ButtonNone;
203 // set the current mouse position (relative to the client area of the
204 // current window) since none is specified for this event
205 lparam = GetRelativeCursorPos(hwnd);
206 break;
207 case WM_LBUTTONDOWN:
208 case WM_LBUTTONDBLCLK:
209 result.type = WebInputEvent::MouseDown;
210 result.button = WebMouseEvent::ButtonLeft;
211 break;
212 case WM_MBUTTONDOWN:
213 case WM_MBUTTONDBLCLK:
214 result.type = WebInputEvent::MouseDown;
215 result.button = WebMouseEvent::ButtonMiddle;
216 break;
217 case WM_RBUTTONDOWN:
218 case WM_RBUTTONDBLCLK:
219 result.type = WebInputEvent::MouseDown;
220 result.button = WebMouseEvent::ButtonRight;
221 break;
222 case WM_LBUTTONUP:
223 result.type = WebInputEvent::MouseUp;
224 result.button = WebMouseEvent::ButtonLeft;
225 break;
226 case WM_MBUTTONUP:
227 result.type = WebInputEvent::MouseUp;
228 result.button = WebMouseEvent::ButtonMiddle;
229 break;
230 case WM_RBUTTONUP:
231 result.type = WebInputEvent::MouseUp;
232 result.button = WebMouseEvent::ButtonRight;
233 break;
234 default:
235 NOTREACHED();
236 }
237
238 // TODO(pkasting): http://b/1117926 Are we guaranteed that the message that
239 // GetMessageTime() refers to is the same one that we're passed in? Perhaps
240 // one of the construction parameters should be the time passed by the
241 // caller, who would know for sure.
242 result.timeStampSeconds = ::GetMessageTime() / 1000.0;
243
244 // set position fields:
245
246 result.x = static_cast<short>(LOWORD(lparam));
247 result.y = static_cast<short>(HIWORD(lparam));
248 result.windowX = result.x;
249 result.windowY = result.y;
250
251 POINT global_point = { result.x, result.y };
252 ClientToScreen(hwnd, &global_point);
253
254 result.globalX = global_point.x;
255 result.globalY = global_point.y;
256
257 // calculate number of clicks:
258
259 // This differs slightly from the WebKit code in WebKit/win/WebView.cpp
260 // where their original code looks buggy.
261 static int last_click_position_x;
262 static int last_click_position_Y;
263 static WebMouseEvent::Button last_click_button = WebMouseEvent::ButtonLeft;
264
265 double current_time = result.timeStampSeconds;
266 bool cancel_previous_click =
267 (abs(last_click_position_x - result.x) >
268 (::GetSystemMetrics(SM_CXDOUBLECLK) / 2))
269 || (abs(last_click_position_x - result.y) >
270 (::GetSystemMetrics(SM_CYDOUBLECLK) / 2))
271 || ((current_time - g_last_click_time) * 1000.0 > ::GetDoubleClickTime());
272
273 if (result.type == WebInputEvent::MouseDown) {
274 if (!cancel_previous_click && (result.button == last_click_button)) {
275 ++g_last_click_count;
276 } else {
277 g_last_click_count = 1;
278 last_click_position_x = result.x;
279 last_click_position_x = result.y;
280 }
281 g_last_click_time = current_time;
282 last_click_button = result.button;
283 } else if (result.type == WebInputEvent::MouseMove
284 || result.type == WebInputEvent::MouseLeave) {
285 if (cancel_previous_click) {
286 g_last_click_count = 0;
287 last_click_position_x = 0;
288 last_click_position_x = 0;
289 g_last_click_time = 0;
290 }
291 }
292 result.clickCount = g_last_click_count;
293
294 // set modifiers:
295
296 if (wparam & MK_CONTROL)
297 result.modifiers |= WebInputEvent::ControlKey;
298 if (wparam & MK_SHIFT)
299 result.modifiers |= WebInputEvent::ShiftKey;
300 if (::GetKeyState(VK_MENU) & 0x8000)
301 result.modifiers |= WebInputEvent::AltKey;
302 if (wparam & MK_LBUTTON)
303 result.modifiers |= WebInputEvent::LeftButtonDown;
304 if (wparam & MK_MBUTTON)
305 result.modifiers |= WebInputEvent::MiddleButtonDown;
306 if (wparam & MK_RBUTTON)
307 result.modifiers |= WebInputEvent::RightButtonDown;
308
309 SetToggleKeyState(&result);
310 return result;
311 }
312
313 // WebMouseWheelEvent ---------------------------------------------------------
314
315 WebMouseWheelEvent
316 WebMouseWheelEventBuilder::Build(HWND hwnd, UINT message,
317 WPARAM wparam, LPARAM lparam) {
318 WebMouseWheelEvent result;
319
320 result.type = WebInputEvent::MouseWheel;
321
322 // TODO(pkasting): http://b/1117926 Are we guaranteed that the message that
323 // GetMessageTime() refers to is the same one that we're passed in? Perhaps
324 // one of the construction parameters should be the time passed by the
325 // caller, who would know for sure.
326 result.timeStampSeconds = ::GetMessageTime() / 1000.0;
327
328 result.button = WebMouseEvent::ButtonNone;
329
330 // Get key state, coordinates, and wheel delta from event.
331 typedef SHORT (WINAPI *GetKeyStateFunction)(int key);
332 GetKeyStateFunction get_key_state_func;
333 UINT key_state;
334 float wheel_delta;
335 bool horizontal_scroll = false;
336 if ((message == WM_VSCROLL) || (message == WM_HSCROLL)) {
337 // Synthesize mousewheel event from a scroll event. This is needed to
338 // simulate middle mouse scrolling in some laptops. Use GetAsyncKeyState
339 // for key state since we are synthesizing the input event.
340 get_key_state_func = GetAsyncKeyState;
341 key_state = 0;
342 if (get_key_state_func(VK_SHIFT))
343 key_state |= MK_SHIFT;
344 if (get_key_state_func(VK_CONTROL))
345 key_state |= MK_CONTROL;
346 // NOTE: There doesn't seem to be a way to query the mouse button state
347 // in this case.
348
349 POINT cursor_position = {0};
350 GetCursorPos(&cursor_position);
351 result.globalX = cursor_position.x;
352 result.globalY = cursor_position.y;
353
354 switch (LOWORD(wparam)) {
355 case SB_LINEUP: // == SB_LINELEFT
356 wheel_delta = WHEEL_DELTA;
357 break;
358 case SB_LINEDOWN: // == SB_LINERIGHT
359 wheel_delta = -WHEEL_DELTA;
360 break;
361 case SB_PAGEUP:
362 wheel_delta = 1;
363 result.scrollByPage = true;
364 break;
365 case SB_PAGEDOWN:
366 wheel_delta = -1;
367 result.scrollByPage = true;
368 break;
369 default: // We don't supoprt SB_THUMBPOSITION or SB_THUMBTRACK here.
370 wheel_delta = 0;
371 break;
372 }
373
374 if (message == WM_HSCROLL)
375 horizontal_scroll = true;
376 } else {
377 // Non-synthesized event; we can just read data off the event.
378 get_key_state_func = ::GetKeyState;
379 key_state = GET_KEYSTATE_WPARAM(wparam);
380
381 result.globalX = static_cast<short>(LOWORD(lparam));
382 result.globalY = static_cast<short>(HIWORD(lparam));
383
384 wheel_delta = static_cast<float>(GET_WHEEL_DELTA_WPARAM(wparam));
385 if (message == WM_MOUSEHWHEEL) {
386 horizontal_scroll = true;
387 wheel_delta = -wheel_delta; // Windows is <- -/+ ->, WebKit <- +/- ->.
388 }
389 }
390 if (key_state & MK_SHIFT)
391 horizontal_scroll = true;
392
393 // Set modifiers based on key state.
394 if (key_state & MK_SHIFT)
395 result.modifiers |= WebInputEvent::ShiftKey;
396 if (key_state & MK_CONTROL)
397 result.modifiers |= WebInputEvent::ControlKey;
398 if (get_key_state_func(VK_MENU) & 0x8000)
399 result.modifiers |= WebInputEvent::AltKey;
400 if (key_state & MK_LBUTTON)
401 result.modifiers |= WebInputEvent::LeftButtonDown;
402 if (key_state & MK_MBUTTON)
403 result.modifiers |= WebInputEvent::MiddleButtonDown;
404 if (key_state & MK_RBUTTON)
405 result.modifiers |= WebInputEvent::RightButtonDown;
406
407 SetToggleKeyState(&result);
408
409 // Set coordinates by translating event coordinates from screen to client.
410 POINT client_point = { result.globalX, result.globalY };
411 MapWindowPoints(0, hwnd, &client_point, 1);
412 result.x = client_point.x;
413 result.y = client_point.y;
414 result.windowX = result.x;
415 result.windowY = result.y;
416
417 // Convert wheel delta amount to a number of pixels to scroll.
418 //
419 // How many pixels should we scroll per line? Gecko uses the height of the
420 // current line, which means scroll distance changes as you go through the
421 // page or go to different pages. IE 8 is ~60 px/line, although the value
422 // seems to vary slightly by page and zoom level. Also, IE defaults to
423 // smooth scrolling while Firefox doesn't, so it can get away with somewhat
424 // larger scroll values without feeling as jerky. Here we use 100 px per
425 // three lines (the default scroll amount is three lines per wheel tick).
426 // Even though we have smooth scrolling, we don't make this as large as IE
427 // because subjectively IE feels like it scrolls farther than you want while
428 // reading articles.
429 static const float kScrollbarPixelsPerLine = 100.0f / 3.0f;
430 wheel_delta /= WHEEL_DELTA;
431 float scroll_delta = wheel_delta * kScrollbarPixelsPerLine;
432 if (horizontal_scroll) {
433 unsigned long scroll_chars = kDefaultScrollCharsPerWheelDelta;
434 SystemParametersInfo(SPI_GETWHEELSCROLLCHARS, 0, &scroll_chars, 0);
435 // TODO(pkasting): Should probably have a different multiplier
436 // scrollbarPixelsPerChar here.
437 scroll_delta *= static_cast<float>(scroll_chars);
438 } else {
439 unsigned long scroll_lines = kDefaultScrollLinesPerWheelDelta;
440 SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &scroll_lines, 0);
441 if (scroll_lines == WHEEL_PAGESCROLL)
442 result.scrollByPage = true;
443 if (!result.scrollByPage)
444 scroll_delta *= static_cast<float>(scroll_lines);
445 }
446
447 // Set scroll amount based on above calculations. WebKit expects positive
448 // deltaY to mean "scroll up" and positive deltaX to mean "scroll left".
449 if (horizontal_scroll) {
450 result.deltaX = scroll_delta;
451 result.wheelTicksX = wheel_delta;
452 } else {
453 result.deltaY = scroll_delta;
454 result.wheelTicksY = wheel_delta;
455 }
456
457 return result;
458 }
459
460 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698