diff --git a/include/freerdp/input.h b/include/freerdp/input.h index 456d10377..512fceead 100644 --- a/include/freerdp/input.h +++ b/include/freerdp/input.h @@ -111,6 +111,7 @@ extern "C" UINT16 y); FREERDP_API BOOL freerdp_input_send_rel_mouse_event(rdpInput* input, UINT16 flags, INT16 xDelta, INT16 yDelta); + FREERDP_API BOOL freerdp_input_send_qoe_timestamp(rdpInput* input, UINT32 timestampMS); FREERDP_API BOOL freerdp_input_send_extended_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y); FREERDP_API BOOL freerdp_input_send_focus_in_event(rdpInput* input, UINT16 toggleStates); diff --git a/libfreerdp/core/fastpath.c b/libfreerdp/core/fastpath.c index 8da9e2f81..40c445b9c 100644 --- a/libfreerdp/core/fastpath.c +++ b/libfreerdp/core/fastpath.c @@ -760,6 +760,34 @@ static BOOL fastpath_recv_input_event_relmouse(rdpFastPath* fastpath, wStream* s return IFCALLRESULT(TRUE, input->RelMouseEvent, input, pointerFlags, xDelta, yDelta); } +static BOOL fastpath_recv_input_event_qoe(rdpFastPath* fastpath, wStream* s, BYTE eventFlags) +{ + WINPR_ASSERT(fastpath); + WINPR_ASSERT(fastpath->rdp); + WINPR_ASSERT(fastpath->rdp->context); + WINPR_ASSERT(fastpath->rdp->input); + WINPR_ASSERT(s); + + if (!Stream_CheckAndLogRequiredLength(TAG, s, 4)) + return FALSE; + + rdpInput* input = fastpath->rdp->input; + + UINT32 timestampMS = 0; + Stream_Read_UINT32(s, timestampMS); /* timestamp (4 bytes) */ + + if (!freerdp_settings_get_bool(input->context->settings, FreeRDP_HasQoeEvent)) + { + WLog_ERR(TAG, + "Received qoe event(timestamp=%" PRIu32 + "ms), but we did not announce support for that", + timestampMS); + return FALSE; + } + + return IFCALLRESULT(TRUE, input->QoEEvent, input, timestampMS); +} + static BOOL fastpath_recv_input_event_mousex(rdpFastPath* fastpath, wStream* s, BYTE eventFlags) { rdpInput* input; @@ -880,6 +908,11 @@ static BOOL fastpath_recv_input_event(rdpFastPath* fastpath, wStream* s) break; + case TS_FP_QOETIMESTAMP_EVENT: + if (!fastpath_recv_input_event_qoe(fastpath, s, eventFlags)) + return FALSE; + break; + default: WLog_ERR(TAG, "Unknown eventCode %" PRIu8 "", eventCode); break; diff --git a/libfreerdp/core/fastpath.h b/libfreerdp/core/fastpath.h index ed03bc7d2..73ea504aa 100644 --- a/libfreerdp/core/fastpath.h +++ b/libfreerdp/core/fastpath.h @@ -92,7 +92,8 @@ enum FASTPATH_INPUT_EVENT_CODE FASTPATH_INPUT_EVENT_MOUSEX = 0x2, FASTPATH_INPUT_EVENT_SYNC = 0x3, FASTPATH_INPUT_EVENT_UNICODE = 0x4, - TS_FP_RELPOINTER_EVENT = 0x5 + TS_FP_RELPOINTER_EVENT = 0x5, + TS_FP_QOETIMESTAMP_EVENT = 0x6 }; /* FastPath Keyboard Event Flags */ diff --git a/libfreerdp/core/input.c b/libfreerdp/core/input.c index c76f02a74..58b97e0ca 100644 --- a/libfreerdp/core/input.c +++ b/libfreerdp/core/input.c @@ -519,6 +519,39 @@ static BOOL input_send_fastpath_relmouse_event(rdpInput* input, UINT16 flags, UI return fastpath_send_input_pdu(rdp->fastpath, s); } +static BOOL input_send_fastpath_qoe_event(rdpInput* input, UINT32 timestampMS) +{ + WINPR_ASSERT(input); + WINPR_ASSERT(input->context); + WINPR_ASSERT(input->context->settings); + + rdpRdp* rdp = input->context->rdp; + WINPR_ASSERT(rdp); + + if (!input_ensure_client_running(input)) + return FALSE; + + if (!freerdp_settings_get_bool(input->context->settings, FreeRDP_HasQoeEvent)) + { + WLog_ERR(TAG, "Sending qoe event, but no support for that announced"); + return FALSE; + } + + wStream* s = fastpath_input_pdu_init(rdp->fastpath, 0, TS_FP_QOETIMESTAMP_EVENT); + + if (!s) + return FALSE; + + if (!Stream_EnsureRemainingCapacity(s, 4)) + { + Stream_Free(s, TRUE); + return FALSE; + } + + Stream_Write_UINT32(s, timestampMS); + return fastpath_send_input_pdu(rdp->fastpath, s); +} + static BOOL input_send_fastpath_focus_in_event(rdpInput* input, UINT16 toggleStates) { wStream* s; @@ -834,6 +867,7 @@ BOOL input_register_client_callbacks(rdpInput* input) input->RelMouseEvent = input_send_fastpath_relmouse_event; input->ExtendedMouseEvent = input_send_fastpath_extended_mouse_event; input->FocusInEvent = input_send_fastpath_focus_in_event; + input->QoEEvent = input_send_fastpath_qoe_event; } else { @@ -917,6 +951,14 @@ BOOL freerdp_input_send_rel_mouse_event(rdpInput* input, UINT16 flags, INT16 xDe return IFCALLRESULT(TRUE, input->RelMouseEvent, input, flags, xDelta, yDelta); } +BOOL freerdp_input_send_qoe_timestamp(rdpInput* input, UINT32 timestampMS) +{ + if (!input || !input->context) + return FALSE; + + return IFCALLRESULT(TRUE, input->QoEEvent, input, timestampMS); +} + BOOL freerdp_input_send_extended_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y) { if (!input || !input->context)