From 6f4690705ace33453a4a1730b3242ec8f333121d Mon Sep 17 00:00:00 2001 From: Zedhugh Chen Date: Thu, 29 Jan 2026 09:18:45 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=AD=A3=E6=B5=AE=E5=8A=A8=E7=AA=97?= =?UTF-8?q?=E5=8F=A3=E5=92=8C=E5=85=A8=E5=B1=8F=E7=AA=97=E5=8F=A3=E9=85=8D?= =?UTF-8?q?=E5=90=88=E8=A1=8C=E4=B8=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/atoms-list.txt | 2 ++ src/client.c | 58 +++++++++++++++++++++++++++++++++++++++++++++- src/client.h | 2 ++ src/monitor.c | 20 +++++++++++++--- src/types.h | 1 + 5 files changed, 79 insertions(+), 4 deletions(-) diff --git a/src/atoms-list.txt b/src/atoms-list.txt index d79c7ae..177f8b9 100644 --- a/src/atoms-list.txt +++ b/src/atoms-list.txt @@ -16,5 +16,7 @@ _NET_WM_NAME _NET_WM_ICON_NAME _NET_WM_STATE _NET_WM_STATE_FULLSCREEN +_NET_WM_WINDOW_TYPE +_NET_WM_WINDOW_TYPE_DIALOG _NET_SUPPORTED _NET_SUPPORTING_WM_CHECK diff --git a/src/client.c b/src/client.c index 916eddc..a71400d 100644 --- a/src/client.c +++ b/src/client.c @@ -234,6 +234,8 @@ void client_manage(xcb_window_t window, client_attach_list(c); client_attach_stack(c); + client_update_window_type(c); + client_update_size_hints(c); xcb_change_property(wm.xcb_conn, XCB_PROP_MODE_APPEND, wm.screen->root, _NET_CLIENT_LIST, XCB_ATOM_WINDOW, 32, 1, &window); @@ -257,7 +259,7 @@ char **client_get_task_title(client_t *client) { bool client_need_layout(client_t *client) { if (client->floating || client->fullscreen || client->maximize || - client->minimize) { + client->minimize || client->size_freeze) { return false; } return true; @@ -331,6 +333,35 @@ void client_change_border_width(client_t *client, uint16_t border_width) { logger("== client 0x%x border width: %u\n", client->window, border_width); } +void client_update_window_type(client_t *client) { + xcb_window_t window = client->window; + xcb_get_property_cookie_t state_cookie = xcb_get_property_unchecked( + wm.xcb_conn, false, window, _NET_WM_STATE, XCB_ATOM_ATOM, 0, 1); + xcb_get_property_cookie_t window_type_cookie = xcb_get_property_unchecked( + wm.xcb_conn, false, window, _NET_WM_WINDOW_TYPE, XCB_ATOM_ATOM, 0, 1); + xcb_get_property_reply_t *state_reply = + xcb_get_property_reply(wm.xcb_conn, state_cookie, nullptr); + xcb_get_property_reply_t *window_type_reply = + xcb_get_property_reply(wm.xcb_conn, window_type_cookie, nullptr); + + if (state_reply) { + xcb_atom_t state = *(xcb_atom_t *)xcb_get_property_value(state_reply); + if (state == _NET_WM_STATE_FULLSCREEN) { + client_set_fullscreen(client, true); + } + p_delete(&state_reply); + } + + if (window_type_reply) { + xcb_atom_t window_type = + *(xcb_atom_t *)xcb_get_property_value(window_type_reply); + if (window_type == _NET_WM_WINDOW_TYPE_DIALOG) { + client_set_floating(client, true); + } + p_delete(&window_type_reply); + } +} + void client_update_wm_hints(client_t *client) { xcb_get_property_cookie_t cookie = xcb_icccm_get_wm_hints(wm.xcb_conn, client->window); @@ -346,6 +377,30 @@ void client_update_wm_hints(client_t *client) { } } +void client_update_size_hints(client_t *client) { + xcb_connection_t *conn = wm.xcb_conn; + xcb_size_hints_t hints; + xcb_get_property_cookie_t cookie = + xcb_icccm_get_wm_normal_hints_unchecked(conn, client->window); + if (!xcb_icccm_get_wm_normal_hints_reply(conn, cookie, &hints, nullptr)) { + return; + } + + int32_t min_width = 0, min_height = 0, max_width = 0, max_height = 0; + if (hints.flags & XCB_ICCCM_SIZE_HINT_P_MIN_SIZE) { + min_width = hints.min_width; + min_height = hints.min_height; + } + if (hints.flags & XCB_ICCCM_SIZE_HINT_P_MAX_SIZE) { + max_width = hints.max_width; + max_height = hints.max_height; + } + if (min_width == max_width && min_height == max_height) { + client->size_freeze = true; + client_set_floating(client, true); + } +} + void client_set_floating(client_t *client, bool floating) { if (client->floating == floating || client->fullscreen) return; @@ -371,6 +426,7 @@ void client_set_fullscreen(client_t *client, bool fullscreen) { _NET_WM_STATE, XCB_ATOM_ATOM, 32, 1, &_NET_WM_STATE_FULLSCREEN); client->old_border_width = client->border_width; + if (client->floating) client->old_geometry = client->geometry; client_change_border_width(client, 0); client_apply_geometry(client, client->monitor->geometry); client_stack_raise(client); diff --git a/src/client.h b/src/client.h index 3147737..0223b90 100644 --- a/src/client.h +++ b/src/client.h @@ -23,7 +23,9 @@ void client_resize(client_t *client, uint16_t width, uint16_t height); void client_change_border_color(client_t *client, color_t *color); void client_change_border_width(client_t *client, uint16_t border_width); +void client_update_window_type(client_t *client); void client_update_wm_hints(client_t *client); +void client_update_size_hints(client_t *client); void client_set_floating(client_t *client, bool floating); void client_set_fullscreen(client_t *client, bool fullscreen); diff --git a/src/monitor.c b/src/monitor.c index 8fc60f5..9d21902 100644 --- a/src/monitor.c +++ b/src/monitor.c @@ -67,6 +67,17 @@ void monitor_deal_focus(monitor_t *monitor) { void monitor_select_tag(monitor_t *monitor, uint32_t tag_mask) { if (monitor->selected_tag->mask == tag_mask) return; + for (task_in_tag_t *task = monitor->selected_tag->task_list; task; + task = task->next) { + if (task->client->floating || task->client->size_freeze) { + task->geometry = task->client->geometry; + } + if (task->client->fullscreen || task->client->maximize || + task->client->minimize) { + task->geometry = task->client->old_geometry; + } + } + for (tag_t *tag = monitor->tag_list; tag; tag = tag->next) { if (tag->mask == tag_mask) { monitor->selected_tag = tag; @@ -274,10 +285,13 @@ void monitor_arrange(monitor_t *monitor) { task_in_tag_t *task = client_get_task_in_tag(c, tag); if (task) { - if (client_need_layout(c)) { - client_apply_geometry(c, task->geometry); + if (c->minimize) continue; + if (c->fullscreen) { + client_apply_geometry(c, c->monitor->geometry); + } else if (c->maximize) { + client_apply_geometry(c, c->monitor->workarea); } else { - client_apply_geometry(c, c->geometry); + client_apply_geometry(c, task->geometry); } } else { int16_t x = -client_width(c); diff --git a/src/types.h b/src/types.h index d2b9996..4e042d3 100644 --- a/src/types.h +++ b/src/types.h @@ -38,6 +38,7 @@ struct client_t { bool minimize; bool sticky; bool urgent; + bool size_freeze; /* 尺寸冻结窗口一定是浮动窗口 */ char *class, *instance; char *name, *icon_name, *net_name, *net_icon_name;