diff --git a/README.md b/README.md index 7e0dc6a..1574bd5 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,7 @@ This avoids drift from letting two outputs auto-adjust independently. - Internal display controlled with `brightnessctl` - External monitor mirrored with `ddcutil` VCP code `10` - Compact GTK4/libadwaita OSD for custom brightness shortcuts +- Debounced brightness changes: fast repeated key presses become one final jump - Optional Wayland top-edge positioning with `gtk4-layer-shell` - systemd user service for continuous external sync - Configurable backlight device, DDC bus, monitor model, step size, and sync interval @@ -53,6 +54,7 @@ The installer writes: ```text ~/.local/bin/brightness-osd +~/.local/bin/brightness-step ~/.local/bin/brightness-up-all ~/.local/bin/brightness-down-all ~/.local/bin/brightness-sync-hg342pcb @@ -89,8 +91,11 @@ BRIGHTNESS_DDCUTIL_BUS="16" BRIGHTNESS_SYNC_INTERVAL="1" BRIGHTNESS_SYNC_MIN_PERCENT="1" BRIGHTNESS_OSD_VISIBLE_MS="1400" +BRIGHTNESS_APPLY_DEBOUNCE_MS="180" ``` +`BRIGHTNESS_APPLY_DEBOUNCE_MS` controls how long the scripts wait for another key press before applying the final brightness. The OSD updates immediately to the target value, but `brightnessctl` runs only once at the end of a quick key-press burst. + After changing DDC or sync values: ```bash diff --git a/bin/brightness-down-all b/bin/brightness-down-all index e7b1a69..1752e4a 100755 --- a/bin/brightness-down-all +++ b/bin/brightness-down-all @@ -7,8 +7,4 @@ if [[ -f "$CONFIG" ]]; then source "$CONFIG" fi -BACKLIGHT_DEVICE="${BRIGHTNESS_BACKLIGHT_DEVICE:-intel_backlight}" -STEP="${BRIGHTNESS_STEP:-10}" - -brightnessctl -q -d "$BACKLIGHT_DEVICE" set "${STEP}%-" -"$HOME/.local/bin/brightness-osd" || true +"$HOME/.local/bin/brightness-step" down diff --git a/bin/brightness-step b/bin/brightness-step new file mode 100755 index 0000000..12a0d94 --- /dev/null +++ b/bin/brightness-step @@ -0,0 +1,92 @@ +#!/usr/bin/env bash +set -euo pipefail + +CONFIG="${BRIGHTNESS_AUTOMATION_CONFIG:-$HOME/.config/brightness-automation/env}" +if [[ -f "$CONFIG" ]]; then + # shellcheck disable=SC1090 + source "$CONFIG" +fi + +BACKLIGHT_DEVICE="${BRIGHTNESS_BACKLIGHT_DEVICE:-intel_backlight}" +BACKLIGHT_PATH="${BRIGHTNESS_SYNC_BACKLIGHT:-/sys/class/backlight/${BACKLIGHT_DEVICE}}" +STEP="${BRIGHTNESS_STEP:-10}" +DEBOUNCE_MS="${BRIGHTNESS_APPLY_DEBOUNCE_MS:-180}" +STATE_DIR="${XDG_RUNTIME_DIR:-/tmp}/brightness-automation" +STATE_FILE="$STATE_DIR/target-percent" +STAMP_FILE="$STATE_DIR/target-stamp" +LOCK_FILE="$STATE_DIR/lock" + +mkdir -p "$STATE_DIR" + +read_current_percent() { + local current max + current="$(<"${BACKLIGHT_PATH}/brightness")" + max="$(<"${BACKLIGHT_PATH}/max_brightness")" + printf '%s\n' "$(( (current * 100 + max / 2) / max ))" +} + +clamp_percent() { + local value="$1" + if (( value < 1 )); then + value=1 + elif (( value > 100 )); then + value=100 + fi + printf '%s\n' "$value" +} + +now_ms() { + date +%s%3N +} + +apply_after_quiet_period() { + while true; do + sleep "$(awk "BEGIN { printf \"%.3f\", ${DEBOUNCE_MS} / 1000 }")" + + local now stamp age target + now="$(now_ms)" + stamp="$(<"$STAMP_FILE")" + age="$(( now - stamp ))" + + if (( age >= DEBOUNCE_MS )); then + target="$(<"$STATE_FILE")" + brightnessctl -q -d "$BACKLIGHT_DEVICE" set "${target}%" + exit 0 + fi + done +} + +if [[ "${1:-}" == "--apply-worker" ]]; then + apply_after_quiet_period +fi + +if [[ "$#" -ne 1 || ! "$1" =~ ^(up|down)$ ]]; then + echo "Usage: $(basename "$0") up|down" >&2 + exit 2 +fi + +( + flock 9 + + current="$(read_current_percent)" + if [[ -f "$STATE_FILE" ]]; then + base="$(<"$STATE_FILE")" + else + base="$current" + fi + + case "$1" in + up) target="$(( base + STEP ))" ;; + down) target="$(( base - STEP ))" ;; + esac + + target="$(clamp_percent "$target")" + printf '%s\n' "$target" >"$STATE_FILE" + now_ms >"$STAMP_FILE" + + "$HOME/.local/bin/brightness-osd" "$target" || true +) 9>"$LOCK_FILE" + +if ! pgrep -f "$HOME/.local/bin/brightness-step --apply-worker" >/dev/null 2>&1; then + nohup "$HOME/.local/bin/brightness-step" --apply-worker >/dev/null 2>&1 & +fi diff --git a/bin/brightness-up-all b/bin/brightness-up-all index 27a9daa..20fc67a 100755 --- a/bin/brightness-up-all +++ b/bin/brightness-up-all @@ -7,8 +7,4 @@ if [[ -f "$CONFIG" ]]; then source "$CONFIG" fi -BACKLIGHT_DEVICE="${BRIGHTNESS_BACKLIGHT_DEVICE:-intel_backlight}" -STEP="${BRIGHTNESS_STEP:-10}" - -brightnessctl -q -d "$BACKLIGHT_DEVICE" set "+${STEP}%" -"$HOME/.local/bin/brightness-osd" || true +"$HOME/.local/bin/brightness-step" up diff --git a/install.sh b/install.sh index ded9cf4..9777fed 100755 --- a/install.sh +++ b/install.sh @@ -17,6 +17,7 @@ install -d "$HOME/.config/systemd/user" install -d "$HOME/.config/brightness-automation" install -m 0755 "$ROOT/bin/brightness-osd" "$HOME/.local/bin/brightness-osd" +install -m 0755 "$ROOT/bin/brightness-step" "$HOME/.local/bin/brightness-step" install -m 0755 "$ROOT/bin/brightness-up-all" "$HOME/.local/bin/brightness-up-all" install -m 0755 "$ROOT/bin/brightness-down-all" "$HOME/.local/bin/brightness-down-all" install -m 0755 "$ROOT/bin/brightness-sync-hg342pcb" "$HOME/.local/bin/brightness-sync-hg342pcb" @@ -33,6 +34,7 @@ BRIGHTNESS_DDCUTIL_BUS="$DDC_BUS" BRIGHTNESS_SYNC_INTERVAL="$INTERVAL" BRIGHTNESS_SYNC_MIN_PERCENT="$MIN_PERCENT" BRIGHTNESS_OSD_VISIBLE_MS="1400" +BRIGHTNESS_APPLY_DEBOUNCE_MS="180" EOF fi diff --git a/uninstall.sh b/uninstall.sh index 08d09e7..2d23f74 100755 --- a/uninstall.sh +++ b/uninstall.sh @@ -4,6 +4,7 @@ set -euo pipefail systemctl --user disable --now external-brightness-sync.service 2>/dev/null || true rm -f "$HOME/.config/systemd/user/external-brightness-sync.service" rm -f "$HOME/.local/bin/brightness-osd" +rm -f "$HOME/.local/bin/brightness-step" rm -f "$HOME/.local/bin/brightness-up-all" rm -f "$HOME/.local/bin/brightness-down-all" rm -f "$HOME/.local/bin/brightness-sync-hg342pcb"