diff --git a/dotfiles/lib/bin/desktop_shell_ui b/dotfiles/lib/bin/desktop_shell_ui new file mode 100755 index 00000000..c168cf4b --- /dev/null +++ b/dotfiles/lib/bin/desktop_shell_ui @@ -0,0 +1,93 @@ +#!/usr/bin/env bash +set -euo pipefail + +state_file="${IM_DESKTOP_SHELL_UI_STATE:-${XDG_STATE_HOME:-$HOME/.local/state}/imalison/desktop-shell-ui}" +default_shell_ui="${IM_HYPRLAND_SHELL_UI:-taffybar}" + +normalize_shell_ui() { + case "${1:-}" in + noctalia) + printf '%s\n' "noctalia" + ;; + taffybar|rofi) + printf '%s\n' "taffybar" + ;; + *) + return 1 + ;; + esac +} + +current_shell_ui() { + local configured="" + + if [[ -r "$state_file" ]]; then + IFS= read -r configured < "$state_file" || true + fi + + normalize_shell_ui "$configured" 2>/dev/null \ + || normalize_shell_ui "$default_shell_ui" 2>/dev/null \ + || printf '%s\n' "taffybar" +} + +write_shell_ui() { + local shell_ui="$1" + mkdir -p "$(dirname "$state_file")" + printf '%s\n' "$shell_ui" > "$state_file" +} + +apply_shell_ui() { + local shell_ui="$1" + + export IM_HYPRLAND_SHELL_UI="$shell_ui" + systemctl --user import-environment IM_HYPRLAND_SHELL_UI 2>/dev/null || true + + case "$shell_ui" in + noctalia) + systemctl --user stop taffybar.service 2>/dev/null || true + systemctl --user reset-failed taffybar.service 2>/dev/null || true + systemctl --user start noctalia-shell.service + ;; + taffybar) + systemctl --user stop noctalia-shell.service 2>/dev/null || true + systemctl --user reset-failed noctalia-shell.service 2>/dev/null || true + systemctl --user start taffybar.service + ;; + esac +} + +set_shell_ui() { + local shell_ui + shell_ui="$(normalize_shell_ui "${1:-}")" || { + echo "usage: desktop_shell_ui set {taffybar|noctalia}" >&2 + exit 2 + } + + write_shell_ui "$shell_ui" + apply_shell_ui "$shell_ui" +} + +case "${1:-current}" in + current) + current_shell_ui + ;; + set) + set_shell_ui "${2:-}" + ;; + toggle) + case "$(current_shell_ui)" in + noctalia) set_shell_ui taffybar ;; + *) set_shell_ui noctalia ;; + esac + ;; + apply) + apply_shell_ui "$(current_shell_ui)" + ;; + exec-condition) + [[ "$(current_shell_ui)" == "$(normalize_shell_ui "${2:-}")" ]] + ;; + *) + echo "usage: desktop_shell_ui {current|set|toggle|apply|exec-condition}" >&2 + exit 2 + ;; +esac diff --git a/nixos/desktop.nix b/nixos/desktop.nix index 7b733d0a..c884e362 100644 --- a/nixos/desktop.nix +++ b/nixos/desktop.nix @@ -6,7 +6,19 @@ makeEnable, ... }: -makeEnable config "myModules.desktop" true { +let + cfg = config.myModules.desktop; + desktopShellUi = pkgs.writeShellApplication { + name = "desktop_shell_ui"; + runtimeInputs = [ + pkgs.coreutils + pkgs.systemd + ]; + text = '' + exec ${../dotfiles/lib/bin/desktop_shell_ui} "$@" + ''; + }; + enabledModule = makeEnable config "myModules.desktop" true { services.greenclip.enable = true; imports = [ ./fonts.nix @@ -40,8 +52,11 @@ makeEnable config "myModules.desktop" true { enable = true; }; - # This is for the benefit of VSCODE running natively in wayland - environment.sessionVariables.NIXOS_OZONE_WL = "1"; + environment.sessionVariables = { + # This is for the benefit of VSCODE running natively in wayland + NIXOS_OZONE_WL = "1"; + IM_HYPRLAND_SHELL_UI = cfg.shellUi; + }; system.activationScripts.playwrightChromeCompat.text = lib.optionalString (pkgs.stdenv.hostPlatform.system == "x86_64-linux") '' # Playwright's Chrome channel lookup expects the FHS path below. @@ -87,6 +102,8 @@ makeEnable config "myModules.desktop" true { environment.systemPackages = with pkgs; [ + desktopShellUi + # Appearance adwaita-icon-theme hicolor-icon-theme @@ -169,4 +186,18 @@ makeEnable config "myModules.desktop" true { ] else [] ); + }; +in +enabledModule +// { + options = lib.recursiveUpdate enabledModule.options { + myModules.desktop.shellUi = lib.mkOption { + type = lib.types.enum [ "noctalia" "taffybar" ]; + default = "taffybar"; + description = '' + Desktop shell UI used by Hyprland-oriented bindings. This controls + the active shell service and Hyprland launcher/window picker dispatch. + ''; + }; + }; }