Created
April 18, 2026 03:52
-
-
Save abbood/d97f0fc3c14ad26daa8d3c1ea66a0c9c to your computer and use it in GitHub Desktop.
hyprmon-auto-switch
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/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