Skip to content

Instantly share code, notes, and snippets.

@kiko
Last active December 24, 2015 01:39
Show Gist options
  • Save kiko/6724792 to your computer and use it in GitHub Desktop.
Save kiko/6724792 to your computer and use it in GitHub Desktop.
diff --git a/chroot-bin/croutonclip b/chroot-bin/croutonclip
index a280419..226f26d 100755
--- a/chroot-bin/croutonclip
+++ b/chroot-bin/croutonclip
@@ -5,6 +5,7 @@
#
# Synchronizes clipboard between X displays, making use of crouton's WebSocket
# server and Chromium extension to synchronize the clipboard with Chromium OS
+# Define XMETHOD variable (x11, xephyr or cros) in prior to run this script.
VERBOSE=''
@@ -47,7 +48,7 @@ copyclip() {
# Copy clipboard content from the current display
{
- if [ "$current" = ':0' ]; then
+ if [ "$current" = 'aura' ]; then
echo -n 'R' | websocketcommand
else
# Check if display is still running
@@ -68,7 +69,7 @@ copyclip() {
fi
# Paste clipboard content to the next display
- if [ "$next" = ':0' ]; then
+ if [ "$next" = 'aura' ]; then
STATUS="`(echo -n 'W'; cat) | websocketcommand`"
if [ "$STATUS" != 'WOK' ]; then
# Write failed, skip Chromium OS (do not update $current)
@@ -125,20 +126,19 @@ waitwebsocket() {
croutonwebsocket &
addtrap "kill $! 2>/dev/null"
-xmethod="`readlink -f '/etc/X11/xinit/xserverrc'`"
-xmethod="${xmethod##*-}"
-
# For both x11/xephyr, the code works as follow:
# - A command outputs one line per event (window/tty change).
# - In a second subshell, read these events, one by one, and transfer the
# clipboard content.
# This makes sure we do not miss any events and that we copy the clipboard
# around in the right sequence.
+# For cros, guest OS shares X display with Chrome OS (:0).
-if [ "$xmethod" = 'xephyr' ]; then
+case "$XMETHOD" in
+'xephyr' | 'cros')
# Assume current display is Chromium OS, as the awk script does not detect
# the current window
- current=':0'
+ current='aura'
# Wait for ratpoison to come up
while ! host-x11 xprop -root _NET_WM_NAME | grep -q 'ratpoison'; do
@@ -175,7 +175,9 @@ if [ "$xmethod" = 'xephyr' ]; then
# Translate window id to display number
id="${line%,}"
if [ "$id" = "$aura" ]; then
- display=":0"
+ display="aura"
+ elif [ "$XMETHOD" = 'cros' ]; then
+ display=':0'
else
# This relies on WM_NAME looking like "Xephyr on :1.0 (...)"
display="`host-x11 xprop -format WM_NAME 8s '\t$0' \
@@ -185,8 +187,8 @@ if [ "$xmethod" = 'xephyr' ]; then
copyclip "$display"
done
- }
-elif [ "$xmethod" = 'x11' ]; then
+ };;
+'x11')
# No need to set $current:
# croutonvtmonitor outputs the current tty right after it is started
@@ -204,7 +206,7 @@ elif [ "$xmethod" = 'x11' ]; then
while read tty; do
display=''
if [ "$tty" = "tty1" ]; then
- display=":0"
+ display="aura"
else
# Find which process owns the tty
process="`ps -o pid= -t "$tty" | sed 's/ //g'`"
@@ -222,9 +224,8 @@ elif [ "$xmethod" = 'x11' ]; then
copyclip "$display"
done
- }
-else
- echo "Invalid xmethod='$xmethod'." >&2
-fi
-
+ };;
+*)
+ echo "Invalid xmethod='$XMETHOD'." >&2;;
+esac
exit 1
#!/bin/sh -e
# Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
#
# Synchronizes clipboard between X displays, making use of crouton's WebSocket
# server and Chromium extension to synchronize the clipboard with Chromium OS
# Define XMETHOD variable (x11, xephyr or cros) in prior to run this script.
VERBOSE=''
. "`dirname "$0"`/../installer/functions"
PIPEDIR='/tmp/crouton-ext'
PIPEIN="$PIPEDIR/in"
PIPEOUT="$PIPEDIR/out"
PIPELOCK="$PIPEDIR/lock"
# Write a command to croutonwebsocket, and read back response
websocketcommand() {
# Check that $PIPEDIR and the FIFO pipes exist
if ! [ -d "$PIPEDIR" -a -p "$PIPEIN" -a -p "$PIPEOUT" ]; then
echo "EError $PIPEIN or $PIPEOUT are not pipes."
exit 0
fi
(
flock 5
cat > "$PIPEIN"
cat "$PIPEOUT"
) 5>"$PIPELOCK"
}
current=''
copyclip() {
next="$1"
# Do not copy if next is empty (display cannot be detected), or
# if current == next. Also set current=$next if $current is empty
if [ -z "$next" -o "${current:="$next"}" = "$next" ]; then
return 0
fi
if [ -n "$VERBOSE" ]; then
echo ">>Current: $current>>"
fi
# Copy clipboard content from the current display
{
if [ "$current" = 'aura' ]; then
echo -n 'R' | websocketcommand
else
# Check if display is still running
if DISPLAY="$current" xdpyinfo >/dev/null 2>&1; then
echo -n 'R'
DISPLAY="$current" xclip -o -sel clip
else
echo -n "EUnable to open display '$current'."
fi
fi
} | (
STATUS="`head -c 1`"
if [ "$STATUS" != 'R' ]; then
echo -n "croutonwebsocket error: " >&2
cat >&2
# Stop here (the clipboard content is lost in this case)
exit 0
fi
# Paste clipboard content to the next display
if [ "$next" = 'aura' ]; then
STATUS="`(echo -n 'W'; cat) | websocketcommand`"
if [ "$STATUS" != 'WOK' ]; then
# Write failed, skip Chromium OS (do not update $current)
echo -n "croutonwebsocket error: $STATUS" >&2
exit 1
fi
else
# Do not override content if it "looks" the same
# (we might have rich text or other content in the clipboard)
cliptmp="`mktemp "croutonclip.XXX" --tmpdir=/tmp`"
trap "rm -f '$cliptmp'" 0
cat > $cliptmp
if ! DISPLAY="$next" xclip -o -sel clip | diff -q - "$cliptmp" > /dev/null; then
cat "$cliptmp" | DISPLAY="$next" xclip -i -sel clip
fi
fi
) && current="$next"
if [ -n "$VERBOSE" ]; then
echo "<<Next: $current<<"
fi
}
# Wait for the websocket server to get connected to the extension
# Timeout after 10 seconds (twice crouton extension retry period)
waitwebsocket() {
timeout=10
while [ $timeout -gt 0 ]; do
if [ -n "$VERBOSE" ]; then
echo "Ping..."
fi
# Prepare and send a ping message
MSG="PING$$$timeout"
STATUS="`echo -n "$MSG" | websocketcommand`"
if [ "$STATUS" = "$MSG" ]; then
if [ -n "$VERBOSE" ]; then
echo "OK!"
fi
return 0
fi
if [ -n "$VERBOSE" ]; then
echo "$STATUS"
fi
sleep 1
timeout=$(($timeout-1))
done
echo "Timeout waiting for extension to connect." >&2
}
croutonwebsocket &
addtrap "kill $! 2>/dev/null"
# For both x11/xephyr, the code works as follow:
# - A command outputs one line per event (window/tty change).
# - In a second subshell, read these events, one by one, and transfer the
# clipboard content.
# This makes sure we do not miss any events and that we copy the clipboard
# around in the right sequence.
# For cros, guest OS shares X display with Chrome OS (:0).
case "$XMETHOD" in
'xephyr' | 'cros')
# Assume current display is Chromium OS, as the awk script does not detect
# the current window
current='aura'
# Wait for ratpoison to come up
while ! host-x11 xprop -root _NET_WM_NAME | grep -q 'ratpoison'; do
sleep .1
done 2>&-
# Get the aura root window number (hex)
aura="`host-x11 xwininfo -root -children | mawk '/aura_root/ {print $1}'`"
# Detect window change using MapNotify events that do not have the
# override-redirect flag ("override NO" in xev events)
{
host-x11 xev -root &
cpid=$!
addtrap "kill $cpid 2>/dev/null"
if ! wait $cpid; then
echo "croutonclip: xev error ($?)"
fi
} | mawk -W interactive '
m {
if ($6 == "NO") {
print $4 # Window id
}
m = 0
}
/^MapNotify/ {
m = 1
}
' | {
# Wait for extension to connect (do not fail even if it times out)
waitwebsocket
while read line; do
# Translate window id to display number
id="${line%,}"
if [ "$id" = "$aura" ]; then
display="aura"
elif [ "$XMETHOD" = 'cros' ]; then
display=':0'
else
# This relies on WM_NAME looking like "Xephyr on :1.0 (...)"
display="`host-x11 xprop -format WM_NAME 8s '\t$0' \
-id "$id" WM_NAME | cut -f 2 | \
sed -n -e 's/^\"Xephyr on \(:[0-9]\{1,\}\).*$/\1/p'`"
fi
copyclip "$display"
done
};;
'x11')
# No need to set $current:
# croutonvtmonitor outputs the current tty right after it is started
{
croutonvtmonitor &
cpid=$!
addtrap "kill $cpid 2>/dev/null"
if ! wait $cpid; then
echo "croutonclip: croutonvtmonitor error ($?)"
fi
} | {
# Wait for extension to connect (do not fail even if it times out)
waitwebsocket
while read tty; do
display=''
if [ "$tty" = "tty1" ]; then
display="aura"
else
# Find which process owns the tty
process="`ps -o pid= -t "$tty" | sed 's/ //g'`"
if [ -n "$process" ]; then
# Find which display the process owns (if any)
for lock in /tmp/.X*-lock; do
if grep -q "^ *$process$" "$lock"; then
display="${lock#/tmp/.X}"
display=":${display%-lock}"
fi
done
fi
fi
copyclip "$display"
done
};;
*)
echo "Invalid xmethod='$XMETHOD'." >&2;;
esac
exit 1
@kiko
Copy link
Author

kiko commented Oct 2, 2013

You genius, all hacks are removed now. Thanks again!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment