Implement live-reload of config colors on SIGUSR1.

This commit is contained in:
wreald 2024-09-18 18:40:26 +10:00
parent a50f78c599
commit 341cdabdd2
7 changed files with 87 additions and 0 deletions

View file

@ -3276,6 +3276,7 @@ config_load(struct config *conf, const char *conf_path,
enum fcft_capabilities fcft_caps = fcft_capabilities(); enum fcft_capabilities fcft_caps = fcft_capabilities();
*conf = (struct config) { *conf = (struct config) {
.path = NULL,
.term = xstrdup(FOOT_DEFAULT_TERM), .term = xstrdup(FOOT_DEFAULT_TERM),
.shell = get_shell(), .shell = get_shell(),
.title = xstrdup("foot"), .title = xstrdup("foot"),
@ -3517,6 +3518,8 @@ config_load(struct config *conf, const char *conf_path,
if (conf_file.path && conf_file.fd >= 0) { if (conf_file.path && conf_file.fd >= 0) {
LOG_INFO("loading configuration from %s", conf_file.path); LOG_INFO("loading configuration from %s", conf_file.path);
conf->path = xstrdup(conf_file.path);
FILE *f = fdopen(conf_file.fd, "r"); FILE *f = fdopen(conf_file.fd, "r");
if (f == NULL) { if (f == NULL) {
LOG_AND_NOTIFY_ERRNO("%s: failed to open", conf_file.path); LOG_AND_NOTIFY_ERRNO("%s: failed to open", conf_file.path);
@ -3788,6 +3791,20 @@ config_clone(const struct config *old)
return conf; return conf;
} }
void
config_reload_colors(struct config *conf)
{
user_notifications_t notifications = tll_init();
config_override_t overrides = tll_init();
struct config new_conf = {NULL};
config_load(&new_conf, conf->path, &notifications, &overrides, false, false);
// TODO: should we do something with any notifications that come from
// loading the config?
conf->colors = new_conf.colors;
}
UNITTEST UNITTEST
{ {
struct config original; struct config original;
@ -3816,6 +3833,7 @@ UNITTEST
void void
config_free(struct config *conf) config_free(struct config *conf)
{ {
free(conf->path);
free(conf->term); free(conf->term);
free(conf->shell); free(conf->shell);
free(conf->title); free(conf->title);

View file

@ -132,6 +132,7 @@ struct custom_regex {
}; };
struct config { struct config {
char *path;
char *term; char *term;
char *shell; char *shell;
char *title; char *title;
@ -423,6 +424,7 @@ bool config_load(
bool as_server); bool as_server);
void config_free(struct config *conf); void config_free(struct config *conf);
struct config *config_clone(const struct config *old); struct config *config_clone(const struct config *old);
void config_reload_colors(struct config *conf);
bool config_font_parse(const char *pattern, struct config_font *font); bool config_font_parse(const char *pattern, struct config_font *font);
void config_font_list_destroy(struct config_font_list *font_list); void config_font_list_destroy(struct config_font_list *font_list);

24
main.c
View file

@ -45,6 +45,20 @@ fdm_sigint(struct fdm *fdm, int signo, void *data)
return true; return true;
} }
static bool
fdm_sigusr1_server(struct fdm *fdm, int signo, void *data)
{
server_hard_reload_config_colors(data);
return true;
}
static bool
fdm_sigusr1_term(struct fdm *fdm, int signo, void *data)
{
term_hard_reload_config_colors(data);
return true;
}
static void static void
print_usage(const char *prog_name) print_usage(const char *prog_name)
{ {
@ -608,6 +622,15 @@ main(int argc, char *const *argv)
goto out; goto out;
} }
bool ok = as_server ?
fdm_signal_add(fdm, SIGUSR1, fdm_sigusr1_server, server)
: fdm_signal_add(fdm, SIGUSR1, fdm_sigusr1_term, term);
if (!ok) {
LOG_WARN("failed to set SIGUSR1 handler");
goto out;
}
LOG_INFO("added USR1 handler");
struct sigaction sig_ign = {.sa_handler = SIG_IGN}; struct sigaction sig_ign = {.sa_handler = SIG_IGN};
sigemptyset(&sig_ign.sa_mask); sigemptyset(&sig_ign.sa_mask);
if (sigaction(SIGHUP, &sig_ign, NULL) < 0 || if (sigaction(SIGHUP, &sig_ign, NULL) < 0 ||
@ -645,6 +668,7 @@ out:
reaper_destroy(reaper); reaper_destroy(reaper);
fdm_signal_del(fdm, SIGTERM); fdm_signal_del(fdm, SIGTERM);
fdm_signal_del(fdm, SIGINT); fdm_signal_del(fdm, SIGINT);
fdm_signal_del(fdm, SIGUSR1);
fdm_destroy(fdm); fdm_destroy(fdm);
config_free(&conf); config_free(&conf);

View file

@ -591,6 +591,20 @@ err:
return NULL; return NULL;
} }
/* Reload configured colors from disk. */
void
server_hard_reload_config_colors(struct server *server) {
config_reload_colors((struct config *)server->conf);
tll_foreach(server->wayl->terms, it) {
struct terminal *term = it->item;
((struct config *)term->conf)->colors = server->conf->colors;
term_soft_reload_config_colors(term);
}
}
void void
server_destroy(struct server *server) server_destroy(struct server *server)
{ {

View file

@ -9,3 +9,4 @@ struct server;
struct server *server_init(const struct config *conf, struct fdm *fdm, struct server *server_init(const struct config *conf, struct fdm *fdm,
struct reaper *reaper, struct wayland *wayl); struct reaper *reaper, struct wayland *wayl);
void server_destroy(struct server *server); void server_destroy(struct server *server);
void server_hard_reload_config_colors(struct server *server);

View file

@ -4693,3 +4693,28 @@ term_send_size_notification(struct terminal *term)
term->rows, term->cols, height, width); term->rows, term->cols, height, width);
term_to_slave(term, buf, n); term_to_slave(term, buf, n);
} }
/* Reload configured colors from disk. */
void
term_hard_reload_config_colors(struct terminal *term) {
config_reload_colors((struct config *)term->conf);
term_soft_reload_config_colors(term);
}
/* Reset colors to the in-memory config values. Does not reload the config from
disk. */
void
term_soft_reload_config_colors(struct terminal *term) {
term->colors.fg = term->conf->colors.fg;
term->colors.bg = term->conf->colors.bg;
term->colors.alpha = term->conf->colors.alpha;
term->colors.cursor_fg = term->conf->cursor.color.text;
term->colors.cursor_bg = term->conf->cursor.color.cursor;
term->colors.selection_fg = term->conf->colors.selection_fg;
term->colors.selection_bg = term->conf->colors.selection_bg;
memcpy(term->colors.table, term->conf->colors.table, sizeof(term->colors.table));
term_damage_all(term);
render_refresh(term);
}

View file

@ -982,6 +982,9 @@ void term_enable_size_notifications(struct terminal *term);
void term_disable_size_notifications(struct terminal *term); void term_disable_size_notifications(struct terminal *term);
void term_send_size_notification(struct terminal *term); void term_send_size_notification(struct terminal *term);
void term_hard_reload_config_colors(struct terminal *term);
void term_soft_reload_config_colors(struct terminal *term);
static inline void term_reset_grapheme_state(struct terminal *term) static inline void term_reset_grapheme_state(struct terminal *term)
{ {
#if defined(FOOT_GRAPHEME_CLUSTERING) #if defined(FOOT_GRAPHEME_CLUSTERING)