diff options
Diffstat (limited to 'sway/desktop/output.c')
-rw-r--r-- | sway/desktop/output.c | 182 |
1 files changed, 72 insertions, 110 deletions
diff --git a/sway/desktop/output.c b/sway/desktop/output.c index c30e52a1..c182bad6 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c | |||
@@ -28,10 +28,10 @@ | |||
28 | #include "sway/tree/view.h" | 28 | #include "sway/tree/view.h" |
29 | #include "sway/tree/workspace.h" | 29 | #include "sway/tree/workspace.h" |
30 | 30 | ||
31 | struct sway_container *output_by_name(const char *name) { | 31 | struct sway_output *output_by_name(const char *name) { |
32 | for (int i = 0; i < root_container.children->length; ++i) { | 32 | for (int i = 0; i < root->outputs->length; ++i) { |
33 | struct sway_container *output = root_container.children->items[i]; | 33 | struct sway_output *output = root->outputs->items[i]; |
34 | if (strcasecmp(output->name, name) == 0) { | 34 | if (strcasecmp(output->wlr_output->name, name) == 0) { |
35 | return output; | 35 | return output; |
36 | } | 36 | } |
37 | } | 37 | } |
@@ -98,8 +98,8 @@ static bool get_surface_box(struct surface_iterator_data *data, | |||
98 | wlr_box_rotated_bounds(&box, data->rotation, &rotated_box); | 98 | wlr_box_rotated_bounds(&box, data->rotation, &rotated_box); |
99 | 99 | ||
100 | struct wlr_box output_box = { | 100 | struct wlr_box output_box = { |
101 | .width = output->swayc->current.swayc_width, | 101 | .width = output->wlr_output->width, |
102 | .height = output->swayc->current.swayc_height, | 102 | .height = output->wlr_output->height, |
103 | }; | 103 | }; |
104 | 104 | ||
105 | struct wlr_box intersection; | 105 | struct wlr_box intersection; |
@@ -145,12 +145,12 @@ void output_view_for_each_surface(struct sway_output *output, | |||
145 | .user_iterator = iterator, | 145 | .user_iterator = iterator, |
146 | .user_data = user_data, | 146 | .user_data = user_data, |
147 | .output = output, | 147 | .output = output, |
148 | .ox = view->swayc->current.view_x - output->swayc->current.swayc_x | 148 | .ox = view->container->current.view_x - output->wlr_output->lx |
149 | - view->geometry.x, | 149 | - view->geometry.x, |
150 | .oy = view->swayc->current.view_y - output->swayc->current.swayc_y | 150 | .oy = view->container->current.view_y - output->wlr_output->ly |
151 | - view->geometry.y, | 151 | - view->geometry.y, |
152 | .width = view->swayc->current.view_width, | 152 | .width = view->container->current.view_width, |
153 | .height = view->swayc->current.view_height, | 153 | .height = view->container->current.view_height, |
154 | .rotation = 0, // TODO | 154 | .rotation = 0, // TODO |
155 | }; | 155 | }; |
156 | 156 | ||
@@ -164,12 +164,12 @@ void output_view_for_each_popup(struct sway_output *output, | |||
164 | .user_iterator = iterator, | 164 | .user_iterator = iterator, |
165 | .user_data = user_data, | 165 | .user_data = user_data, |
166 | .output = output, | 166 | .output = output, |
167 | .ox = view->swayc->current.view_x - output->swayc->current.swayc_x | 167 | .ox = view->container->current.view_x - output->wlr_output->lx |
168 | - view->geometry.x, | 168 | - view->geometry.x, |
169 | .oy = view->swayc->current.view_y - output->swayc->current.swayc_y | 169 | .oy = view->container->current.view_y - output->wlr_output->ly |
170 | - view->geometry.y, | 170 | - view->geometry.y, |
171 | .width = view->swayc->current.view_width, | 171 | .width = view->container->current.view_width, |
172 | .height = view->swayc->current.view_height, | 172 | .height = view->container->current.view_height, |
173 | .rotation = 0, // TODO | 173 | .rotation = 0, // TODO |
174 | }; | 174 | }; |
175 | 175 | ||
@@ -197,8 +197,8 @@ void output_unmanaged_for_each_surface(struct sway_output *output, | |||
197 | wl_list_for_each(unmanaged_surface, unmanaged, link) { | 197 | wl_list_for_each(unmanaged_surface, unmanaged, link) { |
198 | struct wlr_xwayland_surface *xsurface = | 198 | struct wlr_xwayland_surface *xsurface = |
199 | unmanaged_surface->wlr_xwayland_surface; | 199 | unmanaged_surface->wlr_xwayland_surface; |
200 | double ox = unmanaged_surface->lx - output->swayc->current.swayc_x; | 200 | double ox = unmanaged_surface->lx - output->wlr_output->lx; |
201 | double oy = unmanaged_surface->ly - output->swayc->current.swayc_y; | 201 | double oy = unmanaged_surface->ly - output->wlr_output->ly; |
202 | 202 | ||
203 | output_surface_for_each_surface(output, xsurface->surface, ox, oy, | 203 | output_surface_for_each_surface(output, xsurface->surface, ox, oy, |
204 | iterator, user_data); | 204 | iterator, user_data); |
@@ -211,8 +211,8 @@ void output_drag_icons_for_each_surface(struct sway_output *output, | |||
211 | void *user_data) { | 211 | void *user_data) { |
212 | struct sway_drag_icon *drag_icon; | 212 | struct sway_drag_icon *drag_icon; |
213 | wl_list_for_each(drag_icon, drag_icons, link) { | 213 | wl_list_for_each(drag_icon, drag_icons, link) { |
214 | double ox = drag_icon->x - output->swayc->x; | 214 | double ox = drag_icon->x - output->wlr_output->lx; |
215 | double oy = drag_icon->y - output->swayc->y; | 215 | double oy = drag_icon->y - output->wlr_output->ly; |
216 | 216 | ||
217 | if (drag_icon->wlr_drag_icon->mapped) { | 217 | if (drag_icon->wlr_drag_icon->mapped) { |
218 | output_surface_for_each_surface(output, | 218 | output_surface_for_each_surface(output, |
@@ -229,19 +229,13 @@ static void scale_box(struct wlr_box *box, float scale) { | |||
229 | box->height *= scale; | 229 | box->height *= scale; |
230 | } | 230 | } |
231 | 231 | ||
232 | struct sway_container *output_get_active_workspace(struct sway_output *output) { | 232 | struct sway_workspace *output_get_active_workspace(struct sway_output *output) { |
233 | struct sway_seat *seat = input_manager_current_seat(input_manager); | 233 | struct sway_seat *seat = input_manager_current_seat(input_manager); |
234 | struct sway_container *focus = | 234 | struct sway_node *focus = seat_get_active_child(seat, &output->node); |
235 | seat_get_focus_inactive(seat, output->swayc); | ||
236 | if (!focus) { | 235 | if (!focus) { |
237 | // We've never been to this output before | 236 | return output->workspaces->items[0]; |
238 | focus = output->swayc->current.children->items[0]; | ||
239 | } | 237 | } |
240 | struct sway_container *workspace = focus; | 238 | return focus->sway_workspace; |
241 | if (workspace->type != C_WORKSPACE) { | ||
242 | workspace = container_parent(workspace, C_WORKSPACE); | ||
243 | } | ||
244 | return workspace; | ||
245 | } | 239 | } |
246 | 240 | ||
247 | bool output_has_opaque_overlay_layer_surface(struct sway_output *output) { | 241 | bool output_has_opaque_overlay_layer_surface(struct sway_output *output) { |
@@ -255,8 +249,8 @@ bool output_has_opaque_overlay_layer_surface(struct sway_output *output) { | |||
255 | struct sway_layer_surface *sway_layer_surface = | 249 | struct sway_layer_surface *sway_layer_surface = |
256 | layer_from_wlr_layer_surface(wlr_layer_surface); | 250 | layer_from_wlr_layer_surface(wlr_layer_surface); |
257 | pixman_box32_t output_box = { | 251 | pixman_box32_t output_box = { |
258 | .x2 = output->swayc->current.swayc_width, | 252 | .x2 = output->wlr_output->width, |
259 | .y2 = output->swayc->current.swayc_height, | 253 | .y2 = output->wlr_output->height, |
260 | }; | 254 | }; |
261 | pixman_region32_t surface_opaque_box; | 255 | pixman_region32_t surface_opaque_box; |
262 | pixman_region32_init(&surface_opaque_box); | 256 | pixman_region32_init(&surface_opaque_box); |
@@ -307,15 +301,15 @@ struct send_frame_done_data { | |||
307 | 301 | ||
308 | static void send_frame_done_container_iterator(struct sway_container *con, | 302 | static void send_frame_done_container_iterator(struct sway_container *con, |
309 | void *_data) { | 303 | void *_data) { |
310 | if (con->type != C_VIEW) { | 304 | if (!con->view) { |
311 | return; | 305 | return; |
312 | } | 306 | } |
313 | if (!view_is_visible(con->sway_view)) { | 307 | if (!view_is_visible(con->view)) { |
314 | return; | 308 | return; |
315 | } | 309 | } |
316 | 310 | ||
317 | struct send_frame_done_data *data = _data; | 311 | struct send_frame_done_data *data = _data; |
318 | output_view_for_each_surface(data->output, con->sway_view, | 312 | output_view_for_each_surface(data->output, con->view, |
319 | send_frame_done_iterator, data->when); | 313 | send_frame_done_iterator, data->when); |
320 | } | 314 | } |
321 | 315 | ||
@@ -328,15 +322,14 @@ static void send_frame_done(struct sway_output *output, struct timespec *when) { | |||
328 | .output = output, | 322 | .output = output, |
329 | .when = when, | 323 | .when = when, |
330 | }; | 324 | }; |
331 | struct sway_container *workspace = output_get_active_workspace(output); | 325 | struct sway_workspace *workspace = output_get_active_workspace(output); |
332 | if (workspace->current.ws_fullscreen) { | 326 | if (workspace->current.fullscreen) { |
333 | send_frame_done_container_iterator( | 327 | send_frame_done_container_iterator( |
334 | workspace->current.ws_fullscreen, &data); | 328 | workspace->current.fullscreen, &data); |
335 | container_for_each_child(workspace->current.ws_fullscreen, | 329 | container_for_each_child(workspace->current.fullscreen, |
336 | send_frame_done_container_iterator, &data); | 330 | send_frame_done_container_iterator, &data); |
337 | #ifdef HAVE_XWAYLAND | 331 | #ifdef HAVE_XWAYLAND |
338 | send_frame_done_unmanaged(output, | 332 | send_frame_done_unmanaged(output, &root->xwayland_unmanaged, when); |
339 | &root_container.sway_root->xwayland_unmanaged, when); | ||
340 | #endif | 333 | #endif |
341 | } else { | 334 | } else { |
342 | send_frame_done_layer(output, | 335 | send_frame_done_layer(output, |
@@ -348,8 +341,7 @@ static void send_frame_done(struct sway_output *output, struct timespec *when) { | |||
348 | send_frame_done_container_iterator, &data); | 341 | send_frame_done_container_iterator, &data); |
349 | 342 | ||
350 | #ifdef HAVE_XWAYLAND | 343 | #ifdef HAVE_XWAYLAND |
351 | send_frame_done_unmanaged(output, | 344 | send_frame_done_unmanaged(output, &root->xwayland_unmanaged, when); |
352 | &root_container.sway_root->xwayland_unmanaged, when); | ||
353 | #endif | 345 | #endif |
354 | send_frame_done_layer(output, | 346 | send_frame_done_layer(output, |
355 | &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP], when); | 347 | &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP], when); |
@@ -358,8 +350,7 @@ static void send_frame_done(struct sway_output *output, struct timespec *when) { | |||
358 | send_frame_overlay: | 350 | send_frame_overlay: |
359 | send_frame_done_layer(output, | 351 | send_frame_done_layer(output, |
360 | &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], when); | 352 | &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], when); |
361 | send_frame_done_drag_icons(output, &root_container.sway_root->drag_icons, | 353 | send_frame_done_drag_icons(output, &root->drag_icons, when); |
362 | when); | ||
363 | } | 354 | } |
364 | 355 | ||
365 | static void damage_handle_frame(struct wl_listener *listener, void *data) { | 356 | static void damage_handle_frame(struct wl_listener *listener, void *data) { |
@@ -391,7 +382,11 @@ static void damage_handle_frame(struct wl_listener *listener, void *data) { | |||
391 | } | 382 | } |
392 | 383 | ||
393 | void output_damage_whole(struct sway_output *output) { | 384 | void output_damage_whole(struct sway_output *output) { |
394 | wlr_output_damage_add_whole(output->damage); | 385 | // The output can exist with no wlr_output if it's just been disconnected |
386 | // and the transaction to evacuate it has't completed yet. | ||
387 | if (output && output->wlr_output) { | ||
388 | wlr_output_damage_add_whole(output->damage); | ||
389 | } | ||
395 | } | 390 | } |
396 | 391 | ||
397 | static void damage_surface_iterator(struct sway_output *output, | 392 | static void damage_surface_iterator(struct sway_output *output, |
@@ -446,14 +441,9 @@ void output_damage_surface(struct sway_output *output, double ox, double oy, | |||
446 | 441 | ||
447 | static void output_damage_view(struct sway_output *output, | 442 | static void output_damage_view(struct sway_output *output, |
448 | struct sway_view *view, bool whole) { | 443 | struct sway_view *view, bool whole) { |
449 | if (!sway_assert(view->swayc != NULL, "expected a view in the tree")) { | ||
450 | return; | ||
451 | } | ||
452 | |||
453 | if (!view_is_visible(view)) { | 444 | if (!view_is_visible(view)) { |
454 | return; | 445 | return; |
455 | } | 446 | } |
456 | |||
457 | output_view_for_each_surface(output, view, damage_surface_iterator, &whole); | 447 | output_view_for_each_surface(output, view, damage_surface_iterator, &whole); |
458 | } | 448 | } |
459 | 449 | ||
@@ -466,31 +456,29 @@ void output_damage_from_view(struct sway_output *output, | |||
466 | void output_damage_box(struct sway_output *output, struct wlr_box *_box) { | 456 | void output_damage_box(struct sway_output *output, struct wlr_box *_box) { |
467 | struct wlr_box box; | 457 | struct wlr_box box; |
468 | memcpy(&box, _box, sizeof(struct wlr_box)); | 458 | memcpy(&box, _box, sizeof(struct wlr_box)); |
469 | box.x -= output->swayc->current.swayc_x; | 459 | box.x -= output->wlr_output->lx; |
470 | box.y -= output->swayc->current.swayc_y; | 460 | box.y -= output->wlr_output->ly; |
471 | scale_box(&box, output->wlr_output->scale); | 461 | scale_box(&box, output->wlr_output->scale); |
472 | wlr_output_damage_add_box(output->damage, &box); | 462 | wlr_output_damage_add_box(output->damage, &box); |
473 | } | 463 | } |
474 | 464 | ||
475 | static void output_damage_whole_container_iterator(struct sway_container *con, | 465 | static void output_damage_whole_container_iterator(struct sway_container *con, |
476 | void *data) { | 466 | void *data) { |
477 | struct sway_output *output = data; | 467 | if (!sway_assert(con->view, "expected a view")) { |
478 | |||
479 | if (!sway_assert(con->type == C_VIEW, "expected a view")) { | ||
480 | return; | 468 | return; |
481 | } | 469 | } |
482 | 470 | struct sway_output *output = data; | |
483 | output_damage_view(output, con->sway_view, true); | 471 | output_damage_view(output, con->view, true); |
484 | } | 472 | } |
485 | 473 | ||
486 | void output_damage_whole_container(struct sway_output *output, | 474 | void output_damage_whole_container(struct sway_output *output, |
487 | struct sway_container *con) { | 475 | struct sway_container *con) { |
488 | // Pad the box by 1px, because the width is a double and might be a fraction | 476 | // Pad the box by 1px, because the width is a double and might be a fraction |
489 | struct wlr_box box = { | 477 | struct wlr_box box = { |
490 | .x = con->current.swayc_x - output->wlr_output->lx - 1, | 478 | .x = con->current.con_x - output->wlr_output->lx - 1, |
491 | .y = con->current.swayc_y - output->wlr_output->ly - 1, | 479 | .y = con->current.con_y - output->wlr_output->ly - 1, |
492 | .width = con->current.swayc_width + 2, | 480 | .width = con->current.con_width + 2, |
493 | .height = con->current.swayc_height + 2, | 481 | .height = con->current.con_height + 2, |
494 | }; | 482 | }; |
495 | scale_box(&box, output->wlr_output->scale); | 483 | scale_box(&box, output->wlr_output->scale); |
496 | wlr_output_damage_add_box(output->damage, &box); | 484 | wlr_output_damage_add_box(output->damage, &box); |
@@ -499,44 +487,48 @@ void output_damage_whole_container(struct sway_output *output, | |||
499 | static void damage_handle_destroy(struct wl_listener *listener, void *data) { | 487 | static void damage_handle_destroy(struct wl_listener *listener, void *data) { |
500 | struct sway_output *output = | 488 | struct sway_output *output = |
501 | wl_container_of(listener, output, damage_destroy); | 489 | wl_container_of(listener, output, damage_destroy); |
502 | output_begin_destroy(output->swayc); | 490 | output_disable(output); |
491 | transaction_commit_dirty(); | ||
503 | } | 492 | } |
504 | 493 | ||
505 | static void handle_destroy(struct wl_listener *listener, void *data) { | 494 | static void handle_destroy(struct wl_listener *listener, void *data) { |
506 | struct sway_output *output = wl_container_of(listener, output, destroy); | 495 | struct sway_output *output = wl_container_of(listener, output, destroy); |
507 | wl_signal_emit(&output->events.destroy, output); | 496 | wl_signal_emit(&output->events.destroy, output); |
508 | 497 | ||
509 | if (output->swayc) { | 498 | if (output->enabled) { |
510 | output_begin_destroy(output->swayc); | 499 | output_disable(output); |
511 | } | 500 | } |
501 | output_begin_destroy(output); | ||
512 | 502 | ||
513 | wl_list_remove(&output->link); | 503 | transaction_commit_dirty(); |
514 | wl_list_remove(&output->destroy.link); | ||
515 | output->wlr_output->data = NULL; | ||
516 | free(output); | ||
517 | |||
518 | arrange_windows(&root_container); | ||
519 | } | 504 | } |
520 | 505 | ||
521 | static void handle_mode(struct wl_listener *listener, void *data) { | 506 | static void handle_mode(struct wl_listener *listener, void *data) { |
522 | struct sway_output *output = wl_container_of(listener, output, mode); | 507 | struct sway_output *output = wl_container_of(listener, output, mode); |
523 | arrange_layers(output); | 508 | arrange_layers(output); |
524 | arrange_windows(output->swayc); | 509 | arrange_output(output); |
525 | transaction_commit_dirty(); | 510 | transaction_commit_dirty(); |
526 | } | 511 | } |
527 | 512 | ||
528 | static void handle_transform(struct wl_listener *listener, void *data) { | 513 | static void handle_transform(struct wl_listener *listener, void *data) { |
529 | struct sway_output *output = wl_container_of(listener, output, transform); | 514 | struct sway_output *output = wl_container_of(listener, output, transform); |
530 | arrange_layers(output); | 515 | arrange_layers(output); |
531 | arrange_windows(output->swayc); | 516 | arrange_output(output); |
532 | transaction_commit_dirty(); | 517 | transaction_commit_dirty(); |
533 | } | 518 | } |
534 | 519 | ||
520 | static void update_textures(struct sway_container *con, void *data) { | ||
521 | container_update_title_textures(con); | ||
522 | if (con->view) { | ||
523 | view_update_marks_textures(con->view); | ||
524 | } | ||
525 | } | ||
526 | |||
535 | static void handle_scale(struct wl_listener *listener, void *data) { | 527 | static void handle_scale(struct wl_listener *listener, void *data) { |
536 | struct sway_output *output = wl_container_of(listener, output, scale); | 528 | struct sway_output *output = wl_container_of(listener, output, scale); |
537 | arrange_layers(output); | 529 | arrange_layers(output); |
538 | container_update_textures_recursive(output->swayc); | 530 | output_for_each_container(output, update_textures, NULL); |
539 | arrange_windows(output->swayc); | 531 | arrange_output(output); |
540 | transaction_commit_dirty(); | 532 | transaction_commit_dirty(); |
541 | } | 533 | } |
542 | 534 | ||
@@ -545,57 +537,27 @@ void handle_new_output(struct wl_listener *listener, void *data) { | |||
545 | struct wlr_output *wlr_output = data; | 537 | struct wlr_output *wlr_output = data; |
546 | wlr_log(WLR_DEBUG, "New output %p: %s", wlr_output, wlr_output->name); | 538 | wlr_log(WLR_DEBUG, "New output %p: %s", wlr_output, wlr_output->name); |
547 | 539 | ||
548 | struct sway_output *output = calloc(1, sizeof(struct sway_output)); | 540 | struct sway_output *output = output_create(wlr_output); |
549 | if (!output) { | 541 | if (!output) { |
550 | return; | 542 | return; |
551 | } | 543 | } |
552 | output->wlr_output = wlr_output; | ||
553 | wlr_output->data = output; | ||
554 | output->server = server; | 544 | output->server = server; |
555 | output->damage = wlr_output_damage_create(wlr_output); | 545 | output->damage = wlr_output_damage_create(wlr_output); |
556 | |||
557 | wl_signal_add(&wlr_output->events.destroy, &output->destroy); | ||
558 | output->destroy.notify = handle_destroy; | 546 | output->destroy.notify = handle_destroy; |
559 | 547 | ||
560 | wl_list_insert(&root_container.sway_root->all_outputs, &output->link); | 548 | struct output_config *oc = output_find_config(output); |
561 | |||
562 | output_enable(output); | ||
563 | } | ||
564 | |||
565 | void output_enable(struct sway_output *output) { | ||
566 | struct wlr_output *wlr_output = output->wlr_output; | ||
567 | |||
568 | if (!sway_assert(output->swayc == NULL, "output is already enabled")) { | ||
569 | return; | ||
570 | } | ||
571 | |||
572 | output->swayc = output_create(output); | ||
573 | if (!output->swayc) { | ||
574 | // Output is disabled | ||
575 | return; | ||
576 | } | ||
577 | 549 | ||
578 | size_t len = sizeof(output->layers) / sizeof(output->layers[0]); | 550 | if (oc && oc->enabled) { |
579 | for (size_t i = 0; i < len; ++i) { | 551 | output_enable(output, oc); |
580 | wl_list_init(&output->layers[i]); | ||
581 | } | 552 | } |
582 | wl_signal_init(&output->events.destroy); | ||
583 | 553 | ||
584 | input_manager_configure_xcursor(input_manager); | 554 | transaction_commit_dirty(); |
555 | } | ||
585 | 556 | ||
586 | wl_signal_add(&wlr_output->events.mode, &output->mode); | 557 | void output_add_listeners(struct sway_output *output) { |
587 | output->mode.notify = handle_mode; | 558 | output->mode.notify = handle_mode; |
588 | wl_signal_add(&wlr_output->events.transform, &output->transform); | ||
589 | output->transform.notify = handle_transform; | 559 | output->transform.notify = handle_transform; |
590 | wl_signal_add(&wlr_output->events.scale, &output->scale); | ||
591 | output->scale.notify = handle_scale; | 560 | output->scale.notify = handle_scale; |
592 | |||
593 | wl_signal_add(&output->damage->events.frame, &output->damage_frame); | ||
594 | output->damage_frame.notify = damage_handle_frame; | 561 | output->damage_frame.notify = damage_handle_frame; |
595 | wl_signal_add(&output->damage->events.destroy, &output->damage_destroy); | ||
596 | output->damage_destroy.notify = damage_handle_destroy; | 562 | output->damage_destroy.notify = damage_handle_destroy; |
597 | |||
598 | arrange_layers(output); | ||
599 | arrange_windows(&root_container); | ||
600 | transaction_commit_dirty(); | ||
601 | } | 563 | } |