mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-03-17 05:33:52 -04:00
Merge branch 'app-id'
This commit is contained in:
commit
0b95e72073
9 changed files with 103 additions and 2 deletions
|
|
@ -59,6 +59,8 @@
|
||||||
* Support for custom (i.e. other than ctrl/shift/alt/super) modifiers
|
* Support for custom (i.e. other than ctrl/shift/alt/super) modifiers
|
||||||
in key bindings ([#1348][1348]).
|
in key bindings ([#1348][1348]).
|
||||||
* `pipe-command-output` key binding.
|
* `pipe-command-output` key binding.
|
||||||
|
* Support for OSC-176, _"Set App-ID"_
|
||||||
|
(https://gist.github.com/delthas/d451e2cc1573bb2364839849c7117239).
|
||||||
|
|
||||||
[1348]: https://codeberg.org/dnkl/foot/issues/1348
|
[1348]: https://codeberg.org/dnkl/foot/issues/1348
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -536,6 +536,7 @@ with the terminal emulator itself. Foot implements the following OSCs:
|
||||||
* `OSC 117` - reset highlight background color
|
* `OSC 117` - reset highlight background color
|
||||||
* `OSC 119` - reset highlight foreground color
|
* `OSC 119` - reset highlight foreground color
|
||||||
* `OSC 133` - [shell integration](#shell-integration)
|
* `OSC 133` - [shell integration](#shell-integration)
|
||||||
|
* `OSC 176` - set app ID
|
||||||
* `OSC 555` - flash screen (**foot specific**)
|
* `OSC 555` - flash screen (**foot specific**)
|
||||||
* `OSC 777` - desktop notification (only the `;notify` sub-command of
|
* `OSC 777` - desktop notification (only the `;notify` sub-command of
|
||||||
OSC 777 is supported.)
|
OSC 777 is supported.)
|
||||||
|
|
|
||||||
|
|
@ -693,6 +693,11 @@ All _OSC_ sequences begin with *\\E]*, sometimes abbreviated _OSC_.
|
||||||
| \\E] 133 ; D \\E\\
|
| \\E] 133 ; D \\E\\
|
||||||
: FinalTerm
|
: FinalTerm
|
||||||
: Mark end of command output
|
: Mark end of command output
|
||||||
|
| \\E] 176 ; _app-id_ \\E\\
|
||||||
|
: foot
|
||||||
|
: Set app ID. _app-id_ is optional; if assigned,
|
||||||
|
the terminal window App ID will be set to the value.
|
||||||
|
An empty App ID resets the value to the default.
|
||||||
| \\E] 555 \\E\\
|
| \\E] 555 \\E\\
|
||||||
: foot
|
: foot
|
||||||
: Flash the entire terminal (foot extension)
|
: Flash the entire terminal (foot extension)
|
||||||
|
|
|
||||||
2
notify.c
2
notify.c
|
|
@ -36,7 +36,7 @@ notify_notify(const struct terminal *term, const char *title, const char *body)
|
||||||
if (!spawn_expand_template(
|
if (!spawn_expand_template(
|
||||||
&term->conf->notify, 4,
|
&term->conf->notify, 4,
|
||||||
(const char *[]){"app-id", "window-title", "title", "body"},
|
(const char *[]){"app-id", "window-title", "title", "body"},
|
||||||
(const char *[]){term->conf->app_id, term->window_title, title, body},
|
(const char *[]){term->app_id ? term->app_id : term->conf->app_id, term->window_title, title, body},
|
||||||
&argc, &argv))
|
&argc, &argv))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
4
osc.c
4
osc.c
|
|
@ -916,6 +916,10 @@ osc_dispatch(struct terminal *term)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 176:
|
||||||
|
term_set_app_id(term, string);
|
||||||
|
break;
|
||||||
|
|
||||||
case 555:
|
case 555:
|
||||||
osc_flash(term);
|
osc_flash(term);
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
22
render.c
22
render.c
|
|
@ -4529,6 +4529,28 @@ render_refresh_title(struct terminal *term)
|
||||||
render_refresh_csd(term);
|
render_refresh_csd(term);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
render_refresh_app_id(struct terminal *term)
|
||||||
|
{
|
||||||
|
struct timespec now;
|
||||||
|
if (clock_gettime(CLOCK_MONOTONIC, &now) < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
struct timespec diff;
|
||||||
|
timespec_sub(&now, &term->render.app_id.last_update, &diff);
|
||||||
|
|
||||||
|
if (diff.tv_sec == 0 && diff.tv_nsec < 8333 * 1000) {
|
||||||
|
const struct itimerspec timeout = {
|
||||||
|
.it_value = {.tv_nsec = 8333 * 1000 - diff.tv_nsec},
|
||||||
|
};
|
||||||
|
|
||||||
|
timerfd_settime(term->render.app_id.timer_fd, 0, &timeout, NULL);
|
||||||
|
} else {
|
||||||
|
term->render.app_id.last_update = now;
|
||||||
|
xdg_toplevel_set_app_id(term->window->xdg_toplevel, term->app_id ? term->app_id : term->conf->app_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
render_refresh(struct terminal *term)
|
render_refresh(struct terminal *term)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
1
render.h
1
render.h
|
|
@ -21,6 +21,7 @@ bool render_resize(
|
||||||
struct terminal *term, int width, int height, uint8_t resize_options);
|
struct terminal *term, int width, int height, uint8_t resize_options);
|
||||||
|
|
||||||
void render_refresh(struct terminal *term);
|
void render_refresh(struct terminal *term);
|
||||||
|
void render_refresh_app_id(struct terminal *term);
|
||||||
void render_refresh_csd(struct terminal *term);
|
void render_refresh_csd(struct terminal *term);
|
||||||
void render_refresh_search(struct terminal *term);
|
void render_refresh_search(struct terminal *term);
|
||||||
void render_refresh_title(struct terminal *term);
|
void render_refresh_title(struct terminal *term);
|
||||||
|
|
|
||||||
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;
|
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
|
static bool
|
||||||
initialize_render_workers(struct terminal *term)
|
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 delay_upper_fd = -1;
|
||||||
int app_sync_updates_fd = -1;
|
int app_sync_updates_fd = -1;
|
||||||
int title_update_fd = -1;
|
int title_update_fd = -1;
|
||||||
|
int app_id_update_fd = -1;
|
||||||
|
|
||||||
struct terminal *term = malloc(sizeof(*term));
|
struct terminal *term = malloc(sizeof(*term));
|
||||||
if (unlikely(term == NULL)) {
|
if (unlikely(term == NULL)) {
|
||||||
|
|
@ -1084,6 +1109,12 @@ term_init(const struct config *conf, struct fdm *fdm, struct reaper *reaper,
|
||||||
goto close_fds;
|
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,
|
if (ioctl(ptmx, (unsigned int)TIOCSWINSZ,
|
||||||
&(struct winsize){.ws_row = 24, .ws_col = 80}) < 0)
|
&(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_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))
|
!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;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
@ -1210,6 +1242,9 @@ term_init(const struct config *conf, struct fdm *fdm, struct reaper *reaper,
|
||||||
.title = {
|
.title = {
|
||||||
.timer_fd = title_update_fd,
|
.timer_fd = title_update_fd,
|
||||||
},
|
},
|
||||||
|
.app_id = {
|
||||||
|
.timer_fd = app_id_update_fd,
|
||||||
|
},
|
||||||
.workers = {
|
.workers = {
|
||||||
.count = conf->render_worker_count,
|
.count = conf->render_worker_count,
|
||||||
.queue = tll_init(),
|
.queue = tll_init(),
|
||||||
|
|
@ -1318,6 +1353,7 @@ close_fds:
|
||||||
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);
|
fdm_del(fdm, title_update_fd);
|
||||||
|
fdm_del(fdm, app_id_update_fd);
|
||||||
|
|
||||||
free(term);
|
free(term);
|
||||||
return NULL;
|
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->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.app_id.timer_fd);
|
||||||
fdm_del(term->fdm, term->render.title.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);
|
||||||
|
|
@ -1548,6 +1585,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.app_id.timer_fd = -1;
|
||||||
term->render.title.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;
|
||||||
|
|
@ -1601,6 +1639,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.app_id.timer_fd);
|
||||||
fdm_del(term->fdm, term->render.title.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);
|
||||||
|
|
@ -1644,6 +1683,7 @@ term_destroy(struct terminal *term)
|
||||||
|
|
||||||
composed_free(term->composed);
|
composed_free(term->composed);
|
||||||
|
|
||||||
|
free(term->app_id);
|
||||||
free(term->window_title);
|
free(term->window_title);
|
||||||
tll_free_and_free(term->window_title_stack, free);
|
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;
|
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
|
void
|
||||||
term_flash(struct terminal *term, unsigned duration_ms)
|
term_flash(struct terminal *term, unsigned duration_ms)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -483,6 +483,7 @@ struct terminal {
|
||||||
bool window_title_has_been_set;
|
bool window_title_has_been_set;
|
||||||
char *window_title;
|
char *window_title;
|
||||||
tll(char *) window_title_stack;
|
tll(char *) window_title_stack;
|
||||||
|
char *app_id;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
bool active;
|
bool active;
|
||||||
|
|
@ -606,6 +607,11 @@ struct terminal {
|
||||||
int timer_fd;
|
int timer_fd;
|
||||||
} title;
|
} title;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
struct timespec last_update;
|
||||||
|
int timer_fd;
|
||||||
|
} app_id;
|
||||||
|
|
||||||
uint32_t scrollback_lines; /* Number of scrollback lines, from conf (TODO: move out from render struct?) */
|
uint32_t scrollback_lines; /* Number of scrollback lines, from conf (TODO: move out from render struct?) */
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
|
|
@ -832,6 +838,7 @@ void term_xcursor_update_for_seat(struct terminal *term, struct seat *seat);
|
||||||
void term_set_user_mouse_cursor(struct terminal *term, const char *cursor);
|
void term_set_user_mouse_cursor(struct terminal *term, const char *cursor);
|
||||||
|
|
||||||
void term_set_window_title(struct terminal *term, const char *title);
|
void term_set_window_title(struct terminal *term, const char *title);
|
||||||
|
void term_set_app_id(struct terminal *term, const char *app_id);
|
||||||
void term_flash(struct terminal *term, unsigned duration_ms);
|
void term_flash(struct terminal *term, unsigned duration_ms);
|
||||||
void term_bell(struct terminal *term);
|
void term_bell(struct terminal *term);
|
||||||
bool term_spawn_new(const struct terminal *term);
|
bool term_spawn_new(const struct terminal *term);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue