mirror of
https://github.com/emacs-exwm/exwm.git
synced 2024-11-23 21:17:59 +01:00
Fix workspace creation and deletion
* exwm-workspace.el (exwm-workspace-switch) (exwm-workspace-switch-create): Move support for creating missing workspaces from the former to the latter.. (exwm-workspace-switch-create-limit): New variable limiting the number of new workspaces allowed to create each time. * exwm-workspace.el (exwm-workspace--prompt-add) (exwm-workspace--prompt-delete): New commands for adding and deleting workspaces from the `read-from-minibuffer' prompt. (exwm-workspace--prompt-add-allowed) (exwm-workspace--prompt-delete-allowed): New variables telling whether the above two commands are allowed to run. (exwm-workspace--switch-map): Change "+" / "-" to use the new commands. * exwm-workspace.el (exwm-workspace-switch, exwm-workspace-swap) (exwm-workspace-move-window): Use this new feature. * exwm-workspace.el (exwm-workspace-add, exwm-workspace-delete): Since they are not used by the keymap any more, drop the use of idle timer. * exwm-workspace.el (exwm-workspace--create-silently): New variable indicating whether new workspaces should be created in the background. (exwm-workspace--add-frame-as-workspace): Support creating new workspaces in the background. * exwm-workspace.el (exwm-workspace--on-ConfigureNotify): Update workareas if it's not up to date. * exwm-randr.el (exwm-randr--refresh): Raise the standalone minibuffer when refreshed. * exwm-config.el (exwm-config-default): Add `exwm-workspace-number' and `exwm-workspace-switch-create'.
This commit is contained in:
parent
f48b8eafb0
commit
0c114d97b7
3 changed files with 96 additions and 43 deletions
|
@ -30,6 +30,8 @@
|
||||||
|
|
||||||
(defun exwm-config-default ()
|
(defun exwm-config-default ()
|
||||||
"Default configuration of EXWM."
|
"Default configuration of EXWM."
|
||||||
|
;; Set the initial workspace number.
|
||||||
|
(setq exwm-workspace-number 4)
|
||||||
;; Make class name the buffer name
|
;; Make class name the buffer name
|
||||||
(add-hook 'exwm-update-class-hook
|
(add-hook 'exwm-update-class-hook
|
||||||
(lambda ()
|
(lambda ()
|
||||||
|
@ -41,7 +43,9 @@
|
||||||
;; 's-N': Switch to certain workspace
|
;; 's-N': Switch to certain workspace
|
||||||
(dotimes (i 10)
|
(dotimes (i 10)
|
||||||
(exwm-input-set-key (kbd (format "s-%d" i))
|
(exwm-input-set-key (kbd (format "s-%d" i))
|
||||||
`(lambda () (interactive) (exwm-workspace-switch ,i))))
|
`(lambda ()
|
||||||
|
(interactive)
|
||||||
|
(exwm-workspace-switch-create ,i))))
|
||||||
;; 's-&': Launch application
|
;; 's-&': Launch application
|
||||||
(exwm-input-set-key (kbd "s-&")
|
(exwm-input-set-key (kbd "s-&")
|
||||||
(lambda (command)
|
(lambda (command)
|
||||||
|
|
|
@ -60,6 +60,7 @@
|
||||||
(declare-function exwm-workspace--count "exwm-workspace.el")
|
(declare-function exwm-workspace--count "exwm-workspace.el")
|
||||||
(declare-function exwm-workspace--set-fullscreen "exwm-workspace.el" (frame))
|
(declare-function exwm-workspace--set-fullscreen "exwm-workspace.el" (frame))
|
||||||
(declare-function exwm-workspace--update-workareas "exwm-workspace.el" ())
|
(declare-function exwm-workspace--update-workareas "exwm-workspace.el" ())
|
||||||
|
(declare-function exwm-workspace--show-minibuffer "exwm-workspace.el" ())
|
||||||
(declare-function exwm-workspace--set-desktop-geometry "exwm-workspace.el" ())
|
(declare-function exwm-workspace--set-desktop-geometry "exwm-workspace.el" ())
|
||||||
|
|
||||||
(defun exwm-randr--refresh ()
|
(defun exwm-randr--refresh ()
|
||||||
|
@ -111,6 +112,10 @@
|
||||||
;; Resize workspace.
|
;; Resize workspace.
|
||||||
(dolist (f exwm-workspace--list)
|
(dolist (f exwm-workspace--list)
|
||||||
(exwm-workspace--set-fullscreen f))
|
(exwm-workspace--set-fullscreen f))
|
||||||
|
;; Raise the minibuffer if it's active.
|
||||||
|
(when (and (active-minibuffer-window)
|
||||||
|
(exwm-workspace--minibuffer-own-frame-p))
|
||||||
|
(exwm-workspace--show-minibuffer))
|
||||||
;; Set _NET_DESKTOP_GEOMETRY.
|
;; Set _NET_DESKTOP_GEOMETRY.
|
||||||
(exwm-workspace--set-desktop-geometry)
|
(exwm-workspace--set-desktop-geometry)
|
||||||
(xcb:flush exwm--connection)
|
(xcb:flush exwm--connection)
|
||||||
|
|
|
@ -63,8 +63,8 @@ NIL if FRAME is not a workspace"
|
||||||
(defvar exwm-workspace--switch-map
|
(defvar exwm-workspace--switch-map
|
||||||
(let ((map (make-sparse-keymap)))
|
(let ((map (make-sparse-keymap)))
|
||||||
(define-key map [t] (lambda () (interactive)))
|
(define-key map [t] (lambda () (interactive)))
|
||||||
(define-key map "+" #'exwm-workspace-add)
|
(define-key map "+" #'exwm-workspace--prompt-add)
|
||||||
(define-key map "-" #'exwm-workspace-delete)
|
(define-key map "-" #'exwm-workspace--prompt-delete)
|
||||||
(dotimes (i 10)
|
(dotimes (i 10)
|
||||||
(define-key map (int-to-string i)
|
(define-key map (int-to-string i)
|
||||||
#'exwm-workspace--switch-map-nth-prefix))
|
#'exwm-workspace--switch-map-nth-prefix))
|
||||||
|
@ -105,6 +105,38 @@ NIL if FRAME is not a workspace"
|
||||||
:test #'equal)))
|
:test #'equal)))
|
||||||
(elt exwm-workspace--list workspace-idx)))
|
(elt exwm-workspace--list workspace-idx)))
|
||||||
|
|
||||||
|
(defvar exwm-workspace--prompt-add-allowed nil
|
||||||
|
"Non-nil to allow adding workspace from the prompt.")
|
||||||
|
(defvar exwm-workspace--prompt-delete-allowed nil
|
||||||
|
"Non-nil to allow deleting workspace from the prompt")
|
||||||
|
(defvar exwm-workspace--create-silently nil
|
||||||
|
"When non-nil workspaces are created in the background (not switched to).")
|
||||||
|
|
||||||
|
(defun exwm-workspace--prompt-add ()
|
||||||
|
"Add workspace from the prompt."
|
||||||
|
(interactive)
|
||||||
|
(when exwm-workspace--prompt-add-allowed
|
||||||
|
(let ((exwm-workspace--create-silently t))
|
||||||
|
(make-frame))
|
||||||
|
(exwm-workspace--update-switch-history)
|
||||||
|
(goto-history-element minibuffer-history-position)))
|
||||||
|
|
||||||
|
(defun exwm-workspace--prompt-delete ()
|
||||||
|
"Delete workspace from the prompt."
|
||||||
|
(interactive)
|
||||||
|
(when (and exwm-workspace--prompt-delete-allowed
|
||||||
|
(< 1 (exwm-workspace--count)))
|
||||||
|
(let ((frame (elt exwm-workspace--list (1- minibuffer-history-position))))
|
||||||
|
(if (eq frame exwm-workspace--current)
|
||||||
|
;; Abort the recursive minibuffer if deleting the current workspace.
|
||||||
|
(progn
|
||||||
|
(run-with-idle-timer 0 nil #'delete-frame frame)
|
||||||
|
(abort-recursive-edit))
|
||||||
|
(delete-frame frame)
|
||||||
|
(exwm-workspace--update-switch-history)
|
||||||
|
(goto-history-element (min minibuffer-history-position
|
||||||
|
(exwm-workspace--count)))))))
|
||||||
|
|
||||||
(defun exwm-workspace--update-switch-history ()
|
(defun exwm-workspace--update-switch-history ()
|
||||||
"Update the history for switching workspace to reflect the latest status."
|
"Update the history for switching workspace to reflect the latest status."
|
||||||
(when exwm-workspace--switch-history-outdated
|
(when exwm-workspace--switch-history-outdated
|
||||||
|
@ -390,25 +422,16 @@ PREFIX-DIGITS is a list of the digits introduced so far."
|
||||||
"Normal hook run after switching workspace.")
|
"Normal hook run after switching workspace.")
|
||||||
|
|
||||||
;;;###autoload
|
;;;###autoload
|
||||||
(cl-defun exwm-workspace-switch (frame-or-index &optional force)
|
(defun exwm-workspace-switch (frame-or-index &optional force)
|
||||||
"Switch to workspace INDEX. Query for FRAME-OR-INDEX if it's not specified.
|
"Switch to workspace INDEX. Query for FRAME-OR-INDEX if it's not specified.
|
||||||
|
|
||||||
The optional FORCE option is for internal use only."
|
The optional FORCE option is for internal use only."
|
||||||
(interactive
|
(interactive
|
||||||
(list
|
(list
|
||||||
(unless (and (eq major-mode 'exwm-mode) exwm--fullscreen) ;it's invisible
|
(unless (and (eq major-mode 'exwm-mode) exwm--fullscreen) ;it's invisible
|
||||||
(exwm-workspace--prompt-for-workspace "Workspace [+/-]: "))))
|
(let ((exwm-workspace--prompt-add-allowed t)
|
||||||
;; Try to create workspace(s) when INDEX is out-of-range.
|
(exwm-workspace--prompt-delete-allowed t))
|
||||||
(when (and (integerp frame-or-index)
|
(exwm-workspace--prompt-for-workspace "Switch to [+/-]: ")))))
|
||||||
(>= frame-or-index (exwm-workspace--count)))
|
|
||||||
(run-with-idle-timer 0 nil
|
|
||||||
(lambda (times)
|
|
||||||
(dotimes (_ times)
|
|
||||||
(make-frame)))
|
|
||||||
;; Create no more than 9 workspaces.
|
|
||||||
(min 9
|
|
||||||
(1+ (- frame-or-index (exwm-workspace--count)))))
|
|
||||||
(cl-return-from exwm-workspace-switch))
|
|
||||||
(let* ((frame (exwm-workspace--workspace-from-frame-or-index frame-or-index))
|
(let* ((frame (exwm-workspace--workspace-from-frame-or-index frame-or-index))
|
||||||
(index (exwm-workspace--position frame))
|
(index (exwm-workspace--position frame))
|
||||||
(workspace (frame-parameter frame 'exwm-workspace))
|
(workspace (frame-parameter frame 'exwm-workspace))
|
||||||
|
@ -469,6 +492,23 @@ The optional FORCE option is for internal use only."
|
||||||
(xcb:flush exwm--connection))
|
(xcb:flush exwm--connection))
|
||||||
(run-hooks 'exwm-workspace-switch-hook)))
|
(run-hooks 'exwm-workspace-switch-hook)))
|
||||||
|
|
||||||
|
(defvar exwm-workspace-switch-create-limit 10
|
||||||
|
"Number of workspaces `exwm-workspace-switch-create' allowed to create
|
||||||
|
each time.")
|
||||||
|
|
||||||
|
(defun exwm-workspace-switch-create (frame-or-index)
|
||||||
|
"Switch to workspace FRAME-OR-INDEX, creating it if it does not exist yet."
|
||||||
|
(interactive)
|
||||||
|
(if (or (framep frame-or-index)
|
||||||
|
(< frame-or-index (exwm-workspace--count)))
|
||||||
|
(exwm-workspace-switch frame-or-index)
|
||||||
|
(let ((exwm-workspace--create-silently t))
|
||||||
|
(dotimes (_ (min exwm-workspace-switch-create-limit
|
||||||
|
(1+ (- frame-or-index
|
||||||
|
(exwm-workspace--count)))))
|
||||||
|
(make-frame)))
|
||||||
|
(exwm-workspace-switch (car (last exwm-workspace--list)))))
|
||||||
|
|
||||||
(defvar exwm-workspace-list-change-hook nil
|
(defvar exwm-workspace-list-change-hook nil
|
||||||
"Normal hook run when the workspace list is changed (workspace added,
|
"Normal hook run when the workspace list is changed (workspace added,
|
||||||
deleted, moved, etc).")
|
deleted, moved, etc).")
|
||||||
|
@ -478,10 +518,14 @@ deleted, moved, etc).")
|
||||||
"Interchange position of WORKSPACE1 with that of WORKSPACE2."
|
"Interchange position of WORKSPACE1 with that of WORKSPACE2."
|
||||||
(interactive
|
(interactive
|
||||||
(unless (and (eq major-mode 'exwm-mode) exwm--fullscreen) ;it's invisible
|
(unless (and (eq major-mode 'exwm-mode) exwm--fullscreen) ;it's invisible
|
||||||
(let* ((w1 (exwm-workspace--prompt-for-workspace "Pick a workspace: "))
|
(let (w1 w2)
|
||||||
(w2 (exwm-workspace--prompt-for-workspace
|
(let ((exwm-workspace--prompt-add-allowed t)
|
||||||
|
(exwm-workspace--prompt-delete-allowed t))
|
||||||
|
(setq w1 (exwm-workspace--prompt-for-workspace
|
||||||
|
"Pick a workspace [+/-]: ")))
|
||||||
|
(setq w2 (exwm-workspace--prompt-for-workspace
|
||||||
(format "Swap workspace %d with: "
|
(format "Swap workspace %d with: "
|
||||||
(exwm-workspace--position w1)))))
|
(exwm-workspace--position w1))))
|
||||||
(list w1 w2))))
|
(list w1 w2))))
|
||||||
(let ((pos1 (exwm-workspace--position workspace1))
|
(let ((pos1 (exwm-workspace--position workspace1))
|
||||||
(pos2 (exwm-workspace--position workspace2)))
|
(pos2 (exwm-workspace--position workspace2)))
|
||||||
|
@ -544,31 +588,20 @@ before it."
|
||||||
|
|
||||||
INDEX must not exceed the current number of workspaces."
|
INDEX must not exceed the current number of workspaces."
|
||||||
(interactive)
|
(interactive)
|
||||||
(run-with-idle-timer
|
(if (and index
|
||||||
0 nil
|
;; No need to move if it's the last one.
|
||||||
(lambda (index)
|
(< index (exwm-workspace--count)))
|
||||||
(if (and index
|
(exwm-workspace-move (make-frame) index)
|
||||||
;; No need to move if it's the last one.
|
(make-frame)))
|
||||||
(< index (exwm-workspace--count)))
|
|
||||||
(exwm-workspace-move (make-frame) index)
|
|
||||||
(make-frame)))
|
|
||||||
index)
|
|
||||||
(when (active-minibuffer-window)
|
|
||||||
(abort-recursive-edit)))
|
|
||||||
|
|
||||||
;;;###autoload
|
;;;###autoload
|
||||||
(defun exwm-workspace-delete (&optional frame-or-index)
|
(defun exwm-workspace-delete (&optional frame-or-index)
|
||||||
"Delete the workspace FRAME-OR-INDEX."
|
"Delete the workspace FRAME-OR-INDEX."
|
||||||
(interactive)
|
(interactive)
|
||||||
(run-with-idle-timer 0 nil #'delete-frame
|
(delete-frame
|
||||||
;; We should not simply delete the selected frame
|
(if frame-or-index
|
||||||
;; since it can be e.g. a floating frame.
|
(exwm-workspace--workspace-from-frame-or-index frame-or-index)
|
||||||
(if frame-or-index
|
exwm-workspace--current)))
|
||||||
(exwm-workspace--workspace-from-frame-or-index
|
|
||||||
frame-or-index)
|
|
||||||
exwm-workspace--current))
|
|
||||||
(when (active-minibuffer-window)
|
|
||||||
(abort-recursive-edit)))
|
|
||||||
|
|
||||||
(defun exwm-workspace--on-focus-in ()
|
(defun exwm-workspace--on-focus-in ()
|
||||||
"Handle unexpected frame switch."
|
"Handle unexpected frame switch."
|
||||||
|
@ -601,7 +634,9 @@ INDEX must not exceed the current number of workspaces."
|
||||||
(defun exwm-workspace-move-window (frame-or-index &optional id)
|
(defun exwm-workspace-move-window (frame-or-index &optional id)
|
||||||
"Move window ID to workspace FRAME-OR-INDEX."
|
"Move window ID to workspace FRAME-OR-INDEX."
|
||||||
(interactive (list
|
(interactive (list
|
||||||
(exwm-workspace--prompt-for-workspace "Move to: ")))
|
(let ((exwm-workspace--prompt-add-allowed t)
|
||||||
|
(exwm-workspace--prompt-delete-allowed t))
|
||||||
|
(exwm-workspace--prompt-for-workspace "Move to [+/-]: "))))
|
||||||
(let ((frame (exwm-workspace--workspace-from-frame-or-index frame-or-index)))
|
(let ((frame (exwm-workspace--workspace-from-frame-or-index frame-or-index)))
|
||||||
(unless id (setq id (exwm--buffer->id (window-buffer))))
|
(unless id (setq id (exwm--buffer->id (window-buffer))))
|
||||||
(with-current-buffer (exwm--id->buffer id)
|
(with-current-buffer (exwm--id->buffer id)
|
||||||
|
@ -874,6 +909,9 @@ Please check `exwm-workspace--minibuffer-own-frame-p' first."
|
||||||
:window window
|
:window window
|
||||||
:value-mask xcb:ConfigWindow:Height
|
:value-mask xcb:ConfigWindow:Height
|
||||||
:height height)))
|
:height height)))
|
||||||
|
(when (/= (exwm-workspace--count) (length exwm-workspace--workareas))
|
||||||
|
;; There is a chance the workareas are not updated timely.
|
||||||
|
(exwm-workspace--update-workareas))
|
||||||
(setq workarea (elt exwm-workspace--workareas
|
(setq workarea (elt exwm-workspace--workareas
|
||||||
exwm-workspace-current-index)
|
exwm-workspace-current-index)
|
||||||
y (if (eq exwm-workspace-minibuffer-position 'top)
|
y (if (eq exwm-workspace-minibuffer-position 'top)
|
||||||
|
@ -1064,8 +1102,7 @@ Please check `exwm-workspace--minibuffer-own-frame-p' first."
|
||||||
(exwm--log "Frame `%s' is floating" frame))
|
(exwm--log "Frame `%s' is floating" frame))
|
||||||
(t
|
(t
|
||||||
(exwm--log "Adding frame `%s' as workspace" frame)
|
(exwm--log "Adding frame `%s' as workspace" frame)
|
||||||
(setq exwm-workspace--list (nconc exwm-workspace--list (list frame))
|
(setq exwm-workspace--list (nconc exwm-workspace--list (list frame)))
|
||||||
exwm-workspace--current frame)
|
|
||||||
(let ((outer-id (string-to-number (frame-parameter frame
|
(let ((outer-id (string-to-number (frame-parameter frame
|
||||||
'outer-window-id)))
|
'outer-window-id)))
|
||||||
(container (xcb:generate-id exwm--connection))
|
(container (xcb:generate-id exwm--connection))
|
||||||
|
@ -1093,6 +1130,11 @@ Please check `exwm-workspace--minibuffer-own-frame-p' first."
|
||||||
xcb:CW:EventMask)
|
xcb:CW:EventMask)
|
||||||
:override-redirect 1
|
:override-redirect 1
|
||||||
:event-mask xcb:EventMask:SubstructureRedirect))
|
:event-mask xcb:EventMask:SubstructureRedirect))
|
||||||
|
(xcb:+request exwm--connection
|
||||||
|
(make-instance 'xcb:ConfigureWindow
|
||||||
|
:window workspace
|
||||||
|
:value-mask xcb:ConfigWindow:StackMode
|
||||||
|
:stack-mode xcb:StackMode:Below))
|
||||||
(xcb:+request exwm--connection
|
(xcb:+request exwm--connection
|
||||||
(make-instance 'xcb:CreateWindow
|
(make-instance 'xcb:CreateWindow
|
||||||
:depth 0 :wid container :parent workspace
|
:depth 0 :wid container :parent workspace
|
||||||
|
@ -1129,7 +1171,9 @@ Please check `exwm-workspace--minibuffer-own-frame-p' first."
|
||||||
frame 'fullscreen 'fullboth)
|
frame 'fullscreen 'fullboth)
|
||||||
;; Update EWMH properties.
|
;; Update EWMH properties.
|
||||||
(exwm-workspace--update-ewmh-props)
|
(exwm-workspace--update-ewmh-props)
|
||||||
(exwm-workspace-switch frame t)
|
(if exwm-workspace--create-silently
|
||||||
|
(setq exwm-workspace--switch-history-outdated t)
|
||||||
|
(exwm-workspace-switch frame t))
|
||||||
(run-hooks 'exwm-workspace-list-change-hook))))
|
(run-hooks 'exwm-workspace-list-change-hook))))
|
||||||
|
|
||||||
(defun exwm-workspace--remove-frame-as-workspace (frame)
|
(defun exwm-workspace--remove-frame-as-workspace (frame)
|
||||||
|
|
Loading…
Reference in a new issue