aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/sway/desktop.h7
-rw-r--r--include/sway/output.h8
-rw-r--r--include/sway/tree/view.h4
-rw-r--r--sway/commands/opacity.c5
-rw-r--r--sway/desktop/desktop.c14
-rw-r--r--sway/desktop/layer_shell.c44
-rw-r--r--sway/desktop/output.c439
-rw-r--r--sway/desktop/wl_shell.c2
-rw-r--r--sway/desktop/xdg_shell_v6.c26
-rw-r--r--sway/desktop/xwayland.c18
-rw-r--r--sway/tree/view.c27
11 files changed, 332 insertions, 262 deletions
diff --git a/include/sway/desktop.h b/include/sway/desktop.h
index 96bdc94c..f1ad759a 100644
--- a/include/sway/desktop.h
+++ b/include/sway/desktop.h
@@ -1,7 +1,4 @@
#include <wlr/types/wlr_surface.h>
-void desktop_damage_whole_surface(struct wlr_surface *surface, double lx,
- double ly);
-
-void desktop_damage_from_surface(struct wlr_surface *surface, double lx,
- double ly);
+void desktop_damage_surface(struct wlr_surface *surface, double lx, double ly,
+ bool whole);
diff --git a/include/sway/output.h b/include/sway/output.h
index 4bffa2b7..56571548 100644
--- a/include/sway/output.h
+++ b/include/sway/output.h
@@ -34,11 +34,11 @@ struct sway_output {
void output_damage_whole(struct sway_output *output);
-void output_damage_whole_surface(struct sway_output *output,
- double ox, double oy, struct wlr_surface *surface);
+void output_damage_surface(struct sway_output *output, double ox, double oy,
+ struct wlr_surface *surface, bool whole);
-void output_damage_whole_view(struct sway_output *output,
- struct sway_view *view);
+void output_damage_view(struct sway_output *output, struct sway_view *view,
+ bool whole);
void output_damage_whole_container(struct sway_output *output,
struct sway_container *con);
diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h
index 611c4f0b..b51c54b5 100644
--- a/include/sway/tree/view.h
+++ b/include/sway/tree/view.h
@@ -157,9 +157,7 @@ void view_set_activated(struct sway_view *view, bool activated);
void view_close(struct sway_view *view);
-void view_damage_whole(struct sway_view *view);
-
-void view_damage_from(struct sway_view *view);
+void view_damage(struct sway_view *view, bool whole);
void view_for_each_surface(struct sway_view *view,
wlr_surface_iterator_func_t iterator, void *user_data);
diff --git a/sway/commands/opacity.c b/sway/commands/opacity.c
index b8cd1f09..68fd9f42 100644
--- a/sway/commands/opacity.c
+++ b/sway/commands/opacity.c
@@ -30,10 +30,7 @@ struct cmd_results *cmd_opacity(int argc, char **argv) {
}
con->alpha = opacity;
-
- if (con->type == C_VIEW) {
- view_damage_whole(con->sway_view);
- }
+ container_damage_whole(con);
return cmd_results_new(CMD_SUCCESS, NULL, NULL);
}
diff --git a/sway/desktop/desktop.c b/sway/desktop/desktop.c
index 3a13191f..66f33151 100644
--- a/sway/desktop/desktop.c
+++ b/sway/desktop/desktop.c
@@ -2,19 +2,13 @@
#include "sway/desktop.h"
#include "sway/output.h"
-void desktop_damage_whole_surface(struct wlr_surface *surface, double lx,
- double ly) {
+void desktop_damage_surface(struct wlr_surface *surface, double lx, double ly,
+ bool whole) {
for (int i = 0; i < root_container.children->length; ++i) {
struct sway_container *cont = root_container.children->items[i];
if (cont->type == C_OUTPUT) {
- output_damage_whole_surface(cont->sway_output,
- lx - cont->x, ly - cont->y, surface);
+ output_damage_surface(cont->sway_output, lx - cont->x, ly - cont->y,
+ surface, whole);
}
}
}
-
-void desktop_damage_from_surface(struct wlr_surface *surface, double lx,
- double ly) {
- // TODO
- desktop_damage_whole_surface(surface, lx, ly);
-}
diff --git a/sway/desktop/layer_shell.c b/sway/desktop/layer_shell.c
index 663ec7ba..f841e5f1 100644
--- a/sway/desktop/layer_shell.c
+++ b/sway/desktop/layer_shell.c
@@ -229,33 +229,39 @@ static void handle_surface_commit(struct wl_listener *listener, void *data) {
wl_container_of(listener, layer, surface_commit);
struct wlr_layer_surface *layer_surface = layer->layer_surface;
struct wlr_output *wlr_output = layer_surface->output;
- if (wlr_output != NULL) {
- struct sway_output *output = wlr_output->data;
- struct wlr_box old_geo = layer->geo;
- arrange_layers(output);
- if (memcmp(&old_geo, &layer->geo, sizeof(struct wlr_box)) != 0) {
- // TODO DAMAGE apply whole surface from previous and new geos
- } else {
- // TODO DAMAGE from surface damage
- }
- wlr_output_damage_add_box(output->damage, &old_geo);
- wlr_output_damage_add_box(output->damage, &layer->geo);
+ if (wlr_output == NULL) {
+ return;
+ }
+
+ struct sway_output *output = wlr_output->data;
+ struct wlr_box old_geo = layer->geo;
+ arrange_layers(output);
+ if (memcmp(&old_geo, &layer->geo, sizeof(struct wlr_box)) != 0) {
+ output_damage_surface(output, old_geo.x, old_geo.y,
+ layer_surface->surface, true);
+ output_damage_surface(output, layer->geo.x, layer->geo.y,
+ layer_surface->surface, true);
+ } else {
+ output_damage_surface(output, layer->geo.x, layer->geo.y,
+ layer_surface->surface, false);
}
}
static void unmap(struct sway_layer_surface *sway_layer) {
struct wlr_output *wlr_output = sway_layer->layer_surface->output;
- if (wlr_output != NULL) {
- struct sway_output *output = wlr_output->data;
- wlr_output_damage_add_box(output->damage, &sway_layer->geo);
+ if (wlr_output == NULL) {
+ return;
}
+ struct sway_output *output = wlr_output->data;
+ output_damage_surface(output, sway_layer->geo.x, sway_layer->geo.y,
+ sway_layer->layer_surface->surface, true);
}
static void handle_destroy(struct wl_listener *listener, void *data) {
- struct sway_layer_surface *sway_layer = wl_container_of(listener,
- sway_layer, destroy);
+ struct sway_layer_surface *sway_layer =
+ wl_container_of(listener, sway_layer, destroy);
wlr_log(L_DEBUG, "Layer surface destroyed (%s)",
- sway_layer->layer_surface->namespace);
+ sway_layer->layer_surface->namespace);
if (sway_layer->layer_surface->mapped) {
unmap(sway_layer);
}
@@ -277,7 +283,9 @@ static void handle_map(struct wl_listener *listener, void *data) {
struct sway_layer_surface *sway_layer = wl_container_of(listener,
sway_layer, map);
struct sway_output *output = sway_layer->layer_surface->output->data;
- wlr_output_damage_add_box(output->damage, &sway_layer->geo);
+ output_damage_surface(output, sway_layer->geo.x, sway_layer->geo.y,
+ sway_layer->layer_surface->surface, true);
+ // TODO: send enter to subsurfaces and popups
wlr_surface_send_enter(sway_layer->layer_surface->surface,
sway_layer->layer_surface->output);
}
diff --git a/sway/desktop/output.c b/sway/desktop/output.c
index ad777796..23d20b79 100644
--- a/sway/desktop/output.c
+++ b/sway/desktop/output.c
@@ -1,8 +1,8 @@
#define _POSIX_C_SOURCE 200809L
#include <assert.h>
#include <stdlib.h>
-#include <time.h>
#include <strings.h>
+#include <time.h>
#include <wayland-server.h>
#include <wlr/render/wlr_renderer.h>
#include <wlr/types/wlr_box.h>
@@ -12,6 +12,7 @@
#include <wlr/types/wlr_output.h>
#include <wlr/types/wlr_surface.h>
#include <wlr/types/wlr_wl_shell.h>
+#include <wlr/util/region.h>
#include "log.h"
#include "sway/input/input-manager.h"
#include "sway/input/seat.h"
@@ -38,191 +39,201 @@ struct sway_container *output_by_name(const char *name) {
*/
static void rotate_child_position(double *sx, double *sy, double sw, double sh,
double pw, double ph, float rotation) {
- if (rotation != 0.0) {
- // Coordinates relative to the center of the subsurface
- double ox = *sx - pw/2 + sw/2,
- oy = *sy - ph/2 + sh/2;
- // Rotated coordinates
- double rx = cos(-rotation)*ox - sin(-rotation)*oy,
- ry = cos(-rotation)*oy + sin(-rotation)*ox;
- *sx = rx + pw/2 - sw/2;
- *sy = ry + ph/2 - sh/2;
+ if (rotation == 0.0f) {
+ return;
}
+
+ // Coordinates relative to the center of the subsurface
+ double ox = *sx - pw/2 + sw/2,
+ oy = *sy - ph/2 + sh/2;
+ // Rotated coordinates
+ double rx = cos(-rotation)*ox - sin(-rotation)*oy,
+ ry = cos(-rotation)*oy + sin(-rotation)*ox;
+ *sx = rx + pw/2 - sw/2;
+ *sy = ry + ph/2 - sh/2;
}
/**
- * Checks whether a surface at (lx, ly) intersects an output. If `box` is not
- * NULL, it populates it with the surface box in the output, in output-local
- * coordinates.
+ * Contains a surface's root geometry information. For instance, when rendering
+ * a popup, this will contain the parent view's position and size.
*/
-static bool surface_intersect_output(struct wlr_surface *surface,
- struct wlr_output_layout *output_layout, struct wlr_output *wlr_output,
- double ox, double oy, float rotation, struct wlr_box *box) {
- if (box != NULL) {
- box->x = ox * wlr_output->scale;
- box->y = oy * wlr_output->scale;
- box->width = surface->current->width * wlr_output->scale;
- box->height = surface->current->height * wlr_output->scale;
+struct root_geometry {
+ double x, y;
+ int width, height;
+ float rotation;
+};
+
+static bool get_surface_box(struct root_geometry *geo,
+ struct sway_output *output, struct wlr_surface *surface, int sx, int sy,
+ struct wlr_box *surface_box) {
+ int sw = surface->current->width;
+ int sh = surface->current->height;
+
+ double _sx = sx, _sy = sy;
+ rotate_child_position(&_sx, &_sy, sw, sh, geo->width, geo->height,
+ geo->rotation);
+
+ struct wlr_box box = {
+ .x = geo->x + _sx,
+ .y = geo->y + _sy,
+ .width = sw,
+ .height = sh,
+ };
+ if (surface_box != NULL) {
+ memcpy(surface_box, &box, sizeof(struct wlr_box));
}
- struct wlr_box layout_box = {
- .x = wlr_output->lx + ox, .y = wlr_output->ly + oy,
- .width = surface->current->width, .height = surface->current->height,
+ struct wlr_box rotated_box;
+ wlr_box_rotated_bounds(&box, geo->rotation, &rotated_box);
+
+ struct wlr_box output_box = {
+ .width = output->swayc->width,
+ .height = output->swayc->height,
};
- wlr_box_rotated_bounds(&layout_box, rotation, &layout_box);
- return wlr_output_layout_intersects(output_layout, wlr_output, &layout_box);
+
+ struct wlr_box intersection;
+ return wlr_box_intersection(&output_box, &rotated_box, &intersection);
}
-static void render_surface(struct wlr_surface *surface,
- struct wlr_output *wlr_output, struct timespec *when,
- double ox, double oy, float rotation, float alpha) {
- struct wlr_renderer *renderer =
- wlr_backend_get_renderer(wlr_output->backend);
+static void output_surface_for_each_surface(struct wlr_surface *surface,
+ double ox, double oy, struct root_geometry *geo,
+ wlr_surface_iterator_func_t iterator, void *user_data) {
+ geo->x = ox;
+ geo->y = oy;
+ geo->width = surface->current->width;
+ geo->height = surface->current->height;
+ geo->rotation = 0;
+
+ wlr_surface_for_each_surface(surface, iterator, user_data);
+}
+
+static void output_view_for_each_surface(struct sway_view *view,
+ struct root_geometry *geo, wlr_surface_iterator_func_t iterator,
+ void *user_data) {
+ geo->x = view->swayc->x;
+ geo->y = view->swayc->y;
+ geo->width = view->surface->current->width;
+ geo->height = view->surface->current->height;
+ geo->rotation = 0; // TODO
+
+ view_for_each_surface(view, iterator, user_data);
+}
+
+static void scale_box(struct wlr_box *box, float scale) {
+ box->x *= scale;
+ box->y *= scale;
+ box->width *= scale;
+ box->height *= scale;
+}
+
+struct render_data {
+ struct root_geometry root_geo;
+ struct sway_output *output;
+ struct timespec *when;
+ float alpha;
+};
+
+static void render_surface_iterator(struct wlr_surface *surface, int sx, int sy,
+ void *_data) {
+ struct render_data *data = _data;
+ struct wlr_output *wlr_output = data->output->wlr_output;
+ struct timespec *when = data->when;
+ float rotation = data->root_geo.rotation;
+ float alpha = data->alpha;
if (!wlr_surface_has_buffer(surface)) {
return;
}
- struct wlr_output_layout *layout = root_container.sway_root->output_layout;
-
struct wlr_box box;
- bool intersects = surface_intersect_output(surface, layout, wlr_output,
- ox, oy, rotation, &box);
- if (intersects) {
- float matrix[9];
- enum wl_output_transform transform =
- wlr_output_transform_invert(surface->current->transform);
- wlr_matrix_project_box(matrix, &box, transform, rotation,
- wlr_output->transform_matrix);
-
- wlr_render_texture_with_matrix(renderer, surface->texture,
- matrix, alpha);
-
- wlr_surface_send_frame_done(surface, when);
+ bool intersects = get_surface_box(&data->root_geo, data->output, surface,
+ sx, sy, &box);
+ if (!intersects) {
+ return;
}
- struct wlr_subsurface *subsurface;
- wl_list_for_each(subsurface, &surface->subsurface_list, parent_link) {
- struct wlr_surface_state *state = subsurface->surface->current;
- double sx = state->subsurface_position.x;
- double sy = state->subsurface_position.y;
- rotate_child_position(&sx, &sy, state->width, state->height,
- surface->current->width, surface->current->height, rotation);
-
- render_surface(subsurface->surface, wlr_output, when,
- ox + sx, oy + sy, rotation, alpha);
+ struct wlr_renderer *renderer =
+ wlr_backend_get_renderer(wlr_output->backend);
+ if (!sway_assert(renderer != NULL,
+ "expected the output backend to have a renderer")) {
+ return;
}
+
+ scale_box(&box, wlr_output->scale);
+
+ float matrix[9];
+ enum wl_output_transform transform =
+ wlr_output_transform_invert(surface->current->transform);
+ wlr_matrix_project_box(matrix, &box, transform, rotation,
+ wlr_output->transform_matrix);
+
+ wlr_render_texture_with_matrix(renderer, surface->texture,
+ matrix, alpha);
+
+ // TODO: don't send the frame done event now
+ wlr_surface_send_frame_done(surface, when);
}
-static void render_xdg_v6_popups(struct wlr_xdg_surface_v6 *surface,
- struct wlr_output *wlr_output, struct timespec *when, double base_x,
- double base_y, float rotation, float alpha) {
- double width = surface->surface->current->width;
- double height = surface->surface->current->height;
-
- struct wlr_xdg_popup_v6 *popup_state;
- wl_list_for_each(popup_state, &surface->popups, link) {
- struct wlr_xdg_surface_v6 *popup = popup_state->base;
- if (!popup->configured) {
- continue;
- }
+static void render_surface(struct sway_output *output, struct timespec *when,
+ struct wlr_surface *surface, double ox, double oy) {
+ struct render_data data = {
+ .output = output,
+ .when = when,
+ .alpha = 1.0f,
+ };
- double popup_width = popup->surface->current->width;
- double popup_height = popup->surface->current->height;
+ output_surface_for_each_surface(surface, ox, oy, &data.root_geo,
+ render_surface_iterator, &data);
+}
- double popup_sx, popup_sy;
- wlr_xdg_surface_v6_popup_get_position(popup, &popup_sx, &popup_sy);
- rotate_child_position(&popup_sx, &popup_sy, popup_width, popup_height,
- width, height, rotation);
+static void render_view(struct sway_output *output, struct timespec *when,
+ struct sway_view *view) {
+ struct render_data data = {
+ .output = output,
+ .when = when,
+ .alpha = view->swayc->alpha,
+ };
- render_surface(popup->surface, wlr_output, when,
- base_x + popup_sx, base_y + popup_sy, rotation, alpha);
- render_xdg_v6_popups(popup, wlr_output, when,
- base_x + popup_sx, base_y + popup_sy, rotation, alpha);
- }
+ output_view_for_each_surface(view, &data.root_geo,
+ render_surface_iterator, &data);
}
-static void render_wl_shell_surface(struct wlr_wl_shell_surface *surface,
- struct wlr_output *wlr_output, struct timespec *when,
- double lx, double ly, float rotation, float alpha,
- bool is_child) {
- if (is_child || surface->state != WLR_WL_SHELL_SURFACE_STATE_POPUP) {
- render_surface(surface->surface, wlr_output, when,
- lx, ly, rotation, alpha);
-
- double width = surface->surface->current->width;
- double height = surface->surface->current->height;
-
- struct wlr_wl_shell_surface *popup;
- wl_list_for_each(popup, &surface->popups, popup_link) {
- double popup_width = popup->surface->current->width;
- double popup_height = popup->surface->current->height;
-
- double popup_x = popup->transient_state->x;
- double popup_y = popup->transient_state->y;
- rotate_child_position(&popup_x, &popup_y, popup_width, popup_height,
- width, height, rotation);
-
- render_wl_shell_surface(popup, wlr_output, when,
- lx + popup_x, ly + popup_y, rotation, alpha, true);
- }
+static void render_layer(struct sway_output *output, struct timespec *when,
+ struct wl_list *layer_surfaces) {
+ struct sway_layer_surface *layer_surface;
+ wl_list_for_each(layer_surface, layer_surfaces, link) {
+ struct wlr_layer_surface *wlr_layer_surface =
+ layer_surface->layer_surface;
+ render_surface(output, when, wlr_layer_surface->surface,
+ layer_surface->geo.x, layer_surface->geo.y);
}
}
-struct render_data {
+struct render_view_data {
struct sway_output *output;
struct timespec *when;
};
-static void render_view(struct sway_container *view, void *data) {
- struct render_data *rdata = data;
- struct sway_output *output = rdata->output;
- struct timespec *when = rdata->when;
- struct wlr_output *wlr_output = output->wlr_output;
- struct sway_view *sway_view = view->sway_view;
- struct wlr_surface *surface = sway_view->surface;
- float alpha = sway_view->swayc->alpha;
+static void render_view_iterator(struct sway_container *con, void *_data) {
+ struct render_view_data *data = _data;
- if (!surface) {
+ if (!sway_assert(con->type == C_VIEW, "expected a view")) {
return;
}
- switch (sway_view->type) {
- case SWAY_VIEW_XDG_SHELL_V6: {
- int window_offset_x = view->sway_view->wlr_xdg_surface_v6->geometry.x;
- int window_offset_y = view->sway_view->wlr_xdg_surface_v6->geometry.y;
- render_surface(surface, wlr_output, when,
- view->x - window_offset_x, view->y - window_offset_y, 0, alpha);
- render_xdg_v6_popups(sway_view->wlr_xdg_surface_v6, wlr_output,
- when, view->x - window_offset_x, view->y - window_offset_y, 0, alpha);
- break;
- }
- case SWAY_VIEW_WL_SHELL:
- render_wl_shell_surface(sway_view->wlr_wl_shell_surface, wlr_output,
- when, view->x, view->y, 0, alpha, false);
- break;
- case SWAY_VIEW_XWAYLAND:
- render_surface(surface, wlr_output, when, view->x, view->y, 0, alpha);
- break;
- }
-}
-
-static void render_layer(struct sway_output *output, struct timespec *when,
- struct wl_list *layer) {
- struct sway_layer_surface *sway_layer;
- wl_list_for_each(sway_layer, layer, link) {
- struct wlr_layer_surface *layer = sway_layer->layer_surface;
- render_surface(layer->surface, output->wlr_output, when,
- sway_layer->geo.x, sway_layer->geo.y, 0, 1.0f);
- wlr_surface_send_frame_done(layer->surface, when);
- }
+ render_view(data->output, data->when, con->sway_view);
}
static void render_output(struct sway_output *output, struct timespec *when,
pixman_region32_t *damage) {
struct wlr_output *wlr_output = output->wlr_output;
+
struct wlr_renderer *renderer =
- wlr_backend_get_renderer(wlr_output->backend);
+ wlr_backend_get_renderer(wlr_output->backend);
+ if (!sway_assert(renderer != NULL,
+ "expected the output backend to have a renderer")) {
+ return;
+ }
wlr_renderer_begin(renderer, wlr_output->width, wlr_output->height);
@@ -231,7 +242,7 @@ static void render_output(struct sway_output *output, struct timespec *when,
goto renderer_end;
}
- // TODO: don't damage the whole output here
+ // TODO: don't damage the whole output
int width, height;
wlr_output_transformed_resolution(wlr_output, &width, &height);
pixman_region32_union_rect(damage, damage, 0, 0, width, height);
@@ -239,16 +250,12 @@ static void render_output(struct sway_output *output, struct timespec *when,
float clear_color[] = {0.25f, 0.25f, 0.25f, 1.0f};
wlr_renderer_clear(renderer, clear_color);
- struct wlr_output_layout *output_layout =
- root_container.sway_root->output_layout;
- const struct wlr_box *output_box =
- wlr_output_layout_get_box(output_layout, wlr_output);
-
render_layer(output, when,
&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND]);
render_layer(output, when,
&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM]);
+ // Render all views in the current workspace
struct sway_seat *seat = input_manager_current_seat(input_manager);
struct sway_container *focus =
seat_get_focus_inactive(seat, output->swayc);
@@ -258,36 +265,21 @@ static void render_output(struct sway_output *output, struct timespec *when,
}
struct sway_container *workspace = focus->type == C_WORKSPACE ?
focus : container_parent(focus, C_WORKSPACE);
+ struct render_view_data data = { .output = output, .when = when };
+ container_descendants(workspace, C_VIEW, render_view_iterator, &data);
- struct render_data rdata = {
- .output = output,
- .when = when,
- };
- container_descendants(workspace, C_VIEW, render_view, &rdata);
-
- // render unmanaged views on top
+ // Render unmanaged views on top
struct wl_list *unmanaged = &root_container.sway_root->xwayland_unmanaged;
struct sway_xwayland_unmanaged *unmanaged_surface;
wl_list_for_each(unmanaged_surface, unmanaged, link) {
struct wlr_xwayland_surface *xsurface =
unmanaged_surface->wlr_xwayland_surface;
-
- const struct wlr_box view_box = {
- .x = unmanaged_surface->lx,
- .y = unmanaged_surface->ly,
- .width = xsurface->width,
- .height = xsurface->height,
- };
- struct wlr_box intersection;
- if (!wlr_box_intersection(&view_box, output_box, &intersection)) {
- continue;
- }
-
- render_surface(xsurface->surface, wlr_output, &output->last_frame,
- view_box.x - output_box->x, view_box.y - output_box->y, 0, 1.0f);
+ double ox = unmanaged_surface->lx - output->swayc->x;
+ double oy = unmanaged_surface->ly - output->swayc->y;
+ render_surface(output, when, xsurface->surface, ox, oy);
}
- // TODO: Consider revising this when fullscreen windows are supported
+ // TODO: consider revising this when fullscreen windows are supported
render_layer(output, when,
&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]);
render_layer(output, when,
@@ -337,22 +329,107 @@ void output_damage_whole(struct sway_output *output) {
wlr_output_damage_add_whole(output->damage);
}
-void output_damage_whole_surface(struct sway_output *output,
- double ox, double oy, struct wlr_surface *surface) {
- // TODO
- output_damage_whole(output);
+struct damage_data {
+ struct root_geometry root_geo;
+ struct sway_output *output;
+ bool whole;
+};
+
+static void damage_surface_iterator(struct wlr_surface *surface, int sx, int sy,
+ void *_data) {
+ struct damage_data *data = _data;
+ struct sway_output *output = data->output;
+ float rotation = data->root_geo.rotation;
+ bool whole = data->whole;
+
+ if (!wlr_surface_has_buffer(surface)) {
+ return;
+ }
+
+ struct wlr_box box;
+ bool intersects = get_surface_box(&data->root_geo, data->output, surface,
+ sx, sy, &box);
+ if (!intersects) {
+ return;
+ }
+
+ scale_box(&box, output->wlr_output->scale);
+
+ if (whole) {
+ wlr_box_rotated_bounds(&box, rotation, &box);
+ wlr_output_damage_add_box(output->damage, &box);
+ } else {
+ int center_x = box.x + box.width/2;
+ int center_y = box.y + box.height/2;
+
+ pixman_region32_t damage;
+ pixman_region32_init(&damage);
+ pixman_region32_copy(&damage, &surface->current->surface_damage);
+ wlr_region_scale(&damage, &damage, output->wlr_output->scale);
+ if (ceil(output->wlr_output->scale) > surface->current->scale) {
+ // When scaling up a surface, it'll become blurry so we need to
+ // expand the damage region
+ wlr_region_expand(&damage, &damage,
+ ceil(output->wlr_output->scale) - surface->current->scale);
+ }
+ pixman_region32_translate(&damage, box.x, box.y);
+ wlr_region_rotated_bounds(&damage, &damage, rotation,
+ center_x, center_y);
+ wlr_output_damage_add(output->damage, &damage);
+ pixman_region32_fini(&damage);
+ }
+}
+
+void output_damage_surface(struct sway_output *output, double ox, double oy,
+ struct wlr_surface *surface, bool whole) {
+ struct damage_data data = {
+ .output = output,
+ .whole = whole,
+ };
+
+ output_surface_for_each_surface(surface, ox, oy, &data.root_geo,
+ damage_surface_iterator, &data);
}
-void output_damage_whole_view(struct sway_output *output,
- struct sway_view *view) {
- // TODO
- output_damage_whole(output);
+void output_damage_view(struct sway_output *output, struct sway_view *view,
+ bool whole) {
+ if (!sway_assert(view->swayc != NULL, "expected a view in the tree")) {
+ return;
+ }
+
+ struct damage_data data = {
+ .output = output,
+ .whole = whole,
+ };
+
+ output_view_for_each_surface(view, &data.root_geo,
+ damage_surface_iterator, &data);
+}
+
+static void output_damage_whole_container_iterator(struct sway_container *con,
+ void *data) {
+ struct sway_output *output = data;
+
+ if (!sway_assert(con->type != C_VIEW, "expected a view")) {
+ return;
+ }
+
+ output_damage_view(output, con->sway_view, true);
}
void output_damage_whole_container(struct sway_output *output,
struct sway_container *con) {
- // TODO
- output_damage_whole(output);
+ float scale = output->wlr_output->scale;
+ struct wlr_box box = {
+ .x = con->x * scale,
+ .y = con->y * scale,
+ .width = con->width * scale,
+ .height = con->height * scale,
+ };
+ wlr_output_damage_add_box(output->damage, &box);
+
+ container_descendants(con, C_VIEW, output_damage_whole_container_iterator,
+ output);
}
static void damage_handle_destroy(struct wl_listener *listener, void *data) {
diff --git a/sway/desktop/wl_shell.c b/sway/desktop/wl_shell.c
index fff31da8..b63c220c 100644
--- a/sway/desktop/wl_shell.c
+++ b/sway/desktop/wl_shell.c
@@ -79,7 +79,7 @@ static void handle_commit(struct wl_listener *listener, void *data) {
// TODO: Let floating views do whatever
view_update_size(view, wl_shell_view->pending_width,
wl_shell_view->pending_height);
- view_damage_from(view);
+ view_damage(view, false);
}
static void handle_destroy(struct wl_listener *listener, void *data) {
diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c
index 8361aab3..e4703040 100644
--- a/sway/desktop/xdg_shell_v6.c
+++ b/sway/desktop/xdg_shell_v6.c
@@ -143,9 +143,7 @@ static void destroy(struct sway_view *view) {
if (xdg_shell_v6_view == NULL) {
return;
}
- wl_list_remove(&xdg_shell_v6_view->commit.link);
wl_list_remove(&xdg_shell_v6_view->destroy.link);
- wl_list_remove(&xdg_shell_v6_view->new_popup.link);
wl_list_remove(&xdg_shell_v6_view->map.link);
wl_list_remove(&xdg_shell_v6_view->unmap.link);
free(xdg_shell_v6_view);
@@ -169,7 +167,7 @@ static void handle_commit(struct wl_listener *listener, void *data) {
// TODO: Let floating views do whatever
view_update_size(view, xdg_shell_v6_view->pending_width,
xdg_shell_v6_view->pending_height);
- view_damage_from(view);
+ view_damage(view, false);
}
static void handle_new_popup(struct wl_listener *listener, void *data) {
@@ -182,14 +180,28 @@ static void handle_new_popup(struct wl_listener *listener, void *data) {
static void handle_unmap(struct wl_listener *listener, void *data) {
struct sway_xdg_shell_v6_view *xdg_shell_v6_view =
wl_container_of(listener, xdg_shell_v6_view, unmap);
+
view_unmap(&xdg_shell_v6_view->view);
+
+ wl_list_remove(&xdg_shell_v6_view->commit.link);
+ wl_list_remove(&xdg_shell_v6_view->new_popup.link);
}
static void handle_map(struct wl_listener *listener, void *data) {
struct sway_xdg_shell_v6_view *xdg_shell_v6_view =
wl_container_of(listener, xdg_shell_v6_view, map);
struct sway_view *view = &xdg_shell_v6_view->view;
+ struct wlr_xdg_surface_v6 *xdg_surface = view->wlr_xdg_surface_v6;
+
view_map(view, view->wlr_xdg_surface_v6->surface);
+
+ xdg_shell_v6_view->commit.notify = handle_commit;
+ wl_signal_add(&xdg_surface->surface->events.commit,
+ &xdg_shell_v6_view->commit);
+
+ xdg_shell_v6_view->new_popup.notify = handle_new_popup;
+ wl_signal_add(&xdg_surface->events.new_popup,
+ &xdg_shell_v6_view->new_popup);
}
static void handle_destroy(struct wl_listener *listener, void *data) {
@@ -226,14 +238,6 @@ void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) {
// - Look up pid and open on appropriate workspace
// - Criteria
- xdg_shell_v6_view->commit.notify = handle_commit;
- wl_signal_add(&xdg_surface->surface->events.commit,
- &xdg_shell_v6_view->commit);
-
- xdg_shell_v6_view->new_popup.notify = handle_new_popup;
- wl_signal_add(&xdg_surface->events.new_popup,
- &xdg_shell_v6_view->new_popup);
-
xdg_shell_v6_view->map.notify = handle_map;
wl_signal_add(&xdg_surface->events.map, &xdg_shell_v6_view->map);
diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c
index 10bfcc89..6de1365d 100644
--- a/sway/desktop/xwayland.c
+++ b/sway/desktop/xwayland.c
@@ -32,15 +32,15 @@ static void unmanaged_handle_commit(struct wl_listener *listener, void *data) {
if (xsurface->x != surface->lx || xsurface->y != surface->ly) {
// Surface has moved
- desktop_damage_whole_surface(xsurface->surface,
- surface->lx, surface->ly);
+ desktop_damage_surface(xsurface->surface, surface->lx, surface->ly,
+ true);
surface->lx = xsurface->x;
surface->ly = xsurface->y;
- desktop_damage_whole_surface(xsurface->surface,
- surface->lx, surface->ly);
+ desktop_damage_surface(xsurface->surface, surface->lx, surface->ly,
+ true);
} else {
- desktop_damage_from_surface(xsurface->surface,
- xsurface->x, xsurface->y);
+ desktop_damage_surface(xsurface->surface, xsurface->x, xsurface->y,
+ false);
}
}
@@ -57,7 +57,7 @@ static void unmanaged_handle_map(struct wl_listener *listener, void *data) {
surface->lx = xsurface->x;
surface->ly = xsurface->y;
- desktop_damage_whole_surface(xsurface->surface, surface->lx, surface->ly);
+ desktop_damage_surface(xsurface->surface, surface->lx, surface->ly, true);
// TODO: we don't send surface enter/leave events to xwayland unmanaged
// surfaces, but xwayland doesn't support HiDPI anyway
@@ -67,7 +67,7 @@ static void unmanaged_handle_unmap(struct wl_listener *listener, void *data) {
struct sway_xwayland_unmanaged *surface =
wl_container_of(listener, surface, unmap);
struct wlr_xwayland_surface *xsurface = surface->wlr_xwayland_surface;
- desktop_damage_whole_surface(xsurface->surface, xsurface->x, xsurface->y);
+ desktop_damage_surface(xsurface->surface, xsurface->x, xsurface->y, true);
wl_list_remove(&surface->link);
wl_list_remove(&surface->commit.link);
}
@@ -209,7 +209,7 @@ static void handle_commit(struct wl_listener *listener, void *data) {
// TODO: Let floating views do whatever
view_update_size(view, xwayland_view->pending_width,
xwayland_view->pending_height);
- view_damage_from(view);
+ view_damage(view, false);
}
static void handle_unmap(struct wl_listener *listener, void *data) {
diff --git a/sway/tree/view.c b/sway/tree/view.c
index 9855c5e1..99b44720 100644
--- a/sway/tree/view.c
+++ b/sway/tree/view.c
@@ -79,20 +79,15 @@ void view_close(struct sway_view *view) {
}
}
-void view_damage_whole(struct sway_view *view) {
+void view_damage(struct sway_view *view, bool whole) {
for (int i = 0; i < root_container.children->length; ++i) {
struct sway_container *cont = root_container.children->items[i];
if (cont->type == C_OUTPUT) {
- output_damage_whole_view(cont->sway_output, view);
+ output_damage_view(cont->sway_output, view, whole);
}
}
}
-void view_damage_from(struct sway_view *view) {
- // TODO
- view_damage_whole(view);
-}
-
static void view_get_layout_box(struct sway_view *view, struct wlr_box *box) {
struct sway_container *output = container_parent(view->swayc, C_OUTPUT);
@@ -191,7 +186,7 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) {
arrange_windows(cont->parent, -1, -1);
input_manager_set_focus(input_manager, cont);
- view_damage_whole(view);
+ view_damage(view, true);
view_handle_container_reparent(&view->container_reparent, NULL);
}
@@ -202,7 +197,7 @@ void view_unmap(struct sway_view *view) {
wl_signal_emit(&view->events.unmap, view);
- view_damage_whole(view);
+ view_damage(view, true);
wl_list_remove(&view->surface_new_subsurface.link);
wl_list_remove(&view->container_reparent.link);
@@ -220,10 +215,10 @@ void view_update_position(struct sway_view *view, double ox, double oy) {
return;
}
- view_damage_whole(view);
+ view_damage(view, true);
view->swayc->x = ox;
view->swayc->y = oy;
- view_damage_whole(view);
+ view_damage(view, true);
}
void view_update_size(struct sway_view *view, int width, int height) {
@@ -231,10 +226,10 @@ void view_update_size(struct sway_view *view, int width, int height) {
return;
}
- view_damage_whole(view);
+ view_damage(view, true);
view->width = width;
view->height = height;
- view_damage_whole(view);
+ view_damage(view, true);
}
@@ -253,7 +248,7 @@ static void view_child_handle_surface_commit(struct wl_listener *listener,
struct sway_view_child *child =
wl_container_of(listener, child, surface_commit);
// TODO: only accumulate damage from the child
- view_damage_from(child->view);
+ view_damage(child->view, false);
}
static void view_child_handle_surface_new_subsurface(
@@ -315,12 +310,12 @@ void view_child_init(struct sway_view_child *child,
view_init_subsurfaces(child->view, surface);
// TODO: only damage the whole child
- view_damage_whole(child->view);
+ view_damage(child->view, true);
}
void view_child_destroy(struct sway_view_child *child) {
// TODO: only damage the whole child
- view_damage_whole(child->view);
+ view_damage(child->view, true);
wl_list_remove(&child->surface_commit.link);
wl_list_remove(&child->surface_destroy.link);