diff --git a/README.md b/README.md index f721894..40de085 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/config/autostart b/config/autostart index ca3737e..c774670 100644 --- a/config/autostart +++ b/config/autostart @@ -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//" \ # ~/.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. # diff --git a/config/bin/hyprcosmic-wallpaper b/config/bin/hyprcosmic-wallpaper new file mode 100755 index 0000000..a56b408 --- /dev/null +++ b/config/bin/hyprcosmic-wallpaper @@ -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" diff --git a/packaging/fedora/hyprcosmic.spec b/packaging/fedora/hyprcosmic.spec index a1e4f94..dba4003 100644 --- a/packaging/fedora/hyprcosmic.spec +++ b/packaging/fedora/hyprcosmic.spec @@ -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 diff --git a/tools/install-assets.sh b/tools/install-assets.sh index 902dbdb..83b3b55 100755 --- a/tools/install-assets.sh +++ b/tools/install-assets.sh @@ -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