bugaevc / wl-clipboard

Command-line copy/paste utilities for Wayland
GNU General Public License v3.0
1.62k stars 59 forks source link

wl-copy hangs reading stdin if it is not run from a pseudoterminal #228

Open dkg opened 4 months ago

dkg commented 4 months ago

I'm using wl-clipboard 2.2.1-1 on debian.

I have a machine running a wayland session (with sway as a compositor) on wayland-1. If i ssh into that machine and do env WL_DISPLAY=wayland-1 wl-copy then i can type on stdin, and hit ctrl-D to end the input, and it gets placed in the wayland clipboard.

Alternately, from the ssh session, i can do:

echo test | env WAYLAND_DISPLAY=wayland-1 wl-copy

and it puts the string test in the wayland clipboard and terminates. Success so far!

however, if i do this all in one go from outside the machine, it hangs:

echo test | ssh $MACHINE env WAYLAND_DISPLAY=wayland-1 wl-copy

i've tried using strace to understand what's happening, but it looks like there are subprocesses i don't understand (cat and file)

dkg commented 4 months ago

does this have something to do with wl-copy forking into the background?

jidanni commented 4 months ago

Maybe we could make a shell script wrapper so that I can even call my-wl-copy on a region in emacs and it won't hang.

P.S., I checked but don't unhttps://www.emacswiki.org/emacs/CopyAndPaste#h5o-4

methuselah-0 commented 3 weeks ago

does this have something to do with wl-copy forking into the background?

Related issues: #110, #154, #212, #224

FWIW, I wrote a little shell script to sync the clipboard over ssh, maybe only works on text idk, but it keeps it synced two-way which is nice, and you can probably sync multiple virtual machines like this if you want.

# Protect trailing newlines from chomping
latestlocal="$(${HOST_PASTE_COMMAND} && printf '%s' x)"
latestlocal="${latestlocal%x}"
latestremote="$(ssh -p $PORT -S ~/.ssh/sockets/$USERNAME@$HOSTNAME:$PORT $USERNAME@$HOSTNAME "WAYLAND_DISPLAY=wayland-1 ${REMOTE_PASTE_COMMAND} && printf '%s' x")"
latestremote="${latestremote%$'\n'x}" # an extra newline at the end is actually added not sure why, so we remove that too.

while : ; do sleep 1;
  new="$(ssh -p $PORT -S ~/.ssh/sockets/$USERNAME@$HOSTNAME:$PORT $USERNAME@$HOSTNAME "WAYLAND_DISPLAY=wayland-1 ${REMOTE_PASTE_COMMAND} && printf '%s' x")"
  new="${new%$'\n'x}" # remove the extra newline and the x
  if [[ "$new" != "$latestremote" ]]; then 
    latestremote="$new" && printf '%s' "$new" | ${HOST_COPY_COMMAND}
    latestlocal="$new";
  fi

  newlocal="$($HOST_PASTE_COMMAND && printf '%s' x)" # deal with newline-chomps, removing it at destination
  if [[ "$latestlocal" != "$newlocal" ]]; then
     latestlocal="$newlocal"
     secret="$RANDOM$RANDOM$RANDOM$RANDOM"
     ssh -p $PORT -t -S ~/.ssh/sockets/$USERNAME@$HOSTNAME:$PORT $USERNAME@$HOSTNAME "export WAYLAND_DISPLAY=wayland-1 ; a=\"\$(cat <<'$secret'
$latestlocal
$secret
)\"; printf '%s' \"\${a%x}\" | ${REMOTE_COPY_COMMAND}"
  fi
done

For emacs, check this out: https://www.emacswiki.org/emacs/CopyAndPaste#h5o-4