Automatic dark mode with OpenBSD and dwm
(Edited )Lately I’ve been on a quest to use OpenBSD for as much of my computing as possible. Prior to this I spent several years using macOS, so one of my goals is to recreate some of the “quality of life” features I’ve come to appreciate from that world — like the automatic use of light mode in the daytime and dark mode at night.
dwm
Things might be easier with a full desktop environment, but on BSD and Linux I tend to prefer just running a simple window manager like dwm.
I wrote a
patch for dwm 6.5 to make it look for a ~/.lightmode
file on startup — if it exists, dwm will use a light theme, otherwise it
defaults to dark. This method allows the setting to persist when
restarting dwm. To switch themes while dwm is running, just send it
SIGHUP and it will check again.
xsettingsd
To update the appearance of Firefox and such, you’ll need an
XSettings daemon. xsettingsd is a simple
one for those who don’t use GNOME. All you have to do is make an
~/.xsettingsd
file and run xsettingsd in the background.
The file can be reloaded as needed by sending SIGHUP to xsettingsd.
You’ll need to at least set your GTK theme. For example:
Net/ThemeName "Adwaita-dark"
(On OpenBSD, you can get Adwaita-dark by installing
gnome-themes-extra
.)
~/bin/set-theme
This is a little script I wrote to change the theme of dwm, GTK, and Emacs, and set an appropriate wallpaper. Take it as an example to be tweaked according to your needs.
#!/bin/sh
set_wallpaper() {
feh --bg-fill "$1" &
}
set_gtk_theme() {
# sed -i does not work when invoked by Redshift hook script
( tmp=$(mktemp) &&
sed "s/^\(Net\/ThemeName\) .*/\1 \"$1\"/" ~/.xsettingsd >"$tmp" &&
mv "$tmp" ~/.xsettingsd &&
pkill -HUP -x xsettingsd ) &
}
# (defun load-theme-exclusively (theme)
# (mapc #'disable-theme custom-enabled-themes)
# (load-theme theme t))
set_emacs_theme() {
emacsclient -ue "(load-theme-exclusively '$1)" &
}
case $1 in
dark)
rm -f ~/.lightmode
set_wallpaper ~/wallpapers/dark.jpg
set_gtk_theme Adwaita-dark
set_emacs_theme leuven-dark
;;
light)
touch ~/.lightmode
set_wallpaper ~/wallpapers/light.jpg
set_gtk_theme Adwaita
set_emacs_theme leuven
;;
*)
echo "usage: set-theme <dark|light>"
exit 1
;;
esac
pkill -HUP -x dwm &
Redshift
To automate the switching, we need something that can call our
set-theme
script at sunrise and sunset. There are several
tools dedicated to this, but I opted to use Redshift, which also adjusts the
color temperature of your screen throughout the day to make it easier on
the eyes.
You’ll need a ~/.config/redshift.conf
file:
[redshift]
location-provider=manual
[manual]
lat=51.51
lon=-0.13
And a hook script in ~/.config/redshift/hooks/
:
#!/bin/sh
[ $1 != period-changed ] && exit
case $3 in
daytime) set-theme light ;;
night) set-theme dark ;;
esac
Note that if you launch Redshift during a transition period (i.e. dusk or dawn), this script might not be called right away.
Parting thoughts
I’m just scratching the surface here, and I doubt I’ve covered all the programs and use cases you’re likely to have.
A perk of the .lightmode
system is that it’s not too
hard to make other programs use it. For example, whenever I restart
Emacs, my config checks for it to ensure that it always enables the
right theme.
As a bonus, I recommend the excellent Stylus browser extension together with dark themes for Wikipedia, Stack Overflow, etc. When you install them, you’ll have the option to enable them in dark mode only.