cipper
cipper

Reputation: 287

automatic dimming keyboard backlight in linux

I'd like to automate keyboard backlight on my Thinkpad X1, like I was used in my old XPS13. At any key press the backlight should switch on, and after a certain idle time (here 30 s) backlight should switch off. I've written this basic bash script, which works fine although it polls every second through xprintidle, and it may drain some battery:

#!/bin/bash

function switch {
  echo $1 > /sys/devices/platform/thinkpad_acpi/leds/tpacpi\:\:kbd_backlight/brightness
}

while (true); do

  sleep 1
  last=`xprintidle`
  status=`cat /sys/devices/platform/thinkpad_acpi/leds/tpacpi\:\:kbd_backlight/brightness`
  [ $last -lt 20000 -a $status -lt 2 ] && switch 2 && continue
  [ $last -ge 20000 -a $status -eq 2 ] && switch 1 && continue
  [ $last -ge 30000 -a $status -ge 1 ] && switch 0 && continue

done

I was wondering if some non-polling way could be done, such as through systemd or dbus.

Upvotes: 1

Views: 1378

Answers (2)

Victor Lamoine
Victor Lamoine

Reputation: 389

xprintidle is not an option when using Wayland, here is an other solution:

sudo apt install swayidle

Create the script /usr/local/bin/keyboard_backlit_timeout and make sure it is executable

#!/bin/bash
# sudo apt install swayidle

idle_after=10 # in seconds
low_state=0
high_state=1

export WAYLAND_DISPLAY="wayland-0"
export XDG_RUNTIME_DIR="/run/user/1001"

swayidle \
    timeout $idle_after "echo $low_state | tee /sys/class/leds/asus::kbd_backlight/brightness" \
    resume "echo $high_state | tee /sys/class/leds/asus::kbd_backlight/brightness"

Create a systemd service that will auto restart until a display is available:

echo "[Unit]
Description=Keyboard backlight auto on/off
[Service]
Restart=on-failure
RestartSec=5s
ExecStart=/usr/local/bin/keyboard_backlit_timeout
[Install]
WantedBy=multi-user.target" | sudo tee /etc/systemd/system/keyboard_backlit_timeout.service

Enable, start and check status of the service:

sudo systemctl enable keyboard_backlit_timeout.service
sudo systemctl start keyboard_backlit_timeout.service
sudo systemctl status keyboard_backlit_timeout.service

This script does not remember the "current" keyboard lit value so the keyboard lit can't be turned off unless you stop the service. Improvements are welcome in the comments!

Upvotes: 0

cipper
cipper

Reputation: 287

I have managed to optimize the script so that it polls much less often when the light in on. I have also included dbus way to detect status and switch backlight. In order to use qdbus the script must be run as user, and thus writing permission for /sys/devices/../kbd_backlight/brightness is required.

#!/bin/bash

idletime=30000  # in milliseconds

prepath=/sys/class/leds/tpacpi\:\:kbd_backlight
sudo chmod a+w $prepath/brightness

function switch {
  echo $1 > $prepath/brightness
  # ALTERNATIVE WITH QDBUS: WORKS BUT SHOWS NOISY OVERLAY ICON
  #qdbus local.org_kde_powerdevil /org/kde/Solid/PowerManagement/Actions/KeyboardBrightnessControl setKeyboardBrightness $1
}

while (true); do

  # BOTH THE FOLLOWING WORK FINE, BUT THE SECOND DONT WORK AS ROOT
  #last=`xprintidle`
  last=`qdbus org.kde.screensaver /ScreenSaver GetSessionIdleTime`

  # BOTH THE FOLLOWING WORK FINE, BUT THE SECOND DONT WORK AS ROOT
  status=`< $prepath/brightness`
  #status=`qdbus org.kde.Solid.PowerManagement /org/kde/Solid/PowerManagement/Actions/KeyboardBrightnessControl keyboardBrightness`

  val=`< $prepath/brightness_hw_changed`

  [ $last -lt $idletime -a $status -lt $val ] && switch $val && sleep ${idletime}e-3 && continue  #SWITCH ON
  [ $last -ge $idletime -a $status -ge $val ] && switch 0                             #SWITCH OFF
  sleep 1

done

edit: now the script keeps trace to the brightness chosen by the user with fn key

Upvotes: 1

Related Questions