Check out the final code here.
¶What is EXWM?
Check out the wiki: https://github.com/ch11ng/exwm/wiki
Benefits
- You can use your Emacs keybindings everywhere
- You can manage your windows like any other Emacs window
- Instead of searching around your open windows, fuzzy match by title!
- You can simulate Emacs keybindings in programs that don’t support it
Comparison to other WMs
- Has floating windows, fullscreen
- You control the window placement
- You can easily script how individual programs are handled
¶Settings up .emacs.d
Make sure to install prerequisites:
sudo apt install emacs git fonts-firacode fonts-cantarell
git clone https://github.com/daviwil/emacs-from-scratch .emacs.d
- Disable Forge temporarily (it needs
gcc
) - Disable tangle on the last block
¶How to boot into Emacs
The startup script launches anything that needs to happen before Emacs starts and then starts Emacs with a D-BUS session.
#!/bin/sh # NOTE: This is only for the live demo, not needed for your configuration! # spice-vdagent # Fire it up exec dbus-launch --exit-with-session emacs -mm --debug-init
[Desktop Entry] Name=EXWM Comment=Emacs Window Manager Exec=sh /home/daviwil/.emacs.d/exwm/start-exwm.sh TryExec=sh Type=Application X-LightDM-DesktopName=exwm DesktopNames=exwm
- Set this up with
sudo ln -f ~/.emacs.d/exwm/exwm.desktop /usr/share/xsessions/exwm.desktop
- You may need to restart GDM!
sudo systemctl restart gdm
¶Setting up EXWM
(defun efs/exwm-update-class () (exwm-workspace-rename-buffer exwm-class-name))) (use-package exwm :config ;; Set the default number of workspaces (setq exwm-workspace-number 5) ;; When window "class" updates, use it to set the buffer name ;; (add-hook 'exwm-update-class-hook #'efs/exwm-update-class) ;; These keys should always pass through to Emacs (setq exwm-input-prefix-keys '(?\C-x ?\C-u ?\C-h ?\M-x ?\M-` ?\M-& ?\M-: ?\C-\M-j ;; Buffer list ?\C-\ )) ;; Ctrl+Space ;; Ctrl+Q will enable the next key to be sent directly (define-key exwm-mode-map [?\C-q] 'exwm-input-send-next-key) ;; Set up global key bindings. These always work, no matter the input state! ;; Keep in mind that changing this list after EXWM initializes has no effect. (setq exwm-input-global-keys `( ;; Reset to line-mode (C-c C-k switches to char-mode via exwm-input-release-keyboard) ([?\s-r] . exwm-reset) ;; Move between windows ([s-left] . windmove-left) ([s-right] . windmove-right) ([s-up] . windmove-up) ([s-down] . windmove-down) ;; Launch applications via shell command ([?\s-&] . (lambda (command) (interactive (list (read-shell-command "$ "))) (start-process-shell-command command nil command))) ;; Switch workspace ([?\s-w] . exwm-workspace-switch) ;; 's-N': Switch to certain workspace with Super (Win) plus a number key (0 - 9) ,@(mapcar (lambda (i) `(,(kbd (format "s-%d" i)) . (lambda () (interactive) (exwm-workspace-switch-create ,i)))) (number-sequence 0 9)))) (exwm-enable))
¶Managing windows
- Use
M-&
to launch a process asynchronously - Use
S-M-&
binding from EXWM to launch without popup - Split windows just like you would anywhere else
split-window-below/right
,evil-window-split/vsplit
- Move between windows:
windmove-left/right/up/down
- Move windows:
windmove-swap-states-left/right/up/down
(only on Emacs 27!) - Floating windows:
exwm-floating-toggle-floating
- Fullscreen:
exwm-layout-toggle-fullscreen
- line-mode vs char-mode
¶Workspaces
s+(0-9)
- Switch to numbered workspaces+w
- Workspace selectorC-c RET
: Move window to numbered workspace- NOTE: Windows are attached to a single workspace!
- We will show how to display the current workspace in modeline in the next stream
¶Rebind CapsLock to Ctrl
Contents of ~/.emacs/exwm/Xmodmap
. Make sure xmodmap
is installed! This swaps CapsLock with Ctrl and places CapsLock on the Ctrl on the right side of the keyboard so you can get to it if needed.
clear lock clear control keycode 66 = Control_L add control = Control_L add Lock = Control_R
Put this in the EXWM configuration:
;; Remap CapsLock to Ctrl (start-process-shell-command "xmodmap" nil "xmodmap ~/.emacs.d/exwm/Xmodmap")
¶Setting screen resolution
;; Ensure screen updates with xrandr will refresh EXWM frames (require 'exwm-randr) (exwm-randr-enable)
- Generate a script with
arandr
- Add
xrandr
invocation to the init hook
;; Set the screen resolution (start-process-shell-command "xrandr" nil "")
- We will discuss multiple displays in a future stream!
¶Set screen DPI (optional)
This belongs in ~/.emacs.d/exwm/Xresources
Xft.dpi: 180 # Set this to your desired DPI! Larger number means bigger text and UI
Add this to start-exwm.sh
. Make sure xrdb
is installed!
xrdb ~/.emacs.d/exwm/Xresources
¶System Tray
;; Load the system tray before exwm-init (require 'exwm-systemtray) (exwm-systemtray-enable)
- Use
nm-applet
to test
¶Debugging startup issues
check-parens
- Use
emacs -q -nw
in a virtual terminal - Use another desktop environment
¶What’s next?
- Setting UI and icon themes
- Desktop notifications
- More tips on window management and keybindings