diff options
Diffstat (limited to 'sway/config/output.c')
-rw-r--r-- | sway/config/output.c | 172 |
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) { } 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; } @@ -86,11 +82,61 @@ void merge_output_config(struct output_config *dst, struct output_config *src) { } } +static void merge_wildcard_on_all(struct output_config *wildcard) { + for (int i = 0; i < config->output_configs->length; i++) { + struct output_config *oc = config->output_configs->items[i]; + if (strcmp(wildcard->name, oc->name) != 0) { + wlr_log(WLR_DEBUG, "Merging output * config on %s", oc->name); + merge_output_config(oc, wildcard); + } + } +} + +struct output_config *store_output_config(struct output_config *oc) { + bool wildcard = strcmp(oc->name, "*") == 0; + if (wildcard) { + merge_wildcard_on_all(oc); + } + + int i = list_seq_find(config->output_configs, output_name_cmp, oc->name); + if (i >= 0) { + wlr_log(WLR_DEBUG, "Merging on top of existing output config"); + struct output_config *current = config->output_configs->items[i]; + merge_output_config(current, oc); + free_output_config(oc); + oc = current; + } else if (!wildcard) { + wlr_log(WLR_DEBUG, "Adding non-wildcard output config"); + i = list_seq_find(config->output_configs, output_name_cmp, "*"); + if (i >= 0) { + wlr_log(WLR_DEBUG, "Merging on top of output * config"); + struct output_config *current = new_output_config(oc->name); + merge_output_config(current, config->output_configs->items[i]); + merge_output_config(current, oc); + free_output_config(oc); + oc = current; + } + list_add(config->output_configs, oc); + } else { + // New wildcard config. Just add it + wlr_log(WLR_DEBUG, "Adding output * config"); + list_add(config->output_configs, oc); + } + + wlr_log(WLR_DEBUG, "Config stored for output %s (enabled: %d) (%dx%d@%fHz " + "position %d,%d scale %f transform %d) (bg %s %s) (dpms %d)", + oc->name, oc->enabled, oc->width, oc->height, oc->refresh_rate, + oc->x, oc->y, oc->scale, oc->transform, oc->background, + oc->background_option, oc->dpms_state); + + return oc; +} + 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)) { - wlr_log(L_DEBUG, "Assigning custom mode to %s", output->name); + wlr_log(WLR_DEBUG, "Assigning custom mode to %s", output->name); wlr_output_set_custom_mode(output, width, height, mhz); return; } @@ -106,9 +152,9 @@ static void set_mode(struct wlr_output *output, int width, int height, } } if (!best) { - wlr_log(L_ERROR, "Configured mode for %s not available", output->name); + wlr_log(WLR_ERROR, "Configured mode for %s not available", output->name); } else { - wlr_log(L_DEBUG, "Assigning configured mode to %s", output->name); + wlr_log(WLR_DEBUG, "Assigning configured mode to %s", output->name); wlr_output_set_mode(output, best); } } @@ -116,7 +162,7 @@ static void set_mode(struct wlr_output *output, int width, int height, void terminate_swaybg(pid_t pid) { int ret = kill(pid, SIGTERM); if (ret != 0) { - wlr_log(L_ERROR, "Unable to terminate swaybg [pid: %d]", pid); + wlr_log(WLR_ERROR, "Unable to terminate swaybg [pid: %d]", pid); } else { int status; waitpid(pid, &status, 0); @@ -144,37 +190,27 @@ void apply_output_config(struct output_config *oc, struct sway_container *output } if (oc && oc->width > 0 && oc->height > 0) { - wlr_log(L_DEBUG, "Set %s mode to %dx%d (%f GHz)", oc->name, oc->width, + wlr_log(WLR_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) { - wlr_log(L_DEBUG, "Set %s scale to %f", oc->name, oc->scale); + wlr_log(WLR_DEBUG, "Set %s scale to %f", oc->name, oc->scale); wlr_output_set_scale(wlr_output, oc->scale); } if (oc && oc->transform >= 0) { - wlr_log(L_DEBUG, "Set %s transform to %d", oc->name, oc->transform); + wlr_log(WLR_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)) { - wlr_log(L_DEBUG, "Set %s position to %d, %d", oc->name, oc->x, oc->y); + wlr_log(WLR_DEBUG, "Set %s position to %d, %d", oc->name, oc->x, oc->y); wlr_output_layout_add(output_layout, wlr_output, oc->x, oc->y); } else { wlr_output_layout_add_auto(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) { @@ -187,7 +223,7 @@ void apply_output_config(struct output_config *oc, struct sway_container *output terminate_swaybg(output->sway_output->bg_pid); } - wlr_log(L_DEBUG, "Setting background for output %d to %s", + wlr_log(WLR_DEBUG, "Setting background for output %d to %s", output_i, oc->background); 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 output_i, oc->background, oc->background_option); char *command = malloc(len + 1); if (!command) { - wlr_log(L_DEBUG, "Unable to allocate swaybg command"); + wlr_log(WLR_DEBUG, "Unable to allocate swaybg command"); return; } snprintf(command, len + 1, "%s %d %s %s", config->swaybg_command ? config->swaybg_command : "swaybg", output_i, oc->background, oc->background_option); - wlr_log(L_DEBUG, "-> %s", command); + wlr_log(WLR_DEBUG, "-> %s", command); char *const cmd[] = { "sh", "-c", command, NULL }; output->sway_output->bg_pid = fork(); if (output->sway_output->bg_pid == 0) { execvp(cmd[0], cmd); + } else { + free(command); } } if (oc && oc->dpms_state != DPMS_IGNORE) { switch (oc->dpms_state) { case DPMS_ON: - wlr_log(L_DEBUG, "Turning on screen"); + wlr_log(WLR_DEBUG, "Turning on screen"); wlr_output_enable(wlr_output, true); break; case DPMS_OFF: - wlr_log(L_DEBUG, "Turning off screen"); + wlr_log(WLR_DEBUG, "Turning off screen"); wlr_output_enable(wlr_output, false); break; case DPMS_IGNORE: @@ -225,6 +263,60 @@ void apply_output_config(struct output_config *oc, struct sway_container *output } } +static struct output_config *get_output_config(char *name, char *identifier) { + int i = list_seq_find(config->output_configs, output_name_cmp, name); + if (i >= 0) { + return config->output_configs->items[i]; + } + + i = list_seq_find(config->output_configs, output_name_cmp, identifier); + if (i >= 0) { + return config->output_configs->items[i]; + } + + return NULL; +} + +void apply_output_config_to_outputs(struct output_config *oc) { + // 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. + bool wildcard = strcmp(oc->name, "*") == 0; + char id[128]; + struct sway_output *sway_output; + wl_list_for_each(sway_output, &root_container.sway_root->outputs, link) { + char *name = sway_output->wlr_output->name; + output_get_identifier(id, sizeof(id), sway_output); + if (wildcard || !strcmp(name, oc->name) || !strcmp(id, oc->name)) { + if (!sway_output->swayc) { + if (!oc->enabled) { + if (!wildcard) { + break; + } + continue; + } + + output_enable(sway_output); + } + + struct output_config *current = oc; + if (wildcard) { + struct output_config *tmp = get_output_config(name, id); + if (tmp) { + current = tmp; + } + } + apply_output_config(current, sway_output->swayc); + + if (!wildcard) { + // Stop looking if the output config isn't applicable to all + // outputs + break; + } + } + } +} + void free_output_config(struct output_config *oc) { if (!oc) { return; @@ -234,3 +326,29 @@ void free_output_config(struct output_config *oc) { free(oc->background_option); free(oc); } + +static void default_output_config(struct output_config *oc, + struct wlr_output *wlr_output) { + oc->enabled = 1; + if (!wl_list_empty(&wlr_output->modes)) { + struct wlr_output_mode *mode = + wl_container_of(wlr_output->modes.prev, mode, link); + oc->width = mode->width; + oc->height = mode->height; + oc->refresh_rate = mode->refresh; + } + oc->x = oc->y = -1; + oc->scale = 1; + oc->transform = WL_OUTPUT_TRANSFORM_NORMAL; +} + +void create_default_output_configs(void) { + struct sway_output *sway_output; + wl_list_for_each(sway_output, &root_container.sway_root->outputs, link) { + char *name = sway_output->wlr_output->name; + struct output_config *oc = new_output_config(name); + default_output_config(oc, sway_output->wlr_output); + list_add(config->output_configs, oc); + } +} + |