From 47d578ca71bd96618524e791be28e96e452cc454 Mon Sep 17 00:00:00 2001 From: Zedhugh Chen Date: Sun, 25 Jan 2026 15:57:19 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=9E=E7=8E=B0=20wm=5Fscan=5Fclients=20?= =?UTF-8?q?=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/event.c | 9 ++------ src/wm.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++- src/xwindow.c | 34 +++++++++++++++++++++++++++ src/xwindow.h | 5 ++++ 4 files changed, 103 insertions(+), 8 deletions(-) diff --git a/src/event.c b/src/event.c index 20488fd..268c13a 100644 --- a/src/event.c +++ b/src/event.c @@ -2,7 +2,6 @@ #include #include -#include #include #include #include @@ -107,10 +106,8 @@ static void key_press(xcb_key_press_event_t *ev) { } static void map_request(xcb_map_request_event_t *ev) { - xcb_get_window_attributes_cookie_t wa_cookie = - xcb_get_window_attributes_unchecked(wm.xcb_conn, ev->window); xcb_get_window_attributes_reply_t *wa_reply = - xcb_get_window_attributes_reply(wm.xcb_conn, wa_cookie, nullptr); + xwindow_get_attributes_reply(ev->window); if (!wa_reply) return; if (wa_reply->override_redirect) { @@ -120,10 +117,8 @@ static void map_request(xcb_map_request_event_t *ev) { client_t *c = client_get_by_window(ev->window); if (!c) { - xcb_get_geometry_cookie_t geo_cookie = - xcb_get_geometry(wm.xcb_conn, ev->window); xcb_get_geometry_reply_t *geo_reply = - xcb_get_geometry_reply(wm.xcb_conn, geo_cookie, nullptr); + xwindow_get_geometry_reply(ev->window); if (!geo_reply) { p_delete(&wa_reply); return; diff --git a/src/wm.c b/src/wm.c index b326662..2ee8549 100644 --- a/src/wm.c +++ b/src/wm.c @@ -243,7 +243,67 @@ void wm_detect_monitor(void) { wm.current_monitor = monitor; } -void wm_scan_clients(void) {} +typedef struct window_list_t { + xcb_window_t *normal_list; + xcb_window_t *transient_list; + uint32_t normal_count; + uint32_t transient_count; +} window_list_t; +void wm_scan_clients(void) { + xcb_query_tree_cookie_t cookie = xcb_query_tree(wm.xcb_conn, wm.screen->root); + xcb_query_tree_reply_t *tree_reply = + xcb_query_tree_reply(wm.xcb_conn, cookie, nullptr); + if (!tree_reply) return; + + xcb_window_t *list = xcb_query_tree_children(tree_reply); + int len = xcb_query_tree_children_length(tree_reply); + if (!len) { + p_delete(&tree_reply); + return; + } + + xcb_get_window_attributes_reply_t *wa_reply = nullptr; + xcb_get_geometry_reply_t *geo_reply = nullptr; + for (int i = 0; i < len; i++) { + xcb_window_t window = list[i]; + wa_reply = xwindow_get_attributes_reply(window); + if (!wa_reply) continue; + + uint8_t override_redirect = wa_reply->override_redirect; + uint8_t map_state = wa_reply->map_state; + p_delete(&wa_reply); + + if (override_redirect || xwindow_get_transient_for(window)) continue; + + geo_reply = xwindow_get_geometry_reply(window); + if (!geo_reply) continue; + + if (map_state == XCB_MAP_STATE_VIEWABLE || + xwindow_get_state(window) == XCB_ICCCM_WM_STATE_ICONIC) { + client_manage(window, geo_reply); + } + p_delete(&geo_reply); + } + for (int i = 0; i < len; i++) { + xcb_window_t window = list[i]; + wa_reply = xwindow_get_attributes_reply(window); + if (!wa_reply) continue; + + uint8_t map_state = wa_reply->map_state; + p_delete(&wa_reply); + + geo_reply = xwindow_get_geometry_reply(window); + if (!geo_reply) continue; + + if (xwindow_get_transient_for(window) && + (map_state == XCB_MAP_STATE_VIEWABLE || + xwindow_get_state(window) == XCB_ICCCM_WM_STATE_ICONIC)) { + client_manage(window, geo_reply); + } + p_delete(&geo_reply); + } + p_delete(&tree_reply); +} void wm_clean(void) { text_clean_pango_layout(); @@ -483,6 +543,7 @@ int main(int argc, char *argv[]) { wm_detect_monitor(); wm_setup(); setup_event_loop(); + wm_scan_clients(); debug_show_monitor_list(); diff --git a/src/xwindow.c b/src/xwindow.c index 02a0f63..66f547f 100644 --- a/src/xwindow.c +++ b/src/xwindow.c @@ -205,3 +205,37 @@ void xwindow_get_text_property(xcb_window_t window, xcb_atom_t property, p_delete(&reply); } + +xcb_window_t xwindow_get_transient_for(xcb_window_t window) { + xcb_connection_t *conn = wm.xcb_conn; + xcb_window_t t_window = XCB_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, &t_window, nullptr); + return t_window; +} + +/** + * @brief 获取窗口的状态 + * @param window 目标窗口 + * @returns 成功返回 xcb_icccm_wm_state_t 枚举类型,失败返回 -1 + */ +int32_t xwindow_get_state(xcb_window_t window) { + xcb_connection_t *conn = wm.xcb_conn; + 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, nullptr)) return -1; + return hints.initial_state; +} + +xcb_get_geometry_reply_t *xwindow_get_geometry_reply(xcb_window_t window) { + xcb_get_geometry_cookie_t cookie = xcb_get_geometry(wm.xcb_conn, window); + return xcb_get_geometry_reply(wm.xcb_conn, cookie, nullptr); +} + +xcb_get_window_attributes_reply_t *xwindow_get_attributes_reply( + xcb_window_t window) { + xcb_get_window_attributes_cookie_t wa_cookie = + xcb_get_window_attributes(wm.xcb_conn, window); + return xcb_get_window_attributes_reply(wm.xcb_conn, wa_cookie, nullptr); +} diff --git a/src/xwindow.h b/src/xwindow.h index c65d931..cdf51a3 100644 --- a/src/xwindow.h +++ b/src/xwindow.h @@ -20,6 +20,11 @@ bool xwindow_send_event(xcb_window_t window, xcb_atom_t atom); void xwindow_focus(xcb_window_t window); void xwindow_get_text_property(xcb_window_t window, xcb_atom_t property, char **out); +xcb_window_t xwindow_get_transient_for(xcb_window_t window); +int32_t xwindow_get_state(xcb_window_t window); +xcb_get_geometry_reply_t *xwindow_get_geometry_reply(xcb_window_t window); +xcb_get_window_attributes_reply_t *xwindow_get_attributes_reply( + xcb_window_t window); #define xwindow_set_name_static(window, name) \ xcb_icccm_set_wm_name(wm.xcb_conn, window, XCB_ATOM_STRING, 8, \