Fix bytecompiler warnings, improve docstrings

* exwm-core.el:
* exwm-input.el:
* exwm-layout.el:
* exwm-manage.el:
* exwm-systemtray.el:
* exwm-workspace.el:
* exwm-xim.el: Improve docstrings.

* exwm-xim.el (cl-lib): Require `cl-lib' at runtime for
  `cl-position'.
* exwm-core.el (exwm-debug): Specify custom's group.
* exwm-systemtray.el (xcb:systemtray:-ClientMessage): Quote
  `:initform''s argument.
This commit is contained in:
Adrián Medraño Calvo 2023-08-18 00:00:00 +00:00
parent c7d1fd45bc
commit d3567a8c7f
8 changed files with 198 additions and 99 deletions

View file

@ -93,10 +93,12 @@ Here are some predefined candidates:
(frame-or-index &optional id)) (frame-or-index &optional id))
(define-minor-mode exwm-debug (define-minor-mode exwm-debug
"Debug-logging enabled if non-nil" "Debug-logging enabled if non-nil."
:global t) :global t
:group 'exwm-debug)
(defmacro exwm--debug (&rest forms) (defmacro exwm--debug (&rest forms)
"Evaluate FORMS if mode `exwm-debug' is active."
(when exwm-debug `(progn ,@forms))) (when exwm-debug `(progn ,@forms)))
(defmacro exwm--log (&optional format-string &rest objects) (defmacro exwm--log (&optional format-string &rest objects)
@ -161,7 +163,9 @@ Nil can be passed as placeholder."
:x x :y y :width width :height height))) :x x :y y :width width :height height)))
(defun exwm--intern-atom (atom &optional conn) (defun exwm--intern-atom (atom &optional conn)
"Intern X11 ATOM." "Intern X11 ATOM.
If CONN is non-nil, use it instead of the value of the variable
`exwm--connection'."
(slot-value (xcb:+request-unchecked+reply (or conn exwm--connection) (slot-value (xcb:+request-unchecked+reply (or conn exwm--connection)
(make-instance 'xcb:InternAtom (make-instance 'xcb:InternAtom
:only-if-exists 0 :only-if-exists 0
@ -206,7 +210,10 @@ If FRAME is null, use selected frame."
(defun exwm--get-visual-depth-colormap (conn id) (defun exwm--get-visual-depth-colormap (conn id)
"Get visual, depth and colormap from X window ID. "Get visual, depth and colormap from X window ID.
Return a three element list with the respective results." Return a three element list with the respective results.
If CONN is non-nil, use it instead of the value of the variable
`exwm--connection'."
(let (ret-visual ret-depth ret-colormap) (let (ret-visual ret-depth ret-colormap)
(with-slots (visual colormap) (with-slots (visual colormap)
(xcb:+request-unchecked+reply conn (xcb:+request-unchecked+reply conn
@ -238,7 +245,7 @@ One of `line-mode' or `char-mode'.")
(defvar-local exwm--geometry nil) (defvar-local exwm--geometry nil)
(defvar-local exwm-class-name nil "Class name in WM_CLASS.") (defvar-local exwm-class-name nil "Class name in WM_CLASS.")
(defvar-local exwm-instance-name nil "Instance name in WM_CLASS.") (defvar-local exwm-instance-name nil "Instance name in WM_CLASS.")
(defvar-local exwm-title nil "Window title (either _NET_WM_NAME or WM_NAME)") (defvar-local exwm-title nil "Window title (either _NET_WM_NAME or WM_NAME).")
(defvar-local exwm--title-is-utf8 nil) (defvar-local exwm--title-is-utf8 nil)
(defvar-local exwm-transient-for nil "WM_TRANSIENT_FOR.") (defvar-local exwm-transient-for nil "WM_TRANSIENT_FOR.")
(defvar-local exwm--protocols nil) (defvar-local exwm--protocols nil)

View file

@ -45,9 +45,9 @@
(defcustom exwm-input-prefix-keys (defcustom exwm-input-prefix-keys
'(?\C-x ?\C-u ?\C-h ?\M-x ?\M-` ?\M-& ?\M-:) '(?\C-x ?\C-u ?\C-h ?\M-x ?\M-` ?\M-& ?\M-:)
"List of prefix keys EXWM should forward to Emacs when in line-mode. "List of prefix keys EXWM should forward to Emacs when in `line-mode'.
The point is to make keys like 'C-x C-f' forwarded to Emacs in line-mode. The point is to make keys like 'C-x C-f' forwarded to Emacs in `line-mode'.
There is no need to add prefix keys for global/simulation keys or those There is no need to add prefix keys for global/simulation keys or those
defined in `exwm-mode-map' here." defined in `exwm-mode-map' here."
:type '(repeat key-sequence) :type '(repeat key-sequence)
@ -87,7 +87,7 @@ defined in `exwm-mode-map' here."
value)))) value))))
(defcustom exwm-input-line-mode-passthrough nil (defcustom exwm-input-line-mode-passthrough nil
"Non-nil makes 'line-mode' forward all events to Emacs." "Non-nil makes `line-mode' forward all events to Emacs."
:type 'boolean) :type 'boolean)
;; Input focus update requests should be accumulated for a short time ;; Input focus update requests should be accumulated for a short time
@ -115,13 +115,13 @@ defined in `exwm-mode-map' here."
(defvar exwm-input--local-simulation-keys nil (defvar exwm-input--local-simulation-keys nil
"Whether simulation keys are local.") "Whether simulation keys are local.")
(defvar exwm-input--simulation-keys nil "Simulation keys in line-mode.") (defvar exwm-input--simulation-keys nil "Simulation keys in `line-mode'.")
(defvar exwm-input--skip-buffer-list-update nil (defvar exwm-input--skip-buffer-list-update nil
"Skip the upcoming 'buffer-list-update'.") "Skip the upcoming `buffer-list-update'.")
(defvar exwm-input--temp-line-mode nil (defvar exwm-input--temp-line-mode nil
"Non-nil indicates it's in temporary line-mode for char-mode.") "Non-nil indicates it's in temporary line-mode for `char-mode'.")
(defvar exwm-input--timestamp-atom nil) (defvar exwm-input--timestamp-atom nil)
@ -713,7 +713,7 @@ Current buffer must be an `exwm-mode' buffer."
(xcb:flush exwm--connection)))) (xcb:flush exwm--connection))))
(defun exwm-input--on-KeyPress-char-mode (key-press &optional _raw-data) (defun exwm-input--on-KeyPress-char-mode (key-press &optional _raw-data)
"Handle KeyPress event in char-mode." "Handle KeyPress event in `char-mode'."
(with-slots (detail state) key-press (with-slots (detail state) key-press
(let ((keysym (xcb:keysyms:keycode->keysym exwm--connection detail state)) (let ((keysym (xcb:keysyms:keycode->keysym exwm--connection detail state))
event raw-event) event raw-event)
@ -754,7 +754,7 @@ button event."
xcb:Allow:ReplayPointer)))) xcb:Allow:ReplayPointer))))
(defun exwm-input--on-ButtonPress-char-mode () (defun exwm-input--on-ButtonPress-char-mode ()
"Handle button events in char-mode. "Handle button events in `char-mode'.
The return value is used as event_mode to release the original The return value is used as event_mode to release the original
button event." button event."
(exwm--log) (exwm--log)
@ -830,7 +830,7 @@ button event."
;;;###autoload ;;;###autoload
(defun exwm-input-grab-keyboard (&optional id) (defun exwm-input-grab-keyboard (&optional id)
"Switch to line-mode." "Switch to `line-mode'."
(interactive (list (when (derived-mode-p 'exwm-mode) (interactive (list (when (derived-mode-p 'exwm-mode)
(exwm--buffer->id (window-buffer))))) (exwm--buffer->id (window-buffer)))))
(when id (when id
@ -841,7 +841,7 @@ button event."
;;;###autoload ;;;###autoload
(defun exwm-input-release-keyboard (&optional id) (defun exwm-input-release-keyboard (&optional id)
"Switch to char-mode." "Switch to `char-mode`."
(interactive (list (when (derived-mode-p 'exwm-mode) (interactive (list (when (derived-mode-p 'exwm-mode)
(exwm--buffer->id (window-buffer))))) (exwm--buffer->id (window-buffer)))))
(when id (when id
@ -852,7 +852,7 @@ button event."
;;;###autoload ;;;###autoload
(defun exwm-input-toggle-keyboard (&optional id) (defun exwm-input-toggle-keyboard (&optional id)
"Toggle between 'line-mode' and 'char-mode'." "Toggle between `line-mode' and `char-mode'."
(interactive (list (when (derived-mode-p 'exwm-mode) (interactive (list (when (derived-mode-p 'exwm-mode)
(exwm--buffer->id (window-buffer))))) (exwm--buffer->id (window-buffer)))))
(when id (when id
@ -969,7 +969,7 @@ multiple keys. If END-KEY is non-nil, stop sending keys if it's pressed."
It is an alist of the form (original-key . simulated-key), where both It is an alist of the form (original-key . simulated-key), where both
original-key and simulated-key are key sequences. Original-key is what you original-key and simulated-key are key sequences. Original-key is what you
type to an X window in line-mode which then gets translated to simulated-key type to an X window in `line-mode' which then gets translated to simulated-key
by EXWM and forwarded to the X window. by EXWM and forwarded to the X window.
Notes: Notes:
@ -1080,7 +1080,7 @@ where both ORIGINAL-KEY and SIMULATED-KEY are key sequences."
(defmacro exwm-input-invoke-factory (keys) (defmacro exwm-input-invoke-factory (keys)
"Make a command that invokes KEYS when called. "Make a command that invokes KEYS when called.
One use is to access the keymap bound to KEYS (as prefix keys) in char-mode." One use is to access the keymap bound to KEYS (as prefix keys) in `char-mode'."
(let* ((keys (kbd keys)) (let* ((keys (kbd keys))
(description (key-description keys))) (description (key-description keys)))
`(defun ,(intern (concat "exwm-input--invoke--" description)) () `(defun ,(intern (concat "exwm-input--invoke--" description)) ()

View file

@ -57,6 +57,7 @@
(declare-function exwm-input--grab-keyboard "exwm-input.el") (declare-function exwm-input--grab-keyboard "exwm-input.el")
(declare-function exwm-input-grab-keyboard "exwm-input.el") (declare-function exwm-input-grab-keyboard "exwm-input.el")
(declare-function exwm-workspace--active-p "exwm-workspace.el" (frame)) (declare-function exwm-workspace--active-p "exwm-workspace.el" (frame))
(declare-function exwm-workspace--get-geometry "exwm-workspace.el" (frame))
(declare-function exwm-workspace--minibuffer-own-frame-p "exwm-workspace.el") (declare-function exwm-workspace--minibuffer-own-frame-p "exwm-workspace.el")
(declare-function exwm-workspace--workspace-p "exwm-workspace.el" (declare-function exwm-workspace--workspace-p "exwm-workspace.el"
(workspace)) (workspace))
@ -64,7 +65,7 @@
(frame-or-index &optional id)) (frame-or-index &optional id))
(defun exwm-layout--set-state (id state) (defun exwm-layout--set-state (id state)
"Set WM_STATE." "Set WM_STATE of X window ID to STATE."
(exwm--log "id=#x%x" id) (exwm--log "id=#x%x" id)
(xcb:+request exwm--connection (xcb:+request exwm--connection
(make-instance 'xcb:icccm:set-WM_STATE (make-instance 'xcb:icccm:set-WM_STATE
@ -73,24 +74,28 @@
(setq exwm-state state))) (setq exwm-state state)))
(defun exwm-layout--iconic-state-p (&optional id) (defun exwm-layout--iconic-state-p (&optional id)
"Check whether X window ID is in iconic state."
(= xcb:icccm:WM_STATE:IconicState (= xcb:icccm:WM_STATE:IconicState
(if id (if id
(buffer-local-value 'exwm-state (exwm--id->buffer id)) (buffer-local-value 'exwm-state (exwm--id->buffer id))
exwm-state))) exwm-state)))
(defun exwm-layout--set-ewmh-state (xwin) (defun exwm-layout--set-ewmh-state (id)
"Set _NET_WM_STATE." "Set _NET_WM_STATE of X window ID to the value of variable `exwm--ewmh-state'."
(with-current-buffer (exwm--id->buffer xwin) (with-current-buffer (exwm--id->buffer id)
(xcb:+request exwm--connection (xcb:+request exwm--connection
(make-instance 'xcb:ewmh:set-_NET_WM_STATE (make-instance 'xcb:ewmh:set-_NET_WM_STATE
:window exwm--id :window exwm--id
:data exwm--ewmh-state)))) :data exwm--ewmh-state))))
(defun exwm-layout--fullscreen-p () (defun exwm-layout--fullscreen-p ()
"Check whether current `exwm-mode' buffer is in fullscreen state."
(when (derived-mode-p 'exwm-mode) (when (derived-mode-p 'exwm-mode)
(memq xcb:Atom:_NET_WM_STATE_FULLSCREEN exwm--ewmh-state))) (memq xcb:Atom:_NET_WM_STATE_FULLSCREEN exwm--ewmh-state)))
(defun exwm-layout--auto-iconify () (defun exwm-layout--auto-iconify ()
"Helper function to iconify unused X windows.
See variable `exwm-layout-auto-iconify'."
(when (and exwm-layout-auto-iconify (when (and exwm-layout-auto-iconify
(not exwm-transient-for)) (not exwm-transient-for))
(let ((xwin exwm--id) (let ((xwin exwm--id)
@ -210,7 +215,7 @@
;;;###autoload ;;;###autoload
(cl-defun exwm-layout-unset-fullscreen (&optional id) (cl-defun exwm-layout-unset-fullscreen (&optional id)
"Restore window from fullscreen state." "Restore X window ID from fullscreen state."
(interactive) (interactive)
(exwm--log "id=#x%x" (or id 0)) (exwm--log "id=#x%x" (or id 0))
(unless (and (or id (derived-mode-p 'exwm-mode)) (unless (and (or id (derived-mode-p 'exwm-mode))
@ -241,7 +246,7 @@
;;;###autoload ;;;###autoload
(cl-defun exwm-layout-toggle-fullscreen (&optional id) (cl-defun exwm-layout-toggle-fullscreen (&optional id)
"Toggle fullscreen mode." "Toggle fullscreen mode of X window ID."
(interactive (list (exwm--buffer->id (window-buffer)))) (interactive (list (exwm--buffer->id (window-buffer))))
(exwm--log "id=#x%x" (or id 0)) (exwm--log "id=#x%x" (or id 0))
(unless (or id (derived-mode-p 'exwm-mode)) (unless (or id (derived-mode-p 'exwm-mode))
@ -298,7 +303,8 @@ selected by `other-buffer'."
clients clients-floating)))))) clients clients-floating))))))
(defun exwm-layout--refresh (&optional frame) (defun exwm-layout--refresh (&optional frame)
"Refresh layout." "Refresh layout of FRAME.
If FRAME is nil, refresh layout of selected frame."
;; `window-size-change-functions' sets this argument while ;; `window-size-change-functions' sets this argument while
;; `window-configuration-change-hook' makes the frame selected. ;; `window-configuration-change-hook' makes the frame selected.
(unless frame (unless frame
@ -412,7 +418,8 @@ selected by `other-buffer'."
(exwm-layout--refresh frame))))))) (exwm-layout--refresh frame)))))))
(defun exwm-layout--on-echo-area-change (&optional dirty) (defun exwm-layout--on-echo-area-change (&optional dirty)
"Run when message arrives or in `echo-area-clear-hook' to refresh layout." "Run when message arrives or in `echo-area-clear-hook' to refresh layout.
If DIRTY is non-nil, refresh layout immediately."
(let ((frame (window-frame (active-minibuffer-window))) (let ((frame (window-frame (active-minibuffer-window)))
(msg (current-message))) (msg (current-message)))
;; Check whether the frame where current window's minibuffer resides (not ;; Check whether the frame where current window's minibuffer resides (not

View file

@ -34,8 +34,8 @@
:group 'exwm) :group 'exwm)
(defcustom 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 "Normal hook run after a window is just managed.
corresponding buffer." This hook runs in the context of the corresponding `exwm-mode' buffer."
:type 'hook) :type 'hook)
(defcustom exwm-manage-force-tiling nil (defcustom exwm-manage-force-tiling nil
@ -169,10 +169,13 @@ want to match against EXWM internal variables such as `exwm-title',
(declare-function exwm--update-window-type "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--set-floating "exwm-floating.el" (id))
(declare-function exwm-floating--unset-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-input-grab-keyboard "exwm-input.el" (&optional id))
(declare-function exwm-input-release-keyboard "exwm-input.el" (&optional id))
(declare-function exwm-input-set-local-simulation-keys "exwm-input.el") (declare-function exwm-input-set-local-simulation-keys "exwm-input.el")
(declare-function exwm-layout--fullscreen-p "exwm-layout.el" ()) (declare-function exwm-layout--fullscreen-p "exwm-layout.el" ())
(declare-function exwm-layout--iconic-state-p "exwm-layout.el" (&optional id)) (declare-function exwm-layout--iconic-state-p "exwm-layout.el" (&optional id))
(declare-function exwm-layout-set-fullscreen "exwm-layout.el" (&optional id))
(declare-function exwm-workspace--get-geometry "exwm-workspace.el" (frame))
(declare-function exwm-workspace--position "exwm-workspace.el" (frame)) (declare-function exwm-workspace--position "exwm-workspace.el" (frame))
(declare-function exwm-workspace--set-fullscreen "exwm-workspace.el" (frame)) (declare-function exwm-workspace--set-fullscreen "exwm-workspace.el" (frame))
(declare-function exwm-workspace--update-struts "exwm-workspace.el" ()) (declare-function exwm-workspace--update-struts "exwm-workspace.el" ())
@ -180,7 +183,8 @@ want to match against EXWM internal variables such as `exwm-title',
(declare-function exwm-workspace--workarea "exwm-workspace.el" (frame)) (declare-function exwm-workspace--workarea "exwm-workspace.el" (frame))
(defun exwm-manage--update-geometry (id &optional force) (defun exwm-manage--update-geometry (id &optional force)
"Update window geometry." "Update geometry of X window ID.
Override current geometry if FORCE is non-nil."
(exwm--log "id=#x%x" id) (exwm--log "id=#x%x" id)
(with-current-buffer (exwm--id->buffer id) (with-current-buffer (exwm--id->buffer id)
(unless (and exwm--geometry (not force)) (unless (and exwm--geometry (not force))
@ -196,7 +200,7 @@ want to match against EXWM internal variables such as `exwm-title',
:height (/ (x-display-pixel-height) 2)))))))) :height (/ (x-display-pixel-height) 2))))))))
(defun exwm-manage--update-ewmh-state (id) (defun exwm-manage--update-ewmh-state (id)
"Update _NET_WM_STATE." "Update _NET_WM_STATE of X window ID."
(exwm--log "id=#x%x" id) (exwm--log "id=#x%x" id)
(with-current-buffer (exwm--id->buffer id) (with-current-buffer (exwm--id->buffer id)
(unless exwm--ewmh-state (unless exwm--ewmh-state
@ -207,7 +211,8 @@ want to match against EXWM internal variables such as `exwm-title',
(setq exwm--ewmh-state (append (slot-value reply 'value) nil))))))) (setq exwm--ewmh-state (append (slot-value reply 'value) nil)))))))
(defun exwm-manage--update-mwm-hints (id &optional force) (defun exwm-manage--update-mwm-hints (id &optional force)
"Update _MOTIF_WM_HINTS." "Update _MOTIF_WM_HINTS of X window ID.
Override current hinds if FORCE is non-nil."
(exwm--log "id=#x%x" id) (exwm--log "id=#x%x" id)
(with-current-buffer (exwm--id->buffer id) (with-current-buffer (exwm--id->buffer id)
(unless (and (not exwm--mwm-hints-decorations) (not force)) (unless (and (not exwm--mwm-hints-decorations) (not force))
@ -411,7 +416,7 @@ want to match against EXWM internal variables such as `exwm-title',
"Unmanage window ID. "Unmanage window ID.
If WITHDRAW-ONLY is non-nil, the X window will be properly placed back to the If WITHDRAW-ONLY is non-nil, the X window will be properly placed back to the
root window. Set WITHDRAW-ONLY to 'quit if this functions is used when window root window. Set WITHDRAW-ONLY to `quit' if this functions is used when window
manager is shutting down." manager is shutting down."
(let ((buffer (exwm--id->buffer id))) (let ((buffer (exwm--id->buffer id)))
(exwm--log "Unmanage #x%x (buffer: %s, widthdraw: %s)" (exwm--log "Unmanage #x%x (buffer: %s, widthdraw: %s)"
@ -591,7 +596,8 @@ Would you like to kill it? "
(throw 'return nil))))) (throw 'return nil)))))
(defun exwm-manage--kill-client (&optional id) (defun exwm-manage--kill-client (&optional id)
"Kill an X client." "Kill X client ID.
If ID is nil, kill X window corresponding to current buffer."
(unless id (setq id (exwm--buffer->id (current-buffer)))) (unless id (setq id (exwm--buffer->id (current-buffer))))
(exwm--log "id=#x%x" id) (exwm--log "id=#x%x" id)
(let* ((response (xcb:+request-unchecked+reply exwm--connection (let* ((response (xcb:+request-unchecked+reply exwm--connection
@ -609,14 +615,16 @@ Would you like to kill it? "
(xcb:flush exwm--connection))) (xcb:flush exwm--connection)))
(defun exwm-manage--add-frame (frame) (defun exwm-manage--add-frame (frame)
"Run in `after-make-frame-functions'." "Run in `after-make-frame-functions'.
FRAME is the newly created frame."
(exwm--log "frame=%s" frame) (exwm--log "frame=%s" frame)
(when (display-graphic-p frame) (when (display-graphic-p frame)
(push (string-to-number (frame-parameter frame 'outer-window-id)) (push (string-to-number (frame-parameter frame 'outer-window-id))
exwm-manage--frame-outer-id-list))) exwm-manage--frame-outer-id-list)))
(defun exwm-manage--remove-frame (frame) (defun exwm-manage--remove-frame (frame)
"Run in `delete-frame-functions'." "Run in `delete-frame-functions'.
FRAME is the frame to be deleted."
(exwm--log "frame=%s" frame) (exwm--log "frame=%s" frame)
(when (display-graphic-p frame) (when (display-graphic-p frame)
(setq exwm-manage--frame-outer-id-list (setq exwm-manage--frame-outer-id-list
@ -624,7 +632,8 @@ Would you like to kill it? "
exwm-manage--frame-outer-id-list)))) exwm-manage--frame-outer-id-list))))
(defun exwm-manage--on-ConfigureRequest (data _synthetic) (defun exwm-manage--on-ConfigureRequest (data _synthetic)
"Handle ConfigureRequest event." "Handle ConfigureRequest event.
DATA contains unmarshalled ConfigureRequest event data."
(exwm--log) (exwm--log)
(let ((obj (make-instance 'xcb:ConfigureRequest)) (let ((obj (make-instance 'xcb:ConfigureRequest))
buffer edges width-delta height-delta) buffer edges width-delta height-delta)
@ -714,7 +723,8 @@ border-width: %d; sibling: #x%x; stack-mode: %d"
(xcb:flush exwm--connection)) (xcb:flush exwm--connection))
(defun exwm-manage--on-MapRequest (data _synthetic) (defun exwm-manage--on-MapRequest (data _synthetic)
"Handle MapRequest event." "Handle MapRequest event.
DATA contains unmarshalled MapRequest event data."
(let ((obj (make-instance 'xcb:MapRequest))) (let ((obj (make-instance 'xcb:MapRequest)))
(xcb:unmarshal obj data) (xcb:unmarshal obj data)
(with-slots (parent window) obj (with-slots (parent window) obj
@ -734,7 +744,8 @@ border-width: %d; sibling: #x%x; stack-mode: %d"
(exwm-manage--manage-window window)))))) (exwm-manage--manage-window window))))))
(defun exwm-manage--on-UnmapNotify (data _synthetic) (defun exwm-manage--on-UnmapNotify (data _synthetic)
"Handle UnmapNotify event." "Handle UnmapNotify event.
DATA contains unmarshalled UnmapNotify event data."
(let ((obj (make-instance 'xcb:UnmapNotify))) (let ((obj (make-instance 'xcb:UnmapNotify)))
(xcb:unmarshal obj data) (xcb:unmarshal obj data)
(with-slots (window) obj (with-slots (window) obj
@ -742,7 +753,8 @@ border-width: %d; sibling: #x%x; stack-mode: %d"
(exwm-manage--unmanage-window window t)))) (exwm-manage--unmanage-window window t))))
(defun exwm-manage--on-MapNotify (data _synthetic) (defun exwm-manage--on-MapNotify (data _synthetic)
"Handle MapNotify event." "Handle MapNotify event.
DATA contains unmarshalled MapNotify event data."
(let ((obj (make-instance 'xcb:MapNotify))) (let ((obj (make-instance 'xcb:MapNotify)))
(xcb:unmarshal obj data) (xcb:unmarshal obj data)
(with-slots (window) obj (with-slots (window) obj
@ -767,7 +779,9 @@ border-width: %d; sibling: #x%x; stack-mode: %d"
(xcb:flush exwm--connection))))) (xcb:flush exwm--connection)))))
(defun exwm-manage--on-DestroyNotify (data synthetic) (defun exwm-manage--on-DestroyNotify (data synthetic)
"Handle DestroyNotify event." "Handle DestroyNotify event.
DATA contains unmarshalled DestroyNotify event data.
SYNTHETIC indicates whether the event is a synthetic event."
(unless synthetic (unless synthetic
(exwm--log) (exwm--log)
(let ((obj (make-instance 'xcb:DestroyNotify))) (let ((obj (make-instance 'xcb:DestroyNotify)))

View file

@ -49,7 +49,7 @@
(defclass xcb:systemtray:-ClientMessage (defclass xcb:systemtray:-ClientMessage
(xcb:icccm:--ClientMessage xcb:ClientMessage) (xcb:icccm:--ClientMessage xcb:ClientMessage)
((format :initform 32) ((format :initform 32)
(type :initform xcb:Atom:MANAGER) (type :initform 'xcb:Atom:MANAGER)
(time :initarg :time :type xcb:TIMESTAMP) ;new slot (time :initarg :time :type xcb:TIMESTAMP) ;new slot
(selection :initarg :selection :type xcb:ATOM) ;new slot (selection :initarg :selection :type xcb:ATOM) ;new slot
(owner :initarg :owner :type xcb:WINDOW)) ;new slot (owner :initarg :owner :type xcb:WINDOW)) ;new slot
@ -121,7 +121,7 @@ using 32-bit depth. Using `workspace-background' instead.")
(defvar xcb:Atom:_NET_SYSTEM_TRAY_S0) (defvar xcb:Atom:_NET_SYSTEM_TRAY_S0)
(defun exwm-systemtray--embed (icon) (defun exwm-systemtray--embed (icon)
"Embed an icon." "Embed an ICON."
(exwm--log "Try to embed #x%x" icon) (exwm--log "Try to embed #x%x" icon)
(let ((info (xcb:+request-unchecked+reply exwm-systemtray--connection (let ((info (xcb:+request-unchecked+reply exwm-systemtray--connection
(make-instance 'xcb:xembed:get-_XEMBED_INFO (make-instance 'xcb:xembed:get-_XEMBED_INFO
@ -210,7 +210,7 @@ using 32-bit depth. Using `workspace-background' instead.")
(exwm-systemtray--refresh)))) (exwm-systemtray--refresh))))
(defun exwm-systemtray--unembed (icon) (defun exwm-systemtray--unembed (icon)
"Unembed an icon." "Unembed an ICON."
(exwm--log "Unembed #x%x" icon) (exwm--log "Unembed #x%x" icon)
(xcb:+request exwm-systemtray--connection (xcb:+request exwm-systemtray--connection
(make-instance 'xcb:UnmapWindow :window icon)) (make-instance 'xcb:UnmapWindow :window icon))
@ -331,7 +331,8 @@ indicate how to support actual transparency."
(<= planes 24)))) (<= planes 24))))
(defun exwm-systemtray--on-DestroyNotify (data _synthetic) (defun exwm-systemtray--on-DestroyNotify (data _synthetic)
"Unembed icons on DestroyNotify." "Unembed icons on DestroyNotify.
Argument DATA contains the raw event data."
(exwm--log) (exwm--log)
(let ((obj (make-instance 'xcb:DestroyNotify))) (let ((obj (make-instance 'xcb:DestroyNotify)))
(xcb:unmarshal obj data) (xcb:unmarshal obj data)
@ -340,7 +341,8 @@ indicate how to support actual transparency."
(exwm-systemtray--unembed window))))) (exwm-systemtray--unembed window)))))
(defun exwm-systemtray--on-ReparentNotify (data _synthetic) (defun exwm-systemtray--on-ReparentNotify (data _synthetic)
"Unembed icons on ReparentNotify." "Unembed icons on ReparentNotify.
Argument DATA contains the raw event data."
(exwm--log) (exwm--log)
(let ((obj (make-instance 'xcb:ReparentNotify))) (let ((obj (make-instance 'xcb:ReparentNotify)))
(xcb:unmarshal obj data) (xcb:unmarshal obj data)
@ -350,7 +352,8 @@ indicate how to support actual transparency."
(exwm-systemtray--unembed window))))) (exwm-systemtray--unembed window)))))
(defun exwm-systemtray--on-ResizeRequest (data _synthetic) (defun exwm-systemtray--on-ResizeRequest (data _synthetic)
"Resize the tray icon on ResizeRequest." "Resize the tray icon on ResizeRequest.
Argument DATA contains the raw event data."
(exwm--log) (exwm--log)
(let ((obj (make-instance 'xcb:ResizeRequest)) (let ((obj (make-instance 'xcb:ResizeRequest))
attr) attr)
@ -378,7 +381,8 @@ indicate how to support actual transparency."
(exwm-systemtray--refresh))))) (exwm-systemtray--refresh)))))
(defun exwm-systemtray--on-PropertyNotify (data _synthetic) (defun exwm-systemtray--on-PropertyNotify (data _synthetic)
"Map/Unmap the tray icon on PropertyNotify." "Map/Unmap the tray icon on PropertyNotify.
Argument DATA contains the raw event data."
(exwm--log) (exwm--log)
(let ((obj (make-instance 'xcb:PropertyNotify)) (let ((obj (make-instance 'xcb:PropertyNotify))
attr info visible) attr info visible)
@ -403,7 +407,8 @@ indicate how to support actual transparency."
(exwm-systemtray--refresh)))))) (exwm-systemtray--refresh))))))
(defun exwm-systemtray--on-ClientMessage (data _synthetic) (defun exwm-systemtray--on-ClientMessage (data _synthetic)
"Handle client messages." "Handle client messages.
Argument DATA contains the raw event data."
(let ((obj (make-instance 'xcb:ClientMessage)) (let ((obj (make-instance 'xcb:ClientMessage))
opcode data32) opcode data32)
(xcb:unmarshal obj data) (xcb:unmarshal obj data)
@ -422,7 +427,8 @@ indicate how to support actual transparency."
(exwm--log "Unknown opcode message: %s" obj))))))) (exwm--log "Unknown opcode message: %s" obj)))))))
(defun exwm-systemtray--on-KeyPress (data _synthetic) (defun exwm-systemtray--on-KeyPress (data _synthetic)
"Forward all KeyPress events to Emacs frame." "Forward all KeyPress events to Emacs frame.
Argument DATA contains the raw event data."
(exwm--log) (exwm--log)
;; This function is only executed when there's no autohide minibuffer, ;; This function is only executed when there's no autohide minibuffer,
;; a workspace frame has the input focus and the pointer is over a ;; a workspace frame has the input focus and the pointer is over a

View file

@ -39,8 +39,8 @@
:type 'hook) :type 'hook)
(defcustom exwm-workspace-list-change-hook nil (defcustom exwm-workspace-list-change-hook nil
"Normal hook run when the workspace list is changed (workspace added, "Normal hook run when the workspace list is changed.
deleted, moved, etc)." This happens when a workspace is added, deleted, moved, etc."
:type 'hook) :type 'hook)
(defcustom exwm-workspace-show-all-buffers nil (defcustom exwm-workspace-show-all-buffers nil
@ -74,8 +74,7 @@ A restart is required for this change to take effect."
:type 'integer) :type 'integer)
(defcustom exwm-workspace-switch-create-limit 10 (defcustom exwm-workspace-switch-create-limit 10
"Number of workspaces `exwm-workspace-switch-create' allowed to create "Number of workspaces `exwm-workspace-switch-create' is allowed to create."
each time."
:type 'integer) :type 'integer)
(defvar exwm-workspace-current-index 0 "Index of current active workspace.") (defvar exwm-workspace-current-index 0 "Index of current active workspace.")
@ -176,6 +175,7 @@ FRAME may be either a workspace frame or a workspace position."
"Keymap used for interactively selecting workspace.") "Keymap used for interactively selecting workspace.")
(defun exwm-workspace--init-switch-map () (defun exwm-workspace--init-switch-map ()
"Initialize variable `exwm-workspace--switch-map'."
(let ((map (make-sparse-keymap))) (let ((map (make-sparse-keymap)))
(define-key map [t] (lambda () (interactive))) (define-key map [t] (lambda () (interactive)))
(define-key map "+" #'exwm-workspace--prompt-add) (define-key map "+" #'exwm-workspace--prompt-add)
@ -226,7 +226,8 @@ FRAME may be either a workspace frame or a workspace position."
(t (user-error "[EXWM] Invalid workspace: %s" frame-or-index)))) (t (user-error "[EXWM] Invalid workspace: %s" frame-or-index))))
(defun exwm-workspace--prompt-for-workspace (&optional prompt) (defun exwm-workspace--prompt-for-workspace (&optional prompt)
"Prompt for a workspace, returning the workspace frame." "Prompt for a workspace, returning the workspace frame.
Show PROMPT to the user if non-nil."
(exwm-workspace--update-switch-history) (exwm-workspace--update-switch-history)
(let* ((current-idx (exwm-workspace--position exwm-workspace--current)) (let* ((current-idx (exwm-workspace--position exwm-workspace--current))
(history-add-new-input nil) ;prevent modifying history (history-add-new-input nil) ;prevent modifying history
@ -437,7 +438,8 @@ FRAME may be either a workspace frame or a workspace position."
exwm-workspace--window-y-offset (- (elt edges 1) y)))))))) exwm-workspace--window-y-offset (- (elt edges 1) y))))))))
(defun exwm-workspace--set-active (frame active) (defun exwm-workspace--set-active (frame active)
"Make frame FRAME active on its monitor." "Make frame FRAME active on its monitor.
ACTIVE indicates whether to set the frame active or inactive."
(exwm--log "active=%s; frame=%s" active frame) (exwm--log "active=%s; frame=%s" active frame)
(set-frame-parameter frame 'exwm-active active) (set-frame-parameter frame 'exwm-active active)
(if active (if active
@ -447,7 +449,7 @@ FRAME may be either a workspace frame or a workspace position."
(xcb:flush exwm--connection)) (xcb:flush exwm--connection))
(defun exwm-workspace--active-p (frame) (defun exwm-workspace--active-p (frame)
"Return non-nil if FRAME is active" "Return non-nil if FRAME is active."
(frame-parameter frame 'exwm-active)) (frame-parameter frame 'exwm-active))
(defun exwm-workspace--set-fullscreen (frame) (defun exwm-workspace--set-fullscreen (frame)
@ -560,11 +562,13 @@ PREFIX-DIGITS is a list of the digits introduced so far."
;;;###autoload ;;;###autoload
(defun exwm-workspace-switch (frame-or-index &optional force) (defun exwm-workspace-switch (frame-or-index &optional force)
"Switch to workspace INDEX (0-based). "Switch to workspace FRAME-OR-INDEX (0-based).
Query for the index if not specified when called interactively. Passing a 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 workspace frame as the first option or making use of the rest options are
for internal use only." for internal use only.
When FORCE is true, allow switching to current workspace."
(interactive (interactive
(list (list
(cond (cond
@ -690,7 +694,7 @@ for internal use only."
;;;###autoload ;;;###autoload
(defun exwm-workspace-switch-create (frame-or-index) (defun exwm-workspace-switch-create (frame-or-index)
"Switch to workspace INDEX or creating it first if it does not exist yet. "Switch to workspace FRAME-OR-INDEX creating it first non-existent.
Passing a workspace frame as the first option is for internal use only." Passing a workspace frame as the first option is for internal use only."
(interactive (interactive
@ -976,7 +980,7 @@ INDEX must not exceed the current number of workspaces."
;;;###autoload ;;;###autoload
(defun exwm-workspace-switch-to-buffer (buffer-or-name) (defun exwm-workspace-switch-to-buffer (buffer-or-name)
"Make the current Emacs window display another buffer." "Make selected window display BUFFER-OR-NAME."
(interactive (interactive
(let ((inhibit-quit t)) (let ((inhibit-quit t))
;; Show all buffers ;; Show all buffers
@ -1028,7 +1032,7 @@ INDEX must not exceed the current number of workspaces."
(switch-to-buffer buffer-or-name))))) (switch-to-buffer buffer-or-name)))))
(defun exwm-workspace-rename-buffer (newname) (defun exwm-workspace-rename-buffer (newname)
"Rename a buffer." "Rename current buffer to NEWNAME."
(let ((hidden (= ?\s (aref newname 0))) (let ((hidden (= ?\s (aref newname 0)))
(basename (replace-regexp-in-string "<[0-9]+>$" "" newname)) (basename (replace-regexp-in-string "<[0-9]+>$" "" newname))
(counter 1) (counter 1)
@ -1044,10 +1048,12 @@ INDEX must not exceed the current number of workspaces."
buffer-list-update-hook))) buffer-list-update-hook)))
(rename-buffer (concat (and hidden " ") newname))))) (rename-buffer (concat (and hidden " ") newname)))))
(defun exwm-workspace--x-create-frame (orig-fun params) (defun exwm-workspace--x-create-frame (orig-x-create-frame params)
"Set override-redirect on the frame created by `x-create-frame'." "Set override-redirect on the frame created by `x-create-frame'.
ORIG-X-CREATE-FRAME is the advised function `x-create-frame'.
PARAMS are the original arguments."
(exwm--log) (exwm--log)
(let ((frame (funcall orig-fun params))) (let ((frame (funcall orig-x-create-frame params)))
(xcb:+request exwm--connection (xcb:+request exwm--connection
(make-instance 'xcb:ChangeWindowAttributes (make-instance 'xcb:ChangeWindowAttributes
:window (string-to-number :window (string-to-number
@ -1066,7 +1072,7 @@ Please check `exwm-workspace--minibuffer-own-frame-p' first."
;;;###autoload ;;;###autoload
(defun exwm-workspace-attach-minibuffer () (defun exwm-workspace-attach-minibuffer ()
"Attach the minibuffer so that it always shows." "Attach the minibuffer making it always visible."
(interactive) (interactive)
(exwm--log) (exwm--log)
(when (and (exwm-workspace--minibuffer-own-frame-p) (when (and (exwm-workspace--minibuffer-own-frame-p)
@ -1118,7 +1124,9 @@ Please check `exwm-workspace--minibuffer-own-frame-p' first."
(exwm-workspace-attach-minibuffer)))) (exwm-workspace-attach-minibuffer))))
(defun exwm-workspace--update-minibuffer-height (&optional echo-area) (defun exwm-workspace--update-minibuffer-height (&optional echo-area)
"Update the minibuffer frame height." "Update the minibuffer frame height.
When ECHO-AREA is non-nil, take the size of the echo area into
account when calculating the height."
(when (exwm--terminal-p) (when (exwm--terminal-p)
(let ((height (let ((height
(with-current-buffer (with-current-buffer
@ -1141,7 +1149,8 @@ Please check `exwm-workspace--minibuffer-own-frame-p' first."
(set-frame-height exwm-workspace--minibuffer height)))) (set-frame-height exwm-workspace--minibuffer height))))
(defun exwm-workspace--on-ConfigureNotify (data _synthetic) (defun exwm-workspace--on-ConfigureNotify (data _synthetic)
"Adjust the container to fit the minibuffer frame." "Adjust the container to fit the minibuffer frame.
DATA contains unmarshalled ConfigureNotify event data."
(let ((obj (make-instance 'xcb:ConfigureNotify)) y) (let ((obj (make-instance 'xcb:ConfigureNotify)) y)
(xcb:unmarshal obj data) (xcb:unmarshal obj data)
(with-slots (window height) obj (with-slots (window height) obj
@ -1180,7 +1189,8 @@ Please check `exwm-workspace--minibuffer-own-frame-p' first."
(xcb:flush exwm--connection))))) (xcb:flush exwm--connection)))))
(defun exwm-workspace--display-buffer (buffer alist) (defun exwm-workspace--display-buffer (buffer alist)
"Display BUFFER as if the current workspace is selected." "Display BUFFER as if the current workspace were selected.
ALIST is an action alist, as accepted by function `display-buffer'."
;; Only when the floating minibuffer frame is selected. ;; Only when the floating minibuffer frame is selected.
;; This also protect this functions from being recursively called. ;; This also protect this functions from being recursively called.
(when (eq (selected-frame) exwm-workspace--minibuffer) (when (eq (selected-frame) exwm-workspace--minibuffer)
@ -1232,7 +1242,7 @@ Please check `exwm-workspace--minibuffer-own-frame-p' first."
(xcb:flush exwm--connection)) (xcb:flush exwm--connection))
(defun exwm-workspace--on-minibuffer-setup () (defun exwm-workspace--on-minibuffer-setup ()
"Run in minibuffer-setup-hook to show the minibuffer and its container." "Run in `minibuffer-setup-hook' to show the minibuffer and its container."
(exwm--log) (exwm--log)
(when (and (= 1 (minibuffer-depth)) (when (and (= 1 (minibuffer-depth))
(exwm--terminal-p)) (exwm--terminal-p))
@ -1254,7 +1264,7 @@ Please check `exwm-workspace--minibuffer-own-frame-p' first."
(window-preserve-size window))))) (window-preserve-size window)))))
(defun exwm-workspace--on-minibuffer-exit () (defun exwm-workspace--on-minibuffer-exit ()
"Run in minibuffer-exit-hook to hide the minibuffer container." "Run in `minibuffer-exit-hook' to hide the minibuffer container."
(exwm--log) (exwm--log)
(when (and (= 1 (minibuffer-depth)) (when (and (= 1 (minibuffer-depth))
(exwm--terminal-p)) (exwm--terminal-p))
@ -1288,7 +1298,7 @@ Please check `exwm-workspace--minibuffer-own-frame-p' first."
#'exwm-workspace--echo-area-maybe-clear)))) #'exwm-workspace--echo-area-maybe-clear))))
(defun exwm-workspace--on-echo-area-clear () (defun exwm-workspace--on-echo-area-clear ()
"Run in echo-area-clear-hook to hide echo area container." "Run in `echo-area-clear-hook' to hide echo area container."
(when (exwm--terminal-p) (when (exwm--terminal-p)
(unless (active-minibuffer-window) (unless (active-minibuffer-window)
(exwm-workspace--hide-minibuffer)) (exwm-workspace--hide-minibuffer))
@ -1398,7 +1408,8 @@ Return nil if FRAME is the only workspace."
nextw))) nextw)))
(defun exwm-workspace--remove-frame-as-workspace (frame &optional quit) (defun exwm-workspace--remove-frame-as-workspace (frame &optional quit)
"Stop treating frame FRAME as a workspace." "Stop treating FRAME as a workspace.
When QUIT is non-nil cleanup avoid communicating with the X server."
;; TODO: restore all frame parameters (e.g. exwm-workspace, buffer-predicate, ;; TODO: restore all frame parameters (e.g. exwm-workspace, buffer-predicate,
;; etc) ;; etc)
(exwm--log "Removing frame `%s' as workspace" frame) (exwm--log "Removing frame `%s' as workspace" frame)
@ -1463,7 +1474,7 @@ Return nil if FRAME is the only workspace."
(run-hooks 'exwm-workspace-list-change-hook))) (run-hooks 'exwm-workspace-list-change-hook)))
(defun exwm-workspace--on-delete-frame (frame) (defun exwm-workspace--on-delete-frame (frame)
"Hook run upon `delete-frame' that tears down FRAME's configuration as a workspace." "Hook run upon `delete-frame' removing FRAME as a workspace."
(cond (cond
((not (exwm-workspace--workspace-p frame)) ((not (exwm-workspace--workspace-p frame))
(exwm--log "Frame `%s' is not a workspace" frame)) (exwm--log "Frame `%s' is not a workspace" frame))
@ -1548,6 +1559,7 @@ applied to all subsequently created X frames."
(interactive "e")) (interactive "e"))
(defun exwm-workspace--init-minibuffer-frame () (defun exwm-workspace--init-minibuffer-frame ()
"Initialize minibuffer-only frame."
(exwm--log) (exwm--log)
;; Initialize workspaces without minibuffers. ;; Initialize workspaces without minibuffers.
(setq exwm-workspace--minibuffer (setq exwm-workspace--minibuffer
@ -1618,6 +1630,7 @@ applied to all subsequently created X frames."
:test #'equal)) :test #'equal))
(defun exwm-workspace--exit-minibuffer-frame () (defun exwm-workspace--exit-minibuffer-frame ()
"Cleanup minibuffer-only frame."
(exwm--log) (exwm--log)
;; Only on minibuffer-frame. ;; Only on minibuffer-frame.
(remove-hook 'minibuffer-setup-hook #'exwm-workspace--on-minibuffer-setup) (remove-hook 'minibuffer-setup-hook #'exwm-workspace--on-minibuffer-setup)

View file

@ -68,7 +68,7 @@
;;; Code: ;;; Code:
(eval-when-compile (require 'cl-lib)) (require 'cl-lib)
(require 'xcb-keysyms) (require 'xcb-keysyms)
(require 'xcb-xim) (require 'xcb-xim)
@ -167,6 +167,7 @@ C,no"
(defun exwm-xim--on-SelectionRequest (data _synthetic) (defun exwm-xim--on-SelectionRequest (data _synthetic)
"Handle SelectionRequest events on IMS window. "Handle SelectionRequest events on IMS window.
DATA contains unmarshalled SelectionRequest event data.
Such events would be received when clients query for LOCALES or TRANSPORT." Such events would be received when clients query for LOCALES or TRANSPORT."
(exwm--log) (exwm--log)

99
exwm.el
View file

@ -153,7 +153,8 @@
(kill-emacs)))))) (kill-emacs))))))
(defun exwm--update-desktop (xwin) (defun exwm--update-desktop (xwin)
"Update _NET_WM_DESKTOP." "Update _NET_WM_DESKTOP.
Argument XWIN contains the X window of the `exwm-mode' buffer."
(exwm--log "#x%x" xwin) (exwm--log "#x%x" xwin)
(with-current-buffer (exwm--id->buffer xwin) (with-current-buffer (exwm--id->buffer xwin)
(let ((reply (xcb:+request-unchecked+reply exwm--connection (let ((reply (xcb:+request-unchecked+reply exwm--connection
@ -180,7 +181,11 @@
(exwm-workspace--set-desktop xwin))))))) (exwm-workspace--set-desktop xwin)))))))
(defun exwm--update-window-type (id &optional force) (defun exwm--update-window-type (id &optional force)
"Update _NET_WM_WINDOW_TYPE." "Update `exwm-window-type' from _NET_WM_WINDOW_TYPE.
Argument ID contains the X window of the `exwm-mode' buffer.
When FORCE is nil the update only takes place if
`exwm-window-type' is unset."
(exwm--log "#x%x" id) (exwm--log "#x%x" id)
(with-current-buffer (exwm--id->buffer id) (with-current-buffer (exwm--id->buffer id)
(unless (and exwm-window-type (not force)) (unless (and exwm-window-type (not force))
@ -191,7 +196,11 @@
(setq exwm-window-type (append (slot-value reply 'value) nil))))))) (setq exwm-window-type (append (slot-value reply 'value) nil)))))))
(defun exwm--update-class (id &optional force) (defun exwm--update-class (id &optional force)
"Update WM_CLASS." "Update `exwm-instance-name' and `exwm-class' from WM_CLASS.
Argument ID contains the X window of the `exwm-mode' buffer.
When FORCE is nil the update only takes place if any of
`exwm-instance-name' or `exwm-class' is unset."
(exwm--log "#x%x" id) (exwm--log "#x%x" id)
(with-current-buffer (exwm--id->buffer id) (with-current-buffer (exwm--id->buffer id)
(unless (and exwm-instance-name exwm-class-name (not force)) (unless (and exwm-instance-name exwm-class-name (not force))
@ -204,7 +213,11 @@
(run-hooks 'exwm-update-class-hook))))))) (run-hooks 'exwm-update-class-hook)))))))
(defun exwm--update-utf8-title (id &optional force) (defun exwm--update-utf8-title (id &optional force)
"Update _NET_WM_NAME." "Update `exwm-title' from _NET_WM_NAME.
Argument ID contains the X window of the `exwm-mode' buffer.
When FORCE is nil the update only takes place if `exwm-title' is
unset."
(exwm--log "#x%x" id) (exwm--log "#x%x" id)
(with-current-buffer (exwm--id->buffer id) (with-current-buffer (exwm--id->buffer id)
(when (or force (not exwm-title)) (when (or force (not exwm-title))
@ -217,7 +230,11 @@
(run-hooks 'exwm-update-title-hook))))))) (run-hooks 'exwm-update-title-hook)))))))
(defun exwm--update-ctext-title (id &optional force) (defun exwm--update-ctext-title (id &optional force)
"Update WM_NAME." "Update `exwm-title' from WM_NAME.
Argument ID contains the X window of the `exwm-mode' buffer.
When FORCE is nil the update only takes place if `exwm-title' is
unset."
(exwm--log "#x%x" id) (exwm--log "#x%x" id)
(with-current-buffer (exwm--id->buffer id) (with-current-buffer (exwm--id->buffer id)
(unless (or exwm--title-is-utf8 (unless (or exwm--title-is-utf8
@ -230,13 +247,18 @@
(run-hooks 'exwm-update-title-hook))))))) (run-hooks 'exwm-update-title-hook)))))))
(defun exwm--update-title (id) (defun exwm--update-title (id)
"Update _NET_WM_NAME or WM_NAME." "Update _NET_WM_NAME or WM_NAME.
Argument ID contains the X window of the `exwm-mode' buffer."
(exwm--log "#x%x" id) (exwm--log "#x%x" id)
(exwm--update-utf8-title id) (exwm--update-utf8-title id)
(exwm--update-ctext-title id)) (exwm--update-ctext-title id))
(defun exwm--update-transient-for (id &optional force) (defun exwm--update-transient-for (id &optional force)
"Update WM_TRANSIENT_FOR." "Update `exwm-transient-for' from WM_TRANSIENT_FOR.
Argument ID contains the X window of the `exwm-mode' buffer.
When FORCE is nil the update only takes place if `exwm-title' is
unset."
(exwm--log "#x%x" id) (exwm--log "#x%x" id)
(with-current-buffer (exwm--id->buffer id) (with-current-buffer (exwm--id->buffer id)
(unless (and exwm-transient-for (not force)) (unless (and exwm-transient-for (not force))
@ -247,7 +269,15 @@
(setq exwm-transient-for (slot-value reply 'value))))))) (setq exwm-transient-for (slot-value reply 'value)))))))
(defun exwm--update-normal-hints (id &optional force) (defun exwm--update-normal-hints (id &optional force)
"Update WM_NORMAL_HINTS." "Update normal hints from WM_NORMAL_HINTS.
Argument ID contains the X window of the `exwm-mode' buffer.
When FORCE is nil the update only takes place all of
`exwm--normal-hints-x exwm--normal-hints-y',
`exwm--normal-hints-width exwm--normal-hints-height',
`exwm--normal-hints-min-width exwm--normal-hints-min-height' and
`exwm--normal-hints-max-width exwm--normal-hints-max-height' are
unset."
(exwm--log "#x%x" id) (exwm--log "#x%x" id)
(with-current-buffer (exwm--id->buffer id) (with-current-buffer (exwm--id->buffer id)
(unless (and (not force) (unless (and (not force)
@ -295,7 +325,11 @@
exwm--normal-hints-max-height))))))))) exwm--normal-hints-max-height)))))))))
(defun exwm--update-hints (id &optional force) (defun exwm--update-hints (id &optional force)
"Update WM_HINTS." "Update hints from WM_HINTS.
Argument ID contains the X window of the `exwm-mode' buffer.
When FORCE is nil the update only takes place if both of
`exwm--hints-input' and `exwm--hints-urgency' are unset."
(exwm--log "#x%x" id) (exwm--log "#x%x" id)
(with-current-buffer (exwm--id->buffer id) (with-current-buffer (exwm--id->buffer id)
(unless (and (not force) exwm--hints-input exwm--hints-urgency) (unless (and (not force) exwm--hints-input exwm--hints-urgency)
@ -317,7 +351,11 @@
(setq exwm-workspace--switch-history-outdated t)))))))) (setq exwm-workspace--switch-history-outdated t))))))))
(defun exwm--update-protocols (id &optional force) (defun exwm--update-protocols (id &optional force)
"Update WM_PROTOCOLS." "Update `exwm--protocols' from WM_PROTOCOLS.
Argument ID contains the X window of the `exwm-mode' buffer.
When FORCE is nil the update only takes place if `exwm--protocols'
is unset."
(exwm--log "#x%x" id) (exwm--log "#x%x" id)
(with-current-buffer (exwm--id->buffer id) (with-current-buffer (exwm--id->buffer id)
(unless (and exwm--protocols (not force)) (unless (and exwm--protocols (not force))
@ -328,7 +366,7 @@
(setq exwm--protocols (append (slot-value reply 'value) nil))))))) (setq exwm--protocols (append (slot-value reply 'value) nil)))))))
(defun exwm--update-struts-legacy (id) (defun exwm--update-struts-legacy (id)
"Update _NET_WM_STRUT." "Update struts of X window ID from _NET_WM_STRUT."
(exwm--log "#x%x" id) (exwm--log "#x%x" id)
(let ((pair (assq id exwm-workspace--id-struts-alist)) (let ((pair (assq id exwm-workspace--id-struts-alist))
reply struts) reply struts)
@ -349,7 +387,7 @@
(exwm-workspace--set-fullscreen f))))) (exwm-workspace--set-fullscreen f)))))
(defun exwm--update-struts-partial (id) (defun exwm--update-struts-partial (id)
"Update _NET_WM_STRUT_PARTIAL." "Update struts of X window ID from _NET_WM_STRUT_PARTIAL."
(exwm--log "#x%x" id) (exwm--log "#x%x" id)
(let ((reply (xcb:+request-unchecked+reply exwm--connection (let ((reply (xcb:+request-unchecked+reply exwm--connection
(make-instance 'xcb:ewmh:get-_NET_WM_STRUT_PARTIAL (make-instance 'xcb:ewmh:get-_NET_WM_STRUT_PARTIAL
@ -369,13 +407,14 @@
(exwm-workspace--set-fullscreen f)))) (exwm-workspace--set-fullscreen f))))
(defun exwm--update-struts (id) (defun exwm--update-struts (id)
"Update _NET_WM_STRUT_PARTIAL or _NET_WM_STRUT." "Update struts of X window ID from _NET_WM_STRUT_PARTIAL or _NET_WM_STRUT."
(exwm--log "#x%x" id) (exwm--log "#x%x" id)
(exwm--update-struts-partial id) (exwm--update-struts-partial id)
(exwm--update-struts-legacy id)) (exwm--update-struts-legacy id))
(defun exwm--on-PropertyNotify (data _synthetic) (defun exwm--on-PropertyNotify (data _synthetic)
"Handle PropertyNotify event." "Handle PropertyNotify event.
DATA contains unmarshalled PropertyNotify event data."
(let ((obj (make-instance 'xcb:PropertyNotify)) (let ((obj (make-instance 'xcb:PropertyNotify))
atom id buffer) atom id buffer)
(xcb:unmarshal obj data) (xcb:unmarshal obj data)
@ -413,7 +452,8 @@
atom))))))) atom)))))))
(defun exwm--on-ClientMessage (raw-data _synthetic) (defun exwm--on-ClientMessage (raw-data _synthetic)
"Handle ClientMessage event." "Handle ClientMessage event.
RAW-DATA contains unmarshalled ClientMessage event data."
(let ((obj (make-instance 'xcb:ClientMessage)) (let ((obj (make-instance 'xcb:ClientMessage))
type id data) type id data)
(xcb:unmarshal obj raw-data) (xcb:unmarshal obj raw-data)
@ -598,7 +638,8 @@
(x-get-atom-name type exwm-workspace--current) type))))) (x-get-atom-name type exwm-workspace--current) type)))))
(defun exwm--on-SelectionClear (data _synthetic) (defun exwm--on-SelectionClear (data _synthetic)
"Handle SelectionClear events." "Handle SelectionClear events.
DATA contains unmarshalled SelectionClear event data."
(exwm--log) (exwm--log)
(let ((obj (make-instance 'xcb:SelectionClear)) (let ((obj (make-instance 'xcb:SelectionClear))
owner selection) owner selection)
@ -611,6 +652,10 @@
(defun exwm--on-delete-terminal (terminal) (defun exwm--on-delete-terminal (terminal)
"Handle terminal being deleted without Emacs being killed. "Handle terminal being deleted without Emacs being killed.
This function is Hooked to `delete-terminal-functions'.
TERMINAL is the terminal being (or that has been) deleted.
This may happen when invoking `save-buffers-kill-terminal' within an emacsclient This may happen when invoking `save-buffers-kill-terminal' within an emacsclient
session." session."
(when (eq terminal exwm--terminal) (when (eq terminal exwm--terminal)
@ -836,7 +881,8 @@ manager. If t, replace it, if nil, abort and ask the user if `ask'."
;;;###autoload ;;;###autoload
(cl-defun exwm-init (&optional frame) (cl-defun exwm-init (&optional frame)
"Initialize EXWM." "Initialize EXWM.
FRAME, if given, indicates the X display EXWM should manage."
(interactive) (interactive)
(exwm--log "%s" frame) (exwm--log "%s" frame)
(if frame (if frame
@ -956,10 +1002,11 @@ manager. If t, replace it, if nil, abort and ask the user if `ask'."
(delete-process exwm--server-process) (delete-process exwm--server-process)
(setq exwm--server-process nil))) (setq exwm--server-process nil)))
(defun exwm--server-eval-at (&rest args) (defun exwm--server-eval-at (function &rest args)
"Wrapper of `server-eval-at' used to advice subrs." "Wrapper of `server-eval-at' used to advice subrs.
FUNCTION is the function to be evaluated, ARGS are the arguments."
;; Start the subordinate Emacs server if it's not alive ;; Start the subordinate Emacs server if it's not alive
(exwm--log "%s" args) (exwm--log "%s %s" function args)
(unless (server-running-p exwm--server-name) (unless (server-running-p exwm--server-name)
(when exwm--server-process (delete-process exwm--server-process)) (when exwm--server-process (delete-process exwm--server-process))
(setq exwm--server-process (setq exwm--server-process
@ -977,8 +1024,8 @@ manager. If t, replace it, if nil, abort and ask the user if `ask'."
(server-eval-at (server-eval-at
exwm--server-name exwm--server-name
`(progn (select-frame (car (frame-list))) `(progn (select-frame (car (frame-list)))
(let ((result ,(nconc (list (make-symbol (subr-name (car args)))) (let ((result ,(nconc (list (make-symbol (subr-name function)))
(cdr args)))) args)))
(pcase (type-of result) (pcase (type-of result)
;; Return the name of a buffer ;; Return the name of a buffer
(`buffer (buffer-name result)) (`buffer (buffer-name result))
@ -1001,11 +1048,15 @@ manager. If t, replace it, if nil, abort and ask the user if `ask'."
;; This is invoked instead of `save-buffers-kill-emacs' (C-x C-c) on client ;; This is invoked instead of `save-buffers-kill-emacs' (C-x C-c) on client
;; frames. ;; frames.
(if (exwm--terminal-p) (if (exwm--terminal-p)
(exwm--confirm-kill-emacs "[EXWM] Kill terminal?") (exwm--confirm-kill-emacs "Kill terminal?")
t)) t))
(defun exwm--confirm-kill-emacs (prompt &optional force) (defun exwm--confirm-kill-emacs (prompt &optional force)
"Confirm before exiting Emacs." "Confirm before exiting Emacs.
PROMPT a reason to present to the user.
If FORCE is nil, ask the user for confirmation.
If FORCE is the symbol `no-check', ask if there are unsaved buffers.
If FORCE is any other non-nil value, force killing of Emacs."
(exwm--log) (exwm--log)
(when (cond (when (cond
((and force (not (eq force 'no-check))) ((and force (not (eq force 'no-check)))