correct Pause key sequence

This commit is contained in:
Daryl Poe 2014-06-04 15:41:17 -06:00
parent 01865f0e28
commit 46a00b5c9e
4 changed files with 72 additions and 7 deletions

View File

@ -102,13 +102,13 @@ void xf_kbd_send_key(xfContext* xfc, BOOL down, BYTE keycode)
else if (rdp_scancode == RDP_SCANCODE_PAUSE &&
!xf_kbd_key_pressed(xfc, XK_Control_L) && !xf_kbd_key_pressed(xfc, XK_Control_R))
{
/* Pause without Ctrl has to be sent as Ctrl + NumLock. */
/* Pause without Ctrl has to be sent as a series of keycodes
* in a single input PDU. Pause only happens on "press";
* no code is sent on "release".
*/
if (down)
{
freerdp_input_send_keyboard_event_ex(input, TRUE, RDP_SCANCODE_LCONTROL);
freerdp_input_send_keyboard_event_ex(input, TRUE, RDP_SCANCODE_NUMLOCK);
freerdp_input_send_keyboard_event_ex(input, FALSE, RDP_SCANCODE_LCONTROL);
freerdp_input_send_keyboard_event_ex(input, FALSE, RDP_SCANCODE_NUMLOCK);
freerdp_input_send_keyboard_pause_event(input);
}
}
else

View File

@ -64,6 +64,7 @@ typedef struct rdp_input_proxy rdpInputProxy;
typedef void (*pSynchronizeEvent)(rdpInput* input, UINT32 flags);
typedef void (*pKeyboardEvent)(rdpInput* input, UINT16 flags, UINT16 code);
typedef void (*pKeyboardPauseEvent)(rdpInput* input);
typedef void (*pUnicodeKeyboardEvent)(rdpInput* input, UINT16 flags, UINT16 code);
typedef void (*pMouseEvent)(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y);
typedef void (*pExtendedMouseEvent)(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y);
@ -81,8 +82,9 @@ struct rdp_input
pMouseEvent MouseEvent; /* 19 */
pExtendedMouseEvent ExtendedMouseEvent; /* 20 */
pFocusInEvent FocusInEvent; /*21 */
pKeyboardPauseEvent KeyboardPauseEvent; /* 22 */
UINT32 paddingB[32 - 22]; /* 22 */
UINT32 paddingB[32 - 23]; /* 23 */
/* Internal */
@ -98,6 +100,7 @@ extern "C" {
FREERDP_API void freerdp_input_send_synchronize_event(rdpInput* input, UINT32 flags);
FREERDP_API void freerdp_input_send_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code);
FREERDP_API void freerdp_input_send_keyboard_event_ex(rdpInput* input, BOOL down, UINT32 rdp_scancode);
FREERDP_API void freerdp_input_send_keyboard_pause_event(rdpInput* input);
FREERDP_API void freerdp_input_send_unicode_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code);
FREERDP_API void freerdp_input_send_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y);
FREERDP_API void freerdp_input_send_extended_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y);

View File

@ -92,7 +92,8 @@ enum FASTPATH_INPUT_EVENT_CODE
enum FASTPATH_INPUT_KBDFLAGS
{
FASTPATH_INPUT_KBDFLAGS_RELEASE = 0x01,
FASTPATH_INPUT_KBDFLAGS_EXTENDED = 0x02
FASTPATH_INPUT_KBDFLAGS_EXTENDED = 0x02,
FASTPATH_INPUT_KBDFLAGS_PREFIX_E1 = 0x04 /* for pause sequence */
};
struct rdp_fastpath

View File

