mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-03-16 05:34:00 -04:00
commit
fa06cf31ff
4 changed files with 78 additions and 24 deletions
|
|
@ -184,6 +184,8 @@
|
||||||
(https://codeberg.org/dnkl/foot/issues/586).
|
(https://codeberg.org/dnkl/foot/issues/586).
|
||||||
* Crash in scrollback search when current XKB layout is missing
|
* Crash in scrollback search when current XKB layout is missing
|
||||||
_compose_ definitions.
|
_compose_ definitions.
|
||||||
|
* Window title not being updated while window is hidden
|
||||||
|
(https://codeberg.org/dnkl/foot/issues/591).
|
||||||
|
|
||||||
|
|
||||||
### Security
|
### Security
|
||||||
|
|
|
||||||
35
render.c
35
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 grid = term->render.pending.grid;
|
||||||
bool csd = term->render.pending.csd;
|
bool csd = term->render.pending.csd;
|
||||||
bool search = term->is_searching && term->render.pending.search;
|
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;
|
bool urls = urls_mode_is_active(term) > 0 && term->render.pending.urls;
|
||||||
|
|
||||||
term->render.pending.grid = false;
|
term->render.pending.grid = false;
|
||||||
term->render.pending.csd = false;
|
term->render.pending.csd = false;
|
||||||
term->render.pending.search = false;
|
term->render.pending.search = false;
|
||||||
term->render.pending.title = false;
|
|
||||||
term->render.pending.urls = false;
|
term->render.pending.urls = false;
|
||||||
|
|
||||||
struct grid *original_grid = term->grid;
|
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);
|
quirk_weston_csd_off(term);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (title)
|
|
||||||
render_update_title(term);
|
|
||||||
|
|
||||||
if (search)
|
if (search)
|
||||||
render_search_box(term);
|
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 grid = term->render.refresh.grid;
|
||||||
bool csd = term->render.refresh.csd;
|
bool csd = term->render.refresh.csd;
|
||||||
bool search = term->is_searching && term->render.refresh.search;
|
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;
|
bool urls = urls_mode_is_active(term) && term->render.refresh.urls;
|
||||||
|
|
||||||
if (!(grid | csd | search | title | urls))
|
if (!(grid | csd | search | urls))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (term->render.app_sync_updates.enabled && !(csd | search | title | urls))
|
if (term->render.app_sync_updates.enabled && !(csd | search | urls))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
term->render.refresh.grid = false;
|
term->render.refresh.grid = false;
|
||||||
term->render.refresh.csd = false;
|
term->render.refresh.csd = false;
|
||||||
term->render.refresh.search = false;
|
term->render.refresh.search = false;
|
||||||
term->render.refresh.title = false;
|
|
||||||
term->render.refresh.urls = false;
|
term->render.refresh.urls = false;
|
||||||
|
|
||||||
if (term->window->frame_callback == NULL) {
|
if (term->window->frame_callback == NULL) {
|
||||||
|
|
@ -3474,8 +3467,6 @@ fdm_hook_refresh_pending_terminals(struct fdm *fdm, void *data)
|
||||||
render_csd(term);
|
render_csd(term);
|
||||||
quirk_weston_csd_off(term);
|
quirk_weston_csd_off(term);
|
||||||
}
|
}
|
||||||
if (title)
|
|
||||||
render_update_title(term);
|
|
||||||
if (search)
|
if (search)
|
||||||
render_search_box(term);
|
render_search_box(term);
|
||||||
if (urls)
|
if (urls)
|
||||||
|
|
@ -3494,7 +3485,6 @@ fdm_hook_refresh_pending_terminals(struct fdm *fdm, void *data)
|
||||||
term->render.pending.grid |= grid;
|
term->render.pending.grid |= grid;
|
||||||
term->render.pending.csd |= csd;
|
term->render.pending.csd |= csd;
|
||||||
term->render.pending.search |= search;
|
term->render.pending.search |= search;
|
||||||
term->render.pending.title |= title;
|
|
||||||
term->render.pending.urls |= urls;
|
term->render.pending.urls |= urls;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -3514,7 +3504,26 @@ fdm_hook_refresh_pending_terminals(struct fdm *fdm, void *data)
|
||||||
void
|
void
|
||||||
render_refresh_title(struct terminal *term)
|
render_refresh_title(struct terminal *term)
|
||||||
{
|
{
|
||||||
term->render.refresh.title = true;
|
if (term->render.title.is_armed)
|
||||||
|
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) {
|
||||||
|
const struct itimerspec timeout = {
|
||||||
|
.it_value = {.tv_nsec = 8333 * 1000 - diff.tv_usec * 1000},
|
||||||
|
};
|
||||||
|
|
||||||
|
timerfd_settime(term->render.title.timer_fd, 0, &timeout, NULL);
|
||||||
|
} else {
|
||||||
|
term->render.title.last_update = now;
|
||||||
|
render_update_title(term);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
||||||
57
terminal.c
57
terminal.c
|
|
@ -552,6 +552,31 @@ fdm_app_sync_updates_timeout(
|
||||||
return true;
|
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
|
static bool
|
||||||
initialize_render_workers(struct terminal *term)
|
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_lower_fd = -1;
|
||||||
int delay_upper_fd = -1;
|
int delay_upper_fd = -1;
|
||||||
int app_sync_updates_fd = -1;
|
int app_sync_updates_fd = -1;
|
||||||
|
int title_update_fd = -1;
|
||||||
|
|
||||||
struct terminal *term = malloc(sizeof(*term));
|
struct terminal *term = malloc(sizeof(*term));
|
||||||
if (unlikely(term == NULL)) {
|
if (unlikely(term == NULL)) {
|
||||||
|
|
@ -987,27 +1013,33 @@ term_init(const struct config *conf, struct fdm *fdm, struct reaper *reaper,
|
||||||
return NULL;
|
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");
|
LOG_ERRNO("failed to open PTY");
|
||||||
goto close_fds;
|
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");
|
LOG_ERRNO("failed to create flash timer FD");
|
||||||
goto close_fds;
|
goto close_fds;
|
||||||
}
|
}
|
||||||
if ((delay_lower_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)) == -1)
|
(delay_upper_fd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK)) < 0)
|
||||||
{
|
{
|
||||||
LOG_ERRNO("failed to create delayed rendering timer FDs");
|
LOG_ERRNO("failed to create delayed rendering timer FDs");
|
||||||
goto close_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");
|
LOG_ERRNO("failed to create application synchronized updates timer FD");
|
||||||
goto close_fds;
|
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,
|
if (ioctl(ptmx, (unsigned int)TIOCSWINSZ,
|
||||||
&(struct winsize){.ws_row = 24, .ws_col = 80}) < 0)
|
&(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) ||
|
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_lower_fd, EPOLLIN, &fdm_delayed_render, term) ||
|
||||||
!fdm_add(fdm, delay_upper_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;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
@ -1113,6 +1146,10 @@ term_init(const struct config *conf, struct fdm *fdm, struct reaper *reaper,
|
||||||
.render = {
|
.render = {
|
||||||
.scrollback_lines = conf->scrollback.lines,
|
.scrollback_lines = conf->scrollback.lines,
|
||||||
.app_sync_updates.timer_fd = app_sync_updates_fd,
|
.app_sync_updates.timer_fd = app_sync_updates_fd,
|
||||||
|
.title = {
|
||||||
|
.is_armed = false,
|
||||||
|
.timer_fd = title_update_fd,
|
||||||
|
},
|
||||||
.workers = {
|
.workers = {
|
||||||
.count = conf->render_worker_count,
|
.count = conf->render_worker_count,
|
||||||
.queue = tll_init(),
|
.queue = tll_init(),
|
||||||
|
|
@ -1217,6 +1254,7 @@ close_fds:
|
||||||
fdm_del(fdm, delay_lower_fd);
|
fdm_del(fdm, delay_lower_fd);
|
||||||
fdm_del(fdm, delay_upper_fd);
|
fdm_del(fdm, delay_upper_fd);
|
||||||
fdm_del(fdm, app_sync_updates_fd);
|
fdm_del(fdm, app_sync_updates_fd);
|
||||||
|
fdm_del(fdm, title_update_fd);
|
||||||
|
|
||||||
free(term);
|
free(term);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
@ -1289,6 +1327,7 @@ term_shutdown(struct terminal *term)
|
||||||
|
|
||||||
fdm_del(term->fdm, term->selection.auto_scroll.fd);
|
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.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.lower_fd);
|
||||||
fdm_del(term->fdm, term->delayed_render_timer.upper_fd);
|
fdm_del(term->fdm, term->delayed_render_timer.upper_fd);
|
||||||
fdm_del(term->fdm, term->blink.fd);
|
fdm_del(term->fdm, term->blink.fd);
|
||||||
|
|
@ -1304,6 +1343,7 @@ term_shutdown(struct terminal *term)
|
||||||
|
|
||||||
term->selection.auto_scroll.fd = -1;
|
term->selection.auto_scroll.fd = -1;
|
||||||
term->render.app_sync_updates.timer_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.lower_fd = -1;
|
||||||
term->delayed_render_timer.upper_fd = -1;
|
term->delayed_render_timer.upper_fd = -1;
|
||||||
term->blink.fd = -1;
|
term->blink.fd = -1;
|
||||||
|
|
@ -1354,6 +1394,7 @@ term_destroy(struct terminal *term)
|
||||||
|
|
||||||
fdm_del(term->fdm, term->selection.auto_scroll.fd);
|
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.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.lower_fd);
|
||||||
fdm_del(term->fdm, term->delayed_render_timer.upper_fd);
|
fdm_del(term->fdm, term->delayed_render_timer.upper_fd);
|
||||||
fdm_del(term->fdm, term->cursor_blink.fd);
|
fdm_del(term->fdm, term->cursor_blink.fd);
|
||||||
|
|
@ -2670,9 +2711,7 @@ term_enable_app_sync_updates(struct terminal *term)
|
||||||
/* Disable pending refresh *iff* the grid is the *only* thing
|
/* Disable pending refresh *iff* the grid is the *only* thing
|
||||||
* scheduled to be re-rendered */
|
* scheduled to be re-rendered */
|
||||||
if (!term->render.refresh.csd && !term->render.refresh.search &&
|
if (!term->render.refresh.csd && !term->render.refresh.search &&
|
||||||
!term->render.refresh.title &&
|
!term->render.pending.csd && !term->render.pending.search)
|
||||||
!term->render.pending.csd && !term->render.pending.search &&
|
|
||||||
!term->render.pending.title)
|
|
||||||
{
|
{
|
||||||
term->render.refresh.grid = false;
|
term->render.refresh.grid = false;
|
||||||
term->render.pending.grid = false;
|
term->render.pending.grid = false;
|
||||||
|
|
|
||||||
|
|
@ -474,7 +474,6 @@ struct terminal {
|
||||||
bool grid;
|
bool grid;
|
||||||
bool csd;
|
bool csd;
|
||||||
bool search;
|
bool search;
|
||||||
bool title;
|
|
||||||
bool urls;
|
bool urls;
|
||||||
} refresh;
|
} refresh;
|
||||||
|
|
||||||
|
|
@ -483,13 +482,18 @@ struct terminal {
|
||||||
bool grid;
|
bool grid;
|
||||||
bool csd;
|
bool csd;
|
||||||
bool search;
|
bool search;
|
||||||
bool title;
|
|
||||||
bool urls;
|
bool urls;
|
||||||
} pending;
|
} pending;
|
||||||
|
|
||||||
bool margins; /* Someone explicitly requested a refresh of the margins */
|
bool margins; /* Someone explicitly requested a refresh of the margins */
|
||||||
bool urgency; /* Signal 'urgency' (paint borders red) */
|
bool urgency; /* Signal 'urgency' (paint borders red) */
|
||||||
|
|
||||||
|
struct {
|
||||||
|
struct timeval last_update;
|
||||||
|
bool is_armed;
|
||||||
|
int timer_fd;
|
||||||
|
} title;
|
||||||
|
|
||||||
int scrollback_lines; /* Number of scrollback lines, from conf (TODO: move out from render struct?) */
|
int scrollback_lines; /* Number of scrollback lines, from conf (TODO: move out from render struct?) */
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue