feat: add shield_when_capture windowrule to disable capture

This commit is contained in:
DreamMaoMao 2026-02-19 14:39:37 +08:00
parent 68075c0044
commit d9aaf4df3f
3 changed files with 81 additions and 1 deletions

View file

@ -350,6 +350,24 @@ void client_draw_shadow(Client *c) {
wlr_scene_shadow_set_clipped_region(c->shadow, clipped_region); wlr_scene_shadow_set_clipped_region(c->shadow, clipped_region);
} }
void apply_shield(Client *c) {
if (active_capture_count > 0 && c->shield_when_capture) {
wlr_scene_node_raise_to_top(&c->shield->node);
wlr_scene_node_set_position(&c->shield->node, c->bw, c->bw);
wlr_scene_rect_set_size(c->shield,
c->animation.current.width - 2 * c->bw,
c->animation.current.height - 2 * c->bw);
wlr_scene_node_set_enabled(&c->shield->node, true);
} else {
if (c->shield->node.enabled) {
wlr_scene_node_lower_to_bottom(&c->shield->node);
wlr_scene_rect_set_size(c->shield, c->animation.current.width,
c->animation.current.height);
wlr_scene_node_set_enabled(&c->shield->node, false);
}
}
}
void apply_border(Client *c) { void apply_border(Client *c) {
if (!c || c->iskilling || !client_surface(c)->mapped) if (!c || c->iskilling || !client_surface(c)->mapped)
return; return;
@ -535,6 +553,7 @@ void client_apply_clip(Client *c, float factor) {
apply_border(c); apply_border(c);
client_draw_shadow(c); client_draw_shadow(c);
apply_shield(c);
if (clip_box.width <= 0 || clip_box.height <= 0) { if (clip_box.width <= 0 || clip_box.height <= 0) {
return; return;
@ -572,6 +591,7 @@ void client_apply_clip(Client *c, float factor) {
// 应用窗口装饰 // 应用窗口装饰
apply_border(c); apply_border(c);
client_draw_shadow(c); client_draw_shadow(c);
apply_shield(c);
// 如果窗口剪切区域已经剪切到0则不渲染窗口表面 // 如果窗口剪切区域已经剪切到0则不渲染窗口表面
if (clip_box.width <= 0 || clip_box.height <= 0) { if (clip_box.width <= 0 || clip_box.height <= 0) {
@ -1000,6 +1020,7 @@ void resize(Client *c, struct wlr_box geo, int32_t interact) {
client_draw_shadow(c); client_draw_shadow(c);
apply_border(c); apply_border(c);
apply_shield(c);
client_get_clip(c, &clip); client_get_clip(c, &clip);
wlr_scene_subsurface_tree_set_clip(&c->scene_surface->node, &clip); wlr_scene_subsurface_tree_set_clip(&c->scene_surface->node, &clip);
return; return;

View file

@ -74,6 +74,7 @@ typedef struct {
int32_t isunglobal; int32_t isunglobal;
int32_t isglobal; int32_t isglobal;
int32_t isoverlay; int32_t isoverlay;
int32_t shield_when_capture;
int32_t allow_shortcuts_inhibit; int32_t allow_shortcuts_inhibit;
int32_t ignore_maximize; int32_t ignore_maximize;
int32_t ignore_minimize; int32_t ignore_minimize;
@ -2011,6 +2012,7 @@ bool parse_option(Config *config, char *key, char *value) {
rule->isunglobal = -1; rule->isunglobal = -1;
rule->isglobal = -1; rule->isglobal = -1;
rule->isoverlay = -1; rule->isoverlay = -1;
rule->shield_when_capture = -1;
rule->allow_shortcuts_inhibit = -1; rule->allow_shortcuts_inhibit = -1;
rule->ignore_maximize = -1; rule->ignore_maximize = -1;
rule->ignore_minimize = -1; rule->ignore_minimize = -1;
@ -2117,6 +2119,8 @@ bool parse_option(Config *config, char *key, char *value) {
rule->focused_opacity = atof(val); rule->focused_opacity = atof(val);
} else if (strcmp(key, "isoverlay") == 0) { } else if (strcmp(key, "isoverlay") == 0) {
rule->isoverlay = atoi(val); rule->isoverlay = atoi(val);
} else if (strcmp(key, "shield_when_capture") == 0) {
rule->shield_when_capture = atoi(val);
} else if (strcmp(key, "allow_shortcuts_inhibit") == 0) { } else if (strcmp(key, "allow_shortcuts_inhibit") == 0) {
rule->allow_shortcuts_inhibit = atoi(val); rule->allow_shortcuts_inhibit = atoi(val);
} else if (strcmp(key, "ignore_maximize") == 0) { } else if (strcmp(key, "ignore_maximize") == 0) {

View file

@ -315,6 +315,7 @@ struct Client {
struct wlr_scene_tree *scene; struct wlr_scene_tree *scene;
struct wlr_scene_rect *border; /* top, bottom, left, right */ struct wlr_scene_rect *border; /* top, bottom, left, right */
struct wlr_scene_shadow *shadow; struct wlr_scene_shadow *shadow;
struct wlr_scene_rect *shield;
struct wlr_scene_tree *scene_surface; struct wlr_scene_tree *scene_surface;
struct wl_list link; struct wl_list link;
struct wl_list flink; struct wl_list flink;
@ -381,6 +382,7 @@ struct Client {
int32_t iskilling; int32_t iskilling;
int32_t istagswitching; int32_t istagswitching;
int32_t isnamedscratchpad; int32_t isnamedscratchpad;
int32_t shield_when_capture;
bool is_pending_open_animation; bool is_pending_open_animation;
bool is_restoring_from_ov; bool is_restoring_from_ov;
float scroller_proportion; float scroller_proportion;
@ -545,6 +547,11 @@ typedef struct {
struct wl_listener destroy; struct wl_listener destroy;
} SessionLock; } SessionLock;
struct capture_session_tracker {
struct wl_listener session_destroy;
struct wlr_ext_image_copy_capture_session_v1 *session;
};
/* function declarations */ /* function declarations */
static void applybounds( static void applybounds(
Client *c, Client *c,
@ -788,6 +795,8 @@ static Client *get_focused_stack_client(Client *sc);
static bool client_is_in_same_stack(Client *sc, Client *tc, Client *fc); static bool client_is_in_same_stack(Client *sc, Client *tc, Client *fc);
static void monitor_stop_skip_timer(Monitor *m); static void monitor_stop_skip_timer(Monitor *m);
static int monitor_skip_frame_timeout_callback(void *data); static int monitor_skip_frame_timeout_callback(void *data);
static void handle_iamge_copy_capture_new_session(struct wl_listener *listener,
void *data);
#include "data/static_keymap.h" #include "data/static_keymap.h"
#include "dispatch/bind_declare.h" #include "dispatch/bind_declare.h"
@ -825,6 +834,7 @@ static struct wlr_keyboard_shortcuts_inhibit_manager_v1
*keyboard_shortcuts_inhibit; *keyboard_shortcuts_inhibit;
static struct wlr_virtual_pointer_manager_v1 *virtual_pointer_mgr; static struct wlr_virtual_pointer_manager_v1 *virtual_pointer_mgr;
static struct wlr_output_power_manager_v1 *power_mgr; static struct wlr_output_power_manager_v1 *power_mgr;
static struct wlr_ext_image_copy_capture_manager_v1 *ext_image_copy_capture_mgr;
static struct wlr_pointer_gestures_v1 *pointer_gestures; static struct wlr_pointer_gestures_v1 *pointer_gestures;
static struct wlr_drm_lease_v1_manager *drm_lease_manager; static struct wlr_drm_lease_v1_manager *drm_lease_manager;
struct mango_print_status_manager *print_status_manager; struct mango_print_status_manager *print_status_manager;
@ -888,6 +898,7 @@ static struct wl_event_source *hide_source;
static bool cursor_hidden = false; static bool cursor_hidden = false;
static bool tag_combo = false; static bool tag_combo = false;
static const char *cli_config_path = NULL; static const char *cli_config_path = NULL;
static int active_capture_count = 0;
static KeyMode keymode = { static KeyMode keymode = {
.mode = {'d', 'e', 'f', 'a', 'u', 'l', 't', '\0'}, .mode = {'d', 'e', 'f', 'a', 'u', 'l', 't', '\0'},
.isdefault = true, .isdefault = true,
@ -938,6 +949,8 @@ static struct wl_listener output_mgr_apply = {.notify = outputmgrapply};
static struct wl_listener output_mgr_test = {.notify = outputmgrtest}; static struct wl_listener output_mgr_test = {.notify = outputmgrtest};
static struct wl_listener output_power_mgr_set_mode = {.notify = static struct wl_listener output_power_mgr_set_mode = {.notify =
powermgrsetmode}; powermgrsetmode};
static struct wl_listener ext_image_copy_capture_mgr_new_session = {
.notify = handle_iamge_copy_capture_new_session};
static struct wl_listener request_activate = {.notify = urgent}; static struct wl_listener request_activate = {.notify = urgent};
static struct wl_listener request_cursor = {.notify = setcursor}; static struct wl_listener request_cursor = {.notify = setcursor};
static struct wl_listener request_set_psel = {.notify = setpsel}; static struct wl_listener request_set_psel = {.notify = setpsel};
@ -1313,6 +1326,7 @@ static void apply_rule_properties(Client *c, const ConfigWinRule *r) {
APPLY_INT_PROP(c, r, isnamedscratchpad); APPLY_INT_PROP(c, r, isnamedscratchpad);
APPLY_INT_PROP(c, r, isglobal); APPLY_INT_PROP(c, r, isglobal);
APPLY_INT_PROP(c, r, isoverlay); APPLY_INT_PROP(c, r, isoverlay);
APPLY_INT_PROP(c, r, shield_when_capture);
APPLY_INT_PROP(c, r, ignore_maximize); APPLY_INT_PROP(c, r, ignore_maximize);
APPLY_INT_PROP(c, r, ignore_minimize); APPLY_INT_PROP(c, r, ignore_minimize);
APPLY_INT_PROP(c, r, isnosizehint); APPLY_INT_PROP(c, r, isnosizehint);
@ -4001,6 +4015,12 @@ mapnotify(struct wl_listener *listener, void *data) {
wlr_scene_node_lower_to_bottom(&c->shadow->node); wlr_scene_node_lower_to_bottom(&c->shadow->node);
wlr_scene_node_set_enabled(&c->shadow->node, true); wlr_scene_node_set_enabled(&c->shadow->node, true);
c->shield =
wlr_scene_rect_create(c->scene, 0, 0, (float[4]){0, 0, 0, 0xff});
c->shield->node.data = c;
wlr_scene_node_lower_to_bottom(&c->shield->node);
wlr_scene_node_set_enabled(&c->shield->node, false);
if (new_is_master && selmon && !is_scroller_layout(selmon)) if (new_is_master && selmon && !is_scroller_layout(selmon))
// tile at the top // tile at the top
wl_list_insert(&clients, &c->link); // 新窗口是master,头部入栈 wl_list_insert(&clients, &c->link); // 新窗口是master,头部入栈
@ -4409,6 +4429,37 @@ void pointerfocus(Client *c, struct wlr_surface *surface, double sx, double sy,
// 修改printstatus函数接受掩码参数 // 修改printstatus函数接受掩码参数
void printstatus(void) { wl_signal_emit(&mango_print_status, NULL); } void printstatus(void) { wl_signal_emit(&mango_print_status, NULL); }
// 会话销毁时的回调
void handle_session_destroy(struct wl_listener *listener, void *data) {
struct capture_session_tracker *tracker =
wl_container_of(listener, tracker, session_destroy);
active_capture_count--;
wl_list_remove(&tracker->session_destroy.link);
wlr_log(WLR_DEBUG, "Capture session ended, active count: %d",
active_capture_count);
free(tracker);
}
// 新会话创建时的回调
void handle_iamge_copy_capture_new_session(struct wl_listener *listener,
void *data) {
struct wlr_ext_image_copy_capture_session_v1 *session = data;
struct capture_session_tracker *tracker = calloc(1, sizeof(*tracker));
if (!tracker) {
wlr_log(WLR_ERROR, "Failed to allocate capture session tracker");
return;
}
tracker->session = session;
tracker->session_destroy.notify = handle_session_destroy;
// 监听会话的 destroy 信号,以便在会话结束时减少计数
wl_signal_add(&session->events.destroy, &tracker->session_destroy);
active_capture_count++;
wlr_log(WLR_DEBUG, "New capture session started, active count: %d",
active_capture_count);
}
void powermgrsetmode(struct wl_listener *listener, void *data) { void powermgrsetmode(struct wl_listener *listener, void *data) {
struct wlr_output_power_v1_set_mode_event *event = data; struct wlr_output_power_v1_set_mode_event *event = data;
struct wlr_output_state state = {0}; struct wlr_output_state state = {0};
@ -5344,7 +5395,6 @@ void setup(void) {
compositor = wlr_compositor_create(dpy, 6, drw); compositor = wlr_compositor_create(dpy, 6, drw);
wlr_export_dmabuf_manager_v1_create(dpy); wlr_export_dmabuf_manager_v1_create(dpy);
wlr_screencopy_manager_v1_create(dpy); wlr_screencopy_manager_v1_create(dpy);
wlr_ext_image_copy_capture_manager_v1_create(dpy, 1);
wlr_ext_output_image_capture_source_manager_v1_create(dpy, 1); wlr_ext_output_image_capture_source_manager_v1_create(dpy, 1);
wlr_data_control_manager_v1_create(dpy); wlr_data_control_manager_v1_create(dpy);
wlr_data_device_manager_create(dpy); wlr_data_device_manager_create(dpy);
@ -5361,6 +5411,11 @@ void setup(void) {
wl_signal_init(&mango_print_status); wl_signal_init(&mango_print_status);
wl_signal_add(&mango_print_status, &print_status_listener); wl_signal_add(&mango_print_status, &print_status_listener);
ext_image_copy_capture_mgr =
wlr_ext_image_copy_capture_manager_v1_create(dpy, 1);
wl_signal_add(&ext_image_copy_capture_mgr->events.new_session,
&ext_image_copy_capture_mgr_new_session);
/* Initializes the interface used to implement urgency hints */ /* Initializes the interface used to implement urgency hints */
activation = wlr_xdg_activation_v1_create(dpy); activation = wlr_xdg_activation_v1_create(dpy);
wl_signal_add(&activation->events.request_activate, &request_activate); wl_signal_add(&activation->events.request_activate, &request_activate);