Last active
April 19, 2025 23:26
-
-
Save miyl/7c4ebc95c5a02f84f36a769a3690cde6 to your computer and use it in GitHub Desktop.
A hyprland script for a laptop-external-monitor setup, toggling between which is in use
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
#! /usr/bin/env sh | |
# A hyprland script for a laptop-external-monitor setup, toggling between which is in use | |
# 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" | |
# Previous approach | |
#hyprctl swapactiveworkspaces $EXTERNAL_MONITOR $INTERNAL_MONITOR | |
} | |
# TODO: Detect these instead of hardcoding them | |
INTERNAL_MONITOR="ADD YOUR INTERNAL MONITOR NAME HERE" | |
EXTERNAL_MONITOR="ADD YOUR EXTERNAL MONITOR NAME HERE" | |
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 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I had some issues where the script stopped randomly working and enabled my internal monitor again. Not sure why exactly but i have been working on a different implementation using Hyprlands IPC socket (hyprctl-like requests) and socket2 (live events).
I have not managed to make the hyprctl-like requests work for socket. For example
monitors
works exactly like it does with hyprctl butworkspaces
returns nothing. What i did make work however was listing to socket2 events, so this would eliminate the need for manual reloading of the config for you script. Here is a example: