aboutsummaryrefslogtreecommitdiffstats
path: root/sway/tree/view.c
diff options
context:
space:
mode:
Diffstat (limited to 'sway/tree/view.c')
-rw-r--r--sway/tree/view.c275
1 files changed, 123 insertions, 152 deletions
diff --git a/sway/tree/view.c b/sway/tree/view.c
index 6bd0ef67..f63a35b5 100644
--- a/sway/tree/view.c
+++ b/sway/tree/view.c
@@ -33,6 +33,8 @@ void view_init(struct sway_view *view, enum sway_view_type type,
33 view->marks = create_list(); 33 view->marks = create_list();
34 view->allow_request_urgent = true; 34 view->allow_request_urgent = true;
35 wl_signal_init(&view->events.unmap); 35 wl_signal_init(&view->events.unmap);
36
37 view->container = container_create(view);
36} 38}
37 39
38void view_destroy(struct sway_view *view) { 40void view_destroy(struct sway_view *view) {
@@ -43,8 +45,8 @@ void view_destroy(struct sway_view *view) {
43 "Tried to free view which wasn't marked as destroying")) { 45 "Tried to free view which wasn't marked as destroying")) {
44 return; 46 return;
45 } 47 }
46 if (!sway_assert(view->swayc == NULL, 48 if (!sway_assert(view->container == NULL,
47 "Tried to free view which still has a swayc " 49 "Tried to free view which still has a container "
48 "(might have a pending transaction?)")) { 50 "(might have a pending transaction?)")) {
49 return; 51 return;
50 } 52 }
@@ -57,6 +59,7 @@ void view_destroy(struct sway_view *view) {
57 wlr_texture_destroy(view->marks_focused_inactive); 59 wlr_texture_destroy(view->marks_focused_inactive);
58 wlr_texture_destroy(view->marks_unfocused); 60 wlr_texture_destroy(view->marks_unfocused);
59 wlr_texture_destroy(view->marks_urgent); 61 wlr_texture_destroy(view->marks_urgent);
62 free(view->title_format);
60 63
61 if (view->impl->destroy) { 64 if (view->impl->destroy) {
62 view->impl->destroy(view); 65 view->impl->destroy(view);
@@ -65,23 +68,13 @@ void view_destroy(struct sway_view *view) {
65 } 68 }
66} 69}
67 70
68/**
69 * The view may or may not be involved in a transaction. For example, a view may
70 * unmap then attempt to destroy itself before we've applied the new layout. If
71 * an unmapping view is still involved in a transaction then it'll still have a
72 * swayc.
73 *
74 * If there's no transaction we can simply free the view. Otherwise the
75 * destroying flag will make the view get freed when the transaction is
76 * finished.
77 */
78void view_begin_destroy(struct sway_view *view) { 71void view_begin_destroy(struct sway_view *view) {
79 if (!sway_assert(view->surface == NULL, "Tried to destroy a mapped view")) { 72 if (!sway_assert(view->surface == NULL, "Tried to destroy a mapped view")) {
80 return; 73 return;
81 } 74 }
82 view->destroying = true; 75 view->destroying = true;
83 76
84 if (!view->swayc) { 77 if (!view->container) {
85 view_destroy(view); 78 view_destroy(view);
86 } 79 }
87} 80}
@@ -171,30 +164,31 @@ uint32_t view_configure(struct sway_view *view, double lx, double ly, int width,
171} 164}
172 165
173void view_autoconfigure(struct sway_view *view) { 166void view_autoconfigure(struct sway_view *view) {
174 if (!sway_assert(view->swayc, 167 if (!view->container->workspace) {
175 "Called view_autoconfigure() on a view without a swayc")) { 168 // Hidden in the scratchpad
176 return; 169 return;
177 } 170 }
171 struct sway_output *output = view->container->workspace->output;
178 172
179 struct sway_container *output = container_parent(view->swayc, C_OUTPUT); 173 if (view->container->is_fullscreen) {
180 174 view->x = output->lx;
181 if (view->swayc->is_fullscreen) { 175 view->y = output->ly;
182 view->x = output->x;
183 view->y = output->y;
184 view->width = output->width; 176 view->width = output->width;
185 view->height = output->height; 177 view->height = output->height;
186 return; 178 return;
187 } 179 }
188 180
189 struct sway_container *ws = container_parent(view->swayc, C_WORKSPACE); 181 struct sway_workspace *ws = view->container->workspace;
190 182
191 int other_views = 0; 183 bool other_views = false;
192 if (config->hide_edge_borders == E_SMART) { 184 if (config->hide_edge_borders == E_SMART) {
193 struct sway_container *con = view->swayc; 185 struct sway_container *con = view->container;
194 while (con != output) { 186 while (con) {
195 if (con->layout != L_TABBED && con->layout != L_STACKED) { 187 enum sway_container_layout layout = container_parent_layout(con);
196 other_views += con->children ? con->children->length - 1 : 0; 188 if (layout != L_TABBED && layout != L_STACKED) {
197 if (other_views > 0) { 189 list_t *siblings = container_get_siblings(con);
190 if (siblings && siblings->length > 1) {
191 other_views = true;
198 break; 192 break;
199 } 193 }
200 } 194 }
@@ -202,7 +196,7 @@ void view_autoconfigure(struct sway_view *view) {
202 } 196 }
203 } 197 }
204 198
205 struct sway_container *con = view->swayc; 199 struct sway_container *con = view->container;
206 200
207 view->border_top = view->border_bottom = true; 201 view->border_top = view->border_bottom = true;
208 view->border_left = view->border_right = true; 202 view->border_left = view->border_right = true;
@@ -228,7 +222,8 @@ void view_autoconfigure(struct sway_view *view) {
228 // In a tabbed or stacked container, the swayc's y is the bottom of the 222 // In a tabbed or stacked container, the swayc's y is the bottom of the
229 // title area. We have to disable any top border because the title bar is 223 // title area. We have to disable any top border because the title bar is
230 // rendered by the parent. 224 // rendered by the parent.
231 if (con->parent->layout == L_TABBED || con->parent->layout == L_STACKED) { 225 enum sway_container_layout layout = container_parent_layout(con);
226 if (layout == L_TABBED || layout == L_STACKED) {
232 view->border_top = false; 227 view->border_top = false;
233 } else { 228 } else {
234 y_offset = container_titlebar_height(); 229 y_offset = container_titlebar_height();
@@ -281,13 +276,16 @@ void view_set_activated(struct sway_view *view, bool activated) {
281} 276}
282 277
283void view_request_activate(struct sway_view *view) { 278void view_request_activate(struct sway_view *view) {
284 struct sway_container *ws = container_parent(view->swayc, C_WORKSPACE); 279 struct sway_workspace *ws = view->container->workspace;
280 if (!ws) { // hidden scratchpad container
281 return;
282 }
285 struct sway_seat *seat = input_manager_current_seat(input_manager); 283 struct sway_seat *seat = input_manager_current_seat(input_manager);
286 284
287 switch (config->focus_on_window_activation) { 285 switch (config->focus_on_window_activation) {
288 case FOWA_SMART: 286 case FOWA_SMART:
289 if (workspace_is_visible(ws)) { 287 if (workspace_is_visible(ws)) {
290 seat_set_focus(seat, view->swayc); 288 seat_set_focus(seat, &view->container->node);
291 } else { 289 } else {
292 view_set_urgent(view, true); 290 view_set_urgent(view, true);
293 } 291 }
@@ -296,7 +294,7 @@ void view_request_activate(struct sway_view *view) {
296 view_set_urgent(view, true); 294 view_set_urgent(view, true);
297 break; 295 break;
298 case FOWA_FOCUS: 296 case FOWA_FOCUS:
299 seat_set_focus(seat, view->swayc); 297 seat_set_focus(seat, &view->container->node);
300 break; 298 break;
301 case FOWA_NONE: 299 case FOWA_NONE:
302 break; 300 break;
@@ -331,23 +329,12 @@ void view_close_popups(struct sway_view *view) {
331} 329}
332 330
333void view_damage_from(struct sway_view *view) { 331void view_damage_from(struct sway_view *view) {
334 for (int i = 0; i < root_container.children->length; ++i) { 332 for (int i = 0; i < root->outputs->length; ++i) {
335 struct sway_container *cont = root_container.children->items[i]; 333 struct sway_output *output = root->outputs->items[i];
336 if (cont->type == C_OUTPUT) { 334 output_damage_from_view(output, view);
337 output_damage_from_view(cont->sway_output, view);
338 }
339 } 335 }
340} 336}
341 337
342static void view_get_layout_box(struct sway_view *view, struct wlr_box *box) {
343 struct sway_container *output = container_parent(view->swayc, C_OUTPUT);
344
345 box->x = output->x + view->swayc->x;
346 box->y = output->y + view->swayc->y;
347 box->width = view->width;
348 box->height = view->height;
349}
350
351void view_for_each_surface(struct sway_view *view, 338void view_for_each_surface(struct sway_view *view,
352 wlr_surface_iterator_func_t iterator, void *user_data) { 339 wlr_surface_iterator_func_t iterator, void *user_data) {
353 if (!view->surface) { 340 if (!view->surface) {
@@ -396,11 +383,8 @@ static bool view_has_executed_criteria(struct sway_view *view,
396} 383}
397 384
398void view_execute_criteria(struct sway_view *view) { 385void view_execute_criteria(struct sway_view *view) {
399 if (!view->swayc) {
400 return;
401 }
402 struct sway_seat *seat = input_manager_current_seat(input_manager); 386 struct sway_seat *seat = input_manager_current_seat(input_manager);
403 struct sway_container *prior_focus = seat_get_focus(seat); 387 struct sway_node *prior_focus = seat_get_focus(seat);
404 list_t *criterias = criteria_for_view(view, CT_COMMAND); 388 list_t *criterias = criteria_for_view(view, CT_COMMAND);
405 for (int i = 0; i < criterias->length; i++) { 389 for (int i = 0; i < criterias->length; i++) {
406 struct criteria *criteria = criterias->items[i]; 390 struct criteria *criteria = criterias->items[i];
@@ -411,7 +395,7 @@ void view_execute_criteria(struct sway_view *view) {
411 } 395 }
412 wlr_log(WLR_DEBUG, "for_window '%s' matches view %p, cmd: '%s'", 396 wlr_log(WLR_DEBUG, "for_window '%s' matches view %p, cmd: '%s'",
413 criteria->raw, view, criteria->cmdlist); 397 criteria->raw, view, criteria->cmdlist);
414 seat_set_focus(seat, view->swayc); 398 seat_set_focus(seat, &view->container->node);
415 list_add(view->executed_criteria, criteria); 399 list_add(view->executed_criteria, criteria);
416 struct cmd_results *res = execute_command(criteria->cmdlist, NULL); 400 struct cmd_results *res = execute_command(criteria->cmdlist, NULL);
417 if (res->status != CMD_SUCCESS) { 401 if (res->status != CMD_SUCCESS) {
@@ -423,19 +407,19 @@ void view_execute_criteria(struct sway_view *view) {
423 seat_set_focus(seat, prior_focus); 407 seat_set_focus(seat, prior_focus);
424} 408}
425 409
426static struct sway_container *select_workspace(struct sway_view *view) { 410static struct sway_workspace *select_workspace(struct sway_view *view) {
427 struct sway_seat *seat = input_manager_current_seat(input_manager); 411 struct sway_seat *seat = input_manager_current_seat(input_manager);
428 412
429 // Check if there's any `assign` criteria for the view 413 // Check if there's any `assign` criteria for the view
430 list_t *criterias = criteria_for_view(view, 414 list_t *criterias = criteria_for_view(view,
431 CT_ASSIGN_WORKSPACE | CT_ASSIGN_WORKSPACE_NUMBER | CT_ASSIGN_OUTPUT); 415 CT_ASSIGN_WORKSPACE | CT_ASSIGN_WORKSPACE_NUMBER | CT_ASSIGN_OUTPUT);
432 struct sway_container *ws = NULL; 416 struct sway_workspace *ws = NULL;
433 for (int i = 0; i < criterias->length; ++i) { 417 for (int i = 0; i < criterias->length; ++i) {
434 struct criteria *criteria = criterias->items[i]; 418 struct criteria *criteria = criterias->items[i];
435 if (criteria->type == CT_ASSIGN_OUTPUT) { 419 if (criteria->type == CT_ASSIGN_OUTPUT) {
436 struct sway_container *output = output_by_name(criteria->target); 420 struct sway_output *output = output_by_name(criteria->target);
437 if (output) { 421 if (output) {
438 ws = seat_get_active_child(seat, output); 422 ws = output_get_active_workspace(output);
439 break; 423 break;
440 } 424 }
441 } else { 425 } else {
@@ -484,20 +468,14 @@ static struct sway_container *select_workspace(struct sway_view *view) {
484 } 468 }
485 469
486 // Use the focused workspace 470 // Use the focused workspace
487 ws = seat_get_focus_inactive(seat, &root_container); 471 return seat_get_focused_workspace(seat);
488 if (ws->type != C_WORKSPACE) {
489 ws = container_parent(ws, C_WORKSPACE);
490 }
491 return ws;
492} 472}
493 473
494static bool should_focus(struct sway_view *view) { 474static bool should_focus(struct sway_view *view) {
495 struct sway_seat *seat = input_manager_current_seat(input_manager); 475 struct sway_seat *seat = input_manager_current_seat(input_manager);
496 struct sway_container *prev_focus = 476 struct sway_container *prev_con = seat_get_focused_container(seat);
497 seat_get_focus_inactive(seat, &root_container); 477 struct sway_workspace *prev_ws = seat_get_focused_workspace(seat);
498 struct sway_container *prev_ws = prev_focus->type == C_WORKSPACE ? 478 struct sway_workspace *map_ws = view->container->workspace;
499 prev_focus : container_parent(prev_focus, C_WORKSPACE);
500 struct sway_container *map_ws = container_parent(view->swayc, C_WORKSPACE);
501 479
502 // Views can only take focus if they are mapped into the active workspace 480 // Views can only take focus if they are mapped into the active workspace
503 if (prev_ws != map_ws) { 481 if (prev_ws != map_ws) {
@@ -506,10 +484,9 @@ static bool should_focus(struct sway_view *view) {
506 484
507 // If the view is the only one in the focused workspace, it'll get focus 485 // If the view is the only one in the focused workspace, it'll get focus
508 // regardless of any no_focus criteria. 486 // regardless of any no_focus criteria.
509 struct sway_container *parent = view->swayc->parent; 487 if (!view->container->parent && !prev_con) {
510 if (parent->type == C_WORKSPACE && prev_focus == parent) { 488 size_t num_children = view->container->workspace->tiling->length +
511 size_t num_children = parent->children->length + 489 view->container->workspace->floating->length;
512 parent->sway_workspace->floating->length;
513 if (num_children == 1) { 490 if (num_children == 1) {
514 return true; 491 return true;
515 } 492 }
@@ -529,16 +506,24 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) {
529 view->surface = wlr_surface; 506 view->surface = wlr_surface;
530 507
531 struct sway_seat *seat = input_manager_current_seat(input_manager); 508 struct sway_seat *seat = input_manager_current_seat(input_manager);
532 struct sway_container *ws = select_workspace(view); 509 struct sway_workspace *ws = select_workspace(view);
533 struct sway_container *target_sibling = seat_get_focus_inactive(seat, ws); 510 struct sway_node *node = seat_get_focus_inactive(seat, &ws->node);
511 struct sway_container *target_sibling = node->type == N_CONTAINER ?
512 node->sway_container : NULL;
534 513
535 // If we're about to launch the view into the floating container, then 514 // If we're about to launch the view into the floating container, then
536 // launch it as a tiled view in the root of the workspace instead. 515 // launch it as a tiled view in the root of the workspace instead.
537 if (container_is_floating(target_sibling)) { 516 if (target_sibling && container_is_floating(target_sibling)) {
538 target_sibling = target_sibling->parent; 517 target_sibling = NULL;
539 } 518 }
540 519
541 view->swayc = container_view_create(target_sibling, view); 520 view->container = container_create(view);
521 if (target_sibling) {
522 container_add_sibling(target_sibling, view->container);
523 } else {
524 workspace_add_tiling(ws, view->container);
525 }
526 ipc_event_window(view->container, "new");
542 527
543 view_init_subsurfaces(view, wlr_surface); 528 view_init_subsurfaces(view, wlr_surface);
544 wl_signal_add(&wlr_surface->events.new_subsurface, 529 wl_signal_add(&wlr_surface->events.new_subsurface,
@@ -548,7 +533,7 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) {
548 if (view->impl->wants_floating && view->impl->wants_floating(view)) { 533 if (view->impl->wants_floating && view->impl->wants_floating(view)) {
549 view->border = config->floating_border; 534 view->border = config->floating_border;
550 view->border_thickness = config->floating_border_thickness; 535 view->border_thickness = config->floating_border_thickness;
551 container_set_floating(view->swayc, true); 536 container_set_floating(view->container, true);
552 } else { 537 } else {
553 view->border = config->border; 538 view->border = config->border;
554 view->border_thickness = config->border_thickness; 539 view->border_thickness = config->border_thickness;
@@ -556,11 +541,11 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) {
556 } 541 }
557 542
558 if (should_focus(view)) { 543 if (should_focus(view)) {
559 input_manager_set_focus(input_manager, view->swayc); 544 input_manager_set_focus(input_manager, &view->container->node);
560 } 545 }
561 546
562 view_update_title(view, false); 547 view_update_title(view, false);
563 container_notify_subtree_changed(view->swayc->parent); 548 container_update_representation(view->container);
564 view_execute_criteria(view); 549 view_execute_criteria(view);
565} 550}
566 551
@@ -574,17 +559,17 @@ void view_unmap(struct sway_view *view) {
574 view->urgent_timer = NULL; 559 view->urgent_timer = NULL;
575 } 560 }
576 561
577 bool was_fullscreen = view->swayc->is_fullscreen; 562 struct sway_container *parent = view->container->parent;
578 struct sway_container *parent = view->swayc->parent; 563 struct sway_workspace *ws = view->container->workspace;
579 container_begin_destroy(view->swayc); 564 container_begin_destroy(view->container);
580 struct sway_container *surviving_ancestor = container_reap_empty(parent); 565 if (parent) {
566 container_reap_empty(parent);
567 } else if (ws) {
568 workspace_consider_destroy(ws);
569 }
581 570
582 // If the workspace wasn't reaped 571 if (ws && !ws->node.destroying) {
583 if (surviving_ancestor && surviving_ancestor->type >= C_WORKSPACE) { 572 arrange_workspace(ws);
584 struct sway_container *ws = surviving_ancestor->type == C_WORKSPACE ?
585 surviving_ancestor :
586 container_parent(surviving_ancestor, C_WORKSPACE);
587 arrange_windows(was_fullscreen ? ws : surviving_ancestor);
588 workspace_detect_urgent(ws); 573 workspace_detect_urgent(ws);
589 } 574 }
590 575
@@ -593,15 +578,15 @@ void view_unmap(struct sway_view *view) {
593} 578}
594 579
595void view_update_size(struct sway_view *view, int width, int height) { 580void view_update_size(struct sway_view *view, int width, int height) {
596 if (!sway_assert(container_is_floating(view->swayc), 581 if (!sway_assert(container_is_floating(view->container),
597 "Expected a floating container")) { 582 "Expected a floating container")) {
598 return; 583 return;
599 } 584 }
600 view->width = width; 585 view->width = width;
601 view->height = height; 586 view->height = height;
602 view->swayc->current.view_width = width; 587 view->container->current.view_width = width;
603 view->swayc->current.view_height = height; 588 view->container->current.view_height = height;
604 container_set_geometry_from_floating_view(view->swayc); 589 container_set_geometry_from_floating_view(view->container);
605} 590}
606 591
607static void view_subsurface_create(struct sway_view *view, 592static void view_subsurface_create(struct sway_view *view,
@@ -670,27 +655,18 @@ void view_child_init(struct sway_view_child *child,
670 wl_signal_add(&view->events.unmap, &child->view_unmap); 655 wl_signal_add(&view->events.unmap, &child->view_unmap);
671 child->view_unmap.notify = view_child_handle_view_unmap; 656 child->view_unmap.notify = view_child_handle_view_unmap;
672 657
673 struct sway_container *output = child->view->swayc->parent; 658 struct sway_output *output = child->view->container->workspace->output;
674 if (output != NULL) { 659 wlr_surface_send_enter(child->surface, output->wlr_output);
675 if (output->type != C_OUTPUT) {
676 output = container_parent(output, C_OUTPUT);
677 }
678 wlr_surface_send_enter(child->surface, output->sway_output->wlr_output);
679 }
680 660
681 view_init_subsurfaces(child->view, surface); 661 view_init_subsurfaces(child->view, surface);
682 662
683 // TODO: only damage the whole child 663 // TODO: only damage the whole child
684 if (child->view->swayc) { 664 container_damage_whole(child->view->container);
685 container_damage_whole(child->view->swayc);
686 }
687} 665}
688 666
689void view_child_destroy(struct sway_view_child *child) { 667void view_child_destroy(struct sway_view_child *child) {
690 // TODO: only damage the whole child 668 // TODO: only damage the whole child
691 if (child->view->swayc) { 669 container_damage_whole(child->view->container);
692 container_damage_whole(child->view->swayc);
693 }
694 670
695 wl_list_remove(&child->surface_commit.link); 671 wl_list_remove(&child->surface_commit.link);
696 wl_list_remove(&child->surface_destroy.link); 672 wl_list_remove(&child->surface_destroy.link);
@@ -808,22 +784,20 @@ static char *escape_title(char *buffer) {
808} 784}
809 785
810void view_update_title(struct sway_view *view, bool force) { 786void view_update_title(struct sway_view *view, bool force) {
811 if (!view->swayc) {
812 return;
813 }
814 const char *title = view_get_title(view); 787 const char *title = view_get_title(view);
815 788
816 if (!force) { 789 if (!force) {
817 if (title && view->swayc->name && strcmp(title, view->swayc->name) == 0) { 790 if (title && view->container->title &&
791 strcmp(title, view->container->title) == 0) {
818 return; 792 return;
819 } 793 }
820 if (!title && !view->swayc->name) { 794 if (!title && !view->container->title) {
821 return; 795 return;
822 } 796 }
823 } 797 }
824 798
825 free(view->swayc->name); 799 free(view->container->title);
826 free(view->swayc->formatted_title); 800 free(view->container->formatted_title);
827 if (title) { 801 if (title) {
828 size_t len = parse_title_format(view, NULL); 802 size_t len = parse_title_format(view, NULL);
829 char *buffer = calloc(len + 1, sizeof(char)); 803 char *buffer = calloc(len + 1, sizeof(char));
@@ -836,25 +810,25 @@ void view_update_title(struct sway_view *view, bool force) {
836 buffer = escape_title(buffer); 810 buffer = escape_title(buffer);
837 } 811 }
838 812
839 view->swayc->name = strdup(title); 813 view->container->title = strdup(title);
840 view->swayc->formatted_title = buffer; 814 view->container->formatted_title = buffer;
841 } else { 815 } else {
842 view->swayc->name = NULL; 816 view->container->title = NULL;
843 view->swayc->formatted_title = NULL; 817 view->container->formatted_title = NULL;
844 } 818 }
845 container_calculate_title_height(view->swayc); 819 container_calculate_title_height(view->container);
846 config_update_font_height(false); 820 config_update_font_height(false);
847 821
848 // Update title after the global font height is updated 822 // Update title after the global font height is updated
849 container_update_title_textures(view->swayc); 823 container_update_title_textures(view->container);
850 824
851 ipc_event_window(view->swayc, "title"); 825 ipc_event_window(view->container, "title");
852} 826}
853 827
854static bool find_by_mark_iterator(struct sway_container *con, 828static bool find_by_mark_iterator(struct sway_container *con,
855 void *data) { 829 void *data) {
856 char *mark = data; 830 char *mark = data;
857 return con->type == C_VIEW && view_has_mark(con->sway_view, mark); 831 return con->view && view_has_mark(con->view, mark);
858} 832}
859 833
860struct sway_view *view_find_mark(char *mark) { 834struct sway_view *view_find_mark(char *mark) {
@@ -863,7 +837,7 @@ struct sway_view *view_find_mark(char *mark) {
863 if (!container) { 837 if (!container) {
864 return NULL; 838 return NULL;
865 } 839 }
866 return container->sway_view; 840 return container->view;
867} 841}
868 842
869bool view_find_and_unmark(char *mark) { 843bool view_find_and_unmark(char *mark) {
@@ -872,7 +846,7 @@ bool view_find_and_unmark(char *mark) {
872 if (!container) { 846 if (!container) {
873 return false; 847 return false;
874 } 848 }
875 struct sway_view *view = container->sway_view; 849 struct sway_view *view = container->view;
876 850
877 for (int i = 0; i < view->marks->length; ++i) { 851 for (int i = 0; i < view->marks->length; ++i) {
878 char *view_mark = view->marks->items[i]; 852 char *view_mark = view->marks->items[i];
@@ -888,10 +862,9 @@ bool view_find_and_unmark(char *mark) {
888} 862}
889 863
890void view_clear_marks(struct sway_view *view) { 864void view_clear_marks(struct sway_view *view) {
891 while (view->marks->length) { 865 list_foreach(view->marks, free);
892 list_del(view->marks, 0); 866 view->marks->length = 0;
893 ipc_event_window(view->swayc, "mark"); 867 ipc_event_window(view->container, "mark");
894 }
895} 868}
896 869
897bool view_has_mark(struct sway_view *view, char *mark) { 870bool view_has_mark(struct sway_view *view, char *mark) {
@@ -906,12 +879,13 @@ bool view_has_mark(struct sway_view *view, char *mark) {
906 879
907void view_add_mark(struct sway_view *view, char *mark) { 880void view_add_mark(struct sway_view *view, char *mark) {
908 list_add(view->marks, strdup(mark)); 881 list_add(view->marks, strdup(mark));
909 ipc_event_window(view->swayc, "mark"); 882 ipc_event_window(view->container, "mark");
910} 883}
911 884
912static void update_marks_texture(struct sway_view *view, 885static void update_marks_texture(struct sway_view *view,
913 struct wlr_texture **texture, struct border_colors *class) { 886 struct wlr_texture **texture, struct border_colors *class) {
914 struct sway_output *output = container_get_effective_output(view->swayc); 887 struct sway_output *output =
888 container_get_effective_output(view->container);
915 if (!output) { 889 if (!output) {
916 return; 890 return;
917 } 891 }
@@ -949,7 +923,7 @@ static void update_marks_texture(struct sway_view *view,
949 923
950 double scale = output->wlr_output->scale; 924 double scale = output->wlr_output->scale;
951 int width = 0; 925 int width = 0;
952 int height = view->swayc->title_height * scale; 926 int height = view->container->title_height * scale;
953 927
954 cairo_t *c = cairo_create(NULL); 928 cairo_t *c = cairo_create(NULL);
955 get_text_size(c, config->font, &width, NULL, scale, false, "%s", buffer); 929 get_text_size(c, config->font, &width, NULL, scale, false, "%s", buffer);
@@ -994,44 +968,40 @@ void view_update_marks_textures(struct sway_view *view) {
994 &config->border_colors.unfocused); 968 &config->border_colors.unfocused);
995 update_marks_texture(view, &view->marks_urgent, 969 update_marks_texture(view, &view->marks_urgent,
996 &config->border_colors.urgent); 970 &config->border_colors.urgent);
997 container_damage_whole(view->swayc); 971 container_damage_whole(view->container);
998} 972}
999 973
1000bool view_is_visible(struct sway_view *view) { 974bool view_is_visible(struct sway_view *view) {
1001 if (!view->swayc || view->swayc->destroying) { 975 if (view->container->node.destroying) {
1002 return false; 976 return false;
1003 } 977 }
1004 struct sway_container *workspace = 978 struct sway_workspace *workspace = view->container->workspace;
1005 container_parent(view->swayc, C_WORKSPACE);
1006 if (!workspace) { 979 if (!workspace) {
1007 return false; 980 return false;
1008 } 981 }
1009 // Determine if view is nested inside a floating container which is sticky. 982 // Determine if view is nested inside a floating container which is sticky
1010 // A simple floating view will have this ancestry: 983 struct sway_container *floater = view->container;
1011 // C_VIEW -> floating -> workspace 984 while (floater->parent) {
1012 // A more complex ancestry could be:
1013 // C_VIEW -> C_CONTAINER (tabbed) -> floating -> workspace
1014 struct sway_container *floater = view->swayc;
1015 while (floater->parent->type != C_WORKSPACE
1016 && floater->parent->parent->type != C_WORKSPACE) {
1017 floater = floater->parent; 985 floater = floater->parent;
1018 } 986 }
1019 bool is_sticky = container_is_floating(floater) && floater->is_sticky; 987 bool is_sticky = container_is_floating(floater) && floater->is_sticky;
1020 // Check view isn't in a tabbed or stacked container on an inactive tab 988 // Check view isn't in a tabbed or stacked container on an inactive tab
1021 struct sway_seat *seat = input_manager_current_seat(input_manager); 989 struct sway_seat *seat = input_manager_current_seat(input_manager);
1022 struct sway_container *container = view->swayc; 990 struct sway_container *container = view->container;
1023 while (container->type != C_WORKSPACE) { 991 while (container) {
1024 if (container->parent->layout == L_TABBED || 992 enum sway_container_layout layout = container_parent_layout(container);
1025 container->parent->layout == L_STACKED) { 993 if (layout == L_TABBED || layout == L_STACKED) {
1026 if (seat_get_active_child(seat, container->parent) != container) { 994 struct sway_node *parent = container->parent ?
995 &container->parent->node : &container->workspace->node;
996 if (seat_get_active_child(seat, parent) != &container->node) {
1027 return false; 997 return false;
1028 } 998 }
1029 } 999 }
1030 container = container->parent; 1000 container = container->parent;
1031 } 1001 }
1032 // Check view isn't hidden by another fullscreen view 1002 // Check view isn't hidden by another fullscreen view
1033 if (workspace->sway_workspace->fullscreen && 1003 if (workspace->fullscreen &&
1034 !container_is_fullscreen_or_child(view->swayc)) { 1004 !container_is_fullscreen_or_child(view->container)) {
1035 return false; 1005 return false;
1036 } 1006 }
1037 // Check the workspace is visible 1007 // Check the workspace is visible
@@ -1047,7 +1017,7 @@ void view_set_urgent(struct sway_view *view, bool enable) {
1047 } 1017 }
1048 if (enable) { 1018 if (enable) {
1049 struct sway_seat *seat = input_manager_current_seat(input_manager); 1019 struct sway_seat *seat = input_manager_current_seat(input_manager);
1050 if (seat_get_focus(seat) == view->swayc) { 1020 if (seat_get_focused_container(seat) == view->container) {
1051 return; 1021 return;
1052 } 1022 }
1053 clock_gettime(CLOCK_MONOTONIC, &view->urgent); 1023 clock_gettime(CLOCK_MONOTONIC, &view->urgent);
@@ -1058,12 +1028,13 @@ void view_set_urgent(struct sway_view *view, bool enable) {
1058 view->urgent_timer = NULL; 1028 view->urgent_timer = NULL;
1059 } 1029 }
1060 } 1030 }
1061 container_damage_whole(view->swayc); 1031 container_damage_whole(view->container);
1062 1032
1063 ipc_event_window(view->swayc, "urgent"); 1033 ipc_event_window(view->container, "urgent");
1064 1034
1065 struct sway_container *ws = container_parent(view->swayc, C_WORKSPACE); 1035 if (view->container->workspace) {
1066 workspace_detect_urgent(ws); 1036 workspace_detect_urgent(view->container->workspace);
1037 }
1067} 1038}
1068 1039
1069bool view_is_urgent(struct sway_view *view) { 1040bool view_is_urgent(struct sway_view *view) {