feat: hyprshutdown power binds, 76% scrolling windows, single-sudo sysupdate

- hyprshutdown wired into the graceful power flow (Super+Shift+O logout,
  Super+Ctrl+O power off, Super+Ctrl+Shift+O reboot) so apps close cleanly with a
  UI before Hyprland exits, instead of a hard systemctl call. Added to the hyprlua
  package list.
- Scrolling layout: default window is now 76% of the monitor along the scroll axis
  (column_width 0.5 -> 0.76).
- sysupdate.sh: primes sudo once at startup and keeps the credential alive for the
  whole run, so no later step re-prompts.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SUN7gg6GGfnToghMijLm5Y
main
Amir Alexander Abdelbaki 2026-07-07 13:26:48 +02:00
parent 48505a5726
commit 9d1ec69a11
4 changed files with 25 additions and 8 deletions

View File

@ -4,9 +4,12 @@
-- * focus_fit_method 0/1 ("Centered follow") — see M.set_fit(); when centered the -- * focus_fit_method 0/1 ("Centered follow") — see M.set_fit(); when centered the
-- focused column is centred and the previous/next columns peek in from the sides. -- focused column is centred and the previous/next columns peek in from the sides.
-- --
-- column_width is kept < 1.0 (0.5) so the active column is narrower than the viewport -- column_width is the default window size along the scroll axis, as a fraction of the
-- and the prev/next columns stay on-screen and clickable. fullscreen_on_one_column -- monitor (0.76 = 76% of the monitor's width for a horizontal tape, or its height for a
-- lets a lone window still fill the screen, so the narrow width costs nothing alone. -- vertical one — the layout applies it to whichever axis `direction` scrolls). Keeping it
-- < 1.0 leaves the prev/next windows peeking in on-screen and clickable;
-- fullscreen_on_one_column lets a lone window still fill the screen, so it costs nothing
-- when a window is alone.
return { return {
name = "scrolling", name = "scrolling",
label = "Scrolling", label = "Scrolling",
@ -18,7 +21,7 @@ return {
config = { config = {
scrolling = { scrolling = {
direction = "down", direction = "down",
column_width = 0.5, column_width = 0.76, -- 76% of the monitor along the scroll axis
focus_fit_method = 1, focus_fit_method = 1,
follow_focus = true, follow_focus = true,
fullscreen_on_one_column = true, fullscreen_on_one_column = true,

View File

@ -88,10 +88,12 @@ hl.bind(mainMod .. " + SHIFT + Q", hl.dsp.exec_cmd("hyprctl kill"))
hl.bind(mainMod .. " + CTRL + M", hl.dsp.exec_cmd("~/.config/scripts/toggle-layout.sh")) hl.bind(mainMod .. " + CTRL + M", hl.dsp.exec_cmd("~/.config/scripts/toggle-layout.sh"))
-- lock/exit -- lock/exit — hyprshutdown gracefully closes every app (with a UI) before it exits
-- Hyprland and runs its --post-cmd, instead of yanking the session out from under them.
hl.bind(mainMod .. " + O", hl.dsp.exec_cmd("hyprlock")) hl.bind(mainMod .. " + O", hl.dsp.exec_cmd("hyprlock"))
hl.bind(mainMod .. " + SHIFT + O", hl.dsp.exec_cmd("hyprctl dispatch exit")) hl.bind(mainMod .. " + SHIFT + O", hl.dsp.exec_cmd("hyprshutdown")) -- graceful logout
hl.bind(mainMod .. " + CTRL + O", hl.dsp.exec_cmd("systemctl poweroff")) hl.bind(mainMod .. " + CTRL + O", hl.dsp.exec_cmd('hyprshutdown -p "systemctl poweroff"')) -- graceful power off
hl.bind(mainMod .. " + CTRL + SHIFT + O",hl.dsp.exec_cmd('hyprshutdown -p "systemctl reboot"')) -- graceful reboot
hl.bind(mainMod .. " + ALT + O", hl.dsp.exec_cmd("~/.config/scripts/pwr-dmenu.sh")) hl.bind(mainMod .. " + ALT + O", hl.dsp.exec_cmd("~/.config/scripts/pwr-dmenu.sh"))
hl.bind(mainMod .. " + ALT + CTRL + SHIFT + END", hl.dsp.exit()) hl.bind(mainMod .. " + ALT + CTRL + SHIFT + END", hl.dsp.exit())

View File

@ -89,6 +89,7 @@ HYPRLUA_PACKAGES=(
hyprsunset # blue-light filter / night-mode daemon hyprsunset # blue-light filter / night-mode daemon
hypridle # idle daemon triggering lock/suspend after inactivity hypridle # idle daemon triggering lock/suspend after inactivity
hyprshutdown # hyprtoolkit graphical power/shutdown dialog (Super+Alt+O)
ksshaskpass # Qt SSH passphrase dialog registered as ssh-askpass ksshaskpass # Qt SSH passphrase dialog registered as ssh-askpass
nm-connection-editor # GTK editor for NetworkManager connection profiles nm-connection-editor # GTK editor for NetworkManager connection profiles

View File

@ -96,7 +96,17 @@ spin_stop() {
printf '\r%*s\r' "$(_cols)" '' printf '\r%*s\r' "$(_cols)" ''
} }
trap 'spin_stop; tput cnorm 2>/dev/null || true' EXIT _SUDO_KEEPALIVE=""
trap 'spin_stop; [[ -n "${_SUDO_KEEPALIVE:-}" ]] && kill "$_SUDO_KEEPALIVE" 2>/dev/null; tput cnorm 2>/dev/null || true' EXIT
# Prime sudo ONCE at startup and keep the credential fresh for the whole run, so no
# later step (config deploy, pacman -S per package, state-file write) re-prompts.
sudo_prime() {
printf " ${Y}?${RS} ${BO}Elevated access${RS} — enter your password once for this run.\n"
sudo -v || { err "sudo is required."; exit 1; }
( while true; do sudo -n true 2>/dev/null; sleep 50; kill -0 "$$" 2>/dev/null || exit; done ) &
_SUDO_KEEPALIVE=$!
}
# ═══════════════════════════════════════════════════════════════════════════════ # ═══════════════════════════════════════════════════════════════════════════════
# STATE FILE # STATE FILE
@ -694,6 +704,7 @@ declare -a FLATPAK_PKGS=()
main() { main() {
header header
sudo_prime # single password prompt up front; kept alive for the whole run
# ── Configs-only mode ──────────────────────────────────────────────────── # ── Configs-only mode ────────────────────────────────────────────────────
if [[ "$UPDATE_MODE" == "configs" ]]; then if [[ "$UPDATE_MODE" == "configs" ]]; then