diff --git a/CONTRIBUTORS b/CONTRIBUTORS index a7a6169ec..915787ff0 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -1,22 +1,33 @@ Alex Bennée +Alfred Suleymanov +Andrew Kanner Aron Griffis Blaine Bublitz Chris Galle +Christopher MÃ¥rtensson Corey Garst David Schneider Dennis Lockhart dimonf +dumpweed +George Shank Igor Bukanov +Javi Merino Jim Tittsler John Tantalo +Kenny Strawn Maurice van Kruchten Micah Lee Michael Orr +Mike Kasick Mikito Takada Nevada Romsdahl Nicolas Boichat +Samuel Dionne-Riel Stephen Barber Steven Maude +Ted Matsumura Tobbe Lundberg Tony Xue +Yu-Hsi Chiang Yuri Pole diff --git a/LICENSE b/LICENSE index c93141311..ef05f9ed6 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -// Copyright (c) 2014 The crouton Authors. All rights reserved. +// Copyright (c) 2015 The crouton Authors. All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are diff --git a/Makefile b/Makefile index 9a3eb63a1..6883b1687 100644 --- a/Makefile +++ b/Makefile @@ -1,10 +1,12 @@ -# Copyright (c) 2014 The crouton Authors. All rights reserved. +# Copyright (c) 2015 The crouton Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. TARGET = crouton EXTTARGET = crouton.zip -SRCTARGETS = $(patsubst src/%.c,crouton%,$(wildcard src/*.c)) +LIBS = src/freon.c +LIBSTARGETS = $(patsubst src/%.c, crouton%.so, $(LIBS)) +SRCTARGETS = $(patsubst src/%.c,crouton%,$(filter-out $(LIBS),$(wildcard src/*.c))) CONTRIBUTORS = CONTRIBUTORS WRAPPER = build/wrapper.sh SCRIPTS := \ @@ -15,6 +17,9 @@ SCRIPTS := \ $(wildcard installer/*/*) \ $(wildcard src/*) \ $(wildcard targets/*) +EXTPEXE = host-ext/crouton/kiwi.pexe +EXTPEXESOURCES = $(wildcard host-ext/nacl_src/*.h) \ + $(wildcard host-ext/nacl_src/*.cc) EXTSOURCES = $(wildcard host-ext/crouton/*) GENVERSION = build/genversion.sh CONTRIBUTORSSED = build/CONTRIBUTORS.sed @@ -28,6 +33,7 @@ croutoncursor_LIBS = -lX11 -lXfixes -lXrender croutonfbserver_LIBS = -lX11 -lXdamage -lXext -lXfixes -lXtst croutonwmtools_LIBS = -lX11 croutonxi2event_LIBS = -lX11 -lXi +croutonfreon.so_LIBS = -ldl croutonwebsocket_DEPS = src/websocket.h croutonfbserver_DEPS = src/websocket.h @@ -56,13 +62,19 @@ $(TARGET): $(WRAPPER) $(SCRIPTS) $(GENVERSION) $(GITHEAD) Makefile $(EXTTARGET): $(EXTSOURCES) Makefile rm -f $(EXTTARGET) && zip -q --junk-paths $(EXTTARGET) $(EXTSOURCES) -$(SRCTARGETS): src/$(patsubst crouton%,src/%.c,$@) $($@_DEPS) Makefile +$(EXTPEXE): $(EXTPEXESOURCES) + $(MAKE) -C host-ext/nacl_src + +$(SRCTARGETS): $(patsubst crouton%,src/%.c,$@) $($@_DEPS) Makefile gcc $(CFLAGS) $(patsubst crouton%,src/%.c,$@) $($@_LIBS) -o $@ +$(LIBSTARGETS): $(patsubst crouton%.so,src/%.c,$@) $($@_DEPS) Makefile + gcc $(CFLAGS) -shared -fPIC $(patsubst crouton%.so,src/%.c,$@) $($@_LIBS) -o $@ + extension: $(EXTTARGET) $(CONTRIBUTORS): $(GITHEAD) $(CONTRIBUTORSSED) - git shortlog -s | sed -f $(CONTRIBUTORSSED) | sort -u > $(CONTRIBUTORS) + git shortlog -s | sed -f $(CONTRIBUTORSSED) | sort -uf > $(CONTRIBUTORS) contributors: $(CONTRIBUTORS) @@ -74,9 +86,9 @@ release: $(CONTRIBUTORS) $(TARGET) $(RELEASE) force-release: $(CONTRIBUTORS) $(TARGET) $(RELEASE) $(RELEASE) -f $(TARGET) -all: $(TARGET) $(SRCTARGETS) $(EXTTARGET) +all: $(TARGET) $(SRCTARGETS) $(LIBSTARGETS) $(EXTTARGET) clean: - rm -f $(TARGET) $(EXTTARGET) $(SRCTARGETS) + rm -f $(TARGET) $(EXTTARGET) $(SRCTARGETS) $(LIBSTARGETS) .PHONY: all clean contributors extension release force-release diff --git a/README.md b/README.md index 44119b465..34b8ac7ee 100644 --- a/README.md +++ b/README.md @@ -192,7 +192,7 @@ Examples 2. Run `sh ~/Downloads/crouton -r list` to list the recognized releases and which distros they belong to. -### Wasteful rendundancies are wasteful: one clipboard, one browser, one window +### Wasteful redundancies are wasteful: one clipboard, one browser, one window 1. Install the [crouton extension](https://goo.gl/OVQOEt) into Chromium OS. 2. Add the `extension` or `xiwi` version to your chroot. 3. Try some copy-pasta, or uninstall all your web browsers from the chroot. @@ -355,7 +355,7 @@ There's a way For Everyone to help! License ------- -crouton (including this eloquently-written README) is copyright © 2014 The +crouton (including this eloquently-written README) is copyright © 2015 The crouton Authors. All rights reserved. Use of the source code included here is governed by a BSD-style license that can be found in the LICENSE file in the source tree. diff --git a/build/CONTRIBUTORS.sed b/build/CONTRIBUTORS.sed index 89347ce2e..df4ca8db2 100644 --- a/build/CONTRIBUTORS.sed +++ b/build/CONTRIBUTORS.sed @@ -1,6 +1,8 @@ s/^[ \t0-9]*// s/^DennisL.*$/Dennis Lockhart/ s/^divx118$/Maurice van Kruchten/ +s/^tedm$/Ted Matsumura/ /^root$/d /^ttk153$/d /^lnxsrt$/d +/\?/d diff --git a/build/genversion.sh b/build/genversion.sh index f9f253b95..a269e140f 100755 --- a/build/genversion.sh +++ b/build/genversion.sh @@ -1,5 +1,5 @@ #!/bin/sh -e -# Copyright (c) 2014 The crouton Authors. All rights reserved. +# Copyright (c) 2015 The crouton Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. diff --git a/build/release.sh b/build/release.sh index a18d857e6..c8d24eeba 100755 --- a/build/release.sh +++ b/build/release.sh @@ -1,5 +1,5 @@ #!/bin/sh -e -# Copyright (c) 2014 The crouton Authors. All rights reserved. +# Copyright (c) 2015 The crouton Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. diff --git a/build/wrapper.sh b/build/wrapper.sh index ea7f11d5c..7da5354d5 100644 --- a/build/wrapper.sh +++ b/build/wrapper.sh @@ -1,5 +1,5 @@ #!/bin/sh -e -# Copyright (c) 2014 The crouton Authors. All rights reserved. +# Copyright (c) 2015 The crouton Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file of the source repository, which has been replicated # below for convenience of distribution: diff --git a/chroot-bin/brightness b/chroot-bin/brightness index 8f1a14062..380672395 100755 --- a/chroot-bin/brightness +++ b/chroot-bin/brightness @@ -1,5 +1,5 @@ #!/bin/sh -e -# Copyright (c) 2014 The crouton Authors. All rights reserved. +# Copyright (c) 2015 The crouton Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. diff --git a/chroot-bin/crouton-noroot b/chroot-bin/crouton-noroot index 08b94fb0e..07fe28b5b 100755 --- a/chroot-bin/crouton-noroot +++ b/chroot-bin/crouton-noroot @@ -1,5 +1,5 @@ #!/bin/sh -e -# Copyright (c) 2014 The crouton Authors. All rights reserved. +# Copyright (c) 2015 The crouton Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. diff --git a/chroot-bin/crouton-unity-autostart b/chroot-bin/crouton-unity-autostart index eec2f18f8..bfbfa891f 100755 --- a/chroot-bin/crouton-unity-autostart +++ b/chroot-bin/crouton-unity-autostart @@ -1,5 +1,5 @@ #!/bin/sh -e -# Copyright (c) 2014 The crouton Authors. All rights reserved. +# Copyright (c) 2015 The crouton Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/chroot-bin/croutonclip b/chroot-bin/croutonclip index 310419ab1..8180287eb 100755 --- a/chroot-bin/croutonclip +++ b/chroot-bin/croutonclip @@ -1,5 +1,5 @@ #!/bin/sh -e -# Copyright (c) 2014 The crouton Authors. All rights reserved. +# Copyright (c) 2015 The crouton Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/chroot-bin/croutoncycle b/chroot-bin/croutoncycle index 1d1c152c1..331b3736c 100755 --- a/chroot-bin/croutoncycle +++ b/chroot-bin/croutoncycle @@ -1,5 +1,5 @@ #!/bin/sh -e -# Copyright (c) 2014 The crouton Authors. All rights reserved. +# Copyright (c) 2015 The crouton Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. @@ -76,9 +76,6 @@ export XAUTHORITY='' # Set to y if there is any xiwi instance running xiwiactive='' -# Set to y if aura is running without a X server -noaurax='' - # Prepare display list for easier looping displist='' for disp in /tmp/.X*-lock; do @@ -91,33 +88,36 @@ for disp in /tmp/.X*-lock; do | grep -q 'INTEGER'; then displist="$displist $disp" elif DISPLAY="$disp" xprop -root 'CROUTON_XMETHOD' 2>/dev/null \ - | grep -q '= "xiwi"$'; then + | grep -q '= "xiwi'; then displist="$displist $disp" xiwiactive='y' fi done -# host-x11 fails if no Chromium OS server exist -if host-x11 true 2>/dev/null; then +# Set to the freon display owner if freon is used +freonowner='' +if [ ! -f "/sys/class/tty/tty0/active" ]; then + if [ -f "/tmp/crouton-lock/display" ]; then + read -r freonowner < "/tmp/crouton-lock/display" + fi + freonowner="${freonowner:-0}" + winlist="aura*" + aurawin="aura" + tty='' +else # List windows on :0. Includes aura winlist="`host-x11 croutonwmtools list nim | \ sort | awk '{ printf $NF " " }'`" aurawin="`host-x11 croutonwmtools list ni | \ awk '$1 == "aura_root_0" { print $NF; exit }'`" tty="`cat '/sys/class/tty/tty0/active'`" -else - # No X11 server - noaurax='y' - winlist="aura*" - aurawin="aura" - tty="tty1" fi # Combine the two fulllist="$winlist$displist" fulllist="${fulllist% }" -if [ "$tty" = 'tty1' ]; then +if [ "$freonowner" = 0 -o "$tty" = 'tty1' ]; then # Either in Chromium OS, xephyr/xiwi chroot, or window. # Active window is starred. for disp in $winlist; do @@ -133,7 +133,7 @@ if [ "$tty" = 'tty1' ]; then break fi done -else +elif [ -z "$freonowner" ]; then # Poll the displays to figure out which one owns this VT curdisp="$tty" for disp in $displist; do @@ -143,6 +143,14 @@ else break fi done +else + # Match the pid to the current freon owner + for lockfile in /tmp/.X*-lock; do + if grep -q "\\<$freonowner$" "$lockfile"; then + curdisp="${lockfile#*X}" + curdisp=":${curdisp%%-*}" + fi + done fi # List the displays if requested @@ -153,13 +161,14 @@ if [ "$cmd" = 'l' -o "$cmd" = 'd' ]; then '/var/host/lsb-release'`" fi ( - if [ -z "$noaurax" ]; then + if [ -z "$freonowner" ]; then host-x11 croutonwmtools list nim else echo "aura_root_0 aura*" fi ) | sort | while read -r line; do disp="${line##* }" + display="${disp%"*"}" line="${line% *}" number='0' active=' ' @@ -169,7 +178,7 @@ if [ "$cmd" = 'l' -o "$cmd" = 'd' ]; then if [ "${number#[0-9]}" = "$number" ]; then number='0' else - disp=":$number" + display=":$number" line="`getname "$number"`" fi fi @@ -187,11 +196,11 @@ if [ "$cmd" = 'l' -o "$cmd" = 'd' ]; then fi if [ "$line" = 'aura_root_0' ]; then line="$chromiumos" - disp="cros" + display="cros" window='' fi if [ "$cmd" = 'l' ]; then - echo "${disp%"*"}$active $line" + echo "$display$active $line" fi done for disp in $displist; do @@ -216,6 +225,12 @@ fi if [ -n "${cmd#[pn]}" ]; then if [ "${cmd#:}" != "$cmd" ]; then destdisp="$cmd" + # Resolve a xephyr display into its ID + if DISPLAY="$destdisp" xprop -root 'CROUTON_XMETHOD' 2>/dev/null \ + | grep -q '= "xephyr"$'; then + destdisp="`host-x11 croutonwmtools list ni | \ + awk "/^Xephyr on $destdisp\.0/"' { print $NF; exit }'`" + fi else i=0 destdisp='' @@ -261,7 +276,7 @@ if [ "$destdisp" = "$curdisp" -a -z "$force" ]; then fi # Make sure tap-to-click is enabled -if [ -z "$noaurax" ] && hash xinput 2>/dev/null; then +if [ -z "$freonowner" ] && hash xinput 2>/dev/null; then for id in `host-x11 xinput --list --id-only`; do host-x11 xinput set-prop "$id" 'Tap Paused' 0 2>/dev/null || true done @@ -269,7 +284,7 @@ fi # Determine if the target display is on a VT if [ "${destdisp#:}" = "$destdisp" ]; then - if [ -z "$noaurax" ]; then + if [ -z "$freonowner" ]; then eval "`host-x11`" # Raise the right window after chvting, so that it can update if [ "$tty" != 'tty1' ]; then @@ -277,6 +292,8 @@ if [ "${destdisp#:}" = "$destdisp" ]; then sleep .1 fi croutonwmtools raise "${destdisp%"*"}" + elif [ "${freonowner:-0}" != 0 ]; then + kill -USR1 "$freonowner" fi if [ -n "$xiwiactive" -a "${destdisp%"*"}" = "$aurawin" ]; then @@ -287,16 +304,23 @@ if [ "${destdisp#:}" = "$destdisp" ]; then fi else export DISPLAY="$destdisp" - if xprop -root 'CROUTON_XMETHOD' 2>/dev/null | grep -q '= "xiwi"$'; then - if [ -z "$noaurax" -a "$tty" != 'tty1' ]; then + xmethod="`xprop -root 'CROUTON_XMETHOD' 2>/dev/null \ + | sed -n 's/^.*\"\(.*\)\"/\1/p'`" + if [ "${xmethod%%-*}" = 'xiwi' ]; then + if [ -z "$freonowner" -a "$tty" != 'tty1' ]; then sudo -n chvt 1 sleep .1 + elif [ "${freonowner:-0}" != 0 ]; then + kill -USR1 "$freonowner" + fi + if [ -z "$freonowner" ]; then + host-x11 croutonwmtools raise "$aurawin" fi - STATUS="`echo -n "X${destdisp}" | websocketcommand`" + STATUS="`echo -n "X${destdisp} ${xmethod#*-}" | websocketcommand`" if [ "$STATUS" != 'XOK' ]; then error 1 "${STATUS#?}" fi - else + elif [ -z "$freonowner" ]; then dest="`xprop -root 'XFree86_VT' 2>/dev/null`" dest="${dest##* }" if [ "${dest#[1-9]}" = "$dest" ]; then @@ -307,6 +331,15 @@ else # display will be stuck on the old vt. sudo -n chvt 2 sudo -n chvt "$dest" + else + dest="/tmp/.X${destdisp#:}-lock" + if [ -f "$dest" ]; then + # Trigger the target before releasing the current owner + kill -USR1 `cat /tmp/.X${destdisp#:}-lock` + fi + if [ "${freonowner:-0}" != 0 ]; then + kill -USR1 "$freonowner" + fi fi fi diff --git a/chroot-bin/croutonfindnacl b/chroot-bin/croutonfindnacl index 80d54ea24..e374aa470 100755 --- a/chroot-bin/croutonfindnacl +++ b/chroot-bin/croutonfindnacl @@ -1,5 +1,5 @@ #!/bin/sh -e -# Copyright (c) 2014 The crouton Authors. All rights reserved. +# Copyright (c) 2015 The crouton Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. diff --git a/chroot-bin/croutonpowerd b/chroot-bin/croutonpowerd index 120d2b87e..30130db1a 100755 --- a/chroot-bin/croutonpowerd +++ b/chroot-bin/croutonpowerd @@ -1,5 +1,5 @@ #!/bin/sh -e -# Copyright (c) 2014 The crouton Authors. All rights reserved. +# Copyright (c) 2015 The crouton Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. diff --git a/chroot-bin/croutontriggerd b/chroot-bin/croutontriggerd new file mode 100755 index 000000000..0db94a8a5 --- /dev/null +++ b/chroot-bin/croutontriggerd @@ -0,0 +1,99 @@ +#!/bin/sh -e +# Copyright (c) 2015 The crouton Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Monitors keyboard events for the crouton switch command. + +. "`dirname "$0"`/../installer/functions" + +# hexdump output format variables +if getconf LONG_BIT | grep -q 32; then + HEXDUMP_FMT='2/4 "%u 0 " " " 2/2 "%u " " " 1/4 "%u " "\n"' +else + HEXDUMP_FMT='4/4 "%u " " " 2/2 "%u " " " 1/4 "%u " "\n"' +fi +SECONDS_LO='$1' +SECONDS_HI='$2' +USECONDS_LO='$3' +USECONDS_HI='$4' +TYPE='$5' +KEY='$6' +STATE='$7' + +# constants +TYPE_EV_KEY=1 +STATE_DOWN=1 +STATE_UP=0 +KEY_LEFTCTRL=29 +KEY_LEFTALT=56 +KEY_LEFTSHIFT=42 +KEY_RIGHTCTRL=97 +KEY_RIGHTALT=100 +KEY_RIGHTSHIFT=54 +KEY_F1=59 +KEY_F2=60 + +EVENT_DEV_POLL=15 + +# Only one at a time. xbindkeys lockfile is for legacy compatibility +mkdir -m 775 -p "$CROUTONLOCKDIR" +exec 3>>"$CROUTONLOCKDIR/xbindkeys" +if ! flock -n 3; then + echo "Another instance of ${0##*/} running, waiting..." + flock 3 +fi + +# Reset event variables to handle strange environments +unset `set | grep -o '^event[0-9]*'` 2>/dev/null || true + +# Poll for new event files and dump the output +while :; do + # Clean up old hexdumps and start new ones + for event in `set | grep -o '^event[0-9]*'` /dev/input/event*; do + # Check if the event file is already monitored + eval "pid=\"\${${event##*/}:-0}\"" + if [ "$pid" != 0 ]; then + # Check if it's still running + if kill -0 "$pid" 2>/dev/null; then + continue + fi + wait "$pid" || true + fi + # Clean up old variables + if [ "${event#/}" = "$event" ]; then + unset "$event" + else + # Read in the event files and split into input_event fields + stdbuf -oL hexdump -e "$HEXDUMP_FMT" "$event" & + eval "${event##*/}='$!'" + fi + done + # Avoid picking up the event variable + unset event + # Kill all event daemons + pids="`set | sed -n 's/^event[0-9]*=.\(.*\).$/\1/p' | tr '\n' ' '`" + settrap "kill $pids 2>/dev/null;" + # Wait for next poll + sleep "$EVENT_DEV_POLL" +done | unbuffered_awk " + function update() { + c = lc || rc; s = ls || rs; a = la || ra + if (!cmd && c && s && a && p) { + cmd = \"p\" + } else if (!cmd && c && s && a && n) { + cmd = \"n\" + } else if (cmd && !c && !s && !a && !p && !n) { + system(\"/usr/local/bin/croutoncycle \" cmd) + cmd = \"\" + } + } + $TYPE == $TYPE_EV_KEY && $KEY == $KEY_LEFTCTRL { lc = $STATE; update() } + $TYPE == $TYPE_EV_KEY && $KEY == $KEY_LEFTSHIFT { ls = $STATE; update() } + $TYPE == $TYPE_EV_KEY && $KEY == $KEY_LEFTALT { la = $STATE; update() } + $TYPE == $TYPE_EV_KEY && $KEY == $KEY_RIGHTCTRL { rc = $STATE; update() } + $TYPE == $TYPE_EV_KEY && $KEY == $KEY_RIGHTSHIFT { rs = $STATE; update() } + $TYPE == $TYPE_EV_KEY && $KEY == $KEY_RIGHTALT { ra = $STATE; update() } + $TYPE == $TYPE_EV_KEY && $KEY == $KEY_F1 { p = $STATE; update() } + $TYPE == $TYPE_EV_KEY && $KEY == $KEY_F2 { n = $STATE; update() } +" diff --git a/chroot-bin/croutonurlhandler b/chroot-bin/croutonurlhandler index d28e63362..ae735dfbf 100755 --- a/chroot-bin/croutonurlhandler +++ b/chroot-bin/croutonurlhandler @@ -1,5 +1,5 @@ #!/bin/sh -e -# Copyright (c) 2014 The crouton Authors. All rights reserved. +# Copyright (c) 2015 The crouton Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. diff --git a/chroot-bin/croutonversion b/chroot-bin/croutonversion index 169f31664..4217b3a4d 100755 --- a/chroot-bin/croutonversion +++ b/chroot-bin/croutonversion @@ -1,5 +1,5 @@ #!/bin/sh -e -# Copyright (c) 2014 The crouton Authors. All rights reserved. +# Copyright (c) 2015 The crouton Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. @@ -85,6 +85,12 @@ if [ -z "$CHANGES$DOWNLOAD$UPDATES" ]; then host="`awk -F= '/_RELEASE_DESCRIPTION=/{print $2}' "$hostrel"`" fi echo "host: version ${host:-unknown}" + echo "kernel: $(uname -a)" + freon="yes" + if [ -f /sys/class/tty/tty0/active ]; then + freon="no" + fi + echo "freon: $freon" exit 0 fi diff --git a/chroot-bin/croutonwheel b/chroot-bin/croutonwheel index dc492baa3..ce5affdbd 100755 --- a/chroot-bin/croutonwheel +++ b/chroot-bin/croutonwheel @@ -1,5 +1,5 @@ #!/bin/sh -e -# Copyright (c) 2014 The crouton Authors. All rights reserved. +# Copyright (c) 2015 The crouton Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. diff --git a/chroot-bin/croutonxinitrc-wrapper b/chroot-bin/croutonxinitrc-wrapper index d4eb93b63..494a3681f 100755 --- a/chroot-bin/croutonxinitrc-wrapper +++ b/chroot-bin/croutonxinitrc-wrapper @@ -1,5 +1,5 @@ #!/bin/sh -e -# Copyright (c) 2014 The crouton Authors. All rights reserved. +# Copyright (c) 2015 The crouton Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. @@ -43,6 +43,10 @@ else fi # Run crouton-specific commands: + +# Show chroot specifics for troubleshooting +croutonversion 1>&2 + if [ -z "$XMETHOD" ]; then if [ -f '/etc/crouton/xmethod' ]; then read -r XMETHOD _ < /etc/crouton/xmethod @@ -52,6 +56,8 @@ if [ -z "$XMETHOD" ]; then exit 1 fi fi +xmethodtype="${XMETHOD%%-*}" +xmethodargs="${XMETHOD#*-}" # Record the name of the chroot in the root window properties if [ -f '/etc/crouton/name' ] && hash xprop 2>/dev/null; then @@ -70,7 +76,7 @@ if hash croutonclip 2>/dev/null; then fi # Pass through the host cursor and correct mousewheels on xephyr -if [ "$XMETHOD" = 'xephyr' ]; then +if [ "$xmethodtype" = 'xephyr' ]; then host-x11 croutoncursor "$DISPLAY" & if [ -z "$CROUTON_WHEEL_PARAMS" -a -r "$HOME/.croutonwheel" ]; then CROUTON_WHEEL_PARAMS="`head -n1 "$HOME/.croutonwheel"`" @@ -78,25 +84,23 @@ if [ "$XMETHOD" = 'xephyr' ]; then croutonwheel $CROUTON_WHEEL_PARAMS & fi -# xbindkeys and other input-related apps are not needed for kiwi -if [ "$XMETHOD" != "xiwi" ]; then +# Launch system-wide trigger daemon +croutontriggerd & + + +# Apply the Chromebook keyboard map. Not needed for non-Freon xiwi. +if [ "$xmethodtype" != 'xiwi' -o ! -f "/sys/class/tty/tty0/active" ]; then # Apply the Chromebook keyboard map if installed. if [ -f '/usr/share/X11/xkb/compat/chromebook' ]; then setxkbmap -model chromebook fi +fi - # Launch key binding daemon - xbindkeys -fg /etc/crouton/xbindkeysrc.scm +# Input-related stuff is not needed for kiwi +if [ "$xmethodtype" != "xiwi" ]; then - # Launch xbindkeys for the Chromium OS X server if it isn't running - mkdir -m 775 -p /tmp/crouton-lock - { - # Only let one instance *really* run at a time - flock 3 - XMETHOD='' host-x11 xbindkeys -n -fg /etc/crouton/xbindkeysrc.scm & - trap "kill '$!' 2>/dev/null" HUP INT TERM - wait "$!" || true - } 3>/tmp/crouton-lock/xbindkeys & + # Launch X-server-local key binding daemon + xbindkeys -fg /etc/crouton/xbindkeysrc.scm # Launch touchegg if it is requested. toucheggconf='/etc/touchegg.conf' @@ -128,7 +132,7 @@ if [ "$XMETHOD" != "xiwi" ]; then fi # Crouton-in-a-tab: Start fbserver and launch display -if [ "$XMETHOD" = 'xiwi' ]; then +if [ "$xmethodtype" = 'xiwi' ]; then # The extension sends evdev key codes: fix the keyboard mapping rules setxkbmap -rules evdev # Reapply xkb map: This fixes autorepeat mask in "xset q" @@ -153,7 +157,7 @@ and enabled, and up to date. (download from http://goo.gl/OVQOEt)" 1>&2 try="$((try+1))" done if [ "$ret" -eq 0 ]; then - echo "Connected to extension, launched crouton in a tab window." 1>&2 + echo "Connected to extension, launched crouton in a window." 1>&2 fi fi @@ -180,13 +184,4 @@ fi echo "Running exit commands..." 1>&2 -# Restore framebuffer compression if there are no other non-Chromium X servers -fbc='/sys/module/i915/parameters/i915_enable_fbc' -if [ -w "$fbc" ]; then - # There is at least 2 servers running (the current one and Chromium OS) - if [ "`ps -CX -CXorg -CXephyr -opid= | wc -l`" -le 2 ]; then - echo 1 > "$fbc" - fi -fi - exit "$ret" diff --git a/chroot-bin/gnome-session-wrapper b/chroot-bin/gnome-session-wrapper index 40eb76efc..c0d4a6814 100755 --- a/chroot-bin/gnome-session-wrapper +++ b/chroot-bin/gnome-session-wrapper @@ -1,5 +1,5 @@ #!/bin/sh -e -# Copyright (c) 2014 The crouton Authors. All rights reserved. +# Copyright (c) 2015 The crouton Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/chroot-bin/host-dbus b/chroot-bin/host-dbus index a2ffcb3c0..5c3a9ed14 100755 --- a/chroot-bin/host-dbus +++ b/chroot-bin/host-dbus @@ -1,5 +1,5 @@ #!/bin/sh -e -# Copyright (c) 2014 The crouton Authors. All rights reserved. +# Copyright (c) 2015 The crouton Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. diff --git a/chroot-bin/host-x11 b/chroot-bin/host-x11 index 4e2977af3..89e9794e6 100755 --- a/chroot-bin/host-x11 +++ b/chroot-bin/host-x11 @@ -1,5 +1,5 @@ #!/bin/sh -e -# Copyright (c) 2014 The crouton Authors. All rights reserved. +# Copyright (c) 2015 The crouton Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. diff --git a/chroot-bin/setres b/chroot-bin/setres index bfcb3688d..56782a32e 100755 --- a/chroot-bin/setres +++ b/chroot-bin/setres @@ -1,5 +1,5 @@ #!/bin/sh -e -# Copyright (c) 2014 The crouton Authors. All rights reserved. +# Copyright (c) 2015 The crouton Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. @@ -27,7 +27,7 @@ fi xmethod="`xprop -root 'CROUTON_XMETHOD' | sed -n 's/^.*\"\(.*\)\"/\1/p'`" -if [ "$xmethod" != "xiwi" ]; then +if [ "${xmethod%%-*}" != "xiwi" ]; then cvt "$x" "$y" "$r" | { read -r _ read -r _ mode data diff --git a/chroot-bin/startgnome b/chroot-bin/startgnome index 3b628d8e8..63400135e 100755 --- a/chroot-bin/startgnome +++ b/chroot-bin/startgnome @@ -1,5 +1,5 @@ #!/bin/sh -e -# Copyright (c) 2014 The crouton Authors. All rights reserved. +# Copyright (c) 2015 The crouton Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. diff --git a/chroot-bin/startunity b/chroot-bin/startunity index c127f0737..daa686747 100755 --- a/chroot-bin/startunity +++ b/chroot-bin/startunity @@ -1,5 +1,5 @@ #!/bin/sh -e -# Copyright (c) 2014 The crouton Authors. All rights reserved. +# Copyright (c) 2015 The crouton Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. diff --git a/chroot-bin/volume b/chroot-bin/volume new file mode 100755 index 000000000..77320325d --- /dev/null +++ b/chroot-bin/volume @@ -0,0 +1,203 @@ +#!/bin/sh +# Copyright (c) 2015 The crouton Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# This script uses amixer to present an interface similar to the brightness +# script for crouton. + +set -e +set -u + +DEFAULT_VOLUME_DELTA=5 + +APPLICATION="${0##*/}" +USAGE="$APPLICATION [set] [0-100] +$APPLICATION up|down [0-100] +$APPLICATION mute [set|unset|toggle] +$APPLICATION get [all|volume|mute] + +This script changes the volume of the current output +device, as would changing it with the shortcut keys or +with the GUI in Chrome OS. + +Shortcut invocations: + $APPLICATION up increases by $DEFAULT_VOLUME_DELTA + $APPLICATION down decreases by $DEFAULT_VOLUME_DELTA + $APPLICATION mute sets muted + $APPLICATION 0-100 sets volume to given value + $APPLICATION get shortcut for get all +" +# The control which controls the current output. +ALSA_CONTROL="Master" + +# Tiny sugar coating around amixer for common parameters. +_amixer() { + amixer -Dcras "$@" +} +amixer_get_value() { + # $1 is the control name to get the value for + _amixer cget "name=$1" | sed -n \ + -e "/[[:space:]]\+:/s/.*=//p" + # ^ ^ ^ Print the line. + # ^ ^ Replace everything before the equal sign. + # ^ Search for the line with spaces and a colon (the value). +} + +get_volume() { + amixer_get_value "$ALSA_CONTROL Playback Volume" +} + +set_volume() { + local volume="$1" + _amixer -q sset $ALSA_CONTROL "$volume" +} + +get_is_muted() { + # Get the alsa state of the control. + local state="$(amixer_get_value "$ALSA_CONTROL Playback Switch")" + + # Muted is off (control is off) + if [ "$state" = "on" ]; then + # Is not muted, so is_muted is false + return 1 + else + # Is muted, so is_muted is true + return 0 + fi +} + +get_is_muted_as_text() { + if get_is_muted; then + echo "yes" + else + echo "no" + fi +} + +toggle_mute() { + _amixer -q sset $ALSA_CONTROL toggle +} + +mute() { + _amixer -q sset $ALSA_CONTROL mute +} +unmute() { + _amixer -q sset $ALSA_CONTROL unmute +} + +relative_volume() { + local delta="$1" + + # Check that this is integer-ish enough. + if ! [ "$delta" -eq "$delta" ] 2>/dev/null; then + error_help "Error: $APPLICATION needs a number [0-100]" + exit 1 + fi + + if get_is_muted; then + if [ "$delta" -lt 0 ]; then + set_volume 0 + fi + unmute + else + # Is the volume going down or up? + if [ "$delta" -lt 0 ]; then + # Going down, we strip the leading minus sign, + # And suffix the minus sign. + set_volume "${delta#*-}-" + else + # Only suffix the plus sign. + set_volume "${delta}+" + fi + fi +} + +print_help() { + echo "$USAGE" +} +error_help() { + # Prints an error message and the usage to stderr + [ $# -gt 0 ] && echo "$@" 1>&2 + print_help 1>&2 +} + +# Do a sanity check with amixer. +# An out of date crouton chroot might exhibit problems like: +# amixer: Control cras element read error: Input/output error +# We cannot do it in _amixer since it's executed in a subshell and its value is +# used as a substitution. +if ! _amixer > /dev/null 2>&1; then + echo "Failed to communicate with the audio server. Please update your chroot." 1>&2 + exit 2 +fi + +if [ $# -lt 1 ]; then + error_help "Error: $APPLICATION needs at least a command." + exit 1 +fi + +cmd="$1" +shift + +case "$cmd" in +h*|-h*|--help) + print_help + ;; +up) + relative_volume "${1:-$DEFAULT_VOLUME_DELTA}" + ;; +down) + relative_volume "-${1:-$DEFAULT_VOLUME_DELTA}" + ;; +mute) + action="${1-set}" + case "$action" in + toggle) toggle_mute ;; + set) mute ;; + unset) unmute ;; + *) + error_help "Invalid action: $action for mute." + exit 1 + ;; + esac + ;; +set|[0-9]|[0-9][0-9]|100) + amount="$cmd" + # First, check that we received a value to set the volume to. + if [ $# -eq 0 ] && [ "$cmd" = "set" ]; then + error_help "Error: $APPLICATION set needs an amount to set." + exit 1 + fi + # The value /could/ have been a parameter or the command itself. + if [ $# -gt 0 ]; then + amount="$1" + shift + fi + # Check that this is integer-ish enough. + if ! [ "$amount" -eq "$amount" ] 2>/dev/null; then + error_help "Error: $APPLICATION set needs a number [0-100]" + exit 1 + fi + set_volume "$amount" + ;; +get) + action="${1-all}" + case "$action" in + mute) get_is_muted_as_text ;; + volume) get_volume ;; + all) + echo "Volume: $(get_volume)" + echo "Muted: $(get_is_muted_as_text)" + ;; + *) + error_help "Invalid action: $action for get." + exit 1 + ;; + esac + ;; +*) + error_help "Error: Unkown command $cmd" + exit 1 + ;; +esac diff --git a/chroot-bin/xinit b/chroot-bin/xinit index 8140fdb79..f17f6bca5 100755 --- a/chroot-bin/xinit +++ b/chroot-bin/xinit @@ -1,5 +1,5 @@ #!/bin/sh -e -# Copyright (c) 2014 The crouton Authors. All rights reserved. +# Copyright (c) 2015 The crouton Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. diff --git a/chroot-bin/xiwi b/chroot-bin/xiwi new file mode 100755 index 000000000..50c428aa3 --- /dev/null +++ b/chroot-bin/xiwi @@ -0,0 +1,125 @@ +#!/bin/sh -e +# Copyright (c) 2015 The crouton Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# Runs the specified X11 application in its own X server in Chromium OS. + +USAGE="Usage: ${0##*/} [-f] [-F|-T] APPLICATION [PARAMETERS ...] +Launches a windowed session in Chromium OS for any graphical application. +Applications launched in this way show in independent windows or tabs. +All parameters are passed to the specified application. + +By default, the app is launched in a window. + +Options: + -F Launch the APPLICATION full-screen. + -T Launch the APPLICATION in a tab. + -f Prevent ${0##*/} from quitting automatically. (see NOTE below) + +NOTE: +${0##*/} will normally close when the application returns. Some gui applications +fork before or during normal operation, which can confuse ${0##*/} and cause it to +quit prematurely. If your application does not have a parameter that prevents +it from forking, and crouton is unable to automatically detect the fork, you can +use -f to prevent ${0##*/} from quitting automatically. +${0##*/} will quit if you close the Chromium OS window when nothing is displayed. + +A default window manager will full-screen all windows, unless APPLICATION begins +with 'start' or is 'xinit'. You can cycle through multiple windows inside the +application via Ctrl-Alt-Tab/Ctrl-Alt-Shift-Tab, or close them via +Ctrl-Alt-Shift-Escape. If APPLICATION begins with 'start' but you still want to +use the default window manager, specify the full path of the application." + +. "`dirname "$0"`/../installer/functions" +xiwicmd="`readlink -f "$0"`" +OPTSTRING='FfTt' + +if [ "$#" = 0 ]; then + error 2 "$USAGE" +elif [ "$1" = '/' ]; then + shift 1 + foreground='' + while getopts "$OPTSTRING" f; do + case "$f" in + f) foreground='y';; + t|T|F) :;; + \?) error 2 "$USAGE";; + esac + done + shift "$((OPTIND-1))" + xsetroot -cursor_name left_ptr + if [ "$1" != 'xinit' -a "${1#start}" = "$1" ]; then + i3 -c "/etc/crouton/xiwi.conf" & + # Wait for i3 to launch + xprop -spy -root | grep -q _NET_ACTIVE_WINDOW + # Launch the window title monitoring daemon + # _NET_ACTIVE_WINDOW is more reliable than _NET_CLIENT_LIST_STACKING for + # keeping track of the topmost window. + xprop -spy -notype -root 0i ' $0\n' '_NET_ACTIVE_WINDOW' 2>/dev/null | { + name="`cat /etc/crouton/name`" + monpid='' + monwid='' + while read _ wid; do + if [ "$wid" = "$monwid" ]; then + continue + fi + if [ -n "$monpid" ]; then + kill "$monpid" 2>/dev/null + fi + monwid="$wid" + (xprop -spy -notype -id "$wid" 'WM_NAME' 2>/dev/null || echo) \ + | while read _ title; do + title="${title%\"}" + xprop -root -f CROUTON_NAME 8s -set CROUTON_NAME \ + "$name/$1${title:+": "}${title#*\"}" + { + echo -n 'C' + croutoncycle l + } | websocketcommand >/dev/null + done & + monpid="$!" + done + if [ -n "$monpid" ]; then + kill "$monpid" 2>/dev/null + fi + } & + # Launch user init scripts + if [ -f "$HOME/.xiwirc" ]; then + /bin/sh "$HOME/.xiwirc" || true + fi + fi + starttime="$(date +%s)" + "$@" + endtime="$(date +%s)" + if [ -n "$foreground" -o "$(($endtime-$starttime))" -le 2 ]; then + xprop -spy -notype -root 0i ' $0\n' 'CROUTON_CONNECTED' \ + | while read _ connected; do + if [ "$connected" != 0 ]; then + continue + fi + # _NET_CLIENT_LIST_STACKING is more reliable than + # _NET_ACTIVE_WINDOW for detecting when no windows exist + if ! xprop -notype -root '_NET_CLIENT_LIST_STACKING' \ + | grep -q '0x'; then + kill "$$" + break + fi + done + fi +else + export XMETHOD='xiwi-window' + while getopts "$OPTSTRING" f; do + case "$f" in + f) :;; + F) export XMETHOD='xiwi-fullscreen';; + t|T) export XMETHOD='xiwi-tab';; + \?) error 2 "$USAGE";; + esac + done + eval "exe=\"\$$OPTIND\"" + if ! hash "$exe" 2>/dev/null; then + error 2 "${0##*/}: $exe: not found" + fi + exec /usr/local/bin/xinit "$xiwicmd" / "$@" +fi diff --git a/chroot-etc/pulseaudio-default.pa b/chroot-etc/pulseaudio-default.pa new file mode 100644 index 000000000..dc14092b2 --- /dev/null +++ b/chroot-etc/pulseaudio-default.pa @@ -0,0 +1,13 @@ +#!/usr/bin/pulseaudio -nF +# Copyright (c) 2015 The crouton Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# Include default configuration first +.include /etc/pulse/default.pa + +# Forward audio to Chromium OS audio server +load-module module-alsa-sink device=cras sink_name=cras-sink +load-module module-alsa-source device=cras source_name=cras-source +set-default-sink cras-sink +set-default-source cras-source diff --git a/chroot-etc/unity-autostart.desktop b/chroot-etc/unity-autostart.desktop index 79b041df7..c4fa46a39 100644 --- a/chroot-etc/unity-autostart.desktop +++ b/chroot-etc/unity-autostart.desktop @@ -1,4 +1,4 @@ -# Copyright (c) 2014 The crouton Authors. All rights reserved. +# Copyright (c) 2015 The crouton Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. diff --git a/chroot-etc/unity-profiled b/chroot-etc/unity-profiled index 7ba193a3c..32b35b570 100644 --- a/chroot-etc/unity-profiled +++ b/chroot-etc/unity-profiled @@ -1,5 +1,5 @@ #!/bin/sh -e -# Copyright (c) 2014 The crouton Authors. All rights reserved. +# Copyright (c) 2015 The crouton Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/chroot-etc/xbindkeysrc.scm b/chroot-etc/xbindkeysrc.scm index ad06b55f1..8b2008b91 100644 --- a/chroot-etc/xbindkeysrc.scm +++ b/chroot-etc/xbindkeysrc.scm @@ -1,12 +1,18 @@ -;; Copyright (c) 2014 The crouton Authors. All rights reserved. +;; Copyright (c) 2015 The crouton Authors. All rights reserved. ;; Use of this source code is governed by a BSD-style license that can be ;; found in the LICENSE file. ;; Run xbindkeys -dg for some example configuration file with explanation -; Cycle chroots -(xbindkey '(control shift alt F1) "xte 'keyup F1'; croutoncycle prev") -(xbindkey '(control shift alt F2) "xte 'keyup F2'; croutoncycle next") +; Cycle chroots. On most systems, this is handled by the triggerhappy daemon. +; On freon, we have to do it ourselves since we currently grab the event device. +(if (access? "/sys/class/tty/tty0/active" F_OK) (begin + (xbindkey '(control shift alt F1) "") + (xbindkey '(control shift alt F2) "") +) (begin + (xbindkey '(control shift alt F1) "xte 'keyup F1'; croutoncycle prev") + (xbindkey '(control shift alt F2) "xte 'keyup F2'; croutoncycle next") +)) ; Extra bindings that must only be activated in chroot X11/Xephyr (if (not (string-null? (getenv "XMETHOD"))) diff --git a/chroot-etc/xbmc-cycle.py b/chroot-etc/xbmc-cycle.py index 914b76c36..a6cebdffd 100644 --- a/chroot-etc/xbmc-cycle.py +++ b/chroot-etc/xbmc-cycle.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -# Copyright (c) 2014 The crouton Authors. All rights reserved. +# Copyright (c) 2015 The crouton Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # diff --git a/chroot-etc/xbmc-keyboard.xml b/chroot-etc/xbmc-keyboard.xml index 95ad439b7..6fbc79a14 100644 --- a/chroot-etc/xbmc-keyboard.xml +++ b/chroot-etc/xbmc-keyboard.xml @@ -1,4 +1,4 @@ - + diff --git a/chroot-etc/xiwi.conf b/chroot-etc/xiwi.conf new file mode 100644 index 000000000..f8e1ff59a --- /dev/null +++ b/chroot-etc/xiwi.conf @@ -0,0 +1,27 @@ +# i3 config file (v4) +# Copyright (c) 2015 The crouton Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# Style +new_window none +new_float normal +workspace_layout tabbed +font pango:Sans 8 + +# Colors border backgr. text indicator +client.focused #8E8E8F #EAEAEB #000000 #8E8E8F +client.focused_inactive #8E8E8F #CACACB #525252 #8E8E8F +client.unfocused #8E8E8F #CACACB #525252 #8E8E8F +client.urgent #FF8E8E #FFCACB #520000 #FF8E8E +client.background #C3C3C4 + +# Interaction +focus_follows_mouse no +bindsym Mod1+Shift+Control+Escape kill +floating_modifier Mod1 +bindsym Mod1+Tab focus right +bindsym Mod1+Shift+Tab focus left +bindsym Mod1+Control+Tab focus right +bindsym Mod1+Shift+Control+Tab focus left +bindsym --release button2 kill diff --git a/chroot-etc/xorg-dummy.conf b/chroot-etc/xorg-dummy.conf index d3199324f..6f3d7a445 100644 --- a/chroot-etc/xorg-dummy.conf +++ b/chroot-etc/xorg-dummy.conf @@ -1,4 +1,4 @@ -# Copyright (c) 2014 The crouton Authors. All rights reserved. +# Copyright (c) 2015 The crouton Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. @@ -33,6 +33,7 @@ EndSection Section "ServerFlags" Option "AutoAddDevices" "false" + Option "AutoAddGPU" "false" Option "DontVTSwitch" "true" Option "AllowMouseOpenFail" "true" Option "PciForceNone" "true" diff --git a/chroot-etc/xorg-intel-sna.conf b/chroot-etc/xorg-intel-sna.conf new file mode 100644 index 000000000..3f2b369b9 --- /dev/null +++ b/chroot-etc/xorg-intel-sna.conf @@ -0,0 +1,12 @@ +# Copyright (c) 2015 The crouton Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# On Intel platforms with FBC enabled, in order to see anything we need to use +# the SNA driver with the TearFree option. +Section "Device" + Identifier "Intel Graphics SNA+TearFree" + Driver "intel" + Option "AccelMethod" "sna" + Option "TearFree" "true" +EndSection diff --git a/chroot-etc/xserverrc b/chroot-etc/xserverrc index 545ddfbe1..dbd55ee8f 100644 --- a/chroot-etc/xserverrc +++ b/chroot-etc/xserverrc @@ -1,5 +1,5 @@ #!/bin/sh -e -# Copyright (c) 2014 The crouton Authors. All rights reserved. +# Copyright (c) 2015 The crouton Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. @@ -12,7 +12,7 @@ if [ -z "$XMETHOD" ]; then fi fi -xserverrc="/etc/crouton/xserverrc-$XMETHOD" +xserverrc="/etc/crouton/xserverrc-${XMETHOD%%-*}" if [ "${XMETHOD##*/}" != "$XMETHOD" -o ! -f "$xserverrc" ]; then echo "Invalid X11 backend '$XMETHOD'" 1>&2 exit 2 diff --git a/chroot-etc/xserverrc-local.example b/chroot-etc/xserverrc-local.example index 558b68be6..70b3ce2f1 100644 --- a/chroot-etc/xserverrc-local.example +++ b/chroot-etc/xserverrc-local.example @@ -1,5 +1,5 @@ #!/bin/sh -# Copyright (c) 2014 The crouton Authors. All rights reserved. +# Copyright (c) 2015 The crouton Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. diff --git a/chroot-etc/xserverrc-xephyr b/chroot-etc/xserverrc-xephyr index b613fff9a..a498d7f0e 100644 --- a/chroot-etc/xserverrc-xephyr +++ b/chroot-etc/xserverrc-xephyr @@ -1,5 +1,5 @@ #!/bin/sh -e -# Copyright (c) 2014 The crouton Authors. All rights reserved. +# Copyright (c) 2015 The crouton Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. diff --git a/chroot-etc/xserverrc-xiwi b/chroot-etc/xserverrc-xiwi index bd2ddab93..5e26833c5 100644 --- a/chroot-etc/xserverrc-xiwi +++ b/chroot-etc/xserverrc-xiwi @@ -1,5 +1,5 @@ #!/bin/sh -e -# Copyright (c) 2014 The crouton Authors. All rights reserved. +# Copyright (c) 2015 The crouton Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. @@ -11,12 +11,16 @@ for arg in "$@"; do fi done -export XMETHOD='xiwi' +if [ "${XMETHOD%%-*}" != 'xiwi' ]; then + export XMETHOD='xiwi' +fi XARGS="-nolisten tcp -config xorg-dummy.conf -logfile $logfile" if [ -f /etc/crouton/xserverrc-local ]; then . /etc/crouton/xserverrc-local fi +<<<<<<< HEAD +<<<<<<< HEAD # Find the Xorg executable (first 2 required by Arch, third by Debian/Ubuntu) XBINS="/usr/lib/xorg-server/Xorg /usr/bin/Xorg.bin /usr/bin/Xorg" XBIN="" @@ -32,4 +36,11 @@ if [ -z "$XBIN" ]; then exit 1 fi +# Handle Freon systems +# if [ ! -f "/sys/class/tty/tty0/active" ]; then +# export LD_PRELOAD="/usr/local/lib/croutonfreon.so:$LD_PRELOAD" +# fi + +export LD_PRELOAD="/usr/local/lib/croutonxorg.so:$LD_PRELOAD" + exec "$XBIN" $XARGS "$@" diff --git a/chroot-etc/xserverrc-xorg b/chroot-etc/xserverrc-xorg index d5fb6f234..e7cd065a4 100644 --- a/chroot-etc/xserverrc-xorg +++ b/chroot-etc/xserverrc-xorg @@ -1,19 +1,46 @@ #!/bin/sh -e -# Copyright (c) 2014 The crouton Authors. All rights reserved. +# Copyright (c) 2015 The crouton Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -# Disable framebuffer compression when displaying natively. -# TODO: test FBC with SNA enabled on Haswell to regain power savings -fbc='/sys/module/i915/parameters/i915_enable_fbc' -if [ -w "$fbc" ]; then - echo 0 > "$fbc" +if [ "${XMETHOD%%-*}" != 'xorg' ]; then + export XMETHOD='xorg' fi - -export XMETHOD='xorg' XARGS='-nolisten tcp' if [ -f /etc/crouton/xserverrc-local ]; then . /etc/crouton/xserverrc-local fi -exec /usr/bin/X $XARGS "$@" +X=/usr/bin/X + +# Handle Freon systems +if [ ! -f "/sys/class/tty/tty0/active" ]; then + # We won't be able to launch properly if running from frecon + ppid="$$" + while [ -n "$ppid" -a "$ppid" -ne 1 ]; do + ppid="`ps -p "$ppid" -o 'ppid=' 2>/dev/null | sed 's/ //g'`" + if ps -p "$ppid" -o 'comm=' | grep -q '^frecon$'; then + echo 'Xorg X11 servers cannot be launched from Frecon.' 1>&2 + echo 'Return to Chromium OS and use crosh to launch X.' 1>&2 + exit 2 + fi + done + # Use the daemon to kill frecon. + # FIXME: remove when crbug.com/457075 is resolved + if [ -w '/tmp/crouton-lock/frecon' ]; then + echo >> '/tmp/crouton-lock/frecon' + fi + # Freon necessitates the preload hack for X to coexist + X=/usr/bin/Xorg + logfile="/tmp/Xorg.crouton.$$.log" + for arg in "$@"; do + disp="`echo "$arg" | sed -n 's/^\:\([0-9]*\)$/\1/p'`" + if [ -n "$disp" ]; then + logfile="/tmp/Xorg.crouton.$disp.log" + fi + done + XARGS="$XARGS -logfile $logfile" + export LD_PRELOAD="/usr/local/lib/croutonfreon.so:$LD_PRELOAD" +fi + +exec "$X" $XARGS "$@" diff --git a/host-bin/crash_reporter_wrapper b/host-bin/crash_reporter_wrapper index d6e4003bb..4a821c17f 100755 --- a/host-bin/crash_reporter_wrapper +++ b/host-bin/crash_reporter_wrapper @@ -1,5 +1,5 @@ #!/bin/sh -e -# Copyright (c) 2014 The crouton Authors. All rights reserved. +# Copyright (c) 2015 The crouton Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. diff --git a/host-bin/edit-chroot b/host-bin/edit-chroot index 86fbf99ac..6b9a2e60e 100755 --- a/host-bin/edit-chroot +++ b/host-bin/edit-chroot @@ -1,5 +1,5 @@ #!/bin/sh -e -# Copyright (c) 2014 The crouton Authors. All rights reserved. +# Copyright (c) 2015 The crouton Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. @@ -163,7 +163,7 @@ elif [ $# -gt 1 -a -f "$TARBALL" ]; then fi # Don't allow moving to non-ext filesystems (but don't check if just renaming) -if [ -n "$MOVE" -a "${MOVE#*/}" = "$MOVE" ] && \ +if [ -n "$MOVE" -a "${MOVE#*/}" != "$MOVE" ] && \ df -T "`getmountpoint "$MOVE"`" | awk '$2~"^ext"{exit 1}'; then error 2 "Chroots can only be moved to ext filesystems." fi @@ -307,7 +307,7 @@ for NAME in "$@"; do -a "$LISTDETAILS" -gt 1 ]; then sh "$BINDIR/mount-chroot" -c "$CHROOTS" -- "$NAME" || true fi - if [ -d "/var/run/crouton/$CHROOT" ]; then + if mountpoint -q "/var/run/crouton/$CHROOT"; then echo "encrypted: yes, unlocked" else echo "encrypted: yes, locked" diff --git a/host-bin/enter-chroot b/host-bin/enter-chroot index 671216b7f..f73f90f83 100755 --- a/host-bin/enter-chroot +++ b/host-bin/enter-chroot @@ -1,5 +1,5 @@ #!/bin/sh -e -# Copyright (c) 2014 The crouton Authors. All rights reserved. +# Copyright (c) 2015 The crouton Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. @@ -138,22 +138,14 @@ fi # Check to ensure that the XMETHOD requested has been installed if [ -n "$TMPXMETHOD" ]; then - if ! grep -q "^$TMPXMETHOD$" "$CHROOTS/$NAME/.crouton-targets" 2>/dev/null; then - error 1 "$CHROOTS/$NAME does not contain XMETHOD '$TMPXMETHOD'" + if ! grep -q "^${TMPXMETHOD%%-*}$" "$CHROOTS/$NAME/.crouton-targets"; then + error 1 "$CHROOTS/$NAME does not contain XMETHOD '${TMPXMETHOD%%-*}'" fi fi # Avoid kernel panics due to slow I/O disablehungtask -# Enable control of framebuffer compression (if used) by video users -for fbc in '/sys/kernel/debug/dri/0/'*fbc*; do :; done -if [ -f "$fbc" ] && ! grep -q 'disabled per module param' "$fbc"; then - fbc='/sys/module/i915/parameters/i915_enable_fbc' - chgrp video "$fbc" - chmod g+w "$fbc" -fi - # Allow X server running as normal user to set/drop DRM master drm_relax_file="/sys/kernel/debug/dri/drm_master_relax" if [ -f "$drm_relax_file" ]; then @@ -654,6 +646,27 @@ if [ ! "$NOLOGIN" = 1 ] && grep -q '^root:' "$passwd" 2>/dev/null; then # systemd-logind doesn't fork chrootcmd "/lib/systemd/systemd-logind >/dev/null 2>&1 /dev/null 2>&1 > '$CROUTONLOCKDIR/frecon') & :" + fi fi # Start the chroot and any specified command @@ -671,10 +684,16 @@ if [ -n "$NOLOGIN" ]; then fi fi else - # Run rc.local + # Check and run rc.local if [ -n "$firstrun" -a -x "$CHROOT/etc/rc.local" ]; then + ( sleep 10; echo "Still running chroot's rc.local..." 2>&1 ) & + noticepid="$!" + addtrap "kill '$noticepid' 2>/dev/null" chrootcmd 'exec /etc/rc.local >/dev/null 2>/dev/null /dev/null || true + wait "$noticepid" || true if [ ! "$ret" = 0 ]; then echo "WARNING: /etc/rc.local failed with code $ret" 1>&2 ret=0 diff --git a/host-bin/mount-chroot b/host-bin/mount-chroot index 0b1e6eea6..902743e6f 100755 --- a/host-bin/mount-chroot +++ b/host-bin/mount-chroot @@ -1,5 +1,5 @@ #!/bin/sh -e -# Copyright (c) 2014 The crouton Authors. All rights reserved. +# Copyright (c) 2015 The crouton Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. @@ -60,27 +60,27 @@ addtrap "stty echo 2>/dev/null" # Function to prompt the user for a passphrase. Sets $passphrase. promptNewPassphrase() { - echo -n "Choose an encryption passphrase for $NAME: " 1>&2 + echo_tty -n "Choose an encryption passphrase for $NAME: " [ -t 0 ] && stty -echo while [ -z "$passphrase" ]; do read -r passphrase if [ -z "$passphrase" ]; then - echo 1>&2 - echo -n 'You must specify a passphrase: ' 1>&2 + echo_tty '' + echo_tty -n 'You must specify a passphrase: ' continue fi - echo 1>&2 - echo -n 'Please confirm your passphrase: ' 1>&2 + echo_tty '' + echo_tty -n 'Please confirm your passphrase: ' read -r confirmation if [ ! "$confirmation" = "$passphrase" ]; then passphrase='' - echo 1>&2 - echo -n 'Passphrases do not match; try again: ' 1>&2 + echo_tty '' + echo_tty -n 'Passphrases do not match; try again: ' fi confirmation='' done [ -t 0 ] && stty echo - echo 1>&2 + echo_tty '' } # Mount each chroot @@ -139,7 +139,8 @@ for NAME in "$@"; do # Ensure that there's a root password set before decrypting the chroot, # unless the passphrase was specified via env, which isn't secure anyway if [ ! -f '/mnt/stateful_partition/etc/devmode.passwd' ]; then - echo 'You must have a root password in Chromium OS to mount encrypted chroots.' 1>&2 + echo_tty \ +'You must have a root password in Chromium OS to mount encrypted chroots.' if [ -z "$CROUTON_PASSPHRASE$CROUTON_NEW_PASSPHRASE" ]; then while ! chromeos-setdevpasswd; do :; done fi @@ -180,8 +181,8 @@ for NAME in "$@"; do random="/dev/urandom" echo 'Generating keys from /dev/urandom...' 1>&2 fi - key="`hexdump -v -n32 -e'"%02x"' "$random"`" - fnek="`hexdump -v -n32 -e'"%02x"' "$random"`" + key="`hexdump -v -n32 -e'32/1 "%02x"' "$random"`" + fnek="`hexdump -v -n32 -e'32/1 "%02x"' "$random"`" echo 'done' 1>&2 # Create key file @@ -200,13 +201,13 @@ $passphrase" | ecryptfs-wrap-passphrase "$wrappedfnek" - elif [ ! -f "$KEYFILE" ]; then error 1 "Unable to find encryption key file $KEYFILE" else - echo -n "Enter encryption passphrase for $NAME: " 1>&2 + echo_tty -n "Enter encryption passphrase for $NAME: " [ -t 0 ] && stty -echo if [ -z "$passphrase" ]; then read -r passphrase fi [ -t 0 ] && stty echo - echo 1>&2 + echo_tty '' wrappedkey="`mktemp`" wrappedfnek="`mktemp`" diff --git a/host-bin/startcli b/host-bin/startcli index 1e997caa7..290078db7 100755 --- a/host-bin/startcli +++ b/host-bin/startcli @@ -1,5 +1,5 @@ #!/bin/sh -e -# Copyright (c) 2014 The crouton Authors. All rights reserved. +# Copyright (c) 2015 The crouton Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. @@ -14,6 +14,12 @@ By default, it will log into the primary user on the first chroot found. Options are directly passed to enter-chroot; run enter-chroot to list them." +if [ -f /sbin/frecon ]; then + echo "$APPLICATION no longer works on systems using 'Freon'. +Please use enter-chroot instead." 1>&2 + exit 2 +fi + export TERM='linux' exec sh -e "`dirname "\`readlink -f "$0"\`"`/enter-chroot" -t cli-extra -l \ "$@" "" openvt -vws -- diff --git a/host-bin/starte17 b/host-bin/starte17 index 719081194..dc90c7b89 100755 --- a/host-bin/starte17 +++ b/host-bin/starte17 @@ -1,5 +1,5 @@ #!/bin/sh -e -# Copyright (c) 2014 The crouton Authors. All rights reserved. +# Copyright (c) 2015 The crouton Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. diff --git a/host-bin/startgnome b/host-bin/startgnome index e3e1b5eab..b93261d58 100755 --- a/host-bin/startgnome +++ b/host-bin/startgnome @@ -1,5 +1,5 @@ #!/bin/sh -e -# Copyright (c) 2014 The crouton Authors. All rights reserved. +# Copyright (c) 2015 The crouton Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. diff --git a/host-bin/startkde b/host-bin/startkde index c3a4e55f6..d80b59b4f 100755 --- a/host-bin/startkde +++ b/host-bin/startkde @@ -1,5 +1,5 @@ #!/bin/sh -e -# Copyright (c) 2014 The crouton Authors. All rights reserved. +# Copyright (c) 2015 The crouton Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. diff --git a/host-bin/startlxde b/host-bin/startlxde index bbec40e76..3894bea30 100755 --- a/host-bin/startlxde +++ b/host-bin/startlxde @@ -1,5 +1,5 @@ #!/bin/sh -e -# Copyright (c) 2014 The crouton Authors. All rights reserved. +# Copyright (c) 2015 The crouton Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. diff --git a/host-bin/startunity b/host-bin/startunity index 4beea9ab4..ed329e519 100755 --- a/host-bin/startunity +++ b/host-bin/startunity @@ -1,5 +1,5 @@ #!/bin/sh -e -# Copyright (c) 2014 The crouton Authors. All rights reserved. +# Copyright (c) 2015 The crouton Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. diff --git a/host-bin/startxbmc b/host-bin/startxbmc index 5af361e15..68be7cc6e 100755 --- a/host-bin/startxbmc +++ b/host-bin/startxbmc @@ -1,5 +1,5 @@ #!/bin/sh -e -# Copyright (c) 2014 The crouton Authors. All rights reserved. +# Copyright (c) 2015 The crouton Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. diff --git a/host-bin/startxfce4 b/host-bin/startxfce4 index 9e9ca881a..caa563acb 100755 --- a/host-bin/startxfce4 +++ b/host-bin/startxfce4 @@ -1,5 +1,5 @@ #!/bin/sh -e -# Copyright (c) 2014 The crouton Authors. All rights reserved. +# Copyright (c) 2015 The crouton Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. diff --git a/host-bin/startxiwi b/host-bin/startxiwi new file mode 100644 index 000000000..83cc29bae --- /dev/null +++ b/host-bin/startxiwi @@ -0,0 +1,61 @@ +#!/bin/sh -e +# Copyright (c) 2015 The crouton Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +set -e + +APPLICATION="${0##*/}" +ENTERCHROOT="$(dirname "$(readlink -f "$0")")/enter-chroot" +OPTS_ENTER='' +OPTS_XIWI='' + +USAGE="$APPLICATION [options] chroot_app [parameters] + +Wraps enter-chroot to launch a window or tab in Chromium OS for any graphical application. +Applications launched in this way show in independent windows or tabs. + +By default, it will use the primary user on the first xiwi-enabled chroot found and launch +the chroot_app in a window. + +Options: +$("$ENTERCHROOT" -h 2>&1 | grep -e ' -[bckntu]') + -F Launch the chroot_app full-screen. + -T Launch the chroot_app in a tab. + -f Prevent xiwi from quitting automatically. (see NOTE below) + +NOTE: +xiwi will normally close when the application returns. Some gui applications +fork before or during normal operation, which can confuse xiwi and cause it to +quit prematurely. If your application does not have a parameter that prevents +it from forking, and crouton is unable to automatically detect the fork, you can +use -f to prevent xiwi from quitting automatically. +xiwi will quit if you close the Chromium OS window when nothing is displayed. + +You can cycle through multiple windows inside the application +via Ctrl-Alt-Tab/Ctrl-Alt-Shift-Tab, or close them via Ctrl-Alt-Shift-Escape. +If the chroot_app begins with 'start' but you still want to +use the default window manager, specify the full path of the application. +" + +while getopts 'bc:k:n:t:u:FTf' OPT; do + case "$OPT" in + b) OPTS_ENTER="$OPTS_ENTER -$OPT";; + c|k|n|t|u) + OPTARG="$(echo -n "$OPTARG" | sed -e "s/'/'\\\\\\''/g")" + OPTS_ENTER="$OPTS_ENTER -$OPT '$OPTARG'";; + f|F|T) OPTS_XIWI="$OPTS_XIWI -$OPT";; + \?) echo "$USAGE" 1>&2 + exit 2;; + esac +done +shift "$((OPTIND-1))" + +if [ "$#" = "0" ]; then + echo "$USAGE" 1>&2 + exit 2 +fi + +eval "exec sh -e \"\$ENTERCHROOT\" -t xiwi $OPTS_ENTER \ + exec xiwi $OPTS_XIWI \"\$@\"" + diff --git a/host-bin/unmount-chroot b/host-bin/unmount-chroot index 424e48e3e..11db88c7f 100755 --- a/host-bin/unmount-chroot +++ b/host-bin/unmount-chroot @@ -1,5 +1,5 @@ #!/bin/sh -e -# Copyright (c) 2014 The crouton Authors. All rights reserved. +# Copyright (c) 2015 The crouton Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. @@ -78,15 +78,16 @@ fi # appropriate commands by checking if the command's parent root is not equal # to the pid's root. This avoids not unmounting due to a lazy-quitting # background application within the chroot. We also don't consider processes -# that have a parent PID of 1 (which would mean an orphaned process in this -# case), as enter-chroot never orphans its children. +# that have a parent PID of 1 or that of session_manager's (which would mean an +# orphaned process in this case), as enter-chroot never orphans its children. # $1: $base; the canonicalized base path of the chroot # Returns: non-zero if the chroot is in use. checkusage() { if [ -n "$FORCE" ]; then return 0 fi - local b="${1%/}/" pid ppid proot prootdir root rootdir + local b="${1%/}/" pid ppid proot prootdir root rootdir pids='' + local smgrpid="`pgrep -o -u 0 -x session_manager || echo 1`" for root in /proc/*/root; do if [ ! -r "$root" ]; then continue @@ -99,7 +100,7 @@ checkusage() { pid="${root#/proc/}" pid="${pid%/root}" ppid="`ps -p "$pid" -o ppid= 2>/dev/null | sed 's/ //g'`" - if [ -z "$ppid" ] || [ "$ppid" -eq 1 ]; then + if [ -z "$ppid" ] || [ "$ppid" -eq 1 -o "$ppid" -eq "$smgrpid" ]; then continue fi proot="/proc/$ppid/root" @@ -110,10 +111,15 @@ checkusage() { fi fi if [ -n "$PRINT" ]; then - ps -p "$pid" -o pid= -o cmd= || true + pids="$pids $pid" + continue fi return 1 done + if [ -n "$PRINT" -a -n "$pids" ]; then + ps -p "${pids# }" -o pid= -o cmd= || true + return 1 + fi return 0 } diff --git a/host-ext/crouton/background.html b/host-ext/crouton/background.html index 90f6ac41e..18b8b2fba 100644 --- a/host-ext/crouton/background.html +++ b/host-ext/crouton/background.html @@ -1,6 +1,6 @@ - diff --git a/host-ext/crouton/background.js b/host-ext/crouton/background.js index 126ad72fe..9872628d6 100644 --- a/host-ext/crouton/background.js +++ b/host-ext/crouton/background.js @@ -1,6 +1,7 @@ -// Copyright (c) 2014 The crouton Authors. All rights reserved. +// Copyright (c) 2015 The crouton Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +'use strict'; /* Constants */ var URL = "ws://localhost:30001/"; @@ -12,11 +13,11 @@ var WINDOW_UPDATE_INTERVAL = 15; /* Update window list every 15" at most */ /* String to copy to the clipboard if it should be empty */ var DUMMY_EMPTYSTRING = "%"; -LogLevel = { +var LogLevel = Object.freeze({ ERROR : "error", - INFO : "info", + INFO : "info", DEBUG : "debug" -} +}); /* Global variables */ var clipboardholder_; /* textarea used to hold clipboard content */ @@ -42,7 +43,7 @@ var logger_ = []; /* Array of status messages: [LogLevel, time, message] */ var windows_ = []; /* Array of windows. (.display, .name) */ var kiwi_win_ = {}; /* Map of kiwi windows. Key is display, value is object - (.id, .window: window element) */ + (.id, .isTab, .window: window element) */ var focus_win_ = -1; /* Focused kiwi window. -1 if no kiwi window focused. */ var notifications_ = {}; /* Map of notification id to function to be called when @@ -110,8 +111,8 @@ function updateWindowList(force) { /* Called from kiwi (window.js), so we can directly access each window */ function registerKiwi(displaynum, window) { - display = ":" + displaynum - if (kiwi_win_[display] && kiwi_win_[display].id >= 0) { + var display = ":" + displaynum; + if (kiwi_win_[display] && kiwi_win_[display].id >= -1) { kiwi_win_[display].window = window; } } @@ -128,30 +129,34 @@ function closePopup() { function refreshUI() { updateWindowList(false); + var icon = "disconnected"; if (error_) - icon = "error" + icon = "error"; else if (!enabled_) - icon = "disabled" + icon = "disabled"; else if (active_) icon = "connected"; - else - icon = "disconnected"; chrome.browserAction.setIcon( - {path: {'19': icon + '-19.png', '38': icon + '-38.png'}} + {path: {19: icon + '-19.png', 38: icon + '-38.png'}} ); chrome.browserAction.setTitle({title: 'crouton: ' + icon}); + chrome.browserAction.setBadgeText( + {text: windows_.length > 1 ? '' + (windows_.length-1) : ''} + ); + chrome.browserAction.setBadgeBackgroundColor({color: '#2E822B'}); + var views = chrome.extension.getViews({type: "popup"}); for (var i = 0; i < views.length; views++) { var view = views[i]; /* Make sure page is ready */ - if (document.readyState === "complete") { + if (view.document.readyState != "loading") { /* Update "help" link */ - helplink = view.document.getElementById("help"); + var helplink = view.document.getElementById("help"); helplink.onclick = showHelp; /* Update enable/disable link. */ - enablelink = view.document.getElementById("enable"); + var enablelink = view.document.getElementById("enable"); if (enabled_) { enablelink.textContent = "Disable"; enablelink.onclick = function() { @@ -175,28 +180,42 @@ function refreshUI() { } /* Update debug mode according to checkbox state. */ - debugcheck = view.document.getElementById("debugcheck"); + var debugcheck = view.document.getElementById("debugcheck"); debugcheck.onclick = function() { debug_ = debugcheck.checked; refreshUI(); var disps = Object.keys(kiwi_win_); for (var i = 0; i < disps.length; i++) { - if (kiwi_win_[disps[i]].window) - kiwi_win_[disps[i]].window.setDebug(debug_?1:0); + var win = kiwi_win_[disps[i]]; + if (win.window) { + if (win.isTab) { + chrome.tabs.sendMessage(win.id, + {func: 'setDebug', param: debug_?1:0}); + } else { + win.window.setDebug(debug_?1:0); + } + } } } debugcheck.checked = debug_; /* Update hidpi mode according to checkbox state. */ - hidpicheck = view.document.getElementById("hidpicheck"); + var hidpicheck = view.document.getElementById("hidpicheck"); if (window.devicePixelRatio > 1) { hidpicheck.onclick = function() { hidpi_ = hidpicheck.checked; refreshUI(); var disps = Object.keys(kiwi_win_); for (var i = 0; i < disps.length; i++) { - if (kiwi_win_[disps[i]].window) - kiwi_win_[disps[i]].window.setHiDPI(hidpi_?1:0); + var win = kiwi_win_[disps[i]]; + if (win.window) { + if (win.isTab) { + chrome.tabs.sendMessage(win.id, + {func: 'setHiDPI', param: hidpi_?1:0}); + } else { + win.window.setHiDPI(hidpi_?1:0); + } + } } } hidpicheck.disabled = false; @@ -210,7 +229,7 @@ function refreshUI() { /* Update window table */ /* FIXME: Improve UI */ - windowlist = view.document.getElementById("windowlist"); + var windowlist = view.document.getElementById("windowlist"); while (windowlist.rows.length > 0) { windowlist.deleteRow(0); @@ -233,7 +252,7 @@ function refreshUI() { } /* Update logger table */ - loggertable = view.document.getElementById("logger"); + var loggertable = view.document.getElementById("logger"); /* FIXME: only update needed rows */ while (loggertable.rows.length > 0) { @@ -241,7 +260,7 @@ function refreshUI() { } /* Only update if "show log" is enabled */ - logcheck = view.document.getElementById("logcheck"); + var logcheck = view.document.getElementById("logcheck"); logcheck.onclick = function() { showlog_ = logcheck.checked; refreshUI(); @@ -249,7 +268,7 @@ function refreshUI() { logcheck.checked = showlog_; if (showlog_) { for (var i = 0; i < logger_.length; i++) { - value = logger_[i]; + var value = logger_[i]; if (value[0] == LogLevel.DEBUG && !debug_) continue; @@ -274,9 +293,15 @@ function clipboardStart() { LogLevel.INFO); setStatus("Started...", false); - /* Monitor window focus changes/removals and report to croutonclip */ - chrome.windows.onFocusChanged.addListener(windowFocusChanged) - chrome.windows.onRemoved.addListener(windowRemoved) + /* Monitor window/tab focus changes/removals and report to croutonclip */ + chrome.windows.onFocusChanged.addListener( + function(id) { onFocusChanged(id, false); }); + chrome.windows.onRemoved.addListener( + function(id) { onRemoved(id, false); }); + chrome.tabs.onActivated.addListener( + function(data) { onFocusChanged(data.tabId, true); }); + chrome.tabs.onRemoved.addListener( + function(id, data) { onRemoved(id, true); }); clipboardholder_ = document.getElementById("clipboardholder"); @@ -463,7 +488,7 @@ function websocketMessage(evt) { if (payload.length > 0) { windows_ = payload.split('\n').map( function(x) { - m = x.match(/^([^ *]*)\*? +(.*)$/) + var m = x.match(/^([^ *]*)\*? +(.*)$/); if (!m) return null; @@ -471,78 +496,115 @@ function websocketMessage(evt) { if (m[1] != "cros" && !m[1].match(/^:([0-9]+)$/)) return null; - k = new Object() + var k = new Object(); k.display = m[1]; k.name = m[2]; return k; } - ).filter( function(x) { return !!x; } ) + ).filter( function(x) { return !!x; } ); windows_.forEach(function(k) { - if (kiwi_win_[k.display] && kiwi_win_[k.display].window) { - kiwi_win_[k.display].window.setTitle(k.name); + var win = kiwi_win_[k.display]; + if (win && win.window) { + if (win.isTab) { + chrome.tabs.sendMessage(win.id, + {func: 'setTitle', param: k.name}); + } else { + win.window.setTitle(k.name); + } } - }) + }); + + lastwindowlistupdate_ = new Date().getTime(); + websocket_.send("COK"); } refreshUI(); break; - case 'X': /* Ask to open a crouton-in-a-tab window */ - display = payload - match = display.match(/^:([0-9]+)$/) - displaynum = match ? match[1] : null + case 'X': /* Ask to open a crouton window */ + var display = payload; + var match = display.match(/^:([0-9]+)([- ][^- ]*)*$/); + var displaynum = match ? match[1] : null; + var mode = null; + if (displaynum) { + display = ":" + displaynum; + mode = match[2] && match[2].length >= 2 ? match[2].charAt(1) : 'f'; + if ('fwt'.indexOf(mode) == -1) { + console.log('invalid xiwi mode: ' + mode); + mode = 'f'; + } + } if (!displaynum) { /* Minimize all kiwi windows */ var disps = Object.keys(kiwi_win_); for (var i = 0; i < disps.length; i++) { + if (kiwi_win_[disps[i]].isTab) { + continue; + } var winid = kiwi_win_[disps[i]].id; chrome.windows.update(winid, {focused: false}); - minimize = function(win) { - chrome.windows.update(winid, - {'state': 'minimized'}, function(win) {})} + var minimize = function(win) { + chrome.windows.update(winid, {state: 'minimized'}); }; chrome.windows.get(winid, function(win) { /* To make restore nicer, first exit full screen, * then minimize */ if (win.state == "fullscreen") { - chrome.windows.update(winid, - {'state': 'maximized'}, minimize) + chrome.windows.update(winid, {state: 'maximized'}, + minimize); } else { - minimize() + minimize(); } - }) + }); } } else if (kiwi_win_[display] && kiwi_win_[display].id >= 0 && (!kiwi_win_[display].window || !kiwi_win_[display].window.closing)) { /* focus/full screen an existing window */ var winid = kiwi_win_[display].id; - chrome.windows.update(winid, {focused: true}); - chrome.windows.get(winid, function(win) { - if (win.state == "maximized") - chrome.windows.update(winid, {'state': 'fullscreen'}, - function(win) {}) - }) + if (kiwi_win_[display].isTab) { + chrome.tabs.update(winid, {active: true}); + chrome.tabs.get(winid, function(tab) { + chrome.windows.update(tab.windowId, {focused: true}); + }); + } else { + chrome.windows.update(winid, {focused: true}); + chrome.windows.get(winid, function(win) { + if (win.state == "maximized") + chrome.windows.update(winid, {state: 'fullscreen'}); + }); + } } else { /* Open a new window */ kiwi_win_[display] = new Object(); kiwi_win_[display].id = -1; + kiwi_win_[display].isTab = (mode == 't'); kiwi_win_[display].window = null; - win = windows_.filter(function(x){ return x.display == display })[0] - name = win ? win.name : "crouton in a tab"; - - chrome.windows.create({ 'url': "window.html?display=" + displaynum + - "&debug=" + (debug_ ? 1 : 0) + - "&hidpi=" + (hidpi_ ? 1 : 0) + - "&title=" + encodeURIComponent(name), - 'type': "popup" }, - function(newwin) { - kiwi_win_[display].id = newwin.id; - focus_win_ = display; - if (active_ && sversion_ >= 2) - websocket_.send("Cs" + focus_win_); - }); + var win = windows_.filter(function(x){return x.display == display})[0]; + var name = win ? win.name : "crouton in a window"; + var create = chrome.windows.create; + var data = {}; + + if (kiwi_win_[display].isTab) { + name = win ? win.name : "crouton in a tab"; + create = chrome.tabs.create; + } else { + data['type'] = "popup"; + } + + data['url'] = "window.html?display=" + displaynum + + "&debug=" + (debug_ ? 1 : 0) + + "&hidpi=" + (hidpi_ ? 1 : 0) + + "&title=" + encodeURIComponent(name) + + "&mode=" + mode; + + create(data, function(newwin) { + kiwi_win_[display].id = newwin.id; + focus_win_ = display; + if (active_ && sversion_ >= 2) + websocket_.send("Cs" + focus_win_); + }); } websocket_.send("XOK"); closePopup(); @@ -586,33 +648,38 @@ function websocketClose() { checkUpdate(false); } -/* Called when window in focus changes: feeback to the extension so the +/* Called when window/tab in focus changes: feedback to the extension so the * clipboard can be transfered. */ -function windowFocusChanged(windowid) { +function onFocusChanged(id, isTab) { var disps = Object.keys(kiwi_win_); - nextfocus_win_ = "cros"; + var nextfocus_win = "cros"; for (var i = 0; i < disps.length; i++) { - if (kiwi_win_[disps[i]].id == windowid) { - nextfocus_win_ = disps[i]; + if (kiwi_win_[disps[i]].isTab == isTab + && kiwi_win_[disps[i]].id == id) { + nextfocus_win = disps[i]; break; } } - if (focus_win_ != nextfocus_win_) { - focus_win_ = nextfocus_win_; + if (focus_win_ != nextfocus_win) { + focus_win_ = nextfocus_win; if (active_ && sversion_ >= 2) websocket_.send("Cs" + focus_win_); printLog("Window " + focus_win_ + " focused", LogLevel.DEBUG); } } -/* Called when a window is removed, so we can delete its reference. */ -function windowRemoved(windowid) { +/* Called when a window/tab is removed, so we can delete its reference. */ +function onRemoved(id, isTab) { var disps = Object.keys(kiwi_win_); for (var i = 0; i < disps.length; i++) { - if (kiwi_win_[disps[i]].id == windowid) { - kiwi_win_[disps[i]].id = -1; + if (kiwi_win_[disps[i]].isTab == isTab + && kiwi_win_[disps[i]].id == id) { + kiwi_win_[disps[i]].id = -2; + kiwi_win_[disps[i]].isTab = false; kiwi_win_[disps[i]].window = null; printLog("Window " + disps[i] + " removed", LogLevel.DEBUG); + /* Force a window list update */ + updateWindowList(true); } } } @@ -642,10 +709,10 @@ function padstr0(i) { /* Add a message in the log. */ function printLog(str, level) { - date = new Date; - datestr = padstr0(date.getHours()) + ":" + - padstr0(date.getMinutes()) + ":" + - padstr0(date.getSeconds()); + var date = new Date; + var datestr = padstr0(date.getHours()) + ":" + + padstr0(date.getMinutes()) + ":" + + padstr0(date.getSeconds()); if (str.length > 200) str = str.substring(0, 197) + "..."; @@ -688,7 +755,7 @@ chrome.runtime.onInstalled.addListener(function(details) { chrome.runtime.getPlatformInfo(function(platforminfo) { if (platforminfo.os == 'cros') { /* On error: disconnect WebSocket, then log errors */ - onerror = function(msg, url, line) { + var onerror = function(msg, url, line) { if (websocket_) websocket_.close(); error("Uncaught JS error: " + msg, false); diff --git a/host-ext/crouton/first.html b/host-ext/crouton/first.html index a0f004c70..183c2356b 100644 --- a/host-ext/crouton/first.html +++ b/host-ext/crouton/first.html @@ -1,6 +1,6 @@ - diff --git a/host-ext/crouton/manifest.json b/host-ext/crouton/manifest.json index 300874770..347fdc18f 100644 --- a/host-ext/crouton/manifest.json +++ b/host-ext/crouton/manifest.json @@ -4,7 +4,7 @@ "name": "crouton integration", "short_name": "crouton", "description": "Improves integration with crouton chroots.", - "version": "2.2.0", + "version": "2.5.0", "icons": { "48": "icon-48.png", "128": "icon-128.png" @@ -25,7 +25,6 @@ "permissions": [ "clipboardRead", "clipboardWrite", - "notifications", - "tabs" + "notifications" ] } diff --git a/host-ext/crouton/popup.html b/host-ext/crouton/popup.html index c4f901e19..07e7d9864 100644 --- a/host-ext/crouton/popup.html +++ b/host-ext/crouton/popup.html @@ -1,6 +1,6 @@ - diff --git a/host-ext/crouton/popup.js b/host-ext/crouton/popup.js index b3811cd53..6e2466400 100644 --- a/host-ext/crouton/popup.js +++ b/host-ext/crouton/popup.js @@ -1,7 +1,9 @@ -/* Copyright (c) 2014 The crouton Authors. All rights reserved. +/* Copyright (c) 2015 The crouton Authors. All rights reserved. * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ +'use strict'; + document.addEventListener('DOMContentLoaded', function() { chrome.extension.getBackgroundPage().refreshUI(); }); diff --git a/host-ext/crouton/window.html b/host-ext/crouton/window.html index 9d381c227..078ccfca6 100644 --- a/host-ext/crouton/window.html +++ b/host-ext/crouton/window.html @@ -1,16 +1,16 @@ - - - + + Crouton in a tab -