[GH-ISSUE #105] [Feature Request] Clipboard #41

Open
opened 2026-05-05 22:06:00 -06:00 by gitea-mirror · 36 comments
Owner

Originally created by @DrYak on GitHub (Apr 13, 2024).
Original GitHub issue: https://github.com/feschber/lan-mouse/issues/105

For sharing clipboard, I've found something that can both be used as a building block for users to make their workaround and which could be used to add clipboard support into lan-mouse:

wl-clipboard

It provides a pair of command that can read from- / write to- the wayland clipboard (and thus be used to store stuff in files, send over pipes or tunnels, etc.)

At the end of the readme, they also mention a rust crate wl-clipboard-rs handling the same which could be used for lan-mouse.

Originally created by @DrYak on GitHub (Apr 13, 2024). Original GitHub issue: https://github.com/feschber/lan-mouse/issues/105 For sharing clipboard, I've found something that can both be used as a building block for users to make their workaround and which could be used to add clipboard support into lan-mouse: [wl-clipboard](https://github.com/bugaevc/wl-clipboard) It provides a pair of command that can read from- / write to- the wayland clipboard (and thus be used to store stuff in files, send over pipes or tunnels, etc.) At the end of the readme, they also mention a rust crate [wl-clipboard-rs](https://github.com/YaLTeR/wl-clipboard-rs) handling the same which could be used for lan-mouse.
gitea-mirror added the
enhancement
label 2026-05-05 22:06:00 -06:00
Author
Owner

@feschber commented on GitHub (Apr 13, 2024):

wl-clipboard-rs is definitely a good starting point. It uses the same underlying library as the layer-shell backend in lan-mouse.

There are however some additional problems to solve other than just interacting with the clipboard.

I will just lay out some of my thoughts here for future reference:

  1. How to send the clipboard contents to the destination client reliably? (especially larger clipboard contents)
    (a) Use an additional TCP server socket on each client
    (b) Chunk the contents into smaller chunks and send them via the same UDP socket.

Option (a) would be a lot easier to implement but I'm definitely leaning towards the second option because it does not require an additional port and protocol. There are however a few issues with it that need solving:

  • The clipboard contents must be chunked into a size that fits within UDP packets and later reassembled on the target client.
  • Mouse and Keyboard events must not be blocked while clipboard contents are being sent (The mouse should not hang while a 1GiB file is being sent) so this is probably going to require some form of a priority queue (or maybe just a QoS header to let the kernel handle it?).
  • Both of the above require changes to the protocol.
  1. When to send the clipboard contents?
    (a) When something is copied on the source client
    (b) When the cusor enters the destination client
    (c) When something is pasted on the destination client

I'm also leaning towards the last option here because it would require the least amount of data being sent but I'm also not sure if it is possible to do via standard wayland protocols so I may just resort to option (b) at first.

<!-- gh-comment-id:2053609251 --> @feschber commented on GitHub (Apr 13, 2024): wl-clipboard-rs is definitely a good starting point. It uses the same underlying library as the layer-shell backend in lan-mouse. There are however some additional problems to solve other than just interacting with the clipboard. I will just lay out some of my thoughts here for future reference: 1. **_How_** to send the clipboard contents to the destination client reliably? (especially larger clipboard contents) (a) Use an additional TCP server socket on each client (b) Chunk the contents into smaller chunks and send them via the same UDP socket. Option (a) would be a lot easier to implement but I'm definitely leaning towards the second option because it does not require an additional port and protocol. There are however a few issues with it that need solving: - The clipboard contents must be chunked into a size that fits within UDP packets and later reassembled on the target client. - Mouse and Keyboard events must not be blocked while clipboard contents are being sent (The mouse should not hang while a 1GiB file is being sent) so this is probably going to require some form of a priority queue (or maybe just a QoS header to let the kernel handle it?). - Both of the above require changes to the protocol. 2. **_When_** to send the clipboard contents? (a) When something is copied on the source client (b) When the cusor enters the destination client (c) When something is pasted on the destination client I'm also leaning towards the last option here because it would require the least amount of data being sent but I'm also not sure if it is possible to do via standard wayland protocols so I may just resort to option (b) at first.
Author
Owner

@DrYak commented on GitHub (Apr 13, 2024):

Copying the clipboard upon cursor entering client seems indeed the most reasonable.

(And sounds that you almost need to manually implement your own TCP-like layer on top of UDP)

<!-- gh-comment-id:2053637211 --> @DrYak commented on GitHub (Apr 13, 2024): Copying the clipboard upon cursor entering client seems indeed the most reasonable. (And sounds that you almost need to manually implement your own TCP-like layer on top of UDP)
Author
Owner

@DrYak commented on GitHub (Apr 23, 2024):

Hum, maybe #107 could be a temporary solution for the clipboard:
just handle it externally of lan-mouse for now (e.g. by using wl-clipboard and the like in external scripts that move the clipboard content around upon moving the pointer to another machine) and so no need to think how to organise transfer of large blocks of data over a piece of software optimised for small and frequent UDP packets.

<!-- gh-comment-id:2071625340 --> @DrYak commented on GitHub (Apr 23, 2024): Hum, maybe #107 could be a temporary solution for the clipboard: just handle it externally of lan-mouse for now (e.g. by using wl-clipboard and the like in external scripts that move the clipboard content around upon moving the pointer to another machine) and so no need to think how to organise transfer of large blocks of data over a piece of software optimised for small and frequent UDP packets.
Author
Owner

@feschber commented on GitHub (Apr 23, 2024):

Hum, maybe #107 could be a temporary solution for the clipboard:
just handle it externally of lan-mouse for now (e.g. by using wl-clipboard and the like in external scripts that move the clipboard content around upon moving the pointer to another machine) and so no need to think how to organise transfer of large blocks of data over a piece of software optimised for small and frequent UDP packets.

After giving it some thought this might actually not be the worst idea. Using wl-paste | netcat on device A and netcat | wl-copy on device B would probably work as a hack.

<!-- gh-comment-id:2073647093 --> @feschber commented on GitHub (Apr 23, 2024): > Hum, maybe #107 could be a temporary solution for the clipboard: > just handle it externally of lan-mouse for now (e.g. by using wl-clipboard and the like in external scripts that move the clipboard content around upon moving the pointer to another machine) and so no need to think how to organise transfer of large blocks of data over a piece of software optimised for small and frequent UDP packets. After giving it some thought this might actually not be the worst idea. Using `wl-paste | netcat` on device A and `netcat | wl-copy` on device B would probably work as a hack.
Author
Owner

@DrYak commented on GitHub (Apr 24, 2024):

Using wl-paste | netcat on device A and netcat | wl-copy on device B would probably work as a hack.

Yup! My though also.
Specially as wrapping everything in SSH for encryption is also trivial.

wl-paste | ssh env WAYLAND_DISPLAY="wayland-0" ${remote} wl-copy

and attack surface could even be further be reduced by using forced-command and task-specific keys (so for the given ed25519 key used by that script, remote will only ever perform wl-copy and nothing else).


edit: environment variable from the actual command

<!-- gh-comment-id:2074761590 --> @DrYak commented on GitHub (Apr 24, 2024): > Using `wl-paste | netcat` on device A and `netcat | wl-copy` on device B would probably work as a hack. Yup! My though also. Specially as wrapping everything in SSH for encryption is also trivial. ``` bash wl-paste | ssh env WAYLAND_DISPLAY="wayland-0" ${remote} wl-copy ``` and attack surface could even be further be reduced by using `forced-command` and task-specific keys (so for the given ed25519 key used by that script, remote will only ever perform wl-copy and nothing else). --- edit: environment variable from the actual command
Author
Owner

@FireMasterK commented on GitHub (May 11, 2024):

Couldn't the message size limitation be addressed in #104 when implementing DTLS? We wouldn't have any message/packet size issues when using QUIC or DTLS from what I see 🤔

<!-- gh-comment-id:2105687345 --> @FireMasterK commented on GitHub (May 11, 2024): Couldn't the message size limitation be addressed in #104 when implementing DTLS? We wouldn't have any message/packet size issues when using QUIC or DTLS from what I see :thinking:
Author
Owner

@feschber commented on GitHub (May 12, 2024):

Couldn't the message size limitation be addressed in #104 when implementing DTLS? We wouldn't have any message/packet size issues when using QUIC or DTLS from what I see 🤔

DTLS is still packet based and those packets are limited in size.

QUIC may be interesting to look into for the future but also does not solve the problem of prioritizing input events over clipboard data.

For now, I want to keep using plain UDP with DTLS.

<!-- gh-comment-id:2106066928 --> @feschber commented on GitHub (May 12, 2024): > Couldn't the message size limitation be addressed in #104 when implementing DTLS? We wouldn't have any message/packet size issues when using QUIC or DTLS from what I see 🤔 DTLS is still packet based and those packets are limited in size. QUIC may be interesting to look into for the future but also does not solve the problem of prioritizing input events over clipboard data. For now, I want to keep using plain UDP with DTLS.
Author
Owner

@feschber commented on GitHub (May 12, 2024):

Using wl-paste | netcat on device A and netcat | wl-copy on device B would probably work as a hack.

Yup! My though also.
Specially as wrapping everything in SSH for encryption is also trivial.

wl-paste | ssh env WAYLAND_DISPLAY="wayland-0" ${remote} wl-copy

and attack surface could even be further be reduced by using forced-command and task-specific keys (so for the given ed25519 key used by that script, remote will only ever perform wl-copy and nothing else).


edit: environment variable from the actual command

Will check tomorrow if this works

<!-- gh-comment-id:2106259714 --> @feschber commented on GitHub (May 12, 2024): > > Using `wl-paste | netcat` on device A and `netcat | wl-copy` on device B would probably work as a hack. > > Yup! My though also. > Specially as wrapping everything in SSH for encryption is also trivial. > ``` bash > wl-paste | ssh env WAYLAND_DISPLAY="wayland-0" ${remote} wl-copy > ``` > and attack surface could even be further be reduced by using `forced-command` and task-specific keys (so for the given ed25519 key used by that script, remote will only ever perform wl-copy and nothing else). > > --- > > edit: environment variable from the actual command Will check tomorrow if this works
Author
Owner

@feschber commented on GitHub (May 13, 2024):

Seems to be working! (order of host and command was swapped)

enter_hook = "wl-paste | ssh thorium env WAYLAND_DISPLAY='wayland-1' wl-copy"
<!-- gh-comment-id:2106740745 --> @feschber commented on GitHub (May 13, 2024): Seems to be working! (order of host and command was swapped) ```toml enter_hook = "wl-paste | ssh thorium env WAYLAND_DISPLAY='wayland-1' wl-copy" ```
Author
Owner

@feschber commented on GitHub (May 13, 2024):

Let me know, if someone can figure out a way of copying files as well ;)

<!-- gh-comment-id:2106745373 --> @feschber commented on GitHub (May 13, 2024): Let me know, if someone can figure out a way of copying files as well ;)
Author
Owner

@DrYak commented on GitHub (May 16, 2024):

Tested it with:

enter_hook="wl-paste | ssh argo.fritz.box '-oIdentitiesOnly yes' -i .ssh/id_ed25519_clipboard"

and in the remote's ~/.ssh/authorized_keys:

# forced command
command="/usr/bin/env WAYLAND_DISPLAY='wayland-0' wl-copy",no-agent-forwarding,no-pty,no-X11-forwarding ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDkqOfEBruPi9ceKwIoNS4VqpLX0uEwA0egJPcmMIDMj dryak@saturn

WORKS! YAY!

🎊 🎊 🎊

When do you plan to tag the release?

<!-- gh-comment-id:2114745692 --> @DrYak commented on GitHub (May 16, 2024): Tested it with: ```toml enter_hook="wl-paste | ssh argo.fritz.box '-oIdentitiesOnly yes' -i .ssh/id_ed25519_clipboard" ``` and in the remote's `~/.ssh/authorized_keys`: ``` # forced command command="/usr/bin/env WAYLAND_DISPLAY='wayland-0' wl-copy",no-agent-forwarding,no-pty,no-X11-forwarding ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDkqOfEBruPi9ceKwIoNS4VqpLX0uEwA0egJPcmMIDMj dryak@saturn ``` **WORKS! YAY!** :confetti_ball: :confetti_ball: :confetti_ball: When do you plan to tag the release?
Author
Owner

