diff options
-rw-r--r-- | common/stringop.c | 14 | ||||
-rw-r--r-- | include/stringop.h | 5 | ||||
-rw-r--r-- | include/sway/tree/container.h | 6 | ||||
-rw-r--r-- | sway/commands/layout.c | 1 | ||||
-rw-r--r-- | sway/tree/container.c | 90 | ||||
-rw-r--r-- | sway/tree/layout.c | 32 | ||||
-rw-r--r-- | sway/tree/view.c | 34 |
7 files changed, 94 insertions, 88 deletions
diff --git a/common/stringop.c b/common/stringop.c index 4a37543d..d9ae9925 100644 --- a/common/stringop.c +++ b/common/stringop.c | |||
@@ -55,6 +55,20 @@ void strip_quotes(char *str) { | |||
55 | *end = '\0'; | 55 | *end = '\0'; |
56 | } | 56 | } |
57 | 57 | ||
58 | char *lenient_strcat(char *dest, const char *src) { | ||
59 | if (dest && src) { | ||
60 | return strcat(dest, src); | ||
61 | } | ||
62 | return dest; | ||
63 | } | ||
64 | |||
65 | char *lenient_strncat(char *dest, const char *src, size_t len) { | ||
66 | if (dest && src) { | ||
67 | return strncat(dest, src, len); | ||
68 | } | ||
69 | return dest; | ||
70 | } | ||
71 | |||
58 | // strcmp that also handles null pointers. | 72 | // strcmp that also handles null pointers. |
59 | int lenient_strcmp(char *a, char *b) { | 73 | int lenient_strcmp(char *a, char *b) { |
60 | if (a == b) { | 74 | if (a == b) { |
diff --git a/include/stringop.h b/include/stringop.h index 7c29a745..e7f58011 100644 --- a/include/stringop.h +++ b/include/stringop.h | |||
@@ -1,5 +1,6 @@ | |||
1 | #ifndef _SWAY_STRINGOP_H | 1 | #ifndef _SWAY_STRINGOP_H |
2 | #define _SWAY_STRINGOP_H | 2 | #define _SWAY_STRINGOP_H |
3 | #include <stdlib.h> | ||
3 | #include "list.h" | 4 | #include "list.h" |
4 | 5 | ||
5 | #if !HAVE_DECL_SETENV | 6 | #if !HAVE_DECL_SETENV |
@@ -14,6 +15,10 @@ char *strip_whitespace(char *str); | |||
14 | char *strip_comments(char *str); | 15 | char *strip_comments(char *str); |
15 | void strip_quotes(char *str); | 16 | void strip_quotes(char *str); |
16 | 17 | ||
18 | // strcat that does nothing if dest or src is NULL | ||
19 | char *lenient_strcat(char *dest, const char *src); | ||
20 | char *lenient_strncat(char *dest, const char *src, size_t len); | ||
21 | |||
17 | // strcmp that also handles null pointers. | 22 | // strcmp that also handles null pointers. |
18 | int lenient_strcmp(char *a, char *b); | 23 | int lenient_strcmp(char *a, char *b); |
19 | 24 | ||
diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h index 493c70e2..a5f591ce 100644 --- a/include/sway/tree/container.h +++ b/include/sway/tree/container.h | |||
@@ -216,7 +216,11 @@ void container_update_title_textures(struct sway_container *container); | |||
216 | */ | 216 | */ |
217 | void container_calculate_title_height(struct sway_container *container); | 217 | void container_calculate_title_height(struct sway_container *container); |
218 | 218 | ||
219 | void container_notify_child_title_changed(struct sway_container *container); | 219 | /** |
220 | * Notify a container that a tree modification has changed in its children, | ||
221 | * so the container can update its tree representation. | ||
222 | */ | ||
223 | void container_notify_subtree_changed(struct sway_container *container); | ||
220 | 224 | ||
221 | /** | 225 | /** |
222 | * Return the height of a regular title bar. | 226 | * Return the height of a regular title bar. |
diff --git a/sway/commands/layout.c b/sway/commands/layout.c index 58728f16..6b44b001 100644 --- a/sway/commands/layout.c +++ b/sway/commands/layout.c | |||
@@ -52,6 +52,7 @@ struct cmd_results *cmd_layout(int argc, char **argv) { | |||
52 | } | 52 | } |
53 | } | 53 | } |
54 | 54 | ||
55 | container_notify_subtree_changed(parent); | ||
55 | arrange_children_of(parent); | 56 | arrange_children_of(parent); |
56 | 57 | ||
57 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | 58 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); |
diff --git a/sway/tree/container.c b/sway/tree/container.c index 9cf18f61..f29a9adc 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include "sway/tree/view.h" | 21 | #include "sway/tree/view.h" |
22 | #include "sway/tree/workspace.h" | 22 | #include "sway/tree/workspace.h" |
23 | #include "log.h" | 23 | #include "log.h" |
24 | #include "stringop.h" | ||
24 | 25 | ||
25 | static list_t *bfs_queue; | 26 | static list_t *bfs_queue; |
26 | 27 | ||
@@ -774,42 +775,36 @@ void container_calculate_title_height(struct sway_container *container) { | |||
774 | } | 775 | } |
775 | 776 | ||
776 | /** | 777 | /** |
777 | * Calculate and return the length of the concatenated child titles. | 778 | * Calculate and return the length of the tree representation. |
778 | * An example concatenated title is: V[Terminal, Firefox] | 779 | * An example tree representation is: V[Terminal, Firefox] |
779 | * If buffer is not NULL, also populate the buffer with the concatenated title. | 780 | * If buffer is not NULL, also populate the buffer with the representation. |
780 | */ | 781 | */ |
781 | static size_t concatenate_child_titles(struct sway_container *parent, | 782 | static size_t get_tree_representation(struct sway_container *parent, char *buffer) { |
782 | char *buffer) { | 783 | size_t len = 2; |
783 | size_t len = 2; // V[ | 784 | switch (parent->layout) { |
784 | if (buffer) { | 785 | case L_VERT: |
785 | switch (parent->layout) { | 786 | lenient_strcat(buffer, "V["); |
786 | case L_VERT: | 787 | break; |
787 | strcpy(buffer, "V["); | 788 | case L_HORIZ: |
788 | break; | 789 | lenient_strcat(buffer, "H["); |
789 | case L_HORIZ: | 790 | break; |
790 | strcpy(buffer, "H["); | 791 | case L_TABBED: |
791 | break; | 792 | lenient_strcat(buffer, "T["); |
792 | case L_TABBED: | 793 | break; |
793 | strcpy(buffer, "T["); | 794 | case L_STACKED: |
794 | break; | 795 | lenient_strcat(buffer, "S["); |
795 | case L_STACKED: | 796 | break; |
796 | strcpy(buffer, "S["); | 797 | case L_FLOATING: |
797 | break; | 798 | lenient_strcat(buffer, "F["); |
798 | case L_FLOATING: | 799 | break; |
799 | strcpy(buffer, "F["); | 800 | case L_NONE: |
800 | break; | 801 | lenient_strcat(buffer, "D["); |
801 | case L_NONE: | 802 | break; |
802 | strcpy(buffer, "D["); | ||
803 | break; | ||
804 | } | ||
805 | } | 803 | } |
806 | |||
807 | for (int i = 0; i < parent->children->length; ++i) { | 804 | for (int i = 0; i < parent->children->length; ++i) { |
808 | if (i != 0) { | 805 | if (i != 0) { |
809 | len += 1; | 806 | ++len; |
810 | if (buffer) { | 807 | lenient_strcat(buffer, " "); |
811 | strcat(buffer, " "); | ||
812 | } | ||
813 | } | 808 | } |
814 | struct sway_container *child = parent->children->items[i]; | 809 | struct sway_container *child = parent->children->items[i]; |
815 | const char *identifier = NULL; | 810 | const char *identifier = NULL; |
@@ -819,48 +814,39 @@ static size_t concatenate_child_titles(struct sway_container *parent, | |||
819 | identifier = view_get_app_id(child->sway_view); | 814 | identifier = view_get_app_id(child->sway_view); |
820 | } | 815 | } |
821 | } else { | 816 | } else { |
822 | identifier = child->name; | 817 | identifier = child->formatted_title; |
823 | } | 818 | } |
824 | if (identifier) { | 819 | if (identifier) { |
825 | len += strlen(identifier); | 820 | len += strlen(identifier); |
826 | if (buffer) { | 821 | lenient_strcat(buffer, identifier); |
827 | strcat(buffer, identifier); | ||
828 | } | ||
829 | } else { | 822 | } else { |
830 | len += 6; | 823 | len += 6; |
831 | if (buffer) { | 824 | lenient_strcat(buffer, "(null)"); |
832 | strcat(buffer, "(null)"); | ||
833 | } | ||
834 | } | 825 | } |
835 | } | 826 | } |
836 | 827 | ++len; | |
837 | len += 1; | 828 | lenient_strcat(buffer, "]"); |
838 | if (buffer) { | ||
839 | strcat(buffer, "]"); | ||
840 | } | ||
841 | return len; | 829 | return len; |
842 | } | 830 | } |
843 | 831 | ||
844 | void container_notify_child_title_changed(struct sway_container *container) { | 832 | void container_notify_subtree_changed(struct sway_container *container) { |
845 | if (!container || container->type != C_CONTAINER) { | 833 | if (!container || container->type != C_CONTAINER) { |
846 | return; | 834 | return; |
847 | } | 835 | } |
848 | if (container->formatted_title) { | 836 | free(container->formatted_title); |
849 | free(container->formatted_title); | 837 | container->formatted_title = NULL; |
850 | } | ||
851 | 838 | ||
852 | size_t len = concatenate_child_titles(container, NULL); | 839 | size_t len = get_tree_representation(container, NULL); |
853 | char *buffer = calloc(len + 1, sizeof(char)); | 840 | char *buffer = calloc(len + 1, sizeof(char)); |
854 | if (!sway_assert(buffer, "Unable to allocate title string")) { | 841 | if (!sway_assert(buffer, "Unable to allocate title string")) { |
855 | return; | 842 | return; |
856 | } | 843 | } |
857 | concatenate_child_titles(container, buffer); | 844 | get_tree_representation(container, buffer); |
858 | 845 | ||
859 | container->name = buffer; | ||
860 | container->formatted_title = buffer; | 846 | container->formatted_title = buffer; |
861 | container_calculate_title_height(container); | 847 | container_calculate_title_height(container); |
862 | container_update_title_textures(container); | 848 | container_update_title_textures(container); |
863 | container_notify_child_title_changed(container->parent); | 849 | container_notify_subtree_changed(container->parent); |
864 | } | 850 | } |
865 | 851 | ||
866 | size_t container_titlebar_height() { | 852 | size_t container_titlebar_height() { |
diff --git a/sway/tree/layout.c b/sway/tree/layout.c index 91759f7b..21cec529 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c | |||
@@ -149,7 +149,7 @@ struct sway_container *container_remove_child(struct sway_container *child) { | |||
149 | } | 149 | } |
150 | } | 150 | } |
151 | child->parent = NULL; | 151 | child->parent = NULL; |
152 | container_notify_child_title_changed(parent); | 152 | container_notify_subtree_changed(parent); |
153 | 153 | ||
154 | return parent; | 154 | return parent; |
155 | } | 155 | } |
@@ -184,8 +184,8 @@ void container_move_to(struct sway_container *container, | |||
184 | container_sort_workspaces(new_parent); | 184 | container_sort_workspaces(new_parent); |
185 | seat_set_focus(seat, new_parent); | 185 | seat_set_focus(seat, new_parent); |
186 | } | 186 | } |
187 | container_notify_child_title_changed(old_parent); | 187 | container_notify_subtree_changed(old_parent); |
188 | container_notify_child_title_changed(new_parent); | 188 | container_notify_subtree_changed(new_parent); |
189 | if (old_parent) { | 189 | if (old_parent) { |
190 | if (old_parent->type == C_OUTPUT) { | 190 | if (old_parent->type == C_OUTPUT) { |
191 | arrange_output(old_parent); | 191 | arrange_output(old_parent); |
@@ -327,9 +327,11 @@ void container_move(struct sway_container *container, | |||
327 | current = container_parent(container, C_OUTPUT); | 327 | current = container_parent(container, C_OUTPUT); |
328 | } | 328 | } |
329 | 329 | ||
330 | if (parent != container_flatten(parent)) { | 330 | struct sway_container *new_parent = container_flatten(parent); |
331 | if (new_parent != parent) { | ||
331 | // Special case: we were the last one in this container, so flatten it | 332 | // Special case: we were the last one in this container, so flatten it |
332 | // and leave | 333 | // and leave |
334 | arrange_children_of(new_parent); | ||
333 | update_debug_tree(); | 335 | update_debug_tree(); |
334 | return; | 336 | return; |
335 | } | 337 | } |
@@ -497,8 +499,8 @@ void container_move(struct sway_container *container, | |||
497 | } | 499 | } |
498 | } | 500 | } |
499 | 501 | ||
500 | container_notify_child_title_changed(old_parent); | 502 | container_notify_subtree_changed(old_parent); |
501 | container_notify_child_title_changed(container->parent); | 503 | container_notify_subtree_changed(container->parent); |
502 | 504 | ||
503 | if (old_parent) { | 505 | if (old_parent) { |
504 | seat_set_focus(config->handler_context.seat, old_parent); | 506 | seat_set_focus(config->handler_context.seat, old_parent); |
@@ -586,11 +588,19 @@ static struct sway_container *get_swayc_in_output_direction( | |||
586 | if (ws->children->length > 0) { | 588 | if (ws->children->length > 0) { |
587 | switch (dir) { | 589 | switch (dir) { |
588 | case MOVE_LEFT: | 590 | case MOVE_LEFT: |
589 | // get most right child of new output | 591 | if (ws->layout == L_HORIZ || ws->layout == L_TABBED) { |
590 | return ws->children->items[ws->children->length-1]; | 592 | // get most right child of new output |
593 | return ws->children->items[ws->children->length-1]; | ||
594 | } else { | ||
595 | return seat_get_focus_inactive(seat, ws); | ||
596 | } | ||
591 | case MOVE_RIGHT: | 597 | case MOVE_RIGHT: |
592 | // get most left child of new output | 598 | if (ws->layout == L_HORIZ || ws->layout == L_TABBED) { |
593 | return ws->children->items[0]; | 599 | // get most left child of new output |
600 | return ws->children->items[0]; | ||
601 | } else { | ||
602 | return seat_get_focus_inactive(seat, ws); | ||
603 | } | ||
594 | case MOVE_UP: | 604 | case MOVE_UP: |
595 | case MOVE_DOWN: { | 605 | case MOVE_DOWN: { |
596 | struct sway_container *focused = | 606 | struct sway_container *focused = |
@@ -847,7 +857,7 @@ struct sway_container *container_split(struct sway_container *child, | |||
847 | container_add_child(cont, child); | 857 | container_add_child(cont, child); |
848 | } | 858 | } |
849 | 859 | ||
850 | container_notify_child_title_changed(cont); | 860 | container_notify_subtree_changed(cont); |
851 | 861 | ||
852 | return cont; | 862 | return cont; |
853 | } | 863 | } |
diff --git a/sway/tree/view.c b/sway/tree/view.c index 349a16a4..812d7740 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include "sway/tree/workspace.h" | 17 | #include "sway/tree/workspace.h" |
18 | #include "sway/config.h" | 18 | #include "sway/config.h" |
19 | #include "pango.h" | 19 | #include "pango.h" |
20 | #include "stringop.h" | ||
20 | 21 | ||
21 | void view_init(struct sway_view *view, enum sway_view_type type, | 22 | void view_init(struct sway_view *view, enum sway_view_type type, |
22 | const struct sway_view_impl *impl) { | 23 | const struct sway_view_impl *impl) { |
@@ -474,7 +475,7 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) { | |||
474 | } | 475 | } |
475 | 476 | ||
476 | view_update_title(view, false); | 477 | view_update_title(view, false); |
477 | container_notify_child_title_changed(view->swayc->parent); | 478 | container_notify_subtree_changed(view->swayc->parent); |
478 | view_execute_criteria(view); | 479 | view_execute_criteria(view); |
479 | 480 | ||
480 | container_damage_whole(cont); | 481 | container_damage_whole(cont); |
@@ -665,49 +666,35 @@ static size_t parse_title_format(struct sway_view *view, char *buffer) { | |||
665 | char *format = view->title_format; | 666 | char *format = view->title_format; |
666 | char *next = strchr(format, '%'); | 667 | char *next = strchr(format, '%'); |
667 | while (next) { | 668 | while (next) { |
668 | if (buffer) { | 669 | // Copy everything up to the % |
669 | // Copy everything up to the % | 670 | lenient_strncat(buffer, format, next - format); |
670 | strncat(buffer, format, next - format); | ||
671 | } | ||
672 | len += next - format; | 671 | len += next - format; |
673 | format = next; | 672 | format = next; |
674 | 673 | ||
675 | if (strncmp(next, "%title", 6) == 0) { | 674 | if (strncmp(next, "%title", 6) == 0) { |
676 | if (buffer && title) { | 675 | lenient_strcat(buffer, title); |
677 | strcat(buffer, title); | ||
678 | } | ||
679 | len += title_len; | 676 | len += title_len; |
680 | format += 6; | 677 | format += 6; |
681 | } else if (strncmp(next, "%class", 6) == 0) { | 678 | } else if (strncmp(next, "%class", 6) == 0) { |
682 | if (buffer && class) { | 679 | lenient_strcat(buffer, class); |
683 | strcat(buffer, class); | ||
684 | } | ||
685 | len += class_len; | 680 | len += class_len; |
686 | format += 6; | 681 | format += 6; |
687 | } else if (strncmp(next, "%instance", 9) == 0) { | 682 | } else if (strncmp(next, "%instance", 9) == 0) { |
688 | if (buffer && instance) { | 683 | lenient_strcat(buffer, instance); |
689 | strcat(buffer, instance); | ||
690 | } | ||
691 | len += instance_len; | 684 | len += instance_len; |
692 | format += 9; | 685 | format += 9; |
693 | } else if (strncmp(next, "%shell", 6) == 0) { | 686 | } else if (strncmp(next, "%shell", 6) == 0) { |
694 | if (buffer) { | 687 | lenient_strcat(buffer, shell); |
695 | strcat(buffer, shell); | ||
696 | } | ||
697 | len += shell_len; | 688 | len += shell_len; |
698 | format += 6; | 689 | format += 6; |
699 | } else { | 690 | } else { |
700 | if (buffer) { | 691 | lenient_strcat(buffer, "%"); |
701 | strcat(buffer, "%"); | ||
702 | } | ||
703 | ++format; | 692 | ++format; |
704 | ++len; | 693 | ++len; |
705 | } | 694 | } |
706 | next = strchr(format, '%'); | 695 | next = strchr(format, '%'); |
707 | } | 696 | } |
708 | if (buffer) { | 697 | lenient_strcat(buffer, format); |
709 | strcat(buffer, format); | ||
710 | } | ||
711 | len += strlen(format); | 698 | len += strlen(format); |
712 | 699 | ||
713 | return len; | 700 | return len; |
@@ -763,7 +750,6 @@ void view_update_title(struct sway_view *view, bool force) { | |||
763 | } | 750 | } |
764 | container_calculate_title_height(view->swayc); | 751 | container_calculate_title_height(view->swayc); |
765 | container_update_title_textures(view->swayc); | 752 | container_update_title_textures(view->swayc); |
766 | container_notify_child_title_changed(view->swayc->parent); | ||
767 | config_update_font_height(false); | 753 | config_update_font_height(false); |
768 | } | 754 | } |
769 | 755 | ||