branch: externals/exwm
commit 5c89ff82dbc6e839908e8f4042c29ec1d2d7a3ec
Author: Steven Allen <[email protected]>
Commit: Steven Allen <[email protected]>

    Refuse to delete active workspaces when there all are active
    
    Deleting a workspace in this case will attempt to "steal" a workspace
    from another monitor. This will fail and we'll end up re-creating a
    workspace, causing us to juggle workspaces around.
    
    An alternative would be to ALLOW ourselves to delete the workspace in
    this case, but refuse to steal an active workspace to replace it AND
    refuse to re-create it. But, IMO, the user likely wants one workspace
    per monitor and would rather not delete the last workspace on a monitor
    when there are none available to replace it.
    
    * exwm-workspace.el (exwm-workspace-delete): Refuse to delete thej
    current workspace if we don't have any to replace it.
    (exwm-workspace--get-next-workspace): Make it possible to get the next
    workspace, including active workspaces.
---
 exwm-workspace.el | 41 +++++++++++++++++++++++------------------
 1 file changed, 23 insertions(+), 18 deletions(-)

diff --git a/exwm-workspace.el b/exwm-workspace.el
index 953d68c482..cc9c0625ee 100644
--- a/exwm-workspace.el
+++ b/exwm-workspace.el
@@ -797,17 +797,20 @@ INDEX must not exceed the current number of workspaces."
   "Delete the workspace FRAME-OR-INDEX."
   (interactive)
   (exwm--log "%s" frame-or-index)
-  (when (< 1 (exwm-workspace--count))
-    (let ((frame (if frame-or-index
-                     (exwm-workspace--workspace-from-frame-or-index
-                      frame-or-index)
-                   exwm-workspace--current)))
-      ;; Transfer over any surrogate minibuffers before trying to delete the 
workspace.
-      (let ((minibuf (minibuffer-window frame))
-            (newminibuf (minibuffer-window (exwm-workspace--get-next-workspace 
frame))))
-        (dolist (f (filtered-frame-list (lambda (f) (eq (frame-parameter f 
'minibuffer) minibuf))))
-          (set-frame-parameter f 'minibuffer newminibuf)))
-      (delete-frame frame))))
+  (if-let* ((frame (if frame-or-index
+                       (exwm-workspace--workspace-from-frame-or-index
+                        frame-or-index)
+                     exwm-workspace--current))
+            (next-frame (exwm-workspace--get-next-workspace
+                         frame (not (exwm-workspace--active-p frame)))))
+      (progn
+        ;; Transfer over any surrogate minibuffers before trying to delete the 
workspace.
+        (let ((minibuf (minibuffer-window frame))
+              (newminibuf (minibuffer-window next-frame)))
+          (dolist (f (filtered-frame-list (lambda (f) (eq (frame-parameter f 
'minibuffer) minibuf))))
+            (set-frame-parameter f 'minibuffer newminibuf)))
+        (delete-frame frame))
+    (error "All other workspaces are active")))
 
 (defun exwm-workspace--set-desktop (id)
   "Set _NET_WM_DESKTOP for X window ID."
@@ -1375,22 +1378,24 @@ ALIST is an action alist, as accepted by function 
`display-buffer'."
                frame exwm-workspace-current-index original-index))
     (run-hooks 'exwm-workspace-list-change-hook)))
 
-(defun exwm-workspace--get-next-workspace (frame)
+(defun exwm-workspace--get-next-workspace (frame &optional allow-active)
   "Return the next workspace if workspace FRAME were removed.
-Return nil there are no other worksapces and/or all other workspaces
-are currently visible on other monitors."
+Return nil there are no other worksapces or ALLOW-ACTIVE is non-nil and
+all other workspaces are currently visible on other monitors."
   (let* ((index (exwm-workspace--position frame))
          (count (exwm-workspace--count)))
     (or
      (cl-loop for i from (1+ index) below count
               for nextw = (elt exwm-workspace--list i)
-              unless (or (eq frame nextw)
-                         (exwm-workspace--active-p nextw))
+              when (and (not (eq frame nextw))
+                        (or allow-active
+                            (exwm-workspace--active-p nextw)))
               return nextw)
      (cl-loop for i from (1- index) downto 0
               for nextw = (elt exwm-workspace--list i)
-              unless (or (eq frame nextw)
-                         (exwm-workspace--active-p nextw))
+              when (and (not (eq frame nextw))
+                        (or allow-active
+                            (exwm-workspace--active-p nextw)))
               return nextw))))
 
 (defun exwm-workspace--remove-frame-as-workspace (frame &optional quit)

Reply via email to