]> git.sur5r.net Git - i3/i3/commitdiff
Ignore X11 errors caused by ReparentWindow / ChangeProperty on already destroyed...
authorMichael Stapelberg <michael@stapelberg.de>
Sun, 10 Jul 2011 21:44:13 +0000 (23:44 +0200)
committerMichael Stapelberg <michael@stapelberg.de>
Sun, 10 Jul 2011 21:44:13 +0000 (23:44 +0200)
These errors can happen because a DestroyWindow request by a client will
trigger an UnmapNotify, then a DestroyNotify. We cannot distinguish this
UnmapNotify from an UnmapNotify not followed by a DestroyNotify, so we just try
to send the ReparentWindow / ChangeProperty and ignore the errors, if any.

include/handlers.h
src/handlers.c
src/main.c
src/tree.c
src/xcb.c

index 839bac619278226ffa6fc8cb4531a6168056e948..0aaaf158a67c33730958e5ba3ede0a087ae2dbb9 100644 (file)
 
 extern int randr_base;
 
+/**
+ * Adds the given sequence to the list of events which are ignored.
+ * If this ignore should only affect a specific response_type, pass
+ * response_type, otherwise, pass -1.
+ *
+ * Every ignored sequence number gets garbage collected after 5 seconds.
+ *
+ */
 void add_ignore_event(const int sequence, const int response_type);
 
+/**
+ * Checks if the given sequence is ignored and returns true if so.
+ *
+ */
+bool event_is_ignored(const int sequence, const int response_type);
+
 /**
  * Takes an xcb_generic_event_t and calls the appropriate handler, based on the
  * event type.
index 8e9bbb0448cddb7c598dd7232b8599f02adef02d..0b64d14160b710d6fb03a17c608c2fa6af1ed509 100644 (file)
@@ -21,6 +21,14 @@ int randr_base = -1;
    changing workspaces */
 static SLIST_HEAD(ignore_head, Ignore_Event) ignore_events;
 
+/*
+ * Adds the given sequence to the list of events which are ignored.
+ * If this ignore should only affect a specific response_type, pass
+ * response_type, otherwise, pass -1.
+ *
+ * Every ignored sequence number gets garbage collected after 5 seconds.
+ *
+ */
 void add_ignore_event(const int sequence, const int response_type) {
     struct Ignore_Event *event = smalloc(sizeof(struct Ignore_Event));
 
@@ -35,7 +43,7 @@ void add_ignore_event(const int sequence, const int response_type) {
  * Checks if the given sequence is ignored and returns true if so.
  *
  */
-static bool event_is_ignored(const int sequence, const int response_type) {
+bool event_is_ignored(const int sequence, const int response_type) {
     struct Ignore_Event *event;
     time_t now = time(NULL);
     for (event = SLIST_FIRST(&ignore_events); event != SLIST_END(&ignore_events);) {
@@ -51,7 +59,7 @@ static bool event_is_ignored(const int sequence, const int response_type) {
         if (event->sequence != sequence)
             continue;
 
-        if (event->response_type != 0 &&
+        if (event->response_type != -1 &&
             event->response_type != response_type)
             continue;
 
@@ -286,7 +294,7 @@ static int handle_map_request(xcb_map_request_event_t *event) {
     cookie = xcb_get_window_attributes_unchecked(conn, event->window);
 
     DLOG("window = 0x%08x, serial is %d.\n", event->window, event->sequence);
-    add_ignore_event(event->sequence, 0);
+    add_ignore_event(event->sequence, -1);
 
     manage_window(event->window, cookie, false);
     x_push_changes(croot);
index a2764cc18067054724a6e1bd53f6f94546875e43..7910c8b1a6655c51b391e54e3a58a69ee6a16ecb 100644 (file)
@@ -70,7 +70,9 @@ static void xcb_check_cb(EV_P_ ev_check *w, int revents) {
 
     while ((event = xcb_poll_for_event(conn)) != NULL) {
         if (event->response_type == 0) {
-            ELOG("X11 Error received! sequence %x\n", event->sequence);
+            if (event_is_ignored(event->sequence, 0))
+                DLOG("Expected X11 Error received for sequence %x\n", event->sequence);
+            else ELOG("X11 Error received! sequence %x\n", event->sequence);
             continue;
         }
 
index caf2967841751840519cf578dc6811fdf137853d..272276f467bd3a84b4fc8baa829e6eddc22dc2e3 100644 (file)
@@ -153,13 +153,23 @@ bool tree_close(Con *con, kill_window_t kill_window, bool dont_kill_parent) {
             x_window_kill(con->window->id, kill_window);
             return false;
         } else {
+            xcb_void_cookie_t cookie;
             /* un-parent the window */
-            xcb_reparent_window(conn, con->window->id, root, 0, 0);
+            cookie = xcb_reparent_window(conn, con->window->id, root, 0, 0);
+
+            /* Ignore X11 errors for the ReparentWindow request.
+             * X11 Errors are returned when the window was already destroyed */
+            add_ignore_event(cookie.sequence, 0);
+
             /* We are no longer handling this window, thus set WM_STATE to
              * WM_STATE_WITHDRAWN (see ICCCM 4.1.3.1) */
             long data[] = { XCB_ICCCM_WM_STATE_WITHDRAWN, XCB_NONE };
-            xcb_change_property(conn, XCB_PROP_MODE_REPLACE, con->window->id,
-                                A_WM_STATE, A_WM_STATE, 32, 2, data);
+            cookie = xcb_change_property(conn, XCB_PROP_MODE_REPLACE,
+                        con->window->id, A_WM_STATE, A_WM_STATE, 32, 2, data);
+
+            /* Ignore X11 errors for the ReparentWindow request.
+             * X11 Errors are returned when the window was already destroyed */
+            add_ignore_event(cookie.sequence, 0);
         }
         FREE(con->window->class_class);
         FREE(con->window->class_instance);
index 3fd0bfcde2f5d87cf62f421f56f0dfe5d2ac932a..07f3ce1e4036a2d16afaa2e9829e0c6dfd220520 100644 (file)
--- a/src/xcb.c
+++ b/src/xcb.c
@@ -328,7 +328,7 @@ void xcb_set_window_rect(xcb_connection_t *conn, xcb_window_t window, Rect r) {
                          XCB_CONFIG_WINDOW_HEIGHT,
                          &(r.x));
     /* ignore events which are generated because we configured a window */
-    add_ignore_event(cookie.sequence, 0);
+    add_ignore_event(cookie.sequence, -1);
 }
 
 /*