diff --git a/src/include/xcb.h b/src/include/xcb.h index 7c76e5c..c35de1e 100644 --- a/src/include/xcb.h +++ b/src/include/xcb.h @@ -84,8 +84,10 @@ rect_size_t *get_screen_size(void); void set_wallpaper(uint32_t *wallpaper_data); typedef struct window_list_t { - uint32_t count; - xcb_window_t *list; + xcb_window_t *normal_list; + xcb_window_t *transient_list; + uint32_t normal_count; + uint32_t transient_count; } window_list_t; window_list_t *scan_window_list(void); void free_window_list(window_list_t *window_list); @@ -103,5 +105,12 @@ typedef enum atom_t { atom_wm_take_focus, } atom_t; bool send_event(xcb_window_t window, atom_t atom); +typedef enum wm_state_t { + wm_state_withdrawn = 0, + wm_state_normal = 1, + wm_state_iconic = 3 +} wm_state_t; +int32_t get_window_state(xcb_window_t window); +void set_window_state(xcb_window_t window, wm_state_t state); bool get_pointer_position(int32_t *x, int32_t *y); diff --git a/src/main.c b/src/main.c index 49e9906..0d83a0c 100644 --- a/src/main.c +++ b/src/main.c @@ -146,8 +146,11 @@ static void print_window_list(window_list_t *window_list) { return; } - for (uint32_t i = 0; i < window_list->count; i++) { - logger("window[%u]: 0x%x\n", i, window_list->list[i]); + for (uint32_t i = 0; i < window_list->normal_count; i++) { + logger("normal window[%u]: 0x%x\n", i, window_list->normal_list[i]); + } + for (uint32_t i = 0; i < window_list->transient_count; i++) { + logger("transient window[%u]: 0x%x\n", i, window_list->transient_list[i]); } } static char *bool2string(bool b) { return b ? "true" : "false"; } @@ -877,6 +880,15 @@ int main(int argc, char *argv[]) { print_wallpaper_config(wallpaper_config); print_window_list(window_list); + if (window_list) { + for (uint32_t i = 0; i < window_list->normal_count; i++) { + manage_window(window_list->normal_list[i]); + } + for (uint32_t i = 0; i < window_list->transient_count; i++) { + manage_window(window_list->transient_list[i]); + } + } + free_window_list(window_list); grab_keybindings(keys, LENGTH(keys)); diff --git a/src/xcb/window.c b/src/xcb/window.c index 6d3a754..3c7906d 100644 --- a/src/xcb/window.c +++ b/src/xcb/window.c @@ -218,11 +218,14 @@ bool get_window_visible(xcb_window_t window) { } xcb_window_t get_transient_window_for(xcb_window_t window) { - xcb_window_t transient_for = XCB_NONE; + xcb_window_t transient_for = WINDOW_NONE; xcb_get_property_cookie_t cookie = xcb_icccm_get_wm_transient_for(conn, window); - xcb_icccm_get_wm_transient_for_reply(conn, cookie, &transient_for, NULL); - return transient_for; + if (xcb_icccm_get_wm_transient_for_reply(conn, cookie, &transient_for, + NULL)) { + return transient_for; + } + return WINDOW_NONE; } window_geometry_t *get_window_geometry(xcb_window_t window) { diff --git a/src/xcb/wm-extension.c b/src/xcb/wm-extension.c index f6f711c..1f1f260 100644 --- a/src/xcb/wm-extension.c +++ b/src/xcb/wm-extension.c @@ -125,3 +125,27 @@ bool send_event(xcb_window_t window, atom_t atom) { return exist; } + +int32_t get_window_state(xcb_window_t window) { + xcb_icccm_wm_hints_t hints; + xcb_get_property_cookie_t cookie = xcb_icccm_get_wm_hints(conn, window); + if (!xcb_icccm_get_wm_hints_reply(conn, cookie, &hints, NULL)) return -1; + return hints.initial_state; +} + +void set_window_state(xcb_window_t window, wm_state_t state) { + xcb_icccm_wm_hints_t hints; + xcb_icccm_wm_hints_set_none(&hints); + switch (state) { + case wm_state_withdrawn: + xcb_icccm_wm_hints_set_withdrawn(&hints); + break; + case wm_state_normal: + xcb_icccm_wm_hints_set_normal(&hints); + break; + case wm_state_iconic: + xcb_icccm_wm_hints_set_iconic(&hints); + break; + } + xcb_icccm_set_wm_hints(conn, window, &hints); +} diff --git a/src/xcb/xcb.c b/src/xcb/xcb.c index e380a47..7e65eb5 100644 --- a/src/xcb/xcb.c +++ b/src/xcb/xcb.c @@ -185,8 +185,9 @@ window_list_t *scan_window_list(void) { xcb_window_t *list = xcb_query_tree_children(tree_reply); int len = xcb_query_tree_children_length(tree_reply); - uint32_t count = 0; - xcb_window_t temp_window_array[len]; + uint32_t normal_count = 0, transient_count = 0; + xcb_window_t normal_window_array[len]; + xcb_window_t transient_window_array[len]; for (int i = 0; i < len; i++) { xcb_window_t window = list[i]; @@ -199,34 +200,47 @@ window_list_t *scan_window_list(void) { uint8_t override_redirect = attribute_reply->override_redirect; uint8_t map_state = attribute_reply->map_state; free(attribute_reply); - if (override_redirect || map_state != XCB_MAP_STATE_VIEWABLE) continue; + if (!(map_state == XCB_MAP_STATE_VIEWABLE || + get_window_state(window) == wm_state_iconic)) { + continue; + } - xcb_window_t transient_for = XCB_NONE; - xcb_get_property_cookie_t p_cookie = - xcb_icccm_get_wm_transient_for(conn, window); - xcb_icccm_get_wm_transient_for_reply(conn, p_cookie, &transient_for, NULL); - if (transient_for != XCB_NONE) continue; - - temp_window_array[count] = window; - count++; + xcb_window_t transient_for = get_transient_window_for(window); + if (transient_for) { + transient_window_array[transient_count++] = window; + } else if (!override_redirect) { + normal_window_array[normal_count++] = window; + } } free(tree_reply); - if (!count) return NULL; - - xcb_window_t *window_list = ecalloc(count, sizeof(xcb_window_t)); - for (uint32_t i = 0; i < count; i++) window_list[i] = temp_window_array[i]; + if ((!normal_count) && (!transient_count)) return NULL; window_list_t *r = ecalloc(1, sizeof(window_list_t)); - r->count = count; - r->list = window_list; + r->normal_count = normal_count; + r->transient_count = transient_count; + + if (normal_count) { + r->normal_list = ecalloc(normal_count, sizeof(xcb_window_t)); + for (uint32_t i = 0; i < normal_count; i++) { + r->normal_list[i] = normal_window_array[i]; + } + } + if (transient_count) { + r->transient_list = ecalloc(transient_count, sizeof(xcb_window_t)); + for (uint32_t i = 0; i < transient_count; i++) { + r->transient_list[i] = transient_window_array[i]; + } + } return r; } void free_window_list(window_list_t *window_list) { if (window_list == NULL) return; - free(window_list->list); + + if (window_list->normal_list) free(window_list->normal_list); + if (window_list->transient_list) free(window_list->transient_list); free(window_list); }