-void reparent_window(xcb_connection_t *conn, xcb_window_t child,
- xcb_visualid_t visual, xcb_window_t root, uint8_t depth,
- int16_t x, int16_t y, uint16_t width, uint16_t height) {
-
- Client *new = table_get(byChild, child);
- if (new == NULL) {
- /* TODO: When does this happen for existing clients? Is that a bug? */
- printf("oh, it's new\n");
- new = calloc(sizeof(Client), 1);
- /* We initialize x and y with the invalid coordinates -1 so that they will
- get updated at the next render_layout() at any case */
- new->x = -1;
- new->y = -1;
- }
- uint32_t mask = 0;
- uint32_t values[3];
-
- /* Insert into the currently active container */
- CIRCLEQ_INSERT_TAIL(&(CUR_CELL->clients), new, clients);
-
- /* Update the data structures */
- CUR_CELL->currently_focused = new;
- new->container = CUR_CELL;
-
- new->frame = xcb_generate_id(conn);
- new->child = child;
- new->width = width;
- new->height = height;
-
- /* Don’t generate events for our new window, it should *not* be managed */
- mask |= XCB_CW_OVERRIDE_REDIRECT;
- values[0] = 1;
-
- /* We want to know when… */
- mask |= XCB_CW_EVENT_MASK;
- values[1] = XCB_EVENT_MASK_BUTTON_PRESS | /* …mouse is pressed/released */
- XCB_EVENT_MASK_BUTTON_RELEASE |
- XCB_EVENT_MASK_EXPOSURE | /* …our window needs to be redrawn */
- XCB_EVENT_MASK_ENTER_WINDOW; /* …user moves cursor inside our window */
-
- printf("Reparenting 0x%08x under 0x%08x.\n", child, new->frame);
-
- i3Font *font = load_font(conn, pattern);
-
- /* Yo dawg, I heard you like windows, so I create a window around your window… */
- xcb_void_cookie_t cookie = xcb_create_window_checked(conn,
- depth,
- new->frame,
- root,
- x,
- y,
- width + 2 + 2, /* 2 px border at each side */
- height + 2 + 2 + font->height, /* 2 px border plus font’s height */
- 0, /* border_width = 0, we draw our own borders */
- XCB_WINDOW_CLASS_INPUT_OUTPUT,
- XCB_WINDOW_CLASS_COPY_FROM_PARENT,
- mask,
- values);
- check_error(conn, cookie, "Could not create frame");
- xcb_change_save_set(conn, XCB_SET_MODE_INSERT, child);
-
- /* Map the window on the screen (= make it visible) */
- xcb_map_window(conn, new->frame);
-
- /* Generate a graphics context for the titlebar */
- new->titlegc = xcb_generate_id(conn);
- xcb_create_gc(conn, new->titlegc, new->frame, 0, 0);
-
- /* Put our data structure (Client) into the table */
- table_put(byParent, new->frame, new);
- 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);
-
- /* 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);
-
- /* We need to grab the mouse buttons for click to focus */
- xcb_grab_button(conn, false, child, XCB_EVENT_MASK_BUTTON_PRESS,
- XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC, root, XCB_NONE,
- 1 /* left mouse button */,
- XCB_BUTTON_MASK_ANY /* don’t filter for any modifiers */);
-
- /* Focus the new window */
- xcb_set_input_focus(conn, XCB_INPUT_FOCUS_NONE, new->child, XCB_CURRENT_TIME);
-
- render_layout(conn);
-}
-
-void manage_existing_windows(xcb_connection_t *c, xcb_property_handlers_t *prophs, xcb_window_t root) {
- xcb_query_tree_cookie_t wintree;
- xcb_query_tree_reply_t *rep;
- int i, len;
- xcb_window_t *children;
- xcb_get_window_attributes_cookie_t *cookies;
-
- wintree = xcb_query_tree(c, root);
- rep = xcb_query_tree_reply(c, wintree, 0);
- if(!rep)
- return;
- len = xcb_query_tree_children_length(rep);
- cookies = malloc(len * sizeof(*cookies));
- if(!cookies)
- {
- free(rep);
- return;
- }
- children = xcb_query_tree_children(rep);
- for(i = 0; i < len; ++i)
- cookies[i] = xcb_get_window_attributes(c, children[i]);
- for(i = 0; i < len; ++i)
- {
- window_attributes_t wa = { TAG_COOKIE, { cookies[i] } };
- manage_window(prophs, c, children[i], wa);
- }
- free(rep);