[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/exwm 3f77220: Fix floating X window bugs introduced by
From: |
Chris Feng |
Subject: |
[elpa] externals/exwm 3f77220: Fix floating X window bugs introduced by 9c95c03e |
Date: |
Thu, 18 Feb 2016 12:00:15 +0000 |
branch: externals/exwm
commit 3f7722079cebd0d998239ce40457899135250a15
Author: Chris Feng <address@hidden>
Commit: Chris Feng <address@hidden>
Fix floating X window bugs introduced by 9c95c03e
* exwm-floating.el (exwm-floating--set-floating): Make floating frames
invisible before resizing them.
(exwm-floating--fit-frame-to-window): Removed since unused.
* exwm-layout.el (exwm-layout-hide-mode-line, exwm-layout-show-mode-line):
Use set frame height instead of exwm-floating--fit-frame-to-window.
* exwm-core.el (exwm-mode): Replace `exwm-manage--close-window' with
`exwm-manage--kill-buffer-query-function'.
* exwm-floating.el (exwm-floating--unset-floating): Reparent out floating
frames.
* exwm-manage.el (exwm-manage--unmanage-window): Reparent out floating
frames. Hide floating frames.
(exwm-manage--close-window, exwm-manage--kill-buffer-query-function):
Rename `exwm-manage--close-window' since it's only used in
`kill-buffer-query-functions'. Reparent out floating frames.
---
exwm-core.el | 4 +-
exwm-floating.el | 60 ++++++++++----------
exwm-layout.el | 29 ++++++----
exwm-manage.el | 158 ++++++++++++++++++++++++++++++------------------------
4 files changed, 137 insertions(+), 114 deletions(-)
diff --git a/exwm-core.el b/exwm-core.el
index 9430b43..b09ca52 100644
--- a/exwm-core.el
+++ b/exwm-core.el
@@ -142,9 +142,7 @@
(add-hook 'change-major-mode-hook #'kill-buffer nil t)
;; Kill buffer -> close window
(add-hook 'kill-buffer-query-functions
- (lambda ()
- (exwm-manage--close-window exwm--id (current-buffer)))
- nil t)
+ #'exwm-manage--kill-buffer-query-function nil t)
(setq buffer-read-only t
left-margin-width nil
right-margin-width nil
diff --git a/exwm-floating.el b/exwm-floating.el
index b5ab8a8..82b4487 100644
--- a/exwm-floating.el
+++ b/exwm-floating.el
@@ -50,6 +50,8 @@
(defvar exwm-floating--cursor-bottom-left nil)
(defvar exwm-floating--cursor-left nil)
+(declare-function exwm-layout--refresh "exwm-layout.el")
+
;;;###autoload
(defun exwm-floating--set-floating (id)
"Make window ID floating."
@@ -78,6 +80,8 @@
(internal-border-width . ,exwm-floating-border-width)
(left . 10000)
(top . 10000)
+ (width . ,window-min-width)
+ (height . ,window-min-height)
(unsplittable . t))))) ;and fix the size later
(outer-id (string-to-number (frame-parameter frame 'outer-window-id)))
(container (with-current-buffer (exwm--id->buffer id)
@@ -151,7 +155,17 @@
y (/ (- display-height height) 2))))))
(exwm--log "Floating geometry (corrected): %dx%d%+d%+d" width height x y)
;; Fit frame to client
- (exwm-floating--fit-frame-to-window outer-id width height)
+ ;; It seems we have to make the frame invisible in order to resize it
+ ;; 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
(xcb:+request exwm--connection
(make-instance 'xcb:ReparentWindow
@@ -171,8 +185,12 @@
(setq window-size-fixed exwm--fixed-size
exwm--frame original-frame
exwm--floating-frame frame)
+ ;; Do the refresh manually.
+ (remove-hook 'window-configuration-change-hook #'exwm-layout--refresh)
(set-window-buffer window (current-buffer)) ;this changes current buffer
- (set-window-dedicated-p window t))
+ (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))
@@ -182,6 +200,16 @@
(interactive)
(let ((buffer (exwm--id->buffer id)))
(with-current-buffer buffer
+ ;; Reparent the frame back to the root window.
+ (when exwm--floating-frame
+ (let ((frame-id (frame-parameter exwm--floating-frame 'exwm-outer-id)))
+ (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
@@ -221,34 +249,6 @@
(exwm-floating--unset-floating exwm--id)
(exwm-floating--set-floating exwm--id))))
-;;;###autoload
-(defun exwm-floating--fit-frame-to-window (&optional frame-outer-id
- width height)
- "Resize a floating frame to make it fit the size of the window.
-
-Default to resize `exwm--floating-frame' unless FRAME-OUTER-ID is non-nil.
-This function will issue an `xcb:GetGeometry' request unless WIDTH and HEIGHT
-are provided. You should call `xcb:flush' and restore the value of
-`window-size-fixed' afterwards."
- (setq window-size-fixed nil)
- (unless (and width height)
- (let ((geometry (xcb:+request-unchecked+reply exwm--connection
- (make-instance 'xcb:GetGeometry :drawable exwm--id))))
- (setq width (slot-value geometry 'width)
- height (slot-value geometry 'height))))
- (xcb:+request exwm--connection
- (make-instance 'xcb:ConfigureWindow
- :window (or frame-outer-id
- (frame-parameter exwm--floating-frame
- 'exwm-outer-id))
- :value-mask (eval-when-compile
- (logior xcb:ConfigWindow:Width
- xcb:ConfigWindow:Height))
- :width (+ width (* 2 exwm-floating-border-width))
- :height (+ height (* 2 exwm-floating-border-width)
- (window-mode-line-height)
- (window-header-line-height)))))
-
(define-obsolete-function-alias 'exwm-floating-hide-mode-line
'exwm-layout-hide-mode-line "25.1" "Hide mode-line of a floating frame.")
(define-obsolete-function-alias 'exwm-floating-show-mode-line
diff --git a/exwm-layout.el b/exwm-layout.el
index a70cf1b..52a84b0 100644
--- a/exwm-layout.el
+++ b/exwm-layout.el
@@ -396,13 +396,18 @@ See also `exwm-layout-enlarge-window'."
"Hide mode-line."
(interactive)
(when (and (eq major-mode 'exwm-mode) mode-line-format)
- (setq exwm--mode-line-format mode-line-format
- mode-line-format nil)
- (if (not exwm--floating-frame)
- (exwm-layout--show exwm--id)
- (exwm-floating--fit-frame-to-window)
- (xcb:flush exwm--connection)
- (setq window-size-fixed exwm--fixed-size))))
+ (let (mode-line-height)
+ (when exwm--floating-frame
+ (setq mode-line-height (window-mode-line-height
+ (frame-root-window exwm--floating-frame))))
+ (setq exwm--mode-line-format mode-line-format
+ mode-line-format nil)
+ (if (not exwm--floating-frame)
+ (exwm-layout--show exwm--id)
+ (set-frame-height exwm--floating-frame
+ (- (frame-pixel-height exwm--floating-frame)
+ mode-line-height)
+ nil t)))))
(defun exwm-layout-show-mode-line ()
"Show mode-line."
@@ -412,10 +417,12 @@ See also `exwm-layout-enlarge-window'."
exwm--mode-line-format nil)
(if (not exwm--floating-frame)
(exwm-layout--show exwm--id)
- (exwm-floating--fit-frame-to-window)
- (exwm-input-grab-keyboard)
- (xcb:flush exwm--connection)
- (setq window-size-fixed exwm--fixed-size))))
+ (set-frame-height exwm--floating-frame
+ (+ (frame-pixel-height exwm--floating-frame)
+ (window-mode-line-height (frame-root-window
+ exwm--floating-frame)))
+ nil t)
+ (exwm-input-grab-keyboard))))
;;;###autoload
(defun exwm-layout-toggle-mode-line ()
diff --git a/exwm-manage.el b/exwm-manage.el
index 21e18ff..50784ce 100644
--- a/exwm-manage.el
+++ b/exwm-manage.el
@@ -103,7 +103,7 @@ corresponding buffer.")
exwm-window-type))))
(exwm--log "No need to manage #x%x" id)
;; Remove all events
- (xcb:+request-checked+request-check exwm--connection
+ (xcb:+request exwm--connection
(make-instance 'xcb:ChangeWindowAttributes
:window id :value-mask xcb:CW:EventMask
:event-mask xcb:EventMask:NoEvent))
@@ -173,7 +173,7 @@ corresponding buffer.")
:border-width 0))
(dolist (button ;grab buttons to set focus / move / resize
(list xcb:ButtonIndex:1 xcb:ButtonIndex:2 xcb:ButtonIndex:3))
- (xcb:+request-checked+request-check exwm--connection
+ (xcb:+request exwm--connection
(make-instance 'xcb:GrabButton
:owner-events 0 :grab-window id
:event-mask xcb:EventMask:ButtonPress
@@ -206,13 +206,10 @@ corresponding buffer.")
(let ((buffer (exwm--id->buffer id)))
(exwm--log "Unmanage #x%x (buffer: %s)" id buffer)
(setq exwm--id-buffer-alist (assq-delete-all id exwm--id-buffer-alist))
- (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)
(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))
(xcb:+request exwm--connection
(make-instance 'xcb:UnmapWindow :window exwm--container))
(setq exwm-workspace--switch-history-outdated t)
@@ -245,21 +242,29 @@ corresponding buffer.")
;; Delete WM_STATE property
(xcb:+request exwm--connection
(make-instance 'xcb:DeleteProperty
- :window id :property xcb:Atom:WM_STATE))
- (xcb:flush exwm--connection))
+ :window id :property xcb:Atom:WM_STATE)))
;; Destroy the container (it seems it has to be delayed).
- (run-with-idle-timer 0 nil
- `(lambda ()
- (xcb:+request exwm--connection
- ,(make-instance 'xcb:DestroyWindow
- :window exwm--container))
- (xcb:flush exwm--connection)))
+ (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)))
+ (xcb:+request exwm--connection
+ (make-instance 'xcb:DestroyWindow :window exwm--container))
+ (xcb:flush exwm--connection)
(let ((kill-buffer-query-functions nil)
(floating exwm--floating-frame))
(kill-buffer)
(when floating
(select-window
- (frame-selected-window exwm-workspace--current))))))))
+ (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."
@@ -280,64 +285,77 @@ corresponding buffer.")
(defvar exwm-manage-ping-timeout 3 "Seconds to wait before killing a client.")
;;;###autoload
-(defun exwm-manage--close-window (id &optional buffer)
- "Close window ID in a proper way."
- (let (container)
- (catch 'return
- (unless (exwm--id->buffer id)
- (throw 'return t))
- (unless buffer (setq buffer (exwm--id->buffer id)))
- (when (buffer-live-p buffer)
- (setq container exwm--container))
- ;; Destroy the client window if it does not support WM_DELETE_WINDOW
- (unless (and (buffer-live-p buffer)
- (with-current-buffer buffer
- (memq xcb:Atom:WM_DELETE_WINDOW exwm--protocols)))
+(defun exwm-manage--kill-buffer-query-function ()
+ "Run in `kill-buffer-query-functions'."
+ (catch 'return
+ (when (xcb:+request-checked+request-check exwm--connection
+ (make-instance 'xcb:MapWindow :window exwm--id))
+ ;; The X window is no longer alive so just close the buffer.
+ ;; Destroy the container.
+ (when exwm--floating-frame
(xcb:+request exwm--connection
- (make-instance 'xcb:DestroyWindow :window id))
- (xcb:flush exwm--connection)
- (throw 'return nil))
- ;; Try to close the window with WM_DELETE_WINDOW client message
+ (make-instance 'xcb:ReparentWindow
+ :window (frame-parameter exwm--floating-frame
+ 'exwm-outer-id)
+ :parent exwm--root
+ :x 0 :y 0)))
(xcb:+request exwm--connection
- (make-instance 'xcb:icccm:SendEvent
- :destination id
- :event (xcb:marshal
- (make-instance 'xcb:icccm:WM_DELETE_WINDOW
- :window id)
- exwm--connection)))
+ (make-instance 'xcb:DestroyWindow :window exwm--container))
(xcb:flush exwm--connection)
- ;; Try to determine if the client stop responding
- (with-current-buffer buffer
- (unless (memq xcb:Atom:_NET_WM_PING exwm--protocols)
- ;; Ensure it's dead
- (run-with-timer exwm-manage-ping-timeout nil
- `(lambda () (exwm-manage--kill-client ,id)))
- (throw 'return nil))
- (setq exwm-manage--ping-lock t)
- (xcb:+request exwm--connection
- (make-instance 'xcb:SendEvent
- :propagate 0 :destination id
- :event-mask xcb:EventMask:NoEvent
- :event (xcb:marshal
- (make-instance 'xcb:ewmh:_NET_WM_PING
- :window id :timestamp 0
- :client-window id)
- exwm--connection)))
- (xcb:flush exwm--connection)
- (with-timeout (exwm-manage-ping-timeout
- (if (yes-or-no-p (format "`%s' is not responding. \
-Would you like to kill it? "
- (buffer-name buffer)))
- (progn (exwm-manage--kill-client id)
- (throw 'return nil))
- (throw 'return nil)))
- (while (and exwm-manage--ping-lock
- (exwm--id->buffer id)) ;may have been destroyed
- (accept-process-output nil 0.1)))))
- ;; Finally destroy the container
+ (throw 'return t))
+ (unless (memq xcb:Atom:WM_DELETE_WINDOW exwm--protocols)
+ ;; The X window does not support WM_DELETE_WINDOW; destroy it.
+ (xcb:+request exwm--connection
+ (make-instance 'xcb:DestroyWindow :window exwm--id))
+ (xcb:flush exwm--connection)
+ ;; Wait for DestroyNotify event.
+ (throw 'return nil))
+ ;; Try to close the X window with WM_DELETE_WINDOW client message.
(xcb:+request exwm--connection
- (make-instance 'xcb:DestroyWindow :window container))
- (xcb:flush exwm--connection)))
+ (make-instance 'xcb:icccm:SendEvent
+ :destination exwm--id
+ :event (xcb:marshal
+ (make-instance 'xcb:icccm:WM_DELETE_WINDOW
+ :window exwm--id)
+ exwm--connection)))
+ (xcb:flush exwm--connection)
+ ;;
+ (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.
+ (run-with-timer exwm-manage-ping-timeout nil
+ `(lambda () (exwm-manage--kill-client ,exwm--id)))
+ ;; Wait for DestroyNotify event.
+ (throw 'return nil))
+ ;; Try to determine if the X window is dead with _NET_WM_PING.
+ (setq exwm-manage--ping-lock t)
+ (xcb:+request exwm--connection
+ (make-instance 'xcb:SendEvent
+ :propagate 0
+ :destination exwm--id
+ :event-mask xcb:EventMask:NoEvent
+ :event (xcb:marshal
+ (make-instance 'xcb:ewmh:_NET_WM_PING
+ :window exwm--id
+ :timestamp 0
+ :client-window exwm--id)
+ exwm--connection)))
+ (xcb:flush exwm--connection)
+ (with-timeout (exwm-manage-ping-timeout
+ (if (yes-or-no-p (format "'%s' is not responding. \
+Would you like to kill it? "
+ (buffer-name)))
+ (progn (exwm-manage--kill-client exwm--id)
+ ;; Kill the unresponsive X window and
+ ;; wait for DestroyNotify event.
+ (throw 'return nil))
+ ;; Give up.
+ (throw 'return nil)))
+ (while (and exwm-manage--ping-lock
+ (exwm--id->buffer exwm--id)) ;may have been destroyed.
+ (accept-process-output nil 0.1))
+ ;; Give up.
+ (throw 'return nil))))
(defun exwm-manage--kill-client (&optional id)
"Kill an X client."
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [elpa] externals/exwm 3f77220: Fix floating X window bugs introduced by 9c95c03e,
Chris Feng <=