More fun with EXWM

I have recently started using EXWM, an Emacs window manager. It’s very useful as a window manager itself but it also provides additional functionality and opens new possibilities.

Starting EXWM automatically in KDE

EXWM allows, similarly to other window managers, replacing an already running window manager. Now I’m confident about it enough and start it automatically, by creating ~/.config/plasma-workspace/env/exwm.sh file with the following content:

export KDEWM=~/bin/start-emacs.sh

Why to use a script rather than starting Emacs directly? We’ll see later.

EXWM and input methods

EXWM allows transforming keys sent to applications. I don’t have currently a good use case for transforming key shortcuts or so but I’m absolutely amazed by the possibility to use Emacs input methods in X applications.

The predefined X.org keyboard layouts are far from perfect and everybody who tried to use a customized keyboard using XKB knows the related problems. On the other hand, defining custom keyboard layouts in Emacs is relatively easy, doesn’t require changing system configuration, and offers significantly more flexibility.

Yes, with EXWM, it’s possible to use Emacs input methods in other applications! The following must be added to the exwm.sh file created above:

export XMODIFIERS=@im=exwm-xim
export GTK_IM_MODULE=xim
export QT_IM_MODULE=xim
export CLUTTER_IM_MODULE=xim

On the Emacs side, it’s desirable to add the shortcut for switching input methods, before EXWM is started:

(push ?\C-\\ exwm-input-prefix-keys)

And the last thing needed is to enable exwm-xim:

(autoload 'exwm-xim-enable "exwm-xim")
(exwm-xim-enable)

Using Emacs input methods in e.g. a web browser makes typing there much simpler (at least for those of us who use two or more languages). Then the only missing thing is the possibility to use different input methods in different pages or tabs displayed in the browser, similarly to Emacs buffers. (Spoiler: There is a non-Emacs web browser that allows doing this.)

Editing input in Emacs

It’s also possible to edit input fields in applications directly in Emacs using exwm-edit package. It’s another useful feature but it must be used with some caution, the edited text may get lost e.g. when the input widget in the application is no longer focused once the input text is sent to the application.

Desktop notifications

I use EXWM together with KDE. There is no reason to replace absolutely everything with Emacs. At the dreary times when GNOME was already unusable and KDE 4 not yet usable, I used to use StumpWM and I really missed things such as a normal panel with its widgets and easy access to functions such as network configuration, or a control center for settings.

But one KDE functionality (besides kwin) is worth to move to Emacs: desktop notifications. The desktop notifications do their job in KDE, but nothing more. The notifications are displayed for a while in a popup window and they are also later (not so well) accessible in the panel. But can you easily identify what’s new when looking at the screen at any given moment? Absolutely no. It very calls for a better notification management. Imagine you want to dismiss all e-mail notifications when you switch to your e-mail client. Or you are forced to use a crappy proprietary chat application without a usable API, accessible only via a web browser interface, and providing useful information to the outer world only in the form of temporarily displayed notifications (this is unfortunately a real example!). Etc.

Here the Emacs Desktop Notification Center (EDNC) comes to help. Just enable it:

(use-package ednc)
(ednc-mode 1)

and then you have all the notifications in your hands. Display, format, close, do whatever you want with them in the ways you like. Very useful and another step to a distraction free desktop. No need to use a secondary screen to watch your e-mail or chat messages, or polling their presence by switching to the corresponding applications regularly. With EXWM, one never leaves Emacs, the mode line is always here and notifications about desktop notifications can be displayed there. Now you can detect easily which inbox has new mail or who wrote a chat message or that something else happened. The details are then accessible in the EDNC log buffer or elsewhere, only once you want to see them. And it may be another use case for pip-frame.el, to display selected incoming notifications temporarily.

There is one problem though. I haven’t found a good way to disable the KDE notification service. And while it is running, EDNC cannot be started. I use this ugly (but working) hack:

(shell-command "kill $(pgrep plasmashell)")
(ednc-mode 1)
(start-process-shell-command "plasmashell" nil "plasmashell")

When plasmashell is killed, the notification service is stopped and EDNC can be started. Then plasmashell can be started again.

But this means plasmashell is started from Emacs and is taken down when Emacs is finished. This is not what I want and it is the reason why I use a script in KDEWM environment variable. The script not only starts Emacs but it also starts plasmashell again when Emacs is finished.

Using EXWM

I sometimes miss useful things. For example, many years ago, I missed emerging Org Mode, not recognizing its potential, only to discover some years later how essential tool it is. And the same happened to me with EXWM, an Emacs window manager.

I’ve always thought that making a window manager in Emacs is a crazy cool idea, which is not very useful in practice. If anything bad happens to Emacs or Emacs needs to be restarted then the whole desktop goes down. It may be a good reason itself to avoid it and there is an additional question why would one use it instead of a standard well tuned window manager. I use a tiling approach to window management, with a single window displayed over the whole screen most of the time, and I don’t need much functionality from the window manager after all.

As with many Emacs tools, there is a very good reason to use it. What I missed (my fault, discarding the idea before looking at it properly) was that windows in EXWM behave similarly to regular Emacs buffers. And Emacs already has a powerful built-in window management.

I discovered EXWM because I looked for a way to easily display a web browser window (or occasionally some other application window) side by side with an Emacs frame. This is not difficult to achieve but what if I want to switch to another Emacs workspace and back? What if I want to pop up a help window instead of the web browser window and then return back to the browser? Etc. It starts to be complicated even with advanced tiling window managers like StumpWM. (And no, window manager desktops are not a solution.) While Emacs provides similar functionalities instantly with pop-to-buffer and all the other window management facilities. When realizing this all, I couldn’t understand how I could live without EXWM. Even when not considering added bonuses, such as the possibility to use normal key bindings (compared to e.g. KDE key bindings limited to single-key bindings only and unable to use Super and Hyper modifiers).

And how about the supposed problems? Emacs usually doesn’t crash and also doesn’t block that often. In practice, there don’t seem to be real problems. Whether other applications must be restarted on Emacs restart depends on whether they are started from Emacs or outside it, which is actually not different from using other window managers.

I use Emacs / EXWM just as a replacement for the window manager, not the whole desktop environment. I keep using KDE while using EXWM instead of kwin. This means I can still use panels (with some limitations such as that it’s not possible to use autohiding panels and it’s possible to configure the panels only when EXWM is not running), general key bindings managed by KDE (useful, among other, to be able to run basic applications when Emacs is not running), KDE settings, multiple monitors (they work well without further arrangements in this environment), notifications, etc.

When setting up the EXWM environment, I realized I need a PIP (picture in picture) facility for Emacs buffers. I couldn’t find anything like this, so I wrote a simple utility called pip-frame.el implementing a floating frame displaying Emacs buffers.