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 ;;
|
2) ${pkgs.systemd}/bin/systemctl poweroff ;;
|
||||||
esac
|
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
|
in
|
||||||
{
|
{
|
||||||
imports = [ ./gpg.nix ./media.nix ./texlive.nix ./librewolf.nix ./mc.nix ./mime.nix ./hyprland-workspaces.nix ];
|
imports = [ ./gpg.nix ./media.nix ./texlive.nix ./librewolf.nix ./mc.nix ./mime.nix ./hyprland-workspaces.nix ];
|
||||||
@@ -479,7 +520,10 @@ in
|
|||||||
configType = "hyprlang";
|
configType = "hyprlang";
|
||||||
|
|
||||||
settings = {
|
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
|
# 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
|
# 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.
|
# With two monitors the relative +1 just toggles between them.
|
||||||
"$mod, o, focusmonitor, +1"
|
"$mod, o, focusmonitor, +1"
|
||||||
"$mod SHIFT, o, movecurrentworkspacetomonitor, +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.
|
# 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`.
|
# References physical key codes for robustness with the SHIFT key, e.g. `code:10` instead of `1`.
|
||||||
|
|||||||
Reference in New Issue
Block a user