From 111f3ade7be6a38e0ca07a38fd33c66a2591c72a Mon Sep 17 00:00:00 2001 From: dingo Date: Tue, 11 Aug 2026 18:15:44 +0700 Subject: [PATCH] Ship the per-user config, and recommend a font that exists Two things anyone installing v0.1.0 would have hit. The per-user files were listed in install-assets.sh as installed 'by hand', which meant a clean machine logged in to a bare compositor with nothing drawn on it and no binding that opened anything. They are now installed as a skeleton under share/hyprcosmic/skel, laid out exactly as they sit under ~/.config, and the session copies what is missing at login. The audit still forces every file under config/ into exactly one list, so this could not be quietly skipped again. theme.css, theme.rasi and local.rasi are new and deliberately empty. They are the relative @imports of style.css and config.rasi, and a missing @import is fatal to both consumers rather than a warning they skip: GTK fails the whole stylesheet, and rofi reports the error in place of the launcher. Every colour they could define already has a default from palette.css and palette.rasi, so empty is the correct content until import-theme writes them. style.css's own header has promised 'a sibling file we create at install time' since it was written; now there is one. Recommends: nerd-fonts named a package that is in no Fedora repository, so it could never be satisfied and the font never arrived -- silently, which is what Recommends does when it cannot resolve. Fedora has no Nerd Font at all: texlive-inconsolata-nerd-font lands under texmf-dist and kitty's SymbolsNerdFont under /usr/lib64/kitty, and fontconfig scans neither. Recommend font(notosansmono) instead, the fallback rules.rasi already names, and say in the README how to install the glyphs by hand. --- README.md | 66 +++++++++++++++++++++++++------- config/rofi/local.rasi | 29 ++++++++++++++ config/rofi/theme.rasi | 16 ++++++++ config/waybar/theme.css | 18 +++++++++ cosmic-session | 2 +- packaging/fedora/hyprcosmic.spec | 18 ++++++++- tools/install-assets.sh | 51 ++++++++++++++++-------- 7 files changed, 169 insertions(+), 31 deletions(-) create mode 100644 config/rofi/local.rasi create mode 100644 config/rofi/theme.rasi create mode 100644 config/waybar/theme.css diff --git a/README.md b/README.md index 5f32498..f721894 100644 --- a/README.md +++ b/README.md @@ -153,26 +153,66 @@ Then log out. `HyprCosmic` appears on the greeter's session menu next to ### Per-user setup -`just install` places nothing in a home directory — under `sudo` the only home -directory it could see is root's. Four files are yours to place: +Nothing to do. The session seeds `~/.config` from `/usr/share/hyprcosmic/skel` +at login, copying only what is missing: -```shell -mkdir -p ~/.config/hyprcosmic/waybar -cp config/cosmic.conf config/autostart ~/.config/hyprcosmic/ -cp config/waybar/style.css ~/.config/hyprcosmic/waybar/ +``` +~/.config/hyprcosmic/autostart +~/.config/hyprcosmic/cosmic.conf +~/.config/hyprcosmic/waybar/style.css +~/.config/hyprcosmic/waybar/theme.css +~/.config/rofi/config.rasi +~/.config/rofi/theme.rasi +~/.config/rofi/local.rasi ``` -`style.css` is per-user rather than shared for one reason: it `@import`s a -sibling `theme.css` holding the installed HyDE theme's palette, and a relative -`@import` resolves against the importing file. That sibling is written by -`import-theme --assets`, so the bar is unstyled until you have imported a theme. +An existing file is never touched, not even when the skeleton is newer — the +file wins, one way, and a login is not an invitation to edit your config. Two +things follow: your edits survive every login and upgrade, and deleting a file +is how you ask for the default back. `~/.cache/hyprcosmic/session.log` records +what was seeded. -The fourth file, `~/.config/rofi/config.rasi`, is written by `import-theme ---assets` too, because it names per-machine paths. +`autostart` is the one that matters most, because it is what starts waybar, the +wallpaper daemon and `hyprcosmic-conf watch`. Until the session seeded it, a +machine that had never run HyprCosmic logged in to a bare compositor: running, +holding the display and accepting input, with nothing drawn on the screen and no +binding that opened anything. + +`style.css` and `config.rasi` are per-user rather than shared for one reason: +each `@import`s a sibling holding the installed HyDE theme's palette, and a +relative `@import` resolves against the importing file. Those siblings — +`theme.css`, `theme.rasi` and `local.rasi` — arrive empty and are written by +`import-theme --assets`. They ship empty rather than not at all because a +missing `@import` is fatal to both consumers rather than a warning they skip: +GTK fails the entire stylesheet, and rofi reports the error in place of the +launcher. + +Working from a git checkout, `just install` still places nothing in a home +directory — under `sudo` the only home directory it could see is root's — but it +does install the skeleton, so logging in seeds the same seven files. 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 bar's glyphs. +Font for the glyphs the bar and the launcher draw with. + +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 +`/usr/lib64/kitty`, and fontconfig scans neither. Arch has +`ttf-nerd-fonts-symbols`. Otherwise, install one into your own font directory: + +```shell +mkdir -p ~/.local/share/fonts/JetBrainsMonoNerdFont +# unpack JetBrainsMono.zip from github.com/ryanoasis/nerd-fonts/releases there +fc-cache -f +fc-list ":charset=e0b0" family | grep -i nerd # non-empty: the glyphs resolve +``` + +Query the charset on its own, as above. Adding a family filter — +`":charset=e0b0:family=JetBrainsMono Nerd Font"` — reports nothing even when the +font does cover the codepoint, because the family string is a comma-separated +alias list (`JetBrainsMono Nerd Font,JetBrainsMono NF`). Without the font the +bar still works; every icon is a tofu box. ## Configuration diff --git a/config/rofi/local.rasi b/config/rofi/local.rasi new file mode 100644 index 0000000..bc7a555 --- /dev/null +++ b/config/rofi/local.rasi @@ -0,0 +1,29 @@ +/* Per-machine launcher settings for HyprCosmic. + * + * Empty until `hyprcosmic-conf import-theme --assets` writes it. It exists from + * the first session because config.rasi imports it, and a missing @import is an + * error rofi reports in place of the launcher rather than a warning it skips. + * + * It is the last of the four imports in config.rasi, so anything here wins; it + * is also overwritten by the next import run with --overwrite, so keep hand + * edits somewhere else. + * + * Two things belong in this file and nothing else does: values that name a path + * or a package on this particular machine, which neither /usr/share/hyprcosmic + * nor a HyDE theme file can know. Concretely, that is the icon theme and the + * sidebar image: + * + * configuration { + * icon-theme: "Tela-circle-purple", "Adwaita"; + * } + * + * dummywall { + * background-image: url("/home/you/.local/share/wallpapers/hyprcosmic/current", height); + * } + * + * Both are shown commented out rather than set, because a default that named + * an icon theme nobody has installed, or a wallpaper path under someone else's + * home, would be worse than no default at all. + */ + +* {} diff --git a/config/rofi/theme.rasi b/config/rofi/theme.rasi new file mode 100644 index 0000000..ed12b50 --- /dev/null +++ b/config/rofi/theme.rasi @@ -0,0 +1,16 @@ +/* Step 2 of the import chain in config.rasi: the installed HyDE theme's rofi + * colours. + * + * Empty on purpose, for the same reason as waybar's theme.css: a missing + * @import is an error rofi reports in place of the launcher rather than a + * warning it skips, so config.rasi can only import a file that is guaranteed + * to exist. palette.rasi already defines every name rules.rasi reads, so + * defining nothing here leaves a complete theme rather than an unresolved + * reference. + * + * `hyprcosmic-conf import-theme` overwrites this with the imported theme's + * rofi colours. Hand-written overrides belong in local.rasi, which is imported + * after the rules and is left alone unless --overwrite is passed. + */ + +* {} diff --git a/config/waybar/theme.css b/config/waybar/theme.css new file mode 100644 index 0000000..ce4db86 --- /dev/null +++ b/config/waybar/theme.css @@ -0,0 +1,18 @@ +/* Step 2 of the import chain in style.css: the installed HyDE theme's + * waybar.theme. + * + * This copy is deliberately empty of rules. It is not a stub waiting to be + * written -- an empty file is the correct content when no theme has been + * imported, and it is what makes the other three steps work: + * + * - A missing @import is fatal in GTK, so style.css cannot name a file that + * might not exist. This one always exists, from the moment the session + * first starts. + * - Every colour the rules consume already has a default from palette.css + * and bridge-hyde.css, so a file that defines nothing leaves a complete + * stylesheet rather than an undefined name. + * + * `hyprcosmic-conf import-theme` overwrites this with the waybar.theme of the + * theme being imported. Anything written here by hand is lost at that point, + * which is why the per-user override belongs in style.css instead. + */ diff --git a/cosmic-session b/cosmic-session index d65baf6..75267c5 160000 --- a/cosmic-session +++ b/cosmic-session @@ -1 +1 @@ -Subproject commit d65baf688c0bdf21d0c3f9831b87eca037daee66 +Subproject commit 75267c5977f12b0bbc6cf41ec8344b9c40275bf8 diff --git a/packaging/fedora/hyprcosmic.spec b/packaging/fedora/hyprcosmic.spec index e63052c..a1e4f94 100644 --- a/packaging/fedora/hyprcosmic.spec +++ b/packaging/fedora/hyprcosmic.spec @@ -81,8 +81,22 @@ Requires: rofi-wayland # unsatisfiable dependency is not. Recommends: awww -# Nerd Font glyphs are most of what the bar draws. -Recommends: nerd-fonts +# 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 +# the fonts never arrived, silently, because that is what Recommends does when +# it cannot resolve. The two patched fonts Fedora does ship are no help either: +# texlive-inconsolata-nerd-font lands under texmf-dist and kitty's +# SymbolsNerdFont under /usr/lib64/kitty, and fontconfig scans neither path. +# +# So recommend the fallback the configuration actually names. rules.rasi asks +# for "JetBrainsMono Nerd Font, Noto Sans Mono": this is the second of the two. +# It cannot draw a single glyph, but it decides what the text is set in instead +# of leaving that to whatever fontconfig happens to pick. A virtual provide +# rather than a name, because two packages carry it and either will do. +# +# The glyphs themselves have to be installed by hand. See README.md. +Recommends: font(notosansmono) %description HyprCosmic is a fork of the COSMIC desktop that takes its configuration in diff --git a/tools/install-assets.sh b/tools/install-assets.sh index 2e9f7b3..902dbdb 100755 --- a/tools/install-assets.sh +++ b/tools/install-assets.sh @@ -97,23 +97,43 @@ SOURCES=( "config/waybar/generate-config.py" # the generator, and the icon table ) -# Files under config/ that are deliberately NOT installed here, each with the -# thing that does install it. This list is not decoration: the audit below -# refuses to run unless every file under config/ appears in exactly one of the -# three lists, so adding a file forces a decision about where it belongs instead -# of letting it be quietly left out of all of them. -PER_USER=( - "config/autostart" # ~/.config/hyprcosmic/autostart, by hand - "config/cosmic.conf" # ~/.config/hyprcosmic/cosmic.conf, by hand - "config/waybar/style.css" # ~/.config/hyprcosmic/waybar/style.css; @imports a sibling theme.css - "config/rofi/config.rasi" # ~/.config/rofi/config.rasi, by `cosmic-conf import-theme --assets` +# Per-user files. These cannot live in share/hyprcosmic with the rest: style.css +# and config.rasi reach their theme through relative @imports, which resolve +# against the importing file, so the importer has to sit in the same per-user +# directory as the theme it picks up. +# +# They are still installed, as a skeleton. start-hyprcosmic copies anything +# missing out of share/hyprcosmic/skel into $XDG_CONFIG_HOME when a session +# starts, and never overwrites. Destinations below therefore mirror the layout +# under ~/.config exactly -- skel/hyprcosmic/autostart becomes +# ~/.config/hyprcosmic/autostart -- because the seeding is a plain copy that +# reads the layout off this tree rather than a list it keeps in step by hand. +# +# Before this existed the answer was "by hand", which meant a machine that had +# never seen HyprCosmic logged into a bare compositor: no autostart, so no +# waybar and no wallpaper, and no keybindings, on a screen with nothing drawn on +# it. Nothing reported an error, because from the session's point of view +# nothing had gone wrong. +SKEL=( + "config/autostart:share/hyprcosmic/skel/hyprcosmic/autostart:644" + "config/cosmic.conf:share/hyprcosmic/skel/hyprcosmic/cosmic.conf:644" + "config/waybar/style.css:share/hyprcosmic/skel/hyprcosmic/waybar/style.css:644" + "config/waybar/theme.css:share/hyprcosmic/skel/hyprcosmic/waybar/theme.css:644" + "config/rofi/config.rasi:share/hyprcosmic/skel/rofi/config.rasi:644" + "config/rofi/theme.rasi:share/hyprcosmic/skel/rofi/theme.rasi:644" + "config/rofi/local.rasi:share/hyprcosmic/skel/rofi/local.rasi:644" ) +# Refuses to run unless every file under config/ appears in exactly one of +# SHARED, SKEL or SOURCES. This is not decoration: adding a file forces a +# decision about where it belongs instead of letting it be quietly left out of +# all three and never installed. audit_config_tree() { - local f rel known=" ${PER_USER[*]} ${SOURCES[*]} " unclassified=() + local f rel known=" ${SOURCES[*]} " unclassified=() # Built with a loop, not `${SHARED[*]%%:*}`: that form strips the suffix # from the first element only and silently keeps the rest whole. for f in "${SHARED[@]}"; do known+="${f%%:*} "; done + for f in "${SKEL[@]}"; do known+="${f%%:*} "; done while IFS= read -r -d '' f; do rel="${f#"$REPO"/}" @@ -126,8 +146,8 @@ audit_config_tree() { # only directories are pruned. done < <(find "$REPO/config" -name '.?*' -type d -prune -o -type f -print0 | sort -z) - ((${#unclassified[@]} == 0)) || die "not listed as shared or per-user: ${unclassified[*]} - Add each to SHARED or PER_USER in $(basename "${BASH_SOURCE[0]}") and say which." + ((${#unclassified[@]} == 0)) || die "not listed as shared, skeleton or generator input: ${unclassified[*]} + Add each to SHARED, SKEL or SOURCES in $(basename "${BASH_SOURCE[0]}") and say which." } # The prefix is only half honoured, and pretending otherwise would be worse than @@ -138,11 +158,12 @@ audit_config_tree() { check_prefix_assumptions() { [[ "$PREFIX" == /usr ]] && return 0 local hits - hits="$(cd "$REPO" && grep -rl '/usr/share/hyprcosmic' config/ 2>/dev/null | sort | tr '\n' ' ')" + hits="$(cd "$REPO" && grep -rl '/usr/share/hyprcosmic' config/ cosmic-session/data/ 2>/dev/null | sort | tr '\n' ' ')" [[ -z "$hits" ]] && return 0 warn "PREFIX=$PREFIX, but these name /usr/share/hyprcosmic literally and cannot interpolate it:" warn " $hits" warn "they will keep reading /usr/share unless you edit them; rofi will show a parse error if it is empty" + warn "start-hyprcosmic is the exception: set HYPRCOSMIC_SKEL=$PREFIX/share/hyprcosmic/skel to point the seeding at this prefix" } # Fail before touching anything rather than half way through. The nearest @@ -198,7 +219,7 @@ handle() { audit_config_tree [[ "$MODE" == install ]] && check_prefix_assumptions -targets=("${SHARED[@]}") +targets=("${SHARED[@]}" "${SKEL[@]}") if ((WITH_SESSION)); then if [[ -d "$REPO/cosmic-session/data" ]]; then targets+=("${SESSION[@]}")