1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #import "ui/events/keycodes/keyboard_code_conversion_mac.h" 6 7 #include <algorithm> 8 9 #import <Carbon/Carbon.h> 10 11 #include "base/logging.h" 12 #include "ui/events/keycodes/dom4/keycode_converter.h" 13 14 namespace ui { 15 16 namespace { 17 18 // A struct to hold a Windows keycode to Mac virtual keycode mapping. 19 struct KeyCodeMap { 20 KeyboardCode keycode; 21 int macKeycode; 22 unichar characterIgnoringModifiers; 23 }; 24 25 // Customized less operator for using std::lower_bound() on a KeyCodeMap array. 26 bool operator<(const KeyCodeMap& a, const KeyCodeMap& b) { 27 return a.keycode < b.keycode; 28 } 29 30 // This array must keep sorted ascending according to the value of |keycode|, 31 // so that we can binary search it. 32 // TODO(suzhe): This map is not complete, missing entries have macKeycode == -1. 33 const KeyCodeMap kKeyCodesMap[] = { 34 { VKEY_BACK /* 0x08 */, kVK_Delete, kBackspaceCharCode }, 35 { VKEY_TAB /* 0x09 */, kVK_Tab, kTabCharCode }, 36 { VKEY_BACKTAB /* 0x0A */, 0x21E4, '\031' }, 37 { VKEY_CLEAR /* 0x0C */, kVK_ANSI_KeypadClear, kClearCharCode }, 38 { VKEY_RETURN /* 0x0D */, kVK_Return, kReturnCharCode }, 39 { VKEY_SHIFT /* 0x10 */, kVK_Shift, 0 }, 40 { VKEY_CONTROL /* 0x11 */, kVK_Control, 0 }, 41 { VKEY_MENU /* 0x12 */, kVK_Option, 0 }, 42 { VKEY_PAUSE /* 0x13 */, -1, NSPauseFunctionKey }, 43 { VKEY_CAPITAL /* 0x14 */, kVK_CapsLock, 0 }, 44 { VKEY_KANA /* 0x15 */, kVK_JIS_Kana, 0 }, 45 { VKEY_HANGUL /* 0x15 */, -1, 0 }, 46 { VKEY_JUNJA /* 0x17 */, -1, 0 }, 47 { VKEY_FINAL /* 0x18 */, -1, 0 }, 48 { VKEY_HANJA /* 0x19 */, -1, 0 }, 49 { VKEY_KANJI /* 0x19 */, -1, 0 }, 50 { VKEY_ESCAPE /* 0x1B */, kVK_Escape, kEscapeCharCode }, 51 { VKEY_CONVERT /* 0x1C */, -1, 0 }, 52 { VKEY_NONCONVERT /* 0x1D */, -1, 0 }, 53 { VKEY_ACCEPT /* 0x1E */, -1, 0 }, 54 { VKEY_MODECHANGE /* 0x1F */, -1, 0 }, 55 { VKEY_SPACE /* 0x20 */, kVK_Space, kSpaceCharCode }, 56 { VKEY_PRIOR /* 0x21 */, kVK_PageUp, NSPageUpFunctionKey }, 57 { VKEY_NEXT /* 0x22 */, kVK_PageDown, NSPageDownFunctionKey }, 58 { VKEY_END /* 0x23 */, kVK_End, NSEndFunctionKey }, 59 { VKEY_HOME /* 0x24 */, kVK_Home, NSHomeFunctionKey }, 60 { VKEY_LEFT /* 0x25 */, kVK_LeftArrow, NSLeftArrowFunctionKey }, 61 { VKEY_UP /* 0x26 */, kVK_UpArrow, NSUpArrowFunctionKey }, 62 { VKEY_RIGHT /* 0x27 */, kVK_RightArrow, NSRightArrowFunctionKey }, 63 { VKEY_DOWN /* 0x28 */, kVK_DownArrow, NSDownArrowFunctionKey }, 64 { VKEY_SELECT /* 0x29 */, -1, 0 }, 65 { VKEY_PRINT /* 0x2A */, -1, NSPrintFunctionKey }, 66 { VKEY_EXECUTE /* 0x2B */, -1, NSExecuteFunctionKey }, 67 { VKEY_SNAPSHOT /* 0x2C */, -1, NSPrintScreenFunctionKey }, 68 { VKEY_INSERT /* 0x2D */, -1, NSInsertFunctionKey }, 69 { VKEY_DELETE /* 0x2E */, kVK_ForwardDelete, kDeleteCharCode }, 70 { VKEY_HELP /* 0x2F */, kVK_Help, kHelpCharCode }, 71 { VKEY_0 /* 0x30 */, kVK_ANSI_0, '0' }, 72 { VKEY_1 /* 0x31 */, kVK_ANSI_1, '1' }, 73 { VKEY_2 /* 0x32 */, kVK_ANSI_2, '2' }, 74 { VKEY_3 /* 0x33 */, kVK_ANSI_3, '3' }, 75 { VKEY_4 /* 0x34 */, kVK_ANSI_4, '4' }, 76 { VKEY_5 /* 0x35 */, kVK_ANSI_5, '5' }, 77 { VKEY_6 /* 0x36 */, kVK_ANSI_6, '6' }, 78 { VKEY_7 /* 0x37 */, kVK_ANSI_7, '7' }, 79 { VKEY_8 /* 0x38 */, kVK_ANSI_8, '8' }, 80 { VKEY_9 /* 0x39 */, kVK_ANSI_9, '9' }, 81 { VKEY_A /* 0x41 */, kVK_ANSI_A, 'a' }, 82 { VKEY_B /* 0x42 */, kVK_ANSI_B, 'b' }, 83 { VKEY_C /* 0x43 */, kVK_ANSI_C, 'c' }, 84 { VKEY_D /* 0x44 */, kVK_ANSI_D, 'd' }, 85 { VKEY_E /* 0x45 */, kVK_ANSI_E, 'e' }, 86 { VKEY_F /* 0x46 */, kVK_ANSI_F, 'f' }, 87 { VKEY_G /* 0x47 */, kVK_ANSI_G, 'g' }, 88 { VKEY_H /* 0x48 */, kVK_ANSI_H, 'h' }, 89 { VKEY_I /* 0x49 */, kVK_ANSI_I, 'i' }, 90 { VKEY_J /* 0x4A */, kVK_ANSI_J, 'j' }, 91 { VKEY_K /* 0x4B */, kVK_ANSI_K, 'k' }, 92 { VKEY_L /* 0x4C */, kVK_ANSI_L, 'l' }, 93 { VKEY_M /* 0x4D */, kVK_ANSI_M, 'm' }, 94 { VKEY_N /* 0x4E */, kVK_ANSI_N, 'n' }, 95 { VKEY_O /* 0x4F */, kVK_ANSI_O, 'o' }, 96 { VKEY_P /* 0x50 */, kVK_ANSI_P, 'p' }, 97 { VKEY_Q /* 0x51 */, kVK_ANSI_Q, 'q' }, 98 { VKEY_R /* 0x52 */, kVK_ANSI_R, 'r' }, 99 { VKEY_S /* 0x53 */, kVK_ANSI_S, 's' }, 100 { VKEY_T /* 0x54 */, kVK_ANSI_T, 't' }, 101 { VKEY_U /* 0x55 */, kVK_ANSI_U, 'u' }, 102 { VKEY_V /* 0x56 */, kVK_ANSI_V, 'v' }, 103 { VKEY_W /* 0x57 */, kVK_ANSI_W, 'w' }, 104 { VKEY_X /* 0x58 */, kVK_ANSI_X, 'x' }, 105 { VKEY_Y /* 0x59 */, kVK_ANSI_Y, 'y' }, 106 { VKEY_Z /* 0x5A */, kVK_ANSI_Z, 'z' }, 107 { VKEY_LWIN /* 0x5B */, kVK_Command, 0 }, 108 { VKEY_RWIN /* 0x5C */, 0x36, 0 }, 109 { VKEY_APPS /* 0x5D */, 0x36, 0 }, 110 { VKEY_SLEEP /* 0x5F */, -1, 0 }, 111 { VKEY_NUMPAD0 /* 0x60 */, kVK_ANSI_Keypad0, '0' }, 112 { VKEY_NUMPAD1 /* 0x61 */, kVK_ANSI_Keypad1, '1' }, 113 { VKEY_NUMPAD2 /* 0x62 */, kVK_ANSI_Keypad2, '2' }, 114 { VKEY_NUMPAD3 /* 0x63 */, kVK_ANSI_Keypad3, '3' }, 115 { VKEY_NUMPAD4 /* 0x64 */, kVK_ANSI_Keypad4, '4' }, 116 { VKEY_NUMPAD5 /* 0x65 */, kVK_ANSI_Keypad5, '5' }, 117 { VKEY_NUMPAD6 /* 0x66 */, kVK_ANSI_Keypad6, '6' }, 118 { VKEY_NUMPAD7 /* 0x67 */, kVK_ANSI_Keypad7, '7' }, 119 { VKEY_NUMPAD8 /* 0x68 */, kVK_ANSI_Keypad8, '8' }, 120 { VKEY_NUMPAD9 /* 0x69 */, kVK_ANSI_Keypad9, '9' }, 121 { VKEY_MULTIPLY /* 0x6A */, kVK_ANSI_KeypadMultiply, '*' }, 122 { VKEY_ADD /* 0x6B */, kVK_ANSI_KeypadPlus, '+' }, 123 { VKEY_SEPARATOR /* 0x6C */, -1, 0 }, 124 { VKEY_SUBTRACT /* 0x6D */, kVK_ANSI_KeypadMinus, '-' }, 125 { VKEY_DECIMAL /* 0x6E */, kVK_ANSI_KeypadDecimal, '.' }, 126 { VKEY_DIVIDE /* 0x6F */, kVK_ANSI_KeypadDivide, '/' }, 127 { VKEY_F1 /* 0x70 */, kVK_F1, NSF1FunctionKey }, 128 { VKEY_F2 /* 0x71 */, kVK_F2, NSF2FunctionKey }, 129 { VKEY_F3 /* 0x72 */, kVK_F3, NSF3FunctionKey }, 130 { VKEY_F4 /* 0x73 */, kVK_F4, NSF4FunctionKey }, 131 { VKEY_F5 /* 0x74 */, kVK_F5, NSF5FunctionKey }, 132 { VKEY_F6 /* 0x75 */, kVK_F6, NSF6FunctionKey }, 133 { VKEY_F7 /* 0x76 */, kVK_F7, NSF7FunctionKey }, 134 { VKEY_F8 /* 0x77 */, kVK_F8, NSF8FunctionKey }, 135 { VKEY_F9 /* 0x78 */, kVK_F9, NSF9FunctionKey }, 136 { VKEY_F10 /* 0x79 */, kVK_F10, NSF10FunctionKey }, 137 { VKEY_F11 /* 0x7A */, kVK_F11, NSF11FunctionKey }, 138 { VKEY_F12 /* 0x7B */, kVK_F12, NSF12FunctionKey }, 139 { VKEY_F13 /* 0x7C */, kVK_F13, NSF13FunctionKey }, 140 { VKEY_F14 /* 0x7D */, kVK_F14, NSF14FunctionKey }, 141 { VKEY_F15 /* 0x7E */, kVK_F15, NSF15FunctionKey }, 142 { VKEY_F16 /* 0x7F */, kVK_F16, NSF16FunctionKey }, 143 { VKEY_F17 /* 0x80 */, kVK_F17, NSF17FunctionKey }, 144 { VKEY_F18 /* 0x81 */, kVK_F18, NSF18FunctionKey }, 145 { VKEY_F19 /* 0x82 */, kVK_F19, NSF19FunctionKey }, 146 { VKEY_F20 /* 0x83 */, kVK_F20, NSF20FunctionKey }, 147 { VKEY_F21 /* 0x84 */, -1, NSF21FunctionKey }, 148 { VKEY_F22 /* 0x85 */, -1, NSF22FunctionKey }, 149 { VKEY_F23 /* 0x86 */, -1, NSF23FunctionKey }, 150 { VKEY_F24 /* 0x87 */, -1, NSF24FunctionKey }, 151 { VKEY_NUMLOCK /* 0x90 */, -1, 0 }, 152 { VKEY_SCROLL /* 0x91 */, -1, NSScrollLockFunctionKey }, 153 { VKEY_LSHIFT /* 0xA0 */, kVK_Shift, 0 }, 154 { VKEY_RSHIFT /* 0xA1 */, kVK_Shift, 0 }, 155 { VKEY_LCONTROL /* 0xA2 */, kVK_Control, 0 }, 156 { VKEY_RCONTROL /* 0xA3 */, kVK_Control, 0 }, 157 { VKEY_LMENU /* 0xA4 */, -1, 0 }, 158 { VKEY_RMENU /* 0xA5 */, -1, 0 }, 159 { VKEY_BROWSER_BACK /* 0xA6 */, -1, 0 }, 160 { VKEY_BROWSER_FORWARD /* 0xA7 */, -1, 0 }, 161 { VKEY_BROWSER_REFRESH /* 0xA8 */, -1, 0 }, 162 { VKEY_BROWSER_STOP /* 0xA9 */, -1, 0 }, 163 { VKEY_BROWSER_SEARCH /* 0xAA */, -1, 0 }, 164 { VKEY_BROWSER_FAVORITES /* 0xAB */, -1, 0 }, 165 { VKEY_BROWSER_HOME /* 0xAC */, -1, 0 }, 166 { VKEY_VOLUME_MUTE /* 0xAD */, -1, 0 }, 167 { VKEY_VOLUME_DOWN /* 0xAE */, -1, 0 }, 168 { VKEY_VOLUME_UP /* 0xAF */, -1, 0 }, 169 { VKEY_MEDIA_NEXT_TRACK /* 0xB0 */, -1, 0 }, 170 { VKEY_MEDIA_PREV_TRACK /* 0xB1 */, -1, 0 }, 171 { VKEY_MEDIA_STOP /* 0xB2 */, -1, 0 }, 172 { VKEY_MEDIA_PLAY_PAUSE /* 0xB3 */, -1, 0 }, 173 { VKEY_MEDIA_LAUNCH_MAIL /* 0xB4 */, -1, 0 }, 174 { VKEY_MEDIA_LAUNCH_MEDIA_SELECT /* 0xB5 */, -1, 0 }, 175 { VKEY_MEDIA_LAUNCH_APP1 /* 0xB6 */, -1, 0 }, 176 { VKEY_MEDIA_LAUNCH_APP2 /* 0xB7 */, -1, 0 }, 177 { VKEY_OEM_1 /* 0xBA */, kVK_ANSI_Semicolon, ';' }, 178 { VKEY_OEM_PLUS /* 0xBB */, kVK_ANSI_Equal, '=' }, 179 { VKEY_OEM_COMMA /* 0xBC */, kVK_ANSI_Comma, ',' }, 180 { VKEY_OEM_MINUS /* 0xBD */, kVK_ANSI_Minus, '-' }, 181 { VKEY_OEM_PERIOD /* 0xBE */, kVK_ANSI_Period, '.' }, 182 { VKEY_OEM_2 /* 0xBF */, kVK_ANSI_Slash, '/' }, 183 { VKEY_OEM_3 /* 0xC0 */, kVK_ANSI_Grave, '`' }, 184 { VKEY_OEM_4 /* 0xDB */, kVK_ANSI_LeftBracket, '[' }, 185 { VKEY_OEM_5 /* 0xDC */, kVK_ANSI_Backslash, '\\' }, 186 { VKEY_OEM_6 /* 0xDD */, kVK_ANSI_RightBracket, ']' }, 187 { VKEY_OEM_7 /* 0xDE */, kVK_ANSI_Quote, '\'' }, 188 { VKEY_OEM_8 /* 0xDF */, -1, 0 }, 189 { VKEY_OEM_102 /* 0xE2 */, -1, 0 }, 190 { VKEY_PROCESSKEY /* 0xE5 */, -1, 0 }, 191 { VKEY_PACKET /* 0xE7 */, -1, 0 }, 192 { VKEY_ATTN /* 0xF6 */, -1, 0 }, 193 { VKEY_CRSEL /* 0xF7 */, -1, 0 }, 194 { VKEY_EXSEL /* 0xF8 */, -1, 0 }, 195 { VKEY_EREOF /* 0xF9 */, -1, 0 }, 196 { VKEY_PLAY /* 0xFA */, -1, 0 }, 197 { VKEY_ZOOM /* 0xFB */, -1, 0 }, 198 { VKEY_NONAME /* 0xFC */, -1, 0 }, 199 { VKEY_PA1 /* 0xFD */, -1, 0 }, 200 { VKEY_OEM_CLEAR /* 0xFE */, kVK_ANSI_KeypadClear, kClearCharCode } 201 }; 202 203 // A convenient array for getting symbol characters on the number keys. 204 const char kShiftCharsForNumberKeys[] = ")!@#$%^&*("; 205 206 // Translates from character code to keyboard code. 207 KeyboardCode KeyboardCodeFromCharCode(unichar charCode) { 208 switch (charCode) { 209 case 8: case 0x7F: return VKEY_BACK; 210 case 9: return VKEY_TAB; 211 case 0xD: case 3: return VKEY_RETURN; 212 case 0x1B: return VKEY_ESCAPE; 213 case ' ': return VKEY_SPACE; 214 case NSHomeFunctionKey: return VKEY_HOME; 215 case NSEndFunctionKey: return VKEY_END; 216 case NSPageUpFunctionKey: return VKEY_PRIOR; 217 case NSPageDownFunctionKey: return VKEY_NEXT; 218 case NSUpArrowFunctionKey: return VKEY_UP; 219 case NSDownArrowFunctionKey: return VKEY_DOWN; 220 case NSLeftArrowFunctionKey: return VKEY_LEFT; 221 case NSRightArrowFunctionKey: return VKEY_RIGHT; 222 case NSDeleteFunctionKey: return VKEY_DELETE; 223 224 case '0': case ')': return VKEY_0; 225 case '1': case '!': return VKEY_1; 226 case '2': case '@': return VKEY_2; 227 case '3': case '#': return VKEY_3; 228 case '4': case '$': return VKEY_4; 229 case '5': case '%': return VKEY_5; 230 case '6': case '^': return VKEY_6; 231 case '7': case '&': return VKEY_7; 232 case '8': case '*': return VKEY_8; 233 case '9': case '(': return VKEY_9; 234 235 case 'a': case 'A': return VKEY_A; 236 case 'b': case 'B': return VKEY_B; 237 case 'c': case 'C': return VKEY_C; 238 case 'd': case 'D': return VKEY_D; 239 case 'e': case 'E': return VKEY_E; 240 case 'f': case 'F': return VKEY_F; 241 case 'g': case 'G': return VKEY_G; 242 case 'h': case 'H': return VKEY_H; 243 case 'i': case 'I': return VKEY_I; 244 case 'j': case 'J': return VKEY_J; 245 case 'k': case 'K': return VKEY_K; 246 case 'l': case 'L': return VKEY_L; 247 case 'm': case 'M': return VKEY_M; 248 case 'n': case 'N': return VKEY_N; 249 case 'o': case 'O': return VKEY_O; 250 case 'p': case 'P': return VKEY_P; 251 case 'q': case 'Q': return VKEY_Q; 252 case 'r': case 'R': return VKEY_R; 253 case 's': case 'S': return VKEY_S; 254 case 't': case 'T': return VKEY_T; 255 case 'u': case 'U': return VKEY_U; 256 case 'v': case 'V': return VKEY_V; 257 case 'w': case 'W': return VKEY_W; 258 case 'x': case 'X': return VKEY_X; 259 case 'y': case 'Y': return VKEY_Y; 260 case 'z': case 'Z': return VKEY_Z; 261 262 case NSPauseFunctionKey: return VKEY_PAUSE; 263 case NSSelectFunctionKey: return VKEY_SELECT; 264 case NSPrintFunctionKey: return VKEY_PRINT; 265 case NSExecuteFunctionKey: return VKEY_EXECUTE; 266 case NSPrintScreenFunctionKey: return VKEY_SNAPSHOT; 267 case NSInsertFunctionKey: return VKEY_INSERT; 268 case NSHelpFunctionKey: return VKEY_INSERT; 269 270 case NSF1FunctionKey: return VKEY_F1; 271 case NSF2FunctionKey: return VKEY_F2; 272 case NSF3FunctionKey: return VKEY_F3; 273 case NSF4FunctionKey: return VKEY_F4; 274 case NSF5FunctionKey: return VKEY_F5; 275 case NSF6FunctionKey: return VKEY_F6; 276 case NSF7FunctionKey: return VKEY_F7; 277 case NSF8FunctionKey: return VKEY_F8; 278 case NSF9FunctionKey: return VKEY_F9; 279 case NSF10FunctionKey: return VKEY_F10; 280 case NSF11FunctionKey: return VKEY_F11; 281 case NSF12FunctionKey: return VKEY_F12; 282 case NSF13FunctionKey: return VKEY_F13; 283 case NSF14FunctionKey: return VKEY_F14; 284 case NSF15FunctionKey: return VKEY_F15; 285 case NSF16FunctionKey: return VKEY_F16; 286 case NSF17FunctionKey: return VKEY_F17; 287 case NSF18FunctionKey: return VKEY_F18; 288 case NSF19FunctionKey: return VKEY_F19; 289 case NSF20FunctionKey: return VKEY_F20; 290 291 case NSF21FunctionKey: return VKEY_F21; 292 case NSF22FunctionKey: return VKEY_F22; 293 case NSF23FunctionKey: return VKEY_F23; 294 case NSF24FunctionKey: return VKEY_F24; 295 case NSScrollLockFunctionKey: return VKEY_SCROLL; 296 297 // U.S. Specific mappings. Mileage may vary. 298 case ';': case ':': return VKEY_OEM_1; 299 case '=': case '+': return VKEY_OEM_PLUS; 300 case ',': case '<': return VKEY_OEM_COMMA; 301 case '-': case '_': return VKEY_OEM_MINUS; 302 case '.': case '>': return VKEY_OEM_PERIOD; 303 case '/': case '?': return VKEY_OEM_2; 304 case '`': case '~': return VKEY_OEM_3; 305 case '[': case '{': return VKEY_OEM_4; 306 case '\\': case '|': return VKEY_OEM_5; 307 case ']': case '}': return VKEY_OEM_6; 308 case '\'': case '"': return VKEY_OEM_7; 309 } 310 311 return VKEY_UNKNOWN; 312 } 313 314 KeyboardCode KeyboardCodeFromKeyCode(unsigned short keyCode) { 315 static const KeyboardCode kKeyboardCodes[] = { 316 /* 0 */ VKEY_A, 317 /* 1 */ VKEY_S, 318 /* 2 */ VKEY_D, 319 /* 3 */ VKEY_F, 320 /* 4 */ VKEY_H, 321 /* 5 */ VKEY_G, 322 /* 6 */ VKEY_Z, 323 /* 7 */ VKEY_X, 324 /* 8 */ VKEY_C, 325 /* 9 */ VKEY_V, 326 /* 0x0A */ VKEY_OEM_3, // Section key. 327 /* 0x0B */ VKEY_B, 328 /* 0x0C */ VKEY_Q, 329 /* 0x0D */ VKEY_W, 330 /* 0x0E */ VKEY_E, 331 /* 0x0F */ VKEY_R, 332 /* 0x10 */ VKEY_Y, 333 /* 0x11 */ VKEY_T, 334 /* 0x12 */ VKEY_1, 335 /* 0x13 */ VKEY_2, 336 /* 0x14 */ VKEY_3, 337 /* 0x15 */ VKEY_4, 338 /* 0x16 */ VKEY_6, 339 /* 0x17 */ VKEY_5, 340 /* 0x18 */ VKEY_OEM_PLUS, // =+ 341 /* 0x19 */ VKEY_9, 342 /* 0x1A */ VKEY_7, 343 /* 0x1B */ VKEY_OEM_MINUS, // -_ 344 /* 0x1C */ VKEY_8, 345 /* 0x1D */ VKEY_0, 346 /* 0x1E */ VKEY_OEM_6, // ]} 347 /* 0x1F */ VKEY_O, 348 /* 0x20 */ VKEY_U, 349 /* 0x21 */ VKEY_OEM_4, // {[ 350 /* 0x22 */ VKEY_I, 351 /* 0x23 */ VKEY_P, 352 /* 0x24 */ VKEY_RETURN, // Return 353 /* 0x25 */ VKEY_L, 354 /* 0x26 */ VKEY_J, 355 /* 0x27 */ VKEY_OEM_7, // '" 356 /* 0x28 */ VKEY_K, 357 /* 0x29 */ VKEY_OEM_1, // ;: 358 /* 0x2A */ VKEY_OEM_5, // \| 359 /* 0x2B */ VKEY_OEM_COMMA, // ,< 360 /* 0x2C */ VKEY_OEM_2, // /? 361 /* 0x2D */ VKEY_N, 362 /* 0x2E */ VKEY_M, 363 /* 0x2F */ VKEY_OEM_PERIOD, // .> 364 /* 0x30 */ VKEY_TAB, 365 /* 0x31 */ VKEY_SPACE, 366 /* 0x32 */ VKEY_OEM_3, // `~ 367 /* 0x33 */ VKEY_BACK, // Backspace 368 /* 0x34 */ VKEY_UNKNOWN, // n/a 369 /* 0x35 */ VKEY_ESCAPE, 370 /* 0x36 */ VKEY_APPS, // Right Command 371 /* 0x37 */ VKEY_LWIN, // Left Command 372 /* 0x38 */ VKEY_SHIFT, // Left Shift 373 /* 0x39 */ VKEY_CAPITAL, // Caps Lock 374 /* 0x3A */ VKEY_MENU, // Left Option 375 /* 0x3B */ VKEY_CONTROL, // Left Ctrl 376 /* 0x3C */ VKEY_SHIFT, // Right Shift 377 /* 0x3D */ VKEY_MENU, // Right Option 378 /* 0x3E */ VKEY_CONTROL, // Right Ctrl 379 /* 0x3F */ VKEY_UNKNOWN, // fn 380 /* 0x40 */ VKEY_F17, 381 /* 0x41 */ VKEY_DECIMAL, // Num Pad . 382 /* 0x42 */ VKEY_UNKNOWN, // n/a 383 /* 0x43 */ VKEY_MULTIPLY, // Num Pad * 384 /* 0x44 */ VKEY_UNKNOWN, // n/a 385 /* 0x45 */ VKEY_ADD, // Num Pad + 386 /* 0x46 */ VKEY_UNKNOWN, // n/a 387 /* 0x47 */ VKEY_CLEAR, // Num Pad Clear 388 /* 0x48 */ VKEY_VOLUME_UP, 389 /* 0x49 */ VKEY_VOLUME_DOWN, 390 /* 0x4A */ VKEY_VOLUME_MUTE, 391 /* 0x4B */ VKEY_DIVIDE, // Num Pad / 392 /* 0x4C */ VKEY_RETURN, // Num Pad Enter 393 /* 0x4D */ VKEY_UNKNOWN, // n/a 394 /* 0x4E */ VKEY_SUBTRACT, // Num Pad - 395 /* 0x4F */ VKEY_F18, 396 /* 0x50 */ VKEY_F19, 397 /* 0x51 */ VKEY_OEM_PLUS, // Num Pad =. 398 /* 0x52 */ VKEY_NUMPAD0, 399 /* 0x53 */ VKEY_NUMPAD1, 400 /* 0x54 */ VKEY_NUMPAD2, 401 /* 0x55 */ VKEY_NUMPAD3, 402 /* 0x56 */ VKEY_NUMPAD4, 403 /* 0x57 */ VKEY_NUMPAD5, 404 /* 0x58 */ VKEY_NUMPAD6, 405 /* 0x59 */ VKEY_NUMPAD7, 406 /* 0x5A */ VKEY_F20, 407 /* 0x5B */ VKEY_NUMPAD8, 408 /* 0x5C */ VKEY_NUMPAD9, 409 /* 0x5D */ VKEY_UNKNOWN, // Yen (JIS Keyboard Only) 410 /* 0x5E */ VKEY_UNKNOWN, // Underscore (JIS Keyboard Only) 411 /* 0x5F */ VKEY_UNKNOWN, // KeypadComma (JIS Keyboard Only) 412 /* 0x60 */ VKEY_F5, 413 /* 0x61 */ VKEY_F6, 414 /* 0x62 */ VKEY_F7, 415 /* 0x63 */ VKEY_F3, 416 /* 0x64 */ VKEY_F8, 417 /* 0x65 */ VKEY_F9, 418 /* 0x66 */ VKEY_UNKNOWN, // Eisu (JIS Keyboard Only) 419 /* 0x67 */ VKEY_F11, 420 /* 0x68 */ VKEY_UNKNOWN, // Kana (JIS Keyboard Only) 421 /* 0x69 */ VKEY_F13, 422 /* 0x6A */ VKEY_F16, 423 /* 0x6B */ VKEY_F14, 424 /* 0x6C */ VKEY_UNKNOWN, // n/a 425 /* 0x6D */ VKEY_F10, 426 /* 0x6E */ VKEY_UNKNOWN, // n/a (Windows95 key?) 427 /* 0x6F */ VKEY_F12, 428 /* 0x70 */ VKEY_UNKNOWN, // n/a 429 /* 0x71 */ VKEY_F15, 430 /* 0x72 */ VKEY_INSERT, // Help 431 /* 0x73 */ VKEY_HOME, // Home 432 /* 0x74 */ VKEY_PRIOR, // Page Up 433 /* 0x75 */ VKEY_DELETE, // Forward Delete 434 /* 0x76 */ VKEY_F4, 435 /* 0x77 */ VKEY_END, // End 436 /* 0x78 */ VKEY_F2, 437 /* 0x79 */ VKEY_NEXT, // Page Down 438 /* 0x7A */ VKEY_F1, 439 /* 0x7B */ VKEY_LEFT, // Left Arrow 440 /* 0x7C */ VKEY_RIGHT, // Right Arrow 441 /* 0x7D */ VKEY_DOWN, // Down Arrow 442 /* 0x7E */ VKEY_UP, // Up Arrow 443 /* 0x7F */ VKEY_UNKNOWN // n/a 444 }; 445 446 if (keyCode >= 0x80) 447 return VKEY_UNKNOWN; 448 449 return kKeyboardCodes[keyCode]; 450 } 451 452 } // namespace 453 454 int MacKeyCodeForWindowsKeyCode(KeyboardCode keycode, 455 NSUInteger flags, 456 unichar* character, 457 unichar* characterIgnoringModifiers) { 458 KeyCodeMap from; 459 from.keycode = keycode; 460 461 const KeyCodeMap* ptr = std::lower_bound( 462 kKeyCodesMap, kKeyCodesMap + arraysize(kKeyCodesMap), from); 463 464 if (ptr >= kKeyCodesMap + arraysize(kKeyCodesMap) || 465 ptr->keycode != keycode || ptr->macKeycode == -1) 466 return -1; 467 468 int macKeycode = ptr->macKeycode; 469 if (characterIgnoringModifiers) 470 *characterIgnoringModifiers = ptr->characterIgnoringModifiers; 471 472 if (!character) 473 return macKeycode; 474 475 *character = ptr->characterIgnoringModifiers; 476 477 // Fill in |character| according to flags. 478 if (flags & NSShiftKeyMask) { 479 if (keycode >= VKEY_0 && keycode <= VKEY_9) { 480 *character = kShiftCharsForNumberKeys[keycode - VKEY_0]; 481 } else if (keycode >= VKEY_A && keycode <= VKEY_Z) { 482 *character = 'A' + (keycode - VKEY_A); 483 } else { 484 switch (macKeycode) { 485 case kVK_ANSI_Grave: 486 *character = '~'; 487 break; 488 case kVK_ANSI_Minus: 489 *character = '_'; 490 break; 491 case kVK_ANSI_Equal: 492 *character = '+'; 493 break; 494 case kVK_ANSI_LeftBracket: 495 *character = '{'; 496 break; 497 case kVK_ANSI_RightBracket: 498 *character = '}'; 499 break; 500 case kVK_ANSI_Backslash: 501 *character = '|'; 502 break; 503 case kVK_ANSI_Semicolon: 504 *character = ':'; 505 break; 506 case kVK_ANSI_Quote: 507 *character = '\"'; 508 break; 509 case kVK_ANSI_Comma: 510 *character = '<'; 511 break; 512 case kVK_ANSI_Period: 513 *character = '>'; 514 break; 515 case kVK_ANSI_Slash: 516 *character = '?'; 517 break; 518 default: 519 break; 520 } 521 } 522 } 523 524 // Control characters. 525 if (flags & NSControlKeyMask) { 526 if (keycode >= VKEY_A && keycode <= VKEY_Z) 527 *character = 1 + keycode - VKEY_A; 528 else if (macKeycode == kVK_ANSI_LeftBracket) 529 *character = 27; 530 else if (macKeycode == kVK_ANSI_Backslash) 531 *character = 28; 532 else if (macKeycode == kVK_ANSI_RightBracket) 533 *character = 29; 534 } 535 536 // TODO(suzhe): Support characters for Option key bindings. 537 return macKeycode; 538 } 539 540 KeyboardCode KeyboardCodeFromNSEvent(NSEvent* event) { 541 KeyboardCode code = VKEY_UNKNOWN; 542 543 if ([event type] == NSKeyDown || [event type] == NSKeyUp) { 544 NSString* characters = [event characters]; 545 if ([characters length] > 0) 546 code = KeyboardCodeFromCharCode([characters characterAtIndex:0]); 547 if (code) 548 return code; 549 550 characters = [event charactersIgnoringModifiers]; 551 if ([characters length] > 0) 552 code = KeyboardCodeFromCharCode([characters characterAtIndex:0]); 553 if (code) 554 return code; 555 } 556 return KeyboardCodeFromKeyCode([event keyCode]); 557 } 558 559 const char* CodeFromNSEvent(NSEvent* event) { 560 return KeycodeConverter::GetInstance()->NativeKeycodeToCode( 561 [event keyCode]); 562 } 563 564 } // namespace ui 565