mirror of
				https://github.com/swaywm/sway.git
				synced 2025-10-29 05:40:18 -04:00 
			
		
		
		
	Merge pull request #3108 from RedSoxFan/workspace-output-improved
Allow multiple outputs for workspace output
This commit is contained in:
		
						commit
						101515eb0c
					
				
					 5 changed files with 66 additions and 25 deletions
				
			
		|  | @ -183,7 +183,7 @@ struct side_gaps { | ||||||
|  */ |  */ | ||||||
| struct workspace_config { | struct workspace_config { | ||||||
| 	char *workspace; | 	char *workspace; | ||||||
| 	char *output; | 	list_t *outputs; | ||||||
| 	int gaps_inner; | 	int gaps_inner; | ||||||
| 	struct side_gaps gaps_outer; | 	struct side_gaps gaps_outer; | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | @ -21,6 +21,7 @@ static struct workspace_config *workspace_config_find_or_create(char *ws_name) { | ||||||
| 		return NULL; | 		return NULL; | ||||||
| 	} | 	} | ||||||
| 	wsc->workspace = strdup(ws_name); | 	wsc->workspace = strdup(ws_name); | ||||||
|  | 	wsc->outputs = create_list(); | ||||||
| 	wsc->gaps_inner = INT_MIN; | 	wsc->gaps_inner = INT_MIN; | ||||||
| 	wsc->gaps_outer.top = INT_MIN; | 	wsc->gaps_outer.top = INT_MIN; | ||||||
| 	wsc->gaps_outer.right = INT_MIN; | 	wsc->gaps_outer.right = INT_MIN; | ||||||
|  | @ -32,7 +33,7 @@ static struct workspace_config *workspace_config_find_or_create(char *ws_name) { | ||||||
| 
 | 
 | ||||||
| void free_workspace_config(struct workspace_config *wsc) { | void free_workspace_config(struct workspace_config *wsc) { | ||||||
| 	free(wsc->workspace); | 	free(wsc->workspace); | ||||||
| 	free(wsc->output); | 	free_flat_list(wsc->outputs); | ||||||
| 	free(wsc); | 	free(wsc); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -141,18 +142,20 @@ struct cmd_results *cmd_workspace(int argc, char **argv) { | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	if (output_location >= 0) { | 	if (output_location >= 0) { | ||||||
| 		if ((error = checkarg(argc, "workspace", EXPECTED_EQUAL_TO, output_location + 2))) { | 		if ((error = checkarg(argc, "workspace", EXPECTED_AT_LEAST, | ||||||
|  | 						output_location + 2))) { | ||||||
| 			return error; | 			return error; | ||||||
| 		} | 		} | ||||||
| 		char *ws_name = join_args(argv, argc - 2); | 		char *ws_name = join_args(argv, output_location); | ||||||
| 		struct workspace_config *wsc = workspace_config_find_or_create(ws_name); | 		struct workspace_config *wsc = workspace_config_find_or_create(ws_name); | ||||||
| 		free(ws_name); | 		free(ws_name); | ||||||
| 		if (!wsc) { | 		if (!wsc) { | ||||||
| 			return cmd_results_new(CMD_FAILURE, "workspace output", | 			return cmd_results_new(CMD_FAILURE, "workspace output", | ||||||
| 					"Unable to allocate workspace output"); | 					"Unable to allocate workspace output"); | ||||||
| 		} | 		} | ||||||
| 		free(wsc->output); | 		for (int i = output_location + 1; i < argc; ++i) { | ||||||
| 		wsc->output = strdup(argv[output_location + 1]); | 			list_add(wsc->outputs, strdup(argv[i])); | ||||||
|  | 		} | ||||||
| 	} else if (gaps_location >= 0) { | 	} else if (gaps_location >= 0) { | ||||||
| 		if ((error = cmd_workspace_gaps(argc, argv, gaps_location))) { | 		if ((error = cmd_workspace_gaps(argc, argv, gaps_location))) { | ||||||
| 			return error; | 			return error; | ||||||
|  |  | ||||||
|  | @ -573,8 +573,12 @@ The default colors are: | ||||||
| 	Specifies that workspace _name_ should have the given gaps settings when it | 	Specifies that workspace _name_ should have the given gaps settings when it | ||||||
| 	is created. | 	is created. | ||||||
| 
 | 
 | ||||||
| *workspace* <name> output <output> | *workspace* <name> output <outputs...> | ||||||
| 	Specifies that workspace _name_ should be shown on the specified _output_. | 	Specifies that workspace _name_ should be shown on the specified _outputs_. | ||||||
|  | 	Multiple outputs can be listed and the first available will be used. If the | ||||||
|  | 	workspace gets placed on an output further down the list and an output that | ||||||
|  | 	is higher on the list becomes available, the workspace will be move to the | ||||||
|  | 	higher priority output. | ||||||
| 
 | 
 | ||||||
| *workspace\_auto\_back\_and\_forth* yes|no | *workspace\_auto\_back\_and\_forth* yes|no | ||||||
| 	When _yes_, repeating a workspace switch command will switch back to the | 	When _yes_, repeating a workspace switch command will switch back to the | ||||||
|  |  | ||||||
|  | @ -31,6 +31,13 @@ static void restore_workspaces(struct sway_output *output) { | ||||||
| 				j--; | 				j--; | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  | 
 | ||||||
|  | 		if (other->workspaces->length == 0) { | ||||||
|  | 			char *next = workspace_next_name(other->wlr_output->name); | ||||||
|  | 			struct sway_workspace *ws = workspace_create(other, next); | ||||||
|  | 			free(next); | ||||||
|  | 			ipc_event_workspace(NULL, ws, "init"); | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// Saved workspaces
 | 	// Saved workspaces
 | ||||||
|  |  | ||||||
|  | @ -33,14 +33,15 @@ struct workspace_config *workspace_find_config(const char *ws_name) { | ||||||
| struct sway_output *workspace_get_initial_output(const char *name) { | struct sway_output *workspace_get_initial_output(const char *name) { | ||||||
| 	// Check workspace configs for a workspace<->output pair
 | 	// Check workspace configs for a workspace<->output pair
 | ||||||
| 	struct workspace_config *wsc = workspace_find_config(name); | 	struct workspace_config *wsc = workspace_find_config(name); | ||||||
| 	if (wsc && wsc->output) { | 	if (wsc) { | ||||||
| 		struct sway_output *output = output_by_name(wsc->output); | 		for (int i = 0; i < wsc->outputs->length; i++) { | ||||||
| 		if (!output) { | 			struct sway_output *output = output_by_name(wsc->outputs->items[i]); | ||||||
| 			output = output_by_identifier(wsc->output); | 			if (!output) { | ||||||
| 		} | 				output = output_by_identifier(wsc->outputs->items[i]); | ||||||
| 		 | 			} | ||||||
| 		if (output) { | 			if (output) { | ||||||
| 			return output; | 				return output; | ||||||
|  | 			} | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	// Otherwise put it on the focused output
 | 	// Otherwise put it on the focused output
 | ||||||
|  | @ -85,7 +86,6 @@ struct sway_workspace *workspace_create(struct sway_output *output, | ||||||
| 	ws->floating = create_list(); | 	ws->floating = create_list(); | ||||||
| 	ws->tiling = create_list(); | 	ws->tiling = create_list(); | ||||||
| 	ws->output_priority = create_list(); | 	ws->output_priority = create_list(); | ||||||
| 	workspace_output_add_priority(ws, output); |  | ||||||
| 
 | 
 | ||||||
| 	ws->gaps_outer = config->gaps_outer; | 	ws->gaps_outer = config->gaps_outer; | ||||||
| 	ws->gaps_inner = config->gaps_inner; | 	ws->gaps_inner = config->gaps_inner; | ||||||
|  | @ -110,9 +110,17 @@ struct sway_workspace *workspace_create(struct sway_output *output, | ||||||
| 			// Since default outer gaps can be smaller than the negation of
 | 			// Since default outer gaps can be smaller than the negation of
 | ||||||
| 			// workspace specific inner gaps, check outer gaps again
 | 			// workspace specific inner gaps, check outer gaps again
 | ||||||
| 			prevent_invalid_outer_gaps(ws); | 			prevent_invalid_outer_gaps(ws); | ||||||
|  | 
 | ||||||
|  | 			// Add output priorities
 | ||||||
|  | 			for (int i = 0; i < wsc->outputs->length; ++i) { | ||||||
|  | 				list_add(ws->output_priority, strdup(wsc->outputs->items[i])); | ||||||
|  | 			} | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	// If not already added, add the output to the lowest priority
 | ||||||
|  | 	workspace_output_add_priority(ws, output); | ||||||
|  | 
 | ||||||
| 	output_add_workspace(output, ws); | 	output_add_workspace(output, ws); | ||||||
| 	output_sort_workspaces(output); | 	output_sort_workspaces(output); | ||||||
| 
 | 
 | ||||||
|  | @ -134,8 +142,7 @@ void workspace_destroy(struct sway_workspace *workspace) { | ||||||
| 
 | 
 | ||||||
| 	free(workspace->name); | 	free(workspace->name); | ||||||
| 	free(workspace->representation); | 	free(workspace->representation); | ||||||
| 	list_foreach(workspace->output_priority, free); | 	free_flat_list(workspace->output_priority); | ||||||
| 	list_free(workspace->output_priority); |  | ||||||
| 	list_free(workspace->floating); | 	list_free(workspace->floating); | ||||||
| 	list_free(workspace->tiling); | 	list_free(workspace->tiling); | ||||||
| 	list_free(workspace->current.floating); | 	list_free(workspace->current.floating); | ||||||
|  | @ -177,8 +184,19 @@ static bool workspace_valid_on_output(const char *output_name, | ||||||
| 	char identifier[128]; | 	char identifier[128]; | ||||||
| 	struct sway_output *output = output_by_name(output_name); | 	struct sway_output *output = output_by_name(output_name); | ||||||
| 	output_get_identifier(identifier, sizeof(identifier), output); | 	output_get_identifier(identifier, sizeof(identifier), output); | ||||||
| 		 | 
 | ||||||
| 	return !wsc || !wsc->output || strcmp(wsc->output, output_name) == 0 || strcasecmp(identifier, output_name) == 0; | 	if (!wsc) { | ||||||
|  | 		return true; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	for (int i = 0; i < wsc->outputs->length; i++) { | ||||||
|  | 		if (strcmp(wsc->outputs->items[i], output_name) == 0 || | ||||||
|  | 				strcmp(wsc->outputs->items[i], identifier) == 0) { | ||||||
|  | 			return true; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return false; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void workspace_name_from_binding(const struct sway_binding * binding, | static void workspace_name_from_binding(const struct sway_binding * binding, | ||||||
|  | @ -281,10 +299,19 @@ char *workspace_next_name(const char *output_name) { | ||||||
| 	for (int i = 0; i < config->workspace_configs->length; ++i) { | 	for (int i = 0; i < config->workspace_configs->length; ++i) { | ||||||
| 		// Unlike with bindings, this does not guarantee order
 | 		// Unlike with bindings, this does not guarantee order
 | ||||||
| 		const struct workspace_config *wsc = config->workspace_configs->items[i]; | 		const struct workspace_config *wsc = config->workspace_configs->items[i]; | ||||||
| 		if (wsc->output && strcmp(wsc->output, output_name) == 0 | 		if (workspace_by_name(wsc->workspace)) { | ||||||
| 				&& workspace_by_name(wsc->workspace) == NULL) { | 			continue; | ||||||
| 			free(target); | 		} | ||||||
| 			target = strdup(wsc->workspace); | 		bool found = false; | ||||||
|  | 		for (int j = 0; j < wsc->outputs->length; ++j) { | ||||||
|  | 			if (strcmp(wsc->outputs->items[j], output_name) == 0) { | ||||||
|  | 				found = true; | ||||||
|  | 				free(target); | ||||||
|  | 				target = strdup(wsc->workspace); | ||||||
|  | 				break; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		if (found) { | ||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Drew DeVault
						Drew DeVault