about summary refs log tree commit diff
diff options
context:
space:
mode:
authorChris Feng <chris.w.feng@gmail.com>2015-08-07T13·52+0800
committerChris Feng <chris.w.feng@gmail.com>2015-08-07T13·52+0800
commit14628a940c12051f2538556b97a2ef4531c75201 (patch)
treecd396af0451c08e9131ed61a6cf4a05fc5b5a784
parent84f0f0328b173af82c873e395353bd9a6c3bf1f6 (diff)
Fix race conditions when managing a window
Since it takes some time for EXWM to create a buffer for a window (to do some
checking for example), the window may send several MapRequest events before
it's mapped. This commit should fix such issue.
-rw-r--r--exwm-manage.el14
1 files changed, 13 insertions, 1 deletions
diff --git a/exwm-manage.el b/exwm-manage.el
index 7c82696fb7f2..8594066a71fa 100644
--- a/exwm-manage.el
+++ b/exwm-manage.el
@@ -42,19 +42,28 @@ corresponding buffer.")
         (when reply                     ;nil when destroyed
           (setq exwm--geometry reply))))))
 
+(defvar exwm-manage--manage-window-queue nil
+  "List of window IDs to prevent race conditions.")
+
 (defun exwm-manage--manage-window (id)
   "Manage window ID."
+  (exwm--log "Try to manage #x%x" id)
   (setq exwm-input--focus-lock t)
   (catch 'return
     ;; Ensure it's not managed
-    (when (assoc id exwm--id-buffer-alist)
+    (when (or (assoc id exwm--id-buffer-alist)
+              (memq id exwm-manage--manage-window-queue))
+      (exwm--log "#x%x is already managed" id)
       (throw 'return 'managed))
+    (push id exwm-manage--manage-window-queue) ;prevent reentering
     ;; Ensure it's alive
     (when (xcb:+request-checked+request-check exwm--connection
               (make-instance 'xcb:ChangeWindowAttributes
                              :window id :value-mask xcb:CW:EventMask
                              :event-mask exwm--client-event-mask))
+      (delq id exwm-manage--manage-window-queue) ;cleanup
       (throw 'return 'dead))
+    (delq id exwm-manage--manage-window-queue) ;cleanup (late enough)
     (with-current-buffer (generate-new-buffer "*EXWM*")
       (push `(,id . ,(current-buffer)) exwm--id-buffer-alist)
       (exwm-mode)
@@ -73,6 +82,7 @@ corresponding buffer.")
              (and exwm-instance-name
                   (string-prefix-p "sun-awt-X11-" exwm-instance-name)
                   (not (string-suffix-p "XFramePeer" exwm-instance-name))))
+        (exwm--log "No need to manage #x%x" id)
         ;; Remove all events
         (xcb:+request-checked+request-check exwm--connection
             (make-instance 'xcb:ChangeWindowAttributes
@@ -104,6 +114,7 @@ corresponding buffer.")
         (kill-buffer (current-buffer))
         (throw 'return 'ignored))
       ;; Manage the window
+      (exwm--log "Manage #x%x" id)
       (xcb:+request exwm--connection    ;remove border
           (make-instance 'xcb:ConfigureWindow
                          :window id :value-mask xcb:ConfigWindow:BorderWidth
@@ -140,6 +151,7 @@ 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)
     (setq exwm--id-buffer-alist (assq-delete-all id exwm--id-buffer-alist))
     (when (buffer-live-p buffer)
       (with-current-buffer buffer