From 2e75dbf75e8a1ac0932e77d013050272a9930886 Mon Sep 17 00:00:00 2001 From: Zedhugh Chen Date: Sat, 23 Aug 2025 00:28:35 +0800 Subject: [PATCH] =?UTF-8?q?=E7=AA=97=E5=8F=A3=E6=B6=88=E5=A4=B1=E6=97=B6?= =?UTF-8?q?=E6=B8=85=E7=90=86=E5=AF=B9=E5=BA=94=E7=9A=84=20client?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/include/event-adapter.h | 1 + src/main.c | 47 +++++++++++++++++++++++++++++++++++++ src/xcb/event.c | 8 ++++--- src/xcb/window.c | 8 +++---- 4 files changed, 57 insertions(+), 7 deletions(-) diff --git a/src/include/event-adapter.h b/src/include/event-adapter.h index ae416bd..e7bf18c 100644 --- a/src/include/event-adapter.h +++ b/src/include/event-adapter.h @@ -58,6 +58,7 @@ typedef struct map_request_event_t { typedef struct unmap_notify_event_t { event_type_t type; + xcb_window_t window; } unmap_notify_event_t; typedef struct destroy_notify_event_t { diff --git a/src/main.c b/src/main.c index 5d104d4..e017729 100644 --- a/src/main.c +++ b/src/main.c @@ -37,10 +37,15 @@ static void xcb_event_handler(generic_event_t *event, void *user_data); static void key_press(key_press_event_t *event); static void configure_request(configure_request_event_t *event); static void map_request(map_request_event_t *event); +static void unmap_notify(unmap_notify_event_t *event); static void manage_window(xcb_window_t window); +static void unmanage_client(client_t *client); static void update_client_name(client_t *client); static void apply_rules(client_t *client); static void attach_client(client_t *client); +static void detach_client(client_t *client); +static void attach_stack_client(client_t *client); +static void detach_stack_client(client_t *client); static void show_hide_client(client_t *client); static void apply_monitor_layout(monitor_t *monitor); static client_t *get_client_of_window(xcb_window_t window); @@ -419,6 +424,7 @@ void xcb_event_handler(generic_event_t *event, void *user_data) { EVENT(EVENT_TYPE_KEY_PRESS, key_press); EVENT(EVENT_TYPE_CONFIGURE_REQUEST, configure_request); EVENT(EVENT_TYPE_MAP_REQUEST, map_request); + EVENT(EVENT_TYPE_UNMAP_NOTIFY, unmap_notify); #undef EVENT @@ -460,6 +466,13 @@ void map_request(map_request_event_t *event) { manage_window(event->window); } +void unmap_notify(unmap_notify_event_t *event) { + client_t *c = get_client_of_window(event->window); + if (c) { + unmanage_client(c); + } +} + void manage_window(xcb_window_t window) { window_geometry_t *geometry = get_window_geometry(window); client_t *c = ecalloc(1, sizeof(client_t)); @@ -487,6 +500,7 @@ void manage_window(xcb_window_t window) { } attach_client(c); + attach_stack_client(c); apply_monitor_layout(c->monitor); init_window_event_mask(window); change_window_border_color(window, color_set->border_color.argb); @@ -497,6 +511,16 @@ void manage_window(xcb_window_t window) { update_bars(); } +void unmanage_client(client_t *client) { + monitor_t *monitor = client->monitor; + + detach_client(client); + detach_stack_client(client); + free(client); + apply_monitor_layout(monitor); + flush_xcb_connection(); +} + void update_client_name(client_t *client) { char *name = get_window_name(client->window); strncpy(client->name, name, sizeof(client->name) - 1); @@ -555,6 +579,29 @@ void attach_client(client_t *client) { client->monitor->clients = client; } +void detach_client(client_t *client) { + client_t **c = &client->monitor->clients; + for (; *c && *c != client; c = &(*c)->next); + *c = client->next; +} + +void attach_stack_client(client_t *client) { + client->stack_next = client->monitor->clients_stack; + client->monitor->clients_stack = client; +} + +void detach_stack_client(client_t *client) { + client_t **tc = &client->monitor->clients_stack; + for (; *tc && *tc != client; tc = &(*tc)->stack_next); + *tc = client->stack_next; + + if (client == client->monitor->selected_client) { + client_t *t = client->monitor->clients_stack; + for (; t && !CLIENT_VISIBLE(t); t = t->stack_next); + client->monitor->selected_client = t; + } +} + void show_hide_client(client_t *client) { if (!client || CLIENT_VISIBLE(client)) return; client->x = client->monitor->monitor_x; diff --git a/src/xcb/event.c b/src/xcb/event.c index 67711b3..6bc5716 100644 --- a/src/xcb/event.c +++ b/src/xcb/event.c @@ -62,9 +62,11 @@ static void convert_event(xcb_generic_event_t *xcb_event, event->map_request.parent = ev->parent; break; } - case XCB_UNMAP_NOTIFY: - event->type = EVENT_TYPE_UNMAP_NOTIFY; - break; + case XCB_UNMAP_NOTIFY: { + xcb_unmap_notify_event_t *ev = (xcb_unmap_notify_event_t *)xcb_event; + event->unmap_notify.type = EVENT_TYPE_UNMAP_NOTIFY; + event->unmap_notify.window = ev->window; + } break; case XCB_DESTROY_NOTIFY: event->type = EVENT_TYPE_DESTROY_NOTIFY; break; diff --git a/src/xcb/window.c b/src/xcb/window.c index fa48802..00b76d8 100644 --- a/src/xcb/window.c +++ b/src/xcb/window.c @@ -248,19 +248,19 @@ void map_window(xcb_window_t window) { char *get_window_name(xcb_window_t window) { xcb_get_property_cookie_t cookie = xcb_ewmh_get_wm_name(ewmh, window); xcb_ewmh_get_utf8_strings_reply_t reply; - xcb_ewmh_get_wm_name_reply(ewmh, cookie, &reply, NULL); - if (reply.strings_len) { + if (xcb_ewmh_get_wm_name_reply(ewmh, cookie, &reply, NULL)) { char *name = ecalloc(reply.strings_len + 1, sizeof(char)); strncpy(name, reply.strings, reply.strings_len); + xcb_ewmh_get_utf8_strings_reply_wipe(&reply); return name; } cookie = xcb_icccm_get_wm_name(conn, window); xcb_icccm_get_text_property_reply_t prop; - xcb_icccm_get_wm_name_reply(conn, cookie, &prop, NULL); - if (prop.name_len) { + if (xcb_icccm_get_wm_name_reply(conn, cookie, &prop, NULL)) { char *name = ecalloc(prop.name_len + 1, sizeof(char)); strncpy(name, prop.name, prop.name_len); + xcb_icccm_get_text_property_reply_wipe(&prop); return name; }