处理焦点相关事件

This commit is contained in:
2025-08-24 08:46:17 +08:00
parent 25ef44e5f9
commit 7eea0ee2d3
12 changed files with 341 additions and 106 deletions

View File

@@ -40,6 +40,8 @@ static void configure_request(configure_request_event_t *event);
static void map_request(map_request_event_t *event);
static void unmap_notify(unmap_notify_event_t *event);
static void motion_notify(motion_notify_event_t *event);
static void enter_notify(enter_notify_event_t *event);
static void focus_in(focus_in_event_t *event);
static void manage_window(xcb_window_t window);
static void unmanage_client(client_t *client);
static void update_client_name(client_t *client);
@@ -56,6 +58,7 @@ static void focus(client_t *client);
static void unfocus(client_t *client, bool set_focus);
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 gboolean handle_xcb_event(GIOChannel *channel, GIOCondition condition,
gpointer userdata);
static void cleanup(void);
@@ -96,22 +99,22 @@ void select_tag(const user_action_arg_t *arg) {
/* 调试函数,开发完成后删除 */
static void print_monitor_list_info(monitor_t *monitor_list) {
printf("========================= monitor info =========================\n");
logger("========================= monitor info =========================\n");
for (monitor_t *m = monitor_list; m; m = m->next) {
printf("========== mon[%u]:\n", m->index);
printf("x: %d, y: %d, width: %u, height: %u\n", m->monitor_x, m->monitor_y,
logger("========== mon[%u]:\n", m->index);
logger("x: %d, y: %d, width: %u, height: %u\n", m->monitor_x, m->monitor_y,
m->monitor_width, m->monitor_height);
printf("mon[%u] tags: ", m->index);
logger("mon[%u] tags: ", m->index);
for (int i = 0; m->tags[i]; i++) {
printf("%s%s", i > 0 ? ", " : "", m->tags[i]);
logger("%s%s", i > 0 ? ", " : "", m->tags[i]);
}
printf("\n");
logger("\n");
}
printf("======================= monitor info end =======================\n");
logger("======================= monitor info end =======================\n");
}
static void print_color(const char *prompt, const color_t *color) {
const char *p = strlen(prompt) ? " " : "";
printf("%s%srgba: #%08x, argb: #%08x\n", prompt, p, color->rgba, color->argb);
logger("%s%srgba: #%08x, argb: #%08x\n", prompt, p, color->rgba, color->argb);
}
static void print_color_set(color_set_t *set) {
print_color("== bar bg:", &set->bar_bg);
@@ -128,54 +131,54 @@ static void print_color_set(color_set_t *set) {
}
static void print_wallpaper_config(wallpaper_config_t *config) {
if (!config) {
printf("no wallpaper\n");
logger("no wallpaper\n");
return;
}
printf("wallpaper count: %u\n", config->count);
logger("wallpaper count: %u\n", config->count);
for (uint32_t i = 0; i < config->count; i++) {
printf("wallpaper[%02u]: %s\n", i, config->path_list[i]);
logger("wallpaper[%02u]: %s\n", i, config->path_list[i]);
}
}
static void print_window_list(window_list_t *window_list) {
if (!window_list) {
printf("no window\n");
logger("no window\n");
return;
}
for (uint32_t i = 0; i < window_list->count; i++) {
printf("window[%u]: 0x%x\n", i, window_list->list[i]);
logger("window[%u]: 0x%x\n", i, window_list->list[i]);
}
}
static char *bool2string(bool b) { return b ? "true" : "false"; }
static void print_client(client_t *c) {
if (!c) return;
printf("======= client info ========\n");
printf("window: 0x%x, x: %d, y: %d, w: %u, h: %u, bw: %u\n", c->window, c->x,
logger("======= client info ========\n");
logger("window: 0x%x, x: %d, y: %d, w: %u, h: %u, bw: %u\n", c->window, c->x,
c->y, c->width, c->height, c->border_width);
printf("floating: %s, fullscreen: %s, maximize: %s\n",
logger("floating: %s, fullscreen: %s, maximize: %s\n",
bool2string(c->floating), bool2string(c->fullscreen),
bool2string(c->maximize));
printf("tags: %b, monitor selected tags: %b\n", c->tags,
logger("tags: %b, monitor selected tags: %b\n", c->tags,
c->monitor->selected_tags);
printf("name: %s\n", c->name);
printf("===== client info end ======\n");
logger("name: %s\n", c->name);
logger("===== client info end ======\n");
}
static void print_rule(const rule_t *r) {
printf("==================== rule ====================\n");
printf("class: %s, instance: %s, title: %s\n", r->class, r->instance,
logger("==================== rule ====================\n");
logger("class: %s, instance: %s, title: %s\n", r->class, r->instance,
r->title);
printf("floating: %s, maximize: %s, fullscreen: %s, switch to tag: %s\n",
logger("floating: %s, maximize: %s, fullscreen: %s, switch to tag: %s\n",
bool2string(r->action.floating), bool2string(r->action.maximize),
bool2string(r->action.fullscreen),
bool2string(r->action.switch_to_tag));
for (uint32_t i = 0; r->tag && r->tag[i].tags; i++) {
const rule_tag_t *t = &r->tag[i];
printf("monitor amount: %u, monitor index: %u, tags: %b\n",
logger("monitor amount: %u, monitor index: %u, tags: %b\n",
t->monitor_amount, t->monitor_index, t->tags);
}
printf("================== rule end ==================\n");
logger("================== rule end ==================\n");
}
/* 调试函数结束 */
@@ -279,7 +282,7 @@ void set_wallpaper_by_index(uint32_t index, wallpaper_config_t *config) {
set_wallpaper(wallpaper);
double end = get_time();
free(wallpaper);
printf("set wallpaper cost: %fs\n", end - start);
logger("set wallpaper cost: %fs\n", end - start);
}
free(screen_size);
@@ -413,7 +416,7 @@ void init_monitor_bar(void) {
m->cr = cr;
}
printf("font height: %u, bar height: %u\n", font_height, bar_height);
logger("font height: %u, bar height: %u\n", font_height, bar_height);
}
void get_xresource_config(void) {
@@ -424,7 +427,7 @@ void get_xresource_config(void) {
get_xresource_uint32("zswm.tag_x_padding", &tag_x_pad);
get_xresource_uint32("zswm.border_width", &border_px);
printf("dpi: %u, font family: %s, font size: %u\n", dpi, font_family,
logger("dpi: %u, font family: %s, font size: %u\n", dpi, font_family,
font_size);
clean_xresource();
}
@@ -460,6 +463,8 @@ void xcb_event_handler(generic_event_t *event, void *user_data) {
EVENT(EVENT_TYPE_MAP_REQUEST, map_request);
EVENT(EVENT_TYPE_UNMAP_NOTIFY, unmap_notify);
EVENT(EVENT_TYPE_MOTION_NOTIFY, motion_notify);
EVENT(EVENT_TYPE_ENTER_NOTIFY, enter_notify);
EVENT(EVENT_TYPE_FOCUS_IN, focus_in);
#undef EVENT
@@ -487,7 +492,7 @@ void configure_request(configure_request_event_t *event) {
} else {
configure_window(client->window, client->x, client->y, client->width,
client->height, client->border_width);
printf("configure request: %s\n", client->name);
logger("configure request: %s\n", client->name);
}
flush_xcb_connection();
@@ -509,6 +514,10 @@ void unmap_notify(unmap_notify_event_t *event) {
}
void motion_notify(motion_notify_event_t *event) {
logger("motion: window: 0x%x, root: 0x%x\n", event->window, event->root);
logger("x: %d, y: %d, root_x: %d, root_y: %d\n", event->x, event->y,
event->root_x, event->root_y);
logger("root window: 0x%x\n", get_root_window());
if (event->window != get_root_window()) return;
static monitor_t *mon = NULL;
@@ -521,6 +530,31 @@ void motion_notify(motion_notify_event_t *event) {
mon = m;
}
void enter_notify(enter_notify_event_t *event) {
if ((event->mode != notify_mode_normal ||
event->detail == notify_detail_inferior) &&
event->window != get_root_window()) {
return;
}
client_t *c = get_client_of_window(event->window);
monitor_t *m = c ? c->monitor : get_monitor_of_window(event->window);
if (m != current_monitor) {
unfocus(current_monitor->selected_client, true);
current_monitor = m;
} else if (!c || c == current_monitor->selected_client) {
return;
}
focus(c);
}
void focus_in(focus_in_event_t *event) {
if (current_monitor->selected_client &&
event->window != current_monitor->selected_client->window) {
focus_window(event->window);
send_event(event->window, atom_wm_take_focus);
}
}
void manage_window(xcb_window_t window) {
window_geometry_t *geometry = get_window_geometry(window);
client_t *c = ecalloc(1, sizeof(client_t));
@@ -533,8 +567,8 @@ void manage_window(xcb_window_t window) {
c->border_width = border_px;
update_client_name(c);
printf("== manage window: %u\n", window);
printf("== x: %d, y: %d, w: %u, h: %u, bw: %u\n", c->x, c->y, c->width,
logger("== manage window: %u\n", window);
logger("== x: %d, y: %d, w: %u, h: %u, bw: %u\n", c->x, c->y, c->width,
c->height, c->border_width);
xcb_window_t tw = get_transient_window_for(window);
@@ -551,9 +585,12 @@ void manage_window(xcb_window_t window) {
attach_stack_client(c);
init_window_event_mask(window);
change_window_border_color(window, color_set->border_color.argb);
if (c->monitor == current_monitor) {
unfocus(current_monitor->selected_client, false);
}
arrange(c->monitor);
map_window(window);
draw_all_monitor_bars();
focus(NULL);
}
void unmanage_client(client_t *client) {
@@ -626,7 +663,7 @@ void apply_rules(client_t *client) {
}
print_client(client);
printf("apply rules done\n");
logger("apply rules done\n");
}
uint32_t get_tags_mask_of_monitor(monitor_t *monitor) {
@@ -681,16 +718,33 @@ void restack(monitor_t *monitor) {
/* TODO: */
}
void focus(client_t *client) {
/* TODO: */
if (!client || !CLIENT_VISIBLE(client)) {
for (client = current_monitor->clients_stack;
client && !CLIENT_VISIBLE(client); client = client->stack_next);
}
if (current_monitor->selected_client &&
current_monitor->selected_client != client) {
unfocus(current_monitor->selected_client, false);
}
if (client) {
if (client->monitor != current_monitor) current_monitor = client->monitor;
detach_stack_client(client);
attach_stack_client(client);
change_window_border_color(client->window,
color_set->active_border_color.argb);
focus_window(client->window);
} else {
focus_window(WINDOW_NONE);
}
current_monitor->selected_client = client;
draw_all_monitor_bars();
}
void unfocus(client_t *client, bool set_focus) {
if (!client) return;
change_window_border_color(client->window, color_set->border_color.argb);
if (set_focus) {
/* TODO: */
}
if (set_focus) focus_window(WINDOW_NONE);
}
void show_hide_client(client_t *client) {
@@ -741,6 +795,22 @@ client_t *get_client_of_window(xcb_window_t window) {
return NULL;
}
monitor_t *get_monitor_of_window(xcb_window_t window) {
int32_t x, y;
if (window == get_root_window() && get_pointer_position(&x, &y)) {
return rect_to_monitor(monitors, x, y, 1, 1);
}
for (monitor_t *m = monitors; m; m = m->next) {
if (window == m->bar_window) return m;
}
client_t *c = get_client_of_window(window);
if (c) return c->monitor;
return current_monitor;
}
gboolean handle_xcb_event(GIOChannel *channel, GIOCondition condition,
gpointer userdata) {
if (condition & (G_IO_HUP | G_IO_ERR)) {