{ config, pkgs, ... }: let # Dynamically turns off all unfocused monitors, and restores them on toggle toggleImmersive = pkgs.writeShellScriptBin "toggle-immersive" '' STATE_FILE="$XDG_RUNTIME_DIR/hypr_immersive_mode" if [ -f "$STATE_FILE" ]; then # 1. Restore: Reloading Hyprland snaps monitors back to your declared Nix defaults hyprctl reload rm "$STATE_FILE" ${pkgs.libnotify}/bin/notify-send -u low "Immersive Mode" "Deactivated — Displays restored." else # 2. Activate: Mark state and dynamically disable all non-focused monitors touch "$STATE_FILE" # Use jq to find every monitor that does NOT currently have focus for mon in $(${pkgs.hyprland}/bin/hyprctl monitors -j | ${pkgs.jq}/bin/jq -r '.[] | select(.focused == false) | .name'); do ${pkgs.hyprland}/bin/hyprctl keyword monitor "$mon, disable" done # OPTIONAL: Remove borders and gaps for a true cinema experience # ${pkgs.hyprland}/bin/hyprctl keyword general:gaps_in 0 # ${pkgs.hyprland}/bin/hyprctl keyword general:gaps_out 0 # ${pkgs.hyprland}/bin/hyprctl keyword general:border_size 0 # ${pkgs.hyprland}/bin/hyprctl keyword decoration:rounding 0 ${pkgs.libnotify}/bin/notify-send -u low "Immersive Mode" "Activated — Focused display only." fi ''; in { home.packages = [ toggleImmersive ]; wayland.windowManager.hyprland = { enable = true; settings = { # Bind to your preferred combo (e.g., Super + Alt + M) bind = [ "SUPER ALT, M, exec, ${toggleImmersive}/bin/toggle-immersive" ]; }; }; }