summaryrefslogtreecommitdiffstats
path: root/swaybar
diff options
context:
space:
mode:
authorLibravatar Mikkel Oscar Lyderik <mikkeloscar@gmail.com>2016-01-24 00:23:09 +0100
committerLibravatar Mikkel Oscar Lyderik <mikkeloscar@gmail.com>2016-01-24 14:22:19 +0100
commitfcc47cb3bddd20a2fd068a4e486415112e4d4d20 (patch)
treee75ee1a9a744f6954ae8b2a53c69b8de0c0391a4 /swaybar
parentswaybar: feactor render, statusline (diff)
downloadsway-fcc47cb3bddd20a2fd068a4e486415112e4d4d20.tar.gz
sway-fcc47cb3bddd20a2fd068a4e486415112e4d4d20.tar.zst
sway-fcc47cb3bddd20a2fd068a4e486415112e4d4d20.zip
swaybar: move ipc stuff to ipc.{h,c}
Diffstat (limited to 'swaybar')
-rw-r--r--swaybar/CMakeLists.txt1
-rw-r--r--swaybar/config.c10
-rw-r--r--swaybar/config.h6
-rw-r--r--swaybar/ipc.c259
-rw-r--r--swaybar/ipc.h17
-rw-r--r--swaybar/main.c255
-rw-r--r--swaybar/render.c65
-rw-r--r--swaybar/render.h5
-rw-r--r--swaybar/state.c1
-rw-r--r--swaybar/state.h1
-rw-r--r--swaybar/status_line.c40
11 files changed, 359 insertions, 301 deletions
diff --git a/swaybar/CMakeLists.txt b/swaybar/CMakeLists.txt
index ebb3819b..474d8474 100644
--- a/swaybar/CMakeLists.txt
+++ b/swaybar/CMakeLists.txt
@@ -12,6 +12,7 @@ add_executable(swaybar
12 render.c 12 render.c
13 state.c 13 state.c
14 status_line.c 14 status_line.c
15 ipc.c
15) 16)
16 17
17target_link_libraries(swaybar 18target_link_libraries(swaybar
diff --git a/swaybar/config.c b/swaybar/config.c
index 388daa55..7c03198a 100644
--- a/swaybar/config.c
+++ b/swaybar/config.c
@@ -45,19 +45,15 @@ struct swaybar_config *init_config() {
45 struct swaybar_config *config = calloc(1, sizeof(struct swaybar_config)); 45 struct swaybar_config *config = calloc(1, sizeof(struct swaybar_config));
46 config->status_command = NULL; 46 config->status_command = NULL;
47 config->position = DESKTOP_SHELL_PANEL_POSITION_BOTTOM; 47 config->position = DESKTOP_SHELL_PANEL_POSITION_BOTTOM;
48 config->font = NULL; 48 config->font = strdup("monospace 10");
49 config->mode = NULL; 49 config->mode = NULL;
50 config->sep_symbol = NULL; 50 config->sep_symbol = NULL;
51 config->strip_workspace_numbers = false; 51 config->strip_workspace_numbers = false;
52 config->binding_mode_indicator = true; 52 config->binding_mode_indicator = true;
53 config->workspace_buttons = true; 53 config->workspace_buttons = true;
54 54
55 /* layout */ 55 /* height */
56 config->margin = 3; 56 config->height = 0;
57 config->ws_horizontal_padding = 5;
58 config->ws_vertical_padding = 1.5;
59 config->ws_spacing = 1;
60 config->text_height = 30;
61 57
62 /* colors */ 58 /* colors */
63 config->colors.background = 0x000000FF; 59 config->colors.background = 0x000000FF;
diff --git a/swaybar/config.h b/swaybar/config.h
index 5cda97e6..ee06668e 100644
--- a/swaybar/config.h
+++ b/swaybar/config.h
@@ -26,11 +26,7 @@ struct swaybar_config {
26 bool binding_mode_indicator; 26 bool binding_mode_indicator;
27 bool workspace_buttons; 27 bool workspace_buttons;
28 28
29 int margin; 29 int height;
30 int ws_horizontal_padding;
31 double ws_vertical_padding;
32 int ws_spacing;
33 int text_height;
34 30
35 struct { 31 struct {
36 uint32_t background; 32 uint32_t background;
diff --git a/swaybar/ipc.c b/swaybar/ipc.c
new file mode 100644
index 00000000..cb0b81aa
--- /dev/null
+++ b/swaybar/ipc.c
@@ -0,0 +1,259 @@
1#include <string.h>
2#include <json-c/json.h>
3
4#include "ipc-client.h"
5#include "list.h"
6#include "log.h"
7#include "config.h"
8#include "ipc.h"
9
10static void ipc_parse_config(struct swaybar_config *config, const char *payload) {
11 json_object *bar_config = json_tokener_parse(payload);
12 json_object *tray_output, *mode, *hidden_state, *position, *status_command;
13 json_object *font, *bar_height, *workspace_buttons, *strip_workspace_numbers;
14 json_object *binding_mode_indicator, *verbose, *colors, *sep_symbol;
15 json_object_object_get_ex(bar_config, "tray_output", &tray_output);
16 json_object_object_get_ex(bar_config, "mode", &mode);
17 json_object_object_get_ex(bar_config, "hidden_state", &hidden_state);
18 json_object_object_get_ex(bar_config, "position", &position);
19 json_object_object_get_ex(bar_config, "status_command", &status_command);
20 json_object_object_get_ex(bar_config, "font", &font);
21 json_object_object_get_ex(bar_config, "bar_height", &bar_height);
22 json_object_object_get_ex(bar_config, "workspace_buttons", &workspace_buttons);
23 json_object_object_get_ex(bar_config, "strip_workspace_numbers", &strip_workspace_numbers);
24 json_object_object_get_ex(bar_config, "binding_mode_indicator", &binding_mode_indicator);
25 json_object_object_get_ex(bar_config, "verbose", &verbose);
26 json_object_object_get_ex(bar_config, "separator_symbol", &sep_symbol);
27 json_object_object_get_ex(bar_config, "colors", &colors);
28
29 if (status_command) {
30 free(config->status_command);
31 config->status_command = strdup(json_object_get_string(status_command));
32 }
33
34 if (position) {
35 config->position = parse_position(json_object_get_string(position));
36 }
37
38 if (font) {
39 free(config->font);
40 config->font = parse_font(json_object_get_string(font));
41 }
42
43 if (sep_symbol) {
44 free(config->sep_symbol);
45 config->sep_symbol = strdup(json_object_get_string(sep_symbol));
46 }
47
48 if (strip_workspace_numbers) {
49 config->strip_workspace_numbers = json_object_get_boolean(strip_workspace_numbers);
50 }
51
52 if (binding_mode_indicator) {
53 config->binding_mode_indicator = json_object_get_boolean(binding_mode_indicator);
54 }
55
56 if (workspace_buttons) {
57 config->workspace_buttons = json_object_get_boolean(workspace_buttons);
58 }
59
60 if (bar_height) {
61 config->height = json_object_get_int(bar_height);
62 }
63
64 if (colors) {
65 json_object *background, *statusline, *separator;
66 json_object *focused_workspace_border, *focused_workspace_bg, *focused_workspace_text;
67 json_object *inactive_workspace_border, *inactive_workspace_bg, *inactive_workspace_text;
68 json_object *active_workspace_border, *active_workspace_bg, *active_workspace_text;
69 json_object *urgent_workspace_border, *urgent_workspace_bg, *urgent_workspace_text;
70 json_object *binding_mode_border, *binding_mode_bg, *binding_mode_text;
71 json_object_object_get_ex(colors, "background", &background);
72 json_object_object_get_ex(colors, "statusline", &statusline);
73 json_object_object_get_ex(colors, "separator", &separator);
74 json_object_object_get_ex(colors, "focused_workspace_border", &focused_workspace_border);
75 json_object_object_get_ex(colors, "focused_workspace_bg", &focused_workspace_bg);
76 json_object_object_get_ex(colors, "focused_workspace_text", &focused_workspace_text);
77 json_object_object_get_ex(colors, "active_workspace_border", &active_workspace_border);
78 json_object_object_get_ex(colors, "active_workspace_bg", &active_workspace_bg);
79 json_object_object_get_ex(colors, "active_workspace_text", &active_workspace_text);
80 json_object_object_get_ex(colors, "inactive_workspace_border", &inactive_workspace_border);
81 json_object_object_get_ex(colors, "inactive_workspace_bg", &inactive_workspace_bg);
82 json_object_object_get_ex(colors, "inactive_workspace_text", &inactive_workspace_text);
83 json_object_object_get_ex(colors, "urgent_workspace_border", &urgent_workspace_border);
84 json_object_object_get_ex(colors, "urgent_workspace_bg", &urgent_workspace_bg);
85 json_object_object_get_ex(colors, "urgent_workspace_text", &urgent_workspace_text);
86 json_object_object_get_ex(colors, "binding_mode_border", &binding_mode_border);
87 json_object_object_get_ex(colors, "binding_mode_bg", &binding_mode_bg);
88 json_object_object_get_ex(colors, "binding_mode_text", &binding_mode_text);
89 if (background) {
90 config->colors.background = parse_color(json_object_get_string(background));
91 }
92
93 if (statusline) {
94 config->colors.statusline = parse_color(json_object_get_string(statusline));
95 }
96
97 if (separator) {
98 config->colors.separator = parse_color(json_object_get_string(separator));
99 }
100
101 if (focused_workspace_border) {
102 config->colors.focused_workspace.border = parse_color(json_object_get_string(focused_workspace_border));
103 }
104
105 if (focused_workspace_bg) {
106 config->colors.focused_workspace.background = parse_color(json_object_get_string(focused_workspace_bg));
107 }
108
109 if (focused_workspace_text) {
110 config->colors.focused_workspace.text = parse_color(json_object_get_string(focused_workspace_text));
111 }
112
113 if (active_workspace_border) {
114 config->colors.active_workspace.border = parse_color(json_object_get_string(active_workspace_border));
115 }
116
117 if (active_workspace_bg) {
118 config->colors.active_workspace.background = parse_color(json_object_get_string(active_workspace_bg));
119 }
120
121 if (active_workspace_text) {
122 config->colors.active_workspace.text = parse_color(json_object_get_string(active_workspace_text));
123 }
124
125 if (inactive_workspace_border) {
126 config->colors.inactive_workspace.border = parse_color(json_object_get_string(inactive_workspace_border));
127 }
128
129 if (inactive_workspace_bg) {
130 config->colors.inactive_workspace.background = parse_color(json_object_get_string(inactive_workspace_bg));
131 }
132
133 if (inactive_workspace_text) {
134 config->colors.inactive_workspace.text = parse_color(json_object_get_string(inactive_workspace_text));
135 }
136
137 if (binding_mode_border) {
138 config->colors.binding_mode.border = parse_color(json_object_get_string(binding_mode_border));
139 }
140
141 if (binding_mode_bg) {
142 config->colors.binding_mode.background = parse_color(json_object_get_string(binding_mode_bg));
143 }
144
145 if (binding_mode_text) {
146 config->colors.binding_mode.text = parse_color(json_object_get_string(binding_mode_text));
147 }
148 }
149
150 json_object_put(bar_config);
151}
152
153static void ipc_update_workspaces(struct swaybar_state *state) {
154 if (state->output->workspaces) {
155 list_foreach(state->output->workspaces, free_workspace);
156 list_free(state->output->workspaces);
157 }
158 state->output->workspaces = create_list();
159
160 uint32_t len = 0;
161 char *res = ipc_single_command(state->ipc_socketfd, IPC_GET_WORKSPACES, NULL, &len);
162 json_object *results = json_tokener_parse(res);
163 if (!results) {
164 free(res);
165 return;
166 }
167
168 int i;
169 int length = json_object_array_length(results);
170 json_object *ws_json;
171 json_object *num, *name, *visible, *focused, *out, *urgent;
172 for (i = 0; i < length; ++i) {
173 ws_json = json_object_array_get_idx(results, i);
174
175 json_object_object_get_ex(ws_json, "num", &num);
176 json_object_object_get_ex(ws_json, "name", &name);
177 json_object_object_get_ex(ws_json, "visible", &visible);
178 json_object_object_get_ex(ws_json, "focused", &focused);
179 json_object_object_get_ex(ws_json, "output", &out);
180 json_object_object_get_ex(ws_json, "urgent", &urgent);
181
182 if (strcmp(json_object_get_string(out), state->output->name) == 0) {
183 struct workspace *ws = malloc(sizeof(struct workspace));
184 ws->num = json_object_get_int(num);
185 ws->name = strdup(json_object_get_string(name));
186 ws->visible = json_object_get_boolean(visible);
187 ws->focused = json_object_get_boolean(focused);
188 ws->urgent = json_object_get_boolean(urgent);
189 list_add(state->output->workspaces, ws);
190 }
191 }
192
193 json_object_put(results);
194 free(res);
195}
196
197void ipc_bar_init(struct swaybar_state *state, int outputi, const char *bar_id) {
198 uint32_t len = 0;
199 char *res = ipc_single_command(state->ipc_socketfd, IPC_GET_OUTPUTS, NULL, &len);
200 json_object *outputs = json_tokener_parse(res);
201 json_object *info = json_object_array_get_idx(outputs, outputi);
202 json_object *name;
203 json_object_object_get_ex(info, "name", &name);
204 state->output->name = strdup(json_object_get_string(name));
205 free(res);
206 json_object_put(outputs);
207
208 len = strlen(bar_id);
209 res = ipc_single_command(state->ipc_socketfd, IPC_GET_BAR_CONFIG, bar_id, &len);
210
211 ipc_parse_config(state->config, res);
212 free(res);
213
214 const char *subscribe_json = "[ \"workspace\", \"mode\" ]";
215 len = strlen(subscribe_json);
216 res = ipc_single_command(state->ipc_event_socketfd, IPC_SUBSCRIBE, subscribe_json, &len);
217 free(res);
218
219 ipc_update_workspaces(state);
220}
221
222bool handle_ipc_event(struct swaybar_state *state) {
223 struct ipc_response *resp = ipc_recv_response(state->ipc_event_socketfd);
224 switch (resp->type) {
225 case IPC_EVENT_WORKSPACE:
226 ipc_update_workspaces(state);
227 break;
228 case IPC_EVENT_MODE: {
229 json_object *result = json_tokener_parse(resp->payload);
230 if (!result) {
231 free_ipc_response(resp);
232 sway_log(L_ERROR, "failed to parse payload as json");
233 return false;
234 }
235 json_object *json_change;
236 if (json_object_object_get_ex(result, "change", &json_change)) {
237 const char *change = json_object_get_string(json_change);
238
239 free(state->config->mode);
240 if (strcmp(change, "default") == 0) {
241 state->config->mode = NULL;
242 } else {
243 state->config->mode = strdup(change);
244 }
245 } else {
246 sway_log(L_ERROR, "failed to parse response");
247 }
248
249 json_object_put(result);
250 break;
251 }
252 default:
253 free_ipc_response(resp);
254 return false;
255 }
256
257 free_ipc_response(resp);
258 return true;
259}
diff --git a/swaybar/ipc.h b/swaybar/ipc.h
new file mode 100644
index 00000000..06d30076
--- /dev/null
+++ b/swaybar/ipc.h
@@ -0,0 +1,17 @@
1#ifndef _SWAYBAR_IPC_H
2#define _SWAYBAR_IPC_H
3
4#include "state.h"
5
6/**
7 * Initialize ipc connection to sway and get sway state, outputs, bar_config.
8 */
9void ipc_bar_init(struct swaybar_state *state, int outputi, const char *bar_id);
10
11/**
12 * Handle ipc event from sway.
13 */
14bool handle_ipc_event(struct swaybar_state *state);
15
16#endif /* _SWAYBAR_IPC_H */
17
diff --git a/swaybar/main.c b/swaybar/main.c
index 6ba7c825..a521fa79 100644
--- a/swaybar/main.c
+++ b/swaybar/main.c
@@ -23,8 +23,8 @@
23#include "config.h" 23#include "config.h"
24#include "render.h" 24#include "render.h"
25#include "status_line.h" 25#include "status_line.h"
26#include "ipc.h"
26 27
27char *output;
28struct swaybar_state *state; 28struct swaybar_state *state;
29 29
30void swaybar_teardown() { 30void swaybar_teardown() {
@@ -71,247 +71,6 @@ void sig_handler(int signal) {
71 exit(0); 71 exit(0);
72} 72}
73 73
74void ipc_update_workspaces() {
75 if (state->output->workspaces) {
76 list_foreach(state->output->workspaces, free_workspace);
77 list_free(state->output->workspaces);
78 }
79 state->output->workspaces = create_list();
80
81 uint32_t len = 0;
82 char *res = ipc_single_command(state->ipc_socketfd, IPC_GET_WORKSPACES, NULL, &len);
83 json_object *results = json_tokener_parse(res);
84 if (!results) {
85 free(res);
86 return;
87 }
88
89 int i;
90 int length = json_object_array_length(results);
91 json_object *ws_json;
92 json_object *num, *name, *visible, *focused, *out, *urgent;
93 for (i = 0; i < length; ++i) {
94 ws_json = json_object_array_get_idx(results, i);
95
96 json_object_object_get_ex(ws_json, "num", &num);
97 json_object_object_get_ex(ws_json, "name", &name);
98 json_object_object_get_ex(ws_json, "visible", &visible);
99 json_object_object_get_ex(ws_json, "focused", &focused);
100 json_object_object_get_ex(ws_json, "output", &out);
101 json_object_object_get_ex(ws_json, "urgent", &urgent);
102
103 if (strcmp(json_object_get_string(out), output) == 0) {
104 struct workspace *ws = malloc(sizeof(struct workspace));
105 ws->num = json_object_get_int(num);
106 ws->name = strdup(json_object_get_string(name));
107 ws->visible = json_object_get_boolean(visible);
108 ws->focused = json_object_get_boolean(focused);
109 ws->urgent = json_object_get_boolean(urgent);
110 list_add(state->output->workspaces, ws);
111 }
112 }
113
114 json_object_put(results);
115 free(res);
116}
117
118void bar_ipc_init(int outputi, const char *bar_id) {
119 uint32_t len = 0;
120 char *res = ipc_single_command(state->ipc_socketfd, IPC_GET_OUTPUTS, NULL, &len);
121 json_object *outputs = json_tokener_parse(res);
122 json_object *info = json_object_array_get_idx(outputs, outputi);
123 json_object *name;
124 json_object_object_get_ex(info, "name", &name);
125 output = strdup(json_object_get_string(name));
126 free(res);
127 json_object_put(outputs);
128
129 len = strlen(bar_id);
130 res = ipc_single_command(state->ipc_socketfd, IPC_GET_BAR_CONFIG, bar_id, &len);
131
132 json_object *bar_config = json_tokener_parse(res);
133 json_object *tray_output, *mode, *hidden_state, *position, *_status_command;
134 json_object *font, *bar_height, *_workspace_buttons, *_strip_workspace_numbers;
135 json_object *_binding_mode_indicator, *verbose, *_colors, *sep_symbol;
136 json_object_object_get_ex(bar_config, "tray_output", &tray_output);
137 json_object_object_get_ex(bar_config, "mode", &mode);
138 json_object_object_get_ex(bar_config, "hidden_state", &hidden_state);
139 json_object_object_get_ex(bar_config, "position", &position);
140 json_object_object_get_ex(bar_config, "status_command", &_status_command);
141 json_object_object_get_ex(bar_config, "font", &font);
142 json_object_object_get_ex(bar_config, "bar_height", &bar_height);
143 json_object_object_get_ex(bar_config, "workspace_buttons", &_workspace_buttons);
144 json_object_object_get_ex(bar_config, "strip_workspace_numbers", &_strip_workspace_numbers);
145 json_object_object_get_ex(bar_config, "binding_mode_indicator", &_binding_mode_indicator);
146 json_object_object_get_ex(bar_config, "verbose", &verbose);
147 json_object_object_get_ex(bar_config, "separator_symbol", &sep_symbol);
148 json_object_object_get_ex(bar_config, "colors", &_colors);
149
150 // TODO: More of these options
151 // TODO: Refactor swaybar into several files, create a bar config struct (shared with compositor?)
152 if (_status_command) {
153 free(state->config->status_command);
154 state->config->status_command = strdup(json_object_get_string(_status_command));
155 }
156
157 if (position) {
158 state->config->position = parse_position(json_object_get_string(position));
159 desktop_shell_set_panel_position(state->output->registry->desktop_shell, state->config->position);
160 }
161
162 if (font) {
163 state->output->window->font = parse_font(json_object_get_string(font));
164 }
165
166 if (sep_symbol) {
167 free(state->config->sep_symbol);
168 state->config->sep_symbol = strdup(json_object_get_string(sep_symbol));
169 }
170
171 if (_strip_workspace_numbers) {
172 state->config->strip_workspace_numbers = json_object_get_boolean(_strip_workspace_numbers);
173 }
174
175 if (_binding_mode_indicator) {
176 state->config->binding_mode_indicator = json_object_get_boolean(_binding_mode_indicator);
177 }
178
179 if (_workspace_buttons) {
180 state->config->workspace_buttons = json_object_get_boolean(_workspace_buttons);
181 }
182
183 if (bar_height) {
184 int width, height;
185 get_text_size(state->output->window, &width, &height, "Test string for measuring purposes");
186 int bar_height_value = json_object_get_int(bar_height);
187 if (bar_height_value > 0) {
188 state->config->margin = (bar_height_value - height) / 2;
189 state->config->ws_vertical_padding = state->config->margin - 1.5;
190 }
191 state->output->window->height = height + state->config->margin * 2;
192 }
193
194 if (_colors) {
195 json_object *background, *statusline, *separator;
196 json_object *focused_workspace_border, *focused_workspace_bg, *focused_workspace_text;
197 json_object *inactive_workspace_border, *inactive_workspace_bg, *inactive_workspace_text;
198 json_object *active_workspace_border, *active_workspace_bg, *active_workspace_text;
199 json_object *urgent_workspace_border, *urgent_workspace_bg, *urgent_workspace_text;
200 json_object *binding_mode_border, *binding_mode_bg, *binding_mode_text;
201 json_object_object_get_ex(_colors, "background", &background);
202 json_object_object_get_ex(_colors, "statusline", &statusline);
203 json_object_object_get_ex(_colors, "separator", &separator);
204 json_object_object_get_ex(_colors, "focused_workspace_border", &focused_workspace_border);
205 json_object_object_get_ex(_colors, "focused_workspace_bg", &focused_workspace_bg);
206 json_object_object_get_ex(_colors, "focused_workspace_text", &focused_workspace_text);
207 json_object_object_get_ex(_colors, "active_workspace_border", &active_workspace_border);
208 json_object_object_get_ex(_colors, "active_workspace_bg", &active_workspace_bg);
209 json_object_object_get_ex(_colors, "active_workspace_text", &active_workspace_text);
210 json_object_object_get_ex(_colors, "inactive_workspace_border", &inactive_workspace_border);
211 json_object_object_get_ex(_colors, "inactive_workspace_bg", &inactive_workspace_bg);
212 json_object_object_get_ex(_colors, "inactive_workspace_text", &inactive_workspace_text);
213 json_object_object_get_ex(_colors, "urgent_workspace_border", &urgent_workspace_border);
214 json_object_object_get_ex(_colors, "urgent_workspace_bg", &urgent_workspace_bg);
215 json_object_object_get_ex(_colors, "urgent_workspace_text", &urgent_workspace_text);
216 json_object_object_get_ex(_colors, "binding_mode_border", &binding_mode_border);
217 json_object_object_get_ex(_colors, "binding_mode_bg", &binding_mode_bg);
218 json_object_object_get_ex(_colors, "binding_mode_text", &binding_mode_text);
219 if (background) {
220 state->config->colors.background = parse_color(json_object_get_string(background));
221 }
222 if (statusline) {
223 state->config->colors.statusline = parse_color(json_object_get_string(statusline));
224 }
225 if (separator) {
226 state->config->colors.separator = parse_color(json_object_get_string(separator));
227 }
228 if (focused_workspace_border) {
229 state->config->colors.focused_workspace.border = parse_color(json_object_get_string(focused_workspace_border));
230 }
231 if (focused_workspace_bg) {
232 state->config->colors.focused_workspace.background = parse_color(json_object_get_string(focused_workspace_bg));
233 }
234 if (focused_workspace_text) {
235 state->config->colors.focused_workspace.text = parse_color(json_object_get_string(focused_workspace_text));
236 }
237 if (active_workspace_border) {
238 state->config->colors.active_workspace.border = parse_color(json_object_get_string(active_workspace_border));
239 }
240 if (active_workspace_bg) {
241 state->config->colors.active_workspace.background = parse_color(json_object_get_string(active_workspace_bg));
242 }
243 if (active_workspace_text) {
244 state->config->colors.active_workspace.text = parse_color(json_object_get_string(active_workspace_text));
245 }
246 if (inactive_workspace_border) {
247 state->config->colors.inactive_workspace.border = parse_color(json_object_get_string(inactive_workspace_border));
248 }
249 if (inactive_workspace_bg) {
250 state->config->colors.inactive_workspace.background = parse_color(json_object_get_string(inactive_workspace_bg));
251 }
252 if (inactive_workspace_text) {
253 state->config->colors.inactive_workspace.text = parse_color(json_object_get_string(inactive_workspace_text));
254 }
255 if (binding_mode_border) {
256 state->config->colors.binding_mode.border = parse_color(json_object_get_string(binding_mode_border));
257 }
258 if (binding_mode_bg) {
259 state->config->colors.binding_mode.background = parse_color(json_object_get_string(binding_mode_bg));
260 }
261 if (binding_mode_text) {
262 state->config->colors.binding_mode.text = parse_color(json_object_get_string(binding_mode_text));
263 }
264 }
265
266 json_object_put(bar_config);
267 free(res);
268
269 const char *subscribe_json = "[ \"workspace\", \"mode\" ]";
270 len = strlen(subscribe_json);
271 res = ipc_single_command(state->ipc_event_socketfd, IPC_SUBSCRIBE, subscribe_json, &len);
272 free(res);
273
274 ipc_update_workspaces();
275}
276bool handle_ipc_event() {
277 struct ipc_response *resp = ipc_recv_response(state->ipc_event_socketfd);
278 switch (resp->type) {
279 case IPC_EVENT_WORKSPACE:
280 ipc_update_workspaces();
281 break;
282 case IPC_EVENT_MODE: {
283 json_object *result = json_tokener_parse(resp->payload);
284 if (!result) {
285 free_ipc_response(resp);
286 sway_log(L_ERROR, "failed to parse payload as json");
287 return false;
288 }
289 json_object *json_change;
290 if (json_object_object_get_ex(result, "change", &json_change)) {
291 const char *change = json_object_get_string(json_change);
292
293 free(state->config->mode);
294 if (strcmp(change, "default") == 0) {
295 state->config->mode = NULL;
296 } else {
297 state->config->mode = strdup(change);
298 }
299 } else {
300 sway_log(L_ERROR, "failed to parse response");
301 }
302
303 json_object_put(result);
304 break;
305 }
306 default:
307 free_ipc_response(resp);
308 return false;
309 }
310
311 free_ipc_response(resp);
312 return true;
313}
314
315void poll_for_update() { 74void poll_for_update() {
316 fd_set readfds; 75 fd_set readfds;
317 int activity; 76 int activity;
@@ -341,7 +100,7 @@ void poll_for_update() {
341 100
342 if (FD_ISSET(state->ipc_event_socketfd, &readfds)) { 101 if (FD_ISSET(state->ipc_event_socketfd, &readfds)) {
343 sway_log(L_DEBUG, "Got IPC event."); 102 sway_log(L_DEBUG, "Got IPC event.");
344 dirty = handle_ipc_event(); 103 dirty = handle_ipc_event(state);
345 } 104 }
346 105
347 if (state->config->status_command && FD_ISSET(state->status_read_fd, &readfds)) { 106 if (state->config->status_command && FD_ISSET(state->status_read_fd, &readfds)) {
@@ -435,12 +194,13 @@ int main(int argc, char **argv) {
435 state->ipc_socketfd = ipc_open_socket(socket_path); 194 state->ipc_socketfd = ipc_open_socket(socket_path);
436 state->ipc_event_socketfd = ipc_open_socket(socket_path); 195 state->ipc_event_socketfd = ipc_open_socket(socket_path);
437 196
438
439 if (argc == optind) { 197 if (argc == optind) {
440 sway_abort("No output index provided"); 198 sway_abort("No output index provided");
441 } 199 }
442 200
443 int desired_output = atoi(argv[optind]); 201 int desired_output = atoi(argv[optind]);
202 ipc_bar_init(state, desired_output, bar_id);
203
444 struct output_state *output = state->output->registry->outputs->items[desired_output]; 204 struct output_state *output = state->output->registry->outputs->items[desired_output];
445 205
446 state->output->window = window_setup(state->output->registry, output->width, 30, false); 206 state->output->window = window_setup(state->output->registry, output->width, 30, false);
@@ -448,8 +208,13 @@ int main(int argc, char **argv) {
448 sway_abort("Failed to create window."); 208 sway_abort("Failed to create window.");
449 } 209 }
450 desktop_shell_set_panel(state->output->registry->desktop_shell, output->output, state->output->window->surface); 210 desktop_shell_set_panel(state->output->registry->desktop_shell, output->output, state->output->window->surface);
211 desktop_shell_set_panel_position(state->output->registry->desktop_shell, state->config->position);
212
213 /* set font */
214 state->output->window->font = state->config->font;
451 215
452 bar_ipc_init(desired_output, bar_id); 216 /* set window height */
217 set_window_height(state->output->window, state->config->height);
453 218
454 if (state->config->status_command) { 219 if (state->config->status_command) {
455 int pipefd[2]; 220 int pipefd[2];
diff --git a/swaybar/render.c b/swaybar/render.c
index 1e1554c5..9ac0c766 100644
--- a/swaybar/render.c
+++ b/swaybar/render.c
@@ -8,6 +8,13 @@
8#include "status_line.h" 8#include "status_line.h"
9#include "render.h" 9#include "render.h"
10 10
11
12/* internal spacing */
13static int margin = 3;
14static int ws_horizontal_padding = 5;
15static double ws_vertical_padding = 1.5;
16static int ws_spacing = 1;
17
11static void cairo_set_source_u32(cairo_t *cairo, uint32_t color) { 18static void cairo_set_source_u32(cairo_t *cairo, uint32_t color) {
12 cairo_set_source_rgba(cairo, 19 cairo_set_source_rgba(cairo,
13 ((color & 0xFF000000) >> 24) / 256.0, 20 ((color & 0xFF000000) >> 24) / 256.0,
@@ -62,13 +69,13 @@ static void render_block(struct window *window, struct swaybar_config *config, s
62 *x -= width; 69 *x -= width;
63 70
64 if (block->border != 0 && block->border_left > 0) { 71 if (block->border != 0 && block->border_left > 0) {
65 *x -= (block->border_left + config->margin); 72 *x -= (block->border_left + margin);
66 block_width += block->border_left + config->margin; 73 block_width += block->border_left + margin;
67 } 74 }
68 75
69 if (block->border != 0 && block->border_right > 0) { 76 if (block->border != 0 && block->border_right > 0) {
70 *x -= (block->border_right + config->margin); 77 *x -= (block->border_right + margin);
71 block_width += block->border_right + config->margin; 78 block_width += block->border_right + margin;
72 } 79 }
73 80
74 // Add separator 81 // Add separator
@@ -76,13 +83,13 @@ static void render_block(struct window *window, struct swaybar_config *config, s
76 if (config->sep_symbol) { 83 if (config->sep_symbol) {
77 get_text_size(window, &sep_width, &height, "%s", config->sep_symbol); 84 get_text_size(window, &sep_width, &height, "%s", config->sep_symbol);
78 if (sep_width > block->separator_block_width) { 85 if (sep_width > block->separator_block_width) {
79 block->separator_block_width = sep_width + config->margin * 2; 86 block->separator_block_width = sep_width + margin * 2;
80 } 87 }
81 } 88 }
82 89
83 *x -= block->separator_block_width; 90 *x -= block->separator_block_width;
84 } else { 91 } else {
85 *x -= config->margin; 92 *x -= margin;
86 } 93 }
87 94
88 double pos = *x; 95 double pos = *x;
@@ -120,7 +127,7 @@ static void render_block(struct window *window, struct swaybar_config *config, s
120 block->border_left, 127 block->border_left,
121 window->height - 2); 128 window->height - 2);
122 129
123 pos += block->border_left + config->margin; 130 pos += block->border_left + margin;
124 } 131 }
125 132
126 // render text 133 // render text
@@ -134,7 +141,7 @@ static void render_block(struct window *window, struct swaybar_config *config, s
134 offset = pos + (width - textwidth) / 2; 141 offset = pos + (width - textwidth) / 2;
135 } 142 }
136 143
137 cairo_move_to(window->cairo, offset, config->margin); 144 cairo_move_to(window->cairo, offset, margin);
138 cairo_set_source_u32(window->cairo, block->color); 145 cairo_set_source_u32(window->cairo, block->color);
139 pango_printf(window, "%s", block->full_text); 146 pango_printf(window, "%s", block->full_text);
140 147
@@ -142,7 +149,7 @@ static void render_block(struct window *window, struct swaybar_config *config, s
142 149
143 // render right border 150 // render right border
144 if (block->border != 0 && block->border_right > 0) { 151 if (block->border != 0 && block->border_right > 0) {
145 pos += config->margin; 152 pos += margin;
146 153
147 render_sharp_line(window->cairo, block->border, 154 render_sharp_line(window->cairo, block->border,
148 pos - 0.5, 155 pos - 0.5,
@@ -158,14 +165,14 @@ static void render_block(struct window *window, struct swaybar_config *config, s
158 cairo_set_source_u32(window->cairo, config->colors.separator); 165 cairo_set_source_u32(window->cairo, config->colors.separator);
159 if (config->sep_symbol) { 166 if (config->sep_symbol) {
160 offset = pos + (block->separator_block_width - sep_width) / 2; 167 offset = pos + (block->separator_block_width - sep_width) / 2;
161 cairo_move_to(window->cairo, offset, config->margin); 168 cairo_move_to(window->cairo, offset, margin);
162 pango_printf(window, "%s", config->sep_symbol); 169 pango_printf(window, "%s", config->sep_symbol);
163 } else { 170 } else {
164 cairo_set_line_width(window->cairo, 1); 171 cairo_set_line_width(window->cairo, 1);
165 cairo_move_to(window->cairo, pos + block->separator_block_width/2, 172 cairo_move_to(window->cairo, pos + block->separator_block_width/2,
166 config->margin); 173 margin);
167 cairo_line_to(window->cairo, pos + block->separator_block_width/2, 174 cairo_line_to(window->cairo, pos + block->separator_block_width/2,
168 window->height - config->margin); 175 window->height - margin);
169 cairo_stroke(window->cairo); 176 cairo_stroke(window->cairo);
170 } 177 }
171 } 178 }
@@ -215,22 +222,22 @@ static void render_workspace_button(struct window *window, struct swaybar_config
215 222
216 // background 223 // background
217 cairo_set_source_u32(window->cairo, box_colors.background); 224 cairo_set_source_u32(window->cairo, box_colors.background);
218 cairo_rectangle(window->cairo, *x, 1.5, width + config->ws_horizontal_padding * 2 - 1, 225 cairo_rectangle(window->cairo, *x, 1.5, width + ws_horizontal_padding * 2 - 1,
219 height + config->ws_vertical_padding * 2); 226 height + ws_vertical_padding * 2);
220 cairo_fill(window->cairo); 227 cairo_fill(window->cairo);
221 228
222 // border 229 // border
223 cairo_set_source_u32(window->cairo, box_colors.border); 230 cairo_set_source_u32(window->cairo, box_colors.border);
224 cairo_rectangle(window->cairo, *x, 1.5, width + config->ws_horizontal_padding * 2 - 1, 231 cairo_rectangle(window->cairo, *x, 1.5, width + ws_horizontal_padding * 2 - 1,
225 height + config->ws_vertical_padding * 2); 232 height + ws_vertical_padding * 2);
226 cairo_stroke(window->cairo); 233 cairo_stroke(window->cairo);
227 234
228 // text 235 // text
229 cairo_set_source_u32(window->cairo, box_colors.text); 236 cairo_set_source_u32(window->cairo, box_colors.text);
230 cairo_move_to(window->cairo, (int)*x + config->ws_horizontal_padding, config->margin); 237 cairo_move_to(window->cairo, (int)*x + ws_horizontal_padding, margin);
231 pango_printf(window, "%s", name); 238 pango_printf(window, "%s", name);
232 239
233 *x += width + config->ws_horizontal_padding * 2 + config->ws_spacing; 240 *x += width + ws_horizontal_padding * 2 + ws_spacing;
234 241
235 free(name); 242 free(name);
236} 243}
@@ -241,19 +248,19 @@ static void render_binding_mode_indicator(struct window *window, struct swaybar_
241 248
242 // background 249 // background
243 cairo_set_source_u32(window->cairo, config->colors.binding_mode.background); 250 cairo_set_source_u32(window->cairo, config->colors.binding_mode.background);
244 cairo_rectangle(window->cairo, pos, 1.5, width + config->ws_horizontal_padding * 2 - 1, 251 cairo_rectangle(window->cairo, pos, 1.5, width + ws_horizontal_padding * 2 - 1,
245 height + config->ws_vertical_padding * 2); 252 height + ws_vertical_padding * 2);
246 cairo_fill(window->cairo); 253 cairo_fill(window->cairo);
247 254
248 // border 255 // border
249 cairo_set_source_u32(window->cairo, config->colors.binding_mode.border); 256 cairo_set_source_u32(window->cairo, config->colors.binding_mode.border);
250 cairo_rectangle(window->cairo, pos, 1.5, width + config->ws_horizontal_padding * 2 - 1, 257 cairo_rectangle(window->cairo, pos, 1.5, width + ws_horizontal_padding * 2 - 1,
251 height + config->ws_vertical_padding * 2); 258 height + ws_vertical_padding * 2);
252 cairo_stroke(window->cairo); 259 cairo_stroke(window->cairo);
253 260
254 // text 261 // text
255 cairo_set_source_u32(window->cairo, config->colors.binding_mode.text); 262 cairo_set_source_u32(window->cairo, config->colors.binding_mode.text);
256 cairo_move_to(window->cairo, (int)pos + config->ws_horizontal_padding, config->margin); 263 cairo_move_to(window->cairo, (int)pos + ws_horizontal_padding, margin);
257 pango_printf(window, "%s", config->mode); 264 pango_printf(window, "%s", config->mode);
258} 265}
259 266
@@ -279,7 +286,7 @@ void render(struct output *output, struct swaybar_config *config, struct status_
279 286
280 if (line->protocol == TEXT) { 287 if (line->protocol == TEXT) {
281 get_text_size(window, &width, &height, "%s", line->text_line); 288 get_text_size(window, &width, &height, "%s", line->text_line);
282 cairo_move_to(cairo, window->width - config->margin - width, config->margin); 289 cairo_move_to(cairo, window->width - margin - width, margin);
283 pango_printf(window, "%s", line); 290 pango_printf(window, "%s", line);
284 } else if (line->protocol == I3BAR && line->block_line) { 291 } else if (line->protocol == I3BAR && line->block_line) {
285 double pos = window->width - 0.5; 292 double pos = window->width - 0.5;
@@ -309,3 +316,13 @@ void render(struct output *output, struct swaybar_config *config, struct status_
309 render_binding_mode_indicator(window, config, x); 316 render_binding_mode_indicator(window, config, x);
310 } 317 }
311} 318}
319
320void set_window_height(struct window *window, int height) {
321 int text_width, text_height;
322 get_text_size(window, &text_width, &text_height, "Test string for measuring purposes");
323 if (height > 0) {
324 margin = (height - text_height) / 2;
325 ws_vertical_padding = margin - 1.5;
326 }
327 window->height = text_height + margin * 2;
328}
diff --git a/swaybar/render.h b/swaybar/render.h
index 2815edfc..527cf76a 100644
--- a/swaybar/render.h
+++ b/swaybar/render.h
@@ -9,4 +9,9 @@
9 */ 9 */
10void render(struct output *output, struct swaybar_config *config, struct status_line *line); 10void render(struct output *output, struct swaybar_config *config, struct status_line *line);
11 11
12/**
13 * Set window height and modify internal spacing accordingly.
14 */
15void set_window_height(struct window *window, int height);
16
12#endif /* _SWAYBAR_RENDER_H */ 17#endif /* _SWAYBAR_RENDER_H */
diff --git a/swaybar/state.c b/swaybar/state.c
index 900842e0..77427555 100644
--- a/swaybar/state.c
+++ b/swaybar/state.c
@@ -13,6 +13,7 @@ struct swaybar_state *init_state() {
13 state->output->window = NULL; 13 state->output->window = NULL;
14 state->output->registry = NULL; 14 state->output->registry = NULL;
15 state->output->workspaces = create_list(); 15 state->output->workspaces = create_list();
16 state->output->name = NULL;
16 17
17 return state; 18 return state;
18} 19}
diff --git a/swaybar/state.h b/swaybar/state.h
index 5949548e..f95e03bc 100644
--- a/swaybar/state.h
+++ b/swaybar/state.h
@@ -20,6 +20,7 @@ struct output {
20 struct window *window; 20 struct window *window;
21 struct registry *registry; 21 struct registry *registry;
22 list_t *workspaces; 22 list_t *workspaces;
23 char *name;
23}; 24};
24 25
25struct workspace { 26struct workspace {
diff --git a/swaybar/status_line.c b/swaybar/status_line.c
index a9ed8d8c..ee740c6b 100644
--- a/swaybar/status_line.c
+++ b/swaybar/status_line.c
@@ -48,7 +48,7 @@ static void free_status_block(void *item) {
48 free(sb); 48 free(sb);
49} 49}
50 50
51static void parse_json(struct swaybar_state *st, const char *text) { 51static void parse_json(struct swaybar_state *state, const char *text) {
52 json_object *results = json_tokener_parse(text); 52 json_object *results = json_tokener_parse(text);
53 if (!results) { 53 if (!results) {
54 sway_log(L_DEBUG, "Failed to parse json"); 54 sway_log(L_DEBUG, "Failed to parse json");
@@ -59,12 +59,12 @@ static void parse_json(struct swaybar_state *st, const char *text) {
59 return; 59 return;
60 } 60 }
61 61
62 if (st->status->block_line) { 62 if (state->status->block_line) {
63 list_foreach(st->status->block_line, free_status_block); 63 list_foreach(state->status->block_line, free_status_block);
64 list_free(st->status->block_line); 64 list_free(state->status->block_line);
65 } 65 }
66 66
67 st->status->block_line = create_list(); 67 state->status->block_line = create_list();
68 68
69 int i; 69 int i;
70 for (i = 0; i < json_object_array_length(results); ++i) { 70 for (i = 0; i < json_object_array_length(results); ++i) {
@@ -108,7 +108,7 @@ static void parse_json(struct swaybar_state *st, const char *text) {
108 if (color) { 108 if (color) {
109 new->color = parse_color(json_object_get_string(color)); 109 new->color = parse_color(json_object_get_string(color));
110 } else { 110 } else {
111 new->color = st->config->colors.statusline; 111 new->color = state->config->colors.statusline;
112 } 112 }
113 113
114 if (min_width) { 114 if (min_width) {
@@ -188,7 +188,7 @@ static void parse_json(struct swaybar_state *st, const char *text) {
188 new->border_right = 1; 188 new->border_right = 1;
189 } 189 }
190 190
191 list_add(st->status->block_line, new); 191 list_add(state->status->block_line, new);
192 } 192 }
193 193
194 json_object_put(results); 194 json_object_put(results);
@@ -369,41 +369,41 @@ static int i3json_handle_data(struct swaybar_state *st, char *data) {
369} 369}
370 370
371// read data from fd and parse it. 371// read data from fd and parse it.
372static int i3json_handle_fd(struct swaybar_state *st) { 372static int i3json_handle_fd(struct swaybar_state *state) {
373 i3json_ensure_free(10240); 373 i3json_ensure_free(10240);
374 // get fresh data at the end of the buffer 374 // get fresh data at the end of the buffer
375 int readlen = read(st->status_read_fd, i3json_state.parserpos, 10239); 375 int readlen = read(state->status_read_fd, i3json_state.parserpos, 10239);
376 if (readlen < 0) { 376 if (readlen < 0) {
377 return readlen; 377 return readlen;
378 } 378 }
379 i3json_state.parserpos[readlen] = '\0'; 379 i3json_state.parserpos[readlen] = '\0';
380 return i3json_parse(st); 380 return i3json_parse(state);
381} 381}
382 382
383bool handle_status_line(struct swaybar_state *st) { 383bool handle_status_line(struct swaybar_state *state) {
384 bool dirty = false; 384 bool dirty = false;
385 385
386 switch (st->status->protocol) { 386 switch (state->status->protocol) {
387 case I3BAR: 387 case I3BAR:
388 sway_log(L_DEBUG, "Got i3bar protocol."); 388 sway_log(L_DEBUG, "Got i3bar protocol.");
389 if (i3json_handle_fd(st) > 0) { 389 if (i3json_handle_fd(state) > 0) {
390 dirty = true; 390 dirty = true;
391 } 391 }
392 break; 392 break;
393 case TEXT: 393 case TEXT:
394 sway_log(L_DEBUG, "Got text protocol."); 394 sway_log(L_DEBUG, "Got text protocol.");
395 read_line_tail(st->status_read_fd, line, sizeof(line), line_rest); 395 read_line_tail(state->status_read_fd, line, sizeof(line), line_rest);
396 dirty = true; 396 dirty = true;
397 st->status->text_line = line; 397 state->status->text_line = line;
398 break; 398 break;
399 case UNDEF: 399 case UNDEF:
400 sway_log(L_DEBUG, "Detecting protocol..."); 400 sway_log(L_DEBUG, "Detecting protocol...");
401 if (read_line_tail(st->status_read_fd, line, sizeof(line), line_rest) < 0) { 401 if (read_line_tail(state->status_read_fd, line, sizeof(line), line_rest) < 0) {
402 break; 402 break;
403 } 403 }
404 dirty = true; 404 dirty = true;
405 st->status->text_line = line; 405 state->status->text_line = line;
406 st->status->protocol = TEXT; 406 state->status->protocol = TEXT;
407 if (line[0] == '{') { 407 if (line[0] == '{') {
408 // detect i3bar json protocol 408 // detect i3bar json protocol
409 json_object *proto = json_tokener_parse(line); 409 json_object *proto = json_tokener_parse(line);
@@ -413,8 +413,8 @@ bool handle_status_line(struct swaybar_state *st) {
413 && json_object_get_int(version) == 1 413 && json_object_get_int(version) == 1
414 ) { 414 ) {
415 sway_log(L_DEBUG, "Switched to i3bar protocol."); 415 sway_log(L_DEBUG, "Switched to i3bar protocol.");
416 st->status->protocol = I3BAR; 416 state->status->protocol = I3BAR;
417 i3json_handle_data(st, line_rest); 417 i3json_handle_data(state, line_rest);
418 } 418 }
419 json_object_put(proto); 419 json_object_put(proto);
420 } 420 }