diff options
Diffstat (limited to 'sway/desktop/output.c')
-rw-r--r-- | sway/desktop/output.c | 339 |
1 files changed, 181 insertions, 158 deletions
diff --git a/sway/desktop/output.c b/sway/desktop/output.c index a9808406..66747a3f 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <wlr/types/wlr_surface.h> | 14 | #include <wlr/types/wlr_surface.h> |
15 | #include <wlr/util/region.h> | 15 | #include <wlr/util/region.h> |
16 | #include "log.h" | 16 | #include "log.h" |
17 | #include "config.h" | ||
17 | #include "sway/config.h" | 18 | #include "sway/config.h" |
18 | #include "sway/input/input-manager.h" | 19 | #include "sway/input/input-manager.h" |
19 | #include "sway/input/seat.h" | 20 | #include "sway/input/seat.h" |
@@ -56,9 +57,21 @@ static void rotate_child_position(double *sx, double *sy, double sw, double sh, | |||
56 | *sy = ry + ph/2 - sh/2; | 57 | *sy = ry + ph/2 - sh/2; |
57 | } | 58 | } |
58 | 59 | ||
59 | bool output_get_surface_box(struct root_geometry *geo, | 60 | struct surface_iterator_data { |
60 | struct sway_output *output, struct wlr_surface *surface, int sx, int sy, | 61 | sway_surface_iterator_func_t user_iterator; |
62 | void *user_data; | ||
63 | |||
64 | struct sway_output *output; | ||
65 | double ox, oy; | ||
66 | int width, height; | ||
67 | float rotation; | ||
68 | }; | ||
69 | |||
70 | static bool get_surface_box(struct surface_iterator_data *data, | ||
71 | struct wlr_surface *surface, int sx, int sy, | ||
61 | struct wlr_box *surface_box) { | 72 | struct wlr_box *surface_box) { |
73 | struct sway_output *output = data->output; | ||
74 | |||
62 | if (!wlr_surface_has_buffer(surface)) { | 75 | if (!wlr_surface_has_buffer(surface)) { |
63 | return false; | 76 | return false; |
64 | } | 77 | } |
@@ -67,12 +80,12 @@ bool output_get_surface_box(struct root_geometry *geo, | |||
67 | int sh = surface->current.height; | 80 | int sh = surface->current.height; |
68 | 81 | ||
69 | double _sx = sx, _sy = sy; | 82 | double _sx = sx, _sy = sy; |
70 | rotate_child_position(&_sx, &_sy, sw, sh, geo->width, geo->height, | 83 | rotate_child_position(&_sx, &_sy, sw, sh, data->width, data->height, |
71 | geo->rotation); | 84 | data->rotation); |
72 | 85 | ||
73 | struct wlr_box box = { | 86 | struct wlr_box box = { |
74 | .x = geo->x + _sx, | 87 | .x = data->ox + _sx, |
75 | .y = geo->y + _sy, | 88 | .y = data->oy + _sy, |
76 | .width = sw, | 89 | .width = sw, |
77 | .height = sh, | 90 | .height = sh, |
78 | }; | 91 | }; |
@@ -81,7 +94,7 @@ bool output_get_surface_box(struct root_geometry *geo, | |||
81 | } | 94 | } |
82 | 95 | ||
83 | struct wlr_box rotated_box; | 96 | struct wlr_box rotated_box; |
84 | wlr_box_rotated_bounds(&box, geo->rotation, &rotated_box); | 97 | wlr_box_rotated_bounds(&box, data->rotation, &rotated_box); |
85 | 98 | ||
86 | struct wlr_box output_box = { | 99 | struct wlr_box output_box = { |
87 | .width = output->swayc->current.swayc_width, | 100 | .width = output->swayc->current.swayc_width, |
@@ -92,46 +105,90 @@ bool output_get_surface_box(struct root_geometry *geo, | |||
92 | return wlr_box_intersection(&output_box, &rotated_box, &intersection); | 105 | return wlr_box_intersection(&output_box, &rotated_box, &intersection); |
93 | } | 106 | } |
94 | 107 | ||
95 | void output_surface_for_each_surface(struct wlr_surface *surface, | 108 | static void output_for_each_surface_iterator(struct wlr_surface *surface, |
96 | double ox, double oy, struct root_geometry *geo, | 109 | int sx, int sy, void *_data) { |
97 | wlr_surface_iterator_func_t iterator, void *user_data) { | 110 | struct surface_iterator_data *data = _data; |
98 | geo->x = ox; | ||
99 | geo->y = oy; | ||
100 | geo->width = surface->current.width; | ||
101 | geo->height = surface->current.height; | ||
102 | geo->rotation = 0; | ||
103 | 111 | ||
104 | wlr_surface_for_each_surface(surface, iterator, user_data); | 112 | struct wlr_box box; |
113 | bool intersects = get_surface_box(data, surface, sx, sy, &box); | ||
114 | if (!intersects) { | ||
115 | return; | ||
116 | } | ||
117 | |||
118 | data->user_iterator(data->output, surface, &box, data->rotation, | ||
119 | data->user_data); | ||
120 | } | ||
121 | |||
122 | void output_surface_for_each_surface(struct sway_output *output, | ||
123 | struct wlr_surface *surface, double ox, double oy, | ||
124 | sway_surface_iterator_func_t iterator, void *user_data) { | ||
125 | struct surface_iterator_data data = { | ||
126 | .user_iterator = iterator, | ||
127 | .user_data = user_data, | ||
128 | .output = output, | ||
129 | .ox = ox, | ||
130 | .oy = oy, | ||
131 | .width = surface->current.width, | ||
132 | .height = surface->current.height, | ||
133 | .rotation = 0, | ||
134 | }; | ||
135 | |||
136 | wlr_surface_for_each_surface(surface, | ||
137 | output_for_each_surface_iterator, &data); | ||
105 | } | 138 | } |
106 | 139 | ||
107 | void output_view_for_each_surface(struct sway_view *view, | 140 | void output_view_for_each_surface(struct sway_output *output, |
108 | struct sway_output *output, struct root_geometry *geo, | 141 | struct sway_view *view, sway_surface_iterator_func_t iterator, |
109 | wlr_surface_iterator_func_t iterator, void *user_data) { | 142 | void *user_data) { |
110 | geo->x = view->swayc->current.view_x - output->swayc->current.swayc_x; | 143 | struct surface_iterator_data data = { |
111 | geo->y = view->swayc->current.view_y - output->swayc->current.swayc_y; | 144 | .user_iterator = iterator, |
112 | geo->width = view->swayc->current.view_width; | 145 | .user_data = user_data, |
113 | geo->height = view->swayc->current.view_height; | 146 | .output = output, |
114 | geo->rotation = 0; // TODO | 147 | .ox = view->swayc->current.view_x - output->swayc->current.swayc_x, |
148 | .oy = view->swayc->current.view_y - output->swayc->current.swayc_y, | ||
149 | .width = view->swayc->current.view_width, | ||
150 | .height = view->swayc->current.view_height, | ||
151 | .rotation = 0, // TODO | ||
152 | }; | ||
115 | 153 | ||
116 | view_for_each_surface(view, iterator, user_data); | 154 | view_for_each_surface(view, |
155 | output_for_each_surface_iterator, &data); | ||
117 | } | 156 | } |
118 | 157 | ||
119 | void output_layer_for_each_surface(struct wl_list *layer_surfaces, | 158 | void output_view_for_each_popup(struct sway_output *output, |
120 | struct root_geometry *geo, wlr_surface_iterator_func_t iterator, | 159 | struct sway_view *view, sway_surface_iterator_func_t iterator, |
160 | void *user_data) { | ||
161 | struct surface_iterator_data data = { | ||
162 | .user_iterator = iterator, | ||
163 | .user_data = user_data, | ||
164 | .output = output, | ||
165 | .ox = view->swayc->current.view_x - output->swayc->current.swayc_x, | ||
166 | .oy = view->swayc->current.view_y - output->swayc->current.swayc_y, | ||
167 | .width = view->swayc->current.view_width, | ||
168 | .height = view->swayc->current.view_height, | ||
169 | .rotation = 0, // TODO | ||
170 | }; | ||
171 | |||
172 | view_for_each_popup(view, output_for_each_surface_iterator, &data); | ||
173 | } | ||
174 | |||
175 | void output_layer_for_each_surface(struct sway_output *output, | ||
176 | struct wl_list *layer_surfaces, sway_surface_iterator_func_t iterator, | ||
121 | void *user_data) { | 177 | void *user_data) { |
122 | struct sway_layer_surface *layer_surface; | 178 | struct sway_layer_surface *layer_surface; |
123 | wl_list_for_each(layer_surface, layer_surfaces, link) { | 179 | wl_list_for_each(layer_surface, layer_surfaces, link) { |
124 | struct wlr_layer_surface *wlr_layer_surface = | 180 | struct wlr_layer_surface *wlr_layer_surface = |
125 | layer_surface->layer_surface; | 181 | layer_surface->layer_surface; |
126 | output_surface_for_each_surface(wlr_layer_surface->surface, | 182 | output_surface_for_each_surface(output, wlr_layer_surface->surface, |
127 | layer_surface->geo.x, layer_surface->geo.y, geo, iterator, | 183 | layer_surface->geo.x, layer_surface->geo.y, iterator, |
128 | user_data); | 184 | user_data); |
129 | } | 185 | } |
130 | } | 186 | } |
131 | 187 | ||
132 | void output_unmanaged_for_each_surface(struct wl_list *unmanaged, | 188 | #ifdef HAVE_XWAYLAND |
133 | struct sway_output *output, struct root_geometry *geo, | 189 | void output_unmanaged_for_each_surface(struct sway_output *output, |
134 | wlr_surface_iterator_func_t iterator, void *user_data) { | 190 | struct wl_list *unmanaged, sway_surface_iterator_func_t iterator, |
191 | void *user_data) { | ||
135 | struct sway_xwayland_unmanaged *unmanaged_surface; | 192 | struct sway_xwayland_unmanaged *unmanaged_surface; |
136 | wl_list_for_each(unmanaged_surface, unmanaged, link) { | 193 | wl_list_for_each(unmanaged_surface, unmanaged, link) { |
137 | struct wlr_xwayland_surface *xsurface = | 194 | struct wlr_xwayland_surface *xsurface = |
@@ -139,22 +196,24 @@ void output_unmanaged_for_each_surface(struct wl_list *unmanaged, | |||
139 | double ox = unmanaged_surface->lx - output->swayc->current.swayc_x; | 196 | double ox = unmanaged_surface->lx - output->swayc->current.swayc_x; |
140 | double oy = unmanaged_surface->ly - output->swayc->current.swayc_y; | 197 | double oy = unmanaged_surface->ly - output->swayc->current.swayc_y; |
141 | 198 | ||
142 | output_surface_for_each_surface(xsurface->surface, ox, oy, geo, | 199 | output_surface_for_each_surface(output, xsurface->surface, ox, oy, |
143 | iterator, user_data); | 200 | iterator, user_data); |
144 | } | 201 | } |
145 | } | 202 | } |
203 | #endif | ||
146 | 204 | ||
147 | void output_drag_icons_for_each_surface(struct wl_list *drag_icons, | 205 | void output_drag_icons_for_each_surface(struct sway_output *output, |
148 | struct sway_output *output, struct root_geometry *geo, | 206 | struct wl_list *drag_icons, sway_surface_iterator_func_t iterator, |
149 | wlr_surface_iterator_func_t iterator, void *user_data) { | 207 | void *user_data) { |
150 | struct sway_drag_icon *drag_icon; | 208 | struct sway_drag_icon *drag_icon; |
151 | wl_list_for_each(drag_icon, drag_icons, link) { | 209 | wl_list_for_each(drag_icon, drag_icons, link) { |
152 | double ox = drag_icon->x - output->swayc->x; | 210 | double ox = drag_icon->x - output->swayc->x; |
153 | double oy = drag_icon->y - output->swayc->y; | 211 | double oy = drag_icon->y - output->swayc->y; |
154 | 212 | ||
155 | if (drag_icon->wlr_drag_icon->mapped) { | 213 | if (drag_icon->wlr_drag_icon->mapped) { |
156 | output_surface_for_each_surface(drag_icon->wlr_drag_icon->surface, | 214 | output_surface_for_each_surface(output, |
157 | ox, oy, geo, iterator, user_data); | 215 | drag_icon->wlr_drag_icon->surface, ox, oy, |
216 | iterator, user_data); | ||
158 | } | 217 | } |
159 | } | 218 | } |
160 | } | 219 | } |
@@ -181,21 +240,14 @@ struct sway_container *output_get_active_workspace(struct sway_output *output) { | |||
181 | return workspace; | 240 | return workspace; |
182 | } | 241 | } |
183 | 242 | ||
184 | bool output_has_opaque_lockscreen(struct sway_output *output, | 243 | bool output_has_opaque_overlay_layer_surface(struct sway_output *output) { |
185 | struct sway_seat *seat) { | ||
186 | if (!seat->exclusive_client) { | ||
187 | return false; | ||
188 | } | ||
189 | |||
190 | struct wlr_layer_surface *wlr_layer_surface; | 244 | struct wlr_layer_surface *wlr_layer_surface; |
191 | wl_list_for_each(wlr_layer_surface, &server.layer_shell->surfaces, link) { | 245 | wl_list_for_each(wlr_layer_surface, &server.layer_shell->surfaces, link) { |
192 | if (wlr_layer_surface->output != output->wlr_output) { | 246 | if (wlr_layer_surface->output != output->wlr_output || |
247 | wlr_layer_surface->layer != ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY) { | ||
193 | continue; | 248 | continue; |
194 | } | 249 | } |
195 | struct wlr_surface *wlr_surface = wlr_layer_surface->surface; | 250 | struct wlr_surface *wlr_surface = wlr_layer_surface->surface; |
196 | if (wlr_surface->resource->client != seat->exclusive_client) { | ||
197 | continue; | ||
198 | } | ||
199 | struct sway_layer_surface *sway_layer_surface = | 251 | struct sway_layer_surface *sway_layer_surface = |
200 | layer_from_wlr_layer_surface(wlr_layer_surface); | 252 | layer_from_wlr_layer_surface(wlr_layer_surface); |
201 | pixman_box32_t output_box = { | 253 | pixman_box32_t output_box = { |
@@ -217,46 +269,38 @@ bool output_has_opaque_lockscreen(struct sway_output *output, | |||
217 | return false; | 269 | return false; |
218 | } | 270 | } |
219 | 271 | ||
220 | struct send_frame_done_data { | 272 | static void send_frame_done_iterator(struct sway_output *output, |
221 | struct root_geometry root_geo; | 273 | struct wlr_surface *surface, struct wlr_box *box, float rotation, |
222 | struct sway_output *output; | 274 | void *_data) { |
223 | struct timespec *when; | 275 | struct timespec *when = _data; |
224 | struct wl_client *exclusive_client; | 276 | wlr_surface_send_frame_done(surface, when); |
225 | }; | ||
226 | |||
227 | static void send_frame_done_iterator(struct wlr_surface *surface, | ||
228 | int sx, int sy, void *_data) { | ||
229 | struct send_frame_done_data *data = _data; | ||
230 | if (data->exclusive_client && | ||
231 | data->exclusive_client != surface->resource->client) { | ||
232 | return; | ||
233 | } | ||
234 | |||
235 | bool intersects = output_get_surface_box(&data->root_geo, data->output, surface, | ||
236 | sx, sy, NULL); | ||
237 | if (intersects) { | ||
238 | wlr_surface_send_frame_done(surface, data->when); | ||
239 | } | ||
240 | } | 277 | } |
241 | 278 | ||
242 | static void send_frame_done_layer(struct send_frame_done_data *data, | 279 | static void send_frame_done_layer(struct sway_output *output, |
243 | struct wl_list *layer_surfaces) { | 280 | struct wl_list *layer_surfaces, struct timespec *when) { |
244 | output_layer_for_each_surface(layer_surfaces, &data->root_geo, | 281 | output_layer_for_each_surface(output, layer_surfaces, |
245 | send_frame_done_iterator, data); | 282 | send_frame_done_iterator, when); |
246 | } | 283 | } |
247 | 284 | ||
248 | static void send_frame_done_unmanaged(struct send_frame_done_data *data, | 285 | #ifdef HAVE_XWAYLAND |
249 | struct wl_list *unmanaged) { | 286 | static void send_frame_done_unmanaged(struct sway_output *output, |
250 | output_unmanaged_for_each_surface(unmanaged, data->output, &data->root_geo, | 287 | struct wl_list *unmanaged, struct timespec *when) { |
251 | send_frame_done_iterator, data); | 288 | output_unmanaged_for_each_surface(output, unmanaged, |
289 | send_frame_done_iterator, when); | ||
252 | } | 290 | } |
291 | #endif | ||
253 | 292 | ||
254 | static void send_frame_done_drag_icons(struct send_frame_done_data *data, | 293 | static void send_frame_done_drag_icons(struct sway_output *output, |
255 | struct wl_list *drag_icons) { | 294 | struct wl_list *drag_icons, struct timespec *when) { |
256 | output_drag_icons_for_each_surface(drag_icons, data->output, &data->root_geo, | 295 | output_drag_icons_for_each_surface(output, drag_icons, |
257 | send_frame_done_iterator, data); | 296 | send_frame_done_iterator, when); |
258 | } | 297 | } |
259 | 298 | ||
299 | struct send_frame_done_data { | ||
300 | struct sway_output *output; | ||
301 | struct timespec *when; | ||
302 | }; | ||
303 | |||
260 | static void send_frame_done_container_iterator(struct sway_container *con, | 304 | static void send_frame_done_container_iterator(struct sway_container *con, |
261 | void *_data) { | 305 | void *_data) { |
262 | struct send_frame_done_data *data = _data; | 306 | struct send_frame_done_data *data = _data; |
@@ -268,52 +312,62 @@ static void send_frame_done_container_iterator(struct sway_container *con, | |||
268 | return; | 312 | return; |
269 | } | 313 | } |
270 | 314 | ||
271 | output_view_for_each_surface(con->sway_view, data->output, &data->root_geo, | 315 | output_view_for_each_surface(data->output, con->sway_view, |
272 | send_frame_done_iterator, data); | 316 | send_frame_done_iterator, data->when); |
273 | } | ||
274 | |||
275 | static void send_frame_done_container(struct send_frame_done_data *data, | ||
276 | struct sway_container *con) { | ||
277 | container_descendants(con, C_VIEW, | ||
278 | send_frame_done_container_iterator, data); | ||
279 | } | 317 | } |
280 | 318 | ||
281 | static void send_frame_done(struct sway_output *output, struct timespec *when) { | 319 | static void send_frame_done_container(struct sway_output *output, |
282 | struct sway_seat *seat = input_manager_current_seat(input_manager); | 320 | struct sway_container *con, struct timespec *when) { |
283 | struct send_frame_done_data data = { | 321 | struct send_frame_done_data data = { |
284 | .output = output, | 322 | .output = output, |
285 | .when = when, | 323 | .when = when, |
286 | .exclusive_client = output_has_opaque_lockscreen(output, seat) ? | ||
287 | seat->exclusive_client : NULL, | ||
288 | }; | 324 | }; |
325 | container_descendants(con, C_VIEW, | ||
326 | send_frame_done_container_iterator, &data); | ||
327 | } | ||
328 | |||
329 | static void send_frame_done(struct sway_output *output, struct timespec *when) { | ||
330 | if (output_has_opaque_overlay_layer_surface(output)) { | ||
331 | goto send_frame_overlay; | ||
332 | } | ||
289 | 333 | ||
290 | struct sway_container *workspace = output_get_active_workspace(output); | 334 | struct sway_container *workspace = output_get_active_workspace(output); |
291 | if (workspace->current.ws_fullscreen) { | 335 | if (workspace->current.ws_fullscreen) { |
292 | send_frame_done_container_iterator( | 336 | if (workspace->current.ws_fullscreen->type == C_VIEW) { |
293 | workspace->current.ws_fullscreen->swayc, &data); | 337 | output_view_for_each_surface(output, |
294 | 338 | workspace->current.ws_fullscreen->sway_view, | |
295 | if (workspace->current.ws_fullscreen->type == SWAY_VIEW_XWAYLAND) { | 339 | send_frame_done_iterator, when); |
296 | send_frame_done_unmanaged(&data, | 340 | } else { |
297 | &root_container.sway_root->xwayland_unmanaged); | 341 | send_frame_done_container(output, workspace->current.ws_fullscreen, |
342 | when); | ||
298 | } | 343 | } |
344 | #ifdef HAVE_XWAYLAND | ||
345 | send_frame_done_unmanaged(output, | ||
346 | &root_container.sway_root->xwayland_unmanaged, when); | ||
347 | #endif | ||
299 | } else { | 348 | } else { |
300 | send_frame_done_layer(&data, | 349 | send_frame_done_layer(output, |
301 | &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND]); | 350 | &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], when); |
302 | send_frame_done_layer(&data, | 351 | send_frame_done_layer(output, |
303 | &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM]); | 352 | &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM], when); |
304 | 353 | ||
305 | send_frame_done_container(&data, workspace); | 354 | send_frame_done_container(output, workspace, when); |
306 | send_frame_done_container(&data, workspace->sway_workspace->floating); | 355 | send_frame_done_container(output, workspace->sway_workspace->floating, |
307 | 356 | when); | |
308 | send_frame_done_unmanaged(&data, | 357 | |
309 | &root_container.sway_root->xwayland_unmanaged); | 358 | #ifdef HAVE_XWAYLAND |
310 | send_frame_done_layer(&data, | 359 | send_frame_done_unmanaged(output, |
311 | &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]); | 360 | &root_container.sway_root->xwayland_unmanaged, when); |
361 | #endif | ||
362 | send_frame_done_layer(output, | ||
363 | &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP], when); | ||
312 | } | 364 | } |
313 | 365 | ||
314 | send_frame_done_layer(&data, | 366 | send_frame_overlay: |
315 | &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]); | 367 | send_frame_done_layer(output, |
316 | send_frame_done_drag_icons(&data, &root_container.sway_root->drag_icons); | 368 | &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], when); |
369 | send_frame_done_drag_icons(output, &root_container.sway_root->drag_icons, | ||
370 | when); | ||
317 | } | 371 | } |
318 | 372 | ||
319 | static void damage_handle_frame(struct wl_listener *listener, void *data) { | 373 | static void damage_handle_frame(struct wl_listener *listener, void *data) { |
@@ -348,26 +402,13 @@ void output_damage_whole(struct sway_output *output) { | |||
348 | wlr_output_damage_add_whole(output->damage); | 402 | wlr_output_damage_add_whole(output->damage); |
349 | } | 403 | } |
350 | 404 | ||
351 | struct damage_data { | 405 | static void damage_surface_iterator(struct sway_output *output, |
352 | struct root_geometry root_geo; | 406 | struct wlr_surface *surface, struct wlr_box *_box, float rotation, |
353 | struct sway_output *output; | ||
354 | bool whole; | ||
355 | }; | ||
356 | |||
357 | static void damage_surface_iterator(struct wlr_surface *surface, int sx, int sy, | ||
358 | void *_data) { | 407 | void *_data) { |
359 | struct damage_data *data = _data; | 408 | bool *data = _data; |
360 | struct sway_output *output = data->output; | 409 | bool whole = *data; |
361 | float rotation = data->root_geo.rotation; | ||
362 | bool whole = data->whole; | ||
363 | |||
364 | struct wlr_box box; | ||
365 | bool intersects = output_get_surface_box(&data->root_geo, data->output, surface, | ||
366 | sx, sy, &box); | ||
367 | if (!intersects) { | ||
368 | return; | ||
369 | } | ||
370 | 410 | ||
411 | struct wlr_box box = *_box; | ||
371 | scale_box(&box, output->wlr_output->scale); | 412 | scale_box(&box, output->wlr_output->scale); |
372 | 413 | ||
373 | int center_x = box.x + box.width/2; | 414 | int center_x = box.x + box.width/2; |
@@ -407,13 +448,8 @@ static void damage_surface_iterator(struct wlr_surface *surface, int sx, int sy, | |||
407 | 448 | ||
408 | void output_damage_surface(struct sway_output *output, double ox, double oy, | 449 | void output_damage_surface(struct sway_output *output, double ox, double oy, |
409 | struct wlr_surface *surface, bool whole) { | 450 | struct wlr_surface *surface, bool whole) { |
410 | struct damage_data data = { | 451 | output_surface_for_each_surface(output, surface, ox, oy, |
411 | .output = output, | 452 | damage_surface_iterator, &whole); |
412 | .whole = whole, | ||
413 | }; | ||
414 | |||
415 | output_surface_for_each_surface(surface, ox, oy, &data.root_geo, | ||
416 | damage_surface_iterator, &data); | ||
417 | } | 453 | } |
418 | 454 | ||
419 | static void output_damage_view(struct sway_output *output, | 455 | static void output_damage_view(struct sway_output *output, |
@@ -426,13 +462,7 @@ static void output_damage_view(struct sway_output *output, | |||
426 | return; | 462 | return; |
427 | } | 463 | } |
428 | 464 | ||
429 | struct damage_data data = { | 465 | output_view_for_each_surface(output, view, damage_surface_iterator, &whole); |
430 | .output = output, | ||
431 | .whole = whole, | ||
432 | }; | ||
433 | |||
434 | output_view_for_each_surface(view, output, &data.root_geo, | ||
435 | damage_surface_iterator, &data); | ||
436 | } | 466 | } |
437 | 467 | ||
438 | void output_damage_from_view(struct sway_output *output, | 468 | void output_damage_from_view(struct sway_output *output, |
@@ -463,11 +493,12 @@ static void output_damage_whole_container_iterator(struct sway_container *con, | |||
463 | 493 | ||
464 | void output_damage_whole_container(struct sway_output *output, | 494 | void output_damage_whole_container(struct sway_output *output, |
465 | struct sway_container *con) { | 495 | struct sway_container *con) { |
496 | // Pad the box by 1px, because the width is a double and might be a fraction | ||
466 | struct wlr_box box = { | 497 | struct wlr_box box = { |
467 | .x = con->current.swayc_x - output->wlr_output->lx, | 498 | .x = con->current.swayc_x - output->wlr_output->lx - 1, |
468 | .y = con->current.swayc_y - output->wlr_output->ly, | 499 | .y = con->current.swayc_y - output->wlr_output->ly - 1, |
469 | .width = con->current.swayc_width, | 500 | .width = con->current.swayc_width + 2, |
470 | .height = con->current.swayc_height, | 501 | .height = con->current.swayc_height + 2, |
471 | }; | 502 | }; |
472 | scale_box(&box, output->wlr_output->scale); | 503 | scale_box(&box, output->wlr_output->scale); |
473 | wlr_output_damage_add_box(output->damage, &box); | 504 | wlr_output_damage_add_box(output->damage, &box); |
@@ -509,22 +540,14 @@ static void handle_transform(struct wl_listener *listener, void *data) { | |||
509 | transaction_commit_dirty(); | 540 | transaction_commit_dirty(); |
510 | } | 541 | } |
511 | 542 | ||
512 | static void handle_scale_iterator(struct sway_container *view, void *data) { | ||
513 | view_update_marks_textures(view->sway_view); | ||
514 | } | ||
515 | |||
516 | static void handle_scale(struct wl_listener *listener, void *data) { | 543 | static void handle_scale(struct wl_listener *listener, void *data) { |
517 | struct sway_output *output = wl_container_of(listener, output, scale); | 544 | struct sway_output *output = wl_container_of(listener, output, scale); |
518 | arrange_layers(output); | 545 | arrange_layers(output); |
519 | container_descendants(output->swayc, C_VIEW, handle_scale_iterator, NULL); | 546 | container_update_textures_recursive(output->swayc); |
520 | arrange_windows(output->swayc); | 547 | arrange_windows(output->swayc); |
521 | transaction_commit_dirty(); | 548 | transaction_commit_dirty(); |
522 | } | 549 | } |
523 | 550 | ||
524 | struct sway_output *output_from_wlr_output(struct wlr_output *wlr_output) { | ||
525 | return wlr_output->data; | ||
526 | } | ||
527 | |||
528 | void handle_new_output(struct wl_listener *listener, void *data) { | 551 | void handle_new_output(struct wl_listener *listener, void *data) { |
529 | struct sway_server *server = wl_container_of(listener, server, new_output); | 552 | struct sway_server *server = wl_container_of(listener, server, new_output); |
530 | struct wlr_output *wlr_output = data; | 553 | struct wlr_output *wlr_output = data; |