处理堆叠顺序

This commit is contained in:
2025-12-22 11:37:18 +08:00
parent dee16344ce
commit 6382afeb03
7 changed files with 68 additions and 0 deletions

View File

@@ -3,9 +3,28 @@
#include <glib.h> #include <glib.h>
#include <string.h> #include <string.h>
#include "client.h"
#include "monitor.h" #include "monitor.h"
#include "types.h"
#include "wm.h" #include "wm.h"
void focus_client_in_same_tag(const user_action_arg_t *arg) {
bool next = arg->b;
tag_t *tag = wm.current_monitor->selected_tag;
task_in_tag_t *task = nullptr;
if (next) {
task = client_get_next_task_in_tag(wm.client_focused, tag);
} else {
task = client_get_previous_task_in_tag(wm.client_focused, tag);
}
if (!task) return;
client_stack_raise(task->client);
client_focus(task->client);
}
void select_tag_of_current_monitor(const user_action_arg_t *arg) { void select_tag_of_current_monitor(const user_action_arg_t *arg) {
monitor_select_tag(wm.current_monitor, arg->ui); monitor_select_tag(wm.current_monitor, arg->ui);
} }

View File

@@ -48,6 +48,7 @@ typedef struct keyboard_t {
const user_action_arg_t arg; const user_action_arg_t arg;
} keyboard_t; } keyboard_t;
void focus_client_in_same_tag(const user_action_arg_t *arg);
void select_tag_of_current_monitor(const user_action_arg_t *arg); void select_tag_of_current_monitor(const user_action_arg_t *arg);
void spawn(const user_action_arg_t *arg); void spawn(const user_action_arg_t *arg);
void quit(const user_action_arg_t *arg); void quit(const user_action_arg_t *arg);

View File

@@ -58,6 +58,22 @@ task_in_tag_t *client_get_task_in_tag(client_t *client, tag_t *tag) {
return nullptr; return nullptr;
} }
task_in_tag_t *client_get_next_task_in_tag(client_t *client, tag_t *tag) {
if (!tag->task_list) return nullptr;
task_in_tag_t *task = tag->task_list;
for (; task && task->client != client; task = task->next);
return task && task->next ? task->next : tag->task_list;
}
task_in_tag_t *client_get_previous_task_in_tag(client_t *client, tag_t *tag) {
if (!tag->task_list) return nullptr;
task_in_tag_t *task = tag->task_list;
for (; task && task->next && task->next->client != client; task = task->next);
return task ? task : tag->task_list;
}
static void client_add_to_tag(client_t *client, tag_t *tag) { static void client_add_to_tag(client_t *client, tag_t *tag) {
if (client_get_task_in_tag(client, tag)) return; if (client_get_task_in_tag(client, tag)) return;
@@ -191,6 +207,7 @@ void client_manage(xcb_window_t window,
monitor_arrange(c->monitor); monitor_arrange(c->monitor);
monitor_draw_bar(c->monitor); monitor_draw_bar(c->monitor);
wm_restack_clients();
if (c->tags & c->monitor->selected_tag->mask) client_focus(c); if (c->tags & c->monitor->selected_tag->mask) client_focus(c);
xcb_flush(wm.xcb_conn); xcb_flush(wm.xcb_conn);
@@ -279,6 +296,7 @@ void client_unmanage(client_t *client) {
client_wipe(client); client_wipe(client);
wm_restack_clients();
monitor_deal_focus(m); monitor_deal_focus(m);
monitor_arrange(m); monitor_arrange(m);
monitor_draw_bar(m); monitor_draw_bar(m);
@@ -303,6 +321,12 @@ void client_focus(client_t *client) {
xwindow_focus(client ? client->window : XCB_WINDOW_NONE); xwindow_focus(client ? client->window : XCB_WINDOW_NONE);
} }
void client_stack_raise(client_t *client) {
client_detach_stack(client);
client_attach_stack(client);
wm_restack_clients();
}
bool client_is_visible(client_t *client) { bool client_is_visible(client_t *client) {
return client->tags & client->monitor->selected_tag->mask; return client->tags & client->monitor->selected_tag->mask;
} }

View File

@@ -7,6 +7,8 @@
client_t *client_get_by_window(xcb_window_t window); client_t *client_get_by_window(xcb_window_t window);
task_in_tag_t *client_get_task_in_tag(client_t *client, tag_t *tag); task_in_tag_t *client_get_task_in_tag(client_t *client, tag_t *tag);
task_in_tag_t *client_get_next_task_in_tag(client_t *client, tag_t *tag);
task_in_tag_t *client_get_previous_task_in_tag(client_t *client, tag_t *tag);
void client_manage(xcb_window_t window, void client_manage(xcb_window_t window,
xcb_get_geometry_reply_t *geometry_reply); xcb_get_geometry_reply_t *geometry_reply);
char **client_get_task_title(client_t *client); char **client_get_task_title(client_t *client);

View File

@@ -36,6 +36,8 @@ static const keyboard_t key_list[] = {
{modifier_alt, XK_p, spawn, {.ptr = launcher}}, {modifier_alt, XK_p, spawn, {.ptr = launcher}},
{modifier_alt, XK_q, quit, {.b = false}}, {modifier_alt, XK_q, quit, {.b = false}},
{modifier_alt, XK_r, quit, {.b = true}}, {modifier_alt, XK_r, quit, {.b = true}},
{modifier_alt | modifier_shift, XK_j, focus_client_in_same_tag, {.b = true}},
{modifier_alt | modifier_shift, XK_k, focus_client_in_same_tag, {.b = false}},
}; };
static const layout_t layout_list[] = { static const layout_t layout_list[] = {

View File

@@ -390,6 +390,25 @@ void wm_quit(void) {
} }
} }
void wm_restack_clients(void) {
xcb_window_t sibling_window = XCB_WINDOW_NONE;
for (client_t *c = wm.client_stack_list; c; c = c->stack_next) {
uint16_t mask = XCB_CONFIG_WINDOW_STACK_MODE;
xcb_params_configure_window_t params = {};
if (sibling_window == XCB_WINDOW_NONE) {
mask = XCB_CONFIG_WINDOW_STACK_MODE;
params.stack_mode = XCB_STACK_MODE_ABOVE;
} else {
mask = XCB_CONFIG_WINDOW_STACK_MODE | XCB_CONFIG_WINDOW_SIBLING;
params.stack_mode = XCB_STACK_MODE_BELOW;
params.sibling = sibling_window;
}
sibling_window = c->window;
xcb_aux_configure_window(wm.xcb_conn, c->window, mask, &params);
}
xcb_flush(wm.xcb_conn);
}
static void debug_show_monitor_list(void) { static void debug_show_monitor_list(void) {
logger("\n========================== monitors ==========================\n"); logger("\n========================== monitors ==========================\n");
for (monitor_t *m = wm.monitor_list; m; m = m->next) { for (monitor_t *m = wm.monitor_list; m; m = m->next) {

View File

@@ -51,3 +51,4 @@ extern wm_t wm;
void wm_restart(void); void wm_restart(void);
void wm_quit(void); void wm_quit(void);
void wm_restack_clients(void);