diff --git a/include/data.h b/include/data.h index 32a69307..96a57b29 100644 --- a/include/data.h +++ b/include/data.h @@ -129,6 +129,10 @@ struct Client { will reconfigure the client. */ bool force_reconfigure; + /* When reparenting a window, an unmap-notify is sent. As we delete windows when they’re + unmapped, we need to ignore that one. Therefore, this flag is set when reparenting. */ + bool awaiting_useless_unmap; + /* XCB contexts */ xcb_window_t frame; /* Our window: The frame around the client */ xcb_gcontext_t titlegc; /* The titlebar’s graphic context inside the frame */ diff --git a/src/handlers.c b/src/handlers.c index 793c88a9..01f5efef 100644 --- a/src/handlers.c +++ b/src/handlers.c @@ -299,32 +299,29 @@ int handle_map_notify_event(void *prophs, xcb_connection_t *conn, xcb_map_notify * */ int handle_unmap_notify_event(void *data, xcb_connection_t *c, xcb_unmap_notify_event_t *e) { - Client *client = table_remove(byChild, e->event); - xcb_window_t root; + xcb_window_t root = xcb_setup_roots_iterator(xcb_get_setup(c)).data->root; + + Client *client = table_get(byChild, e->window); + /* First, we need to check if the client is awaiting an unmap-request which + was generated by us reparenting the window. In that case, we just ignore it. */ + if (client != NULL && client->awaiting_useless_unmap) { + printf("Dropping this unmap request, it was generated by reparenting\n"); + client->awaiting_useless_unmap = false; + return 1; + } + client = table_remove(byChild, e->window); + printf("UnmapNotify for 0x%08x (received from 0x%08x): ", e->window, e->event); - if(!client) - { + if(client == NULL) { printf("not a managed window. Ignoring.\n"); return 0; } - int rows, cols; - Client *con_client; - /* TODO: clear this up */ - for (cols = 0; cols < c_ws->cols; cols++) - for (rows = 0; rows < c_ws->rows; rows++) - CIRCLEQ_FOREACH(con_client, &(CUR_TABLE[cols][rows]->clients), clients) - if (con_client == client) { - printf("removing from container\n"); - if (client->container->currently_focused == client) - client->container->currently_focused = NULL; - CIRCLEQ_REMOVE(&(CUR_TABLE[cols][rows]->clients), con_client, clients); - break; - } + if (client->container->currently_focused == client) + client->container->currently_focused = NULL; + CIRCLEQ_REMOVE(&(client->container->clients), client, clients); - - root = xcb_setup_roots_iterator(xcb_get_setup(c)).data->root; printf("child of 0x%08x.\n", client->frame); xcb_reparent_window(c, client->child, root, 0, 0); xcb_destroy_window(c, client->frame); diff --git a/src/mainx.c b/src/mainx.c index 8966c15b..92b9468f 100644 --- a/src/mainx.c +++ b/src/mainx.c @@ -49,9 +49,6 @@ Display *xkbdpy; TAILQ_HEAD(bindings_head, Binding) bindings; xcb_event_handlers_t evenths; -/* hm, xcb_wm wants us to implement this. */ -table_t *byChild = 0; -table_t *byParent = 0; xcb_window_t root_win; xcb_atom_t atoms[6]; @@ -194,15 +191,17 @@ void reparent_window(xcb_connection_t *conn, xcb_window_t child, table_put(byChild, child, new); /* Moves the original window into the new frame we've created for it */ - xcb_reparent_window(conn, child, new->frame, 0, font->height); + new->awaiting_useless_unmap = true; + cookie = xcb_reparent_window_checked(conn, child, new->frame, 0, font->height); + check_error(conn, cookie, "Could not reparent window"); /* We are interested in property changes */ mask = XCB_CW_EVENT_MASK; values[0] = XCB_EVENT_MASK_PROPERTY_CHANGE | XCB_EVENT_MASK_STRUCTURE_NOTIFY | - XCB_EVENT_MASK_ENTER_WINDOW | - XCB_EVENT_MASK_BUTTON_PRESS; - xcb_change_window_attributes(conn, child, mask, values); + XCB_EVENT_MASK_ENTER_WINDOW; + cookie = xcb_change_window_attributes_checked(conn, child, mask, values); + check_error(conn, cookie, "Could not change window attributes"); /* We need to grab the mouse buttons for click to focus */ xcb_grab_button(conn, false, child, XCB_EVENT_MASK_BUTTON_PRESS,