@feschber commented on GitHub (May 16, 2024):

The main thing, I wanted to wait for was

  • #115, which is now mostly fixed except for #133. (which requires upstream changes in Kwin / xdg-desktop-portal-kde)
  • Some bugs I introduced with the internal API change, which is now done
  • Input Capture in Windows not working for certain keys.

I think it's probably a good idea to ignore that last part and make a release anyway.

<!-- gh-comment-id:2114768971 --> @feschber commented on GitHub (May 16, 2024): The main thing, I wanted to wait for was - #115, which is now mostly fixed except for #133. (which requires upstream changes in Kwin / xdg-desktop-portal-kde) - Some bugs I introduced with the internal API change, which is now done - Input Capture in Windows not working for certain keys. I think it's probably a good idea to ignore that last part and make a release anyway.
Author
Owner

@DrYak commented on GitHub (May 21, 2024):

Addendum:

Use the option wl-paste --no-newline , otherwise wl-paste will automatically add an extra new-line at the end of text type clip board (i.e.: when you copy-paste text as opposed to screen shots), and thus on each screen switch the content of the clip board will get longer and longer as each client adds an extra line when copying this ever growing clipboard.

enter_hook="wl-paste --no-newline | 
<!-- gh-comment-id:2122762424 --> @DrYak commented on GitHub (May 21, 2024): Addendum: Use the option `wl-paste --no-newline` , otherwise wl-paste will automatically add an extra new-line at the end of text type clip board (i.e.: when you copy-paste text as opposed to screen shots), and thus on each screen switch the content of the clip board will get longer and longer as each client adds an extra line when copying this ever growing clipboard. ```toml enter_hook="wl-paste --no-newline | … ```
Author
Owner

@DrYak commented on GitHub (May 24, 2024):

Just a short update:
I've updated my OpenSUSE Tumbleweed package to 0.8.0 and are now enjoying the clipboard-over-enter_hook functionnality on several of my machines.

Thanks for the support!

<!-- gh-comment-id:2129323440 --> @DrYak commented on GitHub (May 24, 2024): Just a short update: I've updated my [OpenSUSE Tumbleweed package](https://software.opensuse.org/package/lan-mouse) to 0.8.0 and are now enjoying the clipboard-over-`enter_hook` functionnality on several of my machines. Thanks for the support!
Author
Owner

@Kelerion-UK commented on GitHub (Jun 4, 2024):

This solution still requires external intervention (ie: hooks), right? doesn't work out of the box? is there a timeline for that?

Thanks!

<!-- gh-comment-id:2147540926 --> @Kelerion-UK commented on GitHub (Jun 4, 2024): This solution still requires external intervention (ie: hooks), right? doesn't work out of the box? is there a timeline for that? Thanks!
Author
Owner

@DrYak commented on GitHub (Jun 13, 2024):

As feschber has mentionned above, lan-mouse is designed around UDP sending small packets around without guarantee of arrival, which is fine for real-time input sharing (e.g.: 1 packet per mouse event).

