1#!/bin/sh
2#
3# Set wallpaper for fluxbox.
4#
5# Copyright (c) 2003-2004 Han Boetes <han@mijncomputer.nl>
6#
7# Permission is hereby granted, free of charge, to any person obtaining
8# a copy of this software and associated documentation files (the
9# "Software"), to deal in the Software without restriction, including
10# without limitation the rights to use, copy, modify, merge, publish,
11# distribute, sublicense, and/or sell copies of the Software, and to
12# permit persons to whom the Software is furnished to do so, subject to
13# the following conditions:
14#
15# The above copyright notice and this permission notice shall be
16# included in all copies or substantial portions of the Software.
17#
18# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
22# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25
26# Portability notes:
27# To guarantee this script works on all platforms that support fluxbox
28# please keep the following restrictions in mind:
29#
30# - don't use if ! command;, use command; if [ $? -ne 0 ];
31# - don't use [ -e file ] use [ -r file ]
32# - don't use $(), use ``
33# - don't use ~, use ${HOME}
34# - don't use id -u or $UID, use whoami
35# - don't use echo -e
36# - getopts won't work on all platforms, but the config-file can
37#   compensate for that.
38# - various software like grep/sed/perl may be not present or not
39#   the version you have. for example grep '\W' only works on gnu-grep.
40#   Keep this in mind, use bare basic defaults.
41# - Do _NOT_ suggest to use #!/bin/bash. Not everybody uses bash.
42
43# TODO purheps: xprop -root _WIN_WORKSPACE
44# _NET_CURRENT_DESKTOP
45
46# The wallpapersetter is selected in this order
47wpsetters="${wpsetters:=Esetroot wmsetbg feh hsetroot chbg display qiv xv xsri xli xsetbg}" # broken icewmbg'
48lastwallpaper="${HOME}/.fluxbox/lastwallpaper"
49
50
51WHOAMI=`whoami`
52[ "$WHOAMI" = root ] && PATH=/bin:/usr/bin:/usr/local/bin
53
54command="`basename \"$0\"`"
55
56
57# Functions
58display_usage() {
59    cat << EOF
60Usage: $command [-u/-U [wallpapersetter]] [-fFcCtTaA] /path/to/wallpaper
61       $command [-u/-U [wallpapersetter]] [-fFcCtTaA] -r/-R /path/to/directory
62       $command [-b/-B fbsetrootoptions]
63       $command [-lhip]
64Use \`\`$command -h'' for a complete help message.
65
66EOF
67}
68
69display_help() {
70    display_usage
71    cat << EOF
72
73Options:
74
75    -u  Use specified wallpapersetter, use no argument to forget.
76
77    -f  Set fullscreen wallpaper (default).
78    -c  Set centered wallpaper.
79    -t  Set tiled wallpaper.
80    -a  Set maximized wallpaper, preserving aspect.
81        ( if your wallpapersetter doesn't support this
82          we fall back to -f )
83
84    -r  set random wallpaper from a directory
85
86    -b  Forward the rest of the arguments to fbsetroot(1).
87        This can be used to set solid, pattern, or gradient backgrounds.
88
89    -F,-C,-T,-A,-U,-B,-R same as lower-case, but without remembering.
90
91    -h  Display this help.
92
93    -l  Set previous wallpaper.
94
95    -i  Information about selected wallpaper command.
96    -d  (deprecated, use -i) Debug info.
97    -p  Tips.
98
99
100Files:
101
102    ~/.fluxbox/lastwallpaper     In this file the wallpaper you set
103                                 will be stored, for the -l option:
104Environment variables:
105    wpsetters   Wallpapersetters to use.
106                example:
107                  wpsetters=feh fbsetbg wallpaper.jpg
108
109    DISPLAY     The display you want to set the wallpaper on.
110                example:
111                  DISPLAY=:0.0 fbsetbg -l
112
113EOF
114}
115
116display_tips() {
117    cat << EOF
118Common tips to use with $command:
119
1201) To replace all occurrences of bsetbg with $command in a file use this
121   command:
122
123   perl -pi -e 's,([^f]|^)bsetbg,$command,' filename
124
1252) If you want to set the wallpaper and you want $command to
126   remember the previous wallpaper put this in your ~/.fluxbox/overlay
127
128   background: none
129
1303) Use $command -i to find out what wallpapersetter $command will be
131   used and what $command thinks about it.
132
133EOF
134}
135
136# some which's have a reliable return code, some don't
137# Lets figure out which which we have.
138if which this_program_does_not_exist-no_really-aA1zZ9 >/dev/null 2>/dev/null; then
139    # can't rely on return value
140    find_it() {
141        file=`which $1 2> /dev/null`
142        if [ -x "$file" ]; then
143            if [ $# -gt 1 ]; then
144                shift
145                $*
146            fi
147            return 0
148        else
149            return 1
150        fi
151    }
152else
153    # can rely on return value
154    find_it() {
155        which $1 > /dev/null 2>&1 && shift && $*
156    }
157fi
158
159message() {
160
161    # This Terminal detection method is inaccurate. Looking for a
162    # replacement.
163
164    # echo if we have terminal output, otherwise pop up a window
165    # if [ -t 1 ]; then
166    #     echo "$command: $@"
167    # else
168    extra_args="-default okay"
169        if find_it gxmessage; then
170            gxmessage $extra_args -center "$command: $@" &
171        else
172            xmessage $extra_args -center "$command: $@" &
173        fi
174    # fi
175}
176
177remembercommand() {
178    grep -vs "|${DISPLAY}$" ${lastwallpaper} > ${lastwallpaper}.tmp
179    mv -f ${lastwallpaper}.tmp ${lastwallpaper}
180    if [ "$option" = fbsetroot ]; then
181        echo $option"|$wallpaper|$style|"$DISPLAY >> $lastwallpaper
182        return
183    fi
184    # Make dir/../../path/file.jpg work
185    case $wallpaper in
186        # no spaces allowed between the varname and '|'
187        /*) echo $option $option2"|$wallpaper|$style|"$DISPLAY >> $lastwallpaper ;;
188        *)  echo $option $option2"|$PWD/$wallpaper|$style|"$DISPLAY >> $lastwallpaper ;;
189    esac
190}
191
192debugfbsetbg() {
193    echo
194    echo $debugstory
195    echo $sad_esetroot_story
196    exit 0
197}
198
199use_fbsetroot() {
200
201    fbsetroot $wallpaper
202    if [ ! "$remember" = false ]; then
203        remembercommand
204    fi
205    exit 0
206}
207
208
209if [ $# -eq 0 ]; then
210    message "no options given"
211    display_usage
212    exit 1
213fi
214
215# create directory and last wallpaper file
216if [ ! -d  "$HOME/.fluxbox" ]; then
217	mkdir "$HOME/.fluxbox"
218    touch ${lastwallpaper}
219fi
220
221unset debug setterfromcommandline
222# Parse command-line options
223while [ $# -gt 0 ]; do
224    case "$1" in
225        -u)
226            if find_it "$2"; then
227                grep -v wpsetters $lastwallpaper > ${lastwallpaper}.tmp
228                echo "wpsetters $2" >> ${lastwallpaper}.tmp
229                mv ${lastwallpaper}.tmp $lastwallpaper
230                WPSETTER=$2
231                setterfromcommandline=true
232            elif [ -z "$2" ]; then
233                grep -v wpsetters $lastwallpaper > ${lastwallpaper}.tmp
234                mv ${lastwallpaper}.tmp $lastwallpaper
235                message "wpsetter removed from historyfile"
236                exit 0
237            else
238                message "Couldn't find \"$2\" for wallpapersetter"
239                display_usage
240                exit 1
241            fi
242            shift 2 ;;
243        -U)
244            if find_it "$2"; then
245                WPSETTER=$2
246                setterfromcommandline=true
247            else
248                message "Couldn't find \"$2\" for wallpapersetter"
249                display_usage
250                exit 1
251            fi
252            shift 2 ;;
253        -d|-i) debug=true
254            break ;;
255        -a) option='$aspect'
256            shift ;;
257        -f) option='$full'
258            shift ;;
259        -c) option='$center'
260            shift ;;
261        -t) option='$tile'
262            shift ;;
263        -A) option='$aspect'
264            remember=false
265            shift ;;
266        -F) option='$full'
267            remember=false
268            shift ;;
269        -C) option='$center'
270            remember=false
271            shift ;;
272        -T) option='$tile'
273            remember=false
274            shift ;;
275        -b) option=fbsetroot
276            shift
277            wallpaper=$*
278            break ;;
279        -B) option=fbsetroot
280            shift
281            wallpaper=$*
282            remember=false
283            break ;;
284        -r) option2=$option
285            option=random
286            wallpaper=$2 # in this case it's a dir
287            break ;;
288        -R) option2=$option
289            option=random
290            wallpaper=$2 # in this case it's a dir
291            remember=false
292            break ;;
293        -l)
294            if [ -r "$lastwallpaper" ]; then
295                option=`grep "|${DISPLAY}$"    $lastwallpaper|cut -d'|' -f1`
296                option2=`echo $option|cut -d' ' -f2`
297                option=`echo $option|cut -d' ' -f1`
298                wallpaper=`grep "|${DISPLAY}$" $lastwallpaper|cut -d'|' -f2`
299                if [ -z "$wallpaper" ]; then
300                    option=`grep "|${DISPLAY}.0$"    $lastwallpaper|cut -d'|' -f1`
301                    option2=`echo $option|cut -d' ' -f2`
302                    option=`echo $option|cut -d' ' -f1`
303                    wallpaper=`grep "|${DISPLAY}.0$" $lastwallpaper|cut -d'|' -f2`
304                fi
305                if [ -z "$wallpaper" ]; then
306                    message "No previous wallpaper recorded for display ${DISPLAY}"
307                    exit 1
308                fi
309            else
310                message "No previous wallpaper recorded for display ${DISPLAY}"
311                exit 1
312            fi
313            remember=false
314            break ;;
315        -z)
316            if [ -r "$lastwallpaper" ]; then
317                option=`grep "|${DISPLAY}$"    $lastwallpaper|cut -d'|' -f1`
318                option2=`echo $option|cut -d' ' -f2`
319                option=`echo $option|cut -d' ' -f1`
320                style=`grep "|${DISPLAY}$" $lastwallpaper|cut -d'|' -f3`
321                wallpaper=`grep "|${DISPLAY}$" $lastwallpaper|cut -d'|' -f2`
322                if [ -z "$wallpaper" ]; then
323                    option=`grep "|${DISPLAY}.0$"    $lastwallpaper|cut -d'|' -f1`
324                    option2=`echo $option|cut -d' ' -f2`
325                    option=`echo $option|cut -d' ' -f1`
326                    style=`grep "|${DISPLAY}.0$" $lastwallpaper|cut -d'|' -f3`
327                    wallpaper=`grep "|${DISPLAY}.0$" $lastwallpaper|cut -d'|' -f2`
328                fi
329            fi
330            if [ "$style" != "style" -a -n "$wallpaper" ]; then
331                remember=false
332                break
333            fi
334            ignore_missing_wallpaper=true
335            style="style"
336            shift ;;
337        -Z)
338            style="style"
339            shift ;;
340        -p) display_tips ; exit 0 ;;
341        -h) display_help ; exit 0 ;;
342        --)
343            message "$command doesn't recognize -- gnu-longopts."
344            message 'Use $command -h for a help message.'
345            display_usage
346            exit 1 ;;
347        -*)
348            message "unrecognized option "\`"$1'"
349            display_usage
350            exit 1 ;;
351        *)
352            if [ "$option" = random ]; then
353                option='$aspect'
354            elif [ ! -r "$1" ]; then
355                message "$1 isn't an existing wallpaper or a valid option."
356                display_usage
357                exit 1
358            elif [ -z "$1" ]; then
359                message 'No wallpaper to set'
360                display_usage
361                exit 1
362            else
363                wallpaper=$1
364                break
365            fi ;;
366    esac
367done
368
369if [ "$option" = "fbsetroot" ]; then
370    use_fbsetroot
371fi
372
373# Find the default wallpapersetter
374if [ "$setterfromcommandline" != true ]; then
375    if [ -r "$lastwallpaper" ]; then
376        wpsetters="`awk '/wpsetters/ {print $2}' $lastwallpaper` $wpsetters"
377    fi
378    for wpsetter in $wpsetters; do
379        if find_it $wpsetter; then
380            if [ ! "$wpsetter" = Esetroot ]; then
381                WPSETTER=$wpsetter
382                break
383            elif ldd `which Esetroot`|grep libImlib 2>&1 > /dev/null; then
384                WPSETTER=$wpsetter
385                break
386            else
387                sad_esetroot_story="I also found Esetroot, but it doesn't have support for setting wallpapers. You need to install libimlib2 and rebuild Eterm to get it working."
388            fi
389        fi
390    done
391fi
392
393standardrant=\
394"$WPSETTER doesn't set the wallpaper properly. Transparency for fluxbox and
395apps like aterm and xchat won't work right with it. Consider installing
396feh, wmsetbg (from windowmaker) or Esetroot (from Eterm) and I'll use
397them instead."
398
399standardok=\
400"$WPSETTER is a nice wallpapersetter. You won't have any problems."
401
402case $WPSETTER in
403    chbg)
404        full='-once -mode maximize'
405        tile='-once -mode tile'
406        center='-once -mode center'
407        aspect='-once -mode smart -max_grow 100 -max_size 100'
408        debugstory="chbg supports all features but it doesn't report errors. I reported this bug to the chbg developers."
409        ;;
410    xsri)
411        full='--center-x --center-y --scale-width=100 --scale-height=100'
412        tile='--tile'
413        center='--center-x --center-y --color=black'
414        aspect='--center-x --center-y --scale-width=100 --scale-height=100 --keep-aspect --color=black'
415        debugstory=$standardok
416        ;;
417    display)
418        full="`xwininfo -root 2> /dev/null|grep geom` -window root"
419        tile='-window root'
420        center='-backdrop -window root'
421        aspect=$full
422        debugstory=$standardrant
423        ;;
424    Esetroot)
425        full='-scale'
426        tile=''
427        center='-c'
428        aspect='-fit'
429        debugstory=$standardok
430        ;;
431    wmsetbg)
432        full='-s -S'
433        tile='-t'
434        center='-b black -e'
435        aspect='-b black -a -S'
436        debugstory=$standardok
437        ;;
438    xsetbg)
439        tile='-border black'
440        center='-center -border black'
441        aspect='-fullscreen -border black'
442        full=$aspect #broken
443        debugstory="xsetbg is actually xli. The fillscreen option (-f) is broken, defaults to (-a). $standardrant"
444        ;;
445    xli)
446        tile='-onroot -quiet -border black'
447        center='-center -onroot -quiet -border black'
448        aspect='-fullscreen -onroot -quiet -border black'
449        full=$aspect #broken
450        debugstory="The fillscreen option (-f) is broken, defaults to (-a). $standardrant"
451        ;;
452    qiv)
453        full='--root_s'
454        tile='--root_t'
455        center='--root'
456        aspect='-m --root'
457        debugstory=$standardrant
458        ;;
459    xv)
460        full='-max -smooth -root -quit'
461        tile='-root -quit'
462        center='-rmode 5 -root -quit'
463        aspect='-maxpect -smooth -root -quit'
464        debugstory=$standardrant
465        ;;
466    feh)
467        full='--bg-scale'
468        tile='--bg-tile'
469        center='--bg-center'
470        aspect="--bg-fill"
471        debugstory=$standardok
472        ;;
473    hsetroot)
474        full='-fill'
475        tile='-tile'
476        center='-center'
477        aspect='-full'
478        debugstory=$standardok
479        ;;
480    icewmbg)
481        tile='-s'
482        full=$tile
483        center=$tile
484        aspect=$tile
485        debugstory="icewmbg does support transparency, but only tiling. And I noticed odd
486errormessages with aterm. Don't use it unless you have to."
487        ;;
488    '')
489        message \
490"I can't find an app to set the wallpaper with. You can install one in
491many many ways but I will give you some simple advice: install Eterm and
492you're set. Eterm provides Esetroot and thats a great wallpaper setter. I
493recommend you install the package provided by your distro."
494        exit 1
495        ;;
496esac
497
498if [ "$debug" = true ]; then
499    debugfbsetbg
500    exit 0
501fi
502
503option=${option:='$full'}
504option2=${option2:='$full'}
505
506
507if [ -z "$DISPLAY" ]; then
508    message "You are not connected to an X session\nPerhaps you should set the DISPLAY environment variable?"
509    exit 1
510fi
511
512
513# random wallpaper code
514if [ "$option" = random ]; then
515    # Lets make one thing clear...
516    wallpaperdir="$wallpaper"
517    if [ -z "$wallpaperdir" ]; then
518        message "No random wallpaper directory specified."
519        exit 1
520    fi
521    if [ -d "$wallpaperdir" ]; then
522        number_of_wallpapers=`ls "$wallpaperdir"|wc -l`
523        if find_it random_number; then
524            randomnumber=`random_number`
525        # some shells don't support $RANDOM
526        elif [ -z "$RANDOM" ]; then
527            if [ -r /dev/urandom ]; then
528                randomnumber=`hexdump -n 2 -e '/2 "%u"' /dev/urandom`
529            else
530                randomnumber=`(echo $$; ps; w; date) 2>&1 | cksum | cut -f1 -d' '`
531            fi
532        else
533            randomnumber="$RANDOM"
534        fi
535        wallpapernumber=`expr $randomnumber % $number_of_wallpapers + 1`
536        #remember previous wallpaper
537        if [ ! "$remember" = false ]; then
538            remembercommand
539        fi
540        remember=false
541        #set -x
542        wallpaper="$wallpaperdir/`ls \"$wallpaperdir\"|sed -n ${wallpapernumber}p`"
543        option=$option2 # have to choose something...
544    else
545        message "Invalid random wallpaper directory specified."
546        exit 1
547    fi
548fi
549
550
551if [ ! -r "$wallpaper" ]; then
552	if [ "$ignore_missing_wallpaper" = "true" ]; then
553		exit 0
554	fi
555    message "Can't find wallpaper $wallpaper"
556    exit 1
557fi
558
559
560$WPSETTER `eval echo $option` "$wallpaper"
561if [ $? -ne 0 ]; then
562    message "Something went wrong while setting the wallpaper.
563Run '$WPSETTER "`eval echo $option` $wallpaper"' from an xterm to find out what."
564    exit 1
565fi
566
567
568#remember previous wallpaper
569if [ ! "$remember" = false ]; then
570    remembercommand
571fi
572