aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/keyboard-test.txt4
-rw-r--r--vncviewer/Viewport.cxx34
-rw-r--r--vncviewer/win32.c58
-rw-r--r--vncviewer/win32.h2
4 files changed, 79 insertions, 19 deletions
diff --git a/doc/keyboard-test.txt b/doc/keyboard-test.txt
index 6375a9e5..d66e8533 100644
--- a/doc/keyboard-test.txt
+++ b/doc/keyboard-test.txt
@@ -66,7 +66,8 @@ Client (classic, non-raw, mode)
- CapsLock, NumLock
- Shift, Ctrl
- - Alt, AltGr, Super [Win, X11] (FIXME: Ctrl+AltGr broken on Win)
+ - Alt, AltGr, Super [Win, X11]
+ - Ctrl+AltGr [Win]
- Meta [X11]
- Left/right identification (FIXME: broken for Shift on Win)
- CmdL => AltL, CmdR => SuperL, AltL => ModeSwitch, AltR => Level3Shift [OS X]
@@ -75,7 +76,6 @@ Client (classic, non-raw, mode)
- CapsLock, Shift and AltGr affect symbol lookup
- Ctrl does not affect symbol lookup
- Ctrl+Alt+<ANY> sends the same symbol as <ANY>
- - Ctrl+AltGr+<ANY> sends the same symbol as AltGr+<ANY> (FIXME: broken on Win)
- "Shift press, A press, Shift release, A release" should not send "a release"
- Numpad:
diff --git a/vncviewer/Viewport.cxx b/vncviewer/Viewport.cxx
index ba0b0e93..1c0503c5 100644
--- a/vncviewer/Viewport.cxx
+++ b/vncviewer/Viewport.cxx
@@ -838,24 +838,18 @@ int Viewport::handleSystemEvent(void *event, void *data)
// Ctrl+Alt. However the remote end might not be Windows, so we need
// to merge those in to a single AltGr event. We detect this case
// by seeing the two key events directly after each other with a very
- // short time between them (<50ms).
+ // short time between them (<50ms) and supress the Ctrl event.
if (self->altGrArmed) {
self->altGrArmed = false;
Fl::remove_timeout(handleAltGrTimeout);
if (isExtended && (keyCode == 0x38) && (vKey == VK_MENU) &&
((msg->time - self->altGrCtrlTime) < 50)) {
- // FIXME: We fail to detect this if either Ctrl key is
- // first manually pressed as Windows then no longer
- // sends the fake Ctrl down event. It does however
- // happily send real Ctrl events even when AltGr
- // is already down.
- vlog.debug("Detected AltGr combination");
- self->handleKeyPress(0xb8, XK_ISO_Level3_Shift);
- return 1;
+ // Alt seen, so this is an AltGr sequence
+ } else {
+ // Not Alt, so fire the queued up Ctrl event
+ self->handleKeyPress(0x1d, XK_Control_L);
}
-
- self->handleKeyPress(0x1d, XK_Control_L);
}
if (keyCode == SCAN_FAKE) {
@@ -917,12 +911,18 @@ int Viewport::handleSystemEvent(void *event, void *data)
if ((keySym == XK_Shift_L) && (keyCode == 0x36))
keySym = XK_Shift_R;
- // Possible start of AltGr sequence? (see above)
- if ((keyCode == 0x1d) && (keySym == XK_Control_L)) {
- self->altGrArmed = true;
- self->altGrCtrlTime = msg->time;
- Fl::add_timeout(0.1, handleAltGrTimeout, self);
- return 1;
+ // AltGr handling (see above)
+ if (win32_has_altgr()) {
+ if ((keyCode == 0xb8) && (keySym == XK_Alt_R))
+ keySym = XK_ISO_Level3_Shift;
+
+ // Possible start of AltGr sequence?
+ if ((keyCode == 0x1d) && (keySym == XK_Control_L)) {
+ self->altGrArmed = true;
+ self->altGrCtrlTime = msg->time;
+ Fl::add_timeout(0.1, handleAltGrTimeout, self);
+ return 1;
+ }
}
self->handleKeyPress(keyCode, keySym);
diff --git a/vncviewer/win32.c b/vncviewer/win32.c
index 30c87f18..537ff435 100644
--- a/vncviewer/win32.c
+++ b/vncviewer/win32.c
@@ -33,6 +33,9 @@
#define MAPVK_VK_TO_CHAR 2
#endif
+int has_altgr;
+HKL current_layout = 0;
+
static HANDLE thread;
static DWORD thread_id;
@@ -300,3 +303,58 @@ int win32_vkey_to_keysym(UINT vkey, int extended)
return NoSymbol;
}
+
+int win32_has_altgr(void)
+{
+ BYTE orig_state[256];
+ BYTE altgr_state[256];
+
+ if (current_layout == GetKeyboardLayout(0))
+ return has_altgr;
+
+ // Save current keyboard state so we can get things sane again after
+ // we're done
+ if (!GetKeyboardState(orig_state))
+ return 0;
+
+ // We press Ctrl+Alt (Windows fake AltGr) and then test every key
+ // to see if it produces a printable character. If so then we assume
+ // AltGr is used in the current layout.
+
+ has_altgr = 0;
+
+ memset(altgr_state, 0, sizeof(altgr_state));
+ altgr_state[VK_CONTROL] = 0x80;
+ altgr_state[VK_MENU] = 0x80;
+
+ for (UINT vkey = 0;vkey <= 0xff;vkey++) {
+ int ret;
+ WCHAR wstr[10];
+
+ // Need to skip this one as it is a bit magical and will trigger
+ // a false positive
+ if (vkey == VK_PACKET)
+ continue;
+
+ ret = ToUnicode(vkey, 0, altgr_state, wstr,
+ sizeof(wstr)/sizeof(wstr[0]), 0);
+ if (ret == 1) {
+ has_altgr = 1;
+ break;
+ }
+
+ if (ret == -1) {
+ // Dead key, need to clear out state before we proceed
+ do {
+ ret = ToUnicode(vkey, 0, altgr_state, wstr,
+ sizeof(wstr)/sizeof(wstr[0]), 0);
+ } while (ret < 0);
+ }
+ }
+
+ SetKeyboardState(orig_state);
+
+ current_layout = GetKeyboardLayout(0);
+
+ return has_altgr;
+}
diff --git a/vncviewer/win32.h b/vncviewer/win32.h
index 01487085..9d4704bc 100644
--- a/vncviewer/win32.h
+++ b/vncviewer/win32.h
@@ -32,6 +32,8 @@ void win32_disable_lowlevel_keyboard(HWND hwnd);
int win32_vkey_to_keysym(UINT vkey, int extended);
+int win32_has_altgr(void);
+
};
#endif