You are not logged in.

#121 2025-01-14 02:40:12

johnraff
nullglob
From: Nagoya, Japan
Registered: 2015-09-09
Posts: 12,550
Website

Re: Wallpaper setter for Carbon - X11 and Wayland

micko01 wrote:

@johnraff I've decided to go with the simplest test of all.
...testing pidof 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 )

Introduction to the Bunsenlabs Boron Desktop

Offline

#122 2025-01-14 09:48:14

micko01
void main()
From: Queensland, Australia
Registered: 2024-04-07
Posts: 492
Website

Re: Wallpaper setter for Carbon - X11 and Wayland

johnraff wrote:
micko01 wrote:

@johnraff I've decided to go with the simplest test of all.
...testing pidof 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:~$ 
johnraff wrote:

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

#123 2025-01-14 20:28:10

DeepDayze
Like sands through an hourglass...
From: In Linux Land
Registered: 2017-05-28
Posts: 1,897

Re: Wallpaper setter for Carbon - X11 and Wayland

micko01 wrote:

@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

#124 2025-01-15 04:55:04

johnraff
nullglob
From: Nagoya, Japan
Registered: 2015-09-09
Posts: 12,550
Website

Re: Wallpaper setter for Carbon - X11 and Wayland

micko01 wrote:
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. roll
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.

micko01 wrote:

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. smile

* 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 )

Introduction to the Bunsenlabs Boron Desktop

Offline

#125 2025-01-16 06:44:10

johnraff
nullglob
From: Nagoya, Japan
Registered: 2015-09-09
Posts: 12,550
Website

Re: Wallpaper setter for Carbon - X11 and Wayland

@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. smile


...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 )

Introduction to the Bunsenlabs Boron Desktop

Offline

#126 2025-01-18 12:34:08

micko01
void main()
From: Queensland, Australia
Registered: 2024-04-07
Posts: 492
Website

Re: Wallpaper setter for Carbon - X11 and Wayland

johnraff wrote:

@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. smile

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

#127 2025-01-19 03:03:06

johnraff
nullglob
From: Nagoya, Japan
Registered: 2015-09-09
Posts: 12,550
Website

Re: Wallpaper setter for Carbon - X11 and Wayland

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 )

Introduction to the Bunsenlabs Boron Desktop

Offline

#128 2025-01-19 04:08:59

micko01
void main()
From: Queensland, Australia
Registered: 2024-04-07
Posts: 492
Website

Re: Wallpaper setter for Carbon - X11 and Wayland

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?

Anyway, have added extra directories, a bit of a mission but @ceeslan's advice was helpful, code soon.


KTstOQE4_t.png

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

#129 2025-01-19 04:56:12

micko01
void main()
From: Queensland, Australia
Registered: 2024-04-07
Posts: 492
Website

Re: Wallpaper setter for Carbon - X11 and Wayland

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

#130 2025-01-19 07:34:28

johnraff
nullglob
From: Nagoya, Japan
Registered: 2015-09-09
Posts: 12,550
Website

Re: Wallpaper setter for Carbon - X11 and Wayland

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.


...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 )

Introduction to the Bunsenlabs Boron Desktop

Offline

#131 2025-01-19 11:30:36

micko01
void main()
From: Queensland, Australia
Registered: 2024-04-07
Posts: 492
Website

Re: Wallpaper setter for Carbon - X11 and Wayland

johnraff wrote:
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

#132 2025-01-26 02:11:49

micko01
void main()
From: Queensland, Australia
Registered: 2024-04-07
Posts: 492
Website

Re: Wallpaper setter for Carbon - X11 and Wayland

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. smile

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

#133 2025-01-26 07:41:09

johnraff
nullglob
From: Nagoya, Japan
Registered: 2015-09-09
Posts: 12,550
Website

Re: Wallpaper setter for Carbon - X11 and Wayland

micko01 wrote:

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. smile

Looks very nice! This utility just gets better and better. cool

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. smile


...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 )

Introduction to the Bunsenlabs Boron Desktop

Offline

#134 2025-01-26 08:35:00

johnraff
nullglob
From: Nagoya, Japan
Registered: 2015-09-09
Posts: 12,550
Website

Re: Wallpaper setter for Carbon - X11 and Wayland

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 )

Introduction to the Bunsenlabs Boron Desktop

Offline

#135 2025-01-26 09:46:23

micko01
void main()
From: Queensland, Australia
Registered: 2024-04-07
Posts: 492
Website

Re: Wallpaper setter for Carbon - X11 and Wayland

^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. smile


#!/bin/sh
echo '#include <stdio.h>\nvoid main() { printf("Hi, bunsenlabs\\n"); return; }' > bunsen.c
gcc bunsen.c -o bunsen
./bunsen

Offline

#136 2025-01-27 07:12:29

micko01
void main()
From: Queensland, Australia
Registered: 2024-04-07
Posts: 492
Website

Re: Wallpaper setter for Carbon - X11 and Wayland

johnraff wrote:

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

new_user wrote:

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:

micko01 wrote:

RTFM

big_smile


#!/bin/sh
echo '#include <stdio.h>\nvoid main() { printf("Hi, bunsenlabs\\n"); return; }' > bunsen.c
gcc bunsen.c -o bunsen
./bunsen

Offline

#137 2025-01-27 07:51:42

micko01
void main()
From: Queensland, Australia
Registered: 2024-04-07
Posts: 492
Website

Re: Wallpaper setter for Carbon - X11 and Wayland

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

#138 2025-01-27 12:13:56

Sector11
Mod Squid Tpyo Knig
From: Upstairs
Registered: 2015-08-20
Posts: 8,008

Re: Wallpaper setter for Carbon - X11 and Wayland

Still working as designed here in Debian 12.9, X only.


Debian 12 Beardog, SoxDog and still a Conky 1.9er

Offline

#139 2025-01-28 01:10:20

johnraff
nullglob
From: Nagoya, Japan
Registered: 2015-09-09
Posts: 12,550
Website

Re: Wallpaper setter for Carbon - X11 and Wayland

micko01 wrote:

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 )

Introduction to the Bunsenlabs Boron Desktop

Offline

#140 2025-01-28 08:58:18

hhh
Gaucho
From: High in the Custerdome
Registered: 2015-09-17
Posts: 16,032
Website

Re: Wallpaper setter for Carbon - X11 and Wayland

^ 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

Board footer

Powered by FluxBB