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.
This commit is contained in:
Chris Feng 2016-02-20 21:52:07 +08:00
parent 1c79e1c238
commit e3d33a4aad
5 changed files with 192 additions and 121 deletions

View file

@ -90,6 +90,7 @@
(outer-id (string-to-number (frame-parameter frame 'outer-window-id))) (outer-id (string-to-number (frame-parameter frame 'outer-window-id)))
(container (with-current-buffer (exwm--id->buffer id) (container (with-current-buffer (exwm--id->buffer id)
exwm--container)) exwm--container))
(frame-container (xcb:generate-id exwm--connection))
(window (frame-first-window frame)) ;and it's the only window (window (frame-first-window frame)) ;and it's the only window
(x (slot-value exwm--geometry 'x)) (x (slot-value exwm--geometry 'x))
(y (slot-value exwm--geometry 'y)) (y (slot-value exwm--geometry 'y))
@ -103,8 +104,9 @@
y (- y (slot-value frame-geometry 'y)))) y (- y (slot-value frame-geometry 'y))))
(exwm--log "Floating geometry (original, relative): %dx%d%+d%+d" (exwm--log "Floating geometry (original, relative): %dx%d%+d%+d"
width height x y) width height x y)
;; Save window IDs ;; Save frame parameters.
(set-frame-parameter frame 'exwm-outer-id outer-id) (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 ;; Set urgency flag if it's not appear in the active workspace
(let ((idx (cl-position original-frame exwm-workspace--list))) (let ((idx (cl-position original-frame exwm-workspace--list)))
(when (/= idx exwm-workspace-current-index) (when (/= idx exwm-workspace-current-index)
@ -163,18 +165,43 @@
;; timely. ;; timely.
;; The frame will be made visible by `select-frame-set-input-focus'. ;; The frame will be made visible by `select-frame-set-input-focus'.
(make-frame-invisible frame) (make-frame-invisible frame)
(let ((edges (window-inside-pixel-edges window))) (let* ((edges (window-inside-pixel-edges window))
(set-frame-size frame (frame-width (+ width (- (frame-pixel-width frame)
(+ width (- (frame-pixel-width frame) (- (elt edges 2) (elt edges 0)))))
(- (elt edges 2) (elt edges 0)))) (frame-height (+ height (- (frame-pixel-height frame)
(+ height (- (frame-pixel-height frame) (- (elt edges 3) (elt edges 1))))))
(- (elt edges 3) (elt edges 1)))) (set-frame-size frame frame-width frame-height t)
t)) ;; Create the frame container as the parent of the frame and
;; Reparent this frame to the container ;; 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 (xcb:+request exwm--connection
(make-instance 'xcb:ReparentWindow (make-instance 'xcb:ReparentWindow
:window outer-id :parent container :x 0 :y 0)) :window outer-id :parent frame-container :x 0 :y 0))
;; Place the container ;; Place the X window container.
(xcb:+request exwm--connection (xcb:+request exwm--connection
(make-instance 'xcb:ConfigureWindow (make-instance 'xcb:ConfigureWindow
:window container :window container
@ -193,16 +220,9 @@
(remove-hook 'window-configuration-change-hook #'exwm-layout--refresh) (remove-hook 'window-configuration-change-hook #'exwm-layout--refresh)
(set-window-buffer window (current-buffer)) ;this changes current buffer (set-window-buffer window (current-buffer)) ;this changes current buffer
(add-hook 'window-configuration-change-hook #'exwm-layout--refresh) (add-hook 'window-configuration-change-hook #'exwm-layout--refresh)
(set-window-dedicated-p window t)) (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)) (exwm-layout--show id window))
(select-frame-set-input-focus frame))
(run-hooks 'exwm-floating-setup-hook) (run-hooks 'exwm-floating-setup-hook)
;; Redraw the frame. ;; Redraw the frame.
(redisplay)) (redisplay))
@ -229,29 +249,28 @@
:window id :value-mask xcb:CW:EventMask :window id :value-mask xcb:CW:EventMask
:event-mask exwm--client-event-mask)) :event-mask exwm--client-event-mask))
;; Reparent the floating frame back to the root window. ;; 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 (xcb:+request exwm--connection
(make-instance 'xcb:UnmapWindow :window frame-id)) (make-instance 'xcb:UnmapWindow :window frame-id))
(xcb:+request exwm--connection (xcb:+request exwm--connection
(make-instance 'xcb:ReparentWindow (make-instance 'xcb:ReparentWindow
:window frame-id :window frame-id
:parent exwm--root :parent exwm--root
:x 0 :y 0)))) :x 0 :y 0))
;; Reparent the container to the workspace ;; Also destroy its container.
(xcb:+request exwm--connection (xcb:+request exwm--connection
(make-instance 'xcb:ReparentWindow (make-instance 'xcb:DestroyWindow :window frame-container))))
:window exwm--container ;; Put the X window container just above the Emacs frame container
:parent (frame-parameter exwm-workspace--current ;; (the stacking order won't change from now on).
'exwm-workspace)
:x 0 :y 0)) ;temporary position
;; Put the container just above the Emacs frame
(xcb:+request exwm--connection (xcb:+request exwm--connection
(make-instance 'xcb:ConfigureWindow (make-instance 'xcb:ConfigureWindow
:window exwm--container :window exwm--container
:value-mask (logior xcb:ConfigWindow:Sibling :value-mask (logior xcb:ConfigWindow:Sibling
xcb:ConfigWindow:StackMode) xcb:ConfigWindow:StackMode)
:sibling (frame-parameter exwm-workspace--current :sibling (frame-parameter exwm-workspace--current
'exwm-outer-id) 'exwm-container)
:stack-mode xcb:StackMode:Above))) :stack-mode xcb:StackMode:Above)))
(xcb:flush exwm--connection) (xcb:flush exwm--connection)
(with-current-buffer buffer (with-current-buffer buffer
@ -466,13 +485,19 @@
(geometry (frame-parameter exwm-workspace--current 'exwm-geometry)) (geometry (frame-parameter exwm-workspace--current 'exwm-geometry))
(frame-x 0) (frame-x 0)
(frame-y 0) (frame-y 0)
result) result value-mask width height)
(when geometry (when geometry
(setq frame-x (slot-value geometry 'x) (setq frame-x (slot-value geometry 'x)
frame-y (slot-value geometry 'y))) frame-y (slot-value geometry 'y)))
(xcb:unmarshal obj data) (xcb:unmarshal obj data)
(setq result (funcall exwm-floating--moveresize-calculate (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) (with-current-buffer (aref result 0)
(xcb:+request exwm--connection (xcb:+request exwm--connection
(make-instance 'xcb:ConfigureWindow (make-instance 'xcb:ConfigureWindow
@ -483,16 +508,20 @@
xcb:ConfigWindow:Y))) xcb:ConfigWindow:Y)))
:x (- (aref result 2) frame-x) :x (- (aref result 2) frame-x)
:y (- (aref result 3) frame-y))) :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 (xcb:+request exwm--connection
(make-instance 'xcb:ConfigureWindow (make-instance 'xcb:ConfigureWindow
:window (frame-parameter exwm--floating-frame :window (frame-parameter exwm--floating-frame
'exwm-outer-id) 'exwm-outer-id)
:value-mask :value-mask value-mask
(logand (aref result 1) :width width
(eval-when-compile :height height)))
(logior xcb:ConfigWindow:Width
xcb:ConfigWindow:Height)))
:width (aref result 4) :height (aref result 5))))
(xcb:flush exwm--connection)))) (xcb:flush exwm--connection))))
(defun exwm-floating-move (&optional delta-x delta-y) (defun exwm-floating-move (&optional delta-x delta-y)

View file

@ -113,8 +113,8 @@ It's updated in several occasions, and only used by `exwm-input--set-focus'.")
(exwm-workspace-switch exwm-workspace-current-index t)) (exwm-workspace-switch exwm-workspace-current-index t))
(exwm--log "Set focus on #x%x" exwm--id) (exwm--log "Set focus on #x%x" exwm--id)
(exwm-input--set-focus exwm--id) (exwm-input--set-focus exwm--id)
;; Adjust stacking orders
(when exwm--floating-frame (when exwm--floating-frame
;; Adjust stacking orders of the floating container.
(if (exwm-workspace--minibuffer-own-frame-p) (if (exwm-workspace--minibuffer-own-frame-p)
;; Put this floating X window just below the minibuffer. ;; Put this floating X window just below the minibuffer.
(xcb:+request exwm--connection (xcb:+request exwm--connection
@ -132,16 +132,8 @@ It's updated in several occasions, and only used by `exwm-input--set-focus'.")
(make-instance 'xcb:ConfigureWindow (make-instance 'xcb:ConfigureWindow
:window exwm--container :window exwm--container
:value-mask xcb:ConfigWindow:StackMode :value-mask xcb:ConfigWindow:StackMode
:stack-mode xcb:StackMode:Above)))) :stack-mode xcb:StackMode:Above)))
;; Make sure Emacs frames are at bottom. (xcb:flush exwm--connection)))
(xcb:+request exwm--connection
(make-instance 'xcb:ConfigureWindow
:window (frame-parameter
(or exwm--floating-frame exwm--frame)
'exwm-outer-id)
:value-mask xcb:ConfigWindow:StackMode
:stack-mode xcb:StackMode:BottomIf))
(xcb:flush exwm--connection))
(when (eq (selected-window) exwm-input--focus-window) (when (eq (selected-window) exwm-input--focus-window)
(exwm--log "Focus on %s" exwm-input--focus-window) (exwm--log "Focus on %s" exwm-input--focus-window)
(select-frame-set-input-focus (window-frame exwm-input--focus-window) (select-frame-set-input-focus (window-frame exwm-input--focus-window)

View file

@ -55,20 +55,35 @@
(exwm--log "Show #x%x in %s" id window) (exwm--log "Show #x%x in %s" id window)
(let* ((edges (window-inside-absolute-pixel-edges window)) (let* ((edges (window-inside-absolute-pixel-edges window))
(width (- (elt edges 2) (elt edges 0))) (width (- (elt edges 2) (elt edges 0)))
(height (- (elt edges 3) (elt edges 1)))) (height (- (elt edges 3) (elt edges 1)))
frame-width frame-height)
(with-current-buffer (exwm--id->buffer id) (with-current-buffer (exwm--id->buffer id)
(if exwm--floating-frame (if (not exwm--floating-frame)
(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)))
;; A floating X window is of the same size as the Emacs window, ;; 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. ;; whereas its container is of the same size as the Emacs frame.
(progn (setq frame-width (frame-pixel-width exwm--floating-frame)
frame-height (frame-pixel-height exwm--floating-frame))
(xcb:+request exwm--connection (xcb:+request exwm--connection
(make-instance 'xcb:ConfigureWindow (make-instance 'xcb:ConfigureWindow
:window exwm--container :window exwm--container
:value-mask (logior xcb:ConfigWindow:Width :value-mask (logior xcb:ConfigWindow:Width
xcb:ConfigWindow:Height) xcb:ConfigWindow:Height)
:width (frame-pixel-width exwm--floating-frame) :width frame-width
:height (frame-pixel-height :height frame-height))
exwm--floating-frame))) (xcb:+request exwm--connection
(make-instance 'xcb:ConfigureWindow
:window (frame-parameter exwm--floating-frame
'exwm-container)
:value-mask (logior xcb:ConfigWindow:Width
xcb:ConfigWindow:Height)
:width frame-width
:height frame-height))
(xcb:+request exwm--connection (xcb:+request exwm--connection
(make-instance 'xcb:ConfigureWindow (make-instance 'xcb:ConfigureWindow
:window exwm--id :window exwm--id
@ -80,12 +95,6 @@
:y exwm-floating-border-width :y exwm-floating-border-width
:width width :width width
:height height))) :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))))
;; Make the resizing take effect. ;; Make the resizing take effect.
(xcb:flush exwm--connection) (xcb:flush exwm--connection)
(xcb:+request exwm--connection (make-instance 'xcb:MapWindow :window id)) (xcb:+request exwm--connection (make-instance 'xcb:MapWindow :window id))
@ -151,8 +160,7 @@
(make-instance 'xcb:GetGeometry (make-instance 'xcb:GetGeometry
:drawable exwm--container)))) :drawable exwm--container))))
(setq exwm--floating-frame-position (setq exwm--floating-frame-position
(vector (slot-value geometry 'x) (slot-value geometry 'y)))) (vector (slot-value geometry 'x) (slot-value geometry 'y)))))
(xcb:flush exwm--connection))
(exwm-layout--resize-container exwm--id exwm--container 0 0 (exwm-layout--resize-container exwm--id exwm--container 0 0
(exwm-workspace--current-width) (exwm-workspace--current-width)
(exwm-workspace--current-height)) (exwm-workspace--current-height))
@ -205,12 +213,14 @@
:width (x-display-pixel-width) :width (x-display-pixel-width)
:height (x-display-pixel-height)))) :height (x-display-pixel-height))))
(id (frame-parameter frame 'exwm-outer-id)) (id (frame-parameter frame 'exwm-outer-id))
(container (frame-parameter frame 'exwm-container))
(workspace (frame-parameter frame 'exwm-workspace))) (workspace (frame-parameter frame 'exwm-workspace)))
(with-slots (x y width height) geometry (with-slots (x y width height) geometry
(when (and (eq frame exwm-workspace--current) (when (and (eq frame exwm-workspace--current)
(exwm-workspace--minibuffer-own-frame-p)) (exwm-workspace--minibuffer-own-frame-p))
(exwm-workspace--resize-minibuffer-frame width height)) (exwm-workspace--resize-minibuffer-frame width height))
(exwm-layout--resize-container id workspace x y width height) (exwm-layout--resize-container id container 0 0 width height)
(exwm-layout--resize-container nil workspace x y width height t)
(xcb:flush exwm--connection))) (xcb:flush exwm--connection)))
(cl-incf exwm-layout--fullscreen-frame-count)) (cl-incf exwm-layout--fullscreen-frame-count))
@ -349,6 +359,12 @@ windows."
'exwm-outer-id) 'exwm-outer-id)
:value-mask xcb:ConfigWindow:Width :value-mask xcb:ConfigWindow:Width
:width width)) :width width))
(xcb:+request exwm--connection
(make-instance 'xcb:ConfigureWindow
:window (frame-parameter exwm--floating-frame
'exwm-container)
:value-mask xcb:ConfigWindow:Width
:width width))
(xcb:flush exwm--connection)))) (xcb:flush exwm--connection))))
(t (t
(let* ((height (frame-pixel-height)) (let* ((height (frame-pixel-height))
@ -375,6 +391,12 @@ windows."
'exwm-outer-id) 'exwm-outer-id)
:value-mask xcb:ConfigWindow:Height :value-mask xcb:ConfigWindow:Height
:height height)) :height height))
(xcb:+request exwm--connection
(make-instance 'xcb:ConfigureWindow
:window (frame-parameter exwm--floating-frame
'exwm-container)
:value-mask xcb:ConfigWindow:Height
:height height))
(xcb:flush exwm--connection)))))) (xcb:flush exwm--connection))))))
;;;###autoload ;;;###autoload

