auto-dark-theme: My KDE laptop's archilles heel

Hello folks! It's been a while since I've posted something here.

Today, I'm gonna give you a deep dive into the problem I have with KDE Plasma and the solution(s) I've tried before settling on developing auto-dark-theme from scratch.

Background

KDE Plasma doesn't have a "switch to the dark theme on a custom time" setting by default. Now, to be fair GNOME didn't add support before GNOME 42 but extensions were always available to solve this problem. I used Night Theme Switcher on Manjaro GNOME before I moved to KDE.

In my Windows setups, I install Auto Dark Mode and set it up according to my needs.

Solution 1

A quick Google search for "auto dark mode kde" suggests using Yin Yang which on further inspection looked promising.

So as a Manjaro user, I installed it via AUR. First impressions, it was great! I was able to select the themes I wanted for light and dark modes, setup timings for triggering light vs dark themes and I liked the "Plugins" feature.

However, things weren't as smooth as I thought. For example, the timer wasn't triggering on my machine. I ignored it for a few days until it became an annoyance that I had to take care of and so my investigation had begun. I uninstalled the AUR package, cloned the source to my local and tried to set it up manually to reproduce. This worked but I didn't want to "maintain" a local copy forever so the research continued.

After a few hours, I figured out the problem - yin-yang uses a user-level systemd service in the $HOME directory to store the timer information. The AUR package was setting a different path during installation. This means the user's timer information wasn't seen by systemd even when the GUI reports it correctly.

I reported my findings to the AUR package maintainer here and a few days later, I received a response stating the path change during installation was to comply with AUR packaging guidelines which state that an AUR package is not allowed to reference /home directory.

This was fixed in a few days with the next release however by that time I had lost interest in yin-yang. The experience had given me a sour taste towards the app and I realized I wanted a simpler solution to this problem that gets the job done with few moving parts.

Solution 2

After another research session on Google, I found a Reddit post that said we can use the CLI tool lookandfeeltool to switch between themes.

lookandfeeltool is a simple command-line tool provided by the KDE Plasma team to change themes by the KDE Plasma team.

It doesn't support any fancy features from yin-yang.

I got excited reading this and I began testing it on the terminal.

  1. Check out the help section and list all available commands.
$  lookandfeeltool -h
Usage: lookandfeeltool [options]
Command line tool to apply global theme packages for changing the look and feel.

Options:
  -l, --list                 List available global theme packages
  -a, --apply <packagename>  Apply a global theme package. This can be the name
                             of a package, or a full path to an installed
                             package, at which point this tool will ensure it is
                             a global theme package and then attempt to apply it
  --resetLayout              Reset the Plasma Desktop layout
  -h, --help                 Displays help on commandline options.
  --help-all                 Displays help including Qt specific options.
  -v, --version              Displays version information.
  --author                   Show author information.
  --license                  Show license information.
  --desktopfile <file name>  The base file name of the desktop entry for this
                             application.
  1. Cool! Let's list out all available themes on my local machine.
$  lookandfeel -l
org.manjaro.breath.desktop              # <--  my preferred light theme
org.kde.oxygen
org.kde.breezedark.desktop
org.manjaro.breath-light.desktop
org.kde.breezetwilight.desktop
org.kde.breeze.desktop
org.manjaro.breath-dark.desktop     # <--  my preffered dark theme
  1. Awesome! Let's try switching to the dark theme.
$  lookandfeeltool -a org.manjaro.breath-dark.desktop

It worked!

So the next step was to turn it into a shell script that checks the local time and switches the theme if it's greater than 3 PM which is my preferred time.

Here is the final script I came up with:


echo "Auto theme script for KDE Plasma"

# Get hour number in 24 hour format from current time
# and store it in variable called "hour"
hour=$(date --date="now" +%k)

# log file
LOG_FILE=/tmp/auto-theme.log

# logic to switch themes
if [ "$hour" -ge "18" ]; then

echo "Switching to dark mode"
lookandfeeltool -a org.manjaro.breath-dark.desktop 2>&1 | tee -a $LOG_FILE

else
echo "Switching to light mode"
lookandfeeltool -a org.manjaro.breath.desktop 2>&1 | tee -a $LOG_FILE
fi

echo "Goodbye!"

Finally, I wrote a user-level systemd service to trigger it at startup.

# $HOME/.local/share/systemd/user/auto-dark-theme.service
[Service]
Type=exec
RemainAfterExit=true
Restart=on-failure
RestartSec=5
Environment="QT_QPA_PLATFORM=wayland"
WorkingDirectory=$HOME/Projects/auto-dark-theme
ExecStart=/usr/bin/python -m auto-dark-theme
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=plasma-workspace-wayland.target

I was quite happy to see it in action on each startup.

Limitations

There were a few limitations to this approach:

  1. Lack of screen lock/unlock detection (Win + L) - This means if I lock my screen for a few hours and I come back, the theme wouldn't switch. I was under the assumption was systemd wouldn't know about this event.

  2. Sleep detection - My machine is configured to go to sleep if it's locked for too long. This saves battery life and keeps the laptop cooler. But my systemd service wouldn't trigger when the machine resumes from sleep.

To be fair, this was on me. I didn't know we had a resume.target that can trigger scripts on system resume. It could've fixed this issue.

Conclusion

In part 2 of this series, I will explain how the Python-based implementation overcame these issues.

Please use the emotes on the right if you liked this article. Add a comment with your thoughts on this. I would love to hear how you would've tackled this issue.

You can also @ me on Mastodon here.

Thanks for reading. See you next time :)

Goodbye!