aboutsummaryrefslogtreecommitdiff
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 {
void (*destroy)(struct sway_view *view);
};
+struct sway_saved_buffer {
+ struct wlr_client_buffer *buffer;
+ int x, y;
+ int width, height;
+ struct wl_list link; // sway_view::saved_buffers
+};
+
struct sway_view {
enum sway_view_type type;
const struct sway_view_impl *impl;
@@ -65,9 +72,6 @@ struct sway_view {
pid_t pid;
- double saved_x, saved_y;
- int saved_width, saved_height;
-
// The size the view would want to be if it weren't tiled.
// Used when changing a view from tiled to floating.
int natural_width, natural_height;
@@ -80,8 +84,7 @@ struct sway_view {
bool allow_request_urgent;
struct wl_event_source *urgent_timer;
- struct wlr_client_buffer *saved_buffer;
- int saved_buffer_width, saved_buffer_height;
+ struct wl_list saved_buffers; // sway_saved_buffer::link
// The geometry for whatever the client is committing, regardless of
// 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,
return false;
}
- if (view->saved_buffer) {
+ if (!wl_list_empty(&view->saved_buffers)) {
return false;
}
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,
struct sway_output *output, pixman_region32_t *damage, float alpha) {
struct wlr_output *wlr_output = output->wlr_output;
- if (!view->saved_buffer || !view->saved_buffer->texture) {
+ if (wl_list_empty(&view->saved_buffers)) {
return;
}
- struct wlr_box box = {
- .x = view->container->surface_x - output->lx -
- view->saved_geometry.x,
- .y = view->container->surface_y - output->ly -
- view->saved_geometry.y,
- .width = view->saved_buffer_width,
- .height = view->saved_buffer_height,
- };
-
- struct wlr_box output_box = {
- .width = output->width,
- .height = output->height,
- };
+ struct sway_saved_buffer *saved_buf;
+ wl_list_for_each(saved_buf, &view->saved_buffers, link) {
+ if (!saved_buf->buffer->texture) {
+ continue;
+ }
- struct wlr_box intersection;
- bool intersects = wlr_box_intersection(&intersection, &output_box, &box);
- if (!intersects) {
- return;
- }
+ struct wlr_box box = {
+ .x = view->container->surface_x - output->lx -
+ view->saved_geometry.x + saved_buf->x,
+ .y = view->container->surface_y - output->ly -
+ view->saved_geometry.y + saved_buf->y,
+ .width = saved_buf->width,
+ .height = saved_buf->height,
+ };
+
+ struct wlr_box output_box = {
+ .width = output->width,
+ .height = output->height,
+ };
+
+ struct wlr_box intersection;
+ bool intersects = wlr_box_intersection(&intersection, &output_box, &box);
+ if (!intersects) {
+ continue;
+ }
- scale_box(&box, wlr_output->scale);
+ scale_box(&box, wlr_output->scale);
- float matrix[9];
- wlr_matrix_project_box(matrix, &box, WL_OUTPUT_TRANSFORM_NORMAL, 0,
- wlr_output->transform_matrix);
+ float matrix[9];
+ wlr_matrix_project_box(matrix, &box, WL_OUTPUT_TRANSFORM_NORMAL, 0,
+ wlr_output->transform_matrix);
- render_texture(wlr_output, damage, view->saved_buffer->texture,
- &box, matrix, alpha);
+ render_texture(wlr_output, damage, saved_buf->buffer->texture,
+ &box, matrix, alpha);
+ }
// FIXME: we should set the surface that this saved buffer originates from
// as sampled here.
@@ -323,7 +330,7 @@ static void render_saved_view(struct sway_view *view,
static void render_view(struct sway_output *output, pixman_region32_t *damage,
struct sway_container *con, struct border_colors *colors) {
struct sway_view *view = con->view;
- if (view->saved_buffer) {
+ if (!wl_list_empty(&view->saved_buffers)) {
render_saved_view(view, output, damage, view->container->alpha);
} else if (view->surface) {
render_view_toplevels(view, output, damage, view->container->alpha);
@@ -1020,7 +1027,7 @@ void output_render(struct sway_output *output, struct timespec *when,
}
if (fullscreen_con->view) {
- if (fullscreen_con->view->saved_buffer) {
+ if (!wl_list_empty(&fullscreen_con->view->saved_buffers)) {
render_saved_view(fullscreen_con->view, output, damage, 1.0f);
} else if (fullscreen_con->view->surface) {
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,
struct sway_view *view = container->view;
// Damage the old location
desktop_damage_whole_container(container);
- if (view && view->saved_buffer) {
- struct wlr_box box = {
- .x = container->current.content_x - view->saved_geometry.x,
- .y = container->current.content_y - view->saved_geometry.y,
- .width = view->saved_buffer_width,
- .height = view->saved_buffer_height,
- };
- desktop_damage_box(&box);
+ if (view && !wl_list_empty(&view->saved_buffers)) {
+ struct sway_saved_buffer *saved_buf;
+ wl_list_for_each(saved_buf, &view->saved_buffers, link) {
+ struct wlr_box box = {
+ .x = container->current.content_x - view->saved_geometry.x + saved_buf->x,
+ .y = container->current.content_y - view->saved_geometry.y + saved_buf->y,
+ .width = saved_buf->width,
+ .height = saved_buf->height,
+ };
+ desktop_damage_box(&box);
+ }
}
// There are separate children lists for each instruction state, the
@@ -229,7 +232,7 @@ static void apply_container_state(struct sway_container *container,
memcpy(&container->current, state, sizeof(struct sway_container_state));
- if (view && view->saved_buffer) {
+ if (view && !wl_list_empty(&view->saved_buffers)) {
if (!container->node.destroying || container->node.ntxnrefs == 1) {
view_remove_saved_buffer(view);
}
@@ -432,7 +435,7 @@ static void transaction_commit(struct sway_transaction *transaction) {
wlr_surface_send_frame_done(
node->sway_container->view->surface, &now);
}
- if (node_is_view(node) && !node->sway_container->view->saved_buffer) {
+ if (node_is_view(node) && wl_list_empty(&node->sway_container->view->saved_buffers)) {
view_save_buffer(node->sway_container->view);
memcpy(&node->sway_container->view->saved_geometry,
&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,
view->type = type;
view->impl = impl;
view->executed_criteria = create_list();
+ wl_list_init(&view->saved_buffers);
view->allow_request_urgent = true;
view->shortcuts_inhibit = SHORTCUTS_INHIBIT_DEFAULT;
wl_signal_init(&view->events.unmap);
@@ -54,6 +55,9 @@ void view_destroy(struct sway_view *view) {
"(might have a pending transaction?)")) {
return;
}
+ if (!wl_list_empty(&view->saved_buffers)) {
+ view_remove_saved_buffer(view);
+ }
list_free(view->executed_criteria);
free(view->title_format);
@@ -1176,23 +1180,38 @@ bool view_is_urgent(struct sway_view *view) {
}
void view_remove_saved_buffer(struct sway_view *view) {
- if (!sway_assert(view->saved_buffer, "Expected a saved buffer")) {
+ if (!sway_assert(!wl_list_empty(&view->saved_buffers), "Expected a saved buffer")) {
return;
}
- wlr_buffer_unlock(&view->saved_buffer->base);
- view->saved_buffer = NULL;
+ struct sway_saved_buffer *saved_buf, *tmp;
+ wl_list_for_each_safe(saved_buf, tmp, &view->saved_buffers, link) {
+ wlr_buffer_unlock(&saved_buf->buffer->base);
+ wl_list_remove(&saved_buf->link);
+ free(saved_buf);
+ }
+}
+
+static void view_save_buffer_iterator(struct wlr_surface *surface,
+ int sx, int sy, void *data) {
+ struct sway_view *view = data;
+
+ if (surface && wlr_surface_has_buffer(surface)) {
+ wlr_buffer_lock(&surface->buffer->base);
+ struct sway_saved_buffer *saved_buffer = calloc(1, sizeof(struct sway_saved_buffer));
+ saved_buffer->buffer = surface->buffer;
+ saved_buffer->width = surface->current.width;
+ saved_buffer->height = surface->current.height;
+ saved_buffer->x = sx;
+ saved_buffer->y = sy;
+ wl_list_insert(&view->saved_buffers, &saved_buffer->link);
+ }
}
void view_save_buffer(struct sway_view *view) {
- if (!sway_assert(!view->saved_buffer, "Didn't expect saved buffer")) {
+ if (!sway_assert(wl_list_empty(&view->saved_buffers), "Didn't expect saved buffer")) {
view_remove_saved_buffer(view);
}
- if (view->surface && wlr_surface_has_buffer(view->surface)) {
- wlr_buffer_lock(&view->surface->buffer->base);
- view->saved_buffer = view->surface->buffer;
- view->saved_buffer_width = view->surface->current.width;
- view->saved_buffer_height = view->surface->current.height;
- }
+ view_for_each_surface(view, view_save_buffer_iterator, view);
}
bool view_is_transient_for(struct sway_view *child,