From cff02333e282c692aa685d57cc2b7c32419fffe2 Mon Sep 17 00:00:00 2001 From: Nacho Barrientos Date: Sun, 7 May 2023 12:45:31 +0200 Subject: [PATCH 01/16] Don't assume that exwm--connection is non-nil `exwm-input--exit` could be called (via `exwm-exit`) from `exwm-init` in case of error when initialising EXWM. It could happen that the bit that failed when exwm-init is executed was the call to `xcb:connect`, hence `exwm--connection` would be nil when errors are handled (and `exwm-exit` is called). Without this patch, in the case above, the user will see a crash as there's no method allowing a nil XCB connection object: Debugger entered--Lisp error: (cl-no-applicable-method xcb:-+request nil # Date: Sun, 11 Dec 2022 12:23:42 +0100 Subject: [PATCH 02/16] Make sure the buffer that generates the event is current * exwm-input.el (exwm-input--on-ButtonPress): Set current buffer when running pre- and post-command hooks. --- exwm-input.el | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/exwm-input.el b/exwm-input.el index 79bc78ef0..ab22d60a3 100644 --- a/exwm-input.el +++ b/exwm-input.el @@ -452,9 +452,12 @@ ARGS are additional arguments to CALLBACK." (t ;; Replay this event by default. (setq fake-last-command t) - (setq mode xcb:Allow:ReplayPointer)))) - (when fake-last-command - (exwm-input--fake-last-command)) + (setq mode xcb:Allow:ReplayPointer))) + (when fake-last-command + (if buffer + (with-current-buffer buffer + (exwm-input--fake-last-command)) + (exwm-input--fake-last-command)))) (xcb:+request exwm--connection (make-instance 'xcb:AllowEvents :mode mode :time xcb:Time:CurrentTime)) (xcb:flush exwm--connection)) From 7318f857f2937c421094d66d976d4e926feacc71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A1n=20Medra=C3=B1o=20Calvo?= Date: Fri, 9 Jun 2023 00:00:00 +0000 Subject: [PATCH 03/16] Observe connection status on deinitialization * exwm-workspace.el (exwm-workspace--remove-frame-as-workspace): Add optional argument quit. * exwm-background.el (exwm-background--exit): * exwm-input.el (exwm-input--exit): * exwm-manage.el (exwm-manage--unmanage-window): * exwm-systemtray.el (exwm-systemtray--exit): * exwm-workspace.el (exwm-workspace--exit-minibuffer-frame) (exwm-workspace--exit): * exwm-xim.el (exwm-xim--exit): Observe connection status when deinitializing in order to support deinitializing when the connection breaks. --- exwm-background.el | 6 ++-- exwm-input.el | 2 +- exwm-manage.el | 9 ++++-- exwm-systemtray.el | 27 ++++++++-------- exwm-workspace.el | 81 +++++++++++++++++++++++++--------------------- exwm-xim.el | 6 ++-- exwm.el | 10 +++--- 7 files changed, 77 insertions(+), 64 deletions(-) diff --git a/exwm-background.el b/exwm-background.el index e7a0360c9..f3e0d895c 100644 --- a/exwm-background.el +++ b/exwm-background.el @@ -172,19 +172,17 @@ replace it.") (defun exwm-background--init () "Initialize background module." (exwm--log) - (add-hook 'enable-theme-functions 'exwm-background--update) (add-hook 'disable-theme-functions 'exwm-background--update) - (exwm-background--update)) (defun exwm-background--exit () "Uninitialize the background module." (exwm--log) - (remove-hook 'enable-theme-functions 'exwm-background--update) (remove-hook 'disable-theme-functions 'exwm-background--update) - (when exwm-background--connection + (when (and exwm-background--connection + (slot-value exwm-background--connection 'connected)) (xcb:disconnect exwm-background--connection)) (setq exwm-background--pixmap nil exwm-background--connection nil diff --git a/exwm-input.el b/exwm-input.el index 2c65116aa..3f9a30501 100644 --- a/exwm-input.el +++ b/exwm-input.el @@ -1215,7 +1215,7 @@ One use is to access the keymap bound to KEYS (as prefix keys) in char-mode." (when exwm-input--update-focus-timer (cancel-timer exwm-input--update-focus-timer)) ;; Make input focus working even without a WM. - (when exwm--connection + (when (slot-value exwm--connection 'connected) (xcb:+request exwm--connection (make-instance 'xcb:SetInputFocus :revert-to xcb:InputFocus:PointerRoot diff --git a/exwm-manage.el b/exwm-manage.el index c3d47f722..1adf66d42 100644 --- a/exwm-manage.el +++ b/exwm-manage.el @@ -430,7 +430,9 @@ manager is shutting down." (exwm-workspace--update-workareas) (dolist (f exwm-workspace--list) (exwm-workspace--set-fullscreen f))) - (when (buffer-live-p buffer) + (when (and (buffer-live-p buffer) + ;; Invoked from `exwm-manage--exit' upon disconnection. + (slot-value exwm--connection 'connected)) (with-current-buffer buffer ;; Unmap the X window. (xcb:+request exwm--connection @@ -512,8 +514,11 @@ manager is shutting down." (defun exwm-manage--kill-buffer-query-function () "Run in `kill-buffer-query-functions'." - (exwm--log "id=#x%x; buffer=%s" exwm--id (current-buffer)) + (exwm--log "id=#x%x; buffer=%s" (or exwm--id 0) (current-buffer)) (catch 'return + (when (or (not exwm--connection) + (not (slot-value exwm--connection 'connected))) + (throw 'return t)) (when (or (not exwm--id) (xcb:+request-checked+request-check exwm--connection (make-instance 'xcb:ChangeWindowAttributes diff --git a/exwm-systemtray.el b/exwm-systemtray.el index 0f1998662..51d5213df 100644 --- a/exwm-systemtray.el +++ b/exwm-systemtray.el @@ -652,19 +652,20 @@ indicate how to support actual transparency." "Exit the systemtray module." (exwm--log) (when exwm-systemtray--connection - ;; Hide & reparent out the embedder before disconnection to prevent - ;; embedded icons from being reparented to an Emacs frame (which is the - ;; parent of the embedder). - (xcb:+request exwm-systemtray--connection - (make-instance 'xcb:UnmapWindow - :window exwm-systemtray--embedder-window)) - (xcb:+request exwm-systemtray--connection - (make-instance 'xcb:ReparentWindow - :window exwm-systemtray--embedder-window - :parent exwm--root - :x 0 - :y 0)) - (xcb:disconnect exwm-systemtray--connection) + (when (slot-value exwm-systemtray--connection 'connected) + ;; Hide & reparent out the embedder before disconnection to prevent + ;; embedded icons from being reparented to an Emacs frame (which is the + ;; parent of the embedder). + (xcb:+request exwm-systemtray--connection + (make-instance 'xcb:UnmapWindow + :window exwm-systemtray--embedder-window)) + (xcb:+request exwm-systemtray--connection + (make-instance 'xcb:ReparentWindow + :window exwm-systemtray--embedder-window + :parent exwm--root + :x 0 + :y 0)) + (xcb:disconnect exwm-systemtray--connection)) (setq exwm-systemtray--connection nil exwm-systemtray--list nil exwm-systemtray--selection-owner-window nil diff --git a/exwm-workspace.el b/exwm-workspace.el index 06217a776..67e352366 100644 --- a/exwm-workspace.el +++ b/exwm-workspace.el @@ -1389,32 +1389,34 @@ Return nil if FRAME is the only workspace." (unless (eq frame nextw) nextw))) -(defun exwm-workspace--remove-frame-as-workspace (frame) +(defun exwm-workspace--remove-frame-as-workspace (frame &optional quit) "Stop treating frame FRAME as a workspace." ;; TODO: restore all frame parameters (e.g. exwm-workspace, buffer-predicate, ;; etc) (exwm--log "Removing frame `%s' as workspace" frame) - (let* ((next-frame (exwm-workspace--get-next-workspace frame)) - (following-frames (cdr (memq frame exwm-workspace--list)))) - ;; Need to remove the workspace from the list for the correct calculation of - ;; indexes below. - (setq exwm-workspace--list (delete frame exwm-workspace--list)) - (unless next-frame - ;; The user managed to delete the last workspace, so create a new one. - (exwm--log "Last workspace deleted; create a new one") - (let ((exwm-workspace--create-silently t)) - (setq next-frame (make-frame)))) - (dolist (pair exwm--id-buffer-alist) - (let ((other-frame (buffer-local-value 'exwm--frame (cdr pair)))) - ;; Move X windows to next-frame. - (when (eq other-frame frame) - (exwm-workspace-move-window next-frame (car pair))) - ;; Update the _NET_WM_DESKTOP property of each following X window. - (when (memq other-frame following-frames) - (exwm-workspace--set-desktop (car pair))))) - ;; If the current workspace is deleted, switch to next one. - (when (eq frame exwm-workspace--current) - (exwm-workspace-switch next-frame))) + (unless quit + (let* ((next-frame (exwm-workspace--get-next-workspace frame)) + (following-frames (cdr (memq frame exwm-workspace--list)))) + ;; Need to remove the workspace from the list for the correct calculation of + ;; indexes below. + (setq exwm-workspace--list (delete frame exwm-workspace--list)) + ;; Move the windows to the next workspace and switch to it. + (unless next-frame + ;; The user managed to delete the last workspace, so create a new one. + (exwm--log "Last workspace deleted; create a new one") + (let ((exwm-workspace--create-silently t)) + (setq next-frame (make-frame)))) + (dolist (pair exwm--id-buffer-alist) + (let ((other-frame (buffer-local-value 'exwm--frame (cdr pair)))) + ;; Move X windows to next-frame. + (when (eq other-frame frame) + (exwm-workspace-move-window next-frame (car pair))) + ;; Update the _NET_WM_DESKTOP property of each following X window. + (when (memq other-frame following-frames) + (exwm-workspace--set-desktop (car pair))))) + ;; If the current workspace is deleted, switch to next one. + (when (eq frame exwm-workspace--current) + (exwm-workspace-switch next-frame)))) ;; Reparent out the frame. (let ((outer-id (frame-parameter frame 'exwm-outer-id))) (xcb:+request exwm--connection @@ -1448,8 +1450,9 @@ Return nil if FRAME is the only workspace." ;; Update EWMH properties. (exwm-workspace--update-ewmh-props) ;; Update switch history. - (setq exwm-workspace--switch-history-outdated t) - (run-hooks 'exwm-workspace-list-change-hook)) + (unless quit + (setq exwm-workspace--switch-history-outdated t) + (run-hooks 'exwm-workspace-list-change-hook))) (defun exwm-workspace--on-delete-frame (frame) "Hook run upon `delete-frame' that tears down FRAME's configuration as a workspace." @@ -1623,7 +1626,9 @@ applied to all subsequently created X frames." (setq default-minibuffer-frame nil) (when (frame-live-p exwm-workspace--minibuffer) ; might be already dead (let ((id (frame-parameter exwm-workspace--minibuffer 'exwm-outer-id))) - (when (and exwm-workspace--minibuffer id) + (when (and exwm-workspace--minibuffer id + ;; Invoked from `exwm-manage--exit' upon disconnection. + (slot-value exwm--connection 'connected)) (xcb:+request exwm--connection (make-instance 'xcb:ReparentWindow :window id @@ -1708,19 +1713,21 @@ applied to all subsequently created X frames." #'exwm-workspace--on-echo-area-clear)) ;; Hide & reparent out all frames (save-set can't be used here since ;; X windows will be re-mapped). - (setq exwm-workspace--current nil) - (dolist (i exwm-workspace--list) - (when (frame-live-p i) ; might be already dead - (exwm-workspace--remove-frame-as-workspace i) - (modify-frame-parameters i '((exwm-selected-window . nil) - (exwm-urgency . nil) - (exwm-outer-id . nil) - (exwm-id . nil) - (exwm-container . nil) - ;; (internal-border-width . nil) ; integerp - (fullscreen . nil) - (buffer-predicate . nil))))) + (when (slot-value exwm--connection 'connected) + (dolist (i exwm-workspace--list) + (when (frame-live-p i) ; might be already dead + (exwm-workspace--remove-frame-as-workspace i 'quit) + (modify-frame-parameters i '((exwm-selected-window . nil) + (exwm-urgency . nil) + (exwm-outer-id . nil) + (exwm-id . nil) + (exwm-container . nil) + ;; (internal-border-width . nil) ; integerp + (fullscreen . nil) + (buffer-predicate . nil)))))) ;; Don't let dead frames linger. + (setq exwm-workspace--current nil) + (setq exwm-workspace-current-index 0) (setq exwm-workspace--list nil)) (defun exwm-workspace--post-init () diff --git a/exwm-xim.el b/exwm-xim.el index 9589648d2..ac530f389 100644 --- a/exwm-xim.el +++ b/exwm-xim.el @@ -754,10 +754,12 @@ Such event would be received when the client window is destroyed." ;; Close IMS communication connections. (mapc (lambda (i) (when (vectorp i) - (xcb:disconnect (elt i 0)))) + (when (slot-value (elt i 0) 'connected) + (xcb:disconnect (elt i 0))))) exwm-xim--server-client-plist) ;; Close the IMS connection. - (unless exwm-xim--conn + (unless (and exwm-xim--conn + (slot-value exwm-xim--conn 'connected)) (cl-return-from exwm-xim--exit)) ;; Remove exwm-xim from XIM_SERVERS. (let ((reply (xcb:+request-unchecked+reply exwm-xim--conn diff --git a/exwm.el b/exwm.el index 345f76beb..31fe68495 100644 --- a/exwm.el +++ b/exwm.el @@ -907,12 +907,12 @@ manager. If t, replace it, if nil, abort and ask the user if `ask'." (run-hooks 'exwm-exit-hook) (setq confirm-kill-emacs nil) ;; Exit modules. - (exwm-input--exit) - (exwm-manage--exit) - (exwm-workspace--exit) - (exwm-floating--exit) - (exwm-layout--exit) (when exwm--connection + (exwm-input--exit) + (exwm-manage--exit) + (exwm-workspace--exit) + (exwm-floating--exit) + (exwm-layout--exit) (xcb:flush exwm--connection) (xcb:disconnect exwm--connection)) (setq exwm--connection nil) From 4970d6ad4ef7c9cff92cbfb90a9ec379a61cd5e7 Mon Sep 17 00:00:00 2001 From: Fran Ley Date: Mon, 6 Mar 2023 16:46:47 -0800 Subject: [PATCH 04/16] More selectively ignore top and bottom struts For the case of vertical columns of workareas, top and bottom struts should only apply to workareas containing the respective edge of the strut offset. To simplify, imagine three monitors arranged vertically and one workarea per display: +-------+ | 1 | 2000x1000 px +-------+ | 2 | 2000x1000 px +-------+ | 3 | 2000x1000 px +-------+ In sexp form: ((0 0 2000 1000) (0 1000 2000 1000) (0 2000 2000 1000)) where each element represents a workarea as x, y, width, height And example struts of the form (offset-type offset (x-start x-end)) a.) (top 42 (0 2000)) b.) (top 1042 (0 2000)) c.) (top 2042 (0 2000)) d.) (bottom 42 (0 2000)) e.) (bottom 1042 (0 2000)) f.) (bottom 2042 (0 2000)) Workareas adjusted for struts before this change: a.) ((0 42 2000 958) (0 1000 2000 1000) (0 2000 2000 1000)) b.) ((0 1042 2000 -42) (0 1042 2000 958) (0 2000 2000 1000)) c.) ((0 2042 2000 -1042) (0 2042 2000 -42) (0 2042 2000 958)) d.) ((0 0 2000 1000) (0 1000 2000 1000) (0 2000 2000 902)) e.) ((0 0 2000 1000) (0 1000 2000 902) (0 2000 2000 -98)) f.) ((0 0 2000 902) (0 1000 2000 -98) (0 2000 2000 -1098)) Note that a. and d. are sensible, while b., c., e., and f. are quite user unfriendly. After this change, the same adjusted workareas are: a.) no change b.) ((0 0 2000 1000) (0 1042 2000 958) (0 2000 2000 1000)) c.) ((0 0 2000 1000) (0 1000 2000 1000) (0 2042 2000 958)) d.) no change e.) ((0 0 2000 1000) (0 1000 2000 902) (0 2000 2000 1000)) f.) ((0 0 2000 902) (0 1000 2000 1000) (0 2000 2000 1000)) The intent is to allow dock type windows such as typical status bars to occupy space in a workarea on any of a set of vertically arranged displays without occluding the other workareas due to the limitations of the X spec regarding strut offsets. Note that this behaviour conflicts with EWMH 1.3: > Struts MUST be specified in root window coordinates, that is, they are *not* relative to the edges of any view port or Xinerama monitor. but is accepted by multiple WMs. See: - https://blog.martin-graesslin.com/blog/2016/08/panels-on-shared-screen-edges/ - https://mail.gnome.org/archives/wm-spec-list/2009-November/msg00005.html - https://gitlab.freedesktop.org/xdg/xdg-specs/-/merge_requests/22 * exwm-workspace.el (exwm-workspace--update-workareas): Assume vertical struts apply from the monitor boundary when they cross them. Copyright-paperwork-exempt: yes --- exwm-workspace.el | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/exwm-workspace.el b/exwm-workspace.el index 06217a776..1f60e80c6 100644 --- a/exwm-workspace.el +++ b/exwm-workspace.el @@ -377,7 +377,9 @@ NIL if FRAME is not a workspace" (or (not position) (< (max (aref position 0) (aref w 0)) (min (aref position 1) - (+ (aref w 0) (aref w 2)))))) + (+ (aref w 0) (aref w 2))))) + (< width (+ (aref w 1) (aref w 3))) + (> width (aref w 1))) (cl-incf (aref w 3) delta) (setf (aref w 1) width))) (`bottom @@ -386,7 +388,10 @@ NIL if FRAME is not a workspace" (or (not position) (< (max (aref position 0) (aref w 0)) (min (aref position 1) - (+ (aref w 0) (aref w 2)))))) + (+ (aref w 0) (aref w 2))))) + (< (- root-height width) + (+ (aref w 1) (aref w 3))) + (> (- root-height width) (aref w 1))) (cl-incf (aref w 3) delta)))))) ;; Save the result. (setq exwm-workspace--workareas workareas) From 67c5b316be03eb639bd0cda838579af27bb577b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A1n=20Medra=C3=B1o=20Calvo?= Date: Fri, 9 Jun 2023 00:00:00 +0000 Subject: [PATCH 05/16] Convert `exwm-workspace--workareas' to a list of `xcb:RECTANGLE's * exwm-workspace.el (exwm-workspace--set-fullscreen) (exwm-workspace--resize-minibuffer-frame) (exwm-workspace--on-ConfigureNotify): * exwm-floating.el (exwm-floating--set-floating): * exwm-manage.el (exwm-manage--manage-window): * exwm-systemtray.el (exwm-systemtray--refresh) (exwm-systemtray--on-workspace-switch) (exwm-systemtray--refresh-all, exwm-systemtray--init): Adjust to `xcb:RECTANGLE' workarea. --- exwm-floating.el | 10 +-- exwm-manage.el | 10 +-- exwm-systemtray.el | 25 +++--- exwm-workspace.el | 187 +++++++++++++++++++++++---------------------- 4 files changed, 114 insertions(+), 118 deletions(-) diff --git a/exwm-floating.el b/exwm-floating.el index 69e86a24e..c8e433e27 100644 --- a/exwm-floating.el +++ b/exwm-floating.el @@ -118,13 +118,13 @@ context of the corresponding buffer." (defvar exwm-workspace--current) (defvar exwm-workspace--frame-y-offset) (defvar exwm-workspace--window-y-offset) -(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--position "exwm-workspace.el" (frame)) (declare-function exwm-workspace--update-offsets "exwm-workspace.el" ()) +(declare-function exwm-workspace--workarea "exwm-workspace.el" (frame)) (defun exwm-floating--set-allowed-actions (id tilling) "Set _NET_WM_ALLOWED_ACTIONS." @@ -186,12 +186,8 @@ context of the corresponding buffer." (set-frame-parameter frame 'exwm-container frame-container) ;; Fix illegal parameters ;; FIXME: check normal hints restrictions - (let* ((workarea (elt exwm-workspace--workareas - (exwm-workspace--position original-frame))) - (x* (aref workarea 0)) - (y* (aref workarea 1)) - (width* (aref workarea 2)) - (height* (aref workarea 3))) + (with-slots ((x* x) (y* y) (width* width) (height* height)) + (exwm-workspace--workarea original-frame) ;; Center floating windows (when (and (or (= x 0) (= x x*)) (or (= y 0) (= y y*))) diff --git a/exwm-manage.el b/exwm-manage.el index c3d47f722..36da1932c 100644 --- a/exwm-manage.el +++ b/exwm-manage.el @@ -157,7 +157,6 @@ want to match against EXWM internal variables such as `exwm-title', (defvar exwm-workspace--id-struts-alist) (defvar exwm-workspace--list) (defvar exwm-workspace--switch-history-outdated) -(defvar exwm-workspace--workareas) (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)) @@ -178,6 +177,7 @@ want to match against EXWM internal variables such as `exwm-title', (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--workarea "exwm-workspace.el" (frame)) (defun exwm-manage--update-geometry (id &optional force) "Update window geometry." @@ -326,12 +326,8 @@ want to match against EXWM internal variables such as `exwm-title', (with-slots (x y width height) exwm--geometry ;; Center window of type _NET_WM_WINDOW_TYPE_SPLASH (when (memq xcb:Atom:_NET_WM_WINDOW_TYPE_SPLASH exwm-window-type) - (let* ((workarea (elt exwm-workspace--workareas - (exwm-workspace--position exwm--frame))) - (x* (aref workarea 0)) - (y* (aref workarea 1)) - (width* (aref workarea 2)) - (height* (aref workarea 3))) + (with-slots ((x* x) (y* y) (width* width) (height* height)) + (exwm-workspace--workarea exwm--frame) (exwm--set-geometry id (+ x* (/ (- width* width) 2)) (+ y* (/ (- height* height) 2)) diff --git a/exwm-systemtray.el b/exwm-systemtray.el index 0f1998662..acefd09d2 100644 --- a/exwm-systemtray.el +++ b/exwm-systemtray.el @@ -38,6 +38,8 @@ (require 'exwm-core) (require 'exwm-workspace) +(declare-function exwm-workspace--workarea "exwm-workspace.el" (frame)) + (defclass exwm-systemtray--icon () ((width :initarg :width) (height :initarg :height) @@ -240,14 +242,13 @@ using 32-bit depth. Using `workspace-background' instead.") (setq x (+ x (slot-value (cdr pair) 'width) exwm-systemtray-icon-gap)) (setq map t))) - (let ((workarea (elt exwm-workspace--workareas - exwm-workspace-current-index))) + (let ((workarea (exwm-workspace--workarea exwm-workspace-current-index))) (xcb:+request exwm-systemtray--connection (make-instance 'xcb:ConfigureWindow :window exwm-systemtray--embedder-window :value-mask (logior xcb:ConfigWindow:X xcb:ConfigWindow:Width) - :x (- (aref workarea 2) x) + :x (- (slot-value workarea 'width) x) :width x))) (when map (xcb:+request exwm-systemtray--connection @@ -450,9 +451,9 @@ indicate how to support actual transparency." (frame-parameter exwm-workspace--current 'window-id)) :x 0 - :y (- (elt (elt exwm-workspace--workareas - exwm-workspace-current-index) - 3) + :y (- (slot-value (exwm-workspace--workarea + exwm-workspace-current-index) + 'height) exwm-workspace--frame-y-offset exwm-systemtray-height)))) (exwm-systemtray--refresh-background-color) @@ -471,9 +472,9 @@ indicate how to support actual transparency." (make-instance 'xcb:ConfigureWindow :window exwm-systemtray--embedder-window :value-mask xcb:ConfigWindow:Y - :y (- (elt (elt exwm-workspace--workareas - exwm-workspace-current-index) - 3) + :y (- (slot-value (exwm-workspace--workarea + exwm-workspace-current-index) + 'height) exwm-workspace--frame-y-offset exwm-systemtray-height)))) (exwm-systemtray--refresh)) @@ -567,9 +568,9 @@ indicate how to support actual transparency." (exwm-workspace--update-offsets) (setq frame exwm-workspace--current ;; Bottom aligned. - y (- (elt (elt exwm-workspace--workareas - exwm-workspace-current-index) - 3) + y (- (slot-value (exwm-workspace--workarea + exwm-workspace-current-index) + 'height) exwm-workspace--frame-y-offset exwm-systemtray-height))) (setq parent (string-to-number (frame-parameter frame 'window-id))) diff --git a/exwm-workspace.el b/exwm-workspace.el index 1f60e80c6..1bdc7245a 100644 --- a/exwm-workspace.el +++ b/exwm-workspace.el @@ -162,6 +162,15 @@ NIL if FRAME is not a workspace" "Return t if FRAME is a workspace." (memq frame exwm-workspace--list)) +(defsubst exwm-workspace--workarea (frame) + "Return workarea corresponding to FRAME. +FRAME may be either a workspace frame or a workspace position." + (declare (indent defun)) + (elt exwm-workspace--workareas + (if (integerp frame) + frame + (exwm-workspace--position frame)))) + (defvar exwm-workspace--switch-map nil "Keymap used for interactively selecting workspace.") @@ -331,68 +340,68 @@ NIL if FRAME is not a workspace" (defun exwm-workspace--update-workareas () "Update `exwm-workspace--workareas'." - (let ((root-width (x-display-pixel-width)) - (root-height (x-display-pixel-height)) - workareas - edge width position - delta) - ;; Calculate workareas with no struts. - (if (frame-parameter (car exwm-workspace--list) 'exwm-geometry) - ;; Use the 'exwm-geometry' frame parameter if possible. - (dolist (f exwm-workspace--list) - (with-slots (x y width height) (frame-parameter f 'exwm-geometry) - (setq workareas (append workareas - (list (vector x y width height)))))) - ;; Fall back to use the screen size. - (let ((workarea (vector 0 0 root-width root-height))) - (setq workareas (make-list (exwm-workspace--count) workarea)))) + (let* ((root-width (x-display-pixel-width)) + (root-height (x-display-pixel-height)) + ;; Get workareas prior to struts. + (workareas (mapcar (lambda (f) + (or + ;; Use the 'exwm-geometry' frame parameter if + ;; possible. + (frame-parameter f 'exwm-geometry) + ;; Fall back to use the screen size. + (make-instance 'xcb:RECTANGLE + :x 0 + :y 0 + :width root-width + :height root-height))) + exwm-workspace--list))) ;; Exclude areas occupied by struts. (dolist (struts exwm-workspace--struts) - (setq edge (aref struts 0) - width (aref struts 1) - position (aref struts 2)) - (dolist (w workareas) - (pcase edge - ;; Left and top are always processed first. - (`left - (setq delta (- (aref w 0) width)) - (when (and (< delta 0) - (or (not position) - (< (max (aref position 0) (aref w 1)) - (min (aref position 1) - (+ (aref w 1) (aref w 3)))))) - (cl-incf (aref w 2) delta) - (setf (aref w 0) width))) - (`right - (setq delta (- root-width (aref w 0) (aref w 2) width)) - (when (and (< delta 0) - (or (not position) - (< (max (aref position 0) (aref w 1)) - (min (aref position 1) - (+ (aref w 1) (aref w 3)))))) - (cl-incf (aref w 2) delta))) - (`top - (setq delta (- (aref w 1) width)) - (when (and (< delta 0) - (or (not position) - (< (max (aref position 0) (aref w 0)) - (min (aref position 1) - (+ (aref w 0) (aref w 2))))) - (< width (+ (aref w 1) (aref w 3))) - (> width (aref w 1))) - (cl-incf (aref w 3) delta) - (setf (aref w 1) width))) - (`bottom - (setq delta (- root-height (aref w 1) (aref w 3) width)) - (when (and (< delta 0) - (or (not position) - (< (max (aref position 0) (aref w 0)) - (min (aref position 1) - (+ (aref w 0) (aref w 2))))) - (< (- root-height width) - (+ (aref w 1) (aref w 3))) - (> (- root-height width) (aref w 1))) - (cl-incf (aref w 3) delta)))))) + (let* ((edge (aref struts 0)) + (size (aref struts 1)) + (position (aref struts 2)) + (beg (and position (aref position 0))) + (end (and position (aref position 1))) + delta) + (dolist (w workareas) + (with-slots (x y width height) w + (pcase edge + ;; Left and top are always processed first. + (`left + (setq delta (- x size)) + (when (and (< delta 0) + (or (not position) + (< (max beg y) + (min end (+ y height))))) + (cl-incf width delta) + (setf x size))) + (`right + (setq delta (- root-width x width size)) + (when (and (< delta 0) + (or (not position) + (< (max beg y) + (min end (+ y height))))) + (cl-incf width delta))) + (`top + (setq delta (- y size)) + (when (and (< delta 0) + (or (not position) + (< (max beg x) + (min end (+ x width)))) + (< size (+ y height)) + (> size y)) + (cl-incf height delta) + (setf y size))) + (`bottom + (setq delta (- root-height y height size)) + (when (and (< delta 0) + (or (not position) + (< (max beg x) + (min end (+ x width)))) + (< (- root-height size) + (+ y height)) + (> (- root-height size) y)) + (cl-incf height delta)))))))) ;; Save the result. (setq exwm-workspace--workareas workareas) (xcb:flush exwm--connection)) @@ -444,24 +453,19 @@ NIL if FRAME is not a workspace" (defun exwm-workspace--set-fullscreen (frame) "Make frame FRAME fullscreen according to `exwm-workspace--workareas'." (exwm--log "frame=%s" frame) - (let ((workarea (elt exwm-workspace--workareas - (exwm-workspace--position frame))) - (id (frame-parameter frame 'exwm-outer-id)) - (container (frame-parameter frame 'exwm-container)) - x y width height) - (setq x (aref workarea 0) - y (aref workarea 1) - width (aref workarea 2) - height (aref workarea 3)) - (exwm--log "x=%s; y=%s; w=%s; h=%s" x y width height) - (when (and (eq frame exwm-workspace--current) - (exwm-workspace--minibuffer-own-frame-p)) - (exwm-workspace--resize-minibuffer-frame)) - (if (exwm-workspace--active-p frame) - (exwm--set-geometry container x y width height) - (exwm--set-geometry container x y 1 1)) - (exwm--set-geometry id nil nil width height) - (xcb:flush exwm--connection)) + (let ((id (frame-parameter frame 'exwm-outer-id)) + (container (frame-parameter frame 'exwm-container))) + (with-slots (x y width height) + (exwm-workspace--workarea frame) + (exwm--log "x=%s; y=%s; w=%s; h=%s" x y width height) + (when (and (eq frame exwm-workspace--current) + (exwm-workspace--minibuffer-own-frame-p)) + (exwm-workspace--resize-minibuffer-frame)) + (if (exwm-workspace--active-p frame) + (exwm--set-geometry container x y width height) + (exwm--set-geometry container x y 1 1)) + (exwm--set-geometry id nil nil width height) + (xcb:flush exwm--connection))) ;; This is only used for workspace initialization. (when exwm-workspace--fullscreen-frame-count (cl-incf exwm-workspace--fullscreen-frame-count))) @@ -469,20 +473,20 @@ NIL if FRAME is not a workspace" (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)) - (let ((workarea (elt exwm-workspace--workareas exwm-workspace-current-index)) + (let ((workarea (exwm-workspace--workarea exwm-workspace-current-index)) (container (frame-parameter exwm-workspace--minibuffer 'exwm-container)) y width) (setq y (if (eq exwm-workspace-minibuffer-position 'top) - (- (aref workarea 1) + (- (slot-value workarea 'y) exwm-workspace--attached-minibuffer-height) ;; Reset the frame size. (set-frame-height exwm-workspace--minibuffer 1) (redisplay) ;FIXME. - (+ (aref workarea 1) (aref workarea 3) + (+ (slot-value workarea 'y) (slot-value workarea 'height) (- (frame-pixel-height exwm-workspace--minibuffer)) exwm-workspace--attached-minibuffer-height)) - width (aref workarea 2)) + width (slot-value workarea 'width)) (xcb:+request exwm--connection (make-instance 'xcb:ConfigureWindow :window container @@ -493,7 +497,7 @@ NIL if FRAME is not a workspace" xcb:ConfigWindow:Sibling 0) xcb:ConfigWindow:StackMode) - :x (aref workarea 0) + :x (slot-value workarea 'x) :y y :width width :sibling exwm-manage--desktop @@ -1138,8 +1142,7 @@ Please check `exwm-workspace--minibuffer-own-frame-p' first." (defun exwm-workspace--on-ConfigureNotify (data _synthetic) "Adjust the container to fit the minibuffer frame." - (let ((obj (make-instance 'xcb:ConfigureNotify)) - workarea y) + (let ((obj (make-instance 'xcb:ConfigureNotify)) y) (xcb:unmarshal obj data) (with-slots (window height) obj (when (eq (frame-parameter exwm-workspace--minibuffer 'exwm-outer-id) @@ -1159,13 +1162,13 @@ Please check `exwm-workspace--minibuffer-own-frame-p' first." (when (/= (exwm-workspace--count) (length exwm-workspace--workareas)) ;; There is a chance the workareas are not updated timely. (exwm-workspace--update-workareas)) - (setq workarea (elt exwm-workspace--workareas - exwm-workspace-current-index) - y (if (eq exwm-workspace-minibuffer-position 'top) - (- (aref workarea 1) - exwm-workspace--attached-minibuffer-height) - (+ (aref workarea 1) (aref workarea 3) (- height) - exwm-workspace--attached-minibuffer-height))) + (with-slots ((y* y) (height* height)) + (exwm-workspace--workarea exwm-workspace-current-index) + (setq y (if (eq exwm-workspace-minibuffer-position 'top) + (- y* + exwm-workspace--attached-minibuffer-height) + (+ y* height* (- height) + exwm-workspace--attached-minibuffer-height)))) (xcb:+request exwm--connection (make-instance 'xcb:ConfigureWindow :window (frame-parameter exwm-workspace--minibuffer From 937da8645820ca5abee032c523cc2c72c6ce35e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A1n=20Medra=C3=B1o=20Calvo?= Date: Fri, 9 Jun 2023 00:00:00 +0000 Subject: [PATCH 06/16] Convert `delta' to the size the strut occupies in the workarea * exwm-workspace.el (exwm-workspace--update-workareas): Repurpose `delta' to be the positive size occupied by the strut in the workarea. --- exwm-workspace.el | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/exwm-workspace.el b/exwm-workspace.el index 1bdc7245a..490d83acc 100644 --- a/exwm-workspace.el +++ b/exwm-workspace.el @@ -368,40 +368,40 @@ FRAME may be either a workspace frame or a workspace position." (pcase edge ;; Left and top are always processed first. (`left - (setq delta (- x size)) - (when (and (< delta 0) + (setq delta (- size x)) + (when (and (< 0 delta) (or (not position) (< (max beg y) (min end (+ y height))))) - (cl-incf width delta) + (cl-decf width delta) (setf x size))) (`right - (setq delta (- root-width x width size)) - (when (and (< delta 0) + (setq delta (- size (- root-width x width))) + (when (and (< 0 delta) (or (not position) (< (max beg y) (min end (+ y height))))) - (cl-incf width delta))) + (cl-decf width delta))) (`top - (setq delta (- y size)) - (when (and (< delta 0) + (setq delta (- size y)) + (when (and (< 0 delta) (or (not position) (< (max beg x) (min end (+ x width)))) (< size (+ y height)) (> size y)) - (cl-incf height delta) + (cl-decf height delta) (setf y size))) (`bottom - (setq delta (- root-height y height size)) - (when (and (< delta 0) + (setq delta (- size (- root-height y height))) + (when (and (< 0 delta) (or (not position) (< (max beg x) (min end (+ x width)))) (< (- root-height size) (+ y height)) (> (- root-height size) y)) - (cl-incf height delta)))))))) + (cl-decf height delta)))))))) ;; Save the result. (setq exwm-workspace--workareas workareas) (xcb:flush exwm--connection)) From 23f1ca740d61d435a3bceadddecad8422a05d3fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A1n=20Medra=C3=B1o=20Calvo?= Date: Fri, 9 Jun 2023 00:00:00 +0000 Subject: [PATCH 07/16] Selectively ignore left & right struts in horizontally aligned monitors * exwm-workspace.el (exwm-workspace--update-workareas): Simplify cross-monitor strut conditionals and apply them to horizontally aligned monitors. --- exwm-workspace.el | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/exwm-workspace.el b/exwm-workspace.el index 490d83acc..626d29249 100644 --- a/exwm-workspace.el +++ b/exwm-workspace.el @@ -370,6 +370,7 @@ FRAME may be either a workspace frame or a workspace position." (`left (setq delta (- size x)) (when (and (< 0 delta) + (< delta width) (or (not position) (< (max beg y) (min end (+ y height))))) @@ -378,6 +379,7 @@ FRAME may be either a workspace frame or a workspace position." (`right (setq delta (- size (- root-width x width))) (when (and (< 0 delta) + (< delta width) (or (not position) (< (max beg y) (min end (+ y height))))) @@ -385,22 +387,19 @@ FRAME may be either a workspace frame or a workspace position." (`top (setq delta (- size y)) (when (and (< 0 delta) + (< delta height) (or (not position) (< (max beg x) - (min end (+ x width)))) - (< size (+ y height)) - (> size y)) + (min end (+ x width))))) (cl-decf height delta) (setf y size))) (`bottom (setq delta (- size (- root-height y height))) (when (and (< 0 delta) + (< delta height) (or (not position) (< (max beg x) - (min end (+ x width)))) - (< (- root-height size) - (+ y height)) - (> (- root-height size) y)) + (min end (+ x width))))) (cl-decf height delta)))))))) ;; Save the result. (setq exwm-workspace--workareas workareas) From d8fcf18db77b845e1d787558f00aa21dc93310f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A1n=20Medra=C3=B1o=20Calvo?= Date: Fri, 18 Aug 2023 00:00:00 +0000 Subject: [PATCH 08/16] Declare defsubst indentation * exwm-core.el (exwm--id->buffer, exwm--buffer->id, exwm--terminal-p): * exwm-input.el (exwm-input--unread-event): * exwm-workspace.el (exwm-workspace--position) (exwm-workspace--workspace-p): Declare indentation. --- exwm-core.el | 3 +++ exwm-input.el | 2 ++ exwm-workspace.el | 5 +++-- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/exwm-core.el b/exwm-core.el index 75c7c1b17..bd6fcf822 100644 --- a/exwm-core.el +++ b/exwm-core.el @@ -116,10 +116,12 @@ FORMAT-STRING is a string specifying the message to output, as in (defsubst exwm--id->buffer (id) "X window ID => Emacs buffer." + (declare (indent defun)) (cdr (assoc id exwm--id-buffer-alist))) (defsubst exwm--buffer->id (buffer) "Emacs buffer BUFFER => X window ID." + (declare (indent defun)) (car (rassoc buffer exwm--id-buffer-alist))) (defun exwm--lock (&rest _args) @@ -183,6 +185,7 @@ least SECS seconds later." (defsubst exwm--terminal-p (&optional frame) "Return t when FRAME's terminal is EXWM's terminal. If FRAME is null, use selected frame." + (declare (indent defun)) (eq exwm--terminal (frame-terminal frame))) (defun exwm--get-client-event-mask () diff --git a/exwm-input.el b/exwm-input.el index 30ae89353..7ec9a2912 100644 --- a/exwm-input.el +++ b/exwm-input.el @@ -587,9 +587,11 @@ instead." (and (= emacs-major-version 26) (< emacs-minor-version 2))) (defsubst exwm-input--unread-event (event) + (declare (indent defun)) (setq unread-command-events (append unread-command-events (list event)))) (defsubst exwm-input--unread-event (event) + (declare (indent defun)) (setq unread-command-events (append unread-command-events `((t . ,event))))))) diff --git a/exwm-workspace.el b/exwm-workspace.el index dd1f22a9a..1db91275f 100644 --- a/exwm-workspace.el +++ b/exwm-workspace.el @@ -150,8 +150,8 @@ Please manually run the hook `exwm-workspace-list-change-hook' afterwards.") (defsubst exwm-workspace--position (frame) "Retrieve index of given FRAME in workspace list. - -NIL if FRAME is not a workspace" +NIL if FRAME is not a workspace." + (declare (indent defun)) (cl-position frame exwm-workspace--list)) (defsubst exwm-workspace--count () @@ -160,6 +160,7 @@ NIL if FRAME is not a workspace" (defsubst exwm-workspace--workspace-p (frame) "Return t if FRAME is a workspace." + (declare (indent defun)) (memq frame exwm-workspace--list)) (defsubst exwm-workspace--workarea (frame) From 612e64bf9bcb45d832c60adc049523de80b0f934 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A1n=20Medra=C3=B1o=20Calvo?= Date: Fri, 18 Aug 2023 00:00:00 +0000 Subject: [PATCH 09/16] Update copyright year to 2023 --- exwm-background.el | 2 +- exwm-cm.el | 2 +- exwm-config.el | 2 +- exwm-core.el | 2 +- exwm-floating.el | 2 +- exwm-input.el | 2 +- exwm-layout.el | 2 +- exwm-manage.el | 2 +- exwm-randr.el | 2 +- exwm-systemtray.el | 2 +- exwm-workspace.el | 2 +- exwm-xim.el | 2 +- exwm.el | 2 +- 13 files changed, 13 insertions(+), 13 deletions(-) diff --git a/exwm-background.el b/exwm-background.el index f3e0d895c..9c9bc5e35 100644 --- a/exwm-background.el +++ b/exwm-background.el @@ -1,6 +1,6 @@ ;;; exwm-background.el --- X Background Module for EXWM -*- lexical-binding: t -*- -;; Copyright (C) 2022 Free Software Foundation, Inc. +;; Copyright (C) 2022-2023 Free Software Foundation, Inc. ;; Author: Steven Allen diff --git a/exwm-cm.el b/exwm-cm.el index 8a4501003..d2d04cbf9 100644 --- a/exwm-cm.el +++ b/exwm-cm.el @@ -1,6 +1,6 @@ ;;; exwm-cm.el --- Compositing Manager for EXWM -*- lexical-binding: t -*- -;; Copyright (C) 2016-2021 Free Software Foundation, Inc. +;; Copyright (C) 2016-2023 Free Software Foundation, Inc. ;; Author: Chris Feng diff --git a/exwm-config.el b/exwm-config.el index 9609f4cf3..f3357807b 100644 --- a/exwm-config.el +++ b/exwm-config.el @@ -1,6 +1,6 @@ ;;; exwm-config.el --- Predefined configurations -*- lexical-binding: t -*- -;; Copyright (C) 2015-2021 Free Software Foundation, Inc. +;; Copyright (C) 2015-2023 Free Software Foundation, Inc. ;; Author: Chris Feng diff --git a/exwm-core.el b/exwm-core.el index bd6fcf822..defe2f752 100644 --- a/exwm-core.el +++ b/exwm-core.el @@ -1,6 +1,6 @@ ;;; exwm-core.el --- Core definitions -*- lexical-binding: t -*- -;; Copyright (C) 2015-2021 Free Software Foundation, Inc. +;; Copyright (C) 2015-2023 Free Software Foundation, Inc. ;; Author: Chris Feng diff --git a/exwm-floating.el b/exwm-floating.el index c8e433e27..def7f43e5 100644 --- a/exwm-floating.el +++ b/exwm-floating.el @@ -1,6 +1,6 @@ ;;; exwm-floating.el --- Floating Module for EXWM -*- lexical-binding: t -*- -;; Copyright (C) 2015-2021 Free Software Foundation, Inc. +;; Copyright (C) 2015-2023 Free Software Foundation, Inc. ;; Author: Chris Feng diff --git a/exwm-input.el b/exwm-input.el index 7ec9a2912..c76f1c4af 100644 --- a/exwm-input.el +++ b/exwm-input.el @@ -1,6 +1,6 @@ ;;; exwm-input.el --- Input Module for EXWM -*- lexical-binding: t -*- -;; Copyright (C) 2015-2021 Free Software Foundation, Inc. +;; Copyright (C) 2015-2023 Free Software Foundation, Inc. ;; Author: Chris Feng diff --git a/exwm-layout.el b/exwm-layout.el index ea186fe5a..56668186e 100644 --- a/exwm-layout.el +++ b/exwm-layout.el @@ -1,6 +1,6 @@ ;;; exwm-layout.el --- Layout Module for EXWM -*- lexical-binding: t -*- -;; Copyright (C) 2015-2021 Free Software Foundation, Inc. +;; Copyright (C) 2015-2023 Free Software Foundation, Inc. ;; Author: Chris Feng diff --git a/exwm-manage.el b/exwm-manage.el index a94caeeab..a4d7dabd2 100644 --- a/exwm-manage.el +++ b/exwm-manage.el @@ -1,7 +1,7 @@ ;;; exwm-manage.el --- Window Management Module for -*- lexical-binding: t -*- ;;; EXWM -;; Copyright (C) 2015-2021 Free Software Foundation, Inc. +;; Copyright (C) 2015-2023 Free Software Foundation, Inc. ;; Author: Chris Feng diff --git a/exwm-randr.el b/exwm-randr.el index 68bfdd70e..e15d43f92 100644 --- a/exwm-randr.el +++ b/exwm-randr.el @@ -1,6 +1,6 @@ ;;; exwm-randr.el --- RandR Module for EXWM -*- lexical-binding: t -*- -;; Copyright (C) 2015-2021 Free Software Foundation, Inc. +;; Copyright (C) 2015-2023 Free Software Foundation, Inc. ;; Author: Chris Feng diff --git a/exwm-systemtray.el b/exwm-systemtray.el index 3fcbb8a21..05fd3575a 100644 --- a/exwm-systemtray.el +++ b/exwm-systemtray.el @@ -1,7 +1,7 @@ ;;; exwm-systemtray.el --- System Tray Module for -*- lexical-binding: t -*- ;;; EXWM -;; Copyright (C) 2016-2022 Free Software Foundation, Inc. +;; Copyright (C) 2016-2023 Free Software Foundation, Inc. ;; Author: Chris Feng diff --git a/exwm-workspace.el b/exwm-workspace.el index 1db91275f..4d54f65e7 100644 --- a/exwm-workspace.el +++ b/exwm-workspace.el @@ -1,6 +1,6 @@ ;;; exwm-workspace.el --- Workspace Module for EXWM -*- lexical-binding: t -*- -;; Copyright (C) 1015-2021 Free Software Foundation, Inc. +;; Copyright (C) 1015-2023 Free Software Foundation, Inc. ;; Author: Chris Feng diff --git a/exwm-xim.el b/exwm-xim.el index ac530f389..c03f47620 100644 --- a/exwm-xim.el +++ b/exwm-xim.el @@ -1,6 +1,6 @@ ;;; exwm-xim.el --- XIM Module for EXWM -*- lexical-binding: t -*- -;; Copyright (C) 2019-2021 Free Software Foundation, Inc. +;; Copyright (C) 2019-2023 Free Software Foundation, Inc. ;; Author: Chris Feng diff --git a/exwm.el b/exwm.el index 31fe68495..e7bc134e5 100644 --- a/exwm.el +++ b/exwm.el @@ -1,6 +1,6 @@ ;;; exwm.el --- Emacs X Window Manager -*- lexical-binding: t -*- -;; Copyright (C) 2015-2021 Free Software Foundation, Inc. +;; Copyright (C) 2015-2023 Free Software Foundation, Inc. ;; Author: Chris Feng ;; Maintainer: Adrián Medraño Calvo From fb73aaaf8f67e601c41555262c46a29171ccbc6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A1n=20Medra=C3=B1o=20Calvo?= Date: Fri, 18 Aug 2023 00:00:00 +0000 Subject: [PATCH 10/16] Convert `lsh' to `ash' The former is deprecated. The behavioural difference between those functions does not impact us here, because the numbers returned by `x-color-values' are natural. * exwm-core.el (exwm--color->pixel): Convert `lsh' to `ash'. --- exwm-core.el | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/exwm-core.el b/exwm-core.el index defe2f752..890963d17 100644 --- a/exwm-core.el +++ b/exwm-core.el @@ -200,9 +200,9 @@ If FRAME is null, use selected frame." (when (and color (eq (x-display-visual-class) 'true-color)) (let ((rgb (x-color-values color))) - (logior (lsh (lsh (pop rgb) -8) 16) - (lsh (lsh (pop rgb) -8) 8) - (lsh (pop rgb) -8))))) + (logior (ash (ash (pop rgb) -8) 16) + (ash (ash (pop rgb) -8) 8) + (ash (pop rgb) -8))))) (defun exwm--get-visual-depth-colormap (conn id) "Get visual, depth and colormap from X window ID. From c7d1fd45bcf586e4b62daa94662dfe529cb04ac9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A1n=20Medra=C3=B1o=20Calvo?= Date: Fri, 18 Aug 2023 00:00:00 +0000 Subject: [PATCH 11/16] Fix layout being refreshed too often on minibuffer setup The guard clause was refacored incorrectly, leading to it having no effect on the intended forms. * exwm-layout.el (exwm-layout--on-minibuffer-setup): Guard `exwm-layout--refresh' again. --- exwm-layout.el | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/exwm-layout.el b/exwm-layout.el index 56668186e..d785a71f5 100644 --- a/exwm-layout.el +++ b/exwm-layout.el @@ -408,8 +408,8 @@ selected by `other-buffer'." (frame (window-frame mini-window))) (when (exwm-workspace--workspace-p frame) (exwm--defer 0 (lambda () - (when (< 1 (window-height mini-window))) - (exwm-layout--refresh frame)))))) + (when (< 1 (window-height mini-window)) + (exwm-layout--refresh frame))))))) (defun exwm-layout--on-echo-area-change (&optional dirty) "Run when message arrives or in `echo-area-clear-hook' to refresh layout." From d3567a8c7f41832617624feedc2c1c6477c4acb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A1n=20Medra=C3=B1o=20Calvo?= Date: Fri, 18 Aug 2023 00:00:00 +0000 Subject: [PATCH 12/16] 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. --- exwm-core.el | 17 +++++--- exwm-input.el | 26 ++++++------ exwm-layout.el | 23 +++++++---- exwm-manage.el | 44 ++++++++++++++------- exwm-systemtray.el | 24 ++++++----- exwm-workspace.el | 61 +++++++++++++++++----------- exwm-xim.el | 3 +- exwm.el | 99 +++++++++++++++++++++++++++++++++++----------- 8 files changed, 198 insertions(+), 99 deletions(-) diff --git a/exwm-core.el b/exwm-core.el index 890963d17..4df57e738 100644 --- a/exwm-core.el +++ b/exwm-core.el @@ -93,10 +93,12 @@ Here are some predefined candidates: (frame-or-index &optional id)) (define-minor-mode exwm-debug - "Debug-logging enabled if non-nil" - :global t) + "Debug-logging enabled if non-nil." + :global t + :group 'exwm-debug) (defmacro exwm--debug (&rest forms) + "Evaluate FORMS if mode `exwm-debug' is active." (when exwm-debug `(progn ,@forms))) (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))) (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) (make-instance 'xcb:InternAtom :only-if-exists 0 @@ -206,7 +210,10 @@ If FRAME is null, use selected frame." (defun exwm--get-visual-depth-colormap (conn 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) (with-slots (visual colormap) (xcb:+request-unchecked+reply conn @@ -238,7 +245,7 @@ One of `line-mode' or `char-mode'.") (defvar-local exwm--geometry nil) (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-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-transient-for nil "WM_TRANSIENT_FOR.") (defvar-local exwm--protocols nil) diff --git a/exwm-input.el b/exwm-input.el index c76f1c4af..be3e8f465 100644 --- a/exwm-input.el +++ b/exwm-input.el @@ -45,9 +45,9 @@ (defcustom exwm-input-prefix-keys '(?\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 defined in `exwm-mode-map' here." :type '(repeat key-sequence) @@ -87,7 +87,7 @@ defined in `exwm-mode-map' here." value)))) (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) ;; 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 "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 - "Skip the upcoming 'buffer-list-update'.") + "Skip the upcoming `buffer-list-update'.") (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) @@ -713,7 +713,7 @@ Current buffer must be an `exwm-mode' buffer." (xcb:flush exwm--connection)))) (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 (let ((keysym (xcb:keysyms:keycode->keysym exwm--connection detail state)) event raw-event) @@ -754,7 +754,7 @@ button event." xcb:Allow:ReplayPointer)))) (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 button event." (exwm--log) @@ -830,7 +830,7 @@ button event." ;;;###autoload (defun exwm-input-grab-keyboard (&optional id) - "Switch to line-mode." + "Switch to `line-mode'." (interactive (list (when (derived-mode-p 'exwm-mode) (exwm--buffer->id (window-buffer))))) (when id @@ -841,7 +841,7 @@ button event." ;;;###autoload (defun exwm-input-release-keyboard (&optional id) - "Switch to char-mode." + "Switch to `char-mode`." (interactive (list (when (derived-mode-p 'exwm-mode) (exwm--buffer->id (window-buffer))))) (when id @@ -852,7 +852,7 @@ button event." ;;;###autoload (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) (exwm--buffer->id (window-buffer))))) (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 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. Notes: @@ -1080,7 +1080,7 @@ where both ORIGINAL-KEY and SIMULATED-KEY are key sequences." (defmacro exwm-input-invoke-factory (keys) "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)) (description (key-description keys))) `(defun ,(intern (concat "exwm-input--invoke--" description)) () diff --git a/exwm-layout.el b/exwm-layout.el index d785a71f5..e47620de3 100644 --- a/exwm-layout.el +++ b/exwm-layout.el @@ -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-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--workspace-p "exwm-workspace.el" (workspace)) @@ -64,7 +65,7 @@ (frame-or-index &optional id)) (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) (xcb:+request exwm--connection (make-instance 'xcb:icccm:set-WM_STATE @@ -73,24 +74,28 @@ (setq exwm-state state))) (defun exwm-layout--iconic-state-p (&optional id) + "Check whether X window ID is in iconic state." (= xcb:icccm:WM_STATE:IconicState (if id (buffer-local-value 'exwm-state (exwm--id->buffer id)) exwm-state))) -(defun exwm-layout--set-ewmh-state (xwin) - "Set _NET_WM_STATE." - (with-current-buffer (exwm--id->buffer xwin) +(defun exwm-layout--set-ewmh-state (id) + "Set _NET_WM_STATE of X window ID to the value of variable `exwm--ewmh-state'." + (with-current-buffer (exwm--id->buffer id) (xcb:+request exwm--connection (make-instance 'xcb:ewmh:set-_NET_WM_STATE :window exwm--id :data exwm--ewmh-state)))) (defun exwm-layout--fullscreen-p () + "Check whether current `exwm-mode' buffer is in fullscreen state." (when (derived-mode-p 'exwm-mode) (memq xcb:Atom:_NET_WM_STATE_FULLSCREEN exwm--ewmh-state))) (defun exwm-layout--auto-iconify () + "Helper function to iconify unused X windows. +See variable `exwm-layout-auto-iconify'." (when (and exwm-layout-auto-iconify (not exwm-transient-for)) (let ((xwin exwm--id) @@ -210,7 +215,7 @@ ;;;###autoload (cl-defun exwm-layout-unset-fullscreen (&optional id) - "Restore window from fullscreen state." + "Restore X window ID from fullscreen state." (interactive) (exwm--log "id=#x%x" (or id 0)) (unless (and (or id (derived-mode-p 'exwm-mode)) @@ -241,7 +246,7 @@ ;;;###autoload (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)))) (exwm--log "id=#x%x" (or id 0)) (unless (or id (derived-mode-p 'exwm-mode)) @@ -298,7 +303,8 @@ selected by `other-buffer'." clients clients-floating)))))) (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-configuration-change-hook' makes the frame selected. (unless frame @@ -412,7 +418,8 @@ selected by `other-buffer'." (exwm-layout--refresh frame))))))) (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))) (msg (current-message))) ;; Check whether the frame where current window's minibuffer resides (not diff --git a/exwm-manage.el b/exwm-manage.el index a4d7dabd2..4771c3c08 100644 --- a/exwm-manage.el +++ b/exwm-manage.el @@ -34,8 +34,8 @@ :group 'exwm) (defcustom exwm-manage-finish-hook nil - "Normal hook run after a window is just managed, in the context of the -corresponding buffer." + "Normal hook run after a window is just managed. +This hook runs in the context of the corresponding `exwm-mode' buffer." :type 'hook) (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-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-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-layout--fullscreen-p "exwm-layout.el" ()) (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--set-fullscreen "exwm-workspace.el" (frame)) (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)) (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) (with-current-buffer (exwm--id->buffer id) (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)))))))) (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) (with-current-buffer (exwm--id->buffer id) (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))))))) (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) (with-current-buffer (exwm--id->buffer id) (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. 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." (let ((buffer (exwm--id->buffer id))) (exwm--log "Unmanage #x%x (buffer: %s, widthdraw: %s)" @@ -591,7 +596,8 @@ Would you like to kill it? " (throw 'return nil))))) (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)))) (exwm--log "id=#x%x" id) (let* ((response (xcb:+request-unchecked+reply exwm--connection @@ -609,14 +615,16 @@ Would you like to kill it? " (xcb:flush exwm--connection))) (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) (when (display-graphic-p frame) (push (string-to-number (frame-parameter frame 'outer-window-id)) exwm-manage--frame-outer-id-list))) (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) (when (display-graphic-p frame) (setq exwm-manage--frame-outer-id-list @@ -624,7 +632,8 @@ Would you like to kill it? " exwm-manage--frame-outer-id-list)))) (defun exwm-manage--on-ConfigureRequest (data _synthetic) - "Handle ConfigureRequest event." + "Handle ConfigureRequest event. +DATA contains unmarshalled ConfigureRequest event data." (exwm--log) (let ((obj (make-instance 'xcb:ConfigureRequest)) buffer edges width-delta height-delta) @@ -714,7 +723,8 @@ border-width: %d; sibling: #x%x; stack-mode: %d" (xcb:flush exwm--connection)) (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))) (xcb:unmarshal obj data) (with-slots (parent window) obj @@ -734,7 +744,8 @@ border-width: %d; sibling: #x%x; stack-mode: %d" (exwm-manage--manage-window window)))))) (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))) (xcb:unmarshal obj data) (with-slots (window) obj @@ -742,7 +753,8 @@ border-width: %d; sibling: #x%x; stack-mode: %d" (exwm-manage--unmanage-window window t)))) (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))) (xcb:unmarshal obj data) (with-slots (window) obj @@ -767,7 +779,9 @@ border-width: %d; sibling: #x%x; stack-mode: %d" (xcb:flush exwm--connection))))) (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 (exwm--log) (let ((obj (make-instance 'xcb:DestroyNotify))) diff --git a/exwm-systemtray.el b/exwm-systemtray.el index 05fd3575a..7f2b268df 100644 --- a/exwm-systemtray.el +++ b/exwm-systemtray.el @@ -49,7 +49,7 @@ (defclass xcb:systemtray:-ClientMessage (xcb:icccm:--ClientMessage xcb:ClientMessage) ((format :initform 32) - (type :initform xcb:Atom:MANAGER) + (type :initform 'xcb:Atom:MANAGER) (time :initarg :time :type xcb:TIMESTAMP) ;new slot (selection :initarg :selection :type xcb:ATOM) ;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) (defun exwm-systemtray--embed (icon) - "Embed an icon." + "Embed an ICON." (exwm--log "Try to embed #x%x" icon) (let ((info (xcb:+request-unchecked+reply exwm-systemtray--connection (make-instance 'xcb:xembed:get-_XEMBED_INFO @@ -210,7 +210,7 @@ using 32-bit depth. Using `workspace-background' instead.") (exwm-systemtray--refresh)))) (defun exwm-systemtray--unembed (icon) - "Unembed an icon." + "Unembed an ICON." (exwm--log "Unembed #x%x" icon) (xcb:+request exwm-systemtray--connection (make-instance 'xcb:UnmapWindow :window icon)) @@ -331,7 +331,8 @@ indicate how to support actual transparency." (<= planes 24)))) (defun exwm-systemtray--on-DestroyNotify (data _synthetic) - "Unembed icons on DestroyNotify." + "Unembed icons on DestroyNotify. +Argument DATA contains the raw event data." (exwm--log) (let ((obj (make-instance 'xcb:DestroyNotify))) (xcb:unmarshal obj data) @@ -340,7 +341,8 @@ indicate how to support actual transparency." (exwm-systemtray--unembed window))))) (defun exwm-systemtray--on-ReparentNotify (data _synthetic) - "Unembed icons on ReparentNotify." + "Unembed icons on ReparentNotify. +Argument DATA contains the raw event data." (exwm--log) (let ((obj (make-instance 'xcb:ReparentNotify))) (xcb:unmarshal obj data) @@ -350,7 +352,8 @@ indicate how to support actual transparency." (exwm-systemtray--unembed window))))) (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) (let ((obj (make-instance 'xcb:ResizeRequest)) attr) @@ -378,7 +381,8 @@ indicate how to support actual transparency." (exwm-systemtray--refresh))))) (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) (let ((obj (make-instance 'xcb:PropertyNotify)) attr info visible) @@ -403,7 +407,8 @@ indicate how to support actual transparency." (exwm-systemtray--refresh)))))) (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)) opcode data32) (xcb:unmarshal obj data) @@ -422,7 +427,8 @@ indicate how to support actual transparency." (exwm--log "Unknown opcode message: %s" obj))))))) (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) ;; This function is only executed when there's no autohide minibuffer, ;; a workspace frame has the input focus and the pointer is over a diff --git a/exwm-workspace.el b/exwm-workspace.el index 4d54f65e7..c78089cfb 100644 --- a/exwm-workspace.el +++ b/exwm-workspace.el @@ -39,8 +39,8 @@ :type 'hook) (defcustom exwm-workspace-list-change-hook nil - "Normal hook run when the workspace list is changed (workspace added, -deleted, moved, etc)." + "Normal hook run when the workspace list is changed. +This happens when a workspace is added, deleted, moved, etc." :type 'hook) (defcustom exwm-workspace-show-all-buffers nil @@ -74,8 +74,7 @@ A restart is required for this change to take effect." :type 'integer) (defcustom exwm-workspace-switch-create-limit 10 - "Number of workspaces `exwm-workspace-switch-create' allowed to create -each time." + "Number of workspaces `exwm-workspace-switch-create' is allowed to create." :type 'integer) (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.") (defun exwm-workspace--init-switch-map () + "Initialize variable `exwm-workspace--switch-map'." (let ((map (make-sparse-keymap))) (define-key map [t] (lambda () (interactive))) (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)))) (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) (let* ((current-idx (exwm-workspace--position exwm-workspace--current)) (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)))))))) (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) (set-frame-parameter frame 'exwm-active active) (if active @@ -447,7 +449,7 @@ FRAME may be either a workspace frame or a workspace position." (xcb:flush exwm--connection)) (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)) (defun exwm-workspace--set-fullscreen (frame) @@ -560,11 +562,13 @@ PREFIX-DIGITS is a list of the digits introduced so far." ;;;###autoload (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 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 (list (cond @@ -690,7 +694,7 @@ for internal use only." ;;;###autoload (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." (interactive @@ -976,7 +980,7 @@ INDEX must not exceed the current number of workspaces." ;;;###autoload (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 (let ((inhibit-quit t)) ;; Show all buffers @@ -1028,7 +1032,7 @@ INDEX must not exceed the current number of workspaces." (switch-to-buffer buffer-or-name))))) (defun exwm-workspace-rename-buffer (newname) - "Rename a buffer." + "Rename current buffer to NEWNAME." (let ((hidden (= ?\s (aref newname 0))) (basename (replace-regexp-in-string "<[0-9]+>$" "" newname)) (counter 1) @@ -1044,10 +1048,12 @@ INDEX must not exceed the current number of workspaces." buffer-list-update-hook))) (rename-buffer (concat (and hidden " ") newname))))) -(defun exwm-workspace--x-create-frame (orig-fun params) - "Set override-redirect on the frame created by `x-create-frame'." +(defun exwm-workspace--x-create-frame (orig-x-create-frame params) + "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) - (let ((frame (funcall orig-fun params))) + (let ((frame (funcall orig-x-create-frame params))) (xcb:+request exwm--connection (make-instance 'xcb:ChangeWindowAttributes :window (string-to-number @@ -1066,7 +1072,7 @@ Please check `exwm-workspace--minibuffer-own-frame-p' first." ;;;###autoload (defun exwm-workspace-attach-minibuffer () - "Attach the minibuffer so that it always shows." + "Attach the minibuffer making it always visible." (interactive) (exwm--log) (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)))) (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) (let ((height (with-current-buffer @@ -1141,7 +1149,8 @@ Please check `exwm-workspace--minibuffer-own-frame-p' first." (set-frame-height exwm-workspace--minibuffer height)))) (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) (xcb:unmarshal obj data) (with-slots (window height) obj @@ -1180,7 +1189,8 @@ Please check `exwm-workspace--minibuffer-own-frame-p' first." (xcb:flush exwm--connection))))) (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. ;; This also protect this functions from being recursively called. (when (eq (selected-frame) exwm-workspace--minibuffer) @@ -1232,7 +1242,7 @@ Please check `exwm-workspace--minibuffer-own-frame-p' first." (xcb:flush exwm--connection)) (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) (when (and (= 1 (minibuffer-depth)) (exwm--terminal-p)) @@ -1254,7 +1264,7 @@ Please check `exwm-workspace--minibuffer-own-frame-p' first." (window-preserve-size window))))) (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) (when (and (= 1 (minibuffer-depth)) (exwm--terminal-p)) @@ -1288,7 +1298,7 @@ Please check `exwm-workspace--minibuffer-own-frame-p' first." #'exwm-workspace--echo-area-maybe-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) (unless (active-minibuffer-window) (exwm-workspace--hide-minibuffer)) @@ -1398,7 +1408,8 @@ Return nil if FRAME is the only workspace." nextw))) (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, ;; etc) (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))) (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 ((not (exwm-workspace--workspace-p frame)) (exwm--log "Frame `%s' is not a workspace" frame)) @@ -1548,6 +1559,7 @@ applied to all subsequently created X frames." (interactive "e")) (defun exwm-workspace--init-minibuffer-frame () + "Initialize minibuffer-only frame." (exwm--log) ;; Initialize workspaces without minibuffers. (setq exwm-workspace--minibuffer @@ -1618,6 +1630,7 @@ applied to all subsequently created X frames." :test #'equal)) (defun exwm-workspace--exit-minibuffer-frame () + "Cleanup minibuffer-only frame." (exwm--log) ;; Only on minibuffer-frame. (remove-hook 'minibuffer-setup-hook #'exwm-workspace--on-minibuffer-setup) diff --git a/exwm-xim.el b/exwm-xim.el index c03f47620..aea0eb53f 100644 --- a/exwm-xim.el +++ b/exwm-xim.el @@ -68,7 +68,7 @@ ;;; Code: -(eval-when-compile (require 'cl-lib)) +(require 'cl-lib) (require 'xcb-keysyms) (require 'xcb-xim) @@ -167,6 +167,7 @@ C,no" (defun exwm-xim--on-SelectionRequest (data _synthetic) "Handle SelectionRequest events on IMS window. +DATA contains unmarshalled SelectionRequest event data. Such events would be received when clients query for LOCALES or TRANSPORT." (exwm--log) diff --git a/exwm.el b/exwm.el index e7bc134e5..369d9c8e5 100644 --- a/exwm.el +++ b/exwm.el @@ -153,7 +153,8 @@ (kill-emacs)))))) (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) (with-current-buffer (exwm--id->buffer xwin) (let ((reply (xcb:+request-unchecked+reply exwm--connection @@ -180,7 +181,11 @@ (exwm-workspace--set-desktop xwin))))))) (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) (with-current-buffer (exwm--id->buffer id) (unless (and exwm-window-type (not force)) @@ -191,7 +196,11 @@ (setq exwm-window-type (append (slot-value reply 'value) nil))))))) (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) (with-current-buffer (exwm--id->buffer id) (unless (and exwm-instance-name exwm-class-name (not force)) @@ -204,7 +213,11 @@ (run-hooks 'exwm-update-class-hook))))))) (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) (with-current-buffer (exwm--id->buffer id) (when (or force (not exwm-title)) @@ -217,7 +230,11 @@ (run-hooks 'exwm-update-title-hook))))))) (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) (with-current-buffer (exwm--id->buffer id) (unless (or exwm--title-is-utf8 @@ -230,13 +247,18 @@ (run-hooks 'exwm-update-title-hook))))))) (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--update-utf8-title id) (exwm--update-ctext-title id)) (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) (with-current-buffer (exwm--id->buffer id) (unless (and exwm-transient-for (not force)) @@ -247,7 +269,15 @@ (setq exwm-transient-for (slot-value reply 'value))))))) (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) (with-current-buffer (exwm--id->buffer id) (unless (and (not force) @@ -295,7 +325,11 @@ exwm--normal-hints-max-height))))))))) (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) (with-current-buffer (exwm--id->buffer id) (unless (and (not force) exwm--hints-input exwm--hints-urgency) @@ -317,7 +351,11 @@ (setq exwm-workspace--switch-history-outdated t)))))))) (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) (with-current-buffer (exwm--id->buffer id) (unless (and exwm--protocols (not force)) @@ -328,7 +366,7 @@ (setq exwm--protocols (append (slot-value reply 'value) nil))))))) (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) (let ((pair (assq id exwm-workspace--id-struts-alist)) reply struts) @@ -349,7 +387,7 @@ (exwm-workspace--set-fullscreen f))))) (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) (let ((reply (xcb:+request-unchecked+reply exwm--connection (make-instance 'xcb:ewmh:get-_NET_WM_STRUT_PARTIAL @@ -369,13 +407,14 @@ (exwm-workspace--set-fullscreen f)))) (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--update-struts-partial id) (exwm--update-struts-legacy id)) (defun exwm--on-PropertyNotify (data _synthetic) - "Handle PropertyNotify event." + "Handle PropertyNotify event. +DATA contains unmarshalled PropertyNotify event data." (let ((obj (make-instance 'xcb:PropertyNotify)) atom id buffer) (xcb:unmarshal obj data) @@ -413,7 +452,8 @@ atom))))))) (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)) type id data) (xcb:unmarshal obj raw-data) @@ -598,7 +638,8 @@ (x-get-atom-name type exwm-workspace--current) type))))) (defun exwm--on-SelectionClear (data _synthetic) - "Handle SelectionClear events." + "Handle SelectionClear events. +DATA contains unmarshalled SelectionClear event data." (exwm--log) (let ((obj (make-instance 'xcb:SelectionClear)) owner selection) @@ -611,6 +652,10 @@ (defun exwm--on-delete-terminal (terminal) "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 session." (when (eq terminal exwm--terminal) @@ -836,7 +881,8 @@ manager. If t, replace it, if nil, abort and ask the user if `ask'." ;;;###autoload (cl-defun exwm-init (&optional frame) - "Initialize EXWM." + "Initialize EXWM. +FRAME, if given, indicates the X display EXWM should manage." (interactive) (exwm--log "%s" 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) (setq exwm--server-process nil))) -(defun exwm--server-eval-at (&rest args) - "Wrapper of `server-eval-at' used to advice subrs." +(defun exwm--server-eval-at (function &rest args) + "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 - (exwm--log "%s" args) + (exwm--log "%s %s" function args) (unless (server-running-p exwm--server-name) (when exwm--server-process (delete-process 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 exwm--server-name `(progn (select-frame (car (frame-list))) - (let ((result ,(nconc (list (make-symbol (subr-name (car args)))) - (cdr args)))) + (let ((result ,(nconc (list (make-symbol (subr-name function))) + args))) (pcase (type-of result) ;; Return the name of a buffer (`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 ;; frames. (if (exwm--terminal-p) - (exwm--confirm-kill-emacs "[EXWM] Kill terminal?") + (exwm--confirm-kill-emacs "Kill terminal?") t)) (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) (when (cond ((and force (not (eq force 'no-check))) From 381637aa1c7b82671fab4cfdadebee590f7c1c45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A1n=20Medra=C3=B1o=20Calvo?= Date: Fri, 18 Aug 2023 00:00:00 +0000 Subject: [PATCH 13/16] Declare external function * exwm.el: * exwm-randr.el: Declare `x-get-atom-name' function. --- exwm-randr.el | 2 ++ exwm.el | 2 ++ 2 files changed, 4 insertions(+) diff --git a/exwm-randr.el b/exwm-randr.el index e15d43f92..8d1824bab 100644 --- a/exwm-randr.el +++ b/exwm-randr.el @@ -52,6 +52,8 @@ (require 'exwm-core) (require 'exwm-workspace) +(declare-function x-get-atom-name "C source code" (VALUE &optional FRAME)) + (defgroup exwm-randr nil "RandR." :version "25.3" diff --git a/exwm.el b/exwm.el index 369d9c8e5..4d6b45115 100644 --- a/exwm.el +++ b/exwm.el @@ -72,6 +72,8 @@ (require 'exwm-manage) (require 'exwm-input) +(declare-function x-get-atom-name "C source code" (VALUE &optional FRAME)) + (defgroup exwm nil "Emacs X Window Manager." :tag "EXWM" From 8cab6c03fa2cc59d5863f5cc67197d480452c22a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A1n=20Medra=C3=B1o=20Calvo?= Date: Sun, 10 Sep 2023 00:00:00 +0000 Subject: [PATCH 14/16] Fix workspace height unsharing workarea value * exwm-workspace.el (exwm-workspace--update-workareas): Clone the value of the `exwm-geometry' frame parameter before modifying it for calculating workareas. (exwm-workspace--update-workareas): Simplify `pcase' patterns. --- exwm-workspace.el | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/exwm-workspace.el b/exwm-workspace.el index c78089cfb..61e2f69d2 100644 --- a/exwm-workspace.el +++ b/exwm-workspace.el @@ -345,18 +345,20 @@ Show PROMPT to the user if non-nil." (let* ((root-width (x-display-pixel-width)) (root-height (x-display-pixel-height)) ;; Get workareas prior to struts. - (workareas (mapcar (lambda (f) - (or - ;; Use the 'exwm-geometry' frame parameter if - ;; possible. - (frame-parameter f 'exwm-geometry) - ;; Fall back to use the screen size. - (make-instance 'xcb:RECTANGLE - :x 0 - :y 0 - :width root-width - :height root-height))) - exwm-workspace--list))) + (workareas (mapcar + (lambda (frame) + (if-let (rect (frame-parameter frame 'exwm-geometry)) + ;; Use the 'exwm-geometry' frame parameter if it + ;; exists. Make sure to clone it, will be modified + ;; below! + (clone rect) + ;; Fall back to use the screen size. + (make-instance 'xcb:RECTANGLE + :x 0 + :y 0 + :width root-width + :height root-height))) + exwm-workspace--list))) ;; Exclude areas occupied by struts. (dolist (struts exwm-workspace--struts) (let* ((edge (aref struts 0)) @@ -369,7 +371,7 @@ Show PROMPT to the user if non-nil." (with-slots (x y width height) w (pcase edge ;; Left and top are always processed first. - (`left + ('left (setq delta (- size x)) (when (and (< 0 delta) (< delta width) @@ -378,7 +380,7 @@ Show PROMPT to the user if non-nil." (min end (+ y height))))) (cl-decf width delta) (setf x size))) - (`right + ('right (setq delta (- size (- root-width x width))) (when (and (< 0 delta) (< delta width) @@ -386,7 +388,7 @@ Show PROMPT to the user if non-nil." (< (max beg y) (min end (+ y height))))) (cl-decf width delta))) - (`top + ('top (setq delta (- size y)) (when (and (< 0 delta) (< delta height) @@ -395,7 +397,7 @@ Show PROMPT to the user if non-nil." (min end (+ x width))))) (cl-decf height delta) (setf y size))) - (`bottom + ('bottom (setq delta (- size (- root-height y height))) (when (and (< 0 delta) (< delta height) From 31f0f0a9c7b8e1b7edf0309fc523d67ec90874f2 Mon Sep 17 00:00:00 2001 From: David Wilson Date: Wed, 8 Sep 2021 09:58:15 -0700 Subject: [PATCH 15/16] Catch and report all errors raised when invoking command hooks * exwm-input.el (exwm-input--fake-last-command): Catch and report all errors raised when invoking `pre-command-hook' and `post-command-hook'. Copyright-paperwork-exempt: yes --- exwm-input.el | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/exwm-input.el b/exwm-input.el index be3e8f465..05b021093 100644 --- a/exwm-input.el +++ b/exwm-input.el @@ -668,8 +668,26 @@ Current buffer must be an `exwm-mode' buffer." (defun exwm-input--fake-last-command () "Fool some packages into thinking there is a change in the buffer." (setq last-command #'exwm-input--noop) - (run-hooks 'pre-command-hook) - (run-hooks 'post-command-hook)) + ;; The Emacs manual says: + ;; > Quitting is suppressed while running pre-command-hook and + ;; > post-command-hook. If an error happens while executing one of these + ;; > hooks, it does not terminate execution of the hook; instead the error is + ;; > silenced and the function in which the error occurred is removed from the + ;; > hook. + ;; We supress errors but neither continue execution nor we remove from the + ;; hook. + (condition-case err + (run-hooks 'pre-command-hook) + ((error) + (exwm--log "Error occurred while running pre-command-hook: %s" + (error-message-string err)) + (xcb-debug:backtrace))) + (condition-case err + (run-hooks 'post-command-hook) + ((error) + (exwm--log "Error occurred while running post-command-hook: %s" + (error-message-string err)) + (xcb-debug:backtrace)))) (defun exwm-input--on-KeyPress-line-mode (key-press raw-data) "Parse X KeyPress event to Emacs key event and then feed the command loop." From 86f43494ebd056cd732fb1d10d440e0eba547228 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A1n=20Medra=C3=B1o=20Calvo?= Date: Fri, 6 Oct 2023 00:00:00 +0000 Subject: [PATCH 16/16] Bump version to 0.28 --- exwm.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exwm.el b/exwm.el index 4d6b45115..574553372 100644 --- a/exwm.el +++ b/exwm.el @@ -4,7 +4,7 @@ ;; Author: Chris Feng ;; Maintainer: Adrián Medraño Calvo -;; Version: 0.27 +;; Version: 0.28 ;; Package-Requires: ((xelb "0.18")) ;; Keywords: unix ;; URL: https://github.com/ch11ng/exwm