aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrian Hinz <bphinz@users.sourceforge.net>2013-03-25 20:58:14 +0000
committerBrian Hinz <bphinz@users.sourceforge.net>2013-03-25 20:58:14 +0000
commitaccdd9518674c9c0111dd7263f4d94ecfba2534e (patch)
tree2efdb018d937b50db0348dc657bd232062970cc6
parentfc23895f80b6ab8d19add9bd3f18bfd5818e8935 (diff)
downloadtigervnc-accdd9518674c9c0111dd7263f4d94ecfba2534e.tar.gz
tigervnc-accdd9518674c9c0111dd7263f4d94ecfba2534e.zip
More fixes for key event issues. It seems that on WindowsXP sending the actual key press/release separately can be mis-interpreted by the server as holding the key down. Using a keyTyped event for all character input ensures that we can send an immediate down/up. It also works around the broken AltGr detection in Java 6. Also added support for more keys (F13-F24, etc.). Some key definitions in java don't have X11 equivalents or I could not be sure so I've left them commented out.
git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@5066 3789f03b-4d11-0410-bbf8-ca57d06f2519
-rw-r--r--java/com/tigervnc/rfb/Keysyms.java40
-rw-r--r--java/com/tigervnc/vncviewer/CConn.java161
-rw-r--r--java/com/tigervnc/vncviewer/DesktopWindow.java15
3 files changed, 174 insertions, 42 deletions
diff --git a/java/com/tigervnc/rfb/Keysyms.java b/java/com/tigervnc/rfb/Keysyms.java
index 93aea127..4cf17847 100644
--- a/java/com/tigervnc/rfb/Keysyms.java
+++ b/java/com/tigervnc/rfb/Keysyms.java
@@ -1,5 +1,6 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
* Copyright (C) 2012-2013 D. R. Commander. All Rights Reserved.
+ * Copyright (C) 2013 Brian P. Hinz
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -27,6 +28,7 @@ package com.tigervnc.rfb;
public class Keysyms {
+ public static final int ISO_Level3_Shift = 0xFE03;
public static final int BackSpace = 0xFF08;
public static final int Tab = 0xFF09;
public static final int Linefeed = 0xFF0A;
@@ -38,6 +40,33 @@ public class Keysyms {
public static final int Escape = 0xFF1B;
public static final int Delete = 0xFFFF;
+ public static final int Multi_key = 0xFF20; /* Multi-key character compose */
+ public static final int Codeinput = 0xFF37;
+ public static final int SingleCandidate = 0xFF3C;
+ public static final int MultipleCandidate = 0xFF3D;
+ public static final int PreviousCandidate = 0xFF3E;
+
+ public static final int Kanji = 0xFF21; /* Kanji, Kanji convert */
+ public static final int Muhenkan = 0xFF22; /* Cancel Conversion */
+ public static final int Henkan_Mode = 0xFF23; /* Start/Stop Conversion */
+ public static final int Henkan = 0xFF23; /* Alias for Henkan_Mode */
+ public static final int Romaji = 0xFF24; /* to Romaji */
+ public static final int Hiragana = 0xFF25; /* to Hiragana */
+ public static final int Katakana = 0xFF26; /* to Katakana */
+ public static final int Hiragana_Katakana = 0xFF27; /* Hiragana/Katakana toggle */
+ public static final int Zenkaku = 0xFF28; /* to Zenkaku */
+ public static final int Hankaku = 0xFF29; /* to Hankaku */
+ public static final int Zenkaku_Hankaku = 0xFF2A; /* Zenkaku/Hankaku toggle */
+ public static final int Touroku = 0xFF2B; /* Add to Dictionary */
+ public static final int Massyo = 0xFF2C; /* Delete from Dictionary */
+ public static final int Kana_Lock = 0xFF2D; /* Kana Lock */
+ public static final int Kana_Shift = 0xFF2E; /* Kana Shift */
+ public static final int Eisu_Shift = 0xFF2F; /* Alphanumeric Shift */
+ public static final int Eisu_toggle = 0xFF30; /* Alphanumeric toggle */
+ public static final int Kanji_Bangou = 0xFF37; /* Codeinput */
+ public static final int Zen_Koho = 0xFF3D; /* Multiple/All Candidate(s) */
+ public static final int Mae_Koho = 0xFF3E; /* Previous Candidate */
+
public static final int Home = 0xFF50;
public static final int Left = 0xFF51;
public static final int Up = 0xFF52;
@@ -78,6 +107,17 @@ public class Keysyms {
public static final int F11 = 0xFFC8;
public static final int F12 = 0xFFC9;
public static final int F13 = 0xFFCA;
+ public static final int F14 = 0xFFCB;
+ public static final int F15 = 0xFFCC;
+ public static final int F16 = 0xFFCD;
+ public static final int F17 = 0xFFCE;
+ public static final int F18 = 0xFFCF;
+ public static final int F19 = 0xFFD0;
+ public static final int F20 = 0xFFD1;
+ public static final int F21 = 0xFFD2;
+ public static final int F22 = 0xFFD3;
+ public static final int F23 = 0xFFD4;
+ public static final int F24 = 0xFFD5;
public static final int Shift_L = 0xFFE1;
public static final int Shift_R = 0xFFE2;
diff --git a/java/com/tigervnc/vncviewer/CConn.java b/java/com/tigervnc/vncviewer/CConn.java
index 09fa2d78..97ba9da9 100644
--- a/java/com/tigervnc/vncviewer/CConn.java
+++ b/java/com/tigervnc/vncviewer/CConn.java
@@ -67,6 +67,9 @@ public class CConn extends CConnection
new PixelFormat(8, 6, false, true, 3, 3, 3, 4, 2, 0);
static final PixelFormat mediumColourPF =
new PixelFormat(8, 8, false, false, 7, 7, 3, 0, 3, 6);
+ static final int KEY_LOC_SHIFT_R = 0;
+ static final int KEY_LOC_SHIFT_L = 16;
+ static final int SUPER_MASK = 1<<15;
////////////////////////////////////////////////////////////////////
// The following methods are all called from the RFB thread
@@ -1154,8 +1157,31 @@ public class CConn extends CConnection
writer().writeKeyEvent(keysym, down);
}
+ public void writeKeyEvent(KeyEvent ev, int keysym) {
+ if (keysym < 0)
+ return;
+ String fmt = ev.paramString().replaceAll("%","%%");
+ vlog.debug(String.format(fmt.replaceAll(",","%n ")));
+ // Windows sends an extra CTRL_L + ALT_R when AltGr is down that need to
+ // be suppressed for keyTyped events. In Java 6 KeyEvent.isAltGraphDown()
+ // is broken for keyPressed/keyReleased events.
+ int ALTGR_MASK = ((Event.CTRL_MASK<<KEY_LOC_SHIFT_L) | Event.ALT_MASK);
+ String os = System.getProperty("os.name");
+ if (os.startsWith("Windows") && ((modifiers & ALTGR_MASK) != 0)) {
+ writeKeyEvent(Keysyms.Control_L, false);
+ writeKeyEvent(Keysyms.Alt_R, false);
+ writeKeyEvent(keysym, true);
+ writeKeyEvent(keysym, false);
+ writeKeyEvent(Keysyms.Control_L, true);
+ writeKeyEvent(Keysyms.Alt_R, true);
+ } else {
+ writeKeyEvent(keysym, true);
+ writeKeyEvent(keysym, false);
+ }
+ }
+
public void writeKeyEvent(KeyEvent ev) {
- int keysym = 0, keycode, key, location;
+ int keysym = 0, keycode, key, location, locationShift;
if (shuttingDown)
return;
@@ -1163,11 +1189,14 @@ public class CConn extends CConnection
boolean down = (ev.getID() == KeyEvent.KEY_PRESSED);
keycode = ev.getKeyCode();
+ if (keycode == KeyEvent.VK_UNDEFINED)
+ return;
key = ev.getKeyChar();
location = ev.getKeyLocation();
-
- String fmt = ev.paramString().replaceAll("%","%%");
- vlog.debug(String.format(fmt.replaceAll(",","%n ")));
+ if (location == KeyEvent.KEY_LOCATION_RIGHT)
+ locationShift = KEY_LOC_SHIFT_R;
+ else
+ locationShift = KEY_LOC_SHIFT_L;
if (!ev.isActionKey()) {
if (keycode >= KeyEvent.VK_0 && keycode <= KeyEvent.VK_9 &&
@@ -1209,43 +1238,37 @@ public class CConn extends CConnection
else
keysym = Keysyms.Clear; break;
case KeyEvent.VK_CONTROL:
- // Suppress CTRL+ALT when AltGr is pressed
- if (ev.isAltGraphDown())
- return;
if (down)
- modifiers |= Event.CTRL_MASK;
+ modifiers |= (Event.CTRL_MASK<<locationShift);
else
- modifiers &= ~Event.CTRL_MASK;
+ modifiers &= ~(Event.CTRL_MASK<<locationShift);
if (location == KeyEvent.KEY_LOCATION_RIGHT)
keysym = Keysyms.Control_R;
else
keysym = Keysyms.Control_L; break;
case KeyEvent.VK_ALT:
- // Suppress CTRL+ALT when AltGr is pressed
- if (ev.isAltGraphDown())
- return;
if (down)
- modifiers |= Event.ALT_MASK;
+ modifiers |= (Event.ALT_MASK<<locationShift);
else
- modifiers &= ~Event.ALT_MASK;
+ modifiers &= ~(Event.ALT_MASK<<locationShift);
if (location == KeyEvent.KEY_LOCATION_RIGHT)
keysym = Keysyms.Alt_R;
else
keysym = Keysyms.Alt_L; break;
case KeyEvent.VK_SHIFT:
if (down)
- modifiers |= Event.SHIFT_MASK;
+ modifiers |= (Event.SHIFT_MASK<<locationShift);
else
- modifiers &= ~Event.SHIFT_MASK;
+ modifiers &= ~(Event.SHIFT_MASK<<locationShift);
if (location == KeyEvent.KEY_LOCATION_RIGHT)
keysym = Keysyms.Shift_R;
else
keysym = Keysyms.Shift_L; break;
case KeyEvent.VK_META:
if (down)
- modifiers |= Event.META_MASK;
+ modifiers |= (Event.META_MASK<<locationShift);
else
- modifiers &= ~Event.META_MASK;
+ modifiers &= ~(Event.META_MASK<<locationShift);
if (location == KeyEvent.KEY_LOCATION_RIGHT)
keysym = Keysyms.Meta_R;
else
@@ -1269,6 +1292,7 @@ public class CConn extends CConnection
keycode <= 127)
key = keycode;
}
+
keysym = UnicodeToKeysym.translate(key);
if (keysym == -1)
return;
@@ -1316,6 +1340,15 @@ public class CConn extends CConnection
keysym = Keysyms.KP_Right;
else
keysym = Keysyms.Right; break;
+ case KeyEvent.VK_BEGIN:
+ if (location == KeyEvent.KEY_LOCATION_NUMPAD)
+ keysym = Keysyms.KP_Begin;
+ else
+ keysym = Keysyms.Begin; break;
+ case KeyEvent.VK_KP_LEFT: keysym = Keysyms.KP_Left; break;
+ case KeyEvent.VK_KP_UP: keysym = Keysyms.KP_Up; break;
+ case KeyEvent.VK_KP_RIGHT: keysym = Keysyms.KP_Right; break;
+ case KeyEvent.VK_KP_DOWN: keysym = Keysyms.KP_Down; break;
case KeyEvent.VK_F1: keysym = Keysyms.F1; break;
case KeyEvent.VK_F2: keysym = Keysyms.F2; break;
case KeyEvent.VK_F3: keysym = Keysyms.F3; break;
@@ -1329,7 +1362,21 @@ public class CConn extends CConnection
case KeyEvent.VK_F11: keysym = Keysyms.F11; break;
case KeyEvent.VK_F12: keysym = Keysyms.F12; break;
case KeyEvent.VK_F13: keysym = Keysyms.F13; break;
+ case KeyEvent.VK_F14: keysym = Keysyms.F14; break;
+ case KeyEvent.VK_F15: keysym = Keysyms.F15; break;
+ case KeyEvent.VK_F16: keysym = Keysyms.F16; break;
+ case KeyEvent.VK_F17: keysym = Keysyms.F17; break;
+ case KeyEvent.VK_F18: keysym = Keysyms.F18; break;
+ case KeyEvent.VK_F19: keysym = Keysyms.F19; break;
+ case KeyEvent.VK_F20: keysym = Keysyms.F20; break;
+ case KeyEvent.VK_F21: keysym = Keysyms.F21; break;
+ case KeyEvent.VK_F22: keysym = Keysyms.F22; break;
+ case KeyEvent.VK_F23: keysym = Keysyms.F23; break;
+ case KeyEvent.VK_F24: keysym = Keysyms.F24; break;
case KeyEvent.VK_PRINTSCREEN: keysym = Keysyms.Print; break;
+ case KeyEvent.VK_SCROLL_LOCK: keysym = Keysyms.Scroll_Lock; break;
+ case KeyEvent.VK_CAPS_LOCK: keysym = Keysyms.Caps_Lock; break;
+ case KeyEvent.VK_NUM_LOCK: keysym = Keysyms.Num_Lock; break;
case KeyEvent.VK_PAUSE:
if (ev.isControlDown())
keysym = Keysyms.Break;
@@ -1341,27 +1388,55 @@ public class CConn extends CConnection
keysym = Keysyms.KP_Insert;
else
keysym = Keysyms.Insert; break;
- case KeyEvent.VK_KP_DOWN: keysym = Keysyms.KP_Down; break;
- case KeyEvent.VK_KP_LEFT: keysym = Keysyms.KP_Left; break;
- case KeyEvent.VK_KP_RIGHT: keysym = Keysyms.KP_Right; break;
- case KeyEvent.VK_KP_UP: keysym = Keysyms.KP_Up; break;
- case KeyEvent.VK_NUM_LOCK: keysym = Keysyms.Num_Lock; break;
- case KeyEvent.VK_WINDOWS: keysym = Keysyms.Super_L; break;
- case KeyEvent.VK_CONTEXT_MENU: keysym = Keysyms.Menu; break;
- case KeyEvent.VK_SCROLL_LOCK: keysym = Keysyms.Scroll_Lock; break;
- case KeyEvent.VK_CAPS_LOCK: keysym = Keysyms.Caps_Lock; break;
- case KeyEvent.VK_BEGIN:
- if (location == KeyEvent.KEY_LOCATION_NUMPAD)
- keysym = Keysyms.KP_Begin;
+ // case KeyEvent.VK_FINAL: keysym = Keysyms.?; break;
+ // case KeyEvent.VK_CONVERT: keysym = Keysyms.?; break;
+ // case KeyEvent.VK_NONCONVERT: keysym = Keysyms.?; break;
+ // case KeyEvent.VK_ACCEPT: keysym = Keysyms.?; break;
+ // case KeyEvent.VK_MODECHANGE: keysym = Keysyms.Mode_switch?; break;
+ // case KeyEvent.VK_KANA: keysym = Keysyms.Kana_shift?; break;
+ case KeyEvent.VK_KANJI: keysym = Keysyms.Kanji; break;
+ // case KeyEvent.VK_ALPHANUMERIC: keysym = Keysyms.Eisu_Shift?; break;
+ case KeyEvent.VK_KATAKANA: keysym = Keysyms.Katakana; break;
+ case KeyEvent.VK_HIRAGANA: keysym = Keysyms.Hiragana; break;
+ // case KeyEvent.VK_FULL_WIDTH: keysym = Keysyms.?; break;
+ // case KeyEvent.VK_HALF_WIDTH: keysym = Keysyms.?; break;
+ // case KeyEvent.VK_ROMAN_CHARACTERS: keysym = Keysyms.?; break;
+ // case KeyEvent.VK_ALL_CANDIDATES: keysym = Keysyms.MultipleCandidate?; break;
+ case KeyEvent.VK_PREVIOUS_CANDIDATE: keysym = Keysyms.PreviousCandidate; break;
+ case KeyEvent.VK_CODE_INPUT: keysym = Keysyms.Codeinput; break;
+ // case KeyEvent.VK_JAPANESE_KATAKANA: keysym = Keysyms.?; break;
+ // case KeyEvent.VK_JAPANESE_HIRAGANA: keysym = Keysyms.?; break;
+ case KeyEvent.VK_JAPANESE_ROMAN: keysym = Keysyms.Romaji; break;
+ case KeyEvent.VK_KANA_LOCK: keysym = Keysyms.Kana_Lock; break;
+ // case KeyEvent.VK_INPUT_METHOD_ON_OFF: keysym = Keysyms.?; break;
+
+ case KeyEvent.VK_AGAIN: keysym = Keysyms.Redo; break;
+ case KeyEvent.VK_UNDO: keysym = Keysyms.Undo; break;
+ // case KeyEvent.VK_COPY: keysym = Keysyms.?; break;
+ // case KeyEvent.VK_PASTE: keysym = Keysyms.?; break;
+ // case KeyEvent.VK_CUT: keysym = Keysyms.?; break;
+ case KeyEvent.VK_FIND: keysym = Keysyms.Find; break;
+ // case KeyEvent.VK_PROPS: keysym = Keysyms.?; break;
+ case KeyEvent.VK_STOP: keysym = Keysyms.Cancel; break;
+ case KeyEvent.VK_HELP: keysym = Keysyms.Help; break;
+ case KeyEvent.VK_WINDOWS:
+ if (down)
+ modifiers |= SUPER_MASK;
else
- keysym = Keysyms.Begin; break;
+ modifiers &= ~SUPER_MASK;
+ keysym = Keysyms.Super_L; break;
+ case KeyEvent.VK_CONTEXT_MENU: keysym = Keysyms.Menu; break;
default: return;
}
}
- writeKeyEvent(keysym, down);
- }
+ if (keysym > 0) {
+ String fmt = ev.paramString().replaceAll("%","%%");
+ vlog.debug(String.format(fmt.replaceAll(",","%n ")));
+ writeKeyEvent(keysym, down);
+ }
+ }
public void writePointerEvent(MouseEvent ev) {
if (state() != RFBSTATE_NORMAL || shuttingDown)
@@ -1390,7 +1465,6 @@ public class CConn extends CConnection
writer().writePointerEvent(new Point(ev.getX(), ev.getY()), buttonMask);
}
-
public void writeWheelEvent(MouseWheelEvent ev) {
if (state() != RFBSTATE_NORMAL || shuttingDown)
return;
@@ -1411,16 +1485,25 @@ public class CConn extends CConnection
}
-
synchronized void releaseModifiers() {
- if ((modifiers & Event.SHIFT_MASK) != 0)
+ if ((modifiers & Event.SHIFT_MASK) == Event.SHIFT_MASK)
+ writeKeyEvent(Keysyms.Shift_R, false);
+ if (((modifiers>>KEY_LOC_SHIFT_L) & Event.SHIFT_MASK) == Event.SHIFT_MASK)
writeKeyEvent(Keysyms.Shift_L, false);
- if ((modifiers & Event.CTRL_MASK) != 0)
+ if ((modifiers & Event.CTRL_MASK) == Event.CTRL_MASK)
+ writeKeyEvent(Keysyms.Control_R, false);
+ if (((modifiers>>KEY_LOC_SHIFT_L) & Event.CTRL_MASK) == Event.CTRL_MASK)
writeKeyEvent(Keysyms.Control_L, false);
- if ((modifiers & Event.ALT_MASK) != 0)
+ if ((modifiers & Event.ALT_MASK) == Event.ALT_MASK)
+ writeKeyEvent(Keysyms.Alt_R, false);
+ if (((modifiers>>KEY_LOC_SHIFT_L) & Event.ALT_MASK) == Event.ALT_MASK)
writeKeyEvent(Keysyms.Alt_L, false);
- if ((modifiers & Event.META_MASK) != 0)
+ if ((modifiers & Event.META_MASK) == Event.META_MASK)
+ writeKeyEvent(Keysyms.Meta_R, false);
+ if (((modifiers>>KEY_LOC_SHIFT_L) & Event.META_MASK) == Event.META_MASK)
writeKeyEvent(Keysyms.Meta_L, false);
+ if ((modifiers & SUPER_MASK) == SUPER_MASK)
+ writeKeyEvent(Keysyms.Super_L, false);
modifiers = 0;
}
diff --git a/java/com/tigervnc/vncviewer/DesktopWindow.java b/java/com/tigervnc/vncviewer/DesktopWindow.java
index 5f9ee1a3..7621af50 100644
--- a/java/com/tigervnc/vncviewer/DesktopWindow.java
+++ b/java/com/tigervnc/vncviewer/DesktopWindow.java
@@ -437,12 +437,19 @@ class DesktopWindow extends JPanel implements Runnable, MouseListener,
}
// Handle the key-typed event.
- public void keyTyped(KeyEvent e) {}
+ public void keyTyped(KeyEvent e) {
+ int keysym = UnicodeToKeysym.translate(e.getKeyChar());
+ if (!cc.viewer.viewOnly.getValue())
+ if (!e.isActionKey() && keysym > 0)
+ cc.writeKeyEvent(e, keysym);
+ }
// Handle the key-released event.
public void keyReleased(KeyEvent e) {
+ int keysym = UnicodeToKeysym.translate(e.getKeyChar());
if (!cc.viewer.viewOnly.getValue())
- cc.writeKeyEvent(e);
+ if (e.isActionKey() || keysym < 0)
+ cc.writeKeyEvent(e);
}
// Handle the key-pressed event.
@@ -499,8 +506,10 @@ class DesktopWindow extends JPanel implements Runnable, MouseListener,
return;
}
}
+ int keysym = UnicodeToKeysym.translate(e.getKeyChar());
if (!cc.viewer.viewOnly.getValue())
- cc.writeKeyEvent(e);
+ if (e.isActionKey() || keysym < 0)
+ cc.writeKeyEvent(e);
}
////////////////////////////////////////////////////////////////////