From e3d33a4aad6b5748e9352501b2c6cb058379025f Mon Sep 17 00:00:00 2001 From: Chris Feng Date: Sat, 20 Feb 2016 21:52:07 +0800 Subject: Prevent Emacs frames from restacking themselves Putting Emacs frames (workspace frames, floating frames) into dedicated containers greatly simplifies the stacking order management and totally fixes relevant issues. * exwm-floating.el (exwm-floating--set-floating): Create floating frame container. Remove redundant stacking order modification code. (exwm-floating--unset-floating): Destroy the floating frame container. No need to reparent the X window container. (exwm-floating--do-moveresize): Resize the floating frame container. * exwm-input.el (exwm-input--update-focus): No need to restack frames. * exwm-layout.el (exwm-layout--show, exwm-layout--set-frame-fullscreen) (exwm-layout-enlarge-window): Resize the floating frame container. * exwm-manage.el (exwm-manage--on-ConfigureRequest): Re-enable stacking order modification on ConfigureRequest. * exwm-workspace.el (exwm-workspace--confirm-kill-emacs): Reparent out all frames on exit. No need to remove selected events or created resources. (exwm-workspace--init): Create workspace frame containers. * exwm-layout.el (exwm-layout-set-fullscreen): * exwm-manage.el (exwm-manage--unmanage-window): Remove a redundant call to `xcb:flush'. * exwm-manage.el (exwm-manage--unmanage-window): Force unmap the X window. Unmap the floating frame before reparent it. --- exwm-floating.el | 109 +++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 69 insertions(+), 40 deletions(-) (limited to 'exwm-floating.el') diff --git a/exwm-floating.el b/exwm-floating.el index 276948801d95..1ec54d10fa71 100644 --- a/exwm-floating.el +++ b/exwm-floating.el @@ -90,6 +90,7 @@ (outer-id (string-to-number (frame-parameter frame 'outer-window-id))) (container (with-current-buffer (exwm--id->buffer id) exwm--container)) + (frame-container (xcb:generate-id exwm--connection)) (window (frame-first-window frame)) ;and it's the only window (x (slot-value exwm--geometry 'x)) (y (slot-value exwm--geometry 'y)) @@ -103,8 +104,9 @@ y (- y (slot-value frame-geometry 'y)))) (exwm--log "Floating geometry (original, relative): %dx%d%+d%+d" width height x y) - ;; Save window IDs + ;; Save frame parameters. (set-frame-parameter frame 'exwm-outer-id outer-id) + (set-frame-parameter frame 'exwm-container frame-container) ;; Set urgency flag if it's not appear in the active workspace (let ((idx (cl-position original-frame exwm-workspace--list))) (when (/= idx exwm-workspace-current-index) @@ -163,18 +165,43 @@ ;; timely. ;; The frame will be made visible by `select-frame-set-input-focus'. (make-frame-invisible frame) - (let ((edges (window-inside-pixel-edges window))) - (set-frame-size frame - (+ width (- (frame-pixel-width frame) - (- (elt edges 2) (elt edges 0)))) - (+ height (- (frame-pixel-height frame) - (- (elt edges 3) (elt edges 1)))) - t)) - ;; Reparent this frame to the container + (let* ((edges (window-inside-pixel-edges window)) + (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)))))) + (set-frame-size frame frame-width frame-height t) + ;; Create the frame container as the parent of the frame and + ;; a child of the X window container. + (xcb:+request exwm--connection + (make-instance 'xcb:CreateWindow + :depth 0 :wid frame-container + :parent container + :x 0 :y 0 :width width :height height :border-width 0 + :class xcb:WindowClass:CopyFromParent + :visual 0 ;CopyFromParent + :value-mask xcb:CW:OverrideRedirect + :override-redirect 1)) + ;; Put it at bottom. + (xcb:+request exwm--connection + (make-instance 'xcb:ConfigureWindow + :window frame-container + :value-mask xcb:ConfigWindow:StackMode + :stack-mode xcb:StackMode:Below)) + ;; Map it. + (xcb:+request exwm--connection + (make-instance 'xcb:MapWindow :window frame-container)) + (exwm--debug + (xcb:+request exwm--connection + (make-instance 'xcb:ewmh:set-_NET_WM_NAME + :window frame-container + :data + (format "floating frame container for 0x%x" id))))) + ;; Reparent this frame to its container. (xcb:+request exwm--connection (make-instance 'xcb:ReparentWindow - :window outer-id :parent container :x 0 :y 0)) - ;; Place the container + :window outer-id :parent frame-container :x 0 :y 0)) + ;; Place the X window container. (xcb:+request exwm--connection (make-instance 'xcb:ConfigureWindow :window container @@ -193,16 +220,9 @@ (remove-hook 'window-configuration-change-hook #'exwm-layout--refresh) (set-window-buffer window (current-buffer)) ;this changes current buffer (add-hook 'window-configuration-change-hook #'exwm-layout--refresh) - (set-window-dedicated-p window t)) - (select-frame-set-input-focus frame) - ;; `x_make_frame_visible' autoraises the frame. Force lowering it. - (xcb:+request exwm--connection - (make-instance 'xcb:ConfigureWindow - :window outer-id - :value-mask xcb:ConfigWindow:StackMode - :stack-mode xcb:StackMode:Below)) - ;; Show the X window with its container (and flush). - (exwm-layout--show id window)) + (set-window-dedicated-p window t) + (exwm-layout--show id window)) + (select-frame-set-input-focus frame)) (run-hooks 'exwm-floating-setup-hook) ;; Redraw the frame. (redisplay)) @@ -229,29 +249,28 @@ :window id :value-mask xcb:CW:EventMask :event-mask exwm--client-event-mask)) ;; Reparent the floating frame back to the root window. - (let ((frame-id (frame-parameter exwm--floating-frame 'exwm-outer-id))) + (let ((frame-id (frame-parameter exwm--floating-frame 'exwm-outer-id)) + (frame-container (frame-parameter exwm--floating-frame + 'exwm-container))) (xcb:+request exwm--connection (make-instance 'xcb:UnmapWindow :window frame-id)) (xcb:+request exwm--connection (make-instance 'xcb:ReparentWindow :window frame-id :parent exwm--root - :x 0 :y 0)))) - ;; Reparent the container to the workspace - (xcb:+request exwm--connection - (make-instance 'xcb:ReparentWindow - :window exwm--container - :parent (frame-parameter exwm-workspace--current - 'exwm-workspace) - :x 0 :y 0)) ;temporary position - ;; Put the container just above the Emacs frame + :x 0 :y 0)) + ;; Also destroy its container. + (xcb:+request exwm--connection + (make-instance 'xcb:DestroyWindow :window frame-container)))) + ;; Put the X window container just above the Emacs frame container + ;; (the stacking order won't change from now on). (xcb:+request exwm--connection (make-instance 'xcb:ConfigureWindow :window exwm--container :value-mask (logior xcb:ConfigWindow:Sibling xcb:ConfigWindow:StackMode) :sibling (frame-parameter exwm-workspace--current - 'exwm-outer-id) + 'exwm-container) :stack-mode xcb:StackMode:Above))) (xcb:flush exwm--connection) (with-current-buffer buffer @@ -466,13 +485,19 @@ (geometry (frame-parameter exwm-workspace--current 'exwm-geometry)) (frame-x 0) (frame-y 0) - result) + result value-mask width height) (when geometry (setq frame-x (slot-value geometry 'x) frame-y (slot-value geometry 'y))) (xcb:unmarshal obj data) (setq result (funcall exwm-floating--moveresize-calculate - (slot-value obj 'root-x) (slot-value obj 'root-y))) + (slot-value obj 'root-x) (slot-value obj 'root-y)) + value-mask (logand (aref result 1) + (eval-when-compile + (logior xcb:ConfigWindow:Width + xcb:ConfigWindow:Height))) + width (aref result 4) + height (aref result 5)) (with-current-buffer (aref result 0) (xcb:+request exwm--connection (make-instance 'xcb:ConfigureWindow @@ -483,16 +508,20 @@ xcb:ConfigWindow:Y))) :x (- (aref result 2) frame-x) :y (- (aref result 3) frame-y))) + (xcb:+request exwm--connection + (make-instance 'xcb:ConfigureWindow + :window (frame-parameter exwm--floating-frame + 'exwm-container) + :value-mask value-mask + :width width + :height height)) (xcb:+request exwm--connection (make-instance 'xcb:ConfigureWindow :window (frame-parameter exwm--floating-frame 'exwm-outer-id) - :value-mask - (logand (aref result 1) - (eval-when-compile - (logior xcb:ConfigWindow:Width - xcb:ConfigWindow:Height))) - :width (aref result 4) :height (aref result 5)))) + :value-mask value-mask + :width width + :height height))) (xcb:flush exwm--connection)))) (defun exwm-floating-move (&optional delta-x delta-y) -- cgit 1.4.1