Skip to content

Instantly share code, notes, and snippets.

@RobinKnipe
Last active February 13, 2024 10:20
Show Gist options
  • Select an option

  • Save RobinKnipe/79c48673ce2c920d65e661d32df1eba9 to your computer and use it in GitHub Desktop.

Select an option

Save RobinKnipe/79c48673ce2c920d65e661d32df1eba9 to your computer and use it in GitHub Desktop.
Colour temp theme switcher

Colour temp theme switcher

A simple utility that listens for changes to the desired colour temperature and changes the light/dark mode OS theme accordingly.

auto-theme.webm

Installation

Use the install.sh script directly, or look at the contents to inspire a manual alternative...

curl -s "https://gist.githubusercontent.com/RobinKnipe/79c48673ce2c920d65e661d32df1eba9/raw/install.sh" | bash -s

The install script takes care of downloading the necessary files and registering a unit with systemd. This means everything is running in the background ready to switch themes. The utility should start immediately and make a switch if one is required. The script is run as part of the user session and will persist across restarts, until disabled or removed using systemctl.

Customisation

Set the desired light/dark theme names for your OS, and day/night colour temperatures, in the properties file. By default it should be installed into the unit's directory at ~/.config/systemd/user/col-temp-switch/ct-switch.properties. The script that detects and triggers the theme changes can also be found here (ct-switch.sh), and could be easily extended to trigger other actions.

The trigger is set at the midpoint between the day temp (6500, full white by default) and the "target" night temp, as set in your OS's Night Colour Control feature. The day/night temps should be picked up from your existing OS settings, but can be configured (overridden) in the unit's properties file.

NOTE: after making changes to the properties file systemd must be notified before they take affect:

systemctl --user daemon-reload
systemctl --user restart col-temp-switch.service

OS support

This has been tested with Kubuntu, but other KDE/Plasma varients should also work, and the core concept of listening for dbus changes (with dbus-monitor) should be easy enough to implement for other systems.

[Unit]
Description=Colour temp theme switcher
After=dbus.service
[Service]
Type=simple
ExecStart=%h/.config/systemd/user/col-temp-switch/ct-switch.sh
Restart=always
RestartSec=5
EnvironmentFile=%h/.config/systemd/user/col-temp-switch/ct-switch.properties
[Install]
WantedBy=default.target
# use the following settings to override the default values (the current values are the default)
#DAY_THEME=BreezeLight
#NIGHT_THEME=BreezeDark
#DAY_TEMP=6500
#NIGHT_TEMP=3200
# NOTE: if commented out here, the NIGHT_TEMP will be derived from the "Night Colour Control" set via
# the OS, by lookng in the `~/.config/kwinrc` file
#!/bin/bash
light="${DAY_THEME:-BreezeLight}"
dark="${NIGHT_THEME:-BreezeDark}"
dayTemp=${DAY_TEMP:-6500}
# Function to change Plasma theme
setPlasmaTheme() {
temp=$(qdbus org.kde.KWin /ColorCorrect org.kde.kwin.ColorCorrect.currentTemperature)
# fail fast and hope dbus info is available next rerun when temp is empty
if [ -z "$temp" ] ; then
echo "WARNING: no screen temp info available from dbus, bailing..."
exit 1
fi
# check if night temp has been set in properties file
if [ -z "$NIGHT_TEMP" ] ; then
# try to derive the OS setting
if [ -f ~/.config/kwinrc ] ; then
nightTemp=$(grep -iE 'NightTemperature=[[:digit:]]+' .config/kwinrc | cut -d'=' -f2)
# fallback to using target temp (only works at night)
if [ -z "$nightTemp" ] ; then
nightTemp=$(qdbus org.kde.KWin /ColorCorrect org.kde.kwin.ColorCorrect.targetTemperature)
# check the nightTemp makes sense, i.e. it is lower than dayTemp - otherwise use default
[ $dayTemp -gt $nightTemp ] || unset nightTemp
fi
fi
fi
# NOTE: the above ensures the desired night temp is rechecked each colour temp change to pick-up
# any changes the user may have made to the desired night temp, i.e. via the OS
# echo "night: ${nightTemp}, current: ${temp}, day: ${dayTemp}"
# Check for a change-over point half way between assumed full day and desired night temperatures
if [ $(($temp * 2)) -gt $(($dayTemp + ${nightTemp:-3200})) ]; then
# echo "setting plasma night theme: '${light}'"
plasma-apply-colorscheme "${light}" >/dev/null
else
# echo "setting plasma night theme: '${dark}'"
plasma-apply-colorscheme "${dark}" >/dev/null
fi
}
# ensure the theme is correctly set when the unit first runs
setPlasmaTheme
# D-Bus subscription to monitor blue light filter status changes
profile="interface='org.freedesktop.DBus.Properties',member='PropertiesChanged',path='/ColorCorrect'"
dbus-monitor --session --profile "${profile}" |
while read -r line; do
setPlasmaTheme
done
#!/bin/bash
# Install colour temp auto dark mode switcher
gist="https://gist.githubusercontent.com/RobinKnipe/79c48673ce2c920d65e661d32df1eba9/raw"
base_dir="${HOME}/.config/systemd/user/col-temp-switch"
props="${base_dir}/ct-switch.properties"
script="${base_dir}/ct-switch.sh"
unit="${HOME}/.config/systemd/user/col-temp-switch.service"
# download the necessary files
function install_files {
# do not overwrite existing properties file
if [ ! -e "${props}" ] ; then
# ensure the unit directory exists
mkdir -p "${base_dir}"
curl -Lso "${props}" "${gist}/ct-switch.properties"
curl -Lso "${script}" "${gist}/ct-switch.sh"
fi
}
# download and activate the systemd unit
function install_unit {
# stop the service if it is already installed
if [ -f "${unit}" ] ; then
# check if the unit is already running
if systemctl --user status col-temp-switch.service 2> /dev/null ; then
systemctl --user stop col-temp-switch.service 2> /dev/null
systemctl --user disable col-temp-switch.service 2> /dev/null
fi
systemctl --user daemon-reload
fi
curl -Lso "${unit}" "${gist}/col-temp-switch.service"
chmod u+x "${script}"
systemctl --user daemon-reload
systemctl --user start col-temp-switch.service
systemctl --user enable col-temp-switch.service
}
install_files
install_unit
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment