diff options
Diffstat (limited to 'sway/tree/view.c')
-rw-r--r-- | sway/tree/view.c | 277 |
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 | ||
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,27 @@ 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 | 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 | ||
283 | void view_request_activate(struct sway_view *view) { | 274 | void 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 | ||
333 | void view_damage_from(struct sway_view *view) { | 327 | void 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 | ||
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, | 334 | void 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 | ||
398 | void view_execute_criteria(struct sway_view *view) { | 381 | 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); | 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 | ||
426 | static struct sway_container *select_workspace(struct sway_view *view) { | 406 | static 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 | ||
494 | static bool should_focus(struct sway_view *view) { | 470 | static 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 | ||
595 | void view_update_size(struct sway_view *view, int width, int height) { | 576 | void 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 | ||
607 | static void view_subsurface_create(struct sway_view *view, | 588 | static 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 | ||
689 | void view_child_destroy(struct sway_view_child *child) { | 663 | void 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 | ||
810 | void view_update_title(struct sway_view *view, bool force) { | 782 | 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); | 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 | ||
854 | static bool find_by_mark_iterator(struct sway_container *con, | 824 | static 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 | ||
860 | struct sway_view *view_find_mark(char *mark) { | 830 | struct 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 | ||
869 | bool view_find_and_unmark(char *mark) { | 839 | bool 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 | ||
890 | void view_clear_marks(struct sway_view *view) { | 860 | void 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 | ||
897 | bool view_has_mark(struct sway_view *view, char *mark) { | 866 | bool 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 | ||
907 | void view_add_mark(struct sway_view *view, char *mark) { | 876 | void 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 | ||
912 | static void update_marks_texture(struct sway_view *view, | 881 | static 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 | ||
1000 | bool view_is_visible(struct sway_view *view) { | 970 | bool 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 | ||
1069 | bool view_is_urgent(struct sway_view *view) { | 1034 | bool view_is_urgent(struct sway_view *view) { |