change how the widgets' _dirty flag works so that all inheritence levels of the widge...
[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.2
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 #debug=echo
72
73 quit() 
74 {
75         [ "$1" ] && rc=$1 && shift 1
76         [ "$*" ] && echo -e $*
77         exit ${rc:-0}
78 }
79
80 bool() {
81         case $1 in
82                 [yY][eE][sS]|1|[yY]|[tT][rR][uU][eE]|[oO][nN]) : ;;
83                 *) return 1 ;;
84         esac
85 }
86
87 check_exe_in_path() 
88 {
89         if [ -z "$1" ]; then
90                 return 1
91         elif [ -x "$(which $1 2>/dev/null)" ]; then
92                 return 0
93         elif [ -x "$(type $1 2>/dev/null)" ]; then
94                 return 0
95         else
96                 return 1
97         fi
98 }
99
100 help_msg() 
101 {
102         cat <<EOF
103 $me $version $copyright
104
105   -center <file>           center an image on the desktop
106   -tile <file>             tile an image on the desktop
107   -full <file>             stretch an image to fill the desktop
108   -exec <args> <file>      specify an external command to execute
109   
110   -app  <app>              specify the image application to use
111   -post <string>           arguments to be passed to the post-command
112   -debug                   prints commands without executing them
113
114   -display <string>        use display connection
115   -mod <x> <y>             modula pattern
116   -foreground, -fg <color> modula foreground color
117   -background, -bg <color> modula background color
118
119   -gradient <texture>      gradient texture
120   -from <color>            gradient start color
121   -to <color>              gradient end color
122
123   -solid <color>           solid color
124
125   -generate <string>       generate a config file
126   -help                    this message
127   -version                 output version information
128 EOF
129         quit ${1:-0}
130 }
131
132 get_apps() 
133 {
134         for a in $img_apps; do
135                 if check_exe_in_path $a; then
136                         eval center_cmd=\$$a\_center_cmd
137                         eval full_cmd=\$$a\_full_cmd
138                         eval tile_cmd=\$$a\_tile_cmd
139                         eval default_cmd=\$$a\_default_cmd
140                         return 0
141                 else
142                         if [ "$not_found" ]; then
143                                 not_found="$not_found $a"
144                         else
145                                 not_found=$a
146                         fi
147                 fi
148         done
149         return 1
150 }
151
152 do_generate() 
153 {
154         echo -e "# created by $me $version on $(date)\n#"
155         echo -e "# seting NO_EXEC to a boolean value (eg true/false) will cause $me"
156         echo -e "# to never modify the root window\n#"
157         echo -e "#NO_EXEC=\n#"
158         echo -e "# POST_COMMAND can be set to a command that will be run run every time"
159         echo -e "# $me sets the root image\n#"
160         echo -e "#POST_COMMAND=\n#"
161         echo -e "# if LOG_LAST_CMD is set (boolean), bsetbg will keep a log of the last"
162         echo -e "# two successful commands.\n#"
163         echo -e "#LOG_LAST_CMD=\n#"
164         echo -e "# the LOGFILE specifies the file that bsetbg uses when LOG_LAST_CMD"
165         echo -e "# is defined. this defaults to ~/.bsetbg_last_cmd .\n#"
166         echo -e "#LOGFILE=\n#"
167         echo -e "# the following are default configuration values for the most popular image"
168         echo -e "# programs. See the man page of the respective application for more info.\n" 
169
170         [ "$*" ] && img_apps="$*"
171
172         for a in $img_apps; do
173                 if check_exe_in_path $a; then
174                         if ! bool $have_match; then
175                                 q='\"'
176                                 [ "$(eval echo \$$a\_center_cmd)" ] &&
177                                 eval echo CENTER=$q\$$a\_center_cmd$q &&
178                         
179                                 [ "$(eval echo \$$a\_full_cmd)" ] &&
180                                 eval echo FULL=$q\$$a\_full_cmd$q &&
181                         
182                                 [ "$(eval echo \$$a\_tile_cmd)" ] &&
183                                 eval echo TILE=$q\$$a\_tile_cmd$q &&
184                         
185                                 [ "$(eval echo \$$a\_default_cmd)" ] &&
186                                 eval echo -e DEFAULT=$q\$$a\_default_cmd$q \\\\n &&
187                         
188                                 have_match=1
189                         else
190                                 [ "$(eval echo \$$a\_center_cmd)" ] && 
191                                 eval echo \\#CENTER=$q\$$a\_center_cmd$q
192                         
193                                 [ "$(eval echo \$$a\_full_cmd)" ] &&
194                                 eval echo \\#FULL=$q\$$a\_full_cmd$q
195                         
196                                 [ "$(eval echo \$$a\_tile_cmd)" ] &&
197                                 eval echo \\#TILE=$q\$$a\_tile_cmd$q
198                         
199                                 [ "$(eval echo \$$a\_default_cmd)" ] &&
200                                 eval echo -e \\#DEFAULT=$q\$$a\_default_cmd$q \\\\n
201                         fi
202                 fi
203         done
204         quit 0
205 }
206
207 do_bsetroot() 
208 {
209         if check_exe_in_path bsetroot; then
210                 read_config
211
212                 $debug bsetroot $* 2>/dev/null; rc=$?
213                 
214                 if [ "$rc" -gt 0 ]; then
215                         help_msg $rc
216                 else
217                         log_cmd bsetroot $*; $refresh_cmd 2>/dev/null
218                 fi
219         else
220                 quit 1 "couldn't find bsetroot in $PATH"
221         fi
222 }
223
224 do_standard() 
225 {
226         [ -z "$1" ] && help_msg 1
227
228         bool $noconfig || read_config
229
230         get_img_command $1
231         check_img_command $do_this
232
233         case $# in
234                 1) file="$1" ;;
235                 *) file="$2"
236         esac
237
238         if [ -f "$file" ]; then
239                 exec_img_command $do_this $file 
240         else
241                 quit 1 "$file does not exist"
242         fi
243
244
245 do_exec() 
246 {
247         [ "$#" -lt 3 ] && help_msg 3
248
249         bool $noconfig || read_config
250     
251         # check to see if -*c, -*f, or -*t were spcified, if so
252         # assume the last argument is a filename
253         b_arg=$(eval echo \$$(( $# - 1 )) )
254         app=$1
255
256         case $b_arg in
257                 -c|*-center|c|-t|*-tile*|t|-f|*-full|f)
258                         eval file=\$$#
259                         f_args="$b_arg $file"
260         esac
261
262         # put the rest of the arguments into the varialbe $e_args
263         while [ "$*" ]; do
264                 for a in "$*"; do
265                         case $1 in
266                                 $b_arg|$file) : ;;
267                                 *) e_args="$e_args "$1""
268                         esac
269                         shift 1
270                 done
271         done
272
273         # with $f_args defined, check for image and do things normally
274         if [ "$f_args" ]; then
275                 [ ! -f "$file" ] && quit 1 "$file does not exist"
276         
277                 if check_img_command $e_args; then
278                         do_this="$e_args"
279                 else
280                         read_config
281                         get_img_command $f_args
282                         check_img_command $do_this
283                         echo "$p couldn't find '$app' in path, using $type command instead"
284                 fi
285         # without $f_args, run the command blindly if it's in $PATH
286         elif check_exe_in_path $e_args; then
287                 do_this="$e_args"
288         else
289                 quit 1 "$p unable to run the following command: $e_args"
290         fi
291
292         exec_img_command $do_this $file
293 }    
294
295 get_img_command() 
296 {
297         case $1 in
298                 *-full|-f|f)    type=full; do_this="$full_cmd" ;;
299                 *-tile|-t|t)    type=tile; do_this="$tile_cmd" ;;
300                 *-center|-c|c)  type=center; do_this="$center_cmd" ;;
301                 *)              type=default; do_this="$default_cmd"
302         esac
303 }
304
305 check_img_command() 
306 {
307         if check_exe_in_path $1; then
308                 do_this="$*"
309                 rc=0
310         elif get_apps; then
311                 get_img_command $*
312                 rc=1
313         else
314                 quit 1 "$p couldn't find a suitable image program. tried the following:\\n
315                 $(for a in $not_found; do echo "    $a\\n"; done)"
316         fi
317
318         if [ "$rc" -gt 0 -a -z "$e_args" ] && bool $read_config; then
319                 echo "$p couldn't find a suitable $type command in $config"
320         fi
321
322     return $rc
323 }
324
325 exec_img_command() 
326 {
327         unset rc
328         command=$*
329
330         if [ "$debug" ]; then
331                 $debug $command
332         else
333                 $command >/dev/null 2>&1; rc=$?
334         fi
335
336         if [ "$rc" -gt 0 ]; then
337                 echo "$p '$command' exited with status $rc"
338                 get_apps
339                 noconfig=1
340                 parse_args ${f_args:-$my_args}
341                 echo "$p using '$command' as $type"
342                 $debug $command >/dev/null 2>&1; rc=$?
343                 [ "$rc" =  0 ] && log_cmd $do_this $file && $refresh_cmd 2>/dev/null
344         else
345                 log_cmd $do_this $file; xrefresh 2>/dev/null
346         fi
347         return $rc
348 }
349
350 log_cmd() 
351 {
352         bool $LOG_LAST_CMD || return 1
353         [ "$debug" ] && return 1
354         echo -e "$prev_cmd\n$*" >$last_cmd_file
355         return $?
356 }
357
358 read_config() 
359 {
360         [ -f $config ] || return 1
361
362         if bool $read_config; then
363                 unset read_config
364         else
365                 read_config=1
366         fi
367
368         . $HOME/.bsetbgrc 2>/dev/null
369         check_no_exec
370
371         full_cmd=$FULL
372         center_cmd=$CENTER
373         tile_cmd=$TILE
374         default_cmd=$CENTER
375         last_cmd_file=${LOGFILE:-$last_cmd_file}
376     
377         bool $LOG_LAST_CMD && prev_cmd=$(tail -n 1 $last_cmd_file 2>/dev/null)    
378 }
379
380 check_no_exec() 
381 {
382         bool $NO_EXEC && 
383         quit 0 "$p no_exec mode. the root window will not be modified."
384 }
385
386 post_command() 
387 {
388         bool $noconfig || read_config
389
390         if [ -n "$POST_COMMAND" -a "$1" = 0 ]; then
391                 if [ -n "$debug" ]; then
392                         $debug "running post_command: $POST_COMMAND $post_args"
393                 else
394                         post_command_output=$($POST_COMMAND $post_args 2>&1); erc=$?
395                         if [ "$erc" -gt 0 ]; then
396                                 echo "$p post-command '$POST_COMMAND $post_args' exited with status $erc"
397                                 [ -n "$post_command_output" ] &&
398                                         echo "$POST_COMMAND $post_args: $post_command_output"
399                         fi
400                 fi
401         fi
402 }
403
404 add_arg() 
405 {
406         [ "$1" ] || return 1
407         if [ "$args" ]; then
408                 args="$args $1"
409         else
410                 args=$1
411         fi
412 }  
413
414 add_post_arg() 
415 {
416         [ -z "$1" ] && return 1
417         if [ "$post_args" ]; then
418                 post_args="$post_args $1"
419         else
420                 post_args=$1
421         fi
422 }
423
424 check_cmd() 
425 {
426         if [ -z "$command" ]; then
427                 command=${2:-$1}; eval ${3:-${2:-$1}}=1
428         elif bool $do_post; then
429                 add_post_arg ${1}
430         elif [ "$command" = do_exec ]; then
431                 do_exec=1               
432         elif [ "$command" != do_bsetroot ]; then
433                 finished=1
434         fi 
435 }
436
437 parse_args() 
438 {
439         case $1 in
440                 -d|*-debug|d)
441                         unset refresh_cmd; debug=echo\ $me\_debug: ;;
442
443                 -p|*-post|p)    
444                         unset finished do_standard do_exec; do_post=1 ;;
445                                 
446                 -c|*-center|c|-t|*-tile*|t|-f|*-full|f)
447                         case $command in
448                                 do_standard|do_generate|do_bsetroot)
449                                         finished=1 ;;
450                                 do_exec)
451                                         if ! bool $got_fcmd; then
452                                                 add_arg $1 args; got_fcmd=1
453                                         else
454                                                 finished=1
455                                         fi ;;
456                                 *)      
457                                         add_arg $1; do_standard=1; command=do_standard
458                         esac ;;         
459                 
460                 -a|*-app|a|-e|*-exec|e)
461                         command=do_exec; check_cmd ;;
462                 
463                 -mod|-gradient|-solid|-display)
464                         check_cmd "do_bsetroot" && add_arg $1 ;;
465
466                 -g|*-generate*|g)
467                         check_cmd $1 "do_generate" ;;
468                 
469                 -v|*-version|v)
470                         [ -z "$command" ] && quit 0 $me $version $copyright ;;
471                 
472                 -h|*-help|h)
473                         [ -z "$command" ] && help_msg ;;
474                 
475                 *)      
476                         bool $finished && return 1              
477
478                         case $1 in -*)
479                                 bool $do_exec || bool $do_bsetroot || bool $do_post || help_msg 1
480                         esac
481                 
482                         if bool $do_standard || bool $do_exec || bool $do_bsetroot || bool $do_generate; then
483                                 add_arg $1
484                         elif bool $do_post; then
485                                 add_post_arg $1
486                         else
487                                 add_arg $1; command=do_standard; finished=1
488                         fi
489         esac
490 }
491
492 [ -z "$*" ] && help_msg 1
493
494 my_args=$*
495
496 for arg in "$@"; do
497         parse_args "$arg"
498         shift 1
499 done
500
501 [ "$debug" ] && echo
502
503 $debug $command $args
504 post_command ${rc:-0}
505
506 quit $rc