Pinning Emacs in the KDE Launcher
KDE Top Bar and Emacs
I ran into a mildly annoying issue with KDE’s taskbar. I keep a few apps pinned - Firefox, Emacs, Teams, and others - and the order matters because I switch between them using keyboard shortcuts like Meta+1, Meta+2, etc.
KDE couldn’t reliably decide whether it should treat emacs and emacsclient as the same application. As a result, pressing Meta+2 might:
- Launch a new Emacs instance in the pinned slot
- Open
emacsclientat the end of the taskbar - Spawn additional Emacs windows instead of focusing the existing one
In other words, the taskbar kept losing track of which Emacs window belonged where. The only reliable reset was to close Emacs completely and start again.
I assume KDE was getting confused about window classes between the daemon and the client.
Solution
I ended up writing this .desktop file
[Desktop Entry]
Name=Emacs
Comment=GNU Emacs
Exec=emacsclient -c -a ""
Icon=emacs
Type=Application
Terminal=false
Categories=Development;TextEditor;
StartupWMClass=Emacs
StartupNotify=true
I saved this to ~/.local/share/applications/emacs-custom.desktop, then pinned that to my taskbar instead of the default Emacs launcher.
The key parts:
Exec=emacsclient -c -a ""- Always use the client, start daemon if neededStartupWMClass=Emacs- Tells KDE these windows belong to the same app
After this, Meta+2 behaves consistently: it either focuses the existing Emacs window or opens a new one in the correct taskbar slot.
Possibly I created this problem myself in the first place and solved it in a roundabout way - but at least it works.
Plasma 6
June 2025 I was just setting up KDE (with Plasma 6) on another PC (NixOS this time around). I followed the steps above and found that... it doesn't work.
I did get it working by adapting the above slightly: instead of putting emacsclient -c -a "" in the Exec part I call out to a custom script:
# Check if the Emacs daemon is running
# Use 'emacsclient -e "(daemonp)"' to check.
# The '>/dev/null 2>&1' suppresses output and errors.
if emacsclient -e '(daemonp)' >/dev/null 2>&1; then
# Daemon is running, launch Emacs client
# -c: Create a new frame
# "$@": Pass all arguments (like filenames) to emacsclient
exec emacsclient -c "$@"
else
# Daemon is not running, launch full Emacs GUI
# "$@": Pass all arguments (like filenames) to emacs
exec emacs "$@"
fi
Important note: make sure to put %F at the end of the Exec and chmod +x the script:
[...]
Exec=/path/to/script.sh %F
[...]
- ← Previous
The Los Alamos Primer - Next →
How to mount a WSL2 disk on Linux