summaryrefslogtreecommitdiffstats
path: root/sway/tree/view.c
diff options
context:
space:
mode:
Diffstat (limited to 'sway/tree/view.c')
-rw-r--r--sway/tree/view.c277
1 files changed, 121 insertions, 156 deletions
diff --git a/sway/tree/view.c b/sway/tree/view.c
index 6bd0ef67..452c2bd1 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,27 @@ 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 struct sway_output *output = view->container->workspace->output;
175 "Called view_autoconfigure() on a view without a swayc")) {
176 return;
177 }
178
179 struct sway_container *output = container_parent(view->swayc, C_OUTPUT);
180 168
181 if (view->swayc->is_fullscreen) { 169 if (view->container->is_fullscreen) {
182 view->x = output->x; 170 view->x = output->wlr_output->lx;
183 view->y = output->y; 171 view->y = output->wlr_output->ly;
184 view->width = output->width; 172 view->width = output->wlr_output->width;
185 view->height = output->height; 173 view->height = output->wlr_output->height;
186 return; 174 return;
187 } 175 }
188 176
189 struct sway_container *ws = container_parent(view->swayc, C_WORKSPACE); 177 struct sway_workspace *ws = view->container->workspace;
190 178
191 int other_views = 0; 179 bool other_views = false;
192 if (config->hide_edge_borders == E_SMART) { 180 if (config->hide_edge_borders == E_SMART) {
193 struct sway_container *con = view->swayc; 181 struct sway_container *con = view->container;
194 while (con != output) { 182 while (con) {
195 if (con->layout != L_TABBED && con->layout != L_STACKED) { 183 enum sway_container_layout layout = container_parent_layout(con);
196 other_views += con->children ? con->children->length - 1 : 0; 184 if (layout != L_TABBED && layout != L_STACKED) {
197 if (other_views > 0) { 185 list_t *siblings = container_get_siblings(con);
186 if (siblings && siblings->length > 1) {
187 other_views = true;
198 break; 188 break;
199 } 189 }
200 } 190 }
@@ -202,7 +192,7 @@ void view_autoconfigure(struct sway_view *view) {
202 } 192 }
203 } 193 }
204 194
205 struct sway_container *con = view->swayc; 195 struct sway_container *con = view->container;
206 196
207 view->border_top = view->border_bottom = true; 197 view->border_top = view->border_bottom = true;
208 view->border_left = view->border_right = true; 198 view->border_left = view->border_right = true;
@@ -228,7 +218,8 @@ void view_autoconfigure(struct sway_view *view) {
228 // In a tabbed or stacked container, the swayc's y is the bottom of the 218 // 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 219 // title area. We have to disable any top border because the title bar is
230 // rendered by the parent. 220 // rendered by the parent.
231 if (con->parent->layout == L_TABBED || con->parent->layout == L_STACKED) { 221 enum sway_container_layout layout = container_parent_layout(con);
222 if (layout == L_TABBED || layout == L_STACKED) {
232 view->border_top = false; 223 view->border_top = false;
233 } else { 224 } else {
234 y_offset = container_titlebar_height(); 225 y_offset = container_titlebar_height();
@@ -281,13 +272,16 @@ void view_set_activated(struct sway_view *view, bool activated) {
281} 272}
282 273
283void view_request_activate(struct sway_view *view) { 274void view_request_activate(struct sway_view *view) {
284 struct sway_container *ws = container_parent(view->swayc, C_WORKSPACE); 275 struct sway_workspace *ws = view->container->workspace;
276 if (!ws) { // hidden scratchpad container
277 return;
278 }
285 struct sway_seat *seat = input_manager_current_seat(input_manager); 279 struct sway_seat *seat = input_manager_current_seat(input_manager);
286 280
287 switch (config->focus_on_window_activation) { 281 switch (config->focus_on_window_activation) {
288 case FOWA_SMART: 282 case FOWA_SMART:
289 if (workspace_is_visible(ws)) { 283 if (workspace_is_visible(ws)) {
290 seat_set_focus(seat, view->swayc); 284 seat_set_focus(seat, &view->container->node);
291 } else { 285 } else {
292 view_set_urgent(view, true); 286 view_set_urgent(view, true);
293 } 287 }
@@ -296,7 +290,7 @@ void view_request_activate(struct sway_view *view) {
296 view_set_urgent(view, true); 290 view_set_urgent(view, true);
297 break; 291 break;
298 case FOWA_FOCUS: 292 case FOWA_FOCUS:
299 seat_set_focus(seat, view->swayc); 293 seat_set_focus(seat, &view->container->node);
300 break; 294 break;
301 case FOWA_NONE: 295 case FOWA_NONE:
302 break; 296 break;
@@ -331,23 +325,12 @@ void view_close_popups(struct sway_view *view) {
331} 325}
332 326
333void view_damage_from(struct sway_view *view) { 327void view_damage_from(struct sway_view *view) {
334 for (int i = 0; i < root_container.children->length; ++i) { 328 for (int i = 0; i < root->outputs->length; ++i) {
335 struct sway_container *cont = root_container.children->items[i]; 329 struct sway_output *output = root->outputs->items[i];
336 if (cont->type == C_OUTPUT) { 330 output_damage_from_view(output, view);
337 output_damage_from_view(cont->sway_output, view);
338 }
339 } 331 }
340} 332}
341 333
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, 334void view_for_each_surface(struct sway_view *view,
352 wlr_surface_iterator_func_t iterator, void *user_data) { 335 wlr_surface_iterator_func_t iterator, void *user_data) {
353 if (!view->surface) { 336 if (!view->surface) {
@@ -396,11 +379,8 @@ static bool view_has_executed_criteria(struct sway_view *view,
396} 379}
397 380
398void view_execute_criteria(struct sway_view *view) { 381void 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); 382 struct sway_seat *seat = input_manager_current_seat(input_manager);
403 struct sway_container *prior_focus = seat_get_focus(seat); 383 struct sway_node *prior_focus = seat_get_focus(seat);
404 list_t *criterias = criteria_for_view(view, CT_COMMAND); 384 list_t *criterias = criteria_for_view(view, CT_COMMAND);
405 for (int i = 0; i < criterias->length; i++) { 385 for (int i = 0; i < criterias->length; i++) {
406 struct criteria *criteria = criterias->items[i]; 386 struct criteria *criteria = criterias->items[i];
@@ -411,7 +391,7 @@ void view_execute_criteria(struct sway_view *view) {
411 } 391 }
412 wlr_log(WLR_DEBUG, "for_window '%s' matches view %p, cmd: '%s'", 392 wlr_log(WLR_DEBUG, "for_window '%s' matches view %p, cmd: '%s'",
413 criteria->raw, view, criteria->cmdlist); 393 criteria->raw, view, criteria->cmdlist);
414 seat_set_focus(seat, view->swayc); 394 seat_set_focus(seat, &view->container->node);
415 list_add(view->executed_criteria, criteria); 395 list_add(view->executed_criteria, criteria);
416 struct cmd_results *res = execute_command(criteria->cmdlist, NULL); 396 struct cmd_results *res = execute_command(criteria->cmdlist, NULL);
417 if (res->status != CMD_SUCCESS) { 397 if (res->status != CMD_SUCCESS) {
@@ -423,19 +403,19 @@ void view_execute_criteria(struct sway_view *view) {
423 seat_set_focus(seat, prior_focus); 403 seat_set_focus(seat, prior_focus);
424} 404}
425 405
426static struct sway_container *select_workspace(struct sway_view *view) { 406static struct sway_workspace *select_workspace(struct sway_view *view) {
427 struct sway_seat *seat = input_manager_current_seat(input_manager); 407 struct sway_seat *seat = input_manager_current_seat(input_manager);
428 408
429 // Check if there's any `assign` criteria for the view 409 // Check if there's any `assign` criteria for the view
430 list_t *criterias = criteria_for_view(view, 410 list_t *criterias = criteria_for_view(view,
431 CT_ASSIGN_WORKSPACE | CT_ASSIGN_WORKSPACE_NUMBER | CT_ASSIGN_OUTPUT); 411 CT_ASSIGN_WORKSPACE | CT_ASSIGN_WORKSPACE_NUMBER | CT_ASSIGN_OUTPUT);
432 struct sway_container *ws = NULL; 412 struct sway_workspace *ws = NULL;
433 for (int i = 0; i < criterias->length; ++i) { 413 for (int i = 0; i < criterias->length; ++i) {
434 struct criteria *criteria = criterias->items[i]; 414 struct criteria *criteria = criterias->items[i];
435 if (criteria->type == CT_ASSIGN_OUTPUT) { 415 if (criteria->type == CT_ASSIGN_OUTPUT) {
436 struct sway_container *output = output_by_name(criteria->target); 416 struct sway_output *output = output_by_name(criteria->target);
437 if (output) { 417 if (output) {
438 ws = seat_get_active_child(seat, output); 418 ws = output_get_active_workspace(output);
439 break; 419 break;
440 } 420 }
441 } else { 421 } else {
@@ -484,20 +464,14 @@ static struct sway_container *select_workspace(struct sway_view *view) {
484 } 464 }
485 465
486 // Use the focused workspace 466 // Use the focused workspace
487 ws = seat_get_focus_inactive(seat, &root_container); 467 return seat_get_focused_workspace(seat);
488 if (ws->type != C_WORKSPACE) {
489 ws = container_parent(ws, C_WORKSPACE);
490 }
491 return ws;
492} 468}
493 469
494static bool should_focus(struct sway_view *view) { 470static bool should_focus(struct sway_view *view) {
495 struct sway_seat *seat = input_manager_current_seat(input_manager); 471 struct sway_seat *seat = input_manager_current_seat(input_manager);
496 struct sway_container *prev_focus = 472 struct sway_container *prev_con = seat_get_focused_container(seat);
497 seat_get_focus_inactive(seat, &root_container); 473 struct sway_workspace *prev_ws = seat_get_focused_workspace(seat);
498 struct sway_container *prev_ws = prev_focus->type == C_WORKSPACE ? 474 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 475
502 // Views can only take focus if they are mapped into the active workspace 476 // Views can only take focus if they are mapped into the active workspace
503 if (prev_ws != map_ws) { 477 if (prev_ws != map_ws) {
@@ -506,10 +480,9 @@ static bool should_focus(struct sway_view *view) {
506 480
507 // If the view is the only one in the focused workspace, it'll get focus 481 // If the view is the only one in the focused workspace, it'll get focus
508 // regardless of any no_focus criteria. 482 // regardless of any no_focus criteria.
509 struct sway_container *parent = view->swayc->parent; 483 if (!view->container->parent && !prev_con) {
510 if (parent->type == C_WORKSPACE && prev_focus == parent) { 484 size_t num_children = view->container->workspace->tiling->length +
511 size_t num_children = parent->children->length + 485 view->container->workspace->floating->length;
512 parent->sway_workspace->floating->length;
513 if (num_children == 1) { 486 if (num_children == 1) {
514 return true; 487 return true;
515 } 488 }
@@ -529,16 +502,24 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) {
529 view->surface = wlr_surface; 502 view->surface = wlr_surface;
530 503
531 struct sway_seat *seat = input_manager_current_seat(input_manager); 504 struct sway_seat *seat = input_manager_current_seat(input_manager);
532 struct sway_container *ws = select_workspace(view); 505 struct sway_workspace *ws = select_workspace(view);
533 struct sway_container *target_sibling = seat_get_focus_inactive(seat, ws); 506 struct sway_node *node = seat_get_focus_inactive(seat, &ws->node);
507 struct sway_container *target_sibling = node->type == N_CONTAINER ?
508 node->sway_container : NULL;
534 509
535 // If we're about to launch the view into the floating container, then 510 // 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. 511 // launch it as a tiled view in the root of the workspace instead.
537 if (container_is_floating(target_sibling)) { 512 if (target_sibling && container_is_floating(target_sibling)) {
538 target_sibling = target_sibling->parent; 513 target_sibling = NULL;
539 } 514 }
540 515
541 view->swayc = container_view_create(target_sibling, view); 516 view->container = container_create(view);
517 if (target_sibling) {
518 container_add_sibling(target_sibling, view->container, 1);
519 } else {
520 workspace_add_tiling(ws, view->container);
521 }
522 ipc_event_window(view->container, "new");
542 523
543 view_init_subsurfaces(view, wlr_surface); 524 view_init_subsurfaces(view, wlr_surface);
544 wl_signal_add(&wlr_surface->events.new_subsurface, 525 wl_signal_add(&wlr_surface->events.new_subsurface,
@@ -548,7 +529,7 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) {
548 if (view->impl->wants_floating && view->impl->wants_floating(view)) { 529 if (view->impl->wants_floating && view->impl->wants_floating(view)) {
549 view->border = config->floating_border; 530 view->border = config->floating_border;
550 view->border_thickness = config->floating_border_thickness; 531 view->border_thickness = config->floating_border_thickness;
551 container_set_floating(view->swayc, true); 532 container_set_floating(view->container, true);
552 } else { 533 } else {
553 view->border = config->border; 534 view->border = config->border;
554 view->border_thickness = config->border_thickness; 535 view->border_thickness = config->border_thickness;
@@ -556,11 +537,11 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) {
556 } 537 }
557 538
558 if (should_focus(view)) { 539 if (should_focus(view)) {
559 input_manager_set_focus(input_manager, view->swayc); 540 input_manager_set_focus(input_manager, &view->container->node);
560 } 541 }
561 542
562 view_update_title(view, false); 543 view_update_title(view, false);
563 container_notify_subtree_changed(view->swayc->parent); 544 container_update_representation(view->container);
564 view_execute_criteria(view); 545 view_execute_criteria(view);
565} 546}
566 547
@@ -574,17 +555,17 @@ void view_unmap(struct sway_view *view) {
574 view->urgent_timer = NULL; 555 view->urgent_timer = NULL;
575 } 556 }
576 557
577 bool was_fullscreen = view->swayc->is_fullscreen; 558 struct sway_container *parent = view->container->parent;
578 struct sway_container *parent = view->swayc->parent; 559 struct sway_workspace *ws = view->container->workspace;
579 container_begin_destroy(view->swayc); 560 container_begin_destroy(view->container);
580 struct sway_container *surviving_ancestor = container_reap_empty(parent); 561 if (parent) {
562 container_reap_empty(parent);
563 } else {
564 workspace_consider_destroy(ws);
565 }
581 566
582 // If the workspace wasn't reaped 567 if (!ws->node.destroying) {
583 if (surviving_ancestor && surviving_ancestor->type >= C_WORKSPACE) { 568 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); 569 workspace_detect_urgent(ws);
589 } 570 }
590 571
@@ -593,15 +574,15 @@ void view_unmap(struct sway_view *view) {
593} 574}
594 575
595void view_update_size(struct sway_view *view, int width, int height) { 576void view_update_size(struct sway_view *view, int width, int height) {
596 if (!sway_assert(container_is_floating(view->swayc), 577 if (!sway_assert(container_is_floating(view->container),
597 "Expected a floating container")) { 578 "Expected a floating container")) {
598 return; 579 return;
599 } 580 }
600 view->width = width; 581 view->width = width;
601 view->height = height; 582 view->height = height;
602 view->swayc->current.view_width = width; 583 view->container->current.view_width = width;
603 view->swayc->current.view_height = height; 584 view->container->current.view_height = height;
604 container_set_geometry_from_floating_view(view->swayc); 585 container_set_geometry_from_floating_view(view->container);
605} 586}
606 587
607static void view_subsurface_create(struct sway_view *view, 588static void view_subsurface_create(struct sway_view *view,
@@ -670,27 +651,18 @@ void view_child_init(struct sway_view_child *child,
670 wl_signal_add(&view->events.unmap, &child->view_unmap); 651 wl_signal_add(&view->events.unmap, &child->view_unmap);
671 child->view_unmap.notify = view_child_handle_view_unmap; 652 child->view_unmap.notify = view_child_handle_view_unmap;
672 653
673 struct sway_container *output = child->view->swayc->parent; 654 struct sway_output *output = child->view->container->workspace->output;
674 if (output != NULL) { 655 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 656
681 view_init_subsurfaces(child->view, surface); 657 view_init_subsurfaces(child->view, surface);
682 658
683 // TODO: only damage the whole child 659 // TODO: only damage the whole child
684 if (child->view->swayc) { 660 container_damage_whole(child->view->container);
685 container_damage_whole(child->view->swayc);
686 }
687} 661}
688 662
689void view_child_destroy(struct sway_view_child *child) { 663void view_child_destroy(struct sway_view_child *child) {
690 // TODO: only damage the whole child 664 // TODO: only damage the whole child
691 if (child->view->swayc) { 665 container_damage_whole(child->view->container);
692 container_damage_whole(child->view->swayc);
693 }
694 666
695 wl_list_remove(&child->surface_commit.link); 667 wl_list_remove(&child->surface_commit.link);
696 wl_list_remove(&child->surface_destroy.link); 668 wl_list_remove(&child->surface_destroy.link);
@@ -808,22 +780,20 @@ static char *escape_title(char *buffer) {
808} 780}
809 781
810void view_update_title(struct sway_view *view, bool force) { 782void view_update_title(struct sway_view *view, bool force) {
811 if (!view->swayc) {
812 return;
813 }
814 const char *title = view_get_title(view); 783 const char *title = view_get_title(view);
815 784
816 if (!force) { 785 if (!force) {
817 if (title && view->swayc->name && strcmp(title, view->swayc->name) == 0) { 786 if (title && view->container->title &&
787 strcmp(title, view->container->title) == 0) {
818 return; 788 return;
819 } 789 }
820 if (!title && !view->swayc->name) { 790 if (!title && !view->container->title) {
821 return; 791 return;
822 } 792 }
823 } 793 }
824 794
825 free(view->swayc->name); 795 free(view->container->title);
826 free(view->swayc->formatted_title); 796 free(view->container->formatted_title);
827 if (title) { 797 if (title) {
828 size_t len = parse_title_format(view, NULL); 798 size_t len = parse_title_format(view, NULL);
829 char *buffer = calloc(len + 1, sizeof(char)); 799 char *buffer = calloc(len + 1, sizeof(char));
@@ -836,25 +806,25 @@ void view_update_title(struct sway_view *view, bool force) {
836 buffer = escape_title(buffer); 806 buffer = escape_title(buffer);
837 } 807 }
838 808
839 view->swayc->name = strdup(title); 809 view->container->title = strdup(title);
840 view->swayc->formatted_title = buffer; 810 view->container->formatted_title = buffer;
841 } else { 811 } else {
842 view->swayc->name = NULL; 812 view->container->title = NULL;
843 view->swayc->formatted_title = NULL; 813 view->container->formatted_title = NULL;
844 } 814 }
845 container_calculate_title_height(view->swayc); 815 container_calculate_title_height(view->container);
846 config_update_font_height(false); 816 config_update_font_height(false);
847 817
848 // Update title after the global font height is updated 818 // Update title after the global font height is updated
849 container_update_title_textures(view->swayc); 819 container_update_title_textures(view->container);
850 820
851 ipc_event_window(view->swayc, "title"); 821 ipc_event_window(view->container, "title");
852} 822}
853 823
854static bool find_by_mark_iterator(struct sway_container *con, 824static bool find_by_mark_iterator(struct sway_container *con,
855 void *data) { 825 void *data) {
856 char *mark = data; 826 char *mark = data;
857 return con->type == C_VIEW && view_has_mark(con->sway_view, mark); 827 return con->view && view_has_mark(con->view, mark);
858} 828}
859 829
860struct sway_view *view_find_mark(char *mark) { 830struct sway_view *view_find_mark(char *mark) {
@@ -863,7 +833,7 @@ struct sway_view *view_find_mark(char *mark) {
863 if (!container) { 833 if (!container) {
864 return NULL; 834 return NULL;
865 } 835 }
866 return container->sway_view; 836 return container->view;
867} 837}
868 838
869bool view_find_and_unmark(char *mark) { 839bool view_find_and_unmark(char *mark) {
@@ -872,7 +842,7 @@ bool view_find_and_unmark(char *mark) {
872 if (!container) { 842 if (!container) {
873 return false; 843 return false;
874 } 844 }
875 struct sway_view *view = container->sway_view; 845 struct sway_view *view = container->view;
876 846
877 for (int i = 0; i < view->marks->length; ++i) { 847 for (int i = 0; i < view->marks->length; ++i) {
878 char *view_mark = view->marks->items[i]; 848 char *view_mark = view->marks->items[i];
@@ -888,10 +858,9 @@ bool view_find_and_unmark(char *mark) {
888} 858}
889 859
890void view_clear_marks(struct sway_view *view) { 860void view_clear_marks(struct sway_view *view) {
891 while (view->marks->length) { 861 list_foreach(view->marks, free);
892 list_del(view->marks, 0); 862 view->marks->length = 0;
893 ipc_event_window(view->swayc, "mark"); 863 ipc_event_window(view->container, "mark");
894 }
895} 864}
896 865
897bool view_has_mark(struct sway_view *view, char *mark) { 866bool view_has_mark(struct sway_view *view, char *mark) {
@@ -906,12 +875,13 @@ bool view_has_mark(struct sway_view *view, char *mark) {
906 875
907void view_add_mark(struct sway_view *view, char *mark) { 876void view_add_mark(struct sway_view *view, char *mark) {
908 list_add(view->marks, strdup(mark)); 877 list_add(view->marks, strdup(mark));
909 ipc_event_window(view->swayc, "mark"); 878 ipc_event_window(view->container, "mark");
910} 879}
911 880
912static void update_marks_texture(struct sway_view *view, 881static void update_marks_texture(struct sway_view *view,
913 struct wlr_texture **texture, struct border_colors *class) { 882 struct wlr_texture **texture, struct border_colors *class) {
914 struct sway_output *output = container_get_effective_output(view->swayc); 883 struct sway_output *output =
884 container_get_effective_output(view->container);
915 if (!output) { 885 if (!output) {
916 return; 886 return;
917 } 887 }
@@ -949,7 +919,7 @@ static void update_marks_texture(struct sway_view *view,
949 919
950 double scale = output->wlr_output->scale; 920 double scale = output->wlr_output->scale;
951 int width = 0; 921 int width = 0;
952 int height = view->swayc->title_height * scale; 922 int height = view->container->title_height * scale;
953 923
954 cairo_t *c = cairo_create(NULL); 924 cairo_t *c = cairo_create(NULL);
955 get_text_size(c, config->font, &width, NULL, scale, false, "%s", buffer); 925 get_text_size(c, config->font, &width, NULL, scale, false, "%s", buffer);
@@ -994,44 +964,40 @@ void view_update_marks_textures(struct sway_view *view) {
994 &config->border_colors.unfocused); 964 &config->border_colors.unfocused);
995 update_marks_texture(view, &view->marks_urgent, 965 update_marks_texture(view, &view->marks_urgent,
996 &config->border_colors.urgent); 966 &config->border_colors.urgent);
997 container_damage_whole(view->swayc); 967 container_damage_whole(view->container);
998} 968}
999 969
1000bool view_is_visible(struct sway_view *view) { 970bool view_is_visible(struct sway_view *view) {
1001 if (!view->swayc || view->swayc->destroying) { 971 if (view->container->node.destroying) {
1002 return false; 972 return false;
1003 } 973 }
1004 struct sway_container *workspace = 974 struct sway_workspace *workspace = view->container->workspace;
1005 container_parent(view->swayc, C_WORKSPACE);
1006 if (!workspace) { 975 if (!workspace) {
1007 return false; 976 return false;
1008 } 977 }
1009 // Determine if view is nested inside a floating container which is sticky. 978 // Determine if view is nested inside a floating container which is sticky
1010 // A simple floating view will have this ancestry: 979 struct sway_container *floater = view->container;
1011 // C_VIEW -> floating -> workspace 980 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; 981 floater = floater->parent;
1018 } 982 }
1019 bool is_sticky = container_is_floating(floater) && floater->is_sticky; 983 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 984 // 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); 985 struct sway_seat *seat = input_manager_current_seat(input_manager);
1022 struct sway_container *container = view->swayc; 986 struct sway_container *container = view->container;
1023 while (container->type != C_WORKSPACE) { 987 while (container) {
1024 if (container->parent->layout == L_TABBED || 988 enum sway_container_layout layout = container_parent_layout(container);
1025 container->parent->layout == L_STACKED) { 989 if (layout == L_TABBED || layout == L_STACKED) {
1026 if (seat_get_active_child(seat, container->parent) != container) { 990 struct sway_node *parent = container->parent ?
991 &container->parent->node : &container->workspace->node;
992 if (seat_get_active_child(seat, parent) != &container->node) {
1027 return false; 993 return false;
1028 } 994 }
1029 } 995 }
1030 container = container->parent; 996 container = container->parent;
1031 } 997 }
1032 // Check view isn't hidden by another fullscreen view 998 // Check view isn't hidden by another fullscreen view
1033 if (workspace->sway_workspace->fullscreen && 999 if (workspace->fullscreen &&
1034 !container_is_fullscreen_or_child(view->swayc)) { 1000 !container_is_fullscreen_or_child(view->container)) {
1035 return false; 1001 return false;
1036 } 1002 }
1037 // Check the workspace is visible 1003 // Check the workspace is visible
@@ -1047,7 +1013,7 @@ void view_set_urgent(struct sway_view *view, bool enable) {
1047 } 1013 }
1048 if (enable) { 1014 if (enable) {
1049 struct sway_seat *seat = input_manager_current_seat(input_manager); 1015 struct sway_seat *seat = input_manager_current_seat(input_manager);
1050 if (seat_get_focus(seat) == view->swayc) { 1016 if (seat_get_focused_container(seat) == view->container) {
1051 return; 1017 return;
1052 } 1018 }
1053 clock_gettime(CLOCK_MONOTONIC, &view->urgent); 1019 clock_gettime(CLOCK_MONOTONIC, &view->urgent);
@@ -1058,12 +1024,11 @@ void view_set_urgent(struct sway_view *view, bool enable) {
1058 view->urgent_timer = NULL; 1024 view->urgent_timer = NULL;
1059 } 1025 }
1060 } 1026 }
1061 container_damage_whole(view->swayc); 1027 container_damage_whole(view->container);
1062 1028
1063 ipc_event_window(view->swayc, "urgent"); 1029 ipc_event_window(view->container, "urgent");
1064 1030
1065 struct sway_container *ws = container_parent(view->swayc, C_WORKSPACE); 1031 workspace_detect_urgent(view->container->workspace);
1066 workspace_detect_urgent(ws);
1067} 1032}
1068 1033
1069bool view_is_urgent(struct sway_view *view) { 1034bool view_is_urgent(struct sway_view *view) {