Switching Your GTK Theme Based on Time of Day

 

A new trend in software UI/UX is the introduction of dark and light options for user interfaces. Windows and MacOS have both added support for dark window themes in their latest versions, and many iOS and Android apps offer this feature through their application settings. Even many websites are enabling support for this feature using the prefers-color-scheme CSS tag, which alerts a website about the user’s theme preference at OS level. Linux naturally, has had the ability to customize user interface themes for decades, but what is new, is the focus on continuously adapting user interfaces.

For example, If you are using GNOME desktop, you may be aware that the default GNOME wallpaper transitions in color and tone throughout the day, providing brighter colors in the morning, and gradually transitioning to darker tones towards the evening. Furthermore, most operating systems now support “Night light” - a feature that allows a device’s screen to gradually shift from blue tones to red, in order to reduce eye strain at night.

A neat feature missing from most desktop environments is the ability to automatically switch GTK themes, in order to provide a darker environment at night, and improve brightness and contrast during the day. The good news is that in Linux it is not difficult to implement this functionality with systemd timers.

Cron Jobs vs Systemd Timers

So, what are systemd timers? Old time UNIX users will be familiar with cron jobs. Cron is a utility that runs commands, typically from a file stored under: /etc/cronbtab

An example crontab job

SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root

# Example of job definition:
# .---------------- minute (0 - 59)
# |  .------------- hour (0 - 23)
# |  |  .---------- day of month (1 - 31)
# |  |  |  .------- month (1 - 12) OR jan,feb,mar,apr ...
# |  |  |  |  .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# |  |  |  |  |
# *  *  *  *  * user-name  command to be executed

Relevant xkcd

“Take THAT, piece of 1980s-era infrastructure I’ve inexplicably maintained on my systems for 15 years despite never really learning how it works.”

Systemd on the other hand, is a manager for system processes and services. It has replaced much of the functionality that was previously handled by the UNIX init daemon, and has several nice features that the cron utility lacks:

The big benefit for our purpose, is that with cron, if the computer is powered off, a scheduled cron job does not run. Systemd, on the other hand, can run the tasks that it missed the next time that it powers on.

Other advantages of systemd timers:

  • CPU and memory limits
  • Randomized scheduling
  • Jobs can be easily started independently of their timers
  • Jobs are logged in systemd journal, which makes easier debugging

Creating a Systemd Service

Systemd services have the extension .service. All user-created systemd scripts will be stored in ~/.config/systemd/user/. Here are the contents of “dark-theme.sevice”, out systemd service for switching to the Adwaita-dark GTK theme:

[Unit]
Description=Change the GTK theme to dark mode.
After=graphical.target

[Service]
Type=oneshot
ExecStart=/bin/sh -c 'gsettings set org.gnome.desktop.interface gtk-theme Adwaita-dark'

[Install]
WantedBy=default.target

We will need to create a separate “light-theme.service” file to switch to a light GTK theme.

Creating a Systemd Timer

Now, to create a timer, we make another file in the same directory with the same rootname plus the extension .timer. In this case, we named our file “dark-theme.timer”. Here are the contents of this file:

[Unit]
Description=Change the GTK theme daily at a given time.

[Timer]
OnCalendar=*-*-* 16:00:00
Persistent=true

[Install]
WantedBy=timers.target

The OnCalendar setting specifies that this particular timer should run every day at 16:00 hrs. You can also create timers that run every other day, or on specific days of the week. For more on this, I have found that the best resource for documentation is the ArchLinux Wiki: https://wiki.archlinux.org/index.php/Systemd/Timers.

We will additionally need to create a “light-theme.timer” to change theme in the morning.

Running Services as a User

When we are done creating the four configuration files (two for each of dark and light), we need to enable the services. It is recommended that we enable them at the user level (since requiring sudo access would be a hazzle and potential security risk).

Enabling the services:

systemctl --user enable dark-theme.service
systemctl --user enable light-theme.service
systemctl --user enable dark-theme.timer
systemctl --user enable light-theme.timer

Now the operating system will automatically change the GTK theme at the specified times. Furthermore, if we wish to manually change the theme, or test that the service works, we may do so using:

systemctl --user start light-theme.service

or:

systemctl --user start dark-theme.service

What can we use this for?

A couple other applications come to mind:

  • Daily data backups
  • Daily data ingestion

Let me know if you come up with other interesting applications!