Skip to content

Instantly share code, notes, and snippets.

@danii
Created April 28, 2021 02:14
Show Gist options
  • Save danii/26b7edafeb143a863a3f49de4e3f0126 to your computer and use it in GitHub Desktop.
Save danii/26b7edafeb143a863a3f49de4e3f0126 to your computer and use it in GitHub Desktop.
An over engineered script to use feh for multi-wallpaper desktops.
#!/bin/sh
AWK_XRANDR_PARSE='/ connected/ {
split($3,sizePos,"+")
split(sizePos[1],size,"x")
print size[1] "," size[2] "," sizePos[2] "," sizePos[3]
}'
# Fetches a wallpaper for the monitor of size $1x$2. $1 is the required width,
# and $2 is the required height.
wallpaper_file() {
# Use a case or string substitution to pick out any image files you fancy on
# your system... They must be printf'd.
printf "$HOME/.desktop"
}
# Writes any line whose $2nth column is equal to that of the first line.
# Columns are split by $1.
matching() {
SENTINEL="$([ "$#" -gt 2 ] && printf '%s' "$3" || printf 'sentinel')"
awk -F"$1" -v first="$SENTINEL" \
"{if (first == \"$SENTINEL\") first = \$$2; if (\$$2 == first) print}"
}
# Writes the value within the variable named "$1".
cat() {
printf '%s' "${!1}"
}
# Writes the $2nth column. Columns are split by $1.
nth() {
awk -F"$1" "{print \$$2}"
}
# This one variable assignment takes xrandr's output, parses it via awk, runs
# the wallpaper_file, takes it's output, and combines all that information into
# a list of tuples. Each item in the list represents a monitor, and the tuple
# is roughly equivalent to 'W,H,X,Y,F', where W is width, H is height, X is the
# X position, Y is the Y position, and F is the file of the image.
DISPLAYS="$(while read X Y REST; do
printf '%s,%s,%s,%s\n' "$X" "$Y" "$REST" "$(wallpaper_file "$X" "$Y")"
done < <(xrandr | awk "$AWK_XRANDR_PARSE" | \
awk -F',' '{print $1 " " $2 " " $3 "," $4}'))"
# This simply finds the monitor that is the farthest out in the X direction,
# and is the widest. It then combines the X position and the width of the
# monitor to find the absolute width of your desktop.
PLACEMENT_WIDTH="$(cat DISPLAYS | sort -rnt, -k3 | matching , 3)"
SIZE_WIDTH="$(cat PLACEMENT_WIDTH | sort -rnt, -k1 | head -n1)"
WIDTH="$(("$(cat SIZE_WIDTH | nth , 1)" + "$(cat SIZE_WIDTH | nth , 3)"))"
# Same goes on as above, but with the height and Y direction.
PLACEMENT_HEIGHT="$(cat DISPLAYS | sort -rnt, -k4 | matching , 4)"
SIZE_HEIGHT="$(cat PLACEMENT_HEIGHT | sort -rnt, -k2 | head -n1)"
HEIGHT="$(("$(cat SIZE_HEIGHT | nth , 2)" + "$(cat SIZE_HEIGHT | nth , 4)"))"
# Take all that information, and make a wallpaper file from it via imagemagick.
magick -size $WIDTH'x'$HEIGHT canvas:black \
$(cat DISPLAYS | awk -F',' '{print $5 " -geometry " $1 "x" $2 "+" $3 "+" $4 " -composite"}') \
/tmp/wallpaper.png
# Then set it as the background.
feh --bg-fill --no-xinerama /tmp/wallpaper.png
@xathon
Copy link

xathon commented Sep 27, 2022

Thank you! To get this to work, I had to make 2 adjustments: setting the shebang to #!/bin/bash and changing line 42 to
done < <(xrandr | sed 's/primary //g' | awk "$AWK_XRANDR_PARSE" | \, since otherwise it wouldn't have included my primary display. Also, this requires Imagemagick 7 (currently not in the ubuntu apt repos, I had to build it from source).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment