mirror of
https://github.com/emacs-exwm/exwm.git
synced 2024-11-27 06:48:00 +01:00
Add cleanup codes for Emacs daemon
* exwm-floating.el (exwm-floating--exit): * exwm-input.el (exwm-input--exit): * exwm-layout.el (exwm-layout--exit): * exwm-manage.el (exwm-manage--exit): * exwm-randr.el (exwm-randr--exit): * exwm-systemtray.el (exwm-systemtray--exit): * exwm-workspace.el (exwm-workspace--exit): New functions for cleanup each module. * exwm-input.el (exwm-input--on-pre-command, exwm-input--on-post-command) (exwm-input--init): Name lambda functions. * exwm-layout.el (exwm-layout--timer, exwm-layout--init): Save timer. * exwm-randr.el (exwm-randr-enable): Register the cleanup function. * exwm-systemtray.el (exwm-systemtray--init): Force refresh atoms in XEMBED and system tray protocols. (exwm-systemtray-enable): Register the cleanup function. * exwm-workspace.el (exwm-workspace--client): Save the server process. (exwm-workspace--confirm-kill-emacs): Add emacsclient-specific cleanup codes. (exwm-workspace--timer): Save the timer. (exwm-workspace--init): Save the server process and timer; fix problems with emacsclient frames. * exwm.el (exwm-init): Always select the newly created frame; force refresh ICCCM & EWMH atoms. (exwm-exit-hook): New hook for holding cleanup codes. (exwm--exit): Run `exwm-exit-hook', execute cleanup codes for each module and reset the environment.
This commit is contained in:
parent
dc0c0f5131
commit
1b2ae3749e
8 changed files with 149 additions and 22 deletions
|
@ -622,6 +622,9 @@ Both DELTA-X and DELTA-Y default to 1. This command should be bound locally."
|
|||
exwm-floating--cursor-left
|
||||
(xcb:cursor:load-cursor exwm--connection "left_side")))
|
||||
|
||||
(defun exwm-floating--exit ()
|
||||
"Exit the floating module.")
|
||||
|
||||
|
||||
|
||||
(provide 'exwm-floating)
|
||||
|
|
|
@ -476,6 +476,14 @@ SIMULATION-KEYS is an alist of the form (original-key . simulated-key)."
|
|||
(dolist (j pair)
|
||||
(exwm-input--fake-key j))))))
|
||||
|
||||
(defun exwm-input--on-pre-command ()
|
||||
"Run in `pre-command-hook'."
|
||||
(setq exwm-input--during-command t))
|
||||
|
||||
(defun exwm-input--on-post-command ()
|
||||
"Run in `post-command-hook'."
|
||||
(setq exwm-input--during-command nil))
|
||||
|
||||
(declare-function exwm-floating--stop-moveresize "exwm-floating.el"
|
||||
(&rest _args))
|
||||
(declare-function exwm-floating--do-moveresize "exwm-floating.el"
|
||||
|
@ -510,14 +518,20 @@ SIMULATION-KEYS is an alist of the form (original-key . simulated-key)."
|
|||
;; `pre-command-hook' marks the end of a key sequence (existing or not)
|
||||
(add-hook 'pre-command-hook #'exwm-input--finish-key-sequence)
|
||||
;; Control `exwm-input--during-command'
|
||||
(add-hook 'pre-command-hook (lambda () (setq exwm-input--during-command t)))
|
||||
(add-hook 'post-command-hook
|
||||
(lambda () (setq exwm-input--during-command nil)))
|
||||
(add-hook 'pre-command-hook #'exwm-input--on-pre-command)
|
||||
(add-hook 'post-command-hook #'exwm-input--on-post-command)
|
||||
;; Update focus when buffer list updates
|
||||
(add-hook 'buffer-list-update-hook #'exwm-input--on-buffer-list-update)
|
||||
;; Update prefix keys for global keys
|
||||
(exwm-input--update-global-prefix-keys))
|
||||
|
||||
(defun exwm-input--exit ()
|
||||
"Exit the input module."
|
||||
(remove-hook 'pre-command-hook #'exwm-input--finish-key-sequence)
|
||||
(remove-hook 'pre-command-hook #'exwm-input--on-pre-command)
|
||||
(remove-hook 'post-command-hook #'exwm-input--on-post-command)
|
||||
(remove-hook 'buffer-list-update-hook #'exwm-input--on-buffer-list-update))
|
||||
|
||||
|
||||
|
||||
(provide 'exwm-input)
|
||||
|
|
|
@ -528,6 +528,8 @@ See also `exwm-layout-enlarge-window'."
|
|||
(exwm-layout-hide-mode-line)
|
||||
(exwm-layout-show-mode-line))))
|
||||
|
||||
(defvar exwm-layout--timer nil "Timer used to track echo area changes.")
|
||||
|
||||
(defun exwm-layout--init ()
|
||||
"Initialize layout module."
|
||||
;; Auto refresh layout
|
||||
|
@ -535,9 +537,19 @@ See also `exwm-layout-enlarge-window'."
|
|||
(unless (exwm-workspace--minibuffer-own-frame-p)
|
||||
;; Refresh when minibuffer grows
|
||||
(add-hook 'minibuffer-setup-hook #'exwm-layout--on-minibuffer-setup t)
|
||||
(run-with-idle-timer 0 t #'exwm-layout--on-echo-area-change t)
|
||||
(setq exwm-layout--timer
|
||||
(run-with-idle-timer 0 t #'exwm-layout--on-echo-area-change t))
|
||||
(add-hook 'echo-area-clear-hook #'exwm-layout--on-echo-area-change)))
|
||||
|
||||
(defun exwm-layout--exit ()
|
||||
"Exit the layout module."
|
||||
(remove-hook 'window-configuration-change-hook #'exwm-layout--refresh)
|
||||
(remove-hook 'minibuffer-setup-hook #'exwm-layout--on-minibuffer-setup)
|
||||
(when exwm-layout--timer
|
||||
(cancel-timer exwm-layout--timer)
|
||||
(setq exwm-layout--timer nil))
|
||||
(remove-hook 'echo-area-clear-hook #'exwm-layout--on-echo-area-change))
|
||||
|
||||
|
||||
|
||||
(provide 'exwm-layout)
|
||||
|
|
|
@ -555,6 +555,10 @@ border-width: %d; sibling: #x%x; stack-mode: %d"
|
|||
(xcb:+event exwm--connection 'xcb:DestroyNotify
|
||||
#'exwm-manage--on-DestroyNotify))
|
||||
|
||||
(defun exwm-manage--exit ()
|
||||
"Exit the manage module."
|
||||
(setq exwm-manage--_MOTIF_WM_HINTS nil))
|
||||
|
||||
|
||||
|
||||
(provide 'exwm-manage)
|
||||
|
|
|
@ -164,9 +164,13 @@
|
|||
))
|
||||
(xcb:flush exwm--connection)))))
|
||||
|
||||
(defun exwm-randr--exit ()
|
||||
"Exit the RandR module.")
|
||||
|
||||
(defun exwm-randr-enable ()
|
||||
"Enable RandR support for EXWM."
|
||||
(add-hook 'exwm-init-hook #'exwm-randr--init))
|
||||
(add-hook 'exwm-init-hook #'exwm-randr--init)
|
||||
(add-hook 'exwm-exit-hook #'exwm-randr--exit))
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -311,8 +311,8 @@ You shall use the default value if using auto-hide minibuffer.")
|
|||
'process)
|
||||
nil)
|
||||
;; Initialize XELB modules.
|
||||
(xcb:xembed:init exwm-systemtray--connection)
|
||||
(xcb:systemtray:init exwm-systemtray--connection)
|
||||
(xcb:xembed:init exwm-systemtray--connection t)
|
||||
(xcb:systemtray:init exwm-systemtray--connection t)
|
||||
;; Acquire the manager selection _NET_SYSTEM_TRAY_S0.
|
||||
(with-slots (owner)
|
||||
(xcb:+request-unchecked+reply exwm-systemtray--connection
|
||||
|
@ -399,11 +399,27 @@ You shall use the default value if using auto-hide minibuffer.")
|
|||
#'exwm-systemtray--on-ClientMessage)
|
||||
;; Add hook to move/reparent the embedder.
|
||||
(add-hook 'exwm-workspace-switch-hook #'exwm-systemtray--on-workspace-switch)
|
||||
(add-hook 'exwm-randr-refresh-hook #'exwm-systemtray--on-randr-refresh))
|
||||
(when (boundp 'exwm-randr-refresh-hook)
|
||||
(add-hook 'exwm-randr-refresh-hook #'exwm-systemtray--on-randr-refresh)))
|
||||
|
||||
(defun exwm-systemtray--exit ()
|
||||
"Exit the systemtray module."
|
||||
(when exwm-systemtray--connection
|
||||
(xcb:disconnect exwm-systemtray--connection)
|
||||
(setq exwm-systemtray--connection nil
|
||||
exwm-systemtray--list nil
|
||||
exwm-systemtray--selection-owner-window nil
|
||||
exwm-systemtray--embedder nil)
|
||||
(remove-hook 'exwm-workspace-switch-hook
|
||||
#'exwm-systemtray--on-workspace-switch)
|
||||
(when (boundp 'exwm-randr-refresh-hook)
|
||||
(remove-hook 'exwm-randr-refresh-hook
|
||||
#'exwm-systemtray--on-randr-refresh))))
|
||||
|
||||
(defun exwm-systemtray-enable ()
|
||||
"Enable system tray support for EXWM."
|
||||
(add-hook 'exwm-init-hook #'exwm-systemtray--init))
|
||||
(add-hook 'exwm-init-hook #'exwm-systemtray--init)
|
||||
(add-hook 'exwm-exit-hook #'exwm-systemtray--exit))
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -584,7 +584,11 @@ The optional FORCE option is for internal use only."
|
|||
(cancel-timer exwm-workspace--display-echo-area-timer)
|
||||
(setq exwm-workspace--display-echo-area-timer nil))))
|
||||
|
||||
(defvar exwm-workspace--client nil
|
||||
"The 'client' frame parameter of emacsclient frames.")
|
||||
|
||||
(declare-function exwm-manage--unmanage-window "exwm-manage.el")
|
||||
(declare-function exwm--exit "exwm.el")
|
||||
|
||||
(defun exwm-workspace--confirm-kill-emacs (prompt)
|
||||
"Confirm before exiting Emacs."
|
||||
|
@ -615,9 +619,26 @@ The optional FORCE option is for internal use only."
|
|||
:x 0
|
||||
:y 0)))
|
||||
(xcb:flush exwm--connection)
|
||||
;; Destroy all resources created by this connection.
|
||||
(xcb:disconnect exwm--connection)
|
||||
t))
|
||||
(if (not exwm-workspace--client)
|
||||
(progn
|
||||
;; Destroy all resources created by this connection.
|
||||
(xcb:disconnect exwm--connection)
|
||||
t)
|
||||
;; Extra cleanups for emacsclient.
|
||||
(dolist (f exwm-workspace--list)
|
||||
(set-frame-parameter f 'client exwm-workspace--client))
|
||||
(when (exwm-workspace--minibuffer-own-frame-p)
|
||||
(set-frame-parameter exwm-workspace--minibuffer 'client
|
||||
exwm-workspace--client))
|
||||
(let ((connection exwm--connection))
|
||||
(exwm--exit)
|
||||
;; Destroy all resources created by this connection.
|
||||
(xcb:disconnect connection))
|
||||
;; Kill the client.
|
||||
(server-save-buffers-kill-terminal nil)
|
||||
nil)))
|
||||
|
||||
(defvar exwm-workspace--timer nil "Timer used to track echo area changes.")
|
||||
|
||||
(defun exwm-workspace--init ()
|
||||
"Initialize workspace module."
|
||||
|
@ -629,11 +650,13 @@ The optional FORCE option is for internal use only."
|
|||
(progn
|
||||
(setq exwm-workspace--list (frame-list))
|
||||
(when (< 1 (length exwm-workspace--list))
|
||||
;; Emacs client creates an extra (but unusable) frame.
|
||||
;; Exclude the initial frame.
|
||||
(dolist (i exwm-workspace--list)
|
||||
(unless (frame-parameter i 'window-id)
|
||||
(setq exwm-workspace--list (delq i exwm-workspace--list))))
|
||||
(cl-assert (= 1 (length exwm-workspace--list)))
|
||||
(setq exwm-workspace--client
|
||||
(frame-parameter (car exwm-workspace--list) 'client))
|
||||
;; Prevent user from deleting this frame by accident.
|
||||
(set-frame-parameter (car exwm-workspace--list) 'client nil))
|
||||
;; Create remaining frames.
|
||||
|
@ -645,12 +668,17 @@ The optional FORCE option is for internal use only."
|
|||
(setq exwm-workspace--minibuffer
|
||||
(make-frame '((window-system . x) (minibuffer . only)
|
||||
(left . 10000) (right . 10000)
|
||||
(width . 0) (height . 0))))
|
||||
(width . 0) (height . 0)
|
||||
(client . nil))))
|
||||
;; Remove/hide existing frames.
|
||||
(dolist (f old-frames)
|
||||
(if (frame-parameter f 'client)
|
||||
(make-frame-invisible f)
|
||||
(delete-frame f))))
|
||||
(progn
|
||||
(unless exwm-workspace--client
|
||||
(setq exwm-workspace--client (frame-parameter f 'client)))
|
||||
(make-frame-invisible f))
|
||||
(when (eq 'x (framep f)) ;do not delete the initial frame.
|
||||
(delete-frame f)))))
|
||||
;; This is the only usable minibuffer frame.
|
||||
(setq default-minibuffer-frame exwm-workspace--minibuffer)
|
||||
(let ((outer-id (string-to-number
|
||||
|
@ -687,17 +715,20 @@ The optional FORCE option is for internal use only."
|
|||
;; Show/hide minibuffer / echo area when they're active/inactive.
|
||||
(add-hook 'minibuffer-setup-hook #'exwm-workspace--on-minibuffer-setup)
|
||||
(add-hook 'minibuffer-exit-hook #'exwm-workspace--on-minibuffer-exit)
|
||||
(run-with-idle-timer 0 t #'exwm-workspace--on-echo-area-dirty)
|
||||
(setq exwm-workspace--timer
|
||||
(run-with-idle-timer 0 t #'exwm-workspace--on-echo-area-dirty))
|
||||
(add-hook 'echo-area-clear-hook #'exwm-workspace--on-echo-area-clear)
|
||||
;; Create workspace frames.
|
||||
(dotimes (_ exwm-workspace-number)
|
||||
(push (make-frame `((window-system . x)
|
||||
(minibuffer . ,(minibuffer-window
|
||||
exwm-workspace--minibuffer))))
|
||||
exwm-workspace--minibuffer))
|
||||
(client . nil)))
|
||||
exwm-workspace--list))
|
||||
;; The default behavior of `display-buffer' (indirectly called by
|
||||
;; `minibuffer-completion-help') is not correct here.
|
||||
(cl-pushnew '(exwm-workspace--display-buffer) display-buffer-alist))
|
||||
(cl-pushnew '(exwm-workspace--display-buffer) display-buffer-alist
|
||||
:test #'equal))
|
||||
;; Handle unexpected frame switch.
|
||||
(add-hook 'focus-in-hook #'exwm-workspace--on-focus-in)
|
||||
;; Prevent `other-buffer' from selecting already displayed EXWM buffers.
|
||||
|
@ -768,6 +799,25 @@ The optional FORCE option is for internal use only."
|
|||
;; Switch to the first workspace
|
||||
(exwm-workspace-switch 0 t))
|
||||
|
||||
(defun exwm-workspace--exit ()
|
||||
"Exit the workspace module."
|
||||
(setq confirm-kill-emacs nil
|
||||
exwm-workspace--list nil
|
||||
exwm-workspace--client nil
|
||||
exwm-workspace--minibuffer nil
|
||||
default-minibuffer-frame nil)
|
||||
(remove-hook 'minibuffer-setup-hook #'exwm-workspace--on-minibuffer-setup)
|
||||
(remove-hook 'minibuffer-exit-hook #'exwm-workspace--on-minibuffer-exit)
|
||||
(when exwm-workspace--timer
|
||||
(cancel-timer exwm-workspace--timer)
|
||||
(setq exwm-workspace--timer nil))
|
||||
(remove-hook 'echo-area-clear-hook #'exwm-workspace--on-echo-area-clear)
|
||||
(setq display-buffer-alist
|
||||
(cl-delete '(exwm-workspace--display-buffer) display-buffer-alist
|
||||
:test #'equal))
|
||||
(remove-hook 'focus-in-hook #'exwm-workspace--on-focus-in)
|
||||
(advice-remove 'x-create-frame #'exwm-workspace--x-create-frame))
|
||||
|
||||
(defvar exwm-layout--fullscreen-frame-count)
|
||||
|
||||
(defun exwm-workspace--post-init ()
|
||||
|
|
30
exwm.el
30
exwm.el
|
@ -477,7 +477,11 @@
|
|||
|
||||
(defun exwm-init (&optional frame)
|
||||
"Initialize EXWM."
|
||||
(if (not (eq 'x (framep (or frame (selected-frame)))))
|
||||
(if frame
|
||||
;; The frame might not be selected if it's created by emacslicnet.
|
||||
(select-frame-set-input-focus frame)
|
||||
(setq frame (selected-frame)))
|
||||
(if (not (eq 'x (framep frame)))
|
||||
(exwm--log "Not running under X environment")
|
||||
(unless exwm--connection
|
||||
(exwm-enable 'undo) ;never initialize again
|
||||
|
@ -499,8 +503,8 @@
|
|||
;; Disable some features not working well with EXWM
|
||||
(setq use-dialog-box nil)
|
||||
;; Initialize ICCCM/EWMH support
|
||||
;; (xcb:icccm:init exwm--connection)
|
||||
(xcb:ewmh:init exwm--connection)
|
||||
(xcb:icccm:init exwm--connection t)
|
||||
(xcb:ewmh:init exwm--connection t)
|
||||
(exwm--lock)
|
||||
(exwm--init-icccm-ewmh)
|
||||
(exwm-layout--init)
|
||||
|
@ -514,6 +518,26 @@
|
|||
(exwm-manage--scan)
|
||||
(run-hooks 'exwm-init-hook)))))
|
||||
|
||||
(defvar exwm-exit-hook nil
|
||||
"Normal hook run just before EXWM is about to exit.
|
||||
|
||||
This hook is only run when EXWM is started with emacsclient.")
|
||||
|
||||
(defun exwm--exit ()
|
||||
"Exit EXWM."
|
||||
(run-hooks 'exwm-exit-hook)
|
||||
;; Exit modules.
|
||||
(exwm-input--exit)
|
||||
(exwm-workspace--exit)
|
||||
(exwm-manage--exit)
|
||||
(exwm-floating--exit)
|
||||
(exwm-layout--exit)
|
||||
;; Reset several import variables.
|
||||
(setq exwm--connection nil
|
||||
exwm--root nil
|
||||
exwm--id-buffer-alist nil)
|
||||
(exwm-enable))
|
||||
|
||||
(defvar exwm-blocking-subrs '(x-file-dialog x-popup-dialog x-select-font)
|
||||
"Subrs (primitives) that would normally block EXWM.")
|
||||
|
||||
|
|
Loading…
Reference in a new issue