Internal
Public Access
Fix RDP/VNC clipboard sync randomly stopping
Local copies were de-duplicated against the last synced text with no expiry, so one lost send made re-copying the same text a no-op; every open tab listened to the system clipboard, letting background sessions overwrite it and forwarding one tab's update to all others; and RDP never sent the initial Format List MS-RDPECLIP requires after Monitor Ready, which the server can re-send mid-session (e.g. rdpclip.exe restart), leaving sync dead until reconnect. Announce failures are now logged to the event log instead of silently dropped. Bump version to v2026.9.26. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
34c16cbfa8
commit
0f821feeed
5 files changed
+84
-9
No files matched your search
@@ -2000,6 +2000,10 @@ void RdpSessionBackend::sendClipboardTextToRemote(rdp_freerdp* instance, const Q
|
||||
}
|
||||
|
||||
if (cliprdrContext == nullptr || cliprdrContext->ClientFormatList == nullptr) {
|
||||
// Kept in m_pendingLocalClipboardText and announced once the channel
|
||||
// reports MonitorReady (see onCliprdrMonitorReady()).
|
||||
emit eventLogged(QStringLiteral(
|
||||
"RDP clipboard: channel not ready; copied text will be sent once it is."));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2012,7 +2016,11 @@ void RdpSessionBackend::sendClipboardTextToRemote(rdp_freerdp* instance, const Q
|
||||
formatList.formats = &format;
|
||||
|
||||
const UINT rc = cliprdrContext->ClientFormatList(cliprdrContext, &formatList);
|
||||
Q_UNUSED(rc);
|
||||
if (rc != CHANNEL_RC_OK) {
|
||||
emit eventLogged(
|
||||
QStringLiteral("RDP clipboard: failed to announce copied text to the server (0x%1).")
|
||||
.arg(rc, 0, 16));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -2324,6 +2332,29 @@ void RdpSessionBackend::onCliprdrMonitorReady()
|
||||
}
|
||||
|
||||
emit eventLogged(QStringLiteral("RDP clipboard channel ready."));
|
||||
|
||||
QString pendingText;
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(m_cliprdrMutex);
|
||||
pendingText = m_pendingLocalClipboardText;
|
||||
}
|
||||
if (!pendingText.isEmpty()) {
|
||||
sendClipboardTextToRemote(nullptr, pendingText);
|
||||
} else if (cliprdrContext->ClientFormatList != nullptr) {
|
||||
// MS-RDPECLIP requires the client to answer Monitor Ready with its
|
||||
// capabilities *and* an initial Format List (empty is fine); the
|
||||
// server doesn't treat the channel as initialized until it has
|
||||
// both. The server can send Monitor Ready again mid-session -- e.g.
|
||||
// when rdpclip.exe restarts -- and without this the clipboard
|
||||
// stayed dead until the session was reconnected.
|
||||
CLIPRDR_FORMAT_LIST emptyList = {};
|
||||
const UINT rc = cliprdrContext->ClientFormatList(cliprdrContext, &emptyList);
|
||||
if (rc != CHANNEL_RC_OK) {
|
||||
emit eventLogged(
|
||||
QStringLiteral("RDP clipboard: initial format list failed (0x%1).")
|
||||
.arg(rc, 0, 16));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user