diff options
Diffstat (limited to 'sway/commands/layout.c')
-rw-r--r-- | sway/commands/layout.c | 105 |
1 files changed, 80 insertions, 25 deletions
diff --git a/sway/commands/layout.c b/sway/commands/layout.c index c446f1f9..f4e4dda9 100644 --- a/sway/commands/layout.c +++ b/sway/commands/layout.c | |||
@@ -1,3 +1,4 @@ | |||
1 | #include <stdbool.h> | ||
1 | #include <string.h> | 2 | #include <string.h> |
2 | #include <strings.h> | 3 | #include <strings.h> |
3 | #include "sway/commands.h" | 4 | #include "sway/commands.h" |
@@ -5,6 +6,26 @@ | |||
5 | #include "sway/tree/container.h" | 6 | #include "sway/tree/container.h" |
6 | #include "log.h" | 7 | #include "log.h" |
7 | 8 | ||
9 | static bool parse_layout_string(char *s, enum sway_container_layout *ptr) { | ||
10 | if (strcasecmp(s, "splith") == 0) { | ||
11 | *ptr = L_HORIZ; | ||
12 | } else if (strcasecmp(s, "splitv") == 0) { | ||
13 | *ptr = L_VERT; | ||
14 | } else if (strcasecmp(s, "tabbed") == 0) { | ||
15 | *ptr = L_TABBED; | ||
16 | } else if (strcasecmp(s, "stacking") == 0) { | ||
17 | *ptr = L_STACKED; | ||
18 | } else { | ||
19 | return false; | ||
20 | } | ||
21 | return true; | ||
22 | } | ||
23 | |||
24 | static const char* expected_syntax = | ||
25 | "Expected 'layout default|tabbed|stacking|splitv|splith' or " | ||
26 | "'layout toggle [split|all]' or " | ||
27 | "'layout toggle [split|tabbed|stacking|splitv|splith] [split|tabbed|stacking|splitv|splith]...'"; | ||
28 | |||
8 | struct cmd_results *cmd_layout(int argc, char **argv) { | 29 | struct cmd_results *cmd_layout(int argc, char **argv) { |
9 | struct cmd_results *error = NULL; | 30 | struct cmd_results *error = NULL; |
10 | if ((error = checkarg(argc, "layout", EXPECTED_MORE_THAN, 0))) { | 31 | if ((error = checkarg(argc, "layout", EXPECTED_MORE_THAN, 0))) { |
@@ -21,35 +42,69 @@ struct cmd_results *cmd_layout(int argc, char **argv) { | |||
21 | parent = parent->parent; | 42 | parent = parent->parent; |
22 | } | 43 | } |
23 | 44 | ||
24 | if (strcasecmp(argv[0], "default") == 0) { | 45 | enum sway_container_layout prev = parent->layout; |
25 | parent->layout = parent->prev_layout; | 46 | bool assigned_directly = parse_layout_string(argv[0], &parent->layout); |
26 | if (parent->layout == L_NONE) { | 47 | if (!assigned_directly) { |
27 | parent->layout = container_get_default_layout(parent); | 48 | if (strcasecmp(argv[0], "default") == 0) { |
28 | } | 49 | parent->layout = parent->prev_split_layout; |
29 | } else { | 50 | } else if (strcasecmp(argv[0], "toggle") == 0) { |
30 | if (parent->layout != L_TABBED && parent->layout != L_STACKED) { | 51 | if (argc == 1) { |
31 | parent->prev_layout = parent->layout; | 52 | parent->layout = |
32 | } | 53 | parent->layout == L_STACKED ? L_TABBED : |
33 | 54 | parent->layout == L_TABBED ? parent->prev_split_layout : L_STACKED; | |
34 | if (strcasecmp(argv[0], "splith") == 0) { | 55 | } else if (argc == 2) { |
35 | parent->layout = L_HORIZ; | 56 | if (strcasecmp(argv[1], "all") == 0) { |
36 | } else if (strcasecmp(argv[0], "splitv") == 0) { | 57 | parent->layout = |
37 | parent->layout = L_VERT; | 58 | parent->layout == L_HORIZ ? L_VERT : |
38 | } else if (strcasecmp(argv[0], "tabbed") == 0) { | 59 | parent->layout == L_VERT ? L_STACKED : |
39 | parent->layout = L_TABBED; | 60 | parent->layout == L_STACKED ? L_TABBED : L_HORIZ; |
40 | } else if (strcasecmp(argv[0], "stacking") == 0) { | 61 | } else if (strcasecmp(argv[1], "split") == 0) { |
41 | parent->layout = L_STACKED; | 62 | parent->layout = |
42 | } else if (strcasecmp(argv[0], "toggle") == 0 && argc == 2 && strcasecmp(argv[1], "split") == 0) { | 63 | parent->layout == L_HORIZ ? L_VERT : |
43 | if (parent->layout == L_HORIZ) { | 64 | parent->layout == L_VERT ? L_HORIZ : parent->prev_split_layout; |
44 | parent->layout = L_VERT; | 65 | } else { |
66 | return cmd_results_new(CMD_INVALID, "layout", expected_syntax); | ||
67 | } | ||
45 | } else { | 68 | } else { |
46 | parent->layout = L_HORIZ; | 69 | enum sway_container_layout parsed_layout; |
70 | int curr = 1; | ||
71 | for (; curr < argc; curr++) { | ||
72 | bool valid = parse_layout_string(argv[curr], &parsed_layout); | ||
73 | if ((valid && parsed_layout == parent->layout) || | ||
74 | (strcmp(argv[curr], "split") == 0 && | ||
75 | (parent->layout == L_VERT || parent->layout == L_HORIZ))) { | ||
76 | break; | ||
77 | } | ||
78 | } | ||
79 | for (int i = curr + 1; i != curr; ++i) { | ||
80 | // cycle round to find next valid layout | ||
81 | if (i >= argc) { | ||
82 | i = 1; | ||
83 | } | ||
84 | if (parse_layout_string(argv[i], &parent->layout)) { | ||
85 | break; | ||
86 | } else if (strcmp(argv[i], "split") == 0) { | ||
87 | parent->layout = | ||
88 | parent->layout == L_HORIZ ? L_VERT : | ||
89 | parent->layout == L_VERT ? L_HORIZ : parent->prev_split_layout; | ||
90 | break; | ||
91 | } // invalid layout strings are silently ignored | ||
92 | } | ||
47 | } | 93 | } |
94 | } else { | ||
95 | return cmd_results_new(CMD_INVALID, "layout", expected_syntax); | ||
48 | } | 96 | } |
49 | } | 97 | } |
50 | 98 | if (parent->layout == L_NONE) { | |
51 | container_notify_subtree_changed(parent); | 99 | parent->layout = container_get_default_layout(parent); |
52 | arrange_windows(parent); | 100 | } |
101 | if (prev != parent->layout) { | ||
102 | if (prev != L_TABBED && prev != L_STACKED) { | ||
103 | parent->prev_split_layout = prev; | ||
104 | } | ||
105 | container_notify_subtree_changed(parent); | ||
106 | arrange_windows(parent); | ||
107 | } | ||
53 | 108 | ||
54 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | 109 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); |
55 | } | 110 | } |