feat(core+backend/X11): 实现窗口边框管理和焦点跟随鼠标
This commit is contained in:
@@ -21,6 +21,7 @@
|
|||||||
#include "base/log.h"
|
#include "base/log.h"
|
||||||
#include "base/macros.h"
|
#include "base/macros.h"
|
||||||
#include "base/memory.h"
|
#include "base/memory.h"
|
||||||
|
#include "base/window_list.h"
|
||||||
#include "core/plan.h"
|
#include "core/plan.h"
|
||||||
#include "core/types.h"
|
#include "core/types.h"
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
@@ -177,14 +178,9 @@ void backend_destroy(backend_t *backend) {
|
|||||||
p_delete(&backend->config_list.cfgs);
|
p_delete(&backend->config_list.cfgs);
|
||||||
p_clear(&backend->config_list, 1);
|
p_clear(&backend->config_list, 1);
|
||||||
|
|
||||||
p_delete(&backend->unmap.windows);
|
window_list_cleanup(&backend->unmap);
|
||||||
p_clear(&backend->unmap, 1);
|
window_list_cleanup(&backend->map);
|
||||||
|
window_list_cleanup(&backend->kill);
|
||||||
p_delete(&backend->map.windows);
|
|
||||||
p_clear(&backend->map, 1);
|
|
||||||
|
|
||||||
p_delete(&backend->kill.windows);
|
|
||||||
p_clear(&backend->kill, 1);
|
|
||||||
|
|
||||||
xcb_key_symbols_free(backend->key_symbols);
|
xcb_key_symbols_free(backend->key_symbols);
|
||||||
backend->key_symbols = nullptr;
|
backend->key_symbols = nullptr;
|
||||||
|
|||||||
@@ -264,6 +264,17 @@ static bool handle_key_press(
|
|||||||
return true;
|
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) {
|
bool backend_next_event(backend_t *backend, event_t *event) {
|
||||||
if (!backend || !backend->conn || !event) return false;
|
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_DESTROY_NOTIFY, handle_destroy_notify);
|
||||||
EVENT(XCB_CONFIGURE_REQUEST, handle_configure_request);
|
EVENT(XCB_CONFIGURE_REQUEST, handle_configure_request);
|
||||||
EVENT(XCB_KEY_PRESS, handle_key_press);
|
EVENT(XCB_KEY_PRESS, handle_key_press);
|
||||||
|
EVENT(XCB_ENTER_NOTIFY, handle_enter_notify);
|
||||||
|
|
||||||
#undef EVENT
|
#undef EVENT
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,8 @@
|
|||||||
#include <xcb/xcb_keysyms.h>
|
#include <xcb/xcb_keysyms.h>
|
||||||
#include <xcb/xproto.h>
|
#include <xcb/xproto.h>
|
||||||
|
|
||||||
|
#include "base/window_list.h"
|
||||||
|
|
||||||
#define ATOM_LIST(X) \
|
#define ATOM_LIST(X) \
|
||||||
X(COMPOUND_TEXT) \
|
X(COMPOUND_TEXT) \
|
||||||
X(UTF8_STRING) \
|
X(UTF8_STRING) \
|
||||||
@@ -70,12 +72,6 @@ typedef struct window_configure_list_t {
|
|||||||
size_t capacity;
|
size_t capacity;
|
||||||
} window_configure_list_t;
|
} 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 {
|
struct backend_t {
|
||||||
xcb_key_symbols_t *key_symbols;
|
xcb_key_symbols_t *key_symbols;
|
||||||
xcb_connection_t *conn;
|
xcb_connection_t *conn;
|
||||||
|
|||||||
@@ -7,7 +7,6 @@
|
|||||||
#include <xcb/xcb_keysyms.h>
|
#include <xcb/xcb_keysyms.h>
|
||||||
#include <xcb/xproto.h>
|
#include <xcb/xproto.h>
|
||||||
|
|
||||||
#include "base/array.h"
|
|
||||||
#include "base/macros.h"
|
#include "base/macros.h"
|
||||||
#include "base/memory.h"
|
#include "base/memory.h"
|
||||||
#include "core/backend.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) {
|
static uint16_t get_xcb_modifier(modifier_mask_t modifiers) {
|
||||||
typedef struct modifier_map_t {
|
typedef struct modifier_map_t {
|
||||||
modifier_bit_t modifier;
|
modifier_bit_t modifier;
|
||||||
|
|||||||
@@ -97,9 +97,6 @@ void window_set_net_wm_state(
|
|||||||
xcb_atom_t *atoms
|
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(
|
void window_grab_keys(
|
||||||
backend_t *backend,
|
backend_t *backend,
|
||||||
xcb_window_t window,
|
xcb_window_t window,
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#include "color.h"
|
#include "base/color.h"
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|||||||
26
src/base/window_list.c
Normal file
26
src/base/window_list.c
Normal 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
14
src/base/window_list.h
Normal 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);
|
||||||
@@ -80,6 +80,7 @@ bool config_defaults_build(
|
|||||||
|
|
||||||
api->set_default_mode(builder, default_mode);
|
api->set_default_mode(builder, default_mode);
|
||||||
api->set_initial_mode(builder, default_mode);
|
api->set_initial_mode(builder, default_mode);
|
||||||
|
api->set_border_config(builder, 2, "#444444", "#005577");
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,10 +25,6 @@ typedef struct switch_workspace_command_t {
|
|||||||
workspace_id_t workspace;
|
workspace_id_t workspace;
|
||||||
} switch_workspace_command_t;
|
} 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 {
|
typedef struct window_state_change_command_t {
|
||||||
window_id_t window;
|
window_id_t window;
|
||||||
window_state_request_type_t type;
|
window_state_request_type_t type;
|
||||||
@@ -48,10 +44,10 @@ typedef struct command_t {
|
|||||||
command_type_t type;
|
command_type_t type;
|
||||||
union {
|
union {
|
||||||
manage_window_command_t manage_window;
|
manage_window_command_t manage_window;
|
||||||
only_window_command_t unmanage;
|
only_window_data_t unmanage;
|
||||||
only_window_command_t focus;
|
only_window_data_t focus;
|
||||||
only_window_command_t kill;
|
only_window_data_t kill;
|
||||||
only_window_command_t withdraw;
|
only_window_data_t withdraw;
|
||||||
configure_data_t configure;
|
configure_data_t configure;
|
||||||
window_state_change_command_t state_change;
|
window_state_change_command_t state_change;
|
||||||
switch_workspace_command_t switch_workspace;
|
switch_workspace_command_t switch_workspace;
|
||||||
|
|||||||
@@ -46,12 +46,6 @@ typedef struct pointer_motion_event_t {
|
|||||||
point_t local;
|
point_t local;
|
||||||
} pointer_motion_event_t;
|
} 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 {
|
typedef struct window_map_request_event_t {
|
||||||
window_id_t window;
|
window_id_t window;
|
||||||
window_id_t transient_for;
|
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_press;
|
||||||
pointer_button_event_t pointer_button_release;
|
pointer_button_event_t pointer_button_release;
|
||||||
pointer_motion_event_t pointer_motion;
|
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_map_request_event_t window_map_request;
|
||||||
window_remove_event_t window_remove;
|
window_remove_event_t window_remove;
|
||||||
window_metadata_change_event_t window_metadata_change;
|
window_metadata_change_event_t window_metadata_change;
|
||||||
|
|||||||
@@ -22,10 +22,6 @@ typedef enum effect_type_t {
|
|||||||
ZDWM_EFFECT_BIND_KEY,
|
ZDWM_EFFECT_BIND_KEY,
|
||||||
} effect_type_t;
|
} 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 {
|
typedef struct effect_move_window_t {
|
||||||
window_id_t window;
|
window_id_t window;
|
||||||
point_t left_top_point;
|
point_t left_top_point;
|
||||||
@@ -60,11 +56,11 @@ typedef struct effect_bool_window_t {
|
|||||||
typedef struct effect_t {
|
typedef struct effect_t {
|
||||||
effect_type_t type;
|
effect_type_t type;
|
||||||
union {
|
union {
|
||||||
effect_only_window_id_t map;
|
only_window_data_t map;
|
||||||
effect_only_window_id_t unmap;
|
only_window_data_t unmap;
|
||||||
effect_only_window_id_t focus;
|
only_window_data_t focus;
|
||||||
effect_only_window_id_t kill;
|
only_window_data_t kill;
|
||||||
effect_only_window_id_t withdraw;
|
only_window_data_t withdraw;
|
||||||
effect_bool_window_t minimize;
|
effect_bool_window_t minimize;
|
||||||
effect_bool_window_t maximize;
|
effect_bool_window_t maximize;
|
||||||
effect_bool_window_t fullscreen;
|
effect_bool_window_t fullscreen;
|
||||||
|
|||||||
@@ -4,7 +4,9 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <zdwm/types.h>
|
#include <zdwm/types.h>
|
||||||
|
|
||||||
|
#include "base/color.h"
|
||||||
#include "base/macros.h"
|
#include "base/macros.h"
|
||||||
|
#include "base/window_list.h"
|
||||||
#include "core/binding.h"
|
#include "core/binding.h"
|
||||||
#include "core/command.h"
|
#include "core/command.h"
|
||||||
#include "core/command_buffer.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) {
|
static workspace_id_t derive_window_workspace(const state_t *state) {
|
||||||
return state->outputs[state->current_output_index].current_workspace_id;
|
return state->outputs[state->current_output_index].current_workspace_id;
|
||||||
}
|
}
|
||||||
@@ -155,19 +166,6 @@ static void route_configure_request(
|
|||||||
return;
|
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 (!state_workspace_show(state, window->workspace_id)) return;
|
||||||
if (window_need_layout(window)) return;
|
if (window_need_layout(window)) return;
|
||||||
auto workspace = state_workspace_get(state, window->workspace_id);
|
auto workspace = state_workspace_get(state, window->workspace_id);
|
||||||
@@ -193,6 +191,8 @@ void policy_route_event(
|
|||||||
case ZDWM_EVENT_KEY_PRESS:
|
case ZDWM_EVENT_KEY_PRESS:
|
||||||
route_key_press(ctx->bind_table, &ctx->action_ctx, &event->as.key_press);
|
route_key_press(ctx->bind_table, &ctx->action_ctx, &event->as.key_press);
|
||||||
break;
|
break;
|
||||||
|
case ZDWM_EVENT_POINTER_ENTER:
|
||||||
|
route_pointer_enter(state, event->as.pointer_enter.window, out);
|
||||||
case ZDWM_EVENT_WINDOW_MAP_REQUEST:
|
case ZDWM_EVENT_WINDOW_MAP_REQUEST:
|
||||||
route_map_request(state, ctx->rules, &event->as.window_map_request, out);
|
route_map_request(state, ctx->rules, &event->as.window_map_request, out);
|
||||||
break;
|
break;
|
||||||
@@ -207,17 +207,82 @@ 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(
|
static void manage_window(
|
||||||
const policy_context_t *ctx,
|
const policy_context_t *ctx,
|
||||||
const manage_window_command_t *command,
|
const manage_window_command_t *command,
|
||||||
plan_t *plan
|
plan_t *plan
|
||||||
) {
|
) {
|
||||||
auto state = ctx->state;
|
auto state = ctx->state;
|
||||||
auto window = state_window_add(state, &command->info);
|
auto window = state_window_add(state, &command->info);
|
||||||
auto window_id = window->id;
|
auto window_id = window->id;
|
||||||
state_window_set_workspace(state, window_id, command->workspace);
|
auto workspace_id = command->workspace;
|
||||||
state_workspace_set_focused_window(state, command->workspace, window_id);
|
state_window_set_workspace(state, window_id, workspace_id);
|
||||||
state_window_set_floating(state, window_id, command->floating);
|
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;
|
if (!state_workspace_show(state, command->workspace)) return;
|
||||||
|
|
||||||
@@ -234,7 +299,26 @@ static void manage_window(
|
|||||||
|
|
||||||
if (window_need_layout(window)) {
|
if (window_need_layout(window)) {
|
||||||
plan->need_relayout = true;
|
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(
|
static void add_switch_workspace_effects(
|
||||||
@@ -272,7 +356,9 @@ static void add_switch_workspace_effects(
|
|||||||
plan_push_effect(plan, &focus_effect);
|
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);
|
const window_t *win = state_window_get(state, window);
|
||||||
if (!win) return;
|
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;
|
auto old_focused_window = workspace->focused_window_id;
|
||||||
state_window_remove(state, window);
|
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 (output->current_workspace_id != workspace_id) return;
|
||||||
|
|
||||||
if (old_focused_window != workspace->focused_window_id) {
|
if (old_focused_window != workspace->focused_window_id) {
|
||||||
@@ -293,15 +385,17 @@ 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
|
||||||
auto win = state_window_get(state, window);
|
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;
|
if (!win) return;
|
||||||
|
|
||||||
auto workspace_id = win->workspace_id;
|
auto workspace_id = win->workspace_id;
|
||||||
auto workspace = state_workspace_get(state, workspace_id);
|
auto workspace = state_workspace_get(state, workspace_id);
|
||||||
auto old_focused_window = workspace->focused_window_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;
|
if (old_focused_window == workspace->focused_window_id) return;
|
||||||
|
|
||||||
effect_t focus_effect = {
|
effect_t focus_effect = {
|
||||||
@@ -578,10 +672,10 @@ void policy_apply_command(
|
|||||||
manage_window(ctx, &cmd->as.manage_window, plan);
|
manage_window(ctx, &cmd->as.manage_window, plan);
|
||||||
break;
|
break;
|
||||||
case ZDWM_COMMAND_UNMANAGE_WINDOW:
|
case ZDWM_COMMAND_UNMANAGE_WINDOW:
|
||||||
unmanage_window(state, cmd->as.unmanage.window, plan);
|
unmanage_window(ctx, cmd->as.unmanage.window, plan);
|
||||||
break;
|
break;
|
||||||
case ZDWM_COMMAND_FOCUS_WINDOW:
|
case ZDWM_COMMAND_FOCUS_WINDOW:
|
||||||
focus_window(state, cmd->as.focus.window, plan);
|
focus_window(ctx, cmd->as.focus.window, plan);
|
||||||
break;
|
break;
|
||||||
case ZDWM_COMMAND_KILL_WINDOW:
|
case ZDWM_COMMAND_KILL_WINDOW:
|
||||||
kill_window(state, cmd->as.kill.window, plan);
|
kill_window(state, cmd->as.kill.window, plan);
|
||||||
|
|||||||
@@ -9,11 +9,13 @@
|
|||||||
#include "core/plan.h"
|
#include "core/plan.h"
|
||||||
#include "core/rules.h"
|
#include "core/rules.h"
|
||||||
#include "core/state.h"
|
#include "core/state.h"
|
||||||
|
#include "core/types.h"
|
||||||
|
|
||||||
typedef struct policy_context_t {
|
typedef struct policy_context_t {
|
||||||
binding_table_t *bind_table;
|
binding_table_t *bind_table;
|
||||||
state_t *state;
|
state_t *state;
|
||||||
const rules_t *rules;
|
const rules_t *rules;
|
||||||
|
const border_config_t *border;
|
||||||
const layout_registry_t *layouts;
|
const layout_registry_t *layouts;
|
||||||
const zdwm_action_ctx_t action_ctx;
|
const zdwm_action_ctx_t action_ctx;
|
||||||
} policy_context_t;
|
} policy_context_t;
|
||||||
|
|||||||
@@ -224,6 +224,7 @@ static void runtime_apply_window_rect(
|
|||||||
}
|
}
|
||||||
if (need_resize) {
|
if (need_resize) {
|
||||||
changed_fields |= ZDWM_CONFIGURE_FIELD_WIDTH | ZDWM_CONFIGURE_FIELD_HEIGHT;
|
changed_fields |= ZDWM_CONFIGURE_FIELD_WIDTH | ZDWM_CONFIGURE_FIELD_HEIGHT;
|
||||||
|
changed_fields |= ZDWM_CONFIGURE_FIELD_BORDER_WIDTH;
|
||||||
}
|
}
|
||||||
effect_t configure_effect = {
|
effect_t configure_effect = {
|
||||||
.type = ZDWM_EFFECT_CONFIGURE_WINDOW,
|
.type = ZDWM_EFFECT_CONFIGURE_WINDOW,
|
||||||
@@ -231,8 +232,9 @@ static void runtime_apply_window_rect(
|
|||||||
.window = window_id,
|
.window = window_id,
|
||||||
.x = rect.x,
|
.x = rect.x,
|
||||||
.y = rect.y,
|
.y = rect.y,
|
||||||
.width = rect.width,
|
.width = rect.width - 2 * (int32_t)window->border_width,
|
||||||
.height = rect.height,
|
.height = rect.height - 2 * (int32_t)window->border_width,
|
||||||
|
.border_width = window->border_width,
|
||||||
.changed_fields = changed_fields,
|
.changed_fields = changed_fields,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -266,6 +268,7 @@ void runtime_run(runtime_t *runtime) {
|
|||||||
.bind_table = runtime->binding_table,
|
.bind_table = runtime->binding_table,
|
||||||
.state = &runtime->state,
|
.state = &runtime->state,
|
||||||
.rules = &runtime->rules,
|
.rules = &runtime->rules,
|
||||||
|
.border = &runtime->border,
|
||||||
.layouts = &runtime->layouts,
|
.layouts = &runtime->layouts,
|
||||||
.action_ctx = {
|
.action_ctx = {
|
||||||
.spawn = spawn,
|
.spawn = spawn,
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "base/color.h"
|
|
||||||
#include "core/backend.h"
|
#include "core/backend.h"
|
||||||
#include "core/binding.h"
|
#include "core/binding.h"
|
||||||
#include "core/command_buffer.h"
|
#include "core/command_buffer.h"
|
||||||
@@ -13,12 +12,6 @@
|
|||||||
#include "core/state.h"
|
#include "core/state.h"
|
||||||
#include "core/types.h"
|
#include "core/types.h"
|
||||||
|
|
||||||
typedef struct border_config_t {
|
|
||||||
uint32_t width;
|
|
||||||
color_t normal_color;
|
|
||||||
color_t focused_color;
|
|
||||||
} border_config_t;
|
|
||||||
|
|
||||||
typedef struct runtime_init_desc_t {
|
typedef struct runtime_init_desc_t {
|
||||||
backend_t *backend;
|
backend_t *backend;
|
||||||
output_info_t *outputs;
|
output_info_t *outputs;
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
#include "base/array.h"
|
#include "base/array.h"
|
||||||
#include "base/log.h"
|
#include "base/log.h"
|
||||||
#include "base/memory.h"
|
#include "base/memory.h"
|
||||||
|
#include "base/window_list.h"
|
||||||
#include "core/layer.h"
|
#include "core/layer.h"
|
||||||
#include "core/types.h"
|
#include "core/types.h"
|
||||||
#include "core/window.h"
|
#include "core/window.h"
|
||||||
@@ -479,6 +480,15 @@ void state_window_set_fixed_size(
|
|||||||
if (window) window_set_fixed_size(window, 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(
|
void state_window_set_skip_taskbar(
|
||||||
state_t *state,
|
state_t *state,
|
||||||
window_id_t window_id,
|
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);
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "base/window_list.h"
|
||||||
#include "core/layer.h"
|
#include "core/layer.h"
|
||||||
#include "core/types.h"
|
#include "core/types.h"
|
||||||
#include "core/window.h"
|
#include "core/window.h"
|
||||||
@@ -201,6 +202,11 @@ void state_window_set_fixed_size(
|
|||||||
window_id_t window_id,
|
window_id_t window_id,
|
||||||
bool fixed_size
|
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(
|
void state_window_set_skip_taskbar(
|
||||||
state_t *state,
|
state_t *state,
|
||||||
window_id_t window_id,
|
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_raise(state_t *state, window_id_t window_id);
|
||||||
bool state_stack_lower(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
|
||||||
|
);
|
||||||
|
|||||||
@@ -4,6 +4,8 @@
|
|||||||
#include <zdwm/rules.h>
|
#include <zdwm/rules.h>
|
||||||
#include <zdwm/types.h>
|
#include <zdwm/types.h>
|
||||||
|
|
||||||
|
#include "base/color.h"
|
||||||
|
|
||||||
/* clang-format off */
|
/* clang-format off */
|
||||||
typedef zdwm_layout_id_t layout_id_t;
|
typedef zdwm_layout_id_t layout_id_t;
|
||||||
typedef zdwm_window_id_t window_id_t;
|
typedef zdwm_window_id_t window_id_t;
|
||||||
@@ -93,3 +95,13 @@ typedef struct configure_data_t {
|
|||||||
window_id_t sibling;
|
window_id_t sibling;
|
||||||
uint32_t stack_mode;
|
uint32_t stack_mode;
|
||||||
} configure_data_t;
|
} 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;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "core/window.h"
|
#include "core/window.h"
|
||||||
|
|
||||||
#include "base/memory.h"
|
#include "base/memory.h"
|
||||||
|
#include "core/types.h"
|
||||||
|
|
||||||
window_layer_type_t window_classify_layer(const window_layer_props_t *props) {
|
window_layer_type_t window_classify_layer(const window_layer_props_t *props) {
|
||||||
for (size_t i = 0; i < props->type_count; ++i) {
|
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);
|
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) {
|
void window_set_skip_taskbar(window_t *window, bool skip_taskbar) {
|
||||||
window->skip_taskbar = 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 ||
|
return window->frame_rect.width != width ||
|
||||||
window->frame_rect.height != height;
|
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;
|
||||||
|
}
|
||||||
|
|||||||
@@ -87,6 +87,7 @@ typedef struct window_t {
|
|||||||
char *class_name;
|
char *class_name;
|
||||||
char *instance_name;
|
char *instance_name;
|
||||||
|
|
||||||
|
uint32_t border_width;
|
||||||
bool skip_taskbar;
|
bool skip_taskbar;
|
||||||
} window_t;
|
} 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_role(window_t *window, const char *role);
|
||||||
void window_set_class(window_t *window, const char *class_name);
|
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_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_set_skip_taskbar(window_t *window, bool skip_taskbar);
|
||||||
void window_take_metadata(
|
void window_take_metadata(
|
||||||
window_t *window,
|
window_t *window,
|
||||||
@@ -123,3 +125,4 @@ void window_take_metadata(
|
|||||||
bool window_need_layout(const window_t *window);
|
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_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_need_resize(const window_t *window, int32_t width, int32_t height);
|
||||||
|
bool window_should_has_border(const window_t *window);
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ add_executable(${RUNTIME_CONFIG_TEST_APP_NAME}
|
|||||||
${CMAKE_CURRENT_SOURCE_DIR}/runtime_config_test.c
|
${CMAKE_CURRENT_SOURCE_DIR}/runtime_config_test.c
|
||||||
${SOURCE_DIR}/base/color.c
|
${SOURCE_DIR}/base/color.c
|
||||||
${SOURCE_DIR}/base/log.c
|
${SOURCE_DIR}/base/log.c
|
||||||
|
${SOURCE_DIR}/base/window_list.c
|
||||||
${SOURCE_DIR}/config/defaults.c
|
${SOURCE_DIR}/config/defaults.c
|
||||||
${SOURCE_DIR}/config/loader.c
|
${SOURCE_DIR}/config/loader.c
|
||||||
${SOURCE_DIR}/config/runtime_config.c
|
${SOURCE_DIR}/config/runtime_config.c
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ add_executable(${TEST_APP_NAME}
|
|||||||
${CMAKE_CURRENT_SOURCE_DIR}/main.c
|
${CMAKE_CURRENT_SOURCE_DIR}/main.c
|
||||||
${SOURCE_DIR}/base/color.c
|
${SOURCE_DIR}/base/color.c
|
||||||
${SOURCE_DIR}/base/log.c
|
${SOURCE_DIR}/base/log.c
|
||||||
|
${SOURCE_DIR}/base/window_list.c
|
||||||
${SOURCE_DIR}/backend/output_utils.c
|
${SOURCE_DIR}/backend/output_utils.c
|
||||||
${SOURCE_DIR}/config/defaults.c
|
${SOURCE_DIR}/config/defaults.c
|
||||||
${SOURCE_DIR}/config/loader.c
|
${SOURCE_DIR}/config/loader.c
|
||||||
|
|||||||
Reference in New Issue
Block a user