enhanced bell configuration

Add a separate section for bell configuration, with a bell-specific
command option and a setting to allow that command to run without regard
to keyboard focus (for those of us who enjoy being beeped at at all
times, for example). The actions are also no longer mutually exclusive;
this is primarily anticipating urgency support which cannot be
replicated outside the process (in server mode anyway) and would thus be
complementary to any notification or arbitrary command.
This commit is contained in:
Ryan Farley 2021-04-29 04:12:55 -05:00
parent 8cb95018c0
commit 5d71ccc174
5 changed files with 96 additions and 63 deletions

View file

@ -593,23 +593,6 @@ parse_section_main(const char *key, const char *value, struct config *conf,
}
}
else if (strcmp(key, "bell") == 0) {
if (strcmp(value, "set-urgency") == 0)
conf->bell_action = BELL_ACTION_URGENT;
else if (strcmp(value, "notify") == 0)
conf->bell_action = BELL_ACTION_NOTIFY;
else if (strcmp(value, "none") == 0)
conf->bell_action = BELL_ACTION_NONE;
else {
LOG_AND_NOTIFY_ERR(
"%s:%d: [default]: bell: "
"expected either 'set-urgency', 'notify' or 'none'",
path, lineno);
conf->bell_action = BELL_ACTION_NONE;
return false;
}
}
else if (strcmp(key, "initial-window-mode") == 0) {
if (strcmp(value, "windowed") == 0)
conf->startup_mode = STARTUP_WINDOWED;
@ -788,6 +771,28 @@ parse_section_main(const char *key, const char *value, struct config *conf,
return true;
}
static bool
parse_section_bell(const char *key, const char *value, struct config *conf,
const char *path, unsigned lineno)
{
if (strcmp(key, "urgent") == 0)
conf->bell.urgent = str_to_bool(value);
else if (strcmp(key, "notify") == 0)
conf->bell.notify = str_to_bool(value);
else if (strcmp(key, "command") == 0) {
if (!str_to_spawn_template(conf, value, &conf->bell.command, path, lineno, "bell", key))
return false;
}
else if (strcmp(key, "command-focused") == 0)
conf->bell.command_focused = str_to_bool(value);
else {
LOG_AND_NOTIFY_ERR("%s:%u: [bell]: %s: invalid key", path, lineno, key);
return false;
}
return true;
}
static bool
parse_section_scrollback(const char *key, const char *value, struct config *conf,
const char *path, unsigned lineno)
@ -1864,6 +1869,7 @@ parse_config_file(FILE *f, struct config *conf, const char *path, bool errors_ar
{
enum section {
SECTION_MAIN,
SECTION_BELL,
SECTION_SCROLLBACK,
SECTION_COLORS,
SECTION_CURSOR,
@ -1887,6 +1893,7 @@ parse_config_file(FILE *f, struct config *conf, const char *path, bool errors_ar
const char *name;
} section_info[] = {
[SECTION_MAIN] = {&parse_section_main, "main"},
[SECTION_BELL] = {&parse_section_bell, "bell"},
[SECTION_SCROLLBACK] = {&parse_section_scrollback, "scrollback"},
[SECTION_COLORS] = {&parse_section_colors, "colors"},
[SECTION_CURSOR] = {&parse_section_cursor, "cursor"},
@ -2212,7 +2219,6 @@ config_load(struct config *conf, const char *conf_path,
.enabled = false,
.palette_based = false,
},
.bell_action = BELL_ACTION_NONE,
.startup_mode = STARTUP_WINDOWED,
.fonts = {tll_init(), tll_init(), tll_init(), tll_init()},
.line_height = { .pt = 0, .px = -1, },
@ -2221,6 +2227,15 @@ config_load(struct config *conf, const char *conf_path,
.vertical_letter_offset = {.pt = 0, .px = 0, },
.box_drawings_uses_font_glyphs = false,
.dpi_aware = DPI_AWARE_AUTO, /* DPI-aware when scaling-factor == 1 */
.bell = {
.urgent = false,
.notify = false,
.command = {
.raw_cmd = NULL,
.argv = NULL,
},
.command_focused = false,
},
.scrollback = {
.lines = 1000,
.indicator = {
@ -2446,6 +2461,7 @@ config_free(struct config conf)
free(conf.app_id);
free(conf.word_delimiters);
free(conf.jump_label_letters);
free_spawn_template(&conf.bell.command);
free(conf.scrollback.indicator.text);
free_spawn_template(&conf.notify);
free_spawn_template(&conf.url_launch);

View file

@ -84,12 +84,6 @@ struct config {
bool palette_based;
} bold_in_bright;
enum {
BELL_ACTION_NONE,
BELL_ACTION_URGENT,
BELL_ACTION_NOTIFY,
} bell_action;
enum { STARTUP_WINDOWED, STARTUP_MAXIMIZED, STARTUP_FULLSCREEN } startup_mode;
enum {DPI_AWARE_AUTO, DPI_AWARE_YES, DPI_AWARE_NO} dpi_aware;
@ -105,6 +99,13 @@ struct config {
bool box_drawings_uses_font_glyphs;
struct {
bool urgent;
bool notify;
struct config_spawn_template command;
bool command_focused;
} bell;
struct {
int lines;

View file

@ -211,32 +211,6 @@ in this order:
Default: _no_.
*bell*
Action to perform when receiving a *BEL* character. Can be set to
either *set-urgency*, *notify* or *none*.
When set to *set-urgency*, the margins will be painted in red
whenever *BEL* is received while the window does *not* have
keyboard focus. Note that Wayland currently does not have an
_urgency_ hint like X11. The value *set-urgency* was chosen for
forward-compatibility in the hopes that a corresponding Wayland
protocol is added in the future (in which case foot will use that
instead of painting its margins red).
Applications can enable/disable this feature programmatically with
the *CSI ? 1042 h* and *CSI ? 1042 l* escape sequences.
_Note_: expect this feature to be *replaced* with proper
compositor urgency support once/if that gets implemented.
When set to *notify*, foot will emit a desktop notification using
the command specified in the *notify* option, but only if the foot
window does *not* have keyboard focus.
When set to *none*, no special action is taken when receiving *BEL*.
Default: _none_.
*word-delimiters*
String of characters that act as word delimiters when selecting
text. Note that whitespace characters are _always_ word
@ -288,6 +262,39 @@ in this order:
Default: _url-mode_
# SECTION: bell
*urgent*
When set to _true_, the margins will be painted in red
whenever *BEL* is received while the window does *not* have
keyboard focus. Note that Wayland currently does not have an
_urgency_ hint like X11. The name *urgent* was chosen for
forward-compatibility in the hopes that a corresponding Wayland
protocol is added in the future (in which case foot will use that
instead of painting its margins red).
Applications can enable/disable this feature programmatically with
the *CSI ? 1042 h* and *CSI ? 1042 l* escape sequences.
_Note_: expect this feature to be *replaced* with proper
compositor urgency support once/if that gets implemented.
Default: _false_
*notify*
When set to _true_, foot will emit a desktop notification using
the command specified in the *notify* option whenever *BEL* is
received and the window does *not* have keyboard focus. Default:
_false_
*command*
When set, foot will execute this command when *BEL* is received.
Default: none
*command-focused*
Whether to run the command on *BEL* even while focused. Default:
_false_
# SECTION: scrollback
*lines*

View file

@ -32,6 +32,12 @@
# workers=<number of logical CPUs>
# osc8-underline=url-mode
[bell]
# urgent=false
# notify=false
# command=
# command_focused=false
[scrollback]
# lines=1000
# multiplier=3.0

View file

@ -2627,23 +2627,26 @@ term_flash(struct terminal *term, unsigned duration_ms)
void
term_bell(struct terminal *term)
{
if (term->kbd_focus || !term->bell_action_enabled)
if (!term->bell_action_enabled)
return;
switch (term->conf->bell_action) {
case BELL_ACTION_NONE:
break;
if (!term->kbd_focus) {
if (term->conf->bell.urgent) {
/* There's no 'urgency' hint in Wayland - we just paint the
* margins red */
term->render.urgency = true;
term_damage_margins(term);
}
if (term->conf->bell.notify)
notify_notify(term, "Bell", "Bell in terminal");
}
case BELL_ACTION_URGENT:
/* There's no 'urgency' hint in Wayland - we just paint the
* margins red */
term->render.urgency = true;
term_damage_margins(term);
break;
if (term->conf->bell.command.argv && (!term->kbd_focus || term->conf->bell.command_focused)) {
int devnull = open("/dev/null", O_RDONLY);
spawn(term->reaper, NULL, term->conf->bell.command.argv, devnull, -1, -1);
case BELL_ACTION_NOTIFY:
notify_notify(term, "Bell", "Bell in terminal");
break;
if (devnull >= 0)
close(devnull);
}
}