feat(cliprdr): add CliprdrBackend::on_format_list_response(ok) hook#1300
Open
clintcan wants to merge 1 commit into
Open
feat(cliprdr): add CliprdrBackend::on_format_list_response(ok) hook#1300clintcan wants to merge 1 commit into
clintcan wants to merge 1 commit into
Conversation
Add a non-breaking hook that fires when the remote responds to a
FormatList we sent (i.e. an outbound advertise of our own clipboard
contents):
fn on_format_list_response(&mut self, _ok: bool) {}
Called from handle_format_list_response on both branches:
- Ok -> on_format_list_response(true)
- Fail -> on_format_list_response(false) (after Cliprdr has cleared
local_file_list per the spec)
Default impl is a no-op, so this is non-breaking for existing backends.
### Why
Without this signal, a backend has no way to learn whether an outbound
FormatList advertise was accepted or rejected. That matters because
the Fail branch silently wipes `local_file_list` / `local_file_list_format_id`
(MS-RDPECLIP 3.1.5.2.4), so a rejected advertise breaks the paste with
no recovery. A naive timed-retry strategy can also actively WIPE an
already-Ok state by sending a follow-up advertise that happens to be
rejected — observed live (with no hook to stop it):
advertise Devolutions#1 -> Fail
advertise Devolutions#2 (retry) -> Ok (file present)
advertise Devolutions#3 (retry) -> Fail (wiped the accepted state)
^ paste fails
With the hook, a backend can retry on Fail AND stop the moment Ok
arrives, so the success is preserved.
### Use case
Used in https://github.com/clintcan/macrdp (a Rust RDP server for
macOS) to implement reliable Mac→Windows file copy: mstsc commonly
rejects the first FormatList right after an in-session Cmd-C
(it's still processing the input) and accepts one a moment later.
The macrdp poller's retry loop now stops the instant an Ok lands,
fixing the silent-paste-failure case while still recovering from a
transient initial Fail.
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.
Add a non-breaking backend hook that fires when the remote responds to a
FormatListwe sent (an outbound advertise of our own clipboard contents):Called from
handle_format_list_responseon both branches:Ok→on_format_list_response(true)Fail→on_format_list_response(false)(afterCliprdrhas clearedlocal_file_listper MS-RDPECLIP 3.1.5.2.4)Default impl is a no-op, so this is non-breaking for existing backends.
Why
Without this signal, a backend has no way to learn whether an outbound
FormatListwas accepted or rejected. That's a real problem because theFailbranch silently wipeslocal_file_list/local_file_list_format_idper the spec — so a rejected advertise breaks the paste with no recovery and no way to detect it.Worse: a naive timed-retry strategy can actively wipe an already-
Okstate by sending a follow-up advertise that happens to be rejected. Observed live (without the hook, so no way to stop):With the hook, a backend can retry on
Failand stop the momentOkarrives, preserving the success.Use case / verification
Used in macrdp (a Rust RDP server for macOS) to implement reliable Mac→Windows file copy. mstsc commonly rejects the first
FormatListright after an in-sessionCmd-C(it's still processing the input) and accepts one ~0.5–1s later. With this hook, the macrdp poller's retry loop fires retries onFailand stops onOk(via a shared generation/locked-gen pair), fixing the silent-paste-failure case while still recovering from a transient initialFail. Verified end-to-end with real mstsc.Related
Pairs naturally with the upcoming
PreferredDropEffectandFD_PROGRESSUIPRs to deliver the full "Mac→Windows clipboard file paste with native progress dialog" UX, but is independently useful and can be merged on its own.