View file

@ -224,6 +224,9 @@ corresponding buffer.")
(xcb:+request exwm--connection (xcb:+request exwm--connection
(make-instance 'xcb:UnmapWindow :window exwm--container)) (make-instance 'xcb:UnmapWindow :window exwm--container))
(xcb:flush exwm--connection) (xcb:flush exwm--connection)
;; Unmap the X window.
(xcb:+request exwm--connection
(make-instance 'xcb:UnmapWindow :window id))
;; ;;
(setq exwm-workspace--switch-history-outdated t) (setq exwm-workspace--switch-history-outdated t)
;; ;;
@ -256,18 +259,17 @@ corresponding buffer.")
(xcb:+request exwm--connection (xcb:+request exwm--connection
(make-instance 'xcb:DeleteProperty (make-instance 'xcb:DeleteProperty
:window id :property xcb:Atom:WM_STATE))) :window id :property xcb:Atom:WM_STATE)))
;; Destroy the container (it seems it has to be delayed).
(when exwm--floating-frame (when exwm--floating-frame
;; Unmap the floating frame. ;; Unmap the floating frame before destroying the containers.
(let ((window (frame-parameter exwm--floating-frame 'exwm-outer-id))) (let ((window (frame-parameter exwm--floating-frame 'exwm-outer-id)))
(xcb:+request exwm--connection (xcb:+request exwm--connection
(make-instance 'xcb:UnmapWindow :window window)) (make-instance 'xcb:UnmapWindow :window window))
(xcb:+request exwm--connection (xcb:+request exwm--connection
(make-instance 'xcb:ReparentWindow (make-instance 'xcb:ReparentWindow
:window window :parent exwm--root :x 0 :y 0)))) :window window :parent exwm--root :x 0 :y 0))))
;; Destroy the X window container (and the frame container if any).
(xcb:+request exwm--connection (xcb:+request exwm--connection
(make-instance 'xcb:DestroyWindow :window exwm--container)) (make-instance 'xcb:DestroyWindow :window exwm--container))
(xcb:flush exwm--connection)
(let ((kill-buffer-query-functions nil) (let ((kill-buffer-query-functions nil)
(floating exwm--floating-frame)) (floating exwm--floating-frame))
(kill-buffer) (kill-buffer)
@ -310,12 +312,14 @@ corresponding buffer.")
(make-instance 'xcb:UnmapWindow :window exwm--container)) (make-instance 'xcb:UnmapWindow :window exwm--container))
(xcb:flush exwm--connection) (xcb:flush exwm--connection)
(when exwm--floating-frame (when exwm--floating-frame
(let ((window (frame-parameter exwm--floating-frame 'exwm-outer-id)))
(xcb:+request exwm--connection
(make-instance 'xcb:UnmapWindow :window window))
(xcb:+request exwm--connection (xcb:+request exwm--connection
(make-instance 'xcb:ReparentWindow (make-instance 'xcb:ReparentWindow
:window (frame-parameter exwm--floating-frame :window window
'exwm-outer-id)
:parent exwm--root :parent exwm--root
:x 0 :y 0))) :x 0 :y 0))))
(xcb:+request exwm--connection (xcb:+request exwm--connection
(make-instance 'xcb:DestroyWindow :window exwm--container)) (make-instance 'xcb:DestroyWindow :window exwm--container))
(xcb:flush exwm--connection) (xcb:flush exwm--connection)
@ -410,10 +414,13 @@ Would you like to kill it? "
(let ((obj (make-instance 'xcb:ConfigureRequest)) (let ((obj (make-instance 'xcb:ConfigureRequest))
buffer edges) buffer edges)
(xcb:unmarshal obj data) (xcb:unmarshal obj data)
(with-slots (window x y width height border-width value-mask) (with-slots (window x y width height
border-width sibling stack-mode value-mask)
obj obj
(exwm--log "ConfigureRequest from #x%x (#x%x) @%dx%d%+d%+d, border: %d" (exwm--log "ConfigureRequest from #x%x (#x%x) @%dx%d%+d%+d; \
window value-mask width height x y border-width) border-width: %d; sibling: #x%x; stack-mode: %d"
window value-mask width height x y
border-width sibling stack-mode)
(if (setq buffer (exwm--id->buffer window)) (if (setq buffer (exwm--id->buffer window))
;; Send client message for managed windows ;; Send client message for managed windows
(with-current-buffer buffer (with-current-buffer buffer
@ -440,16 +447,15 @@ Would you like to kill it? "
:border-width 0 :override-redirect 0) :border-width 0 :override-redirect 0)
exwm--connection)))) exwm--connection))))
(exwm--log "ConfigureWindow (preserve geometry)") (exwm--log "ConfigureWindow (preserve geometry)")
;; Configure the unmanaged window without changing the stacking order. ;; Configure the unmanaged window.
(xcb:+request exwm--connection (xcb:+request exwm--connection
(make-instance 'xcb:ConfigureWindow (make-instance 'xcb:ConfigureWindow
:window window :window window
:value-mask :value-mask value-mask
(logand value-mask
(lognot xcb:ConfigWindow:Sibling)
(lognot xcb:ConfigWindow:StackMode))
:x x :y y :width width :height height :x x :y y :width width :height height
:border-width border-width))))) :border-width border-width
:sibling sibling
:stack-mode stack-mode)))))
(xcb:flush exwm--connection)) (xcb:flush exwm--connection))
(defun exwm-manage--on-MapRequest (data _synthetic) (defun exwm-manage--on-MapRequest (data _synthetic)

View file

@ -252,7 +252,7 @@ The optional FORCE option is for internal use only."
(concat " " name))))) (concat " " name)))))
(setq exwm--frame frame) (setq exwm--frame frame)
(if exwm--floating-frame (if exwm--floating-frame
;; Move the floating frame is enough ;; Move the floating container.
(progn (progn
(xcb:+request exwm--connection (xcb:+request exwm--connection
(make-instance 'xcb:ReparentWindow (make-instance 'xcb:ReparentWindow
@ -261,7 +261,7 @@ The optional FORCE option is for internal use only."
(frame-parameter frame 'exwm-workspace) (frame-parameter frame 'exwm-workspace)
:x 0 :y 0)) :x 0 :y 0))
(xcb:flush exwm--connection)) (xcb:flush exwm--connection))
;; Move the window itself ;; Move the X window container.
(if (/= index exwm-workspace-current-index) (if (/= index exwm-workspace-current-index)
(bury-buffer) (bury-buffer)
(set-window-buffer (get-buffer-window (current-buffer) t) (set-window-buffer (get-buffer-window (current-buffer) t)
@ -483,28 +483,30 @@ This functions is modified from `display-buffer-reuse-window' and
(0 (y-or-n-p prompt)) (0 (y-or-n-p prompt))
(x (yes-or-no-p (format "[EXWM] %d window%s currently alive. %s" (x (yes-or-no-p (format "[EXWM] %d window%s currently alive. %s"
x (if (= x 1) "" "s") prompt)))) x (if (= x 1) "" "s") prompt))))
;; Remove SubstructureRedirect event.
(xcb:+request exwm--connection
(make-instance 'xcb:ChangeWindowAttributes
:window exwm--root :value-mask xcb:CW:EventMask
:event-mask 0))
;; Remove the _NET_SUPPORTING_WM_CHECK X window.
(with-slots (value)
(xcb:+request-unchecked+reply exwm--connection
(make-instance 'xcb:ewmh:get-_NET_SUPPORTING_WM_CHECK
:window exwm--root))
(xcb:+request exwm--connection
(make-instance 'xcb:DeleteProperty
:window exwm--root
:property xcb:Atom:_NET_SUPPORTING_WM_CHECK))
(xcb:+request exwm--connection
(make-instance 'xcb:DestroyWindow :window value)))
;; Unmanage all X windows. ;; Unmanage all X windows.
(dolist (i exwm--id-buffer-alist) (dolist (i exwm--id-buffer-alist)
(exwm-manage--unmanage-window (car i) t) (exwm-manage--unmanage-window (car i) t)
(xcb:+request exwm--connection (xcb:+request exwm--connection
(make-instance 'xcb:MapWindow :window (car i)))) (make-instance 'xcb:MapWindow :window (car i))))
;; Reparent out the minibuffer frame.
(when exwm-workspace-minibuffer-position
(xcb:+request exwm--connection
(make-instance 'xcb:ReparentWindow
:window (frame-parameter exwm-workspace--minibuffer
'exwm-outer-id)
:parent exwm--root
:x 0
:y 0)))
;; Reparent out all workspace frames.
(dolist (f exwm-workspace--list)
(xcb:+request exwm--connection
(make-instance 'xcb:ReparentWindow
:window (frame-parameter f 'exwm-outer-id)
:parent exwm--root
:x 0
:y 0)))
(xcb:flush exwm--connection) (xcb:flush exwm--connection)
;; Destroy all resources created by this connection.
(xcb:disconnect exwm--connection) (xcb:disconnect exwm--connection)
t)) t))
@ -589,9 +591,11 @@ This functions is modified from `display-buffer-reuse-window' and
;; Configure workspaces ;; Configure workspaces
(dolist (i exwm-workspace--list) (dolist (i exwm-workspace--list)
(let ((outer-id (string-to-number (frame-parameter i 'outer-window-id))) (let ((outer-id (string-to-number (frame-parameter i 'outer-window-id)))
(container (xcb:generate-id exwm--connection))
(workspace (xcb:generate-id exwm--connection))) (workspace (xcb:generate-id exwm--connection)))
;; Save window IDs ;; Save window IDs
(set-frame-parameter i 'exwm-outer-id outer-id) (set-frame-parameter i 'exwm-outer-id outer-id)
(set-frame-parameter i 'exwm-container container)
(set-frame-parameter i 'exwm-workspace workspace) (set-frame-parameter i 'exwm-workspace workspace)
(xcb:+request exwm--connection (xcb:+request exwm--connection
(make-instance 'xcb:CreateWindow (make-instance 'xcb:CreateWindow
@ -605,16 +609,34 @@ This functions is modified from `display-buffer-reuse-window' and
xcb:CW:EventMask) xcb:CW:EventMask)
:override-redirect 1 :override-redirect 1
:event-mask xcb:EventMask:SubstructureRedirect)) :event-mask xcb:EventMask:SubstructureRedirect))
(xcb:+request exwm--connection
(make-instance 'xcb:CreateWindow
:depth 0 :wid container :parent workspace
:x 0 :y 0
:width (x-display-pixel-width)
:height (x-display-pixel-height)
:border-width 0 :class xcb:WindowClass:CopyFromParent
:visual 0 ;CopyFromParent
:value-mask xcb:CW:OverrideRedirect
:override-redirect 1))
(exwm--debug (exwm--debug
(xcb:+request exwm--connection (xcb:+request exwm--connection
(make-instance 'xcb:ewmh:set-_NET_WM_NAME (make-instance 'xcb:ewmh:set-_NET_WM_NAME
:window workspace :window workspace
:data :data
(format "EXWM workspace %d" (format "EXWM workspace %d"
(cl-position i exwm-workspace--list))))
(xcb:+request exwm--connection
(make-instance 'xcb:ewmh:set-_NET_WM_NAME
:window container
:data
(format "EXWM workspace %d frame container"
(cl-position i exwm-workspace--list))))) (cl-position i exwm-workspace--list)))))
(xcb:+request exwm--connection (xcb:+request exwm--connection
(make-instance 'xcb:ReparentWindow (make-instance 'xcb:ReparentWindow
:window outer-id :parent workspace :x 0 :y 0)) :window outer-id :parent container :x 0 :y 0))
(xcb:+request exwm--connection
(make-instance 'xcb:MapWindow :window container))
(xcb:+request exwm--connection (xcb:+request exwm--connection
(make-instance 'xcb:MapWindow :window workspace)))) (make-instance 'xcb:MapWindow :window workspace))))
(xcb:flush exwm--connection) (xcb:flush exwm--connection)