aboutsummaryrefslogtreecommitdiffstats
path: root/sway/commands/output.c
diff options
context:
space:
mode:
authorLibravatar Brian Ashworth <bosrsf04@gmail.com>2018-06-02 21:33:16 -0400
committerLibravatar Brian Ashworth <bosrsf04@gmail.com>2018-06-03 10:26:06 -0400
commit5ea4a4d3eec897b915003ad7fc2b2e274d1a59c1 (patch)
tree8d077f70c7bc462f1987e8d57003a2b11de718ca /sway/commands/output.c
parentMerge pull request #2093 from emersion/damage-debug (diff)
downloadsway-5ea4a4d3eec897b915003ad7fc2b2e274d1a59c1.tar.gz
sway-5ea4a4d3eec897b915003ad7fc2b2e274d1a59c1.tar.zst
sway-5ea4a4d3eec897b915003ad7fc2b2e274d1a59c1.zip
Refactor cmd_output to use config_subcommand
Diffstat (limited to 'sway/commands/output.c')
-rw-r--r--sway/commands/output.c296
1 files changed, 29 insertions, 267 deletions
diff --git a/sway/commands/output.c b/sway/commands/output.c
index e8881f77..a7d325ec 100644
--- a/sway/commands/output.c
+++ b/sway/commands/output.c
@@ -1,254 +1,24 @@
1#define _XOPEN_SOURCE 500
2#include <ctype.h>
3#include <libgen.h>
4#include <stdlib.h>
5#include <string.h>
6#include <strings.h>
7#include <unistd.h>
8#include <wordexp.h>
9#include "sway/commands.h" 1#include "sway/commands.h"
10#include "sway/config.h" 2#include "sway/config.h"
11#include "list.h" 3#include "list.h"
12#include "log.h" 4#include "log.h"
13#include "stringop.h"
14 5
15static char *bg_options[] = { 6// must be in order for the bsearch
16 "stretch", 7static struct cmd_handler output_handlers[] = {
17 "center", 8 { "background", output_cmd_background },
18 "fill", 9 { "bg", output_cmd_background },
19 "fit", 10 { "disable", output_cmd_disable },
20 "tile", 11 { "dpms", output_cmd_dpms },
12 { "enable", output_cmd_enable },
13 { "mode", output_cmd_mode },
14 { "pos", output_cmd_position },
15 { "position", output_cmd_position },
16 { "res", output_cmd_mode },
17 { "resolution", output_cmd_mode },
18 { "scale", output_cmd_scale },
19 { "transform", output_cmd_transform },
21}; 20};
22 21
23static struct cmd_results *cmd_output_dpms(struct output_config *output,
24 int *i, int argc, char **argv) {
25
26 if (++*i >= argc) {
27 return cmd_results_new(CMD_INVALID, "output", "Missing dpms argument.");
28 }
29
30 char *value = argv[*i];
31 if (strcmp(value, "on") == 0) {
32 output->dpms_state = DPMS_ON;
33 } else if (strcmp(value, "off") == 0) {
34 output->dpms_state = DPMS_OFF;
35 } else {
36 return cmd_results_new(CMD_INVALID, "output",
37 "Invalid dpms state, valid states are on/off.");
38 }
39 return NULL;
40}
41
42static struct cmd_results *cmd_output_mode(struct output_config *output,
43 int *i, int argc, char **argv) {
44 if (++*i >= argc) {
45 return cmd_results_new(CMD_INVALID, "output", "Missing mode argument.");
46 }
47
48 char *end;
49 output->width = strtol(argv[*i], &end, 10);
50 if (*end) {
51 // Format is 1234x4321
52 if (*end != 'x') {
53 return cmd_results_new(CMD_INVALID, "output",
54 "Invalid mode width.");
55 }
56 ++end;
57 output->height = strtol(end, &end, 10);
58 if (*end) {
59 if (*end != '@') {
60 return cmd_results_new(CMD_INVALID, "output",
61 "Invalid mode height.");
62 }
63 ++end;
64 output->refresh_rate = strtof(end, &end);
65 if (strcasecmp("Hz", end) != 0) {
66 return cmd_results_new(CMD_INVALID, "output",
67 "Invalid mode refresh rate.");
68 }
69 }
70 } else {
71 // Format is 1234 4321
72 if (++*i >= argc) {
73 return cmd_results_new(CMD_INVALID, "output",
74 "Missing mode argument (height).");
75 }
76 output->height = strtol(argv[*i], &end, 10);
77 if (*end) {
78 return cmd_results_new(CMD_INVALID, "output",
79 "Invalid mode height.");
80 }
81 }
82
83 return NULL;
84}
85
86static struct cmd_results *cmd_output_position(struct output_config *output,
87 int *i, int argc, char **argv) {
88 if (++*i >= argc) {
89 return cmd_results_new(CMD_INVALID, "output",
90 "Missing position argument.");
91 }
92
93 char *end;
94 output->x = strtol(argv[*i], &end, 10);
95 if (*end) {
96 // Format is 1234,4321
97 if (*end != ',') {
98 return cmd_results_new(CMD_INVALID, "output",
99 "Invalid position x.");
100 }
101 ++end;
102 output->y = strtol(end, &end, 10);
103 if (*end) {
104 return cmd_results_new(CMD_INVALID, "output",
105 "Invalid position y.");
106 }
107 } else {
108 // Format is 1234 4321 (legacy)
109 if (++*i >= argc) {
110 return cmd_results_new(CMD_INVALID, "output",
111 "Missing position argument (y).");
112 }
113 output->y = strtol(argv[*i], &end, 10);
114 if (*end) {
115 return cmd_results_new(CMD_INVALID, "output",
116 "Invalid position y.");
117 }
118 }
119
120 return NULL;
121}
122
123static struct cmd_results *cmd_output_scale(struct output_config *output,
124 int *i, int argc, char **argv) {
125 if (++*i >= argc) {
126 return cmd_results_new(CMD_INVALID, "output",
127 "Missing scale argument.");
128 }
129
130 char *end;
131 output->scale = strtof(argv[*i], &end);
132 if (*end) {
133 return cmd_results_new(CMD_INVALID, "output", "Invalid scale.");
134 }
135
136 return NULL;
137}
138
139static struct cmd_results *cmd_output_transform(struct output_config *output,
140 int *i, int argc, char **argv) {
141 if (++*i >= argc) {
142 return cmd_results_new(CMD_INVALID, "output",
143 "Missing transform argument.");
144 }
145
146 char *value = argv[*i];
147 if (strcmp(value, "normal") == 0) {
148 output->transform = WL_OUTPUT_TRANSFORM_NORMAL;
149 } else if (strcmp(value, "90") == 0) {
150 output->transform = WL_OUTPUT_TRANSFORM_90;
151 } else if (strcmp(value, "180") == 0) {
152 output->transform = WL_OUTPUT_TRANSFORM_180;
153 } else if (strcmp(value, "270") == 0) {
154 output->transform = WL_OUTPUT_TRANSFORM_270;
155 } else if (strcmp(value, "flipped") == 0) {
156 output->transform = WL_OUTPUT_TRANSFORM_FLIPPED;
157 } else if (strcmp(value, "flipped-90") == 0) {
158 output->transform = WL_OUTPUT_TRANSFORM_FLIPPED_90;
159 } else if (strcmp(value, "flipped-180") == 0) {
160 output->transform = WL_OUTPUT_TRANSFORM_FLIPPED_180;
161 } else if (strcmp(value, "flipped-270") == 0) {
162 output->transform = WL_OUTPUT_TRANSFORM_FLIPPED_270;
163 } else {
164 return cmd_results_new(CMD_INVALID, "output",
165 "Invalid output transform.");
166 }
167
168 return NULL;
169}
170
171static struct cmd_results *cmd_output_background(struct output_config *output,
172 int *i, int argc, char **argv) {
173 if (++*i >= argc) {
174 return cmd_results_new(CMD_INVALID, "output",
175 "Missing background file or color specification.");
176 }
177 const char *background = argv[*i];
178 if (*i + 1 >= argc) {
179 return cmd_results_new(CMD_INVALID, "output",
180 "Missing background scaling mode or `solid_color`.");
181 }
182 const char *background_option = argv[*i];
183
184 if (strcasecmp(background_option, "solid_color") == 0) {
185 output->background = strdup(background);
186 output->background_option = strdup("solid_color");
187 } else {
188 bool valid = false;
189 char *mode;
190 size_t j;
191 for (j = 0; j < (size_t)(argc - *i); ++j) {
192 mode = argv[*i + j];
193 size_t n = sizeof(bg_options) / sizeof(char *);
194 for (size_t k = 0; k < n; ++k) {
195 if (strcasecmp(mode, bg_options[k]) == 0) {
196 valid = true;
197 break;
198 }
199 }
200 if (valid) {
201 break;
202 }
203 }
204 if (!valid) {
205 return cmd_results_new(CMD_INVALID, "output",
206 "Missing background scaling mode.");
207 }
208
209 wordexp_t p;
210 char *src = join_args(argv + *i, j);
211 if (wordexp(src, &p, 0) != 0 || p.we_wordv[0] == NULL) {
212 return cmd_results_new(CMD_INVALID, "output",
213 "Invalid syntax (%s).", src);
214 }
215 free(src);
216 src = p.we_wordv[0];
217 if (config->reading && *src != '/') {
218 char *conf = strdup(config->current_config);
219 if (conf) {
220 char *conf_path = dirname(conf);
221 src = malloc(strlen(conf_path) + strlen(src) + 2);
222 if (src) {
223 sprintf(src, "%s/%s", conf_path, p.we_wordv[0]);
224 } else {
225 wlr_log(L_ERROR,
226 "Unable to allocate background source");
227 }
228 free(conf);
229 } else {
230 wlr_log(L_ERROR, "Unable to allocate background source");
231 }
232 }
233 if (!src || access(src, F_OK) == -1) {
234 wordfree(&p);
235 return cmd_results_new(CMD_INVALID, "output",
236 "Background file unreadable (%s).", src);
237 }
238
239 output->background = strdup(src);
240 output->background_option = strdup(mode);
241 if (src != p.we_wordv[0]) {
242 free(src);
243 }
244 wordfree(&p);
245
246 *i += j;
247 }
248
249 return NULL;
250}
251
252struct cmd_results *cmd_output(int argc, char **argv) { 22struct cmd_results *cmd_output(int argc, char **argv) {
253 struct cmd_results *error = checkarg(argc, "output", EXPECTED_AT_LEAST, 1); 23 struct cmd_results *error = checkarg(argc, "output", EXPECTED_AT_LEAST, 1);
254 if (error != NULL) { 24 if (error != NULL) {
@@ -260,40 +30,31 @@ struct cmd_results *cmd_output(int argc, char **argv) {
260 wlr_log(L_ERROR, "Failed to allocate output config"); 30 wlr_log(L_ERROR, "Failed to allocate output config");
261 return NULL; 31 return NULL;
262 } 32 }
33 argc--; argv++;
263 34
264 for (int i = 1; i < argc; ++i) { 35 config->handler_context.output_config = output;
265 const char *command = argv[i];
266 36
267 if (strcasecmp(command, "enable") == 0) { 37 while (argc > 0) {
268 output->enabled = 1; 38 if (find_handler(*argv, output_handlers, sizeof(output_handlers))) {
269 } else if (strcasecmp(command, "disable") == 0) { 39 error = config_subcommand(argv, argc, output_handlers,
270 output->enabled = 0; 40 sizeof(output_handlers));
271 } else if (strcasecmp(command, "mode") == 0 ||
272 strcasecmp(command, "resolution") == 0 ||
273 strcasecmp(command, "res") == 0) {
274 error = cmd_output_mode(output, &i, argc, argv);
275 } else if (strcasecmp(command, "position") == 0 ||
276 strcasecmp(command, "pos") == 0) {
277 error = cmd_output_position(output, &i, argc, argv);
278 } else if (strcasecmp(command, "scale") == 0) {
279 error = cmd_output_scale(output, &i, argc, argv);
280 } else if (strcasecmp(command, "transform") == 0) {
281 error = cmd_output_transform(output, &i, argc, argv);
282 } else if (strcasecmp(command, "background") == 0 ||
283 strcasecmp(command, "bg") == 0) {
284 error = cmd_output_background(output, &i, argc, argv);
285 } else if (strcasecmp(command, "dpms") == 0) {
286 error = cmd_output_dpms(output, &i, argc, argv);
287 } else { 41 } else {
288 error = cmd_results_new(CMD_INVALID, "output", 42 error = cmd_results_new(CMD_INVALID, "output",
289 "Invalid output subcommand: %s.", command); 43 "Invalid output subcommand: %s.", *argv);
290 } 44 }
291 45
292 if (error != NULL) { 46 if (error != NULL) {
293 goto fail; 47 goto fail;
294 } 48 }
49
50 argc = config->handler_context.leftovers.argc;
51 argv = config->handler_context.leftovers.argv;
295 } 52 }
296 53
54 config->handler_context.output_config = NULL;
55 config->handler_context.leftovers.argc = 0;
56 config->handler_context.leftovers.argv = NULL;
57
297 int i = list_seq_find(config->output_configs, output_name_cmp, output->name); 58 int i = list_seq_find(config->output_configs, output_name_cmp, output->name);
298 if (i >= 0) { 59 if (i >= 0) {
299 // Merge existing config 60 // Merge existing config
@@ -338,6 +99,7 @@ struct cmd_results *cmd_output(int argc, char **argv) {
338 return cmd_results_new(CMD_SUCCESS, NULL, NULL); 99 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
339 100
340fail: 101fail:
102 config->handler_context.output_config = NULL;
341 free_output_config(output); 103 free_output_config(output);
342 return error; 104 return error;
343} 105}