feat(hyprland): add runtime monitor left/right swap bind
`$mod CTRL o` reflows the two connected monitors adjacent in reversed order (gap-free regardless of differing widths) and re-inits the layer-shell clients, which Hyprland doesn't reliably re-notify on a runtime output move: waybar rebuilds on SIGUSR2, wallpaper is re-pushed. `monitor` default becomes `mkDefault` so a host can pin its own layout. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+47
-1
@@ -79,6 +79,47 @@ let
|
||||
2) ${pkgs.systemd}/bin/systemctl poweroff ;;
|
||||
esac
|
||||
'';
|
||||
|
||||
# Swap the physical left/right placement of a two-monitor setup at runtime.
|
||||
# Reflows the pair adjacent from x=0 (left one at origin, right one butted
|
||||
# against its logical width) after reversing their order — so it stays
|
||||
# gap-free regardless of differing widths, unlike a naive x-origin exchange
|
||||
# (equal widths only). Machine-agnostic: reads whichever two connectors are
|
||||
# live from `hyprctl -j`, no connector names. Ephemeral (hyprctl keyword) —
|
||||
# the per-host default layout is restored on the next reload/relogin. No-op
|
||||
# unless exactly two monitors are connected.
|
||||
#
|
||||
# Hyprland doesn't reliably re-notify layer-shell clients when an output is
|
||||
# reconfigured at runtime (a known limitation — same class as the mirror/unplug
|
||||
# cases where waybar needs a restart). Observed here: after the move, waybar and
|
||||
# the wallpaper keep drawing at the pre-swap offsets, so the moved monitor's
|
||||
# bar/bg land off-screen. Re-init both against the new geometry: waybar rebuilds
|
||||
# its bars on SIGUSR2, and awww only paints outputs present when `awww img` last
|
||||
# ran, so re-push the wallpaper symlink. Both are idempotent — harmless when a
|
||||
# surface happened not to lag (which surface stales seems to race).
|
||||
swapMonitors = pkgs.writeShellScript "hypr-swap-monitors" ''
|
||||
set -eu
|
||||
hc=${config.wayland.windowManager.hyprland.finalPackage}/bin/hyprctl
|
||||
jq=${pkgs.jq}/bin/jq
|
||||
data=$("$hc" monitors -j)
|
||||
n=$(printf '%s' "$data" | "$jq" length)
|
||||
if [ "$n" -ne 2 ]; then
|
||||
${pkgs.libnotify}/bin/notify-send "Monitor swap" "need exactly 2 monitors ($n connected)"
|
||||
exit 0
|
||||
fi
|
||||
# sort by current x → [left, right]; the new left is the old right.
|
||||
cmd=$(printf '%s' "$data" | "$jq" -r '
|
||||
sort_by(.x)
|
||||
| .[1] as $l | .[0] as $r
|
||||
| (($l.width / $l.scale) | floor) as $off
|
||||
| "keyword monitor \($l.name),preferred,0x0,\($l.scale)"
|
||||
+ " ; keyword monitor \($r.name),preferred,\($off)x0,\($r.scale)"')
|
||||
"$hc" --batch "$cmd"
|
||||
# re-anchor the layer-shell clients onto the new geometry (see comment above)
|
||||
${pkgs.procps}/bin/pkill -USR2 -x .waybar-wrapped || true
|
||||
bg="$HOME/.local/share/bg"
|
||||
[ -e "$bg" ] && ${pkgs.awww}/bin/awww img "$bg" || true
|
||||
'';
|
||||
in
|
||||
{
|
||||
imports = [ ./gpg.nix ./media.nix ./texlive.nix ./librewolf.nix ./mc.nix ./mime.nix ./hyprland-workspaces.nix ];
|
||||
@@ -479,7 +520,10 @@ in
|
||||
configType = "hyprlang";
|
||||
|
||||
settings = {
|
||||
monitor = ",preferred,auto,1";
|
||||
# Fallback for hosts that don't pin a layout; a two-monitor host overrides
|
||||
# this with explicit positions (see the private inventory). mkDefault so
|
||||
# that override is a plain value, not a mkForce fight.
|
||||
monitor = lib.mkDefault ",preferred,auto,1";
|
||||
|
||||
# The qt module sets QT_QPA_PLATFORMTHEME=gtk3 (→ Qt apps read the GTK
|
||||
# Adwaita-dark theme), but only into hm-session-vars.sh + the systemd user
|
||||
@@ -582,6 +626,8 @@ in
|
||||
# With two monitors the relative +1 just toggles between them.
|
||||
"$mod, o, focusmonitor, +1"
|
||||
"$mod SHIFT, o, movecurrentworkspacetomonitor, +1"
|
||||
# Swap the two monitors' left/right placement (see swapMonitors above).
|
||||
"$mod CTRL, o, exec, ${swapMonitors}"
|
||||
] ++ (
|
||||
# Dynamic definitions for viewing workspaces 1 to 9 and moving windows between them.
|
||||
# References physical key codes for robustness with the SHIFT key, e.g. `code:10` instead of `1`.
|
||||
|
||||
Reference in New Issue
Block a user