Merge pull request #1569 from anoobs/vnc_improvements_v2

Add support for EXT_KEY_EVENT encoding in XenCenter VNC
This commit is contained in:
Mihaela Stoica 2017-06-06 17:13:22 +01:00 committed by GitHub
commit 30b83bc0b1
4 changed files with 73 additions and 16 deletions

View File

@ -294,7 +294,7 @@ namespace XenAdmin.ConsoleView
internal Set<int> pressedScans = new Set<int>();
private bool modifierKeyPressedAlone = false;
private void handleRDPKey(bool pressed, int scancode)
private void handleRDPKey(bool pressed, int scancode, int keysym)
{
bool containsFocus = parent.ParentForm != null && parent.ParentForm.ContainsFocus;

View File

@ -964,7 +964,7 @@ namespace XenAdmin.ConsoleView
foreach (int key in pressedScans)
{
this.vncStream.keyScanEvent(false, key);
this.vncStream.keyScanEvent(false, key, -1, Helpers.InvernessOrGreater(this.SourceVM.Connection));
}
});
@ -1285,7 +1285,7 @@ namespace XenAdmin.ConsoleView
}
}
public void keyScan(bool pressed, int scanCode)
public void keyScan(bool pressed, int scanCode, int keySym)
{
if (KeyHandler.handleExtras<int>(pressed, pressedScans, KeyHandler.ExtraScans, scanCode, KeyHandler.ModifierScans, ref modifierKeyPressedAlone))
{
@ -1293,21 +1293,26 @@ namespace XenAdmin.ConsoleView
{
// send key up anyway
modifierKeyPressedAlone = false;
keyScan_(pressed, scanCode);
keyScan_(pressed, scanCode, keySym);
return;
}
this.Focus();
return;
}
keyScan_(pressed, scanCode);
keyScan_(pressed, scanCode, keySym);
}
private void keyScan_(bool pressed, int scanCode)
{
keyScan_(pressed, scanCode, -1);
}
private void keyScan_(bool pressed, int scanCode, int keySym)
{
DoIfConnected(delegate()
{
this.vncStream.keyScanEvent(pressed, scanCode);
this.vncStream.keyScanEvent(pressed, scanCode, keySym, Helpers.InvernessOrGreater(this.SourceVM.Connection));
});
}

View File

