FAQ update about enlightenment
[adesklets.git] / utils / adesklets_frontend.sh.in
blob44f187e86f0285291a7fe1a4df9a4618b899ad54
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 $*"
106 echo $*
108 xwininfo $ID -tree | sed -n "/$GEOM/"'{s/^[ \t]*\(0x[0-9a-f]\+\).*/\1/;p}'
111 # ------------------------------------------------------------------------------
112 # Error handling function
114 error () {
115 test $# -gt 0 && echo "Error: $*" && echo
116 test $# -eq 0; exit
119 # Command line error handling function
121 usage () {
122 test $# -gt 0 && echo "Error: $*" && echo
123 if test "x$ADESKLETS_EMBEDDED" = "x" ; then
124 DESC='Usage: adesklets [OPTION]... [string_id]'
125 else
126 DESC='Possible options are:'
128 cat<<EOF
129 $DESC
131 Fake root window detection
132 --kde KDE >= 3.4.1 desktop detection
133 --nautilus Nautilus desktop detection
134 --rox ROX-Filer detection (incomplete)
135 --user Interactive detection (by user click)
136 --xfce4 Xfce4 desktop detection (tested on Xfce4 4.2.x,
137 with xfdesktop managing the icons)
138 --xffm Xffm desktop window detection (tested on xffm 4.3.3.1,
139 with xffm-deskview managing the icons)
141 --do-it-once When applicable, do not run the detection for each desklet,
142 but only once for all. Of course, desklets on multiple
143 screens will unlikely detect the right fake root window, but
144 it will speed things up for single screen settings.
145 Miscellany
146 -h,--help Print out this message and exit
147 -d delay Wait for a given delay (in seconds) before
148 performing any further action
150 if test "x$ADESKLETS_EMBEDDED" = "x" ; then
151 cat<<EOF
152 -v,--version Printout adesklets version
153 -k,--killall Kill all running, registered desklets
154 -c,--cleanup Remove all dead entries from \$HOME/.adesklets
155 (this implies \`--killall')
156 -i,--installer Invoke the desklet frontend installer
157 (requires Python)
158 -f script Execute command set from the \`script' file
160 If no \`string_id' is given, adesklets acts as a launcher (unless
161 the \`-f' switch is involved). Otherwise, adesklets acts as
162 an interpreter, if no \`-k' or \`-c' switch is used.
164 The most usual invokation of adesklets is the bare \`adesklets' command,
165 without arguments: it makes adesklets launch every registered desklets
166 from \$HOME/.adesklets, without any fake root window detection.
169 test $# -eq 0; exit
172 # ------------------------------------------------------------------------------
173 # Initial test
175 test -e $HOME/.adesklets && {
176 test -f $HOME/.adesklets || \
177 error "$HOME/.adesklets is not a configuration file; please remove it."
180 # ------------------------------------------------------------------------------
181 # Parse the command line.
183 SELF=$0
184 OPTS=
185 MODE=
186 DO_IT_ONCE=0
187 while test $# -gt 0 ; do
188 case "$1" in
189 --kde|--nautilus|--rox|--user|--xfce4|--xffm)
190 MODE=`echo $1 | sed 's/--//'`
192 --do-it-once)
193 DO_IT_ONCE=1
195 -h|--help)
196 usage
199 test $# -gt 1 || usage "no delay given after -d switch."
200 sleep $2 > /dev/null 2> /dev/null || \
201 usage "Invalid delay of \`$2' seconds given."
202 shift
204 -v|--version)
205 echo "adesklets @VERSION@"
206 echo "Written By Sylvain Fourmanoit <syfou@users.sourceforge.net>"
207 exit 0
209 -k|--killall)
210 kill_desklets
211 exit 0
213 -c|--cleanup)
214 # The cleanup routine assumes the file is EXACTLY formatted as
215 # it is output by the binary interpreter.
216 kill_desklets
217 LINE=
218 for DESKLET in `sed -n 's/^\[//;s/]$//;/^\//{=;p}' $HOME/.adesklets`
220 if test "$DESKLET" -gt 0 2> /dev/null ; then
221 ID=$DESKLET
222 else
223 test -x "$DESKLET" || LINE="$LINE $ID"
225 done
226 sed -i "`echo "$LINE" | sed 's/[0-9]\+/&,+1d;/g'`" $HOME/.adesklets
227 exit 0
229 -i|--installer)
230 shift
231 exec adesklets_installer $*
234 test $# -gt 1 || usage "no file name given after -f switch."
235 test -r $2 || usage "could not read file \`$2'."
236 OPTS="-f $2"
237 shift
240 usage "invalid option \`$1'."
243 test "x$OPTS" = "x" || \
244 usage "invalid combination, \`$OPTS' and \`$1'."
245 OPTS="$1"
247 esac
248 shift
249 done
251 # ------------------------------------------------------------------------------
252 # Fake root window detection code
254 test "x$MODE" = "x" || ADESKLETS_MODE="$MODE"
255 test "x$ADESKLETS_MODE" = "x" || {
256 case "$ADESKLETS_MODE" in
257 xfce4|nautilus)
258 # Identify the lead desktop window from root property,
259 # then find the last child with the proper dimension
260 # For now on, we take advantage from the "compatibility code"
261 # included in xfce4.
262 DESKTOP=`xprop -root | \
263 sed -n '/^NAUTILUS_DESKTOP_WINDOW_ID/{s/.* \(0x[0-9a-f]\+\)/\1/;p}'`
264 for ROOT in `roots $DESKTOP` ; do : ; done
265 ADESKLETS_ROOT=$ROOT
267 xffm)
268 # Get the first child of the last window named 'xffm-deskview'.
269 # The bet is on: how long before this changes?
270 DESKTOP=`xwininfo -root -tree | \
271 sed -n '/xffm-deskview/{s/[ \t]*\(0x[0-9a-f]\+\).*/\1/;p}' | \
272 sed -n '$p'`
273 ADESKLETS_ROOT=`xwininfo -id $DESKTOP -tree | \
274 sed -n '/^[ \t]*0x[0-9a-f]\+/{s/[ \t]*\(0x[0-9a-f]\+\).*/\1/;p}' | \
275 sed '1q'`
277 kde)
278 test "x`dcop kdesktop default isIconsEnabled`" = "xtrue" && {
279 # First, we need to sync. the real root pixmap
280 # with the desktop: the fake root window is using a
281 # ParentRelative backgroundPixmap, with the real image
282 # from one of its parent, but the root being empty.
283 # We are very lucky this work... But for how long?
284 test "x$MODE" = "x" || {
285 # Just do this at high level
286 for I in 0 1; do
287 dcop kdesktop default setIconsEnabled $I
288 done
290 # Detect the fake root window
291 for ROOT in `roots` ; do
292 ADESKLETS_ROOT=`xprop -id $ROOT | \
293 sed -n '/__SWM_VROOT/{s/.*\(0x[0-9a-f]\+\)/\1/;p}'`
294 test "x$ADESKLETS_ROOT" = "x" || break
295 done
298 rox)
299 # Find first full screen window with a Rox-Filer somewhere in
300 # its property
301 for ROOT in `roots` ; do
302 test "x`xprop -id $ROOT | sed -n '/ROX-Filer/p'`" = "x" || break
303 done
304 ADESKLETS_ROOT=$ROOT
306 user)
307 # In this special mode, the pseudo-root is determined
308 # interactively using xwininfo. Since xwininfo needs to
309 # grab the pointer, just make sure we serialize all calls
310 # using a lock.
311 lock
312 ADESKLETS_ROOT=`xwininfo | \
313 sed -n '/Window id/{s/.*Window id: \([^ ]*\) .*/\1/p}'`
314 unlock
317 error "unknown mode."
319 esac
320 test "$DO_IT_ONCE" -eq 0 && export ADESKLETS_MODE
321 export ADESKLETS_ROOT
324 # ------------------------------------------------------------------------------
325 # Now, re-invoke the binary
327 export ADESKLETS_FRONTEND=1
328 exec adesklets $OPTS