opt: opitmize subtree surface scale in overview

This commit is contained in:
DreamMaoMao 2026-05-21 21:28:38 +08:00
parent 3261950bbf
commit 17d7cb8e7d
3 changed files with 71 additions and 11 deletions

View file

@ -225,10 +225,30 @@ void scene_buffer_apply_overview_effect(struct wlr_scene_buffer *buffer,
int32_t sx, int32_t sy, void *data) {
BufferData *buffer_data = (BufferData *)data;
if (buffer_data->width > 0 && buffer_data->height > 0) {
wlr_scene_buffer_set_dest_size(buffer, buffer_data->width,
buffer_data->height);
if (buffer_data->width_scale >= 1.0 || buffer_data->height_scale >= 1.0)
return;
int32_t surface_width = 0;
int32_t surface_height = 0;
bool is_subsurface = false;
struct wlr_scene_tree *parent_tree = buffer->node.parent;
if (parent_tree->node.data != NULL) {
SnapshotMetadata *meta = (SnapshotMetadata *)parent_tree->node.data;
surface_width = meta->orig_width;
surface_height = meta->orig_height;
is_subsurface = meta->is_subsurface;
}
surface_height = surface_height * buffer_data->height_scale;
surface_width = surface_width * buffer_data->width_scale;
if (buffer_data->width > 0 && buffer_data->height > 0) {
wlr_scene_buffer_set_dest_size(buffer, surface_width, surface_height);
}
if (is_subsurface)
return;
}
void buffer_set_effect(Client *c, BufferData data) {

View file

@ -28,6 +28,12 @@ struct dvec2 calculate_animation_curve_at(double t, int32_t type) {
return point;
}
void handle_snapshot_meta_destroy(struct wl_listener *listener, void *data) {
SnapshotMetadata *meta = wl_container_of(listener, meta, destroy);
wl_list_remove(&meta->destroy.link); // 安全移除监听器
free(meta);
}
void init_baked_points(void) {
baked_points_move = calloc(BAKED_POINTS_COUNT, sizeof(*baked_points_move));
baked_points_open = calloc(BAKED_POINTS_COUNT, sizeof(*baked_points_open));
@ -143,12 +149,43 @@ static bool scene_node_snapshot(struct wlr_scene_node *node, int32_t lx,
struct wlr_scene_buffer *scene_buffer =
wlr_scene_buffer_from_node(node);
struct wlr_scene_buffer *snapshot_buffer =
wlr_scene_buffer_create(snapshot_tree, NULL);
if (snapshot_buffer == NULL) {
// 创建中间包装树节点
struct wlr_scene_tree *wrapper = wlr_scene_tree_create(snapshot_tree);
if (wrapper == NULL) {
return false;
}
snapshot_node = &snapshot_buffer->node;
snapshot_node = &wrapper->node; // 坐标位移应用在外层包装盒上
// 收集表面状态并保存为元数据
SnapshotMetadata *meta = calloc(1, sizeof(SnapshotMetadata));
if (meta == NULL) {
wlr_scene_node_destroy(&wrapper->node);
return false;
}
meta->orig_width = scene_buffer->dst_width;
meta->orig_height = scene_buffer->dst_height;
struct wlr_scene_surface *scene_surface =
wlr_scene_surface_try_from_buffer(scene_buffer);
if (scene_surface != NULL) {
meta->is_subsurface =
!!wlr_subsurface_try_from_wlr_surface(scene_surface->surface);
}
// 绑定销毁回调监听,随包装节点销毁而释放内存
meta->destroy.notify = handle_snapshot_meta_destroy;
wl_signal_add(&wrapper->node.events.destroy, &meta->destroy);
wrapper->node.data = meta;
// 将真正的 buffer 挂靠在 wrapper 下面相对坐标0,0
struct wlr_scene_buffer *snapshot_buffer =
wlr_scene_buffer_create(wrapper, NULL);
if (snapshot_buffer == NULL) {
wlr_scene_node_destroy(&wrapper->node);
return false;
}
// 保留原生的 data 指针(如 Client*),防止事件派发/焦点获取失效
snapshot_buffer->node.data = scene_buffer->node.data;
wlr_scene_buffer_set_dest_size(snapshot_buffer, scene_buffer->dst_width,
@ -165,10 +202,6 @@ static bool scene_node_snapshot(struct wlr_scene_node *node, int32_t lx,
// Effects
wlr_scene_buffer_set_opacity(snapshot_buffer, scene_buffer->opacity);
snapshot_buffer->node.data = scene_buffer->node.data;
struct wlr_scene_surface *scene_surface =
wlr_scene_surface_try_from_buffer(scene_buffer);
if (scene_surface != NULL && scene_surface->surface->buffer != NULL) {
wlr_scene_buffer_set_buffer(snapshot_buffer,
&scene_surface->surface->buffer->base);