Code cleanup
[adesklets.git] / utils / adesklets_frontend.sh.in
blob4c69bb8cee284540bf6174f2b44af632205d10e6
1 #! /bin/sh
2 # adesklets - Shell script frontend for the adesklets interpreter
3 # ------------------------------------------------------------------------------
4 # Copyright (C) 2005 Sylvain Fourmanoit <syfou@users.sourceforge.net>
6 # Permission is hereby granted, free of charge, to any person obtaining a copy
7 # of this software and associated documentation files (the "Software"), to
8 # deal in the Software without restriction, including without limitation the
9 # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 # sell copies of the Software, and to permit persons to whom the Software is
11 # furnished to do so, subject to the following conditions:
13 # The above copyright notice and this permission notice shall be included in
14 # all copies of the Software and its documentation and acknowledgment shall be
15 # given in the documentation and software packages that this Software was
16 # used.
18 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 # THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
22 # IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23 # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 # ------------------------------------------------------------------------------
25 # This is the shell script frontend for the adesklets interpreter, introduced
26 # in adesklets 0.4.11. It serves a couple simple purposes:
28 # - Bring all the fake-root windows detection code out of the binary
29 # interpreter, and detect them from a front-end. It makes it far simpler
30 # and quicker to adapt to new situations, as this code is no longer written
31 # in C, but in a sh-compatible scripting form. Hopefully, in this new format,
32 # people will be able to contribute new detection routines for specific
33 # Window Manager easily.
35 # - Print out a couple of warnings to hopefully prevent some people that
36 # would not read the fourth chapter from the manual from not invoking
37 # adesklets right.
39 # - Add a couple of functionalities, such as configuration file cleanup, and
40 # desklets killing.
42 # PORTABILITY NOTICE:
43 # ===================
45 # This shell script was made to comply with the POSIX 1003.2 and 1003.2a
46 # specification for the shell, and not use any vendor-specific extension
47 # for any program invoked. It has been tested on both BASH 3.00.16 and NetBSD
48 # ash 1.6.1 on a variety of platforms. It also uses some low-level, fairly
49 # common utilities or builtin, all also described in POSIX, namely:
51 # 1) a Streaming EDitor (sed). It as been tested on GNU sed 4.0.9, and FreeBSD
52 # 4.9 sed
53 # 2) test, conforming to POSIX 1003.2
54 # 3) mkdir and rmdir
55 # 4) sleep
56 # 5) kill
57 # 6) ls
59 # The xprop and xwinfinfo programs can also be used, if a given fake-root
60 # window detection routine is explicitely invoked. Both XFree86 and X.org
61 # implementations of these utilities have been tested. Window Manager specific
62 # detection will also potentially need WM specific programs:
64 # kde: need consolde dcop client
66 # ------------------------------------------------------------------------------
67 # Lock/unlock function
68 # Based on the fact that creating a directory is atomic
70 LOCKFILE=@LOCKFILES_DIR@/adesklets_frontend_$UID.lock
72 lock() {
73 while : ; do
74 mkdir $LOCKFILE > /dev/null 2> /dev/null && break
75 sleep .2
76 done
79 unlock() {
80 rmdir $LOCKFILE > /dev/null 2> /dev/null
83 # ------------------------------------------------------------------------------
84 # Kill all desklets function
86 kill_desklets() {
87 LOCK=`ls @LOCKFILES_DIR@/adesklets_uid$UID_*.lock 2> /dev/null`
88 test "x$LOCK" = "x" || {
89 PIDS=`cat $LOCK`
90 kill $PIDS > /dev/null 2> /dev/null
91 sleep 1
92 kill -9 $PIDS > /dev/null 2> /dev/null
96 # ------------------------------------------------------------------------------
97 # Detect potential fake root windows function
99 roots() {
100 local GEOM=`xwininfo -root | sed -n '/geometry/{s/^.*geometry[ \t]*//;p}'`
101 local ID
102 if test $# -eq 0 ; then
103 ID="-root"
104 else
105 ID="-id $*"
107 xwininfo $ID -tree | sed -n "/$GEOM/"'{s/^[ \t]*\(0x[0-9a-f]\+\).*/\1/;p}'
110 # ------------------------------------------------------------------------------
111 # Error handling function
113 error () {
114 test $# -gt 0 && echo "Error: $*" && echo
115 test $# -eq 0; exit
118 # Command line error handling function
120 usage () {
121 test $# -gt 0 && echo "Error: $*" && echo
122 if test "x$ADESKLETS_EMBEDDED" = "x" ; then
123 DESC='Usage: adesklets [OPTION] ... [string_id], where OPTION is in:'
124 else
125 DESC='Possible options are:'
127 cat<<EOF
128 $DESC
130 Fake root window detection
131 --xfce4 Xfce4 desktop detection (tested on Xfce4 4.2.0)
132 --nautilus Nautilus desktop detection
133 --kde KDE >= 3.4.1 desktop detection
134 --user Interactive detection (by user click)
135 --do-it-once When applicable, do not run the detection for each desklet,
136 but only once for all. Of course, desklets on multiple
137 screens will unlikely detect the right fake root window, but
138 it will speed things up for single screen settings.
139 Miscellany
140 -h,--help Print out this message and exit
141 -d delay Wait for a given delay (in seconds) before
142 performing any further action
144 if test "x$ADESKLETS_EMBEDDED" = "x" ; then
145 cat<<EOF
146 -k,--killall Kill all running, registered desklets
147 -c,--cleanup Remove all dead entries from \$HOME/.adesklets
148 (this implies \`--killall')
149 -f script Execute command set from the \`script' file
151 If no \`string_id' is given, adesklets acts as a launcher (unless
152 the \`-f' switch is involved). Otherwise, adesklets acts as
153 an interpreter, if no \`-k' or \`-c' switch is used.
155 The most usual invokation of adesklets is the bare \`adesklets' command,
156 without arguments: it makes adesklets launch every registered desklets
157 from \$HOME/.adesklets.
160 test $# -eq 0; exit
163 # ------------------------------------------------------------------------------
164 # Initial test
166 test -e $HOME/.adesklets && {
167 test -f $HOME/.adesklets || \
168 error "$HOME/.adesklets is not a configuration file; please remove it."
171 # ------------------------------------------------------------------------------
172 # Parse the command line.
174 SELF=$0
175 OPTS=
176 MODE=
177 DO_IT_ONCE=0
178 while test $# -gt 0 ; do
179 case "$1" in
180 --xfce4|--nautilus|--kde|--user)
181 MODE=`echo $1 | sed 's/--//'`
183 --do-it-once)
184 DO_IT_ONCE=1
186 -h|--help)
187 usage
190 test $# -gt 1 || usage "no delay given after -d switch."
191 sleep $2 > /dev/null 2> /dev/null || \
192 usage "Invalid delay of \`$2' seconds given."
193 shift
195 -k|--killall)
196 kill_desklets
197 exit 0
199 -c|--cleanup)
200 # The cleanup routine assumes the file is EXACTLY formatted as
201 # it is output by the binary interpreter.
202 kill_desklets
203 LINE=
204 for DESKLET in `sed -n 's/^\[//;s/]$//;/^\//{=;p}' $HOME/.adesklets`
206 if test "$DESKLET" -gt 0 2> /dev/null ; then
207 ID=$DESKLET
208 else
209 test -x "$DESKLET" || LINE="$LINE $ID"
211 done
212 sed -i "`echo "$LINE" | sed 's/[0-9]\+/&,+1d;/g'`" $HOME/.adesklets
213 exit 0
216 test $# -gt 1 || usage "no file name given after -f switch."
217 test -r $2 || usage "could not read file \`$2'."
218 OPTS="-f $2"
219 shift
222 usage "invalid option \`$1'."
225 test "x$OPTS" = "x" || \
226 usage "invalid combination, \`$OPTS' and \`$1'."
227 OPTS="$1"
229 esac
230 shift
231 done
233 # ------------------------------------------------------------------------------
234 # Fake root window detection code
236 test "x$MODE" = "x" || ADESKLETS_MODE="$MODE"
237 test "x$ADESKLETS_MODE" = "x" || {
238 case "$ADESKLETS_MODE" in
239 xfce4|nautilus)
240 # Identify the lead desktop window from root property,
241 # then find the last child with the proper dimension
242 # For now on, we take advantage from the "compatibility code"
243 # included in xfce4.
244 DESKTOP=`xprop -root | \
245 sed -n '/^NAUTILUS_DESKTOP_WINDOW_ID/{s/.* \(0x[0-9a-f]\+\)/\1/;p}'`
246 ADESKLETS_ROOT=`roots $DESKTOP | sed '$p'`
248 kde)
249 test "x`dcop kdesktop default isIconsEnabled`" = "xtrue" && {
250 # First, we need to sync. the real root pixmap
251 # with the desktop: the fake root window is using a
252 # ParentRelative backgroundPixmap, with the real image
253 # from one of its parent, but the root being empty.
254 # We are very lucky this work... But for how long?
255 test "x$MODE" = "x" || {
256 # Just do this at high level
257 for I in 0 1; do
258 dcop kdesktop default setIconsEnabled $I
259 done
261 # Detect the fake root window
262 for ROOT in `roots` ; do
263 ADESKLETS_ROOT=`xprop -id $ROOT | \
264 sed -n '/__SWM_VROOT/{s/.*\(0x[0-9a-f]\+\)/\1/;p}'`
265 test "x$ADESKLETS_ROOT" = "x" || break
266 done
269 user)
270 # In this special mode, the pseudo-root is determined
271 # interactively using xwininfo. Since xwininfo needs to
272 # grab the pointer, just make sure we serialize all calls
273 # using a lock.
274 lock
275 ADESKLETS_ROOT=`xwininfo | \
276 sed -n '/Window id/{s/.*Window id: \([^ ]*\) .*/\1/p}'`
277 unlock
280 error "unknown mode."
282 esac
283 test "$DO_IT_ONCE" -eq 0 && export ADESKLETS_MODE
284 export ADESKLETS_ROOT
287 # ------------------------------------------------------------------------------
288 # Now, re-invoke the binary
290 export ADESKLETS_FRONTEND=1
291 exec adesklets $OPTS