Compare commits
6 Commits
9a1e015fc1
...
74b30a5d4b
| Author | SHA1 | Date | |
|---|---|---|---|
|
74b30a5d4b
|
|||
|
40c2c328cd
|
|||
|
71f050c2f3
|
|||
|
f355b88b82
|
|||
|
f3b1466dac
|
|||
|
b71b66921e
|
@@ -711,19 +711,47 @@ backend_scan_result_t *backend_scan_windows(backend_t *backend) {
|
||||
|
||||
auto list = xcb_query_tree_children(reply);
|
||||
|
||||
backend_scan_result_t *result = p_new(backend_scan_result_t, 1);
|
||||
auto result = p_new(backend_scan_result_t, 1);
|
||||
auto sub_result = p_new(backend_scan_result_t, 1);
|
||||
|
||||
for (int i = 0; i < length; i++) {
|
||||
auto slot = array_push(result->windows, result->count, result->capacity);
|
||||
if (!populate_window_event(backend, list[i], slot)) {
|
||||
for (typeof(length) i = 0; i < length; ++i) {
|
||||
auto window = list[i];
|
||||
auto wa = window_get_attributes(backend, window);
|
||||
if (!wa) continue;
|
||||
|
||||
auto override_redirect = wa->override_redirect;
|
||||
auto map_state = wa->map_state;
|
||||
p_delete(&wa);
|
||||
if (override_redirect) continue;
|
||||
|
||||
auto hints = (xcb_icccm_wm_hints_t){0};
|
||||
auto hints_getted = window_get_wm_hints(backend, window, &hints);
|
||||
if (!(map_state == XCB_MAP_STATE_VIEWABLE ||
|
||||
(hints_getted && hints.initial_state == XCB_ICCCM_WM_STATE_ICONIC))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto transient_for = window_get_transient_for(backend, window);
|
||||
auto r = transient_for == XCB_WINDOW_NONE ? result : sub_result;
|
||||
auto slot = array_push(r->windows, r->count, r->capacity);
|
||||
if (!populate_window_event(backend, list[i], slot) ||
|
||||
slot->override_redirect) {
|
||||
window_layer_props_cleanup(&slot->props);
|
||||
window_metadata_cleanup(&slot->metadata);
|
||||
result->count--;
|
||||
r->count--;
|
||||
}
|
||||
}
|
||||
|
||||
p_delete(&reply);
|
||||
|
||||
for (size_t i = 0; i < sub_result->count; ++i) {
|
||||
auto slot = array_push(result->windows, result->count, result->capacity);
|
||||
*slot = sub_result->windows[i];
|
||||
}
|
||||
|
||||
p_clear(sub_result->windows, sub_result->count);
|
||||
backend_scan_result_destroy(sub_result);
|
||||
|
||||
if (result->count == 0) {
|
||||
backend_scan_result_destroy(result);
|
||||
result = nullptr;
|
||||
|
||||
@@ -52,10 +52,6 @@ static bool derive_skip_taskbar(
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool minimized_from_hints(const xcb_icccm_wm_hints_t *hints) {
|
||||
return hints->initial_state == XCB_ICCCM_WM_STATE_ICONIC;
|
||||
}
|
||||
|
||||
static bool maximized_from_states(
|
||||
const atoms_t *atoms,
|
||||
const xcb_atom_t *state_atoms,
|
||||
@@ -92,6 +88,28 @@ static bool urgent_from_states(
|
||||
return false;
|
||||
}
|
||||
|
||||
static void parse_size_hints(
|
||||
const xcb_size_hints_t *hints,
|
||||
zdwm_size_t *min,
|
||||
zdwm_size_t *max
|
||||
) {
|
||||
assert(hints != nullptr);
|
||||
assert(min != nullptr);
|
||||
assert(max != nullptr);
|
||||
|
||||
*min = (zdwm_size_t){.width = 0, .height = 0};
|
||||
*max = (zdwm_size_t){.width = INT32_MAX, .height = INT32_MAX};
|
||||
|
||||
if (hints->flags & XCB_ICCCM_SIZE_HINT_P_MIN_SIZE) {
|
||||
min->width = hints->min_width;
|
||||
min->height = hints->min_height;
|
||||
}
|
||||
if (hints->flags & XCB_ICCCM_SIZE_HINT_P_MAX_SIZE) {
|
||||
max->width = hints->max_width;
|
||||
max->height = hints->max_height;
|
||||
}
|
||||
}
|
||||
|
||||
bool populate_window_event(
|
||||
backend_t *backend,
|
||||
xcb_window_t window,
|
||||
@@ -100,8 +118,7 @@ bool populate_window_event(
|
||||
ev->window = (window_id_t)window;
|
||||
ev->transient_for = window_get_transient_for(backend, window);
|
||||
|
||||
xcb_get_window_attributes_reply_t *wa =
|
||||
window_get_attributes(backend, window);
|
||||
auto wa = window_get_attributes(backend, window);
|
||||
if (!wa) return false;
|
||||
ev->override_redirect = (bool)wa->override_redirect;
|
||||
p_delete(&wa);
|
||||
@@ -109,10 +126,13 @@ bool populate_window_event(
|
||||
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->minimized = minimized_from_hints(&wm_hints);
|
||||
ev->minimized = wm_hints.initial_state == XCB_ICCCM_WM_STATE_ICONIC;
|
||||
}
|
||||
|
||||
if (!window_get_fixed_size(backend, window, &ev->fixed_size)) return false;
|
||||
xcb_size_hints_t size_hints = {0};
|
||||
if (!window_get_size_hints(backend, window, &size_hints)) return false;
|
||||
parse_size_hints(&size_hints, &ev->min_size, &ev->max_size);
|
||||
|
||||
if (!window_get_geometry(backend, window, &ev->rect)) return false;
|
||||
|
||||
const atoms_t *atoms = &backend->atoms;
|
||||
@@ -360,34 +380,31 @@ static bool handle_property_notify(
|
||||
|
||||
if (xcb_event->atom == XCB_ATOM_WM_HINTS) {
|
||||
xcb_icccm_wm_hints_t hints = {0};
|
||||
auto handled = window_get_wm_hints(backend, window_id, &hints);
|
||||
if (!handled) return false;
|
||||
if (!window_get_wm_hints(backend, window_id, &hints)) return false;
|
||||
|
||||
event->type = ZDWM_EVENT_WINDOW_STATE_REQUEST;
|
||||
event->type = ZDWM_EVENT_WINDOW_HINTS_CHANGED;
|
||||
|
||||
auto data = &event->as.window_state_request;
|
||||
auto data = &event->as.hints;
|
||||
data->window = window_id;
|
||||
if (hints.flags & XCB_ICCCM_WM_HINT_X_URGENCY) {
|
||||
data->type = ZDWM_WINDOW_STATE_REQUEST_URGENT;
|
||||
data->action = xcb_icccm_wm_hints_get_urgency(&hints)
|
||||
? ZDWM_WINDOW_STATE_ACTION_ADD
|
||||
: ZDWM_WINDOW_STATE_ACTION_REMOVE;
|
||||
data->changed_fields |= ZDWM_HINT_FIELD_URGENT;
|
||||
data->urgent = xcb_icccm_wm_hints_get_urgency(&hints);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (xcb_event->atom == XCB_ATOM_WM_NORMAL_HINTS) {
|
||||
bool fixed_size = false;
|
||||
if (!window_get_fixed_size(backend, window_id, &fixed_size)) return false;
|
||||
xcb_size_hints_t hints = {0};
|
||||
if (!window_get_size_hints(backend, window_id, &hints)) return false;
|
||||
|
||||
event->type = ZDWM_EVENT_WINDOW_STATE_REQUEST;
|
||||
event->type = ZDWM_EVENT_WINDOW_HINTS_CHANGED;
|
||||
|
||||
auto data = &event->as.window_state_request;
|
||||
auto data = &event->as.hints;
|
||||
data->window = window_id;
|
||||
data->type = ZDWM_WINDOW_STATE_REQUEST_FIXED_SIZE;
|
||||
data->action = fixed_size ? ZDWM_WINDOW_STATE_ACTION_ADD
|
||||
: ZDWM_WINDOW_STATE_ACTION_REMOVE;
|
||||
|
||||
data->changed_fields |= ZDWM_HINT_FIELD_SIZE;
|
||||
parse_size_hints(&hints, &data->min_size, &data->max_size);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -467,7 +484,11 @@ static bool handle_client_message(
|
||||
}
|
||||
|
||||
if (urgent_from_states(atoms, properties, count)) {
|
||||
data->type = ZDWM_WINDOW_STATE_REQUEST_URGENT;
|
||||
event->type = ZDWM_EVENT_WINDOW_HINTS_CHANGED;
|
||||
event->as.hints = (typeof(event->as.hints)){
|
||||
.urgent = true,
|
||||
.changed_fields = ZDWM_HINT_FIELD_URGENT,
|
||||
};
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -160,22 +160,18 @@ bool window_get_types(
|
||||
return true;
|
||||
}
|
||||
|
||||
bool window_get_fixed_size(backend_t *backend, xcb_window_t window, bool *out) {
|
||||
xcb_size_hints_t hints = {0};
|
||||
bool window_get_size_hints(
|
||||
backend_t *backend,
|
||||
xcb_window_t window,
|
||||
xcb_size_hints_t *out
|
||||
) {
|
||||
xcb_connection_t *conn = backend->conn;
|
||||
xcb_get_property_cookie_t cookie =
|
||||
xcb_icccm_get_wm_normal_hints_unchecked(conn, window);
|
||||
if (!xcb_icccm_get_wm_normal_hints_reply(conn, cookie, &hints, nullptr)) {
|
||||
if (!xcb_icccm_get_wm_normal_hints_reply(conn, cookie, out, nullptr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((hints.flags & XCB_ICCCM_SIZE_HINT_P_MIN_SIZE) &&
|
||||
(hints.flags & XCB_ICCCM_SIZE_HINT_P_MAX_SIZE)) {
|
||||
*out = hints.min_width == hints.max_width &&
|
||||
hints.min_height == hints.max_height;
|
||||
} else {
|
||||
*out = false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -54,7 +54,11 @@ bool window_get_types(
|
||||
window_type_t **types,
|
||||
size_t *count
|
||||
);
|
||||
bool window_get_fixed_size(backend_t *backend, xcb_window_t window, bool *out);
|
||||
bool window_get_size_hints(
|
||||
backend_t *backend,
|
||||
xcb_window_t window,
|
||||
xcb_size_hints_t *out
|
||||
);
|
||||
bool window_get_geometry(backend_t *backend, xcb_window_t window, rect_t *out);
|
||||
bool window_get_atom_array(
|
||||
backend_t *backend,
|
||||
|
||||
@@ -22,6 +22,7 @@ typedef enum command_type_t {
|
||||
ZDWM_COMMAND_WINDOW_SET_MINIMIZED,
|
||||
ZDWM_COMMAND_WINDOW_SET_MAXIMIZED,
|
||||
ZDWM_COMMAND_WINDOW_SET_FULLSCREEN,
|
||||
ZDWM_COMMAND_CHANGE_HINTS,
|
||||
ZDWM_COMMAND_SWITCH_WORKSPACE,
|
||||
ZDWM_COMMAND_SET_CURRENT_OUTPUT,
|
||||
ZDWM_COMMAND_SET_LAYOUT,
|
||||
@@ -110,6 +111,7 @@ typedef struct command_t {
|
||||
window_bool_state_t minimized;
|
||||
window_bool_state_t maximized;
|
||||
window_bool_state_t fullscreen;
|
||||
hints_data_t hints;
|
||||
switch_workspace_command_t switch_workspace;
|
||||
set_current_output_command_t current_output;
|
||||
set_layout_command_t layout;
|
||||
|
||||
@@ -47,12 +47,14 @@ typedef struct window_map_request_event_t {
|
||||
bool override_redirect;
|
||||
bool skip_taskbar;
|
||||
bool urgent;
|
||||
bool fixed_size;
|
||||
bool fullscreen;
|
||||
bool maximized;
|
||||
bool minimized;
|
||||
rect_t rect;
|
||||
|
||||
zdwm_size_t min_size;
|
||||
zdwm_size_t max_size;
|
||||
|
||||
window_layer_props_t props;
|
||||
window_metadata_t metadata;
|
||||
} window_map_request_event_t;
|
||||
@@ -101,6 +103,7 @@ typedef struct event_t {
|
||||
window_map_request_event_t window_map_request;
|
||||
window_remove_event_t window_remove;
|
||||
window_metadata_change_event_t window_metadata_change;
|
||||
hints_data_t hints;
|
||||
window_activate_request_event_t window_activate_request;
|
||||
window_state_request_event_t window_state_request;
|
||||
configure_data_t configure_request;
|
||||
|
||||
@@ -517,6 +517,7 @@ static void route_pointer_motion(
|
||||
command_buffer_t *out
|
||||
) {
|
||||
auto interaction = ctx->interaction;
|
||||
auto window_id = interaction->window;
|
||||
|
||||
switch (interaction->mode) {
|
||||
case ZDWM_WINDOW_INTERACTION_NONE:
|
||||
@@ -538,14 +539,24 @@ static void route_pointer_motion(
|
||||
command_buffer_push(out, &configure);
|
||||
} break;
|
||||
case ZDWM_WINDOW_INTERACTION_RESIZE: {
|
||||
auto window = state_window_get(ctx->state, window_id);
|
||||
if (!window_can_resize(window)) break;
|
||||
|
||||
auto rect = interaction->origin_rect;
|
||||
auto start = interaction->start_coordinate;
|
||||
auto end = data->root;
|
||||
|
||||
auto min_size = window->min_size;
|
||||
auto max_size = window->max_size;
|
||||
|
||||
auto width = rect.width + (end.x - start.x);
|
||||
auto height = rect.height + (end.y - start.y);
|
||||
width = MAX(width, 10);
|
||||
height = MAX(height, 10);
|
||||
width = MAX(width, min_size.width);
|
||||
height = MAX(height, min_size.height);
|
||||
width = MIN(width, max_size.width);
|
||||
height = MIN(height, max_size.height);
|
||||
|
||||
if (!window_need_resize(window, width, height)) break;
|
||||
|
||||
command_t configure_cmd = {
|
||||
.type = ZDWM_COMMAND_CONFIGURE_WINDOW,
|
||||
@@ -606,8 +617,9 @@ static void route_map_request(
|
||||
.maximized = e->maximized,
|
||||
.minimized = e->minimized,
|
||||
.urgent = e->urgent,
|
||||
.fixed_size = e->fixed_size,
|
||||
.skip_taskbar = e->skip_taskbar,
|
||||
.min_size = e->min_size,
|
||||
.max_size = e->max_size,
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -690,28 +702,35 @@ static void route_window_metadata_changed(
|
||||
listeners_notify_window_updated(ctx->listeners, state, window_id);
|
||||
}
|
||||
|
||||
static void route_window_hints_changed(
|
||||
state_t *state,
|
||||
const hints_data_t *data,
|
||||
command_buffer_t *out
|
||||
) {
|
||||
auto window = (window_t *)state_window_get(state, data->window);
|
||||
if (!window) return;
|
||||
|
||||
command_t change_hints_cmd = {
|
||||
.type = ZDWM_COMMAND_CHANGE_HINTS,
|
||||
.as.hints = *data,
|
||||
};
|
||||
command_buffer_push(out, &change_hints_cmd);
|
||||
}
|
||||
|
||||
static void route_window_activate_request(
|
||||
state_t *state,
|
||||
const window_activate_request_event_t *e,
|
||||
command_buffer_t *out
|
||||
) {
|
||||
auto window = state_window_get(state, e->window);
|
||||
auto window = (window_t *)state_window_get(state, e->window);
|
||||
if (!window) return;
|
||||
|
||||
switch (e->source) {
|
||||
case ZDWM_WINDOW_ACTIVATION_SOURCE_LEGACY:
|
||||
break;
|
||||
case ZDWM_WINDOW_ACTIVATION_SOURCE_APPLICATION: {
|
||||
command_t change_window_state_cmd = {
|
||||
.type = ZDWM_COMMAND_CHANGE_WINDOW_STATE,
|
||||
.as.state_change = {
|
||||
.type = ZDWM_WINDOW_STATE_REQUEST_URGENT,
|
||||
.window = window->id,
|
||||
.action = ZDWM_WINDOW_STATE_ACTION_ADD,
|
||||
}
|
||||
};
|
||||
command_buffer_push(out, &change_window_state_cmd);
|
||||
} break;
|
||||
case ZDWM_WINDOW_ACTIVATION_SOURCE_APPLICATION:
|
||||
window->urgent = true;
|
||||
break;
|
||||
case ZDWM_WINDOW_ACTIVATION_SOURCE_PAGER:
|
||||
add_switch_workspace_command(out, window->workspace_id);
|
||||
add_focus_window_command(out, window->id);
|
||||
@@ -776,6 +795,8 @@ void policy_route_event(
|
||||
) {
|
||||
auto state = ctx->state;
|
||||
switch (event->type) {
|
||||
case ZDWM_EVENT_NONE:
|
||||
break;
|
||||
case ZDWM_EVENT_KEY_PRESS:
|
||||
route_key_press(ctx, &event->as.key_press, out);
|
||||
break;
|
||||
@@ -800,6 +821,9 @@ void policy_route_event(
|
||||
case ZDWM_EVENT_WINDOW_METADATA_CHANGED:
|
||||
route_window_metadata_changed(ctx, &event->as.window_metadata_change);
|
||||
break;
|
||||
case ZDWM_EVENT_WINDOW_HINTS_CHANGED:
|
||||
route_window_hints_changed(state, &event->as.hints, out);
|
||||
break;
|
||||
case ZDWM_EVENT_WINDOW_ACTIVATE_REQUEST: {
|
||||
auto data = &event->as.window_activate_request;
|
||||
route_window_activate_request(state, data, out);
|
||||
@@ -811,7 +835,6 @@ void policy_route_event(
|
||||
auto data = &event->as.configure_request;
|
||||
route_configure_request(state, data, ctx->layouts, out);
|
||||
} break;
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
@@ -842,9 +865,6 @@ static void set_foucs_window(
|
||||
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);
|
||||
plan_push_focus_effect(plan, window_id);
|
||||
|
||||
@@ -852,9 +872,12 @@ static void set_foucs_window(
|
||||
auto color = &border->focused_color;
|
||||
plan_push_change_border_color_effect(plan, window_id, color);
|
||||
}
|
||||
if (state_window_get(state, old_focused_window_id)) {
|
||||
for (size_t i = 0; i < state_window_count(state); ++i) {
|
||||
auto window = state_window_at(state, i);
|
||||
if (window->workspace_id != workspace_id) continue;
|
||||
if (workspace->focused_window_id == window->id) continue;
|
||||
auto color = &border->normal_color;
|
||||
plan_push_change_border_color_effect(plan, old_focused_window_id, color);
|
||||
plan_push_change_border_color_effect(plan, window->id, color);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -902,14 +925,22 @@ static void manage_window(
|
||||
auto window_id = 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);
|
||||
plan_push_grab_button_effect(plan, window_id);
|
||||
push_window_list_effect(state, plan);
|
||||
listeners_notify_window_added(ctx->listeners, state, window_id);
|
||||
|
||||
if (window_should_fix_size(window)) {
|
||||
state_window_set_floating(state, window_id, true);
|
||||
} else {
|
||||
state_window_set_floating(state, window_id, command->floating);
|
||||
}
|
||||
|
||||
auto workspace = state_workspace_get(state, workspace_id);
|
||||
auto need_layout = window_need_layout(window);
|
||||
if (need_layout) {
|
||||
auto layout_func = layout_get(ctx->layouts, workspace->layout_id);
|
||||
|
||||
if (need_layout && layout_func) {
|
||||
adjust_layout_windows_border_width(state, ctx->border->width, workspace_id);
|
||||
} else {
|
||||
state_window_set_border_width(state, window_id, ctx->border->width);
|
||||
@@ -920,12 +951,8 @@ static void manage_window(
|
||||
plan_push_map_effect(plan, window_id);
|
||||
plan_push_focus_effect(plan, window_id);
|
||||
|
||||
if (window_need_layout(window)) {
|
||||
plan->need_relayout = true;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
effect_t configure_effect = {
|
||||
.type = ZDWM_EFFECT_CONFIGURE_WINDOW,
|
||||
.as.configure = {
|
||||
@@ -1297,12 +1324,6 @@ static void change_window_state(
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1320,12 +1341,6 @@ static void change_window_state(
|
||||
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;
|
||||
}
|
||||
|
||||
listeners_notify_window_updated(ctx->listeners, state, command->window);
|
||||
@@ -1490,12 +1505,20 @@ static void command_window_set_maximized(
|
||||
maximize_window(ctx, data->window, data->state, plan);
|
||||
}
|
||||
|
||||
static void command_window_set_fullscreen(
|
||||
const policy_context_t *ctx,
|
||||
const window_bool_state_t *data,
|
||||
plan_t *plan
|
||||
) {
|
||||
fullscreen_window(ctx, data->window, data->state, plan);
|
||||
static void
|
||||
command_change_hints(state_t *state, hints_data_t *data, plan_t *plan) {
|
||||
auto window = (window_t *)state_window_get(state, data->window);
|
||||
if (data->changed_fields & ZDWM_HINT_FIELD_URGENT) {
|
||||
window->urgent = data->urgent;
|
||||
}
|
||||
if (data->changed_fields & ZDWM_HINT_FIELD_SIZE) {
|
||||
window->max_size = data->max_size;
|
||||
window->min_size = data->min_size;
|
||||
|
||||
auto floating = window->floating;
|
||||
if (window_should_fix_size(window)) window_set_floating(window, true);
|
||||
if (floating != window->floating) plan->need_relayout = true;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void change_current_output(
|
||||
@@ -1674,8 +1697,13 @@ void policy_apply_command(
|
||||
case ZDWM_COMMAND_WINDOW_SET_MAXIMIZED:
|
||||
command_window_set_maximized(ctx, &cmd->as.maximized, plan);
|
||||
break;
|
||||
case ZDWM_COMMAND_WINDOW_SET_FULLSCREEN:
|
||||
command_window_set_fullscreen(ctx, &cmd->as.fullscreen, plan);
|
||||
case ZDWM_COMMAND_WINDOW_SET_FULLSCREEN: {
|
||||
auto window = cmd->as.fullscreen.window;
|
||||
auto state = cmd->as.fullscreen.state;
|
||||
fullscreen_window(ctx, window, state, plan);
|
||||
} break;
|
||||
case ZDWM_COMMAND_CHANGE_HINTS:
|
||||
command_change_hints(state, &cmd->as.hints, plan);
|
||||
break;
|
||||
case ZDWM_COMMAND_SWITCH_WORKSPACE:
|
||||
switch_workspace(ctx, cmd->as.switch_workspace.workspace, plan);
|
||||
|
||||
@@ -328,9 +328,9 @@ const window_t *state_window_add(state_t *state, const window_info_t *info) {
|
||||
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);
|
||||
window_set_float_rect(window, info->frame_rect);
|
||||
window_set_size_hint(window, info->min_size, info->max_size);
|
||||
window_set_title(window, info->title);
|
||||
window_set_app_id(window, info->app_id);
|
||||
window_set_role(window, info->role);
|
||||
@@ -469,24 +469,6 @@ void state_window_set_sticky(
|
||||
if (window) window_set_sticky(window, sticky);
|
||||
}
|
||||
|
||||
void state_window_set_urgent(
|
||||
state_t *state,
|
||||
window_id_t window_id,
|
||||
bool urgent
|
||||
) {
|
||||
window_t *window = (window_t *)state_window_get(state, window_id);
|
||||
if (window) window_set_urgent(window, urgent);
|
||||
}
|
||||
|
||||
void state_window_set_fixed_size(
|
||||
state_t *state,
|
||||
window_id_t window_id,
|
||||
bool fixed_size
|
||||
) {
|
||||
window_t *window = (window_t *)state_window_get(state, window_id);
|
||||
if (window) window_set_fixed_size(window, fixed_size);
|
||||
}
|
||||
|
||||
void state_window_set_border_width(
|
||||
state_t *state,
|
||||
window_id_t window_id,
|
||||
@@ -502,7 +484,7 @@ void state_window_set_skip_taskbar(
|
||||
bool skip_taskbar
|
||||
) {
|
||||
window_t *window = (window_t *)state_window_get(state, window_id);
|
||||
if (window) window_set_skip_taskbar(window, skip_taskbar);
|
||||
if (window) window->skip_taskbar = skip_taskbar;
|
||||
}
|
||||
|
||||
void state_window_set_float_rect(
|
||||
|
||||
@@ -224,16 +224,6 @@ void state_window_set_sticky(
|
||||
window_id_t window_id,
|
||||
bool sticky
|
||||
);
|
||||
void state_window_set_urgent(
|
||||
state_t *state,
|
||||
window_id_t window_id,
|
||||
bool urgent
|
||||
);
|
||||
void state_window_set_fixed_size(
|
||||
state_t *state,
|
||||
window_id_t window_id,
|
||||
bool fixed_size
|
||||
);
|
||||
void state_window_set_border_width(
|
||||
state_t *state,
|
||||
window_id_t window_id,
|
||||
|
||||
@@ -72,8 +72,6 @@ typedef enum window_state_request_type_t {
|
||||
ZDWM_WINDOW_STATE_REQUEST_MAXIMIZED,
|
||||
ZDWM_WINDOW_STATE_REQUEST_MINIMIZED,
|
||||
ZDWM_WINDOW_STATE_REQUEST_SKIP_TASKBAR,
|
||||
ZDWM_WINDOW_STATE_REQUEST_URGENT,
|
||||
ZDWM_WINDOW_STATE_REQUEST_FIXED_SIZE,
|
||||
} window_state_request_type_t;
|
||||
|
||||
typedef enum window_state_request_action_t {
|
||||
@@ -114,6 +112,24 @@ typedef struct only_window_data_t {
|
||||
window_id_t window;
|
||||
} only_window_data_t;
|
||||
|
||||
typedef enum hint_field_t {
|
||||
ZDWM_HINT_FIELD_URGENT,
|
||||
ZDWM_HINT_FIELD_SIZE,
|
||||
} hint_field_t;
|
||||
|
||||
typedef struct zdwm_size_t {
|
||||
int32_t width;
|
||||
int32_t height;
|
||||
} zdwm_size_t;
|
||||
|
||||
typedef struct hints_data_t {
|
||||
window_id_t window;
|
||||
uint32_t changed_fields;
|
||||
bool urgent;
|
||||
zdwm_size_t min_size;
|
||||
zdwm_size_t max_size;
|
||||
} hints_data_t;
|
||||
|
||||
typedef enum window_interaction_mode_t {
|
||||
ZDWM_WINDOW_INTERACTION_NONE,
|
||||
ZDWM_WINDOW_INTERACTION_MOVE,
|
||||
|
||||
@@ -49,7 +49,7 @@ void window_set_minimized(window_t *window, bool minimized) {
|
||||
}
|
||||
|
||||
void window_set_floating(window_t *window, bool floating) {
|
||||
if (!floating && (window->fixed_size || window->sticky)) return;
|
||||
if (!floating && (window_should_fix_size(window) || window->sticky)) return;
|
||||
|
||||
if (floating == window->floating) return;
|
||||
|
||||
@@ -67,11 +67,6 @@ void window_set_urgent(window_t *window, bool urgent) {
|
||||
window->urgent = urgent;
|
||||
}
|
||||
|
||||
void window_set_fixed_size(window_t *window, bool fixed_size) {
|
||||
window->fixed_size = 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;
|
||||
}
|
||||
@@ -84,6 +79,18 @@ void window_set_frame_rect(window_t *window, rect_t rect) {
|
||||
window->frame_rect = rect;
|
||||
}
|
||||
|
||||
void window_set_size_hint(window_t *window, zdwm_size_t min, zdwm_size_t max) {
|
||||
window->min_size = min;
|
||||
window->max_size = max;
|
||||
if (!window_should_fix_size(window)) return;
|
||||
|
||||
auto rect = window->frame_rect;
|
||||
rect.width = min.width;
|
||||
rect.height = min.height;
|
||||
window_set_frame_rect(window, rect);
|
||||
window_set_floating(window, true);
|
||||
}
|
||||
|
||||
void window_set_title(window_t *window, const char *title) {
|
||||
p_delete(&window->title);
|
||||
window->title = p_strdup_nullable(title);
|
||||
@@ -158,3 +165,16 @@ bool window_should_has_border(const window_t *window) {
|
||||
if (window->fullscreen || window->maximized) return false;
|
||||
return window->floating;
|
||||
}
|
||||
|
||||
bool window_should_fix_size(const window_t *window) {
|
||||
auto max = window->max_size;
|
||||
auto min = window->min_size;
|
||||
return max.width == min.width && max.height == min.height;
|
||||
}
|
||||
|
||||
bool window_can_resize(const window_t *window) {
|
||||
if (window->fullscreen || window->maximized) return false;
|
||||
if (window_should_fix_size(window)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -76,9 +76,11 @@ typedef struct window_t {
|
||||
bool floating;
|
||||
bool sticky;
|
||||
bool urgent;
|
||||
bool fixed_size;
|
||||
bool skip_taskbar;
|
||||
|
||||
zdwm_size_t min_size;
|
||||
zdwm_size_t max_size;
|
||||
|
||||
/* 几何信息(均为包含边框后的外框矩形) */
|
||||
rect_t float_rect; /* floating 模式下记忆的外框矩形 */
|
||||
rect_t frame_rect; /* 当前外框矩形(由 layout 或 float_rect 解析) */
|
||||
@@ -104,10 +106,10 @@ 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_size_hint(window_t *window, zdwm_size_t min, zdwm_size_t max);
|
||||
void window_set_title(window_t *window, const char *title);
|
||||
void window_set_app_id(window_t *window, const char *app_id);
|
||||
void window_set_role(window_t *window, const char *role);
|
||||
@@ -127,3 +129,5 @@ 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);
|
||||
bool window_should_fix_size(const window_t *window);
|
||||
bool window_can_resize(const window_t *window);
|
||||
|
||||
@@ -27,8 +27,10 @@ typedef struct window_info_t {
|
||||
bool maximized;
|
||||
bool minimized;
|
||||
bool urgent;
|
||||
bool fixed_size;
|
||||
bool skip_taskbar;
|
||||
|
||||
zdwm_size_t min_size;
|
||||
zdwm_size_t max_size;
|
||||
} window_info_t;
|
||||
|
||||
typedef struct workspace_desc_t {
|
||||
|
||||
@@ -303,9 +303,6 @@ static const layout_result_t *runtime_layout_calc(runtime_t *runtime) {
|
||||
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;
|
||||
@@ -333,7 +330,8 @@ static const layout_result_t *runtime_layout_calc(runtime_t *runtime) {
|
||||
}
|
||||
}
|
||||
|
||||
if (window_count) {
|
||||
auto layout_func = layout_get(&runtime->layouts, workspace->layout_id);
|
||||
if (window_count && layout_func) {
|
||||
zdwm_layout_ctx_t ctx = {
|
||||
.workspace_id = workspace->id,
|
||||
.focused_window_id = workspace->focused_window_id,
|
||||
@@ -342,7 +340,7 @@ static const layout_result_t *runtime_layout_calc(runtime_t *runtime) {
|
||||
.window_ids = window_ids,
|
||||
.window_count = window_count,
|
||||
};
|
||||
layout_slot->fn(&ctx, result);
|
||||
layout_func(&ctx, result);
|
||||
}
|
||||
|
||||
if (window_ids) p_delete(&window_ids);
|
||||
|
||||
Reference in New Issue
Block a user