summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-01-31 13:46:56 -0600
committerCraig Jennings <c@cjennings.net>2026-01-31 13:46:56 -0600
commit8d8c148ce83efe8f86037affbc7e67c3db7705cc (patch)
treec5214dd1ad18fd7f036f8d1647ae8ddfd4b92664
parent657d49d1589c8729d249e624ebc825ab5c161097 (diff)
fix(hyprland): auto-rebuild plugins and preserve stash master position
- Add pacman hook to rebuild hyprpm plugins after Hyprland updates - Change startup to hyprpm update -n (rebuilds if needed) - Fix stash-restore to preserve master window using batch commands - Add validation tests for plugins and hyprpm hook
-rwxr-xr-xarchsetup19
-rw-r--r--dotfiles/hyprland/.config/hypr/hyprland.conf2
-rwxr-xr-xdotfiles/hyprland/.local/bin/stash-restore16
-rw-r--r--scripts/testing/lib/validation.sh56
4 files changed, 88 insertions, 5 deletions
diff --git a/archsetup b/archsetup
index 13abac9..f92e58e 100755
--- a/archsetup
+++ b/archsetup
@@ -1449,6 +1449,25 @@ hyprland() {
action="enabling hy3 plugin" && display "task" "$action"
(sudo -u "$username" hyprpm enable hy3 >> "$logfile" 2>&1) || \
error "warn" "$action" "$?"
+
+ # Pacman hook to rebuild plugins after Hyprland updates
+ # Prevents plugin version mismatch that causes plugins to fail loading
+ action="creating hyprpm pacman hook" && display "task" "$action"
+ mkdir -p /etc/pacman.d/hooks
+ cat > /etc/pacman.d/hooks/hyprpm.hook << 'HOOKEOF'
+[Trigger]
+Operation = Upgrade
+Type = Package
+Target = hyprland
+
+[Action]
+Description = Rebuilding Hyprland plugins after update...
+When = PostTransaction
+Exec = /usr/bin/runuser -u ARCHSETUP_USERNAME -- /usr/bin/hyprpm update --no-shallow
+HOOKEOF
+ # Replace placeholder with actual username
+ sed -i "s/ARCHSETUP_USERNAME/$username/" /etc/pacman.d/hooks/hyprpm.hook
+ chmod 644 /etc/pacman.d/hooks/hyprpm.hook
}
### Display Server (conditional)
diff --git a/dotfiles/hyprland/.config/hypr/hyprland.conf b/dotfiles/hyprland/.config/hypr/hyprland.conf
index dfbb49e..78c5bdf 100644
--- a/dotfiles/hyprland/.config/hypr/hyprland.conf
+++ b/dotfiles/hyprland/.config/hypr/hyprland.conf
@@ -17,7 +17,7 @@ exec-once = systemctl --user start xdg-desktop-portal-hyprland xdg-desktop-porta
# Core services
exec-once = /usr/bin/gnome-keyring-daemon --start --components=pkcs11,secrets,ssh
exec-once = dunst > ~/.local/var/log/dunst-$(date +%Y-%m-%d-%H%M%S).log 2>&1
-exec-once = [ -n "$(hyprpm list 2>/dev/null)" ] && hyprpm reload; sleep 2 && hyprctl dismissnotify -1
+exec-once = hyprpm update -n && sleep 2 && hyprctl dismissnotify -1
# Desktop appearance (after portal is ready)
exec-once = swww-daemon && sleep 1 && swww img ~/pictures/wallpaper/trondheim-norway.jpg
diff --git a/dotfiles/hyprland/.local/bin/stash-restore b/dotfiles/hyprland/.local/bin/stash-restore
index e04945a..ddaa5a4 100755
--- a/dotfiles/hyprland/.local/bin/stash-restore
+++ b/dotfiles/hyprland/.local/bin/stash-restore
@@ -1,10 +1,18 @@
#!/bin/bash
# Restore all windows from special:stash to current workspace
+# Preserves current master window position using batch commands
workspace=$(hyprctl activeworkspace -j | jq -r '.id')
+original_focus=$(hyprctl activewindow -j | jq -r '.address')
-# Get all windows in special:stash and move them to current workspace
-hyprctl clients -j | jq -r '.[] | select(.workspace.name == "special:stash") | .address' | \
-while read -r addr; do
- hyprctl dispatch movetoworkspacesilent "$workspace",address:"$addr"
+# Get all windows in special:stash
+stashed=$(hyprctl clients -j | jq -r '.[] | select(.workspace.name == "special:stash") | .address')
+
+if [ -z "$stashed" ]; then
+ exit 0
+fi
+
+# Restore each window, then swap original back to master (batched for atomicity)
+for addr in $stashed; do
+ hyprctl --batch "dispatch movetoworkspacesilent $workspace,address:$addr ; dispatch focuswindow address:$original_focus ; dispatch layoutmsg swapwithmaster master"
done
diff --git a/scripts/testing/lib/validation.sh b/scripts/testing/lib/validation.sh
index 58f2174..16b4122 100644
--- a/scripts/testing/lib/validation.sh
+++ b/scripts/testing/lib/validation.sh
@@ -534,12 +534,68 @@ validate_portal_dark_mode() {
fi
}
+validate_hyprland_plugins() {
+ step "Checking Hyprland plugins installed"
+
+ # Check if hyprpm has repositories configured
+ local repos=$(ssh_cmd "sudo -u cjennings hyprpm list 2>/dev/null | grep -c 'Repository' || echo 0")
+ if [ "$repos" -lt 2 ]; then
+ validation_fail "Hyprland plugin repositories not configured (found $repos, expected 2)"
+ attribute_issue "hyprpm repositories not configured" "archsetup"
+ return 1
+ fi
+
+ # Check for expected enabled plugins
+ local missing=""
+ for plugin in hyprscrolling xtra-dispatchers hy3; do
+ if ! ssh_cmd "sudo -u cjennings hyprpm list 2>/dev/null | grep -A1 'Plugin $plugin' | grep -q 'enabled: true'"; then
+ missing="$missing $plugin"
+ fi
+ done
+
+ if [ -z "$missing" ]; then
+ validation_pass "All Hyprland plugins enabled (hyprscrolling, xtra-dispatchers, hy3)"
+ else
+ validation_fail "Hyprland plugins not enabled:$missing"
+ attribute_issue "Hyprland plugins not enabled:$missing" "archsetup"
+ fi
+}
+
+validate_hyprpm_hook() {
+ step "Checking hyprpm pacman hook"
+
+ local hook_file="/etc/pacman.d/hooks/hyprpm.hook"
+ if ! ssh_cmd "test -f $hook_file"; then
+ validation_fail "hyprpm pacman hook not found at $hook_file"
+ attribute_issue "hyprpm pacman hook missing" "archsetup"
+ return 1
+ fi
+
+ # Verify hook targets hyprland package
+ if ! ssh_cmd "grep -q 'Target = hyprland' $hook_file"; then
+ validation_fail "hyprpm hook doesn't target hyprland package"
+ attribute_issue "hyprpm hook misconfigured" "archsetup"
+ return 1
+ fi
+
+ # Verify hook runs hyprpm update
+ if ! ssh_cmd "grep -q 'hyprpm update' $hook_file"; then
+ validation_fail "hyprpm hook doesn't run hyprpm update"
+ attribute_issue "hyprpm hook misconfigured" "archsetup"
+ return 1
+ fi
+
+ validation_pass "hyprpm pacman hook configured correctly"
+}
+
validate_window_manager() {
# Detect which desktop environment is installed and validate accordingly
if ssh_cmd "pacman -Q hyprland &>/dev/null"; then
section "Hyprland Desktop Environment"
validate_hyprland_tools
validate_hyprland_config
+ validate_hyprland_plugins
+ validate_hyprpm_hook
validate_hyprland_socket
validate_portal_dark_mode
elif ssh_cmd "test -f /usr/local/bin/dwm"; then