diff options
-rw-r--r-- | include/swaybar/bar.h | 1 | ||||
-rw-r--r-- | include/swaybar/status_line.h | 65 | ||||
-rw-r--r-- | swaybar/bar.c | 26 | ||||
-rw-r--r-- | swaybar/config.c | 1 | ||||
-rw-r--r-- | swaybar/meson.build | 1 | ||||
-rw-r--r-- | swaybar/render.c | 56 | ||||
-rw-r--r-- | swaybar/status_line.c | 78 |
7 files changed, 176 insertions, 52 deletions
diff --git a/include/swaybar/bar.h b/include/swaybar/bar.h index c89aa61c..1bf2ea2d 100644 --- a/include/swaybar/bar.h +++ b/include/swaybar/bar.h | |||
@@ -16,6 +16,7 @@ struct swaybar { | |||
16 | 16 | ||
17 | struct swaybar_config *config; | 17 | struct swaybar_config *config; |
18 | struct swaybar_output *focused_output; | 18 | struct swaybar_output *focused_output; |
19 | struct status_line *status; | ||
19 | 20 | ||
20 | int ipc_event_socketfd; | 21 | int ipc_event_socketfd; |
21 | int ipc_socketfd; | 22 | int ipc_socketfd; |
diff --git a/include/swaybar/status_line.h b/include/swaybar/status_line.h index 0664ddee..6c595df0 100644 --- a/include/swaybar/status_line.h +++ b/include/swaybar/status_line.h | |||
@@ -1,61 +1,30 @@ | |||
1 | #ifndef _SWAYBAR_STATUS_LINE_H | 1 | #ifndef _SWAYBAR_STATUS_LINE_H |
2 | #define _SWAYBAR_STATUS_LINE_H | 2 | #define _SWAYBAR_STATUS_LINE_H |
3 | |||
4 | #include <stdint.h> | 3 | #include <stdint.h> |
4 | #include <stdio.h> | ||
5 | #include <stdbool.h> | 5 | #include <stdbool.h> |
6 | |||
7 | #include "list.h" | ||
8 | #include "bar.h" | 6 | #include "bar.h" |
9 | 7 | ||
10 | typedef enum {UNDEF, TEXT, I3BAR} command_protocol; | 8 | enum status_protocol { |
9 | PROTOCOL_UNDEF, | ||
10 | PROTOCOL_TEXT, | ||
11 | PROTOCOL_I3BAR, | ||
12 | }; | ||
11 | 13 | ||
12 | struct status_line { | 14 | struct status_line { |
13 | list_t *block_line; | 15 | pid_t pid; |
14 | const char *text_line; | 16 | int read_fd, write_fd; |
15 | command_protocol protocol; | 17 | FILE *read, *write; |
16 | bool click_events; | ||
17 | }; | ||
18 | 18 | ||
19 | struct status_block { | 19 | enum status_protocol protocol; |
20 | char *full_text, *short_text, *align; | 20 | const char *text; |
21 | bool urgent; | ||
22 | uint32_t color; | ||
23 | int min_width; | ||
24 | char *name, *instance; | ||
25 | bool separator; | ||
26 | int separator_block_width; | ||
27 | bool markup; | ||
28 | // Airblader features | ||
29 | uint32_t background; | ||
30 | uint32_t border; | ||
31 | int border_top; | ||
32 | int border_bottom; | ||
33 | int border_left; | ||
34 | int border_right; | ||
35 | 21 | ||
36 | // Set during rendering | 22 | char *buffer; |
37 | int x; | 23 | size_t buffer_size; |
38 | int width; | ||
39 | }; | 24 | }; |
40 | 25 | ||
41 | /** | 26 | struct status_line *status_line_init(char *cmd); |
42 | * Initialize status line struct. | 27 | void status_line_free(struct status_line *status); |
43 | */ | 28 | bool handle_status_readable(struct status_line *status); |
44 | struct status_line *init_status_line(); | ||
45 | |||
46 | /** | ||
47 | * handle status line activity. | ||
48 | */ | ||
49 | bool handle_status_line(struct bar *bar); | ||
50 | |||
51 | /** | ||
52 | * Handle mouse clicks. | ||
53 | */ | ||
54 | bool status_line_mouse_event(struct bar *bar, int x, int y, uint32_t button); | ||
55 | |||
56 | /** | ||
57 | * Free status line struct. | ||
58 | */ | ||
59 | void free_status_line(struct status_line *line); | ||
60 | 29 | ||
61 | #endif /* _SWAYBAR_STATUS_LINE_H */ | 30 | #endif |
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 | ||
141 | static 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 | |||
137 | static void display_in(int fd, short mask, void *_bar) { | 148 | static 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) { | |||
144 | static void ipc_in(int fd, short mask, void *_bar) { | 155 | static 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 | |
162 | static 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 | ||
154 | void bar_run(struct swaybar *bar) { | 169 | void 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 | ||
14 | static const int ws_horizontal_padding = 5; | 15 | static const int ws_horizontal_padding = 5; |
15 | static const double ws_vertical_padding = 1.5; | 16 | static const double ws_vertical_padding = 1.5; |
16 | static const double border_width = 1; | 17 | static const double border_width = 1; |
17 | 18 | ||
19 | static 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 | |||
43 | static 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 | |||
50 | static 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 | |||
18 | static uint32_t render_binding_mode_indicator(cairo_t *cairo, | 65 | static 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 | |||
12 | bool 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 | |||
37 | struct 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 | |||
76 | void status_line_free(struct status_line *line) { | ||
77 | free(line); | ||
78 | } | ||