Compare commits
2 Commits
10fa3740a8
...
8d838135d6
| Author | SHA1 | Date | |
|---|---|---|---|
|
8d838135d6
|
|||
|
7413d7439a
|
@@ -18,8 +18,9 @@ extern "C" {
|
|||||||
typedef struct zdwm_config_builder_t zdwm_config_builder_t;
|
typedef struct zdwm_config_builder_t zdwm_config_builder_t;
|
||||||
|
|
||||||
typedef struct zdwm_builtin_layouts_t {
|
typedef struct zdwm_builtin_layouts_t {
|
||||||
zdwm_layout_fn tile;
|
zdwm_layout_fn fair;
|
||||||
zdwm_layout_fn monocle;
|
zdwm_layout_fn fullscreen;
|
||||||
|
zdwm_layout_fn maximize;
|
||||||
} zdwm_builtin_layouts_t;
|
} zdwm_builtin_layouts_t;
|
||||||
|
|
||||||
typedef struct zdwm_api_t {
|
typedef struct zdwm_api_t {
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ extern "C" {
|
|||||||
typedef struct zdwm_layout_ctx_t {
|
typedef struct zdwm_layout_ctx_t {
|
||||||
zdwm_workspace_id_t workspace_id;
|
zdwm_workspace_id_t workspace_id;
|
||||||
zdwm_window_id_t focused_window_id;
|
zdwm_window_id_t focused_window_id;
|
||||||
|
zdwm_rect_t output_geometry;
|
||||||
zdwm_rect_t workarea;
|
zdwm_rect_t workarea;
|
||||||
const zdwm_window_id_t *window_ids;
|
const zdwm_window_id_t *window_ids;
|
||||||
size_t window_count;
|
size_t window_count;
|
||||||
@@ -30,6 +31,11 @@ typedef struct zdwm_layout_result_t {
|
|||||||
size_t item_capacity;
|
size_t item_capacity;
|
||||||
} zdwm_layout_result_t;
|
} zdwm_layout_result_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 自动布局算法
|
||||||
|
*
|
||||||
|
* @return out 有变化返回 true 否则返回 true
|
||||||
|
*/
|
||||||
typedef bool (*zdwm_layout_fn)(
|
typedef bool (*zdwm_layout_fn)(
|
||||||
const zdwm_layout_ctx_t *ctx,
|
const zdwm_layout_ctx_t *ctx,
|
||||||
zdwm_layout_result_t *out
|
zdwm_layout_result_t *out
|
||||||
|
|||||||
@@ -20,29 +20,42 @@ bool config_defaults_build(
|
|||||||
) {
|
) {
|
||||||
if (!api || !builder || !outputs || output_count == 0) return false;
|
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,
|
builder,
|
||||||
"tile",
|
"fair",
|
||||||
"[]=",
|
"[]=",
|
||||||
"builtin tile",
|
"builtin fair",
|
||||||
api->builtin_layouts.tile
|
api->builtin_layouts.fair
|
||||||
);
|
);
|
||||||
zdwm_layout_id_t monocle_id = api->register_layout(
|
zdwm_layout_id_t maximize_id = api->register_layout(
|
||||||
builder,
|
builder,
|
||||||
"monocle",
|
"maximize",
|
||||||
"[M]",
|
"[M]",
|
||||||
"builtin monocle",
|
"builtin maximize",
|
||||||
api->builtin_layouts.monocle
|
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 =
|
zdwm_layout_id_t floating_id =
|
||||||
api->register_layout(builder, "floating", "><>", "floating", nullptr);
|
api->register_layout(builder, "floating", "><>", "floating", nullptr);
|
||||||
if (tile_id == ZDWM_LAYOUT_ID_INVALID ||
|
if (fair_id == ZDWM_LAYOUT_ID_INVALID ||
|
||||||
monocle_id == ZDWM_LAYOUT_ID_INVALID ||
|
maximize_id == ZDWM_LAYOUT_ID_INVALID ||
|
||||||
|
fullscreen_id == ZDWM_LAYOUT_ID_INVALID ||
|
||||||
floating_id == ZDWM_LAYOUT_ID_INVALID) {
|
floating_id == ZDWM_LAYOUT_ID_INVALID) {
|
||||||
return false;
|
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++) {
|
for (size_t i = 0; i < output_count; i++) {
|
||||||
if (api->define_workspace(
|
if (api->define_workspace(
|
||||||
builder,
|
builder,
|
||||||
@@ -50,7 +63,7 @@ bool config_defaults_build(
|
|||||||
"main",
|
"main",
|
||||||
layout_ids,
|
layout_ids,
|
||||||
countof(layout_ids),
|
countof(layout_ids),
|
||||||
tile_id
|
fair_id
|
||||||
) == ZDWM_WORKSPACE_ID_INVALID) {
|
) == ZDWM_WORKSPACE_ID_INVALID) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,9 @@
|
|||||||
#include "core/runtime.h"
|
#include "core/runtime.h"
|
||||||
#include "core/types.h"
|
#include "core/types.h"
|
||||||
#include "core/wm_desc.h"
|
#include "core/wm_desc.h"
|
||||||
|
#include "layouts/fair.h"
|
||||||
|
#include "layouts/fullscreen.h"
|
||||||
|
#include "layouts/maximize.h"
|
||||||
|
|
||||||
struct zdwm_config_builder_t {
|
struct zdwm_config_builder_t {
|
||||||
layout_registry_t layouts;
|
layout_registry_t layouts;
|
||||||
@@ -216,8 +219,9 @@ static bool runtime_config_build(
|
|||||||
.abi_version = ZDWM_CONFIG_ABI_VERSION,
|
.abi_version = ZDWM_CONFIG_ABI_VERSION,
|
||||||
.builtin_layouts =
|
.builtin_layouts =
|
||||||
{
|
{
|
||||||
.tile = nullptr,
|
.fair = fair,
|
||||||
.monocle = nullptr,
|
.fullscreen = fullscreen,
|
||||||
|
.maximize = maximize,
|
||||||
},
|
},
|
||||||
.register_layout = runtime_config_register_layout,
|
.register_layout = runtime_config_register_layout,
|
||||||
.define_workspace = runtime_config_define_workspace,
|
.define_workspace = runtime_config_define_workspace,
|
||||||
|
|||||||
@@ -2,8 +2,10 @@
|
|||||||
|
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
#include <zdwm/layout.h>
|
||||||
|
|
||||||
#include "action.h"
|
#include "action.h"
|
||||||
|
#include "base/array.h"
|
||||||
#include "base/memory.h"
|
#include "base/memory.h"
|
||||||
#include "core/backend.h"
|
#include "core/backend.h"
|
||||||
#include "core/binding.h"
|
#include "core/binding.h"
|
||||||
@@ -15,6 +17,7 @@
|
|||||||
#include "core/rules.h"
|
#include "core/rules.h"
|
||||||
#include "core/state.h"
|
#include "core/state.h"
|
||||||
#include "core/types.h"
|
#include "core/types.h"
|
||||||
|
#include "core/window.h"
|
||||||
#include "core/wm_desc.h"
|
#include "core/wm_desc.h"
|
||||||
|
|
||||||
static bool runtime_workspace_desc_has_valid_layouts(
|
static bool runtime_workspace_desc_has_valid_layouts(
|
||||||
@@ -106,6 +109,7 @@ void runtime_shutdown(runtime_t *runtime) {
|
|||||||
layout_registry_cleanup(&runtime->layouts);
|
layout_registry_cleanup(&runtime->layouts);
|
||||||
rules_cleanup(&runtime->rules);
|
rules_cleanup(&runtime->rules);
|
||||||
state_cleanup(&runtime->state);
|
state_cleanup(&runtime->state);
|
||||||
|
layout_result_cleanup(&runtime->layout_result);
|
||||||
binding_table_destroy(runtime->binding_table);
|
binding_table_destroy(runtime->binding_table);
|
||||||
runtime->binding_table = nullptr;
|
runtime->binding_table = nullptr;
|
||||||
backend_destroy(runtime->backend);
|
backend_destroy(runtime->backend);
|
||||||
@@ -140,6 +144,98 @@ void runtime_setup(runtime_t *runtime) {
|
|||||||
plan_reset(plan);
|
plan_reset(plan);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const layout_result_t *runtime_layout_calc(runtime_t *runtime) {
|
||||||
|
auto plan = &runtime->plan;
|
||||||
|
if (!plan->need_relayout) return nullptr;
|
||||||
|
|
||||||
|
auto result = &runtime->layout_result;
|
||||||
|
zdwm_layout_result_reset(result);
|
||||||
|
|
||||||
|
auto state = &runtime->state;
|
||||||
|
for (size_t i = 0; i < state->output_count; ++i) {
|
||||||
|
auto output = state_output_at(state, i);
|
||||||
|
if (!output) continue;
|
||||||
|
|
||||||
|
auto workspace = state_workspace_get(state, output->current_workspace_id);
|
||||||
|
if (!workspace) continue;
|
||||||
|
|
||||||
|
auto layout_slot = layout_slot_get(&runtime->layouts, workspace->layout_id);
|
||||||
|
if (!layout_slot || !layout_slot->fn) continue;
|
||||||
|
|
||||||
|
size_t window_count = 0;
|
||||||
|
size_t window_list_capacity = 0;
|
||||||
|
window_id_t *window_ids = nullptr;
|
||||||
|
|
||||||
|
for (size_t j = 0; j < state_window_count(state); j++) {
|
||||||
|
auto window = state_window_at(state, j);
|
||||||
|
if (!window || window->workspace_id != workspace->id) continue;
|
||||||
|
if (!window_need_layout(window)) continue;
|
||||||
|
|
||||||
|
window_id_t *window_id_slot =
|
||||||
|
array_push(window_ids, window_count, window_list_capacity);
|
||||||
|
*window_id_slot = window->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (window_count) {
|
||||||
|
zdwm_layout_ctx_t ctx = {
|
||||||
|
.workspace_id = workspace->id,
|
||||||
|
.focused_window_id = workspace->focused_window_id,
|
||||||
|
.output_geometry = output->geometry,
|
||||||
|
.workarea = output->workarea,
|
||||||
|
.window_ids = window_ids,
|
||||||
|
.window_count = window_count,
|
||||||
|
};
|
||||||
|
layout_slot->fn(&ctx, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (window_ids) p_delete(&window_ids);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result->item_count ? result : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void runtime_arrange(runtime_t *runtime) {
|
||||||
|
auto result = runtime_layout_calc(runtime);
|
||||||
|
if (!result) return;
|
||||||
|
|
||||||
|
auto state = &runtime->state;
|
||||||
|
auto plan = &runtime->plan;
|
||||||
|
for (size_t i = 0; i < result->item_count; ++i) {
|
||||||
|
auto window_id = result->items[i].window_id;
|
||||||
|
auto window = state_window_get(state, window_id);
|
||||||
|
|
||||||
|
if (!window) continue;
|
||||||
|
|
||||||
|
auto rect = result->items[i].rect;
|
||||||
|
auto frame_rect = window->frame_rect;
|
||||||
|
|
||||||
|
if (frame_rect.x != rect.x || frame_rect.y != rect.y) {
|
||||||
|
effect_t move_window_effect = {
|
||||||
|
.type = ZDWM_EFFECT_MOVE_WINDOW,
|
||||||
|
.as.move = {
|
||||||
|
.window = window->id,
|
||||||
|
.left_top_point = {.x = rect.x, .y = rect.y}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
plan_push_effect(plan, &move_window_effect);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (frame_rect.width != rect.width || frame_rect.height != rect.height) {
|
||||||
|
effect_t resize_window_effect = {
|
||||||
|
.type = ZDWM_EFFECT_RESIZE_WINDOW,
|
||||||
|
.as.resize = {
|
||||||
|
.window = window_id,
|
||||||
|
.width = rect.width,
|
||||||
|
.height = rect.height,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
plan_push_effect(plan, &resize_window_effect);
|
||||||
|
}
|
||||||
|
|
||||||
|
state_window_set_frame_rect(state, window_id, rect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void runtime_run(runtime_t *runtime) {
|
void runtime_run(runtime_t *runtime) {
|
||||||
runtime->running = true;
|
runtime->running = true;
|
||||||
|
|
||||||
@@ -165,6 +261,7 @@ void runtime_run(runtime_t *runtime) {
|
|||||||
|
|
||||||
policy_route_event(&ctx, &event, command_buffer);
|
policy_route_event(&ctx, &event, command_buffer);
|
||||||
policy_apply_command(&ctx, command_buffer, plan);
|
policy_apply_command(&ctx, command_buffer, plan);
|
||||||
|
runtime_arrange(runtime);
|
||||||
if (plan->count) backend_apply_effect(backend, plan->effects, plan->count);
|
if (plan->count) backend_apply_effect(backend, plan->effects, plan->count);
|
||||||
|
|
||||||
event_cleanup(&event);
|
event_cleanup(&event);
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ typedef struct runtime_t {
|
|||||||
plan_t plan;
|
plan_t plan;
|
||||||
command_buffer_t command_buffer;
|
command_buffer_t command_buffer;
|
||||||
state_t state;
|
state_t state;
|
||||||
|
layout_result_t layout_result;
|
||||||
layout_registry_t layouts;
|
layout_registry_t layouts;
|
||||||
rules_t rules;
|
rules_t rules;
|
||||||
backend_t *backend;
|
backend_t *backend;
|
||||||
|
|||||||
1
src/layouts/.clang-format
Symbolic link
1
src/layouts/.clang-format
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../../.clang-format
|
||||||
61
src/layouts/fair.c
Normal file
61
src/layouts/fair.c
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
#include "layouts/fair.h"
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <zdwm/layout.h>
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
5
src/layouts/fair.h
Normal file
5
src/layouts/fair.h
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <zdwm/layout.h>
|
||||||
|
|
||||||
|
bool fair(const zdwm_layout_ctx_t *ctx, zdwm_layout_result_t *out);
|
||||||
17
src/layouts/fullscreen.c
Normal file
17
src/layouts/fullscreen.c
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
#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;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
5
src/layouts/fullscreen.h
Normal file
5
src/layouts/fullscreen.h
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <zdwm/layout.h>
|
||||||
|
|
||||||
|
bool fullscreen(const zdwm_layout_ctx_t *ctx, zdwm_layout_result_t *out);
|
||||||
19
src/layouts/maximize.c
Normal file
19
src/layouts/maximize.c
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
#include "layouts/maximize.h"
|
||||||
|
|
||||||
|
#include <zdwm/layout.h>
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
5
src/layouts/maximize.h
Normal file
5
src/layouts/maximize.h
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <zdwm/layout.h>
|
||||||
|
|
||||||
|
bool maximize(const zdwm_layout_ctx_t *ctx, zdwm_layout_result_t *out);
|
||||||
@@ -53,6 +53,9 @@ add_executable(${RUNTIME_CONFIG_TEST_APP_NAME}
|
|||||||
${SOURCE_DIR}/core/runtime.c
|
${SOURCE_DIR}/core/runtime.c
|
||||||
${SOURCE_DIR}/core/state.c
|
${SOURCE_DIR}/core/state.c
|
||||||
${SOURCE_DIR}/core/window.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
|
target_include_directories(${RUNTIME_CONFIG_TEST_APP_NAME} SYSTEM
|
||||||
PRIVATE ${INCLUDE_DIR}
|
PRIVATE ${INCLUDE_DIR}
|
||||||
@@ -63,6 +66,7 @@ target_include_directories(${RUNTIME_CONFIG_TEST_APP_NAME}
|
|||||||
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
|
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
)
|
)
|
||||||
target_link_libraries(${RUNTIME_CONFIG_TEST_APP_NAME}
|
target_link_libraries(${RUNTIME_CONFIG_TEST_APP_NAME}
|
||||||
|
PRIVATE m
|
||||||
PRIVATE ${deps_xkbcommon_MODULE_NAME}
|
PRIVATE ${deps_xkbcommon_MODULE_NAME}
|
||||||
PRIVATE ${CMAKE_DL_LIBS}
|
PRIVATE ${CMAKE_DL_LIBS}
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -22,6 +22,9 @@ add_executable(${TEST_APP_NAME}
|
|||||||
${SOURCE_DIR}/core/runtime.c
|
${SOURCE_DIR}/core/runtime.c
|
||||||
${SOURCE_DIR}/core/state.c
|
${SOURCE_DIR}/core/state.c
|
||||||
${SOURCE_DIR}/core/window.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
|
target_include_directories(${TEST_APP_NAME} SYSTEM
|
||||||
|
|||||||
Reference in New Issue
Block a user