diff --git a/main.c b/main.c index ec44b8b3..e418b584 100644 --- a/main.c +++ b/main.c @@ -19,6 +19,7 @@ #include "config.h" #include "fdm.h" +#include "render.h" #include "server.h" #include "shm.h" #include "terminal.h" @@ -218,6 +219,7 @@ main(int argc, char *const *argv) struct fdm *fdm = NULL; struct wayland *wayl = NULL; + struct renderer *renderer = NULL; struct terminal *term = NULL; struct server *server = NULL; struct shutdown_context shutdown_ctx = {.term = &term, .exit_code = EXIT_FAILURE}; @@ -238,6 +240,9 @@ main(int argc, char *const *argv) if ((wayl = wayl_init(&conf, fdm)) == NULL) goto out; + if ((renderer = render_init(fdm, wayl)) == NULL) + goto out; + if (!as_server && (term = term_init( &conf, fdm, wayl, conf.term, "foot", cwd, argc, argv, &term_shutdown_cb, &shutdown_ctx)) == NULL) { @@ -276,6 +281,7 @@ out: term_destroy(term); shm_fini(); + render_destroy(renderer); wayl_destroy(wayl); fdm_destroy(fdm); diff --git a/render.c b/render.c index d97da212..2da90187 100644 --- a/render.c +++ b/render.c @@ -22,6 +22,11 @@ #define min(x, y) ((x) < (y) ? (x) : (y)) #define max(x, y) ((x) > (y) ? (x) : (y)) +struct renderer { + struct fdm *fdm; + struct wayland *wayl; +}; + static struct { size_t total; size_t zero; /* commits presented in less than one frame interval */ @@ -29,6 +34,56 @@ static struct { size_t two; /* commits presented in two or more frame intervals */ } presentation_statistics = {0}; +static void +fdm_hook_refresh_pending_terminals(struct fdm *fdm, void *data) +{ + struct renderer *renderer = data; + tll_foreach(renderer->wayl->terms, it) { + struct terminal *term = it->item; + + if (!term->render.refresh_needed) + continue; + + assert(term->window->is_configured); + term->render.refresh_needed = false; + + if (term->window->frame_callback == NULL) { + LOG_INFO("rendering immediately"); + grid_render(term); + } else { + LOG_INFO("setting pending"); + term->render.pending = true; + } + } +} + +struct renderer * +render_init(struct fdm *fdm, struct wayland *wayl) +{ + struct renderer *renderer = calloc(1, sizeof(*renderer)); + *renderer = (struct renderer) { + .fdm = fdm, + .wayl = wayl, + }; + + if (!fdm_hook_add(fdm, &fdm_hook_refresh_pending_terminals, renderer)) { + LOG_ERR("failed to register FDM hook"); + free(renderer); + return NULL; + } + + return renderer; +} + +void +render_destroy(struct renderer *renderer) +{ + if (renderer == NULL) + return; + + fdm_hook_del(renderer->fdm, &fdm_hook_refresh_pending_terminals); +} + static void __attribute__((destructor)) log_presentation_statistics(void) { @@ -1079,10 +1134,5 @@ render_set_title(struct terminal *term, const char *_title) void render_refresh(struct terminal *term) { - assert(term->window->is_configured); - - if (term->window->frame_callback == NULL) - grid_render(term); - else - term->render.pending = true; + term->render.refresh_needed = true; } diff --git a/render.h b/render.h index ad6b6578..74d9b456 100644 --- a/render.h +++ b/render.h @@ -1,9 +1,12 @@ #pragma once #include "terminal.h" +#include "fdm.h" +#include "wayland.h" -struct font *attrs_to_font( - const struct terminal *term, const struct attributes *attrs); +struct renderer; +struct renderer *render_init(struct fdm *fdm, struct wayland *wayl); +void render_destroy(struct renderer *renderer); void grid_render(struct terminal *term); void render_resize(struct terminal *term, int width, int height); diff --git a/terminal.h b/terminal.h index 9d28ff41..fe33ff98 100644 --- a/terminal.h +++ b/terminal.h @@ -283,6 +283,7 @@ struct terminal { bool visual_focus; struct { + bool refresh_needed; int scrollback_lines; struct {