You are not logged in.
@johnraff I've decided to go with the simplest test of all.
...testingpidof Xorg
should be more than enough to differentiate graphical sessions.
Yes that makes sense...
...at first. (Sorry, I'm playing devil's advocate here.)
Try running 'pidof Xorg' in a Wayland session that's been started from LightDM.
You'll get the pid of the X session that LightDM's running on.
Same problem with grepping 'ps aux'.
What was the issue with WAYLAND_DISPLAY?
...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
micko01 wrote:@johnraff I've decided to go with the simplest test of all.
...testingpidof Xorg
should be more than enough to differentiate graphical sessions.Yes that makes sense...
...at first. (Sorry, I'm playing devil's advocate here.)
Try running 'pidof Xorg' in a Wayland session that's been started from LightDM.
You'll get the pid of the X session that LightDM's running on.
If that happens then that's a bug. If Xorg is still hanging around after lightdm is launched and done it's thing I would dare say it's a severe bug because memory is leaking.
In my recently installed trixie VM (xfce chosen in netinstall, like my original system) lightdm is the default session manager and I've just launched xfce4-session (wayland) from that.
mick@trix:~$ pidof Xorg
mick@trix:~$ echo $XDG_SESSION_TYPE
wayland
mick@trix:~$
On my current system launched by greetd -> cage -> nwg-hello
I have this:
mick@dellhome:~$ pidof labwc
1313
mick@dellhome:~$ pidof cage
mick@dellhome:~$ pidof Xorg
mick@dellhome:~$
Same problem with grepping 'ps aux'.
What was the issue with WAYLAND_DISPLAY?
Not always reliably set in sway, and I assume in other compositors.
EDIT to add:
It's only actually lightdm
that should be running. A graphical environment is only needed for the greeter. In lightdm that case is lightdm-gtk-greeter or slick-greeter or whatever. In the greetd case nwg-hello, gtk-greet or whatever.
Last edited by micko01 (2025-01-14 10:14:29)
#!/bin/sh
echo '#include <stdio.h>\nvoid main() { printf("Hi, bunsenlabs\\n"); return; }' > bunsen.c
gcc bunsen.c -o bunsen
./bunsen
Offline
@johnraff I've decided to go with the simplest test of all.
I asked myself, "what is common with all X11 window managers?" Answer.. Xorg.
So naturally a graphical user interface must be running for GTK to work, and AFAIK there are only 2 in linux (excluding legacy stuff like Xvesa) , X11 and Wayland, so testing
pidof Xorg
should be more than enough to differentiate graphical sessions. If there is anything else out there then it's not in scope for a simple application like this anyway.
Seems the simplest methods are the most elegant. If you get a PID back from the call to pidof, X11 is running and if you get nothing back then it's either Wayland or you are not even in a graphical session (eg CLI).
Real Men Use Linux
Offline
johnraff wrote:Try running 'pidof Xorg' in a Wayland session that's been started from LightDM.
You'll get the pid of the X session that LightDM's running on.If that happens then that's a bug. If Xorg is still hanging around after lightdm is launched and done it's thing I would dare say it's a severe bug because memory is leaking.
It would have been a bug yes.
I was wrong to say the session had been "started from LightDM". What I did was boot up to the LightDM login screen, then open TTY2 and run 'labwc'. Of course lightdm-gtk-greeter was still running on Xorg on TTY7.
It's only actually
lightdm
that should be running. A graphical environment is only needed for the greeter.
Right. Confirmed - LightDM is still running after launching (in the normal way) a Wayland session, but Xorg is not.
So when 'pidof Xorg' gives an incorrect result is only that extreme corner case of a user (developer?) leaving the login screen as-is and going off to launch a Wayland session on a different TTY. Or of course, any other case where there is a separate X session running on a different TTY.
(I've just confirmed that Xwayland apps don't invoke Xorg.)
Anyway, it looks quite tricky to find a test whether an app is running on a wayland compositor which is 100% reliable in all situations.* As the dev you should just make your own call I guess.
* If we ever come up with a good sequence of tests in a function UsingWayland() that can be invoked at the top of a script, we should ship it in /usr/lib/bunsen/common/bl-includes
...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
@micko01 I was just about to start a new topic on how to "find a test whether an app is running on a wayland compositor" but I had another idea which might possibly do it.
tl:dr
## near top of script
if wlr-randr >/dev/null 2>&1
then
local_session_type=wayland
else
local_session_type=xorg
fi
export local_session_type
# now refer to $local_session_type later in script
wlr-randr is already a dependency of xwwall and runs very quickly. Anyway, the test only needs doing once.
I was trying to think of some minimal app which would try to actually make a connection to the Wayland compositor and then exit, wondering how hard it would be to write one in C, then realized that wlr-randr was already around.
A thought.
...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
@micko01 I was just about to start a new topic on how to "find a test whether an app is running on a wayland compositor" but I had another idea which might possibly do it.
tl:dr
## near top of script if wlr-randr >/dev/null 2>&1 then local_session_type=wayland else local_session_type=xorg fi export local_session_type # now refer to $local_session_type later in script
wlr-randr is already a dependency of xwwall and runs very quickly. Anyway, the test only needs doing once.
I was trying to think of some minimal app which would try to actually make a connection to the Wayland compositor and then exit, wondering how hard it would be to write one in C, then realized that wlr-randr was already around.A thought.
Yes, looks like a reasonable test.
Only a oneliner works for me.
wlr-randr >/dev/null 2>&1 && export WAYLAND=yes
#!/bin/sh
echo '#include <stdio.h>\nvoid main() { printf("Hi, bunsenlabs\\n"); return; }' > bunsen.c
gcc bunsen.c -o bunsen
./bunsen
Offline
wlr-randr would have to be a hard dependency instead of optional, but it's only 44.0 kB.
...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
wlr-randr would have to be a hard dependency instead of optional, but it's only 44.0 kB.
If it's not installed the test should fail and we'd be on X right?
Anyway, have added extra directories, a bit of a mission but @ceeslan's advice was helpful, code soon.
It's a second GUI over the top of the first but the second is a child of the first so no funny business goes on. Note no yes/no/whatever buttons in the child so the parent is in control.
Last edited by micko01 (2025-01-19 04:57:24)
#!/bin/sh
echo '#include <stdio.h>\nvoid main() { printf("Hi, bunsenlabs\\n"); return; }' > bunsen.c
gcc bunsen.c -o bunsen
./bunsen
Offline
New version https://raw.githubusercontent.com/01mic … bin/xwwall
add wlr-randr test, @johnraff
add support for up to 3 directories, @ceeslans
add -d|--delconf
option to delete $HOME/.config/xwwall/xwwall.conf in case of user mess up
update man page
bump version to 0.1.3
The testing branch man page may be useful: https://github.com/01micko/xwwall/blob/ … wall.1.rst
#!/bin/sh
echo '#include <stdio.h>\nvoid main() { printf("Hi, bunsenlabs\\n"); return; }' > bunsen.c
gcc bunsen.c -o bunsen
./bunsen
Offline
johnraff wrote:wlr-randr would have to be a hard dependency instead of optional, but it's only 44.0 kB.
If it's not installed the test should fail and we'd be on X right?
What about users who want to run this on both X and W? If they already had x11-xserver-utils installed they wouldn't get wlr-randr pulled in.
...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
micko01 wrote:johnraff wrote:wlr-randr would have to be a hard dependency instead of optional, but it's only 44.0 kB.
If it's not installed the test should fail and we'd be on X right?
What about users who want to run this on both X and W? If they already had x11-xserver-utils installed they wouldn't get wlr-randr pulled in.
I don't know what happened but this post had the dependency check, borrowed from bl-includes. That would show it up. However a few wayland things doesn't hurt, especially if small enough.
#!/bin/sh
echo '#include <stdio.h>\nvoid main() { printf("Hi, bunsenlabs\\n"); return; }' > bunsen.c
gcc bunsen.c -o bunsen
./bunsen
Offline
I have done a fairly major refactor such that the main_gui doesn't need to die, but there are some trade offs, and they are quite technical.
TLDR: Go to the code and fetch it!
In the beginning I had the MAINGUI
persistent but that caused issues if you clicked anything in it while the preview (SUBGUI
) window was open so I resorted to running the program in a loop to kill the MAINGUI while the SUBGUI was open. It works well but makes the program a bit clunky, which IMHO is not really acceptable as it lacks polish.
Fortunately, gtk3dialog
is a very powerful GUI building app with lots of features that I didn't use in the early iterations. It has the capability to fire off signals under a variety of different scenarios. To mention a few:
as an attribute to the action
tag one can use different functions and signals.
the signal button-press-event
is very handy for handling timing issues
the same goes for button-release-event
a file-monitor
is an excellent way of controlling timing issues as well.
the close-window
function is very useful
making a GUI sensitive
or insensitive
at the button press/release and changing the monitored temp file is how this thing now works
All of these features are reasonably well documented in the native docs.
Now the program does not clunk around and feel rusty, but rather feels smooth and a little more professional.
There is a trade off. Due to a few more lines in the button_gui
function I've had to reduce the number of allowed images to 250 from 300. I think the change is worth it, especially since you can now configure extra directories if you like.
Of course that doesn't mean it's bug free. I could have introduced some bugs or annoyances. Let me know. I did test in X11 and wayland with my dual monitors, yet to test on a single monitor or multiple (> 2) monitors. However that part of the code is pretty much unchanged so I'd be surprised if that fails at some point. I will test on a single monitor after I post this and edit accordingly if need be.
EDIT0: there was a small bug with single monitors. There is no confirm_gui
with single monitors so the preview GUI (SUBGUI) should close the MAINGUI. Fixed.
The code.
#!/bin/bash
export V=0.1.2alpha
export GTK3DIALOG
export MAINGUI
[[ -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"
wlr-randr >/dev/null 2>&1 && export WAYLAND=yes
case "$1" in
--restore)
PROFILE="$2"
echo $PROFILE
if [[ -n "$PROFILE" && -r "$CONFDIR/$PROFILE/cmd" ]]; then
. "$CONFDIR/$PROFILE/cmd" && exit 0
elif [[ -n "$PROFILE" && -x "$CONFDIR/$PROFILE/.fehbg" ]]; then
exec "$CONFDIR/$PROFILE/.fehbg"
fi
if [[ -f "$CONFDIR/cmd" && "$WAYLAND" == 'yes' ]]; then
. "$CONFDIR/cmd" && exit 0
elif [[ -x "$HOME/.fehbg" ]]; then
exec "$HOME/.fehbg"
else
exit 1
fi
;;
-d|--delconf)
rm -f "$CONF"
exit 0
;;
-*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 -d|--delconf\n\t\tdelete $CONF"
echo -e "\t\tif $PROG doesn't startand exit.\n"
echo -e "\t$PROG --restore\n\t\trestore backgrounds at session start."
echo -e "\tAn optional argumant \"\$PROFILE\" is supported.\n"
echo -e "\ttry \"man $PROG\" for more information."
exit 0
;;
esac
# sort out the monitors and positions
if [[ "$WAYLAND" == 'yes' ]]; 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
[[ -z "$COLOR" ]] && COLOR=666666
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);
}
#ent {
background: @theme_selected_bg_color;
}
#noent {
background: @theme_bg_color;
color: @theme_fg_color;
border: none;
}
#cbg {
background: '#${COLOR}';
}
' > "$TEMP/win.css"
# get the primary output
[[ -z "$TWIDTH" ]] && TWIDTH=9
case $TWIDTH in
12)THEIGHT=8;;
11)THEIGHT=9;;
10)THEIGHT=10;;
9)THEIGHT=11;;
8)THEIGHT=12;;
esac
e=0
if [[ "$WAYLAND" == 'yes' ]]; 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 / TWIDTH))
export MWdth=$((X / 2))
export MHght=$(((Y * 2 / 3) / 11 * THEIGHT))
echo "GUI: MWdth=$MWdth x MHght=$MHght"
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 $f $TEMP/xx2$e && e=$((e+1))
done
rm $TEMP/Xmonitor* # finished with these
export NUM
read -r NUM < "$TEMP/number"
echo $NUM outputs
. $TEMP/xx0
export Wdth=$((X / TWIDTH))
export MWdth=$((X / 2))
export MHght=$(((Y * 2 / 3) / 11 * THEIGHT))
echo "GUI: MWdth=$MWdth x MHght=$MHght"
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;;
7)E_VAL=Warning;CR=-c;;
*)CR=--geometry=+$((X/2-180))+150;ACT='<action>exit:OK</action>';;
esac
IVAL=4
re='^[0-9]'
[[ $3 =~ $re ]] && IVAL=$3
if [[ "$WAYLAND" == 'yes' ]]; 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">
<vbox>
<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>
'$RADIO'
</hbox>
<hbox name="splash">
'$DIS'
<button>
<label>OK</label>
<input file icon="gtk-ok"></input>
'$ACT'
</button>
</hbox>
</vbox>
</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 name="cbg" tooltip-text="'${sel##*\/}'">
<width>220</width>
<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>
<action signal="button-press-event">echo sleep > '$TEMP/wake'</action>
<action signal="button-release-event">exit:Yes</action>
</button>
<button no>
<action>rm -f '$TEMP/increment'</action>
<action>exit:No</action>
</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; read -r a b c <<<$(ps -u | grep -m1 'main_gui'); kill -9 $b;;
REFRESH)rm -f $TEMP/increment $TEMP/selected $TEMP/[XW]set $TEMP/ret;;
*)rm -f $TEMP/$TEMP/increment $TEMP/selected $TEMP/[XW]set $TEMP/ret; return 1;;
esac
}; export -f confirm_gui
# build options for output
_output() {
[[ "$WAYLAND" == 'yes' ]] && 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
[[ -r "$TEMP/increment" ]] || echo -n 1 > "$TEMP/increment"
INC=$(cat $TEMP/increment)
case $INC in
1)DEFAULT=$(sed '1s/item/default/g' < $TEMP/OP | sed -n 1p); echo "$DEFAULT" > $TEMP/default_ent ;;
2)DEFAULT=$(sed '2s/item/default/g' < $TEMP/OP | sed -n 2p); echo "$DEFAULT" > $TEMP/default_ent ;;
3)DEFAULT=$(sed '3s/item/default/g' < $TEMP/OP | sed -n 3p); echo "$DEFAULT" > $TEMP/default_ent ;;
4)DEFAULT=$(sed '4s/item/default/g' < $TEMP/OP | sed -n 4p); echo "$DEFAULT" > $TEMP/default_ent ;;
5)DEFAULT=$(sed '5s/item/default/g' < $TEMP/OP | sed -n 5p); echo "$DEFAULT" > $TEMP/default_ent ;;
6)DEFAULT=$(sed '6s/item/default/g' < $TEMP/OP | sed -n 6p); echo "$DEFAULT" > $TEMP/default_ent ;;
esac
read -r DEF < $TEMP/default_ent
. "$CONF"
sub_gui "$FBG" $INC $DEF
}; export -f _output
# populate buttons for the main GUI
button_gui() {
local c i j n WALL V buttonsx buttons
. "$CONF"
if [[ "$XTRAS" == 'false' || -z "$XTRAS" ]]; then
echo "$BGDIR"
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 name="cbg" image-position="top" tooltip-text="'"${WALL##*/}"'">
<variable>BG'$c'</variable>
<input file>'"\"$WALL\""'</input>
<height>'$Wdth'</height>
<width>'$Wdth'</width>
<action signal="button-press-event">_output '"\"$WALL\""' &</action>
<action signal="button-release-event" type="disable">MAINGUI</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"
elif [[ "$XTRAS" == 'true' ]]; then
echo "${EXTRA_BGDIRS[@]}"
c=0
n=0
while [[ n -lt "${#EXTRA_BGDIRS[@]}" ]]
do
shopt -s globstar
for WALL in "${EXTRA_BGDIRS[n]}"/*{,/**}
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 name="cbg" image-position="top" tooltip-text="'"${WALL##*/}"'">
<variable>BG'$c'</variable>
<input file>'"\"$WALL\""'</input>
<height>'$Wdth'</height>
<width>'$Wdth'</width>
<action signal="button-press-event">_output '"\"$WALL\""' &</action>
<action signal="button-release-event" type="disable">MAINGUI</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
n=$((n+1))
done
for j in "${!buttonsx[@]}"
do buttons+=" <hbox>
${buttonsx[j]}
</hbox>"$'\n'
done
echo "$buttons" > "$TEMP/buttons"
fi
}
# sub GUI
sub_gui() {
INC=$2 DEF=$3
[[ -z "$COLOR" ]] && COLOR=999999
if [[ "$WAYLAND" == 'yes' ]]; then
CCOL="-c $COLOR"
XMODE='<item>tile</item>'
SS='Wset'
ACTION='<action signal="button-press-event">echo -e " -o $OUT -m $MODE '$CCOL' -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}"
[[ $NUM -eq 1 ]] && XMODE='<item>fill</item>'
SS='Xwset'
ACTION='<action signal="button-press-event">if [[ "$MODE" == "stretch" || "$MODE" == "fit" ]];then MODE=fill;fi; echo -e " --bg-$MODE '${XCOL}' '\'$1\'' \\" >> '$TEMP/$SS'</action>'
fi
if [[ $NUM -eq 1 ]]; then
DO_ACTION='<action signal="button-press-event">_build_command &</action>'
ETT='Pressing image will confirm,'
XTRACTION='<action signal="button-release-event">echo sleep > '$TEMP/wake'</action>
<action signal="button-release-event">exit:Yes</action>'
else
DO_ACTION='<action signal="button-press-event">if [[ '$INC' -ge '$NUM' ]]; then confirm_gui;fi &</action>'
ETT='Pressing image will save, you can confirm later,'
fi
MTEXT='Choose the Mode.'
if [[ $INC -eq $NUM && "$WAYLAND" != 'yes' ]]; then # only for X11
COMBO='<hbox space-expand="false" space-fill="false">
<entry name="noent" editable="false"><default>Mode:</default><sensitive>false</sensitive></entry>
<hseparator space-expand="true" space-fill="true" name="sep"></hseparator>
<comboboxtext space-expand="true" space-fill="true">
<variable>MODE</variable>
<item>max</item>
<item>stretch</item>
<item>fit</item>
<item>center</item>
'$XMODE'
</comboboxtext>
</hbox>'
elif [[ "$WAYLAND" == 'yes' ]]; then
COMBO='<hbox space-expand="false" space-fill="false">
<entry name="noent" editable="false"><default>Mode:</default><sensitive>false</sensitive></entry>
<hseparator space-expand="true" space-fill="true" name="sep"></hseparator>
<comboboxtext space-expand="true" space-fill="true">
<variable>MODE</variable>
<item>stretch</item>
<item>fill</item>
<item>fit</item>
<item>center</item>
<item>tile</item>
</comboboxtext>
</hbox>'
fi
export SUBGUI='<window icon-name="xwwall" title="Selection">
<vbox>
<hbox space-expand="true" space-fill="true">
<text><label>'$MTEXT' Press the image to set.</label></text>
</hbox>
'$COMBO'
<hbox space-expand="false" space-fill="false">
<entry name="noent" editable="false"><default>Output: '$INC'</default><sensitive>false</sensitive></entry>
<hseparator space-expand="true" space-fill="true" name="sep"></hseparator>
<entry name="ent" editable="false" width-chars="12">
<variable>OUT</variable>
'$DEF'
</entry>
</hbox>
<hbox space-expand="true" space-fill="true">
<button name="cbg" tooltip-text="'"${1##*/}"$'\n'''$ETT' or Press No to reject and confinue.">
<variable>CBG</variable>
<input file>'$1'</input>
<width>320</width>
<action signal="button-press-event">echo -n '$((INC+1))' > $TEMP/increment</action>
<action signal="button-press-event">echo '$1' >> '$TEMP'/selected</action>
'$ACTION'
<action>sed -i -e "s% .$%%g" '$TEMP/$SS'</action>
<action signal="button-press-event">echo wake > '$TEMP/wake'</action>
'$DO_ACTION'
'$XTRACTION'
<action signal="button-release-event">exit:SUB</action>
</button>
</hbox>
<hbox>
<button no>
<action signal="button-press-event">echo wake > '$TEMP/wake'</action>
<action signal="button-release-event">exit:NO</action>
</button>
</hbox>
</vbox>
<variable>SUBGUI</variable>
</window>'
eval $($GTK3DIALOG -p SUBGUI -c --styles=$TEMP/win.css)
case $EXIT in
Yes)read -r a b c <<<$(ps -u | grep -m1 'main_gui'); kill -9 $b;;
esac
}; export -f sub_gui
# populate the main GUI
main_gui() {
echo 'sleep' > "$TEMP/wake"
[[ -z "$SWIDTH" ]] && SWIDTH=0
[[ -r "$TEMP/main_gui.xml" ]] && _splash "Please wait ..." 6 2 &
BUTTONS=$(cat $TEMP/buttons)
export MAINGUI='<window icon-name="xwwall" file-monitor="true" auto-refresh="true" 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="'$MHght'" width="'$((MWdth+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>
<variable>MAINGUI</variable>
<input file>'$TEMP/wake'</input>
<action signal="file-changed" type="enable">MAINGUI</action>
</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"
if [[ -n "$EXTRA_BGDIRS" ]]; then
[[ -n "$XTRAS" ]] || XTRAS=true
DXTRA=' <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 extra directories.</label>
<variable>CXTRA</variable>
<default>'$XTRAS'</default>
</checkbox>
</hbox>
</hbox>'
fi
export EXTRA_DIRS='<window icon-name="gtk-preferences" title="Extra Directories" width-request="400">
<vbox>
<hbox space-expand="true" space-fill="true">
<text use-markup="true"><label>"<b>Select extra directories.</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>
<hseparator name="ent" space-expand="true" space-fill="true"></hseparator>
<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" fs-title="'$PROG'">
<variable>BACKGROUNDS0</variable>
</entry>
</hbox>
<hbox space-expand="false" space-fill="false">
<button>
<input file icon="directory-open"></input>
<variable>FILE_BROWSE_DIRECTORY0</variable>
<action function="fileselect">BACKGROUNDS0</action>
</button>
</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 accept="directory" fs-title="'$PROG'">
<variable>BACKGROUNDS1</variable>
</entry>
</hbox>
<hbox space-expand="false" space-fill="false">
<button>
<input file icon="directory-open"></input>
<variable>FILE_BROWSE_DIRECTORY1</variable>
<action function="fileselect">BACKGROUNDS1</action>
</button>
</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 accept="directory" fs-title="'$PROG'">
<variable>BACKGROUNDS2</variable>
</entry>
</hbox>
<hbox space-expand="false" space-fill="false">
<button>
<input file icon="directory-open"></input>
<variable>FILE_BROWSE_DIRECTORY2</variable>
<action function="fileselect">BACKGROUNDS2</action>
</button>
</hbox>
</hbox>
</vbox>
<variable>EXTRA_DIRS</variable>
</window>
'
[[ "$SPLASH" == 'false' ]] && CDEF=false || CDEF=true
[[ -n "$COLOR" ]] && DEFCOL=#${COLOR} || DEFCOL=#666666
[[ -n "$SWIDTH" ]] && SW=$SWIDTH || SW=0
[[ -n "$TWIDTH" ]] && TW=$TWIDTH || TW=9
if [[ $NUM -gt 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>
<hseparator name="ent" space-expand="true" space-fill="true"></hseparator>
<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" fs-title="'$PROG'">
<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>
<hseparator space-expand="true" space-fill="true"></hseparator>
<hbox space-expand="true" space-fill="true">
<hbox space-expand="true" space-fill="true">
<text label="Optionally choose extra directories"></text>
</hbox>
<hseparator space-expand="true" space-fill="true" name="sep"></hseparator>
<hbox space-expand="true" space-fill="true">
<button>
<label>Ok</label>
<input file icon="gtk-ok"></input>
<action function="launch">EXTRA_DIRS</action>
</button>
</hbox>
</hbox>
'$DXTRA'
'$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="GUI 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="-300" range-max="300" 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">
<hbox space-expand="false" space-fill="false">
<text label="Thumbnail adjustment" tooltip-text="Adjust the width thumbnail images. May need to adjust above setting to suit. Larger number is smaller width."></text>
</hbox>
<hseparator space-expand="true" space-fill="true" name="sep"></hseparator>
<hbox space-expand="false" space-fill="false">
<spinbutton range-min="8" range-max="12" range-step="1">
<variable>TW0</variable>
<default>'$TW'</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 ! [[ -z "$BACKGROUNDS0" && -z "$BACKGROUNDS1" && -z "$BACKGROUNDS2" ]]; then # do nothing if all vars are empty
if [[ -d "$BACKGROUNDS0" || -d "$BACKGROUNDS1" || -d "$BACKGROUNDS2" ]]; then
if grep -q 'EXTRA_BGDIRS' "$CONF"; then
sed -i '/EXTRA_BGDIRS/d' "$CONF"
fi
printf "%s" "EXTRA_BGDIRS=( " >> "$CONF"
[[ -n "$BACKGROUNDS0" ]] && printf "%s" "\"$BACKGROUNDS0\" " >> "$CONF"
[[ -n "$BACKGROUNDS1" ]] && printf "%s" "\"$BACKGROUNDS1\" " >> "$CONF"
[[ -n "$BACKGROUNDS2" ]] && printf "%s" "\"$BACKGROUNDS2\" " >> "$CONF"
printf "%s\n" ")" >> "$CONF"
rm -f "$TEMP/buttons"
rm -f "$TEMP/main_gui.xml"
# since user just set these, enable them
echo "XTRAS=true" >> "$CONF"
fi
fi
if grep -q 'SPLASH' "$CONF"; then
sed -i "s/^SPLASH.*$/SPLASH=$SPL/" "$CONF"
else
echo "SPLASH=$SPL" >> "$CONF"
fi
if grep -q 'XTRAS' "$CONF"; then
[[ -n "$CXTRA" ]] && \
sed -i "s/^XTRAS.*$/XTRAS=$CXTRA/" "$CONF"
else
[[ -n "$CXTRA" ]] && \
echo "XTRAS=$CXTRA" >> "$CONF"
fi
if grep -q 'SWIDTH' "$CONF"; then
sed -i "s/^SWIDTH.*$/SWIDTH=$SW0/" "$CONF"
else
echo "SWIDTH=$SW0" >> "$CONF"
fi
echo $BACKGROUNDS0 $BACKGROUNDS1 $BACKGROUNDS2
if grep -q 'TWIDTH' "$CONF"; then
sed -i "s/^TWIDTH.*$/TWIDTH=$TW0/" "$CONF"
else
echo "TWIDTH=$TW0" >> "$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_command() {
if [[ "$WAYLAND" == 'yes' ]]; 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
_dependencies() { # adapted from bl-includes
# Usage: _dependencies command [command...]
local missing_commands=()
i=
for i in "$@"
do
hash "$i" 2>/dev/null || missing_commands+=(" $i")
done
if [[ ${missing_commands[0]} ]];then
ERR_MSG="This script requires the following commands: \"${missing_commands[*]}\" .\
Please install the packages containing the missing commands and re-run the script."
_splash "${ERR_MSG}" 3
exit
fi
}
trap_exit() {
trap "rm -rf $TEMP" EXIT
}; export -f trap_exit
######################## main ##############################
# required programs
declare -a APPS
if [[ "$WAYLAND" == 'yes' ]]; then
APPS=( "gtk3dialog" "wlr-randr" "swaybg" )
else
APPS=( "gtk3dialog" "xrandr" "feh" )
fi
_dependencies "${APPS[@]}"
trap_exit
export PID=$$
# test for compatibility
KWNINX=$(pidof kwin_x11)
KWNINW=$(pidof kwin_wayland)
GNOME=$(pidof gnome-session) # covers X11 and wayland
XFCE4=$(pidof xfce4-session) # covers X11 and wayland
if [[ -n "$KWNINX" || "$KWNINW" || "$GNOME" || "$XFCE4" ]]; then # more to add
_splash "WARNING: Your desktop may be unsupported" 7
fi
if [[ ! -d "$BGDIR" ]]; then
_splash "Please set a background directory" 3
_pref
else
[[ -r "$BGDIR/0Solid_Color.svg" ]] || cat > "$BGDIR/0Solid_Color.svg" <<EOS
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 1366 768">
<path style="fill:rgba(0,0,0,0.0);" d="m 0,0 1366,0 0,768 -1366,0 z"/>
</svg>
EOS
fi
if [[ "$NUM" != '1' ]]; then
# this nag can be disabled in prefs
_splash "You have $NUM monitors connected. Carefully choose an image for each of them." 0 b &
fi
echo ================
button_gui
main_gui
Enjoy!
Last edited by micko01 (2025-01-26 02:35:31)
#!/bin/sh
echo '#include <stdio.h>\nvoid main() { printf("Hi, bunsenlabs\\n"); return; }' > bunsen.c
gcc bunsen.c -o bunsen
./bunsen
Offline
I have done a fairly major refactor...
I thought you'd been keeping a low profile the last few days...
Now the program does not clunk around and feel rusty, but rather feels smooth and a little more professional.
Looks very nice! This utility just gets better and better.
Of course that doesn't mean it's bug free. I could have introduced some bugs or annoyances. Let me know.
I'll do my best.
...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
OK I don't think these are new issues, just things I ran into while looking at the new code.
mode selection
1)
In sub_gui() starting at line #427
if [[ "$WAYLAND" == 'yes' ]]; then
CCOL="-c $COLOR"
XMODE='<item>tile</item>'
but XMODE is never referenced under Wayland, and under X is (sometimes) set to '<item>fill</item>'
2)
Some discrepencies between the display options on X vs W.
The display alternatives offered on Wayland are:
<item>stretch</item>
<item>fill</item>
<item>fit</item>
<item>center</item>
<item>tile</item>
and on X (with feh) are:
<item>max</item>
<item>stretch</item>
<item>fit</item>
<item>center</item>
'$XMODE'
I haven't yet checked over the Wayland setter options, but with feh on X both STRETCH and FIT result in the feh option --bg-fill (which isn't offered as "fill"), while the options --bg-scale and --bg-tile aren't offered at all.
3)
Small usability thing: with X "Max" comes at the top of the list, so is the default setting. Maybe "Stretch" would be better at the top? Nitrogen's "zoomed-fill" is the BL default and, I think, corresponds to feh's --bg-fill.
Leaving Wayland and multiple monitors for later...
...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
^Thanks for taking a look.
Some of those options are a bit of a mess and definitely need a clean up.
1) I'll sort out XMODE. TBH I can't even recall why/if it was needed!
2) At some stage I had both the same options for X and W but that didn't work out well. Let's call that WIP for now. One thing, if on X with multiple monitors only the last MODE takes. I need to test with a 3rd monitor to fine tune that.
3)
Nitrogen's "zoomed-fill" is the BL default and, I think, corresponds to feh's --bg-fill.
Thanks for that info. So, what's better? Stretch or Fill as default? Stretch I think, I think that may be your opinion too, going by
Maybe "Stretch" would be better at the top?
Anyway, my computer time will be sporadic this coming week, so I'll do what I can when I can, which is pretty much what we all do anyway, RL and all.
#!/bin/sh
echo '#include <stdio.h>\nvoid main() { printf("Hi, bunsenlabs\\n"); return; }' > bunsen.c
gcc bunsen.c -o bunsen
./bunsen
Offline
The display alternatives offered on Wayland are:
<item>stretch</item>
<item>fill</item>
<item>fit</item>
<item>center</item>
<item>tile</item>
and on X (with feh) are:
<item>max</item>
<item>stretch</item>
<item>fit</item>
<item>center</item>
'$XMODE'
Hmm, that is a actually a hangover from when I was trying to use the same options for X and W, and manipulate them with code. Turns out that's a bad idea. I'm going to use swaybg
and feh
native options going forward, but there is a bug in feh
that doesn't exist in swaybg
. If you tile
any transparent image, seems not to matter the format, it shows a garbled display, however the same transparent image using centered
works as expected. I will report it to the developer, but I doubt the fix will make trixie. This doesn't occur in swaybg
.
I'm reluctant to disable tile
as a non transparent image works just fine. I might note it in the man page, at least then user's can't say
That xwwall prog is a piece of crap! I tried to tile my smiley face and it broke my display!
to which the reply would be:
RTFM
#!/bin/sh
echo '#include <stdio.h>\nvoid main() { printf("Hi, bunsenlabs\\n"); return; }' > bunsen.c
gcc bunsen.c -o bunsen
./bunsen
Offline
Next!
add a splash at startup - requires the icon to look nice! (splashes there now only show if over 250 images or if multi monitors are present)
sort out display modes for X (to do - update manual for feh shortcoming)
make scale fill the default mode for X (feh)
add a better explanation in Preferences for GUI/thumbnail tooltips
#!/bin/bash
export V=0.1.3alpha
export GTK3DIALOG
export MAINGUI
[[ -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"
wlr-randr >/dev/null 2>&1 && export WAYLAND=yes
case "$1" in
--restore)
PROFILE="$2"
echo $PROFILE
if [[ -n "$PROFILE" && -r "$CONFDIR/$PROFILE/cmd" ]]; then
. "$CONFDIR/$PROFILE/cmd" && exit 0
elif [[ -n "$PROFILE" && -x "$CONFDIR/$PROFILE/.fehbg" ]]; then
exec "$CONFDIR/$PROFILE/.fehbg"
fi
if [[ -f "$CONFDIR/cmd" && "$WAYLAND" == 'yes' ]]; then
. "$CONFDIR/cmd" && exit 0
elif [[ -x "$HOME/.fehbg" ]]; then
exec "$HOME/.fehbg"
else
exit 1
fi
;;
-d|--delconf)
rm -f "$CONF"
exit 0
;;
-*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 -d|--delconf\n\t\tdelete $CONF"
echo -e "\t\tif $PROG doesn't startand exit.\n"
echo -e "\t$PROG --restore\n\t\trestore backgrounds at session start."
echo -e "\tAn optional argumant \"\$PROFILE\" is supported.\n"
echo -e "\ttry \"man $PROG\" for more information."
exit 0
;;
esac
# sort out the monitors and positions
if [[ "$WAYLAND" == 'yes' ]]; 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
[[ -z "$COLOR" ]] && COLOR=666666
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);
}
#ent {
background: @theme_selected_bg_color;
}
#noent {
background: @theme_bg_color;
color: @theme_fg_color;
border: none;
}
#cbg {
background: '#${COLOR}';
}
' > "$TEMP/win.css"
# get the primary output
[[ -z "$TWIDTH" ]] && TWIDTH=9
case $TWIDTH in
12)THEIGHT=8;;
11)THEIGHT=9;;
10)THEIGHT=10;;
9)THEIGHT=11;;
8)THEIGHT=12;;
esac
e=0
if [[ "$WAYLAND" == 'yes' ]]; 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 / TWIDTH))
export MWdth=$((X / 2))
export MHght=$(((Y * 2 / 3) / 11 * THEIGHT))
echo "GUI: MWdth=$MWdth x MHght=$MHght"
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 $f $TEMP/xx2$e && e=$((e+1))
done
rm $TEMP/Xmonitor* # finished with these
export NUM
read -r NUM < "$TEMP/number"
echo $NUM outputs
. $TEMP/xx0
export Wdth=$((X / TWIDTH))
export MWdth=$((X / 2))
export MHght=$(((Y * 2 / 3) / 11 * THEIGHT))
echo "GUI: MWdth=$MWdth x MHght=$MHght"
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;;
7)E_VAL=Warning;CR=-c;;
*)CR=--geometry=+$((X/2-180))+150;ACT='<action>exit:OK</action>';;
esac
IVAL=4
re='^[0-9]'
[[ $3 =~ $re ]] && IVAL=$3
if [[ "$WAYLAND" == 'yes' ]]; 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">
<vbox>
<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>
'$RADIO'
</hbox>
<hbox name="splash">
'$DIS'
<button>
<label>OK</label>
<input file icon="gtk-ok"></input>
'$ACT'
</button>
</hbox>
</vbox>
</vbox>
</window>' | $GTK3DIALOG -s "$CR" --styles=$TEMP/win.css
[[ "$2" == '1' ]] && exit $2
}; export -f _splash
# if < 250 images or on a single monitor there is no welcome splash
# on slow kit a user might want to know if the thing is starting
_greeting() {
echo '<window type-hint="6" icon-name="xwwall" '$SOPT' name="splash" title="'$PROG'" width-request="300">
<vbox name="splash" space-expand="true" space-fill="true">
<hbox space-expand="true" space-fill="true">
<pixmap>
<input file icon="xwwall"></input><width>64</width>
</pixmap>
<timer interval="3" visible="false"><action>exit:GREET</action></timer>
</hbox>
<hbox space-expand="true" space-fill="true">
<text use-markup="true">
<label>"<big><big>Welcome to '$PROG'</big></big>"</label>
</text>
</hbox>
</vbox>
</window>' | $GTK3DIALOG -s -c --styles=$TEMP/win.css
}; export -f _greeting
# sort selections
_selections() {
echo '<hbox>' > $TEMP/ret
cat $TEMP/selected | while read -r sel
do
echo ' <pixmap name="cbg" tooltip-text="'${sel##*\/}'">
<width>220</width>
<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>
<action signal="button-press-event">echo sleep > '$TEMP/wake'</action>
<action signal="button-release-event">exit:Yes</action>
</button>
<button no>
<action>rm -f '$TEMP/increment'</action>
<action>exit:No</action>
</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; read -r a b c <<<$(ps -u | grep -m1 'main_gui'); kill -9 $b;;
REFRESH)rm -f $TEMP/increment $TEMP/selected $TEMP/[XW]set $TEMP/ret;;
*)rm -f $TEMP/$TEMP/increment $TEMP/selected $TEMP/[XW]set $TEMP/ret; return 1;;
esac
}; export -f confirm_gui
# build options for output
_output() {
[[ "$WAYLAND" == 'yes' ]] && 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
[[ -r "$TEMP/increment" ]] || echo -n 1 > "$TEMP/increment"
INC=$(cat $TEMP/increment)
case $INC in
1)DEFAULT=$(sed '1s/item/default/g' < $TEMP/OP | sed -n 1p); echo "$DEFAULT" > $TEMP/default_ent ;;
2)DEFAULT=$(sed '2s/item/default/g' < $TEMP/OP | sed -n 2p); echo "$DEFAULT" > $TEMP/default_ent ;;
3)DEFAULT=$(sed '3s/item/default/g' < $TEMP/OP | sed -n 3p); echo "$DEFAULT" > $TEMP/default_ent ;;
4)DEFAULT=$(sed '4s/item/default/g' < $TEMP/OP | sed -n 4p); echo "$DEFAULT" > $TEMP/default_ent ;;
5)DEFAULT=$(sed '5s/item/default/g' < $TEMP/OP | sed -n 5p); echo "$DEFAULT" > $TEMP/default_ent ;;
6)DEFAULT=$(sed '6s/item/default/g' < $TEMP/OP | sed -n 6p); echo "$DEFAULT" > $TEMP/default_ent ;;
esac
read -r DEF < $TEMP/default_ent
. "$CONF"
sub_gui "$FBG" $INC $DEF
}; export -f _output
# populate buttons for the main GUI
button_gui() {
local c i j n WALL V buttonsx buttons
. "$CONF"
if [[ "$XTRAS" == 'false' || -z "$XTRAS" ]]; then
echo "$BGDIR"
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 name="cbg" image-position="top" tooltip-text="'"${WALL##*/}"'">
<variable>BG'$c'</variable>
<input file>'"\"$WALL\""'</input>
<height>'$Wdth'</height>
<width>'$Wdth'</width>
<action signal="button-press-event">_output '"\"$WALL\""' &</action>
<action signal="button-release-event" type="disable">MAINGUI</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"
elif [[ "$XTRAS" == 'true' ]]; then
echo "${EXTRA_BGDIRS[@]}"
c=0
n=0
while [[ n -lt "${#EXTRA_BGDIRS[@]}" ]]
do
shopt -s globstar
for WALL in "${EXTRA_BGDIRS[n]}"/*{,/**}
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 name="cbg" image-position="top" tooltip-text="'"${WALL##*/}"'">
<variable>BG'$c'</variable>
<input file>'"\"$WALL\""'</input>
<height>'$Wdth'</height>
<width>'$Wdth'</width>
<action signal="button-press-event">_output '"\"$WALL\""' &</action>
<action signal="button-release-event" type="disable">MAINGUI</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
n=$((n+1))
done
for j in "${!buttonsx[@]}"
do buttons+=" <hbox>
${buttonsx[j]}
</hbox>"$'\n'
done
echo "$buttons" > "$TEMP/buttons"
fi
}
# sub GUI
sub_gui() {
INC=$2 DEF=$3
[[ -z "$COLOR" ]] && COLOR=999999
if [[ "$WAYLAND" == 'yes' ]]; then
CCOL="-c $COLOR"
XMODE='<item>tile</item>'
SS='Wset'
ACTION='<action signal="button-press-event">echo -e " -o $OUT -m $MODE '$CCOL' -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}"
[[ $NUM -eq 1 ]] && XMODE='<item>fill</item>'
SS='Xwset'
ACTION='<action signal="button-press-event">echo -e " --bg-$MODE '${XCOL}' '\'$1\'' \\" >> '$TEMP/$SS'</action>'
fi
if [[ $NUM -eq 1 ]]; then
DO_ACTION='<action signal="button-press-event">_build_command &</action>'
ETT='Pressing image will confirm,'
XTRACTION='<action signal="button-release-event">echo sleep > '$TEMP/wake'</action>
<action signal="button-release-event">exit:Yes</action>'
else
DO_ACTION='<action signal="button-press-event">if [[ '$INC' -ge '$NUM' ]]; then confirm_gui;fi &</action>'
ETT='Pressing image will save, you can confirm later,'
fi
MTEXT='Choose the Mode.'
if [[ $INC -eq $NUM && "$WAYLAND" != 'yes' ]]; then # only for X11
COMBO='<hbox space-expand="false" space-fill="false">
<entry name="noent" editable="false"><default>Mode:</default><sensitive>false</sensitive></entry>
<hseparator space-expand="true" space-fill="true" name="sep"></hseparator>
<comboboxtext space-expand="true" space-fill="true">
<variable>MODE</variable>
<item>fill</item>
<item>max</item>
<item>scale</item>
<item>center</item>
<item>tile</item>
</comboboxtext>
</hbox>'
elif [[ "$WAYLAND" == 'yes' ]]; then
COMBO='<hbox space-expand="false" space-fill="false">
<entry name="noent" editable="false"><default>Mode:</default><sensitive>false</sensitive></entry>
<hseparator space-expand="true" space-fill="true" name="sep"></hseparator>
<comboboxtext space-expand="true" space-fill="true">
<variable>MODE</variable>
<item>fill</item>
<item>stretch</item>
<item>fit</item>
<item>center</item>
<item>tile</item>
</comboboxtext>
</hbox>'
fi
export SUBGUI='<window icon-name="xwwall" title="Selection">
<vbox>
<hbox space-expand="true" space-fill="true">
<text><label>'$MTEXT' Press the image to set.</label></text>
</hbox>
'$COMBO'
<hbox space-expand="false" space-fill="false">
<entry name="noent" editable="false"><default>Output: '$INC'</default><sensitive>false</sensitive></entry>
<hseparator space-expand="true" space-fill="true" name="sep"></hseparator>
<entry name="ent" editable="false" width-chars="12">
<variable>OUT</variable>
'$DEF'
</entry>
</hbox>
<hbox space-expand="true" space-fill="true">
<button name="cbg" tooltip-text="'"${1##*/}"$'\n'''$ETT' or Press No to reject and confinue.">
<variable>CBG</variable>
<input file>'$1'</input>
<width>320</width>
<action signal="button-press-event">echo -n '$((INC+1))' > $TEMP/increment</action>
<action signal="button-press-event">echo '$1' >> '$TEMP'/selected</action>
'$ACTION'
<action>sed -i -e "s% .$%%g" '$TEMP/$SS'</action>
<action signal="button-press-event">echo wake > '$TEMP/wake'</action>
'$DO_ACTION'
'$XTRACTION'
<action signal="button-release-event">exit:SUB</action>
</button>
</hbox>
<hbox>
<button no>
<action signal="button-press-event">echo wake > '$TEMP/wake'</action>
<action signal="button-release-event">exit:NO</action>
</button>
</hbox>
</vbox>
<variable>SUBGUI</variable>
</window>'
eval $($GTK3DIALOG -p SUBGUI -c --styles=$TEMP/win.css)
case $EXIT in
Yes)read -r a b c <<<$(ps -u | grep -m1 'main_gui'); kill -9 $b;;
esac
}; export -f sub_gui
# populate the main GUI
main_gui() {
echo 'sleep' > "$TEMP/wake"
[[ -z "$SWIDTH" ]] && SWIDTH=0
[[ -r "$TEMP/main_gui.xml" ]] && _splash "Please wait ..." 6 2 &
BUTTONS=$(cat $TEMP/buttons)
export MAINGUI='<window icon-name="xwwall" file-monitor="true" auto-refresh="true" 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="'$MHght'" width="'$((MWdth+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>
<variable>MAINGUI</variable>
<input file>'$TEMP/wake'</input>
<action signal="file-changed" type="enable">MAINGUI</action>
</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"
if [[ -n "$EXTRA_BGDIRS" ]]; then
[[ -n "$XTRAS" ]] || XTRAS=true
DXTRA=' <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 extra directories.</label>
<variable>CXTRA</variable>
<default>'$XTRAS'</default>
</checkbox>
</hbox>
</hbox>'
fi
export EXTRA_DIRS='<window icon-name="gtk-preferences" title="Extra Directories" width-request="400">
<vbox>
<hbox space-expand="true" space-fill="true">
<text use-markup="true"><label>"<b>Select extra directories.</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>
<hseparator name="ent" space-expand="true" space-fill="true"></hseparator>
<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" fs-title="'$PROG'">
<variable>BACKGROUNDS0</variable>
</entry>
</hbox>
<hbox space-expand="false" space-fill="false">
<button>
<input file icon="directory-open"></input>
<variable>FILE_BROWSE_DIRECTORY0</variable>
<action function="fileselect">BACKGROUNDS0</action>
</button>
</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 accept="directory" fs-title="'$PROG'">
<variable>BACKGROUNDS1</variable>
</entry>
</hbox>
<hbox space-expand="false" space-fill="false">
<button>
<input file icon="directory-open"></input>
<variable>FILE_BROWSE_DIRECTORY1</variable>
<action function="fileselect">BACKGROUNDS1</action>
</button>
</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 accept="directory" fs-title="'$PROG'">
<variable>BACKGROUNDS2</variable>
</entry>
</hbox>
<hbox space-expand="false" space-fill="false">
<button>
<input file icon="directory-open"></input>
<variable>FILE_BROWSE_DIRECTORY2</variable>
<action function="fileselect">BACKGROUNDS2</action>
</button>
</hbox>
</hbox>
</vbox>
<variable>EXTRA_DIRS</variable>
</window>
'
[[ "$SPLASH" == 'false' ]] && CDEF=false || CDEF=true
[[ -n "$COLOR" ]] && DEFCOL=#${COLOR} || DEFCOL=#666666
[[ -n "$SWIDTH" ]] && SW=$SWIDTH || SW=0
[[ -n "$TWIDTH" ]] && TW=$TWIDTH || TW=9
if [[ $NUM -gt 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>
<hseparator name="ent" space-expand="true" space-fill="true"></hseparator>
<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" fs-title="'$PROG'">
<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>
<hseparator space-expand="true" space-fill="true"></hseparator>
<hbox space-expand="true" space-fill="true">
<hbox space-expand="true" space-fill="true">
<text label="Optionally choose extra directories"></text>
</hbox>
<hseparator space-expand="true" space-fill="true" name="sep"></hseparator>
<hbox space-expand="true" space-fill="true">
<button>
<label>Ok</label>
<input file icon="gtk-ok"></input>
<action function="launch">EXTRA_DIRS</action>
</button>
</hbox>
</hbox>
'$DXTRA'
'$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="GUI width adjustment" tooltip-text="Adjust the width of the interface to suit. The thumbnail setting below may also need adjustment."></text>
</hbox>
<hseparator space-expand="true" space-fill="true" name="sep"></hseparator>
<hbox space-expand="false" space-fill="false">
<spinbutton range-min="-300" range-max="300" 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">
<hbox space-expand="false" space-fill="false">
<text label="Thumbnail adjustment" tooltip-text="Adjust the width of thumbnail images. May need to adjust above setting to suit. Larger number is smaller width."></text>
</hbox>
<hseparator space-expand="true" space-fill="true" name="sep"></hseparator>
<hbox space-expand="false" space-fill="false">
<spinbutton range-min="8" range-max="12" range-step="1">
<variable>TW0</variable>
<default>'$TW'</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 ! [[ -z "$BACKGROUNDS0" && -z "$BACKGROUNDS1" && -z "$BACKGROUNDS2" ]]; then # do nothing if all vars are empty
if [[ -d "$BACKGROUNDS0" || -d "$BACKGROUNDS1" || -d "$BACKGROUNDS2" ]]; then
if grep -q 'EXTRA_BGDIRS' "$CONF"; then
sed -i '/EXTRA_BGDIRS/d' "$CONF"
fi
printf "%s" "EXTRA_BGDIRS=( " >> "$CONF"
[[ -n "$BACKGROUNDS0" ]] && printf "%s" "\"$BACKGROUNDS0\" " >> "$CONF"
[[ -n "$BACKGROUNDS1" ]] && printf "%s" "\"$BACKGROUNDS1\" " >> "$CONF"
[[ -n "$BACKGROUNDS2" ]] && printf "%s" "\"$BACKGROUNDS2\" " >> "$CONF"
printf "%s\n" ")" >> "$CONF"
rm -f "$TEMP/buttons"
rm -f "$TEMP/main_gui.xml"
# since user just set these, enable them
echo "XTRAS=true" >> "$CONF"
fi
fi
if grep -q 'SPLASH' "$CONF"; then
sed -i "s/^SPLASH.*$/SPLASH=$SPL/" "$CONF"
else
echo "SPLASH=$SPL" >> "$CONF"
fi
if grep -q 'XTRAS' "$CONF"; then
[[ -n "$CXTRA" ]] && \
sed -i "s/^XTRAS.*$/XTRAS=$CXTRA/" "$CONF"
else
[[ -n "$CXTRA" ]] && \
echo "XTRAS=$CXTRA" >> "$CONF"
fi
if grep -q 'SWIDTH' "$CONF"; then
sed -i "s/^SWIDTH.*$/SWIDTH=$SW0/" "$CONF"
else
echo "SWIDTH=$SW0" >> "$CONF"
fi
echo $BACKGROUNDS0 $BACKGROUNDS1 $BACKGROUNDS2
if grep -q 'TWIDTH' "$CONF"; then
sed -i "s/^TWIDTH.*$/TWIDTH=$TW0/" "$CONF"
else
echo "TWIDTH=$TW0" >> "$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_command() {
if [[ "$WAYLAND" == 'yes' ]]; 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
_dependencies() { # adapted from bl-includes
# Usage: _dependencies command [command...]
local missing_commands=()
i=
for i in "$@"
do
hash "$i" 2>/dev/null || missing_commands+=(" $i")
done
if [[ ${missing_commands[0]} ]];then
ERR_MSG="This script requires the following commands: \"${missing_commands[*]}\" .\
Please install the packages containing the missing commands and re-run the script."
_splash "${ERR_MSG}" 3
exit
fi
}
trap_exit() {
trap "rm -rf $TEMP" EXIT
}; export -f trap_exit
######################## main ##############################
# required programs
declare -a APPS
if [[ "$WAYLAND" == 'yes' ]]; then
APPS=( "gtk3dialog" "wlr-randr" "swaybg" )
else
APPS=( "gtk3dialog" "xrandr" "feh" )
fi
_dependencies "${APPS[@]}"
trap_exit
export PID=$$
# test for compatibility
KWNINX=$(pidof kwin_x11)
KWNINW=$(pidof kwin_wayland)
GNOME=$(pidof gnome-session) # covers X11 and wayland
XFCE4=$(pidof xfce4-session) # covers X11 and wayland
if [[ -n "$KWNINX" || "$KWNINW" || "$GNOME" || "$XFCE4" ]]; then # more to add
_splash "WARNING: Your desktop may be unsupported" 7
fi
if [[ ! -d "$BGDIR" ]]; then
_splash "Please set a background directory" 3
_pref
else
[[ -r "$BGDIR/0Solid_Color.svg" ]] || cat > "$BGDIR/0Solid_Color.svg" <<EOS
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 1366 768">
<path style="fill:rgba(0,0,0,0.0);" d="m 0,0 1366,0 0,768 -1366,0 z"/>
</svg>
EOS
fi
_greeting &
if [[ "$NUM" != '1' ]]; then
# this nag can be disabled in prefs
_splash "You have $NUM monitors connected. Carefully choose an image for each of them." 0 b &
fi
echo ================
button_gui
main_gui
EDIT0: s/scale/fill/ -e s/fill/scale/ -e /stretch/fill/ -e s/fill/stretch
Last edited by micko01 (2025-01-28 10:03:49)
#!/bin/sh
echo '#include <stdio.h>\nvoid main() { printf("Hi, bunsenlabs\\n"); return; }' > bunsen.c
gcc bunsen.c -o bunsen
./bunsen
Offline
Still working as designed here in Debian 12.9, X only.
Debian 12 Beardog, SoxDog and still a Conky 1.9er
Offline
make
scale
the default mode for X (feh)
Actually, current BL default is feh --bg-fill (Nitrogen's "zoomed-fill"). This expands the image till it fills the window and trims any overflow if the aspect ratio doesn't match.
I think --bg-scale will distort the aspect ratio to fit the window.
...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
^ I love the zoom, I can't remember the last time I used anything else (I guess for a tiled wall, back then).
Yes vote for the Raffman.
No, he can't sleep on the floor. What do you think I'm yelling for?!!!
Offline