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