diff options
Diffstat (limited to 'sway/commands')
| -rw-r--r-- | sway/commands/gaps.c | 306 | ||||
| -rw-r--r-- | sway/commands/layout.c | 3 | ||||
| -rw-r--r-- | sway/commands/workspace.c | 38 | 
3 files changed, 193 insertions, 154 deletions
diff --git a/sway/commands/gaps.c b/sway/commands/gaps.c index d676e475..2e0876a9 100644 --- a/sway/commands/gaps.c +++ b/sway/commands/gaps.c @@ -1,4 +1,5 @@  #include <string.h> +#include <strings.h>  #include "sway/commands.h"  #include "sway/config.h"  #include "sway/tree/arrange.h" @@ -13,172 +14,173 @@ enum gaps_op {  	GAPS_OP_SUBTRACT  }; -enum gaps_scope { -	GAPS_SCOPE_ALL, -	GAPS_SCOPE_WORKSPACE, -	GAPS_SCOPE_CURRENT +struct gaps_data { +	bool inner; +	enum gaps_op operation; +	int amount;  }; -struct cmd_results *cmd_gaps(int argc, char **argv) { -	struct cmd_results *error = checkarg(argc, "gaps", EXPECTED_AT_LEAST, 1); -	if (error) { +// gaps edge_gaps on|off|toggle +static struct cmd_results *gaps_edge_gaps(int argc, char **argv) { +	struct cmd_results *error; +	if ((error = checkarg(argc, "gaps", EXPECTED_AT_LEAST, 2))) {  		return error;  	} -	if (strcmp(argv[0], "edge_gaps") == 0) { -		if ((error = checkarg(argc, "gaps", EXPECTED_AT_LEAST, 2))) { -			return error; -		} - -		if (strcmp(argv[1], "on") == 0) { -			config->edge_gaps = true; -		} else if (strcmp(argv[1], "off") == 0) { -			config->edge_gaps = false; -		} else if (strcmp(argv[1], "toggle") == 0) { -			if (!config->active) { -				return cmd_results_new(CMD_INVALID, "gaps", -					"Cannot toggle gaps while not running."); -			} -			config->edge_gaps = !config->edge_gaps; -		} else { +	if (strcmp(argv[1], "on") == 0) { +		config->edge_gaps = true; +	} else if (strcmp(argv[1], "off") == 0) { +		config->edge_gaps = false; +	} else if (strcmp(argv[1], "toggle") == 0) { +		if (!config->active) {  			return cmd_results_new(CMD_INVALID, "gaps", -				"gaps edge_gaps on|off|toggle"); +					"Cannot toggle gaps while not running.");  		} -		arrange_root(); +		config->edge_gaps = !config->edge_gaps;  	} else { -		int amount_idx = 0; // the current index in argv -		enum gaps_op op = GAPS_OP_SET; -		enum gaps_scope scope = GAPS_SCOPE_ALL; -		bool inner = true; - -		if (strcmp(argv[0], "inner") == 0) { -			amount_idx++; -			inner = true; -		} else if (strcmp(argv[0], "outer") == 0) { -			amount_idx++; -			inner = false; -		} +		return cmd_results_new(CMD_INVALID, "gaps", +				"gaps edge_gaps on|off|toggle"); +	} +	arrange_root(); +	return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} -		// If one of the long variants of the gaps command is used -		// (which starts with inner|outer) check the number of args -		if (amount_idx > 0) { // if we've seen inner|outer -			if (argc > 2) { // check the longest variant -				error = checkarg(argc, "gaps", EXPECTED_EQUAL_TO, 4); -				if (error) { -					return error; -				} -			} else { // check the next longest format -				error = checkarg(argc, "gaps", EXPECTED_EQUAL_TO, 2); -				if (error) { -					return error; -				} -			} -		} else { -			error = checkarg(argc, "gaps", EXPECTED_EQUAL_TO, 1); -			if (error) { -				return error; -			} -		} +// gaps inner|outer <px> +static struct cmd_results *gaps_set_defaults(int argc, char **argv) { +	struct cmd_results *error = checkarg(argc, "gaps", EXPECTED_EQUAL_TO, 2); +	if (error) { +		return error; +	} -		if (argc == 4) { -			// Long format: all|workspace|current. -			if (strcmp(argv[amount_idx], "all") == 0) { -				amount_idx++; -				scope = GAPS_SCOPE_ALL; -			} else if (strcmp(argv[amount_idx], "workspace") == 0) { -				amount_idx++; -				scope = GAPS_SCOPE_WORKSPACE; -			} else if (strcmp(argv[amount_idx], "current") == 0) { -				amount_idx++; -				scope = GAPS_SCOPE_CURRENT; -			} - -			// Long format: set|plus|minus -			if (strcmp(argv[amount_idx], "set") == 0) { -				amount_idx++; -				op = GAPS_OP_SET; -			} else if (strcmp(argv[amount_idx], "plus") == 0) { -				amount_idx++; -				op = GAPS_OP_ADD; -			} else if (strcmp(argv[amount_idx], "minus") == 0) { -				amount_idx++; -				op = GAPS_OP_SUBTRACT; -			} -		} +	bool inner; +	if (strcasecmp(argv[0], "inner") == 0) { +		inner = true; +	} else if (strcasecmp(argv[0], "outer") == 0) { +		inner = false; +	} else { +		return cmd_results_new(CMD_INVALID, "gaps", +				"Expected 'gaps inner|outer <px>'"); +	} -		char *end; -		double val = strtod(argv[amount_idx], &end); - -		if (strlen(end) && val == 0.0) { // invalid <amount> -			// guess which variant of the command was attempted -			if (argc == 1) { -				return cmd_results_new(CMD_INVALID, "gaps", "gaps <amount>"); -			} -			if (argc == 2) { -				return cmd_results_new(CMD_INVALID, "gaps", -					"gaps inner|outer <amount>"); -			} -			return cmd_results_new(CMD_INVALID, "gaps", -				"gaps inner|outer all|workspace|current set|plus|minus <amount>"); -		} +	char *end; +	int amount = strtol(argv[1], &end, 10); +	if (strlen(end) && strcasecmp(end, "px") != 0) { +		return cmd_results_new(CMD_INVALID, "gaps", +				"Expected 'gaps inner|outer <px>'"); +	} +	if (amount < 0) { +		amount = 0; +	} -		if (amount_idx == 0) { // gaps <amount> -			config->gaps_inner = val; -			config->gaps_outer = val; -			arrange_root(); -			return cmd_results_new(CMD_SUCCESS, NULL, NULL); -		} -		// Other variants. The middle-length variant (gaps inner|outer <amount>) -		// just defaults the scope to "all" and defaults the op to "set". - -		double total; -		switch (op) { -			case GAPS_OP_SUBTRACT: { -				total = (inner ? config->gaps_inner : config->gaps_outer) - val; -				if (total < 0) { -					total = 0; -				} -				break; -			} -			case GAPS_OP_ADD: { -				total = (inner ? config->gaps_inner : config->gaps_outer) + val; -				break; -			} -			case GAPS_OP_SET: { -				total = val; -				break; -			} -		} +	if (inner) { +		config->gaps_inner = amount; +	} else { +		config->gaps_outer = amount; +	} +	return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} -		if (scope == GAPS_SCOPE_ALL) { -			if (inner) { -				config->gaps_inner = total; -			} else { -				config->gaps_outer = total; -			} -			arrange_root(); -		} else { -			if (scope == GAPS_SCOPE_WORKSPACE) { -				struct sway_workspace *ws = config->handler_context.workspace; -				ws->has_gaps = true; -				if (inner) { -					ws->gaps_inner = total; -				} else { -					ws->gaps_outer = total; -				} -				arrange_workspace(ws); -			} else { -				struct sway_container *c = config->handler_context.container; -				c->has_gaps = true; -				if (inner) { -					c->gaps_inner = total; -				} else { -					c->gaps_outer = total; -				} -				arrange_workspace(c->workspace); -			} -		} +static void configure_gaps(struct sway_workspace *ws, void *_data) { +	struct gaps_data *data = _data; +	int *prop = data->inner ? &ws->gaps_inner : &ws->gaps_outer; + +	switch (data->operation) { +	case GAPS_OP_SET: +		*prop = data->amount; +		break; +	case GAPS_OP_ADD: +		*prop += data->amount; +		break; +	case GAPS_OP_SUBTRACT: +		*prop -= data->amount; +		break; +	} +	if (*prop < 0) { +		*prop = 0; +	} +	arrange_workspace(ws); +} + +// gaps inner|outer current|all set|plus|minus <px> +static struct cmd_results *gaps_set_runtime(int argc, char **argv) { +	struct cmd_results *error = checkarg(argc, "gaps", EXPECTED_EQUAL_TO, 4); +	if (error) { +		return error; +	} + +	struct gaps_data data; + +	if (strcasecmp(argv[0], "inner") == 0) { +		data.inner = true; +	} else if (strcasecmp(argv[0], "outer") == 0) { +		data.inner = false; +	} else { +		return cmd_results_new(CMD_INVALID, "gaps", +				"Expected 'gaps inner|outer current|all set|plus|minus <px>'"); +	} + +	bool all; +	if (strcasecmp(argv[1], "current") == 0) { +		all = false; +	} else if (strcasecmp(argv[1], "all") == 0) { +		all = true; +	} else { +		return cmd_results_new(CMD_INVALID, "gaps", +				"Expected 'gaps inner|outer current|all set|plus|minus <px>'"); +	} + +	if (strcasecmp(argv[2], "set") == 0) { +		data.operation = GAPS_OP_SET; +	} else if (strcasecmp(argv[2], "plus") == 0) { +		data.operation = GAPS_OP_ADD; +	} else if (strcasecmp(argv[2], "minus") == 0) { +		data.operation = GAPS_OP_SUBTRACT; +	} else { +		return cmd_results_new(CMD_INVALID, "gaps", +				"Expected 'gaps inner|outer current|all set|plus|minus <px>'"); +	} + +	char *end; +	data.amount = strtol(argv[3], &end, 10); +	if (strlen(end) && strcasecmp(end, "px") != 0) { +		return cmd_results_new(CMD_INVALID, "gaps", +				"Expected 'gaps inner|outer current|all set|plus|minus <px>'"); +	} + +	if (all) { +		root_for_each_workspace(configure_gaps, &data); +	} else { +		configure_gaps(config->handler_context.workspace, &data);  	}  	return cmd_results_new(CMD_SUCCESS, NULL, NULL);  } + +// gaps edge_gaps on|off|toggle +// gaps inner|outer <px> - sets defaults for workspaces +// gaps inner|outer current|all set|plus|minus <px> - runtime only +struct cmd_results *cmd_gaps(int argc, char **argv) { +	struct cmd_results *error = checkarg(argc, "gaps", EXPECTED_AT_LEAST, 2); +	if (error) { +		return error; +	} + +	if (strcmp(argv[0], "edge_gaps") == 0) { +		return gaps_edge_gaps(argc, argv); +	} + +	if (argc == 2) { +		return gaps_set_defaults(argc, argv); +	} +	if (argc == 4) { +		if (config->active) { +			return gaps_set_runtime(argc, argv); +		} else { +			return cmd_results_new(CMD_INVALID, "gaps", +					"This syntax can only be used when sway is running"); +		} +	} +	return cmd_results_new(CMD_INVALID, "gaps", +			"Expected 'gaps inner|outer <px>' or " +			"'gaps inner|outer current|all set|plus|minus <px>'"); +} diff --git a/sway/commands/layout.c b/sway/commands/layout.c index ef3ec1cb..c2ce2e78 100644 --- a/sway/commands/layout.c +++ b/sway/commands/layout.c @@ -138,15 +138,14 @@ struct cmd_results *cmd_layout(int argc, char **argv) {  			}  			container->layout = new_layout;  			container_update_representation(container); -			arrange_container(container);  		} else {  			if (old_layout != L_TABBED && old_layout != L_STACKED) {  				workspace->prev_split_layout = old_layout;  			}  			workspace->layout = new_layout;  			workspace_update_representation(workspace); -			arrange_workspace(workspace);  		} +		arrange_workspace(workspace);  	}  	return cmd_results_new(CMD_SUCCESS, NULL, NULL); diff --git a/sway/commands/workspace.c b/sway/commands/workspace.c index 2ce7872d..63f29641 100644 --- a/sway/commands/workspace.c +++ b/sway/commands/workspace.c @@ -20,6 +20,8 @@ static struct workspace_config *workspace_config_find_or_create(char *ws_name) {  		return NULL;  	}  	wsc->workspace = strdup(ws_name); +	wsc->gaps_inner = -1; +	wsc->gaps_outer = -1;  	list_add(config->workspace_configs, wsc);  	return wsc;  } @@ -37,6 +39,7 @@ struct cmd_results *cmd_workspace(int argc, char **argv) {  	}  	int output_location = -1; +	int gaps_location = -1;  	for (int i = 0; i < argc; ++i) {  		if (strcasecmp(argv[i], "output") == 0) { @@ -44,6 +47,12 @@ struct cmd_results *cmd_workspace(int argc, char **argv) {  			break;  		}  	} +	for (int i = 0; i < argc; ++i) { +		if (strcasecmp(argv[i], "gaps") == 0) { +			gaps_location = i; +			break; +		} +	}  	if (output_location >= 0) {  		if ((error = checkarg(argc, "workspace", EXPECTED_EQUAL_TO, output_location + 2))) {  			return error; @@ -57,6 +66,35 @@ struct cmd_results *cmd_workspace(int argc, char **argv) {  		}  		free(wsc->output);  		wsc->output = strdup(argv[output_location + 1]); +	} else if (gaps_location >= 0) { +		if ((error = checkarg(argc, "workspace", EXPECTED_EQUAL_TO, gaps_location + 3))) { +			return error; +		} +		char *ws_name = join_args(argv, argc - 3); +		struct workspace_config *wsc = workspace_config_find_or_create(ws_name); +		free(ws_name); +		if (!wsc) { +			return cmd_results_new(CMD_FAILURE, "workspace gaps", +					"Unable to allocate workspace output"); +		} +		int *prop = NULL; +		if (strcasecmp(argv[gaps_location + 1], "inner") == 0) { +			prop = &wsc->gaps_inner; +		} else if (strcasecmp(argv[gaps_location + 1], "outer") == 0) { +			prop = &wsc->gaps_outer; +		} else { +			return cmd_results_new(CMD_FAILURE, "workspace gaps", +					"Expected 'workspace <ws> gaps inner|outer <px>'"); +		} +		char *end; +		int val = strtol(argv[gaps_location + 2], &end, 10); + +		if (strlen(end)) { +			free(end); +			return cmd_results_new(CMD_FAILURE, "workspace gaps", +					"Expected 'workspace <ws> gaps inner|outer <px>'"); +		} +		*prop = val >= 0 ? val : 0;  	} else {  		if (config->reading || !config->active) {  			return cmd_results_new(CMD_DEFER, "workspace", NULL);  | 
