Add multi-dock support and fix fullscreen issues with dock

* exwm.el (exwm--update-strut-legacy, exwm--update-strut-partial)
(exwm--update-strut): Rename (strut => struts).

* exwm-manage.el (exwm-manage--manage-window): Listen for
UnmapNotify/DestroyNotify events of docks to stop tracking them.
(exwm-manage--unmanage-window): Remove dock from tracking list when
it's unmapped/destroyed.
* exwm-workspace.el (exwm-workspace--id-struts-alist): New variable
for tracking docks.
(exwm-workspace--struts): Now it stores merged struts.
(exwm-workspace--update-struts): New function for doing the 'merge'.
* exwm.el (exwm--update-struts-legacy, exwm--update-struts-partial):
Now update struts for multiple docks.

* exwm-layout.el (exwm-layout-set-fullscreen)
(exwm-layout-unset-fullscreen):
* exwm-manage.el (exwm-manage--unmanage-window):
Fix fullscreen mode with dock.
* exwm-workspace.el (exwm-workspace--set-fullscreen): Add optional
arguments for ignoring struts / resizing container only.
(exwm-workspace-switch): Restack workspace/docks appropriately.
This commit is contained in:
Chris Feng 2016-07-15 20:04:56 +08:00
parent 0b8a373e4f
commit 7f12d9fc7a
5 changed files with 149 additions and 65 deletions

View file

