[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/exwm 1c79e1c 2/2: Prevent/Reduce flickering issues with
From: |
Chris Feng |
Subject: |
[elpa] externals/exwm 1c79e1c 2/2: Prevent/Reduce flickering issues with floating X windows |
Date: |
Sat, 20 Feb 2016 07:02:43 +0000 |
branch: externals/exwm
commit 1c79e1c2384128915357ea629fc2a0503bd36733
Author: Chris Feng <address@hidden>
Commit: Chris Feng <address@hidden>
Prevent/Reduce flickering issues with floating X windows
* exwm-floating.el (exwm-floating--set-floating)
(exwm-floating--unset-floating): Prevent flickering when creating/removing
a floating X window.
* exwm-layout.el (exwm-layout--show): Show X windows after resizing to
prevent flickering.
* exwm-manage.el (exwm-manage--unmanage-window): Reduce flickering by
hiding the container.
(exwm-manage--kill-buffer-query-function): Prevent flickering by hiding the
container (except that the X window destroys itself after receiving the
WM_DELETE_WINDOW client message).
---
exwm-floating.el | 35 ++++++++++++++++++++++++++++++-----
exwm-layout.el | 19 ++++++++++---------
exwm-manage.el | 53 ++++++++++++++++++++++++++++++++++++++---------------
3 files changed, 78 insertions(+), 29 deletions(-)
diff --git a/exwm-floating.el b/exwm-floating.el
index 209539e..2769488 100644
--- a/exwm-floating.el
+++ b/exwm-floating.el
@@ -193,17 +193,42 @@
(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)
- (exwm-layout--show id window))
- (select-frame-set-input-focus frame))
- (run-hooks 'exwm-floating-setup-hook))
+ (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))
+ (run-hooks 'exwm-floating-setup-hook)
+ ;; Redraw the frame.
+ (redisplay))
(defun exwm-floating--unset-floating (id)
"Make window ID non-floating."
(let ((buffer (exwm--id->buffer id)))
(with-current-buffer buffer
- ;; Reparent the frame back to the root window.
(when exwm--floating-frame
+ ;; The X window is already mapped.
+ ;; Unmap the container to prevent flickering.
+ (xcb:+request exwm--connection
+ (make-instance 'xcb:UnmapWindow :window exwm--container))
+ (xcb:flush exwm--connection)
+ ;; Unmap the X window.
+ (xcb:+request exwm--connection
+ (make-instance 'xcb:ChangeWindowAttributes
+ :window id :value-mask xcb:CW:EventMask
+ :event-mask xcb:EventMask:NoEvent))
+ (xcb:+request exwm--connection
+ (make-instance 'xcb:UnmapWindow :window id))
+ (xcb:+request exwm--connection
+ (make-instance 'xcb:ChangeWindowAttributes
+ :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)))
(xcb:+request exwm--connection
(make-instance 'xcb:UnmapWindow :window frame-id))
diff --git a/exwm-layout.el b/exwm-layout.el
index c0f3c61..e3c1feb 100644
--- a/exwm-layout.el
+++ b/exwm-layout.el
@@ -53,14 +53,6 @@
(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* ((edges (window-inside-absolute-pixel-edges window))
(width (- (elt edges 2) (elt edges 0)))
(height (- (elt edges 3) (elt edges 1))))
@@ -93,7 +85,16 @@
(elt relative-edges 0)
(elt relative-edges 1)
width height
- (active-minibuffer-window)))))
+ (active-minibuffer-window))))
+ ;; Make the resizing take effect.
+ (xcb:flush exwm--connection)
+ (xcb:+request exwm--connection (make-instance 'xcb:MapWindow :window 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)))
(xcb:+request exwm--connection
(make-instance 'xcb:SendEvent
:propagate 0 :destination id
diff --git a/exwm-manage.el b/exwm-manage.el
index 224ee16..c9c6ff9 100644
--- a/exwm-manage.el
+++ b/exwm-manage.el
@@ -213,14 +213,18 @@ corresponding buffer.")
(defun exwm-manage--unmanage-window (id &optional withdraw-only)
"Unmanage window ID."
(let ((buffer (exwm--id->buffer id)))
- (exwm--log "Unmanage #x%x (buffer: %s)" id buffer)
+ (exwm--log "Unmanage #x%x (buffer: %s, widthdraw: %s)"
+ id buffer withdraw-only)
(setq exwm--id-buffer-alist (assq-delete-all id exwm--id-buffer-alist))
(when (buffer-live-p buffer)
(with-current-buffer buffer
- ;; Hide the floating frame as early as possible.
- (when exwm--floating-frame (make-frame-invisible exwm--floating-frame))
+ ;; Flickering seems unavoidable here if the DestroyWindow request is
+ ;; not initiated by us.
+ ;; What we can do is to hide the its container ASAP.
(xcb:+request exwm--connection
(make-instance 'xcb:UnmapWindow :window exwm--container))
+ (xcb:flush exwm--connection)
+ ;;
(setq exwm-workspace--switch-history-outdated t)
;;
(when withdraw-only
@@ -254,12 +258,13 @@ corresponding buffer.")
:window id :property xcb:Atom:WM_STATE)))
;; Destroy the container (it seems it has to be delayed).
(when exwm--floating-frame
- (xcb:+request exwm--connection
- (make-instance 'xcb:ReparentWindow
- :window (frame-parameter exwm--floating-frame
- 'exwm-outer-id)
- :parent exwm--root
- :x 0 :y 0)))
+ ;; Unmap the 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
+ (make-instance 'xcb:ReparentWindow
+ :window window :parent exwm--root :x 0 :y 0))))
(xcb:+request exwm--connection
(make-instance 'xcb:DestroyWindow :window exwm--container))
(xcb:flush exwm--connection)
@@ -268,12 +273,12 @@ corresponding buffer.")
(kill-buffer)
(when floating
(select-window
- (frame-selected-window exwm-workspace--current))))))
- (xcb:+request exwm--connection ;update _NET_CLIENT_LIST
- (make-instance 'xcb:ewmh:set-_NET_CLIENT_LIST
- :window exwm--root
- :data (vconcat (mapcar #'car exwm--id-buffer-alist))))
- (xcb:flush exwm--connection)))
+ (frame-selected-window exwm-workspace--current)))))
+ (xcb:+request exwm--connection ;update _NET_CLIENT_LIST
+ (make-instance 'xcb:ewmh:set-_NET_CLIENT_LIST
+ :window exwm--root
+ :data (vconcat (mapcar #'car exwm--id-buffer-alist))))
+ (xcb:flush exwm--connection))))
(defun exwm-manage--scan ()
"Search for existing windows and try to manage them."
@@ -300,6 +305,10 @@ corresponding buffer.")
(make-instance 'xcb:MapWindow :window exwm--id))
;; The X window is no longer alive so just close the buffer.
;; Destroy the container.
+ ;; Hide the container to prevent flickering.
+ (xcb:+request exwm--connection
+ (make-instance 'xcb:UnmapWindow :window exwm--container))
+ (xcb:flush exwm--connection)
(when exwm--floating-frame
(xcb:+request exwm--connection
(make-instance 'xcb:ReparentWindow
@@ -313,6 +322,9 @@ corresponding buffer.")
(throw 'return t))
(unless (memq xcb:Atom:WM_DELETE_WINDOW exwm--protocols)
;; The X window does not support WM_DELETE_WINDOW; destroy it.
+ ;; Hide the container to prevent flickering.
+ (xcb:+request exwm--connection
+ (make-instance 'xcb:UnmapWindow :window exwm--container))
(xcb:+request exwm--connection
(make-instance 'xcb:DestroyWindow :window exwm--id))
(xcb:flush exwm--connection)
@@ -331,6 +343,10 @@ corresponding buffer.")
(unless (memq xcb:Atom:_NET_WM_PING exwm--protocols)
;; The window does not support _NET_WM_PING. To make sure it'll die,
;; kill it after the time runs out.
+ ;; Hide the container to prevent flickering.
+ (xcb:+request exwm--connection
+ (make-instance 'xcb:UnmapWindow :window exwm--container))
+ (xcb:flush exwm--connection)
(run-with-timer exwm-manage-ping-timeout nil
`(lambda () (exwm-manage--kill-client ,exwm--id)))
;; Wait for DestroyNotify event.
@@ -368,6 +384,13 @@ Would you like to kill it? "
(defun exwm-manage--kill-client (&optional id)
"Kill an X client."
(unless id (setq id (exwm--buffer->id (current-buffer))))
+ ;; Hide the container to prevent flickering.
+ (let ((buffer (exwm--id->buffer id)))
+ (when buffer
+ (with-current-buffer buffer
+ (xcb:+request exwm--connection
+ (make-instance 'xcb:UnmapWindow :window exwm--container))
+ (xcb:flush exwm--connection))))
(let* ((response (xcb:+request-unchecked+reply exwm--connection
(make-instance 'xcb:ewmh:get-_NET_WM_PID :window id)))
(pid (and response (slot-value response 'value)))