Compare commits

...

4 Commits

Author SHA1 Message Date
1dbcf3e654 tile 布局 2026-01-06 04:28:33 +08:00
8fba9ee71f 处理切换 tag 后 client 的焦点 2026-01-05 22:18:57 +08:00
943ede70a0 实现 _NET_ACTIVE_WINDOW 消息协议 2026-01-05 22:04:27 +08:00
fac2a84d7f 更新 clang-format 配置 2026-01-02 18:24:56 +08:00
9 changed files with 115 additions and 2 deletions

View File

@@ -6,6 +6,11 @@ IndentWidth: 2
ConstructorInitializerIndentWidth: 2
ContinuationIndentWidth: 2
---
Language: C
DerivePointerAlignment: false
PointerAlignment: Right
---
Language: Cpp
DerivePointerAlignment: false
PointerAlignment: Right
---

View File

@@ -76,6 +76,7 @@ target_include_directories(${APP_NAME}
)
target_link_libraries(${APP_NAME}
PRIVATE m
PRIVATE ${deps_LIBRARIES}
)

View File

@@ -10,6 +10,7 @@ UTF8_STRING
COMPOUND_TEXT
_NET_ACTIVE_WINDOW
_NET_CLIENT_LIST
_NET_WM_NAME
_NET_WM_ICON_NAME
_NET_SUPPORTING_WM_CHECK

View File

