Moving from KDE to Emacs

When I started using EXWM, I thought that using it together with KDE would be the best combination. But then my Plasma configuration self-destructed by chance, I had to recover it from backup and I started thinking what and how much I actually need from KDE exactly.

The basic principle is simple: Things are easier to do in KDE but what you get is basically all you get. Arranging the complete desktop in Emacs would mean knowing what’s happening and making it flexible, for the price of more initial work. I decided to try it and I switched from KDE to Emacs completely.

Here is what I had to do to make it happen.

Key bindings

This is the easiest part. All key bindings are simply managed by Emacs.

Multiple keyboards

Emacs input methods, which are much better and simpler to customize than X keyboards, can be used in applications supporting XIM. Mainstream applications generally work with Emacs input methods. setxkbmap can be used for those that don’t if needed.

I have already discussed setting up EXWM for input methods in a previous post.

Multiple monitors

This is harder. In KDE, it works some way automatically and there is a user friendly configuration tool. Although it may happen the configured settings change from time to time and the configuration must be fixed. EXWM works well together with KDE; without it, it must be handled using other tools.

On the contrary to what is written in EXWM documentation, no exwm-randr-screen-change-hook arrangements were needed. But there is still configuration needed. Especially when changing to a new monitor setup for the first time, the given setup must be arranged manually using xrandr, ARandR, or another tool. Then it can be saved using autorandr.

In order to make switching between the configured monitor setups automatically on monitor connections and disconnections, and when opening or closing the laptop lid, system environment must be configured accordingly. This is what works for me on NixOS:

services.autorandr.enable = true;
services.acpid.enable = true;
services.acpid.lidEventCommands = "/run/current-system/sw/bin/autorandr --batch --change";

It’s also highly advisable to configure exwm-randr-workspace-monitor-plist accordingly.

Desktop notifications

Emacs Desktop Notification Center (EDNC) handles them and opens new amazing possibilities to process them. I have already discussed it in a previous post. Obviously, KDE absence avoids the conflict with KDE notification handling and it’s no longer needed to apply the plasmashell workaround.

Panel

Panel widgets provide useful functionality such as displaying information about the system or access to various settings.

There are several Emacs add-ons to display system information. I got attracted by lemon, which allows displaying information in the echo area when Emacs is idle. This is a good use of an otherwise unused screen area. But it’s not without problems. The set of provided monitors in lemon is limited, due to EIEIO limitations it’s not always easy to customize the provided monitors or even to customize my own monitors (broken multiple inheritance!), it’s uncomfortable both waiting for the lemon output to appear and having it appearing prematurely, replacing minibuffer or echo area contents (e.g. in isearch or when a function help or an evaluated expression is displayed), and lemon may stop updating the echo area when in a non-Emacs application buffer. I still think lemon is a great idea but it doesn’t match my needs well enough.

So I decided to abandon lemon and to sacrifice one line of the screen space and use it for the tab bar. I use tabs, but I don’t display them in the tab bar, I use the tab bar for displaying global information (e.g. sound settings, system info, notifications, time, battery status). It’s possible to use the mode line for such purposes, but there is much less space there and I keep only buffer-specific information there, which makes more sense.

One problem with using the tab bar is that if something you put there produces an error, even once, then the tab bar disappears and cannot be restored until Emacs is restarted. Annoying.

System settings

Without the KDE panel, an alternative access to some system settings is needed.

As for network, I use nmcli now. It’s not that bad as it sounds and with a couple of Eshell aliases for common actions (handling WiFi, VPN, …), it may be more comfortable in some sense than using the dialogs. And network connections can be still edited using GUI tools if needed.

As for Bluetooth, I use Emacs Bluetooth Mode. It has some quirks but Bluetooth setup has never been easy in (not only) GNU/Linux, in any environment.

As for sound, I had to write my own Emacs add-on, pipewire-0, to manage PipeWire settings. I tailored it for my own needs, so it serves me well. 🙂

GnuPG password entry

Whether using KDE or not, GnuPG password entry doesn’t work well with EXWM when using external dialogs. Several EXWM tutorials contain tips, not exactly the same, how to fix it. Here is my version.

Emacs pinentry must be enabled by putting

allow-emacs-pinentry

line to ~/.gnupg/gpg-agent.conf.

NixOS has a corresponding configuration option (and pinentry-emacs package):

programs.gnupg.agent.pinentryFlavor = "emacs";

And an option to start the agent itself:

programs.gnupg.agent.enable = true;

Finally, Emacs pinentry must be configured in Emacs configuration:

(setenv "GPG_AGENT_INFO" nil)           ; when not using the NixOS option
(use-package pinentry
  :init
  (setq epg-pinentry-mode 'loopback)
  :config
  (pinentry-start))

Using Java applications

Java is infamous for its window manager related problems. Fortunately, it contains a workaround that can be activated by setting an environment variable:

export _JAVA_AWT_WM_NONREPARENTING=1

Starting the desktop

It’s distribution dependent and it was tricky to find it out on NixOS. In theory, a simple setting

services.xserver.windowManager.exwm.enable = true;

might work. But since NixOS makes hard to access additional C libraries and Python packages from Emacs, I must start Emacs with nix-shell, with a help of my custom shell script. Instead of the setting above, I must use the following:

services.xserver.displayManager.session = [
  { manage = "desktop";
    name = "emacs";
    start = ''
      /my/Emacs/startup/script.sh &
      waitPID=$!
    '';
  }
];
services.xserver.displayManager.defaultSession = "emacs";

Autostarting applications after logging in

This can be arranged in various, less or more smart, ways in ~./emacs.d/ using start-process-shell-command.

Now, when applications are always started from Emacs, they are guaranteed to get down together with it. This has two problems.

First, throughout the years with Emacs, I got used to understand the Emacs confirmation question about terminating running processes on exit just as a protection against accidentally hitting C-x C-c. I respond “yes” automatically and this terminates applications forcefully. I must learn to quit them cleanly with kill-buffer before exiting Emacs.

Second, Emacs restart requires restarting the other applications too. This is quite annoying although actually not that big deal since the only non-Emacs application I run most of the time nowadays is a web browser.

Screen saver

There are several screen savers available. I tried using i3lock with xautolock but it didn’t work very well, the screen could get blanked during meetings or while watching videos. The old good XScreenSaver works better although autolocking and switching screen off automatically doesn’t seem to work completely as expected.

Conclusion

My desktop is completely managed by Emacs now (except for the log in screen). I like it, it’s a clean environment, under my full control. It was a non-trivial effort though and it’s always tempting to improve something (unlike with KDE where it’s not possible). It depends on one’s needs whether it’s worth it or not. For us who have Emacs as a hobby, perhaps it is; the others may happily continue to use Emacs with KDE.

emacs-desktop.jpg


Posted

in

by

Tags:

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *