添加 monocle 布局功能

This commit is contained in:
2025-12-09 00:41:41 +08:00
parent 5039ce457e
commit 489ae4bf2a
8 changed files with 95 additions and 1 deletions

View File

@@ -39,6 +39,7 @@ add_executable(${APP_NAME}
${SOURCE_DIR}/action.c
${SOURCE_DIR}/xkb.c
${SOURCE_DIR}/atoms.c
${SOURCE_DIR}/layout.c
)
find_package(PkgConfig REQUIRED)

View File

@@ -1,5 +1,6 @@
#include "client.h"
#include <stdint.h>
#include <string.h>
#include <xcb/xcb.h>
#include <xcb/xcb_aux.h>
@@ -48,6 +49,13 @@ static void client_detach_stack(client_t *client) {
}
}
task_in_tag_t *client_get_task_in_tag(client_t *client, tag_t *tag) {
for (task_in_tag_t *task = tag->task_list; task; task = task->next) {
if (task->client == client) return task;
}
return nullptr;
}
void client_manage(xcb_window_t window,
xcb_get_geometry_reply_t *geometry_reply) {
client_t *c = p_new(client_t, 1);
@@ -104,6 +112,36 @@ void client_manage(xcb_window_t window,
xcb_flush(wm.xcb_conn);
}
bool client_need_layout(client_t *client) {
if (client->floating || client->fullscreen || client->maximize ||
client->minimize) {
return false;
}
return true;
}
void client_move_to(client_t *client, int16_t x, int16_t y) {
client->geometry.x = x;
client->geometry.y = y;
uint16_t mask = XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y;
const xcb_params_configure_window_t params = {.x = x, .y = y};
xcb_aux_configure_window(wm.xcb_conn, client->window, mask, &params);
logger("== client 0x%x move to x: %d, y: %d\n", client->window, x, y);
}
void client_resize(client_t *client, uint16_t width, uint16_t height) {
client->geometry.width = width;
client->geometry.height = height;
uint16_t mask = XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT;
const xcb_params_configure_window_t params = {
.width = width,
.height = height,
};
xcb_aux_configure_window(wm.xcb_conn, client->window, mask, &params);
logger("== client 0x%x resize to width: %d, height: %d\n", client->window,
width, height);
}
bool client_is_visible(client_t *client) {
return client->tags & client->monitor->selected_tag->mask;
}

View File

@@ -6,8 +6,10 @@
#include "types.h"
client_t *client_get_by_window(xcb_window_t window);
task_in_tag_t *client_get_task_in_tag(client_t *client, tag_t *tag);
void client_manage(xcb_window_t window,
xcb_get_geometry_reply_t *geometry_reply);
bool client_need_layout(client_t *client);
void client_send_to_tag(client_t *client, uint32_t tag_mask);
void client_send_to_monitor(client_t *client, monitor_t *monitor);

View File

@@ -4,6 +4,7 @@
#include <stdint.h>
#include "action.h"
#include "layout.h"
#include "types.h"
static const char *const font_family = "monospace";
@@ -35,6 +36,6 @@ static const keyboard_t key_list[] = {
};
static const layout_t layout_list[] = {
{.symbol = "[M]", .arrange = nullptr},
{.symbol = "[M]", .arrange = monocle},
{.symbol = "><=", .arrange = nullptr},
};

19
src/layout.c Normal file
View File

@@ -0,0 +1,19 @@
#include "layout.h"
#include <stdint.h>
#include "client.h"
#include "types.h"
#include "utils.h"
void monocle(tag_t *tag) {
logger("== monocle tag: %s start ==\n", tag->name);
for (task_in_tag_t *task = tag->task_list; task; task = task->next) {
if (!client_need_layout(task->client)) continue;
task->geometry = task->client->monitor->workarea;
logger("== window 0x%x: x: %d, y: %d, width: %u, height: %u\n",
task->client->window, task->geometry.x, task->geometry.y,
task->geometry.width, task->geometry.height);
}
logger("== monocle tag: %s end ==\n", tag->name);
}

5
src/layout.h Normal file
View File

@@ -0,0 +1,5 @@
#pragma once
#include "types.h"
void monocle(tag_t *tag);

View File

@@ -7,6 +7,7 @@
#include <xcb/xcb_aux.h>
#include "base.h"
#include "client.h"
#include "color.h"
#include "text.h"
#include "types.h"
@@ -210,3 +211,29 @@ void monitor_draw_bar(monitor_t *monitor) {
monitor_draw_tags(monitor);
monitor_draw_layout_symbol(monitor);
}
void monitor_arrange(monitor_t *monitor) {
tag_t *tag = monitor->selected_tag;
if (tag->layout && tag->layout->arrange) tag->layout->arrange(tag);
for (client_t *c = wm.client_list; c; c = c->next) {
task_in_tag_t *task = client_get_task_in_tag(c, tag);
if (task) {
if (task->geometry.x != c->geometry.x ||
task->geometry.y != c->geometry.y) {
client_move_to(c, task->geometry.x, task->geometry.y);
}
if (task->geometry.width != c->geometry.width ||
task->geometry.height != c->geometry.height) {
client_resize(c, task->geometry.width, task->geometry.height);
}
} else {
int16_t x = -c->geometry.width;
int16_t y = -c->geometry.height;
if (x != c->geometry.x || y != c->geometry.y) {
client_move_to(c, x, y);
}
}
}
xcb_flush(wm.xcb_conn);
}

View File

@@ -10,3 +10,4 @@ void monitor_select_tag(monitor_t *monitor, uint32_t tag_mask);
void monitor_clean(monitor_t *monitor);
void monitor_init_bar(monitor_t *monitor);
void monitor_draw_bar(monitor_t *monitor);
void monitor_arrange(monitor_t *monitor);