diff --git a/exwm-cm.el b/exwm-cm.el index 77dd277..ff556fb 100644 --- a/exwm-cm.el +++ b/exwm-cm.el @@ -21,7 +21,7 @@ ;;; Commentary: -;; This module is obsolete since EXWM now supports third-porty compositors. +;; This module is obsolete since EXWM now supports third-party compositors. ;;; Code: diff --git a/exwm-core.el b/exwm-core.el index 4e9a389..68ec53b 100644 --- a/exwm-core.el +++ b/exwm-core.el @@ -35,6 +35,32 @@ (eval-and-compile (defvar exwm-debug-on nil "Non-nil to turn on debug for EXWM.")) +(defvar exwm--connection nil "X connection.") + +(defvar exwm--guide-window nil + "An X window separating workspaces and X windows.") + +(defvar exwm--id-buffer-alist nil "Alist of ( . ).") + +(defvar exwm--root nil "Root window.") + +(defvar exwm-input--global-prefix-keys) +(defvar exwm-input--simulation-prefix-keys) +(defvar exwm-input-line-mode-passthrough) +(defvar exwm-input-prefix-keys) +(declare-function exwm-input--fake-key "exwm-input.el" (event)) +(declare-function exwm-input--on-KeyPress-line-mode "exwm-input.el" + (key-press raw-data)) +(declare-function exwm-floating-hide "exwm-floating.el") +(declare-function exwm-floating-toggle-floating "exwm-floating.el") +(declare-function exwm-input-release-keyboard "exwm-input.el") +(declare-function exwm-input-send-next-key "exwm-input.el" (times)) +(declare-function exwm-layout-set-fullscreen "exwm-layout.el" (&optional id)) +(declare-function exwm-layout-toggle-mode-line "exwm-layout.el") +(declare-function exwm-manage--kill-buffer-query-function "exwm-manage.el") +(declare-function exwm-workspace-move-window "exwm-workspace.el" + (frame-or-index &optional id)) + (defmacro exwm--log (format-string &rest args) "Print debug message." (when exwm-debug-on @@ -43,12 +69,6 @@ (defmacro exwm--debug (&rest forms) (when exwm-debug-on `(progn ,@forms))) -(defvar exwm--connection nil "X connection.") -(defvar exwm--root nil "Root window.") -(defvar exwm--id-buffer-alist nil "Alist of ( . ).") -(defvar exwm--guide-window nil - "An X window separating workspaces and X windows.") - (defsubst exwm--id->buffer (id) "X window ID => Emacs buffer." (cdr (assoc id exwm--id-buffer-alist))) @@ -108,15 +128,6 @@ least SECS seconds later." xcb:EventMask:EnterWindow 0)) "Event mask set on all managed windows.") -(defvar exwm-input-line-mode-passthrough) -(defvar exwm-input--global-prefix-keys) -(defvar exwm-input-prefix-keys) -(defvar exwm-input--simulation-prefix-keys) - -(declare-function exwm-input--fake-key "exwm-input.el" (event)) -(declare-function exwm-input--on-KeyPress-line-mode "exwm-input.el" - (key-press raw-data)) - ;; Internal variables (defvar-local exwm--id nil) ;window ID (defvar-local exwm--frame nil) ;workspace frame @@ -154,15 +165,6 @@ least SECS seconds later." ;; _MOTIF_WM_HINTS (defvar-local exwm--mwm-hints-decorations t) -(declare-function exwm-floating-hide "exwm-floating.el") -(declare-function exwm-floating-toggle-floating "exwm-floating.el") -(declare-function exwm-input-release-keyboard "exwm-input.el") -(declare-function exwm-input-send-next-key "exwm-input.el" (times)) -(declare-function exwm-layout-set-fullscreen "exwm-layout.el" (&optional id)) -(declare-function exwm-layout-toggle-mode-line "exwm-layout.el") -(declare-function exwm-workspace-move-window "exwm-workspace.el" - (frame-or-index &optional id)) - (defvar exwm-mode-map (let ((map (make-sparse-keymap))) (define-key map "\C-c\C-f" #'exwm-layout-set-fullscreen) @@ -264,8 +266,6 @@ least SECS seconds later." (/= ,i exwm-workspace-current-index)]) (number-sequence 0 (1- (exwm-workspace--count)))))))) -(declare-function exwm-manage--kill-buffer-query-function "exwm-manage.el") - (define-derived-mode exwm-mode nil "EXWM" "Major mode for managing X windows. diff --git a/exwm-floating.el b/exwm-floating.el index b0afc1d..8cd0491 100644 --- a/exwm-floating.el +++ b/exwm-floating.el @@ -29,22 +29,35 @@ (require 'xcb-cursor) (require 'exwm-core) -(defvar exwm-floating-border-width 1 "Border width of the floating window.") -(defvar exwm-floating-border-color "navy" - "Border color of the floating window.") -(defvar exwm-floating--border-pixel nil - "Border pixel drawn around floating X windows.") +(defgroup exwm-floating nil + "Floating." + :version "25.3" + :group 'exwm) + +(defcustom exwm-floating-setup-hook nil + "Normal hook run when an X window has been made floating, in the +context of the corresponding buffer." + :type 'hook) + +(defcustom exwm-floating-exit-hook nil + "Normal hook run when an X window has exited floating state, in the +context of the corresponding buffer." + :type 'hook) + +(defcustom exwm-floating-border-color "navy" + "Border color of floating windows." + :type 'color) + +(defcustom exwm-floating-border-width 1 + "Border width of floating windows." + :type 'integer) + (defvar exwm-floating--border-colormap nil "Colormap used by the border pixel. This is also used by X window containers.") - -(defvar exwm-floating-setup-hook nil - "Normal hook run when an X window has been made floating, in the -context of the corresponding buffer.") -(defvar exwm-floating-exit-hook nil - "Normal hook run when an X window has exited floating state, in the -context of the corresponding buffer.") +(defvar exwm-floating--border-pixel nil + "Border pixel drawn around floating X windows.") ;; Cursors for moving/resizing a window (defvar exwm-floating--cursor-move nil) @@ -57,6 +70,18 @@ context of the corresponding buffer.") (defvar exwm-floating--cursor-bottom-left nil) (defvar exwm-floating--cursor-left nil) +(defvar exwm-floating--moveresize-calculate nil + "Calculate move/resize parameters [buffer event-mask x y width height].") + +(defvar exwm-workspace--current) +(defvar exwm-workspace--workareas) +(declare-function exwm-layout--hide "exwm-layout.el" (id)) +(declare-function exwm-layout--iconic-state-p "exwm-layout.el" (&optional id)) +(declare-function exwm-layout--refresh "exwm-layout.el" ()) +(declare-function exwm-layout--show "exwm-layout.el" (id &optional window)) +(declare-function exwm-workspace--minibuffer-own-frame-p "exwm-workspace.el") +(declare-function exwm-workspace--position "exwm-workspace.el" (frame)) + (defun exwm-floating--set-allowed-actions (id tilling) "Set _NET_WM_ALLOWED_ACTIONS." (xcb:+request exwm--connection @@ -74,16 +99,6 @@ context of the corresponding buffer.") xcb:Atom:_NET_WM_ACTION_CHANGE_DESKTOP xcb:Atom:_NET_WM_ACTION_CLOSE))))) -(defvar exwm-workspace--current) -(defvar exwm-workspace--workareas) - -(declare-function exwm-layout--refresh "exwm-layout.el" ()) -(declare-function exwm-layout--show "exwm-layout.el" (id &optional window)) -(declare-function exwm-layout--hide "exwm-layout.el" (id)) -(declare-function exwm-layout--iconic-state-p "exwm-layout.el" (&optional id)) -(declare-function exwm-workspace--minibuffer-own-frame-p "exwm-workspace.el") -(declare-function exwm-workspace--position "exwm-workspace.el" (frame)) - (defun exwm-floating--set-floating (id) "Make window ID floating." (let ((window (get-buffer-window (exwm--id->buffer id)))) @@ -331,16 +346,16 @@ context of the corresponding buffer.") (run-hooks 'exwm-floating-exit-hook))) ;;;###autoload -(defun exwm-floating-toggle-floating () +(cl-defun exwm-floating-toggle-floating () "Toggle the current window between floating and non-floating states." (interactive) + (unless (derived-mode-p 'exwm-mode) + (cl-return-from 'exwm-floating-toggle-floating)) (with-current-buffer (window-buffer) (if exwm--floating-frame (exwm-floating--unset-floating exwm--id) (exwm-floating--set-floating exwm--id)))) -(declare-function exwm-layout--set-state "exwm-layout.el" (id state)) - ;;;###autoload (defun exwm-floating-hide () "Hide the current floating X window (which would show again when selected)." @@ -350,14 +365,6 @@ context of the corresponding buffer.") (exwm-layout--hide exwm--id) (select-frame-set-input-focus exwm-workspace--current))) -(define-obsolete-function-alias 'exwm-floating-hide-mode-line - 'exwm-layout-hide-mode-line "25.1" "Hide mode-line of a floating frame.") -(define-obsolete-function-alias 'exwm-floating-show-mode-line - 'exwm-layout-show-mode-line "25.1" "Show mode-line of a floating frame.") - -(defvar exwm-floating--moveresize-calculate nil - "Calculate move/resize parameters [buffer event-mask x y width height].") - (defun exwm-floating--start-moveresize (id &optional type) "Start move/resize." (let ((buffer-or-id (or (exwm--id->buffer id) id)) diff --git a/exwm-input.el b/exwm-input.el index eaddf6b..e536a14 100644 --- a/exwm-input.el +++ b/exwm-input.el @@ -38,32 +38,119 @@ (require 'xcb-keysyms) (require 'exwm-core) -(defvar exwm-input-move-event 's-down-mouse-1 - "Emacs event to start moving a window.") -(defvar exwm-input-resize-event 's-down-mouse-3 - "Emacs event to start resizing a window.") +(defgroup exwm-input nil + "Input." + :version "25.3" + :group 'exwm) -(defvar exwm-input--timestamp-window nil) -(defvar exwm-input--timestamp-atom nil) -(defvar exwm-input--timestamp-callback nil) +(defcustom exwm-input-prefix-keys + '(?\C-c ?\C-x ?\C-u ?\C-h ?\M-x ?\M-` ?\M-& ?\M-:) + "List of prefix keys EXWM should forward to Emacs when in line-mode." + :type '(repeat key-sequence) + :get (lambda (symbol) + (mapcar #'vector (default-value symbol))) + :set (lambda (symbol value) + (set symbol (mapcar (lambda (i) + (if (sequencep i) + (aref i 0) + i)) + value)))) -(defvar exwm-workspace--current) -(defvar exwm-workspace--switch-history-outdated) -(defvar exwm-workspace-current-index) -(defvar exwm-workspace--minibuffer) -(defvar exwm-workspace--list) +(defcustom exwm-input-move-event 's-down-mouse-1 + "Emacs event to start moving a window." + :type 'key-sequence + :get (lambda (symbol) + (let ((value (default-value symbol))) + (if (mouse-event-p value) + value + (vector value)))) + :set (lambda (symbol value) + (set symbol (if (sequencep value) + (aref value 0) + value)))) + +(defcustom exwm-input-resize-event 's-down-mouse-3 + "Emacs event to start resizing a window." + :type 'key-sequence + :get (lambda (symbol) + (let ((value (default-value symbol))) + (if (mouse-event-p value) + value + (vector value)))) + :set (lambda (symbol value) + (set symbol (if (sequencep value) + (aref value 0) + value)))) + +(defcustom exwm-input-line-mode-passthrough nil + "Non-nil makes 'line-mode' forwards all events to Emacs." + :type 'boolean) + +;; Input focus update requests should be accumulated for a short time +;; interval so that only the last one need to be processed. This not +;; improves the overall performance, but avoids the problem of input +;; focus loop, which is a result of the interaction with Emacs frames. +;; +;; FIXME: The time interval is hard to decide and perhaps machine-dependent. +;; A value too small can cause redundant updates of input focus, +;; and even worse, dead loops. OTOH a large value would bring +;; laggy experience. +(defconst exwm-input--update-focus-interval 0.01 + "Time interval (in seconds) for accumulating input focus update requests.") + +(defvar exwm-input--during-command nil + "Indicate whether between `pre-command-hook' and `post-command-hook'.") (defvar exwm-input--global-keys nil "Global key bindings.") + (defvar exwm-input--global-prefix-keys nil "List of prefix keys of global key bindings.") -(defvar exwm-input-prefix-keys - '(?\C-c ?\C-x ?\C-u ?\C-h ?\M-x ?\M-` ?\M-& ?\M-:) - "List of prefix keys EXWM should forward to Emacs when in line-mode.") + +(defvar exwm-input--line-mode-cache nil "Cache for incomplete key sequence.") + +(defvar exwm-input--local-simulation-keys nil + "Whether simulation keys are local.") + (defvar exwm-input--simulation-keys nil "Simulation keys in line-mode.") + (defvar exwm-input--simulation-prefix-keys nil "List of prefix keys of simulation keys in line-mode.") +(defvar exwm-input--temp-line-mode nil + "Non-nil indicates it's in temporary line-mode for char-mode.") + +(defvar exwm-input--timestamp-atom nil) + +(defvar exwm-input--timestamp-callback nil) + +(defvar exwm-input--timestamp-window nil) + +(defvar exwm-input--update-focus-defer-timer nil "Timer for polling the lock.") + +(defvar exwm-input--update-focus-lock nil + "Lock for solving input focus update contention.") + +(defvar exwm-input--update-focus-timer nil + "Timer for deferring the update of input focus.") + +(defvar exwm-input--update-focus-window nil "The (Emacs) window to be focused. +This value should always be overwritten.") + +(defvar exwm-workspace--current) +(declare-function exwm-floating--do-moveresize "exwm-floating.el" + (data _synthetic)) +(declare-function exwm-floating--start-moveresize "exwm-floating.el" + (id &optional type)) +(declare-function exwm-floating--stop-moveresize "exwm-floating.el" + (&rest _args)) +(declare-function exwm-layout--iconic-state-p "exwm-layout.el" (&optional id)) (declare-function exwm-layout--show "exwm-layout.el" (id &optional window)) +(declare-function exwm-workspace--client-p "exwm-workspace.el" + (&optional frame)) +(declare-function exwm-workspace--minibuffer-own-frame-p "exwm-workspace.el") +(declare-function exwm-workspace--workspace-p "exwm-workspace.el" (workspace)) +(declare-function exwm-workspace-switch "exwm-workspace.el" + (frame-or-index &optional force)) (defun exwm-input--set-focus (id) "Set input focus to window ID in a proper way." @@ -185,13 +272,6 @@ ARGS are additional arguments to CALLBACK." (let ((exwm-input--global-prefix-keys nil)) (exwm-input--update-global-prefix-keys))) -(declare-function exwm-workspace--client-p "exwm-workspace.el" - (&optional frame)) - -(defvar exwm-input--update-focus-window nil "The (Emacs) window to be focused. - -This value should always be overwritten.") - (defun exwm-input--on-buffer-list-update () "Run in `buffer-list-update-hook' to track input focus." (when (and (not (eq this-command #'handle-switch-frame)) @@ -205,24 +285,6 @@ This value should always be overwritten.") (setq exwm-input--update-focus-window (selected-window)) (exwm-input--update-focus-defer))) -;; Input focus update requests should be accumulated for a short time -;; interval so that only the last one need to be processed. This not -;; improves the overall performance, but avoids the problem of input -;; focus loop, which is a result of the interaction with Emacs frames. -;; -;; FIXME: The time interval is hard to decide and perhaps machine-dependent. -;; A value too small can cause redundant updates of input focus, -;; and even worse, dead loops. OTOH a large value would bring -;; laggy experience. -(defconst exwm-input--update-focus-interval 0.01 - "Time interval (in seconds) for accumulating input focus update requests.") - -(defvar exwm-input--update-focus-lock nil - "Lock for solving input focus update contention.") -(defvar exwm-input--update-focus-defer-timer nil "Timer for polling the lock.") -(defvar exwm-input--update-focus-timer nil - "Timer for deferring the update of input focus.") - (defun exwm-input--update-focus-defer () "Defer updating input focus." (when exwm-input--update-focus-defer-timer @@ -240,12 +302,6 @@ This value should always be overwritten.") #'exwm-input--update-focus-commit exwm-input--update-focus-window)))) -(declare-function exwm-layout--iconic-state-p "exwm-layout.el" (&optional id)) -(declare-function exwm-workspace--minibuffer-own-frame-p "exwm-workspace.el") -(declare-function exwm-workspace-switch "exwm-workspace.el" - (frame-or-index &optional force)) -(declare-function exwm-workspace--workspace-p "exwm-workspace.el" (workspace)) - (defun exwm-input--update-focus-commit (window) "Commit updating input focus." (setq exwm-input--update-focus-lock t) @@ -317,10 +373,6 @@ This value should always be overwritten.") :window exwm--root :data (or id xcb:Window:None)))) -(declare-function exwm-floating--start-moveresize "exwm-floating.el" - (id &optional type)) -(declare-function exwm-workspace--position "exwm-workspace.el" (frame)) - (defun exwm-input--on-ButtonPress (data _synthetic) "Handle ButtonPress event." (let ((obj (make-instance 'xcb:ButtonPress)) @@ -419,7 +471,10 @@ This value should always be overwritten.") ;;;###autoload (defun exwm-input-set-key (key command) - "Set a global key binding." + "Set a global key binding. + +The new key binding only takes effect in real time when this command is +called interactively. Only invoke it non-interactively in configuration." (interactive "KSet key globally: \nCSet key %s to command: ") (global-set-key key command) (cl-pushnew key exwm-input--global-keys) @@ -437,22 +492,6 @@ This value should always be overwritten.") (setq unread-command-events (append unread-command-events `((t . ,event))))))) -(defvar exwm-input-command-whitelist nil - "A list of commands that when active all keys should be forwarded to Emacs.") -(make-obsolete-variable 'exwm-input-command-whitelist - "This variable can be safely removed." "25.1") - -(defvar exwm-input--during-command nil - "Indicate whether between `pre-command-hook' and `post-command-hook'.") - -(defvar exwm-input-line-mode-passthrough nil - "Non-nil makes 'line-mode' forwards all events to Emacs.") - -(defvar exwm-input--line-mode-cache nil "Cache for incomplete key sequence.") - -(defvar exwm-input--temp-line-mode nil - "Non-nil indicates it's in temporary line-mode for char-mode.") - (cl-defun exwm-input--translate (key) (let (translation) (dolist (map (list input-decode-map @@ -606,7 +645,8 @@ This value should always be overwritten.") ;;;###autoload (defun exwm-input-grab-keyboard (&optional id) "Switch to line-mode." - (interactive (list (exwm--buffer->id (window-buffer)))) + (interactive (list (when (derived-mode-p 'exwm-mode) + (exwm--buffer->id (window-buffer))))) (when id (with-current-buffer (exwm--id->buffer id) (exwm-input--grab-keyboard id) @@ -617,7 +657,8 @@ This value should always be overwritten.") ;;;###autoload (defun exwm-input-release-keyboard (&optional id) "Switch to char-mode." - (interactive (list (exwm--buffer->id (window-buffer)))) + (interactive (list (when (derived-mode-p 'exwm-mode) + (exwm--buffer->id (window-buffer))))) (when id (with-current-buffer (exwm--id->buffer id) (exwm-input--release-keyboard id) @@ -628,7 +669,8 @@ This value should always be overwritten.") ;;;###autoload (defun exwm-input-toggle-keyboard (&optional id) "Toggle between 'line-mode' and 'char-mode'." - (interactive (list (exwm--buffer->id (window-buffer)))) + (interactive (list (when (derived-mode-p 'exwm-mode) + (exwm--buffer->id (window-buffer))))) (when id (with-current-buffer (exwm--id->buffer id) (if exwm--keyboard-grabbed @@ -664,9 +706,14 @@ This value should always be overwritten.") (xcb:flush exwm--connection))) ;;;###autoload -(defun exwm-input-send-next-key (times) - "Send next key to client window." +(cl-defun exwm-input-send-next-key (times) + "Send next key to client window. + +EXWM will prompt for the key to send. This command can be prefixed to send +multiple keys." (interactive "p") + (unless (derived-mode-p 'exwm-mode) + (cl-return-from 'exwm-input-send-next-key)) (when (> times 12) (setq times 12)) (let (key keys) (dotimes (i times) @@ -686,9 +733,6 @@ This value should always be overwritten.") ;; (unless (listp last-input-event) ;not a key event ;; (exwm-input--fake-key last-input-event))) -(defvar exwm-input--local-simulation-keys nil - "Whether simulation keys are local.") - (defun exwm-input--update-simulation-prefix-keys () "Update the list of prefix keys of simulation keys." (setq exwm-input--simulation-prefix-keys nil) @@ -718,9 +762,13 @@ Its usage is the same with `exwm-input-set-simulation-keys'." (exwm-input-set-simulation-keys simulation-keys))) ;;;###autoload -(defun exwm-input-send-simulation-key (times) - "Fake a key event according to last input key sequence." +(cl-defun exwm-input-send-simulation-key (times) + "Fake a key event according to the last input key sequence. + +Sending multiple fake keys at once is only supported by Emacs 27 and later." (interactive "p") + (unless (derived-mode-p 'exwm-mode) + (cl-return-from 'exwm-input-send-simulation-key)) (let ((pair (assoc (this-single-command-keys) exwm-input--simulation-keys))) (when pair (setq pair (cdr pair)) @@ -738,11 +786,6 @@ Its usage is the same with `exwm-input-set-simulation-keys'." "Run in `post-command-hook'." (setq exwm-input--during-command nil)) -(declare-function exwm-floating--stop-moveresize "exwm-floating.el" - (&rest _args)) -(declare-function exwm-floating--do-moveresize "exwm-floating.el" - (data _synthetic)) - (defun exwm-input--init () "Initialize the keyboard module." ;; Refresh keyboard mapping diff --git a/exwm-layout.el b/exwm-layout.el index cda942e..a98e261 100644 --- a/exwm-layout.el +++ b/exwm-layout.el @@ -27,8 +27,35 @@ (require 'exwm-core) -(defvar exwm-floating-border-width) -(defvar exwm-workspace--id-struts-alist) +(defgroup exwm-layout nil + "Layout." + :version "25.3" + :group 'exwm) + +(defcustom exwm-layout-show-all-buffers nil + "Non-nil to allow switching to buffers on other workspaces." + :type 'boolean) + +(defvar exwm-layout--other-buffer-exclude-buffers nil + "List of buffers that should not be selected by `other-buffer'.") + +(defvar exwm-layout--other-buffer-exclude-exwm-mode-buffers nil + "When non-nil, prevent EXWM buffers from being selected by `other-buffer'.") + +(defvar exwm-layout--timer nil "Timer used to track echo area changes.") + +(defvar exwm-workspace--current) +(declare-function exwm-input-grab-keyboard "exwm-input.el") +(declare-function exwm-input-release-keyboard "exwm-input.el") +(declare-function exwm-workspace--client-p "exwm-workspace.el" + (&optional frame)) +(declare-function exwm-workspace--current-height "exwm-workspace.el") +(declare-function exwm-workspace--current-width "exwm-workspace.el") +(declare-function exwm-workspace--minibuffer-own-frame-p "exwm-workspace.el") +(declare-function exwm-workspace--workspace-p "exwm-workspace.el" + (workspace)) +(declare-function exwm-workspace-move-window "exwm-workspace.el" + (frame-or-index &optional id)) (defun exwm-layout--set-state (id state) "Set WM_STATE." @@ -99,23 +126,14 @@ (exwm-layout--set-state id xcb:icccm:WM_STATE:IconicState) (xcb:flush exwm--connection)))) -(defvar exwm-workspace--current) - -(declare-function exwm-input-grab-keyboard "exwm-input.el") -(declare-function exwm-input-release-keyboard "exwm-input.el") -(declare-function exwm-workspace--current-height "exwm-workspace.el") -(declare-function exwm-workspace--current-width "exwm-workspace.el") -(declare-function exwm-workspace--minibuffer-own-frame-p "exwm-workspace.el") -(declare-function exwm-workspace-move-window "exwm-workspace.el" - (frame-or-index &optional id)) - ;;;###autoload -(defun exwm-layout-set-fullscreen (&optional id) +(cl-defun exwm-layout-set-fullscreen (&optional id) "Make window ID fullscreen." (interactive) + (unless (and (or id (derived-mode-p 'exwm-mode)) + (not (memq xcb:Atom:_NET_WM_STATE_FULLSCREEN exwm--ewmh-state))) + (cl-return-from 'exwm-layout-set-fullscreen)) (with-current-buffer (if id (exwm--id->buffer id) (window-buffer)) - (when (memq xcb:Atom:_NET_WM_STATE_FULLSCREEN exwm--ewmh-state) - (user-error "Already in full-screen mode")) ;; Expand the X window to fill the whole screen. ;; Rationale: Floating X windows may not be positioned at (0, 0) ;; due to the extra border. @@ -139,12 +157,13 @@ (call-interactively #'exwm-input-release-keyboard))) ;;;###autoload -(defun exwm-layout-unset-fullscreen (&optional id) +(cl-defun exwm-layout-unset-fullscreen (&optional id) "Restore window from fullscreen state." (interactive) + (unless (and (or id (derived-mode-p 'exwm-mode)) + (memq xcb:Atom:_NET_WM_STATE_FULLSCREEN exwm--ewmh-state)) + (cl-return-from 'exwm-layout-unset-fullscreen)) (with-current-buffer (if id (exwm--id->buffer id) (window-buffer)) - (unless (memq xcb:Atom:_NET_WM_STATE_FULLSCREEN exwm--ewmh-state) - (user-error "Not in full-screen mode")) (if exwm--floating-frame (exwm-layout--show exwm--id (frame-root-window exwm--floating-frame)) (xcb:+request exwm--connection @@ -165,21 +184,17 @@ (call-interactively #'exwm-input-grab-keyboard))) ;;;###autoload -(defun exwm-layout-toggle-fullscreen (&optional id) +(cl-defun exwm-layout-toggle-fullscreen (&optional id) "Toggle fullscreen mode." (interactive (list (exwm--buffer->id (window-buffer)))) + (unless (or id (derived-mode-p 'exwm-mode)) + (cl-return-from 'exwm-layout-toggle-fullscreen)) (when id (with-current-buffer (exwm--id->buffer id) (if (memq xcb:Atom:_NET_WM_STATE_FULLSCREEN exwm--ewmh-state) (exwm-reset) (exwm-layout-set-fullscreen id))))) -(defvar exwm-layout--other-buffer-exclude-exwm-mode-buffers nil - "When non-nil, prevent EXWM buffers from being selected by `other-buffer'.") - -(defvar exwm-layout--other-buffer-exclude-buffers nil - "List of buffers that should not be selected by `other-buffer'.") - (defun exwm-layout--other-buffer-predicate (buffer) "Return non-nil when the BUFFER may be displayed in selected frame. @@ -201,11 +216,6 @@ selected by `other-buffer'." ;; Do not select if already shown in some window. (not (get-buffer-window buffer t))))) -(defvar exwm-layout-show-all-buffers nil - "Non-nil to allow switching to buffers on other workspaces.") -(declare-function exwm-workspace--workspace-p "exwm-workspace.el" - (workspace)) - (defun exwm-layout--set-client-list-stacking () "Set _NET_CLIENT_LIST_STACKING." (let (id clients-floating clients clients-iconic clients-other) @@ -301,9 +311,6 @@ selected by `other-buffer'." (exwm-layout--set-client-list-stacking) (xcb:flush exwm--connection)))) -(declare-function exwm-workspace--client-p "exwm-workspace.el" - (&optional frame)) - (defun exwm-layout--on-minibuffer-setup () "Refresh layout when minibuffer grows." (unless (exwm-workspace--client-p) @@ -479,8 +486,6 @@ See also `exwm-layout-enlarge-window'." (exwm-layout-hide-mode-line) (exwm-layout-show-mode-line)))) -(defvar exwm-layout--timer nil "Timer used to track echo area changes.") - (defun exwm-layout--init () "Initialize layout module." ;; Auto refresh layout diff --git a/exwm-manage.el b/exwm-manage.el index 0a9d92f..b983ebf 100644 --- a/exwm-manage.el +++ b/exwm-manage.el @@ -28,17 +28,66 @@ (require 'exwm-core) -(defvar exwm-manage-force-tiling nil - "Non-nil to force managing all X windows in tiling layout. +(defgroup exwm-manage nil + "Manage." + :version "25.3" + :group 'exwm) -You can still make the X windows floating afterwards.") - -(defvar exwm-manage-finish-hook nil +(defcustom exwm-manage-finish-hook nil "Normal hook run after a window is just managed, in the context of the -corresponding buffer.") +corresponding buffer." + :type 'hook) + +(defcustom exwm-manage-force-tiling nil + "Non-nil to force managing all X windows in tiling layout. +You can still make the X windows floating afterwards." + :type 'boolean) + +;; FIXME: Make the following values as small as possible. +(defconst exwm-manage--height-delta-min 5) +(defconst exwm-manage--width-delta-min 5) + +;; The _MOTIF_WM_HINTS atom (see for more details) +;; It's currently only used in 'exwm-manage' module +(defvar exwm-manage--_MOTIF_WM_HINTS nil "_MOTIF_WM_HINTS atom.") (defvar exwm-manage--desktop nil "The desktop X window.") +(defvar exwm-manage--frame-outer-id-list nil + "List of window-outer-id's of all frames.") + +(defvar exwm-manage--ping-lock nil + "Non-nil indicates EXWM is pinging a window.") + +(defvar exwm-manage-ping-timeout 3 "Seconds to wait before killing a client.") + +(defvar exwm-workspace--current) +(defvar exwm-workspace--id-struts-alist) +(defvar exwm-workspace--list) +(defvar exwm-workspace--switch-history-outdated) +(defvar exwm-workspace-current-index) +(declare-function exwm--update-class "exwm.el" (id &optional force)) +(declare-function exwm--update-hints "exwm.el" (id &optional force)) +(declare-function exwm--update-normal-hints "exwm.el" (id &optional force)) +(declare-function exwm--update-protocols "exwm.el" (id &optional force)) +(declare-function exwm--update-struts "exwm.el" (id)) +(declare-function exwm--update-title "exwm.el" (id)) +(declare-function exwm--update-transient-for "exwm.el" (id &optional force)) +(declare-function exwm--update-window-type "exwm.el" (id &optional force)) +(declare-function exwm-floating--set-floating "exwm-floating.el" (id)) +(declare-function exwm-floating--unset-floating "exwm-floating.el" (id)) +(declare-function exwm-input-grab-keyboard "exwm-input.el") +(declare-function exwm-layout--iconic-state-p "exwm-layout.el" (&optional id)) +(declare-function exwm-workspace--count "exwm-workspace.el" ()) +(declare-function exwm-workspace--current-height "exwm-workspace.el") +(declare-function exwm-workspace--current-width "exwm-workspace.el") +(declare-function exwm-workspace--set-desktop "exwm-workspace.el" (id)) +(declare-function exwm-workspace--set-fullscreen "exwm-workspace.el" (frame)) +(declare-function exwm-workspace--update-struts "exwm-workspace.el" ()) +(declare-function exwm-workspace--update-workareas "exwm-workspace.el" ()) +(declare-function exwm-workspace-move-window "exwm-workspace.el" + (frame-or-index &optional id)) + (defun exwm-manage--update-geometry (id &optional force) "Update window geometry." (with-current-buffer (exwm--id->buffer id) @@ -58,10 +107,6 @@ corresponding buffer.") (when reply (setq exwm--ewmh-state (append (slot-value reply 'value) nil))))))) -;; The _MOTIF_WM_HINTS atom (see for more details) -;; It's currently only used in 'exwm-manage' module -(defvar exwm-manage--_MOTIF_WM_HINTS nil "_MOTIF_WM_HINTS atom.") - (defun exwm-manage--update-mwm-hints (id &optional force) "Update _MOTIF_WM_HINTS." (with-current-buffer (exwm--id->buffer id) @@ -92,29 +137,6 @@ corresponding buffer.") :window exwm--root :data (vconcat (mapcar #'car exwm--id-buffer-alist))))) -(defvar exwm-workspace--current) -(defvar exwm-workspace--switch-history-outdated) -(defvar exwm-workspace-current-index) -(defvar exwm-workspace--workareas) - -(declare-function exwm--update-window-type "exwm.el" (id &optional force)) -(declare-function exwm--update-class "exwm.el" (id &optional force)) -(declare-function exwm--update-transient-for "exwm.el" (id &optional force)) -(declare-function exwm--update-normal-hints "exwm.el" (id &optional force)) -(declare-function exwm--update-title "exwm.el" (id)) -(declare-function exwm--update-hints "exwm.el" (id &optional force)) -(declare-function exwm--update-protocols "exwm.el" (id &optional force)) -(declare-function exwm--update-struts "exwm.el" (id)) -(declare-function exwm-floating--set-floating "exwm-floating.el" (id)) -(declare-function exwm-floating--unset-floating "exwm-floating.el" (id)) -(declare-function exwm-input-grab-keyboard "exwm-input.el") -(declare-function exwm-workspace--current-height "exwm-workspace.el") -(declare-function exwm-workspace--current-width "exwm-workspace.el") -(declare-function exwm-workspace--set-desktop "exwm-workspace.el" (id)) -(declare-function exwm-workspace--count "exwm-workspace.el" ()) -(declare-function exwm-workspace-move-window "exwm-workspace.el" - (frame-or-index &optional id)) - (defun exwm-manage--manage-window (id) "Manage window ID." (exwm--log "Try to manage #x%x" id) @@ -251,13 +273,6 @@ corresponding buffer.") (exwm-layout-set-fullscreen id)) (run-hooks 'exwm-manage-finish-hook))))) -(defvar exwm-workspace--id-struts-alist) -(defvar exwm-workspace--list) - -(declare-function exwm-workspace--update-struts "exwm-workspace.el" ()) -(declare-function exwm-workspace--update-workareas "exwm-workspace.el" ()) -(declare-function exwm-workspace--set-fullscreen "exwm-workspace.el" (frame)) - (defun exwm-manage--unmanage-window (id &optional withdraw-only) "Unmanage window ID. @@ -350,10 +365,6 @@ manager is shutting down." (xcb:flush exwm--connection) (exwm-manage--manage-window i))))))) -(defvar exwm-manage--ping-lock nil - "Non-nil indicates EXWM is pinging a window.") -(defvar exwm-manage-ping-timeout 3 "Seconds to wait before killing a client.") - (defun exwm-manage--kill-buffer-query-function () "Run in `kill-buffer-query-functions'." (catch 'return @@ -447,13 +458,6 @@ Would you like to kill it? " (xcb:+request exwm--connection ,request)))) (xcb:flush exwm--connection))) -;; FIXME: Make the following values as small as possible. -(defconst exwm-manage--width-delta-min 5) -(defconst exwm-manage--height-delta-min 5) - -(defvar exwm-manage--frame-outer-id-list nil - "List of window-outer-id's of all frames.") - (defun exwm-manage--add-frame (frame) "Run in `after-make-frame-functions'." (when (display-graphic-p frame) @@ -560,8 +564,6 @@ border-width: %d; sibling: #x%x; stack-mode: %d" :stack-mode stack-mode))))))) (xcb:flush exwm--connection)) -(declare-function exwm-layout--iconic-state-p "exwm-layout.el" (&optional id)) - (defun exwm-manage--on-MapRequest (data _synthetic) "Handle MapRequest event." (let ((obj (make-instance 'xcb:MapRequest))) diff --git a/exwm-randr.el b/exwm-randr.el index 74938d6..f49073c 100644 --- a/exwm-randr.el +++ b/exwm-randr.el @@ -50,19 +50,42 @@ (require 'xcb-randr) (require 'exwm-core) -(defvar exwm-randr-workspace-output-plist nil) +(defgroup exwm-randr nil + "RandR." + :version "25.3" + :group 'exwm) -(defvar exwm-randr-refresh-hook nil - "Normal hook run when the RandR module just refreshed.") +(defcustom exwm-randr-refresh-hook nil + "Normal hook run when the RandR module just refreshed." + :type 'hook) + +(defcustom exwm-randr-screen-change-hook nil + "Normal hook run when screen changes." + :type 'hook) + +(defcustom exwm-randr-workspace-output-plist nil + "Plist mapping workspace to output. + +If an output is not available, the workspaces mapped to it are displayed on +the primary output until it becomes available. Unspecified workspaces are +all mapped to the primary output. For example, with the following value +workspace other than 1 and 3 would always be displayed on the primary output +where workspace 1 and 3 would be displayed on their corresponding output +whenever the outputs are available. + + '(1 \"HDMI-1\" 3 \"DP-1\") + +The outputs available can be identified by running the 'xrandr' utility with +the first one in result being the primary output." + :type '(plist :key-type integer :value-type string)) (defvar exwm-workspace--fullscreen-frame-count) (defvar exwm-workspace--list) - (declare-function exwm-workspace--count "exwm-workspace.el") -(declare-function exwm-workspace--set-fullscreen "exwm-workspace.el" (frame)) -(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-fullscreen "exwm-workspace.el" (frame)) +(declare-function exwm-workspace--show-minibuffer "exwm-workspace.el" ()) +(declare-function exwm-workspace--update-workareas "exwm-workspace.el" ()) (defun exwm-randr--refresh () "Refresh workspaces according to the updated RandR info." @@ -122,9 +145,6 @@ (xcb:flush exwm--connection) (run-hooks 'exwm-randr-refresh-hook)))) -(defvar exwm-randr-screen-change-hook nil - "Normal hook run when screen changes.") - (defun exwm-randr--init () "Initialize RandR extension and EXWM RandR module." (if (= 0 (slot-value (xcb:get-extension-data exwm--connection 'xcb:randr) diff --git a/exwm-systemtray.el b/exwm-systemtray.el index 33e9762..5377ef8 100644 --- a/exwm-systemtray.el +++ b/exwm-systemtray.el @@ -50,22 +50,38 @@ (owner :initarg :owner :type xcb:WINDOW)) ;new slot :documentation "A systemtray client message.") +(defgroup exwm-systemtray nil + "System tray." + :version "25.3" + :group 'exwm) + +(defcustom exwm-systemtray-height nil + "System tray height. + +You shall use the default value if using auto-hide minibuffer." + :type 'integer) + +(defcustom exwm-systemtray-icon-gap 2 + "Gap between icons." + :type 'integer) + ;; GTK icons require at least 16 pixels to show normally. (defconst exwm-systemtray--icon-min-size 16 "Minimum icon size.") -(defvar exwm-systemtray-height nil "System tray height. - -You shall use the default value if using auto-hide minibuffer.") - -(defvar exwm-systemtray-icon-gap 2 "Gap between icons.") - (defvar exwm-systemtray--connection nil "The X connection.") -(defvar exwm-systemtray--list nil "The icon list.") -(defvar exwm-systemtray--selection-owner-window nil - "The selection owner window.") + (defvar exwm-systemtray--embedder nil "The embedder window.") +(defvar exwm-systemtray--list nil "The icon list.") + +(defvar exwm-systemtray--selection-owner-window nil + "The selection owner window.") + (defvar exwm-workspace--current) +(defvar exwm-workspace--minibuffer) +(defvar exwm-workspace--workareas) +(defvar exwm-workspace-current-index) +(defvar xcb:Atom:_NET_SYSTEM_TRAY_S0) (declare-function exwm-workspace--current-height "exwm-workspace.el") (declare-function exwm-workspace--current-width "exwm-workspace.el") (declare-function exwm-workspace--minibuffer-own-frame-p "exwm-workspace.el") @@ -304,9 +320,6 @@ You shall use the default value if using auto-hide minibuffer.") :event (xcb:marshal obj exwm-systemtray--connection)))) (xcb:flush exwm-systemtray--connection)) -(defvar exwm-workspace--workareas) -(defvar exwm-workspace-current-index) - (defun exwm-systemtray--on-workspace-switch () "Reparent/Refresh the system tray in `exwm-workspace-switch-hook'." (unless (exwm-workspace--minibuffer-own-frame-p) @@ -339,9 +352,6 @@ You shall use the default value if using auto-hide minibuffer.") (defalias 'exwm-systemtray--on-struts-update #'exwm-systemtray--on-randr-refresh) -(defvar xcb:Atom:_NET_SYSTEM_TRAY_S0) -(defvar exwm-workspace--minibuffer) - (cl-defun exwm-systemtray--init () "Initialize system tray module." (cl-assert (not exwm-systemtray--connection)) diff --git a/exwm-workspace.el b/exwm-workspace.el index 2917c69..b9cda25 100644 --- a/exwm-workspace.el +++ b/exwm-workspace.el @@ -29,16 +29,110 @@ (require 'exwm-core) -(defvar exwm-manage--desktop) +(defgroup exwm-workspace nil + "Workspace." + :version "25.3" + :group 'exwm) -(defvar exwm-workspace-number 1 "Initial number of workspaces.") -(defvar exwm-workspace--list nil "List of all workspaces (Emacs frames).") -(defvar exwm-workspace--current nil "Current active workspace.") -(defvar exwm-workspace-current-index 0 "Index of current active workspace.") -(defvar exwm-workspace-index-map #'number-to-string +(defcustom exwm-workspace-switch-hook nil + "Normal hook run after switching workspace." + :type 'hook) + +(defcustom exwm-workspace-list-change-hook nil + "Normal hook run when the workspace list is changed (workspace added, +deleted, moved, etc)." + :type 'hook) + +(defcustom exwm-workspace-show-all-buffers nil + "Non-nil to show buffers on other workspaces." + :type 'boolean) + +(defcustom exwm-workspace-number 1 + "Initial number of workspaces." + :type 'integer) + +(defcustom exwm-workspace-index-map #'number-to-string "Function for mapping a workspace index to a string for display. -By default `number-to-string' is applied which yields 0 1 2 ... .") +By default `number-to-string' is applied which yields 0 1 2 ... ." + :type 'function) + +(defcustom exwm-workspace-minibuffer-position nil + "Position of the minibuffer frame." + :type '(choice (const :tag "Bottom (fixed)" nil) + (const :tag "Bottom (auto-hide)" bottom) + (const :tag "Top (auto-hide)" top))) + +(defcustom exwm-workspace-display-echo-area-timeout 1 + "Timeout for displaying echo area." + :type 'integer) + +(defcustom exwm-workspace-switch-create-limit 10 + "Number of workspaces `exwm-workspace-switch-create' allowed to create +each time." + :type 'integer) + +(defvar exwm-workspace-current-index 0 "Index of current active workspace.") + +(defvar exwm-workspace--attached-minibuffer-height 0 + "Height (in pixel) of the attached minibuffer. + +If the minibuffer is detached, this value is 0.") + +(defvar exwm-workspace--client nil + "The 'client' frame parameter of emacsclient frames.") + +(defvar exwm-workspace--create-silently nil + "When non-nil workspaces are created in the background (not switched to). + +Please manually run the hook `exwm-workspace-list-change-hook' afterwards.") + +(defvar exwm-workspace--current nil "Current active workspace.") + +(defvar exwm-workspace--display-echo-area-timer nil + "Timer for auto-hiding echo area.") + +(defvar exwm-workspace--id-struts-alist nil "Alist of X window and struts.") + +(defvar exwm-workspace--fullscreen-frame-count 0 + "Count the fullscreen workspace frames.") + +(defvar exwm-workspace--list nil "List of all workspaces (Emacs frames).") + +(defvar exwm-workspace--minibuffer nil + "The minibuffer frame shared among all frames.") + +(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--struts nil "Areas occupied by struts.") + +(defvar exwm-workspace--switch-history nil + "History for `read-from-minibuffer' to interactively switch workspace.") + +(defvar exwm-workspace--switch-history-outdated nil + "Non-nil to indicate `exwm-workspace--switch-history' is outdated.") + +(defvar exwm-workspace--timer nil "Timer used to track echo area changes.") + +(defvar exwm-workspace--update-workareas-hook nil + "Normal hook run when workareas get updated.") + +(defvar exwm-workspace--workareas nil "Workareas (struts excluded).") + +(defvar exwm-input--during-command) +(defvar exwm-layout-show-all-buffers) +(defvar exwm-manage--desktop) +(declare-function exwm--exit "exwm.el") +(declare-function exwm-input--on-buffer-list-update "exwm-input.el" ()) +(declare-function exwm-layout--hide "exwm-layout.el" (id)) +(declare-function exwm-layout--other-buffer-predicate "exwm-layout.el" + (buffer)) +(declare-function exwm-layout--refresh "exwm-layout.el") +(declare-function exwm-layout--show "exwm-layout.el" (id &optional window)) (defsubst exwm-workspace--position (frame) "Retrieve index of given FRAME in workspace list. @@ -58,20 +152,6 @@ NIL if FRAME is not a workspace" "Return non-nil if FRAME is an emacsclient frame." (frame-parameter frame 'client)) -(defun exwm-workspace--workspace-from-frame-or-index (frame-or-index) - "Retrieve the workspace frame from FRAME-OR-INDEX." - (cond - ((framep frame-or-index) - (unless (exwm-workspace--position frame-or-index) - (user-error "[EXWM] Frame is not a workspace %S" frame-or-index)) - frame-or-index) - ((integerp frame-or-index) - (unless (and (<= 0 frame-or-index) - (< frame-or-index (exwm-workspace--count))) - (user-error "[EXWM] Workspace index out of range: %d" frame-or-index)) - (elt exwm-workspace--list frame-or-index)) - (t (user-error "[EXWM] Invalid workspace: %s" frame-or-index)))) - (defvar exwm-workspace--switch-map (let ((map (make-sparse-keymap))) (define-key map [t] (lambda () (interactive))) @@ -98,10 +178,19 @@ NIL if FRAME is not a workspace" map) "Keymap used for interactively switch workspace.") -(defvar exwm-workspace--switch-history nil - "History for `read-from-minibuffer' to interactively switch workspace.") -(defvar exwm-workspace--switch-history-outdated nil - "Non-nil to indicate `exwm-workspace--switch-history' is outdated.") +(defun exwm-workspace--workspace-from-frame-or-index (frame-or-index) + "Retrieve the workspace frame from FRAME-OR-INDEX." + (cond + ((framep frame-or-index) + (unless (exwm-workspace--position frame-or-index) + (user-error "[EXWM] Frame is not a workspace %S" frame-or-index)) + frame-or-index) + ((integerp frame-or-index) + (unless (and (<= 0 frame-or-index) + (< frame-or-index (exwm-workspace--count))) + (user-error "[EXWM] Workspace index out of range: %d" frame-or-index)) + (elt exwm-workspace--list frame-or-index)) + (t (user-error "[EXWM] Invalid workspace: %s" frame-or-index)))) (defun exwm-workspace--prompt-for-workspace (&optional prompt) "Prompt for a workspace, returning the workspace frame." @@ -117,15 +206,6 @@ NIL if FRAME is not a workspace" :test #'equal))) (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). - -Please manually run the hook `exwm-workspace-list-change-hook' afterwards.") - (defun exwm-workspace--prompt-add () "Add workspace from the prompt." (interactive) @@ -182,20 +262,6 @@ Please manually run the hook `exwm-workspace-list-change-hook' afterwards.") sequence "")) sequence))))) -(defvar exwm-workspace-show-all-buffers nil - "Non-nil to show buffers on other workspaces.") -(defvar exwm-workspace--minibuffer nil - "The minibuffer frame shared among all frames.") -(defvar exwm-workspace-minibuffer-position nil - "Position of the minibuffer frame. - -Value nil means to use the default position which is fixed at bottom, while -'top and 'bottom mean to use an auto-hiding minibuffer.") -(defvar exwm-workspace-display-echo-area-timeout 1 - "Timeout for displaying echo area.") -(defvar exwm-workspace--display-echo-area-timer nil - "Timer for auto-hiding echo area.") - ;;;###autoload (defun exwm-workspace--get-geometry (frame) "Return the geometry of frame FRAME." @@ -227,9 +293,6 @@ Value nil means to use the default position which is fixed at bottom, while "Reports whether the minibuffer is displayed in its own frame." (memq exwm-workspace-minibuffer-position '(top bottom))) -(defvar exwm-workspace--id-struts-alist nil "Alist of X window and struts.") -(defvar exwm-workspace--struts nil "Areas occupied by struts.") - (defun exwm-workspace--update-struts () "Update `exwm-workspace--struts'." (setq exwm-workspace--struts nil) @@ -250,10 +313,6 @@ Value nil means to use the default position which is fixed at bottom, while (setq exwm-workspace--struts (append exwm-workspace--struts (list struts*)))))))))) -(defvar exwm-workspace--workareas nil "Workareas (struts excluded).") -(defvar exwm-workspace--update-workareas-hook nil - "Normal hook run when workareas get updated.") - (defun exwm-workspace--update-workareas () "Update `exwm-workspace--workareas'." (let ((root-width (x-display-pixel-width)) @@ -318,9 +377,6 @@ Value nil means to use the default position which is fixed at bottom, while (xcb:flush exwm--connection)) (run-hooks 'exwm-workspace--update-workareas-hook)) -(defvar exwm-workspace--fullscreen-frame-count 0 - "Count the fullscreen workspace frames.") - (defun exwm-workspace--set-fullscreen (frame) "Make frame FRAME fullscreen according to `exwm-workspace--workareas'." (let ((workarea (elt exwm-workspace--workareas @@ -342,11 +398,6 @@ Value nil means to use the default position which is fixed at bottom, while (when exwm-workspace--fullscreen-frame-count (cl-incf exwm-workspace--fullscreen-frame-count))) -(defvar exwm-workspace--attached-minibuffer-height 0 - "Height (in pixel) of the attached minibuffer. - -If the minibuffer is detached, this value is 0.") - (defun exwm-workspace--resize-minibuffer-frame () "Resize minibuffer (and its container) to fit the size of workspace." (cl-assert (exwm-workspace--minibuffer-own-frame-p)) @@ -434,14 +485,13 @@ PREFIX-DIGITS is a list of the digits introduced so far." (goto-history-element (1+ n)) (exit-minibuffer)) -(defvar exwm-workspace-switch-hook nil - "Normal hook run after switching workspace.") - ;;;###autoload (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 (0-based). -The optional FORCE option is for internal use only." +Query for the index if not specified when called interactively. Passing a +workspace frame as the first option or making use of the rest options are +for internal use only." (interactive (list (unless (and (eq major-mode 'exwm-mode) @@ -518,13 +568,11 @@ The optional FORCE option is for internal use only." (run-hooks 'focus-in-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.") - ;;;###autoload (defun exwm-workspace-switch-create (frame-or-index) - "Switch to workspace FRAME-OR-INDEX, creating it if it does not exist yet." + "Switch to workspace INDEX or creating it first if it does not exist yet. + +Passing a workspace frame as the first option is for internal use only." (interactive) (if (or (framep frame-or-index) (< frame-or-index (exwm-workspace--count))) @@ -537,10 +585,6 @@ each time.") (run-hooks 'exwm-workspace-list-change-hook)) (exwm-workspace-switch frame-or-index))) -(defvar exwm-workspace-list-change-hook nil - "Normal hook run when the workspace list is changed (workspace added, -deleted, moved, etc).") - ;;;###autoload (defun exwm-workspace-swap (workspace1 workspace2) "Interchange position of WORKSPACE1 with that of WORKSPACE2." @@ -579,6 +623,7 @@ deleted, moved, etc).") ;;;###autoload (defun exwm-workspace-move (workspace nth) "Move WORKSPACE to the NTH position. + When called interactively, prompt for a workspace and move current one just before it." (interactive @@ -645,13 +690,6 @@ INDEX must not exceed the current number of workspaces." :window id :data (exwm-workspace--position exwm--frame))))) -(declare-function exwm-input--on-buffer-list-update "exwm-input.el" ()) -(declare-function exwm-layout--show "exwm-layout.el" (id &optional window)) -(declare-function exwm-layout--hide "exwm-layout.el" (id)) -(declare-function exwm-layout--refresh "exwm-layout.el") -(declare-function exwm-layout--other-buffer-predicate "exwm-layout.el" - (buffer)) - ;;;###autoload (defun exwm-workspace-move-window (frame-or-index &optional id) "Move window ID to workspace FRAME-OR-INDEX." @@ -780,8 +818,6 @@ INDEX must not exceed the current number of workspaces." (xcb:flush exwm--connection))) (setq exwm-workspace--switch-history-outdated t))) -(defvar exwm-layout-show-all-buffers) - ;;;###autoload (defun exwm-workspace-switch-to-buffer (buffer-or-name) "Make the current Emacs window display another buffer." @@ -1049,8 +1085,6 @@ Please check `exwm-workspace--minibuffer-own-frame-p' first." (remove-hook 'post-command-hook #'exwm-workspace--update-minibuffer-height) (exwm-workspace--hide-minibuffer))) -(defvar exwm-input--during-command) - (defun exwm-workspace--on-echo-area-dirty () "Run when new message arrives to show the echo area and its container." (when (and (not (active-minibuffer-window)) @@ -1075,12 +1109,6 @@ Please check `exwm-workspace--minibuffer-own-frame-p' first." (cancel-timer exwm-workspace--display-echo-area-timer) (setq exwm-workspace--display-echo-area-timer nil)))) -(defvar exwm-workspace--client nil - "The 'client' frame parameter of emacsclient frames.") - -(declare-function exwm-manage--unmanage-window "exwm-manage.el") -(declare-function exwm--exit "exwm.el") - (defun exwm-workspace--confirm-kill-emacs (prompt &optional force) "Confirm before exiting Emacs." (when (cond @@ -1157,8 +1185,6 @@ Please check `exwm-workspace--minibuffer-own-frame-p' first." :width (x-display-pixel-width) :height (x-display-pixel-height)))) -(defvar exwm-workspace--timer nil "Timer used to track echo area changes.") - (defun exwm-workspace--add-frame-as-workspace (frame) "Configure frame FRAME to be treated as a workspace." (cond diff --git a/exwm.el b/exwm.el index 02e9152..3e445b2 100644 --- a/exwm.el +++ b/exwm.el @@ -72,9 +72,41 @@ (require 'exwm-manage) (require 'exwm-input) +(defgroup exwm nil + "Emacs X Window Manager." + :tag "EXWM" + :version "25.3" + :group 'applications + :prefix "exwm-") + +(defcustom exwm-init-hook nil + "Normal hook run when EXWM has just finished initialization." + :type 'hook) + +(defcustom exwm-exit-hook nil + "Normal hook run just before EXWM exits." + :type 'hook) + +(defcustom exwm-update-class-hook nil + "Normal hook run when window class is updated." + :type 'hook) + +(defcustom exwm-update-title-hook nil + "Normal hook run when window title is updated." + :type 'hook) + +(defcustom exwm-blocking-subrs '(x-file-dialog x-popup-dialog x-select-font) + "Subrs (primitives) that would normally block EXWM." + :type '(repeat function)) + +(defconst exwm--server-name "server-exwm" + "Name of the subordinate Emacs server.") + +(defvar exwm--server-process nil "Process of the subordinate Emacs server.") + ;;;###autoload (defun exwm-reset () - "Reset window to standard state: non-fullscreen, line-mode." + "Reset the state of the selected window (non-fullscreen, line-mode, etc)." (interactive) (with-current-buffer (window-buffer) (when (eq major-mode 'exwm-mode) @@ -123,9 +155,6 @@ (when reply ;nil when destroyed (setq exwm-window-type (append (slot-value reply 'value) nil))))))) -(defvar exwm-update-class-hook nil - "Normal hook run when window class is updated.") - (defun exwm--update-class (id &optional force) "Update WM_CLASS." (with-current-buffer (exwm--id->buffer id) @@ -138,9 +167,6 @@ (when (and exwm-instance-name exwm-class-name) (run-hooks 'exwm-update-class-hook))))))) -(defvar exwm-update-title-hook nil - "Normal hook run when window title is updated.") - (defun exwm--update-utf8-title (id &optional force) "Update _NET_WM_NAME." (with-current-buffer (exwm--id->buffer id) @@ -645,9 +671,6 @@ :property p)) (xcb:flush exwm--connection))) -(defvar exwm-init-hook nil - "Normal hook run when EXWM has just finished initialization.") - (defun exwm-init (&optional frame) "Initialize EXWM." (if frame @@ -692,8 +715,6 @@ (exwm-manage--scan) (run-hooks 'exwm-init-hook))))) -(defvar exwm-exit-hook nil "Normal hook run just before EXWM exits.") - (defun exwm--exit () "Exit EXWM." (run-hooks 'exwm-exit-hook) @@ -705,9 +726,6 @@ (exwm-layout--exit) (exwm--exit-icccm-ewmh)) -(defvar exwm-blocking-subrs '(x-file-dialog x-popup-dialog x-select-font) - "Subrs (primitives) that would normally block EXWM.") - (defun exwm-enable (&optional undo) "Enable/Disable EXWM." (pcase undo @@ -734,10 +752,6 @@ (dolist (i exwm-blocking-subrs) (advice-add i :around #'exwm--server-eval-at))))) -(defconst exwm--server-name "server-exwm" - "Name of the subordinate Emacs server.") -(defvar exwm--server-process nil "Process of the subordinate Emacs server.") - (defun exwm--server-stop () "Stop the subordinate Emacs server." (server-force-delete exwm--server-name) @@ -784,13 +798,6 @@ ;; For other types, return the value as-is. (t result)))))) -(define-obsolete-function-alias 'exwm-enable-ido-workaround 'exwm-config-ido - "25.1" "Enable workarounds for Ido.") - -(defun exwm-disable-ido-workaround () - "This function does nothing actually." - (declare (obsolete nil "25.1"))) - (provide 'exwm) diff --git a/xinitrc b/xinitrc index 873265f..0adc068 100644 --- a/xinitrc +++ b/xinitrc @@ -1,6 +1,9 @@ # Disable access control xhost +SI:localuser:$USER +# Make Java applications aware this is a non-reparenting window manager. +export _JAVA_AWT_WM_NONREPARENTING=1 + # Themes, etc gnome-settings-daemon &