#!/bin/bash

# A hyprland script for a laptop-external-monitor setup, toggling between which is in use
# by https://gist.github.com/miyl
# Forked by Pavel Hrdina

# Launch at startup to make hyprland disable the internal monitor if an external monitor is detected and enabled
# Additionally it's called with a keybind to switch between a laptop monitor and an external display
# Ideally the conditional monitor behaviour was instead done directly in hyprland.conf, but I'm not sure whether that's possible
#
# Relevant info:
# - hyprctl monitors: identifies currently enabled monitors
# - hyprctl monitors all: identifies ALL connected monitors - including those not in use
#
# Suggested use:
# Add this line somewhere after the regular monitor configuration in hyprland.conf:
# exec = /path/to/hyprland-monitors-toggle.sh
# Add a keybind to run this script on demand:
# bind =,SomeKeyHere, exec, /path/to/hyprland-monitors-toggle.sh

move_all_workspaces_to_monitor() {
	TARGET_MONITOR="$1"
	hyprctl workspaces | grep ^workspace | cut --delimiter ' ' --fields 3 | xargs -I '{}' hyprctl dispatch moveworkspacetomonitor '{}' "$TARGET_MONITOR"
}

# Declare an array of all connected monitors using magical regex.
# Second tr needed to remove any commas, does not work in sed for me.
# It's hacky as hell but it work without problems.
# Grep anything within () form the output of wlr-randr,
# then remove unwanted characters using sed and tr, finally sort the
# output ignoring duplicates.
MONITORS=($(wlr-randr | grep -oP '\(\K[^)]*(?=\))' | sed -r 's/\b(,|current|null|preferred)\b//g' | tr -d "," | tr "\n" ' ' | sort -u))
INTERNAL_MONITOR=${MONITORS[0]}
EXTERNAL_MONITOR=${MONITORS[1]}

NUM_MONITORS=$(hyprctl monitors all | grep --count Monitor)
NUM_MONITORS_ACTIVE=$(hyprctl monitors | grep --count Monitor)

# For initial startup if you use hyprland's default monitor settings:
# Turn off the laptop monitor if it + another monitor is active
if [ "$NUM_MONITORS_ACTIVE" -ge 2 ] && hyprctl monitors | cut --delimiter ' ' --fields 2 | grep --quiet ^"$INTERNAL_MONITOR"; then
	# Doing this I hopefully end up on workspace 1 on the external monitor rather than 2 at startup
	move_all_workspaces_to_monitor "$EXTERNAL_MONITOR"
	hyprctl keyword monitor "$INTERNAL_MONITOR, disable"
	# Alternate fix to ensure I start on workspace 1
	# hyprctl dispatch workspace 1
	exit
fi

# For dynamically toggling which monitor is active later via a keybind
if [ "$NUM_MONITORS" -gt 1 ]; then # Handling multiple monitors
	if hyprctl monitors | cut --delimiter ' ' --fields 2 | grep --quiet ^"$EXTERNAL_MONITOR"; then
		hyprctl keyword monitor "$INTERNAL_MONITOR",preferred,0x0,1
		move_all_workspaces_to_monitor "$INTERNAL_MONITOR"
		hyprctl keyword monitor "$EXTERNAL_MONITOR, disable"
	else
		hyprctl keyword monitor "$EXTERNAL_MONITOR",preferred,0x0,1

		move_all_workspaces_to_monitor "$EXTERNAL_MONITOR"
		hyprctl keyword monitor "$INTERNAL_MONITOR, disable"
	fi
else # If the external monitor is disconnected without running this script first, it might become the case that no monitor is on - therefore turn on the laptop monitor!
	hyprctl keyword monitor "$INTERNAL_MONITOR",preferred,0x0,1
	move_all_workspaces_to_monitor "$INTERNAL_MONITOR"
fi
