diff options
Diffstat (limited to 'swaybar')
-rw-r--r-- | swaybar/bar.c | 55 | ||||
-rw-r--r-- | swaybar/config.c | 2 | ||||
-rw-r--r-- | swaybar/i3bar.c | 7 | ||||
-rw-r--r-- | swaybar/ipc.c | 19 | ||||
-rw-r--r-- | swaybar/main.c | 5 | ||||
-rw-r--r-- | swaybar/meson.build | 1 | ||||
-rw-r--r-- | swaybar/render.c | 134 | ||||
-rw-r--r-- | swaybar/status_line.c | 42 |
8 files changed, 161 insertions, 104 deletions
diff --git a/swaybar/bar.c b/swaybar/bar.c index ab307fd4..388c24c4 100644 --- a/swaybar/bar.c +++ b/swaybar/bar.c | |||
@@ -16,12 +16,13 @@ | |||
16 | #else | 16 | #else |
17 | #include <linux/input-event-codes.h> | 17 | #include <linux/input-event-codes.h> |
18 | #endif | 18 | #endif |
19 | #include "swaybar/render.h" | 19 | #include "swaybar/bar.h" |
20 | #include "swaybar/config.h" | 20 | #include "swaybar/config.h" |
21 | #include "swaybar/event_loop.h" | 21 | #include "swaybar/event_loop.h" |
22 | #include "swaybar/status_line.h" | 22 | #include "swaybar/i3bar.h" |
23 | #include "swaybar/bar.h" | ||
24 | #include "swaybar/ipc.h" | 23 | #include "swaybar/ipc.h" |
24 | #include "swaybar/status_line.h" | ||
25 | #include "swaybar/render.h" | ||
25 | #include "ipc-client.h" | 26 | #include "ipc-client.h" |
26 | #include "list.h" | 27 | #include "list.h" |
27 | #include "log.h" | 28 | #include "log.h" |
@@ -71,6 +72,16 @@ static void swaybar_output_free(struct swaybar_output *output) { | |||
71 | free(output); | 72 | free(output); |
72 | } | 73 | } |
73 | 74 | ||
75 | static void set_output_dirty(struct swaybar_output *output) { | ||
76 | if (output->frame_scheduled) { | ||
77 | output->dirty = true; | ||
78 | return; | ||
79 | } | ||
80 | if (output->surface) { | ||
81 | render_frame(output); | ||
82 | } | ||
83 | } | ||
84 | |||
74 | static void layer_surface_configure(void *data, | 85 | static void layer_surface_configure(void *data, |
75 | struct zwlr_layer_surface_v1 *surface, | 86 | struct zwlr_layer_surface_v1 *surface, |
76 | uint32_t serial, uint32_t width, uint32_t height) { | 87 | uint32_t serial, uint32_t width, uint32_t height) { |
@@ -78,7 +89,7 @@ static void layer_surface_configure(void *data, | |||
78 | output->width = width; | 89 | output->width = width; |
79 | output->height = height; | 90 | output->height = height; |
80 | zwlr_layer_surface_v1_ack_configure(surface, serial); | 91 | zwlr_layer_surface_v1_ack_configure(surface, serial); |
81 | render_frame(output->bar, output); | 92 | set_output_dirty(output); |
82 | } | 93 | } |
83 | 94 | ||
84 | static void layer_surface_closed(void *_output, | 95 | static void layer_surface_closed(void *_output, |
@@ -324,27 +335,22 @@ static void output_geometry(void *data, struct wl_output *wl_output, int32_t x, | |||
324 | const char *make, const char *model, int32_t transform) { | 335 | const char *make, const char *model, int32_t transform) { |
325 | struct swaybar_output *output = data; | 336 | struct swaybar_output *output = data; |
326 | output->subpixel = subpixel; | 337 | output->subpixel = subpixel; |
327 | if (output->surface) { | ||
328 | render_frame(output->bar, output); | ||
329 | } | ||
330 | } | 338 | } |
331 | 339 | ||
332 | static void output_mode(void *data, struct wl_output *output, uint32_t flags, | 340 | static void output_mode(void *data, struct wl_output *wl_output, uint32_t flags, |
333 | int32_t width, int32_t height, int32_t refresh) { | 341 | int32_t width, int32_t height, int32_t refresh) { |
334 | // Who cares | 342 | // Who cares |
335 | } | 343 | } |
336 | 344 | ||
337 | static void output_done(void *data, struct wl_output *output) { | 345 | static void output_done(void *data, struct wl_output *wl_output) { |
338 | // Who cares | 346 | struct swaybar_output *output = data; |
347 | set_output_dirty(output); | ||
339 | } | 348 | } |
340 | 349 | ||
341 | static void output_scale(void *data, struct wl_output *wl_output, | 350 | static void output_scale(void *data, struct wl_output *wl_output, |
342 | int32_t factor) { | 351 | int32_t factor) { |
343 | struct swaybar_output *output = data; | 352 | struct swaybar_output *output = data; |
344 | output->scale = factor; | 353 | output->scale = factor; |
345 | if (output->surface) { | ||
346 | render_frame(output->bar, output); | ||
347 | } | ||
348 | } | 354 | } |
349 | 355 | ||
350 | struct wl_output_listener output_listener = { | 356 | struct wl_output_listener output_listener = { |
@@ -380,7 +386,7 @@ static void xdg_output_handle_done(void *data, | |||
380 | wl_list_insert(&bar->outputs, &output->link); | 386 | wl_list_insert(&bar->outputs, &output->link); |
381 | 387 | ||
382 | add_layer_surface(output); | 388 | add_layer_surface(output); |
383 | render_frame(bar, output); | 389 | set_output_dirty(output); |
384 | } | 390 | } |
385 | } | 391 | } |
386 | 392 | ||
@@ -469,23 +475,23 @@ static const struct wl_registry_listener registry_listener = { | |||
469 | .global_remove = handle_global_remove, | 475 | .global_remove = handle_global_remove, |
470 | }; | 476 | }; |
471 | 477 | ||
472 | static void render_all_frames(struct swaybar *bar) { | 478 | static void set_bar_dirty(struct swaybar *bar) { |
473 | struct swaybar_output *output; | 479 | struct swaybar_output *output; |
474 | wl_list_for_each(output, &bar->outputs, link) { | 480 | wl_list_for_each(output, &bar->outputs, link) { |
475 | if (output->surface != NULL) { | 481 | set_output_dirty(output); |
476 | render_frame(bar, output); | ||
477 | } | ||
478 | } | 482 | } |
479 | } | 483 | } |
480 | 484 | ||
481 | void bar_setup(struct swaybar *bar, | 485 | bool bar_setup(struct swaybar *bar, |
482 | const char *socket_path, const char *bar_id) { | 486 | const char *socket_path, const char *bar_id) { |
483 | bar_init(bar); | 487 | bar_init(bar); |
484 | init_event_loop(); | 488 | init_event_loop(); |
485 | 489 | ||
486 | bar->ipc_socketfd = ipc_open_socket(socket_path); | 490 | bar->ipc_socketfd = ipc_open_socket(socket_path); |
487 | bar->ipc_event_socketfd = ipc_open_socket(socket_path); | 491 | bar->ipc_event_socketfd = ipc_open_socket(socket_path); |
488 | ipc_initialize(bar, bar_id); | 492 | if (!ipc_initialize(bar, bar_id)) { |
493 | return false; | ||
494 | } | ||
489 | if (bar->config->status_command) { | 495 | if (bar->config->status_command) { |
490 | bar->status = status_line_init(bar->config->status_command); | 496 | bar->status = status_line_init(bar->config->status_command); |
491 | } | 497 | } |
@@ -525,7 +531,8 @@ void bar_setup(struct swaybar *bar, | |||
525 | assert(pointer->cursor_surface); | 531 | assert(pointer->cursor_surface); |
526 | 532 | ||
527 | ipc_get_workspaces(bar); | 533 | ipc_get_workspaces(bar); |
528 | render_all_frames(bar); | 534 | set_bar_dirty(bar); |
535 | return true; | ||
529 | } | 536 | } |
530 | 537 | ||
531 | static void display_in(int fd, short mask, void *data) { | 538 | static void display_in(int fd, short mask, void *data) { |
@@ -539,7 +546,7 @@ static void display_in(int fd, short mask, void *data) { | |||
539 | static void ipc_in(int fd, short mask, void *data) { | 546 | static void ipc_in(int fd, short mask, void *data) { |
540 | struct swaybar *bar = data; | 547 | struct swaybar *bar = data; |
541 | if (handle_ipc_readable(bar)) { | 548 | if (handle_ipc_readable(bar)) { |
542 | render_all_frames(bar); | 549 | set_bar_dirty(bar); |
543 | } | 550 | } |
544 | } | 551 | } |
545 | 552 | ||
@@ -547,10 +554,10 @@ static void status_in(int fd, short mask, void *data) { | |||
547 | struct swaybar *bar = data; | 554 | struct swaybar *bar = data; |
548 | if (mask & (POLLHUP | POLLERR)) { | 555 | if (mask & (POLLHUP | POLLERR)) { |
549 | status_error(bar->status, "[error reading from status command]"); | 556 | status_error(bar->status, "[error reading from status command]"); |
550 | render_all_frames(bar); | 557 | set_bar_dirty(bar); |
551 | remove_event(fd); | 558 | remove_event(fd); |
552 | } else if (status_handle_readable(bar->status)) { | 559 | } else if (status_handle_readable(bar->status)) { |
553 | render_all_frames(bar); | 560 | set_bar_dirty(bar); |
554 | } | 561 | } |
555 | } | 562 | } |
556 | 563 | ||
diff --git a/swaybar/config.c b/swaybar/config.c index db7b0db6..4e851cca 100644 --- a/swaybar/config.c +++ b/swaybar/config.c | |||
@@ -22,7 +22,7 @@ uint32_t parse_position(const char *position) { | |||
22 | } | 22 | } |
23 | } | 23 | } |
24 | 24 | ||
25 | struct swaybar_config *init_config() { | 25 | struct swaybar_config *init_config(void) { |
26 | struct swaybar_config *config = calloc(1, sizeof(struct swaybar_config)); | 26 | struct swaybar_config *config = calloc(1, sizeof(struct swaybar_config)); |
27 | config->status_command = NULL; | 27 | config->status_command = NULL; |
28 | config->pango_markup = false; | 28 | config->pango_markup = false; |
diff --git a/swaybar/i3bar.c b/swaybar/i3bar.c index 325aa61a..1d754808 100644 --- a/swaybar/i3bar.c +++ b/swaybar/i3bar.c | |||
@@ -6,7 +6,9 @@ | |||
6 | #include <string.h> | 6 | #include <string.h> |
7 | #include <unistd.h> | 7 | #include <unistd.h> |
8 | #include <wlr/util/log.h> | 8 | #include <wlr/util/log.h> |
9 | #include "swaybar/bar.h" | ||
9 | #include "swaybar/config.h" | 10 | #include "swaybar/config.h" |
11 | #include "swaybar/i3bar.h" | ||
10 | #include "swaybar/status_line.h" | 12 | #include "swaybar/status_line.h" |
11 | 13 | ||
12 | void i3bar_block_unref(struct i3bar_block *block) { | 14 | void i3bar_block_unref(struct i3bar_block *block) { |
@@ -258,7 +260,7 @@ bool i3bar_handle_readable(struct status_line *status) { | |||
258 | 260 | ||
259 | enum hotspot_event_handling i3bar_block_send_click(struct status_line *status, | 261 | enum hotspot_event_handling i3bar_block_send_click(struct status_line *status, |
260 | struct i3bar_block *block, int x, int y, enum x11_button button) { | 262 | struct i3bar_block *block, int x, int y, enum x11_button button) { |
261 | wlr_log(WLR_DEBUG, "block %s clicked", block->name ? block->name : "(nil)"); | 263 | wlr_log(WLR_DEBUG, "block %s clicked", block->name); |
262 | if (!block->name || !status->click_events) { | 264 | if (!block->name || !status->click_events) { |
263 | return HOTSPOT_PROCESS; | 265 | return HOTSPOT_PROCESS; |
264 | } | 266 | } |
@@ -274,10 +276,11 @@ enum hotspot_event_handling i3bar_block_send_click(struct status_line *status, | |||
274 | json_object_object_add(event_json, "button", json_object_new_int(button)); | 276 | json_object_object_add(event_json, "button", json_object_new_int(button)); |
275 | json_object_object_add(event_json, "x", json_object_new_int(x)); | 277 | json_object_object_add(event_json, "x", json_object_new_int(x)); |
276 | json_object_object_add(event_json, "y", json_object_new_int(y)); | 278 | json_object_object_add(event_json, "y", json_object_new_int(y)); |
277 | if (dprintf(status->write_fd, "%s,\n", | 279 | if (dprintf(status->write_fd, "%s%s\n", status->clicked ? "," : "", |
278 | json_object_to_json_string(event_json)) < 0) { | 280 | json_object_to_json_string(event_json)) < 0) { |
279 | status_error(status, "[failed to write click event]"); | 281 | status_error(status, "[failed to write click event]"); |
280 | } | 282 | } |
283 | status->clicked = true; | ||
281 | json_object_put(event_json); | 284 | json_object_put(event_json); |
282 | return HOTSPOT_IGNORE; | 285 | return HOTSPOT_IGNORE; |
283 | } | 286 | } |
diff --git a/swaybar/ipc.c b/swaybar/ipc.c index 0e60c10c..7c53a44f 100644 --- a/swaybar/ipc.c +++ b/swaybar/ipc.c | |||
@@ -141,9 +141,16 @@ static void ipc_parse_colors( | |||
141 | } | 141 | } |
142 | } | 142 | } |
143 | 143 | ||
144 | static void ipc_parse_config( | 144 | static bool ipc_parse_config( |
145 | struct swaybar_config *config, const char *payload) { | 145 | struct swaybar_config *config, const char *payload) { |
146 | json_object *bar_config = json_tokener_parse(payload); | 146 | json_object *bar_config = json_tokener_parse(payload); |
147 | json_object *success; | ||
148 | if (json_object_object_get_ex(bar_config, "success", &success) | ||
149 | && !json_object_get_boolean(success)) { | ||
150 | wlr_log(WLR_ERROR, "No bar with that ID. Use 'swaymsg -t get_bar_config to get the available bar configs."); | ||
151 | json_object_put(bar_config); | ||
152 | return false; | ||
153 | } | ||
147 | json_object *markup, *mode, *hidden_bar, *position, *status_command; | 154 | json_object *markup, *mode, *hidden_bar, *position, *status_command; |
148 | json_object *font, *bar_height, *wrap_scroll, *workspace_buttons, *strip_workspace_numbers; | 155 | json_object *font, *bar_height, *wrap_scroll, *workspace_buttons, *strip_workspace_numbers; |
149 | json_object *binding_mode_indicator, *verbose, *colors, *sep_symbol, *outputs; | 156 | json_object *binding_mode_indicator, *verbose, *colors, *sep_symbol, *outputs; |
@@ -226,10 +233,10 @@ static void ipc_parse_config( | |||
226 | } | 233 | } |
227 | 234 | ||
228 | json_object_put(bar_config); | 235 | json_object_put(bar_config); |
236 | return true; | ||
229 | } | 237 | } |
230 | 238 | ||
231 | void ipc_get_workspaces(struct swaybar *bar) { | 239 | void ipc_get_workspaces(struct swaybar *bar) { |
232 | bar->focused_output = NULL; | ||
233 | struct swaybar_output *output; | 240 | struct swaybar_output *output; |
234 | wl_list_for_each(output, &bar->outputs, link) { | 241 | wl_list_for_each(output, &bar->outputs, link) { |
235 | free_workspaces(&output->workspaces); | 242 | free_workspaces(&output->workspaces); |
@@ -312,11 +319,14 @@ static void ipc_get_outputs(struct swaybar *bar) { | |||
312 | free(res); | 319 | free(res); |
313 | } | 320 | } |
314 | 321 | ||
315 | void ipc_initialize(struct swaybar *bar, const char *bar_id) { | 322 | bool ipc_initialize(struct swaybar *bar, const char *bar_id) { |
316 | uint32_t len = strlen(bar_id); | 323 | uint32_t len = strlen(bar_id); |
317 | char *res = ipc_single_command(bar->ipc_socketfd, | 324 | char *res = ipc_single_command(bar->ipc_socketfd, |
318 | IPC_GET_BAR_CONFIG, bar_id, &len); | 325 | IPC_GET_BAR_CONFIG, bar_id, &len); |
319 | ipc_parse_config(bar->config, res); | 326 | if (!ipc_parse_config(bar->config, res)) { |
327 | free(res); | ||
328 | return false; | ||
329 | } | ||
320 | free(res); | 330 | free(res); |
321 | ipc_get_outputs(bar); | 331 | ipc_get_outputs(bar); |
322 | 332 | ||
@@ -324,6 +334,7 @@ void ipc_initialize(struct swaybar *bar, const char *bar_id) { | |||
324 | len = strlen(subscribe); | 334 | len = strlen(subscribe); |
325 | free(ipc_single_command(bar->ipc_event_socketfd, | 335 | free(ipc_single_command(bar->ipc_event_socketfd, |
326 | IPC_SUBSCRIBE, subscribe, &len)); | 336 | IPC_SUBSCRIBE, subscribe, &len)); |
337 | return true; | ||
327 | } | 338 | } |
328 | 339 | ||
329 | bool handle_ipc_readable(struct swaybar *bar) { | 340 | bool handle_ipc_readable(struct swaybar *bar) { |
diff --git a/swaybar/main.c b/swaybar/main.c index 60e4b37c..d2c579db 100644 --- a/swaybar/main.c +++ b/swaybar/main.c | |||
@@ -96,7 +96,10 @@ int main(int argc, char **argv) { | |||
96 | 96 | ||
97 | signal(SIGTERM, sig_handler); | 97 | signal(SIGTERM, sig_handler); |
98 | 98 | ||
99 | bar_setup(&swaybar, socket_path, bar_id); | 99 | if (!bar_setup(&swaybar, socket_path, bar_id)) { |
100 | free(socket_path); | ||
101 | return 1; | ||
102 | } | ||
100 | 103 | ||
101 | free(socket_path); | 104 | free(socket_path); |
102 | free(bar_id); | 105 | free(bar_id); |
diff --git a/swaybar/meson.build b/swaybar/meson.build index d65edb11..7a02a33f 100644 --- a/swaybar/meson.build +++ b/swaybar/meson.build | |||
@@ -24,5 +24,6 @@ executable( | |||
24 | wlroots, | 24 | wlroots, |
25 | ], | 25 | ], |
26 | link_with: [lib_sway_common, lib_sway_client], | 26 | link_with: [lib_sway_common, lib_sway_client], |
27 | install_rpath : rpathdir, | ||
27 | install: true | 28 | install: true |
28 | ) | 29 | ) |
diff --git a/swaybar/render.c b/swaybar/render.c index 9413dc57..dc31a5ea 100644 --- a/swaybar/render.c +++ b/swaybar/render.c | |||
@@ -10,6 +10,7 @@ | |||
10 | #include "pool-buffer.h" | 10 | #include "pool-buffer.h" |
11 | #include "swaybar/bar.h" | 11 | #include "swaybar/bar.h" |
12 | #include "swaybar/config.h" | 12 | #include "swaybar/config.h" |
13 | #include "swaybar/i3bar.h" | ||
13 | #include "swaybar/ipc.h" | 14 | #include "swaybar/ipc.h" |
14 | #include "swaybar/render.h" | 15 | #include "swaybar/render.h" |
15 | #include "swaybar/status_line.h" | 16 | #include "swaybar/status_line.h" |
@@ -20,47 +21,47 @@ static const double WS_VERTICAL_PADDING = 1.5; | |||
20 | static const double BORDER_WIDTH = 1; | 21 | static const double BORDER_WIDTH = 1; |
21 | 22 | ||
22 | static uint32_t render_status_line_error(cairo_t *cairo, | 23 | static uint32_t render_status_line_error(cairo_t *cairo, |
23 | struct swaybar_output *output, struct swaybar_config *config, | 24 | struct swaybar_output *output, double *x) { |
24 | const char *error, double *x, uint32_t surface_height) { | 25 | const char *error = output->bar->status->text; |
25 | if (!error) { | 26 | if (!error) { |
26 | return 0; | 27 | return 0; |
27 | } | 28 | } |
28 | 29 | ||
29 | uint32_t height = surface_height * output->scale; | 30 | uint32_t height = output->height * output->scale; |
30 | 31 | ||
31 | cairo_set_source_u32(cairo, 0xFF0000FF); | 32 | cairo_set_source_u32(cairo, 0xFF0000FF); |
32 | 33 | ||
33 | int margin = 3 * output->scale; | 34 | int margin = 3 * output->scale; |
34 | int ws_vertical_padding = WS_VERTICAL_PADDING * output->scale; | 35 | int ws_vertical_padding = WS_VERTICAL_PADDING * output->scale; |
35 | 36 | ||
37 | char *font = output->bar->config->font; | ||
36 | int text_width, text_height; | 38 | int text_width, text_height; |
37 | get_text_size(cairo, config->font, &text_width, &text_height, NULL, | 39 | get_text_size(cairo, font, &text_width, &text_height, NULL, |
38 | output->scale, false, "%s", error); | 40 | output->scale, false, "%s", error); |
39 | 41 | ||
40 | uint32_t ideal_height = text_height + ws_vertical_padding * 2; | 42 | uint32_t ideal_height = text_height + ws_vertical_padding * 2; |
41 | uint32_t ideal_surface_height = ideal_height / output->scale; | 43 | uint32_t ideal_surface_height = ideal_height / output->scale; |
42 | if (surface_height < ideal_surface_height) { | 44 | if (output->height < ideal_surface_height) { |
43 | return ideal_surface_height; | 45 | return ideal_surface_height; |
44 | } | 46 | } |
45 | *x -= text_width + margin; | 47 | *x -= text_width + margin; |
46 | 48 | ||
47 | double text_y = height / 2.0 - text_height / 2.0; | 49 | double text_y = height / 2.0 - text_height / 2.0; |
48 | cairo_move_to(cairo, *x, (int)floor(text_y)); | 50 | cairo_move_to(cairo, *x, (int)floor(text_y)); |
49 | pango_printf(cairo, config->font, output->scale, false, "%s", error); | 51 | pango_printf(cairo, font, output->scale, false, "%s", error); |
50 | *x -= margin; | 52 | *x -= margin; |
51 | return surface_height; | 53 | return output->height; |
52 | } | 54 | } |
53 | 55 | ||
54 | static uint32_t render_status_line_text(cairo_t *cairo, | 56 | static uint32_t render_status_line_text(cairo_t *cairo, |
55 | struct swaybar_output *output, struct swaybar_config *config, | 57 | struct swaybar_output *output, double *x) { |
56 | const char *text, bool focused, double *x, uint32_t surface_height) { | 58 | const char *text = output->bar->status->text; |
57 | if (!text) { | 59 | if (!text) { |
58 | return 0; | 60 | return 0; |
59 | } | 61 | } |
60 | 62 | ||
61 | uint32_t height = surface_height * output->scale; | 63 | struct swaybar_config *config = output->bar->config; |
62 | 64 | cairo_set_source_u32(cairo, output->focused ? | |
63 | cairo_set_source_u32(cairo, focused ? | ||
64 | config->colors.focused_statusline : config->colors.statusline); | 65 | config->colors.focused_statusline : config->colors.statusline); |
65 | 66 | ||
66 | int text_width, text_height; | 67 | int text_width, text_height; |
@@ -72,17 +73,18 @@ static uint32_t render_status_line_text(cairo_t *cairo, | |||
72 | 73 | ||
73 | uint32_t ideal_height = text_height + ws_vertical_padding * 2; | 74 | uint32_t ideal_height = text_height + ws_vertical_padding * 2; |
74 | uint32_t ideal_surface_height = ideal_height / output->scale; | 75 | uint32_t ideal_surface_height = ideal_height / output->scale; |
75 | if (surface_height < ideal_surface_height) { | 76 | if (output->height < ideal_surface_height) { |
76 | return ideal_surface_height; | 77 | return ideal_surface_height; |
77 | } | 78 | } |
78 | 79 | ||
79 | *x -= text_width + margin; | 80 | *x -= text_width + margin; |
81 | uint32_t height = output->height * output->scale; | ||
80 | double text_y = height / 2.0 - text_height / 2.0; | 82 | double text_y = height / 2.0 - text_height / 2.0; |
81 | cairo_move_to(cairo, *x, (int)floor(text_y)); | 83 | cairo_move_to(cairo, *x, (int)floor(text_y)); |
82 | pango_printf(cairo, config->font, output->scale, | 84 | pango_printf(cairo, config->font, output->scale, |
83 | config->pango_markup, "%s", text); | 85 | config->pango_markup, "%s", text); |
84 | *x -= margin; | 86 | *x -= margin; |
85 | return surface_height; | 87 | return output->height; |
86 | } | 88 | } |
87 | 89 | ||
88 | static void render_sharp_line(cairo_t *cairo, uint32_t color, | 90 | static void render_sharp_line(cairo_t *cairo, uint32_t color, |
@@ -122,12 +124,11 @@ static void i3bar_block_unref_callback(void *data) { | |||
122 | 124 | ||
123 | static uint32_t render_status_block(cairo_t *cairo, | 125 | static uint32_t render_status_block(cairo_t *cairo, |
124 | struct swaybar_output *output, struct i3bar_block *block, double *x, | 126 | struct swaybar_output *output, struct i3bar_block *block, double *x, |
125 | uint32_t surface_height, bool focused, bool edge) { | 127 | bool edge) { |
126 | if (!block->full_text || !*block->full_text) { | 128 | if (!block->full_text || !*block->full_text) { |
127 | return 0; | 129 | return 0; |
128 | } | 130 | } |
129 | 131 | ||
130 | uint32_t height = surface_height * output->scale; | ||
131 | struct swaybar_config *config = output->bar->config; | 132 | struct swaybar_config *config = output->bar->config; |
132 | 133 | ||
133 | int text_width, text_height; | 134 | int text_width, text_height; |
@@ -145,7 +146,7 @@ static uint32_t render_status_block(cairo_t *cairo, | |||
145 | double block_width = width; | 146 | double block_width = width; |
146 | uint32_t ideal_height = text_height + ws_vertical_padding * 2; | 147 | uint32_t ideal_height = text_height + ws_vertical_padding * 2; |
147 | uint32_t ideal_surface_height = ideal_height / output->scale; | 148 | uint32_t ideal_surface_height = ideal_height / output->scale; |
148 | if (surface_height < ideal_surface_height) { | 149 | if (output->height < ideal_surface_height) { |
149 | return ideal_surface_height; | 150 | return ideal_surface_height; |
150 | } | 151 | } |
151 | 152 | ||
@@ -166,7 +167,7 @@ static uint32_t render_status_block(cairo_t *cairo, | |||
166 | output->scale, false, "%s", config->sep_symbol); | 167 | output->scale, false, "%s", config->sep_symbol); |
167 | uint32_t _ideal_height = sep_height + ws_vertical_padding * 2; | 168 | uint32_t _ideal_height = sep_height + ws_vertical_padding * 2; |
168 | uint32_t _ideal_surface_height = _ideal_height / output->scale; | 169 | uint32_t _ideal_surface_height = _ideal_height / output->scale; |
169 | if (surface_height < _ideal_surface_height) { | 170 | if (output->height < _ideal_surface_height) { |
170 | return _ideal_surface_height; | 171 | return _ideal_surface_height; |
171 | } | 172 | } |
172 | if (sep_width > block->separator_block_width) { | 173 | if (sep_width > block->separator_block_width) { |
@@ -178,6 +179,7 @@ static uint32_t render_status_block(cairo_t *cairo, | |||
178 | *x -= margin; | 179 | *x -= margin; |
179 | } | 180 | } |
180 | 181 | ||
182 | uint32_t height = output->height * output->scale; | ||
181 | if (output->bar->status->click_events) { | 183 | if (output->bar->status->click_events) { |
182 | struct swaybar_hotspot *hotspot = calloc(1, sizeof(struct swaybar_hotspot)); | 184 | struct swaybar_hotspot *hotspot = calloc(1, sizeof(struct swaybar_hotspot)); |
183 | hotspot->x = *x; | 185 | hotspot->x = *x; |
@@ -241,7 +243,7 @@ static uint32_t render_status_block(cairo_t *cairo, | |||
241 | } | 243 | } |
242 | 244 | ||
243 | if (!edge && block->separator) { | 245 | if (!edge && block->separator) { |
244 | if (focused) { | 246 | if (output->focused) { |
245 | cairo_set_source_u32(cairo, config->colors.focused_separator); | 247 | cairo_set_source_u32(cairo, config->colors.focused_separator); |
246 | } else { | 248 | } else { |
247 | cairo_set_source_u32(cairo, config->colors.separator); | 249 | cairo_set_source_u32(cairo, config->colors.separator); |
@@ -260,19 +262,16 @@ static uint32_t render_status_block(cairo_t *cairo, | |||
260 | cairo_stroke(cairo); | 262 | cairo_stroke(cairo); |
261 | } | 263 | } |
262 | } | 264 | } |
263 | return surface_height; | 265 | return output->height; |
264 | } | 266 | } |
265 | 267 | ||
266 | static uint32_t render_status_line_i3bar(cairo_t *cairo, | 268 | static uint32_t render_status_line_i3bar(cairo_t *cairo, |
267 | struct swaybar_config *config, struct swaybar_output *output, | 269 | struct swaybar_output *output, double *x) { |
268 | struct status_line *status, bool focused, | ||
269 | double *x, uint32_t surface_height) { | ||
270 | uint32_t max_height = 0; | 270 | uint32_t max_height = 0; |
271 | bool edge = true; | 271 | bool edge = true; |
272 | struct i3bar_block *block; | 272 | struct i3bar_block *block; |
273 | wl_list_for_each(block, &status->blocks, link) { | 273 | wl_list_for_each(block, &output->bar->status->blocks, link) { |
274 | uint32_t h = render_status_block(cairo, output, | 274 | uint32_t h = render_status_block(cairo, output, block, x, edge); |
275 | block, x, surface_height, focused, edge); | ||
276 | max_height = h > max_height ? h : max_height; | 275 | max_height = h > max_height ? h : max_height; |
277 | edge = false; | 276 | edge = false; |
278 | } | 277 | } |
@@ -280,19 +279,15 @@ static uint32_t render_status_line_i3bar(cairo_t *cairo, | |||
280 | } | 279 | } |
281 | 280 | ||
282 | static uint32_t render_status_line(cairo_t *cairo, | 281 | static uint32_t render_status_line(cairo_t *cairo, |
283 | struct swaybar_config *config, struct swaybar_output *output, | 282 | struct swaybar_output *output, double *x) { |
284 | struct status_line *status, bool focused, | 283 | struct status_line *status = output->bar->status; |
285 | double *x, uint32_t surface_height) { | ||
286 | switch (status->protocol) { | 284 | switch (status->protocol) { |
287 | case PROTOCOL_ERROR: | 285 | case PROTOCOL_ERROR: |
288 | return render_status_line_error(cairo, output, config, | 286 | return render_status_line_error(cairo, output, x); |
289 | status->text, x, surface_height); | ||
290 | case PROTOCOL_TEXT: | 287 | case PROTOCOL_TEXT: |
291 | return render_status_line_text(cairo, output, config, | 288 | return render_status_line_text(cairo, output, x); |
292 | status->text, focused, x, surface_height); | ||
293 | case PROTOCOL_I3BAR: | 289 | case PROTOCOL_I3BAR: |
294 | return render_status_line_i3bar(cairo, config, output, | 290 | return render_status_line_i3bar(cairo, output, x); |
295 | status, focused, x, surface_height); | ||
296 | case PROTOCOL_UNDEF: | 291 | case PROTOCOL_UNDEF: |
297 | return 0; | 292 | return 0; |
298 | } | 293 | } |
@@ -300,10 +295,9 @@ static uint32_t render_status_line(cairo_t *cairo, | |||
300 | } | 295 | } |
301 | 296 | ||
302 | static uint32_t render_binding_mode_indicator(cairo_t *cairo, | 297 | static uint32_t render_binding_mode_indicator(cairo_t *cairo, |
303 | struct swaybar_output *output, struct swaybar_config *config, | 298 | struct swaybar_output *output, double x) { |
304 | const char *mode, double x, uint32_t surface_height) { | 299 | struct swaybar_config *config = output->bar->config; |
305 | uint32_t height = surface_height * output->scale; | 300 | const char *mode = config->mode; |
306 | |||
307 | int text_width, text_height; | 301 | int text_width, text_height; |
308 | get_text_size(cairo, config->font, &text_width, &text_height, NULL, | 302 | get_text_size(cairo, config->font, &text_width, &text_height, NULL, |
309 | output->scale, config->mode_pango_markup, | 303 | output->scale, config->mode_pango_markup, |
@@ -316,11 +310,12 @@ static uint32_t render_binding_mode_indicator(cairo_t *cairo, | |||
316 | uint32_t ideal_height = text_height + ws_vertical_padding * 2 | 310 | uint32_t ideal_height = text_height + ws_vertical_padding * 2 |
317 | + border_width * 2; | 311 | + border_width * 2; |
318 | uint32_t ideal_surface_height = ideal_height / output->scale; | 312 | uint32_t ideal_surface_height = ideal_height / output->scale; |
319 | if (surface_height < ideal_surface_height) { | 313 | if (output->height < ideal_surface_height) { |
320 | return ideal_surface_height; | 314 | return ideal_surface_height; |
321 | } | 315 | } |
322 | uint32_t width = text_width + ws_horizontal_padding * 2 + border_width * 2; | 316 | uint32_t width = text_width + ws_horizontal_padding * 2 + border_width * 2; |
323 | 317 | ||
318 | uint32_t height = output->height * output->scale; | ||
324 | cairo_set_source_u32(cairo, config->colors.binding_mode.background); | 319 | cairo_set_source_u32(cairo, config->colors.binding_mode.background); |
325 | cairo_rectangle(cairo, x, 0, width, height); | 320 | cairo_rectangle(cairo, x, 0, width, height); |
326 | cairo_fill(cairo); | 321 | cairo_fill(cairo); |
@@ -340,7 +335,7 @@ static uint32_t render_binding_mode_indicator(cairo_t *cairo, | |||
340 | cairo_move_to(cairo, x + width / 2 - text_width / 2, (int)floor(text_y)); | 335 | cairo_move_to(cairo, x + width / 2 - text_width / 2, (int)floor(text_y)); |
341 | pango_printf(cairo, config->font, output->scale, config->mode_pango_markup, | 336 | pango_printf(cairo, config->font, output->scale, config->mode_pango_markup, |
342 | "%s", mode); | 337 | "%s", mode); |
343 | return surface_height; | 338 | return output->height; |
344 | } | 339 | } |
345 | 340 | ||
346 | static const char *strip_workspace_number(const char *ws_name) { | 341 | static const char *strip_workspace_number(const char *ws_name) { |
@@ -366,8 +361,9 @@ static enum hotspot_event_handling workspace_hotspot_callback(struct swaybar_out | |||
366 | } | 361 | } |
367 | 362 | ||
368 | static uint32_t render_workspace_button(cairo_t *cairo, | 363 | static uint32_t render_workspace_button(cairo_t *cairo, |
369 | struct swaybar_output *output, struct swaybar_config *config, | 364 | struct swaybar_output *output, |
370 | struct swaybar_workspace *ws, double *x, uint32_t surface_height) { | 365 | struct swaybar_workspace *ws, double *x) { |
366 | struct swaybar_config *config = output->bar->config; | ||
371 | const char *name = ws->name; | 367 | const char *name = ws->name; |
372 | if (config->strip_workspace_numbers) { | 368 | if (config->strip_workspace_numbers) { |
373 | name = strip_workspace_number(ws->name); | 369 | name = strip_workspace_number(ws->name); |
@@ -384,7 +380,7 @@ static uint32_t render_workspace_button(cairo_t *cairo, | |||
384 | box_colors = config->colors.inactive_workspace; | 380 | box_colors = config->colors.inactive_workspace; |
385 | } | 381 | } |
386 | 382 | ||
387 | uint32_t height = surface_height * output->scale; | 383 | uint32_t height = output->height * output->scale; |
388 | 384 | ||
389 | int text_width, text_height; | 385 | int text_width, text_height; |
390 | get_text_size(cairo, config->font, &text_width, &text_height, NULL, | 386 | get_text_size(cairo, config->font, &text_width, &text_height, NULL, |
@@ -397,7 +393,7 @@ static uint32_t render_workspace_button(cairo_t *cairo, | |||
397 | uint32_t ideal_height = ws_vertical_padding * 2 + text_height | 393 | uint32_t ideal_height = ws_vertical_padding * 2 + text_height |
398 | + border_width * 2; | 394 | + border_width * 2; |
399 | uint32_t ideal_surface_height = ideal_height / output->scale; | 395 | uint32_t ideal_surface_height = ideal_height / output->scale; |
400 | if (surface_height < ideal_surface_height) { | 396 | if (output->height < ideal_surface_height) { |
401 | return ideal_surface_height; | 397 | return ideal_surface_height; |
402 | } | 398 | } |
403 | 399 | ||
@@ -434,11 +430,11 @@ static uint32_t render_workspace_button(cairo_t *cairo, | |||
434 | wl_list_insert(&output->hotspots, &hotspot->link); | 430 | wl_list_insert(&output->hotspots, &hotspot->link); |
435 | 431 | ||
436 | *x += width; | 432 | *x += width; |
437 | return surface_height; | 433 | return output->height; |
438 | } | 434 | } |
439 | 435 | ||
440 | static uint32_t render_to_cairo(cairo_t *cairo, | 436 | static uint32_t render_to_cairo(cairo_t *cairo, struct swaybar_output *output) { |
441 | struct swaybar *bar, struct swaybar_output *output) { | 437 | struct swaybar *bar = output->bar; |
442 | struct swaybar_config *config = bar->config; | 438 | struct swaybar_config *config = bar->config; |
443 | cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE); | 439 | cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE); |
444 | if (output->focused) { | 440 | if (output->focused) { |
@@ -458,29 +454,41 @@ static uint32_t render_to_cairo(cairo_t *cairo, | |||
458 | */ | 454 | */ |
459 | double x = output->width * output->scale; | 455 | double x = output->width * output->scale; |
460 | if (bar->status) { | 456 | if (bar->status) { |
461 | uint32_t h = render_status_line(cairo, config, output, | 457 | uint32_t h = render_status_line(cairo, output, &x); |
462 | bar->status, output->focused, &x, output->height); | ||
463 | max_height = h > max_height ? h : max_height; | 458 | max_height = h > max_height ? h : max_height; |
464 | } | 459 | } |
465 | x = 0; | 460 | x = 0; |
466 | if (config->workspace_buttons) { | 461 | if (config->workspace_buttons) { |
467 | struct swaybar_workspace *ws; | 462 | struct swaybar_workspace *ws; |
468 | wl_list_for_each_reverse(ws, &output->workspaces, link) { | 463 | wl_list_for_each_reverse(ws, &output->workspaces, link) { |
469 | uint32_t h = render_workspace_button(cairo, | 464 | uint32_t h = render_workspace_button(cairo, output, ws, &x); |
470 | output, config, ws, &x, output->height); | ||
471 | max_height = h > max_height ? h : max_height; | 465 | max_height = h > max_height ? h : max_height; |
472 | } | 466 | } |
473 | } | 467 | } |
474 | if (config->binding_mode_indicator && config->mode) { | 468 | if (config->binding_mode_indicator && config->mode) { |
475 | uint32_t h = render_binding_mode_indicator(cairo, | 469 | uint32_t h = render_binding_mode_indicator(cairo, output, x); |
476 | output, config, config->mode, x, output->height); | ||
477 | max_height = h > max_height ? h : max_height; | 470 | max_height = h > max_height ? h : max_height; |
478 | } | 471 | } |
479 | 472 | ||
480 | return max_height > output->height ? max_height : output->height; | 473 | return max_height > output->height ? max_height : output->height; |
481 | } | 474 | } |
482 | 475 | ||
483 | void render_frame(struct swaybar *bar, struct swaybar_output *output) { | 476 | static void output_frame_handle_done(void *data, struct wl_callback *callback, |
477 | uint32_t time) { | ||
478 | wl_callback_destroy(callback); | ||
479 | struct swaybar_output *output = data; | ||
480 | output->frame_scheduled = false; | ||
481 | if (output->dirty) { | ||
482 | render_frame(output); | ||
483 | output->dirty = false; | ||
484 | } | ||
485 | } | ||
486 | |||
487 | static const struct wl_callback_listener output_frame_listener = { | ||
488 | .done = output_frame_handle_done | ||
489 | }; | ||
490 | |||
491 | void render_frame(struct swaybar_output *output) { | ||
484 | assert(output->surface != NULL); | 492 | assert(output->surface != NULL); |
485 | 493 | ||
486 | struct swaybar_hotspot *hotspot, *tmp; | 494 | struct swaybar_hotspot *hotspot, *tmp; |
@@ -506,9 +514,10 @@ void render_frame(struct swaybar *bar, struct swaybar_output *output) { | |||
506 | cairo_set_operator(cairo, CAIRO_OPERATOR_CLEAR); | 514 | cairo_set_operator(cairo, CAIRO_OPERATOR_CLEAR); |
507 | cairo_paint(cairo); | 515 | cairo_paint(cairo); |
508 | cairo_restore(cairo); | 516 | cairo_restore(cairo); |
509 | uint32_t height = render_to_cairo(cairo, bar, output); | 517 | uint32_t height = render_to_cairo(cairo, output); |
510 | if (bar->config->height >= 0 && height < (uint32_t)bar->config->height) { | 518 | int config_height = output->bar->config->height; |
511 | height = bar->config->height; | 519 | if (config_height >= 0 && height < (uint32_t)config_height) { |
520 | height = config_height; | ||
512 | } | 521 | } |
513 | if (height != output->height) { | 522 | if (height != output->height) { |
514 | // Reconfigure surface | 523 | // Reconfigure surface |
@@ -519,11 +528,13 @@ void render_frame(struct swaybar *bar, struct swaybar_output *output) { | |||
519 | wl_surface_commit(output->surface); | 528 | wl_surface_commit(output->surface); |
520 | } else if (height > 0) { | 529 | } else if (height > 0) { |
521 | // Replay recording into shm and send it off | 530 | // Replay recording into shm and send it off |
522 | output->current_buffer = get_next_buffer(bar->shm, | 531 | output->current_buffer = get_next_buffer(output->bar->shm, |
523 | output->buffers, | 532 | output->buffers, |
524 | output->width * output->scale, | 533 | output->width * output->scale, |
525 | output->height * output->scale); | 534 | output->height * output->scale); |
526 | if (!output->current_buffer) { | 535 | if (!output->current_buffer) { |
536 | cairo_surface_destroy(recorder); | ||
537 | cairo_destroy(cairo); | ||
527 | return; | 538 | return; |
528 | } | 539 | } |
529 | cairo_t *shm = output->current_buffer->cairo; | 540 | cairo_t *shm = output->current_buffer->cairo; |
@@ -541,6 +552,11 @@ void render_frame(struct swaybar *bar, struct swaybar_output *output) { | |||
541 | output->current_buffer->buffer, 0, 0); | 552 | output->current_buffer->buffer, 0, 0); |
542 | wl_surface_damage(output->surface, 0, 0, | 553 | wl_surface_damage(output->surface, 0, 0, |
543 | output->width, output->height); | 554 | output->width, output->height); |
555 | |||
556 | struct wl_callback *frame_callback = wl_surface_frame(output->surface); | ||
557 | wl_callback_add_listener(frame_callback, &output_frame_listener, output); | ||
558 | output->frame_scheduled = true; | ||
559 | |||
544 | wl_surface_commit(output->surface); | 560 | wl_surface_commit(output->surface); |
545 | } | 561 | } |
546 | cairo_surface_destroy(recorder); | 562 | cairo_surface_destroy(recorder); |
diff --git a/swaybar/status_line.c b/swaybar/status_line.c index 48b43248..ed6dc7c8 100644 --- a/swaybar/status_line.c +++ b/swaybar/status_line.c | |||
@@ -1,12 +1,15 @@ | |||
1 | #define _POSIX_C_SOURCE 200809L | 1 | #define _POSIX_C_SOURCE 200809L |
2 | #include <fcntl.h> | 2 | #include <fcntl.h> |
3 | #include <sys/ioctl.h> | ||
3 | #include <json-c/json.h> | 4 | #include <json-c/json.h> |
4 | #include <stdlib.h> | 5 | #include <stdlib.h> |
5 | #include <string.h> | 6 | #include <string.h> |
6 | #include <stdio.h> | 7 | #include <stdio.h> |
7 | #include <unistd.h> | 8 | #include <unistd.h> |
8 | #include <wlr/util/log.h> | 9 | #include <wlr/util/log.h> |
10 | #include "swaybar/bar.h" | ||
9 | #include "swaybar/config.h" | 11 | #include "swaybar/config.h" |
12 | #include "swaybar/i3bar.h" | ||
10 | #include "swaybar/event_loop.h" | 13 | #include "swaybar/event_loop.h" |
11 | #include "swaybar/status_line.h" | 14 | #include "swaybar/status_line.h" |
12 | #include "readline.h" | 15 | #include "readline.h" |
@@ -34,18 +37,35 @@ bool status_handle_readable(struct status_line *status) { | |||
34 | switch (status->protocol) { | 37 | switch (status->protocol) { |
35 | case PROTOCOL_UNDEF: | 38 | case PROTOCOL_UNDEF: |
36 | errno = 0; | 39 | errno = 0; |
37 | read_bytes = getline(&status->buffer, | 40 | int available_bytes; |
38 | &status->buffer_size, status->read); | 41 | if (ioctl(status->read_fd, FIONREAD, &available_bytes) == -1) { |
39 | if (errno == EAGAIN) { | 42 | wlr_log(WLR_ERROR, "Unable to read status command output size"); |
40 | clearerr(status->read); | ||
41 | } else if (errno) { | ||
42 | status_error(status, "[error reading from status command]"); | 43 | status_error(status, "[error reading from status command]"); |
43 | return true; | 44 | return true; |
44 | } | 45 | } |
45 | 46 | ||
47 | if ((size_t)available_bytes + 1 > status->buffer_size) { | ||
48 | // need room for leading '\0' too | ||
49 | status->buffer_size = available_bytes + 1; | ||
50 | status->buffer = realloc(status->buffer, status->buffer_size); | ||
51 | } | ||
52 | if (status->buffer == NULL) { | ||
53 | wlr_log_errno(WLR_ERROR, "Unable to read status line"); | ||
54 | status_error(status, "[error reading from status command]"); | ||
55 | return true; | ||
56 | } | ||
57 | |||
58 | read_bytes = read(status->read_fd, status->buffer, available_bytes); | ||
59 | if (read_bytes != available_bytes) { | ||
60 | status_error(status, "[error reading from status command]"); | ||
61 | return true; | ||
62 | } | ||
63 | status->buffer[available_bytes] = 0; | ||
64 | |||
46 | // the header must be sent completely the first time round | 65 | // the header must be sent completely the first time round |
66 | char *newline = strchr(status->buffer, '\n'); | ||
47 | json_object *header, *version; | 67 | json_object *header, *version; |
48 | if (status->buffer[read_bytes - 1] == '\n' | 68 | if (newline != NULL |
49 | && (header = json_tokener_parse(status->buffer)) | 69 | && (header = json_tokener_parse(status->buffer)) |
50 | && json_object_object_get_ex(header, "version", &version) | 70 | && json_object_object_get_ex(header, "version", &version) |
51 | && json_object_get_int(version) == 1) { | 71 | && json_object_get_int(version) == 1) { |
@@ -67,13 +87,9 @@ bool status_handle_readable(struct status_line *status) { | |||
67 | 87 | ||
68 | wl_list_init(&status->blocks); | 88 | wl_list_init(&status->blocks); |
69 | status->tokener = json_tokener_new(); | 89 | status->tokener = json_tokener_new(); |
70 | read_bytes = getdelim(&status->buffer, &status->buffer_size, EOF, status->read); | 90 | status->buffer_index = strlen(newline + 1); |
71 | if (read_bytes > 0) { | 91 | memmove(status->buffer, newline + 1, status->buffer_index + 1); |
72 | status->buffer_index = read_bytes; | 92 | return i3bar_handle_readable(status); |
73 | return i3bar_handle_readable(status); | ||
74 | } else { | ||
75 | return false; | ||
76 | } | ||
77 | } | 93 | } |
78 | 94 | ||
79 | wlr_log(WLR_DEBUG, "Using text protocol."); | 95 | wlr_log(WLR_DEBUG, "Using text protocol."); |