2011-07-28 04:14:12 +04:00
|
|
|
/**
|
2012-10-09 07:02:04 +04:00
|
|
|
* FreeRDP: A Remote Desktop Protocol Implementation
|
2011-07-28 04:14:12 +04:00
|
|
|
* Input PDUs
|
|
|
|
*
|
|
|
|
* Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
|
|
|
|
2022-02-16 13:20:38 +03:00
|
|
|
#include <freerdp/config.h>
|
2012-08-15 01:09:01 +04:00
|
|
|
|
2012-11-22 04:22:41 +04:00
|
|
|
#include <winpr/crt.h>
|
2021-06-16 15:50:14 +03:00
|
|
|
#include <winpr/assert.h>
|
2012-11-22 04:22:41 +04:00
|
|
|
|
2012-02-14 02:51:42 +04:00
|
|
|
#include <freerdp/input.h>
|
2014-09-12 16:36:29 +04:00
|
|
|
#include <freerdp/log.h>
|
2012-02-14 02:51:42 +04:00
|
|
|
|
2013-02-04 20:05:24 +04:00
|
|
|
#include "message.h"
|
|
|
|
|
2011-07-28 04:14:12 +04:00
|
|
|
#include "input.h"
|
|
|
|
|
2014-09-12 16:36:29 +04:00
|
|
|
#define TAG FREERDP_TAG("core")
|
|
|
|
|
2017-07-31 13:16:47 +03:00
|
|
|
/* Input Events */
|
2019-11-06 17:24:51 +03:00
|
|
|
#define INPUT_EVENT_SYNC 0x0000
|
|
|
|
#define INPUT_EVENT_SCANCODE 0x0004
|
|
|
|
#define INPUT_EVENT_UNICODE 0x0005
|
|
|
|
#define INPUT_EVENT_MOUSE 0x8001
|
|
|
|
#define INPUT_EVENT_MOUSEX 0x8002
|
2017-07-31 13:16:47 +03:00
|
|
|
|
2022-04-19 15:29:17 +03:00
|
|
|
#define RDP_CLIENT_INPUT_PDU_HEADER_LENGTH 4
|
|
|
|
|
2015-04-14 11:14:23 +03:00
|
|
|
static void rdp_write_client_input_pdu_header(wStream* s, UINT16 number)
|
2011-07-28 04:14:12 +04:00
|
|
|
{
|
2022-04-19 15:29:17 +03:00
|
|
|
WINPR_ASSERT(s);
|
|
|
|
WINPR_ASSERT(Stream_GetRemainingCapacity(s) >= 4);
|
2022-04-13 10:34:05 +03:00
|
|
|
Stream_Write_UINT16(s, number); /* numberEvents (2 bytes) */
|
2022-06-23 08:57:38 +03:00
|
|
|
Stream_Write_UINT16(s, 0); /* pad2Octets (2 bytes) */
|
2011-07-28 04:14:12 +04:00
|
|
|
}
|
|
|
|
|
2015-04-14 11:14:23 +03:00
|
|
|
static void rdp_write_input_event_header(wStream* s, UINT32 time, UINT16 type)
|
2011-08-01 20:24:29 +04:00
|
|
|
{
|
2022-04-19 15:29:17 +03:00
|
|
|
WINPR_ASSERT(s);
|
|
|
|
WINPR_ASSERT(Stream_GetRemainingCapacity(s) >= 6);
|
2013-05-09 00:09:16 +04:00
|
|
|
Stream_Write_UINT32(s, time); /* eventTime (4 bytes) */
|
|
|
|
Stream_Write_UINT16(s, type); /* messageType (2 bytes) */
|
2011-08-01 20:24:29 +04:00
|
|
|
}
|
|
|
|
|
2017-07-31 13:16:47 +03:00
|
|
|
static wStream* rdp_client_input_pdu_init(rdpRdp* rdp, UINT16 type)
|
2011-07-28 04:14:12 +04:00
|
|
|
{
|
2013-03-21 23:19:33 +04:00
|
|
|
wStream* s;
|
2011-07-28 04:14:12 +04:00
|
|
|
s = rdp_data_pdu_init(rdp);
|
2016-11-24 15:18:41 +03:00
|
|
|
|
2015-04-14 11:14:23 +03:00
|
|
|
if (!s)
|
|
|
|
return NULL;
|
2016-11-24 15:18:41 +03:00
|
|
|
|
2011-07-28 04:14:12 +04:00
|
|
|
rdp_write_client_input_pdu_header(s, 1);
|
2011-08-01 20:24:29 +04:00
|
|
|
rdp_write_input_event_header(s, 0, type);
|
2011-07-28 04:14:12 +04:00
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
2017-07-31 13:16:47 +03:00
|
|
|
static BOOL rdp_send_client_input_pdu(rdpRdp* rdp, wStream* s)
|
2011-07-28 04:14:12 +04:00
|
|
|
{
|
2015-04-14 11:14:23 +03:00
|
|
|
return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_INPUT, rdp->mcs->userId);
|
2011-07-28 04:14:12 +04:00
|
|
|
}
|
|
|
|
|
2015-04-14 11:14:23 +03:00
|
|
|
static void input_write_synchronize_event(wStream* s, UINT32 flags)
|
2011-07-28 04:14:12 +04:00
|
|
|
{
|
2022-04-19 15:29:17 +03:00
|
|
|
WINPR_ASSERT(s);
|
|
|
|
WINPR_ASSERT(Stream_GetRemainingCapacity(s) >= 6);
|
2019-11-06 17:24:51 +03:00
|
|
|
Stream_Write_UINT16(s, 0); /* pad2Octets (2 bytes) */
|
2013-05-09 00:09:16 +04:00
|
|
|
Stream_Write_UINT32(s, flags); /* toggleFlags (4 bytes) */
|
2011-07-28 04:14:12 +04:00
|
|
|
}
|
|
|
|
|
2017-07-31 13:16:47 +03:00
|
|
|
static BOOL input_send_synchronize_event(rdpInput* input, UINT32 flags)
|
2011-07-28 04:14:12 +04:00
|
|
|
{
|
2013-03-21 23:19:33 +04:00
|
|
|
wStream* s;
|
2016-04-13 10:47:48 +03:00
|
|
|
rdpRdp* rdp;
|
|
|
|
|
|
|
|
if (!input || !input->context)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
rdp = input->context->rdp;
|
2022-06-24 17:26:51 +03:00
|
|
|
|
|
|
|
if (freerdp_shall_disconnect_context(input->context))
|
|
|
|
return FALSE;
|
|
|
|
|
2011-10-16 08:50:10 +04:00
|
|
|
s = rdp_client_input_pdu_init(rdp, INPUT_EVENT_SYNC);
|
2016-11-24 15:18:41 +03:00
|
|
|
|
2015-04-14 11:14:23 +03:00
|
|
|
if (!s)
|
|
|
|
return FALSE;
|
2016-11-24 15:18:41 +03:00
|
|
|
|
2011-07-28 04:14:12 +04:00
|
|
|
input_write_synchronize_event(s, flags);
|
2015-04-14 11:14:23 +03:00
|
|
|
return rdp_send_client_input_pdu(rdp, s);
|
2011-07-28 04:14:12 +04:00
|
|
|
}
|
|
|
|
|
2015-04-14 11:14:23 +03:00
|
|
|
static void input_write_keyboard_event(wStream* s, UINT16 flags, UINT16 code)
|
2011-07-28 04:14:12 +04:00
|
|
|
{
|
2022-04-13 10:34:05 +03:00
|
|
|
WINPR_ASSERT(s);
|
|
|
|
WINPR_ASSERT(code <= UINT8_MAX);
|
|
|
|
|
2013-05-09 00:09:16 +04:00
|
|
|
Stream_Write_UINT16(s, flags); /* keyboardFlags (2 bytes) */
|
2019-11-06 17:24:51 +03:00
|
|
|
Stream_Write_UINT16(s, code); /* keyCode (2 bytes) */
|
|
|
|
Stream_Write_UINT16(s, 0); /* pad2Octets (2 bytes) */
|
2011-07-28 04:14:12 +04:00
|
|
|
}
|
|
|
|
|
2022-04-13 10:34:05 +03:00
|
|
|
static BOOL input_send_keyboard_event(rdpInput* input, UINT16 flags, UINT8 code)
|
2011-07-28 04:14:12 +04:00
|
|
|
{
|
2013-03-21 23:19:33 +04:00
|
|
|
wStream* s;
|
2016-04-13 10:47:48 +03:00
|
|
|
rdpRdp* rdp;
|
|
|
|
|
|
|
|
if (!input || !input->context)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
rdp = input->context->rdp;
|
2022-06-24 17:26:51 +03:00
|
|
|
|
|
|
|
if (freerdp_shall_disconnect_context(input->context))
|
|
|
|
return FALSE;
|
|
|
|
|
2011-10-16 08:50:10 +04:00
|
|
|
s = rdp_client_input_pdu_init(rdp, INPUT_EVENT_SCANCODE);
|
2016-11-24 15:18:41 +03:00
|
|
|
|
2015-04-14 11:14:23 +03:00
|
|
|
if (!s)
|
|
|
|
return FALSE;
|
2016-11-24 15:18:41 +03:00
|
|
|
|
2011-07-28 04:14:12 +04:00
|
|
|
input_write_keyboard_event(s, flags, code);
|
2015-04-14 11:14:23 +03:00
|
|
|
return rdp_send_client_input_pdu(rdp, s);
|
2011-07-28 04:14:12 +04:00
|
|
|
}
|
|
|
|
|
2015-04-14 11:14:23 +03:00
|
|
|
static void input_write_unicode_keyboard_event(wStream* s, UINT16 flags, UINT16 code)
|
2011-07-28 04:14:12 +04:00
|
|
|
{
|
2013-05-09 00:09:16 +04:00
|
|
|
Stream_Write_UINT16(s, flags); /* keyboardFlags (2 bytes) */
|
2019-11-06 17:24:51 +03:00
|
|
|
Stream_Write_UINT16(s, code); /* unicodeCode (2 bytes) */
|
|
|
|
Stream_Write_UINT16(s, 0); /* pad2Octets (2 bytes) */
|
2011-07-28 04:14:12 +04:00
|
|
|
}
|
|
|
|
|
2017-07-31 13:16:47 +03:00
|
|
|
static BOOL input_send_unicode_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code)
|
2011-07-28 04:14:12 +04:00
|
|
|
{
|
2013-03-21 23:19:33 +04:00
|
|
|
wStream* s;
|
2016-04-13 10:47:48 +03:00
|
|
|
rdpRdp* rdp;
|
|
|
|
|
|
|
|
if (!input || !input->context)
|
|
|
|
return FALSE;
|
|
|
|
|
2022-06-24 17:26:51 +03:00
|
|
|
if (freerdp_shall_disconnect_context(input->context))
|
|
|
|
return FALSE;
|
|
|
|
|
2022-05-02 11:55:44 +03:00
|
|
|
if (!freerdp_settings_get_bool(input->context->settings, FreeRDP_UnicodeInput))
|
2017-07-31 13:16:47 +03:00
|
|
|
{
|
|
|
|
WLog_WARN(TAG, "Unicode input not supported by server.");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2016-04-13 10:47:48 +03:00
|
|
|
rdp = input->context->rdp;
|
2011-10-16 08:50:10 +04:00
|
|
|
s = rdp_client_input_pdu_init(rdp, INPUT_EVENT_UNICODE);
|
2016-11-24 15:18:41 +03:00
|
|
|
|
2015-04-14 11:14:23 +03:00
|
|
|
if (!s)
|
|
|
|
return FALSE;
|
2016-11-24 15:18:41 +03:00
|
|
|
|
2012-02-07 15:22:01 +04:00
|
|
|
input_write_unicode_keyboard_event(s, flags, code);
|
2015-04-14 11:14:23 +03:00
|
|
|
return rdp_send_client_input_pdu(rdp, s);
|
2011-07-28 04:14:12 +04:00
|
|
|
}
|
|
|
|
|
2017-07-31 13:16:47 +03:00
|
|
|
static void input_write_mouse_event(wStream* s, UINT16 flags, UINT16 x, UINT16 y)
|
2011-07-28 04:14:12 +04:00
|
|
|
{
|
2013-05-09 00:09:16 +04:00
|
|
|
Stream_Write_UINT16(s, flags); /* pointerFlags (2 bytes) */
|
2019-11-06 17:24:51 +03:00
|
|
|
Stream_Write_UINT16(s, x); /* xPos (2 bytes) */
|
|
|
|
Stream_Write_UINT16(s, y); /* yPos (2 bytes) */
|
2011-07-28 04:14:12 +04:00
|
|
|
}
|
|
|
|
|
2017-07-31 13:16:47 +03:00
|
|
|
static BOOL input_send_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y)
|
2011-07-28 04:14:12 +04:00
|
|
|
{
|
2013-03-21 23:19:33 +04:00
|
|
|
wStream* s;
|
2016-04-13 10:47:48 +03:00
|
|
|
rdpRdp* rdp;
|
|
|
|
|
2016-11-24 15:18:41 +03:00
|
|
|
if (!input || !input->context || !input->context->settings)
|
2016-04-13 10:47:48 +03:00
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
rdp = input->context->rdp;
|
2011-10-16 08:50:10 +04:00
|
|
|
|
2022-06-24 17:26:51 +03:00
|
|
|
if (freerdp_shall_disconnect_context(input->context))
|
|
|
|
return FALSE;
|
|
|
|
|
2022-05-02 11:55:44 +03:00
|
|
|
if (!freerdp_settings_get_bool(input->context->settings, FreeRDP_HasHorizontalWheel))
|
2016-11-24 15:18:41 +03:00
|
|
|
{
|
|
|
|
if (flags & PTR_FLAGS_HWHEEL)
|
|
|
|
{
|
2019-05-16 16:14:16 +03:00
|
|
|
WLog_WARN(TAG,
|
2019-11-06 17:24:51 +03:00
|
|
|
"skip mouse event %" PRIu16 "x%" PRIu16 " flags=0x%04" PRIX16
|
|
|
|
", no horizontal mouse wheel supported",
|
2016-11-24 15:18:41 +03:00
|
|
|
x, y, flags);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-10-16 08:50:10 +04:00
|
|
|
s = rdp_client_input_pdu_init(rdp, INPUT_EVENT_MOUSE);
|
2016-11-24 15:18:41 +03:00
|
|
|
|
2015-04-14 11:14:23 +03:00
|
|
|
if (!s)
|
|
|
|
return FALSE;
|
2016-11-24 15:18:41 +03:00
|
|
|
|
2011-07-28 04:14:12 +04:00
|
|
|
input_write_mouse_event(s, flags, x, y);
|
2015-04-14 11:14:23 +03:00
|
|
|
return rdp_send_client_input_pdu(rdp, s);
|
2011-07-28 04:14:12 +04:00
|
|
|
}
|
|
|
|
|
2015-04-14 11:14:23 +03:00
|
|
|
static void input_write_extended_mouse_event(wStream* s, UINT16 flags, UINT16 x, UINT16 y)
|
2011-07-28 04:14:12 +04:00
|
|
|
{
|
2013-05-09 00:09:16 +04:00
|
|
|
Stream_Write_UINT16(s, flags); /* pointerFlags (2 bytes) */
|
2019-11-06 17:24:51 +03:00
|
|
|
Stream_Write_UINT16(s, x); /* xPos (2 bytes) */
|
|
|
|
Stream_Write_UINT16(s, y); /* yPos (2 bytes) */
|
2011-07-28 04:14:12 +04:00
|
|
|
}
|
|
|
|
|
2019-11-06 17:24:51 +03:00
|
|
|
static BOOL input_send_extended_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y)
|
2011-07-28 04:14:12 +04:00
|
|
|
{
|
2013-03-21 23:19:33 +04:00
|
|
|
wStream* s;
|
2016-04-13 10:47:48 +03:00
|
|
|
rdpRdp* rdp;
|
|
|
|
|
2022-04-19 15:29:17 +03:00
|
|
|
WINPR_ASSERT(input);
|
|
|
|
WINPR_ASSERT(input->context);
|
|
|
|
WINPR_ASSERT(input->context->settings);
|
|
|
|
|
|
|
|
rdp = input->context->rdp;
|
|
|
|
WINPR_ASSERT(rdp);
|
2016-04-13 10:47:48 +03:00
|
|
|
|
2022-06-24 17:26:51 +03:00
|
|
|
if (freerdp_shall_disconnect_context(input->context))
|
|
|
|
return FALSE;
|
|
|
|
|
2022-05-02 11:55:44 +03:00
|
|
|
if (!freerdp_settings_get_bool(input->context->settings, FreeRDP_HasExtendedMouseEvent))
|
2017-07-31 13:16:47 +03:00
|
|
|
{
|
2019-05-16 16:14:16 +03:00
|
|
|
WLog_WARN(TAG,
|
2019-11-06 17:24:51 +03:00
|
|
|
"skip extended mouse event %" PRIu16 "x%" PRIu16 " flags=0x%04" PRIX16
|
|
|
|
", no extended mouse events supported",
|
2017-07-31 13:16:47 +03:00
|
|
|
x, y, flags);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2011-10-16 08:50:10 +04:00
|
|
|
s = rdp_client_input_pdu_init(rdp, INPUT_EVENT_MOUSEX);
|
2016-11-24 15:18:41 +03:00
|
|
|
|
2015-04-14 11:14:23 +03:00
|
|
|
if (!s)
|
|
|
|
return FALSE;
|
2016-11-24 15:18:41 +03:00
|
|
|
|
2011-07-28 04:14:12 +04:00
|
|
|
input_write_extended_mouse_event(s, flags, x, y);
|
2015-04-14 11:14:23 +03:00
|
|
|
return rdp_send_client_input_pdu(rdp, s);
|
2011-07-28 04:14:12 +04:00
|
|
|
}
|
|
|
|
|
2017-07-31 13:16:47 +03:00
|
|
|
static BOOL input_send_focus_in_event(rdpInput* input, UINT16 toggleStates)
|
2013-04-15 14:14:09 +04:00
|
|
|
{
|
|
|
|
/* send a tab up like mstsc.exe */
|
2015-04-14 11:14:23 +03:00
|
|
|
if (!input_send_keyboard_event(input, KBD_FLAGS_RELEASE, 0x0f))
|
|
|
|
return FALSE;
|
2013-04-15 14:14:09 +04:00
|
|
|
|
|
|
|
/* send the toggle key states */
|
2015-04-14 11:14:23 +03:00
|
|
|
if (!input_send_synchronize_event(input, (toggleStates & 0x1F)))
|
|
|
|
return FALSE;
|
2013-04-15 14:14:09 +04:00
|
|
|
|
|
|
|
/* send another tab up like mstsc.exe */
|
2015-04-14 11:14:23 +03:00
|
|
|
return input_send_keyboard_event(input, KBD_FLAGS_RELEASE, 0x0f);
|
2013-04-15 14:14:09 +04:00
|
|
|
}
|
|
|
|
|
2017-07-31 13:16:47 +03:00
|
|
|
static BOOL input_send_keyboard_pause_event(rdpInput* input)
|
2014-06-05 01:41:17 +04:00
|
|
|
{
|
|
|
|
/* 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) */
|
2019-05-16 16:14:16 +03:00
|
|
|
if (!input_send_keyboard_event(input, KBD_FLAGS_EXTENDED1,
|
2016-11-24 15:18:41 +03:00
|
|
|
RDP_SCANCODE_CODE(RDP_SCANCODE_LCONTROL)))
|
2015-04-14 11:14:23 +03:00
|
|
|
return FALSE;
|
|
|
|
|
2014-06-05 01:41:17 +04:00
|
|
|
/* Numlock down (0x45) */
|
2019-11-06 17:24:51 +03:00
|
|
|
if (!input_send_keyboard_event(input, 0, RDP_SCANCODE_CODE(RDP_SCANCODE_NUMLOCK)))
|
2015-04-14 11:14:23 +03:00
|
|
|
return FALSE;
|
|
|
|
|
2014-06-05 01:41:17 +04:00
|
|
|
/* Control up (0x1D) */
|
2019-05-16 16:14:16 +03:00
|
|
|
if (!input_send_keyboard_event(input, KBD_FLAGS_RELEASE | KBD_FLAGS_EXTENDED1,
|
2016-11-24 15:18:41 +03:00
|
|
|
RDP_SCANCODE_CODE(RDP_SCANCODE_LCONTROL)))
|
2015-04-14 11:14:23 +03:00
|
|
|
return FALSE;
|
|
|
|
|
2014-06-05 01:41:17 +04:00
|
|
|
/* Numlock up (0x45) */
|
2015-04-14 11:14:23 +03:00
|
|
|
return input_send_keyboard_event(input, KBD_FLAGS_RELEASE,
|
2016-11-24 15:18:41 +03:00
|
|
|
RDP_SCANCODE_CODE(RDP_SCANCODE_NUMLOCK));
|
2014-06-05 01:41:17 +04:00
|
|
|
}
|
|
|
|
|
2017-07-31 13:16:47 +03:00
|
|
|
static BOOL input_send_fastpath_synchronize_event(rdpInput* input, UINT32 flags)
|
2011-08-16 10:37:11 +04:00
|
|
|
{
|
2013-03-21 23:19:33 +04:00
|
|
|
wStream* s;
|
2016-04-13 10:47:48 +03:00
|
|
|
rdpRdp* rdp;
|
|
|
|
|
2022-04-19 15:29:17 +03:00
|
|
|
WINPR_ASSERT(input);
|
|
|
|
WINPR_ASSERT(input->context);
|
2016-04-13 10:47:48 +03:00
|
|
|
|
|
|
|
rdp = input->context->rdp;
|
2022-04-19 15:29:17 +03:00
|
|
|
WINPR_ASSERT(rdp);
|
|
|
|
|
2022-06-24 17:26:51 +03:00
|
|
|
if (freerdp_shall_disconnect_context(input->context))
|
|
|
|
return FALSE;
|
|
|
|
|
2011-08-16 10:37:11 +04:00
|
|
|
/* The FastPath Synchronization eventFlags has identical values as SlowPath */
|
2019-11-06 17:24:51 +03:00
|
|
|
s = fastpath_input_pdu_init(rdp->fastpath, (BYTE)flags, FASTPATH_INPUT_EVENT_SYNC);
|
2016-11-24 15:18:41 +03:00
|
|
|
|
2015-04-14 11:14:23 +03:00
|
|
|
if (!s)
|
|
|
|
return FALSE;
|
2016-11-24 15:18:41 +03:00
|
|
|
|
2015-04-14 11:14:23 +03:00
|
|
|
return fastpath_send_input_pdu(rdp->fastpath, s);
|
2011-08-16 10:37:11 +04:00
|
|
|
}
|
|
|
|
|
2022-04-13 10:34:05 +03:00
|
|
|
static BOOL input_send_fastpath_keyboard_event(rdpInput* input, UINT16 flags, UINT8 code)
|
2011-08-16 10:37:11 +04:00
|
|
|
{
|
2013-03-21 23:19:33 +04:00
|
|
|
wStream* s;
|
2012-10-09 11:01:37 +04:00
|
|
|
BYTE eventFlags = 0;
|
2016-04-13 10:47:48 +03:00
|
|
|
rdpRdp* rdp;
|
|
|
|
|
2022-04-19 15:29:17 +03:00
|
|
|
WINPR_ASSERT(input);
|
|
|
|
WINPR_ASSERT(input->context);
|
2016-04-13 10:47:48 +03:00
|
|
|
|
|
|
|
rdp = input->context->rdp;
|
2022-04-19 15:29:17 +03:00
|
|
|
WINPR_ASSERT(rdp);
|
|
|
|
|
2022-06-24 17:26:51 +03:00
|
|
|
if (freerdp_shall_disconnect_context(input->context))
|
|
|
|
return FALSE;
|
|
|
|
|
2011-08-16 10:37:11 +04:00
|
|
|
eventFlags |= (flags & KBD_FLAGS_RELEASE) ? FASTPATH_INPUT_KBDFLAGS_RELEASE : 0;
|
|
|
|
eventFlags |= (flags & KBD_FLAGS_EXTENDED) ? FASTPATH_INPUT_KBDFLAGS_EXTENDED : 0;
|
2019-05-16 16:14:16 +03:00
|
|
|
eventFlags |= (flags & KBD_FLAGS_EXTENDED1) ? FASTPATH_INPUT_KBDFLAGS_PREFIX_E1 : 0;
|
2011-08-23 11:51:51 +04:00
|
|
|
s = fastpath_input_pdu_init(rdp->fastpath, eventFlags, FASTPATH_INPUT_EVENT_SCANCODE);
|
2016-11-24 15:18:41 +03:00
|
|
|
|
2015-04-14 11:14:23 +03:00
|
|
|
if (!s)
|
|
|
|
return FALSE;
|
2016-11-24 15:18:41 +03:00
|
|
|
|
2021-06-16 15:50:14 +03:00
|
|
|
WINPR_ASSERT(code <= UINT8_MAX);
|
|
|
|
Stream_Write_UINT8(s, (UINT8)code); /* keyCode (1 byte) */
|
2015-04-14 11:14:23 +03:00
|
|
|
return fastpath_send_input_pdu(rdp->fastpath, s);
|
2011-08-16 10:37:11 +04:00
|
|
|
}
|
|
|
|
|
2017-07-31 13:16:47 +03:00
|
|
|
static BOOL input_send_fastpath_unicode_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code)
|
2011-08-16 10:37:11 +04:00
|
|
|
{
|
2013-03-21 23:19:33 +04:00
|
|
|
wStream* s;
|
2012-10-09 11:01:37 +04:00
|
|
|
BYTE eventFlags = 0;
|
2016-04-13 10:47:48 +03:00
|
|
|
rdpRdp* rdp;
|
|
|
|
|
2022-04-19 15:29:17 +03:00
|
|
|
WINPR_ASSERT(input);
|
|
|
|
WINPR_ASSERT(input->context);
|
|
|
|
WINPR_ASSERT(input->context->settings);
|
|
|
|
|
|
|
|
rdp = input->context->rdp;
|
|
|
|
WINPR_ASSERT(rdp);
|
2016-04-13 10:47:48 +03:00
|
|
|
|
2022-06-24 17:26:51 +03:00
|
|
|
if (freerdp_shall_disconnect_context(input->context))
|
|
|
|
return FALSE;
|
|
|
|
|
2022-05-02 11:55:44 +03:00
|
|
|
if (!freerdp_settings_get_bool(input->context->settings, FreeRDP_UnicodeInput))
|
2017-07-31 13:16:47 +03:00
|
|
|
{
|
|
|
|
WLog_WARN(TAG, "Unicode input not supported by server.");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2012-02-07 15:22:01 +04:00
|
|
|
eventFlags |= (flags & KBD_FLAGS_RELEASE) ? FASTPATH_INPUT_KBDFLAGS_RELEASE : 0;
|
|
|
|
s = fastpath_input_pdu_init(rdp->fastpath, eventFlags, FASTPATH_INPUT_EVENT_UNICODE);
|
2016-11-24 15:18:41 +03:00
|
|
|
|
2015-04-14 11:14:23 +03:00
|
|
|
if (!s)
|
|
|
|
return FALSE;
|
2016-11-24 15:18:41 +03:00
|
|
|
|
2013-05-09 00:09:16 +04:00
|
|
|
Stream_Write_UINT16(s, code); /* unicodeCode (2 bytes) */
|
2015-04-14 11:14:23 +03:00
|
|
|
return fastpath_send_input_pdu(rdp->fastpath, s);
|
2011-08-16 10:37:11 +04:00
|
|
|
}
|
|
|
|
|
2019-11-06 17:24:51 +03:00
|
|
|
static BOOL input_send_fastpath_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y)
|
2011-08-16 10:37:11 +04:00
|
|
|
{
|
2013-03-21 23:19:33 +04:00
|
|
|
wStream* s;
|
2016-04-13 10:47:48 +03:00
|
|
|
rdpRdp* rdp;
|
|
|
|
|
2022-04-19 15:29:17 +03:00
|
|
|
WINPR_ASSERT(input);
|
|
|
|
WINPR_ASSERT(input->context);
|
|
|
|
WINPR_ASSERT(input->context->settings);
|
2016-04-13 10:47:48 +03:00
|
|
|
|
|
|
|
rdp = input->context->rdp;
|
2022-04-19 15:29:17 +03:00
|
|
|
WINPR_ASSERT(rdp);
|
2011-08-23 11:51:51 +04:00
|
|
|
|
2022-06-24 17:26:51 +03:00
|
|
|
if (freerdp_shall_disconnect_context(input->context))
|
|
|
|
return FALSE;
|
|
|
|
|
2022-05-02 11:55:44 +03:00
|
|
|
if (!freerdp_settings_get_bool(input->context->settings, FreeRDP_HasHorizontalWheel))
|
2016-11-24 15:18:41 +03:00
|
|
|
{
|
|
|
|
if (flags & PTR_FLAGS_HWHEEL)
|
|
|
|
{
|
2019-05-16 16:14:16 +03:00
|
|
|
WLog_WARN(TAG,
|
2019-11-06 17:24:51 +03:00
|
|
|
"skip mouse event %" PRIu16 "x%" PRIu16 " flags=0x%04" PRIX16
|
|
|
|
", no horizontal mouse wheel supported",
|
2016-11-24 15:18:41 +03:00
|
|
|
x, y, flags);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-08-23 11:51:51 +04:00
|
|
|
s = fastpath_input_pdu_init(rdp->fastpath, 0, FASTPATH_INPUT_EVENT_MOUSE);
|
2016-11-24 15:18:41 +03:00
|
|
|
|
2015-04-14 11:14:23 +03:00
|
|
|
if (!s)
|
|
|
|
return FALSE;
|
2016-11-24 15:18:41 +03:00
|
|
|
|
2011-08-16 10:37:11 +04:00
|
|
|
input_write_mouse_event(s, flags, x, y);
|
2015-04-14 11:14:23 +03:00
|
|
|
return fastpath_send_input_pdu(rdp->fastpath, s);
|
2011-08-16 10:37:11 +04:00
|
|
|
}
|
|
|
|
|
2019-11-06 17:24:51 +03:00
|
|
|
static BOOL input_send_fastpath_extended_mouse_event(rdpInput* input, UINT16 flags, UINT16 x,
|
|
|
|
UINT16 y)
|
2011-08-16 10:37:11 +04:00
|
|
|
{
|
2013-03-21 23:19:33 +04:00
|
|
|
wStream* s;
|
2016-04-13 10:47:48 +03:00
|
|
|
rdpRdp* rdp;
|
|
|
|
|
2022-04-19 15:29:17 +03:00
|
|
|
WINPR_ASSERT(input);
|
|
|
|
WINPR_ASSERT(input->context);
|
|
|
|
|
|
|
|
rdp = input->context->rdp;
|
|
|
|
WINPR_ASSERT(rdp);
|
2016-04-13 10:47:48 +03:00
|
|
|
|
2022-06-24 17:26:51 +03:00
|
|
|
if (freerdp_shall_disconnect_context(input->context))
|
|
|
|
return FALSE;
|
|
|
|
|
2022-05-02 11:55:44 +03:00
|
|
|
if (!freerdp_settings_get_bool(input->context->settings, FreeRDP_HasExtendedMouseEvent))
|
2017-07-31 13:16:47 +03:00
|
|
|
{
|
2019-05-16 16:14:16 +03:00
|
|
|
WLog_WARN(TAG,
|
2019-11-06 17:24:51 +03:00
|
|
|
"skip extended mouse event %" PRIu16 "x%" PRIu16 " flags=0x%04" PRIX16
|
|
|
|
", no extended mouse events supported",
|
2017-07-31 13:16:47 +03:00
|
|
|
x, y, flags);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2011-08-23 11:51:51 +04:00
|
|
|
s = fastpath_input_pdu_init(rdp->fastpath, 0, FASTPATH_INPUT_EVENT_MOUSEX);
|
2016-11-24 15:18:41 +03:00
|
|
|
|
2015-04-14 11:14:23 +03:00
|
|
|
if (!s)
|
|
|
|
return FALSE;
|
2016-11-24 15:18:41 +03:00
|
|
|
|
2011-08-16 10:37:11 +04:00
|
|
|
input_write_extended_mouse_event(s, flags, x, y);
|
2015-04-14 11:14:23 +03:00
|
|
|
return fastpath_send_input_pdu(rdp->fastpath, s);
|
2011-08-16 10:37:11 +04:00
|
|
|
}
|
|
|
|
|
2017-07-31 13:16:47 +03:00
|
|
|
static BOOL input_send_fastpath_focus_in_event(rdpInput* input, UINT16 toggleStates)
|
2013-04-15 14:14:09 +04:00
|
|
|
{
|
|
|
|
wStream* s;
|
|
|
|
BYTE eventFlags = 0;
|
2016-04-13 10:47:48 +03:00
|
|
|
rdpRdp* rdp;
|
|
|
|
|
2022-04-19 15:29:17 +03:00
|
|
|
WINPR_ASSERT(input);
|
|
|
|
WINPR_ASSERT(input->context);
|
2016-04-13 10:47:48 +03:00
|
|
|
|
|
|
|
rdp = input->context->rdp;
|
2022-04-19 15:29:17 +03:00
|
|
|
WINPR_ASSERT(rdp);
|
|
|
|
|
2022-06-24 17:26:51 +03:00
|
|
|
if (freerdp_shall_disconnect_context(input->context))
|
|
|
|
return FALSE;
|
|
|
|
|
2013-04-15 14:14:09 +04:00
|
|
|
s = fastpath_input_pdu_init_header(rdp->fastpath);
|
2016-11-24 15:18:41 +03:00
|
|
|
|
2015-04-14 11:14:23 +03:00
|
|
|
if (!s)
|
|
|
|
return FALSE;
|
2016-11-24 15:18:41 +03:00
|
|
|
|
2013-04-15 14:14:09 +04:00
|
|
|
/* send a tab up like mstsc.exe */
|
|
|
|
eventFlags = FASTPATH_INPUT_KBDFLAGS_RELEASE | FASTPATH_INPUT_EVENT_SCANCODE << 5;
|
2013-05-09 00:09:16 +04:00
|
|
|
Stream_Write_UINT8(s, eventFlags); /* Key Release event (1 byte) */
|
2019-11-06 17:24:51 +03:00
|
|
|
Stream_Write_UINT8(s, 0x0f); /* keyCode (1 byte) */
|
2013-04-15 14:14:09 +04:00
|
|
|
/* send the toggle key states */
|
|
|
|
eventFlags = (toggleStates & 0x1F) | FASTPATH_INPUT_EVENT_SYNC << 5;
|
2013-05-09 00:09:16 +04:00
|
|
|
Stream_Write_UINT8(s, eventFlags); /* toggle state (1 byte) */
|
2013-04-15 14:14:09 +04:00
|
|
|
/* send another tab up like mstsc.exe */
|
|
|
|
eventFlags = FASTPATH_INPUT_KBDFLAGS_RELEASE | FASTPATH_INPUT_EVENT_SCANCODE << 5;
|
2013-05-09 00:09:16 +04:00
|
|
|
Stream_Write_UINT8(s, eventFlags); /* Key Release event (1 byte) */
|
2019-11-06 17:24:51 +03:00
|
|
|
Stream_Write_UINT8(s, 0x0f); /* keyCode (1 byte) */
|
2015-04-14 11:14:23 +03:00
|
|
|
return fastpath_send_multiple_input_pdu(rdp->fastpath, s, 3);
|
2013-04-15 14:14:09 +04:00
|
|
|
}
|
|
|
|
|
2017-07-31 13:16:47 +03:00
|
|
|
static BOOL input_send_fastpath_keyboard_pause_event(rdpInput* input)
|
2014-06-05 01:41:17 +04:00
|
|
|
{
|
|
|
|
/* 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;
|
|
|
|
const BYTE keyDownEvent = FASTPATH_INPUT_EVENT_SCANCODE << 5;
|
2019-11-06 17:24:51 +03:00
|
|
|
const BYTE keyUpEvent = (FASTPATH_INPUT_EVENT_SCANCODE << 5) | FASTPATH_INPUT_KBDFLAGS_RELEASE;
|
2016-04-13 10:47:48 +03:00
|
|
|
rdpRdp* rdp;
|
|
|
|
|
2022-04-19 15:29:17 +03:00
|
|
|
WINPR_ASSERT(input);
|
|
|
|
WINPR_ASSERT(input->context);
|
2016-04-13 10:47:48 +03:00
|
|
|
|
|
|
|
rdp = input->context->rdp;
|
2022-04-19 15:29:17 +03:00
|
|
|
WINPR_ASSERT(rdp);
|
|
|
|
|
2022-06-24 17:26:51 +03:00
|
|
|
if (freerdp_shall_disconnect_context(input->context))
|
|
|
|
return FALSE;
|
|
|
|
|
2014-06-05 01:41:17 +04:00
|
|
|
s = fastpath_input_pdu_init_header(rdp->fastpath);
|
2016-11-24 15:18:41 +03:00
|
|
|
|
2015-04-14 11:14:23 +03:00
|
|
|
if (!s)
|
|
|
|
return FALSE;
|
2014-06-05 01:41:17 +04:00
|
|
|
|
|
|
|
/* 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));
|
2015-04-14 11:14:23 +03:00
|
|
|
return fastpath_send_multiple_input_pdu(rdp->fastpath, s, 4);
|
2014-06-05 01:41:17 +04:00
|
|
|
}
|
|
|
|
|
2013-03-21 23:19:33 +04:00
|
|
|
static BOOL input_recv_sync_event(rdpInput* input, wStream* s)
|
2012-02-07 16:38:27 +04:00
|
|
|
{
|
2012-10-09 11:26:39 +04:00
|
|
|
UINT32 toggleFlags;
|
2012-02-07 16:38:27 +04:00
|
|
|
|
2022-04-19 15:29:17 +03:00
|
|
|
WINPR_ASSERT(input);
|
|
|
|
WINPR_ASSERT(s);
|
|
|
|
|
|
|
|
if (!Stream_CheckAndLogRequiredLength(TAG, s, 6))
|
2012-10-09 10:31:28 +04:00
|
|
|
return FALSE;
|
2012-02-07 16:38:27 +04:00
|
|
|
|
2019-11-06 17:24:51 +03:00
|
|
|
Stream_Seek(s, 2); /* pad2Octets (2 bytes) */
|
2013-05-09 00:09:16 +04:00
|
|
|
Stream_Read_UINT32(s, toggleFlags); /* toggleFlags (4 bytes) */
|
2015-04-17 17:21:55 +03:00
|
|
|
return IFCALLRESULT(TRUE, input->SynchronizeEvent, input, toggleFlags);
|
2012-02-07 16:38:27 +04:00
|
|
|
}
|
|
|
|
|
2013-03-21 23:19:33 +04:00
|
|
|
static BOOL input_recv_keyboard_event(rdpInput* input, wStream* s)
|
2012-02-07 16:38:27 +04:00
|
|
|
{
|
2012-10-09 11:01:37 +04:00
|
|
|
UINT16 keyboardFlags, keyCode;
|
2012-02-07 16:38:27 +04:00
|
|
|
|
2022-04-19 15:29:17 +03:00
|
|
|
WINPR_ASSERT(input);
|
|
|
|
WINPR_ASSERT(s);
|
|
|
|
|
|
|
|
if (!Stream_CheckAndLogRequiredLength(TAG, s, 6))
|
2012-10-09 10:31:28 +04:00
|
|
|
return FALSE;
|
2012-02-07 16:38:27 +04:00
|
|
|
|
2013-05-09 00:09:16 +04:00
|
|
|
Stream_Read_UINT16(s, keyboardFlags); /* keyboardFlags (2 bytes) */
|
2019-11-06 17:24:51 +03:00
|
|
|
Stream_Read_UINT16(s, keyCode); /* keyCode (2 bytes) */
|
|
|
|
Stream_Seek(s, 2); /* pad2Octets (2 bytes) */
|
2012-02-07 16:38:27 +04:00
|
|
|
|
2014-10-22 13:24:36 +04:00
|
|
|
/**
|
|
|
|
* Note: A lot of code in FreeRDP and in dependent projects checks the
|
|
|
|
* KBDFLAGS_DOWN flag in order to detect a key press.
|
|
|
|
* According to the specs only the absence of the slow-path
|
|
|
|
* KBDFLAGS_RELEASE flag indicates a key-down event.
|
|
|
|
* The slow-path KBDFLAGS_DOWN flag merely indicates that the key was
|
|
|
|
* down prior to this event.
|
|
|
|
* The checks for KBDFLAGS_DOWN only work successfully because the code
|
|
|
|
* handling the fast-path keyboard input sets the KBDFLAGS_DOWN flag if
|
|
|
|
* the FASTPATH_INPUT_KBDFLAGS_RELEASE flag is missing.
|
|
|
|
* Since the same input callback is used for slow- and fast-path events
|
|
|
|
* we have to follow that "convention" here.
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (keyboardFlags & KBD_FLAGS_RELEASE)
|
|
|
|
keyboardFlags &= ~KBD_FLAGS_DOWN;
|
|
|
|
else
|
|
|
|
keyboardFlags |= KBD_FLAGS_DOWN;
|
|
|
|
|
2022-04-13 10:34:05 +03:00
|
|
|
if (keyCode & 0xFF00)
|
|
|
|
WLog_WARN(TAG,
|
|
|
|
"Problematic [MS-RDPBCGR] 2.2.8.1.1.3.1.1.1 Keyboard Event (TS_KEYBOARD_EVENT) "
|
|
|
|
"keyCode=0x%04" PRIx16
|
|
|
|
", high byte values should be sent in keyboardFlags field, ignoring.",
|
|
|
|
keyCode);
|
|
|
|
return IFCALLRESULT(TRUE, input->KeyboardEvent, input, keyboardFlags, keyCode & 0xFF);
|
2012-02-07 16:38:27 +04:00
|
|
|
}
|
|
|
|
|
2013-03-21 23:19:33 +04:00
|
|
|
static BOOL input_recv_unicode_keyboard_event(rdpInput* input, wStream* s)
|
2012-02-07 16:38:27 +04:00
|
|
|
{
|
2012-10-09 11:01:37 +04:00
|
|
|
UINT16 keyboardFlags, unicodeCode;
|
2012-02-07 16:38:27 +04:00
|
|
|
|
2022-04-19 15:29:17 +03:00
|
|
|
WINPR_ASSERT(input);
|
|
|
|
WINPR_ASSERT(s);
|
|
|
|
|
|
|
|
if (!Stream_CheckAndLogRequiredLength(TAG, s, 6))
|
2012-10-09 10:31:28 +04:00
|
|
|
return FALSE;
|
2012-02-07 16:38:27 +04:00
|
|
|
|
2013-05-09 00:09:16 +04:00
|
|
|
Stream_Read_UINT16(s, keyboardFlags); /* keyboardFlags (2 bytes) */
|
2019-11-06 17:24:51 +03:00
|
|
|
Stream_Read_UINT16(s, unicodeCode); /* unicodeCode (2 bytes) */
|
|
|
|
Stream_Seek(s, 2); /* pad2Octets (2 bytes) */
|
2012-02-07 16:38:27 +04:00
|
|
|
|
2014-10-22 13:24:36 +04:00
|
|
|
/* "fix" keyboardFlags - see comment in input_recv_keyboard_event() */
|
2012-02-07 16:38:27 +04:00
|
|
|
|
2014-10-22 13:24:36 +04:00
|
|
|
if (keyboardFlags & KBD_FLAGS_RELEASE)
|
|
|
|
keyboardFlags &= ~KBD_FLAGS_DOWN;
|
|
|
|
else
|
2012-02-07 16:38:27 +04:00
|
|
|
keyboardFlags |= KBD_FLAGS_DOWN;
|
|
|
|
|
2015-04-17 17:21:55 +03:00
|
|
|
return IFCALLRESULT(TRUE, input->UnicodeKeyboardEvent, input, keyboardFlags, unicodeCode);
|
2012-02-07 16:38:27 +04:00
|
|
|
}
|
|
|
|
|
2013-03-21 23:19:33 +04:00
|
|
|
static BOOL input_recv_mouse_event(rdpInput* input, wStream* s)
|
2012-02-07 16:38:27 +04:00
|
|
|
{
|
2012-10-09 11:01:37 +04:00
|
|
|
UINT16 pointerFlags, xPos, yPos;
|
2012-02-07 16:38:27 +04:00
|
|
|
|
2022-04-19 15:29:17 +03:00
|
|
|
WINPR_ASSERT(input);
|
|
|
|
WINPR_ASSERT(s);
|
|
|
|
|
|
|
|
if (!Stream_CheckAndLogRequiredLength(TAG, s, 6))
|
2012-10-09 10:31:28 +04:00
|
|
|
return FALSE;
|
2012-02-07 16:38:27 +04:00
|
|
|
|
2013-05-09 00:09:16 +04:00
|
|
|
Stream_Read_UINT16(s, pointerFlags); /* pointerFlags (2 bytes) */
|
2019-11-06 17:24:51 +03:00
|
|
|
Stream_Read_UINT16(s, xPos); /* xPos (2 bytes) */
|
|
|
|
Stream_Read_UINT16(s, yPos); /* yPos (2 bytes) */
|
2015-04-17 17:21:55 +03:00
|
|
|
return IFCALLRESULT(TRUE, input->MouseEvent, input, pointerFlags, xPos, yPos);
|
2012-02-07 16:38:27 +04:00
|
|
|
}
|
|
|
|
|
2013-03-21 23:19:33 +04:00
|
|
|
static BOOL input_recv_extended_mouse_event(rdpInput* input, wStream* s)
|
2012-02-07 16:38:27 +04:00
|
|
|
{
|
2012-10-09 11:01:37 +04:00
|
|
|
UINT16 pointerFlags, xPos, yPos;
|
2012-02-07 16:38:27 +04:00
|
|
|
|
2022-04-19 15:29:17 +03:00
|
|
|
WINPR_ASSERT(input);
|
|
|
|
WINPR_ASSERT(s);
|
|
|
|
|
|
|
|
if (!Stream_CheckAndLogRequiredLength(TAG, s, 6))
|
2012-10-09 10:31:28 +04:00
|
|
|
return FALSE;
|
2012-02-07 16:38:27 +04:00
|
|
|
|
2013-05-09 00:09:16 +04:00
|
|
|
Stream_Read_UINT16(s, pointerFlags); /* pointerFlags (2 bytes) */
|
2019-11-06 17:24:51 +03:00
|
|
|
Stream_Read_UINT16(s, xPos); /* xPos (2 bytes) */
|
|
|
|
Stream_Read_UINT16(s, yPos); /* yPos (2 bytes) */
|
2015-04-17 17:21:55 +03:00
|
|
|
return IFCALLRESULT(TRUE, input->ExtendedMouseEvent, input, pointerFlags, xPos, yPos);
|
2012-02-07 16:38:27 +04:00
|
|
|
}
|
|
|
|
|
2013-03-21 23:19:33 +04:00
|
|
|
static BOOL input_recv_event(rdpInput* input, wStream* s)
|
2012-02-07 16:38:27 +04:00
|
|
|
{
|
2012-10-09 11:01:37 +04:00
|
|
|
UINT16 messageType;
|
2012-02-07 16:38:27 +04:00
|
|
|
|
2022-04-19 15:29:17 +03:00
|
|
|
WINPR_ASSERT(input);
|
|
|
|
WINPR_ASSERT(s);
|
|
|
|
|
|
|
|
if (!Stream_CheckAndLogRequiredLength(TAG, s, 6))
|
2012-10-09 10:31:28 +04:00
|
|
|
return FALSE;
|
2012-02-07 16:38:27 +04:00
|
|
|
|
2019-11-06 17:24:51 +03:00
|
|
|
Stream_Seek(s, 4); /* eventTime (4 bytes), ignored by the server */
|
2013-05-09 00:09:16 +04:00
|
|
|
Stream_Read_UINT16(s, messageType); /* messageType (2 bytes) */
|
2012-02-07 16:38:27 +04:00
|
|
|
|
|
|
|
switch (messageType)
|
|
|
|
{
|
|
|
|
case INPUT_EVENT_SYNC:
|
|
|
|
if (!input_recv_sync_event(input, s))
|
2012-10-09 10:31:28 +04:00
|
|
|
return FALSE;
|
2016-11-24 15:18:41 +03:00
|
|
|
|
2012-02-07 16:38:27 +04:00
|
|
|
break;
|
|
|
|
|
|
|
|
case INPUT_EVENT_SCANCODE:
|
|
|
|
if (!input_recv_keyboard_event(input, s))
|
2012-10-09 10:31:28 +04:00
|
|
|
return FALSE;
|
2016-11-24 15:18:41 +03:00
|
|
|
|
2012-02-07 16:38:27 +04:00
|
|
|
break;
|
|
|
|
|
|
|
|
case INPUT_EVENT_UNICODE:
|
|
|
|
if (!input_recv_unicode_keyboard_event(input, s))
|
2012-10-09 10:31:28 +04:00
|
|
|
return FALSE;
|
2016-11-24 15:18:41 +03:00
|
|
|
|
2012-02-07 16:38:27 +04:00
|
|
|
break;
|
|
|
|
|
|
|
|
case INPUT_EVENT_MOUSE:
|
|
|
|
if (!input_recv_mouse_event(input, s))
|
2012-10-09 10:31:28 +04:00
|
|
|
return FALSE;
|
2016-11-24 15:18:41 +03:00
|
|
|
|
2012-02-07 16:38:27 +04:00
|
|
|
break;
|
|
|
|
|
|
|
|
case INPUT_EVENT_MOUSEX:
|
|
|
|
if (!input_recv_extended_mouse_event(input, s))
|
2012-10-09 10:31:28 +04:00
|
|
|
return FALSE;
|
2016-11-24 15:18:41 +03:00
|
|
|
|
2012-02-07 16:38:27 +04:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2019-11-06 17:24:51 +03:00
|
|
|
WLog_ERR(TAG, "Unknown messageType %" PRIu16 "", messageType);
|
2012-02-07 16:38:27 +04:00
|
|
|
/* Each input event uses 6 bytes. */
|
2013-04-30 06:35:15 +04:00
|
|
|
Stream_Seek(s, 6);
|
2012-02-07 16:38:27 +04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2012-10-09 10:31:28 +04:00
|
|
|
return TRUE;
|
2012-02-07 16:38:27 +04:00
|
|
|
}
|
|
|
|
|
2013-03-21 23:19:33 +04:00
|
|
|
BOOL input_recv(rdpInput* input, wStream* s)
|
2012-02-07 16:38:27 +04:00
|
|
|
{
|
2012-10-09 11:01:37 +04:00
|
|
|
UINT16 i, numberEvents;
|
2012-02-07 16:38:27 +04:00
|
|
|
|
2022-04-19 15:29:17 +03:00
|
|
|
WINPR_ASSERT(input);
|
|
|
|
WINPR_ASSERT(s);
|
2016-04-13 10:47:48 +03:00
|
|
|
|
2022-04-19 15:29:17 +03:00
|
|
|
if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
|
2012-10-09 10:31:28 +04:00
|
|
|
return FALSE;
|
2012-02-07 16:38:27 +04:00
|
|
|
|
2013-05-09 00:09:16 +04:00
|
|
|
Stream_Read_UINT16(s, numberEvents); /* numberEvents (2 bytes) */
|
2019-11-06 17:24:51 +03:00
|
|
|
Stream_Seek(s, 2); /* pad2Octets (2 bytes) */
|
2012-02-07 16:38:27 +04:00
|
|
|
|
|
|
|
/* Each input event uses 6 exactly bytes. */
|
2022-04-19 15:29:17 +03:00
|
|
|
if (!Stream_CheckAndLogRequiredLength(TAG, s, 6ull * numberEvents))
|
2012-10-09 10:31:28 +04:00
|
|
|
return FALSE;
|
2012-02-07 16:38:27 +04:00
|
|
|
|
|
|
|
for (i = 0; i < numberEvents; i++)
|
|
|
|
{
|
|
|
|
if (!input_recv_event(input, s))
|
2012-10-09 10:31:28 +04:00
|
|
|
return FALSE;
|
2012-02-07 16:38:27 +04:00
|
|
|
}
|
|
|
|
|
2012-10-09 10:31:28 +04:00
|
|
|
return TRUE;
|
2012-02-07 16:38:27 +04:00
|
|
|
}
|
|
|
|
|
2015-06-16 16:42:07 +03:00
|
|
|
BOOL input_register_client_callbacks(rdpInput* input)
|
2011-08-23 07:50:41 +04:00
|
|
|
{
|
2016-04-13 10:47:48 +03:00
|
|
|
rdpSettings* settings;
|
|
|
|
|
2022-01-11 18:08:44 +03:00
|
|
|
if (!input->context)
|
2016-04-13 10:47:48 +03:00
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
settings = input->context->settings;
|
|
|
|
|
|
|
|
if (!settings)
|
|
|
|
return FALSE;
|
2011-08-23 07:50:41 +04:00
|
|
|
|
2022-05-02 11:55:44 +03:00
|
|
|
if (freerdp_settings_get_bool(settings, FreeRDP_FastPathInput))
|
2011-08-23 07:50:41 +04:00
|
|
|
{
|
|
|
|
input->SynchronizeEvent = input_send_fastpath_synchronize_event;
|
|
|
|
input->KeyboardEvent = input_send_fastpath_keyboard_event;
|
2014-06-05 01:41:17 +04:00
|
|
|
input->KeyboardPauseEvent = input_send_fastpath_keyboard_pause_event;
|
2011-08-23 07:50:41 +04:00
|
|
|
input->UnicodeKeyboardEvent = input_send_fastpath_unicode_keyboard_event;
|
|
|
|
input->MouseEvent = input_send_fastpath_mouse_event;
|
|
|
|
input->ExtendedMouseEvent = input_send_fastpath_extended_mouse_event;
|
2013-04-15 14:14:09 +04:00
|
|
|
input->FocusInEvent = input_send_fastpath_focus_in_event;
|
2011-08-23 07:50:41 +04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
input->SynchronizeEvent = input_send_synchronize_event;
|
|
|
|
input->KeyboardEvent = input_send_keyboard_event;
|
2014-06-05 01:41:17 +04:00
|
|
|
input->KeyboardPauseEvent = input_send_keyboard_pause_event;
|
2011-08-23 07:50:41 +04:00
|
|
|
input->UnicodeKeyboardEvent = input_send_unicode_keyboard_event;
|
|
|
|
input->MouseEvent = input_send_mouse_event;
|
|
|
|
input->ExtendedMouseEvent = input_send_extended_mouse_event;
|
2013-04-15 14:14:09 +04:00
|
|
|
input->FocusInEvent = input_send_focus_in_event;
|
2011-08-23 07:50:41 +04:00
|
|
|
}
|
2013-01-28 06:07:17 +04:00
|
|
|
|
2015-06-16 16:42:07 +03:00
|
|
|
return TRUE;
|
2011-08-23 07:50:41 +04:00
|
|
|
}
|
|
|
|
|
2015-04-14 11:14:23 +03:00
|
|
|
BOOL freerdp_input_send_synchronize_event(rdpInput* input, UINT32 flags)
|
2012-02-14 02:51:42 +04:00
|
|
|
{
|
2021-06-21 14:59:41 +03:00
|
|
|
if (!input || !input->context)
|
2016-04-13 10:47:48 +03:00
|
|
|
return FALSE;
|
|
|
|
|
2021-06-21 14:59:41 +03:00
|
|
|
if (freerdp_settings_get_bool(input->context->settings, FreeRDP_SuspendInput))
|
|
|
|
return TRUE;
|
|
|
|
|
2015-04-17 17:21:55 +03:00
|
|
|
return IFCALLRESULT(TRUE, input->SynchronizeEvent, input, flags);
|
2012-02-14 02:51:42 +04:00
|
|
|
}
|
|
|
|
|
2022-04-13 10:34:05 +03:00
|
|
|
BOOL freerdp_input_send_keyboard_event(rdpInput* input, UINT16 flags, UINT8 code)
|
2012-02-14 02:51:42 +04:00
|
|
|
{
|
2021-06-21 14:59:41 +03:00
|
|
|
if (!input || !input->context)
|
2016-04-13 10:47:48 +03:00
|
|
|
return FALSE;
|
|
|
|
|
2021-06-21 14:59:41 +03:00
|
|
|
if (freerdp_settings_get_bool(input->context->settings, FreeRDP_SuspendInput))
|
|
|
|
return TRUE;
|
|
|
|
|
2015-04-17 17:21:55 +03:00
|
|
|
return IFCALLRESULT(TRUE, input->KeyboardEvent, input, flags, code);
|
2012-02-14 02:51:42 +04:00
|
|
|
}
|
|
|
|
|
2015-04-14 11:14:23 +03:00
|
|
|
BOOL freerdp_input_send_keyboard_event_ex(rdpInput* input, BOOL down, UINT32 rdp_scancode)
|
2012-09-22 22:27:30 +04:00
|
|
|
{
|
2019-11-06 17:24:51 +03:00
|
|
|
return freerdp_input_send_keyboard_event(
|
|
|
|
input,
|
|
|
|
(RDP_SCANCODE_EXTENDED(rdp_scancode) ? KBD_FLAGS_EXTENDED : 0) |
|
2016-11-24 15:18:41 +03:00
|
|
|
((down) ? KBD_FLAGS_DOWN : KBD_FLAGS_RELEASE),
|
2019-11-06 17:24:51 +03:00
|
|
|
RDP_SCANCODE_CODE(rdp_scancode));
|
2012-09-22 22:27:30 +04:00
|
|
|
}
|
|
|
|
|
2015-04-14 11:14:23 +03:00
|
|
|
BOOL freerdp_input_send_unicode_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code)
|
2012-02-14 02:51:42 +04:00
|
|
|
{
|
2021-06-21 14:59:41 +03:00
|
|
|
if (!input || !input->context)
|
2016-04-13 10:47:48 +03:00
|
|
|
return FALSE;
|
|
|
|
|
2021-06-21 14:59:41 +03:00
|
|
|
if (freerdp_settings_get_bool(input->context->settings, FreeRDP_SuspendInput))
|
|
|
|
return TRUE;
|
|
|
|
|
2015-04-17 17:21:55 +03:00
|
|
|
return IFCALLRESULT(TRUE, input->UnicodeKeyboardEvent, input, flags, code);
|
2012-02-14 02:51:42 +04:00
|
|
|
}
|
|
|
|
|
2015-04-14 11:14:23 +03:00
|
|
|
BOOL freerdp_input_send_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y)
|
2012-02-14 02:51:42 +04:00
|
|
|
{
|
2021-06-21 14:59:41 +03:00
|
|
|
if (!input || !input->context)
|
2016-04-13 10:47:48 +03:00
|
|
|
return FALSE;
|
|
|
|
|
2021-06-21 14:59:41 +03:00
|
|
|
if (freerdp_settings_get_bool(input->context->settings, FreeRDP_SuspendInput))
|
|
|
|
return TRUE;
|
|
|
|
|
2015-04-17 17:21:55 +03:00
|
|
|
return IFCALLRESULT(TRUE, input->MouseEvent, input, flags, x, y);
|
2012-02-14 02:51:42 +04:00
|
|
|
}
|
|
|
|
|
2015-04-14 11:14:23 +03:00
|
|
|
BOOL freerdp_input_send_extended_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y)
|
2012-02-14 02:51:42 +04:00
|
|
|
{
|
2021-06-21 14:59:41 +03:00
|
|
|
if (!input || !input->context)
|
2016-04-13 10:47:48 +03:00
|
|
|
return FALSE;
|
|
|
|
|
2021-06-21 14:59:41 +03:00
|
|
|
if (freerdp_settings_get_bool(input->context->settings, FreeRDP_SuspendInput))
|
|
|
|
return TRUE;
|
|
|
|
|
2015-04-17 17:21:55 +03:00
|
|
|
return IFCALLRESULT(TRUE, input->ExtendedMouseEvent, input, flags, x, y);
|
2012-02-14 02:51:42 +04:00
|
|
|
}
|
|
|
|
|
2015-04-14 11:14:23 +03:00
|
|
|
BOOL freerdp_input_send_focus_in_event(rdpInput* input, UINT16 toggleStates)
|
2013-04-15 14:14:09 +04:00
|
|
|
{
|
2021-06-21 14:59:41 +03:00
|
|
|
if (!input || !input->context)
|
2016-04-13 10:47:48 +03:00
|
|
|
return FALSE;
|
|
|
|
|
2021-06-21 14:59:41 +03:00
|
|
|
if (freerdp_settings_get_bool(input->context->settings, FreeRDP_SuspendInput))
|
|
|
|
return TRUE;
|
|
|
|
|
2015-04-17 17:21:55 +03:00
|
|
|
return IFCALLRESULT(TRUE, input->FocusInEvent, input, toggleStates);
|
2013-04-15 14:14:09 +04:00
|
|
|
}
|
|
|
|
|
2015-04-14 11:14:23 +03:00
|
|
|
BOOL freerdp_input_send_keyboard_pause_event(rdpInput* input)
|
2014-06-05 01:41:17 +04:00
|
|
|
{
|
2021-06-21 14:59:41 +03:00
|
|
|
if (!input || !input->context)
|
2016-04-13 10:47:48 +03:00
|
|
|
return FALSE;
|
|
|
|
|
2021-06-21 14:59:41 +03:00
|
|
|
if (freerdp_settings_get_bool(input->context->settings, FreeRDP_SuspendInput))
|
|
|
|
return TRUE;
|
|
|
|
|
2015-04-17 17:21:55 +03:00
|
|
|
return IFCALLRESULT(TRUE, input->KeyboardPauseEvent, input);
|
2014-06-05 01:41:17 +04:00
|
|
|
}
|
|
|
|
|
2013-01-28 06:07:17 +04:00
|
|
|
int input_process_events(rdpInput* input)
|
|
|
|
{
|
2016-04-13 10:47:48 +03:00
|
|
|
if (!input)
|
|
|
|
return FALSE;
|
|
|
|
|
2013-02-04 23:56:54 +04:00
|
|
|
return input_message_queue_process_pending_messages(input);
|
2013-01-28 06:07:17 +04:00
|
|
|
}
|
|
|
|
|
2016-11-24 15:18:41 +03:00
|
|
|
static void input_free_queued_message(void* obj)
|
2013-11-12 18:02:25 +04:00
|
|
|
{
|
2016-11-24 15:18:41 +03:00
|
|
|
wMessage* msg = (wMessage*)obj;
|
2013-11-12 18:02:25 +04:00
|
|
|
input_message_queue_free_message(msg);
|
|
|
|
}
|
|
|
|
|
2011-07-28 04:14:12 +04:00
|
|
|
rdpInput* input_new(rdpRdp* rdp)
|
|
|
|
{
|
2013-11-24 01:39:29 +04:00
|
|
|
const wObject cb = { NULL, NULL, NULL, input_free_queued_message, NULL };
|
2022-01-11 18:08:44 +03:00
|
|
|
rdp_input_internal* input = (rdp_input_internal*)calloc(1, sizeof(rdp_input_internal));
|
|
|
|
|
|
|
|
WINPR_UNUSED(rdp);
|
2016-11-24 15:18:41 +03:00
|
|
|
|
2015-05-18 12:28:00 +03:00
|
|
|
if (!input)
|
|
|
|
return NULL;
|
2011-07-28 04:14:12 +04:00
|
|
|
|
2022-03-23 15:18:35 +03:00
|
|
|
input->common.context = rdp->context;
|
2015-05-18 12:28:00 +03:00
|
|
|
input->queue = MessageQueue_New(&cb);
|
2016-11-24 15:18:41 +03:00
|
|
|
|
2015-05-18 12:28:00 +03:00
|
|
|
if (!input->queue)
|
2011-07-28 04:14:12 +04:00
|
|
|
{
|
2015-05-18 12:28:00 +03:00
|
|
|
free(input);
|
|
|
|
return NULL;
|
2011-07-28 04:14:12 +04:00
|
|
|
}
|
|
|
|
|
2022-01-24 11:49:07 +03:00
|
|
|
return &input->common;
|
2011-07-28 04:14:12 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void input_free(rdpInput* input)
|
|
|
|
{
|
|
|
|
if (input != NULL)
|
|
|
|
{
|
2022-01-11 18:08:44 +03:00
|
|
|
rdp_input_internal* in = input_cast(input);
|
2013-01-28 06:07:17 +04:00
|
|
|
|
2022-01-11 18:08:44 +03:00
|
|
|
MessageQueue_Free(in->queue);
|
|
|
|
free(in);
|
2011-07-28 04:14:12 +04:00
|
|
|
}
|
|
|
|
}
|