窗口消失时清理对应的 client

This commit is contained in:
2025-08-23 00:28:35 +08:00
parent 69c69200d8
commit 2e75dbf75e
4 changed files with 57 additions and 7 deletions

View File

@@ -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 {

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;
}