diff options
author | Alexander Orzechowski <alex@ozal.ski> | 2023-04-27 10:25:40 +0200 |
---|---|---|
committer | Kirill Primak <vyivel@eclair.cafe> | 2024-01-18 18:36:54 +0300 |
commit | 06ad734e70227ad0527fe11b88ad37e93005ce0c (patch) | |
tree | 5a5e2606242e3d229f4979d2b7c5352a139730b0 /sway/tree/view.c | |
parent | xwayland: Cleanup geometry handling on commit (diff) | |
download | sway-06ad734e70227ad0527fe11b88ad37e93005ce0c.tar.gz sway-06ad734e70227ad0527fe11b88ad37e93005ce0c.tar.zst sway-06ad734e70227ad0527fe11b88ad37e93005ce0c.zip |
scene_graph: Port view saved buffers
Diffstat (limited to 'sway/tree/view.c')
-rw-r--r-- | sway/tree/view.c | 88 |
1 files changed, 57 insertions, 31 deletions
diff --git a/sway/tree/view.c b/sway/tree/view.c index ee25faf1..402fa179 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c | |||
@@ -56,7 +56,6 @@ bool view_init(struct sway_view *view, enum sway_view_type type, | |||
56 | view->type = type; | 56 | view->type = type; |
57 | view->impl = impl; | 57 | view->impl = impl; |
58 | view->executed_criteria = create_list(); | 58 | view->executed_criteria = create_list(); |
59 | wl_list_init(&view->saved_buffers); | ||
60 | view->allow_request_urgent = true; | 59 | view->allow_request_urgent = true; |
61 | view->shortcuts_inhibit = SHORTCUTS_INHIBIT_DEFAULT; | 60 | view->shortcuts_inhibit = SHORTCUTS_INHIBIT_DEFAULT; |
62 | wl_signal_init(&view->events.unmap); | 61 | wl_signal_init(&view->events.unmap); |
@@ -77,9 +76,6 @@ void view_destroy(struct sway_view *view) { | |||
77 | return; | 76 | return; |
78 | } | 77 | } |
79 | wl_list_remove(&view->events.unmap.listener_list); | 78 | wl_list_remove(&view->events.unmap.listener_list); |
80 | if (!wl_list_empty(&view->saved_buffers)) { | ||
81 | view_remove_saved_buffer(view); | ||
82 | } | ||
83 | list_free(view->executed_criteria); | 79 | list_free(view->executed_criteria); |
84 | 80 | ||
85 | view_assign_ctx(view, NULL); | 81 | view_assign_ctx(view, NULL); |
@@ -931,10 +927,10 @@ void view_center_surface(struct sway_view *view) { | |||
931 | struct sway_container *con = view->container; | 927 | struct sway_container *con = view->container; |
932 | // We always center the current coordinates rather than the next, as the | 928 | // We always center the current coordinates rather than the next, as the |
933 | // geometry immediately affects the currently active rendering. | 929 | // geometry immediately affects the currently active rendering. |
934 | con->surface_x = fmax(con->current.content_x, con->current.content_x + | 930 | int x = (int) fmax(0, (con->current.content_width - view->geometry.width) / 2); |
935 | (con->current.content_width - view->geometry.width) / 2); | 931 | int y = (int) fmax(0, (con->current.content_height - view->geometry.height) / 2); |
936 | con->surface_y = fmax(con->current.content_y, con->current.content_y + | 932 | |
937 | (con->current.content_height - view->geometry.height) / 2); | 933 | wlr_scene_node_set_position(&view->content_tree->node, x, y); |
938 | } | 934 | } |
939 | 935 | ||
940 | struct sway_view *view_from_wlr_surface(struct wlr_surface *wlr_surface) { | 936 | struct sway_view *view_from_wlr_surface(struct wlr_surface *wlr_surface) { |
@@ -1161,40 +1157,54 @@ bool view_is_urgent(struct sway_view *view) { | |||
1161 | } | 1157 | } |
1162 | 1158 | ||
1163 | void view_remove_saved_buffer(struct sway_view *view) { | 1159 | void view_remove_saved_buffer(struct sway_view *view) { |
1164 | if (!sway_assert(!wl_list_empty(&view->saved_buffers), "Expected a saved buffer")) { | 1160 | if (!sway_assert(view->saved_surface_tree, "Expected a saved buffer")) { |
1165 | return; | 1161 | return; |
1166 | } | 1162 | } |
1167 | struct sway_saved_buffer *saved_buf, *tmp; | 1163 | |
1168 | wl_list_for_each_safe(saved_buf, tmp, &view->saved_buffers, link) { | 1164 | wlr_scene_node_destroy(&view->saved_surface_tree->node); |
1169 | wlr_buffer_unlock(&saved_buf->buffer->base); | 1165 | view->saved_surface_tree = NULL; |
1170 | wl_list_remove(&saved_buf->link); | 1166 | wlr_scene_node_set_enabled(&view->content_tree->node, true); |
1171 | free(saved_buf); | ||
1172 | } | ||
1173 | } | 1167 | } |
1174 | 1168 | ||
1175 | static void view_save_buffer_iterator(struct wlr_surface *surface, | 1169 | static void view_save_buffer_iterator(struct wlr_scene_buffer *buffer, |
1176 | int sx, int sy, void *data) { | 1170 | int sx, int sy, void *data) { |
1177 | struct sway_view *view = data; | 1171 | struct wlr_scene_tree *tree = data; |
1178 | 1172 | ||
1179 | if (surface && surface->buffer) { | 1173 | struct wlr_scene_buffer *sbuf = wlr_scene_buffer_create(tree, NULL); |
1180 | wlr_buffer_lock(&surface->buffer->base); | 1174 | if (!sbuf) { |
1181 | struct sway_saved_buffer *saved_buffer = calloc(1, sizeof(struct sway_saved_buffer)); | 1175 | sway_log(SWAY_ERROR, "Could not allocate a scene buffer when saving a surface"); |
1182 | saved_buffer->buffer = surface->buffer; | 1176 | return; |
1183 | saved_buffer->width = surface->current.width; | ||
1184 | saved_buffer->height = surface->current.height; | ||
1185 | saved_buffer->x = view->container->surface_x + sx; | ||
1186 | saved_buffer->y = view->container->surface_y + sy; | ||
1187 | saved_buffer->transform = surface->current.transform; | ||
1188 | wlr_surface_get_buffer_source_box(surface, &saved_buffer->source_box); | ||
1189 | wl_list_insert(view->saved_buffers.prev, &saved_buffer->link); | ||
1190 | } | 1177 | } |
1178 | |||
1179 | wlr_scene_buffer_set_dest_size(sbuf, | ||
1180 | buffer->dst_width, buffer->dst_height); | ||
1181 | wlr_scene_buffer_set_opaque_region(sbuf, &buffer->opaque_region); | ||
1182 | wlr_scene_buffer_set_source_box(sbuf, &buffer->src_box); | ||
1183 | wlr_scene_node_set_position(&sbuf->node, sx, sy); | ||
1184 | wlr_scene_buffer_set_transform(sbuf, buffer->transform); | ||
1185 | wlr_scene_buffer_set_buffer(sbuf, buffer->buffer); | ||
1191 | } | 1186 | } |
1192 | 1187 | ||
1193 | void view_save_buffer(struct sway_view *view) { | 1188 | void view_save_buffer(struct sway_view *view) { |
1194 | if (!sway_assert(wl_list_empty(&view->saved_buffers), "Didn't expect saved buffer")) { | 1189 | if (!sway_assert(!view->saved_surface_tree, "Didn't expect saved buffer")) { |
1195 | view_remove_saved_buffer(view); | 1190 | view_remove_saved_buffer(view); |
1196 | } | 1191 | } |
1197 | view_for_each_surface(view, view_save_buffer_iterator, view); | 1192 | |
1193 | view->saved_surface_tree = wlr_scene_tree_create(view->scene_tree); | ||
1194 | if (!view->saved_surface_tree) { | ||
1195 | sway_log(SWAY_ERROR, "Could not allocate a scene tree node when saving a surface"); | ||
1196 | return; | ||
1197 | } | ||
1198 | |||
1199 | // Enable and disable the saved surface tree like so to atomitaclly update | ||
1200 | // the tree. This will prevent over damaging or other weirdness. | ||
1201 | wlr_scene_node_set_enabled(&view->saved_surface_tree->node, false); | ||
1202 | |||
1203 | wlr_scene_node_for_each_buffer(&view->content_tree->node, | ||
1204 | view_save_buffer_iterator, view->saved_surface_tree); | ||
1205 | |||
1206 | wlr_scene_node_set_enabled(&view->content_tree->node, false); | ||
1207 | wlr_scene_node_set_enabled(&view->saved_surface_tree->node, true); | ||
1198 | } | 1208 | } |
1199 | 1209 | ||
1200 | bool view_is_transient_for(struct sway_view *child, | 1210 | bool view_is_transient_for(struct sway_view *child, |
@@ -1202,3 +1212,19 @@ bool view_is_transient_for(struct sway_view *child, | |||
1202 | return child->impl->is_transient_for && | 1212 | return child->impl->is_transient_for && |
1203 | child->impl->is_transient_for(child, ancestor); | 1213 | child->impl->is_transient_for(child, ancestor); |
1204 | } | 1214 | } |
1215 | |||
1216 | static void send_frame_done_iterator(struct wlr_scene_buffer *scene_buffer, | ||
1217 | int x, int y, void *data) { | ||
1218 | struct timespec *when = data; | ||
1219 | wl_signal_emit_mutable(&scene_buffer->events.frame_done, when); | ||
1220 | } | ||
1221 | |||
1222 | void view_send_frame_done(struct sway_view *view) { | ||
1223 | struct timespec when; | ||
1224 | clock_gettime(CLOCK_MONOTONIC, &when); | ||
1225 | |||
1226 | struct wlr_scene_node *node; | ||
1227 | wl_list_for_each(node, &view->content_tree->children, link) { | ||
1228 | wlr_scene_node_for_each_buffer(node, send_frame_done_iterator, &when); | ||
1229 | } | ||
1230 | } | ||