支持窗口全屏操作

This commit is contained in:
2026-01-29 07:46:06 +08:00
parent a772d0f56f
commit a5ce85be78
7 changed files with 71 additions and 1 deletions

View File

@@ -81,3 +81,9 @@ void toggle_client_floating(const user_action_arg_t *arg) {
client_set_floating(wm.client_focused, !wm.client_focused->floating); client_set_floating(wm.client_focused, !wm.client_focused->floating);
} }
void toggle_client_fullscreen(const user_action_arg_t *arg) {
if (!wm.client_focused) return;
client_set_fullscreen(wm.client_focused, !wm.client_focused->fullscreen);
}

View File

@@ -56,3 +56,4 @@ void spawn(const user_action_arg_t *arg);
void quit(const user_action_arg_t *arg); void quit(const user_action_arg_t *arg);
void raise_or_run(const user_action_arg_t *arg); void raise_or_run(const user_action_arg_t *arg);
void toggle_client_floating(const user_action_arg_t *arg); void toggle_client_floating(const user_action_arg_t *arg);
void toggle_client_fullscreen(const user_action_arg_t *arg);

View File

@@ -14,4 +14,7 @@ _NET_CLIENT_LIST
_NET_WM_DESKTOP _NET_WM_DESKTOP
_NET_WM_NAME _NET_WM_NAME
_NET_WM_ICON_NAME _NET_WM_ICON_NAME
_NET_WM_STATE
_NET_WM_STATE_FULLSCREEN
_NET_SUPPORTED
_NET_SUPPORTING_WM_CHECK _NET_SUPPORTING_WM_CHECK

View File

@@ -1,9 +1,12 @@
#include "atoms.h" #include "atoms.h"
#include <stdint.h>
#include <string.h>
#include <xcb/xproto.h> #include <xcb/xproto.h>
#include "atoms-intern.h" #include "atoms-intern.h"
#include "utils.h" #include "utils.h"
#include "wm.h"
void atoms_init(xcb_connection_t *conn) { void atoms_init(xcb_connection_t *conn) {
xcb_intern_atom_cookie_t cookies[countof(ATOM_LIST)]; xcb_intern_atom_cookie_t cookies[countof(ATOM_LIST)];
@@ -12,12 +15,25 @@ void atoms_init(xcb_connection_t *conn) {
cookies[i] = xcb_intern_atom_unchecked(conn, false, atom.len, atom.name); cookies[i] = xcb_intern_atom_unchecked(conn, false, atom.len, atom.name);
} }
atom_item_t *atom = nullptr;
uint32_t supported_length = 0;
xcb_atom_t supported_list[countof(ATOM_LIST)] = {XCB_ATOM_NONE};
xcb_intern_atom_reply_t *reply = nullptr; xcb_intern_atom_reply_t *reply = nullptr;
for (int i = 0; i < countof(ATOM_LIST); i++) { for (int i = 0; i < countof(ATOM_LIST); i++) {
reply = xcb_intern_atom_reply(conn, cookies[i], nullptr); reply = xcb_intern_atom_reply(conn, cookies[i], nullptr);
if (reply) { if (reply) {
*ATOM_LIST[i].atom = reply->atom; atom = &ATOM_LIST[i];
*atom->atom = reply->atom;
p_delete(&reply); p_delete(&reply);
if (strstr(atom->name, "_NET_") == atom->name) {
supported_list[supported_length++] = *atom->atom;
} }
} }
} }
xcb_change_property(wm.xcb_conn, XCB_PROP_MODE_REPLACE, wm.screen->root,
_NET_SUPPORTED, XCB_ATOM_ATOM, 32, supported_length,
supported_list);
}

View File

@@ -362,6 +362,28 @@ void client_set_floating(client_t *client, bool floating) {
monitor_arrange(client->monitor); monitor_arrange(client->monitor);
} }
void client_set_fullscreen(client_t *client, bool fullscreen) {
if (client->fullscreen == fullscreen) return;
client->fullscreen = fullscreen;
if (fullscreen) {
xcb_change_property(wm.xcb_conn, XCB_PROP_MODE_REPLACE, client->window,
_NET_WM_STATE, XCB_ATOM_ATOM, 32, 1,
&_NET_WM_STATE_FULLSCREEN);
client->old_border_width = client->border_width;
client_change_border_width(client, 0);
client_apply_geometry(client, client->monitor->geometry);
client_stack_raise(client);
} else {
xcb_change_property(wm.xcb_conn, XCB_PROP_MODE_REPLACE, client->window,
_NET_WM_STATE, XCB_ATOM_ATOM, 32, 0, 0);
client_change_border_width(client, client->old_border_width);
client_apply_geometry(client, client->old_geometry);
monitor_arrange(client->monitor);
}
client_focus(client);
}
static void update_client_list(void) { static void update_client_list(void) {
xcb_connection_t *conn = wm.xcb_conn; xcb_connection_t *conn = wm.xcb_conn;
xcb_window_t root = wm.screen->root; xcb_window_t root = wm.screen->root;

View File

@@ -88,6 +88,7 @@ static const keyboard_t key_list[] = {
{modifier_super, XK_o, send_client_to_next_monitor, {0}}, {modifier_super, XK_o, send_client_to_next_monitor, {0}},
{modifier_super | modifier_control, XK_space, toggle_client_floating, {0}}, {modifier_super | modifier_control, XK_space, toggle_client_floating, {0}},
{modifier_super, XK_f, toggle_client_fullscreen, {0}},
}; };
static const layout_t layout_list[] = { static const layout_t layout_list[] = {

View File

@@ -144,6 +144,27 @@ static void client_message(xcb_client_message_event_t *ev) {
client_focus(c); client_focus(c);
return; return;
} }
} else if (ev->type == _NET_WM_STATE) {
/**
* _NET_WM_STATE 协议数据格式为
* data.data32 = {
* action, // 操作类型(添加/移除/切换)
* property1, // 第一个状态原子如_NET_WM_STATE_FULLSCREEN
* property2, // 第二个状态原子可选通常为0
* 0, // 预留字段固定为0
* 0 // 预留字段固定为0
* };
* action 值可能为
* _NET_WM_STATE_ADD1添加全屏状态窗口进入全屏模式
* _NET_WM_STATE_REMOVE0移除全屏状态窗口退出全屏模式
* _NET_WM_STATE_TOGGLE2切换全屏状态若当前全屏则退出反之进入
*/
if (ev->data.data32[1] == _NET_WM_STATE_FULLSCREEN ||
ev->data.data32[2] == _NET_WM_STATE_FULLSCREEN) {
bool fullscreen = ev->data.data32[0];
if (ev->data.data32[0] == 2) fullscreen = !c->fullscreen;
client_set_fullscreen(c, fullscreen);
}
} }
} }