Draw a wallpaper on a machine that has no theme yet

Seeding the config gets the bar and the keybindings up, and then leaves
you looking at a black screen, because the autostart line that sets the
wallpaper named ~/.local/share/wallpapers/hyprcosmic/current directly.
That is a symlink import-theme --assets maintains, so it does not exist
until a theme has been imported -- which on a machine that has just
installed the package it has not.

The same line waited for the daemon with an unbounded loop:

    until awww query >/dev/null 2>&1; do sleep 0.2; done

awww is a Recommends and lives in a COPR, so on a machine that never
enabled that repository nothing ever answered and the loop spun at 5 Hz
for the length of the session.

Both now live in hyprcosmic-wallpaper, which falls back to the
distribution's own images when there is no link yet, gives up on the
daemon after ten seconds, and exits 0 on every path so autostart is never
left supervising a process that cannot finish. Fedora recommends
cosmic-wallpapers so the fallback has something to find; nothing in the
dependency chain pulled it in before.

Verified against all five paths: no awww at all, a daemon that never
answers, a fresh machine with no link, a link pointing at a real file,
and a link left dangling by a deleted theme.
This commit is contained in:
2026-08-11 18:25:24 +07:00
parent 111f3ade7b
commit e006e95e55
5 changed files with 113 additions and 16 deletions
+9
View File
@@ -195,6 +195,15 @@ Runtime dependencies of the shell itself are not COSMIC's and are not built
here: `waybar`, `rofi` (wayland build), `awww` (formerly `swww`), and a Nerd
Font for the glyphs the bar and the launcher draw with.
The wallpaper is `awww`'s job, and the image it draws is
`~/.local/share/wallpapers/hyprcosmic/current` — a symlink `import-theme
--assets` maintains. Before you have imported a theme there is no such link, so
`hyprcosmic-wallpaper` falls back to whatever the distribution ships,
`/usr/share/backgrounds/cosmic` first; the Fedora package recommends
`cosmic-wallpapers` so there is something there. With no `awww` installed it
says so on the session log and leaves the background alone, rather than waiting
for a daemon that is never coming.
The font is the one thing the packaging cannot do for you on Fedora, which has
no package that provides a Nerd Font at all: `texlive-inconsolata-nerd-font`
installs under `texmf-dist` and kitty's `SymbolsNerdFont` under
+14 -16
View File
@@ -60,28 +60,26 @@ awww-daemon
# get a blank screen below the bar with no error anywhere: the failure is that
# nobody asked for a wallpaper, so nothing reports one missing.
#
# `sh -c` rather than a bare `awww img`, for one reason: awww-daemon above has
# only just been forked and is not listening yet, so an immediate `awww img`
# loses a race and fails silently. The loop waits for the daemon to answer
# before setting the image.
# It sets ~/.local/share/wallpapers/hyprcosmic/current, a symlink
# `hyprcosmic-conf import-theme --assets` maintains beside the wallpapers it
# copies. The link is used rather than a real path so that this and rofi's
# local.rasi -- which shows the same image in the launcher's sidebar -- cannot
# drift apart, and so that importing a different theme does not leave either
# pointing at a file that no longer exists.
#
# This does not weaken the no-shell rule in the header. That rule exists so a
# file naming programs cannot be escalated into arbitrary execution; naming
# `sh` explicitly is just naming a program, and anyone able to write this file
# could already name any binary on the system.
#
# `current` is a symlink `cosmic-conf import-theme --assets` maintains beside
# the wallpapers it copies, pointing at one of them. It is named here rather
# than a real file so that this line and rofi's local.rasi -- which shows the
# same image in the launcher's sidebar -- cannot drift apart, and so that
# importing a different theme does not leave this pointing at a path that no
# longer exists.
# Until a theme has been imported there is no such link, so on a machine that
# has just installed the package it falls back to whatever the distribution
# ships, /usr/share/backgrounds/cosmic first. A first login gets a desktop.
#
# Change the wallpaper by repointing the link, not by editing this file:
#
# ln -sfn ~/".local/share/wallpapers/hyprcosmic/<theme>/<image>" \
# ~/.local/share/wallpapers/hyprcosmic/current
sh -c 'until awww query >/dev/null 2>&1; do sleep 0.2; done; exec awww img "$HOME/.local/share/wallpapers/hyprcosmic/current"'
#
# A program rather than the `sh -c` this used to be, because waiting for the
# daemon needs a bound: awww is a Recommends in a COPR, and the old unbounded
# `until awww query` loop spun for the whole session on a machine without it.
hyprcosmic-wallpaper
# A terminal, unconditionally, as the way back in.
#
+81
View File
@@ -0,0 +1,81 @@
#!/bin/sh
# Set the desktop wallpaper once the wallpaper daemon is listening.
#
# The hyprcosmic profile does not start cosmic-bg, so nothing else draws a
# background: without this there is a black screen below the bar, and no error
# anywhere, because the failure is that nobody asked for a wallpaper.
#
# This was three shell fragments on one autostart line. It became a program for
# two reasons, both of which cost a first login its desktop:
#
# - `current` is a symlink `import-theme --assets` maintains, so it does not
# exist until a theme has been imported. Naming it directly meant a machine
# that had just installed the package set no wallpaper at all.
# - The wait for the daemon was `until awww query; do sleep 0.2; done`, with
# nothing to stop it. awww is a Recommends and lives in a COPR, so on a
# machine that never enabled that repository the loop spun at 5 Hz for the
# length of the session.
#
# Both are now bounded and both say so on the session log.
set -eu
link="${XDG_DATA_HOME:-$HOME/.local/share}/wallpapers/hyprcosmic/current"
# Searched in order when the link is not there yet. The first is cosmic-wallpapers,
# which the Fedora package recommends for exactly this; the other two are where
# freedesktop and KDE put theirs, so a machine with neither still has a chance.
fallbacks='/usr/share/backgrounds/cosmic /usr/share/backgrounds /usr/share/wallpapers'
if ! command -v awww >/dev/null 2>&1; then
echo "hyprcosmic-wallpaper: awww is not installed; no wallpaper set" >&2
exit 0
fi
# awww-daemon is started immediately above this in autostart and has only just
# been forked, so an immediate `awww img` loses the race and fails silently.
# Ten seconds is far longer than the daemon has ever taken and short enough that
# a daemon which is never coming does not leave a process spinning all session.
tries=0
until awww query >/dev/null 2>&1; do
tries=$((tries + 1))
if [ "$tries" -ge 50 ]; then
echo "hyprcosmic-wallpaper: awww-daemon did not answer in 10s; no wallpaper set" >&2
exit 0
fi
sleep 0.2
done
# -e rather than -L, deliberately: it follows the link, so a `current` left
# dangling by a deleted theme falls through to the defaults instead of being
# handed to awww as a path that is not there.
img=''
if [ -e "$link" ]; then
img=$link
else
for dir in $fallbacks; do
[ -d "$dir" ] || continue
for candidate in "$dir"/*.jpg "$dir"/*.jpeg "$dir"/*.png; do
# The glob is literal when nothing matches, which is why
# this tests the file rather than trusting the expansion.
[ -f "$candidate" ] || continue
img=$candidate
break
done
# An if, not `[ -n "$img" ] && break`: under set -e a trailing
# false at the end of the loop body would take the script with it.
if [ -n "$img" ]; then
break
fi
done
if [ -n "$img" ]; then
echo "hyprcosmic-wallpaper: no $link yet, falling back to $img" >&2
fi
fi
if [ -z "$img" ]; then
echo "hyprcosmic-wallpaper: no wallpaper found in $link or $fallbacks" >&2
exit 0
fi
exec awww img "$img"
+8
View File
@@ -81,6 +81,14 @@ Requires: rofi-wayland
# unsatisfiable dependency is not.
Recommends: awww
# Something for the wallpaper daemon to draw before a theme has been imported.
# hyprcosmic-wallpaper looks here first when ~/.local/share/wallpapers has no
# `current` link yet, which on a machine that has just installed this package is
# always. Nothing in the dependency chain pulls it in otherwise -- neither
# cosmic-session nor cosmic-comp requires it -- and without it a first login is
# a bar on a black screen.
Recommends: cosmic-wallpapers
# Nerd Font glyphs are most of what the bar and the launcher draw, and Fedora
# has nothing that provides them. This line used to say `nerd-fonts`, which is
# not a package in any Fedora repository -- so it could never be satisfied, and
+1
View File
@@ -78,6 +78,7 @@ SHARED=(
"config/bin/hyprcosmic-powermenu:bin/hyprcosmic-powermenu:755"
"config/bin/hyprcosmic-fan:bin/hyprcosmic-fan:755"
"config/bin/hyprcosmic-keybinds:bin/hyprcosmic-keybinds:755"
"config/bin/hyprcosmic-wallpaper:bin/hyprcosmic-wallpaper:755"
)
# The session entry point. Kept apart from SHARED because it is versioned in the