@ -150,7 +150,7 @@ namespace DotNetVnc
private static LowLevelKeyboardProc _proc = HookCallback;
private static IntPtr _hookID = IntPtr.Zero;
public delegate void KeyEvent(bool down, int scancode);
public delegate void KeyEvent(bool down, int scancode, int keysym);
private static KeyEvent keyEvent = null;
#pragma warning disable 0649
@ -195,7 +195,8 @@ namespace DotNetVnc
}
}
private const int NUM_LOCK_SCAN = 197;
private const int RIGHT_SHIFT_SCAN = 54;
private const int NUM_LOCK_SCAN = 69;
private static int HookCallback(int nCode, int wParam, KBDLLHOOKSTRUCT* lParam)
{
@ -207,22 +208,40 @@ namespace DotNetVnc
{
KBDLLHOOKSTRUCT kbStruct = *lParam;
bool extended = (kbStruct.flags & FLAG_EXTENDED) == 0;
bool extended = (kbStruct.flags & FLAG_EXTENDED) == FLAG_EXTENDED;
bool down = (wParam == WM_KEYDOWN) || (wParam == WM_SYSKEYDOWN);
int scanCode = kbStruct.scanCode;
int keySym = KeyMap.translateKey((Keys)kbStruct.vkCode);
/* kbStruct.scanCode for NUM_LOCK and PAUSE are the same (69).
* But NUM_LOCK is an extended key, where as PAUSE is not.
* QEMU doesn't support PAUSE and expects NUM_LOCK scanCode
* to be sent as 69
*/
switch (scanCode)
{
case 54:
break;
/* Although RIGHT_SHIFT, NUMS_LOCK are extended keys,
* scan code for these keys are not prefixed with 0xe0.
*/
case RIGHT_SHIFT_SCAN:
case NUM_LOCK_SCAN:
break;
default:
scanCode += (extended ? 0 : 128);
/* 128 is added to scanCode to differentiate
* an extended key. Scan code for all extended keys
* needs to be prefixed with 0xe0, so adding 128
* or ( | 0x80) will give a hint to qemu that this
* scanCode is an extended one and qemu can then prefix
* scanCode with 0xe0
*/
scanCode += (extended ? 128 : 0);
break;
}
if (InterceptKeys.keyEvent != null)
{
InterceptKeys.keyEvent(down, scanCode);
InterceptKeys.keyEvent(down, scanCode, keySym);
}
if (bubble || scanCode == NUM_LOCK_SCAN)

View File

@ -54,12 +54,14 @@ namespace DotNetVnc
private const int CURSOR_PSEUDO_ENCODING = -239;
private const int DESKTOP_SIZE_PSEUDO_ENCODING = -223;
private const int XENCENTER_ENCODING = -254;
private const int QEMU_EXT_KEY_ENCODING = -258;
private const int SET_PIXEL_FORMAT = 0;
private const int SET_ENCODINGS = 2;
private const int FRAMEBUFFER_UPDATE_REQUEST = 3;
private const int KEY_EVENT = 4;
private const int KEY_SCAN_EVENT = 254;
private const int QEMU_MSG = 255;
private const int POINTER_EVENT = 5;
private const int CLIENT_CUT_TEXT = 6;
@ -73,6 +75,8 @@ namespace DotNetVnc
private const int BELL = 2;
private const int SERVER_CUT_TEXT = 3;
private const int QEMU_EXT_KEY_EVENT = 0;
private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
private Thread thread = null;
@ -118,7 +122,8 @@ namespace DotNetVnc
RAW_ENCODING,
CURSOR_PSEUDO_ENCODING,
DESKTOP_SIZE_PSEUDO_ENCODING,
XENCENTER_ENCODING
XENCENTER_ENCODING,
QEMU_EXT_KEY_ENCODING
};
private readonly IVNCGraphicsClient client;
@ -134,6 +139,7 @@ namespace DotNetVnc
private int height;
private bool incremental;
private bool qemu_ext_key_encoding = false;
private PixelFormat pixelFormat;
private PixelFormat pixelFormatCursor;
@ -468,13 +474,36 @@ namespace DotNetVnc
this.stream.writeInt32(key);
}
public void keyScanEvent(bool down, int key)
private void writeQemuExtKey(int command, bool down, int key, int sym)
{
this.stream.writeInt8(command);
this.stream.writeInt8(QEMU_EXT_KEY_EVENT);
this.stream.writePadding(1);
this.stream.writeFlag(down);
this.stream.writeInt32(sym);
this.stream.writeInt32(key);
}
/**
* use_qemu_ext_key_encoding: Dictates if we want to use QEMU_EXT_KEY encoding.
*
* XS6.2 doesn't properly support QEMU_EXT_KEY and XS6.5 supports QEMU_EXT_KEY encoding
* only if XS65ESP1051 is applied, so restrict QEMU_EXT_KEY encoding to Inverness and above.
*/
public void keyScanEvent(bool down, int key, int sym, bool use_qemu_ext_key_encoding)
{
lock (this.writeLock)
{
try
{
writeKey(KEY_SCAN_EVENT, down, key);
if (qemu_ext_key_encoding && use_qemu_ext_key_encoding)
{
writeQemuExtKey(QEMU_MSG, down, key, sym);
}
else
{
writeKey(KEY_SCAN_EVENT, down, key);
}
this.stream.Flush();
}
catch (IOException e)
@ -1274,6 +1303,10 @@ namespace DotNetVnc
incremental = false;
break;
case QEMU_EXT_KEY_ENCODING:
qemu_ext_key_encoding = true;
break;
default:
throw new VNCException("unimplemented encoding: " + encoding);
}