/spacemacsOS

EXWM Layer to turn spacemacs into a full-fledged window manager

Primary LanguageEmacs Lisp

EXWM contribution layer for Spacemacs

Table of Contents

Description

Fork Note: This layer is based on CestDiego’s PR from syl20bnr/spacemacs#3321.

The time has arrived when one can finally use Emacs as a Window Manager, long ago the concepts of windows and frames made so much sense when one was working in a TTY, and basically that’s all the window management you got. In these modern times though, it sounds silly to have those names. But not Anymore!

Thanks to @ch11ng and his EXWM project we can now use Emacs as our window manager, and all those windows that didn’t make sense before, now can not only hold buffers, but X Windows, that means that you can spawn a Browser Window, or your music player, or anything.

I urge you to read the EXWM Wiki for a more in depth explanation and if you can contribute, please do so! The purpose of me making this layer is that I find it awesome and having nice defaults would make more people dive into it and the project would receive more attention and contributions which will only make it more awesome, so if you try it and like it, share it!

This is how it looks like:

img/spacemacsOS.jpg

Install

To use this contribution,

  • (status quo 2021-03-28) install Spacemacs, switch to develop branch
  • place this repository in one of Spacemacs’ layer directories (~/.emacs.d/private/local/exwm, ~/.spacemacs.d/private/exwm, or ~/.spacemacs.d/layers/exwm)
  • add an entry exwm for the layer in your ~/.spacemacs, optionally set some configuration variables:
;; (setq-default dotspacemacs-configuration-layers ...
(exwm :variables
       exwm-enable-systray t
       exwm-autostart-xdg-applications t
       exwm-locking-command "i3lock -n"
       exwm-install-logind-lock-handler t
       exwm-autostart-environment '("DESKTOP_SESSION=kde" "KDE_SESSION_VERSION=5")
       exwm-custom-init (lambda()
                            (exwm/autostart-process "Dunst OSD" "dunst")
                            (exwm/autostart-process "KWallet Daemon" "kwalletd5")))
;; )

Note about Display Managers

This is most common among Ubuntu and derivative users:

LightDM, GDM, and other Display managers that need a session file will need you to copy the desktop file I bundled with this layer to /usr/local/xsessions/exwm.desktop, that’s what I used on my Ubuntu box, but make sure the exwm-start script is in your PATH, you can put it in /usr/local/bin/exwm-start and that should be enough, next time you log out, select the EXWM session instead of the Ubuntu one and you should be alright.

Not having Display Managers

If you use Arch, Gentoo, or any other Linux, most probably you’ll start your configurations via a .xinitrc file, just append exwm-start to the end of that file and you should be fine. I do recommend to check the EXWM Wiki for more details.

OSX

If you are an OSX user, please report back on whether this works with xQuartz, always back up your data before attempting to try stuff like this.

Features

Configurable support for optional EXWM features:

  • System Tray

The following features are preconfigured/provided on top of EXWM:

  • EXWM buffer names are prefixed with a configurable prefix (default: X:), to aid buffer selection in ivy/helm.
  • Session locking with specified lock command
  • Support for D-Bus based locking (e.g. loginctl lock-session)
  • Optionally use ~desktop-environment~ to support special keys for things like audio volume control or brightness control (except for locking)
  • Uses framemove to enable navigation between frames by using window navigation at frame borders. Can be disabled by setting exwm-move-frame-at-edge to nil.

Autostart

If exwm-autostart-xdg-applications is non-nil, .desktop files in $XDG_CONFIG_HOME/autostart and XDG_CONFIG_DIRS will be used to run applications at startup. (See Specification for details).

For the purpose of controlling whether an entry should be run under SpacemacsOS, the OnlyShowIn and NotShowIn keys are checked for the string EXWM.

The variable exwm-autostart-environment can be used to extend process-environment for the started processes.

This is disabled per default.

RandR

If autorandr is found in the current path, exwm//load-autorandr-profile can be used to interactively select from the list of autorandr profiles. The default entry is either the one that autorandr -c would choose, or one of the builtin configurations. The default binding for that command is s-s.

Automatic switching of profiles is supported by autorandr directly, or there should be some OS support to install the corresponding system configuration.

Note that any custom autorandr profiles have to be configured outside of Spacemacs (see autorandr --help).

The variable exwm-randr-dwim, if set (default), will try to assign a sensible value to exwm-randr-monitor-plist to spread the workspaces out to the detected screens.

The s-s binding is not assigned if the autorandr executable is not found at startup.

One tool which is useful for interactively setting up screen configurations is ARandR (note that their save files don’t have anything to with autorandr’s).

