aboutsummaryrefslogtreecommitdiffstats
path: root/sway/config/bar.c
diff options
context:
space:
mode:
Diffstat (limited to 'sway/config/bar.c')
-rw-r--r--sway/config/bar.c240
1 files changed, 240 insertions, 0 deletions
diff --git a/sway/config/bar.c b/sway/config/bar.c
new file mode 100644
index 00000000..2913f059
--- /dev/null
+++ b/sway/config/bar.c
@@ -0,0 +1,240 @@
1#define _POSIX_C_SOURCE 200809L
2#define _XOPEN_SOURCE 700
3#include <stdio.h>
4#include <stdbool.h>
5#include <stdlib.h>
6#include <unistd.h>
7#include <wordexp.h>
8#include <sys/types.h>
9#include <sys/wait.h>
10#include <sys/stat.h>
11#include <signal.h>
12#include <strings.h>
13#include "sway/config.h"
14#include "stringop.h"
15#include "list.h"
16#include "log.h"
17
18static void terminate_swaybar(pid_t pid) {
19 wlr_log(L_DEBUG, "Terminating swaybar %d", pid);
20 int ret = kill(pid, SIGTERM);
21 if (ret != 0) {
22 wlr_log_errno(L_ERROR, "Unable to terminate swaybar %d", pid);
23 } else {
24 int status;
25 waitpid(pid, &status, 0);
26 }
27}
28
29void free_bar_config(struct bar_config *bar) {
30 if (!bar) {
31 return;
32 }
33 free(bar->mode);
34 free(bar->position);
35 free(bar->hidden_state);
36 free(bar->status_command);
37 free(bar->font);
38 free(bar->separator_symbol);
39 // TODO: Free mouse bindings
40 list_free(bar->bindings);
41 if (bar->outputs) {
42 free_flat_list(bar->outputs);
43 }
44 if (bar->pid != 0) {
45 terminate_swaybar(bar->pid);
46 }
47 free(bar->colors.background);
48 free(bar->colors.statusline);
49 free(bar->colors.separator);
50 free(bar->colors.focused_background);
51 free(bar->colors.focused_statusline);
52 free(bar->colors.focused_separator);
53 free(bar->colors.focused_workspace_border);
54 free(bar->colors.focused_workspace_bg);
55 free(bar->colors.focused_workspace_text);
56 free(bar->colors.active_workspace_border);
57 free(bar->colors.active_workspace_bg);
58 free(bar->colors.active_workspace_text);
59 free(bar->colors.inactive_workspace_border);
60 free(bar->colors.inactive_workspace_bg);
61 free(bar->colors.inactive_workspace_text);
62 free(bar->colors.urgent_workspace_border);
63 free(bar->colors.urgent_workspace_bg);
64 free(bar->colors.urgent_workspace_text);
65 free(bar->colors.binding_mode_border);
66 free(bar->colors.binding_mode_bg);
67 free(bar->colors.binding_mode_text);
68 free(bar);
69}
70
71struct bar_config *default_bar_config(void) {
72 struct bar_config *bar = NULL;
73 bar = malloc(sizeof(struct bar_config));
74 if (!bar) {
75 return NULL;
76 }
77 if (!(bar->mode = strdup("dock"))) goto cleanup;
78 if (!(bar->hidden_state = strdup("hide"))) goto cleanup;
79 bar->outputs = NULL;
80 bar->position = strdup("bottom");
81 if (!(bar->bindings = create_list())) goto cleanup;
82 if (!(bar->status_command = strdup("while :; do date +'%Y-%m-%d %l:%M:%S %p'; sleep 1; done"))) goto cleanup;
83 bar->pango_markup = false;
84 bar->swaybar_command = NULL;
85 bar->font = NULL;
86 bar->height = -1;
87 bar->workspace_buttons = true;
88 bar->wrap_scroll = false;
89 bar->separator_symbol = NULL;
90 bar->strip_workspace_numbers = false;
91 bar->binding_mode_indicator = true;
92 bar->verbose = false;
93 bar->pid = 0;
94 // set default colors
95 if (!(bar->colors.background = strndup("#000000ff", 9))) {
96 goto cleanup;
97 }
98 if (!(bar->colors.statusline = strndup("#ffffffff", 9))) {
99 goto cleanup;
100 }
101 if (!(bar->colors.separator = strndup("#666666ff", 9))) {
102 goto cleanup;
103 }
104 if (!(bar->colors.focused_workspace_border = strndup("#4c7899ff", 9))) {
105 goto cleanup;
106 }
107 if (!(bar->colors.focused_workspace_bg = strndup("#285577ff", 9))) {
108 goto cleanup;
109 }
110 if (!(bar->colors.focused_workspace_text = strndup("#ffffffff", 9))) {
111 goto cleanup;
112 }
113 if (!(bar->colors.active_workspace_border = strndup("#333333ff", 9))) {
114 goto cleanup;
115 }
116 if (!(bar->colors.active_workspace_bg = strndup("#5f676aff", 9))) {
117 goto cleanup;
118 }
119 if (!(bar->colors.active_workspace_text = strndup("#ffffffff", 9))) {
120 goto cleanup;
121 }
122 if (!(bar->colors.inactive_workspace_border = strndup("#333333ff", 9))) {
123 goto cleanup;
124 }
125 if (!(bar->colors.inactive_workspace_bg = strndup("#222222ff", 9))) {
126 goto cleanup;
127 }
128 if (!(bar->colors.inactive_workspace_text = strndup("#888888ff", 9))) {
129 goto cleanup;
130 }
131 if (!(bar->colors.urgent_workspace_border = strndup("#2f343aff", 9))) {
132 goto cleanup;
133 }
134 if (!(bar->colors.urgent_workspace_bg = strndup("#900000ff", 9))) {
135 goto cleanup;
136 }
137 if (!(bar->colors.urgent_workspace_text = strndup("#ffffffff", 9))) {
138 goto cleanup;
139 }
140 // if the following colors stay undefined, they fall back to background,
141 // statusline, separator and urgent_workspace_*.
142 bar->colors.focused_background = NULL;
143 bar->colors.focused_statusline = NULL;
144 bar->colors.focused_separator = NULL;
145 bar->colors.binding_mode_border = NULL;
146 bar->colors.binding_mode_bg = NULL;
147 bar->colors.binding_mode_text = NULL;
148
149 list_add(config->bars, bar);
150 return bar;
151cleanup:
152 free_bar_config(bar);
153 return NULL;
154}
155
156void invoke_swaybar(struct bar_config *bar) {
157 // Pipe to communicate errors
158 int filedes[2];
159 if (pipe(filedes) == -1) {
160 wlr_log(L_ERROR, "Pipe setup failed! Cannot fork into bar");
161 return;
162 }
163
164 bar->pid = fork();
165 if (bar->pid == 0) {
166 close(filedes[0]);
167
168 // run custom swaybar
169 size_t len = snprintf(NULL, 0, "%s -b %s",
170 bar->swaybar_command ? bar->swaybar_command : "swaybar",
171 bar->id);
172 char *command = malloc(len + 1);
173 if (!command) {
174 const char msg[] = "Unable to allocate swaybar command string";
175 size_t len = sizeof(msg);
176 if (write(filedes[1], &len, sizeof(int))) {};
177 if (write(filedes[1], msg, len)) {};
178 close(filedes[1]);
179 exit(1);
180 }
181 snprintf(command, len + 1, "%s -b %s",
182 bar->swaybar_command ? bar->swaybar_command : "swaybar",
183 bar->id);
184 char *const cmd[] = { "sh", "-c", command, NULL, };
185 close(filedes[1]);
186 execvp(cmd[0], cmd);
187 exit(1);
188 }
189 wlr_log(L_DEBUG, "Spawned swaybar %d", bar->pid);
190 close(filedes[0]);
191 ssize_t len;
192 if (read(filedes[1], &len, sizeof(int)) == sizeof(int)) {
193 char *buf = malloc(len);
194 if(!buf) {
195 wlr_log(L_ERROR, "Cannot allocate error string");
196 return;
197 }
198 if (read(filedes[1], buf, len)) {
199 wlr_log(L_ERROR, "%s", buf);
200 }
201 free(buf);
202 }
203 close(filedes[1]);
204}
205
206static bool active_output(const char *name) {
207 struct sway_container *cont = NULL;
208 for (int i = 0; i < root_container.children->length; ++i) {
209 cont = root_container.children->items[i];
210 if (cont->type == C_OUTPUT && strcasecmp(name, cont->name) == 0) {
211 return true;
212 }
213 }
214 return false;
215}
216
217void load_swaybars() {
218 for (int i = 0; i < config->bars->length; ++i) {
219 struct bar_config *bar = config->bars->items[i];
220 bool apply = false;
221 if (bar->outputs) {
222 for (int j = 0; j < bar->outputs->length; ++j) {
223 char *o = bar->outputs->items[j];
224 if (!strcmp(o, "*") || active_output(o)) {
225 apply = true;
226 break;
227 }
228 }
229 } else {
230 apply = true;
231 }
232 if (apply) {
233 if (bar->pid != 0) {
234 terminate_swaybar(bar->pid);
235 }
236 wlr_log(L_DEBUG, "Invoking swaybar for bar id '%s'", bar->id);
237 invoke_swaybar(bar);
238 }
239 }
240}