aboutsummaryrefslogtreecommitdiffstats
path: root/sway/desktop/output.c
diff options
context:
space:
mode:
Diffstat (limited to 'sway/desktop/output.c')
-rw-r--r--sway/desktop/output.c95
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
143struct render_data {
144 struct sway_output *output;
145 struct timespec *now;
146};
142 147
143static void output_frame_view(swayc_t *view, void *data) { 148static 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
182static 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
180static void output_frame_notify(struct wl_listener *listener, void *data) { 196static 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
221static void handle_output_destroy(struct wl_listener *listener, void *data) { 256static 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
264static 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
229void handle_new_output(struct wl_listener *listener, void *data) { 270void 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}