Skip to content

Instantly share code, notes, and snippets.

@abbood
Created April 18, 2026 03:53
Show Gist options
  • Select an option

  • Save abbood/578e95cb6875cc297f1daaf7d21cc93f to your computer and use it in GitHub Desktop.

Select an option

Save abbood/578e95cb6875cc297f1daaf7d21cc93f to your computer and use it in GitHub Desktop.
hyprmon-monitor-daemon
#!/bin/bash
# Logging setup
LOG_DIR="$HOME/.local/share/hyprmon-daemon"
LOG_FILE="$LOG_DIR/daemon.log"
mkdir -p "$LOG_DIR"
# Function to log with timestamp
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" >> "$LOG_FILE"
}
log "========== DAEMON STARTED =========="
log "Hyprland instance: $HYPRLAND_INSTANCE_SIGNATURE"
# Track current state
LAST_STATE=""
# Function to get current monitor state from Hyprland
get_hyprland_state() {
hyprctl monitors -j 2>/dev/null | jq -r '.[].name' | grep -E "^DP-" | sort | tr '\n' ',' || echo ""
}
# Function to get current monitor state from DRM (hardware)
get_drm_state() {
grep -h "^connected$" /sys/class/drm/card1-DP-*/status 2>/dev/null | wc -l
}
# Initialize with current state
LAST_STATE=$(get_hyprland_state)
log "Initial Hyprland state: [$LAST_STATE]"
# Function to check and trigger if state changed
check_state_change() {
NEW_STATE=$(get_hyprland_state)
if [ "$NEW_STATE" != "$LAST_STATE" ]; then
log "State changed from [$LAST_STATE] to [$NEW_STATE] - TRIGGERING auto-switch"
LAST_STATE=$NEW_STATE
~/.local/bin/hyprmon-auto-switch
fi
}
# Start polling in background (every 3 seconds)
(
while true; do
sleep 3
# Check if DRM state doesn't match Hyprland state
DRM_EXTERNAL_COUNT=$(get_drm_state)
HYPR_STATE=$(get_hyprland_state)
# DRM says external is connected (count > 0) but Hyprland doesn't see it
if [ "$DRM_EXTERNAL_COUNT" -gt 0 ] && [ -z "$HYPR_STATE" ]; then
log "[POLLING] DRM detects external monitor but Hyprland doesn't - forcing check"
check_state_change
# DRM says no external (count = 0) but Hyprland still sees it
elif [ "$DRM_EXTERNAL_COUNT" -eq 0 ] && [ -n "$HYPR_STATE" ]; then
log "[POLLING] DRM shows no external monitor but Hyprland still sees it - forcing check"
check_state_change
fi
done
) &
# Also listen to Hyprland events (for fast response when they work)
socat -U - UNIX-CONNECT:$XDG_RUNTIME_DIR/hypr/$HYPRLAND_INSTANCE_SIGNATURE/.socket2.sock | \
while read -r line; do
# Log ALL monitor-related events
if echo "$line" | grep -qE "^monitor"; then
log "RAW monitor event: $line"
# Only care about external monitor (DP-*) add/remove
if echo "$line" | grep -qE "^monitor(added|removed)>>DP-"; then
sleep 2
log "[EVENT] External monitor event detected - checking state"
check_state_change
fi
fi
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment