Support for killing the X terminal
Check whether frames are alive upon teardown, as it might not be the case when the terminal is killed as `delete-terminal-functions' might be invoked after the terminal is deleted. * exwm-core.el (exwm--terminal): New variable holding the terminal EXWM runs under. (exwm-init, exwm-exit): Set and unset it. * exwm.el (exwm--on-delete-terminal): New function for exiting EXWM when the terminal is deleted. (exwm-init): Use it. * exwm.el (exwm--confirm-kill-terminal, exwm-init): Ask for confirmation before deleting terminal. * exwm-workspace.el (exwm-workspace--fullscreen-workspace): New function. Ensure the frame is alive. (exwm-workspace--add-frame-as-workspace): Use it. (exwm-workspace--exit-minibuffer-frame): Cancel `exwm-workspace--display-echo-area-timer'. (exwm-workspace--exit-minibuffer-frame): Ensure the minibuffer frame is alive. (exwm-workspace--exit): Ignore dead workspace frames.
This commit is contained in:
		
							parent
							
								
									a11bb099fb
								
							
						
					
					
						commit
						1aa4ca781d
					
				
					 3 changed files with 63 additions and 25 deletions
				
			
		| 
						 | 
					@ -59,6 +59,9 @@ Here are some predefined candidates:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(defvar exwm--connection nil "X connection.")
 | 
					(defvar exwm--connection nil "X connection.")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(defvar exwm--terminal nil
 | 
				
			||||||
 | 
					  "Terminal corresponding to `exwm--connection'.")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(defvar exwm--wmsn-window nil
 | 
					(defvar exwm--wmsn-window nil
 | 
				
			||||||
  "An X window owning the WM_S0 selection.")
 | 
					  "An X window owning the WM_S0 selection.")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1372,7 +1372,7 @@ Please check `exwm-workspace--minibuffer-own-frame-p' first."
 | 
				
			||||||
        (make-instance 'xcb:MapWindow :window container)))
 | 
					        (make-instance 'xcb:MapWindow :window container)))
 | 
				
			||||||
  (xcb:flush exwm--connection)
 | 
					  (xcb:flush exwm--connection)
 | 
				
			||||||
  ;; Delay making the workspace fullscreen until Emacs becomes idle
 | 
					  ;; Delay making the workspace fullscreen until Emacs becomes idle
 | 
				
			||||||
  (exwm--defer 0 #'set-frame-parameter frame 'fullscreen 'fullboth)
 | 
					  (exwm--defer 0 #'exwm-workspace--fullscreen-workspace frame)
 | 
				
			||||||
  ;; Update EWMH properties.
 | 
					  ;; Update EWMH properties.
 | 
				
			||||||
  (exwm-workspace--update-ewmh-props)
 | 
					  (exwm-workspace--update-ewmh-props)
 | 
				
			||||||
  (if exwm-workspace--create-silently
 | 
					  (if exwm-workspace--create-silently
 | 
				
			||||||
| 
						 | 
					@ -1463,6 +1463,12 @@ Return nil if FRAME is the only workspace."
 | 
				
			||||||
    (exwm-workspace--remove-frame-as-workspace frame)
 | 
					    (exwm-workspace--remove-frame-as-workspace frame)
 | 
				
			||||||
    (remhash frame exwm-workspace--client-p-hash-table))))
 | 
					    (remhash frame exwm-workspace--client-p-hash-table))))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(defun exwm-workspace--fullscreen-workspace (frame)
 | 
				
			||||||
 | 
					  "Make workspace FRAME fullscreen.
 | 
				
			||||||
 | 
					Called from a timer."
 | 
				
			||||||
 | 
					  (when (frame-live-p frame)
 | 
				
			||||||
 | 
					    (set-frame-parameter frame 'fullscreen 'fullboth)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(defun exwm-workspace--on-after-make-frame (frame)
 | 
					(defun exwm-workspace--on-after-make-frame (frame)
 | 
				
			||||||
  "Hook run upon `make-frame' that configures FRAME as a workspace."
 | 
					  "Hook run upon `make-frame' that configures FRAME as a workspace."
 | 
				
			||||||
  (cond
 | 
					  (cond
 | 
				
			||||||
| 
						 | 
					@ -1606,6 +1612,8 @@ applied to all subsequently created X frames."
 | 
				
			||||||
  (remove-hook 'minibuffer-setup-hook #'exwm-workspace--on-minibuffer-setup)
 | 
					  (remove-hook 'minibuffer-setup-hook #'exwm-workspace--on-minibuffer-setup)
 | 
				
			||||||
  (remove-hook 'minibuffer-exit-hook #'exwm-workspace--on-minibuffer-exit)
 | 
					  (remove-hook 'minibuffer-exit-hook #'exwm-workspace--on-minibuffer-exit)
 | 
				
			||||||
  (remove-hook 'echo-area-clear-hook #'exwm-workspace--on-echo-area-clear)
 | 
					  (remove-hook 'echo-area-clear-hook #'exwm-workspace--on-echo-area-clear)
 | 
				
			||||||
 | 
					  (when exwm-workspace--display-echo-area-timer
 | 
				
			||||||
 | 
					    (cancel-timer exwm-workspace--display-echo-area-timer))
 | 
				
			||||||
  (when exwm-workspace--timer
 | 
					  (when exwm-workspace--timer
 | 
				
			||||||
    (cancel-timer exwm-workspace--timer)
 | 
					    (cancel-timer exwm-workspace--timer)
 | 
				
			||||||
    (setq exwm-workspace--timer nil))
 | 
					    (setq exwm-workspace--timer nil))
 | 
				
			||||||
| 
						 | 
					@ -1613,15 +1621,16 @@ applied to all subsequently created X frames."
 | 
				
			||||||
        (cl-delete '(exwm-workspace--display-buffer) display-buffer-alist
 | 
					        (cl-delete '(exwm-workspace--display-buffer) display-buffer-alist
 | 
				
			||||||
                   :test #'equal))
 | 
					                   :test #'equal))
 | 
				
			||||||
  (setq default-minibuffer-frame nil)
 | 
					  (setq default-minibuffer-frame nil)
 | 
				
			||||||
  (let ((id (frame-parameter exwm-workspace--minibuffer 'exwm-outer-id)))
 | 
					  (when (frame-live-p exwm-workspace--minibuffer) ; might be already dead
 | 
				
			||||||
    (when (and exwm-workspace--minibuffer id)
 | 
					    (let ((id (frame-parameter exwm-workspace--minibuffer 'exwm-outer-id)))
 | 
				
			||||||
      (xcb:+request exwm--connection
 | 
					      (when (and exwm-workspace--minibuffer id)
 | 
				
			||||||
          (make-instance 'xcb:ReparentWindow
 | 
					        (xcb:+request exwm--connection
 | 
				
			||||||
                         :window id
 | 
					            (make-instance 'xcb:ReparentWindow
 | 
				
			||||||
                         :parent exwm--root
 | 
					                           :window id
 | 
				
			||||||
                         :x 0
 | 
					                           :parent exwm--root
 | 
				
			||||||
                         :y 0)))
 | 
					                           :x 0
 | 
				
			||||||
    (setq exwm-workspace--minibuffer nil)))
 | 
					                           :y 0)))
 | 
				
			||||||
 | 
					      (setq exwm-workspace--minibuffer nil))))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(defun exwm-workspace--init ()
 | 
					(defun exwm-workspace--init ()
 | 
				
			||||||
  "Initialize workspace module."
 | 
					  "Initialize workspace module."
 | 
				
			||||||
| 
						 | 
					@ -1712,24 +1721,28 @@ applied to all subsequently created X frames."
 | 
				
			||||||
  ;; X windows will be re-mapped).
 | 
					  ;; X windows will be re-mapped).
 | 
				
			||||||
  (setq exwm-workspace--current nil)
 | 
					  (setq exwm-workspace--current nil)
 | 
				
			||||||
  (dolist (i exwm-workspace--list)
 | 
					  (dolist (i exwm-workspace--list)
 | 
				
			||||||
    (exwm-workspace--remove-frame-as-workspace i)
 | 
					    (when (frame-live-p i)                    ; might be already dead
 | 
				
			||||||
    (modify-frame-parameters i '((exwm-selected-window . nil)
 | 
					      (exwm-workspace--remove-frame-as-workspace i)
 | 
				
			||||||
                                 (exwm-urgency . nil)
 | 
					      (modify-frame-parameters i '((exwm-selected-window . nil)
 | 
				
			||||||
                                 (exwm-outer-id . nil)
 | 
					                                   (exwm-urgency . nil)
 | 
				
			||||||
                                 (exwm-id . nil)
 | 
					                                   (exwm-outer-id . nil)
 | 
				
			||||||
                                 (exwm-container . nil)
 | 
					                                   (exwm-id . nil)
 | 
				
			||||||
                                 ;; (internal-border-width . nil) ; integerp
 | 
					                                   (exwm-container . nil)
 | 
				
			||||||
                                 ;; (client . nil)
 | 
					                                   ;; (internal-border-width . nil) ; integerp
 | 
				
			||||||
                                 (fullscreen . nil)
 | 
					                                   (fullscreen . nil)
 | 
				
			||||||
                                 (buffer-predicate . nil))))
 | 
					                                   (buffer-predicate . nil)))
 | 
				
			||||||
 | 
					      ;; Restore the 'client' frame parameter (before `exwm-exit').
 | 
				
			||||||
 | 
					      (when exwm-workspace--client
 | 
				
			||||||
 | 
					        (set-frame-parameter f 'client exwm-workspace--client))))
 | 
				
			||||||
  ;; Restore the 'client' frame parameter (before `exwm-exit').
 | 
					  ;; Restore the 'client' frame parameter (before `exwm-exit').
 | 
				
			||||||
  (when exwm-workspace--client
 | 
					  (when exwm-workspace--client
 | 
				
			||||||
    (dolist (f exwm-workspace--list)
 | 
					    (when (and exwm-workspace--minibuffer-own-frame-p
 | 
				
			||||||
      (set-frame-parameter f 'client exwm-workspace--client))
 | 
					               (frame-live-p exwm-workspace--minibuffer))
 | 
				
			||||||
    (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))
 | 
				
			||||||
    (setq exwm-workspace--client nil)))
 | 
					    (setq exwm-workspace--client nil))
 | 
				
			||||||
 | 
					  ;; Don't let dead frames linger.
 | 
				
			||||||
 | 
					  (setq exwm-workspace--list nil))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(defun exwm-workspace--post-init ()
 | 
					(defun exwm-workspace--post-init ()
 | 
				
			||||||
  "The second stage in the initialization of the workspace module."
 | 
					  "The second stage in the initialization of the workspace module."
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										24
									
								
								exwm.el
									
										
									
									
									
								
							
							
						
						
									
										24
									
								
								exwm.el
									
										
									
									
									
								
							| 
						 | 
					@ -604,6 +604,13 @@
 | 
				
			||||||
               (eq selection xcb:Atom:WM_S0))
 | 
					               (eq selection xcb:Atom:WM_S0))
 | 
				
			||||||
      (exwm-exit))))
 | 
					      (exwm-exit))))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(defun exwm--on-delete-terminal (terminal)
 | 
				
			||||||
 | 
					  "Handle terminal being deleted without Emacs being killed.
 | 
				
			||||||
 | 
					This may happen when invoking `save-buffers-kill-terminal' within an emacsclient
 | 
				
			||||||
 | 
					session."
 | 
				
			||||||
 | 
					  (when (eq terminal exwm--terminal)
 | 
				
			||||||
 | 
					    (exwm-exit)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(defun exwm--init-icccm-ewmh ()
 | 
					(defun exwm--init-icccm-ewmh ()
 | 
				
			||||||
  "Initialize ICCCM/EWMH support."
 | 
					  "Initialize ICCCM/EWMH support."
 | 
				
			||||||
  (exwm--log)
 | 
					  (exwm--log)
 | 
				
			||||||
| 
						 | 
					@ -840,6 +847,7 @@ manager.  If t, replace it, if nil, abort and ask the user if `ask'."
 | 
				
			||||||
  (condition-case err
 | 
					  (condition-case err
 | 
				
			||||||
      (progn
 | 
					      (progn
 | 
				
			||||||
        (exwm-enable 'undo)               ;never initialize again
 | 
					        (exwm-enable 'undo)               ;never initialize again
 | 
				
			||||||
 | 
					        (setq exwm--terminal (frame-terminal frame))
 | 
				
			||||||
        (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
 | 
				
			||||||
| 
						 | 
					@ -862,6 +870,10 @@ manager.  If t, replace it, if nil, abort and ask the user if `ask'."
 | 
				
			||||||
        ;; 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)
 | 
				
			||||||
 | 
					        (advice-add 'save-buffers-kill-terminal
 | 
				
			||||||
 | 
					                    :before-while #'exwm--confirm-kill-terminal)
 | 
				
			||||||
 | 
					        ;; Clean up if the terminal is deleted.
 | 
				
			||||||
 | 
					        (add-hook 'delete-terminal-functions 'exwm--on-delete-terminal)
 | 
				
			||||||
        (exwm--lock)
 | 
					        (exwm--lock)
 | 
				
			||||||
        (exwm--init-icccm-ewmh)
 | 
					        (exwm--init-icccm-ewmh)
 | 
				
			||||||
        (exwm-layout--init)
 | 
					        (exwm-layout--init)
 | 
				
			||||||
| 
						 | 
					@ -898,7 +910,9 @@ manager.  If t, replace it, if nil, abort and ask the user if `ask'."
 | 
				
			||||||
  (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--terminal nil)
 | 
				
			||||||
 | 
					  (exwm--log "Exited"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
;;;###autoload
 | 
					;;;###autoload
 | 
				
			||||||
(defun exwm-enable (&optional undo)
 | 
					(defun exwm-enable (&optional undo)
 | 
				
			||||||
| 
						 | 
					@ -977,6 +991,14 @@ manager.  If t, replace it, if nil, abort and ask the user if `ask'."
 | 
				
			||||||
               ;; For other types, return the value as-is.
 | 
					               ;; For other types, return the value as-is.
 | 
				
			||||||
               (t result))))))
 | 
					               (t result))))))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(defun exwm--confirm-kill-terminal (&optional _)
 | 
				
			||||||
 | 
					  "Confirm before killing terminal."
 | 
				
			||||||
 | 
					  ;; This is invoked instead of `save-buffers-kill-emacs' (C-x C-c) on client
 | 
				
			||||||
 | 
					  ;; frames.
 | 
				
			||||||
 | 
					  (if (eq (frame-terminal) exwm--terminal)
 | 
				
			||||||
 | 
					      (exwm--confirm-kill-emacs "[EXWM] Kill terminal?")
 | 
				
			||||||
 | 
					    t))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(defun exwm--confirm-kill-emacs (prompt &optional force)
 | 
					(defun exwm--confirm-kill-emacs (prompt &optional force)
 | 
				
			||||||
  "Confirm before exiting Emacs."
 | 
					  "Confirm before exiting Emacs."
 | 
				
			||||||
  (exwm--log)
 | 
					  (exwm--log)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue