From b645c4cf39925d3aaabe5cc52fe11495ca3853ec Mon Sep 17 00:00:00 2001 From: Zedhugh Chen Date: Mon, 25 Aug 2025 16:45:23 +0800 Subject: [PATCH] =?UTF-8?q?=E8=B0=83=E6=95=B4=E7=AA=97=E5=8F=A3=E5=A0=86?= =?UTF-8?q?=E5=8F=A0=E9=A1=BA=E5=BA=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/include/xcb.h | 13 +++++++++++++ src/main.c | 16 +++++++++++++++- src/xcb/window.c | 15 +++++++++++++++ src/xcb/xcb.c | 9 +++++++++ 4 files changed, 52 insertions(+), 1 deletion(-) diff --git a/src/include/xcb.h b/src/include/xcb.h index 5c6cd84..03a4b44 100644 --- a/src/include/xcb.h +++ b/src/include/xcb.h @@ -50,6 +50,14 @@ char *get_window_name(xcb_window_t window); void set_window_event_mask(xcb_window_t window, bool clear); void change_window_border_color(xcb_window_t window, uint32_t argb); void focus_window(xcb_window_t window); +/** + * @brief 将 window 置于堆叠顺序的顶部 + */ +void raise_window(xcb_window_t window); +/** + * @brief 在堆叠顺序中将 window 置于 sibling 之下 + */ +void place_window_below_sibling(xcb_window_t window, xcb_window_t sibling); typedef struct bar_cairo_params_t { xcb_connection_t *conn; @@ -122,3 +130,8 @@ void set_window_state(xcb_window_t window, wm_state_t state); void set_window_list(xcb_window_t *list, uint32_t length); bool get_pointer_position(int32_t *x, int32_t *y); + +/** + * @brief 非阻塞检查特定事件掩码(模拟 XCheckMaskEvent) + */ +bool xcb_check_mask_event(xcb_event_mask_t event_mask); diff --git a/src/main.c b/src/main.c index e8c02f8..6e6b1b3 100644 --- a/src/main.c +++ b/src/main.c @@ -829,7 +829,21 @@ void arrange(monitor_t *monitor) { void restack(monitor_t *monitor) { draw_monitor_bar(monitor); - /* TODO: */ + if (!monitor->selected_client) return; + if (monitor->selected_client->floating || !monitor->layout->arrange) { + raise_window(monitor->selected_client->window); + } + if (monitor->layout->arrange) { + xcb_window_t sibling = monitor->bar_window; + for (client_t *c = monitor->clients_stack; c; c = c->stack_next) { + if (!c->floating && CLIENT_VISIBLE(c)) { + place_window_below_sibling(c->window, sibling); + sibling = c->window; + } + } + } + flush_xcb_connection(); + while (xcb_check_mask_event(XCB_EVENT_MASK_ENTER_WINDOW)); } void focus(client_t *client) { if (!client || !CLIENT_VISIBLE(client)) { diff --git a/src/xcb/window.c b/src/xcb/window.c index b72c4b3..57e209a 100644 --- a/src/xcb/window.c +++ b/src/xcb/window.c @@ -300,3 +300,18 @@ void focus_window(xcb_window_t window) { send_event(window, atom_wm_take_focus); } } + +void raise_window(xcb_window_t window) { + xcb_params_configure_window_t params = {.stack_mode = XCB_STACK_MODE_TOP_IF}; + xcb_aux_configure_window(conn, window, XCB_CONFIG_WINDOW_STACK_MODE, ¶ms); + xcb_flush(conn); +} + +void place_window_below_sibling(xcb_window_t window, xcb_window_t sibling) { + uint16_t mask = XCB_CONFIG_WINDOW_STACK_MODE | XCB_CONFIG_WINDOW_SIBLING; + xcb_params_configure_window_t params = { + .stack_mode = XCB_STACK_MODE_BELOW, + .sibling = sibling, + }; + xcb_aux_configure_window(conn, window, mask, ¶ms); +} diff --git a/src/xcb/xcb.c b/src/xcb/xcb.c index 7913483..b3d16f4 100644 --- a/src/xcb/xcb.c +++ b/src/xcb/xcb.c @@ -331,3 +331,12 @@ bool get_pointer_position(int32_t *x, int32_t *y) { return false; } + +bool xcb_check_mask_event(xcb_event_mask_t event_mask) { + xcb_generic_event_t *event = xcb_poll_for_event(conn); + if (!event) return false; + + bool result = XCB_EVENT_RESPONSE_TYPE(event) == event_mask; + free(event); + return result; +}