| Index: content/browser/renderer_host/web_input_event_factory_win.cc
|
| diff --git a/content/browser/renderer_host/web_input_event_factory_win.cc b/content/browser/renderer_host/web_input_event_factory_win.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..d7257ed46865528fa0612cc57680c7464fddb5d8
|
| --- /dev/null
|
| +++ b/content/browser/renderer_host/web_input_event_factory_win.cc
|
| @@ -0,0 +1,488 @@
|
| +/*
|
| + * Copyright (C) 2006-2009 Google Inc. All rights reserved.
|
| + *
|
| + * Redistribution and use in source and binary forms, with or without
|
| + * modification, are permitted provided that the following conditions are
|
| + * met:
|
| + *
|
| + * * Redistributions of source code must retain the above copyright
|
| + * notice, this list of conditions and the following disclaimer.
|
| + * * Redistributions in binary form must reproduce the above
|
| + * copyright notice, this list of conditions and the following disclaimer
|
| + * in the documentation and/or other materials provided with the
|
| + * distribution.
|
| + * * Neither the name of Google Inc. nor the names of its
|
| + * contributors may be used to endorse or promote products derived from
|
| + * this software without specific prior written permission.
|
| + *
|
| + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
| + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
| + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
| + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
| + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
| + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
| + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
| + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
| + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
| + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
| + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
| + */
|
| +
|
| +#include "config.h"
|
| +#include "WebInputEventFactory.h"
|
| +
|
| +#include "WebInputEvent.h"
|
| +
|
| +#include <wtf/Assertions.h>
|
| +
|
| +namespace WebKit {
|
| +
|
| +static const unsigned long defaultScrollLinesPerWheelDelta = 3;
|
| +static const unsigned long defaultScrollCharsPerWheelDelta = 1;
|
| +
|
| +// WebKeyboardEvent -----------------------------------------------------------
|
| +
|
| +static bool isKeyDown(WPARAM wparam) { return GetKeyState(wparam) & 0x8000; }
|
| +
|
| +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;
|
| + }
|
| +
|
| + ASSERT(!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 WebInputEventFactory::keyboardEvent(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:
|
| + ASSERT_NOT_REACHED();
|
| + }
|
| +
|
| + 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 gLastClickCount;
|
| +static double gLastClickTime;
|
| +
|
| +static LPARAM GetRelativeCursorPos(HWND hwnd) {
|
| + POINT pos = {-1, -1};
|
| + GetCursorPos(&pos);
|
| + ScreenToClient(hwnd, &pos);
|
| + return MAKELPARAM(pos.x, pos.y);
|
| +}
|
| +
|
| +void WebInputEventFactory::resetLastClickState() {
|
| + gLastClickTime = gLastClickCount = 0;
|
| +}
|
| +
|
| +WebMouseEvent WebInputEventFactory::mouseEvent(HWND hwnd,
|
| + UINT message,
|
| + WPARAM wparam,
|
| + LPARAM lparam) {
|
| + WebMouseEvent result; //(WebInputEvent::Uninitialized());
|
| +
|
| + 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:
|
| + ASSERT_NOT_REACHED();
|
| + }
|
| +
|
| + // 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 globalPoint = {result.x, result.y};
|
| + ClientToScreen(hwnd, &globalPoint);
|
| +
|
| + result.globalX = globalPoint.x;
|
| + result.globalY = globalPoint.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 lastClickPositionX;
|
| + static int lastClickPositionY;
|
| + static WebMouseEvent::Button lastClickButton = WebMouseEvent::ButtonLeft;
|
| +
|
| + double currentTime = result.timeStampSeconds;
|
| + bool cancelPreviousClick =
|
| + (abs(lastClickPositionX - result.x) >
|
| + (GetSystemMetrics(SM_CXDOUBLECLK) / 2)) ||
|
| + (abs(lastClickPositionY - result.y) >
|
| + (GetSystemMetrics(SM_CYDOUBLECLK) / 2)) ||
|
| + ((currentTime - gLastClickTime) * 1000.0 > GetDoubleClickTime());
|
| +
|
| + if (result.type == WebInputEvent::MouseDown) {
|
| + if (!cancelPreviousClick && (result.button == lastClickButton))
|
| + ++gLastClickCount;
|
| + else {
|
| + gLastClickCount = 1;
|
| + lastClickPositionX = result.x;
|
| + lastClickPositionY = result.y;
|
| + }
|
| + gLastClickTime = currentTime;
|
| + lastClickButton = result.button;
|
| + } else if (result.type == WebInputEvent::MouseMove ||
|
| + result.type == WebInputEvent::MouseLeave) {
|
| + if (cancelPreviousClick) {
|
| + gLastClickCount = 0;
|
| + lastClickPositionX = 0;
|
| + lastClickPositionY = 0;
|
| + gLastClickTime = 0;
|
| + }
|
| + }
|
| + result.clickCount = gLastClickCount;
|
| +
|
| + // 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 WebInputEventFactory::mouseWheelEvent(HWND hwnd,
|
| + UINT message,
|
| + WPARAM wparam,
|
| + LPARAM lparam) {
|
| + WebMouseWheelEvent result; //(WebInputEvent::Uninitialized());
|
| +
|
| + 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 getKeyState;
|
| + UINT keyState;
|
| + float wheelDelta;
|
| + bool horizontalScroll = 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.
|
| + getKeyState = GetAsyncKeyState;
|
| + keyState = 0;
|
| + if (getKeyState(VK_SHIFT))
|
| + keyState |= MK_SHIFT;
|
| + if (getKeyState(VK_CONTROL))
|
| + keyState |= MK_CONTROL;
|
| + // NOTE: There doesn't seem to be a way to query the mouse button state
|
| + // in this case.
|
| +
|
| + POINT cursorPosition = {0};
|
| + GetCursorPos(&cursorPosition);
|
| + result.globalX = cursorPosition.x;
|
| + result.globalY = cursorPosition.y;
|
| +
|
| + switch (LOWORD(wparam)) {
|
| + case SB_LINEUP: // == SB_LINELEFT
|
| + wheelDelta = WHEEL_DELTA;
|
| + break;
|
| + case SB_LINEDOWN: // == SB_LINERIGHT
|
| + wheelDelta = -WHEEL_DELTA;
|
| + break;
|
| + case SB_PAGEUP:
|
| + wheelDelta = 1;
|
| + result.scrollByPage = true;
|
| + break;
|
| + case SB_PAGEDOWN:
|
| + wheelDelta = -1;
|
| + result.scrollByPage = true;
|
| + break;
|
| + default: // We don't supoprt SB_THUMBPOSITION or SB_THUMBTRACK here.
|
| + wheelDelta = 0;
|
| + break;
|
| + }
|
| +
|
| + if (message == WM_HSCROLL)
|
| + horizontalScroll = true;
|
| + } else {
|
| + // Non-synthesized event; we can just read data off the event.
|
| + getKeyState = GetKeyState;
|
| + keyState = GET_KEYSTATE_WPARAM(wparam);
|
| +
|
| + result.globalX = static_cast<short>(LOWORD(lparam));
|
| + result.globalY = static_cast<short>(HIWORD(lparam));
|
| +
|
| + wheelDelta = static_cast<float>(GET_WHEEL_DELTA_WPARAM(wparam));
|
| + if (message == WM_MOUSEHWHEEL) {
|
| + horizontalScroll = true;
|
| + wheelDelta = -wheelDelta; // Windows is <- -/+ ->, WebKit <- +/- ->.
|
| + }
|
| + }
|
| + if (keyState & MK_SHIFT)
|
| + horizontalScroll = true;
|
| +
|
| + // Set modifiers based on key state.
|
| + if (keyState & MK_SHIFT)
|
| + result.modifiers |= WebInputEvent::ShiftKey;
|
| + if (keyState & MK_CONTROL)
|
| + result.modifiers |= WebInputEvent::ControlKey;
|
| + if (getKeyState(VK_MENU) & 0x8000)
|
| + result.modifiers |= WebInputEvent::AltKey;
|
| + if (keyState & MK_LBUTTON)
|
| + result.modifiers |= WebInputEvent::LeftButtonDown;
|
| + if (keyState & MK_MBUTTON)
|
| + result.modifiers |= WebInputEvent::MiddleButtonDown;
|
| + if (keyState & MK_RBUTTON)
|
| + result.modifiers |= WebInputEvent::RightButtonDown;
|
| +
|
| + SetToggleKeyState(&result);
|
| +
|
| + // Set coordinates by translating event coordinates from screen to client.
|
| + POINT clientPoint = {result.globalX, result.globalY};
|
| + MapWindowPoints(0, hwnd, &clientPoint, 1);
|
| + result.x = clientPoint.x;
|
| + result.y = clientPoint.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 scrollbarPixelsPerLine = 100.0f / 3.0f;
|
| + wheelDelta /= WHEEL_DELTA;
|
| + float scrollDelta = wheelDelta;
|
| + if (horizontalScroll) {
|
| + unsigned long scrollChars = defaultScrollCharsPerWheelDelta;
|
| + SystemParametersInfo(SPI_GETWHEELSCROLLCHARS, 0, &scrollChars, 0);
|
| + // TODO(pkasting): Should probably have a different multiplier
|
| + // scrollbarPixelsPerChar here.
|
| + scrollDelta *= static_cast<float>(scrollChars) * scrollbarPixelsPerLine;
|
| + } else {
|
| + unsigned long scrollLines = defaultScrollLinesPerWheelDelta;
|
| + SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &scrollLines, 0);
|
| + if (scrollLines == WHEEL_PAGESCROLL)
|
| + result.scrollByPage = true;
|
| + if (!result.scrollByPage)
|
| + scrollDelta *= static_cast<float>(scrollLines) * scrollbarPixelsPerLine;
|
| + }
|
| +
|
| + // Set scroll amount based on above calculations. WebKit expects positive
|
| + // deltaY to mean "scroll up" and positive deltaX to mean "scroll left".
|
| + if (horizontalScroll) {
|
| + result.deltaX = scrollDelta;
|
| + result.wheelTicksX = wheelDelta;
|
| + } else {
|
| + result.deltaY = scrollDelta;
|
| + result.wheelTicksY = wheelDelta;
|
| + }
|
| +
|
| + return result;
|
| +}
|
| +
|
| +} // namespace WebKit
|
|
|