aboutsummaryrefslogtreecommitdiffstats
path: root/sway/config/output.c
diff options
context:
space:
mode:
Diffstat (limited to 'sway/config/output.c')
-rw-r--r--sway/config/output.c172
1 files changed, 145 insertions, 27 deletions
diff --git a/sway/config/output.c b/sway/config/output.c
index 648ded27..504c48c6 100644
--- a/sway/config/output.c
+++ b/sway/config/output.c
@@ -45,10 +45,6 @@ struct output_config *new_output_config(const char *name) {
45} 45}
46 46
47void merge_output_config(struct output_config *dst, struct output_config *src) { 47void merge_output_config(struct output_config *dst, struct output_config *src) {
48 if (src->name) {
49 free(dst->name);
50 dst->name = strdup(src->name);
51 }
52 if (src->enabled != -1) { 48 if (src->enabled != -1) {
53 dst->enabled = src->enabled; 49 dst->enabled = src->enabled;
54 } 50 }
@@ -86,11 +82,61 @@ void merge_output_config(struct output_config *dst, struct output_config *src) {
86 } 82 }
87} 83}
88 84
85static void merge_wildcard_on_all(struct output_config *wildcard) {
86 for (int i = 0; i < config->output_configs->length; i++) {
87 struct output_config *oc = config->output_configs->items[i];
88 if (strcmp(wildcard->name, oc->name) != 0) {
89 wlr_log(WLR_DEBUG, "Merging output * config on %s", oc->name);
90 merge_output_config(oc, wildcard);
91 }
92 }
93}
94
95struct output_config *store_output_config(struct output_config *oc) {
96 bool wildcard = strcmp(oc->name, "*") == 0;
97 if (wildcard) {
98 merge_wildcard_on_all(oc);
99 }
100
101 int i = list_seq_find(config->output_configs, output_name_cmp, oc->name);
102 if (i >= 0) {
103 wlr_log(WLR_DEBUG, "Merging on top of existing output config");
104 struct output_config *current = config->output_configs->items[i];
105 merge_output_config(current, oc);
106 free_output_config(oc);
107 oc = current;
108 } else if (!wildcard) {
109 wlr_log(WLR_DEBUG, "Adding non-wildcard output config");
110 i = list_seq_find(config->output_configs, output_name_cmp, "*");
111 if (i >= 0) {
112 wlr_log(WLR_DEBUG, "Merging on top of output * config");
113 struct output_config *current = new_output_config(oc->name);
114 merge_output_config(current, config->output_configs->items[i]);
115 merge_output_config(current, oc);
116 free_output_config(oc);
117 oc = current;
118 }
119 list_add(config->output_configs, oc);
120 } else {
121 // New wildcard config. Just add it
122 wlr_log(WLR_DEBUG, "Adding output * config");
123 list_add(config->output_configs, oc);
124 }
125
126 wlr_log(WLR_DEBUG, "Config stored for output %s (enabled: %d) (%dx%d@%fHz "
127 "position %d,%d scale %f transform %d) (bg %s %s) (dpms %d)",
128 oc->name, oc->enabled, oc->width, oc->height, oc->refresh_rate,
129 oc->x, oc->y, oc->scale, oc->transform, oc->background,
130 oc->background_option, oc->dpms_state);
131
132 return oc;
133}
134
89static void set_mode(struct wlr_output *output, int width, int height, 135static void set_mode(struct wlr_output *output, int width, int height,
90 float refresh_rate) { 136 float refresh_rate) {
91 int mhz = (int)(refresh_rate * 1000); 137 int mhz = (int)(refresh_rate * 1000);
92 if (wl_list_empty(&output->modes)) { 138 if (wl_list_empty(&output->modes)) {
93 wlr_log(L_DEBUG, "Assigning custom mode to %s", output->name); 139 wlr_log(WLR_DEBUG, "Assigning custom mode to %s", output->name);
94 wlr_output_set_custom_mode(output, width, height, mhz); 140 wlr_output_set_custom_mode(output, width, height, mhz);
95 return; 141 return;
96 } 142 }
@@ -106,9 +152,9 @@ static void set_mode(struct wlr_output *output, int width, int height,
106 } 152 }
107 } 153 }
108 if (!best) { 154 if (!best) {
109 wlr_log(L_ERROR, "Configured mode for %s not available", output->name); 155 wlr_log(WLR_ERROR, "Configured mode for %s not available", output->name);
110 } else { 156 } else {
111 wlr_log(L_DEBUG, "Assigning configured mode to %s", output->name); 157 wlr_log(WLR_DEBUG, "Assigning configured mode to %s", output->name);
112 wlr_output_set_mode(output, best); 158 wlr_output_set_mode(output, best);
113 } 159 }
114} 160}
@@ -116,7 +162,7 @@ static void set_mode(struct wlr_output *output, int width, int height,
116void terminate_swaybg(pid_t pid) { 162void terminate_swaybg(pid_t pid) {
117 int ret = kill(pid, SIGTERM); 163 int ret = kill(pid, SIGTERM);
118 if (ret != 0) { 164 if (ret != 0) {
119 wlr_log(L_ERROR, "Unable to terminate swaybg [pid: %d]", pid); 165 wlr_log(WLR_ERROR, "Unable to terminate swaybg [pid: %d]", pid);
120 } else { 166 } else {
121 int status; 167 int status;
122 waitpid(pid, &status, 0); 168 waitpid(pid, &status, 0);
@@ -144,37 +190,27 @@ void apply_output_config(struct output_config *oc, struct sway_container *output
144 } 190 }
145 191
146 if (oc && oc->width > 0 && oc->height > 0) { 192 if (oc && oc->width > 0 && oc->height > 0) {
147 wlr_log(L_DEBUG, "Set %s mode to %dx%d (%f GHz)", oc->name, oc->width, 193 wlr_log(WLR_DEBUG, "Set %s mode to %dx%d (%f GHz)", oc->name, oc->width,
148 oc->height, oc->refresh_rate); 194 oc->height, oc->refresh_rate);
149 set_mode(wlr_output, oc->width, oc->height, oc->refresh_rate); 195 set_mode(wlr_output, oc->width, oc->height, oc->refresh_rate);
150 } 196 }
151 if (oc && oc->scale > 0) { 197 if (oc && oc->scale > 0) {
152 wlr_log(L_DEBUG, "Set %s scale to %f", oc->name, oc->scale); 198 wlr_log(WLR_DEBUG, "Set %s scale to %f", oc->name, oc->scale);
153 wlr_output_set_scale(wlr_output, oc->scale); 199 wlr_output_set_scale(wlr_output, oc->scale);
154 } 200 }
155 if (oc && oc->transform >= 0) { 201 if (oc && oc->transform >= 0) {
156 wlr_log(L_DEBUG, "Set %s transform to %d", oc->name, oc->transform); 202 wlr_log(WLR_DEBUG, "Set %s transform to %d", oc->name, oc->transform);
157 wlr_output_set_transform(wlr_output, oc->transform); 203 wlr_output_set_transform(wlr_output, oc->transform);
158 } 204 }
159 205
160 // Find position for it 206 // Find position for it
161 if (oc && (oc->x != -1 || oc->y != -1)) { 207 if (oc && (oc->x != -1 || oc->y != -1)) {
162 wlr_log(L_DEBUG, "Set %s position to %d, %d", oc->name, oc->x, oc->y); 208 wlr_log(WLR_DEBUG, "Set %s position to %d, %d", oc->name, oc->x, oc->y);
163 wlr_output_layout_add(output_layout, wlr_output, oc->x, oc->y); 209 wlr_output_layout_add(output_layout, wlr_output, oc->x, oc->y);
164 } else { 210 } else {
165 wlr_output_layout_add_auto(output_layout, wlr_output); 211 wlr_output_layout_add_auto(output_layout, wlr_output);
166 } 212 }
167 213
168 if (!oc || !oc->background) {
169 // Look for a * config for background
170 int i = list_seq_find(config->output_configs, output_name_cmp, "*");
171 if (i >= 0) {
172 oc = config->output_configs->items[i];
173 } else {
174 oc = NULL;
175 }
176 }
177
178 int output_i; 214 int output_i;
179 for (output_i = 0; output_i < root_container.children->length; ++output_i) { 215 for (output_i = 0; output_i < root_container.children->length; ++output_i) {
180 if (root_container.children->items[output_i] == output) { 216 if (root_container.children->items[output_i] == output) {
@@ -187,7 +223,7 @@ void apply_output_config(struct output_config *oc, struct sway_container *output
187 terminate_swaybg(output->sway_output->bg_pid); 223 terminate_swaybg(output->sway_output->bg_pid);
188 } 224 }
189 225
190 wlr_log(L_DEBUG, "Setting background for output %d to %s", 226 wlr_log(WLR_DEBUG, "Setting background for output %d to %s",
191 output_i, oc->background); 227 output_i, oc->background);
192 228
193 size_t len = snprintf(NULL, 0, "%s %d %s %s", 229 size_t len = snprintf(NULL, 0, "%s %d %s %s",
@@ -195,28 +231,30 @@ void apply_output_config(struct output_config *oc, struct sway_container *output
195 output_i, oc->background, oc->background_option); 231 output_i, oc->background, oc->background_option);
196 char *command = malloc(len + 1); 232 char *command = malloc(len + 1);
197 if (!command) { 233 if (!command) {
198 wlr_log(L_DEBUG, "Unable to allocate swaybg command"); 234 wlr_log(WLR_DEBUG, "Unable to allocate swaybg command");
199 return; 235 return;
200 } 236 }
201 snprintf(command, len + 1, "%s %d %s %s", 237 snprintf(command, len + 1, "%s %d %s %s",
202 config->swaybg_command ? config->swaybg_command : "swaybg", 238 config->swaybg_command ? config->swaybg_command : "swaybg",
203 output_i, oc->background, oc->background_option); 239 output_i, oc->background, oc->background_option);
204 wlr_log(L_DEBUG, "-> %s", command); 240 wlr_log(WLR_DEBUG, "-> %s", command);
205 241
206 char *const cmd[] = { "sh", "-c", command, NULL }; 242 char *const cmd[] = { "sh", "-c", command, NULL };
207 output->sway_output->bg_pid = fork(); 243 output->sway_output->bg_pid = fork();
208 if (output->sway_output->bg_pid == 0) { 244 if (output->sway_output->bg_pid == 0) {
209 execvp(cmd[0], cmd); 245 execvp(cmd[0], cmd);
246 } else {
247 free(command);
210 } 248 }
211 } 249 }
212 if (oc && oc->dpms_state != DPMS_IGNORE) { 250 if (oc && oc->dpms_state != DPMS_IGNORE) {
213 switch (oc->dpms_state) { 251 switch (oc->dpms_state) {
214 case DPMS_ON: 252 case DPMS_ON:
215 wlr_log(L_DEBUG, "Turning on screen"); 253 wlr_log(WLR_DEBUG, "Turning on screen");
216 wlr_output_enable(wlr_output, true); 254 wlr_output_enable(wlr_output, true);
217 break; 255 break;
218 case DPMS_OFF: 256 case DPMS_OFF:
219 wlr_log(L_DEBUG, "Turning off screen"); 257 wlr_log(WLR_DEBUG, "Turning off screen");
220 wlr_output_enable(wlr_output, false); 258 wlr_output_enable(wlr_output, false);
221 break; 259 break;
222 case DPMS_IGNORE: 260 case DPMS_IGNORE:
@@ -225,6 +263,60 @@ void apply_output_config(struct output_config *oc, struct sway_container *output
225 } 263 }
226} 264}
227 265
266static struct output_config *get_output_config(char *name, char *identifier) {
267 int i = list_seq_find(config->output_configs, output_name_cmp, name);
268 if (i >= 0) {
269 return config->output_configs->items[i];
270 }
271
272 i = list_seq_find(config->output_configs, output_name_cmp, identifier);
273 if (i >= 0) {
274 return config->output_configs->items[i];
275 }
276
277 return NULL;
278}
279
280void apply_output_config_to_outputs(struct output_config *oc) {
281 // Try to find the output container and apply configuration now. If
282 // this is during startup then there will be no container and config
283 // will be applied during normal "new output" event from wlroots.
284 bool wildcard = strcmp(oc->name, "*") == 0;
285 char id[128];
286 struct sway_output *sway_output;
287 wl_list_for_each(sway_output, &root_container.sway_root->outputs, link) {
288 char *name = sway_output->wlr_output->name;
289 output_get_identifier(id, sizeof(id), sway_output);
290 if (wildcard || !strcmp(name, oc->name) || !strcmp(id, oc->name)) {
291 if (!sway_output->swayc) {
292 if (!oc->enabled) {
293 if (!wildcard) {
294 break;
295 }
296 continue;
297 }
298
299 output_enable(sway_output);
300 }
301
302 struct output_config *current = oc;
303 if (wildcard) {
304 struct output_config *tmp = get_output_config(name, id);
305 if (tmp) {
306 current = tmp;
307 }
308 }
309 apply_output_config(current, sway_output->swayc);
310
311 if (!wildcard) {
312 // Stop looking if the output config isn't applicable to all
313 // outputs
314 break;
315 }
316 }
317 }
318}
319
228void free_output_config(struct output_config *oc) { 320void free_output_config(struct output_config *oc) {
229 if (!oc) { 321 if (!oc) {
230 return; 322 return;
@@ -234,3 +326,29 @@ void free_output_config(struct output_config *oc) {
234 free(oc->background_option); 326 free(oc->background_option);
235 free(oc); 327 free(oc);
236} 328}
329
330static void default_output_config(struct output_config *oc,
331 struct wlr_output *wlr_output) {
332 oc->enabled = 1;
333 if (!wl_list_empty(&wlr_output->modes)) {
334 struct wlr_output_mode *mode =
335 wl_container_of(wlr_output->modes.prev, mode, link);
336 oc->width = mode->width;
337 oc->height = mode->height;
338 oc->refresh_rate = mode->refresh;
339 }
340 oc->x = oc->y = -1;
341 oc->scale = 1;
342 oc->transform = WL_OUTPUT_TRANSFORM_NORMAL;
343}
344
345void create_default_output_configs(void) {
346 struct sway_output *sway_output;
347 wl_list_for_each(sway_output, &root_container.sway_root->outputs, link) {
348 char *name = sway_output->wlr_output->name;
349 struct output_config *oc = new_output_config(name);
350 default_output_config(oc, sway_output->wlr_output);
351 list_add(config->output_configs, oc);
352 }
353}
354