You are not logged in.
Is the 250 image limit and no sub-folders going to be a fixed thing or is it all up in the air for future development?
I mean I could copy it to ~/bin/xwall > /bin/xwalla for my /aircraft folder:
/media/5/Wallpapers/aircraft/
YUP! That works
Notice the
xwalla |
in the header.
Debian 12 Beardog, SoxDog and still a Conky 1.9er
Offline
@Sector11 : afaik the current name would be xwwall (so double w) since it's used in X and in wayland...
Working well here too on MX (Debian12-based) and Devuan. Actually had a similar issue as @johnraff, but on my 1920x1080 screen the main window was too wide ... but this was solved quickly by changing the main_gui width in line 395 to width="'$((MW-50))'">
Offline
Is the 250 image limit and no sub-folders going to be a fixed thing or is it all up in the air for future development?
This post near the top explains the limit: https://forums.bunsenlabs.org/viewtopic … 43#p140143
cap the image limit at 100. This could go higher, haven't actually tested the limit but I do know if '$TEMP/buttons' grows too big we get Argument list too long error and it crashes the program without warning. A _splash is popped notifying the user of the 100 limit and the program carries on. I *think* the limit is based on bytes, so it isn't so easy to calculate. Maybe I can count the bytes in '$TEMP/buttons' and cut off at some conservative level. The limit is around 2MB, on my 64 bit x86 system but this may (IDK) vary across arches and endianess. It's calculated by
getconf ARGMAX
The error I was getting:
/usr/bin/gtk3dialog - Argument list too long
/usr/bin/rm - Argument list too long
The program was crashing at around 340 to 350 images for me, ok with 300 so I was a bit conservative and opted for 250.
For use of apostrophe it needs to be escaped, eg:
export MAINGUI='<window icon-name="background" title="xwall'\''s Background Choice">
I've designed the program to be called by any name you like and configs, temp files whatever will all be saved under dirs of that name.
And, whatever you called it you can replace nitrogen --restore
with xwalla --restore
in your autostart.
I'll be writing up a manpage soon and that will explain all the intricacies in the program.
Love your aircraft wallpapers, and what I see is barely the tip of the iceberg
#!/bin/sh
echo '#include <stdio.h>\nvoid main() { printf("Hi, bunsenlabs\\n"); return; }' > bunsen.c
gcc bunsen.c -o bunsen
./bunsen
Offline
@Sector11 : afaik the current name would be xwwall (so double w) since it's used in X and in wayland...
Working well here too on MX (Debian12-based) and Devuan. Actually had a similar issue as @johnraff, but on my 1920x1080 screen the main window was too wide ... but this was solved quickly by changing the main_gui width in line 395 to width="'$((MW-50))'">
Thanks for testing @ceeslans.
Yes that <hbox> calculation does need refining. I have to find the 'sweet spot' where no additions/subtractions are needed and go from there. I'm developing on 1920x1080 but I have a feeling, going by the feedback that 1366x768 will be sweet. Fortunately, my old HP laptop has that so I'll fire it up and see if I'm right!
BTW, nice scrot
EDIT0: ah the inset, yes those darker bars I should be able to fix with CSS. Thanks.
EDIT1: the following patch fixes it in main_gui
--- xwwall 2024-12-29 08:24:38.499190971 +1000
+++ bin/xwwall 2024-12-29 08:19:48.957288791 +1000
@@ -119,6 +119,9 @@
border-radius: 10px;
padding: 2px;
}
+#sep {
+ background: rgba(0,0,0,0.0);
+}
' > "$TEMP/win.css"
@@ -405,9 +408,9 @@
<action>exit:PREFS</action>
</button>
</hbox>
- <hseparator space-expand="true" space-fill="true"></hseparator>
+ <hseparator space-expand="true" space-fill="true" name="sep"></hseparator>
<text label="Confirmation is required when finished."></text>
- <hseparator space-expand="true" space-fill="true"></hseparator>
+ <hseparator space-expand="true" space-fill="true" name="sep"></hseparator>
<hbox space-expand="false" space-fill="false">
<button>
<label>Cancel</label>
Last edited by micko01 (2024-12-28 22:29:10)
#!/bin/sh
echo '#include <stdio.h>\nvoid main() { printf("Hi, bunsenlabs\\n"); return; }' > bunsen.c
gcc bunsen.c -o bunsen
./bunsen
Offline
OK Understand about the "limit" totally missed that.
Story of my life always late for the party.
I called it xwall because in the code I saw in post 16 of this thread.
set_wall() {
echo setting $1
WALL=''
if [[ -n "$WAYLAND_DISPLAY" ]];then
if [[ -f "$HOME/.config/bunsen/wwall.conf" ]];then
. $HOME/.config/bunsen/wwall.conf
OLDWALL=$WALL
fi
else
if [[ -f "$HOME/.config/bunsen/xwall.conf" ]];then
. $HOME/.config/bunsen/xwall.conf
OLDWALL=$WALL
fi
fi
wall=${1##*/}
See the xwall.conf
Since I'm using it in X 'xwall' seemed appropriate for testing purposes.
I have way to many walls anyway, this might encourage me to cut back.
Debian 12 Beardog, SoxDog and still a Conky 1.9er
Offline
Man page (in rst
format for readability)
xwwall
#####
######
Xwwall
######
:Copyright: GPLv2+
:Manual section: 1
SYNOPSIS
========
| **xwwall** [options]
DESCRIPTION
===========
**xwwall** is a graphical wallpaper setter for the X Window System
often known as **X11** and **Wayland** desktops for Linus and other
\*nix distributions. It should run in light weight desktop environments
like Openbox, fluxbox, JWM for X11 and Labwc, Sway and others for
Wayland. It supports up to 6 monitors. It is a shell script written
in **bash**.
It requires **Gtk3dialog** for the graphical user interface which is
a gtk+-3.0 based UI program that describes dialog boxes from a shell
script.
In X11 it utilises **feh** as the engine to set the wallpaper and
**xrandr** to get screen dimensions and placement of monitors.
In Wayland it uses **swaybg** to set wallpapers and **wlr-randr** for
screen dimensions and placement.
OPTIONS
=======
**xwwall** can be invoked with the following options.
-h | --help
show help and exit.
-v | --version
print version and exit.
--restore
restore backgrounds at session start.
USAGE
========
Normally, **xwwall** is started from a menu entry without any options
although you could start it from a keyboard shortcut.
Main GUI
--------
The first thing you may see is a splash window warning you if you
have too many wallpapers and cuts off at a 250 limit and then a
window opens showing your wallpapers. Just select one and it will
open in a window; select the image by pressing it or **no** to reject.
You can also select if you want the image to stretch, center, tile or fit
your screen. If you do select **no** the program goes back to the main
window.
If you have more than 1 monitor the program cycles through those so you can
choose different back grounds for each of them.
Once done a confirmation window opens and you can either press **yes** or
**no**; **yes** sets your wallpaper(s) while **no** restarts the program
so you can try again.
You can exit the program safely at any stage via **Cancel**, **No** or
the **X** (close) button of your window manager or compositor.
Preferences
-----------
There is a **Preferences** button in the bottom left of the main window
to set the following:
1. Background directory - any directory where you have read access
2. Splash checkbox screen for multiple monitors only:
checked to show, unchecked to hide
3. Slight adjustments to width of the main interface
4. A background color for centered or transparent images
Startup
-------
You can start the program to restore your background choices from
your **autostart** or similar file with the following
``xwwall --restore``
Consult your window manager or compositor documentation for the
correct procedure.
SEE ALSO
========
gtk3dialog(1), feh(1), swaybg(1)
Test with
~$ rst2man xwwall.1.rst xwwall.1
~$ man ./xwwall.1
Requires docutils to convert, but no need to as I'll have it converted when uploaded.
#!/bin/sh
echo '#include <stdio.h>\nvoid main() { printf("Hi, bunsenlabs\\n"); return; }' > bunsen.c
gcc bunsen.c -o bunsen
./bunsen
Offline
So, the next version
fixed the dark areas at bottom for main_gui
added a spinbutton to Preferences to adjust the width of main_gui - there's no solid way to do it programatically with gtk themes differences having a bearing
man page in previous post
Added Bunsenlabs*
to wayland desktop environments (doesn't affect X)
#!/bin/bash
export V=0.1.0
export GTK3DIALOG
[[ -z "$GTK3DIALOG" ]] && GTK3DIALOG=gtk3dialog
export BGDIR="${BGDIR:-$HOME/Pictures/wallpapers}"
export PROG=${0##*\/}
export TEMP=/tmp/$PROG
#export TEMP=$HOME/tmp/$PROG # for testing
rm -rf "$TEMP" # incase of a crash because of "Argument list too long"
mkdir -p "$TEMP"
export CONFDIR="${XDG_CONFIG_HOME:-$HOME/.config}/$PROG"
mkdir -p "$CONFDIR"
export CONF="$CONFDIR/$PROG.conf"
if [[ ! -f "$CONF" ]];then
echo "BGDIR=$BGDIR" > "$CONF"
fi
. "$CONF"
case "$1" in
--restore)
if [[ -f "$CONFDIR/cmd" && -n "$WAYLAND_DISPLAY" ]]; then
. "$CONFDIR/cmd" && exit 0
elif [[ -x "$HOME/.fehbg" ]]; then
exec "$HOME/.fehbg"
else
exit 1
fi
;;
-*v|-*version)
echo -e "\t$PROG $V\n\t\tGPL-2.0+ licence\n"
exit 0
;;
-*h|-*help)
echo -e "\t$PROG -h|--help\n\t\tshow this help and exit.\n"
echo -e "\t$PROG -v|--version\n\t\tprint version and exit.\n"
echo -e "\t$PROG --restore\n\t\trestore backgrounds at session start.\n"
echo -e "\ttry \"man $PROG\" for more information."
exit 0
;;
esac
# sort out the monitors and positions
if [[ -n "$WAYLAND_DISPLAY" ]]; then
b=0
c=1
MON=''
pos=''
while read -r l m n o p q
do
case "${l:0:3}" in
Pos|Mak|Mod|Ser|Phy|Ena|Tra|Sca|Ada)
if [[ "${l:0:3}" == 'Pos' ]];then
export pos
pos=${m%,*}; echo POS=$pos >> "$TEMP/Wmonitor-$((c-1))"
else
continue
fi
;;
[a-zA-Z][a-zA-Z][a-zA-Z0-9])MON=$l;;
esac
case "$q" in
current*)res=$l;;
*)continue;;
esac
resX=${res%x*}
resY=${res#*x}
echo OUTPUT=$MON >> "$TEMP/Wmonitor-$c"
echo X=$resX >> "$TEMP/Wmonitor-$c"
echo Y=$resY >> "$TEMP/Wmonitor-$c"
c=$((c+1))
b=$((b+1))
echo $b > $TEMP/number
done <<<$(wlr-randr)
export POPT='edge="top" dist="100"'
export SOPT='layer="top"'
export CONFILE="$CONFDIR/Wconf"
else
k=0
n=1
MON=''
while read -r a b c d z
do
echo $a
[[ "${a}" == 'Monitors:' ]] && continue
MON=$d
resX=${c/\/[0-9]*/}
resY=${c#*x}
resY=${resY/\/[0-9]*/}
pos=${c#*+}
pos=${pos/+/ }
[[ "${pos%\ *}" == '0' ]] && n=0 # 'xx' position
pos=${pos%\ *}
echo Xmonitor-$n
echo $MON
echo $resX
echo $resY
echo $pos
echo OUTPUT=$MON >> "$TEMP/Xmonitor-$n"
echo X=$resX >> "$TEMP/Xmonitor-$n"
echo Y=$resY >> "$TEMP/Xmonitor-$n"
echo POS=$pos >> "$TEMP/Xmonitor-$n"
n=$((n+1))
k=$((k+1))
echo $k > $TEMP/number
done <<<$(xrandr --listmonitors)
export POPT='decorated="false"'
export SOPT=$POPT
export CONFILE="$CONFDIR/Xconf"
fi
#CSS for splash
echo 'window#splash {
background: rgba(0,0,0,0.0);
}
#splash {
background: #5E003E;
color: #ffffff;
border-radius: 10px;
padding: 2px;
}
#sep {
background: rgba(0,0,0,0.0);
}
' > "$TEMP/win.css"
# get the primary output
e=0
if [[ -n "$WAYLAND_DISPLAY" ]]; then
for i in $TEMP/Wmonitor*
do
# $i is sourced
. "$i"
[[ "$POS" == '0' ]] && echo "$OUTPUT = primary" && cp $i $TEMP/ww0
[[ "$POS" == "$X" ]] && echo "$OUTPUT = secondary" && cp $i $TEMP/ww1
[[ $POS -gt $X ]] && echo "$OUTPUT = extra" && cp $i $TEMP/ww2$e && e=$((e+1))
done
rm $TEMP/Wmonitor* # finished with these
read -r NUM < "$TEMP/number"
export NUM
echo $NUM outputs
. $TEMP/ww0
export W=$((X / 9))
export H=$((Y / 10))
export MW=$((X / 2))
export MH=$((Y * 2 / 3))
else
for f in $TEMP/Xmonitor*
do
# $f is sourced
. "$f"
[[ "$POS" == '0' ]] && echo "$OUTPUT = primary" && cp $f $TEMP/xx0
[[ "$POS" == "$X" ]] && echo "$OUTPUT = secondary" && cp $f $TEMP/xx1
[[ $POS -gt $X ]] && echo "$OUTPUT = extra" && cp $i $TEMP/xx2$e && e=$((e+1))
done
rm $TEMP/Xmonitor* # finished with these
export NUM
read NUM < $TEMP/number
echo $NUM outputs
. $TEMP/xx0
export W=$((X / 9))
export H=$((Y / 10))
export MW=$((X / 2))
export MH=$((Y * 2 / 3))
fi
######################## functions ##############################
# splash window
_splash() {
[[ -z "$1" ]] && return
E_VAL=SPLASH
CR="--geometry=+$((X/2-180))+150"
case $2 in
0)[[ "$SPLASH" == 'false' ]] && return
DIS='
<button tooltip-text="Do not show again">
<input file icon="window-close"></input>
<label>Dismiss</label>
<action>if grep -q "SPLASH" '$CONF'; then sed -i "s/^SPLASH.*$/SPLASH=false/" '$CONF';else echo SPLASH=false >> '$CONF'; fi</action>
<action>exit:DISMISS</action>
</button>'
E_VAL=Monitors
;;
2)E_VAL=Limit;;
3)ACT='<action>main_gui &</action><action>exit:OK</action>';;
5)ACT='<action>kill '$PID'</action><action>exit:abort</action>';KILL='<action>kill '$PID'</action>';;
6)E_VAL=Wait;CR=-c;;
*)CR=-c;ACT='<action>exit:OK</action>';;
esac
IVAL=4
re='^[0-9]'
[[ $3 =~ $re ]] && IVAL=$3
if [[ -n "$WAYLAND_DISPLAY" ]]; then
[[ "$3" == 'b' ]] && POPT='edge="bottom" dist="200"'
else
[[ "$3" == 'b' ]] && CR="--geometry=+$((X/2-240))+$((Y-300))"
fi
TIMER='<timer interval="'$IVAL'" visible="false">'$KILL'<action>exit:'$E_VAL'</action></timer>'
echo '<window type-hint="6" icon-name="gtk-info" '$POPT' name="splash" width-request="360">
<vbox name="splash">
<hbox name="splash">
<hbox space-expand="false" space-fill="false">
<pixmap name="splash"><width>42</width><input file icon="gtk-info"></input></pixmap>
'$TIMER'
</hbox>
<hbox space-expand="true" space-fill="true">
<text name="splash">
<label>'"$1"'</label>
</text>
</hbox>
</hbox>
<hbox name="splash">
'$DIS'
<button>
<label>OK</label>
<input file icon="gtk-ok"></input>
'$ACT'
</button>
</hbox>
</vbox>
</window>' | $GTK3DIALOG -s "$CR" --styles=$TEMP/win.css
[[ "$2" == '1' ]] && exit $2
}; export -f _splash
# sort selections
_selections() {
echo '<hbox>' > $TEMP/ret
cat $TEMP/selected | while read -r sel
do
echo ' <pixmap tooltip-text="'${sel##*\/}'">
<height>120</height>
<input file>'$sel'</input>
</pixmap>' >> $TEMP/ret
done
echo '</hbox>' >> $TEMP/ret
}; export -f _selections
# set each background
confirm_gui() {
_selections
PIX=$(cat $TEMP/ret)
export CON='<window icon-name="background" title="Confirm selection">
<vbox>
<hbox space-expand="true" space-fill="true">
<text><label>Please confirm that the image below is correct.</label></text>
</hbox>
<hbox space-expand="true" space-fill="true">
'$PIX'
</hbox>
<hbox>
<button yes></button>
<button no></button>
<button tooltip-text="If unsatisfied with your choice try again.">
<input file icon="refresh"></input>
<label>Refresh</label>
<action>exit:REFRESH</action>
</button>
</hbox>
</vbox>
</window>'
eval "$($GTK3DIALOG -p CON -c --styles=$TEMP/win.css)"
case $EXIT in
Yes)_build_command;;
REFRESH)rm -f $TEMP/increment $TEMP/selected $TEMP/[XW]set rm -f $TEMP/ret
main_gui &;;
*)return 1;;
esac
}; export -f confirm_gui
# populate the main GUI
button_gui() {
c=0
shopt -s globstar
for WALL in "$BGDIR"/*{,/**}
do
file -b --mime-type "$WALL" | grep -q 'image' || continue # test mime
# we take advantage of bash math here
# for a nicish GUI width *must* be consistent
i=$((c/4))
V=' <button image-position="top" tooltip-text="'"${WALL##*/}"'">
<variable>BG'$c'</variable>
<input file>'"\"$WALL\""'</input>
<height>'$W'</height>
<width>'$W'</width>
<action>_output '"\"$WALL\""' &</action>
<action>exit:BG'$c'</action>
</button>'
echo "$V" >> $TEMP/buttonsx$i
c=$((c+1))
export TOT=$((c+1))
if [[ $c -ge 250 ]];then
export TOT=250
_splash "Warning: Limit of 250 images" 2 2 &
break
fi
done
shopt -u globstar
for j in $(ls "$TEMP" | grep 'buttonsx[0-9]*')
do echo " <hbox>
$(cat "$TEMP/$j")
</hbox>" >> $TEMP/buttons
done
}
# sub GUI
sub_gui() {
[[ -z "$COLOR" ]] && COLOR=999999
if [[ -n "$WAYLAND_DISPLAY" ]]; then
CCOL="-c $COLOR"
SS='Wset'
ACTION='<action>echo -e " -o $OUT -m $MODE '$CCOL' \\ \n\t -i '\'$1\'' \\" >> '$TEMP/$SS'</action>'
else
# feh modes: --bg-scale, --bg-center[ --image-bg=$color], --bg-fill, --bg-max[ --image-bg=$color], --bg-tile
XCOL=" --image-bg=#${COLOR}"
SS='Xwset'
ACTION='<action>if [[ "$MODE" == "stretch" || "$MODE" == "fit" ]];then MODE=fill;fi; echo -e " --bg-$MODE '${XCOL}' \\ \n\t'\'$1\'' \\" >> '$TEMP/$SS'</action>'
fi
[[ -r "$TEMP/increment" ]] || echo -n 1 > $TEMP/increment
INC=$(cat $TEMP/increment)
# set default for entry
case $INC in
1)DEFAULT=$(sed '1s/item/default/g' < $TEMP/OP | sed -n 1p) ;;
2)DEFAULT=$(sed '2s/item/default/g' < $TEMP/OP | sed -n 2p) ;;
3)DEFAULT=$(sed '3s/item/default/g' < $TEMP/OP | sed -n 3p) ;;
4)DEFAULT=$(sed '4s/item/default/g' < $TEMP/OP | sed -n 4p) ;;
5)DEFAULT=$(sed '5s/item/default/g' < $TEMP/OP | sed -n 5p) ;;
6)DEFAULT=$(sed '6s/item/default/g' < $TEMP/OP | sed -n 6p) ;;
esac
if [[ $INC -gt $NUM ]]; then
_splash "You are at your monitor limit. Confirm?" 4
else
export SUBGUI='<window icon-name="background" title="Selection">
<vbox>
<hbox space-expand="true" space-fill="true">
<text><label>Choose Mode and press the image</label></text>
</hbox>
<hbox space-expand="true" space-fill="false">
<text use-markup="true"><label>"<big>Mode:</big>"</label></text>
<comboboxtext>
<variable>MODE</variable>
<item>stretch</item>
<item>center</item>
<item>tile</item>
<item>fit</item>
</comboboxtext>
</hbox>
<hbox space-expand="true" space-fill="false">
<text use-markup="true"><label>"<big>Output:</big>"</label></text>
<entry>
<variable>OUT</variable>
'$DEFAULT'
</entry>
</hbox>
<hbox space-expand="true" space-fill="true">
<button tooltip-text="'"${1##*/}"$'\n''Press image to confirm or No to reject and confinue.">
<variable>CBG</variable>
<input file>'$1'</input>
<width>320</width>
<action>echo -n '$((INC+1))' > $TEMP/increment</action>
<action>if grep -q $OUT '$TEMP'/'$SS' >/dev/null 2>&1; then _splash "Only 1 wall per monitor. Maybe you have reached the monitor limit?." 3;fi;</action>
<action>echo '$1' >> '$TEMP'/selected</action>
'$ACTION'
<action>sed -i "s% $%%g" '$TEMP/$SS'</action>
<action>if [[ '$INC' -ge '$NUM' ]]; then confirm_gui;fi &</action>
<action>if [[ '$INC' -lt '$NUM' ]]; then main_gui;fi &</action>
<action>exit:CBG</action>
</button>
</hbox>
<hbox>
<text label="Output: '$INC'"></text>
<button>
<label>No</label>
<input file icon="gtk-no"></input>
<action>main_gui &</action>
<action>exit:NO</action>
</button>
</hbox>
</vbox>
</window>'
$GTK3DIALOG -p SUBGUI -c --styles=$TEMP/win.css
fi
}; export -f sub_gui
# populate the main GUI
main_gui() {
[[ -z "$SWIDTH" ]] && SWIDTH=0
[[ -r "$TEMP/main_gui.xml" ]] && _splash "Please wait ..." 6 2 &
BUTTONS=$(cat $TEMP/buttons)
export MAINGUI='<window icon-name="background" title="Background Choice">
<vbox>
<hbox space-expand="true" space-fill="true">
<text use-markup="true" tooltip-text="'$TOT' images"><label>"<b>Select an image for your wallpaper by pressing the image.</b>"</label></text>
</hbox>
<hseparator space-expand="true" space-fill="true"></hseparator>
<hbox>
<vbox scrollable="true" height="'$MH'" width="'$((MW+SWIDTH))'">
'$BUTTONS'
</vbox>
</hbox>
<hbox space-expand="true" space-fill="true">
<hbox space-expand="false" space-fill="false">
<button tooltip-text="Preferences">
<label>Preferences</label>
<width>16</width>
<input file icon="preferences-desktop-wallpaper"></input>
<action>exit:PREFS</action>
</button>
</hbox>
<hseparator space-expand="true" space-fill="true" name="sep"></hseparator>
<text label="Confirmation is required when finished."></text>
<hseparator space-expand="true" space-fill="true" name="sep"></hseparator>
<hbox space-expand="false" space-fill="false">
<button>
<label>Cancel</label>
<input file icon="gtk-cancel"></input>
<action>kill '$PID'</action>
<action>exit:abort</action>
</button>
</hbox>
</hbox>
</vbox>
</window>'
[[ -r "$TEMP/main_gui.xml" ]] || printf "%s\n" "$MAINGUI" > $TEMP/main_gui.xml
eval "$($GTK3DIALOG -f $TEMP/main_gui.xml -c --styles=$TEMP/win.css)"
if [[ "$EXIT" == "PREFS" ]]; then
_pref
fi
}; export -f main_gui
# preferences
_pref() {
. $CONF
[[ "$SPLASH" == 'false' ]] && CDEF=false || CDEF=true
[[ -n "$COLOR" ]] && DEFCOL=#${COLOR} || DEFCOL=#666666
[[ -n "$SWIDTH" ]] && SW=$SWIDTH || SW=0
if [[ $NUM > 1 ]]; then
SPLASHPREF=' <hseparator space-expand="true" space-fill="true"></hseparator>
<hbox space-expand="true" space-fill="true">
<hbox space-expand="true" space-fill="true">
<checkbox>
<label>enable initial splash screen.</label>
<variable>SPL</variable>
<default>'$CDEF'</default>
</checkbox>
</hbox>
</hbox>'
fi
export PGUI='<window icon-name="gtk-preferences" title="Preferences" width-request="400">
<vbox>
<hbox space-expand="true" space-fill="true">
<text use-markup="true"><label>"<b>Select your preferences.</b>"</label></text>
</hbox>
<hseparator space-expand="true" space-fill="true"></hseparator>
<hbox space-expand="true" space-fill="true">
<text><label>"Press Save and '$PROG' will restart when you are ready."</label></text>
</hbox>
<hbox space-expand="true" space-fill="true">
<text><label>"Choose the directory to search wallpapers."</label></text>
</hbox>
<hbox space-expand="true" space-fill="true">
<hbox space-expand="true" space-fill="true">
<entry accept="directory">
<default>'$BGDIR'</default>
<variable>BACKGROUNDS</variable>
</entry>
</hbox>
<hbox space-expand="false" space-fill="false">
<button>
<input file icon="directory-open"></input>
<variable>FILE_BROWSE_DIRECTORY</variable>
<action function="fileselect">BACKGROUNDS</action>
</button>
</hbox>
</hbox>
'$SPLASHPREF'
<hseparator space-expand="true" space-fill="true"></hseparator>
<hbox space-expand="true" space-fill="true">
<hbox space-expand="true" space-fill="true">
<hbox space-expand="false" space-fill="false">
<text label="width adjustment" tooltip-text="Adjust the width of the interface to suit"></text>
</hbox>
<hseparator space-expand="true" space-fill="true" name="sep"></hseparator>
<hbox space-expand="false" space-fill="false">
<spinbutton range-min="-200" range-max="200" range-step="2">
<variable>SW0</variable>
<default>'$SW'</default>
</spinbutton>
</hbox>
</hbox>
</hbox>
<hseparator space-expand="true" space-fill="true"></hseparator>
<hbox space-expand="true" space-fill="true">
<hbox space-expand="true" space-fill="true">
<entry editable="false">
<default>Choose a background color</default>
</entry>
</hbox>
<hbox space-expand="false" space-fill="false">
<colorbutton>
<default>'$DEFCOL'</default>
<variable>CLB0</variable>
</colorbutton>
</hbox>
</hbox>
<hseparator space-expand="true" space-fill="true"></hseparator>
<hbox space-expand="false" space-fill="false">
<button>
<label>Cancel</label>
<input file icon="gtk-cancel"></input>
<action>kill '$PID'</action>
<action>exit:abort</action>
</button>
<button>
<label>Save</label>
<input file icon="gtk-save"></input>
<action>exit:SAVE</action>
</button>
</hbox>
</vbox>
</window>'
eval "$($GTK3DIALOG -p PGUI -c --styles=$TEMP/win.css)"
if [[ -d "$BACKGROUNDS" ]]; then
sed -i "s%^BGDIR.*$%BGDIR=\"$BACKGROUNDS\"%" $CONF
rm -f "$TEMP/buttons"
rm -f "$TEMP/main_gui.xml"
fi
if grep -q 'SPLASH' $CONF; then
sed -i "s/^SPLASH.*$/SPLASH=$SPL/" $CONF
else
echo "SPLASH=$SPL" >> $CONF
fi
if grep -q 'SWIDTH' $CONF; then
sed -i "s/^SWIDTH.*$/SWIDTH=$SW0/" $CONF
else
echo "SWIDTH=$SW0" >> $CONF
fi
if grep -q 'COLOR' $CONF; then
sed -i "s/^COLOR.*$/COLOR=${CLB0:1:6}/" $CONF
else
echo "COLOR=${CLB0:1:6}" >> $CONF
fi
if [[ "$EXIT" == 'SAVE' ]]; then
exec $0
fi
}; export -f _pref
# build options for output
_output() {
[[ -n "$WAYLAND_DISPLAY" ]] && fff=ww || fff=xx
rm -f $TEMP/OP
for output in $TEMP/${fff}*
do
. $output
export OUTPUT
export FBG="$1"
echo "<item>$OUTPUT</item>" >> $TEMP/OP
done
. $CONF
sub_gui "$FBG"
}; export -f _output
_build_command() {
if [[ -n "$WAYLAND_DISPLAY" ]]; then
echo 'killall swaybg >/dev/null 2>&1' > $TEMP/cmd
echo 'swaybg \' >> $TEMP/cmd
cat $TEMP/Wset >> $TEMP/cmd
echo '>/dev/null 2>&1 &' >> $TEMP/cmd
# run it
. "$TEMP/cmd"
cat $TEMP/cmd > $CONFDIR/cmd # you can put this in your startup file
else
# this builds ~/.fehbg with the command below.
echo 'killall feh >/dev/null 2>&1' > $TEMP/cmd
echo 'feh \' >> $TEMP/cmd
cat $TEMP/Xwset >> $TEMP/cmd
echo '>/dev/null 2>&1 &' >> $TEMP/cmd
# run it
. "$TEMP/cmd"
fi
}; export -f _build_command
trap_exit() {
trap "rm -rf $TEMP" EXIT
}; export -f trap_exit
######################## main ##############################
trap_exit
export PID=$$
if [[ -n "$WAYLAND_DISPLAY" ]]; then
case "$XDG_CURRENT_DESKTOP" in
wlroots|labwc|sway*|river|niri|hyprland|Bunsen*)echo "$XDG_CURRENT_DESKTOP";; # this can be expanded later
*)_splash "Unfortunately your desktop $XDG_CURRENT_DESKTOP is unsupported" 5;;
esac
fi
if [[ ! -d "$BGDIR" ]]; then
_splash "Please set a background directory" 3
_pref
fi
if [[ "$NUM" != '1' ]]; then
_splash "You have $NUM monitors connected. Carefully choose an image for each of them." 0 b &
fi
echo ================
button_gui
main_gui
#!/bin/sh
echo '#include <stdio.h>\nvoid main() { printf("Hi, bunsenlabs\\n"); return; }' > bunsen.c
gcc bunsen.c -o bunsen
./bunsen
Offline
<gripe>
Single-letter variable names like $W do not make life easier for people trying to search through a 500-line script.
</gripe>
...elevator in the Brain Hotel, broken down but just as well...
( a boring Japan blog (currently paused), now on Bluesky, there's also some GitStuff )
Offline
The icon
save the xvg code as xwwall.svg
and put it in ~/.local/share/icons/hicolor/scalable/apps/
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 192 192">
<path style="fill:#DCCBB3;stroke:#999999;stroke-width:6;" d="m 23,13 146,0 a 10,10 0 0 1 10,10 l 0,146 a 10,10 0 0 1 -10,10 l -146,0 a 10,10 0 0 1 -10,-10 l 0,-146 a 10,10 0 0 1 10,-10 z"/>
<path style="fill:none;stroke:#999999;stroke-width:8;" d="m 16,36.2 160,0 m 0,29.2 -160,0 m 0,29.2 160,0 m 0,29.2 -160,0 m 0,29.2 160,0"/>
<path style="fill:none;stroke:#999999;stroke-width:8;" d="m 66.5,16 0,16.2 m 59,0 0,-16.2 m 0,53.4 0,21.2 m -59,-21.2 0,21.2 m 0,37.2 0,21.2 m 59,0 0,-21.2"/>
<path style="fill:none;stroke:#999999;stroke-width:8;" d="m 36,40.2 0,21.2 m 59,0 0,-21.2 m 0,58.4 0,21.2 m -59,-21.2 0,21.2 m 0,37.2 0,19.2 m 59,0 0,-19.2 m 59,0 0,19.2 m 0,-56.4 0,-21.2 m 0,-37.2 0,-21.2"/>
<g transform="translate(18,18) scale(0.7)">
<path style="fill:#444" d="m 22.5,5 30,40 -40,50 -5,0 35,-45 -35,-45 z m 65,0 -40,50 30,40 15,0 -35,-45 35,-45 z"/>
<path style="fill:#F28A35;" d="m 21,25 a 48,36 0 1 0 58,0 l -0.8,1 a 44,33 0 1 1 -55,2 z m 15,-4 a 48,36 0 0 1 36,1 l -0.8,1 a 44,33 0 0 0 -34,0"/>
</g>
<g transform="translate(42,8) scale(0.28)">
<circle cx="341.4" cy="465.2" r="122.9" style="fill:#ffbc00"/>
<g transform="scale(.9156 1.092)" style="fill:#fff">
<path d="m443.9 314.6h2.35l-1.495 1.495h-0.8544v-1.495m-173 3.631v1.709l-5.554 6.836h-0.8544l-0.8544-5.34c3.275-2.136 5.696-3.204 7.263-3.204m202.5 2.35c4.842 1.9e-4 7.547 3.062 8.117 9.185l-4.059 28.84h1.495l3.204-2.136h0.8544v0.6408c-4.415 2.706-8.687 10.11-12.82 22.22-1.567 10.4-4.201 20.01-7.904 28.84-3.276 9.114-4.913 17.52-4.913 25.21l-6.195 15.17c-1.7e-4 1.282 2.35 2.563 7.049 3.845-0.8546 2.991-2.136 4.486-3.845 4.486v0.8544h1.495v0.6408c-1.7e-4 1.567-2.421 2.35-7.263 2.35l0.8544 0.8544v2.991h-1.495c0.9967 2.991 3.133 4.486 6.408 4.486v1.495h-6.408v0.8544c2.136 4e-5 3.204 1.282 3.204 3.845l-8.972 2.991 0.8544 0.8544v0.6408c-1.6e-4 0.9969-1.068 1.495-3.204 1.495v0.8544c2.706 3e-5 4.058 0.4985 4.059 1.495-3.845 1.282-8.901 7.619-15.17 19.01-6.408 10.11-11.96 15.17-16.66 15.17h-1.709c-3.56-2.279-6.48-9.826-8.758-22.64-9.114-19.51-13.67-30.97-13.67-34.39-1e-4 -8.829-2.919-18.23-8.758-28.2-1.567-4.415-2.635-9.968-3.204-16.66l-3.845-0.8544c-9.684 14.67-14.74 26.13-15.17 34.39-2.706 4.842-4.842 10.68-6.408 17.52 5.839 1.567 8.758 3.062 8.758 4.486v0.8544c-4.557-0.5696-7.761-1.638-9.612-3.204-1.994 3.845-4.628 14.53-7.904 32.04-2.563 8.117-5.768 12.18-9.612 12.18-10.82-3.56-19.87-9.399-27.13-17.52-1.139 2e-5 -2.991-4.059-5.554-12.18-1.566 3e-5 -2.635-4.059-3.204-12.18-5.411-11.53-9.114-24.71-11.11-39.52v-22.22h-0.8544l-3.845 0.8544v-0.8544c1e-5 -0.9967 1.282-1.495 3.845-1.495l-0.8544-12.82v-10.04l-6.195-32.04v-13.67c2.706-8.544 7.405-12.82 14.1-12.82h44.86v1.495c-3.56 0.1426-5.981 0.9258-7.263 2.35-2.706-1.566-5.34-2.35-7.904-2.35h-8.758l-4.913 0.6408-0.8544-0.6408h-0.6408l-6.408 0.6408-3.204-0.6408-2.35 0.6408-2.563-0.6408c10.4 11.39 16.52 21.01 18.37 28.84h7.263v1.495h-5.554v1.709c2.136 6.551 3.703 9.826 4.699 9.826h1.709l3.845-0.8544 0.8544 0.8544 0.8544-0.8544 0.8544 0.8544v0.6408c-2.848 1.709-4.771 4.059-5.767 7.049h-0.6408v1.495h1.495c1.994 23.78 5.696 41.8 11.11 54.04l3.204 2.136h1.709c2.136 8e-5 6.622-8.331 13.46-24.99 4.415-7.547 7.619-14.17 9.612-19.87l-0.8544-2.35c4.415-5.554 8.972-8.331 13.67-8.331h1.495c2.99 1.4e-4 5.127 1.567 6.408 4.699 3.987 4.7 7.191 11.75 9.612 21.15l11.96 22.22c1.566 1.567 2.35 3.347 2.35 5.34 4.414 8.402 8.402 13.96 11.96 16.66h2.563c2.99 6e-5 6.978-10.4 11.96-31.19 0.8543 9e-5 3.204-5.554 7.049-16.66v-0.8544l-13.46-1.495-3.204 0.8544h-4.059v-1.709l8.117-0.6408h15.81c6.123-18.37 11.75-32.61 16.88-42.72 1.709-20.79 4.058-31.19 7.049-31.19l9.612-3.845m-45.5 2.35c-0.8546 1.994-2.706 2.991-5.554 2.991v-1.495l5.554-1.495m-80.53 3.845h21.57v1.495l-4.913 0.6408-4.699-0.6408-4.059 1.495-1.495-1.495h-6.408v-1.495m-112.4 2.991h2.35l1.495 1.495v0.8544l-4.699 4.486v3.845h-1.709v-2.35l0.8544-0.6408v-0.8544l-4.059-3.845c0.9969-1.994 2.919-2.99 5.767-2.991m157 9.185h2.35v0.6408c-1.1e-4 0.997-0.7834 1.495-2.35 1.495l-0.8544 0.8544v0.8544l-2.35-0.8544v-1.495l3.204-1.495m-11.96 8.331v0.8544c-1e-4 1.139-3.418 2.35-10.25 3.631v-1.495l4.699-2.136 0.8544 0.6408h0.6408l4.059-1.495m-139.5 7.69v0.6408l-1.709 1.495-0.6408-0.6408v-0.8544l0.6408-0.6408h1.709m116.4 0v0.6408c-2.991 2.279-7.832 4.344-14.53 6.195v-1.495c1.139 1.5e-4 1.709-0.7831 1.709-2.35l12.82-2.991m40.59 7.476 0.8544 0.8544v0.6408l-1.495 1.709h-0.8544l-1.709-1.709v-0.6408l3.204-0.8544m29.48 0.8544h0.8544v0.6408l-1.495 1.709h-0.8544v-0.8544l1.495-1.495m-13.46 10.68 3.204 2.136c-0.5698 1.567-2.136 2.35-4.699 2.35l-1.709-2.35c-1.3e-4 -0.7119 1.068-1.424 3.204-2.136m19.22 9.826 0.6408 0.8544v0.6408l-0.6408 0.8544h-1.709v-0.8544l1.709-1.495m-30.33 7.69v0.6408l-4.059 3.204h-2.35v-0.8544c-1.1e-4 -1.282 2.136-2.278 6.408-2.991m-132.4 29.69h0.8544v0.6408c-2.136 4.7-3.987 7.548-5.554 8.544h-1.709v-3.204l6.408-5.981m104.5 35.67h0.8544v1.495l-6.408 3.204-0.8544-0.8544v-1.495l6.408-2.35m-87.79 10.04h1.495l2.563 8.331h-1.709l-2.35-7.69v-0.6408m85.44 9.826h0.6408l2.563 2.35-0.8544 0.6408h-0.8544l-1.495-2.136v-0.8544"/>
</g>
</g>
</svg>
Desktop file - save as xwwall.desktop
and put it in ~/.local/share/applications
[Desktop Entry]
Name=XW Wallpaper
Comment=Wallpaper setter for X11 or Wayland
GenericName=Wallpaper Setter
Exec=xwwall
Icon=xwwall
Terminal=false
Type=Application
Categories=Settings;System;Graphics;
<gripe> ... </gripe>
I promise no more unless they are for a count or something in a loop
#!/bin/sh
echo '#include <stdio.h>\nvoid main() { printf("Hi, bunsenlabs\\n"); return; }' > bunsen.c
gcc bunsen.c -o bunsen
./bunsen
Offline
Looking at the button_gui() function I was hoping to speed up the startup time when there are a lot of background images, by cutting down the read/write actions to files in $TEMP/. I collected the buttons in an array, and did a single echo out to "$TEMP/buttons" at the end. Also replaced the calls to grep for the image mimetype test with a bash glob comparison.
Disappointed to find that the startup time didn't seem much different.
But another thing that changed was the order in which the images were presented. I've no idea why, but in my revision they appear in the expected alphabetical order, but in the original some whole groups of images seem to be appearing at another place.
Just in case you'd like to play with it, here's my modified button_gui(). You could just paste it in and rename the original to button_gui_orig() or something:
# populate the main GUI
button_gui() {
local c i j WALL V buttonsx buttons
c=0
shopt -s globstar
for WALL in "$BGDIR"/*{,/**}
do
[[ "$(file --brief --mime-type "$WALL" )" = *image* ]] || continue # test mime
# we take advantage of bash math here
# for a nicish GUI width *must* be consistent
i=$((c/4))
V=' <button image-position="top" tooltip-text="'"${WALL##*/}"'">
<variable>BG'$c'</variable>
<input file>'"\"$WALL\""'</input>
<height>'$W'</height>
<width>'$W'</width>
<action>_output '"\"$WALL\""' &</action>
<action>exit:BG'$c'</action>
</button>'
buttonsx[i]+="$V"$'\n'
c=$((c+1))
export TOT=$((c+1))
if [[ $c -ge 250 ]];then
export TOT=250
_splash "Warning: Limit of 250 images" 2 2 &
break
fi
done
shopt -u globstar
for j in "${!buttonsx[@]}"
do buttons+=" <hbox>
${buttonsx[j]}
</hbox>"$'\n'
done
echo "$buttons" > "$TEMP/buttons"
}
...elevator in the Brain Hotel, broken down but just as well...
( a boring Japan blog (currently paused), now on Bluesky, there's also some GitStuff )
Offline
Oh, for that all to work you need the latest..
change the labwc/rc.xml
windowRule
<windowRule identifier="xwwall*" matchOnce="false">
<action name="AutoPlace" policy="center"/>
</windowRule>
Latest adjustments to the program:
W=Wdth, H=Hght
s/background/xwwall
added $PROG -
in the titlebar
#!/bin/bash
export V=0.1.0
export GTK3DIALOG
[[ -z "$GTK3DIALOG" ]] && GTK3DIALOG=gtk3dialog
export BGDIR="${BGDIR:-$HOME/Pictures/wallpapers}"
export PROG=${0##*\/}
export TEMP=/tmp/$PROG
#export TEMP=$HOME/tmp/$PROG # for testing
rm -rf "$TEMP" # incase of a crash because of "Argument list too long"
mkdir -p "$TEMP"
export CONFDIR="${XDG_CONFIG_HOME:-$HOME/.config}/$PROG"
mkdir -p "$CONFDIR"
export CONF="$CONFDIR/$PROG.conf"
if [[ ! -f "$CONF" ]];then
echo "BGDIR=$BGDIR" > "$CONF"
fi
. "$CONF"
case "$1" in
--restore)
if [[ -f "$CONFDIR/cmd" && -n "$WAYLAND_DISPLAY" ]]; then
. "$CONFDIR/cmd" && exit 0
elif [[ -x "$HOME/.fehbg" ]]; then
exec "$HOME/.fehbg"
else
exit 1
fi
;;
-*v|-*version)
echo -e "\t$PROG $V\n\t\tGPL-2.0+ licence\n"
exit 0
;;
-*h|-*help)
echo -e "\t$PROG -h|--help\n\t\tshow this help and exit.\n"
echo -e "\t$PROG -v|--version\n\t\tprint version and exit.\n"
echo -e "\t$PROG --restore\n\t\trestore backgrounds at session start.\n"
echo -e "\ttry \"man $PROG\" for more information."
exit 0
;;
esac
# sort out the monitors and positions
if [[ -n "$WAYLAND_DISPLAY" ]]; then
b=0
c=1
MON=''
pos=''
while read -r l m n o p q
do
case "${l:0:3}" in
Pos|Mak|Mod|Ser|Phy|Ena|Tra|Sca|Ada)
if [[ "${l:0:3}" == 'Pos' ]];then
export pos
pos=${m%,*}; echo POS=$pos >> "$TEMP/Wmonitor-$((c-1))"
else
continue
fi
;;
[a-zA-Z][a-zA-Z][a-zA-Z0-9])MON=$l;;
esac
case "$q" in
current*)res=$l;;
*)continue;;
esac
resX=${res%x*}
resY=${res#*x}
echo OUTPUT=$MON >> "$TEMP/Wmonitor-$c"
echo X=$resX >> "$TEMP/Wmonitor-$c"
echo Y=$resY >> "$TEMP/Wmonitor-$c"
c=$((c+1))
b=$((b+1))
echo $b > $TEMP/number
done <<<$(wlr-randr)
export POPT='edge="top" dist="100"'
export SOPT='layer="top"'
export CONFILE="$CONFDIR/Wconf"
else
k=0
n=1
MON=''
while read -r a b c d z
do
echo $a
[[ "${a}" == 'Monitors:' ]] && continue
MON=$d
resX=${c/\/[0-9]*/}
resY=${c#*x}
resY=${resY/\/[0-9]*/}
pos=${c#*+}
pos=${pos/+/ }
[[ "${pos%\ *}" == '0' ]] && n=0 # 'xx' position
pos=${pos%\ *}
echo Xmonitor-$n
echo $MON
echo $resX
echo $resY
echo $pos
echo OUTPUT=$MON >> "$TEMP/Xmonitor-$n"
echo X=$resX >> "$TEMP/Xmonitor-$n"
echo Y=$resY >> "$TEMP/Xmonitor-$n"
echo POS=$pos >> "$TEMP/Xmonitor-$n"
n=$((n+1))
k=$((k+1))
echo $k > $TEMP/number
done <<<$(xrandr --listmonitors)
export POPT='decorated="false"'
export SOPT=$POPT
export CONFILE="$CONFDIR/Xconf"
fi
#CSS for splash
echo 'window#splash {
background: rgba(0,0,0,0.0);
}
#splash {
background: #5E003E;
color: #ffffff;
border-radius: 10px;
padding: 2px;
}
#sep {
background: rgba(0,0,0,0.0);
}
' > "$TEMP/win.css"
# get the primary output
e=0
if [[ -n "$WAYLAND_DISPLAY" ]]; then
for i in $TEMP/Wmonitor*
do
# $i is sourced
. "$i"
[[ "$POS" == '0' ]] && echo "$OUTPUT = primary" && cp $i $TEMP/ww0
[[ "$POS" == "$X" ]] && echo "$OUTPUT = secondary" && cp $i $TEMP/ww1
[[ $POS -gt $X ]] && echo "$OUTPUT = extra" && cp $i $TEMP/ww2$e && e=$((e+1))
done
rm $TEMP/Wmonitor* # finished with these
read -r NUM < "$TEMP/number"
export NUM
echo $NUM outputs
. $TEMP/ww0
export Wdth=$((X / 9))
export Hght=$((Y / 10))
export MW=$((X / 2))
export MH=$((Y * 2 / 3))
else
for f in $TEMP/Xmonitor*
do
# $f is sourced
. "$f"
[[ "$POS" == '0' ]] && echo "$OUTPUT = primary" && cp $f $TEMP/xx0
[[ "$POS" == "$X" ]] && echo "$OUTPUT = secondary" && cp $f $TEMP/xx1
[[ $POS -gt $X ]] && echo "$OUTPUT = extra" && cp $i $TEMP/xx2$e && e=$((e+1))
done
rm $TEMP/Xmonitor* # finished with these
export NUM
read NUM < $TEMP/number
echo $NUM outputs
. $TEMP/xx0
export Wdth=$((X / 9))
export Hght=$((Y / 10))
export MW=$((X / 2))
export MH=$((Y * 2 / 3))
fi
######################## functions ##############################
# splash window
_splash() {
[[ -z "$1" ]] && return
E_VAL=SPLASH
CR="--geometry=+$((X/2-180))+150"
case $2 in
0)[[ "$SPLASH" == 'false' ]] && return
DIS='
<button tooltip-text="Do not show again">
<input file icon="window-close"></input>
<label>Dismiss</label>
<action>if grep -q "SPLASH" '$CONF'; then sed -i "s/^SPLASH.*$/SPLASH=false/" '$CONF';else echo SPLASH=false >> '$CONF'; fi</action>
<action>exit:DISMISS</action>
</button>'
E_VAL=Monitors
;;
2)E_VAL=Limit;;
3)ACT='<action>main_gui &</action><action>exit:OK</action>';;
5)ACT='<action>kill '$PID'</action><action>exit:abort</action>';KILL='<action>kill '$PID'</action>';;
6)E_VAL=Wait;CR=-c;;
*)CR=-c;ACT='<action>exit:OK</action>';;
esac
IVAL=4
re='^[0-9]'
[[ $3 =~ $re ]] && IVAL=$3
if [[ -n "$WAYLAND_DISPLAY" ]]; then
[[ "$3" == 'b' ]] && POPT='edge="bottom" dist="200"'
else
[[ "$3" == 'b' ]] && CR="--geometry=+$((X/2-240))+$((Y-300))"
fi
TIMER='<timer interval="'$IVAL'" visible="false">'$KILL'<action>exit:'$E_VAL'</action></timer>'
echo '<window type-hint="6" icon-name="gtk-info" '$POPT' name="splash" width-request="360">
<vbox name="splash">
<hbox name="splash">
<hbox space-expand="false" space-fill="false">
<pixmap name="splash"><width>42</width><input file icon="gtk-info"></input></pixmap>
'$TIMER'
</hbox>
<hbox space-expand="true" space-fill="true">
<text name="splash">
<label>'"$1"'</label>
</text>
</hbox>
</hbox>
<hbox name="splash">
'$DIS'
<button>
<label>OK</label>
<input file icon="gtk-ok"></input>
'$ACT'
</button>
</hbox>
</vbox>
</window>' | $GTK3DIALOG -s "$CR" --styles=$TEMP/win.css
[[ "$2" == '1' ]] && exit $2
}; export -f _splash
# sort selections
_selections() {
echo '<hbox>' > $TEMP/ret
cat $TEMP/selected | while read -r sel
do
echo ' <pixmap tooltip-text="'${sel##*\/}'">
<height>120</height>
<input file>'$sel'</input>
</pixmap>' >> $TEMP/ret
done
echo '</hbox>' >> $TEMP/ret
}; export -f _selections
# set each background
confirm_gui() {
_selections
PIX=$(cat $TEMP/ret)
export CON='<window icon-name="xwwall" title="Confirm selection">
<vbox>
<hbox space-expand="true" space-fill="true">
<text><label>Please confirm that the image below is correct.</label></text>
</hbox>
<hbox space-expand="true" space-fill="true">
'$PIX'
</hbox>
<hbox>
<button yes></button>
<button no></button>
<button tooltip-text="If unsatisfied with your choice try again.">
<input file icon="refresh"></input>
<label>Refresh</label>
<action>exit:REFRESH</action>
</button>
</hbox>
</vbox>
</window>'
eval "$($GTK3DIALOG -p CON -c --styles=$TEMP/win.css)"
case $EXIT in
Yes)_build_command;;
REFRESH)rm -f $TEMP/increment $TEMP/selected $TEMP/[XW]set rm -f $TEMP/ret
main_gui &;;
*)return 1;;
esac
}; export -f confirm_gui
# populate the main GUI
button_gui() {
c=0
shopt -s globstar
for WALL in "$BGDIR"/*{,/**}
do
file -b --mime-type "$WALL" | grep -q 'image' || continue # test mime
# we take advantage of bash math here
# for a nicish GUI width *must* be consistent
i=$((c/4))
V=' <button image-position="top" tooltip-text="'"${WALL##*/}"'">
<variable>BG'$c'</variable>
<input file>'"\"$WALL\""'</input>
<height>'$Wdth'</height>
<width>'$Wdth'</width>
<action>_output '"\"$WALL\""' &</action>
<action>exit:BG'$c'</action>
</button>'
echo "$V" >> $TEMP/buttonsx$i
c=$((c+1))
export TOT=$((c+1))
if [[ $c -ge 250 ]];then
export TOT=250
_splash "Warning: Limit of 250 images" 2 2 &
break
fi
done
shopt -u globstar
for j in $(ls "$TEMP" | grep 'buttonsx[0-9]*')
do echo " <hbox>
$(cat "$TEMP/$j")
</hbox>" >> $TEMP/buttons
done
}
# sub GUI
sub_gui() {
[[ -z "$COLOR" ]] && COLOR=999999
if [[ -n "$WAYLAND_DISPLAY" ]]; then
CCOL="-c $COLOR"
SS='Wset'
ACTION='<action>echo -e " -o $OUT -m $MODE '$CCOL' \\ \n\t -i '\'$1\'' \\" >> '$TEMP/$SS'</action>'
else
# feh modes: --bg-scale, --bg-center[ --image-bg=$color], --bg-fill, --bg-max[ --image-bg=$color], --bg-tile
XCOL=" --image-bg=#${COLOR}"
SS='Xwset'
ACTION='<action>if [[ "$MODE" == "stretch" || "$MODE" == "fit" ]];then MODE=fill;fi; echo -e " --bg-$MODE '${XCOL}' \\ \n\t'\'$1\'' \\" >> '$TEMP/$SS'</action>'
fi
[[ -r "$TEMP/increment" ]] || echo -n 1 > $TEMP/increment
INC=$(cat $TEMP/increment)
# set default for entry
case $INC in
1)DEFAULT=$(sed '1s/item/default/g' < $TEMP/OP | sed -n 1p) ;;
2)DEFAULT=$(sed '2s/item/default/g' < $TEMP/OP | sed -n 2p) ;;
3)DEFAULT=$(sed '3s/item/default/g' < $TEMP/OP | sed -n 3p) ;;
4)DEFAULT=$(sed '4s/item/default/g' < $TEMP/OP | sed -n 4p) ;;
5)DEFAULT=$(sed '5s/item/default/g' < $TEMP/OP | sed -n 5p) ;;
6)DEFAULT=$(sed '6s/item/default/g' < $TEMP/OP | sed -n 6p) ;;
esac
if [[ $INC -gt $NUM ]]; then
_splash "You are at your monitor limit. Confirm?" 4
else
export SUBGUI='<window icon-name="xwwall" title="Selection">
<vbox>
<hbox space-expand="true" space-fill="true">
<text><label>Choose Mode and press the image</label></text>
</hbox>
<hbox space-expand="true" space-fill="false">
<text use-markup="true"><label>"<big>Mode:</big>"</label></text>
<comboboxtext>
<variable>MODE</variable>
<item>stretch</item>
<item>center</item>
<item>tile</item>
<item>fit</item>
</comboboxtext>
</hbox>
<hbox space-expand="true" space-fill="false">
<text use-markup="true"><label>"<big>Output:</big>"</label></text>
<entry>
<variable>OUT</variable>
'$DEFAULT'
</entry>
</hbox>
<hbox space-expand="true" space-fill="true">
<button tooltip-text="'"${1##*/}"$'\n''Press image to confirm or No to reject and confinue.">
<variable>CBG</variable>
<input file>'$1'</input>
<width>320</width>
<action>echo -n '$((INC+1))' > $TEMP/increment</action>
<action>if grep -q $OUT '$TEMP'/'$SS' >/dev/null 2>&1; then _splash "Only 1 wall per monitor. Maybe you have reached the monitor limit?." 3;fi;</action>
<action>echo '$1' >> '$TEMP'/selected</action>
'$ACTION'
<action>sed -i "s% $%%g" '$TEMP/$SS'</action>
<action>if [[ '$INC' -ge '$NUM' ]]; then confirm_gui;fi &</action>
<action>if [[ '$INC' -lt '$NUM' ]]; then main_gui;fi &</action>
<action>exit:CBG</action>
</button>
</hbox>
<hbox>
<text label="Output: '$INC'"></text>
<button>
<label>No</label>
<input file icon="gtk-no"></input>
<action>main_gui &</action>
<action>exit:NO</action>
</button>
</hbox>
</vbox>
</window>'
$GTK3DIALOG -p SUBGUI -c --styles=$TEMP/win.css
fi
}; export -f sub_gui
# populate the main GUI
main_gui() {
[[ -z "$SWIDTH" ]] && SWIDTH=0
[[ -r "$TEMP/main_gui.xml" ]] && _splash "Please wait ..." 6 2 &
BUTTONS=$(cat $TEMP/buttons)
export MAINGUI='<window icon-name="xwwall" title="'$PROG' - Background Choice">
<vbox>
<hbox space-expand="true" space-fill="true">
<text use-markup="true" tooltip-text="'$TOT' images"><label>"<b>Select an image for your wallpaper by pressing the image.</b>"</label></text>
</hbox>
<hseparator space-expand="true" space-fill="true"></hseparator>
<hbox>
<vbox scrollable="true" height="'$MH'" width="'$((MW+SWIDTH))'">
'$BUTTONS'
</vbox>
</hbox>
<hbox space-expand="true" space-fill="true">
<hbox space-expand="false" space-fill="false">
<button tooltip-text="Preferences">
<label>Preferences</label>
<width>16</width>
<input file icon="preferences-desktop-wallpaper"></input>
<action>exit:PREFS</action>
</button>
</hbox>
<hseparator space-expand="true" space-fill="true" name="sep"></hseparator>
<text label="Confirmation is required when finished."></text>
<hseparator space-expand="true" space-fill="true" name="sep"></hseparator>
<hbox space-expand="false" space-fill="false">
<button>
<label>Cancel</label>
<input file icon="gtk-cancel"></input>
<action>kill '$PID'</action>
<action>exit:abort</action>
</button>
</hbox>
</hbox>
</vbox>
</window>'
[[ -r "$TEMP/main_gui.xml" ]] || printf "%s\n" "$MAINGUI" > $TEMP/main_gui.xml
eval "$($GTK3DIALOG -f $TEMP/main_gui.xml -c --styles=$TEMP/win.css)"
if [[ "$EXIT" == "PREFS" ]]; then
_pref
fi
}; export -f main_gui
# preferences
_pref() {
. $CONF
[[ "$SPLASH" == 'false' ]] && CDEF=false || CDEF=true
[[ -n "$COLOR" ]] && DEFCOL=#${COLOR} || DEFCOL=#666666
[[ -n "$SWIDTH" ]] && SW=$SWIDTH || SW=0
if [[ $NUM > 1 ]]; then
SPLASHPREF=' <hseparator space-expand="true" space-fill="true"></hseparator>
<hbox space-expand="true" space-fill="true">
<hbox space-expand="true" space-fill="true">
<checkbox>
<label>enable initial splash screen.</label>
<variable>SPL</variable>
<default>'$CDEF'</default>
</checkbox>
</hbox>
</hbox>'
fi
export PGUI='<window icon-name="gtk-preferences" title="Preferences" width-request="400">
<vbox>
<hbox space-expand="true" space-fill="true">
<text use-markup="true"><label>"<b>Select your preferences.</b>"</label></text>
</hbox>
<hseparator space-expand="true" space-fill="true"></hseparator>
<hbox space-expand="true" space-fill="true">
<text><label>"Press Save and '$PROG' will restart when you are ready."</label></text>
</hbox>
<hbox space-expand="true" space-fill="true">
<text><label>"Choose the directory to search wallpapers."</label></text>
</hbox>
<hbox space-expand="true" space-fill="true">
<hbox space-expand="true" space-fill="true">
<entry accept="directory">
<default>'$BGDIR'</default>
<variable>BACKGROUNDS</variable>
</entry>
</hbox>
<hbox space-expand="false" space-fill="false">
<button>
<input file icon="directory-open"></input>
<variable>FILE_BROWSE_DIRECTORY</variable>
<action function="fileselect">BACKGROUNDS</action>
</button>
</hbox>
</hbox>
'$SPLASHPREF'
<hseparator space-expand="true" space-fill="true"></hseparator>
<hbox space-expand="true" space-fill="true">
<hbox space-expand="true" space-fill="true">
<hbox space-expand="false" space-fill="false">
<text label="width adjustment" tooltip-text="Adjust the width of the interface to suit"></text>
</hbox>
<hseparator space-expand="true" space-fill="true" name="sep"></hseparator>
<hbox space-expand="false" space-fill="false">
<spinbutton range-min="-200" range-max="200" range-step="2">
<variable>SW0</variable>
<default>'$SW'</default>
</spinbutton>
</hbox>
</hbox>
</hbox>
<hseparator space-expand="true" space-fill="true"></hseparator>
<hbox space-expand="true" space-fill="true">
<hbox space-expand="true" space-fill="true">
<entry editable="false">
<default>Choose a background color</default>
</entry>
</hbox>
<hbox space-expand="false" space-fill="false">
<colorbutton>
<default>'$DEFCOL'</default>
<variable>CLB0</variable>
</colorbutton>
</hbox>
</hbox>
<hseparator space-expand="true" space-fill="true"></hseparator>
<hbox space-expand="false" space-fill="false">
<button>
<label>Cancel</label>
<input file icon="gtk-cancel"></input>
<action>kill '$PID'</action>
<action>exit:abort</action>
</button>
<button>
<label>Save</label>
<input file icon="gtk-save"></input>
<action>exit:SAVE</action>
</button>
</hbox>
</vbox>
</window>'
eval "$($GTK3DIALOG -p PGUI -c --styles=$TEMP/win.css)"
if [[ -d "$BACKGROUNDS" ]]; then
sed -i "s%^BGDIR.*$%BGDIR=\"$BACKGROUNDS\"%" $CONF
rm -f "$TEMP/buttons"
rm -f "$TEMP/main_gui.xml"
fi
if grep -q 'SPLASH' $CONF; then
sed -i "s/^SPLASH.*$/SPLASH=$SPL/" $CONF
else
echo "SPLASH=$SPL" >> $CONF
fi
if grep -q 'SWIDTH' $CONF; then
sed -i "s/^SWIDTH.*$/SWIDTH=$SW0/" $CONF
else
echo "SWIDTH=$SW0" >> $CONF
fi
if grep -q 'COLOR' $CONF; then
sed -i "s/^COLOR.*$/COLOR=${CLB0:1:6}/" $CONF
else
echo "COLOR=${CLB0:1:6}" >> $CONF
fi
if [[ "$EXIT" == 'SAVE' ]]; then
exec $0
fi
}; export -f _pref
# build options for output
_output() {
[[ -n "$WAYLAND_DISPLAY" ]] && fff=ww || fff=xx
rm -f $TEMP/OP
for output in $TEMP/${fff}*
do
. $output
export OUTPUT
export FBG="$1"
echo "<item>$OUTPUT</item>" >> $TEMP/OP
done
. $CONF
sub_gui "$FBG"
}; export -f _output
_build_command() {
if [[ -n "$WAYLAND_DISPLAY" ]]; then
echo 'killall swaybg >/dev/null 2>&1' > $TEMP/cmd
echo 'swaybg \' >> $TEMP/cmd
cat $TEMP/Wset >> $TEMP/cmd
echo '>/dev/null 2>&1 &' >> $TEMP/cmd
# run it
. "$TEMP/cmd"
cat $TEMP/cmd > $CONFDIR/cmd # you can put this in your startup file
else
# this builds ~/.fehbg with the command below.
echo 'killall feh >/dev/null 2>&1' > $TEMP/cmd
echo 'feh \' >> $TEMP/cmd
cat $TEMP/Xwset >> $TEMP/cmd
echo '>/dev/null 2>&1 &' >> $TEMP/cmd
# run it
. "$TEMP/cmd"
fi
}; export -f _build_command
trap_exit() {
trap "rm -rf $TEMP" EXIT
}; export -f trap_exit
######################## main ##############################
trap_exit
export PID=$$
if [[ -n "$WAYLAND_DISPLAY" ]]; then
case "$XDG_CURRENT_DESKTOP" in
wlroots|labwc|sway*|river|niri|hyprland|Bunsen*)echo "$XDG_CURRENT_DESKTOP";; # this can be expanded later
*)_splash "Unfortunately your desktop $XDG_CURRENT_DESKTOP is unsupported" 5;;
esac
fi
if [[ ! -d "$BGDIR" ]]; then
_splash "Please set a background directory" 3
_pref
fi
if [[ "$NUM" != '1' ]]; then
_splash "You have $NUM monitors connected. Carefully choose an image for each of them." 0 b &
fi
echo ================
button_gui
main_gui
Next will be up at github. Link when ready - probably NYE.
#!/bin/sh
echo '#include <stdio.h>\nvoid main() { printf("Hi, bunsenlabs\\n"); return; }' > bunsen.c
gcc bunsen.c -o bunsen
./bunsen
Offline
Looking at the button_gui() function I was hoping to speed up the startup time when there are a lot of background images, by cutting down the read/write actions to files in $TEMP/. I collected the buttons in an array, and did a single echo out to "$TEMP/buttons" at the end. Also replaced the calls to grep for the image mimetype test with a bash glob comparison.
Disappointed to find that the startup time didn't seem much different.
But another thing that changed was the order in which the images were presented. I've no idea why, but in my revision they appear in the expected alphabetical order, but in the original some whole groups of images seem to be appearing at another place.
Just in case you'd like to play with it, here's my modified button_gui(). You could just paste it in and rename the original to button_gui_orig() or something:
# populate the main GUI button_gui() { local c i j WALL V buttonsx buttons c=0 shopt -s globstar for WALL in "$BGDIR"/*{,/**} do [[ "$(file --brief --mime-type "$WALL" )" = *image* ]] || continue # test mime # we take advantage of bash math here # for a nicish GUI width *must* be consistent i=$((c/4)) V=' <button image-position="top" tooltip-text="'"${WALL##*/}"'"> <variable>BG'$c'</variable> <input file>'"\"$WALL\""'</input> <height>'$W'</height> <width>'$W'</width> <action>_output '"\"$WALL\""' &</action> <action>exit:BG'$c'</action> </button>' buttonsx[i]+="$V"$'\n' c=$((c+1)) export TOT=$((c+1)) if [[ $c -ge 250 ]];then export TOT=250 _splash "Warning: Limit of 250 images" 2 2 & break fi done shopt -u globstar for j in "${!buttonsx[@]}" do buttons+=" <hbox> ${buttonsx[j]} </hbox>"$'\n' done echo "$buttons" > "$TEMP/buttons" }
I probably won't get time for a day or 2. Anything that speeds things is a good thing IMO.
#!/bin/sh
echo '#include <stdio.h>\nvoid main() { printf("Hi, bunsenlabs\\n"); return; }' > bunsen.c
gcc bunsen.c -o bunsen
./bunsen
Offline
^I was hoping that cutting down on the file access while iterating over a collection of over 100 wallpapers would make a significant speed difference, but it didn't seem to. Still, the array method might be preferable anyway.
---
Oh yes, line #439, that [[ $NUM > 1 ]]
needs to be [[ $NUM -gt 1 ]]
, as you have it elsewhere.
Last edited by johnraff (2024-12-29 08:29:44)
...elevator in the Brain Hotel, broken down but just as well...
( a boring Japan blog (currently paused), now on Bluesky, there's also some GitStuff )
Offline
johnraff wrote:<gripe> ... </gripe>
Latest adjustments to the program:
W=Wdth, H=Hght
I promise no more unless they are for a count or something in a loop
Thanks!
Last edited by johnraff (2024-12-29 08:51:20)
...elevator in the Brain Hotel, broken down but just as well...
( a boring Japan blog (currently paused), now on Bluesky, there's also some GitStuff )
Offline
added a spinbutton to Preferences to adjust the width of main_gui - there's no solid way to do it programatically with gtk themes differences having a bearing
In my 1024X768 VM I had to wind it up to +48 to lose the horizontal scrollbar, but it works.
What also worked here is to make the buttons a bit narrower when setting Wdth, from $((X / 9)) to $((X / 10)), but that might not look so good with wide displays or different gtk/openbox themes.
change the labwc/rc.xml windowRule
<windowRule identifier="xwwall*" matchOnce="false">
<action name="AutoPlace" policy="center"/>
</windowRule>
This worked too on Wayland.
Last edited by johnraff (2024-12-29 09:09:56)
...elevator in the Brain Hotel, broken down but just as well...
( a boring Japan blog (currently paused), now on Bluesky, there's also some GitStuff )
Offline
One OOPS! In the man page:
DESCRIPTION
===========
**xwwall** is a graphical wallpaper setter for the X Window System
often known as **X11** and **Wayland** desktops for Linus and other
\*nix distributions.
Linus Torvalds would probably but it's really:
for Linux and other \*nix distributions.
Caught by: the Tpyo Knig!
Debian 12 Beardog, SoxDog and still a Conky 1.9er
Offline
Trying to reduce the width and height of the xwwall window and images, by tinkering with the width/height values in the script.
On my 1920x1080 screen, thumbnails in the main_gui window are now 160px wide - whereas those in the selection- and confirm_gui are both 320px wide.
In order to adjust the main_gui window width, I had to increase the spinbutton range-max (#487) value, as it needs a little higher value than than -200 as scripted.
Wondering whether it would be possible to skip the last confirm_gui window --> and set the wallpaper when pressing the selection image instead?
Offline
One OOPS! In the man page:
DESCRIPTION =========== **xwwall** is a graphical wallpaper setter for the X Window System often known as **X11** and **Wayland** desktops for Linus and other \*nix distributions.
Linus Torvalds would probably
but it's really:
for Linux and other \*nix distributions.
Caught by: the Tpyo Knig!
Tpyo Knig!
Is that undisputed champion?
Thanks, will be fixed.
Trying to reduce the width and height of the xwwall window and images, by tinkering with the width/height values in the script.
On my 1920x1080 screen, thumbnails in the main_gui window are now 160px wide - whereas those in the selection- and confirm_gui are both 320px wide.
In order to adjust the main_gui window width, I had to increase the spinbutton range-max (#487) value, as it needs a little higher value than than -200 as scripted.
I can change to [+-]300, no problem.
Wondering whether it would be possible to skip the last confirm_gui window --> and set the wallpaper when pressing the selection image instead?
Definitely and a good idea for single monitor setups. The confirm_gui is really designed with multi-monitor setups in mind, so I'll work on that soon.
Thank you both for feedback.
#!/bin/sh
echo '#include <stdio.h>\nvoid main() { printf("Hi, bunsenlabs\\n"); return; }' > bunsen.c
gcc bunsen.c -o bunsen
./bunsen
Offline
I've migrated the code to Github. https://github.com/01micko/xwwall
Direct link to xwwall script
If you like you can install it under /usr/local
using the Makefile. DESTDIR
and uninstall
are supported.
Changes
------------
Replaced button_gui
with @johnraff's array version. I think it is a few milliseconds faster which may show up better on older kit and especially in X11. I find the script is noticeably faster in wayland but that's more the platform than the script.
remove need for 'confirm_gui' when on a single monitor.
fix manpage typos thanks to the Poty Gink, @Sector11
add a another config otpion to adjust height of GUI and width of images thanks to @ceeslans. May be a little fiddly but works well and once set you can forget.
removed a little more redundant code
TODO: debianization.
#!/bin/sh
echo '#include <stdio.h>\nvoid main() { printf("Hi, bunsenlabs\\n"); return; }' > bunsen.c
gcc bunsen.c -o bunsen
./bunsen
Offline
A quick video on the Boron VM (youtube)
Also debianization is done, same for carbon and boron, lintian doesn't complain in carbon about the 4.6.2 standard.
#!/bin/sh
echo '#include <stdio.h>\nvoid main() { printf("Hi, bunsenlabs\\n"); return; }' > bunsen.c
gcc bunsen.c -o bunsen
./bunsen
Offline