diff options
Diffstat (limited to 'sway/desktop/output.c')
-rw-r--r-- | sway/desktop/output.c | 95 |
1 files changed, 72 insertions, 23 deletions
diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 6c990c47..9e7fbcc6 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c | |||
@@ -4,14 +4,17 @@ | |||
4 | #include <time.h> | 4 | #include <time.h> |
5 | #include <wayland-server.h> | 5 | #include <wayland-server.h> |
6 | #include <wlr/render/wlr_renderer.h> | 6 | #include <wlr/render/wlr_renderer.h> |
7 | #include <wlr/types/wlr_box.h> | ||
7 | #include <wlr/types/wlr_matrix.h> | 8 | #include <wlr/types/wlr_matrix.h> |
8 | #include <wlr/types/wlr_output.h> | 9 | #include <wlr/types/wlr_output.h> |
10 | #include <wlr/types/wlr_output_layout.h> | ||
9 | #include <wlr/types/wlr_surface.h> | 11 | #include <wlr/types/wlr_surface.h> |
10 | #include <wlr/types/wlr_wl_shell.h> | 12 | #include <wlr/types/wlr_wl_shell.h> |
11 | #include "log.h" | 13 | #include "log.h" |
12 | #include "sway/container.h" | 14 | #include "sway/container.h" |
13 | #include "sway/input/input-manager.h" | 15 | #include "sway/input/input-manager.h" |
14 | #include "sway/input/seat.h" | 16 | #include "sway/input/seat.h" |
17 | #include "sway/layers.h" | ||
15 | #include "sway/layout.h" | 18 | #include "sway/layout.h" |
16 | #include "sway/output.h" | 19 | #include "sway/output.h" |
17 | #include "sway/server.h" | 20 | #include "sway/server.h" |
@@ -78,9 +81,7 @@ static void render_surface(struct wlr_surface *surface, | |||
78 | rotate_child_position(&sx, &sy, sw, sh, width, height, rotation); | 81 | rotate_child_position(&sx, &sy, sw, sh, width, height, rotation); |
79 | 82 | ||
80 | render_surface(subsurface->surface, wlr_output, when, | 83 | render_surface(subsurface->surface, wlr_output, when, |
81 | lx + sx, | 84 | lx + sx, ly + sy, rotation); |
82 | ly + sy, | ||
83 | rotation); | ||
84 | } | 85 | } |
85 | } | 86 | } |
86 | 87 | ||
@@ -139,9 +140,15 @@ static void render_wl_shell_surface(struct wlr_wl_shell_surface *surface, | |||
139 | } | 140 | } |
140 | } | 141 | } |
141 | 142 | ||
143 | struct render_data { | ||
144 | struct sway_output *output; | ||
145 | struct timespec *now; | ||
146 | }; | ||
142 | 147 | ||
143 | static void output_frame_view(swayc_t *view, void *data) { | 148 | static void output_frame_view(swayc_t *view, void *data) { |
144 | struct sway_output *output = data; | 149 | struct render_data *rdata = data; |
150 | struct sway_output *output = rdata->output; | ||
151 | struct timespec *now = rdata->now; | ||
145 | struct wlr_output *wlr_output = output->wlr_output; | 152 | struct wlr_output *wlr_output = output->wlr_output; |
146 | struct sway_view *sway_view = view->sway_view; | 153 | struct sway_view *sway_view = view->sway_view; |
147 | struct wlr_surface *surface = sway_view->surface; | 154 | struct wlr_surface *surface = sway_view->surface; |
@@ -154,29 +161,38 @@ static void output_frame_view(swayc_t *view, void *data) { | |||
154 | case SWAY_XDG_SHELL_V6_VIEW: { | 161 | case SWAY_XDG_SHELL_V6_VIEW: { |
155 | int window_offset_x = view->sway_view->wlr_xdg_surface_v6->geometry.x; | 162 | int window_offset_x = view->sway_view->wlr_xdg_surface_v6->geometry.x; |
156 | int window_offset_y = view->sway_view->wlr_xdg_surface_v6->geometry.y; | 163 | int window_offset_y = view->sway_view->wlr_xdg_surface_v6->geometry.y; |
157 | render_surface(surface, wlr_output, &output->last_frame, | 164 | render_surface(surface, wlr_output, now, |
158 | view->x - window_offset_x, | 165 | view->x - window_offset_x, view->y - window_offset_y, 0); |
159 | view->y - window_offset_y, | ||
160 | 0); | ||
161 | render_xdg_v6_popups(sway_view->wlr_xdg_surface_v6, wlr_output, | 166 | render_xdg_v6_popups(sway_view->wlr_xdg_surface_v6, wlr_output, |
162 | &output->last_frame, | 167 | now, view->x - window_offset_x, view->y - window_offset_y, 0); |
163 | view->x - window_offset_x, view->y - window_offset_y, | ||
164 | 0); | ||
165 | break; | 168 | break; |
166 | } | 169 | } |
167 | case SWAY_WL_SHELL_VIEW: | 170 | case SWAY_WL_SHELL_VIEW: |
168 | render_wl_shell_surface(sway_view->wlr_wl_shell_surface, wlr_output, | 171 | render_wl_shell_surface(sway_view->wlr_wl_shell_surface, wlr_output, |
169 | &output->last_frame, view->x, view->y, 0, false); | 172 | now, view->x, view->y, 0, false); |
170 | break; | 173 | break; |
171 | case SWAY_XWAYLAND_VIEW: | 174 | case SWAY_XWAYLAND_VIEW: |
172 | render_surface(surface, wlr_output, &output->last_frame, view->x, | 175 | render_surface(surface, wlr_output, now, view->x, view->y, 0); |
173 | view->y, 0); | ||
174 | break; | 176 | break; |
175 | default: | 177 | default: |
176 | break; | 178 | break; |
177 | } | 179 | } |
178 | } | 180 | } |
179 | 181 | ||
182 | static void render_layer(struct sway_output *output, | ||
183 | const struct wlr_box *output_layout_box, | ||
184 | struct timespec *when, | ||
185 | struct wl_list *layer) { | ||
186 | struct sway_layer_surface *sway_layer; | ||
187 | wl_list_for_each(sway_layer, layer, link) { | ||
188 | struct wlr_layer_surface *layer = sway_layer->layer_surface; | ||
189 | render_surface(layer->surface, output->wlr_output, when, | ||
190 | sway_layer->geo.x + output_layout_box->x, | ||
191 | sway_layer->geo.y + output_layout_box->y, 0); | ||
192 | wlr_surface_send_frame_done(layer->surface, when); | ||
193 | } | ||
194 | } | ||
195 | |||
180 | static void output_frame_notify(struct wl_listener *listener, void *data) { | 196 | static void output_frame_notify(struct wl_listener *listener, void *data) { |
181 | struct sway_output *soutput = wl_container_of(listener, soutput, frame); | 197 | struct sway_output *soutput = wl_container_of(listener, soutput, frame); |
182 | struct wlr_output *wlr_output = data; | 198 | struct wlr_output *wlr_output = data; |
@@ -189,13 +205,29 @@ static void output_frame_notify(struct wl_listener *listener, void *data) { | |||
189 | wlr_output_make_current(wlr_output, &buffer_age); | 205 | wlr_output_make_current(wlr_output, &buffer_age); |
190 | wlr_renderer_begin(server->renderer, wlr_output->width, wlr_output->height); | 206 | wlr_renderer_begin(server->renderer, wlr_output->width, wlr_output->height); |
191 | 207 | ||
208 | struct timespec now; | ||
209 | clock_gettime(CLOCK_MONOTONIC, &now); | ||
210 | |||
211 | struct wlr_output_layout *layout = root_container.sway_root->output_layout; | ||
212 | const struct wlr_box *output_box = wlr_output_layout_get_box( | ||
213 | layout, wlr_output); | ||
214 | |||
215 | render_layer(soutput, output_box, &now, | ||
216 | &soutput->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND]); | ||
217 | render_layer(soutput, output_box, &now, | ||
218 | &soutput->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM]); | ||
219 | |||
192 | struct sway_seat *seat = input_manager_current_seat(input_manager); | 220 | struct sway_seat *seat = input_manager_current_seat(input_manager); |
193 | swayc_t *focus = sway_seat_get_focus_inactive(seat, soutput->swayc); | 221 | swayc_t *focus = sway_seat_get_focus_inactive(seat, soutput->swayc); |
194 | swayc_t *workspace = (focus->type == C_WORKSPACE ? | 222 | swayc_t *workspace = (focus->type == C_WORKSPACE ? |
195 | focus : | 223 | focus : |
196 | swayc_parent_by_type(focus, C_WORKSPACE)); | 224 | swayc_parent_by_type(focus, C_WORKSPACE)); |
197 | 225 | ||
198 | swayc_descendants_of_type(workspace, C_VIEW, output_frame_view, soutput); | 226 | struct render_data rdata = { |
227 | .output = soutput, | ||
228 | .now = &now, | ||
229 | }; | ||
230 | swayc_descendants_of_type(workspace, C_VIEW, output_frame_view, &rdata); | ||
199 | 231 | ||
200 | // render unmanaged views on top | 232 | // render unmanaged views on top |
201 | struct sway_view *view; | 233 | struct sway_view *view; |
@@ -210,22 +242,31 @@ static void output_frame_notify(struct wl_listener *listener, void *data) { | |||
210 | } | 242 | } |
211 | } | 243 | } |
212 | 244 | ||
213 | wlr_renderer_end(server->renderer); | 245 | // TODO: Consider revising this when fullscreen windows are supported |
214 | wlr_output_swap_buffers(wlr_output, &soutput->last_frame, NULL); | 246 | render_layer(soutput, output_box, &now, |
247 | &soutput->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]); | ||
248 | render_layer(soutput, output_box, &now, | ||
249 | &soutput->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]); | ||
215 | 250 | ||
216 | struct timespec now; | 251 | wlr_renderer_end(server->renderer); |
217 | clock_gettime(CLOCK_MONOTONIC, &now); | 252 | wlr_output_swap_buffers(wlr_output, &now, NULL); |
218 | soutput->last_frame = now; | 253 | soutput->last_frame = now; |
219 | } | 254 | } |
220 | 255 | ||
221 | static void handle_output_destroy(struct wl_listener *listener, void *data) { | 256 | static void handle_output_destroy(struct wl_listener *listener, void *data) { |
222 | struct sway_output *output = wl_container_of(listener, output, output_destroy); | 257 | struct sway_output *output = wl_container_of(listener, output, destroy); |
223 | struct wlr_output *wlr_output = data; | 258 | struct wlr_output *wlr_output = data; |
224 | wlr_log(L_DEBUG, "Output %p %s removed", wlr_output, wlr_output->name); | 259 | wlr_log(L_DEBUG, "Output %p %s removed", wlr_output, wlr_output->name); |
225 | 260 | ||
226 | destroy_output(output->swayc); | 261 | destroy_output(output->swayc); |
227 | } | 262 | } |
228 | 263 | ||
264 | static void handle_output_mode(struct wl_listener *listener, void *data) { | ||
265 | struct sway_output *output = wl_container_of(listener, output, mode); | ||
266 | arrange_layers(output); | ||
267 | arrange_windows(output->swayc, -1, -1); | ||
268 | } | ||
269 | |||
229 | void handle_new_output(struct wl_listener *listener, void *data) { | 270 | void handle_new_output(struct wl_listener *listener, void *data) { |
230 | struct sway_server *server = wl_container_of(listener, server, new_output); | 271 | struct sway_server *server = wl_container_of(listener, server, new_output); |
231 | struct wlr_output *wlr_output = data; | 272 | struct wlr_output *wlr_output = data; |
@@ -236,6 +277,7 @@ void handle_new_output(struct wl_listener *listener, void *data) { | |||
236 | return; | 277 | return; |
237 | } | 278 | } |
238 | output->wlr_output = wlr_output; | 279 | output->wlr_output = wlr_output; |
280 | wlr_output->data = output; | ||
239 | output->server = server; | 281 | output->server = server; |
240 | 282 | ||
241 | if (!wl_list_empty(&wlr_output->modes)) { | 283 | if (!wl_list_empty(&wlr_output->modes)) { |
@@ -250,13 +292,20 @@ void handle_new_output(struct wl_listener *listener, void *data) { | |||
250 | return; | 292 | return; |
251 | } | 293 | } |
252 | 294 | ||
295 | size_t len = sizeof(output->layers) / sizeof(output->layers[0]); | ||
296 | for (size_t i = 0; i < len; ++i) { | ||
297 | wl_list_init(&output->layers[i]); | ||
298 | } | ||
299 | |||
253 | sway_input_manager_configure_xcursor(input_manager); | 300 | sway_input_manager_configure_xcursor(input_manager); |
254 | 301 | ||
255 | wl_signal_add(&wlr_output->events.frame, &output->frame); | 302 | wl_signal_add(&wlr_output->events.frame, &output->frame); |
256 | output->frame.notify = output_frame_notify; | 303 | output->frame.notify = output_frame_notify; |
304 | wl_signal_add(&wlr_output->events.destroy, &output->destroy); | ||
305 | output->destroy.notify = handle_output_destroy; | ||
306 | wl_signal_add(&wlr_output->events.mode, &output->mode); | ||
307 | output->mode.notify = handle_output_mode; | ||
257 | 308 | ||
258 | wl_signal_add(&wlr_output->events.destroy, &output->output_destroy); | 309 | arrange_layers(output); |
259 | output->output_destroy.notify = handle_output_destroy; | ||
260 | |||
261 | arrange_windows(&root_container, -1, -1); | 310 | arrange_windows(&root_container, -1, -1); |
262 | } | 311 | } |