From 0c029b7bfdf02a9cf57624faeb02925c936a46d2 Mon Sep 17 00:00:00 2001 From: Zedhugh Chen Date: Sun, 14 Dec 2025 22:09:51 +0800 Subject: [PATCH] =?UTF-8?q?=E8=B0=83=E6=95=B4=20client=20=E5=9D=90?= =?UTF-8?q?=E6=A0=87=E9=85=8D=E7=BD=AE=E6=B5=81=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/client.c | 73 ++++++++++++++++++++++++++++++++++++++++----------- src/client.h | 3 +++ src/event.c | 21 ++++++++++++++- src/monitor.c | 9 +------ 4 files changed, 82 insertions(+), 24 deletions(-) diff --git a/src/client.c b/src/client.c index 21f96b7..b401f0f 100644 --- a/src/client.c +++ b/src/client.c @@ -115,8 +115,24 @@ void client_manage(xcb_window_t window, client_t *c = p_new(client_t, 1); c->window = window; - client_attach_list(c); - client_attach_stack(c); + client_move_to(c, geometry_reply->x, geometry_reply->y); + client_resize(c, geometry_reply->width, geometry_reply->height); + client_change_border_width(c, geometry_reply->border_width); + + { + const xcb_params_cw_t params = { + .event_mask = XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_FOCUS_CHANGE | + XCB_EVENT_MASK_PROPERTY_CHANGE | + XCB_EVENT_MASK_STRUCTURE_NOTIFY | + XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY, + }; + xcb_aux_change_window_attributes(wm.xcb_conn, window, XCB_CW_EVENT_MASK, + ¶ms); + xcb_map_window(wm.xcb_conn, window); + } + client_update_names(c); + xwindow_get_text_property(c->window, WM_WINDOW_ROLE, &c->role); + client_update_wm_hints(c); { xcb_icccm_get_wm_class_reply_t prop; @@ -127,7 +143,6 @@ void client_manage(xcb_window_t window, c->instance = strdup(prop.instance_name); xcb_icccm_get_wm_class_reply_wipe(&prop); } - xwindow_get_text_property(c->window, WM_WINDOW_ROLE, &c->role); } { @@ -149,20 +164,12 @@ void client_manage(xcb_window_t window, client_tags_apply(c); } - monitor_arrange(c->monitor); - { - const xcb_params_cw_t params = { - .event_mask = XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_FOCUS_CHANGE | - XCB_EVENT_MASK_PROPERTY_CHANGE | - XCB_EVENT_MASK_STRUCTURE_NOTIFY, - }; - xcb_aux_change_window_attributes(wm.xcb_conn, window, XCB_CW_EVENT_MASK, - ¶ms); - xcb_map_window(wm.xcb_conn, window); - } + client_attach_list(c); + client_attach_stack(c); - client_update_names(c); + monitor_arrange(c->monitor); monitor_draw_bar(c->monitor); + xcb_flush(wm.xcb_conn); } @@ -204,6 +211,29 @@ void client_resize(client_t *client, uint16_t width, uint16_t height) { width, height); } +void client_change_border_width(client_t *client, uint16_t border_width) { + if (client->border_width == border_width) return; + uint16_t mask = XCB_CONFIG_WINDOW_BORDER_WIDTH; + const xcb_params_configure_window_t params = {.border_width = border_width}; + xcb_aux_configure_window(wm.xcb_conn, client->window, mask, ¶ms); + client->border_width = border_width; +} + +void client_update_wm_hints(client_t *client) { + xcb_get_property_cookie_t cookie = + xcb_icccm_get_wm_hints(wm.xcb_conn, client->window); + xcb_icccm_wm_hints_t hints; + if (xcb_icccm_get_wm_hints_reply(wm.xcb_conn, cookie, &hints, nullptr)) { + if (client == wm.client_focused && + (hints.flags & XCB_ICCCM_WM_HINT_X_URGENCY)) { + hints.flags &= ~XCB_ICCCM_WM_HINT_X_URGENCY; + xcb_icccm_set_wm_hints(wm.xcb_conn, client->window, &hints); + } else { + client->urgent = hints.flags & XCB_ICCCM_WM_HINT_X_URGENCY; + } + } +} + void client_unmanage(client_t *client) { monitor_t *m = client->monitor; @@ -221,6 +251,19 @@ void client_unmanage(client_t *client) { xcb_flush(wm.xcb_conn); } +void client_apply_task_geometry(client_t *client, task_in_tag_t *task) { + if (!client || !task || client != task->client) return; + + if (task->geometry.x != client->geometry.x || + task->geometry.y != client->geometry.y) { + client_move_to(client, task->geometry.x, task->geometry.y); + } + if (task->geometry.width != client->geometry.width || + task->geometry.height != client->geometry.height) { + client_resize(client, task->geometry.width, task->geometry.height); + } +} + bool client_is_visible(client_t *client) { return client->tags & client->monitor->selected_tag->mask; } diff --git a/src/client.h b/src/client.h index 73e37ee..2039d53 100644 --- a/src/client.h +++ b/src/client.h @@ -20,6 +20,8 @@ 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_wm_hints(client_t *client); + void client_set_floating(client_t *client, bool floating); void client_set_fullscreen(client_t *client, bool fullscreen); void client_set_maximize(client_t *client, bool maximize); @@ -43,6 +45,7 @@ void client_set_leader_window(client_t *client, xcb_window_t leader_window); void client_kill(client_t *client); void client_unmanage(client_t *client); +void client_apply_task_geometry(client_t *client, task_in_tag_t *task); void client_focus(client_t *client); void client_stack_raise(client_t *client); diff --git a/src/event.c b/src/event.c index 4f5d9a3..f05edbe 100644 --- a/src/event.c +++ b/src/event.c @@ -55,7 +55,23 @@ static void button_press(xcb_button_press_event_t *ev) { static void configure_request(xcb_configure_request_event_t *ev) { client_t *client = client_get_by_window(ev->window); - if (!client) { + if (client) { + if (ev->value_mask & XCB_CONFIG_WINDOW_BORDER_WIDTH) { + client_change_border_width(client, ev->border_width); + } else { + tag_t *tag = client->monitor->selected_tag; + task_in_tag_t *task = client_get_task_in_tag(client, tag); + if (!task || !(client->floating || !tag->layout->arrange)) return; + + if (ev->value_mask & XCB_CONFIG_WINDOW_X) task->geometry.x = ev->x; + if (ev->value_mask & XCB_CONFIG_WINDOW_Y) task->geometry.y = ev->y; + if (ev->value_mask & XCB_CONFIG_WINDOW_WIDTH) + task->geometry.width = ev->width; + if (ev->value_mask & XCB_CONFIG_WINDOW_HEIGHT) + task->geometry.height = ev->height; + client_apply_task_geometry(client, task); + } + } else { uint16_t value_mask = ev->value_mask; xcb_configure_window_value_list_t value_list = { .x = ev->x, @@ -136,6 +152,9 @@ static void property_notify(xcb_property_notify_event_t *ev) { } else if (ev->atom == _NET_WM_ICON_NAME) { xwindow_get_text_property(ev->window, ev->atom, &client->net_icon_name); monitor_draw_bar(client->monitor); + } else if (ev->atom == XCB_ATOM_WM_HINTS) { + client_update_wm_hints(client); + monitor_draw_bar(client->monitor); } } diff --git a/src/monitor.c b/src/monitor.c index 84a61d5..b22cbde 100644 --- a/src/monitor.c +++ b/src/monitor.c @@ -253,14 +253,7 @@ void monitor_arrange(monitor_t *monitor) { for (client_t *c = wm.client_list; c; c = c->next) { task_in_tag_t *task = client_get_task_in_tag(c, tag); if (task) { - if (task->geometry.x != c->geometry.x || - task->geometry.y != c->geometry.y) { - client_move_to(c, task->geometry.x, task->geometry.y); - } - if (task->geometry.width != c->geometry.width || - task->geometry.height != c->geometry.height) { - client_resize(c, task->geometry.width, task->geometry.height); - } + client_apply_task_geometry(c, task); } else { int16_t x = -c->geometry.width; int16_t y = -c->geometry.height;