mirror of
https://github.com/ch11ng/exwm.git
synced 2024-11-23 19:47:58 +01:00
Create exwm-minor-mode
* exwm.el (exwm-minor-mode): New function. (exwm-enable, exwm-disable, exwm-init, exwm-exit): Deprecate in favor of `exwm-minor-mode'. (exwm--init): Rework to signal errors and cleanup in case of errors. (exwm--exit): More thorough cleanup. (exwm--cleanup): New function. (exwm--on-SelectionClear, exwm--confirm-kill-emacs): : Use `exwm--exit'. (exwm--terminal-x-p, exwm--find-any-x-frame) (exwm--init-on-window-setup-hook) (exwm--init-on-after-make-frame, exwm--cleanup): New functions. (exwm--wmsn-acquire): Signal error instead of using `user-error'.
This commit is contained in:
parent
10bd12234e
commit
a824aaddf5
2 changed files with 132 additions and 44 deletions
|
@ -73,7 +73,7 @@
|
||||||
([?\C-d] . [delete])
|
([?\C-d] . [delete])
|
||||||
([?\C-k] . [S-end delete]))))
|
([?\C-k] . [S-end delete]))))
|
||||||
;; Enable EXWM
|
;; Enable EXWM
|
||||||
(exwm-enable)
|
(exwm-minor-mode +1)
|
||||||
;; Configure Ido
|
;; Configure Ido
|
||||||
(exwm-config-ido)
|
(exwm-config-ido)
|
||||||
;; Other configurations
|
;; Other configurations
|
||||||
|
|
174
exwm.el
174
exwm.el
|
@ -71,6 +71,7 @@
|
||||||
(require 'exwm-floating)
|
(require 'exwm-floating)
|
||||||
(require 'exwm-manage)
|
(require 'exwm-manage)
|
||||||
(require 'exwm-input)
|
(require 'exwm-input)
|
||||||
|
(require 'seq)
|
||||||
|
|
||||||
(defgroup exwm nil
|
(defgroup exwm nil
|
||||||
"Emacs X Window Manager."
|
"Emacs X Window Manager."
|
||||||
|
@ -110,6 +111,10 @@
|
||||||
|
|
||||||
(defvar exwm--server-process nil "Process of the subordinate Emacs server.")
|
(defvar exwm--server-process nil "Process of the subordinate Emacs server.")
|
||||||
|
|
||||||
|
(define-error 'exwm-frame-not-x "Frame not running under X environment" 'error)
|
||||||
|
(define-error 'exwm-already-running "EXWM already running" 'error)
|
||||||
|
(define-error 'exwm-other-wm "Other window manager running" 'error)
|
||||||
|
|
||||||
(defun exwm-reset ()
|
(defun exwm-reset ()
|
||||||
"Reset the state of the selected window (non-fullscreen, line-mode, etc)."
|
"Reset the state of the selected window (non-fullscreen, line-mode, etc)."
|
||||||
(interactive)
|
(interactive)
|
||||||
|
@ -603,7 +608,7 @@
|
||||||
selection (slot-value obj 'selection))
|
selection (slot-value obj 'selection))
|
||||||
(when (and (eq owner exwm--wmsn-window)
|
(when (and (eq owner exwm--wmsn-window)
|
||||||
(eq selection xcb:Atom:WM_S0))
|
(eq selection xcb:Atom:WM_S0))
|
||||||
(exwm-exit))))
|
(exwm--exit))))
|
||||||
|
|
||||||
(defun exwm--init-icccm-ewmh ()
|
(defun exwm--init-icccm-ewmh ()
|
||||||
"Initialize ICCCM/EWMH support."
|
"Initialize ICCCM/EWMH support."
|
||||||
|
@ -761,7 +766,7 @@ manager. If t, replace it, if nil, abort and ask the user if `ask'."
|
||||||
(when (eq replace 'ask)
|
(when (eq replace 'ask)
|
||||||
(setq replace (yes-or-no-p "Replace existing window manager? ")))
|
(setq replace (yes-or-no-p "Replace existing window manager? ")))
|
||||||
(when (not replace)
|
(when (not replace)
|
||||||
(user-error "Other window manager detected")))
|
(signal 'exwm-other-wm "Other window manager detected")))
|
||||||
(let ((new-owner (xcb:generate-id exwm--connection)))
|
(let ((new-owner (xcb:generate-id exwm--connection)))
|
||||||
(xcb:+request exwm--connection
|
(xcb:+request exwm--connection
|
||||||
(make-instance 'xcb:CreateWindow
|
(make-instance 'xcb:CreateWindow
|
||||||
|
@ -824,23 +829,61 @@ manager. If t, replace it, if nil, abort and ask the user if `ask'."
|
||||||
(setq exwm--wmsn-window new-owner))))
|
(setq exwm--wmsn-window new-owner))))
|
||||||
|
|
||||||
;;;###autoload
|
;;;###autoload
|
||||||
(cl-defun exwm-init (&optional frame)
|
(define-minor-mode exwm-minor-mode
|
||||||
|
"Minor mode to enable or disable EXWM.
|
||||||
|
|
||||||
|
EXWM (Emacs X Window Manager) is a full-featured tiling X window manager
|
||||||
|
for Emacs built on top of XELB.
|
||||||
|
|
||||||
|
If called interactively, enable EXWM minor mode if ARG is positive, and
|
||||||
|
disable it if ARG is zero or negative. If called from Lisp, also
|
||||||
|
enable the mode if ARG is omitted or nil, and toggle it if ARG is
|
||||||
|
‘toggle’; disable the mode otherwise.
|
||||||
|
|
||||||
|
If no X display can be found, EXWM will be started as soon as the first X
|
||||||
|
frame is created."
|
||||||
|
:global t
|
||||||
|
:group 'exwm
|
||||||
|
(if exwm-minor-mode
|
||||||
|
;; Up
|
||||||
|
(if exwm--connection
|
||||||
|
(exwm--log "EXWM already running")
|
||||||
|
(let ((frame (exwm--find-any-x-frame)))
|
||||||
|
(if frame
|
||||||
|
(exwm--init frame) ; initialize right away if any X frame exists.
|
||||||
|
(exwm--enable)))) ; will initialize as soon as there's an X frame.
|
||||||
|
;; Down
|
||||||
|
(if exwm--connection
|
||||||
|
(exwm--exit)
|
||||||
|
(exwm--disable))))
|
||||||
|
|
||||||
|
(defun exwm--init-on-window-setup-hook ()
|
||||||
|
"Try to start EXWM on selected frame."
|
||||||
|
(exwm--init-on-after-make-frame (selected-frame)))
|
||||||
|
|
||||||
|
(defun exwm--init-on-after-make-frame (frame)
|
||||||
|
"Try to start EXWM if FRAME's window-system is X."
|
||||||
|
(condition-case _
|
||||||
|
(exwm--init frame)
|
||||||
|
;; Ignore non X frames.
|
||||||
|
(exwm-frame-not-x)))
|
||||||
|
|
||||||
|
(defun exwm--init (&optional frame)
|
||||||
"Initialize EXWM."
|
"Initialize EXWM."
|
||||||
(interactive)
|
(interactive)
|
||||||
(exwm--log "%s" frame)
|
(exwm--log "%s" frame)
|
||||||
(if frame
|
(if frame
|
||||||
;; The frame might not be selected if it's created by emacslicnet.
|
;; The frame might not be selected if it's created by emacsclient.
|
||||||
(select-frame-set-input-focus frame)
|
(select-frame-set-input-focus frame)
|
||||||
(setq frame (selected-frame)))
|
(setq frame (selected-frame)))
|
||||||
(when (not (eq 'x (framep frame)))
|
(when (not (eq 'x (framep frame)))
|
||||||
(message "[EXWM] Not running under X environment")
|
(signal 'exwm-frame-not-x frame))
|
||||||
(cl-return-from exwm-init))
|
|
||||||
(when exwm--connection
|
(when exwm--connection
|
||||||
(exwm--log "EXWM already running")
|
(exwm--log "EXWM already running")
|
||||||
(cl-return-from exwm-init))
|
(signal 'exwm-already-running frame))
|
||||||
(condition-case err
|
(condition-case err
|
||||||
(progn
|
(progn
|
||||||
(exwm-enable 'undo) ;never initialize again
|
(exwm--disable) ;never initialize again
|
||||||
(setq exwm--connection (xcb:connect))
|
(setq exwm--connection (xcb:connect))
|
||||||
(set-process-query-on-exit-flag (slot-value exwm--connection 'process)
|
(set-process-query-on-exit-flag (slot-value exwm--connection 'process)
|
||||||
nil) ;prevent query message on exit
|
nil) ;prevent query message on exit
|
||||||
|
@ -860,9 +903,16 @@ manager. If t, replace it, if nil, abort and ask the user if `ask'."
|
||||||
:event-mask
|
:event-mask
|
||||||
xcb:EventMask:SubstructureRedirect))
|
xcb:EventMask:SubstructureRedirect))
|
||||||
(error "Other window manager is running"))
|
(error "Other window manager is running"))
|
||||||
|
;; Mandatory; before init.
|
||||||
|
(setq frame-resize-pixelwise t
|
||||||
|
window-resize-pixelwise t)
|
||||||
;; Disable some features not working well with EXWM
|
;; Disable some features not working well with EXWM
|
||||||
(setq use-dialog-box nil
|
(setq use-dialog-box nil
|
||||||
confirm-kill-emacs #'exwm--confirm-kill-emacs)
|
confirm-kill-emacs #'exwm--confirm-kill-emacs)
|
||||||
|
;; Manage the subordinate Emacs server.
|
||||||
|
(add-hook 'kill-emacs-hook #'exwm--server-stop)
|
||||||
|
(dolist (i exwm-blocking-subrs)
|
||||||
|
(advice-add i :around #'exwm--server-eval-at))
|
||||||
(exwm--lock)
|
(exwm--lock)
|
||||||
(exwm--init-icccm-ewmh)
|
(exwm--init-icccm-ewmh)
|
||||||
(exwm-layout--init)
|
(exwm-layout--init)
|
||||||
|
@ -876,59 +926,59 @@ manager. If t, replace it, if nil, abort and ask the user if `ask'."
|
||||||
(run-hooks 'exwm-init-hook)
|
(run-hooks 'exwm-init-hook)
|
||||||
;; Manage existing windows
|
;; Manage existing windows
|
||||||
(exwm-manage--scan))
|
(exwm-manage--scan))
|
||||||
(user-error)
|
(exwm-other-wm
|
||||||
|
(exwm--cleanup)
|
||||||
|
(signal (car err) (cdr err)))
|
||||||
((quit error)
|
((quit error)
|
||||||
(exwm-exit)
|
(exwm--exit)
|
||||||
;; Rethrow error
|
;; Rethrow error
|
||||||
(warn "[EXWM] EXWM fails to start (%s: %s)" (car err) (cdr err)))))
|
(warn "[EXWM] EXWM fails to start (%s: %s)" (car err) (cdr err)))))
|
||||||
|
|
||||||
|
(defun exwm--exit ()
|
||||||
;;;###autoload
|
|
||||||
(defun exwm-exit ()
|
|
||||||
"Exit EXWM."
|
"Exit EXWM."
|
||||||
(interactive)
|
(interactive)
|
||||||
(exwm--log)
|
(exwm--log)
|
||||||
(run-hooks 'exwm-exit-hook)
|
(run-hooks 'exwm-exit-hook)
|
||||||
|
;; Revert disabled features.
|
||||||
(setq confirm-kill-emacs nil)
|
(setq confirm-kill-emacs nil)
|
||||||
|
(remove-hook 'kill-emacs-hook #'exwm--server-stop)
|
||||||
|
(dolist (i exwm-blocking-subrs)
|
||||||
|
(advice-remove i #'exwm--server-eval-at))
|
||||||
;; Exit modules.
|
;; Exit modules.
|
||||||
(exwm-input--exit)
|
(exwm-input--exit)
|
||||||
(exwm-manage--exit)
|
(exwm-manage--exit)
|
||||||
(exwm-workspace--exit)
|
(exwm-workspace--exit)
|
||||||
(exwm-floating--exit)
|
(exwm-floating--exit)
|
||||||
(exwm-layout--exit)
|
(exwm-layout--exit)
|
||||||
|
(exwm--cleanup))
|
||||||
|
|
||||||
|
(defun exwm--cleanup ()
|
||||||
|
"Cleanup EXWM variables."
|
||||||
(when exwm--connection
|
(when exwm--connection
|
||||||
(xcb:flush exwm--connection)
|
(xcb:flush exwm--connection)
|
||||||
(xcb:disconnect exwm--connection))
|
(xcb:disconnect exwm--connection))
|
||||||
(setq exwm--connection nil))
|
(setq exwm--connection nil)
|
||||||
|
(setq exwm--root nil))
|
||||||
|
|
||||||
;;;###autoload
|
(defun exwm--enable ()
|
||||||
(defun exwm-enable (&optional undo)
|
"Enable EXWM.
|
||||||
"Enable/Disable EXWM."
|
Register functions for EXWM to be initialized as soon as Emacs is and there is
|
||||||
(exwm--log "%s" undo)
|
an X display available."
|
||||||
(pcase undo
|
(exwm--log)
|
||||||
(`undo ;prevent reinitialization
|
;; Ignore unrecognized command line arguments. This can be helpful
|
||||||
(remove-hook 'window-setup-hook #'exwm-init)
|
;; when EXWM is launched by some session manager.
|
||||||
(remove-hook 'after-make-frame-functions #'exwm-init))
|
(push #'vector command-line-functions)
|
||||||
(`undo-all ;attempt to revert everything
|
;; In case EXWM is to be started from a graphical Emacs instance.
|
||||||
(remove-hook 'window-setup-hook #'exwm-init)
|
(add-hook 'window-setup-hook #'exwm--init-on-window-setup-hook t)
|
||||||
(remove-hook 'after-make-frame-functions #'exwm-init)
|
;; In case EXWM is to be started with emacsclient.
|
||||||
(remove-hook 'kill-emacs-hook #'exwm--server-stop)
|
(add-hook 'after-make-frame-functions #'exwm--init-on-after-make-frame t))
|
||||||
(dolist (i exwm-blocking-subrs)
|
|
||||||
(advice-remove i #'exwm--server-eval-at)))
|
(defun exwm--disable ()
|
||||||
(_ ;enable EXWM
|
"Disable EXWM.
|
||||||
(setq frame-resize-pixelwise t ;mandatory; before init
|
See `exwm--enable'."
|
||||||
window-resize-pixelwise t)
|
(exwm--log)
|
||||||
;; Ignore unrecognized command line arguments. This can be helpful
|
(remove-hook 'window-setup-hook #'exwm--init-on-window-setup-hook)
|
||||||
;; when EXWM is launched by some session manager.
|
(remove-hook 'after-make-frame-functions #'exwm--init-on-after-make-frame))
|
||||||
(push #'vector command-line-functions)
|
|
||||||
;; In case EXWM is to be started from a graphical Emacs instance.
|
|
||||||
(add-hook 'window-setup-hook #'exwm-init t)
|
|
||||||
;; In case EXWM is to be started with emacsclient.
|
|
||||||
(add-hook 'after-make-frame-functions #'exwm-init t)
|
|
||||||
;; Manage the subordinate Emacs server.
|
|
||||||
(add-hook 'kill-emacs-hook #'exwm--server-stop)
|
|
||||||
(dolist (i exwm-blocking-subrs)
|
|
||||||
(advice-add i :around #'exwm--server-eval-at)))))
|
|
||||||
|
|
||||||
(defun exwm--server-stop ()
|
(defun exwm--server-stop ()
|
||||||
"Stop the subordinate Emacs server."
|
"Stop the subordinate Emacs server."
|
||||||
|
@ -1008,10 +1058,48 @@ manager. If t, replace it, if nil, abort and ask the user if `ask'."
|
||||||
(run-hooks 'kill-emacs-hook)
|
(run-hooks 'kill-emacs-hook)
|
||||||
(setq kill-emacs-hook nil))
|
(setq kill-emacs-hook nil))
|
||||||
;; Exit each module, destroying all resources created by this connection.
|
;; Exit each module, destroying all resources created by this connection.
|
||||||
(exwm-exit)
|
(exwm--exit)
|
||||||
;; Set the return value.
|
;; Set the return value.
|
||||||
t))
|
t))
|
||||||
|
|
||||||
|
(defun exwm--terminal-x-p (terminal)
|
||||||
|
"Check whether TERMINAL is an X terminal."
|
||||||
|
(eq 'x (terminal-live-p terminal)))
|
||||||
|
|
||||||
|
(defun exwm--find-any-x-frame ()
|
||||||
|
"Find a frame whose terminal is an X display.
|
||||||
|
Selected frame is checked first."
|
||||||
|
(let* ((terminals (cons (frame-terminal (selected-frame))
|
||||||
|
(terminal-list)))
|
||||||
|
(found-terminal (seq-find 'exwm--terminal-x-p terminals)))
|
||||||
|
(when found-terminal
|
||||||
|
(car (frames-on-display-list found-terminal)))))
|
||||||
|
|
||||||
|
|
||||||
|
;;; Obsolete:
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun exwm-enable (&optional undo)
|
||||||
|
"Enable/Disable EXWM."
|
||||||
|
(exwm--log "%s" undo)
|
||||||
|
(pcase undo
|
||||||
|
(`undo (exwm--disable))
|
||||||
|
(_ (exwm--enable))))
|
||||||
|
(make-obsolete 'exwm-enable
|
||||||
|
"Please use `exwm-minor-mode' instead"
|
||||||
|
"exwm-0.28")
|
||||||
|
|
||||||
|
(defalias 'exwm-init 'exwm--init)
|
||||||
|
(make-obsolete 'exwm-init
|
||||||
|
"Please use `exwm-minor-mode' instead"
|
||||||
|
"exwm-0.28")
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defalias 'exwm-exit 'exwm--exit)
|
||||||
|
(make-obsolete 'exwm-exit
|
||||||
|
"Please use `exwm-minor-mode' instead"
|
||||||
|
"exwm-0.28")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
(provide 'exwm)
|
(provide 'exwm)
|
||||||
|
|
Loading…
Reference in a new issue