Compare commits

...

3 Commits

27 changed files with 454 additions and 102 deletions

View File

@@ -140,6 +140,21 @@ typedef struct zdwm_api_t {
zdwm_config_builder_t *builder,
zdwm_binding_mode_id_t mode_id
);
/**
* @brief 设置边框配置信息
*
* @param builder 配置构建上下文
* @param width 边框宽度
* @param normal 普通窗口边框颜色
* @param focused 焦点窗口边框颜色
*/
void (*set_border_config)(
zdwm_config_builder_t *builder,
uint32_t width,
const char *normal,
const char *focused
);
} zdwm_api_t;
/**

View File

@@ -21,6 +21,7 @@
#include "base/log.h"
#include "base/macros.h"
#include "base/memory.h"
#include "base/window_list.h"
#include "core/plan.h"
#include "core/types.h"
#include "internal.h"
@@ -177,14 +178,9 @@ void backend_destroy(backend_t *backend) {
p_delete(&backend->config_list.cfgs);
p_clear(&backend->config_list, 1);
p_delete(&backend->unmap.windows);
p_clear(&backend->unmap, 1);
p_delete(&backend->map.windows);
p_clear(&backend->map, 1);
p_delete(&backend->kill.windows);
p_clear(&backend->kill, 1);
window_list_cleanup(&backend->unmap);
window_list_cleanup(&backend->map);
window_list_cleanup(&backend->kill);
xcb_key_symbols_free(backend->key_symbols);
backend->key_symbols = nullptr;

View File

@@ -264,6 +264,17 @@ static bool handle_key_press(
return true;
}
static bool handle_enter_notify(
backend_t *backend,
event_t *event,
const xcb_enter_notify_event_t *xcb_event
) {
event->type = ZDWM_EVENT_POINTER_ENTER;
event->as.pointer_enter.window = xcb_event->event;
return true;
}
bool backend_next_event(backend_t *backend, event_t *event) {
if (!backend || !backend->conn || !event) return false;
@@ -289,6 +300,7 @@ bool backend_next_event(backend_t *backend, event_t *event) {
EVENT(XCB_DESTROY_NOTIFY, handle_destroy_notify);
EVENT(XCB_CONFIGURE_REQUEST, handle_configure_request);
EVENT(XCB_KEY_PRESS, handle_key_press);
EVENT(XCB_ENTER_NOTIFY, handle_enter_notify);
#undef EVENT

View File

@@ -6,6 +6,8 @@
#include <xcb/xcb_keysyms.h>
#include <xcb/xproto.h>
#include "base/window_list.h"
#define ATOM_LIST(X) \
X(COMPOUND_TEXT) \
X(UTF8_STRING) \
@@ -70,12 +72,6 @@ typedef struct window_configure_list_t {
size_t capacity;
} window_configure_list_t;
typedef struct window_list_t {
xcb_window_t *windows;
size_t count;
size_t capacity;
} window_list_t;
struct backend_t {
xcb_key_symbols_t *key_symbols;
xcb_connection_t *conn;

View File

@@ -7,7 +7,6 @@
#include <xcb/xcb_keysyms.h>
#include <xcb/xproto.h>
#include "base/array.h"
#include "base/macros.h"
#include "base/memory.h"
#include "core/backend.h"
@@ -358,17 +357,6 @@ void window_set_net_wm_state(
);
}
void window_list_push(window_list_t *window_list, xcb_window_t window) {
xcb_window_t *win =
array_push(window_list->windows, window_list->count, window_list->capacity);
*win = window;
}
void window_list_reset(window_list_t *window_list) {
p_clear(window_list->windows, window_list->count);
window_list->count = 0;
}
static uint16_t get_xcb_modifier(modifier_mask_t modifiers) {
typedef struct modifier_map_t {
modifier_bit_t modifier;

View File

@@ -97,9 +97,6 @@ void window_set_net_wm_state(
xcb_atom_t *atoms
);
void window_list_push(window_list_t *window_list, xcb_window_t window);
void window_list_reset(window_list_t *window_list);
void window_grab_keys(
backend_t *backend,
xcb_window_t window,

107
src/base/color.c Normal file
View File

@@ -0,0 +1,107 @@
#include "base/color.h"
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "base/log.h"
/**
* @brief 将 16 进制的颜色配置转换成 uint32 格式的 rgba数据
*
* @param hex 16 进制的颜色表示,支持的格式有
* RGB/RGBA/RRGGBB/RRGGBBAA/#RGB/#RGBA/#RRGGBB/#RRGGBBAA
* @param rgba 返回数据的指针,解析结果会放到这个指针指向的内存中
* @return 如果 hex 是一个能正常解析的颜色,返回 true ,否则返回 false
*/
static bool hex_color_to_rgba(const char *hex, uint32_t *rgba);
/**
* @brief 将 rgba 通道顺序的颜色转换成 argb 顺序
* @description xcb 库用到的颜色需要是 argb 通道顺序
*/
static uint32_t rgba_to_argb(uint32_t rgba);
/**
* @brief 提取颜色中的各个颜色通道数值
* @param rgba uint32 表示的颜色
* @param red red channel, range 0~1
* @param green green channel, range 0~1
* @param blue blue channel, range 0~1
* @param alpha alpha channel, range 0~1
*/
static void extract_color_channel(
const uint32_t rgba,
double *red,
double *green,
double *blue,
double *alpha
);
void color_parse(const char *hex, color_t *const color) {
bool success = hex_color_to_rgba(hex, &color->rgba);
if (!success) fatal("invalid hex color: %s", hex);
color->argb = rgba_to_argb(color->rgba);
extract_color_channel(
color->rgba,
&color->red,
&color->green,
&color->blue,
&color->alpha
);
}
bool hex_color_to_rgba(const char *hex, uint32_t *rgba) {
if (hex[0] == '#') hex++;
size_t len = strlen(hex);
char extended[9] = {0};
uint32_t color = 0x00000000;
if (len == 3 || len == 4) {
extended[0] = extended[1] = hex[0];
extended[2] = extended[3] = hex[1];
extended[4] = extended[5] = hex[2];
if (len == 3) {
extended[6] = extended[7] = 'F';
} else {
extended[6] = extended[7] = hex[3];
}
} else if (len == 6) {
strncpy(extended, hex, len);
extended[6] = extended[7] = 'F';
} else if (len == 8) {
strncpy(extended, hex, len);
} else {
return false;
}
color = strtoul(extended, nullptr, 16) & 0xffffffff;
*rgba = color;
return true;
}
#define EXTRACE_COLOR_BIT(C, R) (((C) >> (R)) & 0xff)
uint32_t rgba_to_argb(uint32_t rgba) {
uint32_t r = EXTRACE_COLOR_BIT(rgba, 24);
uint32_t g = EXTRACE_COLOR_BIT(rgba, 16);
uint32_t b = EXTRACE_COLOR_BIT(rgba, 8);
uint32_t a = EXTRACE_COLOR_BIT(rgba, 0);
uint32_t argb = (a << 24) | (r << 16) | (g << 8) | b;
return argb;
}
#define COLOR_SPLIT(C, R) (EXTRACE_COLOR_BIT((C), (R)) / (double)0xff)
void extract_color_channel(
const uint32_t rgba,
double *red,
double *green,
double *blue,
double *alpha
) {
*red = COLOR_SPLIT(rgba, 24);
*green = COLOR_SPLIT(rgba, 16);
*blue = COLOR_SPLIT(rgba, 8);
*alpha = COLOR_SPLIT(rgba, 0);
}

