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

Unified 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 side-by-side diff with in-line comments
Download patch
Index: content/browser/renderer_host/input/web_input_event_builders_win.cc
diff --git a/content/browser/renderer_host/input/web_input_event_builders_win.cc b/content/browser/renderer_host/input/web_input_event_builders_win.cc
new file mode 100644
index 0000000000000000000000000000000000000000..e376d5ee82f3a08bed79ee476b568981d672dd65
--- /dev/null
+++ b/content/browser/renderer_host/input/web_input_event_builders_win.cc
@@ -0,0 +1,456 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/input/web_input_event_builders_win.h"
+
+#include "base/logging.h"
+
+using WebKit::WebInputEvent;
+using WebKit::WebKeyboardEvent;
+using WebKit::WebMouseEvent;
+using WebKit::WebMouseWheelEvent;
+
+namespace content {
+
+static const unsigned long kDefaultScrollLinesPerWheelDelta = 3;
+static const unsigned long kDefaultScrollCharsPerWheelDelta = 1;
+
+static bool IsKeyDown(WPARAM wparam) {
+ return (GetKeyState(wparam) & 0x8000) != 0;
+}
+
+static int GetLocationModifier(WPARAM wparam, LPARAM lparam) {
+ int modifier = 0;
+ switch (wparam) {
+ case VK_RETURN:
+ if ((lparam >> 16) & KF_EXTENDED)
+ modifier = WebInputEvent::IsKeyPad;
+ break;
+ case VK_INSERT:
+ case VK_DELETE:
+ case VK_HOME:
+ case VK_END:
+ case VK_PRIOR:
+ case VK_NEXT:
+ case VK_UP:
+ case VK_DOWN:
+ case VK_LEFT:
+ case VK_RIGHT:
+ if (!((lparam >> 16) & KF_EXTENDED))
+ modifier = WebInputEvent::IsKeyPad;
+ break;
+ case VK_NUMLOCK:
+ case VK_NUMPAD0:
+ case VK_NUMPAD1:
+ case VK_NUMPAD2:
+ case VK_NUMPAD3:
+ case VK_NUMPAD4:
+ case VK_NUMPAD5:
+ case VK_NUMPAD6:
+ case VK_NUMPAD7:
+ case VK_NUMPAD8:
+ case VK_NUMPAD9:
+ case VK_DIVIDE:
+ case VK_MULTIPLY:
+ case VK_SUBTRACT:
+ case VK_ADD:
+ case VK_DECIMAL:
+ case VK_CLEAR:
+ modifier = WebInputEvent::IsKeyPad;
+ break;
+ case VK_SHIFT:
+ if (IsKeyDown(VK_LSHIFT))
+ modifier = WebInputEvent::IsLeft;
+ else if (IsKeyDown(VK_RSHIFT))
+ modifier = WebInputEvent::IsRight;
+ break;
+ case VK_CONTROL:
+ if (IsKeyDown(VK_LCONTROL))
+ modifier = WebInputEvent::IsLeft;
+ else if (IsKeyDown(VK_RCONTROL))
+ modifier = WebInputEvent::IsRight;
+ break;
+ case VK_MENU:
+ if (IsKeyDown(VK_LMENU))
+ modifier = WebInputEvent::IsLeft;
+ else if (IsKeyDown(VK_RMENU))
+ modifier = WebInputEvent::IsRight;
+ break;
+ case VK_LWIN:
+ modifier = WebInputEvent::IsLeft;
+ break;
+ case VK_RWIN:
+ modifier = WebInputEvent::IsRight;
+ break;
+ }
+
+ DCHECK(!modifier
+ || modifier == WebInputEvent::IsKeyPad
+ || modifier == WebInputEvent::IsLeft
+ || modifier == WebInputEvent::IsRight);
+ return modifier;
+}
+
+// Loads the state for toggle keys into the event.
+static void SetToggleKeyState(WebInputEvent* event) {
+ // Low bit set from GetKeyState indicates "toggled".
+ if (::GetKeyState(VK_NUMLOCK) & 1)
+ event->modifiers |= WebInputEvent::NumLockOn;
+ if (::GetKeyState(VK_CAPITAL) & 1)
+ event->modifiers |= WebInputEvent::CapsLockOn;
+}
+
+WebKeyboardEvent WebKeyboardEventBuilder::Build(HWND hwnd, UINT message,
+ WPARAM wparam, LPARAM lparam) {
+ WebKeyboardEvent result;
+
+ // TODO(pkasting): http://b/1117926 Are we guaranteed that the message that
+ // GetMessageTime() refers to is the same one that we're passed in? Perhaps
+ // one of the construction parameters should be the time passed by the
+ // caller, who would know for sure.
+ result.timeStampSeconds = ::GetMessageTime() / 1000.0;
+
+ result.windowsKeyCode = static_cast<int>(wparam);
+ // Record the scan code (along with other context bits) for this key event.
+ result.nativeKeyCode = static_cast<int>(lparam);
+
+ switch (message) {
+ case WM_SYSKEYDOWN:
+ result.isSystemKey = true;
+ case WM_KEYDOWN:
+ result.type = WebInputEvent::RawKeyDown;
+ break;
+ case WM_SYSKEYUP:
+ result.isSystemKey = true;
+ case WM_KEYUP:
+ result.type = WebInputEvent::KeyUp;
+ break;
+ case WM_IME_CHAR:
+ result.type = WebInputEvent::Char;
+ break;
+ case WM_SYSCHAR:
+ result.isSystemKey = true;
+ result.type = WebInputEvent::Char;
+ case WM_CHAR:
+ result.type = WebInputEvent::Char;
+ break;
+ default:
+ NOTREACHED();
+ }
+
+ if (result.type == WebInputEvent::Char
+ || result.type == WebInputEvent::RawKeyDown) {
+ result.text[0] = result.windowsKeyCode;
+ result.unmodifiedText[0] = result.windowsKeyCode;
+ }
+ if (result.type != WebInputEvent::Char)
+ result.setKeyIdentifierFromWindowsKeyCode();
+
+ if (::GetKeyState(VK_SHIFT) & 0x8000)
+ result.modifiers |= WebInputEvent::ShiftKey;
+ if (::GetKeyState(VK_CONTROL) & 0x8000)
+ result.modifiers |= WebInputEvent::ControlKey;
+ if (::GetKeyState(VK_MENU) & 0x8000)
+ result.modifiers |= WebInputEvent::AltKey;
+ // NOTE: There doesn't seem to be a way to query the mouse button state in
+ // this case.
+
+ if (LOWORD(lparam) > 1)
+ result.modifiers |= WebInputEvent::IsAutoRepeat;
+
+ result.modifiers |= GetLocationModifier(wparam, lparam);
+
+ SetToggleKeyState(&result);
+ return result;
+}
+
+// WebMouseEvent --------------------------------------------------------------
+
+static int g_last_click_count = 0;
+static double g_last_click_time = 0;
+
+static LPARAM GetRelativeCursorPos(HWND hwnd) {
+ POINT pos = {-1, -1};
+ GetCursorPos(&pos);
+ ScreenToClient(hwnd, &pos);
+ return MAKELPARAM(pos.x, pos.y);
+}
+
+WebMouseEvent WebMouseEventBuilder::Build(HWND hwnd, UINT message,
+ WPARAM wparam, LPARAM lparam) {
+ WebMouseEvent result;
+
+ switch (message) {
+ case WM_MOUSEMOVE:
+ result.type = WebInputEvent::MouseMove;
+ if (wparam & MK_LBUTTON)
+ result.button = WebMouseEvent::ButtonLeft;
+ else if (wparam & MK_MBUTTON)
+ result.button = WebMouseEvent::ButtonMiddle;
+ else if (wparam & MK_RBUTTON)
+ result.button = WebMouseEvent::ButtonRight;
+ else
+ result.button = WebMouseEvent::ButtonNone;
+ break;
+ case WM_MOUSELEAVE:
+ result.type = WebInputEvent::MouseLeave;
+ result.button = WebMouseEvent::ButtonNone;
+ // set the current mouse position (relative to the client area of the
+ // current window) since none is specified for this event
+ lparam = GetRelativeCursorPos(hwnd);
+ break;
+ case WM_LBUTTONDOWN:
+ case WM_LBUTTONDBLCLK:
+ result.type = WebInputEvent::MouseDown;
+ result.button = WebMouseEvent::ButtonLeft;
+ break;
+ case WM_MBUTTONDOWN:
+ case WM_MBUTTONDBLCLK:
+ result.type = WebInputEvent::MouseDown;
+ result.button = WebMouseEvent::ButtonMiddle;
+ break;
+ case WM_RBUTTONDOWN:
+ case WM_RBUTTONDBLCLK:
+ result.type = WebInputEvent::MouseDown;
+ result.button = WebMouseEvent::ButtonRight;
+ break;
+ case WM_LBUTTONUP:
+ result.type = WebInputEvent::MouseUp;
+ result.button = WebMouseEvent::ButtonLeft;
+ break;
+ case WM_MBUTTONUP:
+ result.type = WebInputEvent::MouseUp;
+ result.button = WebMouseEvent::ButtonMiddle;
+ break;
+ case WM_RBUTTONUP:
+ result.type = WebInputEvent::MouseUp;
+ result.button = WebMouseEvent::ButtonRight;
+ break;
+ default:
+ NOTREACHED();
+ }
+
+ // TODO(pkasting): http://b/1117926 Are we guaranteed that the message that
+ // GetMessageTime() refers to is the same one that we're passed in? Perhaps
+ // one of the construction parameters should be the time passed by the
+ // caller, who would know for sure.
+ result.timeStampSeconds = ::GetMessageTime() / 1000.0;
+
+ // set position fields:
+
+ result.x = static_cast<short>(LOWORD(lparam));
+ result.y = static_cast<short>(HIWORD(lparam));
+ result.windowX = result.x;
+ result.windowY = result.y;
+
+ POINT global_point = { result.x, result.y };
+ ClientToScreen(hwnd, &global_point);
+
+ result.globalX = global_point.x;
+ result.globalY = global_point.y;
+
+ // calculate number of clicks:
+
+ // This differs slightly from the WebKit code in WebKit/win/WebView.cpp
+ // where their original code looks buggy.
+ static int last_click_position_x;
+ static int last_click_position_Y;
+ static WebMouseEvent::Button last_click_button = WebMouseEvent::ButtonLeft;
+
+ double current_time = result.timeStampSeconds;
+ bool cancel_previous_click =
+ (abs(last_click_position_x - result.x) >
+ (::GetSystemMetrics(SM_CXDOUBLECLK) / 2))
+ || (abs(last_click_position_x - result.y) >
+ (::GetSystemMetrics(SM_CYDOUBLECLK) / 2))
+ || ((current_time - g_last_click_time) * 1000.0 > ::GetDoubleClickTime());
+
+ if (result.type == WebInputEvent::MouseDown) {
+ if (!cancel_previous_click && (result.button == last_click_button)) {
+ ++g_last_click_count;
+ } else {
+ g_last_click_count = 1;
+ last_click_position_x = result.x;
+ last_click_position_x = result.y;
+ }
+ g_last_click_time = current_time;
+ last_click_button = result.button;
+ } else if (result.type == WebInputEvent::MouseMove
+ || result.type == WebInputEvent::MouseLeave) {
+ if (cancel_previous_click) {
+ g_last_click_count = 0;
+ last_click_position_x = 0;
+ last_click_position_x = 0;
+ g_last_click_time = 0;
+ }
+ }
+ result.clickCount = g_last_click_count;
+
+ // set modifiers:
+
+ if (wparam & MK_CONTROL)
+ result.modifiers |= WebInputEvent::ControlKey;
+ if (wparam & MK_SHIFT)
+ result.modifiers |= WebInputEvent::ShiftKey;
+ if (::GetKeyState(VK_MENU) & 0x8000)
+ result.modifiers |= WebInputEvent::AltKey;
+ if (wparam & MK_LBUTTON)
+ result.modifiers |= WebInputEvent::LeftButtonDown;
+ if (wparam & MK_MBUTTON)
+ result.modifiers |= WebInputEvent::MiddleButtonDown;
+ if (wparam & MK_RBUTTON)
+ result.modifiers |= WebInputEvent::RightButtonDown;
+
+ SetToggleKeyState(&result);
+ return result;
+}
+
+// WebMouseWheelEvent ---------------------------------------------------------
+
+WebMouseWheelEvent
+WebMouseWheelEventBuilder::Build(HWND hwnd, UINT message,
+ WPARAM wparam, LPARAM lparam) {
+ WebMouseWheelEvent result;
+
+ result.type = WebInputEvent::MouseWheel;
+
+ // TODO(pkasting): http://b/1117926 Are we guaranteed that the message that
+ // GetMessageTime() refers to is the same one that we're passed in? Perhaps
+ // one of the construction parameters should be the time passed by the
+ // caller, who would know for sure.
+ result.timeStampSeconds = ::GetMessageTime() / 1000.0;
+
+ result.button = WebMouseEvent::ButtonNone;
+
+ // Get key state, coordinates, and wheel delta from event.
+ typedef SHORT (WINAPI *GetKeyStateFunction)(int key);
+ GetKeyStateFunction get_key_state_func;
+ UINT key_state;
+ float wheel_delta;
+ bool horizontal_scroll = false;
+ if ((message == WM_VSCROLL) || (message == WM_HSCROLL)) {
+ // Synthesize mousewheel event from a scroll event. This is needed to
+ // simulate middle mouse scrolling in some laptops. Use GetAsyncKeyState
+ // for key state since we are synthesizing the input event.
+ get_key_state_func = GetAsyncKeyState;
+ key_state = 0;
+ if (get_key_state_func(VK_SHIFT))
+ key_state |= MK_SHIFT;
+ if (get_key_state_func(VK_CONTROL))
+ key_state |= MK_CONTROL;
+ // NOTE: There doesn't seem to be a way to query the mouse button state
+ // in this case.
+
+ POINT cursor_position = {0};
+ GetCursorPos(&cursor_position);
+ result.globalX = cursor_position.x;
+ result.globalY = cursor_position.y;
+
+ switch (LOWORD(wparam)) {
+ case SB_LINEUP: // == SB_LINELEFT
+ wheel_delta = WHEEL_DELTA;
+ break;
+ case SB_LINEDOWN: // == SB_LINERIGHT
+ wheel_delta = -WHEEL_DELTA;
+ break;
+ case SB_PAGEUP:
+ wheel_delta = 1;
+ result.scrollByPage = true;
+ break;
+ case SB_PAGEDOWN:
+ wheel_delta = -1;
+ result.scrollByPage = true;
+ break;
+ default: // We don't supoprt SB_THUMBPOSITION or SB_THUMBTRACK here.
+ wheel_delta = 0;
+ break;
+ }
+
+ if (message == WM_HSCROLL)
+ horizontal_scroll = true;
+ } else {
+ // Non-synthesized event; we can just read data off the event.
+ get_key_state_func = ::GetKeyState;
+ key_state = GET_KEYSTATE_WPARAM(wparam);
+
+ result.globalX = static_cast<short>(LOWORD(lparam));
+ result.globalY = static_cast<short>(HIWORD(lparam));
+
+ wheel_delta = static_cast<float>(GET_WHEEL_DELTA_WPARAM(wparam));
+ if (message == WM_MOUSEHWHEEL) {
+ horizontal_scroll = true;
+ wheel_delta = -wheel_delta; // Windows is <- -/+ ->, WebKit <- +/- ->.
+ }
+ }
+ if (key_state & MK_SHIFT)
+ horizontal_scroll = true;
+
+ // Set modifiers based on key state.
+ if (key_state & MK_SHIFT)
+ result.modifiers |= WebInputEvent::ShiftKey;
+ if (key_state & MK_CONTROL)
+ result.modifiers |= WebInputEvent::ControlKey;
+ if (get_key_state_func(VK_MENU) & 0x8000)
+ result.modifiers |= WebInputEvent::AltKey;
+ if (key_state & MK_LBUTTON)
+ result.modifiers |= WebInputEvent::LeftButtonDown;
+ if (key_state & MK_MBUTTON)
+ result.modifiers |= WebInputEvent::MiddleButtonDown;
+ if (key_state & MK_RBUTTON)
+ result.modifiers |= WebInputEvent::RightButtonDown;
+
+ SetToggleKeyState(&result);
+
+ // Set coordinates by translating event coordinates from screen to client.
+ POINT client_point = { result.globalX, result.globalY };
+ MapWindowPoints(0, hwnd, &client_point, 1);
+ result.x = client_point.x;
+ result.y = client_point.y;
+ result.windowX = result.x;
+ result.windowY = result.y;
+
+ // Convert wheel delta amount to a number of pixels to scroll.
+ //
+ // How many pixels should we scroll per line? Gecko uses the height of the
+ // current line, which means scroll distance changes as you go through the
+ // page or go to different pages. IE 8 is ~60 px/line, although the value
+ // seems to vary slightly by page and zoom level. Also, IE defaults to
+ // smooth scrolling while Firefox doesn't, so it can get away with somewhat
+ // larger scroll values without feeling as jerky. Here we use 100 px per
+ // three lines (the default scroll amount is three lines per wheel tick).
+ // Even though we have smooth scrolling, we don't make this as large as IE
+ // because subjectively IE feels like it scrolls farther than you want while
+ // reading articles.
+ static const float kScrollbarPixelsPerLine = 100.0f / 3.0f;
+ wheel_delta /= WHEEL_DELTA;
+ float scroll_delta = wheel_delta * kScrollbarPixelsPerLine;
+ if (horizontal_scroll) {
+ unsigned long scroll_chars = kDefaultScrollCharsPerWheelDelta;
+ SystemParametersInfo(SPI_GETWHEELSCROLLCHARS, 0, &scroll_chars, 0);
+ // TODO(pkasting): Should probably have a different multiplier
+ // scrollbarPixelsPerChar here.
+ scroll_delta *= static_cast<float>(scroll_chars);
+ } else {
+ unsigned long scroll_lines = kDefaultScrollLinesPerWheelDelta;
+ SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &scroll_lines, 0);
+ if (scroll_lines == WHEEL_PAGESCROLL)
+ result.scrollByPage = true;
+ if (!result.scrollByPage)
+ scroll_delta *= static_cast<float>(scroll_lines);
+ }
+
+ // Set scroll amount based on above calculations. WebKit expects positive
+ // deltaY to mean "scroll up" and positive deltaX to mean "scroll left".
+ if (horizontal_scroll) {
+ result.deltaX = scroll_delta;
+ result.wheelTicksX = wheel_delta;
+ } else {
+ result.deltaY = scroll_delta;
+ result.wheelTicksY = wheel_delta;
+ }
+
+ return result;
+}
+
+} // namespace content

Powered by Google App Engine
This is Rietveld 408576698