diff options
author | emersion <contact@emersion.fr> | 2018-04-06 14:17:58 -0400 |
---|---|---|
committer | emersion <contact@emersion.fr> | 2018-04-06 14:17:58 -0400 |
commit | 58914822aa70d69a61794c52aa2113dbe7fcc7af (patch) | |
tree | ba1de3856366da1883247fe49d463c6ba35b9b57 | |
parent | Refactor rendering code (diff) | |
download | sway-58914822aa70d69a61794c52aa2113dbe7fcc7af.tar.gz sway-58914822aa70d69a61794c52aa2113dbe7fcc7af.tar.zst sway-58914822aa70d69a61794c52aa2113dbe7fcc7af.zip |
Don't damage the whole output
-rw-r--r-- | sway/desktop/output.c | 103 | ||||
-rw-r--r-- | sway/desktop/xdg_shell_v6.c | 24 |
2 files changed, 104 insertions, 23 deletions
diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 90ec3c77..0f25cff1 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c | |||
@@ -1,8 +1,8 @@ | |||
1 | #define _POSIX_C_SOURCE 200809L | 1 | #define _POSIX_C_SOURCE 200809L |
2 | #include <assert.h> | 2 | #include <assert.h> |
3 | #include <stdlib.h> | 3 | #include <stdlib.h> |
4 | #include <time.h> | ||
5 | #include <strings.h> | 4 | #include <strings.h> |
5 | #include <time.h> | ||
6 | #include <wayland-server.h> | 6 | #include <wayland-server.h> |
7 | #include <wlr/render/wlr_renderer.h> | 7 | #include <wlr/render/wlr_renderer.h> |
8 | #include <wlr/types/wlr_box.h> | 8 | #include <wlr/types/wlr_box.h> |
@@ -12,6 +12,7 @@ | |||
12 | #include <wlr/types/wlr_output.h> | 12 | #include <wlr/types/wlr_output.h> |
13 | #include <wlr/types/wlr_surface.h> | 13 | #include <wlr/types/wlr_surface.h> |
14 | #include <wlr/types/wlr_wl_shell.h> | 14 | #include <wlr/types/wlr_wl_shell.h> |
15 | #include <wlr/util/region.h> | ||
15 | #include "log.h" | 16 | #include "log.h" |
16 | #include "sway/input/input-manager.h" | 17 | #include "sway/input/input-manager.h" |
17 | #include "sway/input/seat.h" | 18 | #include "sway/input/seat.h" |
@@ -95,13 +96,13 @@ static bool get_surface_box(struct root_geometry *geo, | |||
95 | } | 96 | } |
96 | 97 | ||
97 | static void output_surface_for_each_surface(struct wlr_surface *surface, | 98 | static void output_surface_for_each_surface(struct wlr_surface *surface, |
98 | double ox, double oy, float rotation, struct root_geometry *geo, | 99 | double ox, double oy, struct root_geometry *geo, |
99 | wlr_surface_iterator_func_t iterator, void *user_data) { | 100 | wlr_surface_iterator_func_t iterator, void *user_data) { |
100 | geo->x = ox; | 101 | geo->x = ox; |
101 | geo->y = oy; | 102 | geo->y = oy; |
102 | geo->width = surface->current->width; | 103 | geo->width = surface->current->width; |
103 | geo->height = surface->current->height; | 104 | geo->height = surface->current->height; |
104 | geo->rotation = rotation; | 105 | geo->rotation = 0; |
105 | 106 | ||
106 | wlr_surface_for_each_surface(surface, iterator, user_data); | 107 | wlr_surface_for_each_surface(surface, iterator, user_data); |
107 | } | 108 | } |
@@ -174,14 +175,14 @@ static void render_surface_iterator(struct wlr_surface *surface, int sx, int sy, | |||
174 | } | 175 | } |
175 | 176 | ||
176 | static void render_surface(struct sway_output *output, struct timespec *when, | 177 | static void render_surface(struct sway_output *output, struct timespec *when, |
177 | struct wlr_surface *surface, double ox, double oy, float rotation) { | 178 | struct wlr_surface *surface, double ox, double oy) { |
178 | struct render_data data = { | 179 | struct render_data data = { |
179 | .output = output, | 180 | .output = output, |
180 | .when = when, | 181 | .when = when, |
181 | .alpha = 1.0f, | 182 | .alpha = 1.0f, |
182 | }; | 183 | }; |
183 | 184 | ||
184 | output_surface_for_each_surface(surface, ox, oy, rotation, &data.root_geo, | 185 | output_surface_for_each_surface(surface, ox, oy, &data.root_geo, |
185 | render_surface_iterator, &data); | 186 | render_surface_iterator, &data); |
186 | } | 187 | } |
187 | 188 | ||
@@ -204,7 +205,7 @@ static void render_layer(struct sway_output *output, struct timespec *when, | |||
204 | struct wlr_layer_surface *wlr_layer_surface = | 205 | struct wlr_layer_surface *wlr_layer_surface = |
205 | layer_surface->layer_surface; | 206 | layer_surface->layer_surface; |
206 | render_surface(output, when, wlr_layer_surface->surface, | 207 | render_surface(output, when, wlr_layer_surface->surface, |
207 | layer_surface->geo.x, layer_surface->geo.y, 0); | 208 | layer_surface->geo.x, layer_surface->geo.y); |
208 | } | 209 | } |
209 | } | 210 | } |
210 | 211 | ||
@@ -241,6 +242,11 @@ static void render_output(struct sway_output *output, struct timespec *when, | |||
241 | goto renderer_end; | 242 | goto renderer_end; |
242 | } | 243 | } |
243 | 244 | ||
245 | // TODO: don't damage the whole output | ||
246 | int width, height; | ||
247 | wlr_output_transformed_resolution(wlr_output, &width, &height); | ||
248 | pixman_region32_union_rect(damage, damage, 0, 0, width, height); | ||
249 | |||
244 | float clear_color[] = {0.25f, 0.25f, 0.25f, 1.0f}; | 250 | float clear_color[] = {0.25f, 0.25f, 0.25f, 1.0f}; |
245 | wlr_renderer_clear(renderer, clear_color); | 251 | wlr_renderer_clear(renderer, clear_color); |
246 | 252 | ||
@@ -270,7 +276,7 @@ static void render_output(struct sway_output *output, struct timespec *when, | |||
270 | unmanaged_surface->wlr_xwayland_surface; | 276 | unmanaged_surface->wlr_xwayland_surface; |
271 | double ox = unmanaged_surface->lx - output->swayc->x; | 277 | double ox = unmanaged_surface->lx - output->swayc->x; |
272 | double oy = unmanaged_surface->ly - output->swayc->y; | 278 | double oy = unmanaged_surface->ly - output->swayc->y; |
273 | render_surface(output, when, xsurface->surface, ox, oy, 0); | 279 | render_surface(output, when, xsurface->surface, ox, oy); |
274 | } | 280 | } |
275 | 281 | ||
276 | // TODO: consider revising this when fullscreen windows are supported | 282 | // TODO: consider revising this when fullscreen windows are supported |
@@ -318,22 +324,93 @@ void output_damage_whole(struct sway_output *output) { | |||
318 | wlr_output_damage_add_whole(output->damage); | 324 | wlr_output_damage_add_whole(output->damage); |
319 | } | 325 | } |
320 | 326 | ||
327 | struct damage_data { | ||
328 | struct root_geometry root_geo; | ||
329 | struct sway_output *output; | ||
330 | bool whole; | ||
331 | }; | ||
332 | |||
333 | static void damage_surface_iterator(struct wlr_surface *surface, int sx, int sy, | ||
334 | void *_data) { | ||
335 | struct damage_data *data = _data; | ||
336 | struct sway_output *output = data->output; | ||
337 | float rotation = data->root_geo.rotation; | ||
338 | bool whole = data->whole; | ||
339 | |||
340 | if (!wlr_surface_has_buffer(surface)) { | ||
341 | return; | ||
342 | } | ||
343 | |||
344 | struct wlr_box box; | ||
345 | bool intersects = get_surface_box(&data->root_geo, data->output, surface, | ||
346 | sx, sy, &box); | ||
347 | if (!intersects) { | ||
348 | return; | ||
349 | } | ||
350 | |||
351 | scale_box(&box, output->wlr_output->scale); | ||
352 | |||
353 | if (whole) { | ||
354 | wlr_box_rotated_bounds(&box, rotation, &box); | ||
355 | wlr_output_damage_add_box(output->damage, &box); | ||
356 | } else { | ||
357 | int center_x = box.x + box.width/2; | ||
358 | int center_y = box.y + box.height/2; | ||
359 | |||
360 | pixman_region32_t damage; | ||
361 | pixman_region32_init(&damage); | ||
362 | pixman_region32_copy(&damage, &surface->current->surface_damage); | ||
363 | wlr_region_scale(&damage, &damage, output->wlr_output->scale); | ||
364 | if (ceil(output->wlr_output->scale) > surface->current->scale) { | ||
365 | // When scaling up a surface, it'll become blurry so we need to | ||
366 | // expand the damage region | ||
367 | wlr_region_expand(&damage, &damage, | ||
368 | ceil(output->wlr_output->scale) - surface->current->scale); | ||
369 | } | ||
370 | pixman_region32_translate(&damage, box.x, box.y); | ||
371 | wlr_region_rotated_bounds(&damage, &damage, rotation, | ||
372 | center_x, center_y); | ||
373 | wlr_output_damage_add(output->damage, &damage); | ||
374 | pixman_region32_fini(&damage); | ||
375 | } | ||
376 | } | ||
377 | |||
321 | void output_damage_surface(struct sway_output *output, double ox, double oy, | 378 | void output_damage_surface(struct sway_output *output, double ox, double oy, |
322 | struct wlr_surface *surface, bool whole) { | 379 | struct wlr_surface *surface, bool whole) { |
323 | // TODO | 380 | struct damage_data data = { |
324 | output_damage_whole(output); | 381 | .output = output, |
382 | .whole = whole, | ||
383 | }; | ||
384 | |||
385 | output_surface_for_each_surface(surface, ox, oy, &data.root_geo, | ||
386 | damage_surface_iterator, &data); | ||
325 | } | 387 | } |
326 | 388 | ||
327 | void output_damage_view(struct sway_output *output, struct sway_view *view, | 389 | void output_damage_view(struct sway_output *output, struct sway_view *view, |
328 | bool whole) { | 390 | bool whole) { |
329 | // TODO | 391 | if (!sway_assert(view->swayc != NULL, "expected a view in the tree")) { |
330 | output_damage_whole(output); | 392 | return; |
393 | } | ||
394 | |||
395 | struct damage_data data = { | ||
396 | .output = output, | ||
397 | .whole = whole, | ||
398 | }; | ||
399 | |||
400 | output_view_for_each_surface(view, &data.root_geo, | ||
401 | damage_surface_iterator, &data); | ||
331 | } | 402 | } |
332 | 403 | ||
333 | void output_damage_whole_container(struct sway_output *output, | 404 | void output_damage_whole_container(struct sway_output *output, |
334 | struct sway_container *con) { | 405 | struct sway_container *con) { |
335 | // TODO | 406 | float scale = output->wlr_output->scale; |
336 | output_damage_whole(output); | 407 | struct wlr_box box = { |
408 | .x = con->x * scale, | ||
409 | .y = con->y * scale, | ||
410 | .width = con->width * scale, | ||
411 | .height = con->height * scale, | ||
412 | }; | ||
413 | wlr_output_damage_add_box(output->damage, &box); | ||
337 | } | 414 | } |
338 | 415 | ||
339 | static void damage_handle_destroy(struct wl_listener *listener, void *data) { | 416 | static void damage_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 b82eec8f..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) { | |||
143 | if (xdg_shell_v6_view == NULL) { | 143 | if (xdg_shell_v6_view == NULL) { |
144 | return; | 144 | return; |
145 | } | 145 | } |
146 | wl_list_remove(&xdg_shell_v6_view->commit.link); | ||
147 | wl_list_remove(&xdg_shell_v6_view->destroy.link); | 146 | wl_list_remove(&xdg_shell_v6_view->destroy.link); |
148 | wl_list_remove(&xdg_shell_v6_view->new_popup.link); | ||
149 | wl_list_remove(&xdg_shell_v6_view->map.link); | 147 | wl_list_remove(&xdg_shell_v6_view->map.link); |
150 | wl_list_remove(&xdg_shell_v6_view->unmap.link); | 148 | wl_list_remove(&xdg_shell_v6_view->unmap.link); |
151 | free(xdg_shell_v6_view); | 149 | free(xdg_shell_v6_view); |
@@ -182,14 +180,28 @@ static void handle_new_popup(struct wl_listener *listener, void *data) { | |||
182 | static void handle_unmap(struct wl_listener *listener, void *data) { | 180 | static void handle_unmap(struct wl_listener *listener, void *data) { |
183 | struct sway_xdg_shell_v6_view *xdg_shell_v6_view = | 181 | struct sway_xdg_shell_v6_view *xdg_shell_v6_view = |
184 | wl_container_of(listener, xdg_shell_v6_view, unmap); | 182 | wl_container_of(listener, xdg_shell_v6_view, unmap); |
183 | |||
185 | view_unmap(&xdg_shell_v6_view->view); | 184 | view_unmap(&xdg_shell_v6_view->view); |
185 | |||
186 | wl_list_remove(&xdg_shell_v6_view->commit.link); | ||
187 | wl_list_remove(&xdg_shell_v6_view->new_popup.link); | ||
186 | } | 188 | } |
187 | 189 | ||
188 | static void handle_map(struct wl_listener *listener, void *data) { | 190 | static void handle_map(struct wl_listener *listener, void *data) { |
189 | struct sway_xdg_shell_v6_view *xdg_shell_v6_view = | 191 | struct sway_xdg_shell_v6_view *xdg_shell_v6_view = |
190 | wl_container_of(listener, xdg_shell_v6_view, map); | 192 | wl_container_of(listener, xdg_shell_v6_view, map); |
191 | struct sway_view *view = &xdg_shell_v6_view->view; | 193 | struct sway_view *view = &xdg_shell_v6_view->view; |
194 | struct wlr_xdg_surface_v6 *xdg_surface = view->wlr_xdg_surface_v6; | ||
195 | |||
192 | view_map(view, view->wlr_xdg_surface_v6->surface); | 196 | view_map(view, view->wlr_xdg_surface_v6->surface); |
197 | |||
198 | xdg_shell_v6_view->commit.notify = handle_commit; | ||
199 | wl_signal_add(&xdg_surface->surface->events.commit, | ||
200 | &xdg_shell_v6_view->commit); | ||
201 | |||
202 | xdg_shell_v6_view->new_popup.notify = handle_new_popup; | ||
203 | wl_signal_add(&xdg_surface->events.new_popup, | ||
204 | &xdg_shell_v6_view->new_popup); | ||
193 | } | 205 | } |
194 | 206 | ||
195 | static void handle_destroy(struct wl_listener *listener, void *data) { | 207 | 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) { | |||
226 | // - Look up pid and open on appropriate workspace | 238 | // - Look up pid and open on appropriate workspace |
227 | // - Criteria | 239 | // - Criteria |
228 | 240 | ||
229 | xdg_shell_v6_view->commit.notify = handle_commit; | ||
230 | wl_signal_add(&xdg_surface->surface->events.commit, | ||
231 | &xdg_shell_v6_view->commit); | ||
232 | |||
233 | xdg_shell_v6_view->new_popup.notify = handle_new_popup; | ||
234 | wl_signal_add(&xdg_surface->events.new_popup, | ||
235 | &xdg_shell_v6_view->new_popup); | ||
236 | |||
237 | xdg_shell_v6_view->map.notify = handle_map; | 241 | xdg_shell_v6_view->map.notify = handle_map; |
238 | wl_signal_add(&xdg_surface->events.map, &xdg_shell_v6_view->map); | 242 | wl_signal_add(&xdg_surface->events.map, &xdg_shell_v6_view->map); |
239 | 243 | ||