diff --git a/CMakeLists.txt b/CMakeLists.txt index 396cd13..5ee0ef9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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) diff --git a/src/client.c b/src/client.c index 365ce18..fe712d6 100644 --- a/src/client.c +++ b/src/client.c @@ -1,5 +1,6 @@ #include "client.h" +#include #include #include #include @@ -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, ¶ms); + 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, ¶ms); + 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; } diff --git a/src/client.h b/src/client.h index 5854e47..df3e8aa 100644 --- a/src/client.h +++ b/src/client.h @@ -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); diff --git a/src/default_config.h b/src/default_config.h index efbc072..0702e7e 100644 --- a/src/default_config.h +++ b/src/default_config.h @@ -4,6 +4,7 @@ #include #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}, }; diff --git a/src/layout.c b/src/layout.c new file mode 100644 index 0000000..5769caf --- /dev/null +++ b/src/layout.c @@ -0,0 +1,19 @@ +#include "layout.h" + +#include + +#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); +} diff --git a/src/layout.h b/src/layout.h new file mode 100644 index 0000000..bace03e --- /dev/null +++ b/src/layout.h @@ -0,0 +1,5 @@ +#pragma once + +#include "types.h" + +void monocle(tag_t *tag); diff --git a/src/monitor.c b/src/monitor.c index 1311357..e86488d 100644 --- a/src/monitor.c +++ b/src/monitor.c @@ -7,6 +7,7 @@ #include #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); +} diff --git a/src/monitor.h b/src/monitor.h index 31b6b01..74895da 100644 --- a/src/monitor.h +++ b/src/monitor.h @@ -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);