Sync Clipboard

I love the global clipboard. And I do use it often.

A bit too often actually. So much that having 4 keyboard shortcuts for every action is tedious and unsustainable when used a lot.
My dev VM and target VM are different, but have the same security level. And so, I felt it is fine to explicitly share the clipboard between them. Even the selection clipboard, so a single middle click works across VMs.

#!/bin/bash

launcher="/home/user/.config/xfce4/panel/launcher-23/17858728661.desktop"
pairs=$(grep Comment "$launcher" | cut -d '=' -f 2)
vms=$(qvm-ls --running --raw-list --fields NAME | grep -Ev "dom0|sys-")
if [[ -n "$pairs" ]]; then vms=$(echo -e "CLEAR ALL\n$vms"); fi

activeVM () {
	id=$(xprop -notype -root _NET_ACTIVE_WINDOW | awk '{print $5}' | tr -d ',')
	xprop -id $id -notype _QUBES_VMNAME | awk '{print $3}' | tr -d '"'
}
VM1=$(activeVM)
if [[ "${vms[*]}" != "$VM1" ]]; then exit 1; fi

VM2=$(echo "$vms" | grep -Ev "^$VM1$" | zenity --list --title="Sync $VM1 Clipboard" --column="To…" --height=400 --width=300 2>/dev/null)
if [[ "$VM2" == "" ]]; then echo "Cancelled"; exit 2; fi
if [[ "$VM2" == "CLEAR ALL" ]]
then
	echo "Clearing"
	sed -i 's/Comment=./Comment=/' "$launcher"
	sed -i 's/Icon=./Icon=qui-clipboard-light/' "$launcher"
	pkill -9 -f $(realpath "$0"); exit 3
fi

sed -i '/Comment=/ s/$/\n'"$VM1 > $VM2"'/' "$launcher"
sed -i 's/Icon=.*/Icon=qui-clipboard-dark/' "$launcher"

_clip=""; _sele=""
while true
do
	if [[ $(activeVM) != "$VM1" ]]; then sleep 1; continue; fi

	sele=$(qvm-run -np "$VM1" 'xclip -o')
	if [[ ! "$sele" == "$_sele" ]]
	    then
			_sele=$(echo "$sele");
		    echo "$VM1 - Selection: $sele"
		    echo -ne "$sele" | qvm-run -np "$VM2" 'xclip -i &>/dev/null'
		n=$(echo "$sele" | wc -c) ; notify-send "Selection: $VM1 > $VM2" "$n bytes" -t 200
	fi

	clip=$(qvm-run -np "$VM1" 'xclip -o -selection clipboard')
	if [[ ! "$clip" == "$_clip" ]]
	then
		_clip=$(echo "$clip");
		echo "$VM1 - Clipboard: $clip"
		echo -ne "$clip" | qvm-run -np "$VM2" 'xclip -i -selection clipboard &>/dev/null'
		n=$(echo "$clip" | wc -c) ; notify-send "Clipboard: $VM1 > $VM2" "$n bytes" -t 5000
	fi
	sleep 1
done

The UI is simple:
Create a launcher to run the script, edit the script launcher var to that launcher so it can dynamically update the icon and tooltip.

2 Likes

I believe that if you wanted to make it more secure (not involve dom0 in such a capacity) you could also just use qrexec directly between VMs.

3 Likes

Yeah, this was a quick and dirty poc.
The proper way would be to do qrexec and use the policy engine.
Would still want to do the UI in dom0 though.

1 Like