output/background: parse background mode into enum

This simplifies the logic in `output_cmd_background` by avoiding
strdup() calls (and their error handling paths) for the background mode.

It also fixes a mismatch between the "background" subcommand (which
accepts mode names case-insensitively) and swaybg (which does not,
requiring lowercase).
This commit is contained in:
Manuel Stoeckl 2025-02-09 09:33:45 -05:00
parent 4852087e61
commit 6914a7158f
3 changed files with 41 additions and 34 deletions

View file

@ -267,6 +267,17 @@ enum render_bit_depth {
RENDER_BIT_DEPTH_10, RENDER_BIT_DEPTH_10,
}; };
enum background_mode {
BACKGROUND_MODE_UNSET, // there is no default
BACKGROUND_MODE_SOLID_COLOR,
BACKGROUND_MODE_STRETCH,
BACKGROUND_MODE_CENTER,
BACKGROUND_MODE_FILL,
BACKGROUND_MODE_FIT,
BACKGROUND_MODE_TILE,
};
extern const char *const background_mode_names[];
/** /**
* Size and position configuration for a particular output. * Size and position configuration for a particular output.
* *
@ -293,7 +304,7 @@ struct output_config {
int allow_tearing; int allow_tearing;
char *background; char *background;
char *background_option; enum background_mode background_option;
char *background_fallback; char *background_fallback;
}; };

View file

@ -8,12 +8,14 @@
#include "log.h" #include "log.h"
#include "stringop.h" #include "stringop.h"
static const char *bg_options[] = { const char *const background_mode_names[] = {
"stretch", [BACKGROUND_MODE_UNSET] = "unset",
"center", [BACKGROUND_MODE_SOLID_COLOR] = "solid_color",
"fill", [BACKGROUND_MODE_STRETCH] = "stretch",
"fit", [BACKGROUND_MODE_CENTER] = "center",
"tile", [BACKGROUND_MODE_FILL] = "fill",
[BACKGROUND_MODE_FIT] = "fit",
[BACKGROUND_MODE_TILE] = "tile",
}; };
static bool validate_color(const char *color) { static bool validate_color(const char *color) {
@ -47,27 +49,25 @@ struct cmd_results *output_cmd_background(int argc, char **argv) {
"Colors should be of the form #RRGGBB"); "Colors should be of the form #RRGGBB");
} }
if (!(output->background = strdup(argv[0]))) goto cleanup; if (!(output->background = strdup(argv[0]))) goto cleanup;
if (!(output->background_option = strdup("solid_color"))) goto cleanup; output->background_option = BACKGROUND_MODE_SOLID_COLOR;
output->background_fallback = NULL; output->background_fallback = NULL;
argc -= 2; argv += 2; argc -= 2; argv += 2;
} else { } else {
bool valid = false; enum background_mode mode = BACKGROUND_MODE_UNSET;
char *mode;
size_t j; size_t j;
for (j = 0; j < (size_t)argc; ++j) { for (j = 0; j < (size_t)argc; ++j) {
mode = argv[j]; size_t n = sizeof(background_mode_names) / sizeof(char *);
size_t n = sizeof(bg_options) / sizeof(char *);
for (size_t k = 0; k < n; ++k) { for (size_t k = 0; k < n; ++k) {
if (strcasecmp(mode, bg_options[k]) == 0) { if (strcasecmp(argv[j], background_mode_names[k]) == 0) {
valid = true; mode = k;
break; break;
} }
} }
if (valid) { if (mode != BACKGROUND_MODE_UNSET) {
break; break;
} }
} }
if (!valid) { if (mode == BACKGROUND_MODE_UNSET) {
return cmd_results_new(CMD_INVALID, return cmd_results_new(CMD_INVALID,
"Missing background scaling mode."); "Missing background scaling mode.");
} }
@ -104,10 +104,9 @@ struct cmd_results *output_cmd_background(int argc, char **argv) {
bool can_access = access(src, F_OK) != -1; bool can_access = access(src, F_OK) != -1;
argc -= j + 1; argv += j + 1; argc -= j + 1; argv += j + 1;
free(output->background_option);
free(output->background_fallback); free(output->background_fallback);
free(output->background); free(output->background);
output->background = output->background_option = output->background_fallback = NULL; output->background = output->background_fallback = NULL;
char *fallback = NULL; char *fallback = NULL;
if (argc && *argv[0] == '#') { if (argc && *argv[0] == '#') {
@ -132,11 +131,11 @@ struct cmd_results *output_cmd_background(int argc, char **argv) {
} }
sway_log(SWAY_DEBUG, "Cannot access file '%s', using fallback '%s'", src, fallback); sway_log(SWAY_DEBUG, "Cannot access file '%s', using fallback '%s'", src, fallback);
output->background = fallback; output->background = fallback;
if (!(output->background_option = strdup("solid_color"))) goto cleanup; output->background_option = BACKGROUND_MODE_SOLID_COLOR;
output->background_fallback = NULL; output->background_fallback = NULL;
} else { } else {
output->background = src; output->background = src;
if (!(output->background_option = strdup(mode))) goto cleanup; output->background_option = mode;
} }
} }
config->handler_context.leftovers.argc = argc; config->handler_context.leftovers.argc = argc;

View file

@ -133,9 +133,8 @@ static void supersede_output_config(struct output_config *dst, struct output_con
free(dst->background); free(dst->background);
dst->background = NULL; dst->background = NULL;
} }
if (src->background_option) { if (src->background_option != BACKGROUND_MODE_UNSET) {
free(dst->background_option); dst->background_option = BACKGROUND_MODE_UNSET;
dst->background_option = NULL;
} }
if (src->background_fallback) { if (src->background_fallback) {
free(dst->background_fallback); free(dst->background_fallback);
@ -205,9 +204,8 @@ static void merge_output_config(struct output_config *dst, struct output_config
free(dst->background); free(dst->background);
dst->background = strdup(src->background); dst->background = strdup(src->background);
} }
if (src->background_option) { if (src->background_option != BACKGROUND_MODE_UNSET) {
free(dst->background_option); dst->background_option = src->background_option;
dst->background_option = strdup(src->background_option);
} }
if (src->background_fallback) { if (src->background_fallback) {
free(dst->background_fallback); free(dst->background_fallback);
@ -264,7 +262,7 @@ void store_output_config(struct output_config *oc) {
"(max render time: %d) (allow tearing: %d)", "(max render time: %d) (allow tearing: %d)",
oc->name, oc->enabled, oc->width, oc->height, oc->refresh_rate, oc->name, oc->enabled, oc->width, oc->height, oc->refresh_rate,
oc->x, oc->y, oc->scale, sway_wl_output_subpixel_to_string(oc->subpixel), oc->x, oc->y, oc->scale, sway_wl_output_subpixel_to_string(oc->subpixel),
oc->transform, oc->background, oc->background_option, oc->power, oc->transform, oc->background, background_mode_names[oc->background_option], oc->power,
oc->max_render_time, oc->allow_tearing); oc->max_render_time, oc->allow_tearing);
// If the configuration was not merged into an existing configuration, add // If the configuration was not merged into an existing configuration, add
@ -1017,7 +1015,6 @@ void free_output_config(struct output_config *oc) {
} }
free(oc->name); free(oc->name);
free(oc->background); free(oc->background);
free(oc->background_option);
free(oc->background_fallback); free(oc->background_fallback);
wlr_color_transform_unref(oc->color_transform); wlr_color_transform_unref(oc->color_transform);
free(oc); free(oc);
@ -1032,7 +1029,7 @@ static void handle_swaybg_client_destroy(struct wl_listener *listener,
sway_config->swaybg_client = NULL; sway_config->swaybg_client = NULL;
} }
static bool _spawn_swaybg(char **command) { static bool _spawn_swaybg(const char **command) {
if (config->swaybg_client != NULL) { if (config->swaybg_client != NULL) {
wl_client_destroy(config->swaybg_client); wl_client_destroy(config->swaybg_client);
} }
@ -1076,7 +1073,7 @@ static bool _spawn_swaybg(char **command) {
"%d", sockets[1]); "%d", sockets[1]);
setenv("WAYLAND_SOCKET", wayland_socket_str, true); setenv("WAYLAND_SOCKET", wayland_socket_str, true);
execvp(command[0], command); execvp(command[0], (char *const *)command);
sway_log_errno(SWAY_ERROR, "failed to execute '%s' " sway_log_errno(SWAY_ERROR, "failed to execute '%s' "
"(background configuration probably not applied)", "(background configuration probably not applied)",
command[0]); command[0]);
@ -1109,7 +1106,7 @@ bool spawn_swaybg(void) {
if (!oc->background) { if (!oc->background) {
continue; continue;
} }
if (strcmp(oc->background_option, "solid_color") == 0) { if (oc->background_option == BACKGROUND_MODE_SOLID_COLOR) {
length += 4; length += 4;
} else if (oc->background_fallback) { } else if (oc->background_fallback) {
length += 8; length += 8;
@ -1118,7 +1115,7 @@ bool spawn_swaybg(void) {
} }
} }
char **cmd = calloc(length, sizeof(char *)); const char **cmd = calloc(length, sizeof(const char *));
if (!cmd) { if (!cmd) {
sway_log(SWAY_ERROR, "Failed to allocate spawn_swaybg command"); sway_log(SWAY_ERROR, "Failed to allocate spawn_swaybg command");
return false; return false;
@ -1131,7 +1128,7 @@ bool spawn_swaybg(void) {
if (!oc->background) { if (!oc->background) {
continue; continue;
} }
if (strcmp(oc->background_option, "solid_color") == 0) { if (oc->background_option == BACKGROUND_MODE_SOLID_COLOR) {
cmd[i++] = "-o"; cmd[i++] = "-o";
cmd[i++] = oc->name; cmd[i++] = oc->name;
cmd[i++] = "-c"; cmd[i++] = "-c";
@ -1142,7 +1139,7 @@ bool spawn_swaybg(void) {
cmd[i++] = "-i"; cmd[i++] = "-i";
cmd[i++] = oc->background; cmd[i++] = oc->background;
cmd[i++] = "-m"; cmd[i++] = "-m";
cmd[i++] = oc->background_option; cmd[i++] = background_mode_names[oc->background_option];
if (oc->background_fallback) { if (oc->background_fallback) {
cmd[i++] = "-c"; cmd[i++] = "-c";
cmd[i++] = oc->background_fallback; cmd[i++] = oc->background_fallback;