mirror of
https://github.com/swaywm/sway.git
synced 2025-11-24 06:59:51 -05:00
swaybg: one instance for all outputs
This makes it so there will only be one swaybg instance running instead of one per output. swaybg's cli has been changed to a xrandr like interface, where you select an output and then change properties for that output and then select another output and repeat. This also makes it so swaybg is only killed and respawned when a background changes or when reloading.
This commit is contained in:
parent
0ad905f23c
commit
75e7bd24cc
8 changed files with 497 additions and 251 deletions
|
|
@ -68,6 +68,8 @@ struct cmd_results *cmd_output(int argc, char **argv) {
|
|||
config->handler_context.leftovers.argc = 0;
|
||||
config->handler_context.leftovers.argv = NULL;
|
||||
|
||||
bool background = output->background;
|
||||
|
||||
output = store_output_config(output);
|
||||
|
||||
// If reloading, the output configs will be applied after reading the
|
||||
|
|
@ -75,6 +77,9 @@ struct cmd_results *cmd_output(int argc, char **argv) {
|
|||
// workspace name is not given to re-enabled outputs.
|
||||
if (!config->reloading) {
|
||||
apply_output_config_to_outputs(output);
|
||||
if (background) {
|
||||
spawn_swaybg();
|
||||
}
|
||||
}
|
||||
|
||||
return cmd_results_new(CMD_SUCCESS, NULL);
|
||||
|
|
|
|||
|
|
@ -104,6 +104,9 @@ void free_config(struct sway_config *config) {
|
|||
}
|
||||
list_free(config->output_configs);
|
||||
}
|
||||
if (config->swaybg_client != NULL) {
|
||||
wl_client_destroy(config->swaybg_client);
|
||||
}
|
||||
if (config->input_configs) {
|
||||
for (int i = 0; i < config->input_configs->length; i++) {
|
||||
free_input_config(config->input_configs->items[i]);
|
||||
|
|
@ -480,6 +483,7 @@ bool load_main_config(const char *file, bool is_active, bool validating) {
|
|||
|
||||
if (is_active) {
|
||||
reset_outputs();
|
||||
spawn_swaybg();
|
||||
|
||||
config->reloading = false;
|
||||
if (config->swaynag_config_errors.pid > 0) {
|
||||
|
|
|
|||
|
|
@ -228,91 +228,6 @@ static bool set_mode(struct wlr_output *output, int width, int height,
|
|||
return wlr_output_set_mode(output, best);
|
||||
}
|
||||
|
||||
static void handle_swaybg_client_destroy(struct wl_listener *listener,
|
||||
void *data) {
|
||||
struct sway_output *output =
|
||||
wl_container_of(listener, output, swaybg_client_destroy);
|
||||
wl_list_remove(&output->swaybg_client_destroy.link);
|
||||
wl_list_init(&output->swaybg_client_destroy.link);
|
||||
output->swaybg_client = NULL;
|
||||
}
|
||||
|
||||
static bool set_cloexec(int fd, bool cloexec) {
|
||||
int flags = fcntl(fd, F_GETFD);
|
||||
if (flags == -1) {
|
||||
sway_log_errno(SWAY_ERROR, "fcntl failed");
|
||||
return false;
|
||||
}
|
||||
if (cloexec) {
|
||||
flags = flags | FD_CLOEXEC;
|
||||
} else {
|
||||
flags = flags & ~FD_CLOEXEC;
|
||||
}
|
||||
if (fcntl(fd, F_SETFD, flags) == -1) {
|
||||
sway_log_errno(SWAY_ERROR, "fcntl failed");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool spawn_swaybg(struct sway_output *output, char *const cmd[]) {
|
||||
int sockets[2];
|
||||
if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) != 0) {
|
||||
sway_log_errno(SWAY_ERROR, "socketpair failed");
|
||||
return false;
|
||||
}
|
||||
if (!set_cloexec(sockets[0], true) || !set_cloexec(sockets[1], true)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
output->swaybg_client = wl_client_create(server.wl_display, sockets[0]);
|
||||
if (output->swaybg_client == NULL) {
|
||||
sway_log_errno(SWAY_ERROR, "wl_client_create failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
output->swaybg_client_destroy.notify = handle_swaybg_client_destroy;
|
||||
wl_client_add_destroy_listener(output->swaybg_client,
|
||||
&output->swaybg_client_destroy);
|
||||
|
||||
pid_t pid = fork();
|
||||
if (pid < 0) {
|
||||
sway_log_errno(SWAY_ERROR, "fork failed");
|
||||
return false;
|
||||
} else if (pid == 0) {
|
||||
pid = fork();
|
||||
if (pid < 0) {
|
||||
sway_log_errno(SWAY_ERROR, "fork failed");
|
||||
_exit(EXIT_FAILURE);
|
||||
} else if (pid == 0) {
|
||||
if (!set_cloexec(sockets[1], false)) {
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
char wayland_socket_str[16];
|
||||
snprintf(wayland_socket_str, sizeof(wayland_socket_str),
|
||||
"%d", sockets[1]);
|
||||
setenv("WAYLAND_SOCKET", wayland_socket_str, true);
|
||||
|
||||
execvp(cmd[0], cmd);
|
||||
sway_log_errno(SWAY_ERROR, "execvp failed");
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
_exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
if (close(sockets[1]) != 0) {
|
||||
sway_log_errno(SWAY_ERROR, "close failed");
|
||||
return false;
|
||||
}
|
||||
if (waitpid(pid, NULL, 0) < 0) {
|
||||
sway_log_errno(SWAY_ERROR, "waitpid failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool apply_output_config(struct output_config *oc, struct sway_output *output) {
|
||||
if (output == root->noop_output) {
|
||||
return false;
|
||||
|
|
@ -397,25 +312,6 @@ bool apply_output_config(struct output_config *oc, struct sway_output *output) {
|
|||
wlr_output_transformed_resolution(wlr_output,
|
||||
&output->width, &output->height);
|
||||
|
||||
if (output->swaybg_client != NULL) {
|
||||
wl_client_destroy(output->swaybg_client);
|
||||
}
|
||||
if (oc && oc->background && config->swaybg_command) {
|
||||
sway_log(SWAY_DEBUG, "Setting background for output %s to %s",
|
||||
wlr_output->name, oc->background);
|
||||
|
||||
char *const cmd[] = {
|
||||
config->swaybg_command,
|
||||
wlr_output->name,
|
||||
oc->background,
|
||||
oc->background_option,
|
||||
oc->background_fallback ? oc->background_fallback : NULL,
|
||||
NULL,
|
||||
};
|
||||
if (!spawn_swaybg(output, cmd)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (oc && oc->dpms_state == DPMS_OFF) {
|
||||
sway_log(SWAY_DEBUG, "Turning off screen");
|
||||
|
|
@ -584,3 +480,151 @@ void free_output_config(struct output_config *oc) {
|
|||
free(oc->background_option);
|
||||
free(oc);
|
||||
}
|
||||
|
||||
static void handle_swaybg_client_destroy(struct wl_listener *listener,
|
||||
void *data) {
|
||||
wl_list_remove(&config->swaybg_client_destroy.link);
|
||||
wl_list_init(&config->swaybg_client_destroy.link);
|
||||
config->swaybg_client = NULL;
|
||||
}
|
||||
|
||||
static bool set_cloexec(int fd, bool cloexec) {
|
||||
int flags = fcntl(fd, F_GETFD);
|
||||
if (flags == -1) {
|
||||
sway_log_errno(SWAY_ERROR, "fcntl failed");
|
||||
return false;
|
||||
}
|
||||
if (cloexec) {
|
||||
flags = flags | FD_CLOEXEC;
|
||||
} else {
|
||||
flags = flags & ~FD_CLOEXEC;
|
||||
}
|
||||
if (fcntl(fd, F_SETFD, flags) == -1) {
|
||||
sway_log_errno(SWAY_ERROR, "fcntl failed");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _spawn_swaybg(char **command) {
|
||||
if (config->swaybg_client != NULL) {
|
||||
wl_client_destroy(config->swaybg_client);
|
||||
}
|
||||
int sockets[2];
|
||||
if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) != 0) {
|
||||
sway_log_errno(SWAY_ERROR, "socketpair failed");
|
||||
return false;
|
||||
}
|
||||
if (!set_cloexec(sockets[0], true) || !set_cloexec(sockets[1], true)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
config->swaybg_client = wl_client_create(server.wl_display, sockets[0]);
|
||||
if (config->swaybg_client == NULL) {
|
||||
sway_log_errno(SWAY_ERROR, "wl_client_create failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
config->swaybg_client_destroy.notify = handle_swaybg_client_destroy;
|
||||
wl_client_add_destroy_listener(config->swaybg_client,
|
||||
&config->swaybg_client_destroy);
|
||||
|
||||
pid_t pid = fork();
|
||||
if (pid < 0) {
|
||||
sway_log_errno(SWAY_ERROR, "fork failed");
|
||||
return false;
|
||||
} else if (pid == 0) {
|
||||
pid = fork();
|
||||
if (pid < 0) {
|
||||
sway_log_errno(SWAY_ERROR, "fork failed");
|
||||
_exit(EXIT_FAILURE);
|
||||
} else if (pid == 0) {
|
||||
if (!set_cloexec(sockets[1], false)) {
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
char wayland_socket_str[16];
|
||||
snprintf(wayland_socket_str, sizeof(wayland_socket_str),
|
||||
"%d", sockets[1]);
|
||||
setenv("WAYLAND_SOCKET", wayland_socket_str, true);
|
||||
|
||||
execvp(command[0], command);
|
||||
sway_log_errno(SWAY_ERROR, "execvp failed");
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
_exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
if (close(sockets[1]) != 0) {
|
||||
sway_log_errno(SWAY_ERROR, "close failed");
|
||||
return false;
|
||||
}
|
||||
if (waitpid(pid, NULL, 0) < 0) {
|
||||
sway_log_errno(SWAY_ERROR, "waitpid failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool spawn_swaybg(void) {
|
||||
if (!config->swaybg_command) {
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t length = 2;
|
||||
for (int i = 0; i < config->output_configs->length; i++) {
|
||||
struct output_config *oc = config->output_configs->items[i];
|
||||
if (!oc->background) {
|
||||
continue;
|
||||
}
|
||||
if (strcmp(oc->background_option, "solid_color") == 0) {
|
||||
length += 4;
|
||||
} else if (oc->background_fallback) {
|
||||
length += 8;
|
||||
} else {
|
||||
length += 6;
|
||||
}
|
||||
}
|
||||
|
||||
char **cmd = calloc(1, sizeof(char **) * length);
|
||||
if (!cmd) {
|
||||
sway_log(SWAY_ERROR, "Failed to allocate spawn_swaybg command");
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t i = 0;
|
||||
cmd[i++] = config->swaybg_command;
|
||||
for (int j = 0; j < config->output_configs->length; j++) {
|
||||
struct output_config *oc = config->output_configs->items[j];
|
||||
if (!oc->background) {
|
||||
continue;
|
||||
}
|
||||
if (strcmp(oc->background_option, "solid_color") == 0) {
|
||||
cmd[i++] = "-o";
|
||||
cmd[i++] = oc->name;
|
||||
cmd[i++] = "-c";
|
||||
cmd[i++] = oc->background;
|
||||
} else {
|
||||
cmd[i++] = "-o";
|
||||
cmd[i++] = oc->name;
|
||||
cmd[i++] = "-i";
|
||||
cmd[i++] = oc->background;
|
||||
cmd[i++] = "-m";
|
||||
cmd[i++] = oc->background_option;
|
||||
if (oc->background_fallback) {
|
||||
cmd[i++] = "-c";
|
||||
cmd[i++] = oc->background_fallback;
|
||||
}
|
||||
}
|
||||
assert(i <= length);
|
||||
}
|
||||
|
||||
for (size_t k = 0; k < i; k++) {
|
||||
sway_log(SWAY_DEBUG, "spawn_swaybg cmd[%ld] = %s", k, cmd[k]);
|
||||
}
|
||||
|
||||
bool result = _spawn_swaybg(cmd);
|
||||
free(cmd);
|
||||
return result;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -525,7 +525,6 @@ static void handle_destroy(struct wl_listener *listener, void *data) {
|
|||
wl_list_remove(&output->present.link);
|
||||
wl_list_remove(&output->damage_destroy.link);
|
||||
wl_list_remove(&output->damage_frame.link);
|
||||
wl_list_remove(&output->swaybg_client_destroy.link);
|
||||
|
||||
transaction_commit_dirty();
|
||||
}
|
||||
|
|
@ -632,7 +631,6 @@ void handle_new_output(struct wl_listener *listener, void *data) {
|
|||
output->damage_frame.notify = damage_handle_frame;
|
||||
wl_signal_add(&output->damage->events.destroy, &output->damage_destroy);
|
||||
output->damage_destroy.notify = damage_handle_destroy;
|
||||
wl_list_init(&output->swaybg_client_destroy.link);
|
||||
|
||||
struct output_config *oc = find_output_config(output);
|
||||
if (!oc || oc->enabled) {
|
||||
|
|
|
|||
|
|
@ -262,10 +262,6 @@ void output_disable(struct sway_output *output) {
|
|||
|
||||
root_for_each_container(untrack_output, output);
|
||||
|
||||
if (output->swaybg_client != NULL) {
|
||||
wl_client_destroy(output->swaybg_client);
|
||||
}
|
||||
|
||||
int index = list_find(root->outputs, output);
|
||||
list_del(root->outputs, index);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue