From 1e385fcaca0cc19e464fdcdd07ed24ad0ddebfbb Mon Sep 17 00:00:00 2001 From: Omarchybot <317366263+omarchybot@users.noreply.github.com> Date: Fri, 9 Oct 2026 02:42:29 +0200 Subject: [PATCH] Fall back to the kernel backlight for an all-in-one's DP panel An all-in-one wires its built-in panel to a DP connector, so the name-based check sends it to DDC/CI, which the panel does not answer, and brightness fails although a working backlight sits in /sys/class/backlight. DDC is still tried first; only a lone DP display that cannot be read over DDC, on a machine with a backlight, is moved to the backlight. Deciding on a failed read rather than a failed write keeps a monitor whose reads work on DDC when a write fails. Fixes #8015 Co-Authored-By: roju <10701214+roju@users.noreply.github.com> Co-Authored-By: Codex Medium Co-Authored-By: Claude Opus 5.5 --- bin/omarchy-brightness-display | 11 +++- test/shell.d/brightness-display-test.sh | 75 +++++++++++++++++++++++++ 2 files changed, 85 insertions(+), 1 deletion(-) diff --git a/bin/omarchy-brightness-display b/bin/omarchy-brightness-display index a6a1e8304bf..f2d4e7ea665 100755 --- a/bin/omarchy-brightness-display +++ b/bin/omarchy-brightness-display @@ -39,8 +39,17 @@ use_apple_display() { omarchy-hyprland-monitor-focused-apple "$monitor" } +# An all-in-one wires its built-in panel to a DP connector, which DDC/CI does not answer. +# When that is the only display and the kernel has a backlight, take the backlight to be its own. +monitor_is_panel_without_ddc() { + [[ $monitor == DP-* ]] && + hyprctl monitors all -j 2>/dev/null | jq -e --arg monitor "$monitor" 'length == 1 and .[0].name == $monitor' >/dev/null 2>&1 && + omarchy-hw-display >/dev/null 2>&1 && + ! omarchy-brightness-display-ddc "$monitor" >/dev/null 2>&1 +} + use_ddc_display() { - [[ -n $monitor ]] && ! monitor_is_internal + [[ -n $monitor ]] && ! monitor_is_internal && ! monitor_is_panel_without_ddc } if (( $# == 0 )); then diff --git a/test/shell.d/brightness-display-test.sh b/test/shell.d/brightness-display-test.sh index 3e41c511ae0..d5998150e61 100755 --- a/test/shell.d/brightness-display-test.sh +++ b/test/shell.d/brightness-display-test.sh @@ -24,9 +24,16 @@ SH cat >"$mock_bin/omarchy-hw-display" <<'SH' #!/bin/bash +[[ ${NO_BACKLIGHT:-0} == "1" ]] && exit 1 printf 'mock_backlight\n' SH +cat >"$mock_bin/hyprctl" <<'SH' +#!/bin/bash +default='[{"name":"eDP-1"},{"name":"DP-1"},{"name":"DP-2"}]' +printf '%s\n' "${HYPR_MONITORS:-$default}" +SH + cat >"$mock_bin/brightnessctl" <<'SH' #!/bin/bash printf 'brightnessctl %s\n' "$*" >>"$CALL_LOG" @@ -45,6 +52,8 @@ Display 1 I2C bus: /dev/i2c-${DDC_BUS:-7} DRM connector: card1-${DDC_CONNECTOR:-DP-1} EOF +elif [[ $* == *" setvcp 10 "* ]]; then + [[ ${DDC_WRITE_FAIL:-0} != "1" ]] elif [[ $* == *" getvcp 10 "* ]]; then [[ ${DDC_READ_FAIL:-0} == "1" ]] && exit 1 printf 'VCP 10 C %s %s\n' "${DDC_CURRENT:-40}" "${DDC_MAXIMUM:-80}" @@ -129,6 +138,72 @@ grep -F 'ddcutil --bus 7 --skip-ddc-checks --noverify setvcp 10 5' "$call_log" > fail "external low brightness writes the one-percent target" pass "external low brightness uses a one-percent step" +# An all-in-one's built-in panel on DP-1 is listed by ddcutil but does not answer it. +aio_panel() { + rm -f "$runtime_dir/omarchy-brightness-display-ddc/DP-1.bus" + HYPR_MONITORS='[{"name":"DP-1"}]' DDC_READ_FAIL=1 run_brightness "$@" +} + +: >"$call_log" +brightness=$(aio_panel --monitor DP-1) || true +[[ $brightness == "40" ]] || fail "all-in-one panel on a DP connector reads the kernel backlight" "actual: $brightness" +aio_panel --no-osd --monitor DP-1 60% +grep -Fx 'brightnessctl -d mock_backlight set 60%' "$call_log" >/dev/null || \ + fail "all-in-one panel on a DP connector sets the kernel backlight" "$(cat "$call_log")" +if grep -F 'setvcp' "$call_log"; then + fail "all-in-one panel on a DP connector writes nothing over DDC" +fi +pass "all-in-one panel on a DP connector falls back to the kernel backlight" + +: >"$call_log" +rm -f "$runtime_dir/omarchy-brightness-display-ddc/DP-1.bus" +brightness=$(HYPR_MONITORS='[{"name":"DP-1"}]' run_brightness --monitor DP-1) +[[ $brightness == "50" ]] || fail "a lone DP display that answers DDC keeps DDC" "actual: $brightness" +HYPR_MONITORS='[{"name":"DP-1"}]' run_brightness --no-osd --monitor DP-1 25% +grep -F 'ddcutil --bus 7 --skip-ddc-checks --noverify setvcp 10 20' "$call_log" >/dev/null || \ + fail "a lone DP display that answers DDC is set over DDC" "$(cat "$call_log")" +if grep -F 'brightnessctl' "$call_log"; then + fail "a lone DP display that answers DDC leaves the kernel backlight alone" +fi +pass "a lone DP display that answers DDC keeps DDC" + +: >"$call_log" +if HYPR_MONITORS='[{"name":"DP-1"}]' DDC_WRITE_FAIL=1 run_brightness --no-osd --monitor DP-1 +5%; then + fail "a failed DDC write is reported" +fi +grep -F 'ddcutil --bus 7 --skip-ddc-checks --noverify setvcp 10 44' "$call_log" >/dev/null || \ + fail "a failed DDC write was attempted over DDC" "$(cat "$call_log")" +if grep -F 'brightnessctl' "$call_log"; then + fail "a failed DDC write on a readable display leaves the kernel backlight alone" +fi +pass "a failed DDC write on a readable display leaves the kernel backlight alone" + +: >"$call_log" +rm -f "$runtime_dir/omarchy-brightness-display-ddc/DP-1.bus" +if HYPR_MONITORS='[{"name":"DP-1"},{"name":"HDMI-A-1"}]' DDC_READ_FAIL=1 run_brightness --no-osd --monitor DP-1 +5%; then + fail "a DP display without DDC beside another display has no brightness backend" +fi +if grep -F 'brightnessctl' "$call_log"; then + fail "a DP display without DDC beside another display leaves the kernel backlight alone" +fi +pass "a DP display without DDC beside another display leaves the kernel backlight alone" + +: >"$call_log" +rm -f "$runtime_dir/omarchy-brightness-display-ddc/DP-1.bus" +if HYPR_MONITORS='[{"name":"DP-1"}]' NO_BACKLIGHT=1 DDC_READ_FAIL=1 run_brightness --no-osd --monitor DP-1 +5%; then + fail "a lone DP display without DDC or a backlight has no brightness backend" +fi +pass "a lone DP display without DDC or a backlight has no brightness backend" + +: >"$call_log" +if HYPR_MONITORS='[{"name":"HEADLESS-1"}]' run_brightness --no-osd --monitor HEADLESS-1 +5%; then + fail "a lone virtual output has no brightness backend" +fi +if grep -F 'brightnessctl' "$call_log"; then + fail "a lone virtual output leaves the kernel backlight alone" +fi +pass "a lone virtual output leaves the kernel backlight alone" + cat >"$mock_bin/hyprctl" <<'SH' #!/bin/bash printf '%s\n' '[