diff --git a/CHANGELOG.md b/CHANGELOG.md index b7e2f51a..6ea8eec3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -184,6 +184,8 @@ (https://codeberg.org/dnkl/foot/issues/586). * Crash in scrollback search when current XKB layout is missing _compose_ definitions. +* Window title not being updated while window is hidden + (https://codeberg.org/dnkl/foot/issues/591). ### Security diff --git a/render.c b/render.c index bebb479a..20af86aa 100644 --- a/render.c +++ b/render.c @@ -2992,13 +2992,11 @@ frame_callback(void *data, struct wl_callback *wl_callback, uint32_t callback_da bool grid = term->render.pending.grid; bool csd = term->render.pending.csd; bool search = term->is_searching && term->render.pending.search; - bool title = term->render.pending.title; bool urls = urls_mode_is_active(term) > 0 && term->render.pending.urls; term->render.pending.grid = false; term->render.pending.csd = false; term->render.pending.search = false; - term->render.pending.title = false; term->render.pending.urls = false; struct grid *original_grid = term->grid; @@ -3013,9 +3011,6 @@ frame_callback(void *data, struct wl_callback *wl_callback, uint32_t callback_da quirk_weston_csd_off(term); } - if (title) - render_update_title(term); - if (search) render_search_box(term); @@ -3447,19 +3442,17 @@ fdm_hook_refresh_pending_terminals(struct fdm *fdm, void *data) bool grid = term->render.refresh.grid; bool csd = term->render.refresh.csd; bool search = term->is_searching && term->render.refresh.search; - bool title = term->render.refresh.title; bool urls = urls_mode_is_active(term) && term->render.refresh.urls; - if (!(grid | csd | search | title | urls)) + if (!(grid | csd | search | urls)) continue; - if (term->render.app_sync_updates.enabled && !(csd | search | title | urls)) + if (term->render.app_sync_updates.enabled && !(csd | search | urls)) continue; term->render.refresh.grid = false; term->render.refresh.csd = false; term->render.refresh.search = false; - term->render.refresh.title = false; term->render.refresh.urls = false; if (term->window->frame_callback == NULL) { @@ -3474,8 +3467,6 @@ fdm_hook_refresh_pending_terminals(struct fdm *fdm, void *data) render_csd(term); quirk_weston_csd_off(term); } - if (title) - render_update_title(term); if (search) render_search_box(term); if (urls) @@ -3494,7 +3485,6 @@ fdm_hook_refresh_pending_terminals(struct fdm *fdm, void *data) term->render.pending.grid |= grid; term->render.pending.csd |= csd; term->render.pending.search |= search; - term->render.pending.title |= title; term->render.pending.urls |= urls; } } @@ -3511,10 +3501,57 @@ 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) { - term->render.refresh.title = true; + if (term->render.title.timer_fd >= 0) + return; + + struct timeval now; + if (gettimeofday(&now, NULL) < 0) + return; + + struct timeval diff; + 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; + } else { + term->render.title.last_update = now; + render_update_title(term); + } } void diff --git a/terminal.c b/terminal.c index e689f4f6..aef21d72 100644 --- a/terminal.c +++ b/terminal.c @@ -1113,6 +1113,9 @@ term_init(const struct config *conf, struct fdm *fdm, struct reaper *reaper, .render = { .scrollback_lines = conf->scrollback.lines, .app_sync_updates.timer_fd = app_sync_updates_fd, + .title = { + .timer_fd = -1, + }, .workers = { .count = conf->render_worker_count, .queue = tll_init(), @@ -1289,6 +1292,7 @@ term_shutdown(struct terminal *term) fdm_del(term->fdm, term->selection.auto_scroll.fd); fdm_del(term->fdm, term->render.app_sync_updates.timer_fd); + fdm_del(term->fdm, term->render.title.timer_fd); fdm_del(term->fdm, term->delayed_render_timer.lower_fd); fdm_del(term->fdm, term->delayed_render_timer.upper_fd); fdm_del(term->fdm, term->blink.fd); @@ -1304,6 +1308,7 @@ term_shutdown(struct terminal *term) term->selection.auto_scroll.fd = -1; term->render.app_sync_updates.timer_fd = -1; + term->render.title.timer_fd = -1; term->delayed_render_timer.lower_fd = -1; term->delayed_render_timer.upper_fd = -1; term->blink.fd = -1; @@ -1354,6 +1359,7 @@ term_destroy(struct terminal *term) fdm_del(term->fdm, term->selection.auto_scroll.fd); fdm_del(term->fdm, term->render.app_sync_updates.timer_fd); + fdm_del(term->fdm, term->render.title.timer_fd); fdm_del(term->fdm, term->delayed_render_timer.lower_fd); fdm_del(term->fdm, term->delayed_render_timer.upper_fd); fdm_del(term->fdm, term->cursor_blink.fd); @@ -2670,9 +2676,7 @@ term_enable_app_sync_updates(struct terminal *term) /* Disable pending refresh *iff* the grid is the *only* thing * scheduled to be re-rendered */ if (!term->render.refresh.csd && !term->render.refresh.search && - !term->render.refresh.title && - !term->render.pending.csd && !term->render.pending.search && - !term->render.pending.title) + !term->render.pending.csd && !term->render.pending.search) { term->render.refresh.grid = false; term->render.pending.grid = false; diff --git a/terminal.h b/terminal.h index b96621fd..c810c0f0 100644 --- a/terminal.h +++ b/terminal.h @@ -474,7 +474,6 @@ struct terminal { bool grid; bool csd; bool search; - bool title; bool urls; } refresh; @@ -483,13 +482,17 @@ struct terminal { bool grid; bool csd; bool search; - bool title; bool urls; } pending; bool margins; /* Someone explicitly requested a refresh of the margins */ bool urgency; /* Signal 'urgency' (paint borders red) */ + struct { + struct timeval last_update; + int timer_fd; + } title; + int scrollback_lines; /* Number of scrollback lines, from conf (TODO: move out from render struct?) */ struct {