Long answer:
There are three modes* in EXWM
.
I. Sending all the keys to the apps except the global bindings (for e.g. this is a global (exwm-input-set-key (kbd "s-c") #'list-processes)
. EXWM
calls this char-mode
II. Sending all the keys to the apps with some simulations. EXWM
calls this line-mode
. You can define simulations like.
(exwm-input-set-simulation-keys
'(([?\C-b] . left)
([?\C-f] . right)))
Now in this mode if I press C-f
apps receive right
arrow key.
III. Not sending any key to the apps, instead Emacs receives all the keys. So you can use normal operations like C-x 2
or C-x 3
to split the window.EXWM
calls this line-mode
too.
C-c
and C-v
doesn't work because you're in mode III. Here are some of the helper functions that I use.
(defun fhd/exwm-input-line-mode ()
"Set exwm window to line-mode and show mode line"
(call-interactively #'exwm-input-grab-keyboard)
(exwm-layout-show-mode-line))
(defun fhd/exwm-input-char-mode ()
"Set exwm window to char-mode and hide mode line"
(call-interactively #'exwm-input-release-keyboard)
(exwm-layout-hide-mode-line))
(defun fhd/exwm-input-toggle-mode ()
"Toggle between line- and char-mode"
(interactive)
(with-current-buffer (window-buffer)
(when (eq major-mode 'exwm-mode)
(if (equal (second (second mode-line-process)) "line")
(fhd/exwm-input-char-mode)
(fhd/exwm-input-line-mode)))))
To make it globally available with s-i
(exwm-input-set-key (kbd "s-i") #'fhd/exwm-input-toggle-mode)
This toggles between modes I and either mode II or III.
Switching between mode II and mode III depends on exwm-input-line-mode-passthrough
. Another helper function I use:
(defun fhd/toggle-exwm-input-line-mode-passthrough ()
(interactive)
(if exwm-input-line-mode-passthrough
(progn
(setq exwm-input-line-mode-passthrough nil)
(message "App receives all the keys now (with some simulation)"))
(progn
(setq exwm-input-line-mode-passthrough t)
(message "emacs receives all the keys now")))
(force-mode-line-update))
And to bind it globally
(exwm-input-set-key (kbd "s-p") 'fhd/toggle-exwm-input-line-mode-passthrough)
I used (force-mode-line-update)
in this function since I have an indicator in my mode-line to show if emacs receives all the keys (mode III) or apps receive all the keys with some simulations (mode II) if mode-line is hidden it means we are in mode I and apps receive all the keys without any simulations. To make sure apps open in mode II you can use (setq exwm-input-line-mode-passthrough nil)
.
If you want all the apps to open in mode I (that is char-mode
in EXWM
terminology) you can use:
(add-hook 'exwm-manage-finish-hook
(lambda () (call-interactively #'exwm-input-release-keyboard)
(exwm-layout-hide-mode-line)))
*The word "mode" is used loosely, it doesn't mean in EXWM
there are actually three modes.
Short answer
Call exwm-input-release-keyboard
function. It switches to char-mode
which means firefox receives all the key events.