Clean up check for dependency_info.
[chromium-blink-merge.git] / content / browser / renderer_host / input / web_input_event_builders_win.cc
blob9d417016c0da49df8d4fd0688ecaf10c50a1b4ba
1 // Copyright 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.
5 #include "content/browser/renderer_host/input/web_input_event_builders_win.h"
7 #include "base/logging.h"
8 #include "content/browser/renderer_host/input/web_input_event_util.h"
9 #include "ui/gfx/win/dpi.h"
11 using blink::WebInputEvent;
12 using blink::WebKeyboardEvent;
13 using blink::WebMouseEvent;
14 using blink::WebMouseWheelEvent;
16 namespace content {
18 static const unsigned long kDefaultScrollLinesPerWheelDelta = 3;
19 static const unsigned long kDefaultScrollCharsPerWheelDelta = 1;
21 // Loads the state for toggle keys into the event.
22 static void SetToggleKeyState(WebInputEvent* event) {
23 // Low bit set from GetKeyState indicates "toggled".
24 if (::GetKeyState(VK_NUMLOCK) & 1)
25 event->modifiers |= WebInputEvent::NumLockOn;
26 if (::GetKeyState(VK_CAPITAL) & 1)
27 event->modifiers |= WebInputEvent::CapsLockOn;
30 WebKeyboardEvent WebKeyboardEventBuilder::Build(HWND hwnd,
31 UINT message,
32 WPARAM wparam,
33 LPARAM lparam,
34 DWORD time_ms) {
35 WebKeyboardEvent result;
37 result.timeStampSeconds = time_ms / 1000.0;
39 result.windowsKeyCode = static_cast<int>(wparam);
40 // Record the scan code (along with other context bits) for this key event.
41 result.nativeKeyCode = static_cast<int>(lparam);
43 switch (message) {
44 case WM_SYSKEYDOWN:
45 result.isSystemKey = true;
46 case WM_KEYDOWN:
47 result.type = WebInputEvent::RawKeyDown;
48 break;
49 case WM_SYSKEYUP:
50 result.isSystemKey = true;
51 case WM_KEYUP:
52 result.type = WebInputEvent::KeyUp;
53 break;
54 case WM_IME_CHAR:
55 result.type = WebInputEvent::Char;
56 break;
57 case WM_SYSCHAR:
58 result.isSystemKey = true;
59 result.type = WebInputEvent::Char;
60 case WM_CHAR:
61 result.type = WebInputEvent::Char;
62 break;
63 default:
64 NOTREACHED();
67 if (result.type == WebInputEvent::Char
68 || result.type == WebInputEvent::RawKeyDown) {
69 result.text[0] = result.windowsKeyCode;
70 result.unmodifiedText[0] = result.windowsKeyCode;
72 if (result.type != WebInputEvent::Char)
73 result.setKeyIdentifierFromWindowsKeyCode();
75 if (::GetKeyState(VK_SHIFT) & 0x8000)
76 result.modifiers |= WebInputEvent::ShiftKey;
77 if (::GetKeyState(VK_CONTROL) & 0x8000)
78 result.modifiers |= WebInputEvent::ControlKey;
79 if (::GetKeyState(VK_MENU) & 0x8000)
80 result.modifiers |= WebInputEvent::AltKey;
81 // NOTE: There doesn't seem to be a way to query the mouse button state in
82 // this case.
84 // Bit 30 of lParam represents the "previous key state". If set, the key was
85 // already down, therefore this is an auto-repeat. Only apply this to key
86 // down events, to match DOM semantics.
87 if ((result.type == WebInputEvent::RawKeyDown) && (lparam & 0x40000000))
88 result.modifiers |= WebInputEvent::IsAutoRepeat;
90 SetToggleKeyState(&result);
91 return result;
94 // WebMouseEvent --------------------------------------------------------------
96 static int g_last_click_count = 0;
97 static double g_last_click_time = 0;
99 static LPARAM GetRelativeCursorPos(HWND hwnd) {
100 POINT pos = {-1, -1};
101 GetCursorPos(&pos);
102 ScreenToClient(hwnd, &pos);
103 return MAKELPARAM(pos.x, pos.y);
106 WebMouseEvent WebMouseEventBuilder::Build(HWND hwnd,
107 UINT message,
108 WPARAM wparam,
109 LPARAM lparam,
110 DWORD time_ms) {
111 WebMouseEvent result;
113 switch (message) {
114 case WM_MOUSEMOVE:
115 result.type = WebInputEvent::MouseMove;
116 if (wparam & MK_LBUTTON)
117 result.button = WebMouseEvent::ButtonLeft;
118 else if (wparam & MK_MBUTTON)
119 result.button = WebMouseEvent::ButtonMiddle;
120 else if (wparam & MK_RBUTTON)
121 result.button = WebMouseEvent::ButtonRight;
122 else
123 result.button = WebMouseEvent::ButtonNone;
124 break;
125 case WM_MOUSELEAVE:
126 case WM_NCMOUSELEAVE:
127 // TODO(rbyers): This should be MouseLeave but is disabled temporarily.
128 // See http://crbug.com/450631
129 result.type = WebInputEvent::MouseMove;
130 result.button = WebMouseEvent::ButtonNone;
131 // set the current mouse position (relative to the client area of the
132 // current window) since none is specified for this event
133 lparam = GetRelativeCursorPos(hwnd);
134 break;
135 case WM_LBUTTONDOWN:
136 case WM_LBUTTONDBLCLK:
137 result.type = WebInputEvent::MouseDown;
138 result.button = WebMouseEvent::ButtonLeft;
139 break;
140 case WM_MBUTTONDOWN:
141 case WM_MBUTTONDBLCLK:
142 result.type = WebInputEvent::MouseDown;
143 result.button = WebMouseEvent::ButtonMiddle;
144 break;
145 case WM_RBUTTONDOWN:
146 case WM_RBUTTONDBLCLK:
147 result.type = WebInputEvent::MouseDown;
148 result.button = WebMouseEvent::ButtonRight;
149 break;
150 case WM_LBUTTONUP:
151 result.type = WebInputEvent::MouseUp;
152 result.button = WebMouseEvent::ButtonLeft;
153 break;
154 case WM_MBUTTONUP:
155 result.type = WebInputEvent::MouseUp;
156 result.button = WebMouseEvent::ButtonMiddle;
157 break;
158 case WM_RBUTTONUP:
159 result.type = WebInputEvent::MouseUp;
160 result.button = WebMouseEvent::ButtonRight;
161 break;
162 default:
163 NOTREACHED();
166 result.timeStampSeconds = time_ms / 1000.0;
168 // set position fields:
170 result.x = static_cast<short>(LOWORD(lparam));
171 result.y = static_cast<short>(HIWORD(lparam));
172 result.windowX = result.x;
173 result.windowY = result.y;
175 POINT global_point = { result.x, result.y };
176 ClientToScreen(hwnd, &global_point);
178 // We need to convert the global point back to DIP before using it.
179 gfx::Point dip_global_point = gfx::win::ScreenToDIPPoint(
180 gfx::Point(global_point.x, global_point.y));
182 result.globalX = dip_global_point.x();
183 result.globalY = dip_global_point.y();
185 // calculate number of clicks:
187 // This differs slightly from the WebKit code in WebKit/win/WebView.cpp
188 // where their original code looks buggy.
189 static int last_click_position_x;
190 static int last_click_position_y;
191 static WebMouseEvent::Button last_click_button = WebMouseEvent::ButtonLeft;
193 double current_time = result.timeStampSeconds;
194 bool cancel_previous_click =
195 (abs(last_click_position_x - result.x) >
196 (::GetSystemMetrics(SM_CXDOUBLECLK) / 2))
197 || (abs(last_click_position_y - result.y) >
198 (::GetSystemMetrics(SM_CYDOUBLECLK) / 2))
199 || ((current_time - g_last_click_time) * 1000.0 > ::GetDoubleClickTime());
201 if (result.type == WebInputEvent::MouseDown) {
202 if (!cancel_previous_click && (result.button == last_click_button)) {
203 ++g_last_click_count;
204 } else {
205 g_last_click_count = 1;
206 last_click_position_x = result.x;
207 last_click_position_y = result.y;
209 g_last_click_time = current_time;
210 last_click_button = result.button;
211 } else if (result.type == WebInputEvent::MouseMove
212 || result.type == WebInputEvent::MouseLeave) {
213 if (cancel_previous_click) {
214 g_last_click_count = 0;
215 last_click_position_x = 0;
216 last_click_position_y = 0;
217 g_last_click_time = 0;
220 result.clickCount = g_last_click_count;
222 // set modifiers:
224 if (wparam & MK_CONTROL)
225 result.modifiers |= WebInputEvent::ControlKey;
226 if (wparam & MK_SHIFT)
227 result.modifiers |= WebInputEvent::ShiftKey;
228 if (::GetKeyState(VK_MENU) & 0x8000)
229 result.modifiers |= WebInputEvent::AltKey;
230 if (wparam & MK_LBUTTON)
231 result.modifiers |= WebInputEvent::LeftButtonDown;
232 if (wparam & MK_MBUTTON)
233 result.modifiers |= WebInputEvent::MiddleButtonDown;
234 if (wparam & MK_RBUTTON)
235 result.modifiers |= WebInputEvent::RightButtonDown;
237 SetToggleKeyState(&result);
238 return result;
241 // WebMouseWheelEvent ---------------------------------------------------------
243 WebMouseWheelEvent WebMouseWheelEventBuilder::Build(HWND hwnd,
244 UINT message,
245 WPARAM wparam,
246 LPARAM lparam,
247 DWORD time_ms) {
248 WebMouseWheelEvent result;
250 result.type = WebInputEvent::MouseWheel;
252 result.timeStampSeconds = time_ms / 1000.0;
254 result.button = WebMouseEvent::ButtonNone;
256 // Get key state, coordinates, and wheel delta from event.
257 typedef SHORT (WINAPI *GetKeyStateFunction)(int key);
258 GetKeyStateFunction get_key_state_func;
259 UINT key_state;
260 float wheel_delta;
261 bool horizontal_scroll = false;
262 if ((message == WM_VSCROLL) || (message == WM_HSCROLL)) {
263 // Synthesize mousewheel event from a scroll event. This is needed to
264 // simulate middle mouse scrolling in some laptops. Use GetAsyncKeyState
265 // for key state since we are synthesizing the input event.
266 get_key_state_func = GetAsyncKeyState;
267 key_state = 0;
268 if (get_key_state_func(VK_SHIFT) & 0x8000)
269 key_state |= MK_SHIFT;
270 if (get_key_state_func(VK_CONTROL) & 0x8000)
271 key_state |= MK_CONTROL;
272 // NOTE: There doesn't seem to be a way to query the mouse button state
273 // in this case.
275 POINT cursor_position = {0};
276 GetCursorPos(&cursor_position);
277 result.globalX = cursor_position.x;
278 result.globalY = cursor_position.y;
280 switch (LOWORD(wparam)) {
281 case SB_LINEUP: // == SB_LINELEFT
282 wheel_delta = WHEEL_DELTA;
283 break;
284 case SB_LINEDOWN: // == SB_LINERIGHT
285 wheel_delta = -WHEEL_DELTA;
286 break;
287 case SB_PAGEUP:
288 wheel_delta = 1;
289 result.scrollByPage = true;
290 break;
291 case SB_PAGEDOWN:
292 wheel_delta = -1;
293 result.scrollByPage = true;
294 break;
295 default: // We don't supoprt SB_THUMBPOSITION or SB_THUMBTRACK here.
296 wheel_delta = 0;
297 break;
300 if (message == WM_HSCROLL)
301 horizontal_scroll = true;
302 } else {
303 // Non-synthesized event; we can just read data off the event.
304 get_key_state_func = ::GetKeyState;
305 key_state = GET_KEYSTATE_WPARAM(wparam);
307 result.globalX = static_cast<short>(LOWORD(lparam));
308 result.globalY = static_cast<short>(HIWORD(lparam));
310 wheel_delta = static_cast<float>(GET_WHEEL_DELTA_WPARAM(wparam));
311 if (message == WM_MOUSEHWHEEL) {
312 horizontal_scroll = true;
313 wheel_delta = -wheel_delta; // Windows is <- -/+ ->, WebKit <- +/- ->.
316 if (key_state & MK_SHIFT)
317 horizontal_scroll = true;
319 // Set modifiers based on key state.
320 if (key_state & MK_SHIFT)
321 result.modifiers |= WebInputEvent::ShiftKey;
322 if (key_state & MK_CONTROL)
323 result.modifiers |= WebInputEvent::ControlKey;
324 if (get_key_state_func(VK_MENU) & 0x8000)
325 result.modifiers |= WebInputEvent::AltKey;
326 if (key_state & MK_LBUTTON)
327 result.modifiers |= WebInputEvent::LeftButtonDown;
328 if (key_state & MK_MBUTTON)
329 result.modifiers |= WebInputEvent::MiddleButtonDown;
330 if (key_state & MK_RBUTTON)
331 result.modifiers |= WebInputEvent::RightButtonDown;
333 SetToggleKeyState(&result);
335 // Set coordinates by translating event coordinates from screen to client.
336 POINT client_point = { result.globalX, result.globalY };
337 MapWindowPoints(0, hwnd, &client_point, 1);
338 result.x = client_point.x;
339 result.y = client_point.y;
340 result.windowX = result.x;
341 result.windowY = result.y;
343 // Convert wheel delta amount to a number of pixels to scroll.
345 // How many pixels should we scroll per line? Gecko uses the height of the
346 // current line, which means scroll distance changes as you go through the
347 // page or go to different pages. IE 8 is ~60 px/line, although the value
348 // seems to vary slightly by page and zoom level. Also, IE defaults to
349 // smooth scrolling while Firefox doesn't, so it can get away with somewhat
350 // larger scroll values without feeling as jerky. Here we use 100 px per
351 // three lines (the default scroll amount is three lines per wheel tick).
352 // Even though we have smooth scrolling, we don't make this as large as IE
353 // because subjectively IE feels like it scrolls farther than you want while
354 // reading articles.
355 static const float kScrollbarPixelsPerLine = 100.0f / 3.0f;
356 wheel_delta /= WHEEL_DELTA;
357 float scroll_delta = wheel_delta;
358 if (horizontal_scroll) {
359 unsigned long scroll_chars = kDefaultScrollCharsPerWheelDelta;
360 SystemParametersInfo(SPI_GETWHEELSCROLLCHARS, 0, &scroll_chars, 0);
361 // TODO(pkasting): Should probably have a different multiplier
362 // scrollbarPixelsPerChar here.
363 scroll_delta *= static_cast<float>(scroll_chars) * kScrollbarPixelsPerLine;
364 } else {
365 unsigned long scroll_lines = kDefaultScrollLinesPerWheelDelta;
366 SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &scroll_lines, 0);
367 if (scroll_lines == WHEEL_PAGESCROLL)
368 result.scrollByPage = true;
369 if (!result.scrollByPage) {
370 scroll_delta *=
371 static_cast<float>(scroll_lines) * kScrollbarPixelsPerLine;
375 // Set scroll amount based on above calculations. WebKit expects positive
376 // deltaY to mean "scroll up" and positive deltaX to mean "scroll left".
377 if (horizontal_scroll) {
378 result.deltaX = scroll_delta;
379 result.wheelTicksX = wheel_delta;
380 } else {
381 result.deltaY = scroll_delta;
382 result.wheelTicksY = wheel_delta;
385 return result;
388 } // namespace content