{ config, inputs, lib, pkgs, makeEnable, ... }: let system = pkgs.stdenv.hostPlatform.system; hyprlandPackage = config.programs.hyprland.package; taffybarPackage = inputs.imalison-taffybar.defaultPackage.${system}; taffybarStart = pkgs.writeShellScript "taffybar-start" '' runtime_dir="''${XDG_RUNTIME_DIR:-/run/user/$(${pkgs.coreutils}/bin/id -u)}" find_hyprland_instance() { instances_json="$(${hyprlandPackage}/bin/hyprctl instances -j 2>/dev/null || true)" [ -n "$instances_json" ] || return 1 if [ -n "''${WAYLAND_DISPLAY:-}" ]; then inst_row="$( printf '%s\n' "$instances_json" | ${pkgs.jq}/bin/jq -r --arg sock "$WAYLAND_DISPLAY" \ '.[] | select(.instance and .wl_socket and .wl_socket == $sock) | [.time, .instance, .wl_socket] | @tsv' 2>/dev/null | ${pkgs.coreutils}/bin/sort -n | ${pkgs.coreutils}/bin/tail -n 1 )" else inst_row="" fi if [ -z "''${inst_row:-}" ]; then inst_row="$( printf '%s\n' "$instances_json" | ${pkgs.jq}/bin/jq -r \ '.[] | select(.instance and .wl_socket) | [.time, .instance, .wl_socket] | @tsv' 2>/dev/null | ${pkgs.coreutils}/bin/sort -n | ${pkgs.coreutils}/bin/tail -n 1 )" fi [ -n "''${inst_row:-}" ] || return 1 set -- $inst_row signature="$2" socket_name="$3" [ -n "$signature" ] && [ -n "$socket_name" ] || return 1 printf '%s\t%s\n' "$signature" "$socket_name" } find_wayland_socket() { if [ -n "''${WAYLAND_DISPLAY:-}" ] && [ -S "$runtime_dir/$WAYLAND_DISPLAY" ]; then printf '%s\n' "$WAYLAND_DISPLAY" return 0 fi for socket in "$runtime_dir"/wayland-*; do case "$socket" in *.lock) continue ;; esac if [ -S "$socket" ]; then printf '%s\n' "''${socket##*/}" return 0 fi done return 1 } x11_socket_ready() { display_number="''${DISPLAY#:}" display_number="''${display_number%%.*}" [ -n "$display_number" ] && [ -S "/tmp/.X11-unix/X$display_number" ] } current_desktop="''${XDG_CURRENT_DESKTOP:-}" desktop_session="''${DESKTOP_SESSION:-}" window_manager="''${IMALISON_WINDOW_MANAGER:-}" is_hyprland=0 case "''${current_desktop}:''${desktop_session}:''${window_manager}" in *Hyprland*|*hyprland*) is_hyprland=1 ;; esac if [ "$is_hyprland" = 1 ] && [ -z "''${XDG_SESSION_TYPE:-}" ]; then export XDG_SESSION_TYPE=wayland fi if [ "$is_hyprland" = 1 ]; then if inst_row="$(find_hyprland_instance)"; then set -- $inst_row signature="$1" socket_name="$2" if [ "''${HYPRLAND_INSTANCE_SIGNATURE:-}" != "$signature" ]; then echo "taffybar-start: correcting HYPRLAND_INSTANCE_SIGNATURE=''${HYPRLAND_INSTANCE_SIGNATURE:-} to $signature" >&2 export HYPRLAND_INSTANCE_SIGNATURE="$signature" fi if [ "''${WAYLAND_DISPLAY:-}" != "$socket_name" ]; then echo "taffybar-start: correcting WAYLAND_DISPLAY=''${WAYLAND_DISPLAY:-} to $socket_name" >&2 export WAYLAND_DISPLAY="$socket_name" fi fi fi if [ "''${XDG_SESSION_TYPE:-}" = "wayland" ] || [ -n "''${WAYLAND_DISPLAY:-}" ] || [ "$is_hyprland" = 1 ]; then if [ -z "''${WAYLAND_DISPLAY:-}" ] || [ ! -S "$runtime_dir/$WAYLAND_DISPLAY" ]; then if socket_name="$(find_wayland_socket)"; then echo "taffybar-start: correcting WAYLAND_DISPLAY=''${WAYLAND_DISPLAY:-} to $socket_name" >&2 export WAYLAND_DISPLAY="$socket_name" fi fi fi if [ -n "''${DISPLAY:-}" ] && [ "''${XDG_SESSION_TYPE:-}" != "wayland" ] && x11_socket_ready; then unset WAYLAND_DISPLAY unset HYPRLAND_INSTANCE_SIGNATURE exec ${taffybarPackage}/bin/taffybar "$@" fi if [ -z "''${WAYLAND_DISPLAY:-}" ] || [ ! -S "$runtime_dir/$WAYLAND_DISPLAY" ]; then if socket_name="$(find_wayland_socket)"; then echo "taffybar-start: correcting WAYLAND_DISPLAY=''${WAYLAND_DISPLAY:-} to $socket_name" >&2 export WAYLAND_DISPLAY="$socket_name" fi fi if [ -n "''${HYPRLAND_INSTANCE_SIGNATURE:-}" ] && [ ! -S "$runtime_dir/hypr/$HYPRLAND_INSTANCE_SIGNATURE/.socket.sock" ]; then echo "taffybar-start: unsetting stale HYPRLAND_INSTANCE_SIGNATURE=$HYPRLAND_INSTANCE_SIGNATURE" >&2 unset HYPRLAND_INSTANCE_SIGNATURE fi if [ "$is_hyprland" = 1 ]; then if [ -z "''${HYPRLAND_INSTANCE_SIGNATURE:-}" ]; then for socket in "$runtime_dir"/hypr/*/.socket.sock; do if [ -S "$socket" ]; then socket_dir="''${socket%/.socket.sock}" signature="''${socket_dir##*/}" echo "taffybar-start: correcting HYPRLAND_INSTANCE_SIGNATURE=''${HYPRLAND_INSTANCE_SIGNATURE:-} to $signature" >&2 export HYPRLAND_INSTANCE_SIGNATURE="$signature" break fi done fi fi exec ${taffybarPackage}/bin/taffybar "$@" ''; waitForGraphicalSocket = pkgs.writeShellScript "wait-for-taffybar-display" '' runtime_dir="''${XDG_RUNTIME_DIR:-/run/user/$(${pkgs.coreutils}/bin/id -u)}" find_wayland_socket() { if [ -n "''${WAYLAND_DISPLAY:-}" ] && [ -S "$runtime_dir/$WAYLAND_DISPLAY" ]; then return 0 fi for socket in "$runtime_dir"/wayland-*; do case "$socket" in *.lock) continue ;; esac if [ -S "$socket" ]; then return 0 fi done return 1 } x11_socket_ready() { display_number="''${DISPLAY#:}" display_number="''${display_number%%.*}" [ -n "$display_number" ] && [ -S "/tmp/.X11-unix/X$display_number" ] } for _ in $(${pkgs.coreutils}/bin/seq 1 50); do current_desktop="''${XDG_CURRENT_DESKTOP:-}" desktop_session="''${DESKTOP_SESSION:-}" window_manager="''${IMALISON_WINDOW_MANAGER:-}" case "''${current_desktop}:''${desktop_session}:''${window_manager}" in *Hyprland*|*hyprland*) find_wayland_socket && exit 0 ;; esac if [ "''${XDG_SESSION_TYPE:-}" = "wayland" ] || [ -n "''${WAYLAND_DISPLAY:-}" ]; then find_wayland_socket && exit 0 elif [ -n "''${DISPLAY:-}" ]; then x11_socket_ready && exit 0 find_wayland_socket && exit 0 else find_wayland_socket && exit 0 fi ${pkgs.coreutils}/bin/sleep 0.1 done echo "taffybar: display socket not ready: XDG_SESSION_TYPE=''${XDG_SESSION_TYPE:-} WAYLAND_DISPLAY=''${WAYLAND_DISPLAY:-} DISPLAY=''${DISPLAY:-} XDG_RUNTIME_DIR=$runtime_dir" >&2 exit 1 ''; skipTaffybarInOtherShells = pkgs.writeShellScript "skip-taffybar-in-other-shells" '' current_desktop="''${XDG_CURRENT_DESKTOP:-}" desktop_session="''${DESKTOP_SESSION:-}" case "''${current_desktop}:''${desktop_session}" in *KDE*|*kde*|*Plasma*|*plasma*) exit 1 ;; esac exit 0 ''; taffybarExecCondition = pkgs.writeShellScript "taffybar-exec-condition" '' ${skipTaffybarInOtherShells} || exit 1 if [ -x /run/current-system/sw/bin/desktop_shell_ui ]; then exec /run/current-system/sw/bin/desktop_shell_ui exec-condition taffybar fi exit 0 ''; statusNotifierWatcherPreStart = pkgs.writeShellScript "status-notifier-watcher-pre-start" '' owner_pid="$( ${pkgs.systemd}/bin/busctl --user status org.kde.StatusNotifierWatcher 2>/dev/null | while IFS='=' read -r key value; do if [ "$key" = PID ]; then printf '%s' "$value" break fi done )" if [ -z "$owner_pid" ]; then exit 0 fi if ${pkgs.systemd}/bin/busctl --user introspect org.kde.StatusNotifierWatcher /StatusNotifierWatcher >/dev/null 2>&1; then exit 0 fi cmdline="$(${pkgs.coreutils}/bin/tr '\0' ' ' < "/proc/$owner_pid/cmdline" 2>/dev/null || true)" case "$cmdline" in *kded6*) echo "status-notifier-watcher-pre-start: killing stale kded6 StatusNotifierWatcher owner pid=$owner_pid" >&2 kill "$owner_pid" 2>/dev/null || true attempts=0 while ${pkgs.systemd}/bin/busctl --user status org.kde.StatusNotifierWatcher >/dev/null 2>&1; do attempts=$((attempts + 1)) if [ "$attempts" -ge 20 ]; then break fi ${pkgs.coreutils}/bin/sleep 0.1 done ;; esac ''; in makeEnable config "myModules.taffybar" false { myModules.sni.enable = true; myModules.chrome-favicon-dbus.enable = true; environment.systemPackages = [ taffybarPackage ]; home-manager.sharedModules = [ ({lib, ...}: { services."status-notifier-watcher".enable = true; # home-manager's module defaults to nixpkgs' status-notifier-item, which can lag. # Point it at the pinned flake version instead. services."status-notifier-watcher".package = pkgs.lib.mkForce inputs.imalison-taffybar.packages.${system}.status-notifier-item; systemd.user.targets.tray.Unit = { PartOf = ["graphical-session.target"]; StopWhenUnneeded = true; }; systemd.user.services."status-notifier-watcher" = { Unit.Before = ["taffybar.service" "plasma-kded6.service"]; Service.ExecStartPre = "${statusNotifierWatcherPreStart}"; }; # Disable kded6's statusnotifierwatcher module so it doesn't race with # the Haskell status-notifier-watcher for the org.kde.StatusNotifierWatcher bus name. xdg.configFile."kded6rc".text = '' [Module-statusnotifierwatcher] autoload=false ''; services.taffybar = { enable = true; package = taffybarPackage; }; xdg.configFile."systemd/user/taffybar.service".force = true; home.activation.removeStaleTaffybarOverride = lib.hm.dag.entryAfter ["writeBoundary"] '' rm -f "$HOME/.config/systemd/user/taffybar.service.d/override.conf" rmdir --ignore-fail-on-non-empty "$HOME/.config/systemd/user/taffybar.service.d" 2>/dev/null || true ''; systemd.user.services.taffybar.Service = { ExecCondition = "${taffybarExecCondition}"; ExecStartPre = "${waitForGraphicalSocket}"; ExecStart = lib.mkForce "${taffybarStart}"; StandardOutput = "journal"; StandardError = "journal"; }; }) ]; }