merging in netwm changes at merge point "netwm-merge1". This add the XAtom class...
[mikachu/openbox.git] / util / bsetbg
1 #!/bin/sh
2
3 # Copyright (c) 2000-2002 Timothy M. King (tmk@lordzork.com)
4 #
5 # Permission is hereby granted, free of charge, to any person obtaining a
6 # copy of this software and associated documentation files (the "Software"),
7 # to deal in the Software without restriction, including without limitation
8 # the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 # and/or sell copies of the Software, and to permit persons to whom the 
10 # Software is furnished to do so, subject to the following conditions:
11
12 # The above copyright notice and this permission notice shall be included in 
13 # all copies or substantial portions of the Software. 
14
15 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
16 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
17 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL 
18 # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
19 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
20 # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
21 # DEALINGS IN THE SOFTWARE.
22
23 PATH=$PATH:/usr/bin:/usr/local/bin:/usr/X11R6/bin
24
25 img_apps="display xli xsetbg Esetroot qiv wmsetbg xv"
26
27 display_full_cmd="display -geometry 800x600 -window root"
28 display_tile_cmd="display -window root"
29 display_center_cmd="display -backdrop -window root"
30 display_default_cmd="$display_center_cmd"
31
32 Esetroot_full_cmd="Esetroot -scale"
33 Esetroot_tile_cmd="Esetroot"
34 Esetroot_center_cmd="Esetroot -c"
35 Esetroot_default_cmd="$Esetroot_center_cmd"
36
37 wmsetbg_full_cmd="wmsetbg -s -S"
38 wmsetbg_tile_cmd="wmsetbg -t"
39 wmsetbg_center_cmd="wmsetbg -e"
40 wmsetbg_default_cmd="$wmsetbg_center_cmd"
41
42 qiv_full_cmd="qiv --root_s"
43 qiv_tile_cmd="qiv --root_t"
44 qiv_center_cmd="qiv --root"
45 qiv_default_cmd="$qiv_center_cmd"
46
47 xv_full_cmd="xv -max -smooth -root -quit"
48 xv_tile_cmd="xv -root -quit"
49 xv_center_cmd="xv -rmode 5 -root -quit"
50 xv_default_cmd="$xv_center_cmd"
51
52 xli_full_cmd="xli -fullscreen -onroot -quiet"
53 xli_tile_cmd="xli -onroot -quiet"
54 xli_center_cmd="xli -center -onroot quiet"
55 xli_default_cmd="$xli_center_cmd"
56
57 xsetbg_full_cmd="xsetbg -fullscreen"
58 xsetbg_tile_cmd="xsetbg"
59 xsetbg_center_cmd="xsetbg -center"
60 xsetbg_default_cmd="$xsetbg_center_cmd"
61
62 ##################################
63
64 me=${0##*/}
65 version=2.1
66 copyright="(c) 2000-$(date +%Y) by Timothy M. King (http://lordzork.com/)"
67 config=$HOME/.bsetbgrc
68 last_cmd_file=$HOME/.bsetbg_last_cmd
69 refresh_cmd=xrefresh
70 p=$me:
71
72 quit() 
73 {
74         [ "$1" ] && rc=$1 && shift 1
75         [ "$*" ] && echo -e $*
76         exit ${rc:-0}
77 }
78
79 bool() {
80         case $1 in
81                 [yY][eE][sS]|1|[yY]|[tT][rR][uU][eE]|[oO][nN]) : ;;
82                 *) return 1 ;;
83         esac
84 }
85
86 check_exe_in_path() 
87 {
88         if [ -z "$1" ]; then
89                 return 1
90         elif [ -x "$(which $1 2>/dev/null)" ]; then
91                 return 0
92         elif [ -x "$(type $1 2>/dev/null)" ]; then
93                 return 0
94         else
95                 return 1
96         fi
97 }
98
99 help_msg() 
100 {
101         cat <<EOF
102 $me $version $copyright
103
104   -center <file>           center an image on the desktop
105   -tile <file>             tile an image on the desktop
106   -full <file>             stretch an image to fill the desktop
107   -exec <args> <file>      specify an external command to execute
108   
109   -post <string>           arguments to be passed to the post-command
110   -debug                   prints commands without executing them
111 EOF
112
113         # this is extremely lame, but probably more portable than grep -E   
114         bsetroot_help=$(bsetroot -help  2>&1| grep -v "^bsetroot" | grep -v "^  -help")
115         case $bsetroot_help in
116                 BaseDisplay*)   echo ;;
117                 *-gradient*)    echo "$bsetroot_help"
118         esac
119
120         cat <<EOF
121   -generate <string>       generate a config file
122   -help                    this message
123   -version                 output version information
124 EOF
125         quit ${1:-0}
126 }
127
128 get_apps() 
129 {
130         for a in $img_apps; do
131                 if check_exe_in_path $a; then
132                         eval center_cmd=\$$a\_center_cmd
133                         eval full_cmd=\$$a\_full_cmd
134                         eval tile_cmd=\$$a\_tile_cmd
135                         eval default_cmd=\$$a\_default_cmd
136                         return 0
137                 else
138                         if [ "$not_found" ]; then
139                                 not_found="$not_found $a"
140                         else
141                                 not_found=$a
142                         fi
143                 fi
144         done
145         return 1
146 }
147
148 do_generate() 
149 {
150         echo -e "# created by $me $version on $(date)\n#"
151         echo -e "# seting NO_EXEC to a boolean value (eg true/false) will cause $me"
152         echo -e "# to never modify the root window\n#"
153         echo -e "#NO_EXEC=\n#"
154         echo -e "# POST_COMMAND can be set to a command that will be run run every time"
155         echo -e "# $me sets the root image\n#"
156         echo -e "#POST_COMMAND=\n#"
157         echo -e "# if LOG_LAST_CMD is set (boolean), bsetbg will keep a log of the last"
158         echo -e "# two successful commands.\n#"
159         echo -e "#LOG_LAST_CMD=\n#"
160         echo -e "# the LOGFILE specifies the file that bsetbg uses when LOG_LAST_CMD"
161         echo -e "# is defined. this defaults to ~/.bsetbg_last_cmd .\n#"
162         echo -e "#LOGFILE=\n#"
163         echo -e "# the following are default configuration values for the most popular image"
164         echo -e "# programs. See the man page of the respective application for more info.\n" 
165
166         [ "$*" ] && img_apps="$*"
167
168         for a in $img_apps; do
169                 if check_exe_in_path $a; then
170                         if ! bool $have_match; then
171                                 q='\"'
172                                 [ "$(eval echo \$$a\_center_cmd)" ] &&
173                                 eval echo CENTER=$q\$$a\_center_cmd$q &&
174                         
175                                 [ "$(eval echo \$$a\_full_cmd)" ] &&
176                                 eval echo FULL=$q\$$a\_full_cmd$q &&
177                         
178                                 [ "$(eval echo \$$a\_tile_cmd)" ] &&
179                                 eval echo TILE=$q\$$a\_tile_cmd$q &&
180                         
181                                 [ "$(eval echo \$$a\_default_cmd)" ] &&
182                                 eval echo -e DEFAULT=$q\$$a\_default_cmd$q \\\\n &&
183                         
184                                 have_match=1
185                         else
186                                 [ "$(eval echo \$$a\_center_cmd)" ] && 
187                                 eval echo \\#CENTER=$q\$$a\_center_cmd$q
188                         
189                                 [ "$(eval echo \$$a\_full_cmd)" ] &&
190                                 eval echo \\#FULL=$q\$$a\_full_cmd$q
191                         
192                                 [ "$(eval echo \$$a\_tile_cmd)" ] &&
193                                 eval echo \\#TILE=$q\$$a\_tile_cmd$q
194                         
195                                 [ "$(eval echo \$$a\_default_cmd)" ] &&
196                                 eval echo -e \\#DEFAULT=$q\$$a\_default_cmd$q \\\\n
197                         fi
198                 fi
199         done
200         quit 0
201 }
202
203 do_bsetroot() 
204 {
205         if check_exe_in_path bsetroot; then
206                 read_config
207
208                 $debug bsetroot $* 2>/dev/null; rc=$?
209                 
210                 if [ "$rc" -gt 0 ]; then
211                         help_msg $rc
212                 else
213                         log_cmd bsetroot $*; $refresh_cmd 2>/dev/null
214                 fi
215         else
216                 quit 1 "couldn't find bsetroot in $PATH"
217         fi
218 }
219
220 do_standard() 
221 {
222         [ -z "$1" ] && help_msg 1
223
224         bool $noconfig || read_config
225
226         get_img_command $1
227         check_img_command $do_this
228
229         case $# in
230                 1) file="$1" ;;
231                 *) file="$2"
232         esac
233
234         if [ -f "$file" ]; then
235                 exec_img_command $do_this $file 
236         else
237                 quit 1 "$file does not exist"
238         fi
239
240
241 do_exec() 
242 {
243         [ "$#" -lt 3 ] && help_msg 3
244
245         bool $noconfig || read_config
246     
247         # check to see if -*c, -*f, or -*t were spcified, if so
248         # assume the last argument is a filename
249         b_arg=$(eval echo \$$(( $# - 1 )) )
250         app=$1
251
252         case $b_arg in
253                 -c|*-center|c|-t|*-tile*|t|-f|*-full|f)
254                         eval file=\$$#
255                         f_args="$b_arg $file"
256         esac
257
258         # put the rest of the arguments into the varialbe $e_args
259         while [ "$*" ]; do
260                 for a in "$*"; do
261                         case $1 in
262                                 $b_arg|$file) : ;;
263                                 *) e_args="$e_args "$1""
264                         esac
265                         shift 1
266                 done
267         done
268
269         # with $f_args defined, check for image and do things normally
270         if [ "$f_args" ]; then
271                 [ ! -f "$file" ] && quit 1 "$file does not exist"
272         
273                 if check_img_command $e_args; then
274                         do_this="$e_args"
275                 else
276                         read_config
277                         get_img_command $f_args
278                         check_img_command $do_this
279                         echo "$p couldn't find '$app' in path, using $type command instead"
280                 fi
281         # without $f_args, run the command blindly if it's in $PATH
282         elif check_exe_in_path $e_args; then
283                 do_this="$e_args"
284         else
285                 quit 1 "$p unable to run the following command: $e_args"
286         fi
287
288         exec_img_command $do_this $file
289 }    
290
291 get_img_command() 
292 {
293         case $1 in
294                 *-full|-f|f)    type=full; do_this="$full_cmd" ;;
295                 *-tile|-t|t)    type=tile; do_this="$tile_cmd" ;;
296                 *-center|-c|c)  type=center; do_this="$center_cmd" ;;
297                 *)              type=default; do_this="$default_cmd"
298         esac
299 }
300
301 check_img_command() 
302 {
303         if check_exe_in_path $1; then
304                 do_this="$*"
305                 rc=0
306         elif get_apps; then
307                 get_img_command $*
308                 rc=1
309         else
310                 quit 1 "$p couldn't find a suitable image program. tried the following:\\n
311                 $(for a in $not_found; do echo "    $a\\n"; done)"
312         fi
313
314         if [ "$rc" -gt 0 -a -z "$e_args" ] && bool $read_config; then
315                 echo "$p couldn't find a suitable $type command in $config"
316         fi
317
318     return $rc
319 }
320
321 exec_img_command() 
322 {
323         unset rc
324         command=$*
325
326         if [ "$debug" ]; then
327                 $debug $command
328         else
329                 $command >/dev/null 2>&1; rc=$?
330         fi
331
332         if [ "$rc" -gt 0 ]; then
333                 echo "$p '$command' exited with status $rc"
334                 get_apps
335                 noconfig=1
336                 parse_args ${f_args:-$my_args}
337                 echo "$p using '$command' as $type"
338                 $debug $command >/dev/null 2>&1; rc=$?
339                 [ "$rc" =  0 ] && log_cmd $do_this $file && $refresh_cmd 2>/dev/null
340         else
341                 log_cmd $do_this $file; xrefresh 2>/dev/null
342         fi
343         return $rc
344 }
345
346 log_cmd() 
347 {
348         bool $LOG_LAST_CMD || return 1
349         [ "$debug" ] && return 1
350         echo -e "$prev_cmd\n$*" >$last_cmd_file
351         return $?
352 }
353
354 read_config() 
355 {
356         [ -f $config ] || return 1
357
358         if bool $read_config; then
359                 unset read_config
360         else
361                 read_config=1
362         fi
363
364         . $HOME/.bsetbgrc 2>/dev/null
365         check_no_exec
366
367         full_cmd=$FULL
368         center_cmd=$CENTER
369         tile_cmd=$TILE
370         default_cmd=$CENTER
371         last_cmd_file=${LOGFILE:-$last_cmd_file}
372     
373         bool $LOG_LAST_CMD && prev_cmd=$(tail -n 1 $last_cmd_file 2>/dev/null)    
374 }
375
376 check_no_exec() 
377 {
378         bool $NO_EXEC && 
379         quit 0 "$p no_exec mode. the root window will not be modified."
380 }
381
382 post_command() 
383 {
384         if [ -n "$POST_COMMAND" -a "$rc" -le 0 ]; then
385                 if [ -n "$debug" ]; then
386                         $debug "running post_command: $POST_COMMAND $post_args"
387                 else
388                         post_command_output=$($POST_COMMAND $post_args 2>&1); erc=$?
389                         if [ "$erc" -gt 0 ]; then
390                                 echo "$p post-command '$POST_COMMAND $post_args' exited with status $erc"
391                                 [ -n "$post_command_output" ] &&
392                                         echo "$POST_COMMAND $post_args: $post_command_output"
393                         fi
394                 fi
395         fi
396 }
397
398 add_arg() 
399 {
400         [ "$1" ] || return 1
401         if [ "$args" ]; then
402                 args="$args $1"
403         else
404                 args=$1
405         fi
406 }  
407
408 add_post_arg() 
409 {
410         [ -z "$1" ] && return 1
411         if [ "$post_args" ]; then
412                 post_args="$post_args $1"
413         else
414                 post_args=$1
415         fi
416 }
417
418 check_cmd() 
419 {
420         if [ -z "$command" ]; then
421                 command=${2:-$1}; eval ${3:-${2:-$1}}=1
422         elif bool $do_post; then
423                 add_post_arg ${1}
424         else
425                 finished=1
426         fi 
427 }
428
429 parse_args() 
430 {
431         case $1 in
432                 -d|*-debug|d)
433                         unset refresh_cmd; debug=echo\ $me\_debug: ;;
434
435                 -p|-*-post|p)                   
436                         unset finished do_standard do_exec; do_post=1 ;;
437                                 
438                 -c|*-center|c|-t|*-tile*|t|-f|*-full|f)
439                         case $command in
440                                 do_standard|do_generate|do_bsetroot)
441                                         finished=1 ;;
442                                 do_exec)
443                                         if ! bool $got_fcmd; then
444                                                 add_arg $1 args; got_fcmd=1
445                                         else
446                                                 finished=1
447                                         fi ;;
448                                 *)      
449                                         add_arg $1; do_standard=1; command=do_standard
450                         esac ;;         
451                 
452                 -a|*-app|a|-e|*-exec|e)
453                         check_cmd "do_exec" ;;
454                 
455                 -mod|-gradient|-solid|-display)
456                         check_cmd "do_bsetroot" && add_arg $1 ;;
457
458                 -g|*-generate*|g)
459                         check_cmd $1 "do_generate" ;;
460                 
461                 -v|*-version|v)
462                         [ -z "$command" ] && quit 0 $me $version $copyright ;;
463                 
464                 -h|*-help|h)
465                         [ -z "$command" ] && help_msg ;;
466                 
467                 *)      
468                         bool $finished && return 1              
469
470                         case $1 in -*)
471                                 bool $do_exec || bool $do_bsetroot || bool $do_post || help_msg 1
472                         esac
473                 
474                         if bool $do_standard || bool $do_exec || bool $do_bsetroot || bool $do_generate; then
475                                 add_arg $1
476                         elif bool $do_post; then
477                                 add_post_arg $1
478                         else
479                                 add_arg $1; command=do_standard; finished=1
480                         fi
481         esac
482 }
483
484 [ -z "$*" ] && help_msg 1
485
486 my_args=$*
487
488 for arg in "$@"; do
489         parse_args "$arg"
490         shift 1
491 done
492
493 [ "$debug" ] && echo
494
495 $command $args
496 post_command $rc
497
498 quit $rc