167 lines
7.7 KiB
Nix
Executable File
167 lines
7.7 KiB
Nix
Executable File
{ lib, config, pkgs, ... }:
|
|
let
|
|
ewwBar = "${pkgs.custom.eww-bar}/bin/eww-bar";
|
|
|
|
# Every script ships as a bash wrapper that pins PATH to its dependencies
|
|
# and inlines the shared helpers, so the sources under bar/scripts stay
|
|
# plain shell files.
|
|
baseInputs = with pkgs; [ coreutils findutils gawk gnugrep gnused systemd util-linux ];
|
|
mkScript = name: src: inputs: pkgs.writeShellScriptBin name ''
|
|
export PATH="${lib.makeBinPath (baseInputs ++ inputs)}:$PATH"
|
|
${builtins.readFile ./bar/scripts/_lib.sh}
|
|
${builtins.readFile src}
|
|
'';
|
|
|
|
scripts = with pkgs; {
|
|
# bar
|
|
"scripts/workspaces" = mkScript "workspaces" ./bar/scripts/workspaces [ hyprland jaq socat ripgrep ];
|
|
"scripts/panel-toggle" = mkScript "panel-toggle" ./bar/scripts/panel-toggle [ eww custom.eww-bar ];
|
|
"scripts/powermenu-toggle" = mkScript "powermenu-toggle" ./bar/scripts/powermenu-toggle [ eww custom.eww-bar ];
|
|
"scripts/net/net" = mkScript "net" ./bar/scripts/net/net [ iproute2 wpa_supplicant ];
|
|
"scripts/net/bt" = mkScript "bt" ./bar/scripts/net/bt [ jq glib ];
|
|
"scripts/net/bt-toggle" = mkScript "bt-toggle" ./bar/scripts/net/bt-toggle [ bluez ];
|
|
"scripts/net/wg-toggle" = mkScript "wg-toggle" ./bar/scripts/net/wg-toggle [ ];
|
|
"scripts/sys/gpu" = mkScript "gpu" ./bar/scripts/sys/gpu [ custom.amdgpu_top jq ];
|
|
"scripts/sys/memory" = mkScript "memory" ./bar/scripts/sys/memory [ ];
|
|
"scripts/sys/battery" = mkScript "battery" ./bar/scripts/sys/battery [ ];
|
|
"scripts/sys/cputemp" = mkScript "cputemp" ./bar/scripts/sys/cputemp [ ];
|
|
# popup panels
|
|
"scripts/volume" = mkScript "volume" ./bar/scripts/volume [ wireplumber pulseaudio ];
|
|
"scripts/brightness" = mkScript "brightness" ./bar/scripts/brightness [ brightnessctl ];
|
|
"scripts/weather" = mkScript "weather" ./bar/scripts/weather [ jq curl ];
|
|
"scripts/radio" = mkScript "radio" ./bar/scripts/radio [ eww jq curl mpv playerctl wireplumber ];
|
|
"scripts/media" = mkScript "media" ./bar/scripts/media [ playerctl ];
|
|
# quick actions (long-running ones are detached via systemd-run)
|
|
"scripts/nightlight" = mkScript "nightlight" ./bar/scripts/nightlight [ eww wlsunset procps ];
|
|
"scripts/read-mode" = mkScript "read-mode" ./bar/scripts/read-mode [ eww hyprland ];
|
|
"scripts/airplane-mode" = mkScript "airplane-mode" ./bar/scripts/airplane-mode [ eww ];
|
|
"scripts/do-not-disturb" = mkScript "do-not-disturb" ./bar/scripts/do-not-disturb [ eww dunst ];
|
|
"scripts/power-save" = mkScript "power-save" ./bar/scripts/power-save [ eww power-profiles-daemon ];
|
|
"scripts/lock" = mkScript "lock" ./bar/scripts/lock [ eww hyprlock ];
|
|
"scripts/screenshot" = mkScript "screenshot" ./bar/scripts/screenshot [ eww hyprshot satty wl-clipboard ];
|
|
"scripts/color-pick" = mkScript "color-pick" ./bar/scripts/color-pick [ eww hyprpicker ];
|
|
"scripts/wallpaper" = mkScript "wallpaper" ./bar/scripts/wallpaper [ eww ];
|
|
};
|
|
in {
|
|
|
|
config = lib.mkIf (config.usercfg.wm == "Wayland") {
|
|
home.packages = [ pkgs.eww pkgs.custom.eww-bar ];
|
|
|
|
# The daemon and the bar are one unit: it starts and stops with the
|
|
# graphical session, opens the bar once the daemon answers, and is
|
|
# restarted on crash. `eww-bar` (packages/eww-bar) does the heavy
|
|
# lifting; kanshi calls `eww-bar place` to move the bar between outputs.
|
|
systemd.user.services.eww = {
|
|
Unit = {
|
|
Description = "eww daemon and bar";
|
|
Documentation = "https://elkowar.github.io/eww/";
|
|
PartOf = [ "graphical-session.target" ];
|
|
After = [ "graphical-session.target" ];
|
|
ConditionEnvironment = "WAYLAND_DISPLAY";
|
|
# Cap crash loops (e.g. a broken config) without giving up for good:
|
|
# the watchdog resets the counter and tries again later.
|
|
StartLimitIntervalSec = 60;
|
|
StartLimitBurst = 5;
|
|
};
|
|
Service = {
|
|
Type = "simple";
|
|
ExecStartPre = "${ewwBar} clean";
|
|
ExecStart = "${lib.getExe pkgs.eww} daemon --no-daemonize";
|
|
ExecStartPost = "${ewwBar} open";
|
|
ExecReload = "${ewwBar} reload";
|
|
Restart = "always";
|
|
RestartSec = 2;
|
|
TimeoutStartSec = 30;
|
|
TimeoutStopSec = 5;
|
|
};
|
|
Install.WantedBy = [ "graphical-session.target" ];
|
|
};
|
|
|
|
# Liveness check: `eww ping` only proves the socket is up, so the check
|
|
# also lists the windows through the GTK main loop. Two consecutive
|
|
# failures (≈40 s) restart the daemon; a missing bar is simply reopened.
|
|
systemd.user.services.eww-watchdog = {
|
|
Unit = {
|
|
Description = "eww health check";
|
|
After = [ "eww.service" ];
|
|
};
|
|
Service = {
|
|
Type = "oneshot";
|
|
ExecStart = "${ewwBar} check";
|
|
};
|
|
};
|
|
systemd.user.timers.eww-watchdog = {
|
|
Unit = {
|
|
Description = "Periodic eww health check";
|
|
PartOf = [ "graphical-session.target" ];
|
|
After = [ "graphical-session.target" ];
|
|
};
|
|
Timer = {
|
|
OnActiveSec = "30s";
|
|
OnUnitActiveSec = "20s";
|
|
AccuracySec = "5s";
|
|
};
|
|
Install.WantedBy = [ "graphical-session.target" ];
|
|
};
|
|
|
|
xdg.configFile = lib.mkMerge [
|
|
{
|
|
"eww" = {
|
|
source = lib.cleanSourceWith {
|
|
# scripts/ is shipped through the wrappers below, never verbatim
|
|
filter = name: _type:
|
|
let
|
|
baseName = baseNameOf (toString name);
|
|
relPath = lib.removePrefix (toString ./bar + "/") (toString name);
|
|
in !(lib.hasSuffix ".nix" baseName)
|
|
&& (baseName != "_colors.scss")
|
|
&& !(lib.hasPrefix "scripts/" relPath);
|
|
src = lib.cleanSource ./bar/.;
|
|
};
|
|
recursive = true;
|
|
};
|
|
|
|
"eww/css/_colors.scss".text = ''
|
|
$base00: #${config.colorScheme.palette.base00};
|
|
$base01: #${config.colorScheme.palette.base01};
|
|
$base02: #${config.colorScheme.palette.base02};
|
|
$base03: #${config.colorScheme.palette.base03};
|
|
$base04: #${config.colorScheme.palette.base04};
|
|
$base05: #${config.colorScheme.palette.base05};
|
|
$base06: #${config.colorScheme.palette.base06};
|
|
$base07: #${config.colorScheme.palette.base07};
|
|
$base08: #${config.colorScheme.palette.base08};
|
|
$base09: #${config.colorScheme.palette.base09};
|
|
$base0A: #${config.colorScheme.palette.base0A};
|
|
$base0B: #${config.colorScheme.palette.base0B};
|
|
$base0C: #${config.colorScheme.palette.base0C};
|
|
$base0D: #${config.colorScheme.palette.base0D};
|
|
$base0E: #${config.colorScheme.palette.base0E};
|
|
$base0F: #${config.colorScheme.palette.base0F};
|
|
|
|
|
|
$fg: $base07;
|
|
$bg0: $base00;
|
|
$bg1: $base01;
|
|
|
|
$border-color: $base03;
|
|
$border-color-focus: $base04;
|
|
$border-radius: ${config.colorScheme.palette.border-radius}px;
|
|
$border-width: ${config.colorScheme.palette.border-width}px;
|
|
|
|
$gaps-screen: ${config.colorScheme.palette.gaps-screen}px;
|
|
$gaps-window: ${config.colorScheme.palette.gaps-window}px;
|
|
|
|
$panel-font-size: 10pt;
|
|
$popup-scale: 1.25;
|
|
'';
|
|
}
|
|
|
|
(lib.mapAttrs' (rel: drv: {
|
|
name = "eww/${rel}";
|
|
value.source = "${drv}/bin/${drv.name}";
|
|
}) scripts)
|
|
];
|
|
};
|
|
}
|