mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-02-05 04:06:08 -05:00
render: use a timer instead of relying on the frame callback for title update throttling
Using the frame callback works most of the time, but e.g. Sway doesn’t call it while the window is hidden, and thus prevents us from updating the title in e.g. stacked views. This patch uses a timer FD instead. We store a timestamp from when the title was last updated. When the application wants to update the title, we first check if we already have a timer running, and if so, does nothing. If no timer is running, check the timestamp. If enough time has passed, update the title immediately. If not, instantiate a timer and wait for it to trigger. Set the minimum time between two updates to ~8ms (twice per frame, for a 60Hz output, and ~once per frame on a 120Hz output). Closes #591
This commit is contained in:
parent
b77dbc341b
commit
535c82d628
4 changed files with 64 additions and 18 deletions
|
|
@ -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
|
||||
|
|
|
|||
63
render.c
63
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
|
||||
|
|
|
|||
10
terminal.c
10
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;
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue