summaryrefslogtreecommitdiffstats
path: root/sway/tree/container.c
diff options
context:
space:
mode:
Diffstat (limited to 'sway/tree/container.c')
-rw-r--r--sway/tree/container.c276
1 files changed, 204 insertions, 72 deletions
diff --git a/sway/tree/container.c b/sway/tree/container.c
index feaf7647..5d88325f 100644
--- a/sway/tree/container.c
+++ b/sway/tree/container.c
@@ -452,79 +452,138 @@ struct sway_container *container_parent(struct sway_container *container,
452 return container; 452 return container;
453} 453}
454 454
455struct sway_container *container_at(struct sway_container *parent, 455static struct sway_container *container_at_view(struct sway_container *swayc,
456 double lx, double ly, 456 double ox, double oy,
457 struct wlr_surface **surface, double *sx, double *sy) { 457 struct wlr_surface **surface, double *sx, double *sy) {
458 list_t *queue = get_bfs_queue(); 458 if (!sway_assert(swayc->type == C_VIEW, "Expected a view")) {
459 if (!queue) {
460 return NULL; 459 return NULL;
461 } 460 }
461 struct sway_view *sview = swayc->sway_view;
462 double view_sx = ox - sview->x;
463 double view_sy = oy - sview->y;
462 464
463 list_add(queue, parent); 465 double _sx, _sy;
466 struct wlr_surface *_surface = NULL;
467 switch (sview->type) {
468 case SWAY_VIEW_XWAYLAND:
469 _surface = wlr_surface_surface_at(sview->surface,
470 view_sx, view_sy, &_sx, &_sy);
471 break;
472 case SWAY_VIEW_XDG_SHELL_V6:
473 // the top left corner of the sway container is the
474 // coordinate of the top left corner of the window geometry
475 view_sx += sview->wlr_xdg_surface_v6->geometry.x;
476 view_sy += sview->wlr_xdg_surface_v6->geometry.y;
477
478 _surface = wlr_xdg_surface_v6_surface_at(
479 sview->wlr_xdg_surface_v6,
480 view_sx, view_sy, &_sx, &_sy);
481 break;
482 case SWAY_VIEW_XDG_SHELL:
483 // the top left corner of the sway container is the
484 // coordinate of the top left corner of the window geometry
485 view_sx += sview->wlr_xdg_surface->geometry.x;
486 view_sy += sview->wlr_xdg_surface->geometry.y;
487
488 _surface = wlr_xdg_surface_surface_at(
489 sview->wlr_xdg_surface,
490 view_sx, view_sy, &_sx, &_sy);
491 break;
492 }
493 if (_surface) {
494 *sx = _sx;
495 *sy = _sy;
496 *surface = _surface;
497 }
498 return swayc;
499}
464 500
465 struct sway_container *swayc = NULL; 501/**
466 while (queue->length) { 502 * container_at for a container with layout L_TABBED.
467 swayc = queue->items[0]; 503 */
468 list_del(queue, 0); 504static struct sway_container *container_at_tabbed(struct sway_container *parent,
469 if (swayc->type == C_VIEW) { 505 double ox, double oy,
470 struct sway_view *sview = swayc->sway_view; 506 struct wlr_surface **surface, double *sx, double *sy) {
471 struct sway_container *soutput = container_parent(swayc, C_OUTPUT); 507 if (oy < parent->y || oy > parent->y + parent->height) {
472 struct wlr_box *output_box = 508 return NULL;
473 wlr_output_layout_get_box( 509 }
474 root_container.sway_root->output_layout, 510 struct sway_seat *seat = input_manager_current_seat(input_manager);
475 soutput->sway_output->wlr_output); 511
476 double ox = lx - output_box->x; 512 // Tab titles
477 double oy = ly - output_box->y; 513 int title_height = config->border_thickness * 2 + config->font_height;
478 double view_sx = ox - sview->x; 514 if (oy < parent->y + title_height) {
479 double view_sy = oy - sview->y; 515 int tab_width = parent->width / parent->children->length;
480 516 int child_index = (ox - parent->x) / tab_width;
481 double _sx, _sy; 517 if (child_index >= parent->children->length) {
482 struct wlr_surface *_surface; 518 child_index = parent->children->length - 1;
483 switch (sview->type) {
484 case SWAY_VIEW_XWAYLAND:
485 _surface = wlr_surface_surface_at(sview->surface,
486 view_sx, view_sy, &_sx, &_sy);
487 break;
488 case SWAY_VIEW_XDG_SHELL_V6:
489 // the top left corner of the sway container is the
490 // coordinate of the top left corner of the window geometry
491 view_sx += sview->wlr_xdg_surface_v6->geometry.x;
492 view_sy += sview->wlr_xdg_surface_v6->geometry.y;
493
494 _surface = wlr_xdg_surface_v6_surface_at(
495 sview->wlr_xdg_surface_v6,
496 view_sx, view_sy, &_sx, &_sy);
497 break;
498 case SWAY_VIEW_XDG_SHELL:
499 // the top left corner of the sway container is the
500 // coordinate of the top left corner of the window geometry
501 view_sx += sview->wlr_xdg_surface->geometry.x;
502 view_sy += sview->wlr_xdg_surface->geometry.y;
503
504 _surface = wlr_xdg_surface_surface_at(
505 sview->wlr_xdg_surface,
506 view_sx, view_sy, &_sx, &_sy);
507 break;
508 }
509 if (_surface) {
510 *sx = _sx;
511 *sy = _sy;
512 *surface = _surface;
513 return swayc;
514 }
515 // Check the view's decorations
516 struct wlr_box swayc_box = {
517 .x = swayc->x,
518 .y = swayc->y,
519 .width = swayc->width,
520 .height = swayc->height,
521 };
522 if (wlr_box_contains_point(&swayc_box, ox, oy)) {
523 return swayc;
524 }
525 } else {
526 list_cat(queue, swayc->children);
527 } 519 }
520 struct sway_container *child = parent->children->items[child_index];
521 return seat_get_focus_inactive(seat, child);
522 }
523
524 // Surfaces
525 struct sway_container *current = seat_get_active_child(seat, parent);
526
527 return container_at(current, ox, oy, surface, sx, sy);
528}
529
530/**
531 * container_at for a container with layout L_STACKED.
532 */
533static struct sway_container *container_at_stacked(
534 struct sway_container *parent, double ox, double oy,
535 struct wlr_surface **surface, double *sx, double *sy) {
536 // TODO
537 return NULL;
538}
539
540/**
541 * container_at for a container with layout L_HORIZ or L_VERT.
542 */
543static struct sway_container *container_at_linear(struct sway_container *parent,
544 double ox, double oy,
545 struct wlr_surface **surface, double *sx, double *sy) {
546 for (int i = 0; i < parent->children->length; ++i) {
547 struct sway_container *child = parent->children->items[i];
548 struct wlr_box box = {
549 .x = child->x,
550 .y = child->y,
551 .width = child->width,
552 .height = child->height,
553 };
554 if (wlr_box_contains_point(&box, ox, oy)) {
555 return container_at(child, ox, oy, surface, sx, sy);
556 }
557 }
558 return NULL;
559}
560
561struct sway_container *container_at(struct sway_container *parent,
562 double ox, double oy,
563 struct wlr_surface **surface, double *sx, double *sy) {
564 if (!sway_assert(parent->type >= C_WORKSPACE,
565 "Expected workspace or deeper")) {
566 return NULL;
567 }
568 if (parent->type == C_VIEW) {
569 return container_at_view(parent, ox, oy, surface, sx, sy);
570 }
571 if (!parent->children->length) {
572 return NULL;
573 }
574
575 switch (parent->layout) {
576 case L_HORIZ:
577 case L_VERT:
578 return container_at_linear(parent, ox, oy, surface, sx, sy);
579 case L_TABBED:
580 return container_at_tabbed(parent, ox, oy, surface, sx, sy);
581 case L_STACKED:
582 return container_at_stacked(parent, ox, oy, surface, sx, sy);
583 case L_FLOATING:
584 return NULL; // TODO
585 case L_NONE:
586 return NULL;
528 } 587 }
529 588
530 return NULL; 589 return NULL;
@@ -699,18 +758,91 @@ void container_calculate_title_height(struct sway_container *container) {
699 container->title_height = height; 758 container->title_height = height;
700} 759}
701 760
761/**
762 * Calculate and return the length of the concatenated child titles.
763 * An example concatenated title is: V[Terminal, Firefox]
764 * If buffer is not NULL, also populate the buffer with the concatenated title.
765 */
766static size_t concatenate_child_titles(struct sway_container *parent,
767 char *buffer) {
768 size_t len = 2; // V[
769 if (buffer) {
770 switch (parent->layout) {
771 case L_VERT:
772 strcpy(buffer, "V[");
773 break;
774 case L_HORIZ:
775 strcpy(buffer, "H[");
776 break;
777 case L_TABBED:
778 strcpy(buffer, "T[");
779 break;
780 case L_STACKED:
781 strcpy(buffer, "S[");
782 break;
783 case L_FLOATING:
784 strcpy(buffer, "F[");
785 break;
786 case L_NONE:
787 strcpy(buffer, "D[");
788 break;
789 }
790 }
791
792 for (int i = 0; i < parent->children->length; ++i) {
793 if (i != 0) {
794 len += 1;
795 if (buffer) {
796 strcat(buffer, " ");
797 }
798 }
799 struct sway_container *child = parent->children->items[i];
800 const char *identifier = NULL;
801 if (child->type == C_VIEW) {
802 identifier = view_get_class(child->sway_view);
803 if (!identifier) {
804 identifier = view_get_app_id(child->sway_view);
805 }
806 } else {
807 identifier = child->name;
808 }
809 if (identifier) {
810 len += strlen(identifier);
811 if (buffer) {
812 strcat(buffer, identifier);
813 }
814 } else {
815 len += 6;
816 if (buffer) {
817 strcat(buffer, "(null)");
818 }
819 }
820 }
821
822 len += 1;
823 if (buffer) {
824 strcat(buffer, "]");
825 }
826 return len;
827}
828
702void container_notify_child_title_changed(struct sway_container *container) { 829void container_notify_child_title_changed(struct sway_container *container) {
703 if (!container || container->type != C_CONTAINER) { 830 if (!container || container->type != C_CONTAINER) {
704 return; 831 return;
705 } 832 }
706 if (container->layout != L_TABBED && container->layout != L_STACKED) {
707 return;
708 }
709 if (container->formatted_title) { 833 if (container->formatted_title) {
710 free(container->formatted_title); 834 free(container->formatted_title);
711 } 835 }
712 // TODO: iterate children and concatenate their titles 836
713 container->formatted_title = strdup(""); 837 size_t len = concatenate_child_titles(container, NULL);
838 char *buffer = calloc(len + 1, sizeof(char));
839 if (!sway_assert(buffer, "Unable to allocate title string")) {
840 return;
841 }
842 concatenate_child_titles(container, buffer);
843
844 container->name = buffer;
845 container->formatted_title = buffer;
714 container_calculate_title_height(container); 846 container_calculate_title_height(container);
715 container_update_title_textures(container); 847 container_update_title_textures(container);
716 container_notify_child_title_changed(container->parent); 848 container_notify_child_title_changed(container->parent);