fix: improve headless RDP input and clipboard lifecycle - #47
Draft
Adamkadaban wants to merge 5 commits into
Draft
Conversation
This was referenced Jul 26, 2026
Adamkadaban
marked this pull request as draft
July 27, 2026 06:55
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes several issues that prevent reliable headless (non-interactive) RDP automation.
Extended scancodes: Keys like Win (0xE05B) were sent as raw 16-bit keycodes. Windows requires keycode 0x5B with the KBDFLAGS.EXTENDED flag set separately. Without this, Win+R is silently ignored when we use
send_key_scancodeSynchronize Event serialization:
TS_SYNC_EVENT.toggleFlagswas serialized as 2 bytes. Both the MS spec and FreeRDP define it as 4 bytes (UINT32) after a 2-byte pad. Sending only 2 bytes caused Windows to immediately close the connection.Keyboard focus initialization: When mstsc or FreeRDP gives the RDP window focus, they send a 3-message sequence: Tab release, Synchronize (current Caps/Num/Scroll Lock state), Tab release. This tells the keyboard that it is ready and then shares the toggle key state. Without it, keystrokes after connecting may get silently dropped.
Input send error propagation:
send_key_scancode,send_mouse,send_focus_in, andhandle_out_datanow return transport errors instead of silently reporting success when the network write failed.Connection state isolation: Added
RDPIOSettings.clone_for_connection()that produces fresh clipboard and dynamic channel state per connection. Prevents cross-connection state contamination when making multiple sequential connections.Clipboard lifecycle:
Handlers are unregistered on channel stop. Exposed
CLIPBOARD_FORMAT_LIST_RESPONSEacceptance as a queue event so callers can synchronize clipboard writes before triggering remote reads.Sources
MS-RDPBCGR
toggleFlagsis 4 bytes (UINT32):https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/6c5d0ef9-4653-4d69-9ba9-09ba3acd660f
keyboardFlagsbit 8 = EXTENDED:https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/08eaaed5-f143-4bfa-a1e2-5414ca0ec67e
FreeRDP
toggleFlagswritten as UINT32:https://github.com/FreeRDP/FreeRDP/blob/0aa3589/libfreerdp/core/input.c#L125-L131
toggleFlagsread as UINT32:https://github.com/FreeRDP/FreeRDP/blob/0aa3589/libfreerdp/core/input.c#L695-L699
https://github.com/FreeRDP/FreeRDP/blob/0aa3589/libfreerdp/core/input.c#L344-L356
keyCode & 0xFFwith warning:https://github.com/FreeRDP/FreeRDP/blob/0aa3589/libfreerdp/core/input.c#L720-L726
KBD_FLAGS_EXTENDED= 0x0100:https://github.com/FreeRDP/FreeRDP/blob/0aa3589/include/freerdp/input.h#L31
https://github.com/FreeRDP/FreeRDP/blob/0aa3589/channels/cliprdr/client/cliprdr_format.c#L191-L206
Testing
(Developed with assistance from Copilot, but all reviewed and tested by a human)