+
+/*
+ * Get depth of visual specified by visualid
+ *
+ */
+uint16_t get_visual_depth(xcb_visualid_t visual_id) {
+ xcb_depth_iterator_t depth_iter;
+
+ depth_iter = xcb_screen_allowed_depths_iterator(root_screen);
+ for (; depth_iter.rem; xcb_depth_next(&depth_iter)) {
+ xcb_visualtype_iterator_t visual_iter;
+
+ visual_iter = xcb_depth_visuals_iterator(depth_iter.data);
+ for (; visual_iter.rem; xcb_visualtype_next(&visual_iter)) {
+ if (visual_id == visual_iter.data->visual_id) {
+ return depth_iter.data->depth;
+ }
+ }
+ }
+ return 0;
+}
+
+/*
+ * Get visual type specified by visualid
+ *
+ */
+xcb_visualtype_t *get_visualtype_by_id(xcb_visualid_t visual_id) {
+ xcb_depth_iterator_t depth_iter;
+
+ depth_iter = xcb_screen_allowed_depths_iterator(root_screen);
+ for (; depth_iter.rem; xcb_depth_next(&depth_iter)) {
+ xcb_visualtype_iterator_t visual_iter;
+
+ visual_iter = xcb_depth_visuals_iterator(depth_iter.data);
+ for (; visual_iter.rem; xcb_visualtype_next(&visual_iter)) {
+ if (visual_id == visual_iter.data->visual_id) {
+ return visual_iter.data;
+ }
+ }
+ }
+ return 0;
+}
+
+/*
+ * Get visualid with specified depth
+ *
+ */
+xcb_visualid_t get_visualid_by_depth(uint16_t depth) {
+ xcb_depth_iterator_t depth_iter;
+
+ depth_iter = xcb_screen_allowed_depths_iterator(root_screen);
+ for (; depth_iter.rem; xcb_depth_next(&depth_iter)) {
+ if (depth_iter.data->depth != depth)
+ continue;
+
+ xcb_visualtype_iterator_t visual_iter;
+
+ visual_iter = xcb_depth_visuals_iterator(depth_iter.data);
+ if (!visual_iter.rem)
+ continue;
+ return visual_iter.data->visual_id;
+ }
+ return 0;
+}
+
+/*
+ * Add an atom to a list of atoms the given property defines.
+ * This is useful, for example, for manipulating _NET_WM_STATE.
+ *
+ */
+void xcb_add_property_atom(xcb_connection_t *conn, xcb_window_t window, xcb_atom_t property, xcb_atom_t atom) {
+ xcb_change_property(conn, XCB_PROP_MODE_APPEND, window, property, XCB_ATOM_ATOM, 32, 1, (uint32_t[]){atom});
+}
+
+/*
+ * Remove an atom from a list of atoms the given property defines without
+ * removing any other potentially set atoms. This is useful, for example, for
+ * manipulating _NET_WM_STATE.
+ *
+ */
+void xcb_remove_property_atom(xcb_connection_t *conn, xcb_window_t window, xcb_atom_t property, xcb_atom_t atom) {
+ xcb_grab_server(conn);
+
+ xcb_get_property_reply_t *reply =
+ xcb_get_property_reply(conn,
+ xcb_get_property(conn, false, window, property, XCB_GET_PROPERTY_TYPE_ANY, 0, 4096), NULL);
+ if (reply == NULL || xcb_get_property_value_length(reply) == 0)
+ goto release_grab;
+ xcb_atom_t *atoms = xcb_get_property_value(reply);
+ if (atoms == NULL) {
+ goto release_grab;
+ }
+
+ {
+ int num = 0;
+ const int current_size = xcb_get_property_value_length(reply) / (reply->format / 8);
+ xcb_atom_t values[current_size];
+ for (int i = 0; i < current_size; i++) {
+ if (atoms[i] != atom)
+ values[num++] = atoms[i];
+ }
+
+ xcb_change_property(conn, XCB_PROP_MODE_REPLACE, window, property, XCB_ATOM_ATOM, 32, num, values);
+ }
+
+release_grab:
+ FREE(reply);
+ xcb_ungrab_server(conn);
+}
+
+/*
+ * Grab the specified buttons on a window when managing it.
+ *
+ */
+void xcb_grab_buttons(xcb_connection_t *conn, xcb_window_t window, int *buttons) {
+ int i = 0;
+ while (buttons[i] > 0) {
+ xcb_grab_button(conn, false, window, XCB_EVENT_MASK_BUTTON_PRESS, XCB_GRAB_MODE_SYNC,
+ XCB_GRAB_MODE_ASYNC, root, XCB_NONE, buttons[i], XCB_BUTTON_MASK_ANY);
+
+ i++;
+ }
+}