From 7413d7439ae341db8585d6344b571a6d6cf641c1 Mon Sep 17 00:00:00 2001 From: Zedhugh Chen Date: Mon, 27 Apr 2026 18:38:49 +0800 Subject: [PATCH] =?UTF-8?q?feat(layouts):=20=E5=AE=9E=E7=8E=B0=20fair/full?= =?UTF-8?q?screen/maximize=20=E5=86=85=E7=BD=AE=E5=B8=83=E5=B1=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/zdwm/config.h | 5 +-- include/zdwm/layout.h | 6 ++++ src/config/defaults.c | 37 +++++++++++++++------- src/config/runtime_config.c | 8 +++-- src/layouts/.clang-format | 1 + src/layouts/fair.c | 63 +++++++++++++++++++++++++++++++++++++ src/layouts/fair.h | 5 +++ src/layouts/fullscreen.c | 18 +++++++++++ src/layouts/fullscreen.h | 5 +++ src/layouts/maximize.c | 20 ++++++++++++ src/layouts/maximize.h | 5 +++ tests/config/CMakeLists.txt | 4 +++ tests/core/CMakeLists.txt | 3 ++ 13 files changed, 164 insertions(+), 16 deletions(-) create mode 120000 src/layouts/.clang-format create mode 100644 src/layouts/fair.c create mode 100644 src/layouts/fair.h create mode 100644 src/layouts/fullscreen.c create mode 100644 src/layouts/fullscreen.h create mode 100644 src/layouts/maximize.c create mode 100644 src/layouts/maximize.h diff --git a/include/zdwm/config.h b/include/zdwm/config.h index d495696..7bb8d50 100644 --- a/include/zdwm/config.h +++ b/include/zdwm/config.h @@ -18,8 +18,9 @@ extern "C" { typedef struct zdwm_config_builder_t zdwm_config_builder_t; typedef struct zdwm_builtin_layouts_t { - zdwm_layout_fn tile; - zdwm_layout_fn monocle; + zdwm_layout_fn fair; + zdwm_layout_fn fullscreen; + zdwm_layout_fn maximize; } zdwm_builtin_layouts_t; typedef struct zdwm_api_t { diff --git a/include/zdwm/layout.h b/include/zdwm/layout.h index 7368bde..ceeed56 100644 --- a/include/zdwm/layout.h +++ b/include/zdwm/layout.h @@ -14,6 +14,7 @@ extern "C" { typedef struct zdwm_layout_ctx_t { zdwm_workspace_id_t workspace_id; zdwm_window_id_t focused_window_id; + zdwm_rect_t output_geometry; zdwm_rect_t workarea; const zdwm_window_id_t *window_ids; size_t window_count; @@ -30,6 +31,11 @@ typedef struct zdwm_layout_result_t { size_t item_capacity; } zdwm_layout_result_t; +/** + * @brief 自动布局算法 + * + * @return out 有变化返回 true 否则返回 true + */ typedef bool (*zdwm_layout_fn)( const zdwm_layout_ctx_t *ctx, zdwm_layout_result_t *out diff --git a/src/config/defaults.c b/src/config/defaults.c index a8511cb..ae8d1ce 100644 --- a/src/config/defaults.c +++ b/src/config/defaults.c @@ -20,29 +20,42 @@ bool config_defaults_build( ) { if (!api || !builder || !outputs || output_count == 0) return false; - zdwm_layout_id_t tile_id = api->register_layout( + zdwm_layout_id_t fair_id = api->register_layout( builder, - "tile", + "fair", "[]=", - "builtin tile", - api->builtin_layouts.tile + "builtin fair", + api->builtin_layouts.fair ); - zdwm_layout_id_t monocle_id = api->register_layout( + zdwm_layout_id_t maximize_id = api->register_layout( builder, - "monocle", + "maximize", "[M]", - "builtin monocle", - api->builtin_layouts.monocle + "builtin maximize", + api->builtin_layouts.maximize + ); + zdwm_layout_id_t fullscreen_id = api->register_layout( + builder, + "fullscreen", + "[F]", + "builtin fullscreen", + api->builtin_layouts.fullscreen ); zdwm_layout_id_t floating_id = api->register_layout(builder, "floating", "><>", "floating", nullptr); - if (tile_id == ZDWM_LAYOUT_ID_INVALID || - monocle_id == ZDWM_LAYOUT_ID_INVALID || + if (fair_id == ZDWM_LAYOUT_ID_INVALID || + maximize_id == ZDWM_LAYOUT_ID_INVALID || + fullscreen_id == ZDWM_LAYOUT_ID_INVALID || floating_id == ZDWM_LAYOUT_ID_INVALID) { return false; } - zdwm_layout_id_t layout_ids[] = {tile_id, monocle_id, floating_id}; + zdwm_layout_id_t layout_ids[] = { + fair_id, + maximize_id, + fullscreen_id, + floating_id, + }; for (size_t i = 0; i < output_count; i++) { if (api->define_workspace( builder, @@ -50,7 +63,7 @@ bool config_defaults_build( "main", layout_ids, countof(layout_ids), - tile_id + fair_id ) == ZDWM_WORKSPACE_ID_INVALID) { return false; } diff --git a/src/config/runtime_config.c b/src/config/runtime_config.c index def7025..150cc1b 100644 --- a/src/config/runtime_config.c +++ b/src/config/runtime_config.c @@ -14,6 +14,9 @@ #include "core/runtime.h" #include "core/types.h" #include "core/wm_desc.h" +#include "layouts/fair.h" +#include "layouts/fullscreen.h" +#include "layouts/maximize.h" struct zdwm_config_builder_t { layout_registry_t layouts; @@ -216,8 +219,9 @@ static bool runtime_config_build( .abi_version = ZDWM_CONFIG_ABI_VERSION, .builtin_layouts = { - .tile = nullptr, - .monocle = nullptr, + .fair = fair, + .fullscreen = fullscreen, + .maximize = maximize, }, .register_layout = runtime_config_register_layout, .define_workspace = runtime_config_define_workspace, diff --git a/src/layouts/.clang-format b/src/layouts/.clang-format new file mode 120000 index 0000000..2d11237 --- /dev/null +++ b/src/layouts/.clang-format @@ -0,0 +1 @@ +../../.clang-format \ No newline at end of file diff --git a/src/layouts/fair.c b/src/layouts/fair.c new file mode 100644 index 0000000..b789775 --- /dev/null +++ b/src/layouts/fair.c @@ -0,0 +1,63 @@ +#include "layouts/fair.h" + +#include +#include +#include +#include + +bool fair(const zdwm_layout_ctx_t *ctx, zdwm_layout_result_t *out) { + auto windows = ctx->window_ids; + auto count = (int32_t)ctx->window_count; + if (!windows || !count) return false; + + zdwm_layout_result_reset(out); + + auto columns = (int32_t)floor(sqrt(count)); + if (columns * (columns + 1) <= count) ++columns; + + auto rows_in_other_cols = count / columns; + auto rows_in_main_col = count - (columns - 1) * rows_in_other_cols; + while (rows_in_main_col > rows_in_other_cols) { + ++rows_in_other_cols; + rows_in_main_col = count - (columns - 1) * rows_in_other_cols; + } + + auto workarea = &ctx->workarea; + auto width_avg = workarea->width / columns; + auto width_for_main_col = workarea->width - (columns - 1) * width_avg; + auto width_for_other_col = width_avg; + + int32_t row = 0, col = 0, row_count; + int32_t x = workarea->x, y = workarea->y; + for (int32_t i = 0; i < count; ++i) { + int32_t width; + + if (i < rows_in_main_col) { + row = i; + width = width_for_main_col; + row_count = rows_in_main_col; + } else { + width = width_for_other_col; + 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_col; + y = workarea->y; + } + } + + auto h_avg = workarea->height / row_count; + auto h_main = workarea->height - h_avg * (row_count - 1); + auto height = row == 0 ? h_main : h_avg; + zdwm_layout_item_t item = { + .window_id = windows[i], + .rect = {.x = x, .y = y, .width = width, .height = height} + }; + zdwm_layout_result_push(out, item); + + y += height; + } + + return true; +} diff --git a/src/layouts/fair.h b/src/layouts/fair.h new file mode 100644 index 0000000..21bdccf --- /dev/null +++ b/src/layouts/fair.h @@ -0,0 +1,5 @@ +#pragma once + +#include + +bool fair(const zdwm_layout_ctx_t *ctx, zdwm_layout_result_t *out); diff --git a/src/layouts/fullscreen.c b/src/layouts/fullscreen.c new file mode 100644 index 0000000..cf37324 --- /dev/null +++ b/src/layouts/fullscreen.c @@ -0,0 +1,18 @@ +#include "layouts/fullscreen.h" + +bool fullscreen(const zdwm_layout_ctx_t *ctx, zdwm_layout_result_t *out) { + auto windows = ctx->window_ids; + auto count = ctx->window_count; + if (!windows || !count) return false; + + zdwm_layout_result_reset(out); + for (size_t i = 0; i < count; ++i) { + zdwm_layout_item_t item = { + .window_id = windows[i], + .rect = ctx->output_geometry, + }; + zdwm_layout_result_push(out, item); + } + + return true; +} diff --git a/src/layouts/fullscreen.h b/src/layouts/fullscreen.h new file mode 100644 index 0000000..dbc37ce --- /dev/null +++ b/src/layouts/fullscreen.h @@ -0,0 +1,5 @@ +#pragma once + +#include + +bool fullscreen(const zdwm_layout_ctx_t *ctx, zdwm_layout_result_t *out); diff --git a/src/layouts/maximize.c b/src/layouts/maximize.c new file mode 100644 index 0000000..00653bd --- /dev/null +++ b/src/layouts/maximize.c @@ -0,0 +1,20 @@ +#include "layouts/maximize.h" + +#include + +bool maximize(const zdwm_layout_ctx_t *ctx, zdwm_layout_result_t *out) { + auto windows = ctx->window_ids; + auto count = ctx->window_count; + if (!windows || !count) return false; + + zdwm_layout_result_reset(out); + for (size_t i = 0; i < count; ++i) { + zdwm_layout_item_t item = { + .window_id = windows[i], + .rect = ctx->workarea, + }; + zdwm_layout_result_push(out, item); + } + + return true; +} diff --git a/src/layouts/maximize.h b/src/layouts/maximize.h new file mode 100644 index 0000000..a19b3f1 --- /dev/null +++ b/src/layouts/maximize.h @@ -0,0 +1,5 @@ +#pragma once + +#include + +bool maximize(const zdwm_layout_ctx_t *ctx, zdwm_layout_result_t *out); diff --git a/tests/config/CMakeLists.txt b/tests/config/CMakeLists.txt index 440ae08..0ac44ef 100644 --- a/tests/config/CMakeLists.txt +++ b/tests/config/CMakeLists.txt @@ -53,6 +53,9 @@ add_executable(${RUNTIME_CONFIG_TEST_APP_NAME} ${SOURCE_DIR}/core/runtime.c ${SOURCE_DIR}/core/state.c ${SOURCE_DIR}/core/window.c + ${SOURCE_DIR}/layouts/fair.c + ${SOURCE_DIR}/layouts/fullscreen.c + ${SOURCE_DIR}/layouts/maximize.c ) target_include_directories(${RUNTIME_CONFIG_TEST_APP_NAME} SYSTEM PRIVATE ${INCLUDE_DIR} @@ -63,6 +66,7 @@ target_include_directories(${RUNTIME_CONFIG_TEST_APP_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ) target_link_libraries(${RUNTIME_CONFIG_TEST_APP_NAME} + PRIVATE m PRIVATE ${deps_xkbcommon_MODULE_NAME} PRIVATE ${CMAKE_DL_LIBS} ) diff --git a/tests/core/CMakeLists.txt b/tests/core/CMakeLists.txt index a3a0c5d..904db84 100644 --- a/tests/core/CMakeLists.txt +++ b/tests/core/CMakeLists.txt @@ -22,6 +22,9 @@ add_executable(${TEST_APP_NAME} ${SOURCE_DIR}/core/runtime.c ${SOURCE_DIR}/core/state.c ${SOURCE_DIR}/core/window.c + ${SOURCE_DIR}/layouts/fair.c + ${SOURCE_DIR}/layouts/fullscreen.c + ${SOURCE_DIR}/layouts/maximize.c ) target_include_directories(${TEST_APP_NAME} SYSTEM