-
-
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 |
Hi, Thanks a lot for your feedback!
- Nice, I didn't like
:1
hack but didn't want to pollute your code. I'll try to rearrange as you suggested. - I don't know why crouton hard code ratpoison here and there. I think we can use virtually any window manager we want, can't we?
- I added
xserverrc-cros
becausecroutonclip
usesxserverrc-*
suffix to determine$xmethod
https://github.com/drinkcat/chroagh/blob/master/chroot-bin/croutonclip#L128
Huh, I don't know why I didn't get notification of your comment.
Yes, you can use another window manager (at long as it allows Chrome to be in full screen, I guess that'd be weird otherwise). ratpoison is what we install by default in the Xephyr setup, that's why it's hardcoded.
Good point about xserverrc-cros
, can't remember what my own code does ,-)
Line 183: Can't just just set this to display=':0'? That'll remove the hacks in copyclip.
Apart from that, looks good!
One more thing... Trying to figure out how to integrate this neatly in the crouton framework.
You could remove lines 130-131, and instead rely on an environment variable XMETHOD that needs to be passed to the script. That removes the need for the xserverr-cros
hack, and make it possible to use the script in both cros
or x11
/xephyr
context.
You genius, all hacks are removed now. Thanks again!
Nice! Thanks for the contribution.
A few things that can be improved:
:0
as meaning that we want to copy the clipboard from Chrome. Since you actually want to update the clipboard on display:0
, you could change that, and usedisplay="aura"
instead ofdisplay=":0"
in both xephyr and x11 methods (and change the original values toaura
, as well as the tests incopyclip
)cros
andxephyr
share a lot of code. You could merge them together, and skip the while loop waiting for ratpoison (but don't you need ratpoison anyway?), and assign display to:0
in the cros case, without to trying to parse the Xephyr window name.chroot-etc/xserverrc-cros
serves (it looks identical to whathost-x11
does).