Clipboard content can be large and needs to be entirely transmitted, more the realm of TCP.

Direct support would require re-engineering lan-mouse to support an entire separate protocol over TCP just for clipboards or re-implent its own content chunking, resend, etc. (i.e. reinvent a TCP-like on top of the existing UDP).

Separating concerns and having lan-mouse concentrate on input forwarding and let other tech handle clipboard transfers as feschber has currently implemented it, is imho the way to go.
What would be still needed is a section in the readme explaining how to get wl-clipboard-over-SSH setup working.

<!-- gh-comment-id:2166195319 --> @DrYak commented on GitHub (Jun 13, 2024): As feschber has mentionned above, lan-mouse is designed around UDP sending small packets around without guarantee of arrival, which is fine for real-time input sharing (e.g.: 1 packet per mouse event). Clipboard content can be large and needs to be entirely transmitted, more the realm of TCP. Direct support would require re-engineering lan-mouse to support an entire separate protocol over TCP just for clipboards or re-implent its own content chunking, resend, etc. (i.e. reinvent a TCP-like on top of the existing UDP). Separating concerns and having lan-mouse concentrate on input forwarding and let other tech handle clipboard transfers as feschber has currently implemented it, is imho the way to go. What would be still needed is a section in the readme explaining how to get wl-clipboard-over-SSH setup working.
Author
Owner

@markmandel commented on GitHub (Jun 23, 2024):

As a suggestion - you may want to look at game udp protocol libraries for this, as they have solved many of these problems, as they are essentially the same as what you are trying to do.

Some ideas:

<!-- gh-comment-id:2184317611 --> @markmandel commented on GitHub (Jun 23, 2024): As a suggestion - you may want to look at game udp protocol libraries for this, as they have solved many of these problems, as they are essentially the same as what you are trying to do. Some ideas: * https://crates.io/crates/laminar is probably the most utilised. * But a KCP implementation might be a fit * https://crates.io/crates/kcp * https://crates.io/crates/tokio_kcp
Author
Owner

@fentas commented on GitHub (Aug 28, 2024):

Not sure, I Had a look around and found this one https://github.com/songokas/clipboard-sync
Worth a look?

<!-- gh-comment-id:2315746186 --> @fentas commented on GitHub (Aug 28, 2024): Not sure, I Had a look around and found this one https://github.com/songokas/clipboard-sync Worth a look?
Author
Owner

@feschber commented on GitHub (Sep 3, 2024):

Not sure, I Had a look around and found this one https://github.com/songokas/clipboard-sync
Worth a look?

Sounds like this could work standalone? I can definitely take some inspiration but will not be working on this until encryption is implemented.

<!-- gh-comment-id:2327559497 --> @feschber commented on GitHub (Sep 3, 2024): > Not sure, I Had a look around and found this one https://github.com/songokas/clipboard-sync > Worth a look? Sounds like this could work standalone? I can definitely take some inspiration but will not be working on this until encryption is implemented.
Author
Owner

@rodhfr commented on GitHub (Nov 19, 2024):

For anyone like me wanting a quick&dirty script

#!/bin/bash
SEND="USER@IP"
notify-send -i clipboard "Copying clipboard to '$SEND'..."
if wl-paste --no-newline | ssh "$SEND" "env WAYLAND_DISPLAY='wayland-1' wl-copy > /dev/null 2>&1"; then
    notify-send -i edit-copy "Clipboard copied to '$SEND'"
else
    notify-send -i error "Failed to copy clipboard to '$SEND'"
fi

Using ssh keys for auth.
Just set this script to a hotkey in hyprland like $mainMod SHIFT, C
push-to-copy clipboard 😸

<!-- gh-comment-id:2484656175 --> @rodhfr commented on GitHub (Nov 19, 2024): For anyone like me wanting a quick&dirty script ```bash #!/bin/bash SEND="USER@IP" notify-send -i clipboard "Copying clipboard to '$SEND'..." if wl-paste --no-newline | ssh "$SEND" "env WAYLAND_DISPLAY='wayland-1' wl-copy > /dev/null 2>&1"; then notify-send -i edit-copy "Clipboard copied to '$SEND'" else notify-send -i error "Failed to copy clipboard to '$SEND'" fi ``` Using ssh keys for auth. Just set this script to a hotkey in hyprland like $mainMod SHIFT, C push-to-copy clipboard 😸
Author
Owner

@dougg0k commented on GitHub (Jan 13, 2025):

I was considering using this tool as it seem a very good tool over the other options. But after seeing that it lacks this functionality, it's not viable, since it's needed.

Has any progress been made on this?

<!-- gh-comment-id:2587992944 --> @dougg0k commented on GitHub (Jan 13, 2025): I was considering using this tool as it seem a very good tool over the other options. But after seeing that it lacks this functionality, it's not viable, since it's needed. Has any progress been made on this?
Author
Owner

@sohanemon commented on GitHub (Jan 19, 2025):

I'm using Syncthing to share the clipboard history file, and it's working perfectly.

<!-- gh-comment-id:2600960087 --> @sohanemon commented on GitHub (Jan 19, 2025): I'm using Syncthing to share the clipboard history file, and it's working perfectly.
Author
Owner

