mirror of
https://github.com/emacs-exwm/exwm.git
synced 2024-11-27 06:48:00 +01:00
Improve the handling of workspaces
* exwm-workspace.el (exwm-workspace--prompt-for-workspace): Add an optional argument to modify prompt. (exwm-workspace-switch, exwm-workspace-swap) (exwm-workspace-move, exwm-workspace-move-window): Use it. * exwm-workspace.el (exwm-workspace-number): Re-introduce the variable (now it stands for the initial workspace number). (exwm-workspace--init): Create remaining initial workspaces. * exwm-workspace.el (exwm-workspace-add, exwm-workspace-delete): New commands for adding/deleting workspaces. (exwm-workspace--switch-map): Add "+"/"-" to increase/descrease workspace number. * exwm-workspace.el (exwm-workspace-switch): Automatically add missing workspaces. * exwm.el (exwm--on-ClientMessage): Support _NET_NUMBER_OF_DESKTOPS client message for adjusting workspace number.
This commit is contained in:
parent
73d890aad4
commit
622618ac6e
2 changed files with 76 additions and 10 deletions
|
@ -27,6 +27,7 @@
|
||||||
|
|
||||||
(require 'exwm-core)
|
(require 'exwm-core)
|
||||||
|
|
||||||
|
(defvar exwm-workspace-number 1 "Initial number of workspaces.")
|
||||||
(defvar exwm-workspace--list nil "List of all workspaces (Emacs frames).")
|
(defvar exwm-workspace--list nil "List of all workspaces (Emacs frames).")
|
||||||
(defvar exwm-workspace--current nil "Current active workspace.")
|
(defvar exwm-workspace--current nil "Current active workspace.")
|
||||||
(defvar exwm-workspace-current-index 0 "Index of current active workspace.")
|
(defvar exwm-workspace-current-index 0 "Index of current active workspace.")
|
||||||
|
@ -62,6 +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-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))
|
||||||
|
@ -88,13 +91,14 @@ NIL if FRAME is not a workspace"
|
||||||
(defvar exwm-workspace--switch-history-outdated nil
|
(defvar exwm-workspace--switch-history-outdated nil
|
||||||
"Non-nil to indicate `exwm-workspace--switch-history' is outdated.")
|
"Non-nil to indicate `exwm-workspace--switch-history' is outdated.")
|
||||||
|
|
||||||
(defun exwm-workspace--prompt-for-workspace ()
|
(defun exwm-workspace--prompt-for-workspace (&optional prompt)
|
||||||
"Prompt for a workspace, returning the workspace frame."
|
"Prompt for a workspace, returning the workspace frame."
|
||||||
(exwm-workspace--update-switch-history)
|
(exwm-workspace--update-switch-history)
|
||||||
(let* ((current-idx (exwm-workspace--position exwm-workspace--current))
|
(let* ((current-idx (exwm-workspace--position exwm-workspace--current))
|
||||||
(history-add-new-input nil) ;prevent modifying history
|
(history-add-new-input nil) ;prevent modifying history
|
||||||
(history-idx (read-from-minibuffer
|
(history-idx (read-from-minibuffer
|
||||||
"Workspace: " (elt exwm-workspace--switch-history current-idx)
|
(or prompt "Workspace: ")
|
||||||
|
(elt exwm-workspace--switch-history current-idx)
|
||||||
exwm-workspace--switch-map nil
|
exwm-workspace--switch-map nil
|
||||||
`(exwm-workspace--switch-history . ,(1+ current-idx))))
|
`(exwm-workspace--switch-history . ,(1+ current-idx))))
|
||||||
(workspace-idx (cl-position history-idx exwm-workspace--switch-history
|
(workspace-idx (cl-position history-idx exwm-workspace--switch-history
|
||||||
|
@ -359,14 +363,25 @@ 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
|
||||||
(defun exwm-workspace-switch (frame-or-index &optional force)
|
(cl-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))))
|
(exwm-workspace--prompt-for-workspace "Workspace [+/-]: "))))
|
||||||
|
;; Try to create workspace(s) when INDEX is out-of-range.
|
||||||
|
(when (and (integerp frame-or-index)
|
||||||
|
(>= 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))
|
||||||
|
@ -440,9 +455,11 @@ The optional FORCE option is for internal use only."
|
||||||
"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
|
||||||
(list
|
(let* ((w1 (exwm-workspace--prompt-for-workspace "Pick a workspace: "))
|
||||||
(exwm-workspace--prompt-for-workspace)
|
(w2 (exwm-workspace--prompt-for-workspace
|
||||||
(exwm-workspace--prompt-for-workspace))))
|
(format "Swap workspace %d with: "
|
||||||
|
(exwm-workspace--position w1)))))
|
||||||
|
(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)))
|
||||||
(if (or (not pos1) (not pos2) (= pos1 pos2))
|
(if (or (not pos1) (not pos2) (= pos1 pos2))
|
||||||
|
@ -469,8 +486,8 @@ before it."
|
||||||
(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
|
||||||
(list exwm-workspace--current
|
(list exwm-workspace--current
|
||||||
(exwm-workspace--position (exwm-workspace--prompt-for-workspace)))))
|
(exwm-workspace--position
|
||||||
(let ((pos (exwm-workspace--position workspace)))
|
(exwm-workspace--prompt-for-workspace "Move workspace to: ")))))
|
||||||
(let ((pos (exwm-workspace--position workspace))
|
(let ((pos (exwm-workspace--position workspace))
|
||||||
flag start end index)
|
flag start end index)
|
||||||
(if (= nth pos)
|
(if (= nth pos)
|
||||||
|
@ -496,6 +513,38 @@ before it."
|
||||||
(selected-window))
|
(selected-window))
|
||||||
(exwm-workspace-switch exwm-workspace--current t)))))
|
(exwm-workspace-switch exwm-workspace--current t)))))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun exwm-workspace-add (&optional index)
|
||||||
|
"Add a workspace as the INDEX-th workspace, or the last one if INDEX is nil.
|
||||||
|
|
||||||
|
INDEX must not exceed the current number of workspaces."
|
||||||
|
(interactive)
|
||||||
|
(run-with-idle-timer
|
||||||
|
0 nil
|
||||||
|
(lambda (index)
|
||||||
|
(if (and index
|
||||||
|
;; No need to move if it's the last one.
|
||||||
|
(< index (exwm-workspace--count)))
|
||||||
|
(exwm-workspace-move (make-frame) index)
|
||||||
|
(make-frame)))
|
||||||
|
index)
|
||||||
|
(when (active-minibuffer-window)
|
||||||
|
(abort-recursive-edit)))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun exwm-workspace-delete (&optional frame-or-index)
|
||||||
|
"Delete the workspace FRAME-OR-INDEX."
|
||||||
|
(interactive)
|
||||||
|
(run-with-idle-timer 0 nil #'delete-frame
|
||||||
|
;; We should not simply delete the selected frame
|
||||||
|
;; since it can be e.g. a floating frame.
|
||||||
|
(if frame-or-index
|
||||||
|
(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."
|
||||||
;; `focus-in-hook' is run by `handle-switch-frame'.
|
;; `focus-in-hook' is run by `handle-switch-frame'.
|
||||||
|
@ -526,7 +575,8 @@ before it."
|
||||||
;;;###autoload
|
;;;###autoload
|
||||||
(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 (exwm-workspace--prompt-for-workspace)))
|
(interactive (list
|
||||||
|
(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)
|
||||||
|
@ -1178,6 +1228,11 @@ applied to all subsequently created X frames."
|
||||||
;; Prevent `other-buffer' from selecting already displayed EXWM buffers.
|
;; Prevent `other-buffer' from selecting already displayed EXWM buffers.
|
||||||
(modify-all-frames-parameters
|
(modify-all-frames-parameters
|
||||||
'((buffer-predicate . exwm-layout--other-buffer-predicate)))
|
'((buffer-predicate . exwm-layout--other-buffer-predicate)))
|
||||||
|
;; Create remaining workspaces.
|
||||||
|
(dotimes (_ (- exwm-workspace-number (length initial-workspaces)))
|
||||||
|
(nconc initial-workspaces (list (make-frame '((window-system . x)
|
||||||
|
(internal-border-width . 0)
|
||||||
|
(client . nil))))))
|
||||||
;; Configure workspaces
|
;; Configure workspaces
|
||||||
(dolist (i initial-workspaces)
|
(dolist (i initial-workspaces)
|
||||||
(exwm-workspace--add-frame-as-workspace i)))
|
(exwm-workspace--add-frame-as-workspace i)))
|
||||||
|
|
11
exwm.el
11
exwm.el
|
@ -325,6 +325,17 @@
|
||||||
id (slot-value obj 'window)
|
id (slot-value obj 'window)
|
||||||
data (slot-value (slot-value obj 'data) 'data32))
|
data (slot-value (slot-value obj 'data) 'data32))
|
||||||
(cond
|
(cond
|
||||||
|
;; _NET_NUMBER_OF_DESKTOPS.
|
||||||
|
((= type xcb:Atom:_NET_NUMBER_OF_DESKTOPS)
|
||||||
|
(let ((current (exwm-workspace--count))
|
||||||
|
(requested (elt data 0)))
|
||||||
|
;; Only allow increasing/decreasing the workspace number by 1.
|
||||||
|
(cond
|
||||||
|
((< current requested)
|
||||||
|
(make-frame))
|
||||||
|
((and (> current requested)
|
||||||
|
(> current 1))
|
||||||
|
(delete-frame (car (last exwm-workspace--list)))))))
|
||||||
;; _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)))
|
||||||
|
|
Loading…
Reference in a new issue