Feature: Web remote desktop bidirectional text clipboard sync
Add keyboard-shortcut (Ctrl+C / Ctrl+X / Ctrl+V) text clipboard transfer between the browser and the remote desktop, reusing the clipboard protocol that already exists in the native viewer (COMMAND_SCREEN_GET_CLIPBOARD=24, COMMAND_SCREEN_SET_CLIPBOARD=25, TOKEN_CLIPBOARD_TEXT=118) so the client needs no change. Local -> remote: pressing Ctrl+V reads the browser clipboard, pushes it to the remote clipboard (UTF-8 -> GBK, matching the client's CF_TEXT/ANSI handling) and then synthesizes a remote Ctrl+V so the pasted text is the newly delivered one. Remote -> local: Ctrl+C or Ctrl+X is forwarded to the remote as usual and, after a short delay, the remote clipboard is pulled back and written to the browser clipboard for a later local Ctrl+V. Both the MFC and Go servers get the same three clipboard signaling paths (clipboard_set, clipboard_get, clipboard_text) so the shared single-page frontend behaves identically on either backend. Co-Authored-By: deepseek-v4-pro
This commit is contained in:
1 parent
e6b4fe3a85
commit
0c04f7516b
10 files changed
+290
-12
No files matched your search
+20
-3
@@ -114,9 +114,9 @@ type wsHub struct {
|
||||
|
||||
func newWSHub(auth *wsauth.Authenticator, devices *hub.Hub, log *logger.Logger) *wsHub {
|
||||
h := &wsHub{
|
||||
auth: auth,
|
||||
devices: devices,
|
||||
log: log,
|
||||
auth: auth,
|
||||
devices: devices,
|
||||
log: log,
|
||||
clients: make(map[*wsClient]struct{}),
|
||||
screenCloseTimers: make(map[string]*time.Timer),
|
||||
}
|
||||
@@ -300,6 +300,23 @@ func (h *wsHub) OnResolutionChange(deviceID string, width, height int) {
|
||||
}
|
||||
}
|
||||
|
||||
// OnClipboardText relays a device's clipboard text back to every browser
|
||||
// watching it (in response to a "clipboard_get" request).
|
||||
func (h *wsHub) OnClipboardText(deviceID string, text string) {
|
||||
msg := mustJSON(map[string]any{
|
||||
"cmd": "clipboard_text",
|
||||
"id": deviceID,
|
||||
"text": text,
|
||||
})
|
||||
h.mu.RLock()
|
||||
defer h.mu.RUnlock()
|
||||
for c := range h.clients {
|
||||
if c.watching == deviceID && c.token != "" {
|
||||
c.queue(msg)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// OnScreenFrame ships a screen packet to every browser currently watching
|
||||
// this device. We hold the read lock for the whole iteration, but each
|
||||
// queueBinary is non-blocking (drops on backpressure) so a slow viewer
|
||||
|
||||
Reference in new issue
Block a user