// x-run: make run #include "windowtree.h" #include #include #include #include #include struct window_info *get_windows_list(xcb_connection_t *conn, size_t *n_windows) { xcb_generic_error_t *err; xcb_screen_t *screen = xcb_setup_roots_iterator(xcb_get_setup(conn)).data; xcb_intern_atom_cookie_t ia_cookie = xcb_intern_atom(conn, 1, 16, "_NET_CLIENT_LIST"); xcb_intern_atom_reply_t *ia_reply = xcb_intern_atom_reply(conn, ia_cookie, &err); if (!ia_reply) { fprintf(stderr, "xcb: error: xcb_intern_atom_reply: %d\n", err->error_code); return NULL; } xcb_get_property_cookie_t gp_client_list_cookie = xcb_get_property(conn, 0, screen->root, ia_reply->atom, XCB_ATOM_WINDOW, 0, (uint32_t)~0UL); xcb_get_property_reply_t *gp_client_list_reply = xcb_get_property_reply(conn, gp_client_list_cookie, &err); if (!gp_client_list_reply) { fprintf(stderr, "xcb: error: xcb_get_property_reply: %d\n", err->error_code); return NULL; } *n_windows = xcb_get_property_value_length(gp_client_list_reply) / sizeof(xcb_window_t); struct window_info *windows = calloc(*n_windows, sizeof(struct window_info)); xcb_window_t *child = xcb_get_property_value(gp_client_list_reply); for (size_t i = 0; i < *n_windows; i++) { windows[i].wid = child[i]; } free(ia_reply); free(gp_client_list_reply); // Get atom: UTF8_STRING {{{ ia_cookie = xcb_intern_atom(conn, 1, 11, "UTF8_STRING"); ia_reply = xcb_intern_atom_reply(conn, ia_cookie, &err); if (!ia_reply) { fprintf(stderr, "xcb: error: xcb_intern_atom(UTF8_STRING): %d\n", err->error_code); return NULL; } xcb_atom_t atom_utf8_string = ia_reply->atom; free(ia_reply); // }}} // Get atom: _NET_WM_NAME {{{ ia_cookie = xcb_intern_atom(conn, 1, 12, "_NET_WM_NAME"); ia_reply = xcb_intern_atom_reply(conn, ia_cookie, &err); if (!ia_reply) { fprintf(stderr, "xcb: error: xcb_intern_atom(_NET_WM_NAME): %d\n", err->error_code); return NULL; } xcb_atom_t atom_net_wm_name = ia_reply->atom; free(ia_reply); // }}} for (size_t i = 0; i < *n_windows; i++) { // Getting geometry {{{ xcb_get_geometry_cookie_t gg_cookie = xcb_get_geometry(conn, windows[i].wid); xcb_get_geometry_reply_t *gg_reply = xcb_get_geometry_reply(conn, gg_cookie, &err); if (!gg_reply) { fprintf(stderr, "xcb: error: xcb_get_geometry: %d\n", err->error_code); return NULL; } windows[i].rect.x = gg_reply->x; windows[i].rect.y = gg_reply->y; windows[i].rect.width = gg_reply->width; windows[i].rect.height = gg_reply->height; free(gg_reply); // }}} // Translating geometry {{{ xcb_translate_coordinates_cookie_t tc_cookie = xcb_translate_coordinates(conn, windows[i].wid, screen->root, windows[i].rect.x, windows[i].rect.y); xcb_translate_coordinates_reply_t *tc_reply = xcb_translate_coordinates_reply(conn, tc_cookie, &err); if (!tc_reply) { fprintf(stderr, "xcb: error: xcb_translate_coordinates: %d\n", err->error_code); return NULL; } windows[i].rect.x = tc_reply->dst_x; windows[i].rect.y = tc_reply->dst_y; free(tc_reply); // }}} // Getting name: {{{ xcb_get_property_cookie_t gp_cookie = xcb_get_property(conn, 0, windows[i].wid, atom_net_wm_name, atom_utf8_string, 0, 1024); xcb_get_property_reply_t *gp_reply = xcb_get_property_reply(conn, gp_cookie, &err); if (!gp_reply) { fprintf(stderr, "xcb: error: xcb_get_property: %d\n", err->error_code); return NULL; } char *gp_value = (char *)xcb_get_property_value(gp_reply); memset(windows[i].title, 0, 1024); strncpy(windows[i].title, gp_value, 1023); free(gp_reply); // }}} } // }}} return windows; // ewww }