;;; WM --- Enables FG42 as a window manager using EXWM ;;; Commentary: ;;; Code: (require 'fpkg) (defmacro when-wm (&rest body) "Run the BODY only if in wm mode." (if (string= (getenv "FG42_WM") "true") `(progn ,@body) nil)) (defmacro when-not-wm (&rest body) "Run the BODY only if in wm mode." (if (string= (getenv "FG42_WM") "true") nil `(progn ,@body))) (defun disable-nlinum () "Disable nlinum and fringe-mode." (fringe-mode -1) (nlinum-mode -1)) (defun run-program (path) "Execute the program at the given PATH." (start-process-shell-command path nil path)) (defun run-program-in-xterm (path &optional name) "Execute the program at the given PATH via xterm with the given NAME." (run-program (concat "xterm -e " path))) (defun rename-x-window (&optional name) "Rename the current buffer to NAME." (interactive) (let ((new-name (or name (read-string "New name: ")))) (exwm-workspace-rename-buffer new-name))) (defability wm () "Window manager ability for FG42." (depends-on 'exwm) (defun initialize-wm () (when-wm (require 'exwm) (require 'exwm-config) (require 'exwm-systemtray) (exwm-config-ido) ;; Set the initial number of workspaces (they can also be created later). (setq exwm-workspace-number 10) ;; All buffers created in EXWM mode are named "*EXWM*". You may want to ;; change it in `exwm-update-class-hook' and `exwm-update-title-hook', which ;; are run when a new X window class name or title is available. Here's ;; some advice on this topic: ;; + Always use `exwm-workspace-rename-buffer` to avoid naming conflict. ;; + For applications with multiple windows (e.g. GIMP), the class names of ; all windows are probably the same. Using window titles for them makes ;; more sense. ;; In the following example, we use class names for all windows except for ;; Java applications and GIMP. (add-hook 'exwm-update-class-hook (lambda () (unless (or (string-prefix-p "sun-awt-X11-" exwm-instance-name) (string= "gimp" exwm-instance-name)) (exwm-workspace-rename-buffer exwm-class-name)))) (add-hook 'exwm-update-title-hook (lambda () (when (or (not exwm-instance-name) (string-prefix-p "sun-awt-X11-" exwm-instance-name) (string= "gimp" exwm-instance-name)) (exwm-workspace-rename-buffer exwm-title)))) ;; Global keybindings can be defined with `exwm-input-global-keys'. ;; Here are a few examples: (setq exwm-input-global-keys `( ;; Bind "s-r" to exit char-mode and fullscreen mode. ([?\s-r] . exwm-reset) ([?\s-g] . keyboard-quit) ([8388640] . other-window) ;; Bind "s-w" to switch workspace interactively. ([?\s-w] . exwm-workspace-switch) ;; Bind "s-0" to "s-9" to switch to a workspace by its index. ,@(mapcar (lambda (i) `(,(kbd (format "s-%d" i)) . (lambda () (interactive) (exwm-workspace-switch-create ,i)))) (number-sequence 0 9)) ;; Bind "s-&" to launch applications ('M-&' also works if the output ;; buffer does not bother you). ([?\s-d] . (lambda (command) (interactive (list (read-shell-command "$ "))) (start-process-shell-command command nil command))) ;; Bind "s-" to "slock", a simple X display locker. ([s-f2] . (lambda () (interactive) (start-process "" nil "/usr/bin/slock"))))) ;; To add a key binding only available in line-mode, simply define it in ;; `exwm-mode-map'. The following example shortens 'C-c q' to 'C-q'. (define-key exwm-mode-map [?\C-q] #'exwm-input-send-next-key) (push ?\C-c exwm-input-prefix-keys) ;; The following example demonstrates how to use simulation keys to mimic ;; the behavior of Emacs. The value of `exwm-input-simulation-keys` is a ;; list of cons cells (SRC . DEST), where SRC is the key sequence you press ;; and DEST is what EXWM actually sends to application. Note that both SRC ;; and DEST should be key sequences (vector or string). (setq exwm-input-simulation-keys `( ;; movement (,(kbd "C-b") . left) (,(kbd "M-b") . ,(kbd "C-")) (,(kbd "C-f") . right) (,(kbd "M-f") . ,(kbd "C-")) (,(kbd "C-p") . up) (,(kbd "C-n") . down) (,(kbd "C-a") . home) (,(kbd "C-e") . end) (,(kbd "M-v") . prior) (,(kbd "C-v") . next) (,(kbd "C-d") . delete) ;;(,(kbs "C-k") . [S-end delete]) ;; navigation (,(kbd "C-c b") . ,(kbd "M-")) (,(kbd "C-c f") . ,(kbd "M-")) (,(kbd "C-c w") . ,(kbd "C-w")) (,(kbd "C-w") . ,(kbd "C-x")) (,(kbd "M-w") . ,(kbd "C-c")) (,(kbd "C-y") . ,(kbd "C-v")) ;; search (,(kbd "C-s") . ,(kbd "C-f")))) ;; You can hide the minibuffer and echo area when they're not used, by ;; uncommenting the following line. ;(setq exwm-workspace-minibuffer-position 'bottom) ;; Do not forget to enable EXWM. It will start by itself when things are ;; ready. You can put it _anywhere_ in your configuration. (exwm-enable) (exwm-systemtray-enable) (with-ability nlinum (add-hook 'exwm-mode-hook 'disable-nlinum))))) (provide 'fg42/wm) ;;; wm.el ends here