diff options
Diffstat (limited to 'vncviewer/KeyboardWin32.cxx')
-rw-r--r-- | vncviewer/KeyboardWin32.cxx | 155 |
1 files changed, 135 insertions, 20 deletions
diff --git a/vncviewer/KeyboardWin32.cxx b/vncviewer/KeyboardWin32.cxx index 1caf4863..095927f1 100644 --- a/vncviewer/KeyboardWin32.cxx +++ b/vncviewer/KeyboardWin32.cxx @@ -24,6 +24,8 @@ #include <assert.h> +#include <algorithm> + // Missing in at least some versions of MinGW #ifndef MAPVK_VK_TO_CHAR #define MAPVK_VK_TO_CHAR 2 @@ -31,12 +33,13 @@ #include <FL/Fl.H> +#include <core/LogWriter.h> + #define XK_MISCELLANY #define XK_XKB_KEYS #define XK_KOREAN #include <rfb/keysymdef.h> #include <rfb/XF86keysym.h> -#include <rfb/LogWriter.h> #include <rfb/ledStates.h> #define NoSymbol 0 @@ -50,7 +53,7 @@ // Used to detect fake input (0xaa is not a real key) static const WORD SCAN_FAKE = 0xaa; -static rfb::LogWriter vlog("KeyboardWin32"); +static core::LogWriter vlog("KeyboardWin32"); // Layout independent keys static const UINT vkey_map[][3] = { @@ -138,6 +141,8 @@ static const UINT vkey_map[][3] = { { VK_MEDIA_STOP, NoSymbol, XF86XK_AudioStop }, { VK_MEDIA_PLAY_PAUSE, NoSymbol, XF86XK_AudioPlay }, { VK_LAUNCH_MAIL, NoSymbol, XF86XK_Mail }, + { VK_LAUNCH_MEDIA_SELECT, NoSymbol, XF86XK_AudioMedia }, + { VK_LAUNCH_APP1, NoSymbol, XF86XK_MyComputer }, { VK_LAUNCH_APP2, NoSymbol, XF86XK_Calculator }, }; @@ -202,6 +207,7 @@ bool KeyboardWin32::handleEvent(const void* event) bool isExtended; int systemKeyCode, keyCode; uint32_t keySym; + BYTE state[256]; vKey = msg->wParam; isExtended = (msg->lParam & (1 << 24)) != 0; @@ -256,7 +262,23 @@ bool KeyboardWin32::handleEvent(const void* event) keyCode = translateSystemKeyCode(systemKeyCode); - keySym = translateVKey(vKey, isExtended); + GetKeyboardState(state); + + // Pressing Ctrl wreaks havoc with the symbol lookup, so turn + // that off. But AltGr shows up as Ctrl+Alt in Windows, so keep + // Ctrl if Alt is active. + if (!(state[VK_LCONTROL] & 0x80) || !(state[VK_RMENU] & 0x80)) + state[VK_CONTROL] = state[VK_LCONTROL] = state[VK_RCONTROL] = 0; + + keySym = translateVKey(vKey, isExtended, state); + + if (keySym == NoSymbol) { + // Most Ctrl+Alt combinations will fail to produce a symbol, so + // try it again with Ctrl unconditionally disabled. + state[VK_CONTROL] = state[VK_LCONTROL] = state[VK_RCONTROL] = 0; + keySym = translateVKey(vKey, isExtended, state); + } + if (keySym == NoSymbol) { if (isExtended) vlog.error(_("No symbol for extended virtual key 0x%02x"), (int)vKey); @@ -354,6 +376,114 @@ bool KeyboardWin32::handleEvent(const void* event) return false; } +std::list<uint32_t> KeyboardWin32::translateToKeySyms(int systemKeyCode) +{ + unsigned vkey; + bool extended; + + std::list<uint32_t> keySyms; + unsigned mods; + + BYTE state[256]; + + uint32_t ks; + + UINT ch; + + extended = systemKeyCode & 0x80; + if (extended) + systemKeyCode = 0xe0 | (systemKeyCode & 0x7f); + + vkey = MapVirtualKey(systemKeyCode, MAPVK_VSC_TO_VK_EX); + if (vkey == 0) + return keySyms; + + // Start with no modifiers + memset(state, 0, sizeof(state)); + ks = translateVKey(vkey, extended, state); + if (ks != NoSymbol) + keySyms.push_back(ks); + + // Next just a single modifier at a time + for (mods = 1; mods < 16; mods <<= 1) { + std::list<uint32_t>::const_iterator iter; + + memset(state, 0, sizeof(state)); + if (mods & 0x1) + state[VK_CONTROL] = state[VK_LCONTROL] = 0x80; + if (mods & 0x2) + state[VK_SHIFT] = state[VK_LSHIFT] = 0x80; + if (mods & 0x4) + state[VK_MENU] = state[VK_LMENU] = 0x80; + if (mods & 0x8) { + state[VK_CONTROL] = state[VK_LCONTROL] = 0x80; + state[VK_MENU] = state[VK_RMENU] = 0x80; + } + + ks = translateVKey(vkey, extended, state); + if (ks == NoSymbol) + continue; + + iter = std::find(keySyms.begin(), keySyms.end(), ks); + if (iter != keySyms.end()) + continue; + + keySyms.push_back(ks); + } + + // Finally everything + for (mods = 0; mods < 16; mods++) { + std::list<uint32_t>::const_iterator iter; + + memset(state, 0, sizeof(state)); + if (mods & 0x1) + state[VK_CONTROL] = state[VK_LCONTROL] = 0x80; + if (mods & 0x2) + state[VK_SHIFT] = state[VK_LSHIFT] = 0x80; + if (mods & 0x4) + state[VK_MENU] = state[VK_LMENU] = 0x80; + if (mods & 0x8) { + state[VK_CONTROL] = state[VK_LCONTROL] = 0x80; + state[VK_MENU] = state[VK_RMENU] = 0x80; + } + + ks = translateVKey(vkey, extended, state); + if (ks == NoSymbol) + continue; + + iter = std::find(keySyms.begin(), keySyms.end(), ks); + if (iter != keySyms.end()) + continue; + + keySyms.push_back(ks); + } + + // As a final resort we use MapVirtualKey() as that gives us a Latin + // character even on non-Latin keyboards, which is useful for + // shortcuts + // + // FIXME: Can this give us anything but ASCII? + + ch = MapVirtualKeyW(vkey, MAPVK_VK_TO_CHAR); + if (ch != 0) { + if (ch & 0x80000000) + ch = ucs2combining(ch & 0xffff); + else + ch = ch & 0xffff; + + ks = ucs2keysym(ch); + if (ks != NoSymbol) { + std::list<uint32_t>::const_iterator iter; + + iter = std::find(keySyms.begin(), keySyms.end(), ks); + if (iter == keySyms.end()) + keySyms.push_back(ks); + } + } + + return keySyms; +} + void KeyboardWin32::reset() { altGrArmed = false; @@ -465,12 +595,12 @@ uint32_t KeyboardWin32::lookupVKeyMap(unsigned vkey, bool extended, return NoSymbol; } -uint32_t KeyboardWin32::translateVKey(unsigned vkey, bool extended) +uint32_t KeyboardWin32::translateVKey(unsigned vkey, bool extended, + const unsigned char state[256]) { HKL layout; WORD lang, primary_lang; - BYTE state[256]; int ret; WCHAR wstr[10]; @@ -524,25 +654,10 @@ uint32_t KeyboardWin32::translateVKey(unsigned vkey, bool extended) // does what we want though. Unfortunately it keeps state, so // we have to be careful around dead characters. - GetKeyboardState(state); - - // Pressing Ctrl wreaks havoc with the symbol lookup, so turn - // that off. But AltGr shows up as Ctrl+Alt in Windows, so keep - // Ctrl if Alt is active. - if (!(state[VK_LCONTROL] & 0x80) || !(state[VK_RMENU] & 0x80)) - state[VK_CONTROL] = state[VK_LCONTROL] = state[VK_RCONTROL] = 0; - // FIXME: Multi character results, like U+0644 U+0627 // on Arabic layout ret = ToUnicode(vkey, 0, state, wstr, sizeof(wstr)/sizeof(wstr[0]), 0); - if (ret == 0) { - // Most Ctrl+Alt combinations will fail to produce a symbol, so - // try it again with Ctrl unconditionally disabled. - state[VK_CONTROL] = state[VK_LCONTROL] = state[VK_RCONTROL] = 0; - ret = ToUnicode(vkey, 0, state, wstr, sizeof(wstr)/sizeof(wstr[0]), 0); - } - if (ret == 1) return ucs2keysym(wstr[0]); |