Observe connection status on deinitialization

* exwm-workspace.el (exwm-workspace--remove-frame-as-workspace):
Add optional argument quit.

* exwm-background.el (exwm-background--exit):
* exwm-input.el (exwm-input--exit):
* exwm-manage.el (exwm-manage--unmanage-window):
* exwm-systemtray.el (exwm-systemtray--exit):
* exwm-workspace.el (exwm-workspace--exit-minibuffer-frame)
(exwm-workspace--exit):
* exwm-xim.el (exwm-xim--exit): Observe connection status when
deinitializing in order to support deinitializing when the
connection breaks.
This commit is contained in:
Adrián Medraño Calvo 2023-06-09 00:00:00 +00:00
parent cff02333e2
commit 7318f857f2
7 changed files with 77 additions and 64 deletions

View file

@ -172,19 +172,17 @@ replace it.")
(defun exwm-background--init () (defun exwm-background--init ()
"Initialize background module." "Initialize background module."
(exwm--log) (exwm--log)
(add-hook 'enable-theme-functions 'exwm-background--update) (add-hook 'enable-theme-functions 'exwm-background--update)
(add-hook 'disable-theme-functions 'exwm-background--update) (add-hook 'disable-theme-functions 'exwm-background--update)
(exwm-background--update)) (exwm-background--update))
(defun exwm-background--exit () (defun exwm-background--exit ()
"Uninitialize the background module." "Uninitialize the background module."
(exwm--log) (exwm--log)
(remove-hook 'enable-theme-functions 'exwm-background--update) (remove-hook 'enable-theme-functions 'exwm-background--update)
(remove-hook 'disable-theme-functions 'exwm-background--update) (remove-hook 'disable-theme-functions 'exwm-background--update)
(when exwm-background--connection (when (and exwm-background--connection
(slot-value exwm-background--connection 'connected))
(xcb:disconnect exwm-background--connection)) (xcb:disconnect exwm-background--connection))
(setq exwm-background--pixmap nil (setq exwm-background--pixmap nil
exwm-background--connection nil exwm-background--connection nil

View file

@ -1215,7 +1215,7 @@ One use is to access the keymap bound to KEYS (as prefix keys) in char-mode."
(when exwm-input--update-focus-timer (when exwm-input--update-focus-timer
(cancel-timer exwm-input--update-focus-timer)) (cancel-timer exwm-input--update-focus-timer))
;; Make input focus working even without a WM. ;; Make input focus working even without a WM.
(when exwm--connection (when (slot-value exwm--connection 'connected)
(xcb:+request exwm--connection (xcb:+request exwm--connection
(make-instance 'xcb:SetInputFocus (make-instance 'xcb:SetInputFocus
:revert-to xcb:InputFocus:PointerRoot :revert-to xcb:InputFocus:PointerRoot

View file

@ -430,7 +430,9 @@ manager is shutting down."
(exwm-workspace--update-workareas) (exwm-workspace--update-workareas)
(dolist (f exwm-workspace--list) (dolist (f exwm-workspace--list)
(exwm-workspace--set-fullscreen f))) (exwm-workspace--set-fullscreen f)))
(when (buffer-live-p buffer) (when (and (buffer-live-p buffer)
;; Invoked from `exwm-manage--exit' upon disconnection.
(slot-value exwm--connection 'connected))
(with-current-buffer buffer (with-current-buffer buffer
;; Unmap the X window. ;; Unmap the X window.
(xcb:+request exwm--connection (xcb:+request exwm--connection
@ -512,8 +514,11 @@ manager is shutting down."
(defun exwm-manage--kill-buffer-query-function () (defun exwm-manage--kill-buffer-query-function ()
"Run in `kill-buffer-query-functions'." "Run in `kill-buffer-query-functions'."
(exwm--log "id=#x%x; buffer=%s" exwm--id (current-buffer)) (exwm--log "id=#x%x; buffer=%s" (or exwm--id 0) (current-buffer))
(catch 'return (catch 'return
(when (or (not exwm--connection)
(not (slot-value exwm--connection 'connected)))
(throw 'return t))
(when (or (not exwm--id) (when (or (not exwm--id)
(xcb:+request-checked+request-check exwm--connection (xcb:+request-checked+request-check exwm--connection
(make-instance 'xcb:ChangeWindowAttributes (make-instance 'xcb:ChangeWindowAttributes

View file

@ -652,19 +652,20 @@ indicate how to support actual transparency."
"Exit the systemtray module." "Exit the systemtray module."
(exwm--log) (exwm--log)
(when exwm-systemtray--connection (when exwm-systemtray--connection
;; Hide & reparent out the embedder before disconnection to prevent (when (slot-value exwm-systemtray--connection 'connected)
;; embedded icons from being reparented to an Emacs frame (which is the ;; Hide & reparent out the embedder before disconnection to prevent
;; parent of the embedder). ;; embedded icons from being reparented to an Emacs frame (which is the
(xcb:+request exwm-systemtray--connection ;; parent of the embedder).
(make-instance 'xcb:UnmapWindow (xcb:+request exwm-systemtray--connection
:window exwm-systemtray--embedder-window)) (make-instance 'xcb:UnmapWindow
(xcb:+request exwm-systemtray--connection :window exwm-systemtray--embedder-window))
(make-instance 'xcb:ReparentWindow (xcb:+request exwm-systemtray--connection
:window exwm-systemtray--embedder-window (make-instance 'xcb:ReparentWindow
:parent exwm--root :window exwm-systemtray--embedder-window
:x 0 :parent exwm--root
:y 0)) :x 0
(xcb:disconnect exwm-systemtray--connection) :y 0))
(xcb:disconnect exwm-systemtray--connection))
(setq exwm-systemtray--connection nil (setq exwm-systemtray--connection nil
exwm-systemtray--list nil exwm-systemtray--list nil
exwm-systemtray--selection-owner-window nil exwm-systemtray--selection-owner-window nil

View file

@ -1389,32 +1389,34 @@ Return nil if FRAME is the only workspace."
(unless (eq frame nextw) (unless (eq frame nextw)
nextw))) nextw)))
(defun exwm-workspace--remove-frame-as-workspace (frame) (defun exwm-workspace--remove-frame-as-workspace (frame &optional quit)
"Stop treating frame FRAME as a workspace." "Stop treating frame FRAME as a workspace."
;; TODO: restore all frame parameters (e.g. exwm-workspace, buffer-predicate, ;; TODO: restore all frame parameters (e.g. exwm-workspace, buffer-predicate,
;; etc) ;; etc)
(exwm--log "Removing frame `%s' as workspace" frame) (exwm--log "Removing frame `%s' as workspace" frame)
(let* ((next-frame (exwm-workspace--get-next-workspace frame)) (unless quit
(following-frames (cdr (memq frame exwm-workspace--list)))) (let* ((next-frame (exwm-workspace--get-next-workspace frame))
;; Need to remove the workspace from the list for the correct calculation of (following-frames (cdr (memq frame exwm-workspace--list))))
;; indexes below. ;; Need to remove the workspace from the list for the correct calculation of
(setq exwm-workspace--list (delete frame exwm-workspace--list)) ;; indexes below.
(unless next-frame (setq exwm-workspace--list (delete frame exwm-workspace--list))
;; The user managed to delete the last workspace, so create a new one. ;; Move the windows to the next workspace and switch to it.
(exwm--log "Last workspace deleted; create a new one") (unless next-frame
(let ((exwm-workspace--create-silently t)) ;; The user managed to delete the last workspace, so create a new one.
(setq next-frame (make-frame)))) (exwm--log "Last workspace deleted; create a new one")
(dolist (pair exwm--id-buffer-alist) (let ((exwm-workspace--create-silently t))
(let ((other-frame (buffer-local-value 'exwm--frame (cdr pair)))) (setq next-frame (make-frame))))
;; Move X windows to next-frame. (dolist (pair exwm--id-buffer-alist)
(when (eq other-frame frame) (let ((other-frame (buffer-local-value 'exwm--frame (cdr pair))))
(exwm-workspace-move-window next-frame (car pair))) ;; Move X windows to next-frame.
;; Update the _NET_WM_DESKTOP property of each following X window. (when (eq other-frame frame)
(when (memq other-frame following-frames) (exwm-workspace-move-window next-frame (car pair)))
(exwm-workspace--set-desktop (car pair))))) ;; Update the _NET_WM_DESKTOP property of each following X window.
;; If the current workspace is deleted, switch to next one. (when (memq other-frame following-frames)
(when (eq frame exwm-workspace--current) (exwm-workspace--set-desktop (car pair)))))
(exwm-workspace-switch next-frame))) ;; If the current workspace is deleted, switch to next one.
(when (eq frame exwm-workspace--current)
(exwm-workspace-switch next-frame))))
;; Reparent out the frame. ;; Reparent out the frame.
(let ((outer-id (frame-parameter frame 'exwm-outer-id))) (let ((outer-id (frame-parameter frame 'exwm-outer-id)))
(xcb:+request exwm--connection (xcb:+request exwm--connection
@ -1448,8 +1450,9 @@ Return nil if FRAME is the only workspace."
;; Update EWMH properties. ;; Update EWMH properties.
(exwm-workspace--update-ewmh-props) (exwm-workspace--update-ewmh-props)
;; Update switch history. ;; Update switch history.
(setq exwm-workspace--switch-history-outdated t) (unless quit
(run-hooks 'exwm-workspace-list-change-hook)) (setq exwm-workspace--switch-history-outdated t)
(run-hooks 'exwm-workspace-list-change-hook)))
(defun exwm-workspace--on-delete-frame (frame) (defun exwm-workspace--on-delete-frame (frame)
"Hook run upon `delete-frame' that tears down FRAME's configuration as a workspace." "Hook run upon `delete-frame' that tears down FRAME's configuration as a workspace."
@ -1623,7 +1626,9 @@ applied to all subsequently created X frames."
(setq default-minibuffer-frame nil) (setq default-minibuffer-frame nil)
(when (frame-live-p exwm-workspace--minibuffer) ; might be already dead (when (frame-live-p exwm-workspace--minibuffer) ; might be already dead
(let ((id (frame-parameter exwm-workspace--minibuffer 'exwm-outer-id))) (let ((id (frame-parameter exwm-workspace--minibuffer 'exwm-outer-id)))
(when (and exwm-workspace--minibuffer id) (when (and exwm-workspace--minibuffer id
;; Invoked from `exwm-manage--exit' upon disconnection.
(slot-value exwm--connection 'connected))
(xcb:+request exwm--connection (xcb:+request exwm--connection
(make-instance 'xcb:ReparentWindow (make-instance 'xcb:ReparentWindow
:window id :window id
@ -1708,19 +1713,21 @@ applied to all subsequently created X frames."
#'exwm-workspace--on-echo-area-clear)) #'exwm-workspace--on-echo-area-clear))
;; 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).
(setq exwm-workspace--current nil) (when (slot-value exwm--connection 'connected)
(dolist (i exwm-workspace--list) (dolist (i exwm-workspace--list)
(when (frame-live-p i) ; might be already dead (when (frame-live-p i) ; might be already dead
(exwm-workspace--remove-frame-as-workspace i) (exwm-workspace--remove-frame-as-workspace i 'quit)
(modify-frame-parameters i '((exwm-selected-window . nil) (modify-frame-parameters i '((exwm-selected-window . nil)
(exwm-urgency . nil) (exwm-urgency . nil)
(exwm-outer-id . nil) (exwm-outer-id . nil)
(exwm-id . nil) (exwm-id . nil)
(exwm-container . nil) (exwm-container . nil)
;; (internal-border-width . nil) ; integerp ;; (internal-border-width . nil) ; integerp
(fullscreen . nil) (fullscreen . nil)
(buffer-predicate . nil))))) (buffer-predicate . nil))))))
;; Don't let dead frames linger. ;; Don't let dead frames linger.
(setq exwm-workspace--current nil)
(setq exwm-workspace-current-index 0)
(setq exwm-workspace--list nil)) (setq exwm-workspace--list nil))
(defun exwm-workspace--post-init () (defun exwm-workspace--post-init ()

View file

@ -754,10 +754,12 @@ Such event would be received when the client window is destroyed."
;; Close IMS communication connections. ;; Close IMS communication connections.
(mapc (lambda (i) (mapc (lambda (i)
(when (vectorp i) (when (vectorp i)
(xcb:disconnect (elt i 0)))) (when (slot-value (elt i 0) 'connected)
(xcb:disconnect (elt i 0)))))
exwm-xim--server-client-plist) exwm-xim--server-client-plist)
;; Close the IMS connection. ;; Close the IMS connection.
(unless exwm-xim--conn (unless (and exwm-xim--conn
(slot-value exwm-xim--conn 'connected))
(cl-return-from exwm-xim--exit)) (cl-return-from exwm-xim--exit))
;; Remove exwm-xim from XIM_SERVERS. ;; Remove exwm-xim from XIM_SERVERS.
(let ((reply (xcb:+request-unchecked+reply exwm-xim--conn (let ((reply (xcb:+request-unchecked+reply exwm-xim--conn

10
exwm.el
View file

@ -907,12 +907,12 @@ manager. If t, replace it, if nil, abort and ask the user if `ask'."
(run-hooks 'exwm-exit-hook) (run-hooks 'exwm-exit-hook)
(setq confirm-kill-emacs nil) (setq confirm-kill-emacs nil)
;; Exit modules. ;; Exit modules.
(exwm-input--exit)
(exwm-manage--exit)
(exwm-workspace--exit)
(exwm-floating--exit)
(exwm-layout--exit)
(when exwm--connection (when exwm--connection
(exwm-input--exit)
(exwm-manage--exit)
(exwm-workspace--exit)
(exwm-floating--exit)
(exwm-layout--exit)
(xcb:flush exwm--connection) (xcb:flush exwm--connection)
(xcb:disconnect exwm--connection)) (xcb:disconnect exwm--connection))
(setq exwm--connection nil) (setq exwm--connection nil)