添加快捷键将窗口移动到其他 tag 和 monitor

This commit is contained in:
2025-08-30 18:47:44 +08:00
parent c5e2b4c081
commit ad1d413c62
5 changed files with 143 additions and 6 deletions

View File

@@ -70,9 +70,12 @@ static void apply_monitor_layout(monitor_t *monitor);
static client_t *get_client_of_window(xcb_window_t window);
static monitor_t *get_monitor_of_window(xcb_window_t window);
static monitor_t *get_monitor_by_direction(bool forward);
static void send_client_to_monitor(client_t *client, monitor_t *monitor);
static void set_client_tag_prop(client_t *client);
static bool apply_initial_client_tag(client_t *client);
static gboolean handle_xcb_event(GIOChannel *channel, GIOCondition condition,
gpointer userdata);
static void cleanup(void);
static void cleanup(bool will_restart);
static monitor_t *monitors = NULL;
static monitor_t *current_monitor = NULL;
@@ -194,6 +197,31 @@ void change_volume(const user_action_arg_t *arg) {
change_pulse_volume(arg->i);
}
void move_to_monitor(const user_action_arg_t *arg) {
if (!current_monitor->selected_client || !monitors->next) return;
bool forward = arg->b;
monitor_t *monitor = get_monitor_by_direction(forward);
send_client_to_monitor(current_monitor->selected_client, monitor);
}
void move_to_tag(const user_action_arg_t *arg) {
if (!current_monitor || !current_monitor->selected_client) return;
uint32_t tag_mask = 0;
for (uint32_t i = 0; i < g_strv_length(current_monitor->tags); i++) {
tag_mask |= 1 << i;
}
uint32_t target_tag = arg->ui & tag_mask;
if (!target_tag) return;
client_t *client = current_monitor->selected_client;
client->tags = target_tag;
set_client_tag_prop(client);
focus(NULL);
arrange(current_monitor);
}
/* 调试函数,开发完成后删除 */
static void print_monitor_list_info(monitor_t *monitor_list) {
logger("========================= monitor info =========================\n");
@@ -365,6 +393,9 @@ void init_wallpaper(void) {
}
wallpaper_cr = cr;
cairo_surface_destroy(surface);
cairo_set_source_rgba(cr, 0, 0, 0, 1);
cairo_paint(cr);
refresh_root_window();
wallpaper_config = parse_wallpaper_config();
if (!wallpaper_config) return;
@@ -805,11 +836,13 @@ void manage_window(xcb_window_t window) {
if (tw != WINDOW_NONE && (tc = get_client_of_window(tw))) {
c->monitor = tc->monitor;
c->tags = tc->tags;
} else {
} else if (!apply_initial_client_tag(c)) {
c->monitor = current_monitor;
apply_rules(c);
}
set_client_tag_prop(c);
set_window_event_mask(window, false);
change_window_border_color(window, color_set->border_color.argb);
@@ -915,8 +948,12 @@ void apply_rules(client_t *client) {
}
if (!client->tags) {
client->monitor = current_monitor;
client->tags = current_monitor->selected_tags;
client_tag_info_t client_info;
if (get_window_tag(client->window, &client_info)) {
} else {
client->monitor = current_monitor;
client->tags = current_monitor->selected_tags;
}
}
if (switch_to_tag) {
current_monitor = client->monitor;
@@ -972,6 +1009,7 @@ void arrange(monitor_t *monitor) {
apply_monitor_layout(monitor);
}
}
flush_xcb_connection();
}
void restack(monitor_t *monitor) {
@@ -1121,6 +1159,53 @@ monitor_t *get_monitor_by_direction(bool forward) {
return m;
}
void send_client_to_monitor(client_t *client, monitor_t *monitor) {
if (client->monitor == monitor) return;
unfocus(client, true);
detach_client(client);
detach_stack_client(client);
client->monitor = monitor;
client->tags = monitor->selected_tags;
attach_client(client);
attach_stack_client(client);
set_client_tag_prop(client);
focus(client);
arrange(NULL);
}
void set_client_tag_prop(client_t *client) {
client_tag_info_t info = {
.tags = client->tags,
.monitor_index = client->monitor->index,
};
set_window_tag(client->window, &info);
}
/**
* @brief 设置 client 的初始 tag 信息
* @returns 成功返回 true 否则返回 false
*/
bool apply_initial_client_tag(client_t *client) {
client_tag_info_t client_tag_info;
if (!get_window_tag(client->window, &client_tag_info)) return false;
for (monitor_t *m = monitors; m; m = m->next) {
if (client_tag_info.monitor_index == m->index) {
uint32_t tag_mask = 0;
for (uint32_t i = 0; i < g_strv_length(m->tags); i++) tag_mask |= 1 << i;
uint32_t target_tag = tag_mask & client_tag_info.tags;
if (target_tag) {
client->monitor = m;
client->tags = target_tag;
return true;
}
}
}
return false;
}
gboolean handle_xcb_event(GIOChannel *channel, GIOCondition condition,
gpointer userdata) {
if (condition & (G_IO_HUP | G_IO_ERR)) {
@@ -1132,7 +1217,7 @@ gboolean handle_xcb_event(GIOChannel *channel, GIOCondition condition,
return true;
}
void cleanup(void) {
void cleanup(bool will_restart) {
clean_status();
g_main_loop_unref(loop);
@@ -1142,6 +1227,7 @@ void cleanup(void) {
client_t *c = m->clients;
while (m) {
while (c) {
if (!will_restart) remove_window_tag(c->window);
client_t *tc = c->next;
unmanage_client(c, false);
c = tc;
@@ -1181,6 +1267,7 @@ int main(int argc, char *argv[]) {
loop = g_main_loop_new(NULL, FALSE);
logger("========================== ZSWM START ==========================\n");
setup_xcb();
init_monitors();
init_color_set();
@@ -1215,7 +1302,7 @@ int main(int argc, char *argv[]) {
g_main_loop_run(loop);
cleanup();
cleanup(need_restart);
if (need_restart) {
need_restart = false;