21#include <freerdp/config.h>
24#include <winpr/assert.h>
26#include <freerdp/input.h>
27#include <freerdp/log.h>
33#define TAG FREERDP_TAG("core")
36#define INPUT_EVENT_SYNC 0x0000
37#define INPUT_EVENT_SCANCODE 0x0004
38#define INPUT_EVENT_UNICODE 0x0005
39#define INPUT_EVENT_MOUSE 0x8001
40#define INPUT_EVENT_MOUSEX 0x8002
41#define INPUT_EVENT_MOUSEREL 0x8004
43static const char* SyncEventFlag2Str(
enum KBD_SYNC_FLAGS flag)
45 if (flag == KBD_SYNC_SCROLL_LOCK)
46 return "SYNC_SCROLL_LOCK";
47 if (flag == KBD_SYNC_NUM_LOCK)
48 return "SYNC_NUM_LOCK";
49 if (flag == KBD_SYNC_CAPS_LOCK)
50 return "SYNC_CAPS_LOCK";
51 if (flag == KBD_SYNC_KANA_LOCK)
52 return "SYNC_KANA_LOCK";
53 return "SYNC_UNKNOWN";
56static const char* SyncEventFlags2Str(
const char* prefix, uint32_t flags,
char* buffer,
size_t len)
58 const uint32_t tflags[] = { KBD_SYNC_SCROLL_LOCK, KBD_SYNC_NUM_LOCK, KBD_SYNC_CAPS_LOCK,
64 if (!winpr_str_append(
"{", buffer, len,
""))
68 for (
size_t x = 0; x < ARRAYSIZE(tflags); x++)
70 const uint32_t flag = tflags[x];
73 char ibuffer[64] = { 0 };
74 (void)_snprintf(ibuffer,
sizeof(ibuffer),
"%s%s", prefix, SyncEventFlag2Str(flag));
75 if (!winpr_str_append(ibuffer, &buffer[1], len - 2,
"|"))
79 if (!winpr_str_append(
"}", &buffer[1], len - 2,
""))
85const char* freerdp_input_keyboard_flags_string(uint32_t flags,
char* buffer,
size_t len)
87 return SyncEventFlags2Str(
"KBD_", flags, buffer, len);
90static void rdp_write_client_input_pdu_header(
wStream* s, UINT16 number)
93 WINPR_ASSERT(Stream_GetRemainingCapacity(s) >= 4);
94 Stream_Write_UINT16(s, number);
95 Stream_Write_UINT16(s, 0);
98static void rdp_write_input_event_header(
wStream* s, UINT32 time, UINT16 type)
101 WINPR_ASSERT(Stream_GetRemainingCapacity(s) >= 6);
102 Stream_Write_UINT32(s, time);
103 Stream_Write_UINT16(s, type);
106static wStream* rdp_client_input_pdu_init(rdpRdp* rdp, UINT16 type, UINT16* sec_flags)
108 wStream* s = rdp_data_pdu_init(rdp, sec_flags);
113 rdp_write_client_input_pdu_header(s, 1);
114 rdp_write_input_event_header(s, 0, type);
118static BOOL rdp_send_client_input_pdu(rdpRdp* rdp,
wStream* s, UINT16 sec_flags)
121 WINPR_ASSERT(rdp->mcs);
122 return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_INPUT, rdp->mcs->userId, sec_flags);
125static void input_write_synchronize_event(
wStream* s, UINT32 flags)
128 WINPR_ASSERT(Stream_GetRemainingCapacity(s) >= 6);
129 Stream_Write_UINT16(s, 0);
130 Stream_Write_UINT32(s, flags);
133static BOOL input_ensure_client_running(rdpInput* input)
136 if (freerdp_shall_disconnect_context(input->context))
138 WLog_WARN(TAG,
"[APPLICATION BUG] input functions called after the session terminated");
144static BOOL input_send_synchronize_event(rdpInput* input, UINT32 flags)
146 UINT16 sec_flags = 0;
148 if (!input || !input->context)
151 rdpRdp* rdp = input->context->rdp;
153 if (!input_ensure_client_running(input))
156 wStream* s = rdp_client_input_pdu_init(rdp, INPUT_EVENT_SYNC, &sec_flags);
161 input_write_synchronize_event(s, flags);
162 return rdp_send_client_input_pdu(rdp, s, sec_flags);
165static void input_write_keyboard_event(
wStream* s, UINT16 flags, UINT16 code)
168 WINPR_ASSERT(code <= UINT8_MAX);
170 Stream_Write_UINT16(s, flags);
171 Stream_Write_UINT16(s, code);
172 Stream_Write_UINT16(s, 0);
175static BOOL input_send_keyboard_event(rdpInput* input, UINT16 flags, UINT8 code)
177 UINT16 sec_flags = 0;
181 if (!input || !input->context)
184 rdp = input->context->rdp;
186 if (!input_ensure_client_running(input))
189 s = rdp_client_input_pdu_init(rdp, INPUT_EVENT_SCANCODE, &sec_flags);
194 input_write_keyboard_event(s, flags, code);
195 return rdp_send_client_input_pdu(rdp, s, sec_flags);
198static void input_write_unicode_keyboard_event(
wStream* s, UINT16 flags, UINT16 code)
200 Stream_Write_UINT16(s, flags);
201 Stream_Write_UINT16(s, code);
202 Stream_Write_UINT16(s, 0);
205static BOOL input_send_unicode_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code)
207 UINT16 sec_flags = 0;
211 if (!input || !input->context)
214 if (!input_ensure_client_running(input))
219 WLog_WARN(TAG,
"Unicode input not supported by server.");
223 rdp = input->context->rdp;
224 s = rdp_client_input_pdu_init(rdp, INPUT_EVENT_UNICODE, &sec_flags);
229 input_write_unicode_keyboard_event(s, flags, code);
230 return rdp_send_client_input_pdu(rdp, s, sec_flags);
233static void input_write_mouse_event(
wStream* s, UINT16 flags, UINT16 x, UINT16 y)
235 Stream_Write_UINT16(s, flags);
236 Stream_Write_UINT16(s, x);
237 Stream_Write_UINT16(s, y);
240static BOOL input_send_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y)
242 UINT16 sec_flags = 0;
244 if (!input || !input->context || !input->context->settings)
247 rdpRdp* rdp = input->context->rdp;
249 if (!input_ensure_client_running(input))
254 if (flags & PTR_FLAGS_HWHEEL)
257 "skip mouse event %" PRIu16
"x%" PRIu16
" flags=0x%04" PRIX16
258 ", no horizontal mouse wheel supported",
264 wStream* s = rdp_client_input_pdu_init(rdp, INPUT_EVENT_MOUSE, &sec_flags);
269 input_write_mouse_event(s, flags, x, y);
270 return rdp_send_client_input_pdu(rdp, s, sec_flags);
273static BOOL input_send_relmouse_event(rdpInput* input, UINT16 flags, INT16 xDelta, INT16 yDelta)
275 UINT16 sec_flags = 0;
279 if (!input || !input->context || !input->context->settings)
282 rdp = input->context->rdp;
284 if (!input_ensure_client_running(input))
289 WLog_ERR(TAG,
"Sending relative mouse event, but no support for that");
293 s = rdp_client_input_pdu_init(rdp, INPUT_EVENT_MOUSEREL, &sec_flags);
298 Stream_Write_UINT16(s, flags);
299 Stream_Write_INT16(s, xDelta);
300 Stream_Write_INT16(s, yDelta);
302 return rdp_send_client_input_pdu(rdp, s, sec_flags);
305static void input_write_extended_mouse_event(
wStream* s, UINT16 flags, UINT16 x, UINT16 y)
307 Stream_Write_UINT16(s, flags);
308 Stream_Write_UINT16(s, x);
309 Stream_Write_UINT16(s, y);
312static BOOL input_send_extended_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y)
314 UINT16 sec_flags = 0;
317 WINPR_ASSERT(input->context);
318 WINPR_ASSERT(input->context->settings);
320 rdpRdp* rdp = input->context->rdp;
323 if (!input_ensure_client_running(input))
329 "skip extended mouse event %" PRIu16
"x%" PRIu16
" flags=0x%04" PRIX16
330 ", no extended mouse events supported",
335 wStream* s = rdp_client_input_pdu_init(rdp, INPUT_EVENT_MOUSEX, &sec_flags);
340 input_write_extended_mouse_event(s, flags, x, y);
341 return rdp_send_client_input_pdu(rdp, s, sec_flags);
344static BOOL input_send_focus_in_event(rdpInput* input, UINT16 toggleStates)
347 if (!input_send_keyboard_event(input, KBD_FLAGS_RELEASE, 0x0f))
351 if (!input_send_synchronize_event(input, (toggleStates & 0x1F)))
355 return input_send_keyboard_event(input, KBD_FLAGS_RELEASE, 0x0f);
358static BOOL input_send_keyboard_pause_event(rdpInput* input)
366 if (!input_send_keyboard_event(input, KBD_FLAGS_EXTENDED1,
367 RDP_SCANCODE_CODE(RDP_SCANCODE_LCONTROL)))
371 if (!input_send_keyboard_event(input, 0, RDP_SCANCODE_CODE(RDP_SCANCODE_NUMLOCK)))
375 if (!input_send_keyboard_event(input, KBD_FLAGS_RELEASE | KBD_FLAGS_EXTENDED1,
376 RDP_SCANCODE_CODE(RDP_SCANCODE_LCONTROL)))
380 return input_send_keyboard_event(input, KBD_FLAGS_RELEASE,
381 RDP_SCANCODE_CODE(RDP_SCANCODE_NUMLOCK));
384static BOOL input_send_fastpath_synchronize_event(rdpInput* input, UINT32 flags)
386 UINT16 sec_flags = 0;
391 WINPR_ASSERT(input->context);
393 rdp = input->context->rdp;
396 if (!input_ensure_client_running(input))
400 s = fastpath_input_pdu_init(rdp->fastpath, (BYTE)flags, FASTPATH_INPUT_EVENT_SYNC, &sec_flags);
405 return fastpath_send_input_pdu(rdp->fastpath, s, sec_flags);
408static BOOL input_send_fastpath_keyboard_event(rdpInput* input, UINT16 flags, UINT8 code)
410 UINT16 sec_flags = 0;
416 WINPR_ASSERT(input->context);
418 rdp = input->context->rdp;
421 if (!input_ensure_client_running(input))
424 eventFlags |= (flags & KBD_FLAGS_RELEASE) ? FASTPATH_INPUT_KBDFLAGS_RELEASE : 0;
425 eventFlags |= (flags & KBD_FLAGS_EXTENDED) ? FASTPATH_INPUT_KBDFLAGS_EXTENDED : 0;
426 eventFlags |= (flags & KBD_FLAGS_EXTENDED1) ? FASTPATH_INPUT_KBDFLAGS_PREFIX_E1 : 0;
427 s = fastpath_input_pdu_init(rdp->fastpath, eventFlags, FASTPATH_INPUT_EVENT_SCANCODE,
433 WINPR_ASSERT(code <= UINT8_MAX);
434 Stream_Write_UINT8(s, code);
435 return fastpath_send_input_pdu(rdp->fastpath, s, sec_flags);
438static BOOL input_send_fastpath_unicode_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code)
440 UINT16 sec_flags = 0;
446 WINPR_ASSERT(input->context);
447 WINPR_ASSERT(input->context->settings);
449 rdp = input->context->rdp;
452 if (!input_ensure_client_running(input))
457 WLog_WARN(TAG,
"Unicode input not supported by server.");
461 eventFlags |= (flags & KBD_FLAGS_RELEASE) ? FASTPATH_INPUT_KBDFLAGS_RELEASE : 0;
462 s = fastpath_input_pdu_init(rdp->fastpath, eventFlags, FASTPATH_INPUT_EVENT_UNICODE,
468 Stream_Write_UINT16(s, code);
469 return fastpath_send_input_pdu(rdp->fastpath, s, sec_flags);
472static BOOL input_send_fastpath_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y)
474 UINT16 sec_flags = 0;
479 WINPR_ASSERT(input->context);
480 WINPR_ASSERT(input->context->settings);
482 rdp = input->context->rdp;
485 if (!input_ensure_client_running(input))
490 if (flags & PTR_FLAGS_HWHEEL)
493 "skip mouse event %" PRIu16
"x%" PRIu16
" flags=0x%04" PRIX16
494 ", no horizontal mouse wheel supported",
500 s = fastpath_input_pdu_init(rdp->fastpath, 0, FASTPATH_INPUT_EVENT_MOUSE, &sec_flags);
505 input_write_mouse_event(s, flags, x, y);
506 return fastpath_send_input_pdu(rdp->fastpath, s, sec_flags);
509static BOOL input_send_fastpath_extended_mouse_event(rdpInput* input, UINT16 flags, UINT16 x,
512 UINT16 sec_flags = 0;
517 WINPR_ASSERT(input->context);
519 rdp = input->context->rdp;
522 if (!input_ensure_client_running(input))
528 "skip extended mouse event %" PRIu16
"x%" PRIu16
" flags=0x%04" PRIX16
529 ", no extended mouse events supported",
534 s = fastpath_input_pdu_init(rdp->fastpath, 0, FASTPATH_INPUT_EVENT_MOUSEX, &sec_flags);
539 input_write_extended_mouse_event(s, flags, x, y);
540 return fastpath_send_input_pdu(rdp->fastpath, s, sec_flags);
543static BOOL input_send_fastpath_relmouse_event(rdpInput* input, UINT16 flags, INT16 xDelta,
546 UINT16 sec_flags = 0;
551 WINPR_ASSERT(input->context);
552 WINPR_ASSERT(input->context->settings);
554 rdp = input->context->rdp;
557 if (!input_ensure_client_running(input))
562 WLog_ERR(TAG,
"Sending relative fastpath mouse event, but no support for that announced");
566 s = fastpath_input_pdu_init(rdp->fastpath, 0, TS_FP_RELPOINTER_EVENT, &sec_flags);
571 Stream_Write_UINT16(s, flags);
572 Stream_Write_INT16(s, xDelta);
573 Stream_Write_INT16(s, yDelta);
574 return fastpath_send_input_pdu(rdp->fastpath, s, sec_flags);
577static BOOL input_send_fastpath_qoe_event(rdpInput* input, UINT32 timestampMS)
580 WINPR_ASSERT(input->context);
581 WINPR_ASSERT(input->context->settings);
583 rdpRdp* rdp = input->context->rdp;
586 if (!input_ensure_client_running(input))
591 WLog_ERR(TAG,
"Sending qoe event, but no support for that announced");
595 UINT16 sec_flags = 0;
596 wStream* s = fastpath_input_pdu_init(rdp->fastpath, 0, TS_FP_QOETIMESTAMP_EVENT, &sec_flags);
601 if (!Stream_EnsureRemainingCapacity(s, 4))
603 Stream_Free(s, TRUE);
607 Stream_Write_UINT32(s, timestampMS);
608 return fastpath_send_input_pdu(rdp->fastpath, s, sec_flags);
611static BOOL input_send_fastpath_focus_in_event(rdpInput* input, UINT16 toggleStates)
613 UINT16 sec_flags = 0;
619 WINPR_ASSERT(input->context);
621 rdp = input->context->rdp;
624 if (!input_ensure_client_running(input))
627 s = fastpath_input_pdu_init_header(rdp->fastpath, &sec_flags);
633 eventFlags = FASTPATH_INPUT_KBDFLAGS_RELEASE | FASTPATH_INPUT_EVENT_SCANCODE << 5;
634 Stream_Write_UINT8(s, eventFlags);
635 Stream_Write_UINT8(s, 0x0f);
637 eventFlags = (toggleStates & 0x1F) | FASTPATH_INPUT_EVENT_SYNC << 5;
638 Stream_Write_UINT8(s, eventFlags);
640 eventFlags = FASTPATH_INPUT_KBDFLAGS_RELEASE | FASTPATH_INPUT_EVENT_SCANCODE << 5;
641 Stream_Write_UINT8(s, eventFlags);
642 Stream_Write_UINT8(s, 0x0f);
643 return fastpath_send_multiple_input_pdu(rdp->fastpath, s, 3, sec_flags);
646static BOOL input_send_fastpath_keyboard_pause_event(rdpInput* input)
652 UINT16 sec_flags = 0;
654 const BYTE keyDownEvent = FASTPATH_INPUT_EVENT_SCANCODE << 5;
655 const BYTE keyUpEvent = (FASTPATH_INPUT_EVENT_SCANCODE << 5) | FASTPATH_INPUT_KBDFLAGS_RELEASE;
659 WINPR_ASSERT(input->context);
661 rdp = input->context->rdp;
664 if (!input_ensure_client_running(input))
667 s = fastpath_input_pdu_init_header(rdp->fastpath, &sec_flags);
673 Stream_Write_UINT8(s, keyDownEvent | FASTPATH_INPUT_KBDFLAGS_PREFIX_E1);
674 Stream_Write_UINT8(s, RDP_SCANCODE_CODE(RDP_SCANCODE_LCONTROL));
676 Stream_Write_UINT8(s, keyDownEvent);
677 Stream_Write_UINT8(s, RDP_SCANCODE_CODE(RDP_SCANCODE_NUMLOCK));
679 Stream_Write_UINT8(s, keyUpEvent | FASTPATH_INPUT_KBDFLAGS_PREFIX_E1);
680 Stream_Write_UINT8(s, RDP_SCANCODE_CODE(RDP_SCANCODE_LCONTROL));
682 Stream_Write_UINT8(s, keyUpEvent);
683 Stream_Write_UINT8(s, RDP_SCANCODE_CODE(RDP_SCANCODE_NUMLOCK));
684 return fastpath_send_multiple_input_pdu(rdp->fastpath, s, 4, sec_flags);
687static BOOL input_recv_sync_event(rdpInput* input,
wStream* s)
689 UINT32 toggleFlags = 0;
694 if (!Stream_CheckAndLogRequiredLength(TAG, s, 6))
698 Stream_Read_UINT32(s, toggleFlags);
699 return IFCALLRESULT(TRUE, input->SynchronizeEvent, input, toggleFlags);
702static BOOL input_recv_keyboard_event(rdpInput* input,
wStream* s)
704 UINT16 keyboardFlags = 0;
710 if (!Stream_CheckAndLogRequiredLength(TAG, s, 6))
713 Stream_Read_UINT16(s, keyboardFlags);
714 Stream_Read_UINT16(s, keyCode);
717 if (keyboardFlags & KBD_FLAGS_RELEASE)
718 keyboardFlags &= ~KBD_FLAGS_DOWN;
720 if (keyCode & 0xFF00)
722 "Problematic [MS-RDPBCGR] 2.2.8.1.1.3.1.1.1 Keyboard Event (TS_KEYBOARD_EVENT) "
723 "keyCode=0x%04" PRIx16
724 ", high byte values should be sent in keyboardFlags field, ignoring.",
726 return IFCALLRESULT(TRUE, input->KeyboardEvent, input, keyboardFlags, keyCode & 0xFF);
729static BOOL input_recv_unicode_keyboard_event(rdpInput* input,
wStream* s)
731 UINT16 keyboardFlags = 0;
732 UINT16 unicodeCode = 0;
737 if (!Stream_CheckAndLogRequiredLength(TAG, s, 6))
740 Stream_Read_UINT16(s, keyboardFlags);
741 Stream_Read_UINT16(s, unicodeCode);
746 if (keyboardFlags & KBD_FLAGS_RELEASE)
747 keyboardFlags &= ~KBD_FLAGS_DOWN;
749 return IFCALLRESULT(TRUE, input->UnicodeKeyboardEvent, input, keyboardFlags, unicodeCode);
752static BOOL input_recv_mouse_event(rdpInput* input,
wStream* s)
754 UINT16 pointerFlags = 0;
761 if (!Stream_CheckAndLogRequiredLength(TAG, s, 6))
764 Stream_Read_UINT16(s, pointerFlags);
765 Stream_Read_UINT16(s, xPos);
766 Stream_Read_UINT16(s, yPos);
767 return IFCALLRESULT(TRUE, input->MouseEvent, input, pointerFlags, xPos, yPos);
770static BOOL input_recv_relmouse_event(rdpInput* input,
wStream* s)
772 UINT16 pointerFlags = 0;
779 if (!Stream_CheckAndLogRequiredLength(TAG, s, 6))
782 Stream_Read_UINT16(s, pointerFlags);
783 Stream_Read_INT16(s, xDelta);
784 Stream_Read_INT16(s, yDelta);
789 "Received relative mouse event(flags=0x%04" PRIx16
", xPos=%" PRId16
790 ", yPos=%" PRId16
"), but we did not announce support for that",
791 pointerFlags, xDelta, yDelta);
795 return IFCALLRESULT(TRUE, input->RelMouseEvent, input, pointerFlags, xDelta, yDelta);
798static BOOL input_recv_extended_mouse_event(rdpInput* input,
wStream* s)
800 UINT16 pointerFlags = 0;
807 if (!Stream_CheckAndLogRequiredLength(TAG, s, 6))
810 Stream_Read_UINT16(s, pointerFlags);
811 Stream_Read_UINT16(s, xPos);
812 Stream_Read_UINT16(s, yPos);
817 "Received extended mouse event(flags=0x%04" PRIx16
", xPos=%" PRIu16
818 ", yPos=%" PRIu16
"), but we did not announce support for that",
819 pointerFlags, xPos, yPos);
823 return IFCALLRESULT(TRUE, input->ExtendedMouseEvent, input, pointerFlags, xPos, yPos);
826static BOOL input_recv_event(rdpInput* input,
wStream* s)
828 UINT16 messageType = 0;
833 if (!Stream_CheckAndLogRequiredLength(TAG, s, 6))
837 Stream_Read_UINT16(s, messageType);
841 case INPUT_EVENT_SYNC:
842 if (!input_recv_sync_event(input, s))
847 case INPUT_EVENT_SCANCODE:
848 if (!input_recv_keyboard_event(input, s))
853 case INPUT_EVENT_UNICODE:
854 if (!input_recv_unicode_keyboard_event(input, s))
859 case INPUT_EVENT_MOUSE:
860 if (!input_recv_mouse_event(input, s))
865 case INPUT_EVENT_MOUSEX:
866 if (!input_recv_extended_mouse_event(input, s))
871 case INPUT_EVENT_MOUSEREL:
872 if (!input_recv_relmouse_event(input, s))
878 WLog_ERR(TAG,
"Unknown messageType %" PRIu16
"", messageType);
887BOOL input_recv(rdpInput* input,
wStream* s)
889 UINT16 numberEvents = 0;
894 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
897 Stream_Read_UINT16(s, numberEvents);
901 if (!Stream_CheckAndLogRequiredLengthOfSize(TAG, s, numberEvents, 6ull))
904 for (UINT16 i = 0; i < numberEvents; i++)
906 if (!input_recv_event(input, s))
913BOOL input_register_client_callbacks(rdpInput* input)
915 rdpSettings* settings = NULL;
920 settings = input->context->settings;
927 input->SynchronizeEvent = input_send_fastpath_synchronize_event;
928 input->KeyboardEvent = input_send_fastpath_keyboard_event;
929 input->KeyboardPauseEvent = input_send_fastpath_keyboard_pause_event;
930 input->UnicodeKeyboardEvent = input_send_fastpath_unicode_keyboard_event;
931 input->MouseEvent = input_send_fastpath_mouse_event;
932 input->RelMouseEvent = input_send_fastpath_relmouse_event;
933 input->ExtendedMouseEvent = input_send_fastpath_extended_mouse_event;
934 input->FocusInEvent = input_send_fastpath_focus_in_event;
935 input->QoEEvent = input_send_fastpath_qoe_event;
939 input->SynchronizeEvent = input_send_synchronize_event;
940 input->KeyboardEvent = input_send_keyboard_event;
941 input->KeyboardPauseEvent = input_send_keyboard_pause_event;
942 input->UnicodeKeyboardEvent = input_send_unicode_keyboard_event;
943 input->MouseEvent = input_send_mouse_event;
944 input->RelMouseEvent = input_send_relmouse_event;
945 input->ExtendedMouseEvent = input_send_extended_mouse_event;
946 input->FocusInEvent = input_send_focus_in_event;
953static BOOL input_update_last_event(rdpInput* input, BOOL mouse, UINT16 x, UINT16 y)
958 WINPR_ASSERT(input->context);
962 const time_t now = time(NULL);
963 in->lastInputTimestamp = WINPR_ASSERTING_INT_CAST(UINT64, now);
974BOOL freerdp_input_send_synchronize_event(rdpInput* input, UINT32 flags)
976 if (!input || !input->context)
980 const BOOL suspended =
982 char buffer[128] = { 0 };
983 WLog_Print(in->log, WLOG_DEBUG,
"Keyboard {Sync, suspend: %d} [%s]", suspended,
984 freerdp_input_keyboard_flags_string(flags, buffer,
sizeof(buffer)));
988 return IFCALLRESULT(TRUE, input->SynchronizeEvent, input, flags);
991BOOL freerdp_input_send_keyboard_event(rdpInput* input, UINT16 flags, UINT8 code)
993 if (!input || !input->context)
999 input_update_last_event(input, FALSE, 0, 0);
1001 return IFCALLRESULT(TRUE, input->KeyboardEvent, input, flags, code);
1004BOOL freerdp_input_send_keyboard_event_ex(rdpInput* input, BOOL down, BOOL repeat,
1005 UINT32 rdp_scancode)
1007 UINT16 flags = (RDP_SCANCODE_EXTENDED(rdp_scancode) ? KBD_FLAGS_EXTENDED : 0);
1009 flags |= KBD_FLAGS_DOWN;
1011 flags |= KBD_FLAGS_RELEASE;
1013 return freerdp_input_send_keyboard_event(input, flags, RDP_SCANCODE_CODE(rdp_scancode));
1016BOOL freerdp_input_send_unicode_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code)
1018 if (!input || !input->context)
1024 input_update_last_event(input, FALSE, 0, 0);
1026 return IFCALLRESULT(TRUE, input->UnicodeKeyboardEvent, input, flags, code);
1029BOOL freerdp_input_send_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y)
1031 if (!input || !input->context)
1037 input_update_last_event(
1038 input, flags & (PTR_FLAGS_MOVE | PTR_FLAGS_BUTTON1 | PTR_FLAGS_BUTTON2 | PTR_FLAGS_BUTTON3),
1041 return IFCALLRESULT(TRUE, input->MouseEvent, input, flags, x, y);
1044BOOL freerdp_input_send_rel_mouse_event(rdpInput* input, UINT16 flags, INT16 xDelta, INT16 yDelta)
1046 if (!input || !input->context)
1052 return IFCALLRESULT(TRUE, input->RelMouseEvent, input, flags, xDelta, yDelta);
1055BOOL freerdp_input_send_qoe_timestamp(rdpInput* input, UINT32 timestampMS)
1057 if (!input || !input->context)
1060 return IFCALLRESULT(TRUE, input->QoEEvent, input, timestampMS);
1063BOOL freerdp_input_send_extended_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y)
1065 if (!input || !input->context)
1071 input_update_last_event(input, TRUE, x, y);
1073 return IFCALLRESULT(TRUE, input->ExtendedMouseEvent, input, flags, x, y);
1076BOOL freerdp_input_send_focus_in_event(rdpInput* input, UINT16 toggleStates)
1078 if (!input || !input->context)
1082 const BOOL suspended =
1084 char buffer[128] = { 0 };
1085 WLog_Print(in->log, WLOG_DEBUG,
"Keyboard {FocusIn, suspend: %s} [%s]",
1086 suspended ?
"true" :
"false",
1087 freerdp_input_keyboard_flags_string(toggleStates, buffer, sizeof(buffer)));
1091 return IFCALLRESULT(TRUE, input->FocusInEvent, input, toggleStates);
1094BOOL freerdp_input_send_keyboard_pause_event(rdpInput* input)
1096 if (!input || !input->context)
1100 const BOOL suspended =
1102 WLog_Print(in->log, WLOG_DEBUG,
"Keyboard {Pause, suspend: %s}", suspended ?
"true" :
"false");
1106 return IFCALLRESULT(TRUE, input->KeyboardPauseEvent, input);
1109int input_process_events(rdpInput* input)
1114 return input_message_queue_process_pending_messages(input);
1117static void input_free_queued_message(
void* obj)
1119 wMessage* msg = (wMessage*)obj;
1120 input_message_queue_free_message(msg);
1123rdpInput* input_new(rdpRdp* rdp)
1125 const wObject cb = { NULL, NULL, NULL, input_free_queued_message, NULL };
1133 input->common.context = rdp->context;
1134 input->queue = MessageQueue_New(&cb);
1135 input->log = WLog_Get(TAG);
1143 return &input->common;
1146void input_free(rdpInput* input)
1152 MessageQueue_Free(in->queue);
FREERDP_API UINT32 freerdp_settings_get_uint32(const rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id)
Returns a UINT32 settings value.
FREERDP_API BOOL freerdp_settings_get_bool(const rdpSettings *settings, FreeRDP_Settings_Keys_Bool id)
Returns a boolean settings value.
This struct contains function pointer to initialize/free objects.