diff options
author | Ian Fan <ianfan0@gmail.com> | 2018-09-28 16:17:15 +0100 |
---|---|---|
committer | Ian Fan <ianfan0@gmail.com> | 2018-09-30 10:07:33 +0100 |
commit | 02dfeea54c4eac2a96c0d8d614d5c16d96358ad0 (patch) | |
tree | 1f1d49abca1369c7e165991f69d8451f01af5c2f | |
parent | Merge pull request #2732 from RyanDwyer/fix-zero-outputs (diff) | |
download | sway-02dfeea54c4eac2a96c0d8d614d5c16d96358ad0.tar.gz sway-02dfeea54c4eac2a96c0d8d614d5c16d96358ad0.tar.zst sway-02dfeea54c4eac2a96c0d8d614d5c16d96358ad0.zip |
swaybar: synchronize rendering to output frames
-rw-r--r-- | include/swaybar/bar.h | 2 | ||||
-rw-r--r-- | include/swaybar/render.h | 4 | ||||
-rw-r--r-- | swaybar/bar.c | 41 | ||||
-rw-r--r-- | swaybar/render.c | 24 |
4 files changed, 48 insertions, 23 deletions
diff --git a/include/swaybar/bar.h b/include/swaybar/bar.h index 20992014..de234111 100644 --- a/include/swaybar/bar.h +++ b/include/swaybar/bar.h | |||
@@ -83,6 +83,8 @@ struct swaybar_output { | |||
83 | enum wl_output_subpixel subpixel; | 83 | enum wl_output_subpixel subpixel; |
84 | struct pool_buffer buffers[2]; | 84 | struct pool_buffer buffers[2]; |
85 | struct pool_buffer *current_buffer; | 85 | struct pool_buffer *current_buffer; |
86 | bool dirty; | ||
87 | bool frame_scheduled; | ||
86 | }; | 88 | }; |
87 | 89 | ||
88 | struct swaybar_workspace { | 90 | struct swaybar_workspace { |
diff --git a/include/swaybar/render.h b/include/swaybar/render.h index 071e2298..ebdc69e4 100644 --- a/include/swaybar/render.h +++ b/include/swaybar/render.h | |||
@@ -1,10 +1,8 @@ | |||
1 | #ifndef _SWAYBAR_RENDER_H | 1 | #ifndef _SWAYBAR_RENDER_H |
2 | #define _SWAYBAR_RENDER_H | 2 | #define _SWAYBAR_RENDER_H |
3 | 3 | ||
4 | struct swaybar; | ||
5 | struct swaybar_output; | 4 | struct swaybar_output; |
6 | struct swaybar_config; | ||
7 | 5 | ||
8 | void render_frame(struct swaybar *bar, struct swaybar_output *output); | 6 | void render_frame(struct swaybar_output *output); |
9 | 7 | ||
10 | #endif | 8 | #endif |
diff --git a/swaybar/bar.c b/swaybar/bar.c index 15e81976..388c24c4 100644 --- a/swaybar/bar.c +++ b/swaybar/bar.c | |||
@@ -72,6 +72,16 @@ static void swaybar_output_free(struct swaybar_output *output) { | |||
72 | free(output); | 72 | free(output); |
73 | } | 73 | } |
74 | 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 | |||
75 | static void layer_surface_configure(void *data, | 85 | static void layer_surface_configure(void *data, |
76 | struct zwlr_layer_surface_v1 *surface, | 86 | struct zwlr_layer_surface_v1 *surface, |
77 | uint32_t serial, uint32_t width, uint32_t height) { | 87 | uint32_t serial, uint32_t width, uint32_t height) { |
@@ -79,7 +89,7 @@ static void layer_surface_configure(void *data, | |||
79 | output->width = width; | 89 | output->width = width; |
80 | output->height = height; | 90 | output->height = height; |
81 | zwlr_layer_surface_v1_ack_configure(surface, serial); | 91 | zwlr_layer_surface_v1_ack_configure(surface, serial); |
82 | render_frame(output->bar, output); | 92 | set_output_dirty(output); |
83 | } | 93 | } |
84 | 94 | ||
85 | static void layer_surface_closed(void *_output, | 95 | static void layer_surface_closed(void *_output, |
@@ -325,27 +335,22 @@ static void output_geometry(void *data, struct wl_output *wl_output, int32_t x, | |||
325 | const char *make, const char *model, int32_t transform) { | 335 | const char *make, const char *model, int32_t transform) { |
326 | struct swaybar_output *output = data; | 336 | struct swaybar_output *output = data; |
327 | output->subpixel = subpixel; | 337 | output->subpixel = subpixel; |
328 | if (output->surface) { | ||
329 | render_frame(output->bar, output); | ||
330 | } | ||
331 | } | 338 | } |
332 | 339 | ||
333 | 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, |
334 | int32_t width, int32_t height, int32_t refresh) { | 341 | int32_t width, int32_t height, int32_t refresh) { |
335 | // Who cares | 342 | // Who cares |
336 | } | 343 | } |
337 | 344 | ||
338 | static void output_done(void *data, struct wl_output *output) { | 345 | static void output_done(void *data, struct wl_output *wl_output) { |
339 | // Who cares | 346 | struct swaybar_output *output = data; |
347 | set_output_dirty(output); | ||
340 | } | 348 | } |
341 | 349 | ||
342 | static void output_scale(void *data, struct wl_output *wl_output, | 350 | static void output_scale(void *data, struct wl_output *wl_output, |
343 | int32_t factor) { | 351 | int32_t factor) { |
344 | struct swaybar_output *output = data; | 352 | struct swaybar_output *output = data; |
345 | output->scale = factor; | 353 | output->scale = factor; |
346 | if (output->surface) { | ||
347 | render_frame(output->bar, output); | ||
348 | } | ||
349 | } | 354 | } |
350 | 355 | ||
351 | struct wl_output_listener output_listener = { | 356 | struct wl_output_listener output_listener = { |
@@ -381,7 +386,7 @@ static void xdg_output_handle_done(void *data, | |||
381 | wl_list_insert(&bar->outputs, &output->link); | 386 | wl_list_insert(&bar->outputs, &output->link); |
382 | 387 | ||
383 | add_layer_surface(output); | 388 | add_layer_surface(output); |
384 | render_frame(bar, output); | 389 | set_output_dirty(output); |
385 | } | 390 | } |
386 | } | 391 | } |
387 | 392 | ||
@@ -470,12 +475,10 @@ static const struct wl_registry_listener registry_listener = { | |||
470 | .global_remove = handle_global_remove, | 475 | .global_remove = handle_global_remove, |
471 | }; | 476 | }; |
472 | 477 | ||
473 | static void render_all_frames(struct swaybar *bar) { | 478 | static void set_bar_dirty(struct swaybar *bar) { |
474 | struct swaybar_output *output; | 479 | struct swaybar_output *output; |
475 | wl_list_for_each(output, &bar->outputs, link) { | 480 | wl_list_for_each(output, &bar->outputs, link) { |
476 | if (output->surface != NULL) { | 481 | set_output_dirty(output); |
477 | render_frame(bar, output); | ||
478 | } | ||
479 | } | 482 | } |
480 | } | 483 | } |
481 | 484 | ||
@@ -528,7 +531,7 @@ bool bar_setup(struct swaybar *bar, | |||
528 | assert(pointer->cursor_surface); | 531 | assert(pointer->cursor_surface); |
529 | 532 | ||
530 | ipc_get_workspaces(bar); | 533 | ipc_get_workspaces(bar); |
531 | render_all_frames(bar); | 534 | set_bar_dirty(bar); |
532 | return true; | 535 | return true; |
533 | } | 536 | } |
534 | 537 | ||
@@ -543,7 +546,7 @@ static void display_in(int fd, short mask, void *data) { | |||
543 | static void ipc_in(int fd, short mask, void *data) { | 546 | static void ipc_in(int fd, short mask, void *data) { |
544 | struct swaybar *bar = data; | 547 | struct swaybar *bar = data; |
545 | if (handle_ipc_readable(bar)) { | 548 | if (handle_ipc_readable(bar)) { |
546 | render_all_frames(bar); | 549 | set_bar_dirty(bar); |
547 | } | 550 | } |
548 | } | 551 | } |
549 | 552 | ||
@@ -551,10 +554,10 @@ static void status_in(int fd, short mask, void *data) { | |||
551 | struct swaybar *bar = data; | 554 | struct swaybar *bar = data; |
552 | if (mask & (POLLHUP | POLLERR)) { | 555 | if (mask & (POLLHUP | POLLERR)) { |
553 | status_error(bar->status, "[error reading from status command]"); | 556 | status_error(bar->status, "[error reading from status command]"); |
554 | render_all_frames(bar); | 557 | set_bar_dirty(bar); |
555 | remove_event(fd); | 558 | remove_event(fd); |
556 | } else if (status_handle_readable(bar->status)) { | 559 | } else if (status_handle_readable(bar->status)) { |
557 | render_all_frames(bar); | 560 | set_bar_dirty(bar); |
558 | } | 561 | } |
559 | } | 562 | } |
560 | 563 | ||
diff --git a/swaybar/render.c b/swaybar/render.c index 90e5bac7..dc31a5ea 100644 --- a/swaybar/render.c +++ b/swaybar/render.c | |||
@@ -473,7 +473,22 @@ static uint32_t render_to_cairo(cairo_t *cairo, struct swaybar_output *output) { | |||
473 | return max_height > output->height ? max_height : output->height; | 473 | return max_height > output->height ? max_height : output->height; |
474 | } | 474 | } |
475 | 475 | ||
476 | 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) { | ||
477 | assert(output->surface != NULL); | 492 | assert(output->surface != NULL); |
478 | 493 | ||
479 | struct swaybar_hotspot *hotspot, *tmp; | 494 | struct swaybar_hotspot *hotspot, *tmp; |
@@ -518,6 +533,8 @@ void render_frame(struct swaybar *bar, struct swaybar_output *output) { | |||
518 | output->width * output->scale, | 533 | output->width * output->scale, |
519 | output->height * output->scale); | 534 | output->height * output->scale); |
520 | if (!output->current_buffer) { | 535 | if (!output->current_buffer) { |
536 | cairo_surface_destroy(recorder); | ||
537 | cairo_destroy(cairo); | ||
521 | return; | 538 | return; |
522 | } | 539 | } |
523 | cairo_t *shm = output->current_buffer->cairo; | 540 | cairo_t *shm = output->current_buffer->cairo; |
@@ -535,6 +552,11 @@ void render_frame(struct swaybar *bar, struct swaybar_output *output) { | |||
535 | output->current_buffer->buffer, 0, 0); | 552 | output->current_buffer->buffer, 0, 0); |
536 | wl_surface_damage(output->surface, 0, 0, | 553 | wl_surface_damage(output->surface, 0, 0, |
537 | 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 | |||
538 | wl_surface_commit(output->surface); | 560 | wl_surface_commit(output->surface); |
539 | } | 561 | } |
540 | cairo_surface_destroy(recorder); | 562 | cairo_surface_destroy(recorder); |