/* * 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 "sky/engine/config.h" #include "sky/engine/web/WebInputEventConversion.h" #include "sky/engine/core/events/KeyboardEvent.h" #include "sky/engine/core/frame/FrameHost.h" #include "sky/engine/core/frame/FrameView.h" #include "sky/engine/core/page/Page.h" #include "sky/engine/core/rendering/RenderObject.h" #include "sky/engine/platform/KeyboardCodes.h" #include "sky/engine/platform/Widget.h" namespace blink { static const double millisPerSecond = 1000.0; // MakePlatformKeyboardEvent -------------------------------------------------- inline PlatformEvent::Type toPlatformKeyboardEventType(WebInputEvent::Type type) { switch (type) { case WebInputEvent::KeyUp: return PlatformEvent::KeyUp; case WebInputEvent::KeyDown: return PlatformEvent::KeyDown; case WebInputEvent::RawKeyDown: return PlatformEvent::RawKeyDown; case WebInputEvent::Char: return PlatformEvent::Char; default: ASSERT_NOT_REACHED(); } return PlatformEvent::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_nativeVirtualKeyCode = e.nativeKeyCode; m_isKeypad = (e.modifiers & WebInputEvent::IsKeyPad); m_isSystemKey = e.isSystemKey; m_modifiers = 0; if (e.modifiers & WebInputEvent::ShiftKey) m_modifiers |= PlatformEvent::ShiftKey; if (e.modifiers & WebInputEvent::ControlKey) m_modifiers |= PlatformEvent::CtrlKey; if (e.modifiers & WebInputEvent::AltKey) m_modifiers |= PlatformEvent::AltKey; if (e.modifiers & WebInputEvent::MetaKey) m_modifiers |= PlatformEvent::MetaKey; // FIXME: PlatformKeyboardEvents expect a locational version of the keycode (e.g. VK_LSHIFT // instead of VK_SHIFT). This should be changed so the location/keycode are stored separately, // as in other places in the code. m_windowsVirtualKeyCode = e.windowsKeyCode; if (e.windowsKeyCode == VK_SHIFT) { if (e.modifiers & WebInputEvent::IsLeft) m_windowsVirtualKeyCode = VK_LSHIFT; else if (e.modifiers & WebInputEvent::IsRight) m_windowsVirtualKeyCode = VK_RSHIFT; } else if (e.windowsKeyCode == VK_CONTROL) { if (e.modifiers & WebInputEvent::IsLeft) m_windowsVirtualKeyCode = VK_LCONTROL; else if (e.modifiers & WebInputEvent::IsRight) m_windowsVirtualKeyCode = VK_RCONTROL; } else if (e.windowsKeyCode == VK_MENU) { if (e.modifiers & WebInputEvent::IsLeft) m_windowsVirtualKeyCode = VK_LMENU; else if (e.modifiers & WebInputEvent::IsRight) m_windowsVirtualKeyCode = VK_RMENU; } } 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; } 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; } WebKeyboardEventBuilder::WebKeyboardEventBuilder(const KeyboardEvent& event) { if (event.type() == EventTypeNames::keydown) type = KeyDown; else if (event.type() == EventTypeNames::keyup) type = WebInputEvent::KeyUp; else if (event.type() == EventTypeNames::keypress) type = WebInputEvent::Char; else return; // Skip all other keyboard events. modifiers = getWebInputModifiers(event); if (event.location() == KeyboardEvent::DOM_KEY_LOCATION_NUMPAD) modifiers |= WebInputEvent::IsKeyPad; else if (event.location() == KeyboardEvent::DOM_KEY_LOCATION_LEFT) modifiers |= WebInputEvent::IsLeft; else if (event.location() == KeyboardEvent::DOM_KEY_LOCATION_RIGHT) modifiers |= WebInputEvent::IsRight; timeStampSeconds = event.timeStamp() / millisPerSecond; 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 numberOfCharacters = std::min(event.keyEvent()->text().length(), static_cast(textLengthCap)); for (unsigned i = 0; i < numberOfCharacters; ++i) { text[i] = event.keyEvent()->text()[i]; unmodifiedText[i] = event.keyEvent()->unmodifiedText()[i]; } memcpy(keyIdentifier, event.keyIdentifier().ascii().data(), event.keyIdentifier().length()); } WebInputEvent::Type toWebKeyboardEventType(PlatformEvent::Type type) { switch (type) { case PlatformEvent::KeyUp: return WebInputEvent::KeyUp; case PlatformEvent::KeyDown: return WebInputEvent::KeyDown; case PlatformEvent::RawKeyDown: return WebInputEvent::RawKeyDown; case PlatformEvent::Char: return WebInputEvent::Char; default: return WebInputEvent::Undefined; } } int toWebKeyboardEventModifiers(int modifiers) { int newModifiers = 0; if (modifiers & PlatformEvent::ShiftKey) newModifiers |= WebInputEvent::ShiftKey; if (modifiers & PlatformEvent::CtrlKey) newModifiers |= WebInputEvent::ControlKey; if (modifiers & PlatformEvent::AltKey) newModifiers |= WebInputEvent::AltKey; if (modifiers & PlatformEvent::MetaKey) newModifiers |= WebInputEvent::MetaKey; return newModifiers; } WebKeyboardEventBuilder::WebKeyboardEventBuilder(const PlatformKeyboardEvent& event) { type = toWebKeyboardEventType(event.type()); modifiers = toWebKeyboardEventModifiers(event.modifiers()); if (event.isAutoRepeat()) modifiers |= WebInputEvent::IsAutoRepeat; if (event.isKeypad()) modifiers |= WebInputEvent::IsKeyPad; isSystemKey = event.isSystemKey(); nativeKeyCode = event.nativeVirtualKeyCode(); windowsKeyCode = windowsKeyCodeWithoutLocation(event.windowsVirtualKeyCode()); modifiers |= locationModifiersFromWindowsKeyCode(event.windowsVirtualKeyCode()); event.text().copyTo(text, 0, textLengthCap); event.unmodifiedText().copyTo(unmodifiedText, 0, textLengthCap); memcpy(keyIdentifier, event.keyIdentifier().ascii().data(), std::min(static_cast(keyIdentifierLengthCap), event.keyIdentifier().length())); } } // namespace blink