diff --git a/render.c b/render.c index 20af86aa..0bf09bd8 100644 --- a/render.c +++ b/render.c @@ -3501,26 +3501,10 @@ fdm_hook_refresh_pending_terminals(struct fdm *fdm, void *data) } } -static bool -fdm_title_update(struct fdm *fdm, int fd, int events, void *data) -{ - struct terminal *term = data; - fdm_del(fdm, fd); - - term->render.title.timer_fd = -1; - render_update_title(term); - - struct timeval now; - if (gettimeofday(&now, NULL) == 0) - term->render.title.last_update = now; - - return true; -} - void render_refresh_title(struct terminal *term) { - if (term->render.title.timer_fd >= 0) + if (term->render.title.is_armed) return; struct timeval now; @@ -3531,23 +3515,11 @@ render_refresh_title(struct terminal *term) timersub(&now, &term->render.title.last_update, &diff); if (diff.tv_sec == 0 && diff.tv_usec < 8333) { - int fd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK); - if (fd < 0) - return; - const struct itimerspec timeout = { .it_value = {.tv_nsec = 8333 * 1000 - diff.tv_usec * 1000}, }; - if (timerfd_settime(fd, 0, &timeout, NULL) < 0) { - close(fd); - return; - } - - if (!fdm_add(term->fdm, fd, EPOLLIN, &fdm_title_update, term)) - close(fd); - else - term->render.title.timer_fd = fd; + timerfd_settime(term->render.title.timer_fd, 0, &timeout, NULL); } else { term->render.title.last_update = now; render_update_title(term); diff --git a/terminal.c b/terminal.c index aef21d72..1e1a7f78 100644 --- a/terminal.c +++ b/terminal.c @@ -552,6 +552,31 @@ fdm_app_sync_updates_timeout( return true; } +static bool +fdm_title_update_timeout(struct fdm *fdm, int fd, int events, void *data) +{ + if (events & EPOLLHUP) + return false; + + struct terminal *term = data; + uint64_t unused; + ssize_t ret = read(term->render.title.timer_fd, &unused, sizeof(unused)); + + if (ret < 0) { + if (errno == EAGAIN) + return true; + LOG_ERRNO("failed to read title update throttle timer"); + return false; + } + + struct itimerspec reset = {{0}}; + timerfd_settime(term->render.title.timer_fd, 0, &reset, NULL); + term->render.title.is_armed = false; + + render_refresh_title(term); + return true; +} + static bool initialize_render_workers(struct terminal *term) { @@ -980,6 +1005,7 @@ term_init(const struct config *conf, struct fdm *fdm, struct reaper *reaper, int delay_lower_fd = -1; int delay_upper_fd = -1; int app_sync_updates_fd = -1; + int title_update_fd = -1; struct terminal *term = malloc(sizeof(*term)); if (unlikely(term == NULL)) { @@ -987,27 +1013,33 @@ term_init(const struct config *conf, struct fdm *fdm, struct reaper *reaper, return NULL; } - if ((ptmx = posix_openpt(O_RDWR | O_NOCTTY)) == -1) { + if ((ptmx = posix_openpt(O_RDWR | O_NOCTTY)) < 0) { LOG_ERRNO("failed to open PTY"); goto close_fds; } - if ((flash_fd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK)) == -1) { + if ((flash_fd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK)) < 0) { LOG_ERRNO("failed to create flash timer FD"); goto close_fds; } - if ((delay_lower_fd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK)) == -1 || - (delay_upper_fd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK)) == -1) + if ((delay_lower_fd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK)) < 0 || + (delay_upper_fd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK)) < 0) { LOG_ERRNO("failed to create delayed rendering timer FDs"); goto close_fds; } - if ((app_sync_updates_fd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK)) == -1) + if ((app_sync_updates_fd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK)) < 0) { LOG_ERRNO("failed to create application synchronized updates timer FD"); goto close_fds; } + if ((title_update_fd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK)) < 0) + { + LOG_ERRNO("failed to create title update throttle timer FD"); + goto close_fds; + } + if (ioctl(ptmx, (unsigned int)TIOCSWINSZ, &(struct winsize){.ws_row = 24, .ws_col = 80}) < 0) { @@ -1032,7 +1064,8 @@ term_init(const struct config *conf, struct fdm *fdm, struct reaper *reaper, if (!fdm_add(fdm, flash_fd, EPOLLIN, &fdm_flash, term) || !fdm_add(fdm, delay_lower_fd, EPOLLIN, &fdm_delayed_render, term) || !fdm_add(fdm, delay_upper_fd, EPOLLIN, &fdm_delayed_render, term) || - !fdm_add(fdm, app_sync_updates_fd, EPOLLIN, &fdm_app_sync_updates_timeout, term)) + !fdm_add(fdm, app_sync_updates_fd, EPOLLIN, &fdm_app_sync_updates_timeout, term) || + !fdm_add(fdm, title_update_fd, EPOLLIN, &fdm_title_update_timeout, term)) { goto err; } @@ -1114,7 +1147,8 @@ term_init(const struct config *conf, struct fdm *fdm, struct reaper *reaper, .scrollback_lines = conf->scrollback.lines, .app_sync_updates.timer_fd = app_sync_updates_fd, .title = { - .timer_fd = -1, + .is_armed = false, + .timer_fd = title_update_fd, }, .workers = { .count = conf->render_worker_count, @@ -1220,6 +1254,7 @@ close_fds: fdm_del(fdm, delay_lower_fd); fdm_del(fdm, delay_upper_fd); fdm_del(fdm, app_sync_updates_fd); + fdm_del(fdm, title_update_fd); free(term); return NULL; diff --git a/terminal.h b/terminal.h index c810c0f0..e6bcfa40 100644 --- a/terminal.h +++ b/terminal.h @@ -490,6 +490,7 @@ struct terminal { struct { struct timeval last_update; + bool is_armed; int timer_fd; } title;