处理 clientmessage 事件和全屏窗口
This commit is contained in:
63
src/main.c
63
src/main.c
@@ -47,6 +47,7 @@ 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 property_notify(property_notify_event_t *event);
|
||||
static void client_message(client_message_event_t *event);
|
||||
static void manage_window(xcb_window_t window);
|
||||
static void unmanage_client(client_t *client, bool destroyed);
|
||||
static void update_client_list(void);
|
||||
@@ -62,6 +63,7 @@ static void show_hide_client(client_t *client);
|
||||
static void restack(monitor_t *monitor);
|
||||
static void focus(client_t *client);
|
||||
static void unfocus(client_t *client, bool set_focus);
|
||||
static void set_client_fullscreen(client_t *client, bool fullscreen);
|
||||
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);
|
||||
@@ -516,6 +518,7 @@ void xcb_event_handler(generic_event_t *event, void *user_data) {
|
||||
EVENT(EVENT_TYPE_ENTER_NOTIFY, enter_notify);
|
||||
EVENT(EVENT_TYPE_FOCUS_IN, focus_in);
|
||||
EVENT(EVENT_TYPE_PROPERTY_NOTIFY, property_notify);
|
||||
EVENT(EVENT_TYPE_CLIENT_MESSAGE, client_message);
|
||||
|
||||
#undef EVENT
|
||||
|
||||
@@ -651,6 +654,35 @@ void property_notify(property_notify_event_t *event) {
|
||||
}
|
||||
}
|
||||
|
||||
void client_message(client_message_event_t *event) {
|
||||
client_t *c = get_client_of_window(event->window);
|
||||
if (!c) return;
|
||||
|
||||
/**
|
||||
* _NET_WM_STATE_FULLSCREEN 协议数据格式为
|
||||
* data.data32 = {
|
||||
* action, // 操作类型(添加/移除/切换)
|
||||
* property1, // 第一个状态原子(如_NET_WM_STATE_FULLSCREEN)
|
||||
* property2, // 第二个状态原子(可选,通常为0)
|
||||
* 0, // 预留字段(固定为0)
|
||||
* 0 // 预留字段(固定为0)
|
||||
* };
|
||||
* action 值可能为
|
||||
* _NET_WM_STATE_ADD(1):添加全屏状态,窗口进入全屏模式
|
||||
* _NET_WM_STATE_REMOVE(0):移除全屏状态,窗口退出全屏模式
|
||||
* _NET_WM_STATE_TOGGLE(2):切换全屏状态(若当前全屏则退出,反之进入)
|
||||
*/
|
||||
if (event->message_type == get_xcb_atom(atom_net_wm_state)) {
|
||||
uint32_t fullscreen_atom = get_xcb_atom(atom_net_wm_fullscreen);
|
||||
if (event->data.data32[1] == fullscreen_atom ||
|
||||
event->data.data32[2] == fullscreen_atom) {
|
||||
bool set_fullscreen = event->data.data32[0] == 1;
|
||||
bool toggle_to_fullscreen = event->data.data32[0] == 2 && !c->fullscreen;
|
||||
set_client_fullscreen(c, set_fullscreen || toggle_to_fullscreen);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void manage_window(xcb_window_t window) {
|
||||
window_geometry_t *geometry = get_window_geometry(window);
|
||||
client_t *c = ecalloc(1, sizeof(client_t));
|
||||
@@ -677,13 +709,18 @@ void manage_window(xcb_window_t window) {
|
||||
apply_rules(c);
|
||||
}
|
||||
|
||||
attach_client(c);
|
||||
attach_stack_client(c);
|
||||
set_window_event_mask(window, false);
|
||||
change_window_border_color(window, color_set->border_color.argb);
|
||||
|
||||
attach_client(c);
|
||||
attach_stack_client(c);
|
||||
update_client_list();
|
||||
set_window_state(window, wm_state_normal);
|
||||
|
||||
if (c->monitor == current_monitor) {
|
||||
unfocus(current_monitor->selected_client, false);
|
||||
}
|
||||
c->monitor->selected_client = c;
|
||||
arrange(c->monitor);
|
||||
map_window(window);
|
||||
focus(NULL);
|
||||
@@ -884,12 +921,32 @@ void unfocus(client_t *client, bool set_focus) {
|
||||
if (set_focus) focus_window(WINDOW_NONE);
|
||||
}
|
||||
|
||||
void set_client_fullscreen(client_t *client, bool fullscreen) {
|
||||
set_window_fullscreen_state(client->window, true);
|
||||
client->fullscreen = fullscreen;
|
||||
if (fullscreen) {
|
||||
fullscreen_client(client);
|
||||
configure_window(client->window, client->x, client->y, client->width,
|
||||
client->height, client->border_width);
|
||||
raise_window(client->window);
|
||||
} else {
|
||||
client->x = client->old_x;
|
||||
client->y = client->old_y;
|
||||
client->width = client->old_width;
|
||||
client->height = client->old_height;
|
||||
client->border_width = client->old_border_width;
|
||||
configure_window(client->window, client->x, client->y, client->width,
|
||||
client->height, client->border_width);
|
||||
arrange(client->monitor);
|
||||
}
|
||||
}
|
||||
|
||||
void show_hide_client(client_t *client) {
|
||||
if (!client) return;
|
||||
|
||||
if (CLIENT_VISIBLE(client)) {
|
||||
if (client->fullscreen) {
|
||||
fullscreen_client(client);
|
||||
set_client_fullscreen(client, true);
|
||||
} else if (client->maximize) {
|
||||
maximize_client(client);
|
||||
} else if (!client->monitor->layout->arrange || client->floating) {
|
||||
|
||||
Reference in New Issue
Block a user