@ -166,6 +166,27 @@ void input_send_focus_in_event(rdpInput* input, UINT16 toggleStates, UINT16 x, U
input_send_extended_mouse_event(input, PTR_FLAGS_MOVE, x, y);
}
static void input_send_keyboard_pause_event(rdpInput* input)
{
/* In ancient days, pause-down without control sent E1 1D 45 E1 9D C5,
* and pause-up sent nothing. However, reverse engineering mstsc shows
* it sending the following sequence:
*/
/* Control down (0x1D) */
input_send_keyboard_event(input, 0,
RDP_SCANCODE_CODE(RDP_SCANCODE_LCONTROL));
/* Numlock down (0x45) */
input_send_keyboard_event(input, 0,
RDP_SCANCODE_CODE(RDP_SCANCODE_NUMLOCK));
/* Control up (0x1D) */
input_send_keyboard_event(input, KBD_FLAGS_RELEASE,
RDP_SCANCODE_CODE(RDP_SCANCODE_LCONTROL));
/* Numlock up (0x45) */
input_send_keyboard_event(input, KBD_FLAGS_RELEASE,
RDP_SCANCODE_CODE(RDP_SCANCODE_NUMLOCK));
}
void input_send_fastpath_synchronize_event(rdpInput* input, UINT32 flags)
{
wStream* s;
@ -250,6 +271,39 @@ void input_send_fastpath_focus_in_event(rdpInput* input, UINT16 toggleStates, UI
fastpath_send_multiple_input_pdu(rdp->fastpath, s, 4);
}
static void input_send_fastpath_keyboard_pause_event(rdpInput* input)
{
/* In ancient days, pause-down without control sent E1 1D 45 E1 9D C5,
* and pause-up sent nothing. However, reverse engineering mstsc shows
* it sending the following sequence:
*/
wStream* s;
rdpRdp* rdp = input->context->rdp;
const BYTE keyDownEvent = FASTPATH_INPUT_EVENT_SCANCODE << 5;
const BYTE keyUpEvent = (FASTPATH_INPUT_EVENT_SCANCODE << 5)
| FASTPATH_INPUT_KBDFLAGS_RELEASE;
s = fastpath_input_pdu_init_header(rdp->fastpath);
/* Control down (0x1D) */
Stream_Write_UINT8(s, keyDownEvent | FASTPATH_INPUT_KBDFLAGS_PREFIX_E1);
Stream_Write_UINT8(s, RDP_SCANCODE_CODE(RDP_SCANCODE_LCONTROL));
/* Numlock down (0x45) */
Stream_Write_UINT8(s, keyDownEvent);
Stream_Write_UINT8(s, RDP_SCANCODE_CODE(RDP_SCANCODE_NUMLOCK));
/* Control up (0x1D) */
Stream_Write_UINT8(s, keyUpEvent | FASTPATH_INPUT_KBDFLAGS_PREFIX_E1);
Stream_Write_UINT8(s, RDP_SCANCODE_CODE(RDP_SCANCODE_LCONTROL));
/* Numlock down (0x45) */
Stream_Write_UINT8(s, keyUpEvent);
Stream_Write_UINT8(s, RDP_SCANCODE_CODE(RDP_SCANCODE_NUMLOCK));
fastpath_send_multiple_input_pdu(rdp->fastpath, s, 4);
}
static BOOL input_recv_sync_event(rdpInput* input, wStream* s)
{
UINT32 toggleFlags;
@ -420,6 +474,7 @@ void input_register_client_callbacks(rdpInput* input)
{
input->SynchronizeEvent = input_send_fastpath_synchronize_event;
input->KeyboardEvent = input_send_fastpath_keyboard_event;
input->KeyboardPauseEvent = input_send_fastpath_keyboard_pause_event;
input->UnicodeKeyboardEvent = input_send_fastpath_unicode_keyboard_event;
input->MouseEvent = input_send_fastpath_mouse_event;
input->ExtendedMouseEvent = input_send_fastpath_extended_mouse_event;
@ -429,6 +484,7 @@ void input_register_client_callbacks(rdpInput* input)
{
input->SynchronizeEvent = input_send_synchronize_event;
input->KeyboardEvent = input_send_keyboard_event;
input->KeyboardPauseEvent = input_send_keyboard_pause_event;
input->UnicodeKeyboardEvent = input_send_unicode_keyboard_event;
input->MouseEvent = input_send_mouse_event;
input->ExtendedMouseEvent = input_send_extended_mouse_event;
@ -481,6 +537,11 @@ void freerdp_input_send_focus_in_event(rdpInput* input, UINT16 toggleStates, UIN
IFCALL(input->FocusInEvent, input, toggleStates, x, y);
}
void freerdp_input_send_keyboard_pause_event(rdpInput* input)
{
IFCALL(input->KeyboardPauseEvent, input);
}
int input_process_events(rdpInput* input)
{
return input_message_queue_process_pending_messages(input);