Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -646,3 +646,7 @@
[submodule "home/.local/share/nvim/site/pack/default/opt/snacks.nvim"]
path = home/.local/share/nvim/site/pack/default/opt/snacks.nvim
url = https://github.com/folke/snacks.nvim.git
[submodule "deps/acpilight"]
path = deps/acpilight
url = https://gitlab.com/wavexx/acpilight
ignore = untracked
47 changes: 47 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,3 +92,50 @@ Custom uBlock Origin filters ("My filters") are declared in [`home/.mozilla/nati
Notes:
- A full browser restart is required to pick up changes to this file.
- `toOverwrite` fully replaces the "My filters" pane content on every launch, so any filters added manually through the uBlock UI will be reverted on restart — treat this file as the source of truth and edit it instead.

### Backlight control (acpilight)

[`acpilight`](https://gitlab.com/wavexx/acpilight) provides a backward-compatible `xbacklight` replacement that controls brightness via `/sys/class/backlight` instead of X11's RandR `Backlight` property, so it works for laptop panels the RandR property was never wired up for, and it's driven by a redshift hook ([`home/.config/redshift/hooks/backlight`](home/.config/redshift/hooks/backlight)) that dims the display along with the day/night cycle.

Controlling an external/desktop monitor's brightness this way additionally requires the **`ddcci-driver-linux`** kernel module, which exposes DDC/CI-controlled monitors under `/sys/class/backlight/ddcci*` (the same interface as a native panel), so the same hook script works unmodified on both a laptop (native panel) and a desktop (DDC/CI monitor):

- **Arch Linux**: AUR package `ddcci-driver-linux-dkms` (or `-git` for newer kernels)
- **Slackware**: [`ddcci-driver-linux`](https://slackbuilds.org/repository/15.0/system/ddcci-driver-linux/) on SlackBuilds.org

System settings required:

- **Registering each monitor's DDC/CI device**, since `ddcci-driver-linux` doesn't autodetect monitors on its own -- it needs the main device (address `0x37`) added manually per i2c bus. Add the following snippet to your system's startup (adjust the `card0-*` glob to match which GPU your monitors are on):
```sh
/sbin/modprobe ddcci-backlight

# DisplayPort connectors expose the real DDC/CI-capable channel as a direct
# i2c-N subdirectory of the connector itself (the AUX-channel-backed
# adapter); their `ddc` symlink instead points to a separate, more limited
# legacy adapter that can't complete the full DDC/CI handshake. HDMI
# connectors have no such split -- their `ddc` symlink is the only (and
# correct) adapter.
(
for conn in /sys/class/drm/card0-*/; do
[ "$(cat "$conn/status" 2>/dev/null)" = "connected" ] || continue
direct=$(ls -d "$conn"i2c-* 2>/dev/null | head -1)
if [ -n "$direct" ]; then
# DP
ddc_bus=$(basename "$direct")
else
# HDMI
ddc_link="$conn/ddc"
[ -e "$ddc_link" ] || continue
ddc_bus=$(basename "$(readlink -f "$ddc_link")")
fi
bus_num=${ddc_bus#i2c-}
[ -e "/sys/bus/ddcci/devices/ddcci$bus_num" ] && continue
echo ddcci 0x37 > "/sys/bus/i2c/devices/$ddc_bus/new_device" 2>/dev/null
done
) & # writing to new_device is a synchronous sysfs call that blocks until the driver's real I2C handshake with that monitor finishes, and it's slow
```
- **Installing acpilight's udev rule** so `xbacklight` can write to `/sys/class/backlight` without root:
```sh
sudo install -vCDt /etc/udev/rules.d deps/acpilight/90-backlight.rules
sudo udevadm trigger -s backlight -c add
```
(also requires your user to be in the `video` group)
1 change: 1 addition & 0 deletions deps/acpilight
Submodule acpilight added at 3f9c62
57 changes: 57 additions & 0 deletions home/.config/redshift/hooks/backlight
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#!/bin/sh
# redshift hook: dim the backlight along with the day/night cycle, via acpilight's
# xbacklight (see deps/acpilight, README). Portable across machines: acpilight
# enumerates both native ACPI panels (/sys/class/backlight/<panel>) and, once the
# ddcci-driver-linux kernel module is loaded, DDC/CI-controlled external monitors
# (/sys/class/backlight/ddcci*) under the same interface.
#
# Called by redshift as: backlight period-changed <old-period> <new-period>
set -u

brightness_day=70
brightness_transition=50
brightness_night=30
# redshift sets period to "none" (and fires this same period-changed hook)
# when disabled via SIGUSR1/the redshift-gtk tray toggle, alongside resetting
# color settings to neutral -- restore full brightness to match.
brightness_default=100

have() { command -v "$1" >/dev/null 2>&1; }

have xbacklight || exit 0

case "${3:-}" in
daytime) brightness=$brightness_day ;;
transition) brightness=$brightness_transition ;;
night) brightness=$brightness_night ;;
none) brightness=$brightness_default ;;
*) exit 0 ;;
esac

# Only look at actual display backlights, never acpilight's /sys/class/leds
# fallback (keyboard/capslock/etc. LEDs) -- on a machine with no backlight
# device at all, xbacklight's "first controller found" default would otherwise
# silently target one of those instead of a screen and fail or do the wrong
# thing. No backlight device present (e.g. ddcci-driver-linux not loaded
# yet): nothing to do.
backlight_ctrls=$(ls /sys/class/backlight 2>/dev/null) || exit 0
[ -n "$backlight_ctrls" ] || exit 0

# Set every ddcci-exposed external monitor (a desktop may have several,
# independently registered per i2c bus -- see README); on machines with no
# ddcci device at all (e.g. a laptop's native panel only), fall through to
# xbacklight's own default controller, which is safe here since we already
# confirmed at least one /sys/class/backlight entry exists. Matched via
# `case`, not `grep ddcci*`, so it never risks shell pathname expansion
# against files in the current directory.
found_ddcci=0
for name in $backlight_ctrls; do
case "$name" in
ddcci*)
xbacklight -ctrl "$name" -set "$brightness"
found_ddcci=1
;;
esac
done

[ "$found_ddcci" -eq 1 ] || xbacklight -set "$brightness"
3 changes: 3 additions & 0 deletions home/.config/redshift/redshift.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[redshift]
; slightly warm daytime color temperature (default neutral is 6500K)
temp-day=5500
1 change: 1 addition & 0 deletions home/.local/bin/xbacklight
8 changes: 8 additions & 0 deletions mk/build.mk
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,13 @@ $(xwinwrap_target): $(xwinwrap_head_file)
$(MAKE) -C $(XWINWRAP_ROOT)
xwinwrap: $(xwinwrap_target)

.PHONY: acpilight
acpilight_target = $(ACPILIGHT_ROOT)/xbacklight
$(eval $(call git_submodule,acpilight,$(ACPILIGHT_ROOT)))
# no build step - just ensure submodule
$(acpilight_target): $(acpilight_head_file)
acpilight: $(acpilight_target)

i3status-config-template := home/.config/i3status/config.template
i3status-config := home/.config/i3status/config
amd-cpu-temperature-path := /sys/class/hwmon/hwmon2/temp1_input
Expand Down Expand Up @@ -292,6 +299,7 @@ logrotate: $(logrotate_target)
TARGETS = \
mpv-mpris \
xwinwrap \
acpilight \
ccls \
fzf \
fzy \
Expand Down
1 change: 1 addition & 0 deletions mk/variables.mk
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ FONTS = home/.local/share/fonts

MPV_MPRIS_ROOT = $(DEPS)/mpv-mpris
XWINWRAP_ROOT = $(DEPS)/xwinwrap
ACPILIGHT_ROOT = $(DEPS)/acpilight
CCLS_ROOT = $(DEPS)/ccls
ATUIN_ROOT = $(DEPS)/atuin
QMK_CLI_ROOT = $(DEPS)/qmk_cli
Expand Down
Loading