mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-03-21 05:33:45 -04:00
osc: add support for osc 176 (app ID)
This adds support for a new OSC escape sequence: OSC 176, that lets terminal programs tell the terminal the name of the app that is running. foot then sets the app ID of the toplevel to that ID, which lets the compositor know which app is running, and typically sets the appropriate icon, window grouping, ... See: https://gist.github.com/delthas/d451e2cc1573bb2364839849c7117239
This commit is contained in:
parent
4801d3a305
commit
6c56b04b3f
8 changed files with 101 additions and 2 deletions
61
terminal.c
61
terminal.c
|
|
@ -627,6 +627,30 @@ fdm_title_update_timeout(struct fdm *fdm, int fd, int events, void *data)
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
fdm_app_id_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.app_id.timer_fd, &unused, sizeof(unused));
|
||||
|
||||
if (ret < 0) {
|
||||
if (errno == EAGAIN)
|
||||
return true;
|
||||
LOG_ERRNO("failed to read app ID update throttle timer");
|
||||
return false;
|
||||
}
|
||||
|
||||
struct itimerspec reset = {{0}};
|
||||
timerfd_settime(term->render.app_id.timer_fd, 0, &reset, NULL);
|
||||
|
||||
render_refresh_app_id(term);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
initialize_render_workers(struct terminal *term)
|
||||
{
|
||||
|
|
@ -1050,6 +1074,7 @@ term_init(const struct config *conf, struct fdm *fdm, struct reaper *reaper,
|
|||
int delay_upper_fd = -1;
|
||||
int app_sync_updates_fd = -1;
|
||||
int title_update_fd = -1;
|
||||
int app_id_update_fd = -1;
|
||||
|
||||
struct terminal *term = malloc(sizeof(*term));
|
||||
if (unlikely(term == NULL)) {
|
||||
|
|
@ -1084,6 +1109,12 @@ term_init(const struct config *conf, struct fdm *fdm, struct reaper *reaper,
|
|||
goto close_fds;
|
||||
}
|
||||
|
||||
if ((app_id_update_fd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK)) < 0)
|
||||
{
|
||||
LOG_ERRNO("failed to create app ID update throttle timer FD");
|
||||
goto close_fds;
|
||||
}
|
||||
|
||||
if (ioctl(ptmx, (unsigned int)TIOCSWINSZ,
|
||||
&(struct winsize){.ws_row = 24, .ws_col = 80}) < 0)
|
||||
{
|
||||
|
|
@ -1114,7 +1145,8 @@ term_init(const struct config *conf, struct fdm *fdm, struct reaper *reaper,
|
|||
!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, title_update_fd, EPOLLIN, &fdm_title_update_timeout, term))
|
||||
!fdm_add(fdm, title_update_fd, EPOLLIN, &fdm_title_update_timeout, term) ||
|
||||
!fdm_add(fdm, app_id_update_fd, EPOLLIN, &fdm_app_id_update_timeout, term))
|
||||
{
|
||||
goto err;
|
||||
}
|
||||
|
|
@ -1210,6 +1242,9 @@ term_init(const struct config *conf, struct fdm *fdm, struct reaper *reaper,
|
|||
.title = {
|
||||
.timer_fd = title_update_fd,
|
||||
},
|
||||
.app_id = {
|
||||
.timer_fd = app_id_update_fd,
|
||||
},
|
||||
.workers = {
|
||||
.count = conf->render_worker_count,
|
||||
.queue = tll_init(),
|
||||
|
|
@ -1318,6 +1353,7 @@ close_fds:
|
|||
fdm_del(fdm, delay_upper_fd);
|
||||
fdm_del(fdm, app_sync_updates_fd);
|
||||
fdm_del(fdm, title_update_fd);
|
||||
fdm_del(fdm, app_id_update_fd);
|
||||
|
||||
free(term);
|
||||
return NULL;
|
||||
|
|
@ -1510,6 +1546,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.app_id.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);
|
||||
|
|
@ -1548,6 +1585,7 @@ term_shutdown(struct terminal *term)
|
|||
|
||||
term->selection.auto_scroll.fd = -1;
|
||||
term->render.app_sync_updates.timer_fd = -1;
|
||||
term->render.app_id.timer_fd = -1;
|
||||
term->render.title.timer_fd = -1;
|
||||
term->delayed_render_timer.lower_fd = -1;
|
||||
term->delayed_render_timer.upper_fd = -1;
|
||||
|
|
@ -1601,6 +1639,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.app_id.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);
|
||||
|
|
@ -1644,6 +1683,7 @@ term_destroy(struct terminal *term)
|
|||
|
||||
composed_free(term->composed);
|
||||
|
||||
free(term->app_id);
|
||||
free(term->window_title);
|
||||
tll_free_and_free(term->window_title_stack, free);
|
||||
|
||||
|
|
@ -3260,6 +3300,25 @@ term_set_window_title(struct terminal *term, const char *title)
|
|||
term->window_title_has_been_set = true;
|
||||
}
|
||||
|
||||
void
|
||||
term_set_app_id(struct terminal *term, const char *app_id)
|
||||
{
|
||||
if (app_id != NULL && *app_id == '\0')
|
||||
app_id = NULL;
|
||||
if (term->app_id == NULL && app_id == NULL)
|
||||
return;
|
||||
if (term->app_id != NULL && app_id != NULL && strcmp(term->app_id, app_id) == 0)
|
||||
return;
|
||||
|
||||
free(term->app_id);
|
||||
if (app_id != NULL) {
|
||||
term->app_id = xstrdup(app_id);
|
||||
} else {
|
||||
term->app_id = NULL;
|
||||
}
|
||||
render_refresh_app_id(term);
|
||||
}
|
||||
|
||||
void
|
||||
term_flash(struct terminal *term, unsigned duration_ms)
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue