things/img/scrall/windowtree.c

120 lines
3.7 KiB
C

// x-run: make run
#include "windowtree.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <xcb/xcb.h>
#include <xcb/xproto.h>
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
}