diff options
Diffstat (limited to 'sway/tree/view.c')
-rw-r--r-- | sway/tree/view.c | 275 |
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 | ||
38 | void view_destroy(struct sway_view *view) { | 40 | void 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 | */ | ||
78 | void view_begin_destroy(struct sway_view *view) { | 71 | void 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 | ||
173 | void view_autoconfigure(struct sway_view *view) { | 166 | void 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 | ||
283 | void view_request_activate(struct sway_view *view) { | 278 | void 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 | ||
333 | void view_damage_from(struct sway_view *view) { | 331 | void 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 | ||
342 | static 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 | |||
351 | void view_for_each_surface(struct sway_view *view, | 338 | void 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 | ||
398 | void view_execute_criteria(struct sway_view *view) { | 385 | void 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 | ||
426 | static struct sway_container *select_workspace(struct sway_view *view) { | 410 | static 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 | ||
494 | static bool should_focus(struct sway_view *view) { | 474 | static 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 | ||
595 | void view_update_size(struct sway_view *view, int width, int height) { | 580 | void 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 | ||
607 | static void view_subsurface_create(struct sway_view *view, | 592 | static 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 | ||
689 | void view_child_destroy(struct sway_view_child *child) { | 667 | void 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 | ||
810 | void view_update_title(struct sway_view *view, bool force) { | 786 | void 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 | ||
854 | static bool find_by_mark_iterator(struct sway_container *con, | 828 | static 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 | ||
860 | struct sway_view *view_find_mark(char *mark) { | 834 | struct 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 | ||
869 | bool view_find_and_unmark(char *mark) { | 843 | bool 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 | ||
890 | void view_clear_marks(struct sway_view *view) { | 864 | void 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 | ||
897 | bool view_has_mark(struct sway_view *view, char *mark) { | 870 | bool 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 | ||
907 | void view_add_mark(struct sway_view *view, char *mark) { | 880 | void 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 | ||
912 | static void update_marks_texture(struct sway_view *view, | 885 | static 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 | ||
1000 | bool view_is_visible(struct sway_view *view) { | 974 | bool 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 | ||
1069 | bool view_is_urgent(struct sway_view *view) { | 1040 | bool view_is_urgent(struct sway_view *view) { |