/* * Copyright (C) 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 "WebInputEventConversion.h" #include "EventNames.h" #include "KeyboardCodes.h" #include "KeyboardEvent.h" #include "MouseEvent.h" #include "PlatformKeyboardEvent.h" #include "PlatformMouseEvent.h" #include "PlatformWheelEvent.h" #include "ScrollView.h" #include "WebInputEvent.h" #include "WheelEvent.h" #include "Widget.h" using namespace WebCore; namespace WebKit { // MakePlatformMouseEvent ----------------------------------------------------- PlatformMouseEventBuilder::PlatformMouseEventBuilder(Widget* widget, const WebMouseEvent& e) { // FIXME: widget is always toplevel, unless it's a popup. We may be able // to get rid of this once we abstract popups into a WebKit API. m_position = widget->convertFromContainingWindow(IntPoint(e.x, e.y)); m_globalPosition = IntPoint(e.globalX, e.globalY); m_button = static_cast(e.button); m_shiftKey = (e.modifiers & WebInputEvent::ShiftKey); m_ctrlKey = (e.modifiers & WebInputEvent::ControlKey); m_altKey = (e.modifiers & WebInputEvent::AltKey); m_metaKey = (e.modifiers & WebInputEvent::MetaKey); m_modifierFlags = e.modifiers; m_timestamp = e.timeStampSeconds; m_clickCount = e.clickCount; switch (e.type) { case WebInputEvent::MouseMove: case WebInputEvent::MouseLeave: // synthesize a move event m_eventType = MouseEventMoved; break; case WebInputEvent::MouseDown: m_eventType = MouseEventPressed; break; case WebInputEvent::MouseUp: m_eventType = MouseEventReleased; break; default: ASSERT_NOT_REACHED(); } } // PlatformWheelEventBuilder -------------------------------------------------- PlatformWheelEventBuilder::PlatformWheelEventBuilder(Widget* widget, const WebMouseWheelEvent& e) { m_position = widget->convertFromContainingWindow(IntPoint(e.x, e.y)); m_globalPosition = IntPoint(e.globalX, e.globalY); m_deltaX = e.deltaX; m_deltaY = e.deltaY; m_wheelTicksX = e.wheelTicksX; m_wheelTicksY = e.wheelTicksY; m_isAccepted = false; m_granularity = e.scrollByPage ? ScrollByPageWheelEvent : ScrollByPixelWheelEvent; m_shiftKey = (e.modifiers & WebInputEvent::ShiftKey); m_ctrlKey = (e.modifiers & WebInputEvent::ControlKey); m_altKey = (e.modifiers & WebInputEvent::AltKey); m_metaKey = (e.modifiers & WebInputEvent::MetaKey); } // MakePlatformKeyboardEvent -------------------------------------------------- static inline PlatformKeyboardEvent::Type toPlatformKeyboardEventType(WebInputEvent::Type type) { switch (type) { case WebInputEvent::KeyUp: return PlatformKeyboardEvent::KeyUp; case WebInputEvent::KeyDown: return PlatformKeyboardEvent::KeyDown; case WebInputEvent::RawKeyDown: return PlatformKeyboardEvent::RawKeyDown; case WebInputEvent::Char: return PlatformKeyboardEvent::Char; default: ASSERT_NOT_REACHED(); } return PlatformKeyboardEvent::KeyDown; } PlatformKeyboardEventBuilder::PlatformKeyboardEventBuilder(const WebKeyboardEvent& e) { m_type = toPlatformKeyboardEventType(e.type); m_text = String(e.text); m_unmodifiedText = String(e.unmodifiedText); m_keyIdentifier = String(e.keyIdentifier); m_autoRepeat = (e.modifiers & WebInputEvent::IsAutoRepeat); m_windowsVirtualKeyCode = e.windowsKeyCode; m_nativeVirtualKeyCode = e.nativeKeyCode; m_isKeypad = (e.modifiers & WebInputEvent::IsKeyPad); m_shiftKey = (e.modifiers & WebInputEvent::ShiftKey); m_ctrlKey = (e.modifiers & WebInputEvent::ControlKey); m_altKey = (e.modifiers & WebInputEvent::AltKey); m_metaKey = (e.modifiers & WebInputEvent::MetaKey); m_isSystemKey = e.isSystemKey; } void PlatformKeyboardEventBuilder::setKeyType(Type type) { // According to the behavior of Webkit in Windows platform, // we need to convert KeyDown to RawKeydown and Char events // See WebKit/WebKit/Win/WebView.cpp ASSERT(m_type == KeyDown); ASSERT(type == RawKeyDown || type == Char); m_type = type; if (type == RawKeyDown) { m_text = String(); m_unmodifiedText = String(); } else { m_keyIdentifier = String(); m_windowsVirtualKeyCode = 0; } } // Please refer to bug http://b/issue?id=961192, which talks about Webkit // keyboard event handling changes. It also mentions the list of keys // which don't have associated character events. bool PlatformKeyboardEventBuilder::isCharacterKey() const { switch (windowsVirtualKeyCode()) { case VKEY_BACK: case VKEY_ESCAPE: return false; } return true; } #if ENABLE(TOUCH_EVENTS) static inline TouchEventType toPlatformTouchEventType(const WebInputEvent::Type type) { switch (type) { case WebInputEvent::TouchStart: return TouchStart; case WebInputEvent::TouchMove: return TouchMove; case WebInputEvent::TouchEnd: return TouchEnd; case WebInputEvent::TouchCancel: return TouchCancel; default: ASSERT_NOT_REACHED(); } return TouchStart; } static inline PlatformTouchPoint::State toPlatformTouchPointState(const WebTouchPoint::State state) { switch (state) { case WebTouchPoint::StateReleased: return PlatformTouchPoint::TouchReleased; case WebTouchPoint::StatePressed: return PlatformTouchPoint::TouchPressed; case WebTouchPoint::StateMoved: return PlatformTouchPoint::TouchMoved; case WebTouchPoint::StateStationary: return PlatformTouchPoint::TouchStationary; case WebTouchPoint::StateCancelled: return PlatformTouchPoint::TouchCancelled; case WebTouchPoint::StateUndefined: ASSERT_NOT_REACHED(); } return PlatformTouchPoint::TouchReleased; } PlatformTouchPointBuilder::PlatformTouchPointBuilder(Widget* widget, const WebTouchPoint& point) { m_id = point.id; m_state = toPlatformTouchPointState(point.state); m_pos = widget->convertFromContainingWindow(point.position); m_screenPos = point.screenPosition; } PlatformTouchEventBuilder::PlatformTouchEventBuilder(Widget* widget, const WebTouchEvent& event) { m_type = toPlatformTouchEventType(event.type); m_ctrlKey = event.modifiers & WebInputEvent::ControlKey; m_altKey = event.modifiers & WebInputEvent::AltKey; m_shiftKey = event.modifiers & WebInputEvent::ShiftKey; m_metaKey = event.modifiers & WebInputEvent::MetaKey; for (int i = 0; i < event.touchPointsLength; ++i) m_touchPoints.append(PlatformTouchPointBuilder(widget, event.touchPoints[i])); } #endif static int getWebInputModifiers(const UIEventWithKeyState& event) { int modifiers = 0; if (event.ctrlKey()) modifiers |= WebInputEvent::ControlKey; if (event.shiftKey()) modifiers |= WebInputEvent::ShiftKey; if (event.altKey()) modifiers |= WebInputEvent::AltKey; if (event.metaKey()) modifiers |= WebInputEvent::MetaKey; return modifiers; } WebMouseEventBuilder::WebMouseEventBuilder(const Widget* widget, const MouseEvent& event) { if (event.type() == eventNames().mousemoveEvent) type = WebInputEvent::MouseMove; else if (event.type() == eventNames().mouseoutEvent) type = WebInputEvent::MouseLeave; else if (event.type() == eventNames().mouseoverEvent) type = WebInputEvent::MouseEnter; else if (event.type() == eventNames().mousedownEvent) type = WebInputEvent::MouseDown; else if (event.type() == eventNames().mouseupEvent) type = WebInputEvent::MouseUp; else if (event.type() == eventNames().contextmenuEvent) type = WebInputEvent::ContextMenu; else return; // Skip all other mouse events. timeStampSeconds = event.timeStamp() * 1.0e-3; switch (event.button()) { case LeftButton: button = WebMouseEvent::ButtonLeft; break; case MiddleButton: button = WebMouseEvent::ButtonMiddle; break; case RightButton: button = WebMouseEvent::ButtonRight; break; } modifiers = getWebInputModifiers(event); if (event.buttonDown()) { switch (event.button()) { case LeftButton: modifiers |= WebInputEvent::LeftButtonDown; break; case MiddleButton: modifiers |= WebInputEvent::MiddleButtonDown; break; case RightButton: modifiers |= WebInputEvent::RightButtonDown; break; } } ScrollView* view = widget->parent(); IntPoint p = view->contentsToWindow( IntPoint(event.absoluteLocation().x(), event.absoluteLocation().y())); globalX = event.screenX(); globalY = event.screenY(); windowX = p.x(); windowY = p.y(); x = event.absoluteLocation().x() - widget->pos().x(); y = event.absoluteLocation().y() - widget->pos().y(); clickCount = event.detail(); } WebMouseWheelEventBuilder::WebMouseWheelEventBuilder(const Widget* widget, const WheelEvent& event) { if (event.type() != eventNames().mousewheelEvent) return; type = WebInputEvent::MouseWheel; timeStampSeconds = event.timeStamp() * 1.0e-3; modifiers = getWebInputModifiers(event); ScrollView* view = widget->parent(); IntPoint p = view->contentsToWindow( IntPoint(event.absoluteLocation().x(), event.absoluteLocation().y())); globalX = event.screenX(); globalY = event.screenY(); windowX = p.x(); windowY = p.y(); x = event.absoluteLocation().x() - widget->pos().x(); y = event.absoluteLocation().y() - widget->pos().y(); deltaX = static_cast(event.rawDeltaX()); deltaY = static_cast(event.rawDeltaY()); // The 120 is from WheelEvent::initWheelEvent(). wheelTicksX = static_cast(event.wheelDeltaX()) / 120; wheelTicksY = static_cast(event.wheelDeltaY()) / 120; scrollByPage = event.granularity() == WheelEvent::Page; } WebKeyboardEventBuilder::WebKeyboardEventBuilder(const KeyboardEvent& event) { if (event.type() == eventNames().keydownEvent) type = KeyDown; else if (event.type() == eventNames().keyupEvent) type = WebInputEvent::KeyUp; else if (event.type() == eventNames().keypressEvent) type = WebInputEvent::Char; else return; // Skip all other keyboard events. modifiers = getWebInputModifiers(event); timeStampSeconds = event.timeStamp() * 1.0e-3; windowsKeyCode = event.keyCode(); // The platform keyevent does not exist if the event was created using // initKeyboardEvent. if (!event.keyEvent()) return; nativeKeyCode = event.keyEvent()->nativeVirtualKeyCode(); unsigned int numChars = std::min(event.keyEvent()->text().length(), static_cast(WebKeyboardEvent::textLengthCap)); for (unsigned int i = 0; i < numChars; i++) { text[i] = event.keyEvent()->text()[i]; unmodifiedText[i] = event.keyEvent()->unmodifiedText()[i]; } } } // namespace WebKit