@@ -204,6 +204,9 @@ void client_manage(xcb_window_t window,
client_attach_list(c);
client_attach_stack(c);
xcb_change_property(wm.xcb_conn, XCB_PROP_MODE_APPEND, wm.screen->root,
_NET_CLIENT_LIST, XCB_ATOM_WINDOW, 32, 1, &window);
monitor_arrange(c->monitor);
monitor_draw_bar(c->monitor);
@@ -284,6 +287,19 @@ void client_update_wm_hints(client_t *client) {
}
}
static void update_client_list(void) {
xcb_connection_t *conn = wm.xcb_conn;
xcb_window_t root = wm.screen->root;
xcb_atom_t atom = _NET_CLIENT_LIST;
uint8_t mode = XCB_PROP_MODE_PREPEND;
xcb_atom_t type = XCB_ATOM_WINDOW;
xcb_delete_property(conn, root, atom);
for (client_t *c = wm.client_list; c; c = c->next) {
xcb_change_property(conn, mode, root, atom, type, 32, 1, &c->window);
}
}
void client_unmanage(client_t *client) {
monitor_t *m = client->monitor;
@@ -296,6 +312,8 @@ void client_unmanage(client_t *client) {
client_wipe(client);
update_client_list();
wm_restack_clients();
monitor_deal_focus(m);
monitor_arrange(m);

View File

@@ -41,6 +41,7 @@ static const keyboard_t key_list[] = {
};
static const layout_t layout_list[] = {
{.symbol = "[]=", .arrange = tile},
{.symbol = "[M]", .arrange = monocle},
{.symbol = "><=", .arrange = nullptr},
};

View File

@@ -135,6 +135,22 @@ static void map_request(xcb_map_request_event_t *ev) {
p_delete(&wa_reply);
}
static void client_message(xcb_client_message_event_t *ev) {
client_t *c = client_get_by_window(ev->window);
if (c == nullptr) return;
if (ev->type == _NET_ACTIVE_WINDOW) {
for (tag_t *t = c->monitor->tag_list; t; t = t->next) {
if ((t->mask & c->tags) == 0) continue;
wm.current_monitor = c->monitor;
monitor_select_tag(c->monitor, t->mask);
client_focus(c);
return;
}
}
}
static void property_notify(xcb_property_notify_event_t *ev) {
client_t *client = client_get_by_window(ev->window);
if (client == nullptr) return;
@@ -185,6 +201,7 @@ static void handle_xcb_event(xcb_generic_event_t *event) {
EVENT(XCB_KEY_RELEASE, key_press);
EVENT(XCB_CONFIGURE_REQUEST, configure_request);
EVENT(XCB_MAP_REQUEST, map_request);
EVENT(XCB_CLIENT_MESSAGE, client_message);
EVENT(XCB_PROPERTY_NOTIFY, property_notify);
EVENT(XCB_UNMAP_NOTIFY, unmap_notify);
EVENT(XCB_DESTROY_NOTIFY, destroy_notify);

View File

@@ -1,5 +1,6 @@
#include "layout.h"
#include <math.h>
#include <stdint.h>
#include "base.h"
@@ -25,3 +26,68 @@ void monocle(tag_t *tag) {
}
logger("== monocle tag: %s end ==\n", tag->name);
}
void tile(tag_t *tag) {
logger("== tile tag: %s start ==\n", tag->name);
uint16_t amount = 0;
for (task_in_tag_t *task = tag->task_list; task; task = task->next) {
if (client_need_layout(task->client)) ++amount;
}
if (amount == 0) goto end;
uint16_t columns = (uint32_t)floor(sqrt(amount));
if (columns * (columns + 1) <= amount) ++columns;
uint32_t rows_in_other_cols = amount / columns;
uint32_t rows_in_main_col;
while ((rows_in_main_col = amount - (columns - 1) * rows_in_other_cols) >
rows_in_other_cols) {
++rows_in_other_cols;
}
area_t *workarea = &tag->task_list->client->monitor->workarea;
uint16_t width_avg = workarea->width / columns;
uint16_t width_for_main_col = workarea->width - (columns - 1) * width_avg;
uint16_t width_for_other_cols = width_avg;
uint16_t i = 0, row = 0, col = 0, row_count, width, height;
int16_t x = workarea->x, y = workarea->y;
for (task_in_tag_t *task = tag->task_list; task; task = task->next) {
if (!client_need_layout(task->client)) continue;
if (i < rows_in_main_col) {
row = i;
width = width_for_main_col;
row_count = rows_in_main_col;
} else {
width = width_for_other_cols;
row_count = rows_in_other_cols;
if (((i - rows_in_main_col) % row_count) == 0) {
col++;
row = 0;
x += col == 1 ? width_for_main_col : width_for_other_cols;
y = workarea->y;
}
}
uint16_t h_avg = workarea->height / row_count;
uint16_t h_main = workarea->height - h_avg * (row_count - 1);
height = row == 0 ? h_main : h_avg;
task->geometry.x = x;
task->geometry.y = y;
task->geometry.width = width - task->client->border_width * 2;
task->geometry.height = height - task->client->border_width * 2;
y += height;
++i;
logger(
"== window 0x%x: x: %d, y: %d, width: %u, height: %u, border width: %u\n",
task->client->window, task->geometry.x, task->geometry.y,
task->geometry.width, task->geometry.height, task->client->border_width);
}
end:
logger("== tile tag: %s end\n", tag->name);
}

View File

@@ -3,3 +3,4 @@
#include "types.h"
void monocle(tag_t *tag);
void tile(tag_t *tag);

View File

@@ -49,7 +49,10 @@ uint32_t monitor_initialize_tag(monitor_t *monitor, const char **tags,
}
void monitor_deal_focus(monitor_t *monitor) {
if (!monitor->selected_tag->task_list) return;
if (!monitor->selected_tag->task_list) {
client_focus(nullptr);
return;
}
client_t *client = nullptr;
for (client_t *c = wm.client_stack_list; c; c = c->stack_next) {
@@ -69,12 +72,12 @@ void monitor_select_tag(monitor_t *monitor, uint32_t tag_mask) {
monitor->selected_tag = tag;
monitor_arrange(monitor);
monitor_draw_bar(monitor);
xcb_flush(wm.xcb_conn);
break;
}
}
monitor_deal_focus(monitor);
xcb_flush(wm.xcb_conn);
}
static void tag_clean(tag_t *tag) {