aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/sway/tree/view.h13
-rw-r--r--sway/desktop/output.c2
-rw-r--r--sway/desktop/render.c61
-rw-r--r--sway/desktop/transaction.c23
-rw-r--r--sway/tree/view.c39
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
58struct 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
58struct sway_view { 65struct 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,
323static void render_view(struct sway_output *output, pixman_region32_t *damage, 330static 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
1178void view_remove_saved_buffer(struct sway_view *view) { 1182void 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
1194static 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
1186void view_save_buffer(struct sway_view *view) { 1210void 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
1198bool view_is_transient_for(struct sway_view *child, 1217bool view_is_transient_for(struct sway_view *child,