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: | ;;; Code: | ||||||
| 
 | 
 | ||||||
|  | (require 'server) | ||||||
|  | 
 | ||||||
| (require 'exwm-core) | (require 'exwm-core) | ||||||
| 
 | 
 | ||||||
| (defvar exwm-workspace-number 1 "Initial number of workspaces.") | (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) | (defun exwm-workspace--confirm-kill-emacs (prompt &optional force) | ||||||
|   "Confirm before exiting Emacs." |   "Confirm before exiting Emacs." | ||||||
|   (when (or (and force (not (eq force 'no-check))) |   (when (cond | ||||||
|             (and (or (eq force 'no-check) (not exwm--id-buffer-alist)) |          ((and force (not (eq force 'no-check))) | ||||||
|                  (y-or-n-p prompt)) |           ;; 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" |           (yes-or-no-p (format "[EXWM] %d window(s) will be destroyed.  %s" | ||||||
|                                  (length exwm--id-buffer-alist) prompt))) |                                (length exwm--id-buffer-alist) prompt)))) | ||||||
|     ;; Run `kill-emacs-hook' before Emacs frames are unmapped so that |     ;; Run `kill-emacs-hook' (`server-force-stop' excluded) before Emacs | ||||||
|     ;; errors can be visible. |     ;; 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) |           (run-hooks 'kill-emacs-hook) | ||||||
|     (setq kill-emacs-hook nil) |           (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 |     ;; Hide & reparent out all frames (save-set can't be used here since | ||||||
|     ;; X windows will be re-mapped). |     ;; X windows will be re-mapped). | ||||||
|     (when (exwm-workspace--minibuffer-own-frame-p) |     (when (exwm-workspace--minibuffer-own-frame-p) | ||||||
|  | @ -1079,22 +1098,20 @@ Please check `exwm-workspace--minibuffer-own-frame-p' first." | ||||||
|                            :parent exwm--root |                            :parent exwm--root | ||||||
|                            :x 0 |                            :x 0 | ||||||
|                            :y 0)))) |                            :y 0)))) | ||||||
|     ;; Exit each module. |     ;; Restore the 'client' frame parameter (before `exwm--exit'). | ||||||
|     (exwm--exit) |  | ||||||
|     ;; Destroy all resources created by this connection. |  | ||||||
|     (xcb:disconnect exwm--connection) |  | ||||||
|     (setq exwm--connection nil) |  | ||||||
|     ;; Extra cleanups for emacsclient. |  | ||||||
|     (when exwm-workspace--client |     (when exwm-workspace--client | ||||||
|       (dolist (f exwm-workspace--list) |       (dolist (f exwm-workspace--list) | ||||||
|         (set-frame-parameter f 'client exwm-workspace--client)) |         (set-frame-parameter f 'client exwm-workspace--client)) | ||||||
|       (when (exwm-workspace--minibuffer-own-frame-p) |       (when (exwm-workspace--minibuffer-own-frame-p) | ||||||
|         (set-frame-parameter exwm-workspace--minibuffer 'client |         (set-frame-parameter exwm-workspace--minibuffer 'client | ||||||
|                              exwm-workspace--client)) |                              exwm-workspace--client))) | ||||||
|       ;; Kill the client. |     ;; Exit each module. | ||||||
|       (server-save-buffers-kill-terminal nil)) |     (exwm--exit) | ||||||
|  |     ;; Destroy all resources created by this connection. | ||||||
|  |     (xcb:disconnect exwm--connection) | ||||||
|  |     (setq exwm--connection nil) | ||||||
|     ;; Set the return value. |     ;; Set the return value. | ||||||
|     (not exwm-workspace--client))) |     t)) | ||||||
| 
 | 
 | ||||||
| (defun exwm-workspace--set-desktop-geometry () | (defun exwm-workspace--set-desktop-geometry () | ||||||
|   "Set _NET_DESKTOP_GEOMETRY." |   "Set _NET_DESKTOP_GEOMETRY." | ||||||
|  |  | ||||||
							
								
								
									
										27
									
								
								exwm.el
									
										
									
									
									
								
							
							
						
						
									
										27
									
								
								exwm.el
									
										
									
									
									
								
							|  | @ -88,10 +88,29 @@ | ||||||
|   "Restart EXWM." |   "Restart EXWM." | ||||||
|   (interactive) |   (interactive) | ||||||
|   (when (exwm-workspace--confirm-kill-emacs "[EXWM] Restart? " 'no-check) |   (when (exwm-workspace--confirm-kill-emacs "[EXWM] Restart? " 'no-check) | ||||||
|     (apply #'call-process (car command-line-args) nil nil nil |     (let* ((attr (process-attributes (emacs-pid))) | ||||||
|            (cdr command-line-args)) |            (args (cdr (assq 'args attr))) | ||||||
|     ;; Kill this instance at last. |            (ppid (cdr (assq 'ppid attr))) | ||||||
|     (kill-emacs))) |            (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) | (defun exwm--update-window-type (id &optional force) | ||||||
|   "Update _NET_WM_WINDOW_TYPE." |   "Update _NET_WM_WINDOW_TYPE." | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue