aboutsummaryrefslogtreecommitdiffstats
path: root/swaybar
diff options
context:
space:
mode:
authorLibravatar Drew DeVault <sir@cmpwn.com>2018-03-29 15:16:12 -0400
committerLibravatar Drew DeVault <sir@cmpwn.com>2018-03-29 22:11:08 -0400
commit0d0ab7c5ce148bce841fa0682d04bc7b6c21b902 (patch)
treebc3dcefa0e306ac00d81a0cabbd6a0404d7baff6 /swaybar
parentIterate over workspaces backwards (diff)
downloadsway-0d0ab7c5ce148bce841fa0682d04bc7b6c21b902.tar.gz
sway-0d0ab7c5ce148bce841fa0682d04bc7b6c21b902.tar.zst
sway-0d0ab7c5ce148bce841fa0682d04bc7b6c21b902.zip
Implement status line
Does not yet support i3bar json protocol
Diffstat (limited to 'swaybar')
-rw-r--r--swaybar/bar.c26
-rw-r--r--swaybar/config.c1
-rw-r--r--swaybar/meson.build1
-rw-r--r--swaybar/render.c56
-rw-r--r--swaybar/status_line.c78
5 files changed, 158 insertions, 4 deletions
diff --git a/swaybar/bar.c b/swaybar/bar.c
index 90fd5ad4..72c4be8f 100644
--- a/swaybar/bar.c
+++ b/swaybar/bar.c
@@ -13,6 +13,7 @@
13#include "swaybar/render.h" 13#include "swaybar/render.h"
14#include "swaybar/config.h" 14#include "swaybar/config.h"
15#include "swaybar/event_loop.h" 15#include "swaybar/event_loop.h"
16#include "swaybar/status_line.h"
16#include "swaybar/bar.h" 17#include "swaybar/bar.h"
17#include "swaybar/ipc.h" 18#include "swaybar/ipc.h"
18#include "ipc-client.h" 19#include "ipc-client.h"
@@ -98,6 +99,9 @@ void bar_setup(struct swaybar *bar,
98 bar->ipc_socketfd = ipc_open_socket(socket_path); 99 bar->ipc_socketfd = ipc_open_socket(socket_path);
99 bar->ipc_event_socketfd = ipc_open_socket(socket_path); 100 bar->ipc_event_socketfd = ipc_open_socket(socket_path);
100 ipc_initialize(bar, bar_id); 101 ipc_initialize(bar, bar_id);
102 if (bar->config->status_command) {
103 bar->status = status_line_init(bar->config->status_command);
104 }
101 105
102 assert(bar->display = wl_display_connect(NULL)); 106 assert(bar->display = wl_display_connect(NULL));
103 107
@@ -134,6 +138,13 @@ void bar_setup(struct swaybar *bar,
134 } 138 }
135} 139}
136 140
141static void render_all_frames(struct swaybar *bar) {
142 struct swaybar_output *output;
143 wl_list_for_each(output, &bar->outputs, link) {
144 render_frame(bar, output);
145 }
146}
147
137static void display_in(int fd, short mask, void *_bar) { 148static void display_in(int fd, short mask, void *_bar) {
138 struct swaybar *bar = (struct swaybar *)_bar; 149 struct swaybar *bar = (struct swaybar *)_bar;
139 if (wl_display_dispatch(bar->display) == -1) { 150 if (wl_display_dispatch(bar->display) == -1) {
@@ -144,16 +155,23 @@ static void display_in(int fd, short mask, void *_bar) {
144static void ipc_in(int fd, short mask, void *_bar) { 155static void ipc_in(int fd, short mask, void *_bar) {
145 struct swaybar *bar = (struct swaybar *)_bar; 156 struct swaybar *bar = (struct swaybar *)_bar;
146 if (handle_ipc_event(bar)) { 157 if (handle_ipc_event(bar)) {
147 struct swaybar_output *output; 158 render_all_frames(bar);
148 wl_list_for_each(output, &bar->outputs, link) { 159 }
149 render_frame(bar, output); 160}
150 } 161
162static void status_in(int fd, short mask, void *_bar) {
163 struct swaybar *bar = (struct swaybar *)_bar;
164 if (handle_status_readable(bar->status)) {
165 render_all_frames(bar);
151 } 166 }
152} 167}
153 168
154void bar_run(struct swaybar *bar) { 169void bar_run(struct swaybar *bar) {
155 add_event(wl_display_get_fd(bar->display), POLLIN, display_in, bar); 170 add_event(wl_display_get_fd(bar->display), POLLIN, display_in, bar);
156 add_event(bar->ipc_event_socketfd, POLLIN, ipc_in, bar); 171 add_event(bar->ipc_event_socketfd, POLLIN, ipc_in, bar);
172 if (bar->status) {
173 add_event(bar->status->read_fd, POLLIN, status_in, bar);
174 }
157 while (1) { 175 while (1) {
158 event_loop_poll(); 176 event_loop_poll();
159 } 177 }
diff --git a/swaybar/config.c b/swaybar/config.c
index 802d0779..9169ad27 100644
--- a/swaybar/config.c
+++ b/swaybar/config.c
@@ -43,6 +43,7 @@ struct swaybar_config *init_config() {
43 config->colors.background = 0x000000FF; 43 config->colors.background = 0x000000FF;
44 config->colors.focused_background = 0x000000FF; 44 config->colors.focused_background = 0x000000FF;
45 config->colors.statusline = 0xFFFFFFFF; 45 config->colors.statusline = 0xFFFFFFFF;
46 config->colors.focused_statusline = 0xFFFFFFFF;
46 config->colors.separator = 0x666666FF; 47 config->colors.separator = 0x666666FF;
47 48
48 config->colors.focused_workspace.border = 0x4C7899FF; 49 config->colors.focused_workspace.border = 0x4C7899FF;
diff --git a/swaybar/meson.build b/swaybar/meson.build
index 6dc7c564..d15e8b5c 100644
--- a/swaybar/meson.build
+++ b/swaybar/meson.build
@@ -7,6 +7,7 @@ executable(
7 'ipc.c', 7 'ipc.c',
8 'main.c', 8 'main.c',
9 'render.c', 9 'render.c',
10 'status_line.c',
10 ], 11 ],
11 include_directories: [sway_inc], 12 include_directories: [sway_inc],
12 dependencies: [ 13 dependencies: [
diff --git a/swaybar/render.c b/swaybar/render.c
index f797873c..ec1239a1 100644
--- a/swaybar/render.c
+++ b/swaybar/render.c
@@ -9,12 +9,59 @@
9#include "swaybar/bar.h" 9#include "swaybar/bar.h"
10#include "swaybar/config.h" 10#include "swaybar/config.h"
11#include "swaybar/render.h" 11#include "swaybar/render.h"
12#include "swaybar/status_line.h"
12#include "wlr-layer-shell-unstable-v1-client-protocol.h" 13#include "wlr-layer-shell-unstable-v1-client-protocol.h"
13 14
14static const int ws_horizontal_padding = 5; 15static const int ws_horizontal_padding = 5;
15static const double ws_vertical_padding = 1.5; 16static const double ws_vertical_padding = 1.5;
16static const double border_width = 1; 17static const double border_width = 1;
17 18
19static uint32_t render_status_line_text(cairo_t *cairo,
20 struct swaybar_config *config, struct status_line *status,
21 bool focused, uint32_t width, uint32_t height) {
22 if (!status->text) {
23 return 0;
24 }
25 //wlr_log(L_DEBUG, "focused %d", focused);
26 cairo_set_source_u32(cairo, focused ?
27 config->colors.focused_statusline : config->colors.statusline);
28 static const int margin = 3;
29 int text_width, text_height;
30 get_text_size(cairo, config->font, &text_width, &text_height,
31 1, config->pango_markup, "%s", status->text);
32 uint32_t ideal_height = text_height + ws_vertical_padding * 2;
33 if (height < ideal_height) {
34 height = ideal_height;
35 }
36 double text_y = height / 2.0 - text_height / 2.0;
37 cairo_move_to(cairo, width - text_width - margin, (int)floor(text_y));
38 pango_printf(cairo, config->font, 1, config->pango_markup,
39 "%s", status->text);
40 return ideal_height;
41}
42
43static uint32_t render_status_line_i3bar(cairo_t *cairo,
44 struct swaybar_config *config, struct status_line *status,
45 bool focused, uint32_t width, uint32_t height) {
46 // TODO
47 return 0;
48}
49
50static uint32_t render_status_line(cairo_t *cairo,
51 struct swaybar_config *config, struct status_line *status,
52 bool focused, uint32_t width, uint32_t height) {
53 switch (status->protocol) {
54 case PROTOCOL_TEXT:
55 return render_status_line_text(cairo,
56 config, status, focused, width, height);
57 case PROTOCOL_I3BAR:
58 return render_status_line_i3bar(cairo,
59 config, status, focused, width, height);
60 default:
61 return 0;
62 }
63}
64
18static uint32_t render_binding_mode_indicator(cairo_t *cairo, 65static uint32_t render_binding_mode_indicator(cairo_t *cairo,
19 struct swaybar_config *config, const char *mode, double x, 66 struct swaybar_config *config, const char *mode, double x,
20 uint32_t height) { 67 uint32_t height) {
@@ -148,6 +195,11 @@ static uint32_t render_to_cairo(cairo_t *cairo,
148 cairo, config, config->mode, x, output->height); 195 cairo, config, config->mode, x, output->height);
149 max_height = h > max_height ? h : max_height; 196 max_height = h > max_height ? h : max_height;
150 } 197 }
198 if (bar->status) {
199 uint32_t h = render_status_line(cairo, config, bar->status,
200 output->focused, output->width, output->height);
201 max_height = h > max_height ? h : max_height;
202 }
151 203
152 return max_height > output->height ? max_height : output->height; 204 return max_height > output->height ? max_height : output->height;
153} 205}
@@ -157,6 +209,10 @@ void render_frame(struct swaybar *bar,
157 cairo_surface_t *recorder = cairo_recording_surface_create( 209 cairo_surface_t *recorder = cairo_recording_surface_create(
158 CAIRO_CONTENT_COLOR_ALPHA, NULL); 210 CAIRO_CONTENT_COLOR_ALPHA, NULL);
159 cairo_t *cairo = cairo_create(recorder); 211 cairo_t *cairo = cairo_create(recorder);
212 cairo_save(cairo);
213 cairo_set_operator(cairo, CAIRO_OPERATOR_CLEAR);
214 cairo_paint(cairo);
215 cairo_restore(cairo);
160 uint32_t height = render_to_cairo(cairo, bar, output); 216 uint32_t height = render_to_cairo(cairo, bar, output);
161 if (bar->config->height >= 0 && height < (uint32_t)bar->config->height) { 217 if (bar->config->height >= 0 && height < (uint32_t)bar->config->height) {
162 height = bar->config->height; 218 height = bar->config->height;
diff --git a/swaybar/status_line.c b/swaybar/status_line.c
new file mode 100644
index 00000000..ff668c9c
--- /dev/null
+++ b/swaybar/status_line.c
@@ -0,0 +1,78 @@
1#define _POSIX_C_SOURCE
2#include <fcntl.h>
3#include <stdlib.h>
4#include <string.h>
5#include <stdio.h>
6#include <unistd.h>
7#include <wlr/util/log.h>
8#include "swaybar/config.h"
9#include "swaybar/status_line.h"
10#include "readline.h"
11
12bool handle_status_readable(struct status_line *status) {
13 char *line = read_line_buffer(status->read,
14 status->buffer, status->buffer_size);
15 switch (status->protocol) {
16 case PROTOCOL_I3BAR:
17 // TODO
18 break;
19 case PROTOCOL_TEXT:
20 status->text = line;
21 return true;
22 case PROTOCOL_UNDEF:
23 if (!line) {
24 return false;
25 }
26 if (line[0] == '{') {
27 // TODO: JSON
28 } else {
29 status->text = line;
30 status->protocol = PROTOCOL_TEXT;
31 }
32 return false;
33 }
34 return false;
35}
36
37struct status_line *status_line_init(char *cmd) {
38 struct status_line *status = calloc(1, sizeof(struct status_line));
39 status->buffer_size = 4096;
40 status->buffer = malloc(status->buffer_size);
41
42 int pipe_read_fd[2];
43 int pipe_write_fd[2];
44 if (pipe(pipe_read_fd) != 0 || pipe(pipe_write_fd) != 0) {
45 wlr_log(L_ERROR, "Unable to create pipes for status_command fork");
46 exit(1);
47 }
48
49 status->pid = fork();
50 if (status->pid == 0) {
51 dup2(pipe_read_fd[1], STDOUT_FILENO);
52 close(pipe_read_fd[0]);
53 close(pipe_read_fd[1]);
54
55 dup2(pipe_write_fd[0], STDIN_FILENO);
56 close(pipe_write_fd[0]);
57 close(pipe_write_fd[1]);
58
59 char *const _cmd[] = { "sh", "-c", cmd, NULL, };
60 execvp(_cmd[0], _cmd);
61 exit(1);
62 }
63
64 close(pipe_read_fd[1]);
65 status->read_fd = pipe_read_fd[0];
66 fcntl(status->read_fd, F_SETFL, O_NONBLOCK);
67 close(pipe_write_fd[0]);
68 status->write_fd = pipe_write_fd[1];
69 fcntl(status->write_fd, F_SETFL, O_NONBLOCK);
70
71 status->read = fdopen(status->read_fd, "r");
72 status->write = fdopen(status->write_fd, "w");
73 return status;
74}
75
76void status_line_free(struct status_line *line) {
77 free(line);
78}