diff options
author | Chris Feng <chris.w.feng@gmail.com> | 2016-02-03T04·12+0800 |
---|---|---|
committer | Chris Feng <chris.w.feng@gmail.com> | 2016-02-03T04·12+0800 |
commit | 9c95c03e18f6d5cf78bcd54bf00f8055a3863336 (patch) | |
tree | 1733a55d18719fd8eba91055cacfd6de5c63bcad /exwm-layout.el | |
parent | 07921a3731c3b951d7d5ecc35b808c40d1d15bd4 (diff) |
Rework the X windows hierarchy model
This commit add workspace and X window containers support to avoid using Emacs frames as the parents of X windows. This should make it easier to set input focus. * exwm-core.el (exwm--container, exwm--floating-frame-position): New file local variables. (exwm--floating-frame-geometry): Removed file local variable. * exwm-floating.el (exwm-floating--set-floating) (exwm-floating--unset-floating, exwm-floating--do-moveresize) (exwm-floating-move): Use container. (exwm-floating--fit-frame-to-window): No longer adjust stacking order. (exwm-floating--fit-frame-to-window): The first member is changed to buffer. (exwm-floating--start-moveresize): Use container. Correctly set input focus. * exwm-input.el (exwm-input--redirected, exwm-input--on-focus-in): Removed. (exwm-input--on-buffer-list-update): Remove the restriction on floating frames which is no longer valid. (exwm-input--update-focus): Adjust stacking order. (exwm-input--on-minibuffer-setup): New function for setting focus on the Emacs frame when entering minibuffer. (exwm-input--on-KeyPress-line-mode): No longer compensate FocusOut event. (exwm-input--grab-keyboard, exwm-input--release-keyboard): Local keys are now grabbed on the X window container. (exwm-input--init): Add `exwm-input--on-minibuffer-setup' to `minibuffer-setup-hook'. * exwm-layout.el (exwm-layout--resize-container): New function to resize/reposition both the X window and its container. (exwm-layout--show, exwm-layout--hide): Use container. (exwm-layout-set-fullscreen): Use container. No longer save width and height. (exwm-layout-unset-fullscreen, exwm-layout--set-frame-fullscreen): Use container. (exwm-layout--refresh): Update a frame parameter. Remove dead code. * exwm-manage.el (exwm-manage--manage-window): Reparent unmanaged X windows to the workspace. Create X window container as the parent of the X window. (exwm-manage--unmanage-window): Unmap/destroy container when appropriate. Use the position of container. (exwm-manage--unmanage-window): Destroy the container. * exwm-randr.el (exwm-randr--refresh): Resize workspace using container. * exwm-workspace.el (exwm-workspace-switch): Raise workspace. Correctly set input focus. (exwm-workspace--on-focus-in): Removed. (exwm-workspace-move-window): Reparent to workspace container. (exwm-workspace--init): Create workspace frames as visible. Create workspace containers. Remove exwm-workspace--on-focus-in from focus-in-hook. Update _NET_VIRTUAL_ROOTS. * exwm.el (exwm-init): No longer disable hourglass window. Initialize workspace module before input. * exwm-core.el (exwm--debug): New macro for setting debug forms. * exwm-floating.el (exwm-floating--set-floating): No longer do `exwm--lock' and `exwm--unlock' since `make-frame' is already adviced to take care of everything. Correctly set input focus to the newly created floating X window. * exwm-core.el (exwm--floating-edges): Removed file local variable. * exwm-floating.el (exwm-floating--set-floating) (exwm-floating--unset-floating): * exwm-layout.el (exwm-layout--show, exwm-layout-enlarge-window): * exwm-manage.el (exwm-manage--on-ConfigureRequest): No longer use floating geometry. * exwm-input.el (exwm-input--update-global-prefix-keys): Grab global keys on workspaces containers instead of the root window (or input focus would transfer to the workspace containing the pointer when the grab is active). * exwm-workspace.el (exwm-workspace-switch): No longer move mouse.
Diffstat (limited to 'exwm-layout.el')
-rw-r--r-- | exwm-layout.el | 157 |
1 files changed, 75 insertions, 82 deletions
diff --git a/exwm-layout.el b/exwm-layout.el index ffe1f1d0c4fd..c3bfcf8ef94a 100644 --- a/exwm-layout.el +++ b/exwm-layout.el @@ -30,41 +30,72 @@ (defvar exwm-floating-border-width) +(defun exwm-layout--resize-container (id container x y width height + &optional container-only) + "Resize a container (and its content unless CONTAINER-ONLY is non-nil)." + (xcb:+request exwm--connection + (make-instance 'xcb:ConfigureWindow + :window container + :value-mask (eval-when-compile + (logior xcb:ConfigWindow:X + xcb:ConfigWindow:Y + xcb:ConfigWindow:Width + xcb:ConfigWindow:Height)) + :x x :y y :width width :height height)) + (unless container-only + (xcb:+request exwm--connection + (make-instance 'xcb:ConfigureWindow + :window id + :value-mask (eval-when-compile + (logior xcb:ConfigWindow:Width + xcb:ConfigWindow:Height)) + :width width :height height)))) + ;;;###autoload (defun exwm-layout--show (id &optional window) "Show window ID exactly fit in the Emacs window WINDOW." (exwm--log "Show #x%x in %s" id window) (xcb:+request exwm--connection (make-instance 'xcb:MapWindow :window id)) + (with-current-buffer (exwm--id->buffer id) + (xcb:+request exwm--connection + (make-instance 'xcb:MapWindow :window exwm--container))) (xcb:+request exwm--connection (make-instance 'xcb:icccm:set-WM_STATE :window id :state xcb:icccm:WM_STATE:NormalState :icon xcb:Window:None)) - (let* ((buffer (exwm--id->buffer id)) - (edges (or (and buffer - (with-current-buffer buffer exwm--floating-edges)) - (window-inside-absolute-pixel-edges window))) + (let* ((edges (window-inside-absolute-pixel-edges window)) (width (- (elt edges 2) (elt edges 0))) - (height (- (elt edges 3) (elt edges 1))) - x y) - (if exwm--floating-edges - ;; The relative position of a floating X window is determinate - (setq x exwm-floating-border-width - y exwm-floating-border-width) - (let ((relative-edges (window-inside-pixel-edges window))) - (setq x (elt relative-edges 0) - y (elt relative-edges 1)))) - (xcb:+request exwm--connection - (make-instance 'xcb:ConfigureWindow - :window id - :value-mask (eval-when-compile - (logior xcb:ConfigWindow:X - xcb:ConfigWindow:Y - xcb:ConfigWindow:Width - xcb:ConfigWindow:Height - xcb:ConfigWindow:StackMode)) - :x x :y y :width width :height height - ;; In order to put non-floating window at bottom - :stack-mode xcb:StackMode:Below)) + (height (- (elt edges 3) (elt edges 1)))) + (with-current-buffer (exwm--id->buffer id) + (if exwm--floating-frame + ;; A floating X window is of the same size as the Emacs window, + ;; whereas its container is of the same size as the Emacs frame. + (progn + (xcb:+request exwm--connection + (make-instance 'xcb:ConfigureWindow + :window exwm--container + :value-mask (logior xcb:ConfigWindow:Width + xcb:ConfigWindow:Height) + :width (frame-pixel-width exwm--floating-frame) + :height (frame-pixel-height + exwm--floating-frame))) + (xcb:+request exwm--connection + (make-instance 'xcb:ConfigureWindow + :window exwm--id + :value-mask (logior xcb:ConfigWindow:X + xcb:ConfigWindow:Y + xcb:ConfigWindow:Width + xcb:ConfigWindow:Height) + :x exwm-floating-border-width + :y exwm-floating-border-width + :width width + :height height))) + (let ((relative-edges (window-inside-pixel-edges window))) + (exwm-layout--resize-container id exwm--container + (elt relative-edges 0) + (elt relative-edges 1) + width height + (active-minibuffer-window))))) (xcb:+request exwm--connection (make-instance 'xcb:SendEvent :propagate 0 :destination id @@ -96,6 +127,9 @@ (make-instance 'xcb:ChangeWindowAttributes :window id :value-mask xcb:CW:EventMask :event-mask exwm--client-event-mask)) + (with-current-buffer (exwm--id->buffer id) + (xcb:+request exwm--connection + (make-instance 'xcb:UnmapWindow :window exwm--container))) (xcb:+request exwm--connection (make-instance 'xcb:icccm:set-WM_STATE :window id @@ -112,38 +146,16 @@ (user-error "Already in full-screen mode.")) ;; Set the floating frame fullscreen first when the client is floating (when exwm--floating-frame - (let* ((outer-id (frame-parameter exwm--floating-frame 'exwm-outer-id)) - (geometry (xcb:+request-unchecked+reply exwm--connection + (let* ((geometry (xcb:+request-unchecked+reply exwm--connection (make-instance 'xcb:GetGeometry - :drawable outer-id)))) - (setq exwm--floating-frame-geometry - (vector (slot-value geometry 'x) (slot-value geometry 'y) - (slot-value geometry 'width) - (slot-value geometry 'height))) - (xcb:+request exwm--connection - (make-instance 'xcb:ConfigureWindow - :window outer-id - :value-mask (eval-when-compile - (logior xcb:ConfigWindow:X - xcb:ConfigWindow:Y - xcb:ConfigWindow:Width - xcb:ConfigWindow:Height)) - :x 0 :y 0 - :width (frame-pixel-width exwm-workspace--current) - :height (frame-pixel-height - exwm-workspace--current)))) + :drawable exwm--container)))) + (setq exwm--floating-frame-position + (vector (slot-value geometry 'x) (slot-value geometry 'y)))) (xcb:flush exwm--connection)) - (xcb:+request exwm--connection - (make-instance 'xcb:ConfigureWindow - :window exwm--id - :value-mask (eval-when-compile - (logior xcb:ConfigWindow:X - xcb:ConfigWindow:Y - xcb:ConfigWindow:Width - xcb:ConfigWindow:Height)) - :x 0 :y 0 - :width (frame-pixel-width exwm-workspace--current) - :height (frame-pixel-height exwm-workspace--current))) + (exwm-layout--resize-container exwm--id exwm--container 0 0 + (frame-pixel-width exwm-workspace--current) + (frame-pixel-height + exwm-workspace--current)) (xcb:+request exwm--connection (make-instance 'xcb:ewmh:set-_NET_WM_STATE :window exwm--id @@ -162,17 +174,12 @@ (when exwm--floating-frame (xcb:+request exwm--connection (make-instance 'xcb:ConfigureWindow - :window (frame-parameter exwm--floating-frame - 'exwm-outer-id) + :window exwm--container :value-mask (eval-when-compile (logior xcb:ConfigWindow:X - xcb:ConfigWindow:Y - xcb:ConfigWindow:Width - xcb:ConfigWindow:Height)) - :x (elt exwm--floating-frame-geometry 0) - :y (elt exwm--floating-frame-geometry 1) - :width (elt exwm--floating-frame-geometry 2) - :height (elt exwm--floating-frame-geometry 3)))) + xcb:ConfigWindow:Y)) + :x (elt exwm--floating-frame-position 0) + :y (elt exwm--floating-frame-position 1)))) (exwm-layout--show exwm--id) (xcb:+request exwm--connection (make-instance 'xcb:ewmh:set-_NET_WM_STATE :window exwm--id :data [])) @@ -193,19 +200,10 @@ (make-instance 'xcb:RECTANGLE :x 0 :y 0 :width (x-display-pixel-width) :height (x-display-pixel-height)))) - (id (frame-parameter frame 'exwm-outer-id))) + (id (frame-parameter frame 'exwm-outer-id)) + (workspace (frame-parameter frame 'exwm-workspace))) (with-slots (x y width height) geometry - (xcb:+request exwm--connection - (make-instance 'xcb:ConfigureWindow - :window id - :value-mask (eval-when-compile - (logior xcb:ConfigWindow:X - xcb:ConfigWindow:Y - xcb:ConfigWindow:Width - xcb:ConfigWindow:Height)) - :x x :y y - :width width - :height height)) + (exwm-layout--resize-container id workspace x y width height) (xcb:flush exwm--connection)))) (defvar exwm-layout-show-all-buffers nil @@ -221,7 +219,7 @@ (get-buffer "*scratch*")))) windows) (if (not (memq frame exwm-workspace--list)) - (if (frame-parameter frame 'exwm-window-id) + (if (frame-parameter frame 'exwm-outer-id) ;; Refresh a floating frame (when (eq major-mode 'exwm-mode) (let ((window (frame-first-window frame))) @@ -230,9 +228,6 @@ (exwm-layout--show exwm--id window)))) ;; Other frames (e.g. terminal/graphical frame of emacsclient) ;; We shall bury all `exwm-mode' buffers in this case - (unless placeholder ;create the *scratch* buffer if it's killed - (setq placeholder (get-buffer-create "*scratch*")) - (set-buffer-major-mode placeholder)) (setq windows (window-list frame 0)) ;exclude minibuffer (dolist (window windows) (with-current-buffer (window-buffer window) @@ -329,7 +324,6 @@ windows." (setq width (max (+ exwm--normal-hints-min-width margin) (+ width delta)))))) (when width - (setq exwm--floating-edges nil) ;invalid from now on (xcb:+request exwm--connection (make-instance 'xcb:ConfigureWindow :window (frame-parameter exwm--floating-frame @@ -356,7 +350,6 @@ windows." (setq height (max (+ exwm--normal-hints-min-height margin) (+ height delta)))))) (when height - (setq exwm--floating-edges nil) ;invalid from now on (xcb:+request exwm--connection (make-instance 'xcb:ConfigureWindow :window (frame-parameter exwm--floating-frame |