@bushyice commented on GitHub (May 1, 2025):

Sorry but- is this being worked on? i was thinking to use any other workarounds for now, but having this built in would help. are there any forks with this functionality?

<!-- gh-comment-id:2845907657 --> @bushyice commented on GitHub (May 1, 2025): Sorry but- is this being worked on? i was thinking to use any other workarounds for now, but having this built in would help. are there any forks with this functionality?
Author
Owner

@dougg0k commented on GitHub (May 22, 2025):

https://github.com/morn-0/share-clip

https://github.com/reu/clipshare

https://github.com/aweinstock314/rust-clipboard


Maybe this would have worked in wayland GDK_BACKEND=x11 lan-mouse, but since it lacks input capture for x11, it doesnt.

https://github.com/Narsil/rdev

https://github.com/Enigo-rs/Enigo

https://github.com/obv-mikhail/InputBot

<!-- gh-comment-id:2902407691 --> @dougg0k commented on GitHub (May 22, 2025): https://github.com/morn-0/share-clip https://github.com/reu/clipshare https://github.com/aweinstock314/rust-clipboard --- Maybe this would have worked in wayland `GDK_BACKEND=x11 lan-mouse`, but since it lacks input capture for x11, it doesnt. https://github.com/Narsil/rdev https://github.com/Enigo-rs/Enigo https://github.com/obv-mikhail/InputBot
Author
Owner

@dougg0k commented on GitHub (May 28, 2025):

Deskflow are also lacking clipboard in wayland. https://github.com/deskflow/deskflow/issues/8620#issuecomment-2906816285

https://github.com/input-leap/input-leap/issues/1698

<!-- gh-comment-id:2916947793 --> @dougg0k commented on GitHub (May 28, 2025): Deskflow are also lacking clipboard in wayland. https://github.com/deskflow/deskflow/issues/8620#issuecomment-2906816285 https://github.com/input-leap/input-leap/issues/1698
Author
Owner

@dougg0k commented on GitHub (Jun 6, 2025):

There is a simple and working clipboard impl with tls encryption https://github.com/reu/clipshare

It could be what lan-mouse needs. Only two deps that they use that lan-mouse dont yet make use of.

https://crates.io/crates/arboard
https://crates.io/crates/tokio-rustls

<!-- gh-comment-id:2950744718 --> @dougg0k commented on GitHub (Jun 6, 2025): There is a simple and working clipboard impl with tls encryption https://github.com/reu/clipshare It could be what lan-mouse needs. Only two deps that they use that lan-mouse dont yet make use of. https://crates.io/crates/arboard https://crates.io/crates/tokio-rustls
Author
Owner

@DrYak commented on GitHub (Jun 7, 2025):

@dougg0k lan-mouse supports "hooks", commands that are triggered whenever the pointer leaves the screen.

Combining this feature with SSH forced-commands is quite powerful.

With a bit a bash gluecode, you could organize it so the target machine is made sure to join the shared clipboard upon screen change if it's not joined yet.

Only two deps that they use that lan-mouse dont yet make use of.

Add wl-clipboar-rs to this list.
Some people (like me) switched to lan-mouse, because synergy and the like didn't properly support Wayland when Plasma 6 switched the default backend to it.

BTW: On my side I use wl-clipboard-rs and SS forced commands to copy clipboard content upon switching screens.

<!-- gh-comment-id:2952885806 --> @DrYak commented on GitHub (Jun 7, 2025): @dougg0k lan-mouse supports "hooks", commands that are triggered whenever the pointer leaves the screen. Combining this feature with SSH forced-commands is quite powerful. With a bit a bash gluecode, you could organize it so the target machine is made sure to join the shared clipboard upon screen change if it's not joined yet. > Only two deps that they use that lan-mouse dont yet make use of. Add wl-clipboar-rs to this list. Some people (like me) switched to lan-mouse, because synergy and the like didn't properly support Wayland when Plasma 6 switched the default backend to it. BTW: On my side I use wl-clipboard-rs and SS forced commands to copy clipboard content upon switching screens.
Author
Owner

@tv42 commented on GitHub (Jun 8, 2025):

QUIC may be interesting to look into for the future but also does not solve the problem of prioritizing input events over clipboard data.

QUIC streams have independent flow control with per-stream receive windows. A QUIC library SHOULD provide a way for the application to prioritize streams. (https://www.rfc-editor.org/rfc/rfc9000.html#name-stream-prioritization)

You can also send reliable streams and unreliable datagram messages in one connection. The datagrams are not subject to any flow control, so neither some stream nor any congestion control will ever delay a datagram. (https://www.rfc-editor.org/rfc/rfc9221.html#name-flow-control)

I think QUIC should be fine for your use case.

<!-- gh-comment-id:2954218956 --> @tv42 commented on GitHub (Jun 8, 2025): > QUIC may be interesting to look into for the future but also does not solve the problem of prioritizing input events over clipboard data. QUIC streams have independent flow control with per-stream receive windows. A QUIC library SHOULD provide a way for the application to prioritize streams. (https://www.rfc-editor.org/rfc/rfc9000.html#name-stream-prioritization) You can also send reliable streams and unreliable datagram messages in one connection. The datagrams are not subject to any flow control, so neither some stream nor any congestion control will ever delay a datagram. (https://www.rfc-editor.org/rfc/rfc9221.html#name-flow-control) I think QUIC should be fine for your use case.
Author
Owner

@tmcnulty387 commented on GitHub (Jul 22, 2025):

@DrYak With the ssh + lan-mouse hook method you suggested, I'm finding that it causes ssh connections to be spawned that don't self-terminate after a reasonable amount of time. Especially annoying in GNOME because it fills up the dock with "wl-clipboard" applications. Did you find a workaround for this?

Also, currently using https://github.com/quackduck/uniclip/ instead and it's working great so far.

<!-- gh-comment-id:3104890790 --> @tmcnulty387 commented on GitHub (Jul 22, 2025): @DrYak With the ssh + lan-mouse hook method you suggested, I'm finding that it causes ssh connections to be spawned that don't self-terminate after a reasonable amount of time. Especially annoying in GNOME because it fills up the dock with "wl-clipboard" applications. Did you find a workaround for this? Also, currently using https://github.com/quackduck/uniclip/ instead and it's working great so far.
Author
Owner

@DrYak commented on GitHub (Jul 23, 2025):

Did you find a workaround for this?

Good old timeout. It's a sufficient workaround.

But I am sure there a way for one ssh to notice the pipe is closed and correctly foward the information to the other side. Currently:

  • the destination wl-copy (or xcopy) doesn't close because its pipeline doesn't close.
  • the pipeline doesn't close because remote sshd session is still running
  • the remote sshd doesn't end, because the local ssh that initiated the connection is still running
  • the local ssh still runs because even if its input got closed (wl-paste finished and closed its pipe), its output is still up (it's still receiving any stdout / stdin from the remote end)

What I would need to spend a few minutes searching how to forward the "pipe closed" signal over SSH, I am sure it's a simple option somewhere).

Also, currently using https://github.com/quackduck/uniclip/ instead and it's working great so far.

Oh, nice for pointing out this option.

<!-- gh-comment-id:3106595094 --> @DrYak commented on GitHub (Jul 23, 2025): > Did you find a workaround for this? Good old `timeout`. It's a sufficient workaround. But I am sure there a way for one ssh to notice the pipe is closed and correctly foward the information to the other side. Currently: - the destination `wl-copy` (or `xcopy`) doesn't close because its pipeline doesn't close. - the pipeline doesn't close because remote `sshd` session is still running - the remote `sshd` doesn't end, because the local `ssh` that initiated the connection is still running - the local `ssh` still runs because even if its _input_ got closed (`wl-paste` finished and closed its pipe), its output is still up (it's still receiving any _stdout_ / _stdin_ from the remote end) What I would need to spend a few minutes searching how to forward the "pipe closed" signal over SSH, I am sure it's a simple option somewhere). > Also, currently using https://github.com/quackduck/uniclip/ instead and it's working great so far. Oh, nice for pointing out this option.
Author
Owner

@DrYak commented on GitHub (Jul 24, 2025):

@tmcnulty387 Follow up:

Did you find a workaround for this?

I am sure it's a simple option somewhere

Huh, turns out that OpenSSH's ssh command doesn't have such an option for that.

So my over-engineered quickly thrown-together solution would be to run ssh in the background, and then manually send a signal to ask it to quit:

# setup named pipe
pipe_dir="$(mktemp --dir)"
ssh_pipe="${pipe_dir}/clipboard"
mkfifo -m 0700 "${ssh_pipe}"

ls -l "${ssh_pipe}"

# open SSH connection
ssh -o"ControlPath None" -o"IdentitiesOnly Yes" -i ~/.ssh/id_ed25519_clipboard steamdeck.local < "${ssh_pipe}" &
ssh_pid="$!"

# copy-paste
wl-paste > "${ssh_pipe}"

# close SSH
sleep 0.25
kill -TERM "${ssh_pid}"

# tear down named pipe
rm "${ssh_pipe}"
rmdir "${pipe_dir}"

Note

I am using forced commands, and this key is the one that triggers the xclip at the other end of the SSH connection, that's why no command is given to SSH in this example.

Note

Signal TERM always causes ssh to return non-zero, so there's no trivial way to use the above snippet to get success/failure of the SSH connection.

There's probably a cleverer shorter solution that relies on stuff like 'wait' and process substitutions (or unnamed pipes), to avoid the whole mktemp/mkfifo/rm/rmdir, but that's what I managed to throw together in a couple of seconds.

<!-- gh-comment-id:3113984268 --> @DrYak commented on GitHub (Jul 24, 2025): @tmcnulty387 Follow up: > > Did you find a workaround for this? > > I am sure it's a simple option somewhere Huh, turns out that OpenSSH's `ssh` command doesn't have such an option for that. So my over-engineered quickly thrown-together solution would be to run `ssh` in the background, and then manually send a signal to ask it to quit: ```shell # setup named pipe pipe_dir="$(mktemp --dir)" ssh_pipe="${pipe_dir}/clipboard" mkfifo -m 0700 "${ssh_pipe}" ls -l "${ssh_pipe}" # open SSH connection ssh -o"ControlPath None" -o"IdentitiesOnly Yes" -i ~/.ssh/id_ed25519_clipboard steamdeck.local < "${ssh_pipe}" & ssh_pid="$!" # copy-paste wl-paste > "${ssh_pipe}" # close SSH sleep 0.25 kill -TERM "${ssh_pid}" # tear down named pipe rm "${ssh_pipe}" rmdir "${pipe_dir}" ``` > [!NOTE] > I am using forced commands, and this key is the one that triggers the `xclip` at the other end of the SSH connection, that's why no command is given to SSH in this example. > [!NOTE] > Signal TERM always causes `ssh` to return non-zero, so there's no trivial way to use the above snippet to get success/failure of the SSH connection. There's probably a cleverer shorter solution that relies on stuff like 'wait' and process substitutions (or unnamed pipes), to avoid the whole mktemp/mkfifo/rm/rmdir, but that's what I managed to throw together in a couple of seconds.
Author
Owner

@DrYak commented on GitHub (Jul 25, 2025):

@tmcnulty387 Re-Follow up:
Turns out the named pipe works on the command-line, but not within shell scripts: the clipboard content gets buffered inside the FIFO and the wl-paste command terminates before the SSH connection is even established, but...

There's probably a cleverer shorter solution

...I gave it more than a few seconds of thoughs this time and got a better solution.

The whole thing is due to the SSH connection still being kept up as the return pipe still open and waiting, right?
Well, let's use that other pipe:

On the remote end, I add a simple echo to signal once the clipboad has been copied:

# forced command
# Wayland
command="/usr/bin/env WAYLAND_DISPLAY='wayland-0' wl-copy; echo copied",no-agent-forwarding,no-pty,no-X11-forwarding ssh-ed25519 AAAAC3…etc…
# X11
command="xclip -display :0 -in -rmlastnl -selection clipboard; echo copied",no-agent-forwarding,no-pty,no-X11-forwarding ssh-ed25519 AAAAC3…etc…

On the sending script that is used as lan-mouse's hook:

while read -r result; do
	ssh_pid="$!"
	echo -e "${result}"
	kill -TERM "${ssh_pid}"
	exit 0
done < <(exec ssh -o"ControlPath None" -o"IdentitiesOnly Yes" -i ~/.ssh/id_ed25519_clipboard steamdeck.local < <(wl-paste) || echo "fail ?" >&2 )

echo "did not get confirmation" >&2

Details:

  • $! will hold the PID of the last background process started by the current shell. In that case that would be the sub-shell that runs the process substitution with SSH, <( … ssh …). (We ignore the wl-paste process substitution because that one happens in own context of the sub-shell, not in the current script).
  • exec will make the ssh replace that sub-shell and take over it's PID. The $! mentioned above now point to ssh and we can directly issue it signals. (Otherwise ssh gets spawned as a sub-process of the sub-shell, usually at PID $! + 1, but no guaranty)
  • read will wait for the echo output from the forced command that confirms successful copy, or EOF marker if ssh closed before (e.g. couldn't establish connection and errored out).
  • it's also possible to add a timeout to read with option -t.
  • if read gets an input we know that the copy command worked successfully and we can shut down everything cleanly by politely signaling to ssh to terminate.
    I've tested it with my real script, it works.

Tip

I should publish that script more formally and document it.

<!-- gh-comment-id:3116847441 --> @DrYak commented on GitHub (Jul 25, 2025): @tmcnulty387 Re-Follow up: Turns out the named pipe works on the command-line, but not within shell scripts: the clipboard content gets buffered inside the FIFO and the `wl-paste` command terminates before the SSH connection is even established, but... > There's probably a cleverer shorter solution ...I gave it more than a few seconds of thoughs this time and got a better solution. The whole thing is due to the SSH connection still being kept up as the return pipe still open and waiting, right? Well, let's use that other pipe: On the remote end, I add a simple `echo` to signal once the clipboad has been copied: ```text # forced command # Wayland command="/usr/bin/env WAYLAND_DISPLAY='wayland-0' wl-copy; echo copied",no-agent-forwarding,no-pty,no-X11-forwarding ssh-ed25519 AAAAC3…etc… # X11 command="xclip -display :0 -in -rmlastnl -selection clipboard; echo copied",no-agent-forwarding,no-pty,no-X11-forwarding ssh-ed25519 AAAAC3…etc… ``` On the sending script that is used as lan-mouse's hook: ```bash while read -r result; do ssh_pid="$!" echo -e "${result}" kill -TERM "${ssh_pid}" exit 0 done < <(exec ssh -o"ControlPath None" -o"IdentitiesOnly Yes" -i ~/.ssh/id_ed25519_clipboard steamdeck.local < <(wl-paste) || echo "fail ?" >&2 ) echo "did not get confirmation" >&2 ``` Details: - `$!` will hold the PID of the last background process started by the _current_ shell. In that case that would be the sub-shell that runs the process substitution with SSH, `<( … ssh …)`. (We ignore the `wl-paste` process substitution because that one happens in own context of the sub-shell, not in the current script). - `exec` will make the `ssh` _replace_ that sub-shell and take over it's PID. The `$!` mentioned above now point to `ssh` and we can directly issue it signals. (Otherwise `ssh` gets spawned as a sub-process of the sub-shell, usually at PID `$!` + 1, but no guaranty) - `read` will wait for the `echo` output from the forced command that confirms successful copy, or EOF marker if `ssh` closed before (e.g. couldn't establish connection and errored out). - it's also possible to add a timeout to `read` with option `-t`. - if `read` gets an input we know that the copy command worked successfully and we can shut down everything cleanly by politely signaling to `ssh` to terminate. I've tested it with my [real script](https://github.com/user-attachments/files/21427153/pushclipboard.gz), it works. > [!TIP] > I should publish that [script](https://github.com/user-attachments/files/21427153/pushclipboard.gz) more formally and document it.
Author
Owner

@DrYak commented on GitHub (Jul 25, 2025):

I should publish that script more formally and document it.

and...
I finally bit that bullet

Note that this script can also be used on the command line to push things around from X11 clients (where lan-mouse cannot detect attempts of the mouse leaving the screen due to lack of X11 capture support).

@feschber Do you think I should make a PR out of this script?

@all in this thread: could you also document your implemented solutions if you managed to setup some?

We could keep documentation about a couple of solutions such as mine, and make a PR into lan-mouse so future users have a couple of different solutions to pick from.

<!-- gh-comment-id:3117610109 --> @DrYak commented on GitHub (Jul 25, 2025): > I should publish that [script](https://github.com/user-attachments/files/21427153/pushclipboard.gz) more formally and document it. and... [I finally bit that bullet](https://github.com/feschber/lan-mouse/issues/258#issuecomment-3117557919) Note that this script can _also_ be used on the command line to push things around from X11 clients (where lan-mouse cannot detect attempts of the mouse leaving the screen due to lack of X11 capture support). @feschber Do you think I should make a PR out of this script? **\@all** in this thread: could you also document your implemented solutions if you managed to setup some? - @dougg0k > There is a simple and working clipboard impl with tls encryption https://github.com/reu/clipshare https://github.com/morn-0/share-clip - @tmcnulty387 > Also, currently using https://github.com/quackduck/uniclip/ instead and it's working great so far. - @sohanemon > I'm using Syncthing to share the clipboard history file, and it's working perfectly. - @rodhfr > For anyone like me wanting a quick&dirty script - @fentas > Not sure, I Had a look around and found this one https://github.com/songokas/clipboard-sync Worth a look? We could keep documentation about a couple of solutions such as mine, and make a PR into lan-mouse so future users have a couple of different solutions to pick from.
Author
Owner

@tmcnulty387 commented on GitHub (Jul 25, 2025):

It appears that my issue was a GNOME-specific issue, where I believe both wl-copy and wl-paste won't work when GNOME is in the overview mode and will cause the wl-clipboard processes to freeze and build up.

It works fine when I'm not in overview and the processes don't build up, but when something in the background calls wl-copy or wl-paste when in the overview mode it does not work. And usually wl-copy and/or wl-paste just stops working after processes start building up and I need to force quit any processes that had built up and restart lan-mouse or uniclip. I also used to get "wl-clipboard is ready" notifications occasionally which I turned off using an extension.

If anyone else that's also using GNOME could reproduce this that would be helpful. The timeout should work on paper and fix this. I'll try the updated script when I get the chance.

<!-- gh-comment-id:3118731548 --> @tmcnulty387 commented on GitHub (Jul 25, 2025): It appears that my issue was a GNOME-specific issue, where I believe both wl-copy and wl-paste won't work when GNOME is in the overview mode and will cause the wl-clipboard processes to freeze and build up. It works fine when I'm not in overview and the processes don't build up, but when something in the background calls wl-copy or wl-paste when in the overview mode it does not work. And usually wl-copy and/or wl-paste just stops working after processes start building up and I need to force quit any processes that had built up and restart lan-mouse or uniclip. I also used to get "wl-clipboard is ready" notifications occasionally which I turned off using an extension. If anyone else that's also using GNOME could reproduce this that would be helpful. The timeout should work on paper and fix this. I'll try the updated script when I get the chance.
Author
Owner

@tmcnulty387 commented on GitHub (Jul 26, 2025):

Update: Instead of trying the updated script, I ended up switching from GNOME to hyprland and went back to using uniclip. Everything now is working fine.

<!-- gh-comment-id:3123423386 --> @tmcnulty387 commented on GitHub (Jul 26, 2025): Update: Instead of trying the updated script, I ended up switching from GNOME to hyprland and went back to using uniclip. Everything now is working fine.
Author
Owner

@DrYak commented on GitHub (Jul 30, 2025):

@tmcnulty387

went back to using uniclip.

Do you think you could find time to document your configuration of Uniclip in the howto thread #258?

<!-- gh-comment-id:3135381239 --> @DrYak commented on GitHub (Jul 30, 2025): @tmcnulty387 > went back to using uniclip. Do you think you could find time to document your configuration of Uniclip in the howto thread #258?
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: github-starred/lan-mouse#41
No description provided.