b997147284
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.
273 lines
7.1 KiB
C
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);
|
|
}
|
|
}
|