-
Notifications
You must be signed in to change notification settings - Fork 14
Home
This guide serves as an introduction for new users to EXWM as well as a reference for advanced users. It mainly discusses major conceptions, usage and configurations of EXWM. Note that EXWM provides a Customize interface and most configuration options discussed here are also available there. It will be updated accordingly as EXWM evolves. Please consider helping improve this document.
Note: Tiling window managers like EXWM are usually configured as standalone applications without desktop environments / session managers. However it's possible to substitute the window managers of certain desktop environments (e.g. LXDE) with EXWM, or even with recent Gnome (e.g. exwm-gnome-flashback). Most contents in this document still apply there, but have a look at the section on logging out with LXDE.
There's no specific prerequisite indeed. But if there have to be some, here they are (should be easily satisfied):
- GNU Emacs with a version 27.1 or higher.
Also 64-bit build or 32-bit build with
--with-wide-int
set is preferred. You should probably hide menu-bar, tool-bar, scroll-bar etc to make more room for X windows. - X11 server (a recent version please).
- (optional)
dbus-launch
. (NOTE: Do not use on Arch Linux. See https://github.com/ch11ng/exwm/issues/865) - (optional)
gnome-settings-daemon
(or other setting daemons). - to add exwm to the list of available wm or de in your dm (like gdm or slim)
create file /usr/share/xsessions/emacs.desktop and put in it something like this
[Desktop Entry] Name=Emacs Exec=emacs Type=Application
To install a stable EXWM release and all its dependencies, simply invoke
M-x package-install RET exwm RET
.
If you want to follow development and install the newest nightly builds of packages,
configure GNU and NonGNU ELPA-devel as your package archives. Use
package-pinned-packages
if you want to pin packages to specific archives.
(setq package-archives '(("gnu-devel" . "https://elpa.gnu.org/devel/")
("nongnu-devel" . "https://elpa.nongnu.org/nongnu-devel/")))
After configuring the package archives, invoke M-x package-install RET exwm RET
as usual.
Installing manually from source is not recommended. If you want to use a development
version, use GNU ELPA-devel or install via package-vc
.
In order to install from source, first checkout the code of XELB
and EXWM, then add their source directories to load-path
like:
(add-to-list 'load-path "/path/to/xelb/")
(add-to-list 'load-path "/path/to/exwm/")
For those impatient: you might start trying EXWM with the following minimal steps. You should revisit this document later to tweak EXWM if you decide to use it. Also, there is an example configuration that you might find it useful as a starting point.
-
Add following lines to your
.emacs
:(require 'exwm) ;; Set the initial workspace number. (setq exwm-workspace-number 4) ;; Make class name the buffer name. (add-hook 'exwm-update-class-hook (lambda () (exwm-workspace-rename-buffer exwm-class-name))) ;; Global keybindings. (setq exwm-input-global-keys `(([?\s-r] . exwm-reset) ;; s-r: Reset (to line-mode). ([?\s-w] . exwm-workspace-switch) ;; s-w: Switch workspace. ([?\s-&] . (lambda (cmd) ;; s-&: Launch application. (interactive (list (read-shell-command "$ "))) (start-process-shell-command cmd nil cmd))) ;; s-N: Switch to certain workspace. ,@(mapcar (lambda (i) `(,(kbd (format "s-%d" i)) . (lambda () (interactive) (exwm-workspace-switch-create ,i)))) (number-sequence 0 9)))) ;; Enable EXWM (exwm-enable)
-
Create
~/.xinitrc
.# Disable access control for the current user. xhost +SI:localuser:$USER # Make Java applications aware this is a non-reparenting window manager. export _JAVA_AWT_WM_NONREPARENTING=1 # Set default cursor. xsetroot -cursor_name left_ptr # Set keyboard repeat rate. xset r rate 200 60 # Uncomment the following block to use the exwm-xim module. #export XMODIFIERS=@im=exwm-xim #export GTK_IM_MODULE=xim #export QT_IM_MODULE=xim #export CLUTTER_IM_MODULE=xim # Finally start Emacs exec emacs
-
Start EXWM from a console (e.g. tty1) with
xinit -- vt01
P.S. New users often wonder how to properly launch an application in EXWM.
The answer is it doesn't matter because EXWM is a serious X window manager and
knows how to do it correctly.
Do not launch applications with M-! (shell-command
) though
as it will block Emacs and therefore freeze EXWM.
The default/example configuration provides s-& to do this
conveniently.
This section discusses some conventions which you should make clear before going through the rest of this document.
Note: EXWM must be enabled with (exwm-enable)
before the first Emacs
frame is spawned. Thus you should add (exwm-enable)
to your .emacs
. It's
always safe to call exwm-enable
: EXWM will just complain it's unable to start
if there is another window manager. It is also possible to start EXWM from the
Emacs daemon: emacs --daemon -f exwm-enable
.
An X window in this document exclusively refers to a top-level X window created by an application. An application may create multiple such X windows; EXWM just manages them respectively. That is, what EXWM sees are merely top-level X windows; it does not care about which application creates them.
exwm-mode
is a major mode provided by EXWM to manage X windows.
A buffer created in exwm-mode
records all information about the corresponding
X window.
exwm-mode
also provides useful features to interact with that X window.
Things dedicated to an exwm-mode
buffer are said to be local;
otherwise, they are global.
An exwm-mode
buffer has two input modes: line-mode
and char-mode
(these phrases are borrowed from ansi-mode
).
They define how key events should be processed.
In line-mode
, EXWM intercepts all key events and sends applications only keys
not explicitly assigned.
Whereas in char-mode
, EXWM does no interception but only responds to those
globally grabbed key sequences.
exwm-mode
buffers are created in line-mode
by default.
We will discuss how to switch input mode later.
Every exwm-mode
buffer also has a major mode menu,
from which most commands or other features are accessible.
However it has the limitation that you can not access it from other buffers,
so use it as a reference/reminder rather than totally relying on it.
As a tiling X window manger, EXWM manages X windows in a tiling layout by default. However, if an X window explicitly requires it, EXWM can alternatively manage it in a floating (or stacking) layout. There are several ways for a user to switch the layout of an X window, as will be discussed later in this document.
EXWM is a keyboard-driven X window manager, thus it's of great importance to
understand key event representations and learn how to specify/modify
key bindings.
Fortunately, EXWM uses the same syntax as Emacs itself to denote key events, so
you should feel it quite comfortable to configure it.
Besides, it's rather simple to find the representation of a key event by
evaluating (read-key)
or (read-event)
when you are not sure.
As with Emacs, EXWM uses a key sequence (or key for short) rather than a single key event to make a key binding. Indeed, key sequences in EXWM are registered to either global or local keymaps just like what is normally done in Emacs; what EXWM does is to forward those key sequences to Emacs if they are originally intended for other X windows.
One thing worth mentioning is the s- (Super) modifier key. Key sequences consisting of this modifier key (or at least some of them) are usually unusable to Emacs if you are working in other X window managers. However, in EXWM you have full access to any key sequence (though there might still be some rare exceptions like Ctrl Alt F1). The s- modifier key will be frequently used in this document.
Global key bindings are available in both line-mode
and char-mode
.
They even work in normal buffers; take this into account when you make a global
key binding.
Global key bindings can be defined by customizing exwm-input-global-keys
.
By default there is no global key binding.
Key bindings in the following table are recommended however:
Key | Command | Remark |
---|---|---|
s-r | exwm-reset |
Switch to line-mode ;exit fullscreen mode; refresh layout |
s-w | exwm-workspace-switch |
Interactively switch workspace |
s-N | (exwm-workspace-switch-create N) |
Switch to workspace N (N is a digit) |
If you decide to set exwm-input-global-keys
directly, here is an example:
(setq exwm-input-global-keys
`(([?\s-r] . exwm-reset)
([?\s-w] . exwm-workspace-switch)
,@(mapcar (lambda (i)
`(,(kbd (format "s-%d" i)) .
(lambda ()
(interactive)
(exwm-workspace-switch-create ,i))))
(number-sequence 0 9))))
Note: customizing exwm-input-global-keys
may introduce a bit of a quirk or two on GNU-Linux operating system (described below), so one may prefer setting the exwm-input-prefix-keys
instead to avoid this quirk. However, exwm-input-prefix-keys
works only in EXWM line-mode and not in EXWM char-mode.
The quirks of exwm-input-global-keys
one may experience are:
- customization of
exwm-input-global-keys
should be done before callingexwm-enable
, any changing toexwm-input-global-keys
after EXWM has finished instantialization won't take effect. - customize
exwm-input-global-keys
may make starting EXWM a bit slower than usual.
Local key bindings are only available in line-mode
.
The only way to make a local key binding is to modify exwm-mode-map
with e.g.
define-key
.
(define-key exwm-mode-map [?\C-q] 'exwm-input-send-next-key)
When defining local keys prefixed with C-c, you're only allowed to use letters in the remaining of the sequence. Other keys are considered mode-specific and are reserved for either EXWM or other minor modes. Below is a list of mode-specific keys currently found in EXWM:
Key | Command | Remark |
---|---|---|
C-c C-f | exwm-layout-set-fullscreen |
Enter fullscreen mode |
C-c C-h | exwm-floating-hide |
Hide a floating X window |
C-c C-k | exwm-input-release-keyboard |
Switch to char-mode
|
C-c C-m | exwm-workspace-move-window |
Move X window to another workspace |
C-c C-q | exwm-input-send-next-key |
Send a single key to the X window; can be prefixed with C-u to send multiple keys |
C-c C-t C-f | exwm-floating-toggle-floating |
Toggle between tiling and floating mode |
C-c C-t C-m | exwm-layout-toggle-mode-line |
Toggle mode-line |
The following snippet can be used to completely disable mode-specific keys:
(define-key exwm-mode-map (kbd "C-c") nil)
A simulation key exploits a local key binding to map one key sequence to
another and send it to the X window.
There are no predefined simulation keys in EXWM.
One may customize exwm-input-simulation-keys
to easily define them.
One may also set its value directly:
(setq exwm-input-simulation-keys
'(([?\C-b] . [left])
([?\C-f] . [right])
([?\C-p] . [up])
([?\C-n] . [down])
([?\C-a] . [home])
([?\C-e] . [end])
([?\M-v] . [prior])
([?\C-v] . [next])
([?\C-d] . [delete])
([?\C-k] . [S-end delete])))
This example enables Emacs-like line-editing keys for normal applications. Likewise, one should use e.g. C-c C-q C-v to send Ctrl v since it's mapped to next (PgDn).
Note: Simulation keys are currently sent using SendEvent
X requests,
so they will not work for a minority of applications.
Some of them can be configured to accept synthetic events however.
For example, you can enable the allowSendEvents
X resource of xterm
to
achieve this.
Note: The default bindings may also be set otherwise for Gtk.
Simulation keys defined in exwm-input-simulation-keys
are shared among all
applications.
To make this X window-specific, i.e. buffer-local,
exwm-input-set-local-simulation-keys
can be used instead.
For example, the following lines will disable simulation keys for Firefox:
(add-hook 'exwm-manage-finish-hook
(lambda ()
(when (and exwm-class-name
(string= exwm-class-name "Firefox"))
(exwm-input-set-local-simulation-keys nil))))
Button-related key bindings are only used when moving/resizing an X window. Currently there are only two such use cases:
Key | Variable | Remark |
---|---|---|
s-<down-mouse-1> | exwm-input-move-event |
Move X window |
s-<down-mouse-3> | exwm-input-resize-event |
Resize X window |
You may change the behaviors by setting the corresponding variables. Be sure to include a button-down event (e.g. <down-mouse-1>) in the key sequence to make it sense.
After setting up EXWM, you can use Emacs built-in input method, e.g. C-\ and
choose chinese-py
. However, the input method will only work in the emacs
buffer. If you switch to another buffer like LibreOffice, C-\ will not work in
line-mode
.
In order to make the input method work for each buffer, you can use exwm-xim
.
There is emacs init setup example under
https://parrotsec-cn.org/t/exwm/2748
Generally, the following will work:
(require 'exwm)
;; simple system tray
(exwm-systemtray-mode 1)
(exwm-enable)
;; using xim input
(exwm-xim-mode 1)
(push ?\C-\\ exwm-input-prefix-keys) ;; use Ctrl + \ to switch input method
If you have problem, please refer to the issue https://github.com/ch11ng/exwm/issues/846
Some people may find problems in using GPG under EXWM, especially the pinentry is not working properly.
It is recommended to not use the external pinentry, rather, we can setup to use the emacs internal pinentry. The following works for me.
- emacs config
;; let's get encryption established
(setenv "GPG_AGENT_INFO" nil) ;; use emacs pinentry
(setq auth-source-debug t)
(setq epg-gpg-program "gpg2") ;; not necessary
(require 'epa-file)
(epa-file-enable)
(setq epa-pinentry-mode 'loopback)
(setq epg-pinentry-mode 'loopback)
(pinentry-start)
(require 'org-crypt)
(org-crypt-use-before-save-magic)
- ~/.gnupg/gpg-agent.conf
allow-emacs-pinentry
allow-loopback-pinentry
- restart gpg
gpgconf --reload gpg-agent
Let us know if you have further problem.
There is also a pinentry-tty tutorial on emacs, which depends on pinentry.el.
- emacs config
;You can use your favorite package manager to install pinentry, and then start pinentry when you start emacs.
(use-package pinentry
:ensure t
:config
(pinentry-start) )
- ~/.gnupg/gpg-agent.conf
enable-ssh-support
allow-emacs-pinentry
pinentry-program /usr/bin/pinentry-tty
- ~/.xprofile
export GPG_TTY=$(tty)
- restart gpg
gpgconf --reload gpg-agent
There are three layout modes supported in EXWM, i.e. tiling, floating and (inaccurately) fullscreen.
There is nothing special about the tiling mode. An X window is shown where its underlying buffer is displayed. You can use C-x b, C-x 1, C-x 2, C-x 3 or whatever you normally use to switch buffer / resize Emacs window.
The floating mode is a bit different.
An extra Emacs frame is created to hold the X window.
By default, a floating X window can be moved (or resized) by holding
s-<down-mouse-1> (or s-<down-mouse-3>)
when dragging the mouse.
You can alternatively move the window with exwm-floating-move
or resize it
with exwm-layout-{enlarge,shrink}-window[-horizontally]
which by default are
not bound.
Note: X windows will automatically be made floating whenever appropriate
(e.g. the applications explicitly request),
unless exwm-manage-force-tiling
is set to non-nil.
We regard fullscreen as a third layout mode here.
An X window in either tiling or floating mode can be made fullscreen explicitly
by invoking C-c C-f.
If the X window provides other approaches
(typically like pressing F11 or clicking a certain menu entry),
they should also work.
One can leave fullscreen mode with the versatile exwm-reset
.
EXWM supports workspaces and they can be created or removed on-the-fly. EXWM by default creates 1 initial workspace. You may change the number to e.g. 4 with
(setq exwm-workspace-number 4)
exwm-workspace-switch
, when called with no argument, allows you to switch
workspace interactively.
You will be provided with a prompt like
Switch to [+/-]: 0 [1] 2 3
where [1]
indicates you are currently working in Workspace 1
(the index is zero-based).
You may now switch to another workspace by pressing the corresponding index,
or moving [ ]
with line-editing keys followed by <return>.
exwm-workspace-switch
optionally accepts an argument to directly switch to
the target workspace.
There're several ways to add and/or remove workspaces:
- Some workspace related commands, such as
exwm-workspace-switch
, when called interactively provide prompts including the tag[+/-]
. You may then press + to create an empty workspace at the end, or - to remove the selected workspace. - The command
exwm-workspace-switch-create
, similar toexwm-workspace-switch
, automatically creates missing workspaces when given an out-of-range index. - The commands
exwm-workspace-add
/exwm-workspace-delete
allow you to add/delete a workspace at a certain position. When called interactively,exwm-workspace-add
adds a workspace at the end (and switch to it), whereasexwm-workspace-delete
deletes the current workspace. - Emacs frame keys (prefixed with C-x 5) also provide a way to manage workspaces. However, since there're other kinds of Emacs frames in EXWM such as those used in floating X windows, be careful not to mess them up.
A workspace can be moved to another position with exwm-workspace-move
,
and the positions of two workspaces can be interchanged with
exwm-workspace-swap
.
An X window can be moved to another workspace with C-c C-m,
or exwm-workspace-move-window
.
An X window on another workspace can be brought to the current one with
exwm-workspace-switch-to-buffer
.
Note: EXWM only shows X windows belonging to the current workspace by
default.
You may alter this behavior by assigning exwm-workspace-show-all-buffers
a
non-nil value.
Also, you might want to set exwm-layout-show-all-buffers
to t
to allow
automatically moving X windows from inactive workspaces by switching to their
associated buffers.
Note: You are not supposed to move floating X windows when
exwm-layout-show-all-buffers
is non-nil.
As with normal Emacs frames,
the minibuffer and echo area (sharing the same mini-window) are fixed at the
bottom of each workspace by default.
They can be detached and automatically shown/hidden/resized by setting
exwm-workspace-minibuffer-position
to either 'bottom
or 'top
, which
indicates the position of the minibuffer & echo area when they appear.
The minibuffer is shown when it's entered and hidden when exited.
The echo area is shown there're new messages and hidden after a certain amount
of time, which is controlled by exwm-workspace-display-echo-area-timeout
(in seconds).
The autohide minibuffer & echo area can be attached back with
exwm-workspace-attach-minibuffer
, and then detached again with
exwm-workspace-detach-minibuffer
.
Note: exwm-workspace-attach-minibuffer
requires no dock/panel at the same
place to work.
For example, if exwm-workspace-minibuffer-position
is set to 'bottom
, then
there shouldn't be any dock/panel at the bottom of the screen if you want to
attach the autohide minibuffer & echo area.
EXWM creates a new workspace for every new Emacs Frame. Otherwise, Emacs will hang.
The RandR support is optional and disabled by default.
To enable it, add the following code to your .emacs
:
(setq exwm-randr-workspace-monitor-plist '(0 "VGA1"))
(add-hook 'exwm-randr-screen-change-hook
(lambda ()
(start-process-shell-command
"xrandr" nil "xrandr --output VGA1 --left-of LVDS1 --auto")))
(exwm-randr-mode 1)
The second line actually configures the multiple screens support.
The variable exwm-randr-workspace-monitor-plist
is a property list of the form
(workspace-number-1 output-name-1 workspace-number-2 output-name-2 ...)
.
You can find a list of output names together with their info by invoking
xrandr
utility with no argument.
The third line puts output VGA1
on the left of LVDS1
and automatically
resizes the screen every time a monitor is attached/detached.
Please refer to xrandr(1)
for the detailed usage of xrandr
.
If you are looking for an automated behavior to only enable the
connected external screen (and automatically revert to the internal
screen after disconnection), here is an example that can be added to
exwm-randr-screen-change-hook
:
(defun exwm-change-screen-hook ()
(let ((xrandr-output-regexp "\n\\([^ ]+\\) connected ")
default-output)
(with-temp-buffer
(call-process "xrandr" nil t nil)
(goto-char (point-min))
(re-search-forward xrandr-output-regexp nil 'noerror)
(setq default-output (match-string 1))
(forward-line)
(if (not (re-search-forward xrandr-output-regexp nil 'noerror))
(call-process "xrandr" nil nil nil "--output" default-output "--auto")
(call-process
"xrandr" nil nil nil
"--output" (match-string 1) "--primary" "--auto"
"--output" default-output "--off")
(setq exwm-randr-workspace-monitor-plist (list 0 (match-string 1)))))))
As of 0.17 EXWM supports third-party compositing managers and the builtin one are no longer provided.
EXWM provides a simple system tray. It's disabled by default and can be enabled with the following lines:
(exwm-systemtray-mode 1)
Note: The system tray is displayed on active workspace only.
Try
(let* ((buf (or buffer-or-name (current-buffer)))
(id (exwm--buffer->id (get-buffer buf)))) ; ID of X window being displayed
(if id
(slot-value (xcb:+request-unchecked+reply
exwm--connection
(make-instance 'xcb:ewmh:get-_NET_WM_PID :window id))
'value)
(user-error "Target buffer %S is not an X window managed by EXWM!"
buf)))
EXWM cannot make an X window manager by itself; you must tell X to do it.
So first in your ~/.xinitrc
, put a line
exec emacs
to launch Emacs when X starts. Alternatively, if you want to run the daemon:
exec emacsclient -a "" -c
And if you want to leave (exwm-enable)
out of your config (which does no
harm anyway):
emacs --daemon -f exwm-enable
exec emacsclient -c
Sometimes you should disable access control by prepending a line to this file if you get a No protocol specified error:
xhost +SI:localuser:$USER
Then EXWM can be launched in console with
xinit -- vt01
where vt01
indicates you are starting X from tty1
.
Quitting EXWM is as easy as how you do in Emacs (C-x C-c perhaps).
You can also restart EXWM in place with exwm-restart
.
One can run EXWM on top of a fully fledged desktop environment (e.g. XFCE4). In order to do that, start the desktop environment and then start Emacs, load EXWM, execute exwm-init
and agree to replacing current window manager.
-
Make sure you are using the most updated code (including XELB).
-
Check the issues tracker to see whether this has been reported/fixed.
-
Insert the following snippet into your
.emacs
(comment out the second line if this bug makes Emacs frozen, then use C-g to quit):(setq debug-on-error t) ;; (setq debug-on-quit t) (setq edebug-all-forms t)
-
Turn on
exwm-debug
minor mode and try to reproduce it. The result would be in the*XELB-DEBUG*
buffer. You can use C-c C-d C-t to toggle debugging, C-c C-d C-m to clear the entire log and C-c C-d C-m to add a mark (^L) for the current log position. -
Try reproducing the issue with a minimal configuration:
emacs -Q --eval "(progn (package-initialize) (exwm-enable))"
-
Open an issue with a descriptive title, the bug label selected, and the following contents:
- A detailed description of the problem, perhaps with contents from
*Backtrace*
and*XELB-DEBUG*
buffers. Remember to redact the contents of both buffers before posting, as they might contain private information (e.g., in window or buffer names). - Minimal steps to reproduce it
- The possible cause of the problem (like some special configuration)
- Emacs version, architecture, UI toolkit and system info
- X server version (
Xorg -version
)
- A detailed description of the problem, perhaps with contents from
XELB/EXWM are efficient enough to handle most X11 transactions. They also run concurrently.
You can switch to a TTY and send the signal specified in debug-on-event
(defaults to SIGUSR2) to the emacs process. For instance:
pkill -USR2 emacs
Make sure not to kill emacsclient if you run it.
C-c is frequently used in terminal emulators, but since it's by default a prefix key in EXWM, it won't get received by applications normally. Here are some workarounds:
-
Use
ansi-term
instead. -
Work with terminal emulators in
char-mode
. -
Use
exwm-input-send-next-key
(bound to C-c C-q by default) to send C-c.Note: See also Simulation keys for the note on XTerm.
-
Configure EXWM to send C-c with C-c C-c. An example for XTerm:
(add-hook 'exwm-manage-finish-hook (lambda () (when (and exwm-class-name (string= exwm-class-name "XTerm")) (exwm-input-set-local-simulation-keys '(([?\C-c ?\C-c] . ?\C-c))))))
Note: This approach does not work with Emacs 25 due to a bug of Emacs which is fixed in Emacs 26.2.
Note: See also Simulation keys for the note on XTerm.
You will need to set mouse-autoselect-window
and focus-follows-mouse
BEFORE loading EXWM, i.e.
(setq mouse-autoselect-window t
focus-follows-mouse t)
[...]
(package-initialize)
[...]
(require 'exwm)
This is not an X window manager issue. Please refer to this ArchWiki on how to fix this problem.
Java assumes most WMs reparent X windows.
To make Java applications aware that EXWM is a non-reparenting WM, please add
the following line to ~/.xinitrc
:
export _JAVA_AWT_WM_NONREPARENTING=1
Perhaps, but Emacs itself should have a Wayland port first.
As with X11, Wayland is also a network protocol and can be implemented as Elisp libraries just like XELB. Indeed, I (@ch11ng) once made some (unpublished) POC code, but there is very little I can do with it. I turns out it's not possible to implement a Wayland compositor (server) with pure Elisp; we have to find a workaround.
EXWM does not provide a status bar itself but it is known to run well together with dzen2 or xf-panel.
For dzen, you can put something like this in your .xinitrc
:
watch date | dzen2 -dock -p &
exec emacs
Alternatively, Emacs has various mode-line / minibuffer monitors, such as the
builtins display-time
and display-battery-mode
or the
symon package.
You can simply do
(setq exwm-manage-configurations '((t char-mode t))).
EXWM runs concurrently, but it is only true when the event loop of Emacs is not blocked. However, because Emacs is currently single-threaded, this seems inevitable in some situations especially when Emacs tries to display some UI widgets:
- Widgets such as menus which have
OverrideRedirect
set may have a chance to work. - Other widgets like dialog boxes probably can not work at all: they would keep waiting for responses from the X window manager but unfortunately EXWM would have been blocked by that time.
The workaround to this issue is to avoid the use of these features or turn to their text-based alternatives. For instance, most menus can be accessed through M-`.
This issue occurs with non-floating X windows.
If you are used to resize Emacs windows this way,
please enable window-divider-mode
as a workaround:
(setq window-divider-default-right-width 1)
(window-divider-mode)
The autohide echo area can not be activated in certain circumstances:
- Emacs by default echoes keystrokes on echo area on slow input.
There seems to be no way to detect such behavior so the autohide echo area
feature may cause problems for some users.
You can disable keystroke echoing by setting
echo-keystrokes
to0
. - When
tooltip-mode
is disabled, Emacs displays tooltips on echo area, which again is hard to detect. You're encouraged to keeptooltip-mode
enabled (the default behavior) if you use the autohide minibuffer feature.
Note you can always use exwm-workspace-attach-minibuffer
and
exwm-workspace-detach-minibuffer
to temporarily pin the echo area
(and also the minibuffer).
When switching to a buffer (not in exwm-mode
) currently displayed on another
workspace (frame), ido-mode
would raise that workspace instead of displaying
the buffer in the selected Emacs window.
This is probably an unwanted behavior and can be disabled by adding
(exwm-enable-ido-workaround)
to your .emacs
.
ediff
on graphical displays creates new frames. EXWM opens any new frame in workspace of it's own. As a result, you will see that the window displaying your source files are on one workspace and the *"*Ediff Control Panel"*
is on a new workspace. You will also notice that the *Ediff Control Panel*
is not filled.
You can workaround this issue by two means
- Customize
ediff
to open the*Ediff Control Panel*
in a new window instead of a new frame.
(setq ediff-window-setup-function 'ediff-setup-windows-plain)
- Modify
(with-eval-after-load 'ediff-wind
(setq ediff-control-frame-parameters
(cons '(unsplittable . t) ediff-control-frame-parameters)))
Use option (2) if you prefer your *Ediff Control Panel*
as a floating frame, rather than as an Emacs window.
(cf. https://github.com/ch11ng/exwm/issues/606)
This depends on how you fire up Emacs (e.g. as a daemon).
C-x C-c
is bound to save-buffers-kill-terminal
, which will exit the client
but not the daemon. The latter might be force-killed before it has time to run
through all the hooks in kill-emacs-hook
(desktop-kill
among others).
A simple fix is to call save-buffers-kill-emacs
instead:
(global-set-key (kbd "C-x C-c") 'save-buffers-kill-emacs)
The standard way to close emacs is with C-x C-c
(save-buffers-kill-terminal
). When running exwm
with LXDE however, this does not work since closing emacs does not (AFAIK) allow to close LXDE cleanly. Running lxsession-logout
on the other hand does not give emacs time to cleanly close.
The Arch Linux wiki suggests to use this function to logout:
(defun exwm-logout ()
(interactive)
(recentf-save-list)
(save-some-buffers)
(start-process-shell-command "logout" nil "lxsession-logout"))
But:
Emacs also runs a number of functions attached to kill-emacs-hook
and, by default, it also saves bookmarks on exit. It is unknown to me whether the Arch Linux wiki function (see above) runs the kill-emacs-hook
s, but it does not save the bookmarks. Adding (bookmark-save)
to that function should, in theory, solve this problem. But in my case, it does not, probably because the logout process kicks in too quickly and does not give emacs enough time to perform that command. This makes me question whether the other commands always have time to complete...
A way around this is to run the function:
(defun exwm-logout ()
(interactive)
(bookmark-save)
(recentf-save-list)
(save-some-buffers))
(add anything else you want to it) and then logging out by calling lxsession-logout
(by binding it to a 2nd function in emacs or by any other way you usually run programs in LXDE). This 2 step process assures that emacs has time to complete all commands properly.
If the only problem is with bookmarks, another option is to simply save bookmarks with M-x bookmark-save
or to customize the variable bookmark-save-flag
and use the Arch Linux wiki function. I personally remain worried that some of the commands may not always successfully complete before logout and prefer the 2 steps method.
Note: I have not tried playing with exwm-exit-hook
and do not know whether adding bookmark-save
to it would work or whether the LXDE logout process would still interfere with the command being properly executed.
It has been reported that remapping keys with xcape
does not work correctly when using Emac's --with-x-toolkit=athena
toolkit. This can be solved by using other toolkit when building Emacs, for example --with-x-toolkit=no
or --with-x-toolkit=gtk
.
It's found that there will be a long delay in response if Xmodmap is used in changing keyboard mapping. Because Xmodmap is inefficient in handling a file with too many lines. It's built around Xlib and would make an individual call to XChangeKeyboardMapping (which is synchronous) for each effective line beginning with keycode. This may not be noticeable for the C implementation but really a challenge for XELB.
In addition, Xmodmap and xcape mentioned above won't work in the console and neither in a virtual machine guest (vmware). Two better alternatives (works everywhere, no need to specify hardware ids) will be https://github.com/kozikow/keyremaplinux https://github.com/snyball/Hawck
Android Emulator is wrongfully detected to be able to work in tiling mode. Select its window and press C-c C-t C-f to enable floating mode. You can force it to be created in floating mode with the following configuration:
(setq exwm-manage-configurations '(((string-match-p "^ ?Android Emulator -" exwm-title)
floating t)))
If you encounter issues with screen tearing, one possible way to deal with this is to install a compositor like compton or picom. There are a couple of configuration values you can set in order to try to mitigate it.
If you have an nvidia graphics card and adding and configurating a compositor did not help with screen tearing, you may be able to turn on ForceFullcompositionPipeline
to deal with it. The parameters we need to add are setup-specific. In general, there are three things you need:
- The amount of monitors you use
- The identifier of each monitor
- The offset of each monitor
You can find out all of that running the xrandr
command:
Screen 0: minimum 8 x 8, current 5120 x 1440, maximum 32767 x 32767
DP-0.8 connected primary 2560x1440+0+0 (normal left inverted right x axis y axis) 553mm x 311mm
^^^^^^ Identifier ^^^^ Offset
2560x1440 59.95*+
2048x1080 60.00 24.00
1920x1080 60.00 59.94 50.00
1600x1200 60.00
1280x1024 75.02 60.02
1280x720 60.00 59.94 50.00
1152x864 75.00
1024x768 75.03 60.00
800x600 75.00 60.32
720x576 50.00
720x480 59.94
640x480 75.00 59.94 59.93
DP-0.1.8 connected 2560x1440+2560+0 (normal left inverted right x axis y axis) 553mm x 311mm
^^^^^^^^ Identifier ^^^^^^^ Offset
2560x1440 59.95*+
2048x1080 60.00 24.00
1920x1080 60.00 59.94 50.00
1600x1200 60.00
1280x1024 75.02 60.02
1280x720 60.00 59.94 50.00
1152x864 75.00
1024x768 75.03 60.00
800x600 75.00 60.32
720x576 50.00
720x480 59.94
640x480 75.00 59.94 59.93
DVI-D-0 disconnected (normal left inverted right x axis y axis)
HDMI-0 disconnected (normal left inverted right x axis y axis)
DP-0 disconnected (normal left inverted right x axis y axis)
DP-1 disconnected (normal left inverted right x axis y axis)
HDMI-1 disconnected (normal left inverted right x axis y axis)
I have two monitors connected. The identifiers and offset are marked in the snippet above. In my case, that means:
- monitor:
DP-0.8
, offset:+0+0
- monitor:
DP-0.1.8
, offset:+2560+0
That's all the information you need. Open your X11 config file, usually located at /etc/X11/xorg.conf.d/20-nvidia.conf
. If you don't have one yet, simply create it. The name of the file does not matter as long as it is intuitive to you.
Paste the following code into it:
Section "Device"
Identifier "Nvidia Card"
Driver "nvidia"
VendorName "NVIDIA Corporation"
Option "NoLogo" "True"
Option "TripleBuffer" "True"
EndSection
Now we need to the the option MetaModes
below the TripleBuffer
option. It takes the following shape:
Option "MetaModes" "<id of monitor 1>: nvidia-auto-select <offset of monitor 1> { ForceFullCompositionPipeline = On }"
You can add multiple monitors by simply concatenating with a ,
. In my case that would be:
Option "MetaModes" "DP-0.8: nvidia-auto-select +0+0 { ForceFullCompositionPipeline = On },
DP-0.1.8: nvidia-auto-select +2560+0 { ForceFullCompositionPipeline = On }"
The whole config file should now look similar to this:
Section "Device"
Identifier "Nvidia Card"
Driver "nvidia"
VendorName "NVIDIA Corporation"
Option "NoLogo" "True"
Option "TripleBuffer" "True"
Option "MetaModes" "DP-0.8: nvidia-auto-select +0+0 { ForceFullCompositionPipeline = On }, DP-0.1.8:
nvidia-auto-select +2560+0 { ForceFullCompositionPipeline = On }"
EndSection
You're done. Restart your PC for the changes to take effect.
For some users, there is a small border running across the borders of the screen when starting EXWM. See https://github.com/ch11ng/exwm/issues/940 for possible solutions.
This section contains lists of public interfaces that you might find useful when customizing EXWM. Please refer to their documentations for more details.
exwm-debug-log-time
exwm-debug-log-uptime
exwm-enable
exwm-exit
exwm-floating-hide
exwm-floating-move
exwm-floating-toggle-floating
exwm-init
exwm-input-grab-keyboard
exwm-input-release-keyboard
exwm-input-send-next-key
exwm-input-send-simulation-key
exwm-input-set-key
exwm-input-set-simulation-key
exwm-input-set-simulation-keys
exwm-input-toggle-keyboard
exwm-layout-enlarge-window
exwm-layout-enlarge-window-horizontally
exwm-layout-hide-mode-line
exwm-layout-set-fullscreen
exwm-layout-show-mode-line
exwm-layout-shrink-window
exwm-layout-shrink-window-horizontally
exwm-layout-toggle-fullscreen
exwm-layout-toggle-mode-line
exwm-layout-unset-fullscreen
exwm-randr-enable
exwm-randr-refresh
exwm-reset
exwm-restart
exwm-systemtray-enable
exwm-workspace-add
exwm-workspace-attach-minibuffer
exwm-workspace-delete
exwm-workspace-detach-minibuffer
exwm-workspace-move
exwm-workspace-move-window
exwm-workspace-rename-buffer
exwm-workspace-swap
exwm-workspace-switch
exwm-workspace-switch-create
exwm-workspace-switch-to-buffer
exwm-workspace-toggle-minibuffer
exwm-xim-enable
exwm-blocking-subrs
exwm-debug-log-time-function
exwm-exit-hook
exwm-floating-border-color
exwm-floating-border-width
exwm-floating-exit-hook
exwm-floating-setup-hook
exwm-init-hook
exwm-input-global-keys
exwm-input-input-mode-change-hook
exwm-input-line-mode-passthrough
exwm-input-move-event
exwm-input-prefix-keys
exwm-input-pre-post-command-blacklist
exwm-input-resize-event
exwm-input-simulation-keys
exwm-layout-auto-iconify
exwm-layout-show-all-buffers
exwm-manage-configurations
exwm-manage-finish-hook
exwm-manage-force-tiling
exwm-manage-ping-timeout
exwm-randr-refresh-hook
exwm-randr-screen-change-hook
exwm-randr-workspace-monitor-plist
exwm-replace
exwm-systemtray-background-color
exwm-systemtray-height
exwm-systemtray-icon-gap
exwm-update-class-hook
exwm-update-title-hook
exwm-workspace-display-echo-area-timeout
exwm-workspace-index-map
exwm-workspace-list-change-hook
exwm-workspace-minibuffer-position
exwm-workspace-number
exwm-workspace-show-all-buffers
exwm-workspace-switch-create-limit
exwm-workspace-switch-hook
exwm-workspace-warp-cursor
exwm-mode-map
exwm-workspace-current-index
exwm-class-name
exwm-instance-name
exwm-state
exwm-title
exwm-transient-for
exwm-window-type
Both XELB and EXWM are dual-hosted on GitHub and GNU Savannah. GNU Emacs developers may bypass me and make changes to these projects directly; I will keep both repositories in sync. However, due to copyright issues we cannot accept significant changes from other developers. If you want to contribute though, you still have several options:
- Complete the copyright assignment paperwork and become a GNU contributor.
- Instead of implementing a feature, you may introduce the idea.
- You might as well present a draft implementation so that we'll reimplement it later.
Note that the copyright restriction does not apply to minor changes or modifications of the wiki pages here.
- Helm-EXWM: Helm sources and functions for browsing and switching to EXWM buffers.
- GPastel: The Emacs package gpastel makes sure that every copied text in GPaste is also in the Emacs kill-ring. When using EXWM (the Emacs X Window Manager), gpastel makes it possible for the user to use the kill-ring from external applications.
-
Desktop-environment: This package lets you control your computer with standard keys. For example,
<XF86MonBrightnessUp>
raises brightness,<XF86AudioRaiseVolume>
raises volume,<print>
takes screenshots ands-l
locks your screen. - Edit EXWM allows you to edit things in a separate Emacs buffer
This is a brief record of major changes made to each release.
What's new:
- Improve movement of floating windows. Inner window is moved together with the Emacs frame (#73).
- Disable splitting of floating frames (#76).
- Drop obsolete exwm-config.el and xinitrc. See https://github.com/emacs-exwm/exwm/commit/423850fe8315acb050afeeaf6594a090571e23da for details.
Major fixes:
- Bugfix: Transfer surrogate minibuffers to the next workspace on delete (#74).
- Bugfix: Fix on-Notify (#71).
Thanks to everyone participating bug tracker, both reporting issues and, specially, helping others.
What's new:
- Introduce global minor modes as replacement for enable functions.
- exwm-debug-mode
- exwm-randr-mode
- exwm-systemtray-mode
- exwm-xim-mode
- exwm-xsettings-mode
- exwm-background-mode
- Mark enable functions as obsolete.
- Mark exwm-config as obsolete.
- Mark xinitrc as obsolete.
- Depend on Compat 29.1
Major fixes:
- exwm-layout-toggle-fullscreen: Work non-interactively.
- Restore compatibility with Emacs 27.1
Thanks to everyone participating bug tracker, both reporting issues and, specially, helping others.
What's new:
- Depend on xelb 0.19
- Set the EXWM buffer's default directory to match the process's CWD (#14)
- Implement the XSETTINGS protocol
- New customization group exwm-debug
- Remove obsolete functions and variables
- Remove obsolete exwm-cm
- Drop compatibility code for old Emacs versions. Depend on Emacs 27.1.
- Additional maintainers: Steven Allen, Daniel Mendler
Major fixes:
- Correctly activate windows even if they're not in the iconic state (#32)
- Add message-box and message-or-box to exwm-blocking-subrs (fix #874)
- Passthrough input when explicitly reading events and keys
- Correctly stop the subordinate Emacs daemon
- Simplify and improve focus handling (#10)
Thanks to everyone participating bug tracker, both reporting issues and, specially, helping others.
What's new:
- Support placing docks on monitor edges on multi-monitor setups
Major fixes:
- Run hooks on the correct buffer upon button click
- Improve robustness upon connection errors.
A warm welcome to new EXWM contributors Nacho Barrientos (@nbarrientos) and Jo Gay (@jollm). Thank you!
Thank you as well to every one participating bug tracker, both reporting issues and, specially, helping others.
Major fixes:
- Support 32-bit visuals (Emacs'
alpha-background
). - Systemtray supports adjusting its background color to Emacs' background color.
- Hide
tab-bar
in floating windows. - Improvements to focus support on Emacs 29
Caveats:
- Systemtray does not support transparency when Emacs uses 32-bit visuals. Help wanted!
A warm welcome to new EXWM contributors Elijah Malaby (@djeis97), Manuel Giraud (@mgi) and James (@j4m3s-s). Thank you!
Special thanks to long-time contributor Steven Allen (@Stebalien), and to everyone helping each other in the tickets. Thank you as well!
What's new:
- Cache querying of frame parameters for improved performance.
- Let third party libraries detect XIM buffers (
exwm-xim-buffer-p
).
A warm welcome to new EXWM contributors Feng Shu (@tumashu) and Matt Beshara (@mattbeshara). Thank you!
What's new:
- New (acting) maintainer: Adrián Medraño Calvo (@medranocalvo).
Major fixes:
- Make
winner-mode
aware of windows where only mouse event happened. - Reset fullscreen state when unsetting fullscreen mode.
What's new:
- Support accessing keymaps in char-mode (
exwm-input-invoke-factory
). - Support customizing systemtray background color (
exwm-systemtray-background-color
). - New hook run when input mode changes (
exwm-input-input-mode-change-hook
).
Major fixes:
- Various display issues with
menu-bar-mode
/tool-bar-mode
on. -
winner-mode
not working properly onexwm-mode
buffers.
What's new:
- The RandR module now supports monitor mirroring.
- Various user options improved.
Major fixes:
- XIM module drops keys.
- The new hook
after-focus-change-function
not triggered. - For key combinations corresponding to a same Emacs event, only one of them is likely to work.
- Systemtray / floating X windows are positioned incorrectly with menu-bar/tool-bar enabled.
- Impossible to answer questions from Emacs in char-mode.
- False positive 'application not responding' alerts.
What's new:
- New
exwm-xim
module for using Emacs builtin input methods in X windows. - Keep auto-hide echo area displayed when no input is received.
Major fixes:
- User customized options overridden by
exwm-config-default
. - X windows started before EXWM lose input focus.
What's new:
- Support for RandR 1.5 'monitor'.
- New
exwm-randr-refresh
public interface. - EXWM now automatically adjusts to screen changes initiated by external tools.
- Support for 'managed' per-application configuration to allow users to specify whether to manage an X window.
Major fixes:
- Start with a single workspace may fail.
- Keyboard grab state not restored after entering/exiting full screen mode.
- Floating X windows may be incorrectly stacked below tiling ones.
- Performance degradation after triggering a global keybinding.
What's new:
- Support making binding for button events.
- New
exwm-debug
minor mode for debugging.
Major fixes:
- X windows occasionally rendered on wrong workspaces.
- X windows on active workspaces occasionally not rendered.
What's new:
- Allow specifying the initial workspace for each application
- Automatically warp cursor after switching workspace (
exwm-workspace-warp-cursor
)
Major fixes:
- Local simulation keys inaccessible
- line-mode incompatible with Xorg server 1.20
- Full screen X windows hidden after switching buffer
- X windows not properly rendered after resizing
What's new:
- Add support for replacing / being replaced by other window managers.
exwm-init
andexwm-exit
can also be used to manually start/stop EXWM. - The Customize interface now supports customizing global keys.
- Add per-application support for tweaking the initial states of an individual
application.
It can be accessed via the
exwm-manage-configurations
user option. - Mode-specific keys are now enabled by default without the need to add their
prefix keys to
exwm-input-prefix-keys
. -
exwm-workspace-switch
,exwm-workspace-switch-create
,exwm-workspace-move
andexwm-workspace-move-window
now support prefix arguments.
Major fixes:
- X windows not being hidden after switching workspace.
- Fullscreen X window misbehaves after switching workspace.
-
display-buffer-in-side-window
not working with X windows.
What's new:
- Make EXWM a non-reparenting window manager.
As a result third-party compositing managers are now supported and the
built-in one (
exwm-cm
) is thus deprecated. - Add a new Customize interface for accessing most features.
It can be accessed via M-x customize RET and then selecting
Applications
/EXWM
. - Add support for 'focus follows mouse' (requiring
mouse-autoselect-window
andfocus-follows-mouse
both being set). - Add support for
input-decode-map
,local-function-key-map
andkey-translation-map
which can be used for tweaking line-mode. - Add support for displaying floating X windows on all workspaces (by setting
_NET_WM_DESKTOP to
0xffffffff
).
Major fixes:
- Wrong context-menu position for Firefox.
- Global keys not updated after keyboard update.
- Docks not accessible after quitting fullscreen mode.
- Emacs crashes after resizing the width/height of a floating X window to 0.