aboutsummaryrefslogtreecommitdiffstats
path: root/sway/commands/output.c
diff options
context:
space:
mode:
authorLibravatar emersion <contact@emersion.fr>2017-12-27 21:23:30 +0100
committerLibravatar emersion <contact@emersion.fr>2017-12-27 21:23:30 +0100
commit21c61f1c0909b613471f18dd41e984c54540aca8 (patch)
tree9352fe3a49839c0e58fa34ad0f83f7b75970647f /sway/commands/output.c
parentMerge pull request #1535 from martinetd/libinput (diff)
downloadsway-21c61f1c0909b613471f18dd41e984c54540aca8.tar.gz
sway-21c61f1c0909b613471f18dd41e984c54540aca8.tar.zst
sway-21c61f1c0909b613471f18dd41e984c54540aca8.zip
Refactor output command, add output enable
Diffstat (limited to 'sway/commands/output.c')
-rw-r--r--sway/commands/output.c441
1 files changed, 224 insertions, 217 deletions
diff --git a/sway/commands/output.c b/sway/commands/output.c
index 7988e3e4..8cc74bcc 100644
--- a/sway/commands/output.c
+++ b/sway/commands/output.c
@@ -20,253 +20,260 @@ static char *bg_options[] = {
20 "tile", 20 "tile",
21}; 21};
22 22
23static struct cmd_results *cmd_output_mode(struct output_config *output,
24 int *i, int argc, char **argv) {
25 if (++*i >= argc) {
26 return cmd_results_new(CMD_INVALID, "output", "Missing mode argument.");
27 }
28
29 char *end;
30 output->width = strtol(argv[*i], &end, 10);
31 if (*end) {
32 // Format is 1234x4321
33 if (*end != 'x') {
34 return cmd_results_new(CMD_INVALID, "output",
35 "Invalid mode width.");
36 }
37 ++end;
38 output->height = strtol(end, &end, 10);
39 if (*end) {
40 if (*end != '@') {
41 return cmd_results_new(CMD_INVALID, "output",
42 "Invalid mode height.");
43 }
44 ++end;
45 output->refresh_rate = strtof(end, &end);
46 if (strcasecmp("Hz", end) != 0) {
47 return cmd_results_new(CMD_INVALID, "output",
48 "Invalid mode refresh rate.");
49 }
50 }
51 } else {
52 // Format is 1234 4321
53 if (++*i >= argc) {
54 return cmd_results_new(CMD_INVALID, "output",
55 "Missing mode argument (height).");
56 }
57 output->height = strtol(argv[*i], &end, 10);
58 if (*end) {
59 return cmd_results_new(CMD_INVALID, "output",
60 "Invalid mode height.");
61 }
62 }
63
64 return NULL;
65}
66
67static struct cmd_results *cmd_output_position(struct output_config *output,
68 int *i, int argc, char **argv) {
69 if (++*i >= argc) {
70 return cmd_results_new(CMD_INVALID, "output",
71 "Missing position argument.");
72 }
73
74 char *end;
75 output->x = strtol(argv[*i], &end, 10);
76 if (*end) {
77 // Format is 1234,4321
78 if (*end != ',') {
79 return cmd_results_new(CMD_INVALID, "output",
80 "Invalid position x.");
81 }
82 ++end;
83 output->y = strtol(end, &end, 10);
84 if (*end) {
85 return cmd_results_new(CMD_INVALID, "output",
86 "Invalid position y.");
87 }
88 } else {
89 // Format is 1234 4321 (legacy)
90 if (++*i >= argc) {
91 return cmd_results_new(CMD_INVALID, "output",
92 "Missing position argument (y).");
93 }
94 output->y = strtol(argv[*i], &end, 10);
95 if (*end) {
96 return cmd_results_new(CMD_INVALID, "output",
97 "Invalid position y.");
98 }
99 }
100
101 return NULL;
102}
103
104static struct cmd_results *cmd_output_scale(struct output_config *output,
105 int *i, int argc, char **argv) {
106 if (++*i >= argc) {
107 return cmd_results_new(CMD_INVALID, "output",
108 "Missing scale argument.");
109 }
110
111 char *end;
112 output->scale = strtof(argv[*i], &end);
113 if (*end) {
114 return cmd_results_new(CMD_INVALID, "output", "Invalid scale.");
115 }
116
117 return NULL;
118}
119
120static struct cmd_results *cmd_output_transform(struct output_config *output,
121 int *i, int argc, char **argv) {
122 if (++*i >= argc) {
123 return cmd_results_new(CMD_INVALID, "output",
124 "Missing transform argument.");
125 }
126
127 char *value = argv[*i];
128 if (strcmp(value, "normal") == 0) {
129 output->transform = WL_OUTPUT_TRANSFORM_NORMAL;
130 } else if (strcmp(value, "90") == 0) {
131 output->transform = WL_OUTPUT_TRANSFORM_90;
132 } else if (strcmp(value, "180") == 0) {
133 output->transform = WL_OUTPUT_TRANSFORM_180;
134 } else if (strcmp(value, "270") == 0) {
135 output->transform = WL_OUTPUT_TRANSFORM_270;
136 } else if (strcmp(value, "flipped") == 0) {
137 output->transform = WL_OUTPUT_TRANSFORM_FLIPPED;
138 } else if (strcmp(value, "flipped-90") == 0) {
139 output->transform = WL_OUTPUT_TRANSFORM_FLIPPED_90;
140 } else if (strcmp(value, "flipped-180") == 0) {
141 output->transform = WL_OUTPUT_TRANSFORM_FLIPPED_180;
142 } else if (strcmp(value, "flipped-270") == 0) {
143 output->transform = WL_OUTPUT_TRANSFORM_FLIPPED_270;
144 } else {
145 return cmd_results_new(CMD_INVALID, "output",
146 "Invalid output transform.");
147 }
148
149 return NULL;
150}
151
152static struct cmd_results *cmd_output_background(struct output_config *output,
153 int *i, int argc, char **argv) {
154 if (++*i >= argc) {
155 return cmd_results_new(CMD_INVALID, "output",
156 "Missing background file or color specification.");
157 }
158 const char *background = argv[*i];
159 if (*i + 1 >= argc) {
160 return cmd_results_new(CMD_INVALID, "output",
161 "Missing background scaling mode or `solid_color`.");
162 }
163 const char *background_option = argv[*i];
164
165 if (strcasecmp(background_option, "solid_color") == 0) {
166 output->background = strdup(background);
167 output->background_option = strdup("solid_color");
168 } else {
169 bool valid = false;
170 char *mode;
171 size_t j;
172 for (j = 0; j < (size_t)(argc - *i); ++j) {
173 mode = argv[*i + j];
174 size_t n = sizeof(bg_options) / sizeof(char *);
175 for (size_t k = 0; k < n; ++k) {
176 if (strcasecmp(mode, bg_options[k]) == 0) {
177 valid = true;
178 break;
179 }
180 }
181 if (valid) {
182 break;
183 }
184 }
185 if (!valid) {
186 return cmd_results_new(CMD_INVALID, "output",
187 "Missing background scaling mode.");
188 }
189
190 wordexp_t p;
191 char *src = join_args(argv + *i - 1, j);
192 if (wordexp(src, &p, 0) != 0 || p.we_wordv[0] == NULL) {
193 return cmd_results_new(CMD_INVALID, "output",
194 "Invalid syntax (%s).", src);
195 }
196 free(src);
197 src = p.we_wordv[0];
198 if (config->reading && *src != '/') {
199 char *conf = strdup(config->current_config);
200 if (conf) {
201 char *conf_path = dirname(conf);
202 src = malloc(strlen(conf_path) + strlen(src) + 2);
203 if (src) {
204 sprintf(src, "%s/%s", conf_path, p.we_wordv[0]);
205 } else {
206 sway_log(L_ERROR,
207 "Unable to allocate background source");
208 }
209 free(conf);
210 } else {
211 sway_log(L_ERROR, "Unable to allocate background source");
212 }
213 }
214 if (!src || access(src, F_OK) == -1) {
215 wordfree(&p);
216 return cmd_results_new(CMD_INVALID, "output",
217 "Background file unreadable (%s).", src);
218 }
219
220 output->background = strdup(src);
221 output->background_option = strdup(mode);
222 if (src != p.we_wordv[0]) {
223 free(src);
224 }
225 wordfree(&p);
226
227 *i += j;
228 }
229
230 return NULL;
231}
232
23struct cmd_results *cmd_output(int argc, char **argv) { 233struct cmd_results *cmd_output(int argc, char **argv) {
24 struct cmd_results *error = NULL; 234 struct cmd_results *error = NULL;
25 if ((error = checkarg(argc, "output", EXPECTED_AT_LEAST, 1))) { 235 if ((error = checkarg(argc, "output", EXPECTED_AT_LEAST, 1))) {
26 return error; 236 return error;
27 } 237 }
28 const char *name = argv[0];
29 238
30 struct output_config *output = new_output_config(); 239 struct output_config *output = new_output_config(argv[0]);
31 if (!output) { 240 if (!output) {
32 sway_log(L_ERROR, "Failed to allocate output config"); 241 sway_log(L_ERROR, "Failed to allocate output config");
33 return NULL; 242 return NULL;
34 } 243 }
35 output->name = strdup(name);
36 244
37 int i; 245 for (int i = 1; i < argc; ++i) {
38 for (i = 1; i < argc; ++i) {
39 const char *command = argv[i]; 246 const char *command = argv[i];
40 247
41 if (strcasecmp(command, "disable") == 0) { 248 if (strcasecmp(command, "enable") == 0) {
249 output->enabled = 1;
250 } else if (strcasecmp(command, "disable") == 0) {
42 output->enabled = 0; 251 output->enabled = 0;
43 } else if (strcasecmp(command, "mode") == 0 || 252 } else if (strcasecmp(command, "mode") == 0 ||
44 strcasecmp(command, "resolution") == 0 || 253 strcasecmp(command, "resolution") == 0 ||
45 strcasecmp(command, "res") == 0) { 254 strcasecmp(command, "res") == 0) {
46 if (++i >= argc) { 255 error = cmd_output_mode(output, &i, argc, argv);
47 error = cmd_results_new(CMD_INVALID, "output",
48 "Missing mode argument.");
49 goto fail;
50 }
51
52 int width = -1, height = -1;
53 float refresh_rate = -1;
54
55 char *end;
56 width = strtol(argv[i], &end, 10);
57 if (*end) {
58 // Format is 1234x4321
59 if (*end != 'x') {
60 error = cmd_results_new(CMD_INVALID, "output",
61 "Invalid mode width.");
62 goto fail;
63 }
64 ++end;
65 height = strtol(end, &end, 10);
66 if (*end) {
67 if (*end != '@') {
68 error = cmd_results_new(CMD_INVALID, "output",
69 "Invalid mode height.");
70 goto fail;
71 }
72 ++end;
73 refresh_rate = strtof(end, &end);
74 if (strcasecmp("Hz", end) != 0) {
75 error = cmd_results_new(CMD_INVALID, "output",
76 "Invalid mode refresh rate.");
77 goto fail;
78 }
79 }
80 } else {
81 // Format is 1234 4321
82 if (++i >= argc) {
83 error = cmd_results_new(CMD_INVALID, "output",
84 "Missing mode argument (height).");
85 goto fail;
86 }
87 height = strtol(argv[i], &end, 10);
88 if (*end) {
89 error = cmd_results_new(CMD_INVALID, "output",
90 "Invalid mode height.");
91 goto fail;
92 }
93 }
94 output->width = width;
95 output->height = height;
96 output->refresh_rate = refresh_rate;
97 } else if (strcasecmp(command, "position") == 0 || 256 } else if (strcasecmp(command, "position") == 0 ||
98 strcasecmp(command, "pos") == 0) { 257 strcasecmp(command, "pos") == 0) {
99 if (++i >= argc) { 258 error = cmd_output_position(output, &i, argc, argv);
100 error = cmd_results_new(CMD_INVALID, "output",
101 "Missing position argument.");
102 goto fail;
103 }
104
105 int x = -1, y = -1;
106
107 char *end;
108 x = strtol(argv[i], &end, 10);
109 if (*end) {
110 // Format is 1234,4321
111 if (*end != ',') {
112 error = cmd_results_new(CMD_INVALID, "output",
113 "Invalid position x.");
114 goto fail;
115 }
116 ++end;
117 y = strtol(end, &end, 10);
118 if (*end) {
119 error = cmd_results_new(CMD_INVALID, "output",
120 "Invalid position y.");
121 goto fail;
122 }
123 } else {
124 // Format is 1234 4321 (legacy)
125 if (++i >= argc) {
126 error = cmd_results_new(CMD_INVALID, "output",
127 "Missing position argument (y).");
128 goto fail;
129 }
130 y = strtol(argv[i], &end, 10);
131 if (*end) {
132 error = cmd_results_new(CMD_INVALID, "output",
133 "Invalid position y.");
134 goto fail;
135 }
136 }
137
138 output->x = x;
139 output->y = y;
140 } else if (strcasecmp(command, "scale") == 0) { 259 } else if (strcasecmp(command, "scale") == 0) {
141 if (++i >= argc) { 260 error = cmd_output_scale(output, &i, argc, argv);
142 error = cmd_results_new(CMD_INVALID, "output",
143 "Missing scale parameter.");
144 goto fail;
145 }
146 char *end;
147 output->scale = strtof(argv[i], &end);
148 if (*end) {
149 error = cmd_results_new(CMD_INVALID, "output",
150 "Invalid scale.");
151 goto fail;
152 }
153 } else if (strcasecmp(command, "transform") == 0) { 261 } else if (strcasecmp(command, "transform") == 0) {
154 if (++i >= argc) { 262 error = cmd_output_transform(output, &i, argc, argv);
155 error = cmd_results_new(CMD_INVALID, "output",
156 "Missing transform parameter.");
157 goto fail;
158 }
159 char *value = argv[i];
160 if (strcmp(value, "normal") == 0) {
161 output->transform = WL_OUTPUT_TRANSFORM_NORMAL;
162 } else if (strcmp(value, "90") == 0) {
163 output->transform = WL_OUTPUT_TRANSFORM_90;
164 } else if (strcmp(value, "180") == 0) {
165 output->transform = WL_OUTPUT_TRANSFORM_180;
166 } else if (strcmp(value, "270") == 0) {
167 output->transform = WL_OUTPUT_TRANSFORM_270;
168 } else if (strcmp(value, "flipped") == 0) {
169 output->transform = WL_OUTPUT_TRANSFORM_FLIPPED;
170 } else if (strcmp(value, "flipped-90") == 0) {
171 output->transform = WL_OUTPUT_TRANSFORM_FLIPPED_90;
172 } else if (strcmp(value, "flipped-180") == 0) {
173 output->transform = WL_OUTPUT_TRANSFORM_FLIPPED_180;
174 } else if (strcmp(value, "flipped-270") == 0) {
175 output->transform = WL_OUTPUT_TRANSFORM_FLIPPED_270;
176 } else {
177 error = cmd_results_new(CMD_INVALID, "output",
178 "Invalid output transform.");
179 goto fail;
180 }
181 } else if (strcasecmp(command, "background") == 0 || 263 } else if (strcasecmp(command, "background") == 0 ||
182 strcasecmp(command, "bg") == 0) { 264 strcasecmp(command, "bg") == 0) {
183 wordexp_t p; 265 error = cmd_output_background(output, &i, argc, argv);
184 if (++i >= argc) {
185 error = cmd_results_new(CMD_INVALID, "output",
186 "Missing background file or color specification.");
187 goto fail;
188 }
189 if (i + 1 >= argc) {
190 error = cmd_results_new(CMD_INVALID, "output",
191 "Missing background scaling mode or `solid_color`.");
192 goto fail;
193 }
194 if (strcasecmp(argv[i + 1], "solid_color") == 0) {
195 output->background = strdup(argv[argc - 2]);
196 output->background_option = strdup("solid_color");
197 } else {
198 // argv[i+j]=bg_option
199 bool valid = false;
200 char *mode;
201 size_t j;
202 for (j = 0; j < (size_t) (argc - i); ++j) {
203 mode = argv[i + j];
204 size_t n = sizeof(bg_options) / sizeof(char *);
205 for (size_t k = 0; k < n; ++k) {
206 if (strcasecmp(mode, bg_options[k]) == 0) {
207 valid = true;
208 break;
209 }
210 }
211 if (valid) {
212 break;
213 }
214 }
215 if (!valid) {
216 error = cmd_results_new(CMD_INVALID, "output",
217 "Missing background scaling mode.");
218 goto fail;
219 }
220
221 char *src = join_args(argv + i, j);
222 if (wordexp(src, &p, 0) != 0 || p.we_wordv[0] == NULL) {
223 error = cmd_results_new(CMD_INVALID, "output",
224 "Invalid syntax (%s).", src);
225 goto fail;
226 }
227 free(src);
228 src = p.we_wordv[0];
229 if (config->reading && *src != '/') {
230 char *conf = strdup(config->current_config);
231 if (conf) {
232 char *conf_path = dirname(conf);
233 src = malloc(strlen(conf_path) + strlen(src) + 2);
234 if (src) {
235 sprintf(src, "%s/%s", conf_path, p.we_wordv[0]);
236 } else {
237 sway_log(L_ERROR,
238 "Unable to allocate background source");
239 }
240 free(conf);
241 } else {
242 sway_log(L_ERROR,
243 "Unable to allocate background source");
244 }
245 }
246 if (!src || access(src, F_OK) == -1) {
247 error = cmd_results_new(CMD_INVALID, "output",
248 "Background file unreadable (%s).", src);
249 wordfree(&p);
250 goto fail;
251 }
252
253 output->background = strdup(src);
254 output->background_option = strdup(mode);
255 if (src != p.we_wordv[0]) {
256 free(src);
257 }
258 wordfree(&p);
259
260 i += j;
261 }
262 } else { 266 } else {
263 error = cmd_results_new(CMD_INVALID, "output", 267 error = cmd_results_new(CMD_INVALID, "output",
264 "Invalid output subcommand: %s.", command); 268 "Invalid output subcommand: %s.", command);
269 }
270
271 if (error != NULL) {
265 goto fail; 272 goto fail;
266 } 273 }
267 } 274 }
268 275
269 i = list_seq_find(config->output_configs, output_name_cmp, name); 276 int i = list_seq_find(config->output_configs, output_name_cmp, output->name);
270 if (i >= 0) { 277 if (i >= 0) {
271 // merge existing config 278 // merge existing config
272 struct output_config *oc = config->output_configs->items[i]; 279 struct output_config *oc = config->output_configs->items[i];