]> git.sur5r.net Git - i3/i3/blobdiff - src/handlers.c
Bugfix: Only ignore EnterNotify events after UnmapNotifies from managed windows
[i3/i3] / src / handlers.c
index 7ef562e54f28e5e5e028aa556776b1d869ae3b72..09e9f11ed97a0a93ddbc324168f442043d17d6a8 100644 (file)
@@ -376,27 +376,33 @@ static int handle_configure_request(xcb_configure_request_event_t *event) {
             bsr.height -= deco_height;
         }
         Con *floatingcon = con->parent;
-        DLOG("Container is a floating leaf node, will do that.\n");
+
+        Rect newrect = floatingcon->rect;
+
         if (event->value_mask & XCB_CONFIG_WINDOW_X) {
-            floatingcon->rect.x = event->x + (-1) * bsr.x;
-            DLOG("proposed x = %d, new x is %d\n", event->x, floatingcon->rect.x);
+            newrect.x = event->x + (-1) * bsr.x;
+            DLOG("proposed x = %d, new x is %d\n", event->x, newrect.x);
         }
         if (event->value_mask & XCB_CONFIG_WINDOW_Y) {
-            floatingcon->rect.y = event->y + (-1) * bsr.y;
-            DLOG("proposed y = %d, new y is %d\n", event->y, floatingcon->rect.y);
+            newrect.y = event->y + (-1) * bsr.y;
+            DLOG("proposed y = %d, new y is %d\n", event->y, newrect.y);
         }
         if (event->value_mask & XCB_CONFIG_WINDOW_WIDTH) {
-            floatingcon->rect.width = event->width + (-1) * bsr.width;
-            floatingcon->rect.width += con->border_width * 2;
-            DLOG("proposed width = %d, new width is %d (x11 border %d)\n", event->width, floatingcon->rect.width, con->border_width);
+            newrect.width = event->width + (-1) * bsr.width;
+            newrect.width += con->border_width * 2;
+            DLOG("proposed width = %d, new width is %d (x11 border %d)\n",
+                 event->width, newrect.width, con->border_width);
         }
         if (event->value_mask & XCB_CONFIG_WINDOW_HEIGHT) {
-            floatingcon->rect.height = event->height + (-1) * bsr.height;
-            floatingcon->rect.height += con->border_width * 2;
-            DLOG("proposed height = %d, new height is %d (x11 border %d)\n", event->height, floatingcon->rect.height, con->border_width);
+            newrect.height = event->height + (-1) * bsr.height;
+            newrect.height += con->border_width * 2;
+            DLOG("proposed height = %d, new height is %d (x11 border %d)\n",
+                 event->height, newrect.height, con->border_width);
         }
-        floating_maybe_reassign_ws(floatingcon);
-        tree_render();
+
+        DLOG("Container is a floating leaf node, will do that.\n");
+        floating_reposition(floatingcon, newrect);
+        return 1;
     }
 
     /* Dock windows can be reconfigured in their height */
