From b2ee10205177361a5f14dd11c4206b5ffd1cb98c Mon Sep 17 00:00:00 2001 From: Chris Feng Date: Thu, 29 Oct 2015 18:31:16 +0800 Subject: 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. --- exwm-manage.el | 69 +++++++++++++++++++++++++++++++++------------------------- 1 file changed, 39 insertions(+), 30 deletions(-) (limited to 'exwm-manage.el') 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." -- cgit 1.4.1