swayfx/sway/config/bar.c
Daniel Otero b997147284 config: Fix swaybar pango_markup inconsistency
Until now, swaybar did not have pango markup enabled by default, even if
the sway config had it on. This patch aims to mimic the i3 behavior, but
maintaining the functionality of the "pango_markup" sway config command.
2021-06-03 14:18:23 +02:00

273 lines
7.1 KiB
C

#define _POSIX_C_SOURCE 200809L
#include <signal.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <wordexp.h>
#include "sway/config.h"
#include "sway/input/keyboard.h"
#include "sway/output.h"
#include "config.h"
#include "list.h"
#include "log.h"
#include "stringop.h"
#include "util.h"
void free_bar_binding(struct bar_binding *binding) {
if (!binding) {
return;
}
free(binding->command);
free(binding);
}
void free_bar_config(struct bar_config *bar) {
if (!bar) {
return;
}
free(bar->id);
free(bar->mode);
free(bar->position);
free(bar->hidden_state);
free(bar->status_command);
free(bar->swaybar_command);
free(bar->font);
free(bar->separator_symbol);
if (bar->bindings) {
for (int i = 0; i < bar->bindings->length; i++) {
free_bar_binding(bar->bindings->items[i]);
}
}
list_free(bar->bindings);
list_free_items_and_destroy(bar->outputs);
if (bar->client != NULL) {
wl_client_destroy(bar->client);
}
free(bar->colors.background);
free(bar->colors.statusline);
free(bar->colors.separator);
free(bar->colors.focused_background);
free(bar->colors.focused_statusline);
free(bar->colors.focused_separator);
free(bar->colors.focused_workspace_border);
free(bar->colors.focused_workspace_bg);
free(bar->colors.focused_workspace_text);
free(bar->colors.active_workspace_border);
free(bar->colors.active_workspace_bg);
free(bar->colors.active_workspace_text);
free(bar->colors.inactive_workspace_border);
free(bar->colors.inactive_workspace_bg);
free(bar->colors.inactive_workspace_text);
free(bar->colors.urgent_workspace_border);
free(bar->colors.urgent_workspace_bg);
free(bar->colors.urgent_workspace_text);
free(bar->colors.binding_mode_border);
free(bar->colors.binding_mode_bg);
free(bar->colors.binding_mode_text);
#if HAVE_TRAY
list_free_items_and_destroy(bar->tray_outputs);
free(bar->icon_theme);
struct tray_binding *tray_bind = NULL, *tmp_tray_bind = NULL;
wl_list_for_each_safe(tray_bind, tmp_tray_bind, &bar->tray_bindings, link) {
wl_list_remove(&tray_bind->link);
free(tray_bind);
}
#endif
free(bar);
}
struct bar_config *default_bar_config(void) {
struct bar_config *bar = NULL;
bar = calloc(1, sizeof(struct bar_config));
if (!bar) {
return NULL;
}
bar->outputs = NULL;
bar->position = strdup("bottom");
bar->pango_markup = PANGO_MARKUP_DEFAULT;
bar->swaybar_command = NULL;
bar->font = NULL;
bar->height = 0;
bar->workspace_buttons = true;
bar->wrap_scroll = false;
bar->separator_symbol = NULL;
bar->strip_workspace_numbers = false;
bar->strip_workspace_name = false;
bar->binding_mode_indicator = true;
bar->verbose = false;
bar->modifier = get_modifier_mask_by_name("Mod4");
bar->status_padding = 1;
bar->status_edge_padding = 3;
bar->workspace_min_width = 0;
if (!(bar->mode = strdup("dock"))) {
goto cleanup;
}
if (!(bar->hidden_state = strdup("hide"))) {
goto cleanup;
}
if (!(bar->bindings = create_list())) {
goto cleanup;
}
// set default colors
if (!(bar->colors.background = strndup("#000000ff", 9))) {
goto cleanup;
}
if (!(bar->colors.statusline = strndup("#ffffffff", 9))) {
goto cleanup;
}
if (!(bar->colors.separator = strndup("#666666ff", 9))) {
goto cleanup;
}
if (!(bar->colors.focused_workspace_border = strndup("#4c7899ff", 9))) {
goto cleanup;
}
if (!(bar->colors.focused_workspace_bg = strndup("#285577ff", 9))) {
goto cleanup;
}
if (!(bar->colors.focused_workspace_text = strndup("#ffffffff", 9))) {
goto cleanup;
}
if (!(bar->colors.active_workspace_border = strndup("#333333ff", 9))) {
goto cleanup;
}
if (!(bar->colors.active_workspace_bg = strndup("#5f676aff", 9))) {
goto cleanup;
}
if (!(bar->colors.active_workspace_text = strndup("#ffffffff", 9))) {
goto cleanup;
}
if (!(bar->colors.inactive_workspace_border = strndup("#333333ff", 9))) {
goto cleanup;
}
if (!(bar->colors.inactive_workspace_bg = strndup("#222222ff", 9))) {
goto cleanup;
}
if (!(bar->colors.inactive_workspace_text = strndup("#888888ff", 9))) {
goto cleanup;
}
if (!(bar->colors.urgent_workspace_border = strndup("#2f343aff", 9))) {
goto cleanup;
}
if (!(bar->colors.urgent_workspace_bg = strndup("#900000ff", 9))) {
goto cleanup;
}
if (!(bar->colors.urgent_workspace_text = strndup("#ffffffff", 9))) {
goto cleanup;
}
// if the following colors stay undefined, they fall back to background,
// statusline, separator and urgent_workspace_*.
bar->colors.focused_background = NULL;
bar->colors.focused_statusline = NULL;
bar->colors.focused_separator = NULL;
bar->colors.binding_mode_border = NULL;
bar->colors.binding_mode_bg = NULL;
bar->colors.binding_mode_text = NULL;
#if HAVE_TRAY
bar->tray_padding = 2;
wl_list_init(&bar->tray_bindings);
#endif
return bar;
cleanup:
free_bar_config(bar);
return NULL;
}
static void handle_swaybar_client_destroy(struct wl_listener *listener,
void *data) {
struct bar_config *bar = wl_container_of(listener, bar, client_destroy);
wl_list_remove(&bar->client_destroy.link);
wl_list_init(&bar->client_destroy.link);
bar->client = NULL;
}
static void invoke_swaybar(struct bar_config *bar) {
int sockets[2];
if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) != 0) {
sway_log_errno(SWAY_ERROR, "socketpair failed");
return;
}
if (!sway_set_cloexec(sockets[0], true) || !sway_set_cloexec(sockets[1], true)) {
return;
}
bar->client = wl_client_create(server.wl_display, sockets[0]);
if (bar->client == NULL) {
sway_log_errno(SWAY_ERROR, "wl_client_create failed");
return;
}
bar->client_destroy.notify = handle_swaybar_client_destroy;
wl_client_add_destroy_listener(bar->client, &bar->client_destroy);
pid_t pid = fork();
if (pid < 0) {
sway_log(SWAY_ERROR, "Failed to create fork for swaybar");
return;
} else if (pid == 0) {
// Remove the SIGUSR1 handler that wlroots adds for xwayland
sigset_t set;
sigemptyset(&set);
sigprocmask(SIG_SETMASK, &set, NULL);
pid = fork();
if (pid < 0) {
sway_log_errno(SWAY_ERROR, "fork failed");
_exit(EXIT_FAILURE);
} else if (pid == 0) {
if (!sway_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);
// run custom swaybar
char *const cmd[] = {
bar->swaybar_command ? bar->swaybar_command : "swaybar",
"-b", bar->id, NULL};
execvp(cmd[0], cmd);
_exit(EXIT_FAILURE);
}
_exit(EXIT_SUCCESS);
}
if (close(sockets[1]) != 0) {
sway_log_errno(SWAY_ERROR, "close failed");
return;
}
if (waitpid(pid, NULL, 0) < 0) {
sway_log_errno(SWAY_ERROR, "waitpid failed");
return;
}
sway_log(SWAY_DEBUG, "Spawned swaybar %s", bar->id);
return;
}
void load_swaybar(struct bar_config *bar) {
if (bar->client != NULL) {
wl_client_destroy(bar->client);
}
sway_log(SWAY_DEBUG, "Invoking swaybar for bar id '%s'", bar->id);
invoke_swaybar(bar);
}
void load_swaybars(void) {
for (int i = 0; i < config->bars->length; ++i) {
struct bar_config *bar = config->bars->items[i];
load_swaybar(bar);
}
}