diff options
author | Chris Feng <chris.w.feng@gmail.com> | 2015-10-29T10·31+0800 |
---|---|---|
committer | Chris Feng <chris.w.feng@gmail.com> | 2015-10-29T10·32+0800 |
commit | b2ee10205177361a5f14dd11c4206b5ffd1cb98c (patch) | |
tree | 0bc4e0dbef4074a039b882eeb0e2bebcbbaaf4a9 | |
parent | d9b4ba0265fc1674b1205a11e838f86bce434b13 (diff) |
Improve robustness of killing buffers
* exwm-core.el (exwm-mode): Use the return value of exwm-manage--close-window. * exwm-manage.el (exwm-manage--close-window): Kill empty buffers; Handle X windows that does not support _NET_WM_PING. (exwm-manage--kill-client): Kill X windows supporting _NET_WM_PID with both SIGKILL and KillClient.
-rw-r--r-- | exwm-core.el | 3 | ||||
-rw-r--r-- | exwm-manage.el | 69 |
2 files changed, 40 insertions, 32 deletions
diff --git a/exwm-core.el b/exwm-core.el index ec7034737a0f..aaa98e394fc8 100644 --- a/exwm-core.el +++ b/exwm-core.el @@ -139,8 +139,7 @@ ;; Kill buffer -> close window (add-hook 'kill-buffer-query-functions (lambda () - (exwm-manage--close-window exwm--id (current-buffer)) - nil) + (exwm-manage--close-window exwm--id (current-buffer))) nil t) (setq buffer-read-only t left-margin-width nil diff --git a/exwm-manage.el b/exwm-manage.el index bf285ab94406..aa484d657b21 100644 --- a/exwm-manage.el +++ b/exwm-manage.el @@ -249,6 +249,8 @@ corresponding buffer.") (defun exwm-manage--close-window (id &optional buffer) "Close window ID in a proper way." (catch 'return + (unless (exwm--id->buffer id) + (throw 'return t)) (unless buffer (setq buffer (exwm--id->buffer id))) ;; Destroy the client window if it does not support WM_DELETE_WINDOW (unless (and (buffer-live-p buffer) @@ -268,31 +270,33 @@ corresponding buffer.") exwm--connection))) (xcb:flush exwm--connection) ;; Try to determine if the client stop responding - ;; FIXME: check (with-current-buffer buffer - (when (memq xcb:Atom:_NET_WM_PING exwm--protocols) - (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 be destroyed - (accept-process-output nil 0.1))) - (throw 'return nil))) - (throw 'return nil))) + (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)))))) (defun exwm-manage--kill-client (&optional id) "Kill an X client." @@ -300,12 +304,17 @@ corresponding buffer.") (unless id (setq id (exwm--buffer->id (current-buffer)))) (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)))) - (if pid - (signal-process pid 'SIGKILL) - (xcb:+request exwm--connection - (make-instance 'xcb:KillClient :resource id)) - (xcb:flush exwm--connection)))) + (pid (and response (slot-value response 'value))) + (request (make-instance 'xcb:KillClient :resource id))) + (if (not pid) + (xcb:+request exwm--connection request) + ;; What if the PID is fake/wrong? + (signal-process pid 'SIGKILL) + ;; Ensure it's dead + (run-with-timer exwm-manage-ping-timeout nil + `(lambda () + (xcb:+request exwm--connection ,request)))) + (xcb:flush exwm--connection))) (defun exwm-manage--on-ConfigureRequest (data _synthetic) "Handle ConfigureRequest event." |