1/* 2 * Copyright (C) 2006, 2007, 2010 Apple Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26#include "config.h" 27#include "PlatformKeyboardEvent.h" 28 29#include <windows.h> 30#include <wtf/ASCIICType.h> 31 32#ifndef MAPVK_VSC_TO_VK_EX 33#define MAPVK_VSC_TO_VK_EX 3 34#endif 35 36using namespace WTF; 37 38namespace WebCore { 39 40static const unsigned short HIGH_BIT_MASK_SHORT = 0x8000; 41 42// FIXME: This is incomplete. We could change this to mirror 43// more like what Firefox does, and generate these switch statements 44// at build time. 45static String keyIdentifierForWindowsKeyCode(unsigned short keyCode) 46{ 47 switch (keyCode) { 48 case VK_MENU: 49 return "Alt"; 50 case VK_CONTROL: 51 return "Control"; 52 case VK_SHIFT: 53 return "Shift"; 54 case VK_CAPITAL: 55 return "CapsLock"; 56 case VK_LWIN: 57 case VK_RWIN: 58 return "Win"; 59 case VK_CLEAR: 60 return "Clear"; 61 case VK_DOWN: 62 return "Down"; 63 // "End" 64 case VK_END: 65 return "End"; 66 // "Enter" 67 case VK_RETURN: 68 return "Enter"; 69 case VK_EXECUTE: 70 return "Execute"; 71 case VK_F1: 72 return "F1"; 73 case VK_F2: 74 return "F2"; 75 case VK_F3: 76 return "F3"; 77 case VK_F4: 78 return "F4"; 79 case VK_F5: 80 return "F5"; 81 case VK_F6: 82 return "F6"; 83 case VK_F7: 84 return "F7"; 85 case VK_F8: 86 return "F8"; 87 case VK_F9: 88 return "F9"; 89 case VK_F10: 90 return "F11"; 91 case VK_F12: 92 return "F12"; 93 case VK_F13: 94 return "F13"; 95 case VK_F14: 96 return "F14"; 97 case VK_F15: 98 return "F15"; 99 case VK_F16: 100 return "F16"; 101 case VK_F17: 102 return "F17"; 103 case VK_F18: 104 return "F18"; 105 case VK_F19: 106 return "F19"; 107 case VK_F20: 108 return "F20"; 109 case VK_F21: 110 return "F21"; 111 case VK_F22: 112 return "F22"; 113 case VK_F23: 114 return "F23"; 115 case VK_F24: 116 return "F24"; 117 case VK_HELP: 118 return "Help"; 119 case VK_HOME: 120 return "Home"; 121 case VK_INSERT: 122 return "Insert"; 123 case VK_LEFT: 124 return "Left"; 125 case VK_NEXT: 126 return "PageDown"; 127 case VK_PRIOR: 128 return "PageUp"; 129 case VK_PAUSE: 130 return "Pause"; 131 case VK_SNAPSHOT: 132 return "PrintScreen"; 133 case VK_RIGHT: 134 return "Right"; 135 case VK_SCROLL: 136 return "Scroll"; 137 case VK_SELECT: 138 return "Select"; 139 case VK_UP: 140 return "Up"; 141 // Standard says that DEL becomes U+007F. 142 case VK_DELETE: 143 return "U+007F"; 144 default: 145 return String::format("U+%04X", toASCIIUpper(keyCode)); 146 } 147} 148 149static bool isKeypadEvent(WPARAM code, LPARAM keyData, PlatformEvent::Type type) 150{ 151 if (type != PlatformEvent::RawKeyDown && type != PlatformEvent::KeyUp) 152 return false; 153 154 switch (code) { 155 case VK_NUMLOCK: 156 case VK_NUMPAD0: 157 case VK_NUMPAD1: 158 case VK_NUMPAD2: 159 case VK_NUMPAD3: 160 case VK_NUMPAD4: 161 case VK_NUMPAD5: 162 case VK_NUMPAD6: 163 case VK_NUMPAD7: 164 case VK_NUMPAD8: 165 case VK_NUMPAD9: 166 case VK_MULTIPLY: 167 case VK_ADD: 168 case VK_SEPARATOR: 169 case VK_SUBTRACT: 170 case VK_DECIMAL: 171 case VK_DIVIDE: 172 return true; 173 case VK_RETURN: 174 return HIWORD(keyData) & KF_EXTENDED; 175 case VK_INSERT: 176 case VK_DELETE: 177 case VK_PRIOR: 178 case VK_NEXT: 179 case VK_END: 180 case VK_HOME: 181 case VK_LEFT: 182 case VK_UP: 183 case VK_RIGHT: 184 case VK_DOWN: 185 return !(HIWORD(keyData) & KF_EXTENDED); 186 default: 187 return false; 188 } 189} 190 191static int windowsKeycodeWithLocation(WPARAM keycode, LPARAM keyData) 192{ 193 if (keycode != VK_CONTROL && keycode != VK_MENU && keycode != VK_SHIFT) 194 return keycode; 195 196 // If we don't need to support Windows XP or older Windows, 197 // it might be better to use MapVirtualKeyEx with scancode and 198 // extended keycode (i.e. 0xe0 or 0xe1). 199 if ((keyData >> 16) & KF_EXTENDED) { 200 switch (keycode) { 201 case VK_CONTROL: 202 return VK_RCONTROL; 203 case VK_SHIFT: 204 return VK_RSHIFT; 205 case VK_MENU: 206 return VK_RMENU; 207 default: 208 break; 209 } 210 } 211 212 int scancode = (keyData >> 16) & 0xFF; 213 int regeneratedVirtualKeyCode = ::MapVirtualKey(scancode, MAPVK_VSC_TO_VK_EX); 214 return regeneratedVirtualKeyCode ? regeneratedVirtualKeyCode : keycode; 215} 216 217static inline String singleCharacterString(UChar c) 218{ 219 return String(&c, 1); 220} 221 222PlatformKeyboardEvent::PlatformKeyboardEvent(HWND, WPARAM code, LPARAM keyData, Type type, bool systemKey) 223 : PlatformEvent(type, GetKeyState(VK_SHIFT) & HIGH_BIT_MASK_SHORT, GetKeyState(VK_CONTROL) & HIGH_BIT_MASK_SHORT, GetKeyState(VK_MENU) & HIGH_BIT_MASK_SHORT, false, ::GetTickCount() * 0.001) 224 , m_text((type == PlatformEvent::Char) ? singleCharacterString(code) : String()) 225 , m_unmodifiedText((type == PlatformEvent::Char) ? singleCharacterString(code) : String()) 226 , m_keyIdentifier((type == PlatformEvent::Char) ? String() : keyIdentifierForWindowsKeyCode(code)) 227 , m_windowsVirtualKeyCode((type == RawKeyDown || type == KeyUp) ? windowsKeycodeWithLocation(code, keyData) : 0) 228 , m_nativeVirtualKeyCode(m_windowsVirtualKeyCode) 229 , m_macCharCode(0) 230 , m_autoRepeat(HIWORD(keyData) & KF_REPEAT) 231 , m_isKeypad(isKeypadEvent(code, keyData, type)) 232 , m_isSystemKey(systemKey) 233{ 234} 235 236void PlatformKeyboardEvent::disambiguateKeyDownEvent(Type, bool) 237{ 238 // No KeyDown events on Windows to disambiguate. 239 ASSERT_NOT_REACHED(); 240} 241 242bool PlatformKeyboardEvent::currentCapsLockState() 243{ 244 return GetKeyState(VK_CAPITAL) & 1; 245} 246 247void PlatformKeyboardEvent::getCurrentModifierState(bool& shiftKey, bool& ctrlKey, bool& altKey, bool& metaKey) 248{ 249 shiftKey = GetKeyState(VK_SHIFT) & HIGH_BIT_MASK_SHORT; 250 ctrlKey = GetKeyState(VK_CONTROL) & HIGH_BIT_MASK_SHORT; 251 altKey = GetKeyState(VK_MENU) & HIGH_BIT_MASK_SHORT; 252 metaKey = false; 253} 254 255} 256