diff options
Diffstat (limited to 'config/hypr/scripts/Logout.sh')
| -rwxr-xr-x | config/hypr/scripts/Logout.sh | 180 |
1 files changed, 180 insertions, 0 deletions
diff --git a/config/hypr/scripts/Logout.sh b/config/hypr/scripts/Logout.sh new file mode 100755 index 00000000..2f173ffe --- /dev/null +++ b/config/hypr/scripts/Logout.sh @@ -0,0 +1,180 @@ +#!/usr/bin/env bash +# ================================================== +# KoolDots (2026) +# Project URL: https://github.com/LinuxBeginnings +# License: GNU GPLv3 +# SPDX-License-Identifier: GPL-3.0-or-later +# ================================================== +# Logout helper for wlogout and keybind callers. +LOG_DIR="${XDG_STATE_HOME:-$HOME/.local/state}/hypr" +LOG_FILE="${LOG_DIR}/hypr-logout.log" +if ! mkdir -p "$LOG_DIR" >/dev/null 2>&1; then + LOG_FILE="${XDG_RUNTIME_DIR:-/tmp}/hypr-logout.log" +fi + +log_msg() { + printf "[%s] %s\n" "$(date +"%F %T")" "$1" >>"$LOG_FILE" +} + +run_logged() { + local label="$1" + shift + log_msg "RUN ${label}: $*" + "$@" >>"$LOG_FILE" 2>&1 + local rc=$? + log_msg "RC ${label}: ${rc}" + return "$rc" +} +SESSION_USER="${USER:-$(id -un)}" +SESSION_HYPRLAND_PIDS="$(pgrep -xu "$SESSION_USER" -x Hyprland || true)" +SESSION_DM_SERVICE="" +IS_SDDM_SESSION=0 + +session_hyprland_running() { + local pid + if [ -n "$SESSION_HYPRLAND_PIDS" ]; then + for pid in $SESSION_HYPRLAND_PIDS; do + if kill -0 "$pid" >/dev/null 2>&1; then + return 0 + fi + done + return 1 + fi + pgrep -xu "$SESSION_USER" -x Hyprland >/dev/null 2>&1 +} +logout_completed() { + # Give the session up to 2 seconds to terminate after a successful command. + for _ in {1..20}; do + session_hyprland_running || return 0 + sleep 0.1 + done + return 1 +} +stop_proc() { + local name="$1" + pkill -u "$SESSION_USER" -x -TERM "$name" >/dev/null 2>&1 || true + + # Wait up to 1 second for graceful shutdown. + for _ in {1..10}; do + pgrep -xu "$SESSION_USER" -x "$name" >/dev/null 2>&1 || return 0 + sleep 0.1 + done + pkill -u "$SESSION_USER" -x -KILL "$name" >/dev/null 2>&1 || true +} + +# Close wlogout if it is still visible. +stop_proc "wlogout" +HYPRCTL_BIN="$(command -v hyprctl || true)" +HYPRSHUTDOWN_BIN="$(command -v hyprshutdown || true)" +UWSM_BIN="$(command -v uwsm || true)" +LOGINCTL_BIN="$(command -v loginctl || true)" +if [ -n "$LOGINCTL_BIN" ] && [ -n "${XDG_SESSION_ID:-}" ]; then + SESSION_DM_SERVICE="$("$LOGINCTL_BIN" show-session "$XDG_SESSION_ID" -p Service --value 2>/dev/null || true)" + if [ "$SESSION_DM_SERVICE" = "sddm" ] || [ "$SESSION_DM_SERVICE" = "sddm-autologin" ]; then + IS_SDDM_SESSION=1 + fi +fi + +# Preferred path: synchronous hyprshutdown, so script does not silently succeed. +if [ -n "$HYPRSHUTDOWN_BIN" ]; then + if run_logged "hyprshutdown-no-fork" "$HYPRSHUTDOWN_BIN" --no-fork; then + if logout_completed; then + exit 0 + fi + log_msg "hyprshutdown returned success but Hyprland is still running" + fi +fi +# systemd session fallback. +if [ -n "$LOGINCTL_BIN" ] && [ -n "${XDG_SESSION_ID:-}" ]; then + if [ "$IS_SDDM_SESSION" -eq 1 ]; then + log_msg "Skipping loginctl terminate-session for SDDM-managed session (${SESSION_DM_SERVICE})" + elif run_logged "loginctl-terminate-session" "$LOGINCTL_BIN" terminate-session "$XDG_SESSION_ID"; then + if logout_completed; then + exit 0 + fi + log_msg "loginctl terminate-session returned success but Hyprland is still running" + fi +fi + +# Fallback: ask Hyprland to spawn hyprshutdown via a normal dispatch exec call. +if [ -n "$HYPRCTL_BIN" ] && [ -n "$HYPRSHUTDOWN_BIN" ]; then + if run_logged \ + "hyprctl-dispatch-exec-hyprshutdown" \ + "$HYPRCTL_BIN" dispatch exec "hyprshutdown --no-fork"; then + if logout_completed; then + exit 0 + fi + log_msg "hyprctl dispatched hyprshutdown but Hyprland is still running" + fi +fi + +# UWSM-managed session fallback (common on NixOS). +if [ -n "$UWSM_BIN" ] && [ "$IS_SDDM_SESSION" -eq 0 ]; then + if run_logged "uwsm-stop" "$UWSM_BIN" stop; then + if logout_completed; then + exit 0 + fi + log_msg "uwsm stop returned success but Hyprland is still running" + fi +elif [ -n "$UWSM_BIN" ] && [ "$IS_SDDM_SESSION" -eq 1 ]; then + log_msg "Skipping uwsm stop on SDDM-managed session to avoid delayed logout" +fi + + +# Last-resort Hyprland exit fallbacks. +if [ -n "$HYPRCTL_BIN" ]; then + if [ "$IS_SDDM_SESSION" -eq 1 ]; then + if run_logged "hyprctl-exit-1-sddm" "$HYPRCTL_BIN" dispatch exit 1; then + if logout_completed; then + exit 0 + fi + log_msg "hyprctl dispatch exit 1 (sddm) returned success but Hyprland is still running" + fi + if run_logged "hyprctl-exit-x-sddm" "$HYPRCTL_BIN" dispatch exit x; then + if logout_completed; then + exit 0 + fi + log_msg "hyprctl dispatch exit x (sddm) returned success but Hyprland is still running" + fi + else + if run_logged "hyprctl-exit-1" "$HYPRCTL_BIN" dispatch exit 1; then + if logout_completed; then + exit 0 + fi + log_msg "hyprctl dispatch exit 1 returned success but Hyprland is still running" + fi + if run_logged "hyprctl-exit-0" "$HYPRCTL_BIN" dispatch exit 0; then + if logout_completed; then + exit 0 + fi + log_msg "hyprctl dispatch exit 0 returned success but Hyprland is still running" + fi + if run_logged "hyprctl-exit-x" "$HYPRCTL_BIN" dispatch exit x; then + if logout_completed; then + exit 0 + fi + log_msg "hyprctl dispatch exit x returned success but Hyprland is still running" + fi + if run_logged "hyprctl-exit-noarg" "$HYPRCTL_BIN" dispatch exit; then + if logout_completed; then + exit 0 + fi + log_msg "hyprctl dispatch exit (no arg) returned success but Hyprland is still running" + fi + fi +fi + +# Final process-level fallback. +if run_logged "pkill-hyprland-term" pkill -u "$SESSION_USER" -x -TERM Hyprland; then + if logout_completed; then + exit 0 + fi + log_msg "SIGTERM sent to Hyprland but process is still running" +fi +if run_logged "pkill-hyprland-kill" pkill -u "$SESSION_USER" -x -KILL Hyprland; then + exit 0 +fi + +log_msg "Logout failed: no method succeeded" + +exit 1 |
