-
-
Save miyl/7c4ebc95c5a02f84f36a769a3690cde6 to your computer and use it in GitHub Desktop.
#! /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 |
Thanks1
I just did a rewrite that will hopefully solve that issue, but strangely during testing I also noticed that the monitor switch - or at least the version above - occasionally crashes either Hyprland itself or XWayland. Very strange.
XWayland crashes should no longer bring Hyprland down with it in the upcoming version, though, but still.
# Jun 08 12:37:38 cpu kernel: traps: Hyprland[54550] trap invalid opcode ip:64776e17ed94 sp:7fff2fcec150 error:0 in Hyprland[64776e17c000+338000]
# Jun 08 12:37:38 cpu systemd[1]: Started Process Core Dump (PID 55366/UID 0).
# Jun 08 12:37:39 cpu systemd-coredump[55367]: [🡕] Process 54550 (Hyprland) of user 1000 dumped core.
It's something in these three lines (beside the comment) that causes it:
hyprctl keyword monitor "$INTERNAL_MONITOR, preferred, 0, auto"
# Move workspaces from the external monitor to the internal
hyprctl swapactiveworkspaces $EXTERNAL_MONITOR $INTERNAL_MONITOR
hyprctl keyword monitor "$EXTERNAL_MONITOR, disable"
swapactiveworkspaces
is there due to sometimes seeing a crash when there were windows on multiple workspaces.
swapactiveworkspaces 1 0 (or 0 1, dont know which direction hyperland uses) instead of their names maybe ?
keep in mind it completely swaps workspaces.. see:
i think you're better off moving all (hidden) windows to a different workspace?
maybe with this: https://hyprland-community.github.io/pyprland/lost_windows.html
Good point, while it probably would work in my case since I only have one monitor open at a time it doesn't seem ideal.
I've put up a new version which moves them via the dispact moveworkspacetomonitor
instead.
Also changed how the new monitor is enabled, which seems to've fixed the issue with the occasional crashes.
Hello,
I edited line 36 to:
if hyprctl monitors | grep --quiet "\s$EXTERNAL_MONITOR"; then
Case:
INTERNAL_MONITOR="eDP-1"
EXTERNAL_MONITOR="DP-1"
line 36 would always be true due to the naming of my monitors, with the \s it will force a space before the name in the grep and thus work as intended!
thx for the script btw, loving it !