diff options
-rw-r--r-- | include/commands.h | 16 | ||||
-rw-r--r-- | include/config.h | 4 | ||||
-rw-r--r-- | include/container.h | 139 | ||||
-rw-r--r-- | include/stringop.h | 2 | ||||
-rw-r--r-- | include/workspace.h | 16 | ||||
-rw-r--r-- | sway/commands.c | 167 | ||||
-rw-r--r-- | sway/config.c | 25 | ||||
-rw-r--r-- | sway/container.c | 415 | ||||
-rw-r--r-- | sway/handlers.c | 12 | ||||
-rw-r--r-- | sway/ipc.c | 4 | ||||
-rw-r--r-- | sway/stringop.c | 2 | ||||
-rw-r--r-- | sway/workspace.c | 149 |
12 files changed, 370 insertions, 581 deletions
diff --git a/include/commands.h b/include/commands.h index 69ab1380..5c87be51 100644 --- a/include/commands.h +++ b/include/commands.h | |||
@@ -3,21 +3,19 @@ | |||
3 | #include <stdbool.h> | 3 | #include <stdbool.h> |
4 | #include "config.h" | 4 | #include "config.h" |
5 | 5 | ||
6 | typedef enum cmd_status { | ||
7 | CMD_SUCCESS, | ||
8 | CMD_FAILURE, | ||
9 | CMD_DEFER, | ||
10 | } sway_cmd(char *criteria, int argc, char **argv); | ||
11 | |||
12 | struct cmd_handler { | 6 | struct cmd_handler { |
13 | const char*command; | 7 | char *command; |
14 | sway_cmd *handle; | 8 | enum cmd_status { |
9 | CMD_SUCCESS, | ||
10 | CMD_FAILURE, | ||
11 | CMD_DEFER, | ||
12 | } (*handle)(int argc, char **argv); | ||
15 | }; | 13 | }; |
16 | 14 | ||
17 | enum cmd_status handle_command(char *command); | 15 | enum cmd_status handle_command(char *command); |
18 | // Handles commands during config | 16 | // Handles commands during config |
19 | enum cmd_status config_command(char *command); | 17 | enum cmd_status config_command(char *command); |
20 | 18 | ||
21 | void remove_view_from_scratchpad(swayc_t *view); | 19 | void remove_view_from_scratchpad(); |
22 | 20 | ||
23 | #endif | 21 | #endif |
diff --git a/include/config.h b/include/config.h index 04db3e5c..676218c8 100644 --- a/include/config.h +++ b/include/config.h | |||
@@ -63,10 +63,6 @@ bool load_config(const char *file); | |||
63 | bool read_config(FILE *file, bool is_active); | 63 | bool read_config(FILE *file, bool is_active); |
64 | char *do_var_replacement(char *str); | 64 | char *do_var_replacement(char *str); |
65 | 65 | ||
66 | // Find workspace_output from config by workspace or output name | ||
67 | struct workspace_output *wsop_find_workspace(const char *); | ||
68 | struct workspace_output *wsop_find_output(const char *); | ||
69 | |||
70 | extern struct sway_config *config; | 66 | extern struct sway_config *config; |
71 | 67 | ||
72 | #endif | 68 | #endif |
diff --git a/include/container.h b/include/container.h index b164af95..ae9a9fc5 100644 --- a/include/container.h +++ b/include/container.h | |||
@@ -2,25 +2,29 @@ | |||
2 | #define _SWAY_CONTAINER_H | 2 | #define _SWAY_CONTAINER_H |
3 | #include <wlc/wlc.h> | 3 | #include <wlc/wlc.h> |
4 | typedef struct sway_container swayc_t; | 4 | typedef struct sway_container swayc_t; |
5 | |||
5 | #include "layout.h" | 6 | #include "layout.h" |
6 | 7 | ||
7 | enum swayc_types { | 8 | enum swayc_types{ |
8 | C_ROOT = 1 << 0, | 9 | C_ROOT, |
9 | C_OUTPUT = 1 << 1, | 10 | C_OUTPUT, |
10 | C_WORKSPACE = 1 << 2, | 11 | C_WORKSPACE, |
11 | C_CONTAINER = 1 << 3, | 12 | C_CONTAINER, |
12 | C_VIEW = 1 << 4, | 13 | C_VIEW, |
13 | C_TYPES = 5, | 14 | // Keep last |
15 | C_TYPES, | ||
14 | }; | 16 | }; |
15 | 17 | ||
16 | enum swayc_layouts { | 18 | |
17 | L_NONE = 1 << 0, | 19 | enum swayc_layouts{ |
18 | L_HORIZ = 1 << 1, | 20 | L_NONE, |
19 | L_VERT = 1 << 2, | 21 | L_HORIZ, |
20 | L_STACKED = 1 << 3, | 22 | L_VERT, |
21 | L_TABBED = 1 << 4, | 23 | L_STACKED, |
22 | L_FLOATING = 1 << 5, | 24 | L_TABBED, |
23 | L_LAYOUTS = 6, | 25 | L_FLOATING, |
26 | // Keep last | ||
27 | L_LAYOUTS, | ||
24 | }; | 28 | }; |
25 | 29 | ||
26 | struct sway_container { | 30 | struct sway_container { |
@@ -31,16 +35,13 @@ struct sway_container { | |||
31 | 35 | ||
32 | // Not including borders or margins | 36 | // Not including borders or margins |
33 | double width, height; | 37 | double width, height; |
34 | double x, y; | ||
35 | 38 | ||
36 | // Used for setting floating geometry | 39 | // Used for setting floating geometry |
37 | int desired_width, desired_height; | 40 | int desired_width, desired_height; |
38 | 41 | ||
39 | enum visibility_mask { | 42 | double x, y; |
40 | INVISIBLE = false, | ||
41 | VISIBLE = true, | ||
42 | } visible; | ||
43 | 43 | ||
44 | bool visible; | ||
44 | bool is_floating; | 45 | bool is_floating; |
45 | bool is_focused; | 46 | bool is_focused; |
46 | 47 | ||
@@ -55,120 +56,70 @@ struct sway_container { | |||
55 | struct sway_container *focused; | 56 | struct sway_container *focused; |
56 | }; | 57 | }; |
57 | 58 | ||
58 | // swayc Creation | 59 | enum visibility_mask { |
60 | VISIBLE = true | ||
61 | } visible; | ||
59 | 62 | ||
60 | /* Creates and returns new, or an already created output. | 63 | // Container Creation |
61 | * If it creates a new output, it also creates a workspace using | ||
62 | * `new_workspace(outputname, NULL);` */ | ||
63 | swayc_t *new_output(wlc_handle handle); | ||
64 | 64 | ||
65 | /* Creates workspace with given name, under given output. | 65 | swayc_t *new_output(wlc_handle handle); |
66 | * If workspace with that name already exists, returns that workspace | ||
67 | * If name is NULL, it will choose a name automatically. | ||
68 | * If output is NULL, it will choose an output automatically. */ | ||
69 | swayc_t *new_workspace(swayc_t *output, const char *name); | 66 | swayc_t *new_workspace(swayc_t *output, const char *name); |
70 | |||
71 | // Creates container Around child (parent child) -> (parent (container child)) | 67 | // Creates container Around child (parent child) -> (parent (container child)) |
72 | swayc_t *new_container(swayc_t *child, enum swayc_layouts layout); | 68 | swayc_t *new_container(swayc_t *child, enum swayc_layouts layout); |
73 | |||
74 | // Creates view as a sibling of current focused container, or as child of a workspace | 69 | // Creates view as a sibling of current focused container, or as child of a workspace |
75 | swayc_t *new_view(swayc_t *sibling, wlc_handle handle); | 70 | swayc_t *new_view(swayc_t *sibling, wlc_handle handle); |
76 | |||
77 | // Creates view as a new floating view which is in the active workspace | 71 | // Creates view as a new floating view which is in the active workspace |
78 | swayc_t *new_floating_view(wlc_handle handle); | 72 | swayc_t *new_floating_view(wlc_handle handle); |
79 | 73 | ||
80 | // Container Destroying | 74 | // Container Destroying |
81 | // Destroys output and moves workspaces to another output | ||
82 | swayc_t *destroy_output(swayc_t *output); | ||
83 | 75 | ||
76 | swayc_t *destroy_output(swayc_t *output); | ||
84 | // Destroys workspace if empty and returns parent pointer, else returns NULL | 77 | // Destroys workspace if empty and returns parent pointer, else returns NULL |
85 | swayc_t *destroy_workspace(swayc_t *workspace); | 78 | swayc_t *destroy_workspace(swayc_t *workspace); |
86 | |||
87 | // Destroyes container and all parent container if they are empty, returns | 79 | // Destroyes container and all parent container if they are empty, returns |
88 | // topmost non-empty parent. returns NULL otherwise | 80 | // topmost non-empty parent. returns NULL otherwise |
89 | swayc_t *destroy_container(swayc_t *container); | 81 | swayc_t *destroy_container(swayc_t *container); |
90 | |||
91 | // Destroys view and all empty parent containers. return topmost non-empty | 82 | // Destroys view and all empty parent containers. return topmost non-empty |
92 | // parent | 83 | // parent |
93 | swayc_t *destroy_view(swayc_t *view); | 84 | swayc_t *destroy_view(swayc_t *view); |
94 | 85 | ||
95 | // Container Mapping and testing functions | 86 | // Container Lookup |
96 | typedef bool swayc_test_func(swayc_t *view, void *data); | ||
97 | typedef void swayc_map_func(swayc_t *view, void *data); | ||
98 | |||
99 | // Returns the first swayc that matches test() | ||
100 | swayc_t *swayc_by_test_r(swayc_t *root, swayc_test_func test, void *data); | ||
101 | swayc_t *swayc_by_test(swayc_test_func test, void *data); | ||
102 | |||
103 | // Calls func for all children. | ||
104 | void swayc_map_r(swayc_t *root, swayc_map_func func, void *data); | ||
105 | void swayc_map(swayc_map_func func, void *data); | ||
106 | |||
107 | |||
108 | // Call func on container if test passes | ||
109 | void swayc_map_by_test_r(swayc_t *root, | ||
110 | swayc_map_func func, swayc_test_func test, | ||
111 | void *funcdata, void *testdata); | ||
112 | void swayc_map_by_test( | ||
113 | swayc_map_func func, swayc_test_func test, | ||
114 | void *funcdata, void *testdata); | ||
115 | |||
116 | // Map functions | ||
117 | swayc_map_func set_gaps; | ||
118 | swayc_map_func add_gaps; | ||
119 | |||
120 | // Test functions | ||
121 | // generic swayc tests | ||
122 | swayc_test_func test_name; | ||
123 | swayc_test_func test_name_regex; | ||
124 | swayc_test_func test_layout; | ||
125 | swayc_test_func test_type; | ||
126 | swayc_test_func test_visibility; | ||
127 | swayc_test_func test_handle; | ||
128 | |||
129 | // C_VIEW tests | ||
130 | // See wlc_view_*_bit enums | ||
131 | swayc_test_func test_view_state; | ||
132 | swayc_test_func test_view_type; | ||
133 | swayc_test_func test_view_title; | ||
134 | swayc_test_func test_view_class; | ||
135 | swayc_test_func test_view_appid; | ||
136 | swayc_test_func test_view_title_regex; | ||
137 | swayc_test_func test_view_class_regex; | ||
138 | swayc_test_func test_view_appid_regex; | ||
139 | |||
140 | // functions for test_*_regex | ||
141 | void *compile_regex(const char *regex); | ||
142 | void free_regex(void *); | ||
143 | |||
144 | // these take a NULL terminated array of test_list struct. | ||
145 | struct test_list { swayc_test_func *test; void *data ; }; | ||
146 | swayc_test_func test_and; | ||
147 | swayc_test_func test_or; | ||
148 | 87 | ||
88 | swayc_t *swayc_by_test(swayc_t *container, bool (*test)(swayc_t *view, void *data), void *data); | ||
149 | swayc_t *swayc_parent_by_type(swayc_t *container, enum swayc_types); | 89 | swayc_t *swayc_parent_by_type(swayc_t *container, enum swayc_types); |
150 | swayc_t *swayc_parent_by_layout(swayc_t *container, enum swayc_layouts); | 90 | swayc_t *swayc_parent_by_layout(swayc_t *container, enum swayc_layouts); |
151 | // Follow focused until type/layout | 91 | // Follow focused until type/layout |
152 | swayc_t *swayc_focus_by_type(swayc_t *container, enum swayc_types); | 92 | swayc_t *swayc_focus_by_type(swayc_t *container, enum swayc_types); |
153 | swayc_t *swayc_focus_by_layout(swayc_t *container, enum swayc_layouts); | 93 | swayc_t *swayc_focus_by_layout(swayc_t *container, enum swayc_layouts); |
154 | 94 | ||
95 | |||
96 | swayc_t *swayc_by_handle(wlc_handle handle); | ||
97 | swayc_t *swayc_by_name(const char *name); | ||
155 | swayc_t *swayc_active_output(void); | 98 | swayc_t *swayc_active_output(void); |
156 | swayc_t *swayc_active_workspace(void); | 99 | swayc_t *swayc_active_workspace(void); |
157 | swayc_t *swayc_active_workspace_for(swayc_t *view); | 100 | swayc_t *swayc_active_workspace_for(swayc_t *view); |
158 | 101 | ||
159 | // Container information | 102 | // Container information |
160 | // if `parent` is the parent of `child` | 103 | |
104 | bool swayc_is_fullscreen(swayc_t *view); | ||
105 | bool swayc_is_active(swayc_t *view); | ||
106 | // Is `parent` the parent of `child` | ||
161 | bool swayc_is_parent_of(swayc_t *parent, swayc_t *child); | 107 | bool swayc_is_parent_of(swayc_t *parent, swayc_t *child); |
162 | // If `child` is a child of `parent` | 108 | // Is `child` a child of `parent` |
163 | bool swayc_is_child_of(swayc_t *child, swayc_t *parent); | 109 | bool swayc_is_child_of(swayc_t *child, swayc_t *parent); |
164 | // Return gap of specified container | 110 | // Return gap of specified container |
165 | int swayc_gap(swayc_t *container); | 111 | int swayc_gap(swayc_t *container); |
166 | 112 | ||
167 | bool swayc_is_fullscreen(swayc_t *view); | 113 | // Mapping functions |
168 | bool swayc_is_active(swayc_t *view); | 114 | |
115 | void container_map(swayc_t *, void (*f)(swayc_t *, void *), void *); | ||
169 | 116 | ||
117 | // Mappings | ||
118 | void set_view_visibility(swayc_t *view, void *data); | ||
119 | // Set or add to gaps | ||
120 | void set_gaps(swayc_t *view, void *amount); | ||
121 | void add_gaps(swayc_t *view, void *amount); | ||
170 | 122 | ||
171 | // Specialized mapping functions | ||
172 | void update_visibility(swayc_t *container); | 123 | void update_visibility(swayc_t *container); |
173 | 124 | ||
174 | #endif | 125 | #endif |
diff --git a/include/stringop.h b/include/stringop.h index 6e80e729..dde50f13 100644 --- a/include/stringop.h +++ b/include/stringop.h | |||
@@ -19,7 +19,7 @@ void free_argv(int argc, char **argv); | |||
19 | char *code_strchr(const char *string, char delimiter); | 19 | char *code_strchr(const char *string, char delimiter); |
20 | char *code_strstr(const char *haystack, const char *needle); | 20 | char *code_strstr(const char *haystack, const char *needle); |
21 | int unescape_string(char *string); | 21 | int unescape_string(char *string); |
22 | char *join_args(int argc, char **argv); | 22 | char *join_args(char **argv, int argc); |
23 | char *join_list(list_t *list, char *separator); | 23 | char *join_list(list_t *list, char *separator); |
24 | 24 | ||
25 | char *strdup(const char *); | 25 | char *strdup(const char *); |
diff --git a/include/workspace.h b/include/workspace.h index 3a63ea38..7343b055 100644 --- a/include/workspace.h +++ b/include/workspace.h | |||
@@ -7,17 +7,13 @@ | |||
7 | 7 | ||
8 | extern char *prev_workspace_name; | 8 | extern char *prev_workspace_name; |
9 | 9 | ||
10 | // Search for available workspace name on output from config | 10 | char *workspace_next_name(void); |
11 | const char *workspace_output_open_name(swayc_t *output); | 11 | swayc_t *workspace_create(const char*); |
12 | // Search for any available workspace name | ||
13 | const char *workspace_next_name(void); | ||
14 | |||
15 | |||
16 | swayc_t *workspace_by_name(const char*); | 12 | swayc_t *workspace_by_name(const char*); |
17 | void workspace_switch(swayc_t*); | 13 | void workspace_switch(swayc_t*); |
18 | swayc_t *workspace_output_next(void); | 14 | swayc_t *workspace_output_next(); |
19 | swayc_t *workspace_next(void); | 15 | swayc_t *workspace_next(); |
20 | swayc_t *workspace_output_prev(void); | 16 | swayc_t *workspace_output_prev(); |
21 | swayc_t *workspace_prev(void); | 17 | swayc_t *workspace_prev(); |
22 | 18 | ||
23 | #endif | 19 | #endif |
diff --git a/sway/commands.c b/sway/commands.c index 3ed0c8db..e79746ae 100644 --- a/sway/commands.c +++ b/sway/commands.c | |||
@@ -21,35 +21,6 @@ | |||
21 | swayc_t *sp_view; | 21 | swayc_t *sp_view; |
22 | int sp_index = 0; | 22 | int sp_index = 0; |
23 | 23 | ||
24 | // Commands | ||
25 | static sway_cmd cmd_bindsym; | ||
26 | static sway_cmd cmd_orientation; | ||
27 | static sway_cmd cmd_exec; | ||
28 | static sway_cmd cmd_exec_always; | ||
29 | static sway_cmd cmd_exit; | ||
30 | static sway_cmd cmd_floating; | ||
31 | static sway_cmd cmd_floating_mod; | ||
32 | static sway_cmd cmd_focus; | ||
33 | static sway_cmd cmd_focus_follows_mouse; | ||
34 | static sway_cmd cmd_for_window; | ||
35 | static sway_cmd cmd_fullscreen; | ||
36 | static sway_cmd cmd_gaps; | ||
37 | static sway_cmd cmd_kill; | ||
38 | static sway_cmd cmd_layout; | ||
39 | static sway_cmd cmd_log_colors; | ||
40 | static sway_cmd cmd_mode; | ||
41 | static sway_cmd cmd_move; | ||
42 | static sway_cmd cmd_output; | ||
43 | static sway_cmd cmd_reload; | ||
44 | static sway_cmd cmd_resize; | ||
45 | static sway_cmd cmd_scratchpad; | ||
46 | static sway_cmd cmd_set; | ||
47 | static sway_cmd cmd_split; | ||
48 | static sway_cmd cmd_splith; | ||
49 | static sway_cmd cmd_splitv; | ||
50 | static sway_cmd cmd_workspace; | ||
51 | static sway_cmd cmd_ws_auto_back_and_forth; | ||
52 | |||
53 | static struct modifier_key { | 24 | static struct modifier_key { |
54 | char *name; | 25 | char *name; |
55 | uint32_t mod; | 26 | uint32_t mod; |
@@ -123,7 +94,7 @@ static int bindsym_sort(const void *_lbind, const void *_rbind) { | |||
123 | return (rbind->keys->length + rmod) - (lbind->keys->length + lmod); | 94 | return (rbind->keys->length + rmod) - (lbind->keys->length + lmod); |
124 | } | 95 | } |
125 | 96 | ||
126 | enum cmd_status cmd_bindsym(char *criteria, int argc, char **argv) { | 97 | static enum cmd_status cmd_bindsym(int argc, char **argv) { |
127 | if (!checkarg(argc, "bindsym", EXPECTED_MORE_THAN, 1) | 98 | if (!checkarg(argc, "bindsym", EXPECTED_MORE_THAN, 1) |
128 | || !config->reading) { | 99 | || !config->reading) { |
129 | return CMD_FAILURE; | 100 | return CMD_FAILURE; |
@@ -132,7 +103,7 @@ enum cmd_status cmd_bindsym(char *criteria, int argc, char **argv) { | |||
132 | struct sway_binding *binding = malloc(sizeof(struct sway_binding)); | 103 | struct sway_binding *binding = malloc(sizeof(struct sway_binding)); |
133 | binding->keys = create_list(); | 104 | binding->keys = create_list(); |
134 | binding->modifiers = 0; | 105 | binding->modifiers = 0; |
135 | binding->command = join_args(argc - 1, argv + 1); | 106 | binding->command = join_args(argv + 1, argc - 1); |
136 | 107 | ||
137 | list_t *split = split_string(argv[0], "+"); | 108 | list_t *split = split_string(argv[0], "+"); |
138 | int i; | 109 | int i; |
@@ -173,7 +144,7 @@ enum cmd_status cmd_bindsym(char *criteria, int argc, char **argv) { | |||
173 | return CMD_SUCCESS; | 144 | return CMD_SUCCESS; |
174 | } | 145 | } |
175 | 146 | ||
176 | enum cmd_status cmd_exec_always(char *criteria, int argc, char **argv) { | 147 | static enum cmd_status cmd_exec_always(int argc, char **argv) { |
177 | if (!checkarg(argc, "exec_always", EXPECTED_MORE_THAN, 0)) { | 148 | if (!checkarg(argc, "exec_always", EXPECTED_MORE_THAN, 0)) { |
178 | return CMD_FAILURE; | 149 | return CMD_FAILURE; |
179 | } | 150 | } |
@@ -189,7 +160,7 @@ enum cmd_status cmd_exec_always(char *criteria, int argc, char **argv) { | |||
189 | } | 160 | } |
190 | /* Child process */ | 161 | /* Child process */ |
191 | if (pid == 0) { | 162 | if (pid == 0) { |
192 | char *args = join_args(argc, argv); | 163 | char *args = join_args(argv, argc); |
193 | sway_log(L_DEBUG, "Executing %s", args); | 164 | sway_log(L_DEBUG, "Executing %s", args); |
194 | execl("/bin/sh", "sh", "-c", args, (char *)NULL); | 165 | execl("/bin/sh", "sh", "-c", args, (char *)NULL); |
195 | /* Execl doesnt return unless failure */ | 166 | /* Execl doesnt return unless failure */ |
@@ -201,17 +172,17 @@ enum cmd_status cmd_exec_always(char *criteria, int argc, char **argv) { | |||
201 | return CMD_SUCCESS; | 172 | return CMD_SUCCESS; |
202 | } | 173 | } |
203 | 174 | ||
204 | enum cmd_status cmd_exec(char *criteria, int argc, char **argv) { | 175 | static enum cmd_status cmd_exec(int argc, char **argv) { |
205 | if (!config->active) { | 176 | if (!config->active) { |
206 | return CMD_DEFER; | 177 | return CMD_DEFER; |
207 | } | 178 | } |
208 | if (config->reloading) { | 179 | if (config->reloading) { |
209 | char *args = join_args(argc, argv); | 180 | char *args = join_args(argv, argc); |
210 | sway_log(L_DEBUG, "Ignoring 'exec %s' due to reload", args); | 181 | sway_log(L_DEBUG, "Ignoring 'exec %s' due to reload", args); |
211 | free(args); | 182 | free(args); |
212 | return CMD_SUCCESS; | 183 | return CMD_SUCCESS; |
213 | } | 184 | } |
214 | return cmd_exec_always(criteria, argc, argv); | 185 | return cmd_exec_always(argc, argv); |
215 | } | 186 | } |
216 | 187 | ||
217 | static void kill_views(swayc_t *container, void *data) { | 188 | static void kill_views(swayc_t *container, void *data) { |
@@ -220,19 +191,18 @@ static void kill_views(swayc_t *container, void *data) { | |||
220 | } | 191 | } |
221 | } | 192 | } |
222 | 193 | ||
223 | enum cmd_status cmd_exit(char *criteria, int argc, char **argv) { | 194 | static enum cmd_status cmd_exit(int argc, char **argv) { |
224 | (void) argv; | ||
225 | if (!checkarg(argc, "exit", EXPECTED_EQUAL_TO, 0) | 195 | if (!checkarg(argc, "exit", EXPECTED_EQUAL_TO, 0) |
226 | || config->reading || !config->active) { | 196 | || config->reading || !config->active) { |
227 | return CMD_FAILURE; | 197 | return CMD_FAILURE; |
228 | } | 198 | } |
229 | // Close all views | 199 | // Close all views |
230 | swayc_map(kill_views, NULL); | 200 | container_map(&root_container, kill_views, NULL); |
231 | sway_terminate(); | 201 | sway_terminate(); |
232 | return CMD_SUCCESS; | 202 | return CMD_SUCCESS; |
233 | } | 203 | } |
234 | 204 | ||
235 | enum cmd_status cmd_floating(char *criteria, int argc, char **argv) { | 205 | static enum cmd_status cmd_floating(int argc, char **argv) { |
236 | if (!checkarg(argc, "floating", EXPECTED_EQUAL_TO, 1) | 206 | if (!checkarg(argc, "floating", EXPECTED_EQUAL_TO, 1) |
237 | || config->reading || !config->active) { | 207 | || config->reading || !config->active) { |
238 | return CMD_FAILURE; | 208 | return CMD_FAILURE; |
@@ -294,7 +264,7 @@ enum cmd_status cmd_floating(char *criteria, int argc, char **argv) { | |||
294 | return CMD_SUCCESS; | 264 | return CMD_SUCCESS; |
295 | } | 265 | } |
296 | 266 | ||
297 | enum cmd_status cmd_floating_mod(char *criteria, int argc, char **argv) { | 267 | static enum cmd_status cmd_floating_mod(int argc, char **argv) { |
298 | if (!checkarg(argc, "floating_modifier", EXPECTED_EQUAL_TO, 1) | 268 | if (!checkarg(argc, "floating_modifier", EXPECTED_EQUAL_TO, 1) |
299 | || !config->reading) { | 269 | || !config->reading) { |
300 | return CMD_FAILURE; | 270 | return CMD_FAILURE; |
@@ -319,7 +289,7 @@ enum cmd_status cmd_floating_mod(char *criteria, int argc, char **argv) { | |||
319 | return CMD_SUCCESS; | 289 | return CMD_SUCCESS; |
320 | } | 290 | } |
321 | 291 | ||
322 | enum cmd_status cmd_focus(char *criteria, int argc, char **argv) { | 292 | static enum cmd_status cmd_focus(int argc, char **argv) { |
323 | static int floating_toggled_index = 0; | 293 | static int floating_toggled_index = 0; |
324 | static int tiled_toggled_index = 0; | 294 | static int tiled_toggled_index = 0; |
325 | if (!checkarg(argc, "focus", EXPECTED_EQUAL_TO, 1) | 295 | if (!checkarg(argc, "focus", EXPECTED_EQUAL_TO, 1) |
@@ -377,7 +347,7 @@ enum cmd_status cmd_focus(char *criteria, int argc, char **argv) { | |||
377 | return CMD_SUCCESS; | 347 | return CMD_SUCCESS; |
378 | } | 348 | } |
379 | 349 | ||
380 | enum cmd_status cmd_focus_follows_mouse(char *criteria, int argc, char **argv) { | 350 | static enum cmd_status cmd_focus_follows_mouse(int argc, char **argv) { |
381 | if (!checkarg(argc, "focus_follows_mouse", EXPECTED_EQUAL_TO, 1)) { | 351 | if (!checkarg(argc, "focus_follows_mouse", EXPECTED_EQUAL_TO, 1)) { |
382 | return CMD_FAILURE; | 352 | return CMD_FAILURE; |
383 | } | 353 | } |
@@ -386,21 +356,6 @@ enum cmd_status cmd_focus_follows_mouse(char *criteria, int argc, char **argv) { | |||
386 | return CMD_SUCCESS; | 356 | return CMD_SUCCESS; |
387 | } | 357 | } |
388 | 358 | ||
389 | static void debug_for_window(swayc_t *view, void *data) { | ||
390 | layout_log(view, 0); | ||
391 | } | ||
392 | |||
393 | enum cmd_status cmd_for_window(char *criteria, int argc, char **argv) { | ||
394 | if (!checkarg(argc, "for_window", EXPECTED_AT_LEAST, 1)) { | ||
395 | return CMD_FAILURE; | ||
396 | } | ||
397 | //TODO | ||
398 | void *re = compile_regex(argv[0]); | ||
399 | swayc_map_by_test(debug_for_window, test_view_title_regex, NULL, re); | ||
400 | free_regex(re); | ||
401 | return CMD_FAILURE; | ||
402 | } | ||
403 | |||
404 | static void hide_view_in_scratchpad(swayc_t *sp_view) { | 359 | static void hide_view_in_scratchpad(swayc_t *sp_view) { |
405 | if(sp_view == NULL) { | 360 | if(sp_view == NULL) { |
406 | return; | 361 | return; |
@@ -417,7 +372,7 @@ static void hide_view_in_scratchpad(swayc_t *sp_view) { | |||
417 | set_focused_container(container_under_pointer()); | 372 | set_focused_container(container_under_pointer()); |
418 | } | 373 | } |
419 | 374 | ||
420 | enum cmd_status cmd_mode(char *criteria, int argc, char **argv) { | 375 | static enum cmd_status cmd_mode(int argc, char **argv) { |
421 | if (!checkarg(argc, "move", EXPECTED_AT_LEAST, 1)) { | 376 | if (!checkarg(argc, "move", EXPECTED_AT_LEAST, 1)) { |
422 | return CMD_FAILURE; | 377 | return CMD_FAILURE; |
423 | } | 378 | } |
@@ -426,7 +381,7 @@ enum cmd_status cmd_mode(char *criteria, int argc, char **argv) { | |||
426 | return CMD_FAILURE; | 381 | return CMD_FAILURE; |
427 | } | 382 | } |
428 | 383 | ||
429 | char *mode_name = join_args(argc - mode_make, argv); | 384 | char *mode_name = join_args(argv, argc - mode_make); |
430 | struct sway_mode *mode = NULL; | 385 | struct sway_mode *mode = NULL; |
431 | // Find mode | 386 | // Find mode |
432 | int i, len = config->modes->length; | 387 | int i, len = config->modes->length; |
@@ -456,7 +411,7 @@ enum cmd_status cmd_mode(char *criteria, int argc, char **argv) { | |||
456 | return CMD_SUCCESS; | 411 | return CMD_SUCCESS; |
457 | } | 412 | } |
458 | 413 | ||
459 | enum cmd_status cmd_move(char *criteria, int argc, char **argv) { | 414 | static enum cmd_status cmd_move(int argc, char **argv) { |
460 | if (!checkarg(argc, "move", EXPECTED_AT_LEAST, 1) | 415 | if (!checkarg(argc, "move", EXPECTED_AT_LEAST, 1) |
461 | || config->reading || !config->active) { | 416 | || config->reading || !config->active) { |
462 | return CMD_FAILURE; | 417 | return CMD_FAILURE; |
@@ -489,7 +444,11 @@ enum cmd_status cmd_move(char *criteria, int argc, char **argv) { | |||
489 | // move "container to workspace number x" | 444 | // move "container to workspace number x" |
490 | ws_name = argv[4]; | 445 | ws_name = argv[4]; |
491 | } | 446 | } |
492 | swayc_t *ws = new_workspace(NULL, ws_name); | 447 | |
448 | swayc_t *ws = workspace_by_name(ws_name); | ||
449 | if (ws == NULL) { | ||
450 | ws = workspace_create(ws_name); | ||
451 | } | ||
493 | move_container_to(view, get_focused_container(ws)); | 452 | move_container_to(view, get_focused_container(ws)); |
494 | } else if (strcasecmp(argv[0], "scratchpad") == 0) { | 453 | } else if (strcasecmp(argv[0], "scratchpad") == 0) { |
495 | if (view->type != C_CONTAINER && view->type != C_VIEW) { | 454 | if (view->type != C_CONTAINER && view->type != C_VIEW) { |
@@ -523,7 +482,7 @@ enum cmd_status cmd_move(char *criteria, int argc, char **argv) { | |||
523 | return CMD_SUCCESS; | 482 | return CMD_SUCCESS; |
524 | } | 483 | } |
525 | 484 | ||
526 | enum cmd_status cmd_orientation(char *criteria, int argc, char **argv) { | 485 | static enum cmd_status cmd_orientation(int argc, char **argv) { |
527 | if (!checkarg(argc, "orientation", EXPECTED_EQUAL_TO, 1) | 486 | if (!checkarg(argc, "orientation", EXPECTED_EQUAL_TO, 1) |
528 | || !config->reading) { | 487 | || !config->reading) { |
529 | return CMD_FAILURE; | 488 | return CMD_FAILURE; |
@@ -540,7 +499,7 @@ enum cmd_status cmd_orientation(char *criteria, int argc, char **argv) { | |||
540 | return CMD_SUCCESS; | 499 | return CMD_SUCCESS; |
541 | } | 500 | } |
542 | 501 | ||
543 | enum cmd_status cmd_output(char *criteria, int argc, char **argv) { | 502 | static enum cmd_status cmd_output(int argc, char **argv) { |
544 | if (!checkarg(argc, "output", EXPECTED_AT_LEAST, 1)) { | 503 | if (!checkarg(argc, "output", EXPECTED_AT_LEAST, 1)) { |
545 | return CMD_FAILURE; | 504 | return CMD_FAILURE; |
546 | } | 505 | } |
@@ -605,7 +564,7 @@ enum cmd_status cmd_output(char *criteria, int argc, char **argv) { | |||
605 | return CMD_SUCCESS; | 564 | return CMD_SUCCESS; |
606 | } | 565 | } |
607 | 566 | ||
608 | enum cmd_status cmd_gaps(char *criteria, int argc, char **argv) { | 567 | static enum cmd_status cmd_gaps(int argc, char **argv) { |
609 | if (!checkarg(argc, "gaps", EXPECTED_AT_LEAST, 1)) { | 568 | if (!checkarg(argc, "gaps", EXPECTED_AT_LEAST, 1)) { |
610 | return CMD_FAILURE; | 569 | return CMD_FAILURE; |
611 | } | 570 | } |
@@ -739,14 +698,15 @@ enum cmd_status cmd_gaps(char *criteria, int argc, char **argv) { | |||
739 | top = &root_container; | 698 | top = &root_container; |
740 | } | 699 | } |
741 | int top_gap = top->gaps; | 700 | int top_gap = top->gaps; |
742 | swayc_map_r(top, method == SET ? set_gaps : add_gaps, &amount); | 701 | container_map(top, method == SET ? set_gaps : add_gaps, &amount); |
743 | top->gaps = top_gap; | 702 | top->gaps = top_gap; |
744 | arrange_windows(top, -1, -1); | 703 | arrange_windows(top, -1, -1); |
745 | } | 704 | } |
705 | |||
746 | return CMD_SUCCESS; | 706 | return CMD_SUCCESS; |
747 | } | 707 | } |
748 | 708 | ||
749 | enum cmd_status cmd_kill(char *criteria, int argc, char **argv) { | 709 | static enum cmd_status cmd_kill(int argc, char **argv) { |
750 | if (config->reading || !config->active) { | 710 | if (config->reading || !config->active) { |
751 | return CMD_FAILURE; | 711 | return CMD_FAILURE; |
752 | } | 712 | } |
@@ -755,7 +715,7 @@ enum cmd_status cmd_kill(char *criteria, int argc, char **argv) { | |||
755 | return CMD_SUCCESS; | 715 | return CMD_SUCCESS; |
756 | } | 716 | } |
757 | 717 | ||
758 | enum cmd_status cmd_layout(char *criteria, int argc, char **argv) { | 718 | static enum cmd_status cmd_layout(int argc, char **argv) { |
759 | if (!checkarg(argc, "layout", EXPECTED_MORE_THAN, 0) | 719 | if (!checkarg(argc, "layout", EXPECTED_MORE_THAN, 0) |
760 | || config->reading || !config->active) { | 720 | || config->reading || !config->active) { |
761 | return CMD_FAILURE; | 721 | return CMD_FAILURE; |
@@ -781,7 +741,7 @@ enum cmd_status cmd_layout(char *criteria, int argc, char **argv) { | |||
781 | return CMD_SUCCESS; | 741 | return CMD_SUCCESS; |
782 | } | 742 | } |
783 | 743 | ||
784 | enum cmd_status cmd_reload(char *criteria, int argc, char **argv) { | 744 | static enum cmd_status cmd_reload(int argc, char **argv) { |
785 | if (!checkarg(argc, "reload", EXPECTED_EQUAL_TO, 0) | 745 | if (!checkarg(argc, "reload", EXPECTED_EQUAL_TO, 0) |
786 | || config->reading | 746 | || config->reading |
787 | || !load_config(NULL)) { | 747 | || !load_config(NULL)) { |
@@ -791,7 +751,7 @@ enum cmd_status cmd_reload(char *criteria, int argc, char **argv) { | |||
791 | return CMD_SUCCESS; | 751 | return CMD_SUCCESS; |
792 | } | 752 | } |
793 | 753 | ||
794 | enum cmd_status cmd_resize(char *criteria, int argc, char **argv) { | 754 | static enum cmd_status cmd_resize(int argc, char **argv) { |
795 | if (!checkarg(argc, "resize", EXPECTED_AT_LEAST, 3) | 755 | if (!checkarg(argc, "resize", EXPECTED_AT_LEAST, 3) |
796 | || config->reading || !config->active) { | 756 | || config->reading || !config->active) { |
797 | return CMD_FAILURE; | 757 | return CMD_FAILURE; |
@@ -821,7 +781,7 @@ enum cmd_status cmd_resize(char *criteria, int argc, char **argv) { | |||
821 | return CMD_SUCCESS; | 781 | return CMD_SUCCESS; |
822 | } | 782 | } |
823 | 783 | ||
824 | static swayc_t *fetch_view_from_scratchpad(void) { | 784 | static swayc_t *fetch_view_from_scratchpad() { |
825 | if (sp_index >= scratchpad->length) { | 785 | if (sp_index >= scratchpad->length) { |
826 | sp_index = 0; | 786 | sp_index = 0; |
827 | } | 787 | } |
@@ -866,7 +826,7 @@ void remove_view_from_scratchpad(swayc_t *view) { | |||
866 | } | 826 | } |
867 | } | 827 | } |
868 | 828 | ||
869 | enum cmd_status cmd_scratchpad(char *criteria, int argc, char **argv) { | 829 | static enum cmd_status cmd_scratchpad(int argc, char **argv) { |
870 | if (!checkarg(argc, "scratchpad", EXPECTED_EQUAL_TO, 1) | 830 | if (!checkarg(argc, "scratchpad", EXPECTED_EQUAL_TO, 1) |
871 | || config->reading || !config->active) { | 831 | || config->reading || !config->active) { |
872 | return CMD_FAILURE; | 832 | return CMD_FAILURE; |
@@ -900,7 +860,7 @@ static int compare_set(const void *_l, const void *_r) { | |||
900 | return strlen((*r)->name) - strlen((*l)->name); | 860 | return strlen((*r)->name) - strlen((*l)->name); |
901 | } | 861 | } |
902 | 862 | ||
903 | enum cmd_status cmd_set(char *criteria, int argc, char **argv) { | 863 | static enum cmd_status cmd_set(int argc, char **argv) { |
904 | if (!checkarg(argc, "set", EXPECTED_AT_LEAST, 2) | 864 | if (!checkarg(argc, "set", EXPECTED_AT_LEAST, 2) |
905 | || !config->reading) { | 865 | || !config->reading) { |
906 | return CMD_FAILURE; | 866 | return CMD_FAILURE; |
@@ -923,11 +883,11 @@ enum cmd_status cmd_set(char *criteria, int argc, char **argv) { | |||
923 | list_add(config->symbols, var); | 883 | list_add(config->symbols, var); |
924 | list_sort(config->symbols, compare_set); | 884 | list_sort(config->symbols, compare_set); |
925 | } | 885 | } |
926 | var->value = join_args(argc - 1, argv + 1); | 886 | var->value = join_args(argv + 1, argc - 1); |
927 | return CMD_SUCCESS; | 887 | return CMD_SUCCESS; |
928 | } | 888 | } |
929 | 889 | ||
930 | static enum cmd_status _do_split(char *criteria, int argc, char **argv, int layout) { | 890 | static enum cmd_status _do_split(int argc, char **argv, int layout) { |
931 | char *name = layout == L_VERT ? "splitv" : | 891 | char *name = layout == L_VERT ? "splitv" : |
932 | layout == L_HORIZ ? "splith" : "split"; | 892 | layout == L_HORIZ ? "splith" : "split"; |
933 | if (!checkarg(argc, name, EXPECTED_EQUAL_TO, 0) | 893 | if (!checkarg(argc, name, EXPECTED_EQUAL_TO, 0) |
@@ -959,16 +919,16 @@ static enum cmd_status _do_split(char *criteria, int argc, char **argv, int layo | |||
959 | return CMD_SUCCESS; | 919 | return CMD_SUCCESS; |
960 | } | 920 | } |
961 | 921 | ||
962 | enum cmd_status cmd_split(char *criteria, int argc, char **argv) { | 922 | static enum cmd_status cmd_split(int argc, char **argv) { |
963 | if (!checkarg(argc, "split", EXPECTED_EQUAL_TO, 1) | 923 | if (!checkarg(argc, "split", EXPECTED_EQUAL_TO, 1) |
964 | || config->reading || !config->active) { | 924 | || config->reading || !config->active) { |
965 | return CMD_FAILURE; | 925 | return CMD_FAILURE; |
966 | } | 926 | } |
967 | 927 | ||
968 | if (strcasecmp(argv[0], "v") == 0 || strcasecmp(argv[0], "vertical") == 0) { | 928 | if (strcasecmp(argv[0], "v") == 0 || strcasecmp(argv[0], "vertical") == 0) { |
969 | _do_split(criteria, argc - 1, argv + 1, L_VERT); | 929 | _do_split(argc - 1, argv + 1, L_VERT); |
970 | } else if (strcasecmp(argv[0], "h") == 0 || strcasecmp(argv[0], "horizontal") == 0) { | 930 | } else if (strcasecmp(argv[0], "h") == 0 || strcasecmp(argv[0], "horizontal") == 0) { |
971 | _do_split(criteria, argc - 1, argv + 1, L_HORIZ); | 931 | _do_split(argc - 1, argv + 1, L_HORIZ); |
972 | } else { | 932 | } else { |
973 | sway_log(L_ERROR, "Invalid split command (expected either horiziontal or vertical)."); | 933 | sway_log(L_ERROR, "Invalid split command (expected either horiziontal or vertical)."); |
974 | return CMD_FAILURE; | 934 | return CMD_FAILURE; |
@@ -976,15 +936,15 @@ enum cmd_status cmd_split(char *criteria, int argc, char **argv) { | |||
976 | return CMD_SUCCESS; | 936 | return CMD_SUCCESS; |
977 | } | 937 | } |
978 | 938 | ||
979 | enum cmd_status cmd_splitv(char *criteria, int argc, char **argv) { | 939 | static enum cmd_status cmd_splitv(int argc, char **argv) { |
980 | return _do_split(criteria, argc, argv, L_VERT); | 940 | return _do_split(argc, argv, L_VERT); |
981 | } | 941 | } |
982 | 942 | ||
983 | enum cmd_status cmd_splith(char *criteria, int argc, char **argv) { | 943 | static enum cmd_status cmd_splith(int argc, char **argv) { |
984 | return _do_split(criteria, argc, argv, L_HORIZ); | 944 | return _do_split(argc, argv, L_HORIZ); |
985 | } | 945 | } |
986 | 946 | ||
987 | enum cmd_status cmd_log_colors(char *criteria, int argc, char **argv) { | 947 | static enum cmd_status cmd_log_colors(int argc, char **argv) { |
988 | if (!checkarg(argc, "log_colors", EXPECTED_EQUAL_TO, 1) | 948 | if (!checkarg(argc, "log_colors", EXPECTED_EQUAL_TO, 1) |
989 | || !config->reading) { | 949 | || !config->reading) { |
990 | return CMD_FAILURE; | 950 | return CMD_FAILURE; |
@@ -1000,7 +960,7 @@ enum cmd_status cmd_log_colors(char *criteria, int argc, char **argv) { | |||
1000 | return CMD_SUCCESS; | 960 | return CMD_SUCCESS; |
1001 | } | 961 | } |
1002 | 962 | ||
1003 | enum cmd_status cmd_fullscreen(char *criteria, int argc, char **argv) { | 963 | static enum cmd_status cmd_fullscreen(int argc, char **argv) { |
1004 | if (!checkarg(argc, "fullscreen", EXPECTED_AT_LEAST, 0) | 964 | if (!checkarg(argc, "fullscreen", EXPECTED_AT_LEAST, 0) |
1005 | || config->reading || !config->active) { | 965 | || config->reading || !config->active) { |
1006 | return CMD_FAILURE; | 966 | return CMD_FAILURE; |
@@ -1020,7 +980,7 @@ enum cmd_status cmd_fullscreen(char *criteria, int argc, char **argv) { | |||
1020 | return CMD_SUCCESS; | 980 | return CMD_SUCCESS; |
1021 | } | 981 | } |
1022 | 982 | ||
1023 | enum cmd_status cmd_workspace(char *criteria, int argc, char **argv) { | 983 | static enum cmd_status cmd_workspace(int argc, char **argv) { |
1024 | if (!checkarg(argc, "workspace", EXPECTED_AT_LEAST, 1)) { | 984 | if (!checkarg(argc, "workspace", EXPECTED_AT_LEAST, 1)) { |
1025 | return CMD_FAILURE; | 985 | return CMD_FAILURE; |
1026 | } | 986 | } |
@@ -1029,7 +989,28 @@ enum cmd_status cmd_workspace(char *criteria, int argc, char **argv) { | |||
1029 | if (config->reading || !config->active) { | 989 | if (config->reading || !config->active) { |
1030 | return CMD_DEFER; | 990 | return CMD_DEFER; |
1031 | } | 991 | } |
1032 | workspace_switch(new_workspace(NULL, argv[0])); | 992 | // Handle workspace next/prev |
993 | swayc_t *ws = NULL; | ||
994 | if (strcasecmp(argv[0], "next") == 0) { | ||
995 | ws = workspace_next(); | ||
996 | } else if (strcasecmp(argv[0], "prev") == 0) { | ||
997 | ws = workspace_prev(); | ||
998 | } else if (strcasecmp(argv[0], "next_on_output") == 0) { | ||
999 | ws = workspace_output_next(); | ||
1000 | } else if (strcasecmp(argv[0], "prev_on_output") == 0) { | ||
1001 | ws = workspace_output_prev(); | ||
1002 | } else if (strcasecmp(argv[0], "back_and_forth") == 0) { | ||
1003 | if (prev_workspace_name) { | ||
1004 | if (!(ws = workspace_by_name(prev_workspace_name))) { | ||
1005 | ws = workspace_create(prev_workspace_name); | ||
1006 | } | ||
1007 | } | ||
1008 | } else { | ||
1009 | if (!(ws= workspace_by_name(argv[0]))) { | ||
1010 | ws = workspace_create(argv[0]); | ||
1011 | } | ||
1012 | } | ||
1013 | workspace_switch(ws); | ||
1033 | } else { | 1014 | } else { |
1034 | if (strcasecmp(argv[1], "output") == 0) { | 1015 | if (strcasecmp(argv[1], "output") == 0) { |
1035 | if (!checkarg(argc, "workspace", EXPECTED_EQUAL_TO, 3)) { | 1016 | if (!checkarg(argc, "workspace", EXPECTED_EQUAL_TO, 3)) { |
@@ -1040,12 +1021,15 @@ enum cmd_status cmd_workspace(char *criteria, int argc, char **argv) { | |||
1040 | wso->workspace = strdup(argv[0]); | 1021 | wso->workspace = strdup(argv[0]); |
1041 | wso->output = strdup(argv[2]); | 1022 | wso->output = strdup(argv[2]); |
1042 | list_add(config->workspace_outputs, wso); | 1023 | list_add(config->workspace_outputs, wso); |
1024 | if (!config->reading) { | ||
1025 | // TODO: Move workspace to output. (dont do so when reloading) | ||
1026 | } | ||
1043 | } | 1027 | } |
1044 | } | 1028 | } |
1045 | return CMD_SUCCESS; | 1029 | return CMD_SUCCESS; |
1046 | } | 1030 | } |
1047 | 1031 | ||
1048 | enum cmd_status cmd_ws_auto_back_and_forth(char *criteria, int argc, char **argv) { | 1032 | static enum cmd_status cmd_ws_auto_back_and_forth(int argc, char **argv) { |
1049 | if (!checkarg(argc, "workspace_auto_back_and_forth", EXPECTED_EQUAL_TO, 1)) { | 1033 | if (!checkarg(argc, "workspace_auto_back_and_forth", EXPECTED_EQUAL_TO, 1)) { |
1050 | return CMD_FAILURE; | 1034 | return CMD_FAILURE; |
1051 | } | 1035 | } |
@@ -1060,7 +1044,7 @@ enum cmd_status cmd_ws_auto_back_and_forth(char *criteria, int argc, char **argv | |||
1060 | } | 1044 | } |
1061 | 1045 | ||
1062 | /* Keep alphabetized */ | 1046 | /* Keep alphabetized */ |
1063 | static const struct cmd_handler handlers[] = { | 1047 | static struct cmd_handler handlers[] = { |
1064 | { "bindsym", cmd_bindsym }, | 1048 | { "bindsym", cmd_bindsym }, |
1065 | { "default_orientation", cmd_orientation }, | 1049 | { "default_orientation", cmd_orientation }, |
1066 | { "exec", cmd_exec }, | 1050 | { "exec", cmd_exec }, |
@@ -1070,7 +1054,6 @@ static const struct cmd_handler handlers[] = { | |||
1070 | { "floating_modifier", cmd_floating_mod }, | 1054 | { "floating_modifier", cmd_floating_mod }, |
1071 | { "focus", cmd_focus }, | 1055 | { "focus", cmd_focus }, |
1072 | { "focus_follows_mouse", cmd_focus_follows_mouse }, | 1056 | { "focus_follows_mouse", cmd_focus_follows_mouse }, |
1073 | { "for_window", cmd_for_window }, | ||
1074 | { "fullscreen", cmd_fullscreen }, | 1057 | { "fullscreen", cmd_fullscreen }, |
1075 | { "gaps", cmd_gaps }, | 1058 | { "gaps", cmd_gaps }, |
1076 | { "kill", cmd_kill }, | 1059 | { "kill", cmd_kill }, |
@@ -1107,7 +1090,6 @@ static struct cmd_handler *find_handler(char *line) { | |||
1107 | enum cmd_status handle_command(char *exec) { | 1090 | enum cmd_status handle_command(char *exec) { |
1108 | sway_log(L_INFO, "Handling command '%s'", exec); | 1091 | sway_log(L_INFO, "Handling command '%s'", exec); |
1109 | int argc; | 1092 | int argc; |
1110 | char *criteria = NULL; | ||
1111 | char **argv = split_args(exec, &argc); | 1093 | char **argv = split_args(exec, &argc); |
1112 | enum cmd_status status = CMD_FAILURE; | 1094 | enum cmd_status status = CMD_FAILURE; |
1113 | struct cmd_handler *handler; | 1095 | struct cmd_handler *handler; |
@@ -1115,7 +1097,7 @@ enum cmd_status handle_command(char *exec) { | |||
1115 | return status; | 1097 | return status; |
1116 | } | 1098 | } |
1117 | if ((handler = find_handler(argv[0])) == NULL | 1099 | if ((handler = find_handler(argv[0])) == NULL |
1118 | || (status = handler->handle(criteria, argc - 1, argv + 1)) != CMD_SUCCESS) { | 1100 | || (status = handler->handle(argc - 1, argv + 1)) != CMD_SUCCESS) { |
1119 | sway_log(L_ERROR, "Command failed: %s", argv[0]); | 1101 | sway_log(L_ERROR, "Command failed: %s", argv[0]); |
1120 | } | 1102 | } |
1121 | free_argv(argc, argv); | 1103 | free_argv(argc, argv); |
@@ -1126,7 +1108,6 @@ enum cmd_status config_command(char *exec) { | |||
1126 | sway_log(L_INFO, "handling config command '%s'", exec); | 1108 | sway_log(L_INFO, "handling config command '%s'", exec); |
1127 | int argc; | 1109 | int argc; |
1128 | char **argv = split_args(exec, &argc); | 1110 | char **argv = split_args(exec, &argc); |
1129 | char *criteria = NULL; | ||
1130 | enum cmd_status status = CMD_FAILURE; | 1111 | enum cmd_status status = CMD_FAILURE; |
1131 | struct cmd_handler *handler; | 1112 | struct cmd_handler *handler; |
1132 | if (!argc) { | 1113 | if (!argc) { |
@@ -1146,7 +1127,7 @@ enum cmd_status config_command(char *exec) { | |||
1146 | for (; i < e; ++i) { | 1127 | for (; i < e; ++i) { |
1147 | argv[i] = do_var_replacement(argv[i]); | 1128 | argv[i] = do_var_replacement(argv[i]); |
1148 | } | 1129 | } |
1149 | status = handler->handle(criteria, argc - 1, argv + 1); | 1130 | status = handler->handle(argc - 1, argv + 1); |
1150 | if (status == CMD_FAILURE) { | 1131 | if (status == CMD_FAILURE) { |
1151 | sway_log(L_ERROR, "Config load failed for line `%s'", exec); | 1132 | sway_log(L_ERROR, "Config load failed for line `%s'", exec); |
1152 | } else if (status == CMD_DEFER) { | 1133 | } else if (status == CMD_DEFER) { |
diff --git a/sway/config.c b/sway/config.c index da92030e..23d6ac0d 100644 --- a/sway/config.c +++ b/sway/config.c | |||
@@ -286,28 +286,3 @@ char *do_var_replacement(char *str) { | |||
286 | } | 286 | } |
287 | return str; | 287 | return str; |
288 | } | 288 | } |
289 | |||
290 | struct workspace_output *wsop_find_workspace(const char *name) { | ||
291 | int i, len = config->workspace_outputs->length; | ||
292 | struct workspace_output *wsop; | ||
293 | for (i = 0; i < len; ++i) { | ||
294 | wsop = config->workspace_outputs->items[i]; | ||
295 | if (strcasecmp(wsop->workspace, name) == 0) { | ||
296 | return wsop; | ||
297 | } | ||
298 | } | ||
299 | return NULL; | ||
300 | } | ||
301 | |||
302 | struct workspace_output *wsop_find_output(const char *name) { | ||
303 | int i, len = config->workspace_outputs->length; | ||
304 | struct workspace_output *wsop; | ||
305 | for (i = 0; i < len; ++i) { | ||
306 | wsop = config->workspace_outputs->items[i]; | ||
307 | if (strcasecmp(wsop->output, name) == 0) { | ||
308 | return wsop; | ||
309 | } | ||
310 | } | ||
311 | return NULL; | ||
312 | } | ||
313 | |||
diff --git a/sway/container.c b/sway/container.c index baf84378..ef0e6c55 100644 --- a/sway/container.c +++ b/sway/container.c | |||
@@ -1,7 +1,6 @@ | |||
1 | #include <stdlib.h> | 1 | #include <stdlib.h> |
2 | #include <stdbool.h> | 2 | #include <stdbool.h> |
3 | #include <strings.h> | 3 | #include <strings.h> |
4 | #include <pcre.h> | ||
5 | #include "config.h" | 4 | #include "config.h" |
6 | #include "container.h" | 5 | #include "container.h" |
7 | #include "workspace.h" | 6 | #include "workspace.h" |
@@ -54,30 +53,26 @@ static void free_swayc(swayc_t *cont) { | |||
54 | // New containers | 53 | // New containers |
55 | 54 | ||
56 | swayc_t *new_output(wlc_handle handle) { | 55 | swayc_t *new_output(wlc_handle handle) { |
56 | const struct wlc_size *size = wlc_output_get_resolution(handle); | ||
57 | const char *name = wlc_output_get_name(handle); | 57 | const char *name = wlc_output_get_name(handle); |
58 | int i, len; | ||
59 | |||
60 | // Find current outputs to see if this already exists | 58 | // Find current outputs to see if this already exists |
61 | if (name) { | 59 | { |
62 | len = root_container.children->length; | 60 | int i, len = root_container.children->length; |
63 | for (i = 0; i < len; ++i) { | 61 | for (i = 0; i < len; ++i) { |
64 | swayc_t *op = root_container.children->items[i]; | 62 | swayc_t *op = root_container.children->items[i]; |
65 | if (strcmp(op->name, name) == 0) { | 63 | const char *op_name = op->name; |
66 | sway_log(L_DEBUG, "restoring output %lu:%s", handle, op->name); | 64 | if (op_name && name && strcmp(op_name, name) == 0) { |
65 | sway_log(L_DEBUG, "restoring output %lu:%s", handle, op_name); | ||
67 | return op; | 66 | return op; |
68 | } | 67 | } |
69 | } | 68 | } |
70 | } else { | ||
71 | sway_log(L_ERROR, "Output has no given name"); | ||
72 | return NULL; | ||
73 | } | 69 | } |
74 | 70 | ||
75 | sway_log(L_DEBUG, "Adding output %lu:%s", handle, name); | 71 | sway_log(L_DEBUG, "Added output %lu:%s", handle, name); |
76 | 72 | ||
77 | // Find output config | ||
78 | struct output_config *oc = NULL; | 73 | struct output_config *oc = NULL; |
79 | len = config->output_configs->length; | 74 | int i; |
80 | for (i = 0; i < len; ++i) { | 75 | for (i = 0; i < config->output_configs->length; ++i) { |
81 | oc = config->output_configs->items[i]; | 76 | oc = config->output_configs->items[i]; |
82 | if (strcasecmp(name, oc->name) == 0) { | 77 | if (strcasecmp(name, oc->name) == 0) { |
83 | sway_log(L_DEBUG, "Matched output config for %s", name); | 78 | sway_log(L_DEBUG, "Matched output config for %s", name); |
@@ -91,88 +86,77 @@ swayc_t *new_output(wlc_handle handle) { | |||
91 | } | 86 | } |
92 | 87 | ||
93 | swayc_t *output = new_swayc(C_OUTPUT); | 88 | swayc_t *output = new_swayc(C_OUTPUT); |
89 | if (oc && oc->width != -1 && oc->height != -1) { | ||
90 | output->width = oc->width; | ||
91 | output->height = oc->height; | ||
92 | struct wlc_size new_size = { .w = oc->width, .h = oc->height }; | ||
93 | wlc_output_set_resolution(handle, &new_size); | ||
94 | } else { | ||
95 | output->width = size->w; | ||
96 | output->height = size->h; | ||
97 | } | ||
94 | output->handle = handle; | 98 | output->handle = handle; |
95 | output->name = name ? strdup(name) : NULL; | 99 | output->name = name ? strdup(name) : NULL; |
96 | 100 | ||
97 | if (oc) { | 101 | // Find position for it |
98 | // Set output width/height | 102 | if (oc && oc->x != -1 && oc->y != -1) { |
99 | if (oc->width > 0 && oc->height > 0) { | 103 | sway_log(L_DEBUG, "Set %s position to %d, %d", name, oc->x, oc->y); |
100 | output->width = oc->width; | 104 | output->x = oc->x; |
101 | output->height = oc->height; | 105 | output->y = oc->y; |
102 | struct wlc_size geo = { .w = oc->width, .h = oc->height}; | 106 | } else { |
103 | wlc_output_set_resolution(handle, &geo); | 107 | int x = 0; |
104 | } else { | 108 | for (i = 0; i < root_container.children->length; ++i) { |
105 | struct wlc_size geo = *wlc_output_get_resolution(handle); | 109 | swayc_t *c = root_container.children->items[i]; |
106 | output->width = geo.w; | 110 | if (c->type == C_OUTPUT) { |
107 | output->height = geo.h; | 111 | if (c->width + c->x > x) { |
108 | } | 112 | x = c->width + c->x; |
109 | // find position in config or find where it should go | ||
110 | // TODO more intelligent method | ||
111 | if (oc->x > 0 && oc->y > 0) { | ||
112 | output->x = oc->x; | ||
113 | output->y = oc->y; | ||
114 | } else { | ||
115 | unsigned int x = 0; | ||
116 | len = root_container.children->length; | ||
117 | for (i = 0; i < len; ++i) { | ||
118 | swayc_t *c = root_container.children->items[i]; | ||
119 | if (c->type == C_OUTPUT) { | ||
120 | unsigned int cx = c->width + c->x; | ||
121 | if (cx > x) { | ||
122 | x = cx; | ||
123 | } | ||
124 | } | 113 | } |
125 | } | 114 | } |
126 | output->x = x; | ||
127 | } | 115 | } |
116 | output->x = x; | ||
128 | } | 117 | } |
129 | // Add as child to root | 118 | |
130 | add_child(&root_container, output); | 119 | add_child(&root_container, output); |
131 | 120 | ||
121 | // Create workspace | ||
122 | char *ws_name = NULL; | ||
123 | if (name) { | ||
124 | for (i = 0; i < config->workspace_outputs->length; ++i) { | ||
125 | struct workspace_output *wso = config->workspace_outputs->items[i]; | ||
126 | if (strcasecmp(wso->output, name) == 0) { | ||
127 | sway_log(L_DEBUG, "Matched workspace to output: %s for %s", wso->workspace, wso->output); | ||
128 | // Check if any other workspaces are using this name | ||
129 | if (workspace_by_name(wso->workspace)) { | ||
130 | sway_log(L_DEBUG, "But it's already taken"); | ||
131 | break; | ||
132 | } | ||
133 | sway_log(L_DEBUG, "So we're going to use it"); | ||
134 | ws_name = strdup(wso->workspace); | ||
135 | break; | ||
136 | } | ||
137 | } | ||
138 | } | ||
139 | if (!ws_name) { | ||
140 | ws_name = workspace_next_name(); | ||
141 | } | ||
142 | |||
132 | // create and initilize default workspace | 143 | // create and initilize default workspace |
133 | swayc_t *ws = new_workspace(output, NULL); | 144 | swayc_t *ws = new_workspace(output, ws_name); |
134 | ws->is_focused = true; | 145 | ws->is_focused = true; |
135 | 146 | ||
147 | free(ws_name); | ||
148 | |||
136 | return output; | 149 | return output; |
137 | } | 150 | } |
138 | 151 | ||
139 | swayc_t *new_workspace(swayc_t *output, const char *name) { | 152 | swayc_t *new_workspace(swayc_t *output, const char *name) { |
140 | swayc_t *ws = NULL; | 153 | if (!ASSERT_NONNULL(output)) { |
141 | struct workspace_output *wsop; | 154 | return NULL; |
142 | if (name) { | ||
143 | // Find existing workspace with same name. | ||
144 | // or workspace found by special name | ||
145 | if ((ws = workspace_by_name(name))) { | ||
146 | return ws; | ||
147 | } | ||
148 | // Find matching output from config | ||
149 | if (!output) { | ||
150 | if ((wsop = wsop_find_workspace(name))) { | ||
151 | int i, len = root_container.children->length; | ||
152 | for (i = 0; i < len; ++i) { | ||
153 | swayc_t *op = root_container.children->items[i]; | ||
154 | if (strcasecmp(op->name, wsop->output) == 0) { | ||
155 | output = op; | ||
156 | goto find_wsop_end; | ||
157 | } | ||
158 | } | ||
159 | } | ||
160 | // Set output to active_output if there is no output. | ||
161 | output = swayc_active_output(); | ||
162 | find_wsop_end:; | ||
163 | } | ||
164 | } else { | ||
165 | // No name or output, use active_output | ||
166 | if (!output) { | ||
167 | output = swayc_active_output(); | ||
168 | } | ||
169 | // search for available output name | ||
170 | if (!(name = workspace_output_open_name(output))) { | ||
171 | // otherwise just use simple next name | ||
172 | name = workspace_next_name(); | ||
173 | } | ||
174 | } | 155 | } |
156 | sway_log(L_DEBUG, "Added workspace %s for output %u", name, (unsigned int)output->handle); | ||
175 | swayc_t *workspace = new_swayc(C_WORKSPACE); | 157 | swayc_t *workspace = new_swayc(C_WORKSPACE); |
158 | |||
159 | // TODO: default_layout | ||
176 | if (config->default_layout != L_NONE) { | 160 | if (config->default_layout != L_NONE) { |
177 | workspace->layout = config->default_layout; | 161 | workspace->layout = config->default_layout; |
178 | } else if (config->default_orientation != L_NONE) { | 162 | } else if (config->default_orientation != L_NONE) { |
@@ -390,7 +374,7 @@ swayc_t *destroy_view(swayc_t *view) { | |||
390 | // Container lookup | 374 | // Container lookup |
391 | 375 | ||
392 | 376 | ||
393 | swayc_t *swayc_by_test_r(swayc_t *container, swayc_test_func test, void *data) { | 377 | swayc_t *swayc_by_test(swayc_t *container, bool (*test)(swayc_t *view, void *data), void *data) { |
394 | if (!container->children) { | 378 | if (!container->children) { |
395 | return NULL; | 379 | return NULL; |
396 | } | 380 | } |
@@ -409,7 +393,7 @@ swayc_t *swayc_by_test_r(swayc_t *container, swayc_test_func test, void *data) { | |||
409 | if (test(child, data)) { | 393 | if (test(child, data)) { |
410 | return child; | 394 | return child; |
411 | } else { | 395 | } else { |
412 | swayc_t *res = swayc_by_test_r(child, test, data); | 396 | swayc_t *res = swayc_by_test(child, test, data); |
413 | if (res) { | 397 | if (res) { |
414 | return res; | 398 | return res; |
415 | } | 399 | } |
@@ -417,193 +401,18 @@ swayc_t *swayc_by_test_r(swayc_t *container, swayc_test_func test, void *data) { | |||
417 | } | 401 | } |
418 | return NULL; | 402 | return NULL; |
419 | } | 403 | } |
420 | swayc_t *swayc_by_test(swayc_test_func test, void *data) { | ||
421 | return swayc_by_test_r(&root_container, test, data); | ||
422 | } | ||
423 | |||
424 | void swayc_map_r(swayc_t *container, swayc_map_func f, void *data) { | ||
425 | if (container) { | ||
426 | f(container, data); | ||
427 | int i; | ||
428 | if (container->children) { | ||
429 | for (i = 0; i < container->children->length; ++i) { | ||
430 | swayc_t *child = container->children->items[i]; | ||
431 | swayc_map_r(child, f, data); | ||
432 | } | ||
433 | } | ||
434 | if (container->floating) { | ||
435 | for (i = 0; i < container->floating->length; ++i) { | ||
436 | swayc_t *child = container->floating->items[i]; | ||
437 | swayc_map_r(child, f, data); | ||
438 | } | ||
439 | } | ||
440 | } | ||
441 | } | ||
442 | void swayc_map(swayc_map_func f, void *data) { | ||
443 | swayc_map_r(&root_container, f, data); | ||
444 | } | ||
445 | |||
446 | void swayc_map_by_test_r(swayc_t *container, | ||
447 | swayc_map_func func, swayc_test_func test, | ||
448 | void *funcdata, void *testdata) { | ||
449 | if (container) { | ||
450 | if (test(container, testdata)) { | ||
451 | func(container, funcdata); | ||
452 | } | ||
453 | int i; | ||
454 | if (container->children) { | ||
455 | for (i = 0; i < container->children->length; ++i) { | ||
456 | swayc_t *child = container->children->items[i]; | ||
457 | swayc_map_by_test_r(child, func, test, funcdata, testdata); | ||
458 | } | ||
459 | } | ||
460 | if (container->floating) { | ||
461 | for (i = 0; i < container->floating->length; ++i) { | ||
462 | swayc_t *child = container->floating->items[i]; | ||
463 | swayc_map_by_test_r(child, func, test, funcdata, testdata); | ||
464 | } | ||
465 | } | ||
466 | } | ||
467 | } | ||
468 | void swayc_map_by_test( | ||
469 | swayc_map_func func, swayc_test_func test, | ||
470 | void *funcdata, void *testdata) { | ||
471 | swayc_map_by_test_r(&root_container, func, test, funcdata, testdata); | ||
472 | } | ||
473 | |||
474 | |||
475 | |||
476 | // Map functions | ||
477 | void set_gaps(swayc_t *view, void *_data) { | ||
478 | int *data = _data; | ||
479 | if (view->type == C_WORKSPACE || view->type == C_VIEW) { | ||
480 | view->gaps = *data; | ||
481 | } | ||
482 | } | ||
483 | 404 | ||
484 | void add_gaps(swayc_t *view, void *_data) { | 405 | static bool test_name(swayc_t *view, void *data) { |
485 | int *data = _data; | 406 | if (!view && !view->name) { |
486 | if (view->type == C_WORKSPACE || view->type == C_VIEW) { | 407 | return false; |
487 | if ((view->gaps += *data) < 0) { | ||
488 | view->gaps = 0; | ||
489 | } | ||
490 | } | 408 | } |
409 | return strcmp(view->name, data) == 0; | ||
491 | } | 410 | } |
492 | 411 | ||
493 | // Test functions | 412 | swayc_t *swayc_by_name(const char *name) { |
494 | bool test_name(swayc_t *view, void *data) { | 413 | return swayc_by_test(&root_container, test_name, (void *)name); |
495 | return view->name && strcmp(view->name, data) == 0; | ||
496 | } | 414 | } |
497 | 415 | ||
498 | // test_name_regex | ||
499 | struct test_name_regex { | ||
500 | pcre *reg; | ||
501 | pcre_extra *regext; | ||
502 | }; | ||
503 | |||
504 | void *compile_regex(const char *pattern) { | ||
505 | struct test_name_regex *regex = malloc(sizeof *regex); | ||
506 | const char *error; | ||
507 | int erroffset; | ||
508 | if (!(regex->reg = pcre_compile(pattern, 0, &error, &erroffset, NULL))) { | ||
509 | sway_log(L_ERROR, "Regex compilation failed:%s:%s", pattern, error); | ||
510 | free(regex); | ||
511 | return NULL; | ||
512 | } | ||
513 | regex->regext = pcre_study(regex->reg, 0, &error); | ||
514 | if (error) { | ||
515 | sway_log(L_DEBUG, "Regex study failed:%s:%s", pattern, error); | ||
516 | } | ||
517 | return regex; | ||
518 | } | ||
519 | |||
520 | void free_regex(void *_regex) { | ||
521 | struct test_name_regex *regex = _regex; | ||
522 | pcre_free(regex->reg); | ||
523 | pcre_free_study(regex->regext); | ||
524 | free(regex); | ||
525 | } | ||
526 | |||
527 | static bool exec_regex(const char *pattern, struct test_name_regex *regex) { | ||
528 | int ovector[300]; | ||
529 | return 0 < pcre_exec(regex->reg, regex->regext, pattern, | ||
530 | strlen(pattern), 0, 0, ovector, 300); | ||
531 | } | ||
532 | |||
533 | bool test_name_regex(swayc_t *view, void *data) { | ||
534 | return view->name && exec_regex(view->name, data); | ||
535 | } | ||
536 | bool test_layout(swayc_t *view, void *data) { | ||
537 | return view->layout & *(enum swayc_layouts *)data; | ||
538 | } | ||
539 | bool test_type(swayc_t *view, void *data) { | ||
540 | return view->layout & *(enum swayc_types *)data; | ||
541 | } | ||
542 | bool test_visibility(swayc_t *view, void *data) { | ||
543 | return view->visible == *(bool *)data; | ||
544 | } | ||
545 | bool test_handle(swayc_t *view, void *data) { | ||
546 | return view->handle == *(wlc_handle *)data; | ||
547 | } | ||
548 | |||
549 | // C_VIEW tests | ||
550 | bool test_view_state(swayc_t *view, void *data) { | ||
551 | return view->type == C_VIEW | ||
552 | && wlc_view_get_state(view->handle) & *(int *)data; | ||
553 | } | ||
554 | bool test_view_type(swayc_t *view, void *data) { | ||
555 | return view->type == C_VIEW | ||
556 | && wlc_view_get_type(view->handle) & *(int *)data; | ||
557 | } | ||
558 | bool test_view_title(swayc_t *view, void *data) { | ||
559 | return view->type == C_VIEW | ||
560 | && strcmp(view->name, data) == 0; | ||
561 | } | ||
562 | bool test_view_class(swayc_t *view, void *data) { | ||
563 | return view->type == C_VIEW | ||
564 | && strcmp(wlc_view_get_class(view->handle), data) == 0; | ||
565 | } | ||
566 | bool test_view_appid(swayc_t *view, void *data) { | ||
567 | return view->type == C_VIEW | ||
568 | && strcmp(wlc_view_get_app_id(view->handle), data) == 0; | ||
569 | } | ||
570 | bool test_view_title_regex(swayc_t *view, void *data) { | ||
571 | return view->type == C_VIEW | ||
572 | && exec_regex(view->name, data); | ||
573 | } | ||
574 | bool test_view_class_regex(swayc_t *view, void *data) { | ||
575 | return view->type == C_VIEW | ||
576 | && exec_regex(wlc_view_get_class(view->handle), data); | ||
577 | } | ||
578 | bool test_view_appid_regex(swayc_t *view, void *data) { | ||
579 | return view->type == C_VIEW | ||
580 | && exec_regex(wlc_view_get_app_id(view->handle), data); | ||
581 | } | ||
582 | |||
583 | // Fancy test combiners | ||
584 | bool test_and(swayc_t *view, void *data) { | ||
585 | struct test_list *list = data; | ||
586 | while (list->test) { | ||
587 | if (!list->test(view, list->data)) { | ||
588 | return false; | ||
589 | } | ||
590 | ++list; | ||
591 | } | ||
592 | return true; | ||
593 | } | ||
594 | bool test_or(swayc_t *view, void *data) { | ||
595 | struct test_list *list = data; | ||
596 | while (list->test) { | ||
597 | if (list->test(view, list->data)) { | ||
598 | return true; | ||
599 | } | ||
600 | ++list; | ||
601 | } | ||
602 | return false; | ||
603 | } | ||
604 | |||
605 | // Focus|parent lookup | ||
606 | |||
607 | swayc_t *swayc_parent_by_type(swayc_t *container, enum swayc_types type) { | 416 | swayc_t *swayc_parent_by_type(swayc_t *container, enum swayc_types type) { |
608 | if (!ASSERT_NONNULL(container)) { | 417 | if (!ASSERT_NONNULL(container)) { |
609 | return NULL; | 418 | return NULL; |
@@ -656,6 +465,42 @@ swayc_t *swayc_focus_by_layout(swayc_t *container, enum swayc_layouts layout) { | |||
656 | return container; | 465 | return container; |
657 | } | 466 | } |
658 | 467 | ||
468 | |||
469 | static swayc_t *_swayc_by_handle_helper(wlc_handle handle, swayc_t *parent) { | ||
470 | if (!parent || !parent->children) { | ||
471 | return NULL; | ||
472 | } | ||
473 | int i, len; | ||
474 | swayc_t **child; | ||
475 | if (parent->type == C_WORKSPACE) { | ||
476 | len = parent->floating->length; | ||
477 | child = (swayc_t **)parent->floating->items; | ||
478 | for (i = 0; i < len; ++i, ++child) { | ||
479 | if ((*child)->handle == handle) { | ||
480 | return *child; | ||
481 | } | ||
482 | } | ||
483 | } | ||
484 | |||
485 | len = parent->children->length; | ||
486 | child = (swayc_t**)parent->children->items; | ||
487 | for (i = 0; i < len; ++i, ++child) { | ||
488 | if ((*child)->handle == handle) { | ||
489 | return *child; | ||
490 | } else { | ||
491 | swayc_t *res; | ||
492 | if ((res = _swayc_by_handle_helper(handle, *child))) { | ||
493 | return res; | ||
494 | } | ||
495 | } | ||
496 | } | ||
497 | return NULL; | ||
498 | } | ||
499 | |||
500 | swayc_t *swayc_by_handle(wlc_handle handle) { | ||
501 | return _swayc_by_handle_helper(handle, &root_container); | ||
502 | } | ||
503 | |||
659 | swayc_t *swayc_active_output(void) { | 504 | swayc_t *swayc_active_output(void) { |
660 | return root_container.focused; | 505 | return root_container.focused; |
661 | } | 506 | } |
@@ -688,13 +533,11 @@ swayc_t *swayc_active_workspace_for(swayc_t *cont) { | |||
688 | // Container information | 533 | // Container information |
689 | 534 | ||
690 | bool swayc_is_fullscreen(swayc_t *view) { | 535 | bool swayc_is_fullscreen(swayc_t *view) { |
691 | return view && view->type == C_VIEW | 536 | return view && view->type == C_VIEW && (wlc_view_get_state(view->handle) & WLC_BIT_FULLSCREEN); |
692 | && wlc_view_get_state(view->handle) & WLC_BIT_FULLSCREEN; | ||
693 | } | 537 | } |
694 | 538 | ||
695 | bool swayc_is_active(swayc_t *view) { | 539 | bool swayc_is_active(swayc_t *view) { |
696 | return view && view->type == C_VIEW | 540 | return view && view->type == C_VIEW && (wlc_view_get_state(view->handle) & WLC_BIT_ACTIVATED); |
697 | && wlc_view_get_state(view->handle) & WLC_BIT_ACTIVATED; | ||
698 | } | 541 | } |
699 | 542 | ||
700 | bool swayc_is_parent_of(swayc_t *parent, swayc_t *child) { | 543 | bool swayc_is_parent_of(swayc_t *parent, swayc_t *child) { |
@@ -723,6 +566,25 @@ int swayc_gap(swayc_t *container) { | |||
723 | 566 | ||
724 | // Mapping | 567 | // Mapping |
725 | 568 | ||
569 | void container_map(swayc_t *container, void (*f)(swayc_t *view, void *data), void *data) { | ||
570 | if (container) { | ||
571 | f(container, data); | ||
572 | int i; | ||
573 | if (container->children) { | ||
574 | for (i = 0; i < container->children->length; ++i) { | ||
575 | swayc_t *child = container->children->items[i]; | ||
576 | container_map(child, f, data); | ||
577 | } | ||
578 | } | ||
579 | if (container->floating) { | ||
580 | for (i = 0; i < container->floating->length; ++i) { | ||
581 | swayc_t *child = container->floating->items[i]; | ||
582 | container_map(child, f, data); | ||
583 | } | ||
584 | } | ||
585 | } | ||
586 | } | ||
587 | |||
726 | void update_visibility_output(swayc_t *container, wlc_handle output) { | 588 | void update_visibility_output(swayc_t *container, wlc_handle output) { |
727 | // Inherit visibility | 589 | // Inherit visibility |
728 | swayc_t *parent = container->parent; | 590 | swayc_t *parent = container->parent; |
@@ -791,3 +653,24 @@ void update_visibility(swayc_t *container) { | |||
791 | } | 653 | } |
792 | } | 654 | } |
793 | 655 | ||
656 | void set_gaps(swayc_t *view, void *_data) { | ||
657 | int *data = _data; | ||
658 | if (!ASSERT_NONNULL(view)) { | ||
659 | return; | ||
660 | } | ||
661 | if (view->type == C_WORKSPACE || view->type == C_VIEW) { | ||
662 | view->gaps = *data; | ||
663 | } | ||
664 | } | ||
665 | |||
666 | void add_gaps(swayc_t *view, void *_data) { | ||
667 | int *data = _data; | ||
668 | if (!ASSERT_NONNULL(view)) { | ||
669 | return; | ||
670 | } | ||
671 | if (view->type == C_WORKSPACE || view->type == C_VIEW) { | ||
672 | if ((view->gaps += *data) < 0) { | ||
673 | view->gaps = 0; | ||
674 | } | ||
675 | } | ||
676 | } | ||
diff --git a/sway/handlers.c b/sway/handlers.c index 1a8138f8..096df53c 100644 --- a/sway/handlers.c +++ b/sway/handlers.c | |||
@@ -126,7 +126,7 @@ static void handle_output_destroyed(wlc_handle output) { | |||
126 | 126 | ||
127 | static void handle_output_resolution_change(wlc_handle output, const struct wlc_size *from, const struct wlc_size *to) { | 127 | static void handle_output_resolution_change(wlc_handle output, const struct wlc_size *from, const struct wlc_size *to) { |
128 | sway_log(L_DEBUG, "Output %u resolution changed to %d x %d", (unsigned int)output, to->w, to->h); | 128 | sway_log(L_DEBUG, "Output %u resolution changed to %d x %d", (unsigned int)output, to->w, to->h); |
129 | swayc_t *c = swayc_by_test(test_handle, &output); | 129 | swayc_t *c = swayc_by_handle(output); |
130 | if (!c) return; | 130 | if (!c) return; |
131 | c->width = to->w; | 131 | c->width = to->w; |
132 | c->height = to->h; | 132 | c->height = to->h; |
@@ -134,7 +134,7 @@ static void handle_output_resolution_change(wlc_handle output, const struct wlc_ | |||
134 | } | 134 | } |
135 | 135 | ||
136 | static void handle_output_focused(wlc_handle output, bool focus) { | 136 | static void handle_output_focused(wlc_handle output, bool focus) { |
137 | swayc_t *c = swayc_by_test(test_handle, &output); | 137 | swayc_t *c = swayc_by_handle(output); |
138 | // if for some reason this output doesnt exist, create it. | 138 | // if for some reason this output doesnt exist, create it. |
139 | if (!c) { | 139 | if (!c) { |
140 | handle_output_created(output); | 140 | handle_output_created(output); |
@@ -152,7 +152,7 @@ static bool handle_view_created(wlc_handle handle) { | |||
152 | 152 | ||
153 | // Get parent container, to add view in | 153 | // Get parent container, to add view in |
154 | if (parent) { | 154 | if (parent) { |
155 | focused = swayc_by_test(test_handle, &parent); | 155 | focused = swayc_by_handle(parent); |
156 | } | 156 | } |
157 | if (!focused || focused->type == C_OUTPUT) { | 157 | if (!focused || focused->type == C_OUTPUT) { |
158 | focused = get_focused_container(&root_container); | 158 | focused = get_focused_container(&root_container); |
@@ -221,7 +221,7 @@ static bool handle_view_created(wlc_handle handle) { | |||
221 | 221 | ||
222 | static void handle_view_destroyed(wlc_handle handle) { | 222 | static void handle_view_destroyed(wlc_handle handle) { |
223 | sway_log(L_DEBUG, "Destroying window %lu", handle); | 223 | sway_log(L_DEBUG, "Destroying window %lu", handle); |
224 | swayc_t *view = swayc_by_test(test_handle, &handle); | 224 | swayc_t *view = swayc_by_handle(handle); |
225 | 225 | ||
226 | // destroy views by type | 226 | // destroy views by type |
227 | switch (wlc_view_get_type(handle)) { | 227 | switch (wlc_view_get_type(handle)) { |
@@ -258,7 +258,7 @@ static void handle_view_geometry_request(wlc_handle handle, const struct wlc_geo | |||
258 | // If the view is floating, then apply the geometry. | 258 | // If the view is floating, then apply the geometry. |
259 | // Otherwise save the desired width/height for the view. | 259 | // Otherwise save the desired width/height for the view. |
260 | // This will not do anything for the time being as WLC improperly sends geometry requests | 260 | // This will not do anything for the time being as WLC improperly sends geometry requests |
261 | swayc_t *view = swayc_by_test(test_handle, &handle); | 261 | swayc_t *view = swayc_by_handle(handle); |
262 | if (view) { | 262 | if (view) { |
263 | view->desired_width = geometry->size.w; | 263 | view->desired_width = geometry->size.w; |
264 | view->desired_height = geometry->size.h; | 264 | view->desired_height = geometry->size.h; |
@@ -274,7 +274,7 @@ static void handle_view_geometry_request(wlc_handle handle, const struct wlc_geo | |||
274 | } | 274 | } |
275 | 275 | ||
276 | static void handle_view_state_request(wlc_handle view, enum wlc_view_state_bit state, bool toggle) { | 276 | static void handle_view_state_request(wlc_handle view, enum wlc_view_state_bit state, bool toggle) { |
277 | swayc_t *c = swayc_by_test(test_handle, &view); | 277 | swayc_t *c = swayc_by_handle(view); |
278 | switch (state) { | 278 | switch (state) { |
279 | case WLC_BIT_FULLSCREEN: | 279 | case WLC_BIT_FULLSCREEN: |
280 | // i3 just lets it become fullscreen | 280 | // i3 just lets it become fullscreen |
@@ -207,7 +207,7 @@ void ipc_client_handle_command(struct ipc_client *client) { | |||
207 | case IPC_GET_WORKSPACES: | 207 | case IPC_GET_WORKSPACES: |
208 | { | 208 | { |
209 | json_object *workspaces = json_object_new_array(); | 209 | json_object *workspaces = json_object_new_array(); |
210 | swayc_map(ipc_get_workspaces_callback, workspaces); | 210 | container_map(&root_container, ipc_get_workspaces_callback, workspaces); |
211 | const char *json_string = json_object_to_json_string(workspaces); | 211 | const char *json_string = json_object_to_json_string(workspaces); |
212 | ipc_send_reply(client, json_string, (uint32_t) strlen(json_string)); | 212 | ipc_send_reply(client, json_string, (uint32_t) strlen(json_string)); |
213 | json_object_put(workspaces); // free | 213 | json_object_put(workspaces); // free |
@@ -216,7 +216,7 @@ void ipc_client_handle_command(struct ipc_client *client) { | |||
216 | case IPC_GET_OUTPUTS: | 216 | case IPC_GET_OUTPUTS: |
217 | { | 217 | { |
218 | json_object *outputs = json_object_new_array(); | 218 | json_object *outputs = json_object_new_array(); |
219 | swayc_map(ipc_get_outputs_callback, outputs); | 219 | container_map(&root_container, ipc_get_outputs_callback, outputs); |
220 | const char *json_string = json_object_to_json_string(outputs); | 220 | const char *json_string = json_object_to_json_string(outputs); |
221 | ipc_send_reply(client, json_string, (uint32_t) strlen(json_string)); | 221 | ipc_send_reply(client, json_string, (uint32_t) strlen(json_string)); |
222 | json_object_put(outputs); // free | 222 | json_object_put(outputs); // free |
diff --git a/sway/stringop.c b/sway/stringop.c index 54faf74c..191e40c8 100644 --- a/sway/stringop.c +++ b/sway/stringop.c | |||
@@ -258,7 +258,7 @@ int unescape_string(char *string) { | |||
258 | return len - shift; | 258 | return len - shift; |
259 | } | 259 | } |
260 | 260 | ||
261 | char *join_args(int argc, char **argv) { | 261 | char *join_args(char **argv, int argc) { |
262 | int len = 0, i; | 262 | int len = 0, i; |
263 | for (i = 0; i < argc; ++i) { | 263 | for (i = 0; i < argc; ++i) { |
264 | len += strlen(argv[i]) + 1; | 264 | len += strlen(argv[i]) + 1; |
diff --git a/sway/workspace.c b/sway/workspace.c index 80141f71..658f79bc 100644 --- a/sway/workspace.c +++ b/sway/workspace.c | |||
@@ -15,26 +15,7 @@ | |||
15 | 15 | ||
16 | char *prev_workspace_name = NULL; | 16 | char *prev_workspace_name = NULL; |
17 | 17 | ||
18 | static swayc_t *workspace_by_name_only(const char *name); | 18 | char *workspace_next_name(void) { |
19 | |||
20 | const char *workspace_output_open_name(swayc_t *output) { | ||
21 | struct workspace_output *wsop; | ||
22 | int i, len = config->workspace_outputs->length; | ||
23 | // Search config for output | ||
24 | for (i = 0; i < len; ++i) { | ||
25 | wsop = config->workspace_outputs->items[i]; | ||
26 | // Find matching outputs | ||
27 | if (strcasecmp(wsop->output, output->name)) { | ||
28 | // Check if workspace is available and use that name | ||
29 | if (!workspace_by_name(wsop->workspace)) { | ||
30 | return wsop->workspace; | ||
31 | } | ||
32 | } | ||
33 | } | ||
34 | return NULL; | ||
35 | } | ||
36 | |||
37 | const char *workspace_next_name(void) { | ||
38 | sway_log(L_DEBUG, "Workspace: Generating new name"); | 19 | sway_log(L_DEBUG, "Workspace: Generating new name"); |
39 | int i; | 20 | int i; |
40 | int l = 1; | 21 | int l = 1; |
@@ -44,29 +25,42 @@ const char *workspace_next_name(void) { | |||
44 | 25 | ||
45 | for (i = 0; i < mode->bindings->length; ++i) { | 26 | for (i = 0; i < mode->bindings->length; ++i) { |
46 | struct sway_binding *binding = mode->bindings->items[i]; | 27 | struct sway_binding *binding = mode->bindings->items[i]; |
47 | const char *command = binding->command; | 28 | const char* command = binding->command; |
48 | const char *ws = "workspace"; | 29 | list_t *args = split_string(command, " "); |
49 | const int wslen = sizeof("workspace") - 1; | 30 | |
50 | if (strncmp(ws, command, wslen) == 0) { | 31 | if (strcmp("workspace", args->items[0]) == 0 && args->length > 1) { |
51 | command += wslen; | 32 | sway_log(L_DEBUG, "Got valid workspace command for target: '%s'", (char *)args->items[1]); |
52 | // Skip whitespace | 33 | char* target = malloc(strlen(args->items[1]) + 1); |
53 | command += strspn(command, whitespace); | 34 | strcpy(target, args->items[1]); |
54 | // make sure its not a special command | 35 | while (*target == ' ' || *target == '\t') |
55 | if (strcmp(command, "next") == 0 | 36 | target++; |
56 | || strcmp(command, "prev") == 0 | 37 | |
57 | || strcmp(command, "next_on_output") == 0 | 38 | // Make sure that the command references an actual workspace |
58 | || strcmp(command, "prev_on_output") == 0 | 39 | // not a command about workspaces |
59 | || strcmp(command, "number") == 0 | 40 | if (strcmp(target, "next") == 0 || |
60 | || strcmp(command, "back_and_forth") == 0 | 41 | strcmp(target, "prev") == 0 || |
61 | || strcmp(command, "current") == 0 | 42 | strcmp(target, "next_on_output") == 0 || |
62 | // Or if it already exists | 43 | strcmp(target, "prev_on_output") == 0 || |
63 | || workspace_by_name_only(command)) { | 44 | strcmp(target, "number") == 0 || |
45 | strcmp(target, "back_and_forth") == 0 || | ||
46 | strcmp(target, "current") == 0) | ||
47 | { | ||
48 | free_flat_list(args); | ||
64 | continue; | 49 | continue; |
65 | } else { | ||
66 | // otherwise we found it | ||
67 | return command; | ||
68 | } | 50 | } |
51 | |||
52 | // Make sure that the workspace doesn't already exist | ||
53 | if (workspace_by_name(target)) { | ||
54 | free_flat_list(args); | ||
55 | continue; | ||
56 | } | ||
57 | |||
58 | free_flat_list(args); | ||
59 | |||
60 | sway_log(L_DEBUG, "Workspace: Found free name %s", target); | ||
61 | return target; | ||
69 | } | 62 | } |
63 | free_flat_list(args); | ||
70 | } | 64 | } |
71 | // As a fall back, get the current number of active workspaces | 65 | // As a fall back, get the current number of active workspaces |
72 | // and return that + 1 for the next workspace's name | 66 | // and return that + 1 for the next workspace's name |
@@ -81,40 +75,55 @@ const char *workspace_next_name(void) { | |||
81 | return name; | 75 | return name; |
82 | } | 76 | } |
83 | 77 | ||
84 | swayc_t *workspace_by_name_only(const char *name) { | 78 | swayc_t *workspace_create(const char* name) { |
85 | int i, len = root_container.children->length; | 79 | swayc_t *parent; |
86 | for (i = 0; i < len; ++i) { | 80 | // Search for workspace<->output pair |
87 | swayc_t *op = root_container.children->items[i]; | 81 | int i, e = config->workspace_outputs->length; |
88 | int i, len = op->children->length; | 82 | for (i = 0; i < e; ++i) { |
89 | for (i = 0; i < len; ++i) { | 83 | struct workspace_output *wso = config->workspace_outputs->items[i]; |
90 | swayc_t *ws = op->children->items[i]; | 84 | if (strcasecmp(wso->workspace, name) == 0) |
91 | if (strcasecmp(ws->name, name) == 0) { | 85 | { |
92 | return ws; | 86 | // Find output to use if it exists |
87 | e = root_container.children->length; | ||
88 | for (i = 0; i < e; ++i) { | ||
89 | parent = root_container.children->items[i]; | ||
90 | if (strcmp(parent->name, wso->output) == 0) { | ||
91 | return new_workspace(parent, name); | ||
92 | } | ||
93 | } | 93 | } |
94 | break; | ||
94 | } | 95 | } |
95 | } | 96 | } |
96 | return NULL; | 97 | // Otherwise create a new one |
98 | parent = get_focused_container(&root_container); | ||
99 | parent = swayc_parent_by_type(parent, C_OUTPUT); | ||
100 | return new_workspace(parent, name); | ||
101 | } | ||
102 | |||
103 | static bool _workspace_by_name(swayc_t *view, void *data) { | ||
104 | return (view->type == C_WORKSPACE) && | ||
105 | (strcasecmp(view->name, (char *) data) == 0); | ||
97 | } | 106 | } |
98 | 107 | ||
99 | swayc_t *workspace_by_name(const char* name) { | 108 | swayc_t *workspace_by_name(const char* name) { |
100 | if (strcmp(name, "prev") == 0) { | 109 | if (strcmp(name, "prev") == 0) { |
101 | return workspace_prev(); | 110 | return workspace_prev(); |
102 | } else if (!strcmp(name, "prev_on_output")) { | 111 | } |
112 | else if (strcmp(name, "prev_on_output") == 0) { | ||
103 | return workspace_output_prev(); | 113 | return workspace_output_prev(); |
104 | } else if (!strcmp(name, "next")) { | 114 | } |
115 | else if (strcmp(name, "next") == 0) { | ||
105 | return workspace_next(); | 116 | return workspace_next(); |
106 | } else if (!strcmp(name, "next_on_output")) { | 117 | } |
118 | else if (strcmp(name, "next_on_output") == 0) { | ||
107 | return workspace_output_next(); | 119 | return workspace_output_next(); |
108 | } else if (!strcmp(name, "current")) { | 120 | } |
121 | else if (strcmp(name, "current") == 0) { | ||
109 | return swayc_active_workspace(); | 122 | return swayc_active_workspace(); |
110 | } else if (!strcmp(name, "back_and_forth")) { | ||
111 | if (prev_workspace_name) { | ||
112 | name = prev_workspace_name; | ||
113 | } else { // If there is no prev workspace name. just return current | ||
114 | return swayc_active_workspace(); | ||
115 | } | ||
116 | } | 123 | } |
117 | return workspace_by_name_only(name); | 124 | else { |
125 | return swayc_by_test(&root_container, _workspace_by_name, (void *) name); | ||
126 | } | ||
118 | } | 127 | } |
119 | 128 | ||
120 | /** | 129 | /** |
@@ -172,19 +181,19 @@ swayc_t *workspace_prev_next_impl(swayc_t *workspace, bool next) { | |||
172 | return NULL; | 181 | return NULL; |
173 | } | 182 | } |
174 | 183 | ||
175 | swayc_t *workspace_output_next(void) { | 184 | swayc_t *workspace_output_next() { |
176 | return workspace_output_prev_next_impl(swayc_active_output(), true); | 185 | return workspace_output_prev_next_impl(swayc_active_output(), true); |
177 | } | 186 | } |
178 | 187 | ||
179 | swayc_t *workspace_next(void) { | 188 | swayc_t *workspace_next() { |
180 | return workspace_prev_next_impl(swayc_active_workspace(), true); | 189 | return workspace_prev_next_impl(swayc_active_workspace(), true); |
181 | } | 190 | } |
182 | 191 | ||
183 | swayc_t *workspace_output_prev(void) { | 192 | swayc_t *workspace_output_prev() { |
184 | return workspace_output_prev_next_impl(swayc_active_output(), false); | 193 | return workspace_output_prev_next_impl(swayc_active_output(), false); |
185 | } | 194 | } |
186 | 195 | ||
187 | swayc_t *workspace_prev(void) { | 196 | swayc_t *workspace_prev() { |
188 | return workspace_prev_next_impl(swayc_active_workspace(), false); | 197 | return workspace_prev_next_impl(swayc_active_workspace(), false); |
189 | } | 198 | } |
190 | 199 | ||
@@ -193,17 +202,17 @@ void workspace_switch(swayc_t *workspace) { | |||
193 | return; | 202 | return; |
194 | } | 203 | } |
195 | swayc_t *active_ws = swayc_active_workspace(); | 204 | swayc_t *active_ws = swayc_active_workspace(); |
196 | // set workspace to prev_workspace | 205 | if (config->auto_back_and_forth && active_ws == workspace && prev_workspace_name) { |
197 | if (config->auto_back_and_forth && active_ws == workspace) { | 206 | swayc_t *new_ws = workspace_by_name(prev_workspace_name); |
198 | workspace = new_workspace(NULL, "back_and_forth"); | 207 | workspace = new_ws ? new_ws : workspace_create(prev_workspace_name); |
199 | } | 208 | } |
200 | 209 | ||
201 | // set prev workspace name | ||
202 | if (!prev_workspace_name | 210 | if (!prev_workspace_name |
203 | || (strcmp(prev_workspace_name, active_ws->name) | 211 | || (strcmp(prev_workspace_name, active_ws->name) |
204 | && active_ws != workspace)) { | 212 | && active_ws != workspace)) { |
205 | free(prev_workspace_name); | 213 | free(prev_workspace_name); |
206 | prev_workspace_name = strdup(active_ws->name); | 214 | prev_workspace_name = malloc(strlen(active_ws->name)+1); |
215 | strcpy(prev_workspace_name, active_ws->name); | ||
207 | } | 216 | } |
208 | 217 | ||
209 | sway_log(L_DEBUG, "Switching to workspace %p:%s", workspace, workspace->name); | 218 | sway_log(L_DEBUG, "Switching to workspace %p:%s", workspace, workspace->name); |