Updating my KDE Background Based on the Time

10 September 2021

Linux

Abstract

Updating my background with the time of the day adds some variety throughout the day, but it’s also been a great at drawing my attention to when certain times roll over. Doing so in KDE was a very striaghtforward process.

Changing my background based off the time of the day came down to needing two simple parts to work:

  1. A way to programmatically update the current background of KDE based on the current hour.
  2. A way to have that process run every hour.

Updating the background

The first thing I wanted to do, was given the current hour of the day, select a wallpaper that corresponds to the hour.

#!/bin/bash

if [ -z "$1" ]; then
	HH=$(date +%H)
else
	HH="$1"
fi

bg_dir="/home/joe/Pictures/DesktopSlides"

case "$HH" in
	23|00|01)
		bg="7.png"
		;;
	02|04)
		bg="8.jpg"
		;;
	03)
		bg="9.jpg"
		;;
	05|06|07)
		bg="1.jpg"
		;;
	08|09|10)
		bg="2.png"
		;;
	11|12|13)
		bg="3.jpg"
		;;
	14|15|16)
		bg="4.jpg"
		;;
	17|18|19)
		bg="5.jpg"
		;;
	20|21|22)
		bg="6.jpg"
		;;
esac

After this, the image that we’ll want to assign to the background is ${bg_dir}/{bg}.

From here, the only thing left to do is tell KDE we want this to be our desktop and lock screen backgrounds. The following is the solution I found for telling KDE that we want the given image file to be the desktop background on all desktop screens.

DISPLAY=:0 qdbus org.kde.plasmashell /PlasmaShell org.kde.PlasmaShell.evaluateScript "var allDesktops = desktops(); print (allDesktops); for (i=0;i<allDesktops.length;i++) {d = allDesktops[i]; d.wallpaperPlugin = 'org.kde.image'; d.currentConfigGroup = Array('Wallpaper', 'org.kde.image', 'General'); d.writeConfig('Image', '${bg_dir}/${bg}')}"

Similarly, this was the solution that I found for updating the lock screen on all screens:

DISPLAY=:0 kwriteconfig5 --file /home/joe/.config/kscreenlockerrc --group Greeter --group Wallpaper --group org.kde.image --group General --key Image "file://${bg_dir}/${bg}"

This process is then saved as an executable script called ~/.local/bin/set-time-theme

Running it on the hour

Normally, for scheduling tasks, I’d reach for cron. The biggest issue that I have with cron however is easily scheduling tasks to be run for by the user. I found creating a user systemd service and timer to be easier than trying to jump through the sudo/su hoops of getting cron to run as the desktop user.

The following systemd unit file was installed to ~/.config/systemd/user/background-slides.service, which when called, will run shot call the ~/.local/bin/set-time-theme script from above.

[Unit]
Description=Update the desktop and lockscreen background to match the current time.
Wants=background-slides.timer

[Service]
Type=oneshot
ExecStart=/home/joe/.local/bin/set-time-theme

[Install]
WantedBy=default.target

This service is setup to want the background-slides.timer. This is a systemd timer setup to be bound to background-slides.service, setup to be run every hour on the hour. The following are the contents of the ~/.config/systemd/user/background-slides.timer file

[Unit]
Description=Try to update the lockscreen and desktop background every hour.
Requires=background-slides.service

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

[Install]
WantedBy=timers.target

Following all of that, this service can be setup to run on login, as well as on the timer by running:

$ systemctl --user enable background-slides.service
$ systemctl --user enable background-slides.timer

2