refactor(backend/X11): 重构 effect 应用为延迟批量模式并添加 KILL_WINDOW 支持
- 添加 ZDWM_EFFECT_KILL_WINDOW 副作用和 WM_DELETE_WINDOW 协议支持 - 将 backend_apply_effect 从即时调用 X11 拆分为 merge + batch apply 两阶段: - 先收集 effect 到后端持有的列表 - 再按 unmap(grab server) → map → kill → configure → focus 顺序统一提交
This commit is contained in:
@@ -15,6 +15,7 @@
|
|||||||
|
|
||||||
#include "backend/output_utils.h"
|
#include "backend/output_utils.h"
|
||||||
#include "backend/x11/window.h"
|
#include "backend/x11/window.h"
|
||||||
|
#include "base/array.h"
|
||||||
#include "base/log.h"
|
#include "base/log.h"
|
||||||
#include "base/macros.h"
|
#include "base/macros.h"
|
||||||
#include "base/memory.h"
|
#include "base/memory.h"
|
||||||
@@ -169,6 +170,15 @@ backend_t *backend_create(const char *display_name) {
|
|||||||
void backend_destroy(backend_t *backend) {
|
void backend_destroy(backend_t *backend) {
|
||||||
if (!backend) return;
|
if (!backend) return;
|
||||||
|
|
||||||
|
p_delete(&backend->config_list.cfgs);
|
||||||
|
p_clear(&backend->config_list, 1);
|
||||||
|
|
||||||
|
p_delete(&backend->unmap.windows);
|
||||||
|
p_clear(&backend->unmap, 1);
|
||||||
|
|
||||||
|
p_delete(&backend->kill.windows);
|
||||||
|
p_clear(&backend->kill, 1);
|
||||||
|
|
||||||
xcb_disconnect(backend->conn);
|
xcb_disconnect(backend->conn);
|
||||||
backend->conn = nullptr;
|
backend->conn = nullptr;
|
||||||
free(backend);
|
free(backend);
|
||||||
@@ -415,70 +425,70 @@ backend_restack_windows(backend_t *backend, const effect_window_list_t *list) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct window_configure_t {
|
static void window_configure_list_reset(window_configure_list_t *configs) {
|
||||||
xcb_window_t window;
|
p_clear(configs->cfgs, configs->count);
|
||||||
uint16_t mask;
|
configs->count = 0;
|
||||||
xcb_configure_window_value_list_t value;
|
}
|
||||||
} window_configure_t;
|
|
||||||
|
static void backend_apply_window_configure_list(backend_t *backend) {
|
||||||
|
xcb_connection_t *conn = backend->conn;
|
||||||
|
window_configure_list_t *configs = &backend->config_list;
|
||||||
|
for (size_t i = 0; i < configs->count; ++i) {
|
||||||
|
window_configure_t *cfg = &configs->cfgs[i];
|
||||||
|
if (!cfg->mask) continue;
|
||||||
|
|
||||||
static void
|
|
||||||
flush_configure(xcb_connection_t *conn, const window_configure_t *cfg) {
|
|
||||||
if (cfg->mask) {
|
|
||||||
xcb_configure_window_aux(conn, cfg->window, cfg->mask, &cfg->value);
|
xcb_configure_window_aux(conn, cfg->window, cfg->mask, &cfg->value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static window_configure_t *find_or_push_configure(
|
static window_configure_t *
|
||||||
window_configure_t *cfgs,
|
find_or_push_configure(window_configure_list_t *configs, xcb_window_t window) {
|
||||||
size_t *cfg_count,
|
window_configure_t *cfg = nullptr;
|
||||||
xcb_window_t window
|
for (size_t i = 0; i < configs->count; ++i) {
|
||||||
) {
|
cfg = &configs->cfgs[i];
|
||||||
for (size_t j = 0; j < *cfg_count; ++j) {
|
if (cfg->window == window) return cfg;
|
||||||
if (cfgs[j].window == window) return &cfgs[j];
|
|
||||||
}
|
}
|
||||||
window_configure_t *cfg = &cfgs[(*cfg_count)++];
|
|
||||||
|
cfg = array_push(configs->cfgs, configs->count, configs->capacity);
|
||||||
|
p_clear(cfg, 1);
|
||||||
cfg->window = window;
|
cfg->window = window;
|
||||||
cfg->mask = 0;
|
cfg->mask = 0;
|
||||||
return cfg;
|
return cfg;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool backend_apply_effect(
|
static void backend_merge_effects(
|
||||||
backend_t *backend,
|
backend_t *backend,
|
||||||
const effect_t *effects,
|
const effect_t *effects,
|
||||||
size_t effect_count
|
size_t effect_count
|
||||||
) {
|
) {
|
||||||
xcb_connection_t *conn = backend->conn;
|
window_configure_list_t *configs = &backend->config_list;
|
||||||
|
|
||||||
/* collect configure-like effects per window */
|
|
||||||
window_configure_t *cfgs = p_new(window_configure_t, effect_count);
|
|
||||||
size_t cfg_count = 0;
|
|
||||||
|
|
||||||
bool focus_window_changed = false;
|
|
||||||
xcb_window_t focus_window = XCB_WINDOW_NONE;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < effect_count; ++i) {
|
for (size_t i = 0; i < effect_count; ++i) {
|
||||||
const effect_t *e = &effects[i];
|
const effect_t *e = &effects[i];
|
||||||
switch (e->type) {
|
switch (e->type) {
|
||||||
case ZDWM_EFFECT_MAP_WINDOW:
|
case ZDWM_EFFECT_MAP_WINDOW:
|
||||||
xcb_map_window(conn, e->as.map.window);
|
window_list_push(&backend->map, e->as.map.window);
|
||||||
break;
|
break;
|
||||||
case ZDWM_EFFECT_UNMAP_WINDOW:
|
case ZDWM_EFFECT_UNMAP_WINDOW:
|
||||||
xcb_unmap_window(conn, e->as.unmap.window);
|
window_list_push(&backend->unmap, e->as.unmap.window);
|
||||||
break;
|
break;
|
||||||
case ZDWM_EFFECT_FOCUS_WINDOW:
|
case ZDWM_EFFECT_FOCUS_WINDOW:
|
||||||
focus_window = e->as.focus.window;
|
backend->focus_window = e->as.focus.window;
|
||||||
focus_window_changed = true;
|
backend->update_focus = true;
|
||||||
|
break;
|
||||||
|
case ZDWM_EFFECT_KILL_WINDOW:
|
||||||
|
window_list_push(&backend->kill, e->as.kill.window);
|
||||||
break;
|
break;
|
||||||
case ZDWM_EFFECT_MOVE_WINDOW: {
|
case ZDWM_EFFECT_MOVE_WINDOW: {
|
||||||
window_configure_t *cfg =
|
window_configure_t *cfg =
|
||||||
find_or_push_configure(cfgs, &cfg_count, e->as.move.window);
|
find_or_push_configure(configs, e->as.move.window);
|
||||||
cfg->mask |= XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y;
|
cfg->mask |= XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y;
|
||||||
cfg->value.x = e->as.move.left_top_point.x;
|
cfg->value.x = e->as.move.left_top_point.x;
|
||||||
cfg->value.y = e->as.move.left_top_point.y;
|
cfg->value.y = e->as.move.left_top_point.y;
|
||||||
} break;
|
} break;
|
||||||
case ZDWM_EFFECT_RESIZE_WINDOW: {
|
case ZDWM_EFFECT_RESIZE_WINDOW: {
|
||||||
window_configure_t *cfg =
|
window_configure_t *cfg =
|
||||||
find_or_push_configure(cfgs, &cfg_count, e->as.resize.window);
|
find_or_push_configure(configs, e->as.resize.window);
|
||||||
cfg->mask |= XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT;
|
cfg->mask |= XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT;
|
||||||
cfg->value.width = (uint32_t)e->as.resize.width;
|
cfg->value.width = (uint32_t)e->as.resize.width;
|
||||||
cfg->value.height = (uint32_t)e->as.resize.height;
|
cfg->value.height = (uint32_t)e->as.resize.height;
|
||||||
@@ -488,18 +498,15 @@ bool backend_apply_effect(
|
|||||||
.border_pixel = e->as.change_border_color.color->argb
|
.border_pixel = e->as.change_border_color.color->argb
|
||||||
};
|
};
|
||||||
xcb_change_window_attributes_aux(
|
xcb_change_window_attributes_aux(
|
||||||
conn,
|
backend->conn,
|
||||||
e->as.change_border_color.window,
|
e->as.change_border_color.window,
|
||||||
XCB_CW_BORDER_PIXEL,
|
XCB_CW_BORDER_PIXEL,
|
||||||
&value
|
&value
|
||||||
);
|
);
|
||||||
} break;
|
} break;
|
||||||
case ZDWM_EFFECT_CHANGE_BORDER_WIDTH: {
|
case ZDWM_EFFECT_CHANGE_BORDER_WIDTH: {
|
||||||
window_configure_t *cfg = find_or_push_configure(
|
window_configure_t *cfg =
|
||||||
cfgs,
|
find_or_push_configure(configs, e->as.change_border_width.window);
|
||||||
&cfg_count,
|
|
||||||
e->as.change_border_width.window
|
|
||||||
);
|
|
||||||
cfg->mask |= XCB_CONFIG_WINDOW_BORDER_WIDTH;
|
cfg->mask |= XCB_CONFIG_WINDOW_BORDER_WIDTH;
|
||||||
cfg->value.border_width = e->as.change_border_width.border_width;
|
cfg->value.border_width = e->as.change_border_width.border_width;
|
||||||
} break;
|
} break;
|
||||||
@@ -512,14 +519,56 @@ bool backend_apply_effect(
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < cfg_count; ++i) {
|
|
||||||
flush_configure(conn, &cfgs[i]);
|
|
||||||
}
|
}
|
||||||
p_delete(&cfgs);
|
|
||||||
|
|
||||||
if (focus_window_changed) backend_focus_window(backend, focus_window);
|
static void backend_batch_apply_effects(backend_t *backend) {
|
||||||
|
xcb_connection_t *conn = backend->conn;
|
||||||
|
if (backend->unmap.count) {
|
||||||
|
xcb_grab_server(conn);
|
||||||
|
window_clean_event_mask(conn, backend->screen->root);
|
||||||
|
|
||||||
xcb_flush(conn);
|
window_list_t *unmap = &backend->unmap;
|
||||||
|
for (size_t i = 0; i < unmap->count; ++i) {
|
||||||
|
xcb_window_t window = unmap->windows[i];
|
||||||
|
window_clean_event_mask(conn, window);
|
||||||
|
xcb_unmap_window(conn, window);
|
||||||
|
}
|
||||||
|
|
||||||
|
root_set_event_mask(backend);
|
||||||
|
xcb_ungrab_server(conn);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < backend->map.count; ++i) {
|
||||||
|
xcb_window_t window = backend->map.windows[i];
|
||||||
|
window_set_event_mask(conn, window);
|
||||||
|
xcb_map_window(conn, window);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < backend->kill.count; ++i) {
|
||||||
|
window_kill(backend, backend->kill.windows[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
backend_apply_window_configure_list(backend);
|
||||||
|
|
||||||
|
if (backend->update_focus) {
|
||||||
|
backend_focus_window(backend, backend->focus_window);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool backend_apply_effect(
|
||||||
|
backend_t *backend,
|
||||||
|
const effect_t *effects,
|
||||||
|
size_t effect_count
|
||||||
|
) {
|
||||||
|
backend->update_focus = false;
|
||||||
|
window_configure_list_reset(&backend->config_list);
|
||||||
|
window_list_reset(&backend->unmap);
|
||||||
|
window_list_reset(&backend->map);
|
||||||
|
window_list_reset(&backend->kill);
|
||||||
|
|
||||||
|
backend_merge_effects(backend, effects, effect_count);
|
||||||
|
backend_batch_apply_effects(backend);
|
||||||
|
|
||||||
|
xcb_flush(backend->conn);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
#include <xcb/xcb.h>
|
#include <xcb/xcb.h>
|
||||||
#include <xcb/xproto.h>
|
#include <xcb/xproto.h>
|
||||||
|
|
||||||
@@ -13,6 +15,7 @@
|
|||||||
\
|
\
|
||||||
X(WM_PROTOCOLS) \
|
X(WM_PROTOCOLS) \
|
||||||
X(WM_TAKE_FOCUS) \
|
X(WM_TAKE_FOCUS) \
|
||||||
|
X(WM_DELETE_WINDOW) \
|
||||||
X(_NET_ACTIVE_WINDOW) \
|
X(_NET_ACTIVE_WINDOW) \
|
||||||
\
|
\
|
||||||
X(_NET_SUPPORTING_WM_CHECK) \
|
X(_NET_SUPPORTING_WM_CHECK) \
|
||||||
@@ -54,6 +57,24 @@ typedef struct atoms_t {
|
|||||||
#undef DECLARATION_ATOM
|
#undef DECLARATION_ATOM
|
||||||
} atoms_t;
|
} atoms_t;
|
||||||
|
|
||||||
|
typedef struct window_configure_t {
|
||||||
|
xcb_window_t window;
|
||||||
|
uint16_t mask;
|
||||||
|
xcb_configure_window_value_list_t value;
|
||||||
|
} window_configure_t;
|
||||||
|
|
||||||
|
typedef struct window_configure_list_t {
|
||||||
|
window_configure_t *cfgs;
|
||||||
|
size_t count;
|
||||||
|
size_t capacity;
|
||||||
|
} 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_connection_t *conn;
|
xcb_connection_t *conn;
|
||||||
xcb_screen_t *screen;
|
xcb_screen_t *screen;
|
||||||
@@ -65,4 +86,12 @@ struct backend_t {
|
|||||||
/* When no window should take focus, then focus this window */
|
/* When no window should take focus, then focus this window */
|
||||||
xcb_window_t window_no_focus;
|
xcb_window_t window_no_focus;
|
||||||
xcb_window_t wm_check_window;
|
xcb_window_t wm_check_window;
|
||||||
|
|
||||||
|
xcb_window_t focus_window;
|
||||||
|
bool update_focus;
|
||||||
|
|
||||||
|
window_configure_list_t config_list;
|
||||||
|
window_list_t unmap;
|
||||||
|
window_list_t map;
|
||||||
|
window_list_t kill;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#include <xcb/xcb_icccm.h>
|
#include <xcb/xcb_icccm.h>
|
||||||
#include <xcb/xproto.h>
|
#include <xcb/xproto.h>
|
||||||
|
|
||||||
|
#include "base/array.h"
|
||||||
#include "base/memory.h"
|
#include "base/memory.h"
|
||||||
#include "core/backend.h"
|
#include "core/backend.h"
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
@@ -244,16 +245,84 @@ window_state_t atom_to_window_state(const atoms_t *atoms, xcb_atom_t atom) {
|
|||||||
return (window_state_t)-1;
|
return (window_state_t)-1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void window_takefocus(backend_t *backend, xcb_window_t window) {
|
static bool
|
||||||
xcb_client_message_event_t ev = {0};
|
window_send_event(backend_t *backend, xcb_window_t window, xcb_atom_t atom) {
|
||||||
|
bool exist = false;
|
||||||
ev.response_type = XCB_CLIENT_MESSAGE;
|
|
||||||
ev.window = window;
|
|
||||||
ev.format = 32;
|
|
||||||
ev.type = backend->atoms.WM_PROTOCOLS,
|
|
||||||
ev.data.data32[0] = backend->atoms.WM_TAKE_FOCUS;
|
|
||||||
ev.data.data32[1] = XCB_CURRENT_TIME;
|
|
||||||
|
|
||||||
xcb_connection_t *conn = backend->conn;
|
xcb_connection_t *conn = backend->conn;
|
||||||
|
auto WM_PROTOCOLS = backend->atoms.WM_PROTOCOLS;
|
||||||
|
|
||||||
|
xcb_get_property_cookie_t cookie =
|
||||||
|
xcb_icccm_get_wm_protocols_unchecked(conn, window, WM_PROTOCOLS);
|
||||||
|
xcb_icccm_get_wm_protocols_reply_t reply = {0};
|
||||||
|
if (xcb_icccm_get_wm_protocols_reply(conn, cookie, &reply, nullptr)) {
|
||||||
|
for (uint32_t i = 0; !exist && i < reply.atoms_len; ++i) {
|
||||||
|
exist = reply.atoms[i] == atom;
|
||||||
|
}
|
||||||
|
xcb_icccm_get_wm_protocols_reply_wipe(&reply);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (exist) {
|
||||||
|
xcb_client_message_event_t ev = {
|
||||||
|
.response_type = XCB_CLIENT_MESSAGE,
|
||||||
|
.format = 32,
|
||||||
|
.window = window,
|
||||||
|
.type = WM_PROTOCOLS,
|
||||||
|
.data.data32 = {atom, XCB_CURRENT_TIME},
|
||||||
|
};
|
||||||
xcb_send_event(conn, false, window, XCB_EVENT_MASK_NO_EVENT, (char *)&ev);
|
xcb_send_event(conn, false, window, XCB_EVENT_MASK_NO_EVENT, (char *)&ev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return exist;
|
||||||
|
}
|
||||||
|
|
||||||
|
void window_takefocus(backend_t *backend, xcb_window_t window) {
|
||||||
|
window_send_event(backend, window, backend->atoms.WM_TAKE_FOCUS);
|
||||||
|
}
|
||||||
|
|
||||||
|
void window_kill(backend_t *backend, xcb_window_t window) {
|
||||||
|
if (window_send_event(backend, window, backend->atoms.WM_DELETE_WINDOW)) {
|
||||||
|
xcb_kill_client(backend->conn, window);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void root_set_event_mask(backend_t *backend) {
|
||||||
|
xcb_connection_t *conn = backend->conn;
|
||||||
|
xcb_window_t root = backend->screen->root;
|
||||||
|
xcb_cw_t change_mask = XCB_CW_EVENT_MASK;
|
||||||
|
xcb_change_window_attributes_value_list_t value_list = {
|
||||||
|
.event_mask =
|
||||||
|
XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | XCB_EVENT_MASK_KEY_PRESS,
|
||||||
|
};
|
||||||
|
xcb_change_window_attributes_aux(conn, root, change_mask, &value_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
void window_set_event_mask(xcb_connection_t *conn, xcb_window_t window) {
|
||||||
|
xcb_cw_t change_mask = XCB_CW_EVENT_MASK;
|
||||||
|
xcb_change_window_attributes_value_list_t value_list = {
|
||||||
|
.event_mask = XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_FOCUS_CHANGE |
|
||||||
|
XCB_EVENT_MASK_PROPERTY_CHANGE |
|
||||||
|
XCB_EVENT_MASK_STRUCTURE_NOTIFY |
|
||||||
|
XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY,
|
||||||
|
};
|
||||||
|
xcb_change_window_attributes_aux(conn, window, change_mask, &value_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
void window_clean_event_mask(xcb_connection_t *conn, xcb_window_t window) {
|
||||||
|
xcb_cw_t change_mask = XCB_CW_EVENT_MASK;
|
||||||
|
xcb_change_window_attributes_value_list_t value_list = {
|
||||||
|
.event_mask = XCB_EVENT_MASK_NO_EVENT,
|
||||||
|
};
|
||||||
|
xcb_change_window_attributes_aux(conn, window, change_mask, &value_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|||||||
@@ -7,9 +7,10 @@
|
|||||||
#include <xcb/xproto.h>
|
#include <xcb/xproto.h>
|
||||||
|
|
||||||
#include "core/backend.h"
|
#include "core/backend.h"
|
||||||
#include "core/window.h"
|
#include "internal.h"
|
||||||
|
|
||||||
typedef struct atoms_t atoms_t;
|
typedef struct atoms_t atoms_t;
|
||||||
|
typedef struct window_list_t window_list_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 获取窗口的 role 属性
|
* @brief 获取窗口的 role 属性
|
||||||
@@ -78,3 +79,11 @@ window_state_t atom_to_window_state(const atoms_t *atoms, xcb_atom_t atom);
|
|||||||
xcb_icccm_set_wm_class(conn, win, sizeof(instance_class), instance_class)
|
xcb_icccm_set_wm_class(conn, win, sizeof(instance_class), instance_class)
|
||||||
|
|
||||||
void window_takefocus(backend_t *backend, xcb_window_t window);
|
void window_takefocus(backend_t *backend, xcb_window_t window);
|
||||||
|
void window_kill(backend_t *backend, xcb_window_t window);
|
||||||
|
|
||||||
|
void root_set_event_mask(backend_t *backend);
|
||||||
|
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_list_push(window_list_t *window_list, xcb_window_t window);
|
||||||
|
void window_list_reset(window_list_t *window_list);
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ typedef enum effect_type_t {
|
|||||||
ZDWM_EFFECT_MAP_WINDOW = 1,
|
ZDWM_EFFECT_MAP_WINDOW = 1,
|
||||||
ZDWM_EFFECT_UNMAP_WINDOW,
|
ZDWM_EFFECT_UNMAP_WINDOW,
|
||||||
ZDWM_EFFECT_FOCUS_WINDOW,
|
ZDWM_EFFECT_FOCUS_WINDOW,
|
||||||
|
ZDWM_EFFECT_KILL_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,
|
||||||
@@ -53,6 +54,7 @@ typedef struct effect_t {
|
|||||||
effect_only_window_id_t map;
|
effect_only_window_id_t map;
|
||||||
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_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;
|
||||||
|
|||||||
Reference in New Issue
Block a user