-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,
- uint32_t border_width) {
-
- xcb_get_property_cookie_t wm_type_cookie, strut_cookie, state_cookie,
- utf8_title_cookie, title_cookie,
- class_cookie, leader_cookie;
- uint32_t mask = 0;
- uint32_t values[3];
- uint16_t original_height = height;
- bool map_frame = true;
-
- /* We are interested in property changes */
- mask = XCB_CW_EVENT_MASK;
- values[0] = CHILD_EVENT_MASK;
- xcb_change_window_attributes(conn, child, mask, values);
-
- /* Place requests for properties ASAP */
- wm_type_cookie = xcb_get_any_property_unchecked(conn, false, child, atoms[_NET_WM_WINDOW_TYPE], UINT32_MAX);
- strut_cookie = xcb_get_any_property_unchecked(conn, false, child, atoms[_NET_WM_STRUT_PARTIAL], UINT32_MAX);
- state_cookie = xcb_get_any_property_unchecked(conn, false, child, atoms[_NET_WM_STATE], UINT32_MAX);
- utf8_title_cookie = xcb_get_any_property_unchecked(conn, false, child, atoms[_NET_WM_NAME], 128);
- leader_cookie = xcb_get_any_property_unchecked(conn, false, child, atoms[WM_CLIENT_LEADER], UINT32_MAX);
- title_cookie = xcb_get_any_property_unchecked(conn, false, child, WM_NAME, 128);
- class_cookie = xcb_get_any_property_unchecked(conn, false, child, WM_CLASS, 128);
-
- Client *new = table_get(&by_child, child);
-
- /* Events for already managed windows should already be filtered in manage_window() */
- assert(new == NULL);
-
- LOG("Reparenting window 0x%08x\n", child);
- LOG("x = %d, y = %d, width = %d, height = %d\n", x, y, width, height);
- new = calloc(sizeof(Client), 1);
- new->force_reconfigure = true;
-
- /* Update the data structures */
- Client *old_focused = CUR_CELL->currently_focused;
-
- new->container = CUR_CELL;
- new->workspace = new->container->workspace;
-
- /* Minimum useful size for managed windows is 75x50 (primarily affects floating) */
- width = max(width, 75);
- height = max(height, 50);
-
- new->frame = xcb_generate_id(conn);
- new->child = child;
- new->rect.width = width;
- new->rect.height = height;
- new->width_increment = 1;
- new->height_increment = 1;
- new->border_width = border_width;
- /* Pre-initialize the values for floating */
- new->floating_rect.x = -1;
- new->floating_rect.width = width;
- new->floating_rect.height = height;
-
- if (config.default_border != NULL)
- client_init_border(conn, new, config.default_border[1]);
-
- mask = 0;
-
- /* 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] = FRAME_EVENT_MASK;
-
- i3Font *font = load_font(conn, config.font);
- width = min(width, c_ws->rect.x + c_ws->rect.width);
- height = min(height, c_ws->rect.y + c_ws->rect.height);
-
- Rect framerect = {x, y,
- width + 2 + 2, /* 2 px border at each side */
- height + 2 + 2 + font->height}; /* 2 px border plus font’s height */
-
- /* Yo dawg, I heard you like windows, so I create a window around your window… */
- new->frame = create_window(conn, framerect, XCB_WINDOW_CLASS_INPUT_OUTPUT, XCB_CURSOR_LEFT_PTR, false, mask, values);
-
- /* Put the client inside the save set. Upon termination (whether killed or normal exit
- does not matter) of the window manager, these clients will be correctly reparented
- to their most closest living ancestor (= cleanup) */
- xcb_change_save_set(conn, XCB_SET_MODE_INSERT, child);
-
- /* Generate a graphics context for the titlebar */
- new->titlegc = xcb_generate_id(conn);
- xcb_create_gc(conn, new->titlegc, new->frame, 0, 0);
-
- /* Moves the original window into the new frame we've created for it */
- new->awaiting_useless_unmap = true;
- xcb_void_cookie_t cookie = xcb_reparent_window_checked(conn, child, new->frame, 0, font->height);
- if (xcb_request_check(conn, cookie) != NULL) {
- LOG("Could not reparent the window, aborting\n");
- xcb_destroy_window(conn, new->frame);
- free(new);
- return;
- }