commit
						9fa70ce426
					
				| @ -0,0 +1,311 @@ | |||||||
|  | #define _XOPEN_SOURCE 500 | ||||||
|  | #include <ctype.h> | ||||||
|  | #include <libgen.h> | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include <string.h> | ||||||
|  | #include <strings.h> | ||||||
|  | #include <unistd.h> | ||||||
|  | #include <wordexp.h> | ||||||
|  | #include "sway/commands.h" | ||||||
|  | #include "sway/config.h" | ||||||
|  | #include "list.h" | ||||||
|  | #include "log.h" | ||||||
|  | #include "stringop.h" | ||||||
|  | 
 | ||||||
|  | static char *bg_options[] = { | ||||||
|  | 	"stretch", | ||||||
|  | 	"center", | ||||||
|  | 	"fill", | ||||||
|  | 	"fit", | ||||||
|  | 	"tile", | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct cmd_results *cmd_output(int argc, char **argv) { | ||||||
|  | 	struct cmd_results *error = NULL; | ||||||
|  | 	if ((error = checkarg(argc, "output", EXPECTED_AT_LEAST, 1))) { | ||||||
|  | 		return error; | ||||||
|  | 	} | ||||||
|  | 	const char *name = argv[0]; | ||||||
|  | 
 | ||||||
|  | 	struct output_config *output = new_output_config(); | ||||||
|  | 	if (!output) { | ||||||
|  | 		sway_log(L_ERROR, "Failed to allocate output config"); | ||||||
|  | 		return NULL; | ||||||
|  | 	} | ||||||
|  | 	output->name = strdup(name); | ||||||
|  | 
 | ||||||
|  | 	int i; | ||||||
|  | 	for (i = 1; i < argc; ++i) { | ||||||
|  | 		const char *command = argv[i]; | ||||||
|  | 
 | ||||||
|  | 		if (strcasecmp(command, "disable") == 0) { | ||||||
|  | 			output->enabled = 0; | ||||||
|  | 		} else if (strcasecmp(command, "mode") == 0 || | ||||||
|  | 				strcasecmp(command, "resolution") == 0 || | ||||||
|  | 				strcasecmp(command, "res") == 0) { | ||||||
|  | 			if (++i >= argc) { | ||||||
|  | 				error = cmd_results_new(CMD_INVALID, "output", | ||||||
|  | 					"Missing mode argument."); | ||||||
|  | 				goto fail; | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			int width = -1, height = -1; | ||||||
|  | 			float refresh_rate = -1; | ||||||
|  | 
 | ||||||
|  | 			char *end; | ||||||
|  | 			width = strtol(argv[i], &end, 10); | ||||||
|  | 			if (*end) { | ||||||
|  | 				// Format is 1234x4321
 | ||||||
|  | 				if (*end != 'x') { | ||||||
|  | 					error = cmd_results_new(CMD_INVALID, "output", | ||||||
|  | 						"Invalid mode width."); | ||||||
|  | 					goto fail; | ||||||
|  | 				} | ||||||
|  | 				++end; | ||||||
|  | 				height = strtol(end, &end, 10); | ||||||
|  | 				if (*end) { | ||||||
|  | 					if (*end != '@') { | ||||||
|  | 						error = cmd_results_new(CMD_INVALID, "output", | ||||||
|  | 							"Invalid mode height."); | ||||||
|  | 						goto fail; | ||||||
|  | 					} | ||||||
|  | 					++end; | ||||||
|  | 					refresh_rate = strtof(end, &end); | ||||||
|  | 					if (strcasecmp("Hz", end) != 0) { | ||||||
|  | 						error = cmd_results_new(CMD_INVALID, "output", | ||||||
|  | 							"Invalid mode refresh rate."); | ||||||
|  | 						goto fail; | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 			} else { | ||||||
|  | 				// Format is 1234 4321
 | ||||||
|  | 				if (++i >= argc) { | ||||||
|  | 					error = cmd_results_new(CMD_INVALID, "output", | ||||||
|  | 						"Missing mode argument (height)."); | ||||||
|  | 					goto fail; | ||||||
|  | 				} | ||||||
|  | 				height = strtol(argv[i], &end, 10); | ||||||
|  | 				if (*end) { | ||||||
|  | 					error = cmd_results_new(CMD_INVALID, "output", | ||||||
|  | 						"Invalid mode height."); | ||||||
|  | 					goto fail; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			output->width = width; | ||||||
|  | 			output->height = height; | ||||||
|  | 			output->refresh_rate = refresh_rate; | ||||||
|  | 		} else if (strcasecmp(command, "position") == 0 || | ||||||
|  | 				strcasecmp(command, "pos") == 0) { | ||||||
|  | 			if (++i >= argc) { | ||||||
|  | 				error = cmd_results_new(CMD_INVALID, "output", | ||||||
|  | 					"Missing position argument."); | ||||||
|  | 				goto fail; | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			int x = -1, y = -1; | ||||||
|  | 
 | ||||||
|  | 			char *end; | ||||||
|  | 			x = strtol(argv[i], &end, 10); | ||||||
|  | 			if (*end) { | ||||||
|  | 				// Format is 1234,4321
 | ||||||
|  | 				if (*end != ',') { | ||||||
|  | 					error = cmd_results_new(CMD_INVALID, "output", | ||||||
|  | 						"Invalid position x."); | ||||||
|  | 					goto fail; | ||||||
|  | 				} | ||||||
|  | 				++end; | ||||||
|  | 				y = strtol(end, &end, 10); | ||||||
|  | 				if (*end) { | ||||||
|  | 					error = cmd_results_new(CMD_INVALID, "output", | ||||||
|  | 						"Invalid position y."); | ||||||
|  | 					goto fail; | ||||||
|  | 				} | ||||||
|  | 			} else { | ||||||
|  | 				// Format is 1234 4321 (legacy)
 | ||||||
|  | 				if (++i >= argc) { | ||||||
|  | 					error = cmd_results_new(CMD_INVALID, "output", | ||||||
|  | 						"Missing position argument (y)."); | ||||||
|  | 					goto fail; | ||||||
|  | 				} | ||||||
|  | 				y = strtol(argv[i], &end, 10); | ||||||
|  | 				if (*end) { | ||||||
|  | 					error = cmd_results_new(CMD_INVALID, "output", | ||||||
|  | 						"Invalid position y."); | ||||||
|  | 					goto fail; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			output->x = x; | ||||||
|  | 			output->y = y; | ||||||
|  | 		} else if (strcasecmp(command, "scale") == 0) { | ||||||
|  | 			if (++i >= argc) { | ||||||
|  | 				error = cmd_results_new(CMD_INVALID, "output", | ||||||
|  | 					"Missing scale parameter."); | ||||||
|  | 				goto fail; | ||||||
|  | 			} | ||||||
|  | 			char *end; | ||||||
|  | 			output->scale = strtol(argv[i], &end, 10); | ||||||
|  | 			if (*end) { | ||||||
|  | 				error = cmd_results_new(CMD_INVALID, "output", | ||||||
|  | 					"Invalid scale."); | ||||||
|  | 				goto fail; | ||||||
|  | 			} | ||||||
|  | 		} else if (strcasecmp(command, "transform") == 0) { | ||||||
|  | 			if (++i >= argc) { | ||||||
|  | 				error = cmd_results_new(CMD_INVALID, "output", | ||||||
|  | 					"Missing transform parameter."); | ||||||
|  | 				goto fail; | ||||||
|  | 			} | ||||||
|  | 			char *value = argv[i]; | ||||||
|  | 			if (strcmp(value, "normal") == 0) { | ||||||
|  | 				output->transform = WL_OUTPUT_TRANSFORM_NORMAL; | ||||||
|  | 			} else if (strcmp(value, "90") == 0) { | ||||||
|  | 				output->transform = WL_OUTPUT_TRANSFORM_90; | ||||||
|  | 			} else if (strcmp(value, "180") == 0) { | ||||||
|  | 				output->transform = WL_OUTPUT_TRANSFORM_180; | ||||||
|  | 			} else if (strcmp(value, "270") == 0) { | ||||||
|  | 				output->transform = WL_OUTPUT_TRANSFORM_270; | ||||||
|  | 			} else if (strcmp(value, "flipped") == 0) { | ||||||
|  | 				output->transform = WL_OUTPUT_TRANSFORM_FLIPPED; | ||||||
|  | 			} else if (strcmp(value, "flipped-90") == 0) { | ||||||
|  | 				output->transform = WL_OUTPUT_TRANSFORM_FLIPPED_90; | ||||||
|  | 			} else if (strcmp(value, "flipped-180") == 0) { | ||||||
|  | 				output->transform = WL_OUTPUT_TRANSFORM_FLIPPED_180; | ||||||
|  | 			} else if (strcmp(value, "flipped-270") == 0) { | ||||||
|  | 				output->transform = WL_OUTPUT_TRANSFORM_FLIPPED_270; | ||||||
|  | 			} else { | ||||||
|  | 				error = cmd_results_new(CMD_INVALID, "output", | ||||||
|  | 					"Invalid output transform."); | ||||||
|  | 				goto fail; | ||||||
|  | 			} | ||||||
|  | 		} else if (strcasecmp(command, "background") == 0 || | ||||||
|  | 				strcasecmp(command, "bg") == 0) { | ||||||
|  | 			wordexp_t p; | ||||||
|  | 			if (++i >= argc) { | ||||||
|  | 				error = cmd_results_new(CMD_INVALID, "output", | ||||||
|  | 					"Missing background file or color specification."); | ||||||
|  | 				goto fail; | ||||||
|  | 			} | ||||||
|  | 			if (i + 1 >= argc) { | ||||||
|  | 				error = cmd_results_new(CMD_INVALID, "output", | ||||||
|  | 					"Missing background scaling mode or `solid_color`."); | ||||||
|  | 				goto fail; | ||||||
|  | 			} | ||||||
|  | 			if (strcasecmp(argv[i + 1], "solid_color") == 0) { | ||||||
|  | 				output->background = strdup(argv[argc - 2]); | ||||||
|  | 				output->background_option = strdup("solid_color"); | ||||||
|  | 			} else { | ||||||
|  | 				// argv[i+j]=bg_option
 | ||||||
|  | 				bool valid = false; | ||||||
|  | 				char *mode; | ||||||
|  | 				size_t j; | ||||||
|  | 				for (j = 0; j < (size_t) (argc - i); ++j) { | ||||||
|  | 					mode = argv[i + j]; | ||||||
|  | 					size_t n = sizeof(bg_options) / sizeof(char *); | ||||||
|  | 					for (size_t k = 0; k < n; ++k) { | ||||||
|  | 						if (strcasecmp(mode, bg_options[k]) == 0) { | ||||||
|  | 							valid = true; | ||||||
|  | 							break; | ||||||
|  | 						} | ||||||
|  | 					} | ||||||
|  | 					if (valid) { | ||||||
|  | 						break; | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 				if (!valid) { | ||||||
|  | 					error = cmd_results_new(CMD_INVALID, "output", | ||||||
|  | 						"Missing background scaling mode."); | ||||||
|  | 					goto fail; | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				char *src = join_args(argv + i, j); | ||||||
|  | 				if (wordexp(src, &p, 0) != 0 || p.we_wordv[0] == NULL) { | ||||||
|  | 					error = cmd_results_new(CMD_INVALID, "output", | ||||||
|  | 						"Invalid syntax (%s).", src); | ||||||
|  | 					goto fail; | ||||||
|  | 				} | ||||||
|  | 				free(src); | ||||||
|  | 				src = p.we_wordv[0]; | ||||||
|  | 				if (config->reading && *src != '/') { | ||||||
|  | 					char *conf = strdup(config->current_config); | ||||||
|  | 					if (conf) { | ||||||
|  | 						char *conf_path = dirname(conf); | ||||||
|  | 						src = malloc(strlen(conf_path) + strlen(src) + 2); | ||||||
|  | 						if (src) { | ||||||
|  | 							sprintf(src, "%s/%s", conf_path, p.we_wordv[0]); | ||||||
|  | 						} else { | ||||||
|  | 							sway_log(L_ERROR, | ||||||
|  | 								"Unable to allocate background source"); | ||||||
|  | 						} | ||||||
|  | 						free(conf); | ||||||
|  | 					} else { | ||||||
|  | 						sway_log(L_ERROR, | ||||||
|  | 							"Unable to allocate background source"); | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 				if (!src || access(src, F_OK) == -1) { | ||||||
|  | 					error = cmd_results_new(CMD_INVALID, "output", | ||||||
|  | 						"Background file unreadable (%s).", src); | ||||||
|  | 					wordfree(&p); | ||||||
|  | 					goto fail; | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				output->background = strdup(src); | ||||||
|  | 				output->background_option = strdup(mode); | ||||||
|  | 				if (src != p.we_wordv[0]) { | ||||||
|  | 					free(src); | ||||||
|  | 				} | ||||||
|  | 				wordfree(&p); | ||||||
|  | 
 | ||||||
|  | 				i += j; | ||||||
|  | 			} | ||||||
|  | 		} else { | ||||||
|  | 			error = cmd_results_new(CMD_INVALID, "output", | ||||||
|  | 				"Invalid output subcommand: %s.", command); | ||||||
|  | 			goto fail; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	i = list_seq_find(config->output_configs, output_name_cmp, name); | ||||||
|  | 	if (i >= 0) { | ||||||
|  | 		// merge existing config
 | ||||||
|  | 		struct output_config *oc = config->output_configs->items[i]; | ||||||
|  | 		merge_output_config(oc, output); | ||||||
|  | 		free_output_config(output); | ||||||
|  | 		output = oc; | ||||||
|  | 	} else { | ||||||
|  | 		list_add(config->output_configs, output); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	sway_log(L_DEBUG, "Config stored for output %s (enabled: %d) (%dx%d@%fHz " | ||||||
|  | 		"position %d,%d scale %d transform %d) (bg %s %s)", | ||||||
|  | 		output->name, output->enabled, output->width, output->height, | ||||||
|  | 		output->refresh_rate, output->x, output->y, output->scale, | ||||||
|  | 		output->transform, output->background, output->background_option); | ||||||
|  | 
 | ||||||
|  | 	if (output->name) { | ||||||
|  | 		// Try to find the output container and apply configuration now. If
 | ||||||
|  | 		// this is during startup then there will be no container and config
 | ||||||
|  | 		// will be applied during normal "new output" event from wlroots.
 | ||||||
|  | 		swayc_t *cont = NULL; | ||||||
|  | 		for (int i = 0; i < root_container.children->length; ++i) { | ||||||
|  | 			cont = root_container.children->items[i]; | ||||||
|  | 			if (cont->name && ((strcmp(cont->name, output->name) == 0) || | ||||||
|  | 					(strcmp(output->name, "*") == 0))) { | ||||||
|  | 				apply_output_config(output, cont); | ||||||
|  | 
 | ||||||
|  | 				if (strcmp(output->name, "*") != 0) { | ||||||
|  | 					// Stop looking if the output config isn't applicable to all
 | ||||||
|  | 					// outputs
 | ||||||
|  | 					break; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||||||
|  | 
 | ||||||
|  | fail: | ||||||
|  | 	free_output_config(output); | ||||||
|  | 	return error; | ||||||
|  | } | ||||||
| @ -0,0 +1,185 @@ | |||||||
|  | #define _XOPEN_SOURCE 700 | ||||||
|  | #include <string.h> | ||||||
|  | #include <assert.h> | ||||||
|  | #include <wlr/types/wlr_output.h> | ||||||
|  | #include <wlr/types/wlr_output_layout.h> | ||||||
|  | #include "sway/config.h" | ||||||
|  | #include "sway/output.h" | ||||||
|  | #include "log.h" | ||||||
|  | 
 | ||||||
|  | int output_name_cmp(const void *item, const void *data) { | ||||||
|  | 	const struct output_config *output = item; | ||||||
|  | 	const char *name = data; | ||||||
|  | 
 | ||||||
|  | 	return strcmp(output->name, name); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | struct output_config *new_output_config() { | ||||||
|  | 	struct output_config *oc = calloc(1, sizeof(struct output_config)); | ||||||
|  | 	if (oc == NULL) { | ||||||
|  | 		return NULL; | ||||||
|  | 	} | ||||||
|  | 	oc->enabled = -1; | ||||||
|  | 	oc->width = oc->height = -1; | ||||||
|  | 	oc->refresh_rate = -1; | ||||||
|  | 	oc->x = oc->y = -1; | ||||||
|  | 	oc->scale = -1; | ||||||
|  | 	oc->transform = -1; | ||||||
|  | 	return oc; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void merge_output_config(struct output_config *dst, struct output_config *src) { | ||||||
|  | 	if (src->name) { | ||||||
|  | 		free(dst->name); | ||||||
|  | 		dst->name = strdup(src->name); | ||||||
|  | 	} | ||||||
|  | 	if (src->enabled != -1) { | ||||||
|  | 		dst->enabled = src->enabled; | ||||||
|  | 	} | ||||||
|  | 	if (src->width != -1) { | ||||||
|  | 		dst->width = src->width; | ||||||
|  | 	} | ||||||
|  | 	if (src->height != -1) { | ||||||
|  | 		dst->height = src->height; | ||||||
|  | 	} | ||||||
|  | 	if (src->x != -1) { | ||||||
|  | 		dst->x = src->x; | ||||||
|  | 	} | ||||||
|  | 	if (src->y != -1) { | ||||||
|  | 		dst->y = src->y; | ||||||
|  | 	} | ||||||
|  | 	if (src->scale != -1) { | ||||||
|  | 		dst->scale = src->scale; | ||||||
|  | 	} | ||||||
|  | 	if (src->refresh_rate != -1) { | ||||||
|  | 		dst->refresh_rate = src->refresh_rate; | ||||||
|  | 	} | ||||||
|  | 	if (src->transform != -1) { | ||||||
|  | 		dst->transform = src->transform; | ||||||
|  | 	} | ||||||
|  | 	if (src->background) { | ||||||
|  | 		free(dst->background); | ||||||
|  | 		dst->background = strdup(src->background); | ||||||
|  | 	} | ||||||
|  | 	if (src->background_option) { | ||||||
|  | 		free(dst->background_option); | ||||||
|  | 		dst->background_option = strdup(src->background_option); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void set_mode(struct wlr_output *output, int width, int height, | ||||||
|  | 		float refresh_rate) { | ||||||
|  | 	int mhz = (int)(refresh_rate * 1000); | ||||||
|  | 	if (wl_list_empty(&output->modes)) { | ||||||
|  | 		sway_log(L_DEBUG, "Assigning custom mode to %s", output->name); | ||||||
|  | 		wlr_output_set_custom_mode(output, width, height, mhz); | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	struct wlr_output_mode *mode, *best = NULL; | ||||||
|  | 	wl_list_for_each(mode, &output->modes, link) { | ||||||
|  | 		if (mode->width == width && mode->height == height) { | ||||||
|  | 			if (mode->refresh == mhz) { | ||||||
|  | 				best = mode; | ||||||
|  | 				break; | ||||||
|  | 			} | ||||||
|  | 			best = mode; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	if (!best) { | ||||||
|  | 		sway_log(L_ERROR, "Configured mode for %s not available", output->name); | ||||||
|  | 	} else { | ||||||
|  | 		sway_log(L_DEBUG, "Assigning configured mode to %s", output->name); | ||||||
|  | 		wlr_output_set_mode(output, best); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void apply_output_config(struct output_config *oc, swayc_t *output) { | ||||||
|  | 	assert(output->type == C_OUTPUT); | ||||||
|  | 
 | ||||||
|  | 	struct wlr_output *wlr_output = output->sway_output->wlr_output; | ||||||
|  | 	if (oc && oc->enabled == 0) { | ||||||
|  | 		wlr_output_layout_remove(root_container.sway_root->output_layout, | ||||||
|  | 			wlr_output); | ||||||
|  | 		destroy_output(output); | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (oc && oc->width > 0 && oc->height > 0) { | ||||||
|  | 		sway_log(L_DEBUG, "Set %s mode to %dx%d (%f GHz)", oc->name, oc->width, | ||||||
|  | 			oc->height, oc->refresh_rate); | ||||||
|  | 		set_mode(wlr_output, oc->width, oc->height, oc->refresh_rate); | ||||||
|  | 	} | ||||||
|  | 	if (oc && oc->scale > 0) { | ||||||
|  | 		sway_log(L_DEBUG, "Set %s scale to %d", oc->name, oc->scale); | ||||||
|  | 		wlr_output_set_scale(wlr_output, oc->scale); | ||||||
|  | 	} | ||||||
|  | 	if (oc && oc->transform >= 0) { | ||||||
|  | 		sway_log(L_DEBUG, "Set %s transform to %d", oc->name, oc->transform); | ||||||
|  | 		wlr_output_set_transform(wlr_output, oc->transform); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// Find position for it
 | ||||||
|  | 	if (oc && (oc->x != -1 || oc->y != -1)) { | ||||||
|  | 		sway_log(L_DEBUG, "Set %s position to %d, %d", oc->name, oc->x, oc->y); | ||||||
|  | 		wlr_output_layout_add(root_container.sway_root->output_layout, | ||||||
|  | 			wlr_output, oc->x, oc->y); | ||||||
|  | 	} else { | ||||||
|  | 		wlr_output_layout_add_auto(root_container.sway_root->output_layout, | ||||||
|  | 			wlr_output); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (!oc || !oc->background) { | ||||||
|  | 		// Look for a * config for background
 | ||||||
|  | 		int i = list_seq_find(config->output_configs, output_name_cmp, "*"); | ||||||
|  | 		if (i >= 0) { | ||||||
|  | 			oc = config->output_configs->items[i]; | ||||||
|  | 		} else { | ||||||
|  | 			oc = NULL; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	int output_i; | ||||||
|  | 	for (output_i = 0; output_i < root_container.children->length; ++output_i) { | ||||||
|  | 		if (root_container.children->items[output_i] == output) { | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (oc && oc->background) { | ||||||
|  | 		// TODO swaybg
 | ||||||
|  | 		/*if (output->bg_pid != 0) {
 | ||||||
|  | 			terminate_swaybg(output->bg_pid); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		sway_log(L_DEBUG, "Setting background for output %d to %s", output_i, oc->background); | ||||||
|  | 
 | ||||||
|  | 		size_t bufsize = 12; | ||||||
|  | 		char output_id[bufsize]; | ||||||
|  | 		snprintf(output_id, bufsize, "%d", output_i); | ||||||
|  | 		output_id[bufsize-1] = 0; | ||||||
|  | 
 | ||||||
|  | 		char *const cmd[] = { | ||||||
|  | 			"swaybg", | ||||||
|  | 			output_id, | ||||||
|  | 			oc->background, | ||||||
|  | 			oc->background_option, | ||||||
|  | 			NULL, | ||||||
|  | 		}; | ||||||
|  | 
 | ||||||
|  | 		output->bg_pid = fork(); | ||||||
|  | 		if (output->bg_pid == 0) { | ||||||
|  | 			execvp(cmd[0], cmd); | ||||||
|  | 		}*/ | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void free_output_config(struct output_config *oc) { | ||||||
|  | 	if (!oc) { | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 	free(oc->name); | ||||||
|  | 	free(oc->background); | ||||||
|  | 	free(oc->background_option); | ||||||
|  | 	free(oc); | ||||||
|  | } | ||||||
					Loading…
					
					
				
		Reference in new issue