20
src/base/color.h Normal file
View File

@@ -0,0 +1,20 @@
#pragma once
#include <stdint.h>
typedef struct color_t {
uint32_t rgba;
uint32_t argb;
/* RGBA color channels for Cairo, each channel in the range [0, 1] */
double red, green, blue, alpha;
} color_t;
/**
* @brief 解析 16 进制表示的颜色
*
* @param hex 颜色的 16 进制表示,支持的格式有
* RGB/RGBA/RRGGBB/RRGGBBAA/#RGB/#RGBA/#RRGGBB/#RRGGBBAA
* @param color 存储颜色值的结构体指针,不能为 nullptr
*/
void color_parse(const char *hex, color_t *const color);

26
src/base/window_list.c Normal file
View File

@@ -0,0 +1,26 @@
#include "base/window_list.h"
#include <zdwm/types.h>
#include "base/array.h"
#include "base/memory.h"
void window_list_push(
window_list_t *window_list,
zdwm_window_id_t window_id
) {
zdwm_window_id_t *window =
array_push(window_list->windows, window_list->count, window_list->capacity);
*window = window_id;
}
void window_list_reset(window_list_t *window_list) {
p_clear(window_list->windows, window_list->capacity);
window_list->count = 0;
}
void window_list_cleanup(window_list_t *window_list) {
p_delete(window_list->windows);
window_list->count = 0;
window_list->capacity = 0;
}

