refactor(core): 使用独立 bool 字段代替 geometry_mode 字段

将 fullscreen/maximized/minimized 从互斥枚举拆分为独立 bool 字段,以便
窗口状态切换时能回到上一状态。比如窗口初始为最大化状态,如果进入全屏状
态后从全屏状态退出时还能恢复最大化状态。
This commit is contained in:
2026-05-04 04:07:36 +08:00
parent c777b58d80
commit 12bfce4745
10 changed files with 133 additions and 119 deletions

View File

@@ -51,27 +51,32 @@ static bool derive_skip_taskbar(
return false;
}
static window_geometry_mode_t geometry_mode_from_hints(
const xcb_icccm_wm_hints_t *hints
) {
if (hints->initial_state == XCB_ICCCM_WM_STATE_ICONIC)
return ZDWM_GEOMETRY_MINIMIZED;
return ZDWM_GEOMETRY_NORMAL;
static bool minimized_from_hints(const xcb_icccm_wm_hints_t *hints) {
return hints->initial_state == XCB_ICCCM_WM_STATE_ICONIC;
}
static window_geometry_mode_t geometry_mode_from_states(
static bool maximized_from_states(
const atoms_t *atoms,
const xcb_atom_t *state_atoms,
uint32_t state_count
) {
for (uint32_t i = 0; i < state_count; i++) {
if (state_atoms[i] == atoms->_NET_WM_STATE_FULLSCREEN)
return ZDWM_GEOMETRY_FULLSCREEN;
if (state_atoms[i] == atoms->_NET_WM_STATE_MAXIMIZED_VERT ||
state_atoms[i] == atoms->_NET_WM_STATE_MAXIMIZED_HORZ)
return ZDWM_GEOMETRY_MAXIMIZED;
return true;
}
return ZDWM_GEOMETRY_NORMAL;
return false;
}
static bool fullscreen_from_states(
const atoms_t *atoms,
const xcb_atom_t *state_atoms,
uint32_t state_count
) {
for (uint32_t i = 0; i < state_count; i++) {
if (state_atoms[i] == atoms->_NET_WM_STATE_FULLSCREEN) return true;
}
return false;
}
static bool urgent_from_states(
@@ -98,7 +103,6 @@ static bool handle_map_request(
window_map_request_event_t *ev = &event->as.window_map_request;
ev->window = (window_id_t)window;
ev->transient_for = window_get_transient_for(backend, window);
ev->geometry_mode = ZDWM_GEOMETRY_NORMAL;
xcb_get_window_attributes_reply_t *wa =
window_get_attributes(backend, window);
@@ -108,8 +112,8 @@ static bool handle_map_request(
xcb_icccm_wm_hints_t wm_hints = {0};
if (window_get_wm_hints(backend, window, &wm_hints)) {
ev->urgent = (bool)xcb_icccm_wm_hints_get_urgency(&wm_hints);
ev->geometry_mode = geometry_mode_from_hints(&wm_hints);
ev->urgent = (bool)xcb_icccm_wm_hints_get_urgency(&wm_hints);
ev->minimized = minimized_from_hints(&wm_hints);
}
if (!window_get_fixed_size(backend, window, &ev->fixed_size)) return false;
@@ -128,12 +132,9 @@ static bool handle_map_request(
return false;
}
if (ev->geometry_mode == ZDWM_GEOMETRY_NORMAL && state_atoms) {
ev->geometry_mode =
geometry_mode_from_states(atoms, state_atoms, state_count);
}
if (state_atoms) {
ev->maximized = maximized_from_states(atoms, state_atoms, state_count);
ev->fullscreen = fullscreen_from_states(atoms, state_atoms, state_count);
ev->skip_taskbar = derive_skip_taskbar(atoms, state_atoms, state_count);
ev->props.states = derive_window_states(
atoms,
@@ -409,18 +410,16 @@ static bool handle_client_message(
data->action = ZDWM_WINDOW_STATE_ACTION_TOGGLE;
break;
}
auto properties = &xcb_event->data.data32[1];
uint32_t count = 2;
auto geometry_mode = geometry_mode_from_states(atoms, properties, count);
switch (geometry_mode) {
case ZDWM_GEOMETRY_FULLSCREEN:
data->type = ZDWM_WINDOW_STATE_REQUEST_FULLSCREEN;
return true;
case ZDWM_GEOMETRY_MAXIMIZED:
auto properties = &xcb_event->data.data32[1];
uint32_t count = 2;
if (maximized_from_states(atoms, properties, count)) {
data->type = ZDWM_WINDOW_STATE_REQUEST_MAXIMIZED;
return true;
case ZDWM_GEOMETRY_MINIMIZED:
case ZDWM_GEOMETRY_NORMAL:
}
if (fullscreen_from_states(atoms, properties, count)) {
data->type = ZDWM_WINDOW_STATE_REQUEST_FULLSCREEN;
return true;
}
if (derive_skip_taskbar(atoms, properties, count)) {

View File

@@ -53,7 +53,9 @@ typedef struct window_map_request_event_t {
bool skip_taskbar;
bool urgent;
bool fixed_size;
window_geometry_mode_t geometry_mode;
bool fullscreen;
bool maximized;
bool minimized;
rect_t rect;
window_layer_props_t props;

View File

@@ -77,11 +77,13 @@ static void route_map_request(
.class_name = e->metadata.class_name,
.instance_name = e->metadata.instance_name,
.geometry_mode = e->geometry_mode,
.layer_type = layer_type,
.urgent = e->urgent,
.fixed_size = e->fixed_size,
.skip_taskbar = e->skip_taskbar,
.layer_type = layer_type,
.fullscreen = e->fullscreen,
.maximized = e->maximized,
.minimized = e->minimized,
.urgent = e->urgent,
.fixed_size = e->fixed_size,
.skip_taskbar = e->skip_taskbar,
},
},
};
@@ -93,15 +95,9 @@ static void route_map_request(
if (action.workspace != ZDWM_WORKSPACE_ID_INVALID) {
data->workspace = action.workspace;
}
if (action.floating) {
data->floating = true;
}
if (action.fullscreen) {
data->info.geometry_mode = ZDWM_GEOMETRY_FULLSCREEN;
} else if (action.maximize) {
data->info.geometry_mode = ZDWM_GEOMETRY_MAXIMIZED;
}
if (action.floating) data->floating = true;
if (action.fullscreen) data->info.fullscreen = true;
if (action.maximize) data->info.maximized = true;
}
command_buffer_push(out, &manage_window_cmd);
@@ -436,22 +432,17 @@ static void fullscreen_window(
auto window = state_window_get(state, window_id);
if (!window) return;
if ((value && window->geometry_mode == ZDWM_GEOMETRY_FULLSCREEN) ||
(!value && window->geometry_mode != ZDWM_GEOMETRY_FULLSCREEN)) {
return;
}
if (window->fullscreen == value) return;
state_window_set_border_width(state, window_id, 0);
plan_push_fullscreen_effect(plan, window_id, value);
state_window_set_fullscreen(state, window_id, value);
if (value) {
state_window_set_geometry_mode(state, window_id, ZDWM_GEOMETRY_FULLSCREEN);
state_window_set_border_width(state, window_id, 0);
if (window->floating) {
state_window_set_float_rect(state, window_id, window->frame_rect);
}
} else {
state_window_set_geometry_mode(state, window_id, ZDWM_GEOMETRY_NORMAL);
state_window_set_border_width(state, window_id, ctx->border->width);
if (window->floating) {
state_window_set_frame_rect(state, window_id, window->float_rect);
@@ -474,22 +465,17 @@ static void maximize_window(
auto window = state_window_get(state, window_id);
if (!window) return;
if ((value && window->geometry_mode == ZDWM_GEOMETRY_MAXIMIZED) ||
(!value && window->geometry_mode != ZDWM_GEOMETRY_MAXIMIZED)) {
return;
}
if (window->maximized == value) return;
state_window_set_border_width(state, window_id, 0);
plan_push_maximize_effect(plan, window_id, value);
state_window_set_maximized(state, window_id, value);
if (value) {
state_window_set_geometry_mode(state, window_id, ZDWM_GEOMETRY_MAXIMIZED);
state_window_set_border_width(state, window_id, 0);
if (window->floating) {
state_window_set_float_rect(state, window_id, window->frame_rect);
}
} else {
state_window_set_geometry_mode(state, window_id, ZDWM_GEOMETRY_NORMAL);
state_window_set_border_width(state, window_id, ctx->border->width);
if (window->floating) {
state_window_set_frame_rect(state, window_id, window->float_rect);
@@ -511,19 +497,16 @@ static void minimize_window(
auto window = state_window_get(state, window_id);
if (!window) return;
if ((value && window->geometry_mode == ZDWM_GEOMETRY_MINIMIZED) ||
(!value && window->geometry_mode != ZDWM_GEOMETRY_MINIMIZED)) {
return;
}
if (window->minimized == value) return;
plan_push_minimize_effect(plan, window_id, value);
state_window_set_minimized(state, window_id, value);
if (value) {
plan_push_unmap_effect(plan, window_id);
auto workspace = state_workspace_get(state, window->workspace_id);
auto old_focused_window_id = workspace->focused_window_id;
state_window_set_geometry_mode(state, window_id, ZDWM_GEOMETRY_MINIMIZED);
auto new_focused_window_id = workspace->focused_window_id;
if (old_focused_window_id != new_focused_window_id) {
auto color = &ctx->border->normal_color;
@@ -533,7 +516,6 @@ static void minimize_window(
plan_push_change_border_color_effect(plan, new_focused_window_id, color);
}
} else {
state_window_set_geometry_mode(state, window_id, ZDWM_GEOMETRY_NORMAL);
plan_push_map_effect(plan, window_id);
set_foucs_window(ctx, window->workspace_id, window_id, plan);
}
@@ -564,13 +546,22 @@ static void change_window_state(
case ZDWM_WINDOW_STATE_ACTION_TOGGLE:
switch (command->type) {
case ZDWM_WINDOW_STATE_REQUEST_FULLSCREEN:
value = !(window->geometry_mode == ZDWM_GEOMETRY_FULLSCREEN);
value = !window->fullscreen;
break;
case ZDWM_WINDOW_STATE_REQUEST_MAXIMIZED:
value = !(window->geometry_mode == ZDWM_GEOMETRY_MAXIMIZED);
value = !window->maximized;
break;
case ZDWM_WINDOW_STATE_REQUEST_MINIMIZED:
value = !(window->geometry_mode == ZDWM_GEOMETRY_MINIMIZED);
value = !window->minimized;
break;
case ZDWM_WINDOW_STATE_REQUEST_SKIP_TASKBAR:
value = !window->skip_taskbar;
break;
case ZDWM_WINDOW_STATE_REQUEST_URGENT:
value = !window->urgent;
break;
case ZDWM_WINDOW_STATE_REQUEST_FIXED_SIZE:
value = !window->fixed_size;
break;
}
}
@@ -585,6 +576,16 @@ static void change_window_state(
case ZDWM_WINDOW_STATE_REQUEST_MINIMIZED:
minimize_window(ctx, window->id, value, plan);
break;
/* TODO: 下面三个可能需要添加处理,尤其是 fixed_size 和 floating 相关 */
case ZDWM_WINDOW_STATE_REQUEST_SKIP_TASKBAR:
state_window_set_skip_taskbar(state, window->id, value);
break;
case ZDWM_WINDOW_STATE_REQUEST_URGENT:
state_window_set_urgent(state, window->id, value);
break;
case ZDWM_WINDOW_STATE_REQUEST_FIXED_SIZE:
state_window_set_fixed_size(state, window->id, value);
break;
}
}

View File

@@ -173,13 +173,13 @@ static const layout_result_t *runtime_layout_calc(runtime_t *runtime) {
window_id_t *window_id_slot =
array_push(window_ids, window_count, window_list_capacity);
*window_id_slot = window->id;
} else if (window->geometry_mode == ZDWM_GEOMETRY_FULLSCREEN) {
} else if (window->fullscreen) {
layout_item_t item = {
.window_id = window->id,
.rect = output->geometry,
};
layout_result_push(result, item);
} else if (window->geometry_mode == ZDWM_GEOMETRY_MAXIMIZED) {
} else if (window->maximized) {
layout_item_t item = {
.window_id = window->id,
.rect = output->workarea,

View File

@@ -338,7 +338,9 @@ const window_t *state_window_add(state_t *state, const window_info_t *info) {
window->layer = info->layer_type;
}
window_set_geometry_mode(window, info->geometry_mode);
window_set_fullscreen(window, info->fullscreen);
window_set_maximized(window, info->maximized);
window_set_minimized(window, info->minimized);
window_set_urgent(window, info->urgent);
window_set_fixed_size(window, info->fixed_size);
window_set_frame_rect(window, info->frame_rect);
@@ -435,20 +437,31 @@ void state_window_set_workspace(
state_workspace_adjust_focused_window(state, workspace_id);
}
void state_window_set_geometry_mode(
void state_window_set_fullscreen(
state_t *state,
window_id_t window_id,
window_geometry_mode_t geometry_mode
bool fullscreen
) {
window_t *window = (window_t *)state_window_get(state, window_id);
if (window) window_set_geometry_mode(window, geometry_mode);
auto window = (window_t *)state_window_get(state, window_id);
if (window) window_set_fullscreen(window, fullscreen);
}
if (geometry_mode != ZDWM_GEOMETRY_MINIMIZED) return;
void state_window_set_maximized(
state_t *state,
window_id_t window_id,
bool maximized
) {
auto window = (window_t *)state_window_get(state, window_id);
if (window) window_set_maximized(window, maximized);
}
auto workspace = state_workspace_get(state, window->workspace_id);
if (workspace->focused_window_id == window_id) {
state_workspace_adjust_focused_window(state, window->workspace_id);
}
void state_window_set_minimized(
state_t *state,
window_id_t window_id,
bool minimized
) {
auto window = (window_t *)state_window_get(state, window_id);
if (window) window_set_minimized(window, minimized);
}
void state_window_set_floating(

View File

@@ -177,10 +177,20 @@ void state_window_set_workspace(
window_id_t window_id,
workspace_id_t workspace_id
);
void state_window_set_geometry_mode(
void state_window_set_fullscreen(
state_t *state,
window_id_t window_id,
window_geometry_mode_t geometry_mode
bool fullscreen
);
void state_window_set_maximized(
state_t *state,
window_id_t window_id,
bool maximized
);
void state_window_set_minimized(
state_t *state,
window_id_t window_id,
bool minimized
);
void state_window_set_floating(
state_t *state,

View File

@@ -29,13 +29,6 @@ typedef struct point_t {
int32_t y;
} point_t;
typedef enum window_geometry_mode_t {
ZDWM_GEOMETRY_NORMAL,
ZDWM_GEOMETRY_MAXIMIZED,
ZDWM_GEOMETRY_FULLSCREEN,
ZDWM_GEOMETRY_MINIMIZED,
} window_geometry_mode_t;
typedef enum focus_direction_t {
ZDWM_FOCUS_PREV,
ZDWM_FOCUS_NEXT,

View File

@@ -36,11 +36,16 @@ void window_metadata_cleanup(window_metadata_t *metadata) {
p_delete(&metadata->instance_name);
}
void window_set_geometry_mode(
window_t *window,
window_geometry_mode_t geometry_mode
) {
window->geometry_mode = geometry_mode;
void window_set_fullscreen(window_t *window, bool fullscreen) {
window->fullscreen = fullscreen;
}
void window_set_maximized(window_t *window, bool maximized) {
window->maximized = maximized;
}
void window_set_minimized(window_t *window, bool minimized) {
window->minimized = minimized;
}
void window_set_floating(window_t *window, bool floating) {
@@ -64,6 +69,10 @@ void window_set_fixed_size(window_t *window, bool fixed_size) {
if (fixed_size) window_set_floating(window, true);
}
void window_set_skip_taskbar(window_t *window, bool skip_taskbar) {
window->skip_taskbar = skip_taskbar;
}
void window_set_float_rect(window_t *window, rect_t rect) {
window->float_rect = rect;
}
@@ -101,10 +110,6 @@ 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;
}
void window_take_metadata(
window_t *window,
window_metadata_t *metadata,
@@ -130,19 +135,13 @@ void window_take_metadata(
bool window_need_layout(const window_t *window) {
if (window->floating) return false;
switch (window->geometry_mode) {
case ZDWM_GEOMETRY_FULLSCREEN:
case ZDWM_GEOMETRY_MAXIMIZED:
case ZDWM_GEOMETRY_MINIMIZED:
if (window->fullscreen || window->maximized || window->minimized) {
return false;
default:
}
return true;
}
bool window_need_resize(const window_t *window, int32_t width, int32_t height);
bool window_need_move(const window_t *window, int32_t x, int32_t y) {
return window->frame_rect.x != x || window->frame_rect.y != y;
}
@@ -153,12 +152,6 @@ bool window_need_resize(const window_t *window, int32_t width, int32_t 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:
}
if (window->fullscreen || window->maximized) return false;
return window->floating;
}

View File

@@ -70,11 +70,14 @@ typedef struct window_t {
workspace_id_t workspace_id;
window_layer_type_t layer;
window_geometry_mode_t geometry_mode;
bool fullscreen;
bool maximized;
bool minimized;
bool floating;
bool sticky;
bool urgent;
bool fixed_size;
bool skip_taskbar;
/* 几何信息(均为包含边框后的外框矩形) */
rect_t float_rect; /* floating 模式下记忆的外框矩形 */
@@ -88,7 +91,6 @@ typedef struct window_t {
char *instance_name;
uint32_t border_width;
bool skip_taskbar;
} window_t;
window_layer_type_t window_classify_layer(const window_layer_props_t *props);
@@ -96,14 +98,14 @@ window_layer_type_t window_classify_layer(const window_layer_props_t *props);
void window_layer_props_cleanup(window_layer_props_t *props);
void window_metadata_cleanup(window_metadata_t *metadata);
void window_set_geometry_mode(
window_t *window,
window_geometry_mode_t geometry_mode
);
void window_set_fullscreen(window_t *window, bool fullscreen);
void window_set_maximized(window_t *window, bool maximized);
void window_set_minimized(window_t *window, bool minimized);
void window_set_floating(window_t *window, bool floating);
void window_set_sticky(window_t *window, bool sticky);
void window_set_urgent(window_t *window, bool urgent);
void window_set_fixed_size(window_t *window, bool fixed_size);
void window_set_skip_taskbar(window_t *window, bool skip_taskbar);
void window_set_float_rect(window_t *window, rect_t rect);
void window_set_frame_rect(window_t *window, rect_t rect);
void window_set_title(window_t *window, const char *title);
@@ -112,7 +114,6 @@ 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,
window_metadata_t *metadata,

View File

@@ -22,8 +22,10 @@ typedef struct window_info_t {
const char *class_name;
const char *instance_name;
window_geometry_mode_t geometry_mode;
window_layer_type_t layer_type;
bool fullscreen;
bool maximized;
bool minimized;
bool urgent;
bool fixed_size;
bool skip_taskbar;