From 0bea2e2122bd573d1f9dc68b5a990c8f2ad3f3f0 Mon Sep 17 00:00:00 2001 From: taiyu Date: Mon, 14 Sep 2015 19:59:25 -0700 Subject: [PATCH 1/8] multi command keybinds --- include/commands.h | 16 ++-- include/stringop.h | 6 ++ sway/commands.c | 214 +++++++++++++++++++++++++++++++-------------- sway/config.c | 34 ++++++- sway/log.c | 8 +- sway/stringop.c | 111 ++++++++++++++++------- 6 files changed, 280 insertions(+), 109 deletions(-) diff --git a/include/commands.h b/include/commands.h index 5c87be51..1b4cd9ca 100644 --- a/include/commands.h +++ b/include/commands.h @@ -3,13 +3,15 @@ #include #include "config.h" -struct cmd_handler { - char *command; - enum cmd_status { - CMD_SUCCESS, - CMD_FAILURE, - CMD_DEFER, - } (*handle)(int argc, char **argv); + +enum cmd_status { + CMD_SUCCESS, + CMD_FAILURE, + CMD_INVALID, + CMD_DEFER, + // Config Blocks + CMD_BLOCK_END, + CMD_BLOCK_MODE, }; enum cmd_status handle_command(char *command); diff --git a/include/stringop.h b/include/stringop.h index dde50f13..dc81cdae 100644 --- a/include/stringop.h +++ b/include/stringop.h @@ -7,6 +7,7 @@ extern const char *whitespace; char *strip_whitespace(char *str); char *strip_comments(char *str); +void strip_quotes(char *str); // Simply split a string with delims, free with `free_flat_list` list_t *split_string(const char *str, const char *delims); @@ -22,5 +23,10 @@ int unescape_string(char *string); char *join_args(char **argv, int argc); char *join_list(list_t *list, char *separator); +// split string into 2 by delim. +char *cmdsep(char **stringp, const char *delim); +// Split string into 2 by delim, handle quotes +char *argsep(char **stringp, const char *delim); + char *strdup(const char *); #endif diff --git a/sway/commands.c b/sway/commands.c index e79746ae..c426928e 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -18,6 +18,45 @@ #include "sway.h" #include "resize.h" +typedef enum cmd_status sway_cmd(int argc, char **argv); + +struct cmd_handler { + char *command; + sway_cmd *handle; +}; + +static sway_cmd cmd_bindsym; +static sway_cmd cmd_orientation; +static sway_cmd cmd_exec; +static sway_cmd cmd_exec_always; +static sway_cmd cmd_exit; +static sway_cmd cmd_floating; +static sway_cmd cmd_floating_mod; +static sway_cmd cmd_focus; +static sway_cmd cmd_focus_follows_mouse; +static sway_cmd cmd_for_window; +static sway_cmd cmd_fullscreen; +static sway_cmd cmd_gaps; +static sway_cmd cmd_kill; +static sway_cmd cmd_layout; +static sway_cmd cmd_log_colors; +static sway_cmd cmd_mode; +static sway_cmd cmd_move; +static sway_cmd cmd_output; +static sway_cmd cmd_reload; +static sway_cmd cmd_resize; +static sway_cmd cmd_scratchpad; +static sway_cmd cmd_set; +static sway_cmd cmd_split; +static sway_cmd cmd_splith; +static sway_cmd cmd_splitv; +static sway_cmd cmd_workspace; +static sway_cmd cmd_ws_auto_back_and_forth; + +#define NO_BIND() if (!config->reading) return CMD_FAILURE; +#define NO_CONF() if (config->reading) return CMD_FAILURE; +#define DEFER() if (!config->active) return CMD_DEFER; + swayc_t *sp_view; int sp_index = 0; @@ -145,14 +184,19 @@ static enum cmd_status cmd_bindsym(int argc, char **argv) { } static enum cmd_status cmd_exec_always(int argc, char **argv) { + DEFER(); if (!checkarg(argc, "exec_always", EXPECTED_MORE_THAN, 0)) { return CMD_FAILURE; } - if (!config->active) { - return CMD_DEFER; - } + // Put argument into cmd array + char *tmp = join_args(argv, argc); + char cmd[4096]; + strcpy(cmd, tmp); + free(tmp); + + char *args[] = {"sh", "-c", cmd, 0 }; - pid_t pid = fork(); + pid_t pid = vfork(); /* Failed to fork */ if (pid < 0) { sway_log(L_ERROR, "exec command failed, sway did not fork"); @@ -160,22 +204,18 @@ static enum cmd_status cmd_exec_always(int argc, char **argv) { } /* Child process */ if (pid == 0) { - char *args = join_args(argv, argc); - sway_log(L_DEBUG, "Executing %s", args); - execl("/bin/sh", "sh", "-c", args, (char *)NULL); - /* Execl doesnt return unless failure */ - sway_log(L_ERROR, "could not find /bin/sh"); - free(args); - exit(-1); + sway_log(L_DEBUG, "Executing %s", cmd); + execv("/bin/sh", args); + /* Execv doesnt return unless failure */ + sway_log(L_ERROR, "execv failde to return"); + _exit(-1); } /* Parent */ return CMD_SUCCESS; } static enum cmd_status cmd_exec(int argc, char **argv) { - if (!config->active) { - return CMD_DEFER; - } + DEFER(); if (config->reloading) { char *args = join_args(argv, argc); sway_log(L_DEBUG, "Ignoring 'exec %s' due to reload", args); @@ -373,15 +413,19 @@ static void hide_view_in_scratchpad(swayc_t *sp_view) { } static enum cmd_status cmd_mode(int argc, char **argv) { - if (!checkarg(argc, "move", EXPECTED_AT_LEAST, 1)) { + if (!checkarg(argc, "mode", EXPECTED_AT_LEAST, 1)) { return CMD_FAILURE; } - bool mode_make = !strcmp(argv[argc-1], "{"); - if (mode_make && !config->reading) { - return CMD_FAILURE; + char *mode_name = join_args(argv, argc); + int mode_len = strlen(mode_name); + bool mode_make = mode_name[mode_len-1] == '{'; + if (mode_make) { + NO_BIND(); + // Trim trailing spaces + do { + mode_name[--mode_len] = 0; + } while(isspace(mode_name[mode_len-1])); } - - char *mode_name = join_args(argv, argc - mode_make); struct sway_mode *mode = NULL; // Find mode int i, len = config->modes->length; @@ -404,16 +448,18 @@ static enum cmd_status cmd_mode(int argc, char **argv) { free(mode_name); return CMD_FAILURE; } - sway_log(L_DEBUG, "Switching to mode `%s'",mode->name); + if ((config->reading && mode_make) || (!config->reading && !mode_make)) { + sway_log(L_DEBUG, "Switching to mode `%s'",mode->name); + } free(mode_name); // Set current mode config->current_mode = mode; - return CMD_SUCCESS; + return mode_make ? CMD_BLOCK_MODE : CMD_SUCCESS; } static enum cmd_status cmd_move(int argc, char **argv) { - if (!checkarg(argc, "move", EXPECTED_AT_LEAST, 1) - || config->reading || !config->active) { + NO_CONF(); + if (!checkarg(argc, "move", EXPECTED_AT_LEAST, 1)) { return CMD_FAILURE; } @@ -483,10 +529,11 @@ static enum cmd_status cmd_move(int argc, char **argv) { } static enum cmd_status cmd_orientation(int argc, char **argv) { - if (!checkarg(argc, "orientation", EXPECTED_EQUAL_TO, 1) - || !config->reading) { + NO_BIND(); + if (!checkarg(argc, "orientation", EXPECTED_EQUAL_TO, 1)) { return CMD_FAILURE; } + if (strcasecmp(argv[0], "horizontal") == 0) { config->default_orientation = L_HORIZ; } else if (strcasecmp(argv[0], "vertical") == 0) { @@ -500,6 +547,7 @@ static enum cmd_status cmd_orientation(int argc, char **argv) { } static enum cmd_status cmd_output(int argc, char **argv) { + NO_BIND(); if (!checkarg(argc, "output", EXPECTED_AT_LEAST, 1)) { return CMD_FAILURE; } @@ -510,7 +558,6 @@ static enum cmd_status cmd_output(int argc, char **argv) { output->enabled = true; // TODO: atoi doesn't handle invalid numbers - if (strcasecmp(argv[1], "disable") == 0) { output->enabled = false; } @@ -960,6 +1007,11 @@ static enum cmd_status cmd_log_colors(int argc, char **argv) { return CMD_SUCCESS; } +__attribute__((unused)) +enum cmd_status cmd_for_window(int argc, char **argv) { + return CMD_FAILURE; +} + static enum cmd_status cmd_fullscreen(int argc, char **argv) { if (!checkarg(argc, "fullscreen", EXPECTED_AT_LEAST, 0) || config->reading || !config->active) { @@ -1087,57 +1139,89 @@ static struct cmd_handler *find_handler(char *line) { return res; } -enum cmd_status handle_command(char *exec) { - sway_log(L_INFO, "Handling command '%s'", exec); - int argc; - char **argv = split_args(exec, &argc); - enum cmd_status status = CMD_FAILURE; - struct cmd_handler *handler; - if (!argc) { - return status; - } - if ((handler = find_handler(argv[0])) == NULL - || (status = handler->handle(argc - 1, argv + 1)) != CMD_SUCCESS) { - sway_log(L_ERROR, "Command failed: %s", argv[0]); - } - free_argv(argc, argv); +enum cmd_status handle_command(char *_exec) { + enum cmd_status status = CMD_SUCCESS; + char *exec = strdup(_exec); + char *head = exec; + char *cmdlist; + char *cmd; + char *criteria __attribute__((unused)); + + head = exec; + do { + // Handle criteria + if (*head == '[') { + criteria = argsep(&head, "]"); + if (head) { + ++head; + // TODO handle criteria + } else { + sway_log(L_ERROR, "Unmatched ["); + status = CMD_INVALID; + } + // Skip leading whitespace + head += strspn(head, whitespace); + } + // Split command list + cmdlist = argsep(&head, ";"); + cmdlist += strspn(cmdlist, whitespace); + do { + // Split commands + cmd = argsep(&cmdlist, ","); + cmd += strspn(cmd, whitespace); + sway_log(L_INFO, "Handling command '%s'", cmd); + //TODO better handling of argv + int argc; + char **argv = split_args(cmd, &argc); + if (argc>1 && (*argv[1] == '\"' || *argv[1] == '\'')) { + strip_quotes(argv[1]); + } + struct cmd_handler *handler = find_handler(argv[0]); + enum cmd_status res = CMD_INVALID; + if (!handler + || (res = handler->handle(argc-1, argv+1)) != CMD_SUCCESS) { + sway_log(L_ERROR, "Command '%s' failed", cmd); + free_argv(argc, argv); + status = res; + goto cleanup; + } + free_argv(argc, argv); + } while(cmdlist); + } while(head); + cleanup: + free(exec); return status; } enum cmd_status config_command(char *exec) { sway_log(L_INFO, "handling config command '%s'", exec); + enum cmd_status status = CMD_SUCCESS; int argc; char **argv = split_args(exec, &argc); - enum cmd_status status = CMD_FAILURE; - struct cmd_handler *handler; if (!argc) { - status = CMD_SUCCESS; goto cleanup; } - // TODO better block handling - if (strncmp(argv[0], "}", 1) == 0) { - config->current_mode = config->modes->items[0]; - status = CMD_SUCCESS; + // Endblock + if (**argv == '}') { + status = CMD_BLOCK_END; goto cleanup; } - if ((handler = find_handler(argv[0]))) { - // Dont replace first argument in cmd_set - int i = handler->handle == cmd_set ? 2 : 1; - int e = argc; - for (; i < e; ++i) { - argv[i] = do_var_replacement(argv[i]); - } - status = handler->handle(argc - 1, argv + 1); - if (status == CMD_FAILURE) { - sway_log(L_ERROR, "Config load failed for line `%s'", exec); - } else if (status == CMD_DEFER) { - sway_log(L_DEBUG, "Defferring command `%s'", exec); - list_add(config->cmd_queue, strdup(exec)); - status = CMD_SUCCESS; - } - } else { - sway_log(L_ERROR, "Unknown command `%s'", exec); + struct cmd_handler *handler = find_handler(argv[0]); + if (!handler) { + status = CMD_INVALID; + goto cleanup; } + int i; + // Var replacement, for all but first argument of set + for (i = handler->handle == cmd_set ? 2 : 1; i < argc; ++i) { + argv[i] = do_var_replacement(argv[i]); + } + /* Strip quotes for first argument. + * TODO This part needs to be handled much better */ + if (argc>1 && (*argv[1] == '\"' || *argv[1] == '\'')) { + strip_quotes(argv[1]); + } + status = handler->handle(argc-1, argv+1); cleanup: free_argv(argc, argv); return status; diff --git a/sway/config.c b/sway/config.c index 23d6ac0d..0026e0af 100644 --- a/sway/config.c +++ b/sway/config.c @@ -225,14 +225,46 @@ bool read_config(FILE *file, bool is_active) { config->active = true; } bool success = true; + enum cmd_status block = CMD_BLOCK_END; char *line; while (!feof(file)) { line = read_line(file); line = strip_comments(line); - if (config_command(line) == CMD_FAILURE) { + switch(config_command(line)) { + case CMD_FAILURE: + case CMD_INVALID: sway_log(L_ERROR, "Error on line '%s'", line); success = false; + break; + + case CMD_DEFER: + sway_log(L_DEBUG, "Defferring command `%s'", line); + list_add(config->cmd_queue, strdup(line)); + break; + + case CMD_BLOCK_MODE: + if (block == CMD_BLOCK_END) { + block = CMD_BLOCK_MODE; + } else { + sway_log(L_ERROR, "Invalid block '%s'", line); + } + break; + + case CMD_BLOCK_END: + switch(block) { + case CMD_BLOCK_MODE: + sway_log(L_DEBUG, "End of mode block"); + config->current_mode = config->modes->items[0]; + break; + + case CMD_BLOCK_END: + sway_log(L_ERROR, "Unmatched }"); + break; + + default:; + } + default:; } free(line); } diff --git a/sway/log.c b/sway/log.c index cf5c2092..3859fd92 100644 --- a/sway/log.c +++ b/sway/log.c @@ -14,10 +14,10 @@ int colored = 1; log_importance_t v = L_SILENT; static const char *verbosity_colors[] = { - "", // L_SILENT - "\x1B[1;31m", // L_ERROR - "\x1B[1;34m", // L_INFO - "\x1B[1;30m", // L_DEBUG + [L_SILENT] = "", + [L_ERROR ] = "\x1B[1;31m", + [L_INFO ] = "\x1B[1;34m", + [L_DEBUG ] = "\x1B[1;30m", }; void init_log(log_importance_t verbosity) { diff --git a/sway/stringop.c b/sway/stringop.c index 191e40c8..90f963d6 100644 --- a/sway/stringop.c +++ b/sway/stringop.c @@ -105,40 +105,40 @@ char **split_args(const char *start, int *argc) { bool in_char = false; bool escaped = false; const char *end = start; - while (*start) { - if (!in_token) { - start = (end += strspn(end, whitespace)); - in_token = true; - } - if (*end == '"' && !in_char && !escaped) { - in_string = !in_string; - } else if (*end == '\'' && !in_string && !escaped) { - in_char = !in_char; - } else if (*end == '\\') { - escaped = !escaped; - } else if (*end == '\0' || (!in_string && !in_char && !escaped - && strchr(whitespace, *end))) { - goto add_part; - } - if (*end != '\\') { + if (start) { + while (*start) { + if (!in_token) { + start = (end += strspn(end, whitespace)); + in_token = true; + } + if (*end == '"' && !in_char && !escaped) { + in_string = !in_string; + } else if (*end == '\'' && !in_string && !escaped) { + in_char = !in_char; + } else if (*end == '\\') { + escaped = !escaped; + } else if (*end == '\0' || (!in_string && !in_char && !escaped + && strchr(whitespace, *end))) { + goto add_token; + } + if (*end != '\\') { + escaped = false; + } + ++end; + continue; + add_token: + if (end - start > 0) { + char *token = malloc(end - start + 1); + strncpy(token, start, end - start + 1); + token[end - start] = '\0'; + argv[*argc] = token; + if (++*argc + 1 == alloc) { + argv = realloc(argv, (alloc *= 2) * sizeof(char *)); + } + } + in_token = false; escaped = false; } - ++end; - continue; - add_part: - if (end - start > 0) { - char *token = malloc(end - start + 1); - strncpy(token, start, end - start + 1); - token[end - start] = '\0'; - strip_quotes(token); - unescape_string(token); - argv[*argc] = token; - if (++*argc + 1 == alloc) { - argv = realloc(argv, (alloc *= 2) * sizeof(char *)); - } - } - in_token = false; - escaped = false; } argv[*argc] = NULL; return argv; @@ -311,3 +311,50 @@ char *join_list(list_t *list, char *separator) { return res; } + +char *cmdsep(char **stringp, const char *delim) { + char *head = strsep(stringp, delim); + // But skip over trailing delims. '3 tokens here' -> '3' 'tokens here' + if (*stringp) { + *stringp += strspn(*stringp, delim); + // If skiping over delims brings us to the end of string, set to NULL + if (!**stringp) *stringp = NULL; + } + return head; +} + +char *argsep(char **stringp, const char *delim) { + char *start = *stringp; + char *end = start; + bool in_string = false; + bool in_char = false; + bool escaped = false; + while (1) { + if (*end == '"' && !in_char && !escaped) { + in_string = !in_string; + } else if (*end == '\'' && !in_string && !escaped) { + in_char = !in_char; + } else if (*end == '\\') { + escaped = !escaped; + } else if (*end == '\0') { + *stringp = NULL; + goto found; + } else if (!in_string && !in_char && !escaped && strchr(delim, *end)) { + if (end - start) { + *(end++) = 0; + *stringp = end + strspn(end, delim);; + if (!**stringp) *stringp = NULL; + goto found; + } else { + ++start; + end = start; + } + } + if (*end != '\\') { + escaped = false; + } + ++end; + } + found: + return start; +} From a18caf6706d9b5640247737ecd9c8589ccf4817b Mon Sep 17 00:00:00 2001 From: taiyu Date: Tue, 15 Sep 2015 06:39:24 -0700 Subject: [PATCH 2/8] nomacro --- sway/commands.c | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/sway/commands.c b/sway/commands.c index c426928e..bbf0bde2 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -34,7 +34,6 @@ static sway_cmd cmd_floating; static sway_cmd cmd_floating_mod; static sway_cmd cmd_focus; static sway_cmd cmd_focus_follows_mouse; -static sway_cmd cmd_for_window; static sway_cmd cmd_fullscreen; static sway_cmd cmd_gaps; static sway_cmd cmd_kill; @@ -53,10 +52,6 @@ static sway_cmd cmd_splitv; static sway_cmd cmd_workspace; static sway_cmd cmd_ws_auto_back_and_forth; -#define NO_BIND() if (!config->reading) return CMD_FAILURE; -#define NO_CONF() if (config->reading) return CMD_FAILURE; -#define DEFER() if (!config->active) return CMD_DEFER; - swayc_t *sp_view; int sp_index = 0; @@ -184,7 +179,7 @@ static enum cmd_status cmd_bindsym(int argc, char **argv) { } static enum cmd_status cmd_exec_always(int argc, char **argv) { - DEFER(); + if (!config->active) return CMD_DEFER;; if (!checkarg(argc, "exec_always", EXPECTED_MORE_THAN, 0)) { return CMD_FAILURE; } @@ -215,7 +210,8 @@ static enum cmd_status cmd_exec_always(int argc, char **argv) { } static enum cmd_status cmd_exec(int argc, char **argv) { - DEFER(); + if (!config->active) return CMD_DEFER;; + if (config->reloading) { char *args = join_args(argv, argc); sway_log(L_DEBUG, "Ignoring 'exec %s' due to reload", args); @@ -420,7 +416,7 @@ static enum cmd_status cmd_mode(int argc, char **argv) { int mode_len = strlen(mode_name); bool mode_make = mode_name[mode_len-1] == '{'; if (mode_make) { - NO_BIND(); + if (!config->reading) return CMD_FAILURE;; // Trim trailing spaces do { mode_name[--mode_len] = 0; @@ -458,7 +454,7 @@ static enum cmd_status cmd_mode(int argc, char **argv) { } static enum cmd_status cmd_move(int argc, char **argv) { - NO_CONF(); + if (config->reading) return CMD_FAILURE;; if (!checkarg(argc, "move", EXPECTED_AT_LEAST, 1)) { return CMD_FAILURE; } @@ -529,7 +525,7 @@ static enum cmd_status cmd_move(int argc, char **argv) { } static enum cmd_status cmd_orientation(int argc, char **argv) { - NO_BIND(); + if (!config->reading) return CMD_FAILURE;; if (!checkarg(argc, "orientation", EXPECTED_EQUAL_TO, 1)) { return CMD_FAILURE; } @@ -547,7 +543,7 @@ static enum cmd_status cmd_orientation(int argc, char **argv) { } static enum cmd_status cmd_output(int argc, char **argv) { - NO_BIND(); + if (!config->reading) return CMD_FAILURE;; if (!checkarg(argc, "output", EXPECTED_AT_LEAST, 1)) { return CMD_FAILURE; } @@ -1007,11 +1003,6 @@ static enum cmd_status cmd_log_colors(int argc, char **argv) { return CMD_SUCCESS; } -__attribute__((unused)) -enum cmd_status cmd_for_window(int argc, char **argv) { - return CMD_FAILURE; -} - static enum cmd_status cmd_fullscreen(int argc, char **argv) { if (!checkarg(argc, "fullscreen", EXPECTED_AT_LEAST, 0) || config->reading || !config->active) { From a04f645d7cb4f54ebc11119220b4adb5d0b82ef1 Mon Sep 17 00:00:00 2001 From: taiyu Date: Tue, 15 Sep 2015 06:56:51 -0700 Subject: [PATCH 3/8] style, safer fork --- sway/commands.c | 53 ++++++++++++++++++++++--------------------------- 1 file changed, 24 insertions(+), 29 deletions(-) diff --git a/sway/commands.c b/sway/commands.c index bbf0bde2..f2ee0184 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -179,7 +179,7 @@ static enum cmd_status cmd_bindsym(int argc, char **argv) { } static enum cmd_status cmd_exec_always(int argc, char **argv) { - if (!config->active) return CMD_DEFER;; + if (!config->active) return CMD_DEFER; if (!checkarg(argc, "exec_always", EXPECTED_MORE_THAN, 0)) { return CMD_FAILURE; } @@ -190,27 +190,21 @@ static enum cmd_status cmd_exec_always(int argc, char **argv) { free(tmp); char *args[] = {"sh", "-c", cmd, 0 }; + sway_log(L_DEBUG, "Executing %s", cmd); - pid_t pid = vfork(); - /* Failed to fork */ - if (pid < 0) { - sway_log(L_ERROR, "exec command failed, sway did not fork"); + pid_t pid; + if ((pid = vfork()) == 0) { + execv("/bin/sh", args); + _exit(-1); + } else if (pid < 0) { + sway_log(L_ERROR, "exec command failed, sway could not fork"); return CMD_FAILURE; } - /* Child process */ - if (pid == 0) { - sway_log(L_DEBUG, "Executing %s", cmd); - execv("/bin/sh", args); - /* Execv doesnt return unless failure */ - sway_log(L_ERROR, "execv failde to return"); - _exit(-1); - } - /* Parent */ return CMD_SUCCESS; } static enum cmd_status cmd_exec(int argc, char **argv) { - if (!config->active) return CMD_DEFER;; + if (!config->active) return CMD_DEFER; if (config->reloading) { char *args = join_args(argv, argc); @@ -228,8 +222,8 @@ static void kill_views(swayc_t *container, void *data) { } static enum cmd_status cmd_exit(int argc, char **argv) { - if (!checkarg(argc, "exit", EXPECTED_EQUAL_TO, 0) - || config->reading || !config->active) { + if (config->reading) return CMD_INVALID; + if (!checkarg(argc, "exit", EXPECTED_EQUAL_TO, 0)) { return CMD_FAILURE; } // Close all views @@ -239,8 +233,8 @@ static enum cmd_status cmd_exit(int argc, char **argv) { } static enum cmd_status cmd_floating(int argc, char **argv) { - if (!checkarg(argc, "floating", EXPECTED_EQUAL_TO, 1) - || config->reading || !config->active) { + if (config->reading) return CMD_INVALID; + if (!checkarg(argc, "floating", EXPECTED_EQUAL_TO, 1)) { return CMD_FAILURE; } @@ -301,8 +295,8 @@ static enum cmd_status cmd_floating(int argc, char **argv) { } static enum cmd_status cmd_floating_mod(int argc, char **argv) { - if (!checkarg(argc, "floating_modifier", EXPECTED_EQUAL_TO, 1) - || !config->reading) { + if (!config->reading) return CMD_INVALID; + if (!checkarg(argc, "floating_modifier", EXPECTED_EQUAL_TO, 1)) { return CMD_FAILURE; } int i, j; @@ -326,10 +320,10 @@ static enum cmd_status cmd_floating_mod(int argc, char **argv) { } static enum cmd_status cmd_focus(int argc, char **argv) { + if (config->reading) return CMD_INVALID; static int floating_toggled_index = 0; static int tiled_toggled_index = 0; - if (!checkarg(argc, "focus", EXPECTED_EQUAL_TO, 1) - || config->reading || !config->active) { + if (!checkarg(argc, "focus", EXPECTED_EQUAL_TO, 1)) { return CMD_FAILURE; } if (strcasecmp(argv[0], "left") == 0) { @@ -384,6 +378,7 @@ static enum cmd_status cmd_focus(int argc, char **argv) { } static enum cmd_status cmd_focus_follows_mouse(int argc, char **argv) { + if (!config->reading) return CMD_INVALID; if (!checkarg(argc, "focus_follows_mouse", EXPECTED_EQUAL_TO, 1)) { return CMD_FAILURE; } @@ -393,7 +388,7 @@ static enum cmd_status cmd_focus_follows_mouse(int argc, char **argv) { } static void hide_view_in_scratchpad(swayc_t *sp_view) { - if(sp_view == NULL) { + if (sp_view == NULL) { return; } @@ -416,7 +411,7 @@ static enum cmd_status cmd_mode(int argc, char **argv) { int mode_len = strlen(mode_name); bool mode_make = mode_name[mode_len-1] == '{'; if (mode_make) { - if (!config->reading) return CMD_FAILURE;; + if (!config->reading) return CMD_INVALID; // Trim trailing spaces do { mode_name[--mode_len] = 0; @@ -454,7 +449,7 @@ static enum cmd_status cmd_mode(int argc, char **argv) { } static enum cmd_status cmd_move(int argc, char **argv) { - if (config->reading) return CMD_FAILURE;; + if (config->reading) return CMD_FAILURE; if (!checkarg(argc, "move", EXPECTED_AT_LEAST, 1)) { return CMD_FAILURE; } @@ -525,7 +520,7 @@ static enum cmd_status cmd_move(int argc, char **argv) { } static enum cmd_status cmd_orientation(int argc, char **argv) { - if (!config->reading) return CMD_FAILURE;; + if (!config->reading) return CMD_FAILURE; if (!checkarg(argc, "orientation", EXPECTED_EQUAL_TO, 1)) { return CMD_FAILURE; } @@ -543,7 +538,7 @@ static enum cmd_status cmd_orientation(int argc, char **argv) { } static enum cmd_status cmd_output(int argc, char **argv) { - if (!config->reading) return CMD_FAILURE;; + if (!config->reading) return CMD_FAILURE; if (!checkarg(argc, "output", EXPECTED_AT_LEAST, 1)) { return CMD_FAILURE; } @@ -994,7 +989,7 @@ static enum cmd_status cmd_log_colors(int argc, char **argv) { } if (strcasecmp(argv[0], "no") == 0) { sway_log_colors(0); - } else if(strcasecmp(argv[0], "yes") == 0) { + } else if (strcasecmp(argv[0], "yes") == 0) { sway_log_colors(1); } else { sway_log(L_ERROR, "Invalid log_colors command (expected `yes` or `no`, got '%s')", argv[0]); From d2e2b04bfd505561981c9137bfc493bb8effe63e Mon Sep 17 00:00:00 2001 From: taiyu Date: Fri, 18 Sep 2015 06:52:04 -0700 Subject: [PATCH 4/8] minor fix --- sway/container.c | 2 +- sway/handlers.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sway/container.c b/sway/container.c index ef0e6c55..d6bcc4c2 100644 --- a/sway/container.c +++ b/sway/container.c @@ -403,7 +403,7 @@ swayc_t *swayc_by_test(swayc_t *container, bool (*test)(swayc_t *view, void *dat } static bool test_name(swayc_t *view, void *data) { - if (!view && !view->name) { + if (!view || !view->name) { return false; } return strcmp(view->name, data) == 0; diff --git a/sway/handlers.c b/sway/handlers.c index 096df53c..15fa6521 100644 --- a/sway/handlers.c +++ b/sway/handlers.c @@ -331,7 +331,7 @@ static bool handle_key(wlc_handle view, uint32_t time, const struct wlc_modifier struct sway_binding *binding = mode->bindings->items[i]; if ((modifiers->mods ^ binding->modifiers) == 0) { - bool match; + bool match = false; int j; for (j = 0; j < binding->keys->length; ++j) { xkb_keysym_t *key = binding->keys->items[j]; From 7672886cb5927977617d274ebaec4a3840df0a5d Mon Sep 17 00:00:00 2001 From: taiyu Date: Fri, 18 Sep 2015 08:33:28 -0700 Subject: [PATCH 5/8] dont log empty config lines --- sway/commands.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/sway/commands.c b/sway/commands.c index 80770e87..03c682d7 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -1182,13 +1182,12 @@ enum cmd_status handle_command(char *_exec) { } enum cmd_status config_command(char *exec) { - sway_log(L_INFO, "handling config command '%s'", exec); enum cmd_status status = CMD_SUCCESS; int argc; char **argv = split_args(exec, &argc); - if (!argc) { - goto cleanup; - } + if (!argc) goto cleanup; + + sway_log(L_INFO, "handling config command '%s'", exec); // Endblock if (**argv == '}') { status = CMD_BLOCK_END; From 9fd2d635a1f167daf0b0111e084d0e519fca0386 Mon Sep 17 00:00:00 2001 From: taiyu Date: Fri, 18 Sep 2015 11:34:57 -0700 Subject: [PATCH 6/8] container_move check --- sway/layout.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sway/layout.c b/sway/layout.c index bef1b88d..66f0be29 100644 --- a/sway/layout.c +++ b/sway/layout.c @@ -206,7 +206,8 @@ void swap_geometry(swayc_t *a, swayc_t *b) { void move_container(swayc_t *container, enum movement_direction dir) { enum swayc_layouts layout; - if (container->is_floating) { + if (container->is_floating + || (container->type != C_VIEW && container->type != C_CONTAINER)) { return; } if (dir == MOVE_UP || dir == MOVE_DOWN) { From 72aaffcf5b96f7d20438191e17c1df7174e52e66 Mon Sep 17 00:00:00 2001 From: taiyu Date: Sun, 20 Sep 2015 10:56:22 -0700 Subject: [PATCH 7/8] fix config search paths --- sway/config.c | 40 +++++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/sway/config.c b/sway/config.c index 0026e0af..46a26424 100644 --- a/sway/config.c +++ b/sway/config.c @@ -110,47 +110,49 @@ static void config_defaults(struct sway_config *config) { static char *get_config_path(void) { char *config_path = NULL; - char *paths[3] = {getenv("HOME"), getenv("XDG_CONFIG_HOME"), ""}; - int pathlen[3] = {0, 0, 0}; + char *paths[3] = { getenv("HOME"), getenv("XDG_CONFIG_HOME"), "" }; + int pathlen[3] = { 0, 0, 0 }; int i; #define home paths[0] #define conf paths[1] // Get home and config directories + conf = conf ? strdup(conf) : NULL; home = home ? strdup(home) : NULL; - if (conf) { - conf = strdup(conf); - } else if (home) { + // If config folder is unset, set it to $HOME/.config + if (!conf && home) { const char *def = "/.config"; conf = malloc(strlen(home) + strlen(def) + 1); strcpy(conf, home); strcat(conf, def); - } else { - home = strdup(""); - conf = strdup(""); } - pathlen[0] = strlen(home); - pathlen[1] = strlen(conf); + // Get path lengths + pathlen[0] = home ? strlen(home) : 0; + pathlen[1] = conf ? strlen(conf) : 0; #undef home #undef conf + // Search for config file from search paths static const char *search_paths[] = { "/.sway/config", // Prepend with $home "/sway/config", // Prepend with $config "/etc/sway/config", "/.i3/config", // $home - "/.i3/config", // $config + "/i3/config", // $config "/etc/i3/config" }; for (i = 0; i < (int)(sizeof(search_paths) / sizeof(char *)); ++i) { - char *test = malloc(pathlen[i%3] + strlen(search_paths[i]) + 1); - strcpy(test, paths[i%3]); - strcat(test, search_paths[i]); - sway_log(L_DEBUG, "Checking for config at %s", test); - if (file_exists(test)) { - config_path = test; - goto cleanup; + // Only try path if it is set by enviroment variables + if (paths[i%3]) { + char *test = malloc(pathlen[i%3] + strlen(search_paths[i]) + 1); + strcpy(test, paths[i%3]); + strcpy(test + pathlen[i%3], search_paths[i]); + sway_log(L_DEBUG, "Checking for config at %s", test); + if (file_exists(test)) { + config_path = test; + goto cleanup; + } + free(test); } - free(test); } sway_log(L_DEBUG, "Trying to find config in XDG_CONFIG_DIRS"); From 6c33f8122a3c4bb8fc22129d1d2ad03f535885f7 Mon Sep 17 00:00:00 2001 From: taiyu Date: Tue, 22 Sep 2015 09:41:01 -0700 Subject: [PATCH 8/8] #184 --- sway/handlers.c | 4 ++-- sway/layout.c | 39 +++++++++++++++++++++++---------------- 2 files changed, 25 insertions(+), 18 deletions(-) diff --git a/sway/handlers.c b/sway/handlers.c index 096df53c..cef4a980 100644 --- a/sway/handlers.c +++ b/sway/handlers.c @@ -253,8 +253,8 @@ static void handle_view_focus(wlc_handle view, bool focus) { } static void handle_view_geometry_request(wlc_handle handle, const struct wlc_geometry *geometry) { - sway_log(L_DEBUG, "geometry request %d x %d : %d x %d", - geometry->origin.x, geometry->origin.y, geometry->size.w, geometry->size.h); + sway_log(L_DEBUG, "geometry request for %ld %dx%d : %dx%d", + handle, geometry->origin.x, geometry->origin.y, geometry->size.w, geometry->size.h); // If the view is floating, then apply the geometry. // Otherwise save the desired width/height for the view. // This will not do anything for the time being as WLC improperly sends geometry requests diff --git a/sway/layout.c b/sway/layout.c index bef1b88d..086dc542 100644 --- a/sway/layout.c +++ b/sway/layout.c @@ -280,7 +280,6 @@ void move_container(swayc_t *container, enum movement_direction dir) { // Dirty hack to fix a certain case arrange_windows(parent, -1, -1); arrange_windows(parent->parent, -1, -1); - update_visibility(parent->parent); set_focused_container_for(parent->parent, container); } @@ -319,31 +318,34 @@ void update_geometry(swayc_t *container) { if (container->type != C_VIEW) { return; } - int gap = swayc_gap(container); + swayc_t *ws = swayc_parent_by_type(container, C_WORKSPACE); + swayc_t *op = ws->parent; + int gap = container->is_floating ? 0 : swayc_gap(container); + struct wlc_geometry geometry = { .origin = { - .x = container->x + (container->is_floating ? 0 : gap / 2), - .y = container->y + (container->is_floating ? 0 : gap / 2) + .x = container->x + gap/2 < op->width ? container->x + gap/2 : op->width-1, + .y = container->y + gap/2 < op->height ? container->y + gap/2 : op->height-1 }, .size = { - .w = container->width > (container->is_floating ? 0 : gap) ? - container->width - (container->is_floating ? 0 : gap) : 0, - .h = container->height > (container->is_floating ? 0 : gap) ? - container->height - (container->is_floating ? 0 : gap) : 0, + .w = container->width > gap ? container->width - gap : 1, + .h = container->height > gap ? container->height - gap : 1, } }; if (swayc_is_fullscreen(container)) { - swayc_t *parent = swayc_parent_by_type(container, C_OUTPUT); geometry.origin.x = 0; geometry.origin.y = 0; - geometry.size.w = parent->width; - geometry.size.h = parent->height; + geometry.size.w = op->width; + geometry.size.h = op->height; + if (op->focused == ws) { + wlc_view_bring_to_front(container->handle); + } } wlc_view_set_geometry(container->handle, 0, &geometry); return; } -void arrange_windows(swayc_t *container, double width, double height) { +static void arrange_windows_r(swayc_t *container, double width, double height) { int i; if (width == -1 || height == -1) { sway_log(L_DEBUG, "Arranging layout for %p", container); @@ -357,7 +359,7 @@ void arrange_windows(swayc_t *container, double width, double height) { for (i = 0; i < container->children->length; ++i) { swayc_t *child = container->children->items[i]; sway_log(L_DEBUG, "Arranging output at %d", x); - arrange_windows(child, -1, -1); + arrange_windows_r(child, -1, -1); x += child->width; } return; @@ -373,7 +375,7 @@ void arrange_windows(swayc_t *container, double width, double height) { child->width = width - gap * 2; child->height = height - gap * 2; sway_log(L_DEBUG, "Arranging workspace #%d at %f, %f", i, child->x, child->y); - arrange_windows(child, -1, -1); + arrange_windows_r(child, -1, -1); } return; case C_VIEW: @@ -417,7 +419,7 @@ void arrange_windows(swayc_t *container, double width, double height) { sway_log(L_DEBUG, "Calculating arrangement for %p:%d (will scale %f by %f)", child, child->type, width, scale); child->x = x + container->x; child->y = y + container->y; - arrange_windows(child, child->width * scale, height); + arrange_windows_r(child, child->width * scale, height); x += child->width; } } @@ -444,7 +446,7 @@ void arrange_windows(swayc_t *container, double width, double height) { sway_log(L_DEBUG, "Calculating arrangement for %p:%d (will scale %f by %f)", child, child->type, height, scale); child->x = x + container->x; child->y = y + container->y; - arrange_windows(child, width, child->height * scale); + arrange_windows_r(child, width, child->height * scale); y += child->height; } } @@ -466,6 +468,11 @@ void arrange_windows(swayc_t *container, double width, double height) { } } } +} + +void arrange_windows(swayc_t *container, double width, double height) { + update_visibility(container); + arrange_windows_r(container, width, height); layout_log(&root_container, 0); }