Compare commits
9 Commits
b14be7b8dd
...
9275d14c5f
| Author | SHA1 | Date | |
|---|---|---|---|
|
9275d14c5f
|
|||
|
c1a4795a85
|
|||
|
8fcf46979a
|
|||
|
56f8380028
|
|||
|
2c3c264ddd
|
|||
|
3031adf3cb
|
|||
|
1b6a4788be
|
|||
|
474ed8dc69
|
|||
|
964de33b23
|
@@ -22,8 +22,10 @@
|
||||
#include "base/macros.h"
|
||||
#include "base/memory.h"
|
||||
#include "base/window_list.h"
|
||||
#include "core/event.h"
|
||||
#include "core/plan.h"
|
||||
#include "core/types.h"
|
||||
#include "core/window.h"
|
||||
#include "internal.h"
|
||||
|
||||
typedef struct atom_item_t {
|
||||
@@ -625,3 +627,54 @@ bool backend_apply_effect(
|
||||
xcb_flush(backend->conn);
|
||||
return true;
|
||||
}
|
||||
|
||||
backend_scan_result_t *backend_scan_windows(backend_t *backend) {
|
||||
auto conn = backend->conn;
|
||||
auto root = backend->screen->root;
|
||||
auto cookie = xcb_query_tree_unchecked(conn, root);
|
||||
auto reply = xcb_query_tree_reply(conn, cookie, nullptr);
|
||||
if (!reply) return nullptr;
|
||||
|
||||
auto length = xcb_query_tree_children_length(reply);
|
||||
if (!length) {
|
||||
p_delete(&reply);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto list = xcb_query_tree_children(reply);
|
||||
|
||||
backend_scan_result_t *result = p_new(backend_scan_result_t, 1);
|
||||
|
||||
for (int i = 0; i < length; i++) {
|
||||
auto slot = (window_map_request_event_t *)
|
||||
array_push(result->windows, result->count, result->capacity);
|
||||
if (!populate_window_event(backend, list[i], slot)) {
|
||||
window_layer_props_cleanup(&slot->props);
|
||||
window_metadata_cleanup(&slot->metadata);
|
||||
result->count--;
|
||||
}
|
||||
}
|
||||
|
||||
p_delete(&reply);
|
||||
|
||||
if (result->count == 0) {
|
||||
backend_scan_result_destroy(result);
|
||||
result = nullptr;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void backend_scan_result_destroy(backend_scan_result_t *result) {
|
||||
if (!result) return;
|
||||
|
||||
for (size_t i = 0; i < result->count; i++) {
|
||||
window_map_request_event_t *ev = &result->windows[i];
|
||||
window_layer_props_cleanup(&ev->props);
|
||||
window_metadata_cleanup(&ev->metadata);
|
||||
}
|
||||
|
||||
p_delete(&result->windows);
|
||||
p_delete(&result);
|
||||
}
|
||||
|
||||
@@ -91,16 +91,11 @@ static bool urgent_from_states(
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool handle_map_request(
|
||||
bool populate_window_event(
|
||||
backend_t *backend,
|
||||
event_t *event,
|
||||
const xcb_map_request_event_t *xcb_event
|
||||
xcb_window_t window,
|
||||
window_map_request_event_t *ev
|
||||
) {
|
||||
xcb_window_t window = xcb_event->window;
|
||||
|
||||
event->type = ZDWM_EVENT_WINDOW_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);
|
||||
|
||||
@@ -167,6 +162,19 @@ static bool handle_map_request(
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool handle_map_request(
|
||||
backend_t *backend,
|
||||
event_t *event,
|
||||
const xcb_map_request_event_t *xcb_event
|
||||
) {
|
||||
event->type = ZDWM_EVENT_WINDOW_MAP_REQUEST;
|
||||
return populate_window_event(
|
||||
backend,
|
||||
xcb_event->window,
|
||||
&event->as.window_map_request
|
||||
);
|
||||
}
|
||||
|
||||
static bool handle_unmap_notify(
|
||||
backend_t *backend,
|
||||
event_t *event,
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <xcb/xproto.h>
|
||||
|
||||
#include "base/window_list.h"
|
||||
#include "core/event.h"
|
||||
|
||||
#define ATOM_LIST(X) \
|
||||
X(COMPOUND_TEXT) \
|
||||
@@ -94,3 +95,9 @@ struct backend_t {
|
||||
window_list_t map;
|
||||
window_list_t kill;
|
||||
};
|
||||
|
||||
bool populate_window_event(
|
||||
struct backend_t *backend,
|
||||
xcb_window_t window,
|
||||
window_map_request_event_t *ev
|
||||
);
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
#include <zdwm/action.h>
|
||||
#include <zdwm/types.h>
|
||||
|
||||
#include "base/log.h"
|
||||
#include "base/macros.h"
|
||||
|
||||
static constexpr char launcher[] =
|
||||
@@ -32,7 +31,6 @@ static void quit(
|
||||
const zdwm_action_api_t *api,
|
||||
const zdwm_action_arg_t *arg
|
||||
) {
|
||||
logger("quit: restart: %s\n", arg->b ? "true" : "false");
|
||||
api->quit(runtime, arg->b);
|
||||
}
|
||||
|
||||
@@ -45,6 +43,30 @@ static void raise_or_run(
|
||||
api->raise_or_run(runtime, args->class_name, args->command);
|
||||
}
|
||||
|
||||
static void toggle_fullscreen(
|
||||
zdwm_runtime_t *runtime,
|
||||
const zdwm_action_api_t *api,
|
||||
const zdwm_action_arg_t *arg
|
||||
) {
|
||||
api->toggle_fullscreen(runtime);
|
||||
}
|
||||
|
||||
static void toggle_maximize(
|
||||
zdwm_runtime_t *runtime,
|
||||
const zdwm_action_api_t *api,
|
||||
const zdwm_action_arg_t *arg
|
||||
) {
|
||||
api->toggle_maximize(runtime);
|
||||
}
|
||||
|
||||
static void toggle_floating(
|
||||
zdwm_runtime_t *runtime,
|
||||
const zdwm_action_api_t *api,
|
||||
const zdwm_action_arg_t *arg
|
||||
) {
|
||||
api->toggle_floating(runtime);
|
||||
}
|
||||
|
||||
bool config_defaults_build(
|
||||
const zdwm_api_t *api,
|
||||
zdwm_config_builder_t *builder,
|
||||
@@ -118,6 +140,9 @@ bool config_defaults_build(
|
||||
BIND(default_mode, Super "+e", raise_or_run, {.ptr = &editor});
|
||||
BIND(default_mode, Super "+q", raise_or_run, {.ptr = &browser});
|
||||
BIND(default_mode, Super "+a", raise_or_run, {.ptr = &chrome});
|
||||
BIND(default_mode, Super "+f", toggle_fullscreen, {0});
|
||||
BIND(default_mode, Super "+m", toggle_maximize, {0});
|
||||
BIND(default_mode, Super "+Control+space", toggle_floating, {0});
|
||||
|
||||
#undef BIND
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <paths.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
@@ -10,6 +11,7 @@
|
||||
#include "base/macros.h"
|
||||
#include "core/command.h"
|
||||
#include "core/command_buffer.h"
|
||||
#include "core/runtime.h"
|
||||
#include "core/state.h"
|
||||
#include "core/types.h"
|
||||
#include "core/window.h"
|
||||
@@ -66,7 +68,7 @@ get_next_window_by_class(state_t *state, const char *class_name) {
|
||||
}
|
||||
|
||||
void raise_or_run(
|
||||
zdwm_runtime_t *runtime,
|
||||
runtime_t *runtime,
|
||||
const char *class_name,
|
||||
const char *command
|
||||
) {
|
||||
@@ -88,3 +90,90 @@ void raise_or_run(
|
||||
};
|
||||
command_buffer_push(&runtime->command_buffer, &focus_cmd);
|
||||
}
|
||||
|
||||
static const window_t *get_current_focused_window(const state_t *state) {
|
||||
auto output = state_output_at(state, state->current_output_index);
|
||||
auto workspace = state_workspace_get(state, output->current_workspace_id);
|
||||
return state_window_get(state, workspace->focused_window_id);
|
||||
}
|
||||
|
||||
void toggle_fullscreen(runtime_t *runtime) {
|
||||
auto window = get_current_focused_window(&runtime->state);
|
||||
if (!window) return;
|
||||
|
||||
command_t window_set_fullscreen_cmd = {
|
||||
.type = ZDWM_COMMAND_WINDOW_SET_FULLSCREEN,
|
||||
.as.fullscreen = {
|
||||
.window = window->id,
|
||||
.state = !window->fullscreen,
|
||||
}
|
||||
};
|
||||
command_buffer_push(&runtime->command_buffer, &window_set_fullscreen_cmd);
|
||||
}
|
||||
|
||||
void toggle_maximize(runtime_t *runtime) {
|
||||
auto window = get_current_focused_window(&runtime->state);
|
||||
if (!window) return;
|
||||
|
||||
command_t window_set_maximized_cmd = {
|
||||
.type = ZDWM_COMMAND_WINDOW_SET_MAXIMIZED,
|
||||
.as.maximized = {
|
||||
.window = window->id,
|
||||
.state = !window->maximized,
|
||||
}
|
||||
};
|
||||
command_buffer_push(&runtime->command_buffer, &window_set_maximized_cmd);
|
||||
}
|
||||
|
||||
void toggle_floating(runtime_t *runtime) {
|
||||
auto window = get_current_focused_window(&runtime->state);
|
||||
if (!window) return;
|
||||
|
||||
command_t window_set_floating_cmd = {
|
||||
.type = ZDWM_COMMAND_WINDOW_SET_FLOATING,
|
||||
.as.floating = {
|
||||
.window = window->id,
|
||||
.state = !window->floating,
|
||||
}
|
||||
};
|
||||
command_buffer_push(&runtime->command_buffer, &window_set_floating_cmd);
|
||||
}
|
||||
|
||||
void toggle_sticky(runtime_t *runtime) {
|
||||
auto window = get_current_focused_window(&runtime->state);
|
||||
if (!window) return;
|
||||
|
||||
command_t window_set_sticky_cmd = {
|
||||
.type = ZDWM_COMMAND_WINDOW_SET_STICKY,
|
||||
.as.sticky = {
|
||||
.window = window->id,
|
||||
.state = !window->sticky,
|
||||
}
|
||||
};
|
||||
command_buffer_push(&runtime->command_buffer, &window_set_sticky_cmd);
|
||||
}
|
||||
|
||||
void switch_workspace(runtime_t *runtime, workspace_id_t workspace_id) {
|
||||
auto workspace = state_workspace_get(&runtime->state, workspace_id);
|
||||
if (!workspace) return;
|
||||
|
||||
command_t switch_workspace_cmd = {
|
||||
.type = ZDWM_COMMAND_SWITCH_WORKSPACE,
|
||||
.as.switch_workspace.workspace = workspace_id
|
||||
};
|
||||
command_buffer_push(&runtime->command_buffer, &switch_workspace_cmd);
|
||||
}
|
||||
|
||||
void cycle_layout(runtime_t *runtime, int32_t delta) {
|
||||
auto state = &runtime->state;
|
||||
auto output = state_output_at(state, state->current_output_index);
|
||||
auto workspace = state_workspace_get(state, output->current_workspace_id);
|
||||
if (!state_workspace_cycle_layout(state, workspace->id, delta)) return;
|
||||
|
||||
runtime->plan.need_relayout = true;
|
||||
}
|
||||
|
||||
void cycle_current_output(runtime_t *runtime, int32_t delta) {
|
||||
auto state = &runtime->state;
|
||||
state_cycle_current_output(state, delta);
|
||||
}
|
||||
|
||||
@@ -1,11 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include "core/runtime.h"
|
||||
#include <stdint.h>
|
||||
#include <zdwm/action.h>
|
||||
|
||||
void spawn(const char *command);
|
||||
void quit(runtime_t *runtime, bool restart);
|
||||
void quit(zdwm_runtime_t *runtime, bool restart);
|
||||
void raise_or_run(
|
||||
zdwm_runtime_t *runtime,
|
||||
const char *class_name,
|
||||
const char *command
|
||||
);
|
||||
|
||||
void toggle_fullscreen(zdwm_runtime_t *runtime);
|
||||
void toggle_maximize(zdwm_runtime_t *runtime);
|
||||
void toggle_floating(zdwm_runtime_t *runtime);
|
||||
void toggle_sticky(zdwm_runtime_t *runtime);
|
||||
void switch_workspace(
|
||||
zdwm_runtime_t *runtime,
|
||||
zdwm_workspace_id_t workspace_id
|
||||
);
|
||||
void cycle_layout(zdwm_runtime_t *runtime, int32_t delta);
|
||||
void cycle_current_output(zdwm_runtime_t *runtime, int32_t delta);
|
||||
|
||||
@@ -37,3 +37,17 @@ bool backend_apply_effect(
|
||||
const effect_t *effects,
|
||||
size_t effect_count
|
||||
);
|
||||
|
||||
typedef struct backend_scan_result_t {
|
||||
window_map_request_event_t *windows;
|
||||
size_t count;
|
||||
size_t capacity;
|
||||
} backend_scan_result_t;
|
||||
|
||||
/**
|
||||
* @brief 扫描已有窗口
|
||||
*
|
||||
* @details 仅扫描窗口并获取其基础信息
|
||||
*/
|
||||
backend_scan_result_t *backend_scan_windows(backend_t *backend);
|
||||
void backend_scan_result_destroy(backend_scan_result_t *result);
|
||||
|
||||
@@ -53,6 +53,7 @@ static void route_map_request(
|
||||
const window_map_request_event_t *e,
|
||||
command_buffer_t *out
|
||||
) {
|
||||
if (e->override_redirect) return;
|
||||
if (state_window_get(state, e->window)) return;
|
||||
|
||||
window_layer_type_t layer_type = window_classify_layer(&e->props);
|
||||
@@ -140,6 +141,90 @@ static void route_window_remove(
|
||||
}
|
||||
}
|
||||
|
||||
static void route_window_metadata_changed(
|
||||
state_t *state,
|
||||
const window_metadata_change_event_t *e
|
||||
) {
|
||||
auto window = state_window_get(state, e->window);
|
||||
if (!window) return;
|
||||
|
||||
auto window_id = e->window;
|
||||
auto metadata = &e->metadata;
|
||||
|
||||
if (e->changed_fields & ZDWM_WINDOW_METADATA_CHANGE_TITLE) {
|
||||
state_window_set_title(state, window_id, metadata->title);
|
||||
}
|
||||
if (e->changed_fields & ZDWM_WINDOW_METADATA_CHANGE_APP_ID) {
|
||||
state_window_set_app_id(state, window_id, metadata->app_id);
|
||||
}
|
||||
if (e->changed_fields & ZDWM_WINDOW_METADATA_CHANGE_ROLE) {
|
||||
state_window_set_role(state, window_id, metadata->role);
|
||||
}
|
||||
if (e->changed_fields & ZDWM_WINDOW_METADATA_CHANGE_CLASS) {
|
||||
state_window_set_class(state, window_id, metadata->class_name);
|
||||
}
|
||||
if (e->changed_fields & ZDWM_WINDOW_METADATA_CHANGE_INSTANCE) {
|
||||
state_window_set_instance(state, window_id, metadata->instance_name);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
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_PAGER: {
|
||||
command_t switch_workspace_cmd = {
|
||||
.type = ZDWM_COMMAND_SWITCH_WORKSPACE,
|
||||
.as.switch_workspace.workspace = window->workspace_id,
|
||||
};
|
||||
command_buffer_push(out, &switch_workspace_cmd);
|
||||
|
||||
command_t focus_cmd = {
|
||||
.type = ZDWM_COMMAND_FOCUS_WINDOW,
|
||||
.as.focus.window = window->id,
|
||||
};
|
||||
command_buffer_push(out, &focus_cmd);
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
static void route_window_state_request(
|
||||
state_t *state,
|
||||
const window_state_request_event_t *e,
|
||||
command_buffer_t *out
|
||||
) {
|
||||
auto window = state_window_get(state, e->window);
|
||||
if (!window) return;
|
||||
|
||||
command_t change_window_state_cmd = {
|
||||
.type = ZDWM_COMMAND_CHANGE_WINDOW_STATE,
|
||||
.as.state_change = {
|
||||
.type = e->type,
|
||||
.window = e->window,
|
||||
.action = e->action,
|
||||
}
|
||||
};
|
||||
command_buffer_push(out, &change_window_state_cmd);
|
||||
}
|
||||
|
||||
static void route_configure_request(
|
||||
state_t *state,
|
||||
const configure_data_t *data,
|
||||
@@ -190,6 +275,16 @@ void policy_route_event(
|
||||
case ZDWM_EVENT_WINDOW_REMOVE:
|
||||
route_window_remove(state, &event->as.window_remove, out);
|
||||
break;
|
||||
case ZDWM_EVENT_WINDOW_METADATA_CHANGED:
|
||||
route_window_metadata_changed(state, &event->as.window_metadata_change);
|
||||
break;
|
||||
case ZDWM_EVENT_WINDOW_ACTIVATE_REQUEST: {
|
||||
auto data = &event->as.window_activate_request;
|
||||
route_window_activate_request(state, data, out);
|
||||
} break;
|
||||
case ZDWM_EVENT_WINDOW_STATE_REQUEST:
|
||||
route_window_state_request(state, &event->as.window_state_request, out);
|
||||
break;
|
||||
case ZDWM_EVENT_CONFIGURE_REQUEST: {
|
||||
auto data = &event->as.configure_request;
|
||||
route_configure_request(state, data, ctx->layouts, out);
|
||||
@@ -339,13 +434,14 @@ unmanage_window(const policy_context_t *ctx, window_id_t window, plan_t *plan) {
|
||||
auto workspace_id = win->workspace_id;
|
||||
auto workspace = state_workspace_get(state, workspace_id);
|
||||
auto output = state_output_get(state, workspace->output_id);
|
||||
auto need_layout = window_need_layout(win);
|
||||
|
||||
auto old_focused_window = workspace->focused_window_id;
|
||||
state_window_remove(state, window);
|
||||
|
||||
push_window_list_effect(state, plan);
|
||||
|
||||
if (window_need_layout(win)) {
|
||||
if (need_layout) {
|
||||
adjust_layout_windows_border_width(state, ctx->border->width, workspace_id);
|
||||
plan->need_relayout = true;
|
||||
}
|
||||
|
||||
@@ -257,6 +257,59 @@ static void runtime_arrange(runtime_t *runtime) {
|
||||
}
|
||||
}
|
||||
|
||||
policy_context_t policy_context_init(runtime_t *runtime) {
|
||||
policy_context_t ctx = {
|
||||
.bind_table = (runtime)->binding_table,
|
||||
.state = &(runtime)->state,
|
||||
.rules = &(runtime)->rules,
|
||||
.border = &(runtime)->border,
|
||||
.layouts = &(runtime)->layouts,
|
||||
.runtime = (runtime),
|
||||
.action_api = {
|
||||
.spawn = spawn,
|
||||
.quit = quit,
|
||||
.raise_or_run = raise_or_run,
|
||||
.toggle_fullscreen = toggle_fullscreen,
|
||||
.toggle_maximize = toggle_maximize,
|
||||
.toggle_floating = toggle_floating,
|
||||
.toggle_sticky = toggle_sticky,
|
||||
.switch_workspace = switch_workspace,
|
||||
.cycle_layout = cycle_layout,
|
||||
.cycle_current_output = cycle_current_output,
|
||||
},
|
||||
};
|
||||
return ctx;
|
||||
}
|
||||
|
||||
void runtime_scan(runtime_t *runtime) {
|
||||
auto result = backend_scan_windows(runtime->backend);
|
||||
if (!result) return;
|
||||
|
||||
policy_context_t ctx = policy_context_init(runtime);
|
||||
|
||||
auto backend = runtime->backend;
|
||||
auto command_buffer = &runtime->command_buffer;
|
||||
auto plan = &runtime->plan;
|
||||
|
||||
command_buffer_reset(command_buffer);
|
||||
plan_reset(plan);
|
||||
|
||||
for (size_t i = 0; i < result->count; i++) {
|
||||
event_t event = {
|
||||
.type = ZDWM_EVENT_WINDOW_MAP_REQUEST,
|
||||
.as.window_map_request = result->windows[i],
|
||||
};
|
||||
policy_route_event(&ctx, &event, command_buffer);
|
||||
}
|
||||
|
||||
policy_apply_command(&ctx, command_buffer, plan);
|
||||
if (plan->need_relayout) runtime_arrange(runtime);
|
||||
if (plan->count) backend_apply_effect(backend, plan->effects, plan->count);
|
||||
|
||||
backend_scan_result_destroy(result);
|
||||
result = nullptr;
|
||||
}
|
||||
|
||||
void runtime_run(runtime_t *runtime) {
|
||||
runtime->running = true;
|
||||
|
||||
@@ -264,19 +317,7 @@ void runtime_run(runtime_t *runtime) {
|
||||
command_buffer_t *command_buffer = &runtime->command_buffer;
|
||||
plan_t *plan = &runtime->plan;
|
||||
|
||||
policy_context_t ctx = {
|
||||
.bind_table = runtime->binding_table,
|
||||
.state = &runtime->state,
|
||||
.rules = &runtime->rules,
|
||||
.border = &runtime->border,
|
||||
.layouts = &runtime->layouts,
|
||||
.runtime = runtime,
|
||||
.action_api = {
|
||||
.spawn = spawn,
|
||||
.quit = quit,
|
||||
.raise_or_run = raise_or_run,
|
||||
},
|
||||
};
|
||||
policy_context_t ctx = policy_context_init(runtime);
|
||||
|
||||
while (runtime->running) {
|
||||
event_t event = {0};
|
||||
|
||||
@@ -46,4 +46,5 @@ bool runtime_init(runtime_t *runtime, runtime_init_desc_t *desc);
|
||||
void runtime_init_desc_cleanup(runtime_init_desc_t *desc);
|
||||
void runtime_shutdown(runtime_t *runtime);
|
||||
void runtime_setup(runtime_t *runtime);
|
||||
void runtime_scan(runtime_t *runtime);
|
||||
void runtime_run(runtime_t *runtime);
|
||||
|
||||
@@ -145,16 +145,21 @@ static void state_workspace_adjust_focused_window(
|
||||
workspace->focused_window_id = ZDWM_WINDOW_ID_INVALID;
|
||||
}
|
||||
|
||||
bool state_workspace_cycle_layout(state_t *state, workspace_id_t workspace_id) {
|
||||
bool state_workspace_cycle_layout(
|
||||
state_t *state,
|
||||
workspace_id_t workspace_id,
|
||||
int32_t delta
|
||||
) {
|
||||
workspace_t *workspace =
|
||||
(workspace_t *)state_workspace_get(state, workspace_id);
|
||||
if (!workspace) return false;
|
||||
|
||||
size_t next_index = 0;
|
||||
int32_t index = 0;
|
||||
bool matched = false;
|
||||
for (size_t i = 0; i < workspace->layout_count; i++) {
|
||||
auto layout_count = (int32_t)workspace->layout_count;
|
||||
for (int32_t i = 0; i < layout_count; i++) {
|
||||
if (workspace->layout_id == workspace->available_layouts[i]) {
|
||||
next_index = (i + 1) % workspace->layout_count;
|
||||
index = i;
|
||||
matched = true;
|
||||
break;
|
||||
}
|
||||
@@ -162,7 +167,13 @@ bool state_workspace_cycle_layout(state_t *state, workspace_id_t workspace_id) {
|
||||
|
||||
if (!matched) return false;
|
||||
|
||||
auto next_layout_id = workspace->available_layouts[next_index];
|
||||
auto new_index = index + delta;
|
||||
new_index %= layout_count;
|
||||
if (new_index < 0) new_index += layout_count;
|
||||
|
||||
if (new_index == index) return false;
|
||||
|
||||
auto next_layout_id = workspace->available_layouts[new_index];
|
||||
workspace->layout_id = next_layout_id;
|
||||
return true;
|
||||
}
|
||||
@@ -344,6 +355,7 @@ const window_t *state_window_add(state_t *state, const window_info_t *info) {
|
||||
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_title(window, info->title);
|
||||
window_set_app_id(window, info->app_id);
|
||||
window_set_role(window, info->role);
|
||||
|
||||
@@ -81,7 +81,11 @@ void state_cleanup(state_t *state);
|
||||
*/
|
||||
const workspace_t *state_workspace_get(const state_t *state, workspace_id_t id);
|
||||
const workspace_t *state_workspace_at(const state_t *state, size_t index);
|
||||
bool state_workspace_cycle_layout(state_t *state, workspace_id_t workspace_id);
|
||||
bool state_workspace_cycle_layout(
|
||||
state_t *state,
|
||||
workspace_id_t workspace_id,
|
||||
int32_t delta
|
||||
);
|
||||
bool state_workspace_set_layout_by_index(
|
||||
state_t *state,
|
||||
workspace_id_t workspace_id,
|
||||
|
||||
@@ -54,7 +54,8 @@ void window_set_floating(window_t *window, bool floating) {
|
||||
if (floating == window->floating) return;
|
||||
|
||||
window->floating = floating;
|
||||
if (floating) window->float_rect = window->frame_rect;
|
||||
if (floating) window_set_frame_rect(window, window->float_rect);
|
||||
else window_set_float_rect(window, window->frame_rect);
|
||||
}
|
||||
|
||||
void window_set_sticky(window_t *window, bool sticky) {
|
||||
|
||||
Reference in New Issue
Block a user