diff options
author | Drew DeVault <sir@cmpwn.com> | 2018-06-02 08:09:18 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-06-02 08:09:18 -0700 |
commit | b0f2fd94791708a84aac2eccc57855a4ce8b6ec0 (patch) | |
tree | 919f22247b71c5562b3c1caff4f0bfa9dfcf0528 | |
parent | Merge pull request #2080 from frsfnrrg/keyboard-remodeling (diff) | |
parent | Fix infinite loop in peek_line for EOF blanks (diff) | |
download | sway-b0f2fd94791708a84aac2eccc57855a4ce8b6ec0.tar.gz sway-b0f2fd94791708a84aac2eccc57855a4ce8b6ec0.tar.zst sway-b0f2fd94791708a84aac2eccc57855a4ce8b6ec0.zip |
Merge pull request #2070 from RedSoxFan/generic-config-blocks
Make command block implementation generic
-rw-r--r-- | common/readline.c | 23 | ||||
-rw-r--r-- | include/readline.h | 1 | ||||
-rw-r--r-- | include/sway/commands.h | 29 | ||||
-rw-r--r-- | include/sway/config.h | 2 | ||||
-rw-r--r-- | sway/commands.c | 153 | ||||
-rw-r--r-- | sway/commands/bar.c | 118 | ||||
-rw-r--r-- | sway/commands/bar/colors.c | 26 | ||||
-rw-r--r-- | sway/commands/bar/id.c | 3 | ||||
-rw-r--r-- | sway/commands/input.c | 103 | ||||
-rw-r--r-- | sway/commands/mode.c | 28 | ||||
-rw-r--r-- | sway/commands/seat.c | 61 | ||||
-rw-r--r-- | sway/config.c | 196 | ||||
-rw-r--r-- | sway/input/keyboard.c | 1 | ||||
-rw-r--r-- | sway/ipc-server.c | 1 |
14 files changed, 349 insertions, 396 deletions
diff --git a/common/readline.c b/common/readline.c index ed5801de..1c396a90 100644 --- a/common/readline.c +++ b/common/readline.c | |||
@@ -1,3 +1,4 @@ | |||
1 | #define _POSIX_C_SOURCE 200809L | ||
1 | #include "readline.h" | 2 | #include "readline.h" |
2 | #include "log.h" | 3 | #include "log.h" |
3 | #include <stdlib.h> | 4 | #include <stdlib.h> |
@@ -48,6 +49,28 @@ char *read_line(FILE *file) { | |||
48 | return string; | 49 | return string; |
49 | } | 50 | } |
50 | 51 | ||
52 | char *peek_line(FILE *file, int line_offset, long *position) { | ||
53 | long pos = ftell(file); | ||
54 | size_t length = 0; | ||
55 | char *line = NULL; | ||
56 | for (int i = 0; i <= line_offset; i++) { | ||
57 | ssize_t read = getline(&line, &length, file); | ||
58 | if (read < 0) { | ||
59 | free(line); | ||
60 | line = NULL; | ||
61 | break; | ||
62 | } | ||
63 | if (read > 0 && line[read - 1] == '\n') { | ||
64 | line[read - 1] = '\0'; | ||
65 | } | ||
66 | } | ||
67 | if (position) { | ||
68 | *position = ftell(file); | ||
69 | } | ||
70 | fseek(file, pos, SEEK_SET); | ||
71 | return line; | ||
72 | } | ||
73 | |||
51 | char *read_line_buffer(FILE *file, char *string, size_t string_len) { | 74 | char *read_line_buffer(FILE *file, char *string, size_t string_len) { |
52 | size_t length = 0; | 75 | size_t length = 0; |
53 | if (!string) { | 76 | if (!string) { |
diff --git a/include/readline.h b/include/readline.h index b3e06d4b..ee2eba5d 100644 --- a/include/readline.h +++ b/include/readline.h | |||
@@ -4,6 +4,7 @@ | |||
4 | #include <stdio.h> | 4 | #include <stdio.h> |
5 | 5 | ||
6 | char *read_line(FILE *file); | 6 | char *read_line(FILE *file); |
7 | char *peek_line(FILE *file, int line_offset, long *position); | ||
7 | char *read_line_buffer(FILE *file, char *string, size_t string_len); | 8 | char *read_line_buffer(FILE *file, char *string, size_t string_len); |
8 | 9 | ||
9 | #endif | 10 | #endif |
diff --git a/include/sway/commands.h b/include/sway/commands.h index b2255c4b..593ae0f1 100644 --- a/include/sway/commands.h +++ b/include/sway/commands.h | |||
@@ -3,6 +3,13 @@ | |||
3 | 3 | ||
4 | #include "config.h" | 4 | #include "config.h" |
5 | 5 | ||
6 | typedef struct cmd_results *sway_cmd(int argc, char **argv); | ||
7 | |||
8 | struct cmd_handler { | ||
9 | char *command; | ||
10 | sway_cmd *handle; | ||
11 | }; | ||
12 | |||
6 | /** | 13 | /** |
7 | * Indicates the result of a command's execution. | 14 | * Indicates the result of a command's execution. |
8 | */ | 15 | */ |
@@ -11,16 +18,9 @@ enum cmd_status { | |||
11 | CMD_FAILURE, /**< The command resulted in an error */ | 18 | CMD_FAILURE, /**< The command resulted in an error */ |
12 | CMD_INVALID, /**< Unknown command or parser error */ | 19 | CMD_INVALID, /**< Unknown command or parser error */ |
13 | CMD_DEFER, /**< Command execution deferred */ | 20 | CMD_DEFER, /**< Command execution deferred */ |
14 | // Config Blocks | 21 | CMD_BLOCK, |
15 | CMD_BLOCK_END, | ||
16 | CMD_BLOCK_MODE, | ||
17 | CMD_BLOCK_BAR, | ||
18 | CMD_BLOCK_BAR_COLORS, | ||
19 | CMD_BLOCK_INPUT, | ||
20 | CMD_BLOCK_SEAT, | ||
21 | CMD_BLOCK_COMMANDS, | 22 | CMD_BLOCK_COMMANDS, |
22 | CMD_BLOCK_IPC, | 23 | CMD_BLOCK_END |
23 | CMD_BLOCK_IPC_EVENTS, | ||
24 | }; | 24 | }; |
25 | 25 | ||
26 | /** | 26 | /** |
@@ -45,6 +45,8 @@ enum expected_args { | |||
45 | struct cmd_results *checkarg(int argc, const char *name, | 45 | struct cmd_results *checkarg(int argc, const char *name, |
46 | enum expected_args type, int val); | 46 | enum expected_args type, int val); |
47 | 47 | ||
48 | struct cmd_handler *find_handler(char *line, struct cmd_handler *cmd_handlers, | ||
49 | int handlers_size); | ||
48 | /** | 50 | /** |
49 | * Parse and executes a command. | 51 | * Parse and executes a command. |
50 | */ | 52 | */ |
@@ -54,7 +56,12 @@ struct cmd_results *execute_command(char *command, struct sway_seat *seat); | |||
54 | * | 56 | * |
55 | * Do not use this under normal conditions. | 57 | * Do not use this under normal conditions. |
56 | */ | 58 | */ |
57 | struct cmd_results *config_command(char *command, enum cmd_status block); | 59 | struct cmd_results *config_command(char *command); |
60 | /** | ||
61 | * Parse and handle a sub command | ||
62 | */ | ||
63 | struct cmd_results *config_subcommand(char **argv, int argc, | ||
64 | struct cmd_handler *handlers, size_t handlers_size); | ||
58 | /* | 65 | /* |
59 | * Parses a command policy rule. | 66 | * Parses a command policy rule. |
60 | */ | 67 | */ |
@@ -77,8 +84,6 @@ const char *cmd_results_to_json(struct cmd_results *results); | |||
77 | struct cmd_results *add_color(const char *name, | 84 | struct cmd_results *add_color(const char *name, |
78 | char *buffer, const char *color); | 85 | char *buffer, const char *color); |
79 | 86 | ||
80 | typedef struct cmd_results *sway_cmd(int argc, char **argv); | ||
81 | |||
82 | sway_cmd cmd_assign; | 87 | sway_cmd cmd_assign; |
83 | sway_cmd cmd_bar; | 88 | sway_cmd cmd_bar; |
84 | sway_cmd cmd_bindcode; | 89 | sway_cmd cmd_bindcode; |
diff --git a/include/sway/config.h b/include/sway/config.h index de651ea4..b597da75 100644 --- a/include/sway/config.h +++ b/include/sway/config.h | |||
@@ -403,8 +403,6 @@ bool read_config(FILE *file, struct sway_config *config); | |||
403 | */ | 403 | */ |
404 | void free_config(struct sway_config *config); | 404 | void free_config(struct sway_config *config); |
405 | 405 | ||
406 | void config_clear_handler_context(struct sway_config *config); | ||
407 | |||
408 | void free_sway_variable(struct sway_variable *var); | 406 | void free_sway_variable(struct sway_variable *var); |
409 | 407 | ||
410 | /** | 408 | /** |
diff --git a/sway/commands.c b/sway/commands.c index e9762bef..3a86ae53 100644 --- a/sway/commands.c +++ b/sway/commands.c | |||
@@ -16,11 +16,6 @@ | |||
16 | #include "stringop.h" | 16 | #include "stringop.h" |
17 | #include "log.h" | 17 | #include "log.h" |
18 | 18 | ||
19 | struct cmd_handler { | ||
20 | char *command; | ||
21 | sway_cmd *handle; | ||
22 | }; | ||
23 | |||
24 | // Returns error object, or NULL if check succeeds. | 19 | // Returns error object, or NULL if check succeeds. |
25 | struct cmd_results *checkarg(int argc, const char *name, enum expected_args type, int val) { | 20 | struct cmd_results *checkarg(int argc, const char *name, enum expected_args type, int val) { |
26 | struct cmd_results *error = NULL; | 21 | struct cmd_results *error = NULL; |
@@ -122,47 +117,6 @@ static struct cmd_handler handlers[] = { | |||
122 | { "workspace_auto_back_and_forth", cmd_ws_auto_back_and_forth }, | 117 | { "workspace_auto_back_and_forth", cmd_ws_auto_back_and_forth }, |
123 | }; | 118 | }; |
124 | 119 | ||
125 | static struct cmd_handler bar_handlers[] = { | ||
126 | { "activate_button", bar_cmd_activate_button }, | ||
127 | { "binding_mode_indicator", bar_cmd_binding_mode_indicator }, | ||
128 | { "bindsym", bar_cmd_bindsym }, | ||
129 | { "colors", bar_cmd_colors }, | ||
130 | { "context_button", bar_cmd_context_button }, | ||
131 | { "font", bar_cmd_font }, | ||
132 | { "height", bar_cmd_height }, | ||
133 | { "hidden_state", bar_cmd_hidden_state }, | ||
134 | { "icon_theme", bar_cmd_icon_theme }, | ||
135 | { "id", bar_cmd_id }, | ||
136 | { "mode", bar_cmd_mode }, | ||
137 | { "modifier", bar_cmd_modifier }, | ||
138 | { "output", bar_cmd_output }, | ||
139 | { "pango_markup", bar_cmd_pango_markup }, | ||
140 | { "position", bar_cmd_position }, | ||
141 | { "secondary_button", bar_cmd_secondary_button }, | ||
142 | { "separator_symbol", bar_cmd_separator_symbol }, | ||
143 | { "status_command", bar_cmd_status_command }, | ||
144 | { "strip_workspace_numbers", bar_cmd_strip_workspace_numbers }, | ||
145 | { "swaybar_command", bar_cmd_swaybar_command }, | ||
146 | { "tray_output", bar_cmd_tray_output }, | ||
147 | { "tray_padding", bar_cmd_tray_padding }, | ||
148 | { "workspace_buttons", bar_cmd_workspace_buttons }, | ||
149 | { "wrap_scroll", bar_cmd_wrap_scroll }, | ||
150 | }; | ||
151 | |||
152 | static struct cmd_handler bar_colors_handlers[] = { | ||
153 | { "active_workspace", bar_colors_cmd_active_workspace }, | ||
154 | { "background", bar_colors_cmd_background }, | ||
155 | { "binding_mode", bar_colors_cmd_binding_mode }, | ||
156 | { "focused_background", bar_colors_cmd_focused_background }, | ||
157 | { "focused_separator", bar_colors_cmd_focused_separator }, | ||
158 | { "focused_statusline", bar_colors_cmd_focused_statusline }, | ||
159 | { "focused_workspace", bar_colors_cmd_focused_workspace }, | ||
160 | { "inactive_workspace", bar_colors_cmd_inactive_workspace }, | ||
161 | { "separator", bar_colors_cmd_separator }, | ||
162 | { "statusline", bar_colors_cmd_statusline }, | ||
163 | { "urgent_workspace", bar_colors_cmd_urgent_workspace }, | ||
164 | }; | ||
165 | |||
166 | /* Config-time only commands. Keep alphabetized */ | 120 | /* Config-time only commands. Keep alphabetized */ |
167 | static struct cmd_handler config_handlers[] = { | 121 | static struct cmd_handler config_handlers[] = { |
168 | { "default_orientation", cmd_default_orientation }, | 122 | { "default_orientation", cmd_default_orientation }, |
@@ -202,62 +156,14 @@ static int handler_compare(const void *_a, const void *_b) { | |||
202 | return strcasecmp(a->command, b->command); | 156 | return strcasecmp(a->command, b->command); |
203 | } | 157 | } |
204 | 158 | ||
205 | // must be in order for the bsearch | 159 | struct cmd_handler *find_handler(char *line, struct cmd_handler *cmd_handlers, |
206 | static struct cmd_handler input_handlers[] = { | 160 | int handlers_size) { |
207 | { "accel_profile", input_cmd_accel_profile }, | ||
208 | { "click_method", input_cmd_click_method }, | ||
209 | { "drag_lock", input_cmd_drag_lock }, | ||
210 | { "dwt", input_cmd_dwt }, | ||
211 | { "events", input_cmd_events }, | ||
212 | { "left_handed", input_cmd_left_handed }, | ||
213 | { "map_from_region", input_cmd_map_from_region }, | ||
214 | { "map_to_output", input_cmd_map_to_output }, | ||
215 | { "middle_emulation", input_cmd_middle_emulation }, | ||
216 | { "natural_scroll", input_cmd_natural_scroll }, | ||
217 | { "pointer_accel", input_cmd_pointer_accel }, | ||
218 | { "repeat_delay", input_cmd_repeat_delay }, | ||
219 | { "repeat_rate", input_cmd_repeat_rate }, | ||
220 | { "scroll_method", input_cmd_scroll_method }, | ||
221 | { "tap", input_cmd_tap }, | ||
222 | { "xkb_layout", input_cmd_xkb_layout }, | ||
223 | { "xkb_model", input_cmd_xkb_model }, | ||
224 | { "xkb_options", input_cmd_xkb_options }, | ||
225 | { "xkb_rules", input_cmd_xkb_rules }, | ||
226 | { "xkb_variant", input_cmd_xkb_variant }, | ||
227 | }; | ||
228 | |||
229 | // must be in order for the bsearch | ||
230 | static struct cmd_handler seat_handlers[] = { | ||
231 | { "attach", seat_cmd_attach }, | ||
232 | { "cursor", seat_cmd_cursor }, | ||
233 | { "fallback", seat_cmd_fallback }, | ||
234 | }; | ||
235 | |||
236 | static struct cmd_handler *find_handler(char *line, enum cmd_status block) { | ||
237 | struct cmd_handler d = { .command=line }; | 161 | struct cmd_handler d = { .command=line }; |
238 | struct cmd_handler *res = NULL; | 162 | struct cmd_handler *res = NULL; |
239 | wlr_log(L_DEBUG, "find_handler(%s) %d", line, block == CMD_BLOCK_SEAT); | 163 | wlr_log(L_DEBUG, "find_handler(%s)", line); |
240 | 164 | ||
241 | bool config_loading = config->reading || !config->active; | 165 | bool config_loading = config->reading || !config->active; |
242 | 166 | ||
243 | if (block == CMD_BLOCK_BAR) { | ||
244 | return bsearch(&d, bar_handlers, | ||
245 | sizeof(bar_handlers) / sizeof(struct cmd_handler), | ||
246 | sizeof(struct cmd_handler), handler_compare); | ||
247 | } else if (block == CMD_BLOCK_BAR_COLORS) { | ||
248 | return bsearch(&d, bar_colors_handlers, | ||
249 | sizeof(bar_colors_handlers) / sizeof(struct cmd_handler), | ||
250 | sizeof(struct cmd_handler), handler_compare); | ||
251 | } else if (block == CMD_BLOCK_INPUT) { | ||
252 | return bsearch(&d, input_handlers, | ||
253 | sizeof(input_handlers) / sizeof(struct cmd_handler), | ||
254 | sizeof(struct cmd_handler), handler_compare); | ||
255 | } else if (block == CMD_BLOCK_SEAT) { | ||
256 | return bsearch(&d, seat_handlers, | ||
257 | sizeof(seat_handlers) / sizeof(struct cmd_handler), | ||
258 | sizeof(struct cmd_handler), handler_compare); | ||
259 | } | ||
260 | |||
261 | if (!config_loading) { | 167 | if (!config_loading) { |
262 | res = bsearch(&d, command_handlers, | 168 | res = bsearch(&d, command_handlers, |
263 | sizeof(command_handlers) / sizeof(struct cmd_handler), | 169 | sizeof(command_handlers) / sizeof(struct cmd_handler), |
@@ -278,8 +184,13 @@ static struct cmd_handler *find_handler(char *line, enum cmd_status block) { | |||
278 | } | 184 | } |
279 | } | 185 | } |
280 | 186 | ||
281 | res = bsearch(&d, handlers, | 187 | if (!cmd_handlers) { |
282 | sizeof(handlers) / sizeof(struct cmd_handler), | 188 | cmd_handlers = handlers; |
189 | handlers_size = sizeof(handlers); | ||
190 | } | ||
191 | |||
192 | res = bsearch(&d, cmd_handlers, | ||
193 | handlers_size / sizeof(struct cmd_handler), | ||
283 | sizeof(struct cmd_handler), handler_compare); | 194 | sizeof(struct cmd_handler), handler_compare); |
284 | 195 | ||
285 | return res; | 196 | return res; |
@@ -349,7 +260,7 @@ struct cmd_results *execute_command(char *_exec, struct sway_seat *seat) { | |||
349 | } | 260 | } |
350 | } | 261 | } |
351 | } | 262 | } |
352 | struct cmd_handler *handler = find_handler(argv[0], CMD_BLOCK_END); | 263 | struct cmd_handler *handler = find_handler(argv[0], NULL, 0); |
353 | if (!handler) { | 264 | if (!handler) { |
354 | if (results) { | 265 | if (results) { |
355 | free_cmd_results(results); | 266 | free_cmd_results(results); |
@@ -413,7 +324,7 @@ cleanup: | |||
413 | // be chained together) | 324 | // be chained together) |
414 | // 4) execute_command handles all state internally while config_command has | 325 | // 4) execute_command handles all state internally while config_command has |
415 | // some state handled outside (notably the block mode, in read_config) | 326 | // some state handled outside (notably the block mode, in read_config) |
416 | struct cmd_results *config_command(char *exec, enum cmd_status block) { | 327 | struct cmd_results *config_command(char *exec) { |
417 | struct cmd_results *results = NULL; | 328 | struct cmd_results *results = NULL; |
418 | int argc; | 329 | int argc; |
419 | char **argv = split_args(exec, &argc); | 330 | char **argv = split_args(exec, &argc); |
@@ -422,13 +333,21 @@ struct cmd_results *config_command(char *exec, enum cmd_status block) { | |||
422 | goto cleanup; | 333 | goto cleanup; |
423 | } | 334 | } |
424 | 335 | ||
425 | wlr_log(L_INFO, "handling config command '%s'", exec); | 336 | // Start block |
337 | if (argc > 1 && strcmp(argv[argc - 1], "{") == 0) { | ||
338 | char *block = join_args(argv, argc - 1); | ||
339 | results = cmd_results_new(CMD_BLOCK, block, NULL); | ||
340 | free(block); | ||
341 | goto cleanup; | ||
342 | } | ||
343 | |||
426 | // Endblock | 344 | // Endblock |
427 | if (**argv == '}') { | 345 | if (strcmp(argv[argc - 1], "}") == 0) { |
428 | results = cmd_results_new(CMD_BLOCK_END, NULL, NULL); | 346 | results = cmd_results_new(CMD_BLOCK_END, NULL, NULL); |
429 | goto cleanup; | 347 | goto cleanup; |
430 | } | 348 | } |
431 | struct cmd_handler *handler = find_handler(argv[0], block); | 349 | wlr_log(L_INFO, "handling config command '%s'", exec); |
350 | struct cmd_handler *handler = find_handler(argv[0], NULL, 0); | ||
432 | if (!handler) { | 351 | if (!handler) { |
433 | char *input = argv[0] ? argv[0] : "(empty)"; | 352 | char *input = argv[0] ? argv[0] : "(empty)"; |
434 | results = cmd_results_new(CMD_INVALID, input, "Unknown/invalid command"); | 353 | results = cmd_results_new(CMD_INVALID, input, "Unknown/invalid command"); |
@@ -457,6 +376,30 @@ cleanup: | |||
457 | return results; | 376 | return results; |
458 | } | 377 | } |
459 | 378 | ||
379 | struct cmd_results *config_subcommand(char **argv, int argc, | ||
380 | struct cmd_handler *handlers, size_t handlers_size) { | ||
381 | char *command = join_args(argv, argc); | ||
382 | wlr_log(L_DEBUG, "Subcommand: %s", command); | ||
383 | free(command); | ||
384 | |||
385 | struct cmd_handler *handler = find_handler(argv[0], handlers, | ||
386 | handlers_size); | ||
387 | if (!handler) { | ||
388 | char *input = argv[0] ? argv[0] : "(empty)"; | ||
389 | return cmd_results_new(CMD_INVALID, input, "Unknown/invalid command"); | ||
390 | } | ||
391 | // Strip quotes for first argument. | ||
392 | // TODO This part needs to be handled much better | ||
393 | if (argc > 1 && (*argv[1] == '\"' || *argv[1] == '\'')) { | ||
394 | strip_quotes(argv[1]); | ||
395 | } | ||
396 | if (handler->handle) { | ||
397 | return handler->handle(argc - 1, argv + 1); | ||
398 | } | ||
399 | return cmd_results_new(CMD_INVALID, argv[0], | ||
400 | "This command is shimmed, but unimplemented"); | ||
401 | } | ||
402 | |||
460 | struct cmd_results *config_commands_command(char *exec) { | 403 | struct cmd_results *config_commands_command(char *exec) { |
461 | struct cmd_results *results = NULL; | 404 | struct cmd_results *results = NULL; |
462 | int argc; | 405 | int argc; |
@@ -474,7 +417,7 @@ struct cmd_results *config_commands_command(char *exec) { | |||
474 | goto cleanup; | 417 | goto cleanup; |
475 | } | 418 | } |
476 | 419 | ||
477 | struct cmd_handler *handler = find_handler(cmd, CMD_BLOCK_END); | 420 | struct cmd_handler *handler = find_handler(cmd, NULL, 0); |
478 | if (!handler && strcmp(cmd, "*") != 0) { | 421 | if (!handler && strcmp(cmd, "*") != 0) { |
479 | char *input = cmd ? cmd : "(empty)"; | 422 | char *input = cmd ? cmd : "(empty)"; |
480 | results = cmd_results_new(CMD_INVALID, input, "Unknown/invalid command"); | 423 | results = cmd_results_new(CMD_INVALID, input, "Unknown/invalid command"); |
diff --git a/sway/commands/bar.c b/sway/commands/bar.c index ff111163..d84ce808 100644 --- a/sway/commands/bar.c +++ b/sway/commands/bar.c | |||
@@ -1,3 +1,4 @@ | |||
1 | #define _XOPEN_SOURCE 500 | ||
1 | #include <string.h> | 2 | #include <string.h> |
2 | #include <strings.h> | 3 | #include <strings.h> |
3 | #include <wlr/util/log.h> | 4 | #include <wlr/util/log.h> |
@@ -5,53 +6,110 @@ | |||
5 | #include "sway/config.h" | 6 | #include "sway/config.h" |
6 | #include "util.h" | 7 | #include "util.h" |
7 | 8 | ||
9 | // Must be in alphabetical order for bsearch | ||
10 | static struct cmd_handler bar_handlers[] = { | ||
11 | { "activate_button", bar_cmd_activate_button }, | ||
12 | { "binding_mode_indicator", bar_cmd_binding_mode_indicator }, | ||
13 | { "bindsym", bar_cmd_bindsym }, | ||
14 | { "colors", bar_cmd_colors }, | ||
15 | { "context_button", bar_cmd_context_button }, | ||
16 | { "font", bar_cmd_font }, | ||
17 | { "height", bar_cmd_height }, | ||
18 | { "hidden_state", bar_cmd_hidden_state }, | ||
19 | { "icon_theme", bar_cmd_icon_theme }, | ||
20 | { "id", bar_cmd_id }, | ||
21 | { "mode", bar_cmd_mode }, | ||
22 | { "modifier", bar_cmd_modifier }, | ||
23 | { "output", bar_cmd_output }, | ||
24 | { "pango_markup", bar_cmd_pango_markup }, | ||
25 | { "position", bar_cmd_position }, | ||
26 | { "secondary_button", bar_cmd_secondary_button }, | ||
27 | { "separator_symbol", bar_cmd_separator_symbol }, | ||
28 | { "status_command", bar_cmd_status_command }, | ||
29 | { "strip_workspace_numbers", bar_cmd_strip_workspace_numbers }, | ||
30 | { "swaybar_command", bar_cmd_swaybar_command }, | ||
31 | { "tray_output", bar_cmd_tray_output }, | ||
32 | { "tray_padding", bar_cmd_tray_padding }, | ||
33 | { "workspace_buttons", bar_cmd_workspace_buttons }, | ||
34 | { "wrap_scroll", bar_cmd_wrap_scroll }, | ||
35 | }; | ||
36 | |||
37 | // Must be in alphabetical order for bsearch | ||
38 | static struct cmd_handler bar_config_handlers[] = { | ||
39 | { "hidden_state", bar_cmd_hidden_state }, | ||
40 | { "mode", bar_cmd_mode } | ||
41 | }; | ||
42 | |||
8 | struct cmd_results *cmd_bar(int argc, char **argv) { | 43 | struct cmd_results *cmd_bar(int argc, char **argv) { |
9 | struct cmd_results *error = NULL; | 44 | struct cmd_results *error = NULL; |
10 | if ((error = checkarg(argc, "bar", EXPECTED_AT_LEAST, 1))) { | 45 | if ((error = checkarg(argc, "bar", EXPECTED_AT_LEAST, 1))) { |
11 | return error; | 46 | return error; |
12 | } | 47 | } |
13 | 48 | ||
14 | if (config->reading && strcmp("{", argv[0]) != 0) { | 49 | if (!config->reading) { |
15 | return cmd_results_new(CMD_INVALID, "bar", | 50 | if (!find_handler(argv[0], bar_config_handlers, |
16 | "Expected '{' at start of bar config definition."); | 51 | sizeof(bar_config_handlers))) { |
52 | return cmd_results_new(CMD_FAILURE, "bar", | ||
53 | "Can only be used in config file."); | ||
54 | } | ||
55 | return config_subcommand(argv, argc, bar_config_handlers, | ||
56 | sizeof(bar_config_handlers)); | ||
17 | } | 57 | } |
18 | 58 | ||
19 | if (!config->reading) { | 59 | if (argc > 1) { |
20 | if (argc > 1) { | 60 | struct bar_config *bar = NULL; |
21 | if (strcasecmp("mode", argv[0]) == 0) { | 61 | if (!find_handler(argv[0], bar_handlers, sizeof(bar_handlers)) |
22 | return bar_cmd_mode(argc-1, argv + 1); | 62 | && find_handler(argv[1], bar_handlers, sizeof(bar_handlers))) { |
63 | for (int i = 0; i < config->bars->length; ++i) { | ||
64 | struct bar_config *item = config->bars->items[i]; | ||
65 | if (strcmp(item->id, argv[0]) == 0) { | ||
66 | wlr_log(L_DEBUG, "Selecting bar: %s", argv[0]); | ||
67 | bar = item; | ||
68 | break; | ||
69 | } | ||
23 | } | 70 | } |
71 | if (!bar) { | ||
72 | wlr_log(L_DEBUG, "Creating bar: %s", argv[0]); | ||
73 | bar = default_bar_config(); | ||
74 | if (!bar) { | ||
75 | return cmd_results_new(CMD_FAILURE, "bar", | ||
76 | "Unable to allocate bar state"); | ||
77 | } | ||
24 | 78 | ||
25 | if (strcasecmp("hidden_state", argv[0]) == 0) { | 79 | bar->id = strdup(argv[0]); |
26 | return bar_cmd_hidden_state(argc-1, argv + 1); | ||
27 | } | 80 | } |
81 | config->current_bar = bar; | ||
82 | ++argv; --argc; | ||
28 | } | 83 | } |
29 | return cmd_results_new(CMD_FAILURE, "bar", "Can only be used in config file."); | ||
30 | } | 84 | } |
31 | 85 | ||
32 | // Create new bar with default values | 86 | if (!config->current_bar) { |
33 | struct bar_config *bar = default_bar_config(); | 87 | // Create new bar with default values |
34 | if (!bar) { | 88 | struct bar_config *bar = default_bar_config(); |
35 | return cmd_results_new(CMD_FAILURE, "bar", "Unable to allocate bar state"); | 89 | if (!bar) { |
36 | } | 90 | return cmd_results_new(CMD_FAILURE, "bar", |
91 | "Unable to allocate bar state"); | ||
92 | } | ||
37 | 93 | ||
38 | // set bar id | 94 | // set bar id |
39 | for (int i = 0; i < config->bars->length; ++i) { | 95 | for (int i = 0; i < config->bars->length; ++i) { |
40 | if (bar == config->bars->items[i]) { | 96 | if (bar == config->bars->items[i]) { |
41 | const int len = 5 + numlen(i); // "bar-" + i + \0 | 97 | const int len = 5 + numlen(i); // "bar-" + i + \0 |
42 | bar->id = malloc(len * sizeof(char)); | 98 | bar->id = malloc(len * sizeof(char)); |
43 | if (bar->id) { | 99 | if (bar->id) { |
44 | snprintf(bar->id, len, "bar-%d", i); | 100 | snprintf(bar->id, len, "bar-%d", i); |
45 | } else { | 101 | } else { |
46 | return cmd_results_new(CMD_FAILURE, | 102 | return cmd_results_new(CMD_FAILURE, |
47 | "bar", "Unable to allocate bar ID"); | 103 | "bar", "Unable to allocate bar ID"); |
104 | } | ||
105 | break; | ||
48 | } | 106 | } |
49 | break; | ||
50 | } | 107 | } |
108 | |||
109 | // Set current bar | ||
110 | config->current_bar = bar; | ||
111 | wlr_log(L_DEBUG, "Creating bar %s", bar->id); | ||
51 | } | 112 | } |
52 | 113 | ||
53 | // Set current bar | 114 | return config_subcommand(argv, argc, bar_handlers, sizeof(bar_handlers)); |
54 | config->current_bar = bar; | ||
55 | wlr_log(L_DEBUG, "Configuring bar %s", bar->id); | ||
56 | return cmd_results_new(CMD_BLOCK_BAR, NULL, NULL); | ||
57 | } | 115 | } |
diff --git a/sway/commands/bar/colors.c b/sway/commands/bar/colors.c index 17ba9b7c..8c862ca9 100644 --- a/sway/commands/bar/colors.c +++ b/sway/commands/bar/colors.c | |||
@@ -1,6 +1,21 @@ | |||
1 | #include <string.h> | 1 | #include <string.h> |
2 | #include "sway/commands.h" | 2 | #include "sway/commands.h" |
3 | 3 | ||
4 | // Must be in alphabetical order for bsearch | ||
5 | static struct cmd_handler bar_colors_handlers[] = { | ||
6 | { "active_workspace", bar_colors_cmd_active_workspace }, | ||
7 | { "background", bar_colors_cmd_background }, | ||
8 | { "binding_mode", bar_colors_cmd_binding_mode }, | ||
9 | { "focused_background", bar_colors_cmd_focused_background }, | ||
10 | { "focused_separator", bar_colors_cmd_focused_separator }, | ||
11 | { "focused_statusline", bar_colors_cmd_focused_statusline }, | ||
12 | { "focused_workspace", bar_colors_cmd_focused_workspace }, | ||
13 | { "inactive_workspace", bar_colors_cmd_inactive_workspace }, | ||
14 | { "separator", bar_colors_cmd_separator }, | ||
15 | { "statusline", bar_colors_cmd_statusline }, | ||
16 | { "urgent_workspace", bar_colors_cmd_urgent_workspace }, | ||
17 | }; | ||
18 | |||
4 | static struct cmd_results *parse_single_color(char **color, | 19 | static struct cmd_results *parse_single_color(char **color, |
5 | const char *cmd_name, int argc, char **argv) { | 20 | const char *cmd_name, int argc, char **argv) { |
6 | struct cmd_results *error = NULL; | 21 | struct cmd_results *error = NULL; |
@@ -37,15 +52,8 @@ static struct cmd_results *parse_three_colors(char ***colors, | |||
37 | } | 52 | } |
38 | 53 | ||
39 | struct cmd_results *bar_cmd_colors(int argc, char **argv) { | 54 | struct cmd_results *bar_cmd_colors(int argc, char **argv) { |
40 | struct cmd_results *error = NULL; | 55 | return config_subcommand(argv, argc, bar_colors_handlers, |
41 | if ((error = checkarg(argc, "colors", EXPECTED_EQUAL_TO, 1))) { | 56 | sizeof(bar_colors_handlers)); |
42 | return error; | ||
43 | } | ||
44 | if (strcmp("{", argv[0]) != 0) { | ||
45 | return cmd_results_new(CMD_INVALID, "colors", | ||
46 | "Expected '{' at the start of colors config definition."); | ||
47 | } | ||
48 | return cmd_results_new(CMD_BLOCK_BAR_COLORS, NULL, NULL); | ||
49 | } | 57 | } |
50 | 58 | ||
51 | struct cmd_results *bar_colors_cmd_active_workspace(int argc, char **argv) { | 59 | struct cmd_results *bar_colors_cmd_active_workspace(int argc, char **argv) { |
diff --git a/sway/commands/bar/id.c b/sway/commands/bar/id.c index c1e56f03..6ce86fef 100644 --- a/sway/commands/bar/id.c +++ b/sway/commands/bar/id.c | |||
@@ -11,6 +11,9 @@ struct cmd_results *bar_cmd_id(int argc, char **argv) { | |||
11 | 11 | ||
12 | const char *name = argv[0]; | 12 | const char *name = argv[0]; |
13 | const char *oldname = config->current_bar->id; | 13 | const char *oldname = config->current_bar->id; |
14 | if (strcmp(name, oldname) == 0) { | ||
15 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); // NOP | ||
16 | } | ||
14 | // check if id is used by a previously defined bar | 17 | // check if id is used by a previously defined bar |
15 | for (int i = 0; i < config->bars->length; ++i) { | 18 | for (int i = 0; i < config->bars->length; ++i) { |
16 | struct bar_config *find = config->bars->items[i]; | 19 | struct bar_config *find = config->bars->items[i]; |
diff --git a/sway/commands/input.c b/sway/commands/input.c index eeb4ee75..22a0bb7c 100644 --- a/sway/commands/input.c +++ b/sway/commands/input.c | |||
@@ -3,85 +3,50 @@ | |||
3 | #include "sway/commands.h" | 3 | #include "sway/commands.h" |
4 | #include "sway/input/input-manager.h" | 4 | #include "sway/input/input-manager.h" |
5 | #include "log.h" | 5 | #include "log.h" |
6 | #include "stringop.h" | ||
7 | |||
8 | // must be in order for the bsearch | ||
9 | static struct cmd_handler input_handlers[] = { | ||
10 | { "accel_profile", input_cmd_accel_profile }, | ||
11 | { "click_method", input_cmd_click_method }, | ||
12 | { "drag_lock", input_cmd_drag_lock }, | ||
13 | { "dwt", input_cmd_dwt }, | ||
14 | { "events", input_cmd_events }, | ||
15 | { "left_handed", input_cmd_left_handed }, | ||
16 | { "map_from_region", input_cmd_map_from_region }, | ||
17 | { "map_to_output", input_cmd_map_to_output }, | ||
18 | { "middle_emulation", input_cmd_middle_emulation }, | ||
19 | { "natural_scroll", input_cmd_natural_scroll }, | ||
20 | { "pointer_accel", input_cmd_pointer_accel }, | ||
21 | { "repeat_delay", input_cmd_repeat_delay }, | ||
22 | { "repeat_rate", input_cmd_repeat_rate }, | ||
23 | { "scroll_method", input_cmd_scroll_method }, | ||
24 | { "tap", input_cmd_tap }, | ||
25 | { "xkb_layout", input_cmd_xkb_layout }, | ||
26 | { "xkb_model", input_cmd_xkb_model }, | ||
27 | { "xkb_options", input_cmd_xkb_options }, | ||
28 | { "xkb_rules", input_cmd_xkb_rules }, | ||
29 | { "xkb_variant", input_cmd_xkb_variant }, | ||
30 | }; | ||
6 | 31 | ||
7 | struct cmd_results *cmd_input(int argc, char **argv) { | 32 | struct cmd_results *cmd_input(int argc, char **argv) { |
8 | struct cmd_results *error = NULL; | 33 | struct cmd_results *error = NULL; |
9 | if ((error = checkarg(argc, "input", EXPECTED_AT_LEAST, 2))) { | 34 | if ((error = checkarg(argc, "input", EXPECTED_AT_LEAST, 1))) { |
10 | return error; | 35 | return error; |
11 | } | 36 | } |
12 | 37 | ||
13 | if (config->reading && strcmp("{", argv[1]) == 0) { | 38 | wlr_log(L_DEBUG, "entering input block: %s", argv[0]); |
14 | free_input_config(config->handler_context.input_config); | ||
15 | config->handler_context.input_config = new_input_config(argv[0]); | ||
16 | if (!config->handler_context.input_config) { | ||
17 | return cmd_results_new(CMD_FAILURE, NULL, "Couldn't allocate config"); | ||
18 | } | ||
19 | wlr_log(L_DEBUG, "entering input block: %s", argv[0]); | ||
20 | return cmd_results_new(CMD_BLOCK_INPUT, NULL, NULL); | ||
21 | } | ||
22 | |||
23 | if ((error = checkarg(argc, "input", EXPECTED_AT_LEAST, 3))) { | ||
24 | return error; | ||
25 | } | ||
26 | 39 | ||
27 | bool has_context = (config->handler_context.input_config != NULL); | 40 | config->handler_context.input_config = new_input_config(argv[0]); |
28 | if (!has_context) { | 41 | if (!config->handler_context.input_config) { |
29 | // caller did not give a context so create one just for this command | 42 | return cmd_results_new(CMD_FAILURE, NULL, "Couldn't allocate config"); |
30 | config->handler_context.input_config = new_input_config(argv[0]); | ||
31 | if (!config->handler_context.input_config) { | ||
32 | return cmd_results_new(CMD_FAILURE, NULL, "Couldn't allocate config"); | ||
33 | } | ||
34 | } | 43 | } |
35 | 44 | ||
36 | int argc_new = argc-2; | 45 | struct cmd_results *res = config_subcommand(argv + 1, argc - 1, |
37 | char **argv_new = argv+2; | 46 | input_handlers, sizeof(input_handlers)); |
38 | 47 | ||
39 | struct cmd_results *res; | 48 | free_input_config(config->handler_context.input_config); |
40 | if (strcasecmp("accel_profile", argv[1]) == 0) { | 49 | config->handler_context.input_config = NULL; |
41 | res = input_cmd_accel_profile(argc_new, argv_new); | ||
42 | } else if (strcasecmp("click_method", argv[1]) == 0) { | ||
43 | res = input_cmd_click_method(argc_new, argv_new); | ||
44 | } else if (strcasecmp("drag_lock", argv[1]) == 0) { | ||
45 | res = input_cmd_drag_lock(argc_new, argv_new); | ||
46 | } else if (strcasecmp("dwt", argv[1]) == 0) { | ||
47 | res = input_cmd_dwt(argc_new, argv_new); | ||
48 | } else if (strcasecmp("events", argv[1]) == 0) { | ||
49 | res = input_cmd_events(argc_new, argv_new); | ||
50 | } else if (strcasecmp("left_handed", argv[1]) == 0) { | ||
51 | res = input_cmd_left_handed(argc_new, argv_new); | ||
52 | } else if (strcasecmp("middle_emulation", argv[1]) == 0) { | ||
53 | res = input_cmd_middle_emulation(argc_new, argv_new); | ||
54 | } else if (strcasecmp("natural_scroll", argv[1]) == 0) { | ||
55 | res = input_cmd_natural_scroll(argc_new, argv_new); | ||
56 | } else if (strcasecmp("pointer_accel", argv[1]) == 0) { | ||
57 | res = input_cmd_pointer_accel(argc_new, argv_new); | ||
58 | } else if (strcasecmp("repeat_delay", argv[1]) == 0) { | ||
59 | res = input_cmd_repeat_delay(argc_new, argv_new); | ||
60 | } else if (strcasecmp("repeat_rate", argv[1]) == 0) { | ||
61 | res = input_cmd_repeat_rate(argc_new, argv_new); | ||
62 | } else if (strcasecmp("scroll_method", argv[1]) == 0) { | ||
63 | res = input_cmd_scroll_method(argc_new, argv_new); | ||
64 | } else if (strcasecmp("tap", argv[1]) == 0) { | ||
65 | res = input_cmd_tap(argc_new, argv_new); | ||
66 | } else if (strcasecmp("xkb_layout", argv[1]) == 0) { | ||
67 | res = input_cmd_xkb_layout(argc_new, argv_new); | ||
68 | } else if (strcasecmp("xkb_model", argv[1]) == 0) { | ||
69 | res = input_cmd_xkb_model(argc_new, argv_new); | ||
70 | } else if (strcasecmp("xkb_options", argv[1]) == 0) { | ||
71 | res = input_cmd_xkb_options(argc_new, argv_new); | ||
72 | } else if (strcasecmp("xkb_rules", argv[1]) == 0) { | ||
73 | res = input_cmd_xkb_rules(argc_new, argv_new); | ||
74 | } else if (strcasecmp("xkb_variant", argv[1]) == 0) { | ||
75 | res = input_cmd_xkb_variant(argc_new, argv_new); | ||
76 | } else { | ||
77 | res = cmd_results_new(CMD_INVALID, "input <device>", "Unknown command %s", argv[1]); | ||
78 | } | ||
79 | |||
80 | if (!has_context) { | ||
81 | // clean up the context we created earlier | ||
82 | free_input_config(config->handler_context.input_config); | ||
83 | config->handler_context.input_config = NULL; | ||
84 | } | ||
85 | 50 | ||
86 | return res; | 51 | return res; |
87 | } | 52 | } |
diff --git a/sway/commands/mode.c b/sway/commands/mode.c index c30a8bac..00331ccc 100644 --- a/sway/commands/mode.c +++ b/sway/commands/mode.c | |||
@@ -7,6 +7,13 @@ | |||
7 | #include "sway/ipc-server.h" | 7 | #include "sway/ipc-server.h" |
8 | #include "list.h" | 8 | #include "list.h" |
9 | #include "log.h" | 9 | #include "log.h" |
10 | #include "stringop.h" | ||
11 | |||
12 | // Must be in order for the bsearch | ||
13 | static struct cmd_handler mode_handlers[] = { | ||
14 | { "bindcode", cmd_bindcode }, | ||
15 | { "bindsym", cmd_bindsym } | ||
16 | }; | ||
10 | 17 | ||
11 | struct cmd_results *cmd_mode(int argc, char **argv) { | 18 | struct cmd_results *cmd_mode(int argc, char **argv) { |
12 | struct cmd_results *error = NULL; | 19 | struct cmd_results *error = NULL; |
@@ -14,12 +21,12 @@ struct cmd_results *cmd_mode(int argc, char **argv) { | |||
14 | return error; | 21 | return error; |
15 | } | 22 | } |
16 | 23 | ||
17 | const char *mode_name = argv[0]; | 24 | if (argc > 1 && !config->reading) { |
18 | bool new_mode = (argc == 2 && strcmp(argv[1], "{") == 0); | ||
19 | if (new_mode && !config->reading) { | ||
20 | return cmd_results_new(CMD_FAILURE, | 25 | return cmd_results_new(CMD_FAILURE, |
21 | "mode", "Can only be used in config file."); | 26 | "mode", "Can only be used in config file."); |
22 | } | 27 | } |
28 | |||
29 | const char *mode_name = argv[0]; | ||
23 | struct sway_mode *mode = NULL; | 30 | struct sway_mode *mode = NULL; |
24 | // Find mode | 31 | // Find mode |
25 | for (int i = 0; i < config->modes->length; ++i) { | 32 | for (int i = 0; i < config->modes->length; ++i) { |
@@ -30,7 +37,7 @@ struct cmd_results *cmd_mode(int argc, char **argv) { | |||
30 | } | 37 | } |
31 | } | 38 | } |
32 | // Create mode if it doesn't exist | 39 | // Create mode if it doesn't exist |
33 | if (!mode && new_mode) { | 40 | if (!mode && argc > 1) { |
34 | mode = calloc(1, sizeof(struct sway_mode)); | 41 | mode = calloc(1, sizeof(struct sway_mode)); |
35 | if (!mode) { | 42 | if (!mode) { |
36 | return cmd_results_new(CMD_FAILURE, | 43 | return cmd_results_new(CMD_FAILURE, |
@@ -46,14 +53,21 @@ struct cmd_results *cmd_mode(int argc, char **argv) { | |||
46 | "mode", "Unknown mode `%s'", mode_name); | 53 | "mode", "Unknown mode `%s'", mode_name); |
47 | return error; | 54 | return error; |
48 | } | 55 | } |
49 | if ((config->reading && new_mode) || (!config->reading && !new_mode)) { | 56 | if ((config->reading && argc > 1) || (!config->reading && argc == 1)) { |
50 | wlr_log(L_DEBUG, "Switching to mode `%s'",mode->name); | 57 | wlr_log(L_DEBUG, "Switching to mode `%s'",mode->name); |
51 | } | 58 | } |
52 | // Set current mode | 59 | // Set current mode |
53 | config->current_mode = mode; | 60 | config->current_mode = mode; |
54 | if (!new_mode) { | 61 | if (argc == 1) { |
55 | // trigger IPC mode event | 62 | // trigger IPC mode event |
56 | ipc_event_mode(config->current_mode->name); | 63 | ipc_event_mode(config->current_mode->name); |
64 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
57 | } | 65 | } |
58 | return cmd_results_new(new_mode ? CMD_BLOCK_MODE : CMD_SUCCESS, NULL, NULL); | 66 | |
67 | // Create binding | ||
68 | struct cmd_results *result = config_subcommand(argv + 1, argc - 1, | ||
69 | mode_handlers, sizeof(mode_handlers)); | ||
70 | config->current_mode = config->modes->items[0]; | ||
71 | |||
72 | return result; | ||
59 | } | 73 | } |
diff --git a/sway/commands/seat.c b/sway/commands/seat.c index 5916015f..5e3c0bd0 100644 --- a/sway/commands/seat.c +++ b/sway/commands/seat.c | |||
@@ -3,59 +3,32 @@ | |||
3 | #include "sway/commands.h" | 3 | #include "sway/commands.h" |
4 | #include "sway/input/input-manager.h" | 4 | #include "sway/input/input-manager.h" |
5 | #include "log.h" | 5 | #include "log.h" |
6 | #include "stringop.h" | ||
7 | |||
8 | // must be in order for the bsearch | ||
9 | static struct cmd_handler seat_handlers[] = { | ||
10 | { "attach", seat_cmd_attach }, | ||
11 | { "cursor", seat_cmd_cursor }, | ||
12 | { "fallback", seat_cmd_fallback }, | ||
13 | }; | ||
6 | 14 | ||
7 | struct cmd_results *cmd_seat(int argc, char **argv) { | 15 | struct cmd_results *cmd_seat(int argc, char **argv) { |
8 | struct cmd_results *error = NULL; | 16 | struct cmd_results *error = NULL; |
9 | if ((error = checkarg(argc, "seat", EXPECTED_AT_LEAST, 2))) { | 17 | if ((error = checkarg(argc, "seat", EXPECTED_AT_LEAST, 1))) { |
10 | return error; | 18 | return error; |
11 | } | 19 | } |
12 | 20 | ||
13 | if (config->reading && strcmp("{", argv[1]) == 0) { | 21 | config->handler_context.seat_config = new_seat_config(argv[0]); |
14 | free_seat_config(config->handler_context.seat_config); | 22 | if (!config->handler_context.seat_config) { |
15 | config->handler_context.seat_config = new_seat_config(argv[0]); | 23 | return cmd_results_new(CMD_FAILURE, NULL, |
16 | if (!config->handler_context.seat_config) { | 24 | "Couldn't allocate config"); |
17 | return cmd_results_new(CMD_FAILURE, NULL, | ||
18 | "Couldn't allocate config"); | ||
19 | } | ||
20 | wlr_log(L_DEBUG, "entering seat block: %s", argv[0]); | ||
21 | return cmd_results_new(CMD_BLOCK_SEAT, NULL, NULL); | ||
22 | } | 25 | } |
23 | 26 | ||
24 | if ((error = checkarg(argc, "seat", EXPECTED_AT_LEAST, 3))) { | 27 | struct cmd_results *res = config_subcommand(argv + 1, argc - 1, |
25 | return error; | 28 | seat_handlers, sizeof(seat_handlers)); |
26 | } | ||
27 | |||
28 | bool has_context = (config->handler_context.seat_config != NULL); | ||
29 | if (!has_context) { | ||
30 | config->handler_context.seat_config = new_seat_config(argv[0]); | ||
31 | if (!config->handler_context.seat_config) { | ||
32 | return cmd_results_new(CMD_FAILURE, NULL, | ||
33 | "Couldn't allocate config"); | ||
34 | } | ||
35 | } | ||
36 | 29 | ||
37 | int argc_new = argc-2; | 30 | free_seat_config(config->handler_context.seat_config); |
38 | char **argv_new = argv+2; | 31 | config->handler_context.seat_config = NULL; |
39 | |||
40 | struct cmd_results *res; | ||
41 | if (strcasecmp("attach", argv[1]) == 0) { | ||
42 | res = seat_cmd_attach(argc_new, argv_new); | ||
43 | } else if (strcasecmp("cursor", argv[1]) == 0) { | ||
44 | res = seat_cmd_cursor(argc_new, argv_new); | ||
45 | } else if (strcasecmp("fallback", argv[1]) == 0) { | ||
46 | res = seat_cmd_fallback(argc_new, argv_new); | ||
47 | } else { | ||
48 | res = | ||
49 | cmd_results_new(CMD_INVALID, | ||
50 | "seat <name>", "Unknown command %s", | ||
51 | argv[1]); | ||
52 | } | ||
53 | |||
54 | if (!has_context) { | ||
55 | // clean up the context we created earlier | ||
56 | free_seat_config(config->handler_context.seat_config); | ||
57 | config->handler_context.seat_config = NULL; | ||
58 | } | ||
59 | 32 | ||
60 | return res; | 33 | return res; |
61 | } | 34 | } |
diff --git a/sway/config.c b/sway/config.c index 27308066..88cc6843 100644 --- a/sway/config.c +++ b/sway/config.c | |||
@@ -59,12 +59,12 @@ static void free_mode(struct sway_mode *mode) { | |||
59 | } | 59 | } |
60 | 60 | ||
61 | void free_config(struct sway_config *config) { | 61 | void free_config(struct sway_config *config) { |
62 | config_clear_handler_context(config); | ||
63 | |||
64 | if (!config) { | 62 | if (!config) { |
65 | return; | 63 | return; |
66 | } | 64 | } |
67 | 65 | ||
66 | memset(&config->handler_context, 0, sizeof(config->handler_context)); | ||
67 | |||
68 | // TODO: handle all currently unhandled lists as we add implementations | 68 | // TODO: handle all currently unhandled lists as we add implementations |
69 | if (config->symbols) { | 69 | if (config->symbols) { |
70 | for (int i = 0; i < config->symbols->length; ++i) { | 70 | for (int i = 0; i < config->symbols->length; ++i) { |
@@ -107,7 +107,6 @@ void free_config(struct sway_config *config) { | |||
107 | list_free(config->command_policies); | 107 | list_free(config->command_policies); |
108 | list_free(config->feature_policies); | 108 | list_free(config->feature_policies); |
109 | list_free(config->ipc_policies); | 109 | list_free(config->ipc_policies); |
110 | free(config->current_bar); | ||
111 | free(config->floating_scroll_up_cmd); | 110 | free(config->floating_scroll_up_cmd); |
112 | free(config->floating_scroll_down_cmd); | 111 | free(config->floating_scroll_down_cmd); |
113 | free(config->floating_scroll_left_cmd); | 112 | free(config->floating_scroll_left_cmd); |
@@ -514,37 +513,87 @@ bool load_include_configs(const char *path, struct sway_config *config) { | |||
514 | return true; | 513 | return true; |
515 | } | 514 | } |
516 | 515 | ||
517 | void config_clear_handler_context(struct sway_config *config) { | 516 | static int detect_brace_on_following_line(FILE *file, char *line, |
518 | free_input_config(config->handler_context.input_config); | 517 | int line_number) { |
519 | free_seat_config(config->handler_context.seat_config); | 518 | int lines = 0; |
519 | if (line[strlen(line) - 1] != '{' && line[strlen(line) - 1] != '}') { | ||
520 | char *peeked = NULL; | ||
521 | long position = 0; | ||
522 | do { | ||
523 | wlr_log(L_DEBUG, "Peeking line %d", line_number + lines + 1); | ||
524 | free(peeked); | ||
525 | peeked = peek_line(file, lines, &position); | ||
526 | if (peeked) { | ||
527 | peeked = strip_whitespace(peeked); | ||
528 | } | ||
529 | wlr_log(L_DEBUG, "Peeked line: `%s`", peeked); | ||
530 | lines++; | ||
531 | } while (peeked && strlen(peeked) == 0); | ||
520 | 532 | ||
521 | memset(&config->handler_context, 0, sizeof(config->handler_context)); | 533 | if (peeked && strlen(peeked) == 1 && peeked[0] == '{') { |
534 | fseek(file, position, SEEK_SET); | ||
535 | } else { | ||
536 | lines = 0; | ||
537 | } | ||
538 | free(peeked); | ||
539 | } | ||
540 | return lines; | ||
541 | } | ||
542 | |||
543 | static char *expand_line(const char *block, const char *line, bool add_brace) { | ||
544 | int size = (block ? strlen(block) + 1 : 0) + strlen(line) | ||
545 | + (add_brace ? 2 : 0) + 1; | ||
546 | char *expanded = calloc(1, size); | ||
547 | if (!expanded) { | ||
548 | wlr_log(L_ERROR, "Cannot allocate expanded line buffer"); | ||
549 | return NULL; | ||
550 | } | ||
551 | snprintf(expanded, size, "%s%s%s%s", block ? block : "", | ||
552 | block ? " " : "", line, add_brace ? " {" : ""); | ||
553 | return expanded; | ||
522 | } | 554 | } |
523 | 555 | ||
524 | bool read_config(FILE *file, struct sway_config *config) { | 556 | bool read_config(FILE *file, struct sway_config *config) { |
525 | bool success = true; | 557 | bool success = true; |
526 | enum cmd_status block = CMD_BLOCK_END; | ||
527 | |||
528 | int line_number = 0; | 558 | int line_number = 0; |
529 | char *line; | 559 | char *line; |
560 | list_t *stack = create_list(); | ||
530 | while (!feof(file)) { | 561 | while (!feof(file)) { |
562 | char *block = stack->length ? stack->items[0] : NULL; | ||
531 | line = read_line(file); | 563 | line = read_line(file); |
532 | if (!line) { | 564 | if (!line) { |
533 | continue; | 565 | continue; |
534 | } | 566 | } |
535 | line_number++; | 567 | line_number++; |
568 | wlr_log(L_DEBUG, "Read line %d: %s", line_number, line); | ||
536 | line = strip_whitespace(line); | 569 | line = strip_whitespace(line); |
537 | if (line[0] == '#') { | 570 | if (line[0] == '#') { |
538 | free(line); | 571 | free(line); |
539 | continue; | 572 | continue; |
540 | } | 573 | } |
574 | if (strlen(line) == 0) { | ||
575 | free(line); | ||
576 | continue; | ||
577 | } | ||
578 | int brace_detected = detect_brace_on_following_line(file, line, | ||
579 | line_number); | ||
580 | if (brace_detected > 0) { | ||
581 | line_number += brace_detected; | ||
582 | wlr_log(L_DEBUG, "Detected open brace on line %d", line_number); | ||
583 | } | ||
584 | char *expanded = expand_line(block, line, brace_detected > 0); | ||
585 | if (!expanded) { | ||
586 | return false; | ||
587 | } | ||
588 | wlr_log(L_DEBUG, "Expanded line: %s", expanded); | ||
541 | struct cmd_results *res; | 589 | struct cmd_results *res; |
542 | if (block == CMD_BLOCK_COMMANDS) { | 590 | if (block && strcmp(block, "<commands>") == 0) { |
543 | // Special case | 591 | // Special case |
544 | res = config_commands_command(line); | 592 | res = config_commands_command(expanded); |
545 | } else { | 593 | } else { |
546 | res = config_command(line, block); | 594 | res = config_command(expanded); |
547 | } | 595 | } |
596 | free(expanded); | ||
548 | switch(res->status) { | 597 | switch(res->status) { |
549 | case CMD_FAILURE: | 598 | case CMD_FAILURE: |
550 | case CMD_INVALID: | 599 | case CMD_INVALID: |
@@ -558,126 +607,41 @@ bool read_config(FILE *file, struct sway_config *config) { | |||
558 | list_add(config->cmd_queue, strdup(line)); | 607 | list_add(config->cmd_queue, strdup(line)); |
559 | break; | 608 | break; |
560 | 609 | ||
561 | case CMD_BLOCK_MODE: | ||
562 | if (block == CMD_BLOCK_END) { | ||
563 | block = CMD_BLOCK_MODE; | ||
564 | } else { | ||
565 | wlr_log(L_ERROR, "Invalid block '%s'", line); | ||
566 | } | ||
567 | break; | ||
568 | |||
569 | case CMD_BLOCK_INPUT: | ||
570 | if (block == CMD_BLOCK_END) { | ||
571 | block = CMD_BLOCK_INPUT; | ||
572 | } else { | ||
573 | wlr_log(L_ERROR, "Invalid block '%s'", line); | ||
574 | } | ||
575 | break; | ||
576 | |||
577 | case CMD_BLOCK_SEAT: | ||
578 | if (block == CMD_BLOCK_END) { | ||
579 | block = CMD_BLOCK_SEAT; | ||
580 | } else { | ||
581 | wlr_log(L_ERROR, "Invalid block '%s'", line); | ||
582 | } | ||
583 | break; | ||
584 | |||
585 | case CMD_BLOCK_BAR: | ||
586 | if (block == CMD_BLOCK_END) { | ||
587 | block = CMD_BLOCK_BAR; | ||
588 | } else { | ||
589 | wlr_log(L_ERROR, "Invalid block '%s'", line); | ||
590 | } | ||
591 | break; | ||
592 | |||
593 | case CMD_BLOCK_BAR_COLORS: | ||
594 | if (block == CMD_BLOCK_BAR) { | ||
595 | block = CMD_BLOCK_BAR_COLORS; | ||
596 | } else { | ||
597 | wlr_log(L_ERROR, "Invalid block '%s'", line); | ||
598 | } | ||
599 | break; | ||
600 | |||
601 | case CMD_BLOCK_COMMANDS: | 610 | case CMD_BLOCK_COMMANDS: |
602 | if (block == CMD_BLOCK_END) { | 611 | wlr_log(L_DEBUG, "Entering commands block"); |
603 | block = CMD_BLOCK_COMMANDS; | 612 | list_insert(stack, 0, "<commands>"); |
604 | } else { | ||
605 | wlr_log(L_ERROR, "Invalid block '%s'", line); | ||
606 | } | ||
607 | break; | ||
608 | |||
609 | case CMD_BLOCK_IPC: | ||
610 | if (block == CMD_BLOCK_END) { | ||
611 | block = CMD_BLOCK_IPC; | ||
612 | } else { | ||
613 | wlr_log(L_ERROR, "Invalid block '%s'", line); | ||
614 | } | ||
615 | break; | 613 | break; |
616 | 614 | ||
617 | case CMD_BLOCK_IPC_EVENTS: | 615 | case CMD_BLOCK: |
618 | if (block == CMD_BLOCK_IPC) { | 616 | wlr_log(L_DEBUG, "Entering block '%s'", res->input); |
619 | block = CMD_BLOCK_IPC_EVENTS; | 617 | list_insert(stack, 0, strdup(res->input)); |
620 | } else { | 618 | if (strcmp(res->input, "bar") == 0) { |
621 | wlr_log(L_ERROR, "Invalid block '%s'", line); | 619 | config->current_bar = NULL; |
622 | } | 620 | } |
623 | break; | 621 | break; |
624 | 622 | ||
625 | case CMD_BLOCK_END: | 623 | case CMD_BLOCK_END: |
626 | switch(block) { | 624 | if (!block) { |
627 | case CMD_BLOCK_MODE: | 625 | wlr_log(L_DEBUG, "Unmatched '}' on line %i", line_number); |
628 | wlr_log(L_DEBUG, "End of mode block"); | 626 | success = false; |
629 | config->current_mode = config->modes->items[0]; | ||
630 | block = CMD_BLOCK_END; | ||
631 | break; | ||
632 | |||
633 | case CMD_BLOCK_INPUT: | ||
634 | wlr_log(L_DEBUG, "End of input block"); | ||
635 | block = CMD_BLOCK_END; | ||
636 | break; | ||
637 | |||
638 | case CMD_BLOCK_SEAT: | ||
639 | wlr_log(L_DEBUG, "End of seat block"); | ||
640 | block = CMD_BLOCK_END; | ||
641 | break; | 627 | break; |
628 | } | ||
629 | wlr_log(L_DEBUG, "Exiting block '%s'", block); | ||
630 | list_del(stack, 0); | ||
631 | free(block); | ||
642 | 632 | ||
643 | case CMD_BLOCK_BAR: | 633 | if (strcmp(block, "bar") == 0) { |
644 | wlr_log(L_DEBUG, "End of bar block"); | ||
645 | config->current_bar = NULL; | 634 | config->current_bar = NULL; |
646 | block = CMD_BLOCK_END; | ||
647 | break; | ||
648 | |||
649 | case CMD_BLOCK_BAR_COLORS: | ||
650 | wlr_log(L_DEBUG, "End of bar colors block"); | ||
651 | block = CMD_BLOCK_BAR; | ||
652 | break; | ||
653 | |||
654 | case CMD_BLOCK_COMMANDS: | ||
655 | wlr_log(L_DEBUG, "End of commands block"); | ||
656 | block = CMD_BLOCK_END; | ||
657 | break; | ||
658 | |||
659 | case CMD_BLOCK_IPC: | ||
660 | wlr_log(L_DEBUG, "End of IPC block"); | ||
661 | block = CMD_BLOCK_END; | ||
662 | break; | ||
663 | |||
664 | case CMD_BLOCK_IPC_EVENTS: | ||
665 | wlr_log(L_DEBUG, "End of IPC events block"); | ||
666 | block = CMD_BLOCK_IPC; | ||
667 | break; | ||
668 | |||
669 | case CMD_BLOCK_END: | ||
670 | wlr_log(L_ERROR, "Unmatched }"); | ||
671 | break; | ||
672 | |||
673 | default:; | ||
674 | } | 635 | } |
675 | config_clear_handler_context(config); | 636 | memset(&config->handler_context, 0, |
637 | sizeof(config->handler_context)); | ||
676 | default:; | 638 | default:; |
677 | } | 639 | } |
678 | free(line); | 640 | free(line); |
679 | free_cmd_results(res); | 641 | free_cmd_results(res); |
680 | } | 642 | } |
643 | list_foreach(stack, free); | ||
644 | list_free(stack); | ||
681 | 645 | ||
682 | return success; | 646 | return success; |
683 | } | 647 | } |
diff --git a/sway/input/keyboard.c b/sway/input/keyboard.c index 420cefa6..d90655f2 100644 --- a/sway/input/keyboard.c +++ b/sway/input/keyboard.c | |||
@@ -98,7 +98,6 @@ static void keyboard_execute_command(struct sway_keyboard *keyboard, | |||
98 | struct sway_binding *binding) { | 98 | struct sway_binding *binding) { |
99 | wlr_log(L_DEBUG, "running command for binding: %s", | 99 | wlr_log(L_DEBUG, "running command for binding: %s", |
100 | binding->command); | 100 | binding->command); |
101 | config_clear_handler_context(config); | ||
102 | config->handler_context.seat = keyboard->seat_device->sway_seat; | 101 | config->handler_context.seat = keyboard->seat_device->sway_seat; |
103 | struct cmd_results *results = execute_command(binding->command, NULL); | 102 | struct cmd_results *results = execute_command(binding->command, NULL); |
104 | if (results->status != CMD_SUCCESS) { | 103 | if (results->status != CMD_SUCCESS) { |
diff --git a/sway/ipc-server.c b/sway/ipc-server.c index 15ed6f80..8d9ab06a 100644 --- a/sway/ipc-server.c +++ b/sway/ipc-server.c | |||
@@ -469,7 +469,6 @@ void ipc_client_handle_command(struct ipc_client *client) { | |||
469 | switch (client->current_command) { | 469 | switch (client->current_command) { |
470 | case IPC_COMMAND: | 470 | case IPC_COMMAND: |
471 | { | 471 | { |
472 | config_clear_handler_context(config); | ||
473 | struct cmd_results *results = execute_command(buf, NULL); | 472 | struct cmd_results *results = execute_command(buf, NULL); |
474 | const char *json = cmd_results_to_json(results); | 473 | const char *json = cmd_results_to_json(results); |
475 | char reply[256]; | 474 | char reply[256]; |