diff --git a/src/animation/client.h b/src/animation/client.h index b1b8e7d8..6428e0a6 100644 --- a/src/animation/client.h +++ b/src/animation/client.h @@ -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) { diff --git a/src/animation/common.h b/src/animation/common.h index 4da33aa7..62a2a494 100644 --- a/src/animation/common.h +++ b/src/animation/common.h @@ -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); diff --git a/src/mango.c b/src/mango.c index 78fc2928..78ca149f 100644 --- a/src/mango.c +++ b/src/mango.c @@ -617,6 +617,13 @@ struct TagScrollerState { int count; }; +typedef struct { + int32_t orig_width; + int32_t orig_height; + bool is_subsurface; + struct wl_listener destroy; +} SnapshotMetadata; + /* function declarations */ static void applybounds( Client *c,