diff --git a/CLAUDE.md b/CLAUDE.md index cb51915..a6ba779 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -109,3 +109,8 @@ The domain model (Host, Module, Skeleton, Auto-loader, Enable convention, overla To actually remove a builtin, list it explicitly with `.metaData.hidden = true` — an engine entry carrying only `metaData` is treated as a builtin rather than a custom engine. Engines are referenced by their current id, which the module maps from the old display names, so the default is `default = "ddg"`, not `"DuckDuckGo"` (the latter only warns and migrates). Prove the result by decoding the built file: `mozlz4a -d ` shows the `_metaData.hidden` flags and `defaultEngineId`. +- `home.sessionVariables` do **not** reach the Hyprland session, so anything the compositor reads from its environment (cursor theme, toolkit hints) has to be declared elsewhere. + home-manager writes those variables to `hm-session-vars.sh`, which only a login shell sources; UWSM starts the graphical session without it, so the compositor's environment never gains them. + This is why a Stylix cursor (`XCURSOR_THEME`/`XCURSOR_SIZE` via `home.pointerCursor`) silently fails to apply and Hyprland draws its built-in cursor: the variables exist in `sessionVariables` but not in the running session (`tr '\0' '\n' < /proc/$(pgrep -x Hyprland)/environ` shows them absent). + The fix is Hyprland's own `env = KEY,VALUE` directive in `settings`, read at compositor startup regardless of the shell profile; `modules/desktop/hyprland/hyprland.nix` sets the cursor that way, sourced from `config.stylix.cursor`. + Bibata ships XCursor format only (no `hyprcursor/` dir), which Hyprland renders through its XCursor fallback, so both `XCURSOR_*` and `HYPRCURSOR_*` naming the same theme are safe. diff --git a/modules/desktop/hyprland/hyprland.nix b/modules/desktop/hyprland/hyprland.nix index 3344aba..d056e4f 100644 --- a/modules/desktop/hyprland/hyprland.nix +++ b/modules/desktop/hyprland/hyprland.nix @@ -8,6 +8,7 @@ let cfg = config.modules.desktop.hyprland; user = config.user.name; + cursor = config.stylix.cursor; # Numbered-workspace switch and move for 1..9, the operator's i3 muscle memory. workspaceBinds = lib.concatMap (n: [ @@ -62,6 +63,19 @@ in "$mod" = "SUPER"; "$terminal" = "alacritty"; + # Hand the cursor theme to the compositor directly. UWSM launches the + # session without the shell profile that carries the pointer-cursor + # variables, so without this Hyprland never sees a theme and falls back + # to its built-in cursor. Bibata ships XCursor only; the hyprcursor + # variables name the same theme, which Hyprland resolves through its + # XCursor fallback. + env = lib.optionals (cursor != null) [ + "XCURSOR_THEME,${cursor.name}" + "XCURSOR_SIZE,${toString cursor.size}" + "HYPRCURSOR_THEME,${cursor.name}" + "HYPRCURSOR_SIZE,${toString cursor.size}" + ]; + input = { kb_layout = "us"; # Caps is a second Escape. diff --git a/modules/desktop/theming.nix b/modules/desktop/theming.nix index f7fa96b..8a3b3ca 100644 --- a/modules/desktop/theming.nix +++ b/modules/desktop/theming.nix @@ -34,6 +34,8 @@ in cursor = { package = pkgs.bibata-cursors; + # Solid white with a dark outline, so it stays easy to spot against the + # dark Nord wallpaper. name = "Bibata-Modern-Ice"; size = 24; };