@ -155,6 +155,9 @@
(defvar exwm-workspace--current) (defvar exwm-workspace--current)
(defvar exwm-workspace--list) (defvar exwm-workspace--list)
(declare-function exwm-workspace--set-fullscreen "exwm-workspace.el"
(frame &optional no-struts container-only))
;;;###autoload ;;;###autoload
(defun exwm-layout-set-fullscreen (&optional id) (defun exwm-layout-set-fullscreen (&optional id)
"Make window ID fullscreen." "Make window ID fullscreen."
@ -169,9 +172,25 @@
: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)))))
(exwm-layout--resize-container exwm--id exwm--container 0 0 ;; Expand the workspace frame & its container to fill the whole screen.
(exwm-workspace--set-fullscreen exwm--frame t t)
;; Raise the workspace container (in case there are docks).
(xcb:+request exwm--connection
(make-instance 'xcb:ConfigureWindow
:window (frame-parameter exwm--frame 'exwm-workspace)
:value-mask xcb:ConfigWindow:StackMode
:stack-mode xcb:StackMode:Above))
;; Expand the X window and its container to fill the whole screen.
;; Rationale: Floating X windows may not be positioned at (0, 0)
;; due to the extra border.
(exwm-layout--resize-container nil exwm--container 0 0
(exwm-workspace--current-width) (exwm-workspace--current-width)
(exwm-workspace--current-height)) (exwm-workspace--current-height)
t)
(exwm-layout--resize-container nil exwm--id 0 0
(exwm-workspace--current-width)
(exwm-workspace--current-height)
t)
;; Raise the X window. ;; Raise the X window.
(xcb:+request exwm--connection (xcb:+request exwm--connection
(make-instance 'xcb:ConfigureWindow (make-instance 'xcb:ConfigureWindow
@ -193,6 +212,8 @@
(with-current-buffer (if id (exwm--id->buffer id) (window-buffer)) (with-current-buffer (if id (exwm--id->buffer id) (window-buffer))
(unless exwm--fullscreen (unless exwm--fullscreen
(user-error "Not in full-screen mode.")) (user-error "Not in full-screen mode."))
;; Restore the size of this workspace.
(exwm-workspace--set-fullscreen exwm--frame)
(if exwm--floating-frame (if exwm--floating-frame
;; Restore the floating frame. ;; Restore the floating frame.
(xcb:+request exwm--connection (xcb:+request exwm--connection

View file

@ -86,7 +86,7 @@ corresponding buffer.")
(declare-function exwm--update-title "exwm.el" (id)) (declare-function exwm--update-title "exwm.el" (id))
(declare-function exwm--update-hints "exwm.el" (id &optional force)) (declare-function exwm--update-hints "exwm.el" (id &optional force))
(declare-function exwm--update-protocols "exwm.el" (id &optional force)) (declare-function exwm--update-protocols "exwm.el" (id &optional force))
(declare-function exwm--update-strut "exwm.el" (id)) (declare-function exwm--update-struts "exwm.el" (id))
(declare-function exwm-floating--set-floating "exwm-floating.el" (id)) (declare-function exwm-floating--set-floating "exwm-floating.el" (id))
(declare-function exwm-floating--unset-floating "exwm-floating.el" (id)) (declare-function exwm-floating--unset-floating "exwm-floating.el" (id))
(declare-function exwm-workspace--set-desktop "exwm-workspace.el" (id)) (declare-function exwm-workspace--set-desktop "exwm-workspace.el" (id))
@ -133,7 +133,7 @@ corresponding buffer.")
(exwm--log "No need to manage #x%x" id) (exwm--log "No need to manage #x%x" id)
;; Update struts. ;; Update struts.
(when (memq xcb:Atom:_NET_WM_WINDOW_TYPE_DOCK exwm-window-type) (when (memq xcb:Atom:_NET_WM_WINDOW_TYPE_DOCK exwm-window-type)
(exwm--update-strut id)) (exwm--update-struts id))
;; Remove all events ;; Remove all events
(xcb:+request exwm--connection (xcb:+request exwm--connection
(make-instance 'xcb:ChangeWindowAttributes (make-instance 'xcb:ChangeWindowAttributes
@ -141,8 +141,9 @@ corresponding buffer.")
:event-mask :event-mask
(if (memq xcb:Atom:_NET_WM_WINDOW_TYPE_DOCK (if (memq xcb:Atom:_NET_WM_WINDOW_TYPE_DOCK
exwm-window-type) exwm-window-type)
;; Listen for change of struts property of dock. ;; Listen for PropertyChange (struts) and
xcb:EventMask:PropertyChange ;; UnmapNotify/DestroyNotify event of the dock.
exwm--client-event-mask
xcb:EventMask:NoEvent))) xcb:EventMask:NoEvent)))
;; The window needs to be mapped ;; The window needs to be mapped
(xcb:+request exwm--connection (xcb:+request exwm--connection
@ -247,6 +248,15 @@ corresponding buffer.")
(with-current-buffer (exwm--id->buffer id) (with-current-buffer (exwm--id->buffer id)
(run-hooks 'exwm-manage-finish-hook))))) (run-hooks 'exwm-manage-finish-hook)))))
(defvar exwm-workspace--id-struts-alist)
(defvar exwm-workspace--list)
(declare-function exwm-workspace--update-struts "exwm-workspace.el" ())
(declare-function exwm-workspace--set-fullscreen "exwm-workspace.el"
(frame &optional no-struts container-only))
(declare-function exwm-workspace--set-workareas "exwm-workspace.el"
(&optional workareas))
(defun exwm-manage--unmanage-window (id &optional withdraw-only) (defun exwm-manage--unmanage-window (id &optional withdraw-only)
"Unmanage window ID. "Unmanage window ID.
@ -257,6 +267,14 @@ manager is shutting down."
(exwm--log "Unmanage #x%x (buffer: %s, widthdraw: %s)" (exwm--log "Unmanage #x%x (buffer: %s, widthdraw: %s)"
id buffer withdraw-only) id buffer withdraw-only)
(setq exwm--id-buffer-alist (assq-delete-all id exwm--id-buffer-alist)) (setq exwm--id-buffer-alist (assq-delete-all id exwm--id-buffer-alist))
;; Update workspaces when a dock is destroyed.
(when (assq id exwm-workspace--id-struts-alist)
(setq exwm-workspace--id-struts-alist
(assq-delete-all id exwm-workspace--id-struts-alist))
(exwm-workspace--update-struts)
(dolist (f exwm-workspace--list)
(exwm-workspace--set-fullscreen f))
(exwm-workspace--set-workareas))
(when (buffer-live-p buffer) (when (buffer-live-p buffer)
(with-current-buffer buffer (with-current-buffer buffer
;; Flickering seems unavoidable here if the DestroyWindow request is ;; Flickering seems unavoidable here if the DestroyWindow request is
@ -314,6 +332,9 @@ manager is shutting down."
(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))))
;; Restore the workspace if this X window is currently fullscreen.
(when exwm--fullscreen
(exwm-workspace--set-fullscreen exwm--frame))
;; Destroy the X window container (and the frame container if any). ;; 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))

View file

@ -58,7 +58,8 @@
(defvar exwm-workspace-number) (defvar exwm-workspace-number)
(defvar exwm-workspace--list) (defvar exwm-workspace--list)
(declare-function exwm-workspace--set-fullscreen "exwm-workspace.el" (frame)) (declare-function exwm-workspace--set-fullscreen "exwm-workspace.el"
(frame &optional no-struts container-only))
(declare-function exwm-workspace--set-workareas "exwm-workspace.el" (declare-function exwm-workspace--set-workareas "exwm-workspace.el"
(&optional workareas)) (&optional workareas))
(declare-function exwm-workspace--set-desktop-geometry "exwm-workspace.el" ()) (declare-function exwm-workspace--set-desktop-geometry "exwm-workspace.el" ())

View file

@ -128,10 +128,30 @@ Value nil means to use the default position which is fixed at bottom, while
"Reports whether the minibuffer is displayed in its own frame." "Reports whether the minibuffer is displayed in its own frame."
(memq exwm-workspace-minibuffer-position '(top bottom))) (memq exwm-workspace-minibuffer-position '(top bottom)))
;; FIXME: RandR and multiple docks. (defvar exwm-workspace--id-struts-alist nil "Alist of X window and struts.")
(defvar exwm-workspace--strut nil "Areas occupied by struts.") (defvar exwm-workspace--struts nil "Areas occupied by struts.")
(defvar exwm-workspace--strut-is-partial nil
"Whether the struts are from _NET_WM_STRUT_PARTIAL.") (defun exwm-workspace--update-struts ()
"Update `exwm-workspace--struts'."
(let ((left 0)
(right 0)
(top 0)
(bottom 0)
struts)
(dolist (pair exwm-workspace--id-struts-alist)
(setq struts (cdr pair))
(when struts
(when (< left (aref struts 0))
(setq left (aref struts 0)))
(when (< right (aref struts 1))
(setq right (aref struts 1)))
(when (< top (aref struts 2))
(setq top (aref struts 2)))
(when (< bottom (aref struts 3))
(setq bottom (aref struts 3)))))
(setq exwm-workspace--struts (vector left right top bottom))
(when (equal exwm-workspace--struts [0 0 0 0])
(setq exwm-workspace--struts nil))))
(defvar exwm-workspace--fullscreen-frame-count 0 (defvar exwm-workspace--fullscreen-frame-count 0
"Count the fullscreen workspace frames.") "Count the fullscreen workspace frames.")
@ -139,8 +159,12 @@ Value nil means to use the default position which is fixed at bottom, while
(declare-function exwm-layout--resize-container "exwm-layout.el" (declare-function exwm-layout--resize-container "exwm-layout.el"
(id container x y width height &optional container-only)) (id container x y width height &optional container-only))
(defun exwm-workspace--set-fullscreen (frame) (defun exwm-workspace--set-fullscreen (frame &optional no-struts
"Make frame FRAME fullscreen, with regard to its RandR output if applicable." container-only)
"Make frame FRAME fullscreen, with regard to its RandR output if applicable.
If NO-STRUTS is non-nil, struts are ignored. If CONTAINER-ONLY is non-nil, the
workspace frame and its container is not resized."
(let ((geometry (or (frame-parameter frame 'exwm-geometry) (let ((geometry (or (frame-parameter frame 'exwm-geometry)
(xcb:+request-unchecked+reply exwm--connection (xcb:+request-unchecked+reply exwm--connection
(make-instance 'xcb:GetGeometry (make-instance 'xcb:GetGeometry
@ -153,24 +177,27 @@ Value nil means to use the default position which is fixed at bottom, while
(workspace (frame-parameter frame 'exwm-workspace)) (workspace (frame-parameter frame 'exwm-workspace))
x* y* width* height*) x* y* width* height*)
(with-slots (x y width height) geometry (with-slots (x y width height) geometry
(if exwm-workspace--strut (if (and exwm-workspace--struts (not no-struts))
(setq x* (+ x (aref exwm-workspace--strut 0)) (setq x* (+ x (aref exwm-workspace--struts 0))
y* (+ y (aref exwm-workspace--strut 2)) y* (+ y (aref exwm-workspace--struts 2))
width* (- width (aref exwm-workspace--strut 0) width* (- width (aref exwm-workspace--struts 0)
(aref exwm-workspace--strut 1)) (aref exwm-workspace--struts 1))
height* (- height (aref exwm-workspace--strut 2) height* (- height (aref exwm-workspace--struts 2)
(aref exwm-workspace--strut 3))) (aref exwm-workspace--struts 3)))
(setq x* x (setq x* x
y* y y* y
width* width width* width
height* height)) height* height))
(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)
(not container-only))
(exwm-workspace--resize-minibuffer-frame width height)) (exwm-workspace--resize-minibuffer-frame width height))
(exwm-layout--resize-container id container 0 0 width* height*) (unless container-only
(exwm-layout--resize-container id container 0 0 width* height*))
(exwm-layout--resize-container nil workspace x* y* width* height* t) (exwm-layout--resize-container nil workspace x* y* width* height* t)
(xcb:flush exwm--connection))) (xcb:flush exwm--connection)))
(cl-incf exwm-workspace--fullscreen-frame-count)) (unless container-only
(cl-incf exwm-workspace--fullscreen-frame-count)))
;;;###autoload ;;;###autoload
(defun exwm-workspace--resize-minibuffer-frame (&optional width height) (defun exwm-workspace--resize-minibuffer-frame (&optional width height)
@ -182,19 +209,19 @@ workspace frame."
(let ((y (if (eq exwm-workspace-minibuffer-position 'top) (let ((y (if (eq exwm-workspace-minibuffer-position 'top)
0 0
(- (or height (exwm-workspace--current-height)) (- (or height (exwm-workspace--current-height))
(if exwm-workspace--strut (if exwm-workspace--struts
(+ (aref exwm-workspace--strut 2) (+ (aref exwm-workspace--struts 2)
(aref exwm-workspace--strut 3)) (aref exwm-workspace--struts 3))
0) 0)
(frame-pixel-height exwm-workspace--minibuffer)))) (frame-pixel-height exwm-workspace--minibuffer))))
(container (frame-parameter exwm-workspace--minibuffer (container (frame-parameter exwm-workspace--minibuffer
'exwm-container))) 'exwm-container)))
(unless width (unless width
(setq width (exwm-workspace--current-width))) (setq width (exwm-workspace--current-width)))
(when exwm-workspace--strut (when exwm-workspace--struts
(setq width (- width (setq width (- width
(aref exwm-workspace--strut 0) (aref exwm-workspace--struts 0)
(aref exwm-workspace--strut 1)))) (aref exwm-workspace--struts 1))))
(xcb:+request exwm--connection (xcb:+request exwm--connection
(make-instance 'xcb:ConfigureWindow (make-instance 'xcb:ConfigureWindow
:window container :window container
@ -233,11 +260,22 @@ The optional FORCE option is for internal use only."
(let* ((frame (elt exwm-workspace--list index)) (let* ((frame (elt exwm-workspace--list index))
(workspace (frame-parameter frame 'exwm-workspace)) (workspace (frame-parameter frame 'exwm-workspace))
(window (frame-parameter frame 'exwm-selected-window))) (window (frame-parameter frame 'exwm-selected-window)))
(unless (window-live-p window)
(setq window (frame-selected-window frame)))
;; Raise the workspace container.
(xcb:+request exwm--connection (xcb:+request exwm--connection
(make-instance 'xcb:ConfigureWindow (make-instance 'xcb:ConfigureWindow
:window workspace :window workspace
:value-mask xcb:ConfigWindow:StackMode :value-mask xcb:ConfigWindow:StackMode
:stack-mode xcb:StackMode:Above)) :stack-mode xcb:StackMode:Above))
;; Raise X windows with struts set if there's no fullscreen X window.
(unless (buffer-local-value 'exwm--fullscreen (window-buffer window))
(dolist (pair exwm-workspace--id-struts-alist)
(xcb:+request exwm--connection
(make-instance 'xcb:ConfigureWindow
:window (car pair)
:value-mask xcb:ConfigWindow:StackMode
:stack-mode xcb:StackMode:Above))))
(setq exwm-workspace--current frame (setq exwm-workspace--current frame
exwm-workspace-current-index index) exwm-workspace-current-index index)
(unless (memq (selected-frame) exwm-workspace--list) (unless (memq (selected-frame) exwm-workspace--list)
@ -245,8 +283,7 @@ The optional FORCE option is for internal use only."
(set-frame-parameter (with-current-buffer (window-buffer) (set-frame-parameter (with-current-buffer (window-buffer)
exwm--frame) exwm--frame)
'exwm-selected-window (selected-window))) 'exwm-selected-window (selected-window)))
(select-window (or (when (window-live-p window) window) (select-window window)
(frame-selected-window frame)))
(set-frame-parameter frame 'exwm-selected-window nil) (set-frame-parameter frame 'exwm-selected-window nil)
;; Close the (possible) active minibuffer ;; Close the (possible) active minibuffer
(when (active-minibuffer-window) (when (active-minibuffer-window)
@ -556,9 +593,9 @@ The optional FORCE option is for internal use only."
y 0) y 0)
(setq value-mask (logior xcb:ConfigWindow:Y xcb:ConfigWindow:Height) (setq value-mask (logior xcb:ConfigWindow:Y xcb:ConfigWindow:Height)
y (- (exwm-workspace--current-height) y (- (exwm-workspace--current-height)
(if exwm-workspace--strut (if exwm-workspace--struts
(+ (aref exwm-workspace--strut 2) (+ (aref exwm-workspace--struts 2)
(aref exwm-workspace--strut 3)) (aref exwm-workspace--struts 3))
0) 0)
height))) height)))
(xcb:+request exwm--connection (xcb:+request exwm--connection
@ -731,13 +768,13 @@ The optional FORCE option is for internal use only."
(setq workareas (vconcat workareas workarea)))))) (setq workareas (vconcat workareas workarea))))))
;; Exclude areas occupied by struts. ;; Exclude areas occupied by struts.
;; FIXME: RandR. ;; FIXME: RandR.
(when exwm-workspace--strut (when exwm-workspace--struts
(let ((dx (aref exwm-workspace--strut 0)) (let ((dx (aref exwm-workspace--struts 0))
(dy (aref exwm-workspace--strut 2)) (dy (aref exwm-workspace--struts 2))
(dw (- (+ (aref exwm-workspace--strut 0) (dw (- (+ (aref exwm-workspace--struts 0)
(aref exwm-workspace--strut 1)))) (aref exwm-workspace--struts 1))))
(dh (- (+ (aref exwm-workspace--strut 2) (dh (- (+ (aref exwm-workspace--struts 2)
(aref exwm-workspace--strut 3))))) (aref exwm-workspace--struts 3)))))
(dotimes (i exwm-workspace-number) (dotimes (i exwm-workspace-number)
(cl-incf (aref workareas (* i 4)) dx) (cl-incf (aref workareas (* i 4)) dx)
(cl-incf (aref workareas (+ (* i 4))) dy) (cl-incf (aref workareas (+ (* i 4))) dy)

52
exwm.el
View file

@ -227,45 +227,49 @@
(when reply ;nil when destroyed (when reply ;nil when destroyed
(setq exwm--protocols (append (slot-value reply 'value) nil))))))) (setq exwm--protocols (append (slot-value reply 'value) nil)))))))
(defun exwm--update-strut-legacy (id) (defun exwm--update-struts-legacy (id)
"Update _NET_WM_STRUT." "Update _NET_WM_STRUT."
(unless exwm-workspace--strut-is-partial (let ((pair (assq id exwm-workspace--id-struts-alist))
(let ((reply (xcb:+request-unchecked+reply exwm--connection reply struts)
(make-instance 'xcb:ewmh:get-_NET_WM_STRUT (unless (and pair (< 4 (length (cdr pair))))
:window id)))) (setq reply (xcb:+request-unchecked+reply exwm--connection
(setq exwm-workspace--strut (when reply (slot-value reply 'value))) (make-instance 'xcb:ewmh:get-_NET_WM_STRUT
:window id)))
(when reply
(setq struts (slot-value reply 'value))
(if pair
(setcdr pair struts)
(push (cons id struts) exwm-workspace--id-struts-alist))
(exwm-workspace--update-struts))
;; Update workspaces. ;; Update workspaces.
(dolist (f exwm-workspace--list) (dolist (f exwm-workspace--list)
(exwm-workspace--set-fullscreen f)) (exwm-workspace--set-fullscreen f))
;; Resize the minibuffer frame.
(when (exwm-workspace--minibuffer-own-frame-p)
(exwm-workspace--resize-minibuffer-frame))
;; Update _NET_WORKAREA. ;; Update _NET_WORKAREA.
(exwm-workspace--set-workareas)))) (exwm-workspace--set-workareas))))
(defun exwm--update-strut-partial (id) (defun exwm--update-struts-partial (id)
"Update _NET_WM_STRUT_PARTIAL." "Update _NET_WM_STRUT_PARTIAL."
(let ((reply (xcb:+request-unchecked+reply exwm--connection (let ((reply (xcb:+request-unchecked+reply exwm--connection
(make-instance 'xcb:ewmh:get-_NET_WM_STRUT_PARTIAL (make-instance 'xcb:ewmh:get-_NET_WM_STRUT_PARTIAL
:window id)))) :window id)))
(setq exwm-workspace--strut (when reply (slot-value reply 'value))) struts pair)
(if (not exwm-workspace--strut) (when reply
(setq exwm-workspace--strut-is-partial nil) (setq struts (slot-value reply 'value)
(setq exwm-workspace--strut (substring exwm-workspace--strut 0 4)) pair (assq id exwm-workspace--id-struts-alist))
(setq exwm-workspace--strut-is-partial t)) (if pair
(setcdr pair struts)
(push (cons id struts) exwm-workspace--id-struts-alist))
(exwm-workspace--update-struts))
;; Update workspaces. ;; Update workspaces.
(dolist (f exwm-workspace--list) (dolist (f exwm-workspace--list)
(exwm-workspace--set-fullscreen f)) (exwm-workspace--set-fullscreen f))
;; Resize the minibuffer frame.
(when (exwm-workspace--minibuffer-own-frame-p)
(exwm-workspace--resize-minibuffer-frame))
;; Update _NET_WORKAREA. ;; Update _NET_WORKAREA.
(exwm-workspace--set-workareas))) (exwm-workspace--set-workareas)))
(defun exwm--update-strut (id) (defun exwm--update-struts (id)
"Update _NET_WM_STRUT_PARTIAL or _NET_WM_STRUT." "Update _NET_WM_STRUT_PARTIAL or _NET_WM_STRUT."
(exwm--update-strut-partial id) (exwm--update-struts-partial id)
(exwm--update-strut-legacy id)) (exwm--update-struts-legacy id))
(defun exwm--on-PropertyNotify (data _synthetic) (defun exwm--on-PropertyNotify (data _synthetic)
"Handle PropertyNotify event." "Handle PropertyNotify event."
@ -279,9 +283,9 @@
(if (not (buffer-live-p buffer)) (if (not (buffer-live-p buffer))
;; Properties of unmanaged X windows. ;; Properties of unmanaged X windows.
(cond ((= atom xcb:Atom:_NET_WM_STRUT) (cond ((= atom xcb:Atom:_NET_WM_STRUT)
(exwm--update-strut-legacy id)) (exwm--update-struts-legacy id))
((= atom xcb:Atom:_NET_WM_STRUT_PARTIAL) ((= atom xcb:Atom:_NET_WM_STRUT_PARTIAL)
(exwm--update-strut-partial id))) (exwm--update-struts-partial id)))
(with-current-buffer buffer (with-current-buffer buffer
(cond ((= atom xcb:Atom:_NET_WM_WINDOW_TYPE) (cond ((= atom xcb:Atom:_NET_WM_WINDOW_TYPE)
(exwm--update-window-type id t)) (exwm--update-window-type id t))