diff options
-rw-r--r-- | include/sway/tree/view.h | 13 | ||||
-rw-r--r-- | sway/desktop/output.c | 2 | ||||
-rw-r--r-- | sway/desktop/render.c | 61 | ||||
-rw-r--r-- | sway/desktop/transaction.c | 23 | ||||
-rw-r--r-- | sway/tree/view.c | 39 |
5 files changed, 85 insertions, 53 deletions
diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index ab2dc8e4..53c5d34e 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h | |||
@@ -55,6 +55,13 @@ struct sway_view_impl { | |||
55 | void (*destroy)(struct sway_view *view); | 55 | void (*destroy)(struct sway_view *view); |
56 | }; | 56 | }; |
57 | 57 | ||
58 | struct sway_saved_buffer { | ||
59 | struct wlr_client_buffer *buffer; | ||
60 | int x, y; | ||
61 | int width, height; | ||
62 | struct wl_list link; // sway_view::saved_buffers | ||
63 | }; | ||
64 | |||
58 | struct sway_view { | 65 | struct sway_view { |
59 | enum sway_view_type type; | 66 | enum sway_view_type type; |
60 | const struct sway_view_impl *impl; | 67 | const struct sway_view_impl *impl; |
@@ -65,9 +72,6 @@ struct sway_view { | |||
65 | 72 | ||
66 | pid_t pid; | 73 | pid_t pid; |
67 | 74 | ||
68 | double saved_x, saved_y; | ||
69 | int saved_width, saved_height; | ||
70 | |||
71 | // The size the view would want to be if it weren't tiled. | 75 | // The size the view would want to be if it weren't tiled. |
72 | // Used when changing a view from tiled to floating. | 76 | // Used when changing a view from tiled to floating. |
73 | int natural_width, natural_height; | 77 | int natural_width, natural_height; |
@@ -80,8 +84,7 @@ struct sway_view { | |||
80 | bool allow_request_urgent; | 84 | bool allow_request_urgent; |
81 | struct wl_event_source *urgent_timer; | 85 | struct wl_event_source *urgent_timer; |
82 | 86 | ||
83 | struct wlr_client_buffer *saved_buffer; | 87 | struct wl_list saved_buffers; // sway_saved_buffer::link |
84 | int saved_buffer_width, saved_buffer_height; | ||
85 | 88 | ||
86 | // The geometry for whatever the client is committing, regardless of | 89 | // The geometry for whatever the client is committing, regardless of |
87 | // transaction state. Updated on every commit. | 90 | // transaction state. Updated on every commit. |
diff --git a/sway/desktop/output.c b/sway/desktop/output.c index a86622e1..18250ae6 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c | |||
@@ -511,7 +511,7 @@ static bool scan_out_fullscreen_view(struct sway_output *output, | |||
511 | return false; | 511 | return false; |
512 | } | 512 | } |
513 | 513 | ||
514 | if (view->saved_buffer) { | 514 | if (!wl_list_empty(&view->saved_buffers)) { |
515 | return false; | 515 | return false; |
516 | } | 516 | } |
517 | 517 | ||
diff --git a/sway/desktop/render.c b/sway/desktop/render.c index 14753df2..491a9bc0 100644 --- a/sway/desktop/render.c +++ b/sway/desktop/render.c | |||
@@ -280,37 +280,44 @@ static void render_saved_view(struct sway_view *view, | |||
280 | struct sway_output *output, pixman_region32_t *damage, float alpha) { | 280 | struct sway_output *output, pixman_region32_t *damage, float alpha) { |
281 | struct wlr_output *wlr_output = output->wlr_output; | 281 | struct wlr_output *wlr_output = output->wlr_output; |
282 | 282 | ||
283 | if (!view->saved_buffer || !view->saved_buffer->texture) { | 283 | if (wl_list_empty(&view->saved_buffers)) { |
284 | return; | 284 | return; |
285 | } | 285 | } |
286 | struct wlr_box box = { | 286 | struct sway_saved_buffer *saved_buf; |
287 | .x = view->container->surface_x - output->lx - | 287 | wl_list_for_each(saved_buf, &view->saved_buffers, link) { |
288 | view->saved_geometry.x, | 288 | if (!saved_buf->buffer->texture) { |
289 | .y = view->container->surface_y - output->ly - | 289 | continue; |
290 | view->saved_geometry.y, | 290 | } |
291 | .width = view->saved_buffer_width, | ||
292 | .height = view->saved_buffer_height, | ||
293 | }; | ||
294 | |||
295 | struct wlr_box output_box = { | ||
296 | .width = output->width, | ||
297 | .height = output->height, | ||
298 | }; | ||
299 | 291 | ||
300 | struct wlr_box intersection; | 292 | struct wlr_box box = { |
301 | bool intersects = wlr_box_intersection(&intersection, &output_box, &box); | 293 | .x = view->container->surface_x - output->lx - |
302 | if (!intersects) { | 294 | view->saved_geometry.x + saved_buf->x, |
303 | return; | 295 | .y = view->container->surface_y - output->ly - |
304 | } | 296 | view->saved_geometry.y + saved_buf->y, |
297 | .width = saved_buf->width, | ||
298 | .height = saved_buf->height, | ||
299 | }; | ||
300 | |||
301 | struct wlr_box output_box = { | ||
302 | .width = output->width, | ||
303 | .height = output->height, | ||
304 | }; | ||
305 | |||
306 | struct wlr_box intersection; | ||
307 | bool intersects = wlr_box_intersection(&intersection, &output_box, &box); | ||
308 | if (!intersects) { | ||
309 | continue; | ||
310 | } | ||
305 | 311 | ||
306 | scale_box(&box, wlr_output->scale); | 312 | scale_box(&box, wlr_output->scale); |
307 | 313 | ||
308 | float matrix[9]; | 314 | float matrix[9]; |
309 | wlr_matrix_project_box(matrix, &box, WL_OUTPUT_TRANSFORM_NORMAL, 0, | 315 | wlr_matrix_project_box(matrix, &box, WL_OUTPUT_TRANSFORM_NORMAL, 0, |
310 | wlr_output->transform_matrix); | 316 | wlr_output->transform_matrix); |
311 | 317 | ||
312 | render_texture(wlr_output, damage, view->saved_buffer->texture, | 318 | render_texture(wlr_output, damage, saved_buf->buffer->texture, |
313 | &box, matrix, alpha); | 319 | &box, matrix, alpha); |
320 | } | ||
314 | 321 | ||
315 | // FIXME: we should set the surface that this saved buffer originates from | 322 | // FIXME: we should set the surface that this saved buffer originates from |
316 | // as sampled here. | 323 | // as sampled here. |
@@ -323,7 +330,7 @@ static void render_saved_view(struct sway_view *view, | |||
323 | static void render_view(struct sway_output *output, pixman_region32_t *damage, | 330 | static void render_view(struct sway_output *output, pixman_region32_t *damage, |
324 | struct sway_container *con, struct border_colors *colors) { | 331 | struct sway_container *con, struct border_colors *colors) { |
325 | struct sway_view *view = con->view; | 332 | struct sway_view *view = con->view; |
326 | if (view->saved_buffer) { | 333 | if (!wl_list_empty(&view->saved_buffers)) { |
327 | render_saved_view(view, output, damage, view->container->alpha); | 334 | render_saved_view(view, output, damage, view->container->alpha); |
328 | } else if (view->surface) { | 335 | } else if (view->surface) { |
329 | render_view_toplevels(view, output, damage, view->container->alpha); | 336 | render_view_toplevels(view, output, damage, view->container->alpha); |
@@ -1020,7 +1027,7 @@ void output_render(struct sway_output *output, struct timespec *when, | |||
1020 | } | 1027 | } |
1021 | 1028 | ||
1022 | if (fullscreen_con->view) { | 1029 | if (fullscreen_con->view) { |
1023 | if (fullscreen_con->view->saved_buffer) { | 1030 | if (!wl_list_empty(&fullscreen_con->view->saved_buffers)) { |
1024 | render_saved_view(fullscreen_con->view, output, damage, 1.0f); | 1031 | render_saved_view(fullscreen_con->view, output, damage, 1.0f); |
1025 | } else if (fullscreen_con->view->surface) { | 1032 | } else if (fullscreen_con->view->surface) { |
1026 | render_view_toplevels(fullscreen_con->view, | 1033 | render_view_toplevels(fullscreen_con->view, |
diff --git a/sway/desktop/transaction.c b/sway/desktop/transaction.c index ccf60514..ef656102 100644 --- a/sway/desktop/transaction.c +++ b/sway/desktop/transaction.c | |||
@@ -210,14 +210,17 @@ static void apply_container_state(struct sway_container *container, | |||
210 | struct sway_view *view = container->view; | 210 | struct sway_view *view = container->view; |
211 | // Damage the old location | 211 | // Damage the old location |
212 | desktop_damage_whole_container(container); | 212 | desktop_damage_whole_container(container); |
213 | if (view && view->saved_buffer) { | 213 | if (view && !wl_list_empty(&view->saved_buffers)) { |
214 | struct wlr_box box = { | 214 | struct sway_saved_buffer *saved_buf; |
215 | .x = container->current.content_x - view->saved_geometry.x, | 215 | wl_list_for_each(saved_buf, &view->saved_buffers, link) { |
216 | .y = container->current.content_y - view->saved_geometry.y, | 216 | struct wlr_box box = { |
217 | .width = view->saved_buffer_width, | 217 | .x = container->current.content_x - view->saved_geometry.x + saved_buf->x, |
218 | .height = view->saved_buffer_height, | 218 | .y = container->current.content_y - view->saved_geometry.y + saved_buf->y, |
219 | }; | 219 | .width = saved_buf->width, |
220 | desktop_damage_box(&box); | 220 | .height = saved_buf->height, |
221 | }; | ||
222 | desktop_damage_box(&box); | ||
223 | } | ||
221 | } | 224 | } |
222 | 225 | ||
223 | // There are separate children lists for each instruction state, the | 226 | // There are separate children lists for each instruction state, the |
@@ -229,7 +232,7 @@ static void apply_container_state(struct sway_container *container, | |||
229 | 232 | ||
230 | memcpy(&container->current, state, sizeof(struct sway_container_state)); | 233 | memcpy(&container->current, state, sizeof(struct sway_container_state)); |
231 | 234 | ||
232 | if (view && view->saved_buffer) { | 235 | if (view && !wl_list_empty(&view->saved_buffers)) { |
233 | if (!container->node.destroying || container->node.ntxnrefs == 1) { | 236 | if (!container->node.destroying || container->node.ntxnrefs == 1) { |
234 | view_remove_saved_buffer(view); | 237 | view_remove_saved_buffer(view); |
235 | } | 238 | } |
@@ -432,7 +435,7 @@ static void transaction_commit(struct sway_transaction *transaction) { | |||
432 | wlr_surface_send_frame_done( | 435 | wlr_surface_send_frame_done( |
433 | node->sway_container->view->surface, &now); | 436 | node->sway_container->view->surface, &now); |
434 | } | 437 | } |
435 | if (node_is_view(node) && !node->sway_container->view->saved_buffer) { | 438 | if (node_is_view(node) && wl_list_empty(&node->sway_container->view->saved_buffers)) { |
436 | view_save_buffer(node->sway_container->view); | 439 | view_save_buffer(node->sway_container->view); |
437 | memcpy(&node->sway_container->view->saved_geometry, | 440 | memcpy(&node->sway_container->view->saved_geometry, |
438 | &node->sway_container->view->geometry, | 441 | &node->sway_container->view->geometry, |
diff --git a/sway/tree/view.c b/sway/tree/view.c index 8e12a229..25951deb 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c | |||
@@ -36,6 +36,7 @@ void view_init(struct sway_view *view, enum sway_view_type type, | |||
36 | view->type = type; | 36 | view->type = type; |
37 | view->impl = impl; | 37 | view->impl = impl; |
38 | view->executed_criteria = create_list(); | 38 | view->executed_criteria = create_list(); |
39 | wl_list_init(&view->saved_buffers); | ||
39 | view->allow_request_urgent = true; | 40 | view->allow_request_urgent = true; |
40 | view->shortcuts_inhibit = SHORTCUTS_INHIBIT_DEFAULT; | 41 | view->shortcuts_inhibit = SHORTCUTS_INHIBIT_DEFAULT; |
41 | wl_signal_init(&view->events.unmap); | 42 | wl_signal_init(&view->events.unmap); |
@@ -54,6 +55,9 @@ void view_destroy(struct sway_view *view) { | |||
54 | "(might have a pending transaction?)")) { | 55 | "(might have a pending transaction?)")) { |
55 | return; | 56 | return; |
56 | } | 57 | } |
58 | if (!wl_list_empty(&view->saved_buffers)) { | ||
59 | view_remove_saved_buffer(view); | ||
60 | } | ||
57 | list_free(view->executed_criteria); | 61 | list_free(view->executed_criteria); |
58 | 62 | ||
59 | free(view->title_format); | 63 | free(view->title_format); |
@@ -1176,23 +1180,38 @@ bool view_is_urgent(struct sway_view *view) { | |||
1176 | } | 1180 | } |
1177 | 1181 | ||
1178 | void view_remove_saved_buffer(struct sway_view *view) { | 1182 | void view_remove_saved_buffer(struct sway_view *view) { |
1179 | if (!sway_assert(view->saved_buffer, "Expected a saved buffer")) { | 1183 | if (!sway_assert(!wl_list_empty(&view->saved_buffers), "Expected a saved buffer")) { |
1180 | return; | 1184 | return; |
1181 | } | 1185 | } |
1182 | wlr_buffer_unlock(&view->saved_buffer->base); | 1186 | struct sway_saved_buffer *saved_buf, *tmp; |
1183 | view->saved_buffer = NULL; | 1187 | wl_list_for_each_safe(saved_buf, tmp, &view->saved_buffers, link) { |
1188 | wlr_buffer_unlock(&saved_buf->buffer->base); | ||
1189 | wl_list_remove(&saved_buf->link); | ||
1190 | free(saved_buf); | ||
1191 | } | ||
1192 | } | ||
1193 | |||
1194 | static void view_save_buffer_iterator(struct wlr_surface *surface, | ||
1195 | int sx, int sy, void *data) { | ||
1196 | struct sway_view *view = data; | ||
1197 | |||
1198 | if (surface && wlr_surface_has_buffer(surface)) { | ||
1199 | wlr_buffer_lock(&surface->buffer->base); | ||
1200 | struct sway_saved_buffer *saved_buffer = calloc(1, sizeof(struct sway_saved_buffer)); | ||
1201 | saved_buffer->buffer = surface->buffer; | ||
1202 | saved_buffer->width = surface->current.width; | ||
1203 | saved_buffer->height = surface->current.height; | ||
1204 | saved_buffer->x = sx; | ||
1205 | saved_buffer->y = sy; | ||
1206 | wl_list_insert(&view->saved_buffers, &saved_buffer->link); | ||
1207 | } | ||
1184 | } | 1208 | } |
1185 | 1209 | ||
1186 | void view_save_buffer(struct sway_view *view) { | 1210 | void view_save_buffer(struct sway_view *view) { |
1187 | if (!sway_assert(!view->saved_buffer, "Didn't expect saved buffer")) { | 1211 | if (!sway_assert(wl_list_empty(&view->saved_buffers), "Didn't expect saved buffer")) { |
1188 | view_remove_saved_buffer(view); | 1212 | view_remove_saved_buffer(view); |
1189 | } | 1213 | } |
1190 | if (view->surface && wlr_surface_has_buffer(view->surface)) { | 1214 | view_for_each_surface(view, view_save_buffer_iterator, view); |
1191 | wlr_buffer_lock(&view->surface->buffer->base); | ||
1192 | view->saved_buffer = view->surface->buffer; | ||
1193 | view->saved_buffer_width = view->surface->current.width; | ||
1194 | view->saved_buffer_height = view->surface->current.height; | ||
1195 | } | ||
1196 | } | 1215 | } |
1197 | 1216 | ||
1198 | bool view_is_transient_for(struct sway_view *child, | 1217 | bool view_is_transient_for(struct sway_view *child, |