Skip to content

Instantly share code, notes, and snippets.

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

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

Select an option

Save abbood/d97f0fc3c14ad26daa8d3c1ea66a0c9c to your computer and use it in GitHub Desktop.
hyprmon-auto-switch
#!/bin/bash
LOG_DIR="$HOME/.local/share/hyprmon-daemon"
LOG_FILE="$LOG_DIR/switch.log"
mkdir -p "$LOG_DIR"
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" >> "$LOG_FILE"
}
# to prevent hyprland from crashing on sudden hdmi disconnect
ungroup_all_windows() {
log "Ungrouping all grouped windows..."
GROUPED=$(hyprctl clients -j | jq -r '.[] | select(.grouped | length > 0) | .address')
while read -r addr; do
[ -z "$addr" ] && continue
hyprctl dispatch moveoutofgroup address:"$addr"
log " Ungrouped window $addr"
done <<< "$GROUPED"
}
log "========== F1 TOGGLE TRIGGERED =========="
# Check eDP-1 DPMS state (true = physically on, false = DPMS off but still "active" in Hyprland)
EDPM_ON=$(hyprctl monitors -j | jq -r '.[] | select(.name == "eDP-1") | .dpmsStatus')
log "eDP-1 dpmsStatus: $EDPM_ON"
# Detect external monitor (DP or HDMI)
EXTERNAL_MONITOR=$(hyprctl monitors -j | jq -r '.[].name' | grep -E "^(DP-[0-9]|HDMI-A-[0-9])" | head -1)
log "External monitor: ${EXTERNAL_MONITOR:-none}"
if [ "$EDPM_ON" = "true" ]; then
# Safety: don't blank the only active display
ACTIVE_COUNT=$(hyprctl monitors -j | jq 'length')
if [ "$ACTIVE_COUNT" -le 1 ]; then
log "Refusing to disable: eDP-1 is the only active display"
notify-send "Monitor" "Can't disable the only active display" -t 2000
exit 1
fi
# Laptop display is on → switch to external only
log "Action: eDP-1 ON → turning OFF (OLED protection)"
#ungroup_all_windows
if [ -n "$EXTERNAL_MONITOR" ]; then
# Migrate workspaces from eDP-1 to external before killing the display
WORKSPACES_TO_MOVE=$(hyprctl workspaces -j | jq -r '.[] | select(.monitor == "eDP-1" and .id > 0 and .windows > 0) |
if .name == (.id | tostring) then .id else "name:" + .name end')
if [ -n "$WORKSPACES_TO_MOVE" ]; then
COUNT=0
MOVED_LIST=""
while read -r ws; do
hyprctl dispatch moveworkspacetomonitor "$ws" "$EXTERNAL_MONITOR"
log " Moved workspace $ws to $EXTERNAL_MONITOR"
MOVED_LIST="$MOVED_LIST $ws"
COUNT=$((COUNT + 1))
done <<< "$WORKSPACES_TO_MOVE"
log "Moved $COUNT workspace(s):$MOVED_LIST"
notify-send "Workspaces Moved" "Migrated $COUNT workspace(s) to $EXTERNAL_MONITOR:$MOVED_LIST" -t 3000
else
log "No workspaces to migrate from eDP-1"
fi
else
log "No external monitor found — turning off laptop display anyway"
fi
hyprctl dispatch dpms off eDP-1
notify-send "Monitor" "Laptop display OFF" -t 2000
else
# Laptop display is DPMS-off → turn it back on
log "Action: eDP-1 OFF → turning ON"
hyprctl dispatch dpms on eDP-1
hyprctl dispatch movecursor 0 0
brightnessctl set 336
log "Restored laptop brightness to 336"
notify-send "Monitor" "Laptop display ON" -t 2000
fi
log "========== TOGGLE COMPLETE =========="
log ""
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment