mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-02-04 04:06:06 -05:00
config: add toplevel-tag=TAG
Add support for the new xdg-toplevel-tag-v1 Wayland protocol, by exposing a new config option, `toplevel-tag`, and a corresponding command option, `--toplevel-tag` (in both `foot` and `footclient`). This can help the compositor with session management, or custom window rules. Closes #2212
This commit is contained in:
parent
c9abab0807
commit
fc9625678f
19 changed files with 113 additions and 6 deletions
|
|
@ -69,6 +69,15 @@
|
|||
|
||||
## Unreleased
|
||||
### Added
|
||||
|
||||
* `toplevel-tag` option (and `--toplevel-tag` command line options to
|
||||
`foot` and `footclient`), allowing you to set a custom toplevel
|
||||
tag. The compositor must implement the new `xdg-toplevel-tag-v1`
|
||||
Wayland protocol ([#2212][2212]).
|
||||
|
||||
[2212]: https://codeberg.org/dnkl/foot/issues/2212
|
||||
|
||||
|
||||
### Changed
|
||||
|
||||
* When enabling _"focus mode"_ (private mode 1004), foot now sends a
|
||||
|
|
|
|||
12
client.c
12
client.c
|
|
@ -76,6 +76,7 @@ print_usage(const char *prog_name)
|
|||
" -t,--term=TERM value to set the environment variable TERM to (" FOOT_DEFAULT_TERM ")\n"
|
||||
" -T,--title=TITLE initial window title (foot)\n"
|
||||
" -a,--app-id=ID window application ID (foot)\n"
|
||||
" --toplevel-tag=TAG set a custom toplevel tag\n"
|
||||
" -w,--window-size-pixels=WIDTHxHEIGHT initial width and height, in pixels\n"
|
||||
" -W,--window-size-chars=WIDTHxHEIGHT initial width and height, in characters\n"
|
||||
" -m,--maximized start in maximized mode\n"
|
||||
|
|
@ -137,6 +138,10 @@ send_string_list(int fd, const string_list_t *string_list)
|
|||
return true;
|
||||
}
|
||||
|
||||
enum {
|
||||
TOPLEVEL_TAG_OPTION = CHAR_MAX + 1,
|
||||
};
|
||||
|
||||
int
|
||||
main(int argc, char *const *argv)
|
||||
{
|
||||
|
|
@ -151,6 +156,7 @@ main(int argc, char *const *argv)
|
|||
{"term", required_argument, NULL, 't'},
|
||||
{"title", required_argument, NULL, 'T'},
|
||||
{"app-id", required_argument, NULL, 'a'},
|
||||
{"toplevel-tag", required_argument, NULL, TOPLEVEL_TAG_OPTION},
|
||||
{"window-size-pixels", required_argument, NULL, 'w'},
|
||||
{"window-size-chars", required_argument, NULL, 'W'},
|
||||
{"maximized", no_argument, NULL, 'm'},
|
||||
|
|
@ -220,6 +226,12 @@ main(int argc, char *const *argv)
|
|||
goto err;
|
||||
break;
|
||||
|
||||
case TOPLEVEL_TAG_OPTION:
|
||||
snprintf(buf, sizeof(buf), "toplevel-tag=%s", optarg);
|
||||
if (!push_string(&overrides, buf, &total_len))
|
||||
goto err;
|
||||
break;
|
||||
|
||||
case 'L':
|
||||
if (!push_string(&overrides, "login-shell=yes", &total_len))
|
||||
goto err;
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ _foot()
|
|||
local cur prev flags word commands match previous_words i offset
|
||||
flags=(
|
||||
"--app-id"
|
||||
"--toplevel-tag"
|
||||
"--check-config"
|
||||
"--config"
|
||||
"--font"
|
||||
|
|
@ -40,7 +41,7 @@ _foot()
|
|||
for word in "${previous_words[@]}" ; do
|
||||
match=$(printf "$commands" | grep -Fx "$word" 2>/dev/null)
|
||||
if [[ ! -z "$match" ]] ; then
|
||||
if [[ ${COMP_WORDS[i-1]} =~ ^(--app-id|--config|--font|--log-level|--pty|--term|--title|--window-size-pixels|--window-size-chars|--working-directory)$ ]] ; then
|
||||
if [[ ${COMP_WORDS[i-1]} =~ ^(--app-id|--toplevel-tag|--config|--font|--log-level|--pty|--term|--title|--window-size-pixels|--window-size-chars|--working-directory)$ ]] ; then
|
||||
(( i++ ))
|
||||
continue
|
||||
fi
|
||||
|
|
@ -75,7 +76,7 @@ _foot()
|
|||
COMPREPLY=( $(compgen -W "none error warning info" -- ${cur}) ) ;;
|
||||
--log-colorize|-l)
|
||||
COMPREPLY=( $(compgen -W "never always auto" -- ${cur}) ) ;;
|
||||
--app-id|--help|--override|--pty|--title|--version|--window-size-chars|--window-size-pixels|--check-config|-[ahoTvWwC])
|
||||
--app-id|--toplevel-tag|--help|--override|--pty|--title|--version|--window-size-chars|--window-size-pixels|--check-config|-[ahoTvWwC])
|
||||
# Don't autocomplete for these flags
|
||||
: ;;
|
||||
*)
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ _footclient()
|
|||
local cur prev flags word commands match previous_words i offset
|
||||
flags=(
|
||||
"--app-id"
|
||||
"--toplevel-tag"
|
||||
"--fullscreen"
|
||||
"--help"
|
||||
"--hold"
|
||||
|
|
@ -35,7 +36,7 @@ _footclient()
|
|||
for word in "${previous_words[@]}" ; do
|
||||
match=$(printf "$commands" | grep -Fx "$word" 2>/dev/null)
|
||||
if [[ ! -z "$match" ]] ; then
|
||||
if [[ ${COMP_WORDS[i-1]} =~ ^(--app-id|--log-level|--server-socket|--term|--title|--window-size-pixels|--window-size-chars|--working-directory)$ ]] ; then
|
||||
if [[ ${COMP_WORDS[i-1]} =~ ^(--app-id|--toplevel-tag|--log-level|--server-socket|--term|--title|--window-size-pixels|--window-size-chars|--working-directory)$ ]] ; then
|
||||
(( i++ ))
|
||||
continue
|
||||
fi
|
||||
|
|
@ -67,7 +68,7 @@ _footclient()
|
|||
COMPREPLY=( $(compgen -W "none error warning info" -- ${cur}) ) ;;
|
||||
--log-colorize|-l)
|
||||
COMPREPLY=( $(compgen -W "never always auto" -- ${cur}) ) ;;
|
||||
--app-id|--help|--override|--title|--version|--window-size-chars|--window-size-pixels|-[ahoTvWw])
|
||||
--app-id|--toplevel-tag|--help|--override|--title|--version|--window-size-chars|--window-size-pixels|-[ahoTvWw])
|
||||
# Don't autocomplete for these flags
|
||||
: ;;
|
||||
*)
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ complete -c foot -x -s f -l font -a "(fc-list : family | sed 's/,/
|
|||
complete -c foot -x -s t -l term -a '(find /usr/share/terminfo -type f -printf "%f\n")' -d "value to set the environment variable TERM to (foot)"
|
||||
complete -c foot -x -s T -l title -d "initial window title"
|
||||
complete -c foot -x -s a -l app-id -d "value to set the app-id property on the Wayland window to (foot)"
|
||||
complete -c foot -x -l toplevel-tag -d "value to set the toplevel-tag property on the Wayland window to"
|
||||
complete -c foot -s m -l maximized -d "start in maximized mode"
|
||||
complete -c foot -s F -l fullscreen -d "start in fullscreen mode"
|
||||
complete -c foot -s L -l login-shell -d "start shell as a login shell"
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ complete -c footclient -x -a "(__fish_complete_subcom
|
|||
complete -c footclient -x -s t -l term -a '(find /usr/share/terminfo -type f -printf "%f\n")' -d "value to set the environment variable TERM to (foot)"
|
||||
complete -c footclient -x -s T -l title -d "initial window title"
|
||||
complete -c footclient -x -s a -l app-id -d "value to set the app-id property on the Wayland window to (foot)"
|
||||
complete -c footclient -x -l toplevel-tag -d "value to set the toplevel-tag property on the Wayland window to"
|
||||
complete -c footclient -s m -l maximized -d "start in maximized mode"
|
||||
complete -c footclient -s F -l fullscreen -d "start in fullscreen mode"
|
||||
complete -c footclient -s L -l login-shell -d "start shell as a login shell"
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ _arguments \
|
|||
'(-t --term)'{-t,--term}'[value to set the environment variable TERM to (foot)]:term:->terms' \
|
||||
'(-T --title)'{-T,--title}'[initial window title]:()' \
|
||||
'(-a --app-id)'{-a,--app-id}'[value to set the app-id property on the Wayland window to (foot)]:()' \
|
||||
'--toplevel-tag=[value to set the toplevel-tag property on the Wayland window to]:()' \
|
||||
'(-m --maximized)'{-m,--maximized}'[start in maximized mode]' \
|
||||
'(-F --fullscreen)'{-F,--fullscreen}'[start in fullscreen mode]' \
|
||||
'(-L --login-shell)'{-L,--login-shell}'[start shell as a login shell]' \
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ _arguments \
|
|||
'(-t --term)'{-t,--term}'[value to set the environment variable TERM to (foot)]:term:->terms' \
|
||||
'(-T --title)'{-T,--title}'[initial window title]:()' \
|
||||
'(-a --app-id)'{-a,--app-id}'[value to set the app-id property on the Wayland window to (foot)]:()' \
|
||||
'--toplevel-tag=[value to set the toplevel-tag property on the Wayland window to]:()' \
|
||||
'(-m --maximized)'{-m,--maximized}'[start in maximized mode]' \
|
||||
'(-F --fullscreen)'{-F,--fullscreen}'[start in fullscreen mode]' \
|
||||
'(-L --login-shell)'{-L,--login-shell}'[start shell as a login shell]' \
|
||||
|
|
|
|||
6
config.c
6
config.c
|
|
@ -923,6 +923,9 @@ parse_section_main(struct context *ctx)
|
|||
else if (streq(key, "app-id"))
|
||||
return value_to_str(ctx, &conf->app_id);
|
||||
|
||||
else if (streq(key, "toplevel-tag"))
|
||||
return value_to_str(ctx, &conf->toplevel_tag);
|
||||
|
||||
else if (streq(key, "initial-window-size-pixels")) {
|
||||
if (!value_to_dimensions(ctx, &conf->size.width, &conf->size.height))
|
||||
return false;
|
||||
|
|
@ -3371,6 +3374,7 @@ config_load(struct config *conf, const char *conf_path,
|
|||
.shell = get_shell(),
|
||||
.title = xstrdup("foot"),
|
||||
.app_id = (as_server ? xstrdup("footclient") : xstrdup("foot")),
|
||||
.toplevel_tag = xstrdup(""),
|
||||
.word_delimiters = xc32dup(U",│`|:\"'()[]{}<>"),
|
||||
.size = {
|
||||
.type = CONF_SIZE_PX,
|
||||
|
|
@ -3823,6 +3827,7 @@ config_clone(const struct config *old)
|
|||
conf->shell = xstrdup(old->shell);
|
||||
conf->title = xstrdup(old->title);
|
||||
conf->app_id = xstrdup(old->app_id);
|
||||
conf->toplevel_tag = xstrdup(old->toplevel_tag);
|
||||
conf->word_delimiters = xc32dup(old->word_delimiters);
|
||||
conf->scrollback.indicator.text = xc32dup(old->scrollback.indicator.text);
|
||||
conf->server_socket_path = xstrdup(old->server_socket_path);
|
||||
|
|
@ -3922,6 +3927,7 @@ config_free(struct config *conf)
|
|||
free(conf->shell);
|
||||
free(conf->title);
|
||||
free(conf->app_id);
|
||||
free(conf->toplevel_tag);
|
||||
free(conf->word_delimiters);
|
||||
spawn_template_free(&conf->bell.command);
|
||||
free(conf->scrollback.indicator.text);
|
||||
|
|
|
|||
1
config.h
1
config.h
|
|
@ -219,6 +219,7 @@ struct config {
|
|||
char *shell;
|
||||
char *title;
|
||||
char *app_id;
|
||||
char *toplevel_tag;
|
||||
char32_t *word_delimiters;
|
||||
bool login_shell;
|
||||
bool locked_title;
|
||||
|
|
|
|||
|
|
@ -67,6 +67,11 @@ the foot command line
|
|||
Value to set the *app-id* property on the Wayland window
|
||||
to. Default: _foot_ (normal mode), or _footclient_ (server mode).
|
||||
|
||||
*toplevel-tag*=_TAG_
|
||||
Value to set the *toplevel-tag* property on the Wayland window
|
||||
to. The compositor can use this value for session management,
|
||||
window rules etc. Default: _not set_
|
||||
|
||||
*-m*,*--maximized*
|
||||
Start in maximized mode. If both *--maximized* and *--fullscreen*
|
||||
are specified, the _last_ one takes precedence.
|
||||
|
|
|
|||
|
|
@ -429,6 +429,11 @@ empty string to be set, but it must be quoted: *KEY=""*)
|
|||
apply window management rules. Default: _foot_ (normal mode), or
|
||||
_footclient_ (server mode).
|
||||
|
||||
*toplevel-tag*
|
||||
Value to set the *toplevel-tag* property on the Wayland window
|
||||
to. The compositor can use this value for session management,
|
||||
window rules etc. Default: _not set_
|
||||
|
||||
*bold-text-in-bright*
|
||||
Semi-boolean. When enabled, bold text is rendered in a brighter
|
||||
color (in addition to using a bold font). The color is brightened
|
||||
|
|
|
|||
|
|
@ -33,6 +33,11 @@ terminal has terminated.
|
|||
Value to set the *app-id* property on the Wayland window
|
||||
to. Default: _foot_ (normal mode), or _footclient_ (server mode).
|
||||
|
||||
*toplevel-tag*=_TAG_
|
||||
Value to set the *toplevel-tag* property on the Wayland window
|
||||
to. The compositor can use this value for session management,
|
||||
window rules etc. Default: _not set_
|
||||
|
||||
*-w*,*--window-size-pixels*=_WIDTHxHEIGHT_
|
||||
Set initial window width and height, in pixels. Default: _700x500_.
|
||||
|
||||
|
|
|
|||
|
|
@ -22,6 +22,12 @@ const char version_and_features[] =
|
|||
" -graphemes"
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_XDG_TOPLEVEL_TAG)
|
||||
" +toplevel-tag"
|
||||
#else
|
||||
" -toplevel-tag"
|
||||
#endif
|
||||
|
||||
#if !defined(NDEBUG)
|
||||
" +assertions"
|
||||
#else
|
||||
|
|
|
|||
7
main.c
7
main.c
|
|
@ -84,6 +84,7 @@ print_usage(const char *prog_name)
|
|||
" -t,--term=TERM value to set the environment variable TERM to (" FOOT_DEFAULT_TERM ")\n"
|
||||
" -T,--title=TITLE initial window title (foot)\n"
|
||||
" -a,--app-id=ID window application ID (foot)\n"
|
||||
" --toplevel-tag=TAG set a custom toplevel tag\n"
|
||||
" -m,--maximized start in maximized mode\n"
|
||||
" -F,--fullscreen start in fullscreen mode\n"
|
||||
" -L,--login-shell start shell as a login shell\n"
|
||||
|
|
@ -185,6 +186,7 @@ sanitize_signals(void)
|
|||
|
||||
enum {
|
||||
PTY_OPTION = CHAR_MAX + 1,
|
||||
TOPLEVEL_TAG_OPTION = CHAR_MAX + 2,
|
||||
};
|
||||
|
||||
int
|
||||
|
|
@ -214,6 +216,7 @@ main(int argc, char *const *argv)
|
|||
{"term", required_argument, NULL, 't'},
|
||||
{"title", required_argument, NULL, 'T'},
|
||||
{"app-id", required_argument, NULL, 'a'},
|
||||
{"toplevel-tag", required_argument, NULL, TOPLEVEL_TAG_OPTION},
|
||||
{"login-shell", no_argument, NULL, 'L'},
|
||||
{"working-directory", required_argument, NULL, 'D'},
|
||||
{"font", required_argument, NULL, 'f'},
|
||||
|
|
@ -285,6 +288,10 @@ main(int argc, char *const *argv)
|
|||
tll_push_back(overrides, xstrjoin("app-id=", optarg));
|
||||
break;
|
||||
|
||||
case TOPLEVEL_TAG_OPTION:
|
||||
tll_push_back(overrides, xstrjoin("toplevel-tag=", optarg));
|
||||
break;
|
||||
|
||||
case 'D': {
|
||||
struct stat st;
|
||||
if (stat(optarg, &st) < 0 || !(st.st_mode & S_IFDIR)) {
|
||||
|
|
|
|||
|
|
@ -182,7 +182,12 @@ wl_proto_xml = [
|
|||
wayland_protocols_datadir / 'staging/xdg-toplevel-icon/xdg-toplevel-icon-v1.xml',
|
||||
wayland_protocols_datadir / 'staging/xdg-system-bell/xdg-system-bell-v1.xml',
|
||||
wayland_protocols_datadir / 'staging/color-management/color-management-v1.xml',
|
||||
]
|
||||
]
|
||||
|
||||
if (wayland_protocols.version().version_compare('>=1.43'))
|
||||
wl_proto_xml += [wayland_protocols_datadir / 'staging/xdg-toplevel-tag/xdg-toplevel-tag-v1.xml']
|
||||
add_project_arguments('-DHAVE_XDG_TOPLEVEL_TAG=1', language: 'c')
|
||||
endif
|
||||
|
||||
foreach prot : wl_proto_xml
|
||||
wl_proto_headers += custom_target(
|
||||
|
|
|
|||
|
|
@ -482,6 +482,7 @@ test_section_main(void)
|
|||
test_string(&ctx, &parse_section_main, "shell", &conf.shell);
|
||||
test_string(&ctx, &parse_section_main, "term", &conf.term);
|
||||
test_string(&ctx, &parse_section_main, "app-id", &conf.app_id);
|
||||
test_string(&ctx, &parse_section_main, "toplevel-tag", &conf.toplevel_tag);
|
||||
test_string(&ctx, &parse_section_main, "utmp-helper", &conf.utmp_helper_path);
|
||||
|
||||
test_c32string(&ctx, &parse_section_main, "word-delimiters", &conf.word_delimiters);
|
||||
|
|
|
|||
33
wayland.c
33
wayland.c
|
|
@ -1548,6 +1548,17 @@ handle_global(void *data, struct wl_registry *registry,
|
|||
wayl->color_management.manager, &color_manager_listener, wayl);
|
||||
}
|
||||
|
||||
#if defined(HAVE_XDG_TOPLEVEL_TAG)
|
||||
else if (streq(interface, xdg_toplevel_tag_manager_v1_interface.name)) {
|
||||
const uint32_t required = 1;
|
||||
if (!verify_iface_version(interface, version, required))
|
||||
return;
|
||||
|
||||
wayl->toplevel_tag_manager = wl_registry_bind(
|
||||
wayl->registry, name, &xdg_toplevel_tag_manager_v1_interface, required);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(FOOT_IME_ENABLED) && FOOT_IME_ENABLED
|
||||
else if (streq(interface, zwp_text_input_manager_v3_interface.name)) {
|
||||
const uint32_t required = 1;
|
||||
|
|
@ -1791,7 +1802,7 @@ wayl_init(struct fdm *fdm, struct key_binding_manager *key_binding_manager,
|
|||
}
|
||||
|
||||
if (wayl->toplevel_icon_manager == NULL) {
|
||||
LOG_WARN("compositor does not implement the XDG toplevel icon protocol");
|
||||
LOG_WARN("compositor does not implement the xdg-toplevel-icon protocol");
|
||||
}
|
||||
|
||||
#if defined(FOOT_IME_ENABLED) && FOOT_IME_ENABLED
|
||||
|
|
@ -1870,6 +1881,11 @@ wayl_destroy(struct wayland *wayl)
|
|||
zwp_text_input_manager_v3_destroy(wayl->text_input_manager);
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_XDG_TOPLEVEL_TAG)
|
||||
if (wayl->toplevel_tag_manager != NULL)
|
||||
xdg_toplevel_tag_manager_v1_destroy(wayl->toplevel_tag_manager);
|
||||
#endif
|
||||
|
||||
if (wayl->color_management.img_description != NULL)
|
||||
wp_image_description_v1_destroy(wayl->color_management.img_description);
|
||||
if (wayl->color_management.manager != NULL)
|
||||
|
|
@ -1995,6 +2011,21 @@ wayl_win_init(struct terminal *term, const char *token)
|
|||
|
||||
xdg_toplevel_set_app_id(win->xdg_toplevel, conf->app_id);
|
||||
|
||||
#if defined(HAVE_XDG_TOPLEVEL_TAG)
|
||||
if (conf->toplevel_tag != NULL && conf->toplevel_tag[0] != '\0') {
|
||||
if (wayl->toplevel_tag_manager != NULL) {
|
||||
xdg_toplevel_tag_manager_v1_set_toplevel_tag(
|
||||
wayl->toplevel_tag_manager, win->xdg_toplevel, conf->toplevel_tag);
|
||||
|
||||
/* TODO: the description is recommended to be the tag, but translated */
|
||||
xdg_toplevel_tag_manager_v1_set_toplevel_description(
|
||||
wayl->toplevel_tag_manager, win->xdg_toplevel, conf->toplevel_tag);
|
||||
} else {
|
||||
LOG_WARN("compositor does not implement the xdg-toplevel-tag protocol");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (wayl->toplevel_icon_manager != NULL) {
|
||||
const char *app_id =
|
||||
term->app_id != NULL ? term->app_id : term->conf->app_id;
|
||||
|
|
|
|||
|
|
@ -23,6 +23,10 @@
|
|||
#include <xdg-system-bell-v1.h>
|
||||
#include <xdg-toplevel-icon-v1.h>
|
||||
|
||||
#if defined(HAVE_XDG_TOPLEVEL_TAG)
|
||||
#include <xdg-toplevel-tag-v1.h>
|
||||
#endif
|
||||
|
||||
#include <fcft/fcft.h>
|
||||
#include <tllist.h>
|
||||
|
||||
|
|
@ -481,6 +485,10 @@ struct wayland {
|
|||
struct wp_presentation *presentation;
|
||||
uint32_t presentation_clock_id;
|
||||
|
||||
#if defined(HAVE_XDG_TOPLEVEL_TAG)
|
||||
struct xdg_toplevel_tag_manager_v1 *toplevel_tag_manager;
|
||||
#endif
|
||||
|
||||
#if defined(FOOT_IME_ENABLED) && FOOT_IME_ENABLED
|
||||
struct zwp_text_input_manager_v3 *text_input_manager;
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue