aboutsummaryrefslogtreecommitdiffstats
path: root/vncviewer/KeyboardWin32.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'vncviewer/KeyboardWin32.cxx')
-rw-r--r--vncviewer/KeyboardWin32.cxx155
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]);