diff --git a/exwm-config.el b/exwm-config.el index 6635e43..4454ea5 100644 --- a/exwm-config.el +++ b/exwm-config.el @@ -47,8 +47,8 @@ ([?\s-w] . exwm-workspace-switch) ;; 's-&': Launch application. ([?\s-&] . (lambda (command) - (interactive (list (read-shell-command "$ "))) - (start-process-shell-command command nil command))) + (interactive (list (read-shell-command "$ "))) + (start-process-shell-command command nil command))) ;; 's-N': Switch to certain workspace. ,@(mapcar (lambda (i) `(,(kbd (format "s-%d" i)) . diff --git a/exwm-core.el b/exwm-core.el index ed9a523..b0a6839 100644 --- a/exwm-core.el +++ b/exwm-core.el @@ -168,8 +168,8 @@ The action is to call FUNCTION with arguments ARGS. If Emacs is not idle, defer the action until Emacs is idle. Otherwise, defer the action until at least SECS seconds later." `(run-with-idle-timer (+ (float-time (or (current-idle-time) - (seconds-to-time (- ,secs)))) - ,secs) + (seconds-to-time (- ,secs)))) + ,secs) nil ,function ,@args)) diff --git a/exwm-floating.el b/exwm-floating.el index 27ee574..189acc4 100644 --- a/exwm-floating.el +++ b/exwm-floating.el @@ -124,12 +124,15 @@ This is also used by X window containers.") "Calculate move/resize parameters [buffer event-mask x y width height].") (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" ()) (defun exwm-floating--set-allowed-actions (id tilling) "Set _NET_WM_ALLOWED_ACTIONS." @@ -166,8 +169,8 @@ This is also used by X window containers.") (get-buffer "*scratch*"))) (make-frame `((minibuffer . ,(minibuffer-window exwm--frame)) - (left . ,(* window-min-width -100)) - (top . ,(* window-min-height -100)) + (left . ,(* window-min-width -10000)) + (top . ,(* window-min-height -10000)) (width . ,window-min-width) (height . ,window-min-height) (unsplittable . t))))) ;and fix the size later @@ -179,6 +182,9 @@ This is also used by X window containers.") (y (slot-value exwm--geometry 'y)) (width (slot-value exwm--geometry 'width)) (height (slot-value exwm--geometry 'height))) + ;; Force drawing menu-bar & tool-bar. + (redisplay t) + (exwm-workspace--update-offsets) (exwm--log "Floating geometry (original): %dx%d%+d%+d" width height x y) ;; Save frame parameters. (set-frame-parameter frame 'exwm-outer-id outer-id) @@ -261,14 +267,12 @@ This is also used by X window containers.") ;; The frame will be made visible by `select-frame-set-input-focus'. (make-frame-invisible frame) (let* ((edges (window-inside-pixel-edges window)) - (geometry (frame-geometry frame)) (frame-width (+ width (- (frame-pixel-width frame) (- (elt edges 2) (elt edges 0))))) (frame-height (+ height (- (frame-pixel-height frame) (- (elt edges 3) (elt edges 1))) ;; Use `frame-outer-height' in the future. - (or (cddr (assq 'menu-bar-size geometry)) 0) - (or (cddr (assq 'tool-bar-size geometry)) 0))) + exwm-workspace--frame-y-offset)) (floating-mode-line (plist-get exwm--configurations 'floating-mode-line)) (floating-header-line (plist-get exwm--configurations @@ -293,7 +297,7 @@ This is also used by X window containers.") 'floating-header-line)) exwm--mwm-hints-decorations) (setq header-line-format nil) - ;; The header-line need to be hidden in floating header. + ;; The header-line need to be hidden in floating mode. (setq frame-height (- frame-height (window-header-line-height (frame-root-window frame))) header-line-format nil))) @@ -304,8 +308,8 @@ This is also used by X window containers.") :depth 0 :wid frame-container :parent exwm--root - :x (- x (elt edges 0)) - :y (- y (elt edges 1)) + :x x + :y (- y exwm-workspace--window-y-offset) :width width :height height :border-width @@ -377,7 +381,7 @@ This is also used by X window containers.") (with-current-buffer (exwm--id->buffer id) (run-hooks 'exwm-floating-setup-hook)) ;; Redraw the frame. - (redisplay)) + (redisplay t)) (defun exwm-floating--unset-floating (id) "Make window ID non-floating." @@ -644,11 +648,38 @@ This is also used by X window containers.") (xcb:+request exwm--connection (make-instance 'xcb:UngrabPointer :time xcb:Time:CurrentTime)) (when exwm-floating--moveresize-calculate - (let (result buffer-or-id) + (let (result buffer-or-id outer-id container-id) (setq result (funcall exwm-floating--moveresize-calculate 0 0) buffer-or-id (aref result 0)) (when (bufferp buffer-or-id) (with-current-buffer buffer-or-id + (setq outer-id (frame-parameter exwm--floating-frame 'exwm-outer-id) + container-id (frame-parameter exwm--floating-frame + 'exwm-container)) + (with-slots (x y width height border-width) + (xcb:+request-unchecked+reply exwm--connection + (make-instance 'xcb:GetGeometry + :drawable container-id)) + ;; Notify Emacs frame about this the position change. + (xcb:+request exwm--connection + (make-instance 'xcb:SendEvent + :propagate 0 + :destination outer-id + :event-mask xcb:EventMask:StructureNotify + :event + (xcb:marshal + (make-instance 'xcb:ConfigureNotify + :event outer-id + :window outer-id + :above-sibling xcb:Window:None + :x (+ x border-width) + :y (+ y border-width) + :width width + :height height + :border-width 0 + :override-redirect 0) + exwm--connection))) + (xcb:flush exwm--connection)) (exwm-layout--show exwm--id (frame-root-window exwm--floating-frame))))) (setq exwm-floating--moveresize-calculate nil))) @@ -657,8 +688,7 @@ This is also used by X window containers.") "Perform move/resize." (when exwm-floating--moveresize-calculate (let* ((obj (make-instance 'xcb:MotionNotify)) - result value-mask x y width height buffer-or-id container-or-id - geometry y-offset) + result value-mask x y width height buffer-or-id container-or-id) (xcb:unmarshal obj data) (setq result (funcall exwm-floating--moveresize-calculate (slot-value obj 'root-x) (slot-value obj 'root-y)) @@ -675,12 +705,11 @@ This is also used by X window containers.") (setq container-or-id (with-current-buffer buffer-or-id (frame-parameter exwm--floating-frame 'exwm-container)) - geometry (frame-geometry exwm--floating-frame) + x (- x exwm-floating-border-width) ;; Use `frame-outer-height' in the future. - y-offset (+ (or (cddr (assq 'menu-bar-size geometry)) 0) - (or (cddr (assq 'tool-bar-size geometry)) 0)) - y (- y y-offset) - height (+ height y-offset))) + y (- y exwm-floating-border-width + exwm-workspace--window-y-offset) + height (+ height exwm-workspace--window-y-offset))) (xcb:+request exwm--connection (make-instance 'xcb:ConfigureWindow :window container-or-id diff --git a/exwm-layout.el b/exwm-layout.el index 0b5adeb..9f1e0cf 100644 --- a/exwm-layout.el +++ b/exwm-layout.el @@ -52,6 +52,7 @@ (defvar exwm-layout--timer nil "Timer used to track echo area changes.") (defvar exwm-workspace--current) +(defvar exwm-workspace--frame-y-offset) (declare-function exwm-input--release-keyboard "exwm-input.el") (declare-function exwm-input--grab-keyboard "exwm-input.el") (declare-function exwm-input-grab-keyboard "exwm-input.el") @@ -105,15 +106,13 @@ (y (pop edges)) (width (- (pop edges) x)) (height (- (pop edges) y)) - geometry frame-x frame-y frame-width frame-height) + frame-x frame-y frame-width frame-height) (with-current-buffer (exwm--id->buffer id) (when exwm--floating-frame (setq frame-width (frame-pixel-width exwm--floating-frame) - geometry (frame-geometry exwm--floating-frame) frame-height (+ (frame-pixel-height exwm--floating-frame) ;; Use `frame-outer-height' in the future. - (or (cddr (assq 'menu-bar-size geometry)) 0) - (or (cddr (assq 'tool-bar-size geometry)) 0))) + exwm-workspace--frame-y-offset)) (when exwm--floating-frame-position (setq frame-x (elt exwm--floating-frame-position 0) frame-y (elt exwm--floating-frame-position 1) diff --git a/exwm-systemtray.el b/exwm-systemtray.el index a095bfa..35010ee 100644 --- a/exwm-systemtray.el +++ b/exwm-systemtray.el @@ -331,42 +331,37 @@ You shall use the default value if using auto-hide minibuffer." "Reparent/Refresh the system tray in `exwm-workspace-switch-hook'." (exwm--log) (unless (exwm-workspace--minibuffer-own-frame-p) - (let ((geometry (frame-geometry exwm-workspace--current))) - (xcb:+request exwm-systemtray--connection - (make-instance 'xcb:ReparentWindow - :window exwm-systemtray--embedder-window - :parent (string-to-number - (frame-parameter exwm-workspace--current - 'window-id)) - :x 0 - :y (- (elt (elt exwm-workspace--workareas - exwm-workspace-current-index) - 3) - (or (cddr (assq 'menu-bar-size geometry)) 0) - (or (cddr (assq 'tool-bar-size geometry)) 0) - exwm-systemtray-height))))) + (exwm-workspace--update-offsets) + (xcb:+request exwm-systemtray--connection + (make-instance 'xcb:ReparentWindow + :window exwm-systemtray--embedder-window + :parent (string-to-number + (frame-parameter exwm-workspace--current + 'window-id)) + :x 0 + :y (- (elt (elt exwm-workspace--workareas + exwm-workspace-current-index) + 3) + exwm-workspace--frame-y-offset + exwm-systemtray-height)))) (exwm-systemtray--refresh)) -(defun exwm-systemtray--on-randr-refresh () - "Reposition/Refresh the system tray in `exwm-randr-refresh-hook'." +(defun exwm-systemtray--refresh-all () + "Reposition/Refresh the system tray." (exwm--log) (unless (exwm-workspace--minibuffer-own-frame-p) - (let ((geometry (frame-geometry exwm-workspace--current))) - (xcb:+request exwm-systemtray--connection - (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) - (or (cddr (assq 'menu-bar-size geometry)) 0) - (or (cddr (assq 'tool-bar-size geometry)) 0) - exwm-systemtray-height))))) + (exwm-workspace--update-offsets) + (xcb:+request exwm-systemtray--connection + (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) + exwm-workspace--frame-y-offset + exwm-systemtray-height)))) (exwm-systemtray--refresh)) -(defalias 'exwm-systemtray--on-struts-update - #'exwm-systemtray--on-randr-refresh) - (cl-defun exwm-systemtray--init () "Initialize system tray module." (exwm--log) @@ -452,11 +447,14 @@ You shall use the default value if using auto-hide minibuffer." (- (line-pixel-height) exwm-systemtray-height) ;; Vertically centered. (/ (- (line-pixel-height) exwm-systemtray-height) 2))) - (let ((workarea (elt exwm-workspace--workareas - exwm-workspace-current-index))) - (setq frame exwm-workspace--current - ;; Bottom aligned. - y (- (aref workarea 3) exwm-systemtray-height)))) + (exwm-workspace--update-offsets) + (setq frame exwm-workspace--current + ;; Bottom aligned. + y (- (elt (elt exwm-workspace--workareas + exwm-workspace-current-index) + 3) + exwm-workspace--frame-y-offset + exwm-systemtray-height))) (setq parent (string-to-number (frame-parameter frame 'window-id)) depth (slot-value (xcb:+request-unchecked+reply exwm-systemtray--connection @@ -501,12 +499,14 @@ You shall use the default value if using auto-hide minibuffer." ;; Add hook to move/reparent the embedder. (add-hook 'exwm-workspace-switch-hook #'exwm-systemtray--on-workspace-switch) (add-hook 'exwm-workspace--update-workareas-hook - #'exwm-systemtray--on-struts-update) + #'exwm-systemtray--refresh-all) + (add-hook 'menu-bar-mode-hook #'exwm-systemtray--refresh-all) + (add-hook 'tool-bar-mode-hook #'exwm-systemtray--refresh-all) (when (boundp 'exwm-randr-refresh-hook) - (add-hook 'exwm-randr-refresh-hook #'exwm-systemtray--on-randr-refresh)) + (add-hook 'exwm-randr-refresh-hook #'exwm-systemtray--refresh-all)) ;; The struts can be updated already. (when exwm-workspace--workareas - (exwm-systemtray--on-struts-update))) + (exwm-systemtray--refresh-all))) (defun exwm-systemtray--exit () "Exit the systemtray module." @@ -532,10 +532,11 @@ You shall use the default value if using auto-hide minibuffer." (remove-hook 'exwm-workspace-switch-hook #'exwm-systemtray--on-workspace-switch) (remove-hook 'exwm-workspace--update-workareas-hook - #'exwm-systemtray--on-struts-update) + #'exwm-systemtray--refresh-all) + (remove-hook 'menu-bar-mode-hook #'exwm-systemtray--refresh-all) + (remove-hook 'tool-bar-mode-hook #'exwm-systemtray--refresh-all) (when (boundp 'exwm-randr-refresh-hook) - (remove-hook 'exwm-randr-refresh-hook - #'exwm-systemtray--on-randr-refresh)))) + (remove-hook 'exwm-randr-refresh-hook #'exwm-systemtray--refresh-all)))) (defun exwm-systemtray-enable () "Enable system tray support for EXWM." diff --git a/exwm-workspace.el b/exwm-workspace.el index ac4cb98..4134318 100644 --- a/exwm-workspace.el +++ b/exwm-workspace.el @@ -134,6 +134,11 @@ Please manually run the hook `exwm-workspace-list-change-hook' afterwards.") (defvar exwm-workspace--workareas nil "Workareas (struts excluded).") +(defvar exwm-workspace--frame-y-offset 0 + "Offset between Emacs inner & outer frame in Y.") +(defvar exwm-workspace--window-y-offset 0 + "Offset between Emacs first window & outer frame in Y.") + (defvar exwm-input--during-command) (defvar exwm-input--event-hook) (defvar exwm-layout-show-all-buffers) @@ -397,6 +402,28 @@ NIL if FRAME is not a workspace" (exwm--log "%s" exwm-workspace--workareas) (run-hooks 'exwm-workspace--update-workareas-hook)) +(defun exwm-workspace--update-offsets () + "Update `exwm-workspace--frame-y-offset'/`exwm-workspace--window-y-offset'." + (exwm--log) + (if (not (and exwm-workspace--list + (or menu-bar-mode tool-bar-mode))) + (setq exwm-workspace--frame-y-offset 0 + exwm-workspace--window-y-offset 0) + (redisplay t) + (let* ((frame (elt exwm-workspace--list 0)) + (edges (window-inside-absolute-pixel-edges (frame-first-window + frame)))) + (with-slots (y) + (xcb:+request-unchecked+reply exwm--connection + (make-instance 'xcb:GetGeometry + :drawable (frame-parameter frame 'exwm-outer-id))) + (with-slots ((y* y)) + (xcb:+request-unchecked+reply exwm--connection + (make-instance 'xcb:GetGeometry + :drawable (frame-parameter frame 'exwm-id))) + (setq exwm-workspace--frame-y-offset (- y* y) + exwm-workspace--window-y-offset (- (elt edges 1) y))))))) + (defun exwm-workspace--set-active (frame active) "Make frame FRAME active on its monitor." (exwm--log "active=%s; frame=%s" frame active)