Handle clamshell monitor hotplug

This commit is contained in:
David Heinemeier Hansson
2026-06-22 21:48:35 +02:00
parent 4772f01148
commit ee65304b92
6 changed files with 72 additions and 16 deletions
+16
View File
@@ -0,0 +1,16 @@
#!/bin/bash
# omarchy:summary=Returns true when clamshell mode is active
# omarchy:hidden=true
lid_closed=false
for state in /proc/acpi/button/lid/*/state; do
[[ -r $state ]] || continue
if [[ $(< "$state") == *"closed"* ]]; then
lid_closed=true
break
fi
done
[[ $lid_closed == "true" ]] && omarchy-hw-external-monitors
+11
View File
@@ -0,0 +1,11 @@
#!/bin/bash
# omarchy:summary=Apply clamshell display state to Hyprland monitors
# omarchy:hidden=true
omarchy-hyprland-monitor-internal recover >/dev/null 2>&1 || true
omarchy-hyprland-monitor-internal-mirror recover >/dev/null 2>&1 || true
if omarchy-hw-clamshell; then
omarchy-hyprland-monitor-internal off >/dev/null 2>&1 || true
fi
+16 -5
View File
@@ -4,22 +4,33 @@
SOCKET="$XDG_RUNTIME_DIR/hypr/$HYPRLAND_INSTANCE_SIGNATURE/.socket2.sock"
recover_internal_monitor_toggles() {
omarchy-hyprland-monitor-internal recover
omarchy-hyprland-monitor-internal-mirror recover
sync_clamshell() {
omarchy-hyprland-monitor-clamshell
}
recover_after_monitor_removal() {
recover_internal_monitor_toggles
sync_clamshell
(
sleep 1
recover_internal_monitor_toggles
sync_clamshell
) &
}
sync_clamshell_after_monitor_change() {
sync_clamshell
(
sleep 1
sync_clamshell
) &
}
socat -U - "UNIX-CONNECT:$SOCKET" | while read -r event; do
case "$event" in
monitoradded\>\>*|monitoraddedv2\>\>*)
sync_clamshell_after_monitor_change
;;
monitorremoved\>\>*|monitorremovedv2\>\>*)
recover_after_monitor_removal
;;
+4 -5
View File
@@ -10,16 +10,15 @@ if [[ ! $wait_attempts =~ ^[0-9]+$ ]] || (( wait_attempts < 1 )); then
wait_attempts=100
fi
recover_internal_monitor_toggles() {
omarchy-hyprland-monitor-internal recover >/dev/null 2>&1 || true
omarchy-hyprland-monitor-internal-mirror recover >/dev/null 2>&1 || true
sync_clamshell() {
omarchy-hyprland-monitor-clamshell >/dev/null 2>&1 || true
}
recover_internal_monitor_toggles
sync_clamshell
omarchy-shell lock lock >/dev/null 2>&1 || exit 1
for (( attempt = 0; attempt < wait_attempts; attempt++ )); do
(( attempt % 5 == 0 )) && recover_internal_monitor_toggles
(( attempt % 5 == 0 )) && sync_clamshell
status=$(omarchy-shell lock status 2>/dev/null || true)
+1
View File
@@ -7,3 +7,4 @@
omarchy-brightness-display on
omarchy-brightness-keyboard restore
omarchy-hyprland-monitor-clamshell >/dev/null 2>&1 || true
+24 -6
View File
@@ -6,18 +6,36 @@ source "$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)/base-test.sh"
monitor_watch="$ROOT/bin/omarchy-hyprland-monitor-watch"
sleep_lock="$ROOT/bin/omarchy-system-sleep-lock"
system_wake="$ROOT/bin/omarchy-system-wake"
clamshell="$ROOT/bin/omarchy-hyprland-monitor-clamshell"
lock_service="$ROOT/shell/plugins/lock/Service.qml"
hw_clamshell="$ROOT/bin/omarchy-hw-clamshell"
grep -F 'recover_after_monitor_removal' "$monitor_watch" >/dev/null
grep -F 'sleep 1' "$monitor_watch" >/dev/null
grep -F 'omarchy-hyprland-monitor-internal recover' "$monitor_watch" >/dev/null
grep -F 'omarchy-hyprland-monitor-internal-mirror recover' "$monitor_watch" >/dev/null
grep -F 'omarchy-hyprland-monitor-clamshell' "$monitor_watch" >/dev/null
pass "monitor watcher retries internal monitor recovery after removal"
grep -F 'omarchy-hyprland-monitor-internal recover >/dev/null 2>&1 || true' "$sleep_lock" >/dev/null
grep -F 'omarchy-hyprland-monitor-internal-mirror recover >/dev/null 2>&1 || true' "$sleep_lock" >/dev/null
grep -F '(( attempt % 5 == 0 )) && recover_internal_monitor_toggles' "$sleep_lock" >/dev/null
pass "sleep lock recovers internal monitor toggles while waiting for secure lock"
grep -F 'monitoradded\>\>*|monitoraddedv2\>\>*)' "$monitor_watch" >/dev/null
grep -F 'omarchy-hyprland-monitor-clamshell' "$monitor_watch" >/dev/null
pass "monitor watcher disables the internal monitor after closed-lid external hotplug"
grep -F '/proc/acpi/button/lid/*/state' "$hw_clamshell" >/dev/null
grep -F 'omarchy-hw-external-monitors' "$hw_clamshell" >/dev/null
pass "clamshell helper detects closed-lid external monitor state"
grep -F 'omarchy-hyprland-monitor-internal recover >/dev/null 2>&1 || true' "$clamshell" >/dev/null
grep -F 'omarchy-hyprland-monitor-internal-mirror recover >/dev/null 2>&1 || true' "$clamshell" >/dev/null
grep -F 'omarchy-hw-clamshell' "$clamshell" >/dev/null
grep -F 'omarchy-hyprland-monitor-internal off >/dev/null 2>&1 || true' "$clamshell" >/dev/null
pass "clamshell monitor sync recovers stale toggles and disables internal display"
grep -F 'omarchy-hyprland-monitor-clamshell >/dev/null 2>&1 || true' "$sleep_lock" >/dev/null
grep -F '(( attempt % 5 == 0 )) && sync_clamshell' "$sleep_lock" >/dev/null
pass "sleep lock syncs clamshell display state while waiting for secure lock"
grep -F 'omarchy-hyprland-monitor-clamshell >/dev/null 2>&1 || true' "$system_wake" >/dev/null
pass "system wake resyncs clamshell display state"
grep -F 'lock-pending: no-real-screen' "$lock_service" >/dev/null
grep -F 'lock-pending: screen-stabilizing' "$lock_service" >/dev/null