2

I would like to setup a paste functionality allowing to paste copied text (like scripts and configuration files) to any kind of application, including virtual guests and remote sessions running graphical clients such as VNC (where a standard copy-paste is not possible).

To achieve this, I associated a shortcut in my desktop manager to the following command:

sh -c 'sleep 1; xdotool type -- "$(xsel -bo)"'

This works... but only for certain apps (and sadly VNC is not part of them, cruel world!).

  • If I use this to paste the text into a vi running in xterm on the local host, then this works perfectly: the content of the file is preserved and written as expected. This also seem to work flawlessly in gnome-terminal.
  • If vi runs in xfce4-terminal for instance still on the local host, all carriage returns are mangled.
  • Similarly, if I try to paste to paste the text to any application (including xterm) through VNC, the text is correctly typed but here again all on a single line.

Where it becomes weird, it's that if I attach the following command to another keyboard shortcut:

sh -c 'sleep 1; xdotool key Return'

Here xdotool manages to input the carriage return in any application, so it is technically possible.

I tried to build on this as an ugly workaround to enforce the carriage return:

sh -c 'sleep 1; xsel -bo | { while read -r LINE; do xdotool type -- "$LINE"; xdotool key Return; done; }'

Now carriage return "works" this workaround now mangles the tabs and in all cases I don't like it as I won't always want the final carriage return (for instance when filling a web form field without immediately submitting it).

I think I have the same problem as this guy, but sadly the thread has no explanation.

Where is the problem? How can I make this work? Or if for some reason this is not possible is there another lightweight alternative for my initial need?

2

For historical reasons, there are two characters that represent line breaks: line feed (commonly represented as LF, \n, \012, Ctrl+J, …) and carriage return (CR, \r, \015, Ctrl+M). Unix uses LF as the line terminator character, but keyboards send CR when you press Return. Some applications recognize a Linefeed key (which exists on some rare keyboards that weren't made for the PC market), but that's rare.

Experimentally, when there's a line break in the string, xdotool sends a Linefeed key. I'm not surprised that some applications don't recognize that. You can make it send Return instead by replacing the newlines with carriage returns.

sleep 1; xdotool type -- "$(xsel -bo | tr \\n \\r | sed s/\\r*\$//)"

Your workaround can also be made to work. Set IFS to an empty value, otherwise read strips off the leading and trailing whitespace on each line (that's why the tabs are disappearing). And don't send a Return after the last line. (This isn't strictly equivalent to the command substitution method: with a command substitution, all trailing empty lines are removed; with the following method, only the one final newline, if any, is ignored.)

sleep 1
xsel -bo | {
  IFS= read -r LINE;
  xdotool type -- "$LINE";
  while IFS= read -r LINE; do
    xdotool key Return;
    xdotool type -- "$LINE";
  done;
}

Note: I haven't tried anything in VNC, so your mileage may vary.

  • Thank you, I wouldn't figure out that "keyboards send CR when you press 'Return'", I really like your one-liner which indeed works fine. I already came up with a solution similar to your second proposition, with an added wid="$( xdotool getwindowfocus )" line and --window "$wid" parameters added to xdotools commands so the resulting script won't potentially impact several windows on focus change, but the one-liner is clearly an improvement and now I understand the root cause! – WhiteWinterWolf Oct 22 '17 at 8:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.