Add customization settings

; Also fix documentations.
This commit is contained in:
Chris Feng 2018-02-19 00:04:27 +08:00
parent 7823eb988c
commit d22e6740d7
11 changed files with 500 additions and 377 deletions

View file

@ -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:

View file

@ -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 (<X window ID> . <Emacs buffer>).")
(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 (<X window ID> . <Emacs buffer>).")
(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.

View file

@ -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))

View file

@ -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

View file

@ -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

View file

@ -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 <Xm/MwmUtil.h> 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 <Xm/MwmUtil.h> 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)))

View file

@ -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)

View file

@ -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))

View file

@ -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

59
exwm.el
View file

@ -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)

View file

@ -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 &