From 44a7bb72efdb9bfb69db8bfca876497cadec4f2d Mon Sep 17 00:00:00 2001 From: Alexander Heldt Date: Sat, 7 Feb 2026 10:08:21 +0100 Subject: [PATCH] pinwheel: Add dynamic hyprland monitor hotplug handler --- hosts/pinwheel/modules/hyprland/default.nix | 82 ++++++++++++++++++--- 1 file changed, 71 insertions(+), 11 deletions(-) diff --git a/hosts/pinwheel/modules/hyprland/default.nix b/hosts/pinwheel/modules/hyprland/default.nix index 7fd3263..a364124 100644 --- a/hosts/pinwheel/modules/hyprland/default.nix +++ b/hosts/pinwheel/modules/hyprland/default.nix @@ -7,6 +7,59 @@ }: let enabled = config.mod.hyprland.enable; + + monitorScript = pkgs.writeShellScript "hyprland-monitor-handler" '' + INTERNAL="eDP-1" + EXTERNAL_MONITORS="HDMI-A-1 DP-3" + HYPRCTL="${pkgs.hyprland}/bin/hyprctl" + JQ="${pkgs.jq}/bin/jq" + + get_active_external() { + # Return the first connected external monitor + for mon in $EXTERNAL_MONITORS; do + if $HYPRCTL monitors -j | $JQ -e ".[] | select(.name == \"$mon\")" > /dev/null 2>&1; then + echo "$mon" + return 0 + fi + done + return 1 + } + + bind_workspaces() { + local external + + if external=$(get_active_external); then + # External monitor connected: 1-5 on external, 6-10 on internal + for ws in 1 2 3 4 5; do + $HYPRCTL keyword workspace "$ws, monitor:$external, default:true" + done + for ws in 6 7 8 9 10; do + $HYPRCTL keyword workspace "$ws, monitor:$INTERNAL, default:true" + done + else + # No external monitor: all workspaces on internal + for ws in 1 2 3 4 5 6 7 8 9 10; do + $HYPRCTL keyword workspace "$ws, monitor:$INTERNAL, default:true" + done + fi + } + + handle_event() { + case $1 in + monitoradded*|monitorremoved*) + sleep 0.5 # Give monitor time to initialize + bind_workspaces + ;; + esac + } + + # Bind workspaces on startup + bind_workspaces + + ${pkgs.socat}/bin/socat -U - UNIX-CONNECT:"$XDG_RUNTIME_DIR/hypr/$HYPRLAND_INSTANCE_SIGNATURE/.socket2.sock" | while read -r line; do + handle_event "$line" + done + ''; in { options = { @@ -41,17 +94,7 @@ in monitor=eDP-1, 1920x1200, auto-center-down, 1 monitor=HDMI-A-1, 2560x1440@100, auto-center-up, 1 - - workspace = 1, monitor:HDMI-A-1 - workspace = 2, monitor:HDMI-A-1 - workspace = 3, monitor:HDMI-A-1 - workspace = 4, monitor:HDMI-A-1 - workspace = 5, monitor:HDMI-A-1 - workspace = 6, monitor:eDP-1 - workspace = 7, monitor:eDP-1 - workspace = 8, monitor:eDP-1 - workspace = 9, monitor:eDP-1 - workspace = 10, monitor:eDP-1 + monitor=DP-3, 2560x1440@60, auto-center-up, 1 workspace = w[tv1], gapsout:0, gapsin:0 workspace = f[1], gapsout:0, gapsin:0 @@ -171,6 +214,23 @@ in pkgs.wdisplays pkgs.bc ]; + + systemd.user.services.hyprland-monitors = { + Unit = { + Description = "Hyprland monitor hotplug handler"; + PartOf = [ "graphical-session.target" ]; + After = [ "graphical-session.target" ]; + }; + Service = { + Type = "simple"; + ExecStart = "${monitorScript}"; + Restart = "on-failure"; + RestartSec = 5; + }; + Install = { + WantedBy = [ "graphical-session.target" ]; + }; + }; }; # To start electron apps like `chromium` with wayland support