Fix restarting issues
* exwm-workspace.el (exwm-workspace--confirm-kill-emacs): Prompt for unsaved files before restarting; avoid running `server-force-stop' early; restore the 'client' frame parameter before calling `exwm--exit'; correctly handle emacsclient. * exwm.el (exwm-restart): Always kill subordinate Emacs instances.
This commit is contained in:
parent
173bbde885
commit
e7ff9a9f90
2 changed files with 59 additions and 23 deletions
|
@ -25,6 +25,8 @@
|
|||
|
||||
;;; Code:
|
||||
|
||||
(require 'server)
|
||||
|
||||
(require 'exwm-core)
|
||||
|
||||
(defvar exwm-workspace-number 1 "Initial number of workspaces.")
|
||||
|
@ -1046,15 +1048,32 @@ Please check `exwm-workspace--minibuffer-own-frame-p' first."
|
|||
|
||||
(defun exwm-workspace--confirm-kill-emacs (prompt &optional force)
|
||||
"Confirm before exiting Emacs."
|
||||
(when (or (and force (not (eq force 'no-check)))
|
||||
(and (or (eq force 'no-check) (not exwm--id-buffer-alist))
|
||||
(y-or-n-p prompt))
|
||||
(yes-or-no-p (format "[EXWM] %d window(s) will be destroyed. %s"
|
||||
(length exwm--id-buffer-alist) prompt)))
|
||||
;; Run `kill-emacs-hook' before Emacs frames are unmapped so that
|
||||
;; errors can be visible.
|
||||
(run-hooks 'kill-emacs-hook)
|
||||
(setq kill-emacs-hook nil)
|
||||
(when (cond
|
||||
((and force (not (eq force 'no-check)))
|
||||
;; Force killing Emacs.
|
||||
t)
|
||||
((or (eq force 'no-check) (not exwm--id-buffer-alist))
|
||||
;; Check if there's any unsaved file.
|
||||
(pcase (catch 'break
|
||||
(let ((kill-emacs-query-functions
|
||||
(append kill-emacs-query-functions
|
||||
(list (lambda ()
|
||||
(throw 'break 'break))))))
|
||||
(save-buffers-kill-emacs)))
|
||||
(`break (y-or-n-p prompt))
|
||||
(x x)))
|
||||
(t
|
||||
(yes-or-no-p (format "[EXWM] %d window(s) will be destroyed. %s"
|
||||
(length exwm--id-buffer-alist) prompt))))
|
||||
;; Run `kill-emacs-hook' (`server-force-stop' excluded) before Emacs
|
||||
;; frames are unmapped so that errors (if any) can be visible.
|
||||
(if (memq #'server-force-stop kill-emacs-hook)
|
||||
(progn
|
||||
(setq kill-emacs-hook (delq #'server-force-stop kill-emacs-hook))
|
||||
(run-hooks 'kill-emacs-hook)
|
||||
(setq kill-emacs-hook (list #'server-force-stop)))
|
||||
(run-hooks 'kill-emacs-hook)
|
||||
(setq kill-emacs-hook nil))
|
||||
;; Hide & reparent out all frames (save-set can't be used here since
|
||||
;; X windows will be re-mapped).
|
||||
(when (exwm-workspace--minibuffer-own-frame-p)
|
||||
|
@ -1079,22 +1098,20 @@ Please check `exwm-workspace--minibuffer-own-frame-p' first."
|
|||
:parent exwm--root
|
||||
:x 0
|
||||
:y 0))))
|
||||
;; Exit each module.
|
||||
(exwm--exit)
|
||||
;; Destroy all resources created by this connection.
|
||||
(xcb:disconnect exwm--connection)
|
||||
(setq exwm--connection nil)
|
||||
;; Extra cleanups for emacsclient.
|
||||
;; Restore the 'client' frame parameter (before `exwm--exit').
|
||||
(when exwm-workspace--client
|
||||
(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))
|
||||
;; Kill the client.
|
||||
(server-save-buffers-kill-terminal nil))
|
||||
exwm-workspace--client)))
|
||||
;; Exit each module.
|
||||
(exwm--exit)
|
||||
;; Destroy all resources created by this connection.
|
||||
(xcb:disconnect exwm--connection)
|
||||
(setq exwm--connection nil)
|
||||
;; Set the return value.
|
||||
(not exwm-workspace--client)))
|
||||
t))
|
||||
|
||||
(defun exwm-workspace--set-desktop-geometry ()
|
||||
"Set _NET_DESKTOP_GEOMETRY."
|
||||
|
|
27
exwm.el
27
exwm.el
|
@ -88,10 +88,29 @@
|
|||
"Restart EXWM."
|
||||
(interactive)
|
||||
(when (exwm-workspace--confirm-kill-emacs "[EXWM] Restart? " 'no-check)
|
||||
(apply #'call-process (car command-line-args) nil nil nil
|
||||
(cdr command-line-args))
|
||||
;; Kill this instance at last.
|
||||
(kill-emacs)))
|
||||
(let* ((attr (process-attributes (emacs-pid)))
|
||||
(args (cdr (assq 'args attr)))
|
||||
(ppid (cdr (assq 'ppid attr)))
|
||||
(pargs (cdr (assq 'args (process-attributes ppid)))))
|
||||
(cond
|
||||
((= ppid 1)
|
||||
;; The parent is the init process. This probably means this
|
||||
;; instance is an emacsclient. Anyway, start a control instance
|
||||
;; to manage the subsequent ones.
|
||||
(call-process (car command-line-args))
|
||||
(kill-emacs))
|
||||
((string= args pargs)
|
||||
;; This is a subordinate instance. Return a magic number to
|
||||
;; inform the parent (control instance) to start another one.
|
||||
(kill-emacs ?R))
|
||||
(t
|
||||
;; This is the control instance. Keep starting subordinate
|
||||
;; instances until told to exit.
|
||||
;; Run `server-force-stop' if it exists.
|
||||
(run-hooks 'kill-emacs-hook)
|
||||
(with-temp-buffer
|
||||
(while (= ?R (shell-command-on-region (point) (point) args))))
|
||||
(kill-emacs))))))
|
||||
|
||||
(defun exwm--update-window-type (id &optional force)
|
||||
"Update _NET_WM_WINDOW_TYPE."
|
||||
|
|
Loading…
Reference in a new issue