diff options
Diffstat (limited to 'webkit/glue/webinputevent_win.cc')
-rw-r--r-- | webkit/glue/webinputevent_win.cc | 304 |
1 files changed, 304 insertions, 0 deletions
diff --git a/webkit/glue/webinputevent_win.cc b/webkit/glue/webinputevent_win.cc new file mode 100644 index 0000000..93f5da7 --- /dev/null +++ b/webkit/glue/webinputevent_win.cc @@ -0,0 +1,304 @@ +// Copyright (c) 2006-2008 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 "config.h" + +#include "webkit/glue/webinputevent.h" + +#include "webkit/glue/event_conversion.h" + +#undef LOG +#include "base/logging.h" + +static const unsigned long kDefaultScrollLinesPerWheelDelta = 3; + +// WebMouseEvent -------------------------------------------------------------- + +static LPARAM GetRelativeCursorPos(HWND hwnd) { + POINT pos = {-1, -1}; + GetCursorPos(&pos); + ScreenToClient(hwnd, &pos); + return MAKELPARAM(pos.x, pos.y); +} + +WebMouseEvent::WebMouseEvent(HWND hwnd, UINT message, WPARAM wparam, + LPARAM lparam) { + switch (message) { + case WM_MOUSEMOVE: + type = MOUSE_MOVE; + if (wparam & MK_LBUTTON) + button = BUTTON_LEFT; + else if (wparam & MK_MBUTTON) + button = BUTTON_MIDDLE; + else if (wparam & MK_RBUTTON) + button = BUTTON_MIDDLE; + else + button = BUTTON_NONE; + break; + case WM_MOUSELEAVE: + type = MOUSE_LEAVE; + button = BUTTON_NONE; + // 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: + type = MOUSE_DOWN; + button = BUTTON_LEFT; + break; + case WM_MBUTTONDOWN: + type = MOUSE_DOWN; + button = BUTTON_MIDDLE; + break; + case WM_RBUTTONDOWN: + type = MOUSE_DOWN; + button = BUTTON_RIGHT; + break; + case WM_LBUTTONUP: + type = MOUSE_UP; + button = BUTTON_LEFT; + break; + case WM_MBUTTONUP: + type = MOUSE_UP; + button = BUTTON_MIDDLE; + break; + case WM_RBUTTONUP: + type = MOUSE_UP; + button = BUTTON_RIGHT; + break; + case WM_LBUTTONDBLCLK: + type = MOUSE_DOUBLE_CLICK; + button = BUTTON_LEFT; + break; + case WM_MBUTTONDBLCLK: + type = MOUSE_DOUBLE_CLICK; + button = BUTTON_MIDDLE; + break; + case WM_RBUTTONDBLCLK: + type = MOUSE_DOUBLE_CLICK; + button = BUTTON_RIGHT; + break; + default: + NOTREACHED() << "unexpected native message"; + } + + // set position fields: + + x = static_cast<short>(LOWORD(lparam)); + y = static_cast<short>(HIWORD(lparam)); + + POINT global_point = { x, y }; + ClientToScreen(hwnd, &global_point); + + global_x = global_point.x; + global_y = global_point.y; + + // set modifiers: + + modifiers = 0; + if (wparam & MK_CONTROL) + modifiers |= CTRL_KEY; + if (wparam & MK_SHIFT) + modifiers |= SHIFT_KEY; + if (GetKeyState(VK_MENU) & 0x8000) + modifiers |= (ALT_KEY | META_KEY); // TODO(darin): set META properly + + // TODO(pkasting): http://b/1117926 Instead of using GetTickCount() here, we + // should use GetMessageTime() on the original Windows message in the browser + // process, and pass that in the WebMouseEvent. + timestamp_sec = GetTickCount() / 1000.0; + + layout_test_click_count = 0; +} + +// WebMouseWheelEvent --------------------------------------------------------- + +WebMouseWheelEvent::WebMouseWheelEvent(HWND hwnd, UINT message, WPARAM wparam, + LPARAM lparam) { + type = MOUSE_WHEEL; + button = BUTTON_NONE; + + UINT key_state = GET_KEYSTATE_WPARAM(wparam); + int wheel_delta = static_cast<int>(GET_WHEEL_DELTA_WPARAM(wparam)); + + typedef SHORT (WINAPI *GetKeyStateFunction)(int key); + GetKeyStateFunction get_key_state = GetKeyState; + + // Synthesize mousewheel event from a scroll event. + // This is needed to simulate middle mouse scrolling in some + // laptops (Thinkpads) + if ((WM_VSCROLL == message) || (WM_HSCROLL == message)) { + + POINT cursor_position = {0}; + GetCursorPos(&cursor_position); + + global_x = cursor_position.x; + global_y = cursor_position.y; + + key_state = 0; + + // Since we are synthesizing the wheel event, we have to + // use GetAsyncKeyState + if (GetAsyncKeyState(VK_SHIFT)) + key_state |= MK_SHIFT; + + if (GetAsyncKeyState(VK_CONTROL)) + key_state |= MK_CONTROL; + + // Add a simple workaround to scroll multiples units per page. + // The right fix needs to extend webkit's implementation of + // wheel events and that's not something we want to do at + // this time. See bug# 928509 + // TODO(joshia): Implement the right fix for bug# 928509 + const int kPageScroll = 10; // 10 times wheel scroll + 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 = kPageScroll * WHEEL_DELTA; + break; + case SB_PAGEDOWN: + wheel_delta = -kPageScroll * WHEEL_DELTA; + break; + // TODO(joshia): Handle SB_THUMBPOSITION and SB_THUMBTRACK + // for compeleteness + default: + break; + } + + // Windows sends the following messages for tilt-wheel events. + // * Tilt a mousewheel (left) + // message == WM_HSCROLL, wparam == SB_LINELEFT (== SB_LINEUP). + // * Tilt a mousewheel (right) + // message == WM_HSCROLL, wparam == SB_LINERIGHT (== SB_LINEDOWN). + // To convert these events to the shift + mousewheel ones, we do not only + // add a shift but also change the signs of their |wheel_delta| values. + if (WM_HSCROLL == message) { + key_state |= MK_SHIFT; + wheel_delta = -wheel_delta; + } + + // Use GetAsyncKeyState for key state since we are synthesizing + // the input + get_key_state = GetAsyncKeyState; + } else { + + global_x = static_cast<short>(LOWORD(lparam)); + global_y = static_cast<short>(HIWORD(lparam)); + } + + POINT client_point = { global_x, global_y }; + ScreenToClient(hwnd, &client_point); + x = client_point.x; + y = client_point.y; + + // compute the scroll delta based on Raymond Chen's algorithm: + // http://blogs.msdn.com/oldnewthing/archive/2003/08/07/54615.aspx + + static int carryover = 0; + static HWND last_window = NULL; + + if (hwnd != last_window) { + last_window = hwnd; + carryover = 0; + } + + unsigned long scroll_lines = kDefaultScrollLinesPerWheelDelta; + SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &scroll_lines, 0); + + // TODO(darin): handle the case where scroll_lines is WHEEL_PAGESIZE + int delta_lines = 0; + if (scroll_lines == 0) { + carryover = 0; + } else { + const int delta = carryover + wheel_delta; + + // see how many lines we should scroll. relies on round-toward-zero. + delta_lines = delta * static_cast<int>(scroll_lines) / WHEEL_DELTA; + + // record the unused portion as the next carryover. + carryover = + delta - delta_lines * WHEEL_DELTA / static_cast<int>(scroll_lines); + } + + // Scroll horizontally if shift is held. WebKit's WebKit/win/WebView.cpp + // does the equivalent. + // TODO(jackson): Support WM_MOUSEHWHEEL = 0x020E event as well. + // (Need a mouse with horizontal scrolling capabilities to test it.) + if (key_state & MK_SHIFT) { + // Scrolling up should move left, scrolling down should move right + delta_x = -delta_lines; + delta_y = 0; + } else { + delta_x = 0; + delta_y = delta_lines; + } + + if (key_state & MK_SHIFT) + modifiers |= SHIFT_KEY; + if (key_state & MK_CONTROL) + modifiers |= CTRL_KEY; + + // Get any additional key states needed + if (get_key_state(VK_MENU) & 0x8000) + modifiers |= (ALT_KEY | META_KEY); +} + +// WebKeyboardEvent ----------------------------------------------------------- + +WebKeyboardEvent::WebKeyboardEvent(HWND hwnd, UINT message, WPARAM wparam, + LPARAM lparam) { + modifiers = 0; + system_key = false; + + actual_message.hwnd = hwnd; + actual_message.message = message; + actual_message.wParam = wparam; + actual_message.lParam = lparam; + + key_code = static_cast<int>(wparam); + key_data = static_cast<int>(lparam); + + switch (message) { + case WM_SYSKEYDOWN: + system_key = true; + case WM_KEYDOWN: + type = KEY_DOWN; + break; + case WM_SYSKEYUP: + system_key = true; + case WM_KEYUP: + type = KEY_UP; + break; + case WM_IME_CHAR: + key_data = static_cast<int>(wparam); + type = CHAR; + break; + case WM_SYSCHAR: + system_key = true; + type = CHAR; + case WM_CHAR: + type = CHAR; + break; + default: + NOTREACHED() << "unexpected native message"; + } + + if (GetKeyState(VK_SHIFT) & 0x8000) + modifiers |= SHIFT_KEY; + if (GetKeyState(VK_CONTROL) & 0x8000) + modifiers |= CTRL_KEY; + if (GetKeyState(VK_MENU) & 0x8000) + modifiers |= (ALT_KEY | META_KEY); + + if (LOWORD(lparam) > 1) + modifiers |= IS_AUTO_REPEAT; + + // TODO(darin): figure out if we should set IS_KEYPAD +} + |