aboutsummaryrefslogtreecommitdiffstats
path: root/sway/config.c
diff options
context:
space:
mode:
Diffstat (limited to 'sway/config.c')
-rw-r--r--sway/config.c157
1 files changed, 109 insertions, 48 deletions
diff --git a/sway/config.c b/sway/config.c
index 512cab31..5f6dd7ad 100644
--- a/sway/config.c
+++ b/sway/config.c
@@ -24,6 +24,7 @@
24#include "sway/input/seat.h" 24#include "sway/input/seat.h"
25#include "sway/commands.h" 25#include "sway/commands.h"
26#include "sway/config.h" 26#include "sway/config.h"
27#include "sway/criteria.h"
27#include "sway/tree/arrange.h" 28#include "sway/tree/arrange.h"
28#include "sway/tree/layout.h" 29#include "sway/tree/layout.h"
29#include "sway/tree/workspace.h" 30#include "sway/tree/workspace.h"
@@ -86,7 +87,12 @@ void free_config(struct sway_config *config) {
86 } 87 }
87 list_free(config->cmd_queue); 88 list_free(config->cmd_queue);
88 list_free(config->workspace_outputs); 89 list_free(config->workspace_outputs);
89 list_free(config->output_configs); 90 if (config->output_configs) {
91 for (int i = 0; i < config->output_configs->length; i++) {
92 free_output_config(config->output_configs->items[i]);
93 }
94 list_free(config->output_configs);
95 }
90 if (config->input_configs) { 96 if (config->input_configs) {
91 for (int i = 0; i < config->input_configs->length; i++) { 97 for (int i = 0; i < config->input_configs->length; i++) {
92 free_input_config(config->input_configs->items[i]); 98 free_input_config(config->input_configs->items[i]);
@@ -99,7 +105,12 @@ void free_config(struct sway_config *config) {
99 } 105 }
100 list_free(config->seat_configs); 106 list_free(config->seat_configs);
101 } 107 }
102 list_free(config->criteria); 108 if (config->criteria) {
109 for (int i = 0; i < config->criteria->length; ++i) {
110 criteria_destroy(config->criteria->items[i]);
111 }
112 list_free(config->criteria);
113 }
103 list_free(config->no_focus); 114 list_free(config->no_focus);
104 list_free(config->active_bar_modifiers); 115 list_free(config->active_bar_modifiers);
105 list_free(config->config_chain); 116 list_free(config->config_chain);
@@ -111,6 +122,7 @@ void free_config(struct sway_config *config) {
111 free(config->floating_scroll_left_cmd); 122 free(config->floating_scroll_left_cmd);
112 free(config->floating_scroll_right_cmd); 123 free(config->floating_scroll_right_cmd);
113 free(config->font); 124 free(config->font);
125 free((char *)config->current_config_path);
114 free((char *)config->current_config); 126 free((char *)config->current_config);
115 free(config); 127 free(config);
116} 128}
@@ -172,6 +184,7 @@ static void config_defaults(struct sway_config *config) {
172 config->default_orientation = L_NONE; 184 config->default_orientation = L_NONE;
173 if (!(config->font = strdup("monospace 10"))) goto cleanup; 185 if (!(config->font = strdup("monospace 10"))) goto cleanup;
174 config->font_height = 17; // height of monospace 10 186 config->font_height = 17; // height of monospace 10
187 config->urgent_timeout = 500;
175 188
176 // floating view 189 // floating view
177 config->floating_maximum_width = 0; 190 config->floating_maximum_width = 0;
@@ -198,6 +211,7 @@ static void config_defaults(struct sway_config *config) {
198 if (!(config->active_bar_modifiers = create_list())) goto cleanup; 211 if (!(config->active_bar_modifiers = create_list())) goto cleanup;
199 212
200 if (!(config->config_chain = create_list())) goto cleanup; 213 if (!(config->config_chain = create_list())) goto cleanup;
214 config->current_config_path = NULL;
201 config->current_config = NULL; 215 config->current_config = NULL;
202 216
203 // borders 217 // borders
@@ -269,12 +283,12 @@ static char *get_config_path(void) {
269 char *home = getenv("HOME"); 283 char *home = getenv("HOME");
270 char *config_home = malloc(strlen(home) + strlen("/.config") + 1); 284 char *config_home = malloc(strlen(home) + strlen("/.config") + 1);
271 if (!config_home) { 285 if (!config_home) {
272 wlr_log(L_ERROR, "Unable to allocate $HOME/.config"); 286 wlr_log(WLR_ERROR, "Unable to allocate $HOME/.config");
273 } else { 287 } else {
274 strcpy(config_home, home); 288 strcpy(config_home, home);
275 strcat(config_home, "/.config"); 289 strcat(config_home, "/.config");
276 setenv("XDG_CONFIG_HOME", config_home, 1); 290 setenv("XDG_CONFIG_HOME", config_home, 1);
277 wlr_log(L_DEBUG, "Set XDG_CONFIG_HOME to %s", config_home); 291 wlr_log(WLR_DEBUG, "Set XDG_CONFIG_HOME to %s", config_home);
278 free(config_home); 292 free(config_home);
279 } 293 }
280 } 294 }
@@ -297,25 +311,22 @@ static char *get_config_path(void) {
297 return NULL; // Not reached 311 return NULL; // Not reached
298} 312}
299 313
300const char *current_config_path;
301
302static bool load_config(const char *path, struct sway_config *config) { 314static bool load_config(const char *path, struct sway_config *config) {
303 wlr_log(L_INFO, "Loading config from %s", path); 315 if (path == NULL) {
304 current_config_path = path; 316 wlr_log(WLR_ERROR, "Unable to find a config file!");
305
306 struct stat sb;
307 if (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)) {
308 return false; 317 return false;
309 } 318 }
310 319
311 if (path == NULL) { 320 wlr_log(WLR_INFO, "Loading config from %s", path);
312 wlr_log(L_ERROR, "Unable to find a config file!"); 321
322 struct stat sb;
323 if (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)) {
313 return false; 324 return false;
314 } 325 }
315 326
316 FILE *f = fopen(path, "r"); 327 FILE *f = fopen(path, "r");
317 if (!f) { 328 if (!f) {
318 wlr_log(L_ERROR, "Unable to open %s for reading", path); 329 wlr_log(WLR_ERROR, "Unable to open %s for reading", path);
319 return false; 330 return false;
320 } 331 }
321 332
@@ -323,10 +334,9 @@ static bool load_config(const char *path, struct sway_config *config) {
323 fclose(f); 334 fclose(f);
324 335
325 if (!config_load_success) { 336 if (!config_load_success) {
326 wlr_log(L_ERROR, "Error(s) loading config!"); 337 wlr_log(WLR_ERROR, "Error(s) loading config!");
327 } 338 }
328 339
329 current_config_path = NULL;
330 return true; 340 return true;
331} 341}
332 342
@@ -346,12 +356,13 @@ bool load_main_config(const char *file, bool is_active) {
346 356
347 config_defaults(config); 357 config_defaults(config);
348 if (is_active) { 358 if (is_active) {
349 wlr_log(L_DEBUG, "Performing configuration file reload"); 359 wlr_log(WLR_DEBUG, "Performing configuration file reload");
350 config->reloading = true; 360 config->reloading = true;
351 config->active = true; 361 config->active = true;
362 create_default_output_configs();
352 } 363 }
353 364
354 config->current_config = path; 365 config->current_config_path = path;
355 list_add(config->config_chain, path); 366 list_add(config->config_chain, path);
356 367
357 config->reading = true; 368 config->reading = true;
@@ -362,7 +373,7 @@ bool load_main_config(const char *file, bool is_active) {
362 /* 373 /*
363 DIR *dir = opendir(SYSCONFDIR "/sway/security.d"); 374 DIR *dir = opendir(SYSCONFDIR "/sway/security.d");
364 if (!dir) { 375 if (!dir) {
365 wlr_log(L_ERROR, 376 wlr_log(WLR_ERROR,
366 "%s does not exist, sway will have no security configuration" 377 "%s does not exist, sway will have no security configuration"
367 " and will probably be broken", SYSCONFDIR "/sway/security.d"); 378 " and will probably be broken", SYSCONFDIR "/sway/security.d");
368 } else { 379 } else {
@@ -391,7 +402,7 @@ bool load_main_config(const char *file, bool is_active) {
391 if (stat(_path, &s) || s.st_uid != 0 || s.st_gid != 0 || 402 if (stat(_path, &s) || s.st_uid != 0 || s.st_gid != 0 ||
392 (((s.st_mode & 0777) != 0644) && 403 (((s.st_mode & 0777) != 0644) &&
393 (s.st_mode & 0777) != 0444)) { 404 (s.st_mode & 0777) != 0444)) {
394 wlr_log(L_ERROR, 405 wlr_log(WLR_ERROR,
395 "Refusing to load %s - it must be owned by root " 406 "Refusing to load %s - it must be owned by root "
396 "and mode 644 or 444", _path); 407 "and mode 644 or 444", _path);
397 success = false; 408 success = false;
@@ -407,6 +418,9 @@ bool load_main_config(const char *file, bool is_active) {
407 success = success && load_config(path, config); 418 success = success && load_config(path, config);
408 419
409 if (is_active) { 420 if (is_active) {
421 for (int i = 0; i < config->output_configs->length; i++) {
422 apply_output_config_to_outputs(config->output_configs->items[i]);
423 }
410 config->reloading = false; 424 config->reloading = false;
411 } 425 }
412 426
@@ -421,26 +435,28 @@ bool load_main_config(const char *file, bool is_active) {
421static bool load_include_config(const char *path, const char *parent_dir, 435static bool load_include_config(const char *path, const char *parent_dir,
422 struct sway_config *config) { 436 struct sway_config *config) {
423 // save parent config 437 // save parent config
424 const char *parent_config = config->current_config; 438 const char *parent_config = config->current_config_path;
425 439
426 char *full_path = strdup(path); 440 char *full_path;
427 int len = strlen(path); 441 int len = strlen(path);
428 if (len >= 1 && path[0] != '/') { 442 if (len >= 1 && path[0] != '/') {
429 len = len + strlen(parent_dir) + 2; 443 len = len + strlen(parent_dir) + 2;
430 full_path = malloc(len * sizeof(char)); 444 full_path = malloc(len * sizeof(char));
431 if (!full_path) { 445 if (!full_path) {
432 wlr_log(L_ERROR, 446 wlr_log(WLR_ERROR,
433 "Unable to allocate full path to included config"); 447 "Unable to allocate full path to included config");
434 return false; 448 return false;
435 } 449 }
436 snprintf(full_path, len, "%s/%s", parent_dir, path); 450 snprintf(full_path, len, "%s/%s", parent_dir, path);
451 } else {
452 full_path = strdup(path);
437 } 453 }
438 454
439 char *real_path = realpath(full_path, NULL); 455 char *real_path = realpath(full_path, NULL);
440 free(full_path); 456 free(full_path);
441 457
442 if (real_path == NULL) { 458 if (real_path == NULL) {
443 wlr_log(L_DEBUG, "%s not found.", path); 459 wlr_log(WLR_DEBUG, "%s not found.", path);
444 return false; 460 return false;
445 } 461 }
446 462
@@ -449,7 +465,7 @@ static bool load_include_config(const char *path, const char *parent_dir,
449 for (j = 0; j < config->config_chain->length; ++j) { 465 for (j = 0; j < config->config_chain->length; ++j) {
450 char *old_path = config->config_chain->items[j]; 466 char *old_path = config->config_chain->items[j];
451 if (strcmp(real_path, old_path) == 0) { 467 if (strcmp(real_path, old_path) == 0) {
452 wlr_log(L_DEBUG, 468 wlr_log(WLR_DEBUG,
453 "%s already included once, won't be included again.", 469 "%s already included once, won't be included again.",
454 real_path); 470 real_path);
455 free(real_path); 471 free(real_path);
@@ -457,25 +473,25 @@ static bool load_include_config(const char *path, const char *parent_dir,
457 } 473 }
458 } 474 }
459 475
460 config->current_config = real_path; 476 config->current_config_path = real_path;
461 list_add(config->config_chain, real_path); 477 list_add(config->config_chain, real_path);
462 int index = config->config_chain->length - 1; 478 int index = config->config_chain->length - 1;
463 479
464 if (!load_config(real_path, config)) { 480 if (!load_config(real_path, config)) {
465 free(real_path); 481 free(real_path);
466 config->current_config = parent_config; 482 config->current_config_path = parent_config;
467 list_del(config->config_chain, index); 483 list_del(config->config_chain, index);
468 return false; 484 return false;
469 } 485 }
470 486
471 // restore current_config 487 // restore current_config_path
472 config->current_config = parent_config; 488 config->current_config_path = parent_config;
473 return true; 489 return true;
474} 490}
475 491
476bool load_include_configs(const char *path, struct sway_config *config) { 492bool load_include_configs(const char *path, struct sway_config *config) {
477 char *wd = getcwd(NULL, 0); 493 char *wd = getcwd(NULL, 0);
478 char *parent_path = strdup(config->current_config); 494 char *parent_path = strdup(config->current_config_path);
479 const char *parent_dir = dirname(parent_path); 495 const char *parent_dir = dirname(parent_path);
480 496
481 if (chdir(parent_dir) < 0) { 497 if (chdir(parent_dir) < 0) {
@@ -503,7 +519,7 @@ bool load_include_configs(const char *path, struct sway_config *config) {
503 // restore wd 519 // restore wd
504 if (chdir(wd) < 0) { 520 if (chdir(wd) < 0) {
505 free(wd); 521 free(wd);
506 wlr_log(L_ERROR, "failed to restore working directory"); 522 wlr_log(WLR_ERROR, "failed to restore working directory");
507 return false; 523 return false;
508 } 524 }
509 525
@@ -518,13 +534,13 @@ static int detect_brace_on_following_line(FILE *file, char *line,
518 char *peeked = NULL; 534 char *peeked = NULL;
519 long position = 0; 535 long position = 0;
520 do { 536 do {
521 wlr_log(L_DEBUG, "Peeking line %d", line_number + lines + 1); 537 wlr_log(WLR_DEBUG, "Peeking line %d", line_number + lines + 1);
522 free(peeked); 538 free(peeked);
523 peeked = peek_line(file, lines, &position); 539 peeked = peek_line(file, lines, &position);
524 if (peeked) { 540 if (peeked) {
525 peeked = strip_whitespace(peeked); 541 peeked = strip_whitespace(peeked);
526 } 542 }
527 wlr_log(L_DEBUG, "Peeked line: `%s`", peeked); 543 wlr_log(WLR_DEBUG, "Peeked line: `%s`", peeked);
528 lines++; 544 lines++;
529 } while (peeked && strlen(peeked) == 0); 545 } while (peeked && strlen(peeked) == 0);
530 546
@@ -543,7 +559,7 @@ static char *expand_line(const char *block, const char *line, bool add_brace) {
543 + (add_brace ? 2 : 0) + 1; 559 + (add_brace ? 2 : 0) + 1;
544 char *expanded = calloc(1, size); 560 char *expanded = calloc(1, size);
545 if (!expanded) { 561 if (!expanded) {
546 wlr_log(L_ERROR, "Cannot allocate expanded line buffer"); 562 wlr_log(WLR_ERROR, "Cannot allocate expanded line buffer");
547 return NULL; 563 return NULL;
548 } 564 }
549 snprintf(expanded, size, "%s%s%s%s", block ? block : "", 565 snprintf(expanded, size, "%s%s%s%s", block ? block : "",
@@ -552,10 +568,33 @@ static char *expand_line(const char *block, const char *line, bool add_brace) {
552} 568}
553 569
554bool read_config(FILE *file, struct sway_config *config) { 570bool read_config(FILE *file, struct sway_config *config) {
571 bool reading_main_config = false;
572 char *this_config = NULL;
573 size_t config_size = 0;
574 if (config->current_config == NULL) {
575 reading_main_config = true;
576
577 int ret_seek = fseek(file, 0, SEEK_END);
578 long ret_tell = ftell(file);
579 if (ret_seek == -1 || ret_tell == -1) {
580 wlr_log(WLR_ERROR, "Unable to get size of config file");
581 return false;
582 }
583 config_size = ret_tell;
584 rewind(file);
585
586 config->current_config = this_config = calloc(1, config_size + 1);
587 if (this_config == NULL) {
588 wlr_log(WLR_ERROR, "Unable to allocate buffer for config contents");
589 return false;
590 }
591 }
592
555 bool success = true; 593 bool success = true;
556 int line_number = 0; 594 int line_number = 0;
557 char *line; 595 char *line;
558 list_t *stack = create_list(); 596 list_t *stack = create_list();
597 size_t read = 0;
559 while (!feof(file)) { 598 while (!feof(file)) {
560 char *block = stack->length ? stack->items[0] : NULL; 599 char *block = stack->length ? stack->items[0] : NULL;
561 line = read_line(file); 600 line = read_line(file);
@@ -563,7 +602,26 @@ bool read_config(FILE *file, struct sway_config *config) {
563 continue; 602 continue;
564 } 603 }
565 line_number++; 604 line_number++;
566 wlr_log(L_DEBUG, "Read line %d: %s", line_number, line); 605 wlr_log(WLR_DEBUG, "Read line %d: %s", line_number, line);
606
607 if (reading_main_config) {
608 size_t length = strlen(line);
609
610 if (read + length > config_size) {
611 wlr_log(WLR_ERROR, "Config file changed during reading");
612 list_foreach(stack, free);
613 list_free(stack);
614 free(line);
615 return false;
616 }
617
618 strcpy(this_config + read, line);
619 if (line_number != 1) {
620 this_config[read - 1] = '\n';
621 }
622 read += length + 1;
623 }
624
567 line = strip_whitespace(line); 625 line = strip_whitespace(line);
568 if (line[0] == '#') { 626 if (line[0] == '#') {
569 free(line); 627 free(line);
@@ -577,13 +635,16 @@ bool read_config(FILE *file, struct sway_config *config) {
577 line_number); 635 line_number);
578 if (brace_detected > 0) { 636 if (brace_detected > 0) {
579 line_number += brace_detected; 637 line_number += brace_detected;
580 wlr_log(L_DEBUG, "Detected open brace on line %d", line_number); 638 wlr_log(WLR_DEBUG, "Detected open brace on line %d", line_number);
581 } 639 }
582 char *expanded = expand_line(block, line, brace_detected > 0); 640 char *expanded = expand_line(block, line, brace_detected > 0);
583 if (!expanded) { 641 if (!expanded) {
642 list_foreach(stack, free);
643 list_free(stack);
644 free(line);
584 return false; 645 return false;
585 } 646 }
586 wlr_log(L_DEBUG, "Expanded line: %s", expanded); 647 wlr_log(WLR_DEBUG, "Expanded line: %s", expanded);
587 struct cmd_results *res; 648 struct cmd_results *res;
588 if (block && strcmp(block, "<commands>") == 0) { 649 if (block && strcmp(block, "<commands>") == 0) {
589 // Special case 650 // Special case
@@ -591,27 +652,26 @@ bool read_config(FILE *file, struct sway_config *config) {
591 } else { 652 } else {
592 res = config_command(expanded); 653 res = config_command(expanded);
593 } 654 }
594 free(expanded);
595 switch(res->status) { 655 switch(res->status) {
596 case CMD_FAILURE: 656 case CMD_FAILURE:
597 case CMD_INVALID: 657 case CMD_INVALID:
598 wlr_log(L_ERROR, "Error on line %i '%s': %s (%s)", line_number, 658 wlr_log(WLR_ERROR, "Error on line %i '%s': %s (%s)", line_number,
599 line, res->error, config->current_config); 659 line, res->error, config->current_config_path);
600 success = false; 660 success = false;
601 break; 661 break;
602 662
603 case CMD_DEFER: 663 case CMD_DEFER:
604 wlr_log(L_DEBUG, "Deferring command `%s'", line); 664 wlr_log(WLR_DEBUG, "Deferring command `%s'", line);
605 list_add(config->cmd_queue, strdup(line)); 665 list_add(config->cmd_queue, strdup(expanded));
606 break; 666 break;
607 667
608 case CMD_BLOCK_COMMANDS: 668 case CMD_BLOCK_COMMANDS:
609 wlr_log(L_DEBUG, "Entering commands block"); 669 wlr_log(WLR_DEBUG, "Entering commands block");
610 list_insert(stack, 0, "<commands>"); 670 list_insert(stack, 0, "<commands>");
611 break; 671 break;
612 672
613 case CMD_BLOCK: 673 case CMD_BLOCK:
614 wlr_log(L_DEBUG, "Entering block '%s'", res->input); 674 wlr_log(WLR_DEBUG, "Entering block '%s'", res->input);
615 list_insert(stack, 0, strdup(res->input)); 675 list_insert(stack, 0, strdup(res->input));
616 if (strcmp(res->input, "bar") == 0) { 676 if (strcmp(res->input, "bar") == 0) {
617 config->current_bar = NULL; 677 config->current_bar = NULL;
@@ -620,7 +680,7 @@ bool read_config(FILE *file, struct sway_config *config) {
620 680
621 case CMD_BLOCK_END: 681 case CMD_BLOCK_END:
622 if (!block) { 682 if (!block) {
623 wlr_log(L_DEBUG, "Unmatched '}' on line %i", line_number); 683 wlr_log(WLR_DEBUG, "Unmatched '}' on line %i", line_number);
624 success = false; 684 success = false;
625 break; 685 break;
626 } 686 }
@@ -628,13 +688,14 @@ bool read_config(FILE *file, struct sway_config *config) {
628 config->current_bar = NULL; 688 config->current_bar = NULL;
629 } 689 }
630 690
631 wlr_log(L_DEBUG, "Exiting block '%s'", block); 691 wlr_log(WLR_DEBUG, "Exiting block '%s'", block);
632 list_del(stack, 0); 692 list_del(stack, 0);
633 free(block); 693 free(block);
634 memset(&config->handler_context, 0, 694 memset(&config->handler_context, 0,
635 sizeof(config->handler_context)); 695 sizeof(config->handler_context));
636 default:; 696 default:;
637 } 697 }
698 free(expanded);
638 free(line); 699 free(line);
639 free_cmd_results(res); 700 free_cmd_results(res);
640 } 701 }
@@ -671,7 +732,7 @@ char *do_var_replacement(char *str) {
671 int vvlen = strlen(var->value); 732 int vvlen = strlen(var->value);
672 char *newstr = malloc(strlen(str) - vnlen + vvlen + 1); 733 char *newstr = malloc(strlen(str) - vnlen + vvlen + 1);
673 if (!newstr) { 734 if (!newstr) {
674 wlr_log(L_ERROR, 735 wlr_log(WLR_ERROR,
675 "Unable to allocate replacement " 736 "Unable to allocate replacement "
676 "during variable expansion"); 737 "during variable expansion");
677 break; 738 break;
@@ -733,6 +794,6 @@ void config_update_font_height(bool recalculate) {
733 } 794 }
734 795
735 if (config->font_height != prev_max_height) { 796 if (config->font_height != prev_max_height) {
736 arrange_and_commit(&root_container); 797 arrange_windows(&root_container);
737 } 798 }
738} 799}