Fix 'Attempt to delete a surrogate minibuffer frame' error

* exwm-workspace.el (exwm-workspace--get-remove-frame-next-workspace):
New function automatically moves X window elsewhere before removing a
workspace; also returns the destination workspace.
(exwm-workspace--prompt-delete, exwm-workspace-delete)
(exwm-workspace--remove-frame-as-workspace): Use it.
* exwm.el (exwm--on-ClientMessage): Use it.
This commit is contained in:
Chris Feng 2019-06-30 00:00:00 +00:00
parent 605b0a9575
commit fe8ee3c578
2 changed files with 27 additions and 13 deletions

View file

@ -240,6 +240,7 @@ NIL if FRAME is not a workspace"
(when (and exwm-workspace--prompt-delete-allowed (when (and exwm-workspace--prompt-delete-allowed
(< 1 (exwm-workspace--count))) (< 1 (exwm-workspace--count)))
(let ((frame (elt exwm-workspace--list (1- minibuffer-history-position)))) (let ((frame (elt exwm-workspace--list (1- minibuffer-history-position))))
(exwm-workspace--get-remove-frame-next-workspace frame)
(if (eq frame exwm-workspace--current) (if (eq frame exwm-workspace--current)
;; Abort the recursive minibuffer if deleting the current workspace. ;; Abort the recursive minibuffer if deleting the current workspace.
(progn (progn
@ -778,10 +779,12 @@ INDEX must not exceed the current number of workspaces."
(interactive) (interactive)
(exwm--log "%s" frame-or-index) (exwm--log "%s" frame-or-index)
(when (< 1 (exwm-workspace--count)) (when (< 1 (exwm-workspace--count))
(delete-frame (let ((frame (if frame-or-index
(if frame-or-index (exwm-workspace--workspace-from-frame-or-index
(exwm-workspace--workspace-from-frame-or-index frame-or-index) frame-or-index)
exwm-workspace--current)))) exwm-workspace--current)))
(exwm-workspace--get-remove-frame-next-workspace frame)
(delete-frame frame))))
(defun exwm-workspace--set-desktop (id) (defun exwm-workspace--set-desktop (id)
"Set _NET_WM_DESKTOP for X window ID." "Set _NET_WM_DESKTOP for X window ID."
@ -1330,23 +1333,32 @@ Please check `exwm-workspace--minibuffer-own-frame-p' first."
(exwm-workspace-switch frame t) (exwm-workspace-switch frame t)
(run-hooks 'exwm-workspace-list-change-hook))) (run-hooks 'exwm-workspace-list-change-hook)))
(defun exwm-workspace--get-remove-frame-next-workspace (frame)
"Return the next workspace if workspace FRAME is removed.
All X windows currently on workspace FRAME will be automatically moved to
the next workspace."
(let* ((index (exwm-workspace--position frame))
(lastp (= index (1- (exwm-workspace--count))))
(nextw (elt exwm-workspace--list (+ index (if lastp -1 +1)))))
;; Clients need to be moved to some other workspace before this being
;; removed.
(dolist (pair exwm--id-buffer-alist)
(with-current-buffer (cdr pair)
(when (eq exwm--frame frame)
(exwm-workspace-move-window nextw exwm--id))))
nextw))
(defun exwm-workspace--remove-frame-as-workspace (frame) (defun exwm-workspace--remove-frame-as-workspace (frame)
"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* ((index (exwm-workspace--position frame)) (let* ((index (exwm-workspace--position frame))
(lastp (= index (1- (exwm-workspace--count)))) (nextw (exwm-workspace--get-remove-frame-next-workspace frame)))
(nextw (elt exwm-workspace--list (+ index (if lastp -1 +1)))))
;; Need to remove the workspace from the list in order for ;; Need to remove the workspace from the list in order for
;; the correct calculation of indexes. ;; the correct calculation of indexes.
(setq exwm-workspace--list (delete frame exwm-workspace--list)) (setq exwm-workspace--list (delete frame exwm-workspace--list))
;; Clients need to be moved to some other workspace before this is being
;; removed.
(dolist (pair exwm--id-buffer-alist)
(with-current-buffer (cdr pair)
(when (eq exwm--frame frame)
(exwm-workspace-move-window nextw exwm--id))))
;; Update the _NET_WM_DESKTOP property of each X window affected. ;; Update the _NET_WM_DESKTOP property of each X window affected.
(dolist (pair exwm--id-buffer-alist) (dolist (pair exwm--id-buffer-alist)
(when (<= (1- index) (when (<= (1- index)

View file

@ -432,7 +432,9 @@
(make-frame)) (make-frame))
((and (> current requested) ((and (> current requested)
(> current 1)) (> current 1))
(delete-frame (car (last exwm-workspace--list))))))) (let ((frame (car (last exwm-workspace--list))))
(exwm-workspace--get-remove-frame-next-workspace frame)
(delete-frame frame))))))
;; _NET_CURRENT_DESKTOP. ;; _NET_CURRENT_DESKTOP.
((= type xcb:Atom:_NET_CURRENT_DESKTOP) ((= type xcb:Atom:_NET_CURRENT_DESKTOP)
(exwm-workspace-switch (elt data 0))) (exwm-workspace-switch (elt data 0)))