/* * synergy -- mouse and keyboard sharing utility * Copyright (C) 2004 Chris Schoeneman * * This package is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * found in the file COPYING that should have accompanied this file. * * This package is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #include "COSXKeyState.h" #include "CLog.h" struct CKeyEntry { public: KeyID m_keyID; KeyButton m_button; }; static const CKeyEntry s_keys[] = { /* ASCII */ { ' ', 49 }, { '!', 18 }, { '\"', 39 }, { '#', 20 }, { '$', 21 }, { '%', 23 }, { '&', 26 }, { '\'', 39 }, { '(', 25 }, { ')', 29 }, { '*', 28 }, { '+', 24 }, { ',', 43 }, { '-', 27 }, { '.', 47 }, { '/', 44 }, { '0', 29 }, { '1', 18 }, { '2', 19 }, { '3', 20 }, { '4', 21 }, { '5', 23 }, { '6', 22 }, { '7', 26 }, { '8', 28 }, { '9', 25 }, { ':', 41 }, { ';', 41 }, { '<', 43 }, { '=', 24 }, { '>', 47 }, { '?', 44 }, { '@', 19 }, { 'A', 0 }, { 'B', 11 }, { 'C', 8 }, { 'D', 2 }, { 'E', 14 }, { 'F', 3 }, { 'G', 5 }, { 'H', 4 }, { 'I', 34 }, { 'J', 38 }, { 'K', 40 }, { 'L', 37 }, { 'M', 46 }, { 'N', 45 }, { 'O', 31 }, { 'P', 35 }, { 'Q', 12 }, { 'R', 15 }, { 'S', 1 }, { 'T', 17 }, { 'U', 32 }, { 'V', 9 }, { 'W', 13 }, { 'X', 7 }, { 'Y', 16 }, { 'Z', 6 }, { '[', 33 }, { '\\', 42 }, { ']', 30 }, { '^', 22 }, { '_', 27 }, { '`', 50 }, { 'a', 0 }, { 'b', 11 }, { 'c', 8 }, { 'd', 2 }, { 'e', 14 }, { 'f', 3 }, { 'g', 5 }, { 'h', 4 }, { 'i', 34 }, { 'j', 38 }, { 'k', 40 }, { 'l', 37 }, { 'm', 46 }, { 'n', 45 }, { 'o', 31 }, { 'p', 35 }, { 'q', 12 }, { 'r', 15 }, { 's', 1 }, { 't', 17 }, { 'u', 32 }, { 'v', 9 }, { 'w', 13 }, { 'x', 7 }, { 'y', 16 }, { 'z', 6 }, { '{', 33 }, { '|', 42 }, { '}', 30 }, { '~', 50 }, /* TTY functions */ { kKeyBackSpace, 51 }, { kKeyTab, 48 }, { kKeyLinefeed, 36 }, // { kKeyClear, 0xFFFF }, { kKeyReturn, 36 }, { kKeyPause, 113 }, { kKeyScrollLock, 107 }, // { kKeySysReq, 0xFFFF }, /* no mapping on apple */ { kKeyEscape, 53 }, { kKeyDelete, 117 }, /* cursor control */ { kKeyHome, 115 }, { kKeyLeft, 123 }, { kKeyUp, 126 }, { kKeyRight, 124 }, { kKeyDown, 125 }, { kKeyPageUp, 116 }, { kKeyPageDown, 121 }, { kKeyEnd, 119 }, { kKeyBegin, 115 }, /* numeric keypad */ { kKeyKP_Space, 49 }, { kKeyKP_0, 82 }, { kKeyKP_1, 83 }, { kKeyKP_2, 84 }, { kKeyKP_3, 85 }, { kKeyKP_4, 86 }, { kKeyKP_5, 87 }, { kKeyKP_6, 88 }, { kKeyKP_7, 89 }, { kKeyKP_8, 91 }, { kKeyKP_9, 92 }, { kKeyKP_Enter, 76 }, { kKeyKP_Decimal, 65 }, { kKeyKP_Add, 69 }, { kKeyKP_Subtract, 78 }, { kKeyKP_Multiply, 67 }, { kKeyKP_Divide, 75 }, /* Function keys */ { kKeyF1, 122 }, { kKeyF2, 120 }, { kKeyF3, 99 }, { kKeyF4, 118 }, { kKeyF5, 96 }, { kKeyF6, 97 }, { kKeyF7, 98 }, { kKeyF8, 100 }, { kKeyF9, 101 }, { kKeyF10, 109 }, { kKeyF11, 103 }, { kKeyF12, 111 }, /* Modifier keys */ { kKeyShift_L, 56 }, { kKeyShift_R, 56 }, { kKeyControl_L, 59 }, { kKeyControl_R, 59 }, { kKeyAlt_L, 55 }, { kKeyAlt_R, 55 }, { kKeyCapsLock, 57 }, { kKeyNumLock, 71 }, { kKeyMeta_L, 58 }, { kKeyMeta_R, 58 }, { kKeySuper_L, 58 }, { kKeySuper_R, 58 }, { kKeyLeftTab, 48 } }; const KeyID COSXKeyState::s_virtualKey[] = { /* 0x00 */ kKeyNone, // A /* 0x01 */ kKeyNone, // S /* 0x02 */ kKeyNone, // D /* 0x03 */ kKeyNone, // F /* 0x04 */ kKeyNone, // H /* 0x05 */ kKeyNone, // G /* 0x06 */ kKeyNone, // Z /* 0x07 */ kKeyNone, // X /* 0x08 */ kKeyNone, // C /* 0x09 */ kKeyNone, // V /* 0x0a */ kKeyNone, // ~ on some european keyboards /* 0x0b */ kKeyNone, // B /* 0x0c */ kKeyNone, // Q /* 0x0d */ kKeyNone, // W /* 0x0e */ kKeyNone, // E /* 0x0f */ kKeyNone, // R /* 0x10 */ kKeyNone, // Y /* 0x11 */ kKeyNone, // T /* 0x12 */ kKeyNone, // 1 /* 0x13 */ kKeyNone, // 2 /* 0x14 */ kKeyNone, // 3 /* 0x15 */ kKeyNone, // 4 /* 0x16 */ kKeyNone, // 6 /* 0x17 */ kKeyNone, // 5 /* 0x18 */ kKeyNone, // = /* 0x19 */ kKeyNone, // 9 /* 0x1a */ kKeyNone, // 7 /* 0x1b */ kKeyNone, // - /* 0x1c */ kKeyNone, // 8 /* 0x1d */ kKeyNone, // 0 /* 0x1e */ kKeyNone, // ] /* 0x1f */ kKeyNone, // O /* 0x20 */ kKeyNone, // U /* 0x21 */ kKeyNone, // [ /* 0x22 */ kKeyNone, // I /* 0x23 */ kKeyNone, // P /* 0x24 */ kKeyReturn, // return /* 0x25 */ kKeyNone, // L /* 0x26 */ kKeyNone, // J /* 0x27 */ kKeyNone, // ' /* 0x28 */ kKeyNone, // K /* 0x29 */ kKeyNone, // ; /* 0x2a */ kKeyNone, /* \ */ /* 0x2b */ kKeyNone, // , /* 0x2c */ kKeyNone, // / /* 0x2d */ kKeyNone, // M /* 0x2e */ kKeyNone, // M /* 0x2f */ kKeyNone, // . /* 0x30 */ kKeyTab, // tab /* 0x31 */ kKeyKP_Space, // space /* 0x32 */ kKeyNone, // ` /* 0x33 */ kKeyBackSpace, // Backspace /* 0x34 */ kKeyNone, // undefined /* 0x35 */ kKeyEscape, // escape /* 0x36 */ kKeyNone, // undefined /* 0x37 */ kKeyAlt_L, // alt /* 0x38 */ kKeyShift_L, // shift /* 0x39 */ kKeyCapsLock, // capslok /* 0x3a */ kKeyMeta_L, // meta /* 0x3b */ kKeyControl_L, // control /* 0x3c */ kKeyNone, // undefined /* 0x3d */ kKeyNone, // undefined /* 0x3e */ kKeyNone, // undefined /* 0x3f */ kKeyNone, // undefined /* 0x40 */ kKeyNone, // undefined /* 0x41 */ kKeyKP_Decimal, // keypad . /* 0x42 */ kKeyNone, // undefined /* 0x43 */ kKeyKP_Multiply, // keypad * /* 0x44 */ kKeyNone, // undefined /* 0x45 */ kKeyKP_Add, // keypad + /* 0x46 */ kKeyNone, // undefined /* 0x47 */ kKeyNumLock, // numlock /* 0x48 */ kKeyNone, // undefined /* 0x49 */ kKeyNone, // undefined /* 0x4a */ kKeyNone, // undefined /* 0x4b */ kKeyKP_Divide, /* keypad \ */ /* 0x4c */ kKeyKP_Enter, // keypad enter /* 0x4d */ kKeyNone, // undefined /* 0x4e */ kKeyKP_Subtract, // keypad - /* 0x4f */ kKeyNone, // undefined /* 0x50 */ kKeyNone, // undefined /* 0x51 */ kKeyNone, // undefined /* 0x52 */ kKeyKP_0, // keypad 0 /* 0x53 */ kKeyKP_1, // keypad 1 /* 0x54 */ kKeyKP_2, // keypad 2 /* 0x55 */ kKeyKP_3, // keypad 3 /* 0x56 */ kKeyKP_4, // keypad 4 /* 0x57 */ kKeyKP_5, // keypad 5 /* 0x58 */ kKeyKP_6, // keypad 6 /* 0x59 */ kKeyKP_7, // keypad 7 /* 0x5a */ kKeyKP_8, // keypad 8 /* 0x5b */ kKeyKP_9, // keypad 9 /* 0x5c */ kKeyNone, // undefined /* 0x5d */ kKeyNone, // undefined /* 0x5e */ kKeyNone, // undefined /* 0x5f */ kKeyNone, // undefined /* 0x60 */ kKeyF5, // F5 /* 0x61 */ kKeyF6, // F6 /* 0x62 */ kKeyF7, // F7 /* 0x63 */ kKeyF3, // F3 /* 0x64 */ kKeyF8, // F8 /* 0x65 */ kKeyF9, // F9 /* 0x66 */ kKeyNone, // undefined /* 0x67 */ kKeyF11, // F11 /* 0x68 */ kKeyNone, // undefined /* 0x69 */ kKeyNone, // undefined /* 0x6a */ kKeyNone, // undefined /* 0x6b */ kKeyF10, // F10 /* 0x6c */ kKeyNone, // undefined /* 0x6d */ kKeyF12, // F12 /* 0x6e */ kKeyNone, // undefined /* 0x6f */ kKeyPause, // pause /* 0x70 */ kKeyNone, // undefined /* 0x71 */ kKeyBegin, // home /* 0x72 */ kKeyPageUp, // PageUP /* 0x73 */ kKeyDelete, // Delete /* 0x74 */ kKeyF4, // F4 /* 0x75 */ kKeyEnd, // end /* 0x76 */ kKeyF2, // F2 /* 0x77 */ kKeyNone, // undefined /* 0x78 */ kKeyF1, // F1 /* 0x79 */ kKeyPageDown, // PageDown /* 0x7a */ kKeyNone, // undefined /* 0x7b */ kKeyLeft, // left /* 0x7c */ kKeyRight, // right /* 0x7d */ kKeyDown, // down /* 0x7e */ kKeyUp, // up /* 0x7f */ kKeyNone, // unassigned /* 0x80 */ kKeyNone, // unassigned /* 0x81 */ kKeyNone, // unassigned /* 0x82 */ kKeyNone, // unassigned /* 0x83 */ kKeyNone, // unassigned /* 0x84 */ kKeyNone, // unassigned /* 0x85 */ kKeyNone, // unassigned /* 0x86 */ kKeyNone, // unassigned /* 0x87 */ kKeyNone, // unassigned /* 0x88 */ kKeyNone, // unassigned /* 0x89 */ kKeyNone, // unassigned /* 0x8a */ kKeyNone, // unassigned /* 0x8b */ kKeyNone, // unassigned /* 0x8c */ kKeyNone, // unassigned /* 0x8d */ kKeyNone, // unassigned /* 0x8e */ kKeyNone, // unassigned /* 0x8f */ kKeyNone, // unassigned /* 0x90 */ kKeyNone, // unassigned /* 0x91 */ kKeyNone, // unassigned /* 0x92 */ kKeyNone, // unassigned /* 0x93 */ kKeyNone, // unassigned /* 0x94 */ kKeyNone, // unassigned /* 0x95 */ kKeyNone, // unassigned /* 0x96 */ kKeyNone, // unassigned /* 0x97 */ kKeyNone, // unassigned /* 0x98 */ kKeyNone, // unassigned /* 0x99 */ kKeyNone, // unassigned /* 0x9a */ kKeyNone, // unassigned /* 0x9b */ kKeyNone, // unassigned /* 0x9c */ kKeyNone, // unassigned /* 0x9d */ kKeyNone, // unassigned /* 0x9e */ kKeyNone, // unassigned /* 0x9f */ kKeyNone, // unassigned /* 0xa0 */ kKeyNone, // unassigned /* 0xa1 */ kKeyNone, // unassigned /* 0xa2 */ kKeyNone, // unassigned /* 0xa3 */ kKeyNone, // unassigned /* 0xa4 */ kKeyNone, // unassigned /* 0xa5 */ kKeyNone, // unassigned /* 0xa6 */ kKeyNone, // unassigned /* 0xa7 */ kKeyNone, // unassigned /* 0xa8 */ kKeyNone, // unassigned /* 0xa9 */ kKeyNone, // unassigned /* 0xaa */ kKeyNone, // unassigned /* 0xab */ kKeyNone, // unassigned /* 0xac */ kKeyNone, // unassigned /* 0xad */ kKeyNone, // unassigned /* 0xae */ kKeyNone, // unassigned /* 0xaf */ kKeyNone, // unassigned /* 0xb0 */ kKeyNone, // unassigned /* 0xb1 */ kKeyNone, // unassigned /* 0xb2 */ kKeyNone, // unassigned /* 0xb3 */ kKeyNone, // unassigned /* 0xb4 */ kKeyNone, // unassigned /* 0xb5 */ kKeyNone, // unassigned /* 0xb6 */ kKeyNone, // unassigned /* 0xb7 */ kKeyNone, // unassigned /* 0xb8 */ kKeyNone, // unassigned /* 0xb9 */ kKeyNone, // unassigned /* 0xba */ kKeyNone, // unassigned /* 0xbb */ kKeyNone, // unassigned /* 0xbc */ kKeyNone, // unassigned /* 0xbd */ kKeyNone, // unassigned /* 0xbe */ kKeyNone, // unassigned /* 0xbf */ kKeyNone, // unassigned /* 0xc0 */ kKeyNone, // unassigned /* 0xc1 */ kKeyNone, // unassigned /* 0xc2 */ kKeyNone, // unassigned /* 0xc3 */ kKeyNone, // unassigned /* 0xc4 */ kKeyNone, // unassigned /* 0xc5 */ kKeyNone, // unassigned /* 0xc6 */ kKeyNone, // unassigned /* 0xc7 */ kKeyNone, // unassigned /* 0xc8 */ kKeyNone, // unassigned /* 0xc9 */ kKeyNone, // unassigned /* 0xca */ kKeyNone, // unassigned /* 0xcb */ kKeyNone, // unassigned /* 0xcc */ kKeyNone, // unassigned /* 0xcd */ kKeyNone, // unassigned /* 0xce */ kKeyNone, // unassigned /* 0xcf */ kKeyNone, // unassigned /* 0xd0 */ kKeyNone, // unassigned /* 0xd1 */ kKeyNone, // unassigned /* 0xd2 */ kKeyNone, // unassigned /* 0xd3 */ kKeyNone, // unassigned /* 0xd4 */ kKeyNone, // unassigned /* 0xd5 */ kKeyNone, // unassigned /* 0xd6 */ kKeyNone, // unassigned /* 0xd7 */ kKeyNone, // unassigned /* 0xd8 */ kKeyNone, // unassigned /* 0xd9 */ kKeyNone, // unassigned /* 0xda */ kKeyNone, // unassigned /* 0xdb */ kKeyNone, // unassigned /* 0xdc */ kKeyNone, // unassigned /* 0xdd */ kKeyNone, // unassigned /* 0xde */ kKeyNone, // unassigned /* 0xdf */ kKeyNone, // unassigned /* 0xe0 */ kKeyNone, // unassigned /* 0xe1 */ kKeyNone, // unassigned /* 0xe2 */ kKeyNone, // unassigned /* 0xe3 */ kKeyNone, // unassigned /* 0xe4 */ kKeyNone, // unassigned /* 0xe5 */ kKeyNone, // unassigned /* 0xe6 */ kKeyNone, // unassigned /* 0xe7 */ kKeyNone, // unassigned /* 0xe8 */ kKeyNone, // unassigned /* 0xe9 */ kKeyNone, // unassigned /* 0xea */ kKeyNone, // unassigned /* 0xeb */ kKeyNone, // unassigned /* 0xec */ kKeyNone, // unassigned /* 0xed */ kKeyNone, // unassigned /* 0xee */ kKeyNone, // unassigned /* 0xef */ kKeyNone, // unassigned /* 0xf0 */ kKeyNone, // unassigned /* 0xf1 */ kKeyNone, // unassigned /* 0xf2 */ kKeyNone, // unassigned /* 0xf3 */ kKeyNone, // unassigned /* 0xf4 */ kKeyNone, // unassigned /* 0xf5 */ kKeyNone, // unassigned /* 0xf6 */ kKeyNone, // unassigned /* 0xf7 */ kKeyNone, // unassigned /* 0xf8 */ kKeyNone, // unassigned /* 0xf9 */ kKeyNone, // unassigned /* 0xfa */ kKeyNone, // unassigned /* 0xfb */ kKeyNone, // unassigned /* 0xfc */ kKeyNone, // unassigned /* 0xfd */ kKeyNone, // unassigned /* 0xfe */ kKeyNone, // unassigned /* 0xff */ kKeyNone // unassigned }; // // COSXKeyState // COSXKeyState::COSXKeyState() { // do nothing } COSXKeyState::~COSXKeyState() { // do nothing } void COSXKeyState::sendKeyEvent(void* target, bool press, bool isAutoRepeat, KeyID key, KeyModifierMask mask, SInt32 count, KeyButton button) { if (press || isAutoRepeat) { // send key if (press) { CKeyState::sendKeyEvent(target, true, false, key, mask, 1, button); if (count > 0) { --count; } } if (count >= 1) { CKeyState::sendKeyEvent(target, true, true, key, mask, count, button); } } else { // do key up CKeyState::sendKeyEvent(target, false, false, key, mask, 1, button); } } bool COSXKeyState::fakeCtrlAltDel() { // pass keys through unchanged return false; } const char* COSXKeyState::getKeyName(KeyButton) const { // FIXME return ""; } void COSXKeyState::doUpdateKeys() { // FIXME -- get the current keyboard state. call setKeyDown(), // setToggled(), and addModifier() as appropriate. // save key mapping // FIXME -- this probably needs to be more dynamic to support // non-english keyboards. also need to map modifiers needed // for each KeyID. for (UInt32 i = 0; i < sizeof(s_keys) / sizeof(s_keys[0]); ++i) { m_keyMap.insert(std::make_pair(s_keys[i].m_keyID, s_keys[i].m_button + 1)); } } void COSXKeyState::doFakeKeyEvent(KeyButton button, bool press, bool isAutoRepeat) { LOG((CLOG_DEBUG2 "doFakeKeyEvent button:%d, press:%d", button, press)); // let system figure out character for us CGPostKeyboardEvent(0, static_cast(button) - 1, press); } KeyButton COSXKeyState::mapKey(Keystrokes& keys, KeyID id, KeyModifierMask desiredMask, bool isAutoRepeat) const { // look up virtual key CKeyMap::const_iterator keyIndex = m_keyMap.find(id); if (keyIndex == m_keyMap.end()) { return 0; } CGKeyCode keyCode = keyIndex->second; // adjust the modifiers to match the desired modifiers Keystrokes undo; if (!adjustModifiers(keys, undo, desiredMask)) { LOG((CLOG_DEBUG2 "failed to adjust modifiers")); return 0; } // add the key event Keystroke keystroke; keystroke.m_key = keyCode; if (!isAutoRepeat) { keystroke.m_press = true; keystroke.m_repeat = false; keys.push_back(keystroke); } else { keystroke.m_press = false; keystroke.m_repeat = true; keys.push_back(keystroke); keystroke.m_press = true; keys.push_back(keystroke); } // put undo keystrokes at end of keystrokes in reverse order while (!undo.empty()) { keys.push_back(undo.back()); undo.pop_back(); } return keyCode; } bool COSXKeyState::adjustModifiers(Keystrokes& /*keys*/, Keystrokes& /*undo*/, KeyModifierMask /*desiredMask*/) const { // FIXME -- should add necessary modifier events to keys and undo return true; } KeyID COSXKeyState::mapKeyFromEvent(EventRef event, KeyModifierMask* maskOut) const { char c; GetEventParameter(event, kEventParamKeyMacCharCodes, typeChar, NULL, sizeof(c), NULL, &c); UInt32 vkCode; GetEventParameter(event, kEventParamKeyCode, typeUInt32, NULL, sizeof(vkCode), NULL, &vkCode); KeyID id = s_virtualKey[vkCode]; // check if not in table; map character to key id if (id == kKeyNone && c != 0) { if ((c & 0x80u) == 0) { // ASCII id = static_cast(c) & 0xffu; } else { // character is not really ASCII. instead it's some // character in the current ANSI code page. try to // convert that to a Unicode character. if we fail // then use the single byte character as is. //FIXME id = static_cast(c) & 0xffu; } } KeyModifierMask activeMask = getActiveModifiers(); if (id != kKeyNone && c != 0) { // FIXME } // map modifier key if (maskOut != NULL) { activeMask &= ~KeyModifierModeSwitch; *maskOut = activeMask; } return id; }