Key bindings

Normal State Bindings

Key BindingDescription
i,<down-mouse-X>Switch from normal state to insert state, (similar to EXWM char mode)

Major Mode Bindings

These bindings are accessible via the major mode leader keys when EXWM buffers are focused, but only in normal state. This means that you usually have to get out of insert state with s-ESC first.

Key BindingDescription
SPC m fToggle floating/tiling for current window
SPC m wMove current window to different workspace
SPC m FToggle fullscreen

Global Bindings

As other window managers the s or Super key (Windows Key) is the one that is the prefix to every action. We’ll use a lot of s. These commands work in both normal state and insert state.

Key BindingDescription
s-SPCSpacemacs Leader Key (in insert state)
s-[1 2 3 ... 8 9 0]Switch to workspace [0 … 9]
s-[, s-]Switch to previous/next workspace
s-{, s-}Move current buffer to previous/next workspace
s-TABSwitch to last workspace
s-cSwitch to EXWM char mode
s-ESCSwitch to normal state, cancel fullscreen
s-rApp Launcher
s-pauseLock Screen
s-<return>Open Terminal in current dir (requires terminal-here)
s-u,UUndo, Redo window configurations
s-bSelect and switch to buffer
s-qClose current buffer
s-h,j,k,lSwitch to left,lower,upper,right window
s-H,J,K,LMove window to far left,down,lower,upper,right
M-s-h,j,k,lResizing (try them, it’s too hard to explain)
s-mToggle maximized buffer
SPC T DToggle desktop-environment-mode
s-dToggle exwm debug mode (for development)
s-s(conditional, see RandR) Change autorandr profile

Since running programs is one of the more common task, some explicit support is provided for that via the leader key SPC &.

For these commands as well as for s-r the working directory is set to the value of user-home-directory for the started process.

Key BindingDescription
SPC & sAsk for program to run in separate window below current window
SPC & vAsk for program to run in separate window to the right of current window.

This layer overrides the leader bindings on SPC F, which are tricky with EXWM anyways, and replaces them with the following bindings.

Key BindingDescription
SPC F rReset state of current window (exwm-reset)
SPC F hHide floating window
SPC F wPrompt for workspace and switch to it
SPC F aAdd new workspace
SPC F dDelete current workspace
SPC F mMove Workspace to different position
SPC F sInterchange position of two workspaces
SPC F M dDetach Minibuffer (for autohide enabled)
SPC F M aAttach Minibuffer (for autohide enabled)

Window behaviour regarding char and line mode

In stock Emacs, EXWM uses char mode and line mode to distinguish between using the keyboard to control an application vs. using the keyboard to control the application’s buffer. Since Spacemacs pursues a different concept regarding keybindings SpacemacsOS handles this differently:

  • EXWM buffers are used in line mode per default, all local key bindings are removed per default. This corresponds to Spacemacs insert state.
  • The command exwm/enter-normal-state (default binding s-ESC) enters EXWM’s input passthrough mode, meaning that all key-presses are sent to Spacemacs, and not the application. This corresponds to Spacemacs normal state. Press i to get back to sending input to the application.
  • Certain applications (e.g. SDL based) may not work correctly with line mode, and register double keyboard events. In this case, s-c can be used to enter EXWM char mode. To return from that, also use exwm/enter-normal-state

Known Limitations

(3rd party research welcome…)

  • s-SPC m does not work for accessing major mode bindings
  • When clicking into a buffer in normal state to press something, it has to be clicked twice, because the first click only gets you into insert state
  • In some cases, the Emacs GUI becomes completely unresponsive if an X window was opened by Emacs’ foreground command loop, e.g. when emacs starts an waits for the return of an interactive graphical password entry dialog. To get it to respond again, switch to a text console and send the SIGUSR2 signal (e.g. pkill -USR2 emacs).
  • Under certain conditions, an EXWM buffer may end up in a state where Emacs wants to insert into the underlying buffer, and pressing i does not get you into insert state. If that happens, use s-ESC to get to line mode/normal state, where you should be able to use i to to get into insert state again.
  • `which-key` does only display “prefix” for nested leader key bindings for s-SPC
  • There are dependencies on EXWM internals:
    • exwm--id
    • exwm-workspace--count
    • exwm-workspace--workspace-from-frame-or-index
    • exwm-layout--fullscreen-p
    • exwm-randr--get-monitors
  • exwm/workspace-move-buffer-to-workspace is buggy. It seems to depend on the window layout whether the current buffer will be moved correctly, or the current frame will be messed up…