Compare commits
4 Commits
8d838135d6
...
a393308704
| Author | SHA1 | Date | |
|---|---|---|---|
|
a393308704
|
|||
|
d602b0111e
|
|||
|
78200debf5
|
|||
|
722d3946c6
|
@@ -9,6 +9,7 @@
|
|||||||
#include <xcb/randr.h>
|
#include <xcb/randr.h>
|
||||||
#include <xcb/xcb.h>
|
#include <xcb/xcb.h>
|
||||||
#include <xcb/xcb_aux.h>
|
#include <xcb/xcb_aux.h>
|
||||||
|
#include <xcb/xcb_icccm.h>
|
||||||
#include <xcb/xcb_keysyms.h>
|
#include <xcb/xcb_keysyms.h>
|
||||||
#include <xcb/xfixes.h>
|
#include <xcb/xfixes.h>
|
||||||
#include <xcb/xinerama.h>
|
#include <xcb/xinerama.h>
|
||||||
@@ -494,6 +495,40 @@ static void backend_merge_effects(
|
|||||||
case ZDWM_EFFECT_KILL_WINDOW:
|
case ZDWM_EFFECT_KILL_WINDOW:
|
||||||
window_list_push(&backend->kill, e->as.kill.window);
|
window_list_push(&backend->kill, e->as.kill.window);
|
||||||
break;
|
break;
|
||||||
|
case ZDWM_EFFECT_WITHDRAW_WINDOW:
|
||||||
|
window_set_icccm_wm_state(
|
||||||
|
backend->conn,
|
||||||
|
e->as.withdraw.window,
|
||||||
|
XCB_ICCCM_WM_STATE_WITHDRAWN
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case ZDWM_EFFECT_MINIMIZE_WINDOW: {
|
||||||
|
auto window = e->as.minimize.window;
|
||||||
|
xcb_icccm_wm_state_t state = XCB_ICCCM_WM_STATE_NORMAL;
|
||||||
|
if (e->as.minimize.value) state = XCB_ICCCM_WM_STATE_ICONIC;
|
||||||
|
window_set_icccm_wm_state(backend->conn, window, state);
|
||||||
|
} break;
|
||||||
|
case ZDWM_EFFECT_MAXIMIZE_WINDOW: {
|
||||||
|
auto window = e->as.maximize.window;
|
||||||
|
if (e->as.maximize.value) {
|
||||||
|
xcb_atom_t max_atoms[] = {
|
||||||
|
backend->atoms._NET_WM_STATE_MAXIMIZED_HORZ,
|
||||||
|
backend->atoms._NET_WM_STATE_MAXIMIZED_VERT
|
||||||
|
};
|
||||||
|
window_set_net_wm_state(backend, window, countof(max_atoms), max_atoms);
|
||||||
|
} else {
|
||||||
|
window_set_net_wm_state(backend, window, 0, nullptr);
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
case ZDWM_EFFECT_FULLSCREEN_WINDOW: {
|
||||||
|
auto window = e->as.fullscreen.window;
|
||||||
|
if (e->as.fullscreen.value) {
|
||||||
|
auto fullscreen_atom = backend->atoms._NET_WM_STATE_FULLSCREEN;
|
||||||
|
window_set_net_wm_state(backend, window, 1, &fullscreen_atom);
|
||||||
|
} else {
|
||||||
|
window_set_net_wm_state(backend, window, 0, nullptr);
|
||||||
|
}
|
||||||
|
} break;
|
||||||
case ZDWM_EFFECT_MOVE_WINDOW: {
|
case ZDWM_EFFECT_MOVE_WINDOW: {
|
||||||
window_configure_t *cfg =
|
window_configure_t *cfg =
|
||||||
find_or_push_configure(configs, e->as.move.window);
|
find_or_push_configure(configs, e->as.move.window);
|
||||||
|
|||||||
@@ -173,7 +173,11 @@ static bool handle_unmap_notify(
|
|||||||
) {
|
) {
|
||||||
event->type = ZDWM_EVENT_WINDOW_REMOVE;
|
event->type = ZDWM_EVENT_WINDOW_REMOVE;
|
||||||
event->as.window_remove.window = xcb_event->window;
|
event->as.window_remove.window = xcb_event->window;
|
||||||
event->as.window_remove.reason = ZDWM_WINDOW_REMOVE_WITHDRAWN;
|
if (XCB_EVENT_SENT(xcb_event)) {
|
||||||
|
event->as.window_remove.reason = ZDWM_WINDOW_REMOVE_WITHDRAWN;
|
||||||
|
} else {
|
||||||
|
event->as.window_remove.reason = ZDWM_WINDOW_REMOVE_DESTROY;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -251,7 +255,8 @@ bool backend_next_event(backend_t *backend, event_t *event) {
|
|||||||
uint8_t response_type = XCB_EVENT_RESPONSE_TYPE(raw_event);
|
uint8_t response_type = XCB_EVENT_RESPONSE_TYPE(raw_event);
|
||||||
bool handled = false;
|
bool handled = false;
|
||||||
|
|
||||||
printf("xcb event type: %u\n", response_type);
|
auto label = xcb_event_get_label(response_type);
|
||||||
|
printf("xcb event type: %s[%u]\n", label, response_type);
|
||||||
|
|
||||||
switch (response_type) {
|
switch (response_type) {
|
||||||
#define EVENT(type, handler) \
|
#define EVENT(type, handler) \
|
||||||
|
|||||||
@@ -319,6 +319,45 @@ void window_clean_event_mask(xcb_connection_t *conn, xcb_window_t window) {
|
|||||||
xcb_change_window_attributes_aux(conn, window, change_mask, &value_list);
|
xcb_change_window_attributes_aux(conn, window, change_mask, &value_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void window_set_icccm_wm_state(
|
||||||
|
xcb_connection_t *conn,
|
||||||
|
xcb_window_t window,
|
||||||
|
xcb_icccm_wm_state_t state
|
||||||
|
) {
|
||||||
|
xcb_icccm_wm_hints_t hints;
|
||||||
|
xcb_icccm_wm_hints_set_none(&hints);
|
||||||
|
switch (state) {
|
||||||
|
case XCB_ICCCM_WM_STATE_WITHDRAWN:
|
||||||
|
xcb_icccm_wm_hints_set_withdrawn(&hints);
|
||||||
|
break;
|
||||||
|
case XCB_ICCCM_WM_STATE_NORMAL:
|
||||||
|
xcb_icccm_wm_hints_set_normal(&hints);
|
||||||
|
break;
|
||||||
|
case XCB_ICCCM_WM_STATE_ICONIC:
|
||||||
|
xcb_icccm_wm_hints_set_iconic(&hints);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
xcb_icccm_set_wm_hints(conn, window, &hints);
|
||||||
|
}
|
||||||
|
|
||||||
|
void window_set_net_wm_state(
|
||||||
|
backend_t *backend,
|
||||||
|
xcb_window_t window,
|
||||||
|
size_t count,
|
||||||
|
xcb_atom_t *atoms
|
||||||
|
) {
|
||||||
|
xcb_change_property(
|
||||||
|
backend->conn,
|
||||||
|
XCB_PROP_MODE_REPLACE,
|
||||||
|
window,
|
||||||
|
backend->atoms._NET_WM_STATE,
|
||||||
|
XCB_ATOM_ATOM,
|
||||||
|
32,
|
||||||
|
count,
|
||||||
|
atoms
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
void window_list_push(window_list_t *window_list, xcb_window_t window) {
|
void window_list_push(window_list_t *window_list, xcb_window_t window) {
|
||||||
xcb_window_t *win =
|
xcb_window_t *win =
|
||||||
array_push(window_list->windows, window_list->count, window_list->capacity);
|
array_push(window_list->windows, window_list->count, window_list->capacity);
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <xcb/xcb.h>
|
||||||
#include <xcb/xcb_icccm.h>
|
#include <xcb/xcb_icccm.h>
|
||||||
#include <xcb/xproto.h>
|
#include <xcb/xproto.h>
|
||||||
|
|
||||||
@@ -84,6 +85,17 @@ void window_kill(backend_t *backend, xcb_window_t window);
|
|||||||
void root_set_event_mask(backend_t *backend);
|
void root_set_event_mask(backend_t *backend);
|
||||||
void window_set_event_mask(xcb_connection_t *conn, xcb_window_t window);
|
void window_set_event_mask(xcb_connection_t *conn, xcb_window_t window);
|
||||||
void window_clean_event_mask(xcb_connection_t *conn, xcb_window_t window);
|
void window_clean_event_mask(xcb_connection_t *conn, xcb_window_t window);
|
||||||
|
void window_set_icccm_wm_state(
|
||||||
|
xcb_connection_t *conn,
|
||||||
|
xcb_window_t window,
|
||||||
|
xcb_icccm_wm_state_t state
|
||||||
|
);
|
||||||
|
void window_set_net_wm_state(
|
||||||
|
backend_t *backend,
|
||||||
|
xcb_window_t window,
|
||||||
|
size_t count,
|
||||||
|
xcb_atom_t *atoms
|
||||||
|
);
|
||||||
|
|
||||||
void window_list_push(window_list_t *window_list, xcb_window_t window);
|
void window_list_push(window_list_t *window_list, xcb_window_t window);
|
||||||
void window_list_reset(window_list_t *window_list);
|
void window_list_reset(window_list_t *window_list);
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ typedef enum command_type_t {
|
|||||||
ZDWM_COMMAND_UNMANAGE_WINDOW,
|
ZDWM_COMMAND_UNMANAGE_WINDOW,
|
||||||
ZDWM_COMMAND_FOCUS_WINDOW,
|
ZDWM_COMMAND_FOCUS_WINDOW,
|
||||||
ZDWM_COMMAND_KILL_WINDOW,
|
ZDWM_COMMAND_KILL_WINDOW,
|
||||||
|
ZDWM_COMMAND_WITHDRAW_WINDOW,
|
||||||
|
ZDWM_COMMAND_CHANGE_WINDOW_STATE,
|
||||||
ZDWM_COMMAND_SWITCH_WORKSPACE,
|
ZDWM_COMMAND_SWITCH_WORKSPACE,
|
||||||
} command_type_t;
|
} command_type_t;
|
||||||
|
|
||||||
@@ -26,6 +28,12 @@ typedef struct only_window_command_t {
|
|||||||
window_id_t window;
|
window_id_t window;
|
||||||
} only_window_command_t;
|
} only_window_command_t;
|
||||||
|
|
||||||
|
typedef struct window_state_change_command_t {
|
||||||
|
window_id_t window;
|
||||||
|
window_state_request_type_t type;
|
||||||
|
window_state_request_action_t action;
|
||||||
|
} window_state_change_command_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 非 owning 的命令值对象
|
* @brief 非 owning 的命令值对象
|
||||||
* @details
|
* @details
|
||||||
@@ -42,6 +50,8 @@ typedef struct command_t {
|
|||||||
only_window_command_t unmanage;
|
only_window_command_t unmanage;
|
||||||
only_window_command_t focus;
|
only_window_command_t focus;
|
||||||
only_window_command_t kill;
|
only_window_command_t kill;
|
||||||
|
only_window_command_t withdraw;
|
||||||
|
window_state_change_command_t state_change;
|
||||||
switch_workspace_command_t switch_workspace;
|
switch_workspace_command_t switch_workspace;
|
||||||
} as;
|
} as;
|
||||||
} command_t;
|
} command_t;
|
||||||
|
|||||||
@@ -108,21 +108,9 @@ typedef struct window_activate_request_event_t {
|
|||||||
window_activation_source_t source;
|
window_activation_source_t source;
|
||||||
} window_activate_request_event_t;
|
} window_activate_request_event_t;
|
||||||
|
|
||||||
typedef enum window_state_request_kind_t {
|
|
||||||
ZDWM_WINDOW_STATE_REQUEST_FULLSCREEN,
|
|
||||||
ZDWM_WINDOW_STATE_REQUEST_MAXIMIZED,
|
|
||||||
ZDWM_WINDOW_STATE_REQUEST_MINIMIZED,
|
|
||||||
} window_state_request_kind_t;
|
|
||||||
|
|
||||||
typedef enum window_state_request_action_t {
|
|
||||||
ZDWM_WINDOW_STATE_REQUEST_ACTION_ADD,
|
|
||||||
ZDWM_WINDOW_STATE_REQUEST_ACTION_REMOVE,
|
|
||||||
ZDWM_WINDOW_STATE_REQUEST_ACTION_TOGGLE,
|
|
||||||
} window_state_request_action_t;
|
|
||||||
|
|
||||||
typedef struct window_state_request_event_t {
|
typedef struct window_state_request_event_t {
|
||||||
window_id_t window;
|
window_id_t window;
|
||||||
window_state_request_kind_t kind;
|
window_state_request_type_t type;
|
||||||
window_state_request_action_t action;
|
window_state_request_action_t action;
|
||||||
} window_state_request_event_t;
|
} window_state_request_event_t;
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,10 @@ typedef enum effect_type_t {
|
|||||||
ZDWM_EFFECT_UNMAP_WINDOW,
|
ZDWM_EFFECT_UNMAP_WINDOW,
|
||||||
ZDWM_EFFECT_FOCUS_WINDOW,
|
ZDWM_EFFECT_FOCUS_WINDOW,
|
||||||
ZDWM_EFFECT_KILL_WINDOW,
|
ZDWM_EFFECT_KILL_WINDOW,
|
||||||
|
ZDWM_EFFECT_WITHDRAW_WINDOW,
|
||||||
|
ZDWM_EFFECT_MINIMIZE_WINDOW,
|
||||||
|
ZDWM_EFFECT_MAXIMIZE_WINDOW,
|
||||||
|
ZDWM_EFFECT_FULLSCREEN_WINDOW,
|
||||||
ZDWM_EFFECT_MOVE_WINDOW,
|
ZDWM_EFFECT_MOVE_WINDOW,
|
||||||
ZDWM_EFFECT_RESIZE_WINDOW,
|
ZDWM_EFFECT_RESIZE_WINDOW,
|
||||||
ZDWM_EFFECT_CHANGE_BORDER_COLOR,
|
ZDWM_EFFECT_CHANGE_BORDER_COLOR,
|
||||||
@@ -54,6 +58,11 @@ typedef struct effect_bind_key_t {
|
|||||||
size_t count;
|
size_t count;
|
||||||
} effect_bind_key_t;
|
} effect_bind_key_t;
|
||||||
|
|
||||||
|
typedef struct effect_bool_window_t {
|
||||||
|
window_id_t window;
|
||||||
|
bool value;
|
||||||
|
} effect_bool_window_t;
|
||||||
|
|
||||||
typedef struct effect_t {
|
typedef struct effect_t {
|
||||||
effect_type_t type;
|
effect_type_t type;
|
||||||
union {
|
union {
|
||||||
@@ -61,6 +70,10 @@ typedef struct effect_t {
|
|||||||
effect_only_window_id_t unmap;
|
effect_only_window_id_t unmap;
|
||||||
effect_only_window_id_t focus;
|
effect_only_window_id_t focus;
|
||||||
effect_only_window_id_t kill;
|
effect_only_window_id_t kill;
|
||||||
|
effect_only_window_id_t withdraw;
|
||||||
|
effect_bool_window_t minimize;
|
||||||
|
effect_bool_window_t maximize;
|
||||||
|
effect_bool_window_t fullscreen;
|
||||||
effect_move_window_t move;
|
effect_move_window_t move;
|
||||||
effect_resize_window_t resize;
|
effect_resize_window_t resize;
|
||||||
effect_change_border_color_t change_border_color;
|
effect_change_border_color_t change_border_color;
|
||||||
|
|||||||
@@ -119,11 +119,22 @@ static void route_window_remove(
|
|||||||
const window_t *window = state_window_get(state, e->window);
|
const window_t *window = state_window_get(state, e->window);
|
||||||
if (!window) return;
|
if (!window) return;
|
||||||
|
|
||||||
command_t unmanage_window_cmd = {
|
switch (e->reason) {
|
||||||
.type = ZDWM_COMMAND_UNMANAGE_WINDOW,
|
case ZDWM_WINDOW_REMOVE_WITHDRAWN:
|
||||||
.as.unmanage.window = e->window,
|
command_t withdrawn_window_cmd = {
|
||||||
};
|
.type = ZDWM_COMMAND_WITHDRAW_WINDOW,
|
||||||
command_buffer_push(out, &unmanage_window_cmd);
|
.as.withdraw.window = e->window,
|
||||||
|
};
|
||||||
|
command_buffer_push(out, &withdrawn_window_cmd);
|
||||||
|
break;
|
||||||
|
case ZDWM_WINDOW_REMOVE_DESTROY:
|
||||||
|
command_t unmanage_window_cmd = {
|
||||||
|
.type = ZDWM_COMMAND_UNMANAGE_WINDOW,
|
||||||
|
.as.unmanage.window = e->window,
|
||||||
|
};
|
||||||
|
command_buffer_push(out, &unmanage_window_cmd);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void policy_route_event(
|
void policy_route_event(
|
||||||
@@ -194,8 +205,8 @@ static void add_switch_workspace_effects(
|
|||||||
plan_push_effect(plan, &unmap_effect);
|
plan_push_effect(plan, &unmap_effect);
|
||||||
} else if (window->workspace_id == new_workspace) {
|
} else if (window->workspace_id == new_workspace) {
|
||||||
effect_t map_effect = {
|
effect_t map_effect = {
|
||||||
.type = ZDWM_EFFECT_MAP_WINDOW,
|
.type = ZDWM_EFFECT_MAP_WINDOW,
|
||||||
.as.unmap.window = window->id,
|
.as.map.window = window->id,
|
||||||
};
|
};
|
||||||
plan_push_effect(plan, &map_effect);
|
plan_push_effect(plan, &map_effect);
|
||||||
}
|
}
|
||||||
@@ -261,6 +272,177 @@ static void kill_window(state_t *state, window_id_t window, plan_t *plan) {
|
|||||||
plan_push_effect(plan, &kill_effect);
|
plan_push_effect(plan, &kill_effect);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void withdraw_window(state_t *state, window_id_t window, plan_t *plan) {
|
||||||
|
auto win = state_window_get(state, window);
|
||||||
|
if (!win) return;
|
||||||
|
|
||||||
|
effect_t withdraw_window_effect = {
|
||||||
|
.type = ZDWM_EFFECT_WITHDRAW_WINDOW,
|
||||||
|
.as.withdraw.window = window,
|
||||||
|
};
|
||||||
|
plan_push_effect(plan, &withdraw_window_effect);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void fullscreen_window(
|
||||||
|
state_t *state,
|
||||||
|
window_id_t window_id,
|
||||||
|
bool value,
|
||||||
|
plan_t *plan
|
||||||
|
) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
effect_t fullscreen_window_effect = {
|
||||||
|
.type = ZDWM_EFFECT_FULLSCREEN_WINDOW,
|
||||||
|
.as.fullscreen = {.window = window_id, .value = value},
|
||||||
|
};
|
||||||
|
plan_push_effect(plan, &fullscreen_window_effect);
|
||||||
|
|
||||||
|
if (value) {
|
||||||
|
state_window_set_geometry_mode(state, window_id, ZDWM_GEOMETRY_FULLSCREEN);
|
||||||
|
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);
|
||||||
|
if (window->floating) {
|
||||||
|
state_window_set_frame_rect(state, window_id, window->float_rect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
plan->need_relayout = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void maximize_window(
|
||||||
|
state_t *state,
|
||||||
|
window_id_t window_id,
|
||||||
|
bool value,
|
||||||
|
plan_t *plan
|
||||||
|
) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
effect_t maximize_window_effect = {
|
||||||
|
.type = ZDWM_EFFECT_MAXIMIZE_WINDOW,
|
||||||
|
.as.maximize = {.window = window_id, .value = value},
|
||||||
|
};
|
||||||
|
plan_push_effect(plan, &maximize_window_effect);
|
||||||
|
|
||||||
|
if (value) {
|
||||||
|
state_window_set_geometry_mode(state, window_id, ZDWM_GEOMETRY_MAXIMIZED);
|
||||||
|
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);
|
||||||
|
if (window->floating) {
|
||||||
|
state_window_set_frame_rect(state, window_id, window->float_rect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
plan->need_relayout = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void minimize_window(
|
||||||
|
state_t *state,
|
||||||
|
window_id_t window_id,
|
||||||
|
bool value,
|
||||||
|
plan_t *plan
|
||||||
|
) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
effect_t minimize_window_effect = {
|
||||||
|
.type = ZDWM_EFFECT_MINIMIZE_WINDOW,
|
||||||
|
.as.minimize = {.window = window_id, .value = value},
|
||||||
|
};
|
||||||
|
plan_push_effect(plan, &minimize_window_effect);
|
||||||
|
|
||||||
|
if (value) {
|
||||||
|
state_window_set_geometry_mode(state, window_id, ZDWM_GEOMETRY_MINIMIZED);
|
||||||
|
|
||||||
|
effect_t unmap_effect = {
|
||||||
|
.type = ZDWM_EFFECT_UNMAP_WINDOW,
|
||||||
|
.as.unmap.window = window_id,
|
||||||
|
};
|
||||||
|
plan_push_effect(plan, &unmap_effect);
|
||||||
|
/* TODO: 可能需要处理焦点 */
|
||||||
|
} else {
|
||||||
|
state_window_set_geometry_mode(state, window_id, ZDWM_GEOMETRY_NORMAL);
|
||||||
|
state_workspace_set_focused_window(state, window->workspace_id, window_id);
|
||||||
|
effect_t map_effect = {
|
||||||
|
.type = ZDWM_EFFECT_MAP_WINDOW,
|
||||||
|
.as.map.window = window_id
|
||||||
|
};
|
||||||
|
effect_t focus_effect = {
|
||||||
|
.type = ZDWM_EFFECT_FOCUS_WINDOW,
|
||||||
|
.as.focus.window = window_id,
|
||||||
|
};
|
||||||
|
plan_push_effect(plan, &map_effect);
|
||||||
|
plan_push_effect(plan, &focus_effect);
|
||||||
|
}
|
||||||
|
|
||||||
|
plan->need_relayout = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void change_window_state(
|
||||||
|
state_t *state,
|
||||||
|
const window_state_change_command_t *command,
|
||||||
|
plan_t *plan
|
||||||
|
) {
|
||||||
|
auto window = state_window_get(state, command->window);
|
||||||
|
if (!window) return;
|
||||||
|
|
||||||
|
bool value = false;
|
||||||
|
switch (command->action) {
|
||||||
|
case ZDWM_WINDOW_STATE_ACTION_ADD:
|
||||||
|
value = true;
|
||||||
|
break;
|
||||||
|
case ZDWM_WINDOW_STATE_ACTION_REMOVE:
|
||||||
|
value = false;
|
||||||
|
break;
|
||||||
|
case ZDWM_WINDOW_STATE_ACTION_TOGGLE:
|
||||||
|
switch (command->type) {
|
||||||
|
case ZDWM_WINDOW_STATE_REQUEST_FULLSCREEN:
|
||||||
|
value = !(window->geometry_mode == ZDWM_GEOMETRY_FULLSCREEN);
|
||||||
|
break;
|
||||||
|
case ZDWM_WINDOW_STATE_REQUEST_MAXIMIZED:
|
||||||
|
value = !(window->geometry_mode == ZDWM_GEOMETRY_MAXIMIZED);
|
||||||
|
break;
|
||||||
|
case ZDWM_WINDOW_STATE_REQUEST_MINIMIZED:
|
||||||
|
value = !(window->geometry_mode == ZDWM_GEOMETRY_MINIMIZED);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (command->type) {
|
||||||
|
case ZDWM_WINDOW_STATE_REQUEST_FULLSCREEN:
|
||||||
|
fullscreen_window(state, window->id, value, plan);
|
||||||
|
break;
|
||||||
|
case ZDWM_WINDOW_STATE_REQUEST_MAXIMIZED:
|
||||||
|
maximize_window(state, window->id, value, plan);
|
||||||
|
break;
|
||||||
|
case ZDWM_WINDOW_STATE_REQUEST_MINIMIZED:
|
||||||
|
minimize_window(state, window->id, value, plan);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void switch_workspace(
|
static void switch_workspace(
|
||||||
state_t *state,
|
state_t *state,
|
||||||
const switch_workspace_command_t *command,
|
const switch_workspace_command_t *command,
|
||||||
@@ -304,10 +486,15 @@ void policy_apply_command(
|
|||||||
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);
|
||||||
break;
|
break;
|
||||||
|
case ZDWM_COMMAND_WITHDRAW_WINDOW:
|
||||||
|
withdraw_window(state, cmd->as.withdraw.window, plan);
|
||||||
|
break;
|
||||||
|
case ZDWM_COMMAND_CHANGE_WINDOW_STATE:
|
||||||
|
change_window_state(state, &cmd->as.state_change, plan);
|
||||||
|
break;
|
||||||
case ZDWM_COMMAND_SWITCH_WORKSPACE:
|
case ZDWM_COMMAND_SWITCH_WORKSPACE:
|
||||||
switch_workspace(state, &cmd->as.switch_workspace, plan);
|
switch_workspace(state, &cmd->as.switch_workspace, plan);
|
||||||
break;
|
break;
|
||||||
default:
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
#include <zdwm/layout.h>
|
#include <zdwm/layout.h>
|
||||||
|
|
||||||
#include "action.h"
|
#include "action.h"
|
||||||
@@ -145,9 +146,6 @@ void runtime_setup(runtime_t *runtime) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const layout_result_t *runtime_layout_calc(runtime_t *runtime) {
|
static const layout_result_t *runtime_layout_calc(runtime_t *runtime) {
|
||||||
auto plan = &runtime->plan;
|
|
||||||
if (!plan->need_relayout) return nullptr;
|
|
||||||
|
|
||||||
auto result = &runtime->layout_result;
|
auto result = &runtime->layout_result;
|
||||||
zdwm_layout_result_reset(result);
|
zdwm_layout_result_reset(result);
|
||||||
|
|
||||||
@@ -169,11 +167,24 @@ static const layout_result_t *runtime_layout_calc(runtime_t *runtime) {
|
|||||||
for (size_t j = 0; j < state_window_count(state); j++) {
|
for (size_t j = 0; j < state_window_count(state); j++) {
|
||||||
auto window = state_window_at(state, j);
|
auto window = state_window_at(state, j);
|
||||||
if (!window || window->workspace_id != workspace->id) continue;
|
if (!window || window->workspace_id != workspace->id) continue;
|
||||||
if (!window_need_layout(window)) continue;
|
|
||||||
|
|
||||||
window_id_t *window_id_slot =
|
if (window_need_layout(window)) {
|
||||||
array_push(window_ids, window_count, window_list_capacity);
|
window_id_t *window_id_slot =
|
||||||
*window_id_slot = window->id;
|
array_push(window_ids, window_count, window_list_capacity);
|
||||||
|
*window_id_slot = window->id;
|
||||||
|
} else if (window->geometry_mode == ZDWM_GEOMETRY_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) {
|
||||||
|
layout_item_t item = {
|
||||||
|
.window_id = window->id,
|
||||||
|
.rect = output->workarea,
|
||||||
|
};
|
||||||
|
layout_result_push(result, item);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (window_count) {
|
if (window_count) {
|
||||||
@@ -194,6 +205,44 @@ static const layout_result_t *runtime_layout_calc(runtime_t *runtime) {
|
|||||||
return result->item_count ? result : nullptr;
|
return result->item_count ? result : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void runtime_apply_window_rect(
|
||||||
|
state_t *state,
|
||||||
|
window_id_t window_id,
|
||||||
|
rect_t rect,
|
||||||
|
plan_t *plan
|
||||||
|
) {
|
||||||
|
auto window = state_window_get(state, window_id);
|
||||||
|
if (!window) return;
|
||||||
|
|
||||||
|
auto need_move = window_need_move(window, rect.x, rect.y);
|
||||||
|
auto need_resize = window_need_resize(window, rect.width, rect.height);
|
||||||
|
if (need_move) {
|
||||||
|
effect_t move_window_effect = {
|
||||||
|
.type = ZDWM_EFFECT_MOVE_WINDOW,
|
||||||
|
.as.move = {
|
||||||
|
.window = window_id,
|
||||||
|
.left_top_point = {.x = rect.x, .y = rect.y}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
plan_push_effect(plan, &move_window_effect);
|
||||||
|
}
|
||||||
|
if (need_resize) {
|
||||||
|
effect_t resize_window_effect = {
|
||||||
|
.type = ZDWM_EFFECT_RESIZE_WINDOW,
|
||||||
|
.as.resize = {
|
||||||
|
.window = window_id,
|
||||||
|
.width = rect.width,
|
||||||
|
.height = rect.height,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
plan_push_effect(plan, &resize_window_effect);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (need_move || need_resize) {
|
||||||
|
state_window_set_frame_rect(state, window_id, rect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void runtime_arrange(runtime_t *runtime) {
|
static void runtime_arrange(runtime_t *runtime) {
|
||||||
auto result = runtime_layout_calc(runtime);
|
auto result = runtime_layout_calc(runtime);
|
||||||
if (!result) return;
|
if (!result) return;
|
||||||
@@ -201,38 +250,8 @@ static void runtime_arrange(runtime_t *runtime) {
|
|||||||
auto state = &runtime->state;
|
auto state = &runtime->state;
|
||||||
auto plan = &runtime->plan;
|
auto plan = &runtime->plan;
|
||||||
for (size_t i = 0; i < result->item_count; ++i) {
|
for (size_t i = 0; i < result->item_count; ++i) {
|
||||||
auto window_id = result->items[i].window_id;
|
auto item = &result->items[i];
|
||||||
auto window = state_window_get(state, window_id);
|
runtime_apply_window_rect(state, item->window_id, item->rect, plan);
|
||||||
|
|
||||||
if (!window) continue;
|
|
||||||
|
|
||||||
auto rect = result->items[i].rect;
|
|
||||||
auto frame_rect = window->frame_rect;
|
|
||||||
|
|
||||||
if (frame_rect.x != rect.x || frame_rect.y != rect.y) {
|
|
||||||
effect_t move_window_effect = {
|
|
||||||
.type = ZDWM_EFFECT_MOVE_WINDOW,
|
|
||||||
.as.move = {
|
|
||||||
.window = window->id,
|
|
||||||
.left_top_point = {.x = rect.x, .y = rect.y}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
plan_push_effect(plan, &move_window_effect);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (frame_rect.width != rect.width || frame_rect.height != rect.height) {
|
|
||||||
effect_t resize_window_effect = {
|
|
||||||
.type = ZDWM_EFFECT_RESIZE_WINDOW,
|
|
||||||
.as.resize = {
|
|
||||||
.window = window_id,
|
|
||||||
.width = rect.width,
|
|
||||||
.height = rect.height,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
plan_push_effect(plan, &resize_window_effect);
|
|
||||||
}
|
|
||||||
|
|
||||||
state_window_set_frame_rect(state, window_id, rect);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -261,7 +280,7 @@ void runtime_run(runtime_t *runtime) {
|
|||||||
|
|
||||||
policy_route_event(&ctx, &event, command_buffer);
|
policy_route_event(&ctx, &event, command_buffer);
|
||||||
policy_apply_command(&ctx, command_buffer, plan);
|
policy_apply_command(&ctx, command_buffer, plan);
|
||||||
runtime_arrange(runtime);
|
if (plan->need_relayout) runtime_arrange(runtime);
|
||||||
if (plan->count) backend_apply_effect(backend, plan->effects, plan->count);
|
if (plan->count) backend_apply_effect(backend, plan->effects, plan->count);
|
||||||
|
|
||||||
event_cleanup(&event);
|
event_cleanup(&event);
|
||||||
|
|||||||
@@ -67,3 +67,15 @@ typedef struct key_bind_t {
|
|||||||
modifier_mask_t modifiers;
|
modifier_mask_t modifiers;
|
||||||
keysym_t keysym;
|
keysym_t keysym;
|
||||||
} key_bind_t;
|
} key_bind_t;
|
||||||
|
|
||||||
|
typedef enum window_state_request_type_t {
|
||||||
|
ZDWM_WINDOW_STATE_REQUEST_FULLSCREEN,
|
||||||
|
ZDWM_WINDOW_STATE_REQUEST_MAXIMIZED,
|
||||||
|
ZDWM_WINDOW_STATE_REQUEST_MINIMIZED,
|
||||||
|
} window_state_request_type_t;
|
||||||
|
|
||||||
|
typedef enum window_state_request_action_t {
|
||||||
|
ZDWM_WINDOW_STATE_ACTION_ADD,
|
||||||
|
ZDWM_WINDOW_STATE_ACTION_REMOVE,
|
||||||
|
ZDWM_WINDOW_STATE_ACTION_TOGGLE,
|
||||||
|
} window_state_request_action_t;
|
||||||
|
|||||||
@@ -135,3 +135,14 @@ bool window_need_layout(const window_t *window) {
|
|||||||
|
|
||||||
return true;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool window_need_resize(const window_t *window, int32_t width, int32_t height) {
|
||||||
|
return window->frame_rect.width != width ||
|
||||||
|
window->frame_rect.height != height;
|
||||||
|
}
|
||||||
|
|||||||
@@ -121,3 +121,5 @@ void window_take_metadata(
|
|||||||
* @brief 窗口是否需要参与布局计算
|
* @brief 窗口是否需要参与布局计算
|
||||||
*/
|
*/
|
||||||
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_resize(const window_t *window, int32_t width, int32_t height);
|
||||||
|
|||||||
Reference in New Issue
Block a user