Files
arthur-os/bin/omarchy-powerprofiles-set
T
ed93a047ee Fix power profile race on plug/unplug events (#5898)
The udev power_supply rule fires before sysfs `online` is updated on
some laptops (notably Lenovo Yoga Pro 7 14IAH10 with USB-C charging).
The autodetect branch reads the stale value and sets the wrong profile,
so the system stays on `performance` after unplug (or vice versa).

A single plug/unplug typically fires 3-4 udev events within ~1s (ACAD +
each USB-C port). With `systemd-run --unit=omarchy-power-profile
--collect`, duplicate invocations against the same unit name can be
dropped while the first is still running, so the surviving event isn't
guaranteed to be the latest one.

This adds a 0.3s settle delay at the top of the autodetect branch only.
Explicit `ac` and `battery` invocations remain instant.

Tested on Lenovo Yoga Pro 7 14IAH10 (Intel Core Ultra 9 285H, Omarchy
3.8.1).

Co-authored-by: Iqbal Attila <iqbal@kcmon.id>
2026-05-19 09:42:13 +02:00

45 lines
1.4 KiB
Bash
Executable File

#!/bin/bash
# omarchy:summary=Set the power profile to the requested level, falling back to balanced
# omarchy:args=[autodetect|ac|battery]
action="${1-}"
# Auto-detect when called with no argument: treat any Mains or USB
# power-supply device reporting online=1 as "on AC". This handles
# USB-C only laptops where the legacy AC device may not fire udev
# events, and also avoids false negatives from per-port USB-C devices
# that are present-but-empty (online=0) while another port supplies power.
if [[ -z $action || $action == "autodetect" ]]; then
# On plug/unplug, udev fires the rule before sysfs `online` is updated
# on some laptops (notably Lenovo Yoga Pro 7 with USB-C charging). A
# short settle delay lets the kernel update before we read state.
sleep 0.3
action=battery
for ps in /sys/class/power_supply/*; do
[[ -r $ps/online && -r $ps/type ]] || continue
type=$(cat "$ps/type")
[[ $type == "Mains" || $type == "USB" ]] || continue
if [[ $(cat "$ps/online") == "1" ]]; then
action=ac
break
fi
done
fi
mapfile -t profiles < <(powerprofilesctl list | awk '/^\s*[* ]\s*[a-zA-Z0-9\-]+:$/ { gsub(/^[*[:space:]]+|:$/,""); print }')
case "$action" in
ac)
# Prefer performance, fall back to balanced
if [[ " ${profiles[*]} " == *" performance "* ]]; then
powerprofilesctl set performance
else
powerprofilesctl set balanced
fi
;;
battery)
powerprofilesctl set balanced
;;
esac