+void check_support() {
+ long *data;
+ unsigned long i, num_items;
+
+ get_atom_longs(supported_atom, XA_ATOM, DefaultRootWindow(DADisplay), &data, &num_items);
+ for (i = 0; i < num_items; i++) {
+ if (data[i] == desktop_geometry_atom) desktop_geometry_supported = 1;
+ if (data[i] == current_desktop_atom) current_desktop_supported = 1;
+ if (data[i] == client_list_atom) client_list_supported = 1;
+ if (data[i] == active_window_atom) active_window_supported = 1;
+ if (data[i] == moveresize_window_atom) moveresize_supported = 1;
+ }
+
+ XFree(data);
+}
+
+void enumerate_clients(client_t ***clients, unsigned long *num_clients, unsigned long *active_desktop, unsigned long *active_window) {
+ Window root, qroot, qparent, child, *wins, client;
+ int x, y;
+ unsigned int width, height, border, depth;
+ unsigned int root_width, root_height;
+ long *data;
+ long *states;
+ unsigned long i, j, num_states;
+ long client_desktop;
+ int draw;
+
+ if (desktop_geometry_supported) {
+ get_atom_longs(desktop_geometry_atom, XA_CARDINAL, DefaultRootWindow(DADisplay), &states, &num_states);
+ root_width = states[0];
+ root_height = states[1];
+ XFree(states);
+ }
+ else {
+ root_width = DisplayWidth(DADisplay, DefaultScreen(DADisplay));
+ root_height = DisplayWidth(DADisplay, DefaultScreen(DADisplay));
+ }
+
+ *num_clients = 0;
+ *clients = 0;
+
+ if (! XGetWindowAttributes(DADisplay, DAWindow, &dockapp_attr)) return;
+ scale = (double) root_width / (double) dockapp_attr.width;
+ aspect = (double) root_height / (double) dockapp_attr.height;
+
+ *active_window = get_atom_long(active_window_atom, XA_WINDOW, dockapp_attr.root);
+ *active_desktop = get_atom_long(current_desktop_atom, XA_CARDINAL, DefaultRootWindow(DADisplay));
+
+ if (client_list_supported) {
+ get_atom_longs(client_list_atom, XA_WINDOW, dockapp_attr.root, &data, num_clients);
+ }
+ else {
+ XQueryTree(DADisplay, dockapp_attr.root, &qroot, &qparent, &wins, (unsigned int *) num_clients);
+ }
+
+ *clients = (client_t **) malloc(sizeof(client_t *) * *num_clients);
+ if (! *clients) {
+ fprintf(stderr, "Out of memory for clients!\n");
+ exit(111);
+ }
+
+ for (i = 0; i < *num_clients; i++) {
+ (*clients)[i] = (client_t *) malloc(sizeof(client_t));
+ if (! (*clients)[i]) {
+ fprintf(stderr, "Out of memory for client!\n");
+ exit(111);
+ }
+ (*clients)[i]->window = 0;
+
+ if (client_list_supported) client = data[i];
+ else client = XmuClientWindow(DADisplay, wins[i]);
+
+ /* Don't page the pager. */
+ if (client == DAWindow) continue;
+
+ /* Check the window is on our desktop (or all desktops). */
+ client_desktop = get_atom_long(client_desktop_atom, XA_CARDINAL, client);
+ if (desktop > -1) {
+ if (client_desktop != desktop && client_desktop != -1) continue;
+ }
+ else {
+ if (client_desktop != *active_desktop && client_desktop != -1) continue;
+ }
+
+ /* Try to get its dimensions. */
+ if (! XGetGeometry(DADisplay, client, &root, &x, &y, &width, &height, &border, &depth)) continue;
+ if (! XTranslateCoordinates(DADisplay, client, root, x, y, &x, &y, &child)) continue;
+
+ /* Make sure it isn't hidden or shaded. */
+ draw = 1;
+ get_atom_longs(client_state_atom, XA_ATOM, client, &states, &num_states);
+ for (j = 0; j < num_states; j++) {
+ if (states[j] == shaded_state) height = 3.0 * scale;
+ if (states[j] == skip_pager_state) draw = 0;
+ if (states[j] == hidden_state) draw = 0;
+ }
+ if (! draw) continue;
+
+ (*clients)[i]->window = client;
+
+ /* Scale it. */
+ (*clients)[i]->rect.x = (double) x / scale;
+ (*clients)[i]->rect.y = (double) y / aspect;
+ (*clients)[i]->rect.width = (double) width / scale;
+ (*clients)[i]->rect.height = (double) height / aspect;
+ }
+
+ if (client_list_supported) XFree(data);
+ else XFree(wins);
+}
+
+void destroy_clients(client_t ***clients, unsigned long num_clients) {
+ unsigned long i;
+
+ if (! *clients) return;
+
+ for (i = 0; i < num_clients; i++) if ((*clients)[i]) free((*clients)[i]);
+ free(*clients);
+}
+