@@ -451,12 +457,7 @@ static int handle_screen_change(xcb_generic_event_t *e) {
  * now, so we better clean up before.
  *
  */
-static int handle_unmap_notify_event(xcb_unmap_notify_event_t *event) {
-    // XXX: this is commented out because in src/x.c we disable EnterNotify events
-    /* we need to ignore EnterNotify events which will be generated because a
-     * different window is visible now */
-    //add_ignore_event(event->sequence, XCB_ENTER_NOTIFY);
-
+static void handle_unmap_notify_event(xcb_unmap_notify_event_t *event) {
     DLOG("UnmapNotify for 0x%08x (received from 0x%08x), serial %d\n", event->window, event->event, event->sequence);
     Con *con = con_by_window_id(event->window);
     if (con == NULL) {
@@ -465,63 +466,40 @@ static int handle_unmap_notify_event(xcb_unmap_notify_event_t *event) {
         con = con_by_frame_id(event->window);
         if (con == NULL) {
             LOG("Not a managed window, ignoring UnmapNotify event\n");
-            return 1;
+            return;
         }
+
         if (con->ignore_unmap > 0)
             con->ignore_unmap--;
         DLOG("ignore_unmap = %d for frame of container %p\n", con->ignore_unmap, con);
-        return 1;
+        goto ignore_end;
     }
 
     if (con->ignore_unmap > 0) {
         DLOG("ignore_unmap = %d, dec\n", con->ignore_unmap);
         con->ignore_unmap--;
-        return 1;
+        goto ignore_end;
     }
 
     tree_close(con, DONT_KILL_WINDOW, false, false);
     tree_render();
     x_push_changes(croot);
-    return 1;
-
-#if 0
-        if (client == NULL) {
-                DLOG("not a managed window. Ignoring.\n");
-
-                /* This was most likely the destroyed frame of a client which is
-                 * currently being unmapped, so we add this sequence (again!) to
-                 * the ignore list (enter_notify events will get sent for both,
-                 * the child and its frame). */
-                add_ignore_event(event->sequence);
-
-                return 0;
-        }
-#endif
 
-
-#if 0
-        /* Let’s see how many clients there are left on the workspace to delete it if it’s empty */
-        bool workspace_empty = SLIST_EMPTY(&(client->workspace->focus_stack));
-        bool workspace_focused = (c_ws == client->workspace);
-        Client *to_focus = (!workspace_empty ? SLIST_FIRST(&(client->workspace->focus_stack)) : NULL);
-
-        /* If this workspace is currently visible, we don’t delete it */
-        if (workspace_is_visible(client->workspace))
-                workspace_empty = false;
-
-        if (workspace_empty) {
-                client->workspace->output = NULL;
-                ipc_send_event("workspace", I3_IPC_EVENT_WORKSPACE, "{\"change\":\"empty\"}");
-        }
-
-        /* Remove the urgency flag if set */
-        client->urgent = false;
-        workspace_update_urgent_flag(client->workspace);
-
-        render_layout(conn);
-#endif
-
-        return 1;
+ignore_end:
+    /* If the client (as opposed to i3) destroyed or unmapped a window, an
+     * EnterNotify event will follow (indistinguishable from an EnterNotify
+     * event caused by moving your mouse), causing i3 to set focus to whichever
+     * window is now visible.
+     *
+     * In a complex stacked or tabbed layout (take two v-split containers in a
+     * tabbed container), when the bottom window in tab2 is closed, the bottom
+     * window of tab1 is visible instead. X11 will thus send an EnterNotify
+     * event for the bottom window of tab1, while the focus should be set to
+     * the remaining window of tab2.
+     *
+     * Therefore, we ignore all EnterNotify events which have the same sequence
+     * as an UnmapNotify event. */
+    add_ignore_event(event->sequence, XCB_ENTER_NOTIFY);
 }
 
 /*
@@ -839,18 +817,16 @@ static bool handle_hints(void *data, xcb_connection_t *conn, uint8_t state, xcb_
 
     xcb_icccm_wm_hints_t hints;
 
-    if (reply != NULL) {
-        if (!xcb_icccm_get_wm_hints_from_reply(&hints, reply))
-            return false;
-    } else {
-        if (!xcb_icccm_get_wm_hints_reply(conn, xcb_icccm_get_wm_hints_unchecked(conn, con->window->id), &hints, NULL))
+    if (reply == NULL)
+        if (!(reply = xcb_get_property_reply(conn, xcb_icccm_get_wm_hints(conn, window), NULL)))
             return false;
-    }
+
+    if (!xcb_icccm_get_wm_hints_from_reply(&hints, reply))
+        return false;
 
     if (!con->urgent && focused == con) {
         DLOG("Ignoring urgency flag for current client\n");
-        FREE(reply);
-        return true;
+        goto end;
     }
 
     /* Update the flag on the client directly */
@@ -866,17 +842,10 @@ static bool handle_hints(void *data, xcb_connection_t *conn, uint8_t state, xcb_
 
     tree_render();
 
-#if 0
-    /* If the workspace this client is on is not visible, we need to redraw
-     * the workspace bar */
-    if (!workspace_is_visible(client->workspace)) {
-            Output *output = client->workspace->output;
-            render_workspace(conn, output, output->current_workspace);
-            xcb_flush(conn);
-    }
-#endif
-
-    FREE(reply);
+end:
+    if (con->window)
+        window_update_hints(con->window, reply);
+    else free(reply);
     return true;
 }