14
src/base/window_list.h Normal file
View File

@@ -0,0 +1,14 @@
#pragma once
#include <stddef.h>
#include <zdwm/types.h>
typedef struct window_list_t {
zdwm_window_id_t *windows;
size_t count;
size_t capacity;
} window_list_t;
void window_list_push(window_list_t *window_list, zdwm_window_id_t window_id);
void window_list_reset(window_list_t *window_list);
void window_list_cleanup(window_list_t *window_list);

View File

@@ -80,6 +80,7 @@ bool config_defaults_build(
api->set_default_mode(builder, default_mode);
api->set_initial_mode(builder, default_mode);
api->set_border_config(builder, 2, "#444444", "#005577");
return true;
}

View File

@@ -5,6 +5,7 @@
#include <zdwm/config.h>
#include "base/array.h"
#include "base/color.h"
#include "base/memory.h"
#include "config/defaults.h"
#include "config/loader.h"
@@ -25,6 +26,7 @@ struct zdwm_config_builder_t {
size_t workspace_count;
size_t workspace_capacity;
size_t output_count;
border_config_t border;
binding_table_t *binding_table;
};
@@ -183,6 +185,17 @@ static bool runtime_config_set_initial_mode(
return binding_table_set_current_mode(builder->binding_table, mode_id);
}
static void runtime_config_set_border_config(
zdwm_config_builder_t *builder,
uint32_t width,
const char *normal,
const char *focused
) {
builder->border.width = width;
color_parse(normal, &builder->border.normal_color);
color_parse(focused, &builder->border.focused_color);
}
static bool config_builder_finish(
zdwm_config_builder_t *builder,
runtime_init_desc_t *out
@@ -193,6 +206,7 @@ static bool config_builder_finish(
if (!layout_registry_move(&builder->layouts, &out->layouts)) return false;
if (!rules_move(&builder->rules, &out->rules)) return false;
out->border = builder->border;
out->binding_table = builder->binding_table;
out->workspaces = builder->workspaces;
out->workspace_count = builder->workspace_count;
@@ -230,6 +244,7 @@ static bool runtime_config_build(
.bind = runtime_config_bind,
.set_default_mode = runtime_config_set_default_mode,
.set_initial_mode = runtime_config_set_initial_mode,
.set_border_config = runtime_config_set_border_config,
};
bool ok = setup(&api, &builder, outputs, output_count) &&
config_builder_finish(&builder, out);

View File

@@ -25,10 +25,6 @@ typedef struct switch_workspace_command_t {
workspace_id_t workspace;
} switch_workspace_command_t;
typedef struct only_window_command_t {
window_id_t window;
} only_window_command_t;
typedef struct window_state_change_command_t {
window_id_t window;
window_state_request_type_t type;
@@ -48,10 +44,10 @@ typedef struct command_t {
command_type_t type;
union {
manage_window_command_t manage_window;
only_window_command_t unmanage;
only_window_command_t focus;
only_window_command_t kill;
only_window_command_t withdraw;
only_window_data_t unmanage;
only_window_data_t focus;
only_window_data_t kill;
only_window_data_t withdraw;
configure_data_t configure;
window_state_change_command_t state_change;
switch_workspace_command_t switch_workspace;

View File

@@ -46,12 +46,6 @@ typedef struct pointer_motion_event_t {
point_t local;
} pointer_motion_event_t;
typedef struct pointer_enter_event_t {
window_id_t window;
point_t root;
point_t local;
} pointer_enter_event_t;
typedef struct window_map_request_event_t {
window_id_t window;
window_id_t transient_for;
@@ -121,7 +115,7 @@ typedef struct event_t {
pointer_button_event_t pointer_button_press;
pointer_button_event_t pointer_button_release;
pointer_motion_event_t pointer_motion;
pointer_enter_event_t pointer_enter;
only_window_data_t pointer_enter;
window_map_request_event_t window_map_request;
window_remove_event_t window_remove;
window_metadata_change_event_t window_metadata_change;

View File

@@ -3,6 +3,7 @@
#include <stddef.h>
#include <stdint.h>
#include "base/color.h"
#include "core/types.h"
typedef enum effect_type_t {
@@ -21,10 +22,6 @@ typedef enum effect_type_t {
ZDWM_EFFECT_BIND_KEY,
} effect_type_t;
typedef struct effect_only_window_id_t {
window_id_t window;
} effect_only_window_id_t;
typedef struct effect_move_window_t {
window_id_t window;
point_t left_top_point;
@@ -59,11 +56,11 @@ typedef struct effect_bool_window_t {
typedef struct effect_t {
effect_type_t type;
union {
effect_only_window_id_t map;
effect_only_window_id_t unmap;
effect_only_window_id_t focus;
effect_only_window_id_t kill;
effect_only_window_id_t withdraw;
only_window_data_t map;
only_window_data_t unmap;
only_window_data_t focus;
only_window_data_t kill;
only_window_data_t withdraw;
effect_bool_window_t minimize;
effect_bool_window_t maximize;
effect_bool_window_t fullscreen;

View File

@@ -4,7 +4,9 @@
#include <stdint.h>
#include <zdwm/types.h>
#include "base/color.h"
#include "base/macros.h"
#include "base/window_list.h"
#include "core/binding.h"
#include "core/command.h"
#include "core/command_buffer.h"
@@ -34,6 +36,15 @@ static void route_key_press(
}
}
static void
route_pointer_enter(state_t *state, window_id_t window, command_buffer_t *out) {
command_t focus_command = {
.type = ZDWM_COMMAND_FOCUS_WINDOW,
.as.focus.window = window,
};
command_buffer_push(out, &focus_command);
}
static workspace_id_t derive_window_workspace(const state_t *state) {
return state->outputs[state->current_output_index].current_workspace_id;
}
@@ -155,19 +166,6 @@ static void route_configure_request(
return;
}
if (data->changed_fields & ZDWM_CONFIGURE_FIELD_BORDER_WIDTH) {
command_t configure_border_width_cmd = {
.type = ZDWM_COMMAND_CONFIGURE_WINDOW,
.as.configure = {
.window = window->id,
.border_width = data->border_width,
.changed_fields = ZDWM_CONFIGURE_FIELD_BORDER_WIDTH,
}
};
command_buffer_push(out, &configure_border_width_cmd);
return;
}
if (!state_workspace_show(state, window->workspace_id)) return;
if (window_need_layout(window)) return;
auto workspace = state_workspace_get(state, window->workspace_id);
@@ -193,6 +191,8 @@ void policy_route_event(
case ZDWM_EVENT_KEY_PRESS:
route_key_press(ctx->bind_table, &ctx->action_ctx, &event->as.key_press);
break;
case ZDWM_EVENT_POINTER_ENTER:
route_pointer_enter(state, event->as.pointer_enter.window, out);
case ZDWM_EVENT_WINDOW_MAP_REQUEST:
route_map_request(state, ctx->rules, &event->as.window_map_request, out);
break;
@@ -207,6 +207,63 @@ void policy_route_event(
}
}
static void adjust_layout_windows_border_width(
state_t *state,
uint32_t border_width,
workspace_id_t workspace_id
) {
window_list_t list = {0};
state_get_windows_need_layout_in_workspace(state, workspace_id, &list);
if (list.count <= 1) border_width = 0;
for (size_t i = 0; i < list.count; ++i) {
auto window_id = list.windows[i];
state_window_set_border_width(state, window_id, border_width);
}
}
static void window_change_border_color(
window_id_t window_id,
const color_t *color,
plan_t *plan
) {
effect_t change_border_color_effect = {
.type = ZDWM_EFFECT_CHANGE_BORDER_COLOR,
.as.change_border_color = {.window = window_id, .color = color}
};
plan_push_effect(plan, &change_border_color_effect);
}
static void set_foucs_window(
const policy_context_t *ctx,
workspace_id_t workspace_id,
window_id_t window_id,
plan_t *plan
) {
auto state = ctx->state;
auto border = ctx->border;
auto workspace = state_workspace_get(state, workspace_id);
if (!workspace) return;
auto old_focused_window_id = workspace->focused_window_id;
if (window_id == old_focused_window_id) return;
state_workspace_set_focused_window(state, workspace_id, window_id);
effect_t focus_effect = {
.type = ZDWM_EFFECT_FOCUS_WINDOW,
.as.focus.window = window_id,
};
plan_push_effect(plan, &focus_effect);
if (state_window_get(state, window_id)) {
window_change_border_color(window_id, &border->focused_color, plan);
}
if (state_window_get(state, old_focused_window_id)) {
auto color = &border->normal_color;
window_change_border_color(old_focused_window_id, color, plan);
}
}
static void manage_window(
const policy_context_t *ctx,
const manage_window_command_t *command,
@@ -215,9 +272,17 @@ static void manage_window(
auto state = ctx->state;
auto window = state_window_add(state, &command->info);
auto window_id = window->id;
state_window_set_workspace(state, window_id, command->workspace);
state_workspace_set_focused_window(state, command->workspace, window_id);
auto workspace_id = command->workspace;
state_window_set_workspace(state, window_id, workspace_id);
state_window_set_floating(state, window_id, command->floating);
set_foucs_window(ctx, workspace_id, window_id, plan);
auto need_layout = window_need_layout(window);
if (need_layout) {
adjust_layout_windows_border_width(state, ctx->border->width, workspace_id);
} else {
state_window_set_border_width(state, window_id, ctx->border->width);
}
if (!state_workspace_show(state, command->workspace)) return;
@@ -234,7 +299,26 @@ static void manage_window(
if (window_need_layout(window)) {
plan->need_relayout = true;
return;
}
effect_t configure_effect = {
.type = ZDWM_EFFECT_CONFIGURE_WINDOW,
.as.configure = {
.window = window_id,
.x = window->frame_rect.x,
.y = window->frame_rect.y,
.width = window->frame_rect.width - 2 * (int32_t)window->border_width,
.height = window->frame_rect.height - 2 * (int32_t)window->border_width,
.border_width = window->border_width,
.changed_fields = ZDWM_CONFIGURE_FIELD_X | ZDWM_CONFIGURE_FIELD_Y |
ZDWM_CONFIGURE_FIELD_WIDTH |
ZDWM_CONFIGURE_FIELD_HEIGHT |
ZDWM_CONFIGURE_FIELD_BORDER_WIDTH,
}
};
plan_push_effect(plan, &configure_effect);
}
static void add_switch_workspace_effects(
@@ -272,7 +356,9 @@ static void add_switch_workspace_effects(
plan_push_effect(plan, &focus_effect);
}
static void unmanage_window(state_t *state, window_id_t window, plan_t *plan) {
static void
unmanage_window(const policy_context_t *ctx, window_id_t window, plan_t *plan) {
auto state = ctx->state;
const window_t *win = state_window_get(state, window);
if (!win) return;
@@ -282,6 +368,12 @@ static void unmanage_window(state_t *state, window_id_t window, plan_t *plan) {
auto old_focused_window = workspace->focused_window_id;
state_window_remove(state, window);
if (window_need_layout(win)) {
adjust_layout_windows_border_width(state, ctx->border->width, workspace_id);
plan->need_relayout = true;
}
if (output->current_workspace_id != workspace_id) return;
if (old_focused_window != workspace->focused_window_id) {
@@ -293,7 +385,9 @@ static void unmanage_window(state_t *state, window_id_t window, plan_t *plan) {
}
}
static void focus_window(state_t *state, window_id_t window, plan_t *plan) {
static void
focus_window(const policy_context_t *ctx, window_id_t window, plan_t *plan) {
auto state = ctx->state;
auto win = state_window_get(state, window);
if (!win) return;
@@ -301,7 +395,7 @@ static void focus_window(state_t *state, window_id_t window, plan_t *plan) {
auto workspace = state_workspace_get(state, workspace_id);
auto old_focused_window = workspace->focused_window_id;
state_workspace_set_focused_window(state, workspace_id, window);
set_foucs_window(ctx, workspace_id, window, plan);
if (old_focused_window == workspace->focused_window_id) return;
effect_t focus_effect = {
@@ -578,10 +672,10 @@ void policy_apply_command(
manage_window(ctx, &cmd->as.manage_window, plan);
break;
case ZDWM_COMMAND_UNMANAGE_WINDOW:
unmanage_window(state, cmd->as.unmanage.window, plan);
unmanage_window(ctx, cmd->as.unmanage.window, plan);
break;
case ZDWM_COMMAND_FOCUS_WINDOW:
focus_window(state, cmd->as.focus.window, plan);
focus_window(ctx, cmd->as.focus.window, plan);
break;
case ZDWM_COMMAND_KILL_WINDOW:
kill_window(state, cmd->as.kill.window, plan);

View File

@@ -9,11 +9,13 @@
#include "core/plan.h"
#include "core/rules.h"
#include "core/state.h"
#include "core/types.h"
typedef struct policy_context_t {
binding_table_t *bind_table;
state_t *state;
const rules_t *rules;
const border_config_t *border;
const layout_registry_t *layouts;
const zdwm_action_ctx_t action_ctx;
} policy_context_t;

View File

@@ -59,6 +59,7 @@ bool runtime_init(runtime_t *runtime, runtime_init_desc_t *desc) {
runtime->backend = desc->backend;
layout_registry_move(&desc->layouts, &runtime->layouts);
rules_move(&desc->rules, &runtime->rules);
runtime->border = desc->border;
runtime->config_module_handle = desc->config_module_handle;
runtime->binding_table = desc->binding_table;
desc->backend = nullptr;
@@ -223,6 +224,7 @@ static void runtime_apply_window_rect(
}
if (need_resize) {
changed_fields |= ZDWM_CONFIGURE_FIELD_WIDTH | ZDWM_CONFIGURE_FIELD_HEIGHT;
changed_fields |= ZDWM_CONFIGURE_FIELD_BORDER_WIDTH;
}
effect_t configure_effect = {
.type = ZDWM_EFFECT_CONFIGURE_WINDOW,
@@ -230,8 +232,9 @@ static void runtime_apply_window_rect(
.window = window_id,
.x = rect.x,
.y = rect.y,
.width = rect.width,
.height = rect.height,
.width = rect.width - 2 * (int32_t)window->border_width,
.height = rect.height - 2 * (int32_t)window->border_width,
.border_width = window->border_width,
.changed_fields = changed_fields,
}
};
@@ -265,6 +268,7 @@ void runtime_run(runtime_t *runtime) {
.bind_table = runtime->binding_table,
.state = &runtime->state,
.rules = &runtime->rules,
.border = &runtime->border,
.layouts = &runtime->layouts,
.action_ctx = {
.spawn = spawn,

View File

@@ -1,6 +1,7 @@
#pragma once
#include <stddef.h>
#include <stdint.h>
#include "core/backend.h"
#include "core/binding.h"
@@ -9,6 +10,7 @@
#include "core/plan.h"
#include "core/rules.h"
#include "core/state.h"
#include "core/types.h"
typedef struct runtime_init_desc_t {
backend_t *backend;
@@ -17,6 +19,7 @@ typedef struct runtime_init_desc_t {
layout_registry_t layouts;
rules_t rules;
border_config_t border;
workspace_desc_t *workspaces;
size_t workspace_count;
void *config_module_handle;
@@ -33,6 +36,7 @@ typedef struct runtime_t {
layout_result_t layout_result;
layout_registry_t layouts;
rules_t rules;
border_config_t border;
backend_t *backend;
void *config_module_handle;
binding_table_t *binding_table;

View File

@@ -8,6 +8,7 @@
#include "base/array.h"
#include "base/log.h"
#include "base/memory.h"
#include "base/window_list.h"
#include "core/layer.h"
#include "core/types.h"
#include "core/window.h"
@@ -479,6 +480,15 @@ void state_window_set_fixed_size(
if (window) window_set_fixed_size(window, fixed_size);
}
void state_window_set_border_width(
state_t *state,
window_id_t window_id,
uint32_t border_width
) {
window_t *window = (window_t *)state_window_get(state, window_id);
if (window) window_set_border_width(window, border_width);
}
void state_window_set_skip_taskbar(
state_t *state,
window_id_t window_id,
@@ -599,3 +609,16 @@ bool state_stack_lower(state_t *state, window_id_t window_id) {
return layer_stack_lower(layer, window_id);
}
void state_get_windows_need_layout_in_workspace(
const state_t *state,
workspace_id_t workspace_id,
window_list_t *window_list_out
) {
for (size_t i = 0; i < state->window_count; ++i) {
auto window = &state->windows[i];
if (window->workspace_id == workspace_id && window_need_layout(window)) {
window_list_push(window_list_out, window->id);
}
}
}

View File

@@ -3,6 +3,7 @@
#include <stddef.h>
#include <stdint.h>
#include "base/window_list.h"
#include "core/layer.h"
#include "core/types.h"
#include "core/window.h"
@@ -201,6 +202,11 @@ void state_window_set_fixed_size(
window_id_t window_id,
bool fixed_size
);
void state_window_set_border_width(
state_t *state,
window_id_t window_id,
uint32_t border_width
);
void state_window_set_skip_taskbar(
state_t *state,
window_id_t window_id,
@@ -264,3 +270,18 @@ bool state_window_set_instance(
bool state_stack_raise(state_t *state, window_id_t window_id);
bool state_stack_lower(state_t *state, window_id_t window_id);
/**
* @brief 获取 workspace_id 对应 workspace 需要自动布局的窗口列表
*
* @details 该函数不负责 window_list_out 参数的初始化
*
* @param state 状态实例指针
* @param workspace_id 目标 workspace 的 id
* @param window_list_out 存储窗口列表结果的结构体指针
*/
void state_get_windows_need_layout_in_workspace(
const state_t *state,
workspace_id_t workspace_id,
window_list_t *window_list_out
);

View File

@@ -4,6 +4,8 @@
#include <zdwm/rules.h>
#include <zdwm/types.h>
#include "base/color.h"
/* clang-format off */
typedef zdwm_layout_id_t layout_id_t;
typedef zdwm_window_id_t window_id_t;
@@ -27,14 +29,6 @@ typedef struct point_t {
int32_t y;
} point_t;
typedef struct color_t {
uint32_t rgba;
uint32_t argb;
/* RGBA color channels for Cairo, each channel in the range [0, 1] */
double red, green, blue, alpha;
} color_t;
typedef enum window_geometry_mode_t {
ZDWM_GEOMETRY_NORMAL,
ZDWM_GEOMETRY_MAXIMIZED,
@@ -101,3 +95,13 @@ typedef struct configure_data_t {
window_id_t sibling;
uint32_t stack_mode;
} configure_data_t;
typedef struct border_config_t {
uint32_t width;
color_t normal_color;
color_t focused_color;
} border_config_t;
typedef struct only_window_data_t {
window_id_t window;
} only_window_data_t;

View File

@@ -1,6 +1,7 @@
#include "core/window.h"
#include "base/memory.h"
#include "core/types.h"
window_layer_type_t window_classify_layer(const window_layer_props_t *props) {
for (size_t i = 0; i < props->type_count; ++i) {
@@ -96,6 +97,10 @@ void window_set_instance(window_t *window, const char *instance_name) {
window->instance_name = p_strdup_nullable(instance_name);
}
void window_set_border_width(window_t *window, uint32_t border_width) {
window->border_width = border_width;
}
void window_set_skip_taskbar(window_t *window, bool skip_taskbar) {
window->skip_taskbar = skip_taskbar;
}
@@ -146,3 +151,14 @@ bool window_need_resize(const window_t *window, int32_t width, int32_t height) {
return window->frame_rect.width != width ||
window->frame_rect.height != height;
}
bool window_should_has_border(const window_t *window) {
switch (window->geometry_mode) {
case ZDWM_GEOMETRY_MAXIMIZED:
case ZDWM_GEOMETRY_FULLSCREEN:
return false;
case ZDWM_GEOMETRY_NORMAL:
case ZDWM_GEOMETRY_MINIMIZED:
}
return window->floating;
}

View File

@@ -87,6 +87,7 @@ typedef struct window_t {
char *class_name;
char *instance_name;
uint32_t border_width;
bool skip_taskbar;
} window_t;
@@ -110,6 +111,7 @@ void window_set_app_id(window_t *window, const char *app_id);
void window_set_role(window_t *window, const char *role);
void window_set_class(window_t *window, const char *class_name);
void window_set_instance(window_t *window, const char *instance_name);
void window_set_border_width(window_t *window, uint32_t border_width);
void window_set_skip_taskbar(window_t *window, bool skip_taskbar);
void window_take_metadata(
window_t *window,
@@ -123,3 +125,4 @@ void window_take_metadata(
bool window_need_layout(const window_t *window);
bool window_need_move(const window_t *window, int32_t x, int32_t y);
bool window_need_resize(const window_t *window, int32_t width, int32_t height);
bool window_should_has_border(const window_t *window);

View File

@@ -37,7 +37,9 @@ add_dependencies(${CONFIG_LOADER_TEST_APP_NAME}
add_executable(${RUNTIME_CONFIG_TEST_APP_NAME}
${CMAKE_CURRENT_SOURCE_DIR}/runtime_config_test.c
${SOURCE_DIR}/base/color.c
${SOURCE_DIR}/base/log.c
${SOURCE_DIR}/base/window_list.c
${SOURCE_DIR}/config/defaults.c
${SOURCE_DIR}/config/loader.c
${SOURCE_DIR}/config/runtime_config.c

View File

@@ -36,17 +36,20 @@ static backend_t *test_backend_create(void) {
static void assert_default_layouts(const runtime_init_desc_t *desc) {
assert(desc);
assert(layout_registry_count(&desc->layouts) == 3);
assert(layout_registry_count(&desc->layouts) == 4);
const layout_slot_t *tile = layout_registry_at(&desc->layouts, 0);
const layout_slot_t *monocle = layout_registry_at(&desc->layouts, 1);
const layout_slot_t *floating = layout_registry_at(&desc->layouts, 2);
const layout_slot_t *fair = layout_registry_at(&desc->layouts, 0);
const layout_slot_t *maximize = layout_registry_at(&desc->layouts, 1);
const layout_slot_t *fullscreen = layout_registry_at(&desc->layouts, 2);
const layout_slot_t *floating = layout_registry_at(&desc->layouts, 3);
assert(tile);
assert(monocle);
assert(fair);
assert(maximize);
assert(fullscreen);
assert(floating);
assert(strcmp(tile->name, "tile") == 0);
assert(strcmp(monocle->name, "monocle") == 0);
assert(strcmp(fair->name, "fair") == 0);
assert(strcmp(maximize->name, "maximize") == 0);
assert(strcmp(fullscreen->name, "fullscreen") == 0);
assert(strcmp(floating->name, "floating") == 0);
}

View File

@@ -2,7 +2,9 @@ set(TEST_APP_NAME "zdwm-tests")
add_executable(${TEST_APP_NAME}
${CMAKE_CURRENT_SOURCE_DIR}/main.c
${SOURCE_DIR}/base/color.c
${SOURCE_DIR}/base/log.c
${SOURCE_DIR}/base/window_list.c
${SOURCE_DIR}/backend/output_utils.c
${SOURCE_DIR}/config/defaults.c
${SOURCE_DIR}/config/loader.c