diff --git a/CHANGELOG.md b/CHANGELOG.md index 3a310289..3e5b9a85 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,8 @@ * User configurable key- and mouse bindings. See `man 5 foot` and the example `footrc` (https://codeberg.org/dnkl/foot/issues/1) +* **startup-mode** option to `footrc`, that lets you control the + initial window mode: _windowed_, _maximized_ or _fullscreen_. ### Changed diff --git a/client.c b/client.c index faa7c919..7d188609 100644 --- a/client.c +++ b/client.c @@ -33,6 +33,8 @@ print_usage(const char *prog_name) printf("\n"); printf("Options:\n"); printf(" -t,--term=TERM value to set the environment variable TERM to (foot)\n" + " --maximized start in maximized mode\n" + " --fullscreen start in fullscreen mode\n" " --login-shell start shell as a login shell\n" " -s,--server-socket=PATH path to the server UNIX domain socket (default=$XDG_RUNTIME_DIR/foot-$XDG_SESSION_ID.sock)\n" " -l,--log-colorize=[never|always|auto] enable/disable colorization of log output on stderr\n" @@ -48,6 +50,8 @@ main(int argc, char *const *argv) static const struct option longopts[] = { {"term", required_argument, 0, 't'}, + {"maximized", no_argument, 0, 'm'}, + {"fullscreen", no_argument, 0, 'F'}, {"login-shell", no_argument, 0, 'L'}, {"server-socket", required_argument, 0, 's'}, {"log-colorize", optional_argument, NULL, 'l'}, @@ -60,6 +64,8 @@ main(int argc, char *const *argv) const char *server_socket_path = NULL; enum log_colorize log_colorize = LOG_COLORIZE_AUTO; bool login_shell = false; + bool maximized = false; + bool fullscreen = false; while (true) { int c = getopt_long(argc, argv, ":t:s:l::hv", longopts, NULL); @@ -75,6 +81,16 @@ main(int argc, char *const *argv) login_shell = true; break; + case ',': + maximized = true; + fullscreen = false; + break; + + case 'F': + fullscreen = true; + maximized = false; + break; + case 's': server_socket_path = optarg; break; @@ -177,6 +193,8 @@ main(int argc, char *const *argv) /* Calculate total length */ total_len += sizeof(cwd_len) + cwd_len; total_len += sizeof(term_len) + term_len; + total_len += sizeof(uint8_t); /* maximized */ + total_len += sizeof(uint8_t); /* fullscreen */ total_len += sizeof(uint8_t); /* login_shell */ total_len += sizeof(argc); @@ -207,6 +225,16 @@ main(int argc, char *const *argv) goto err; } + if (send(fd, &(uint8_t){maximized}, sizeof(uint8_t), 0) != sizeof(uint8_t)) { + LOG_ERRNO("failed to send maximized"); + goto err; + } + + if (send(fd, &(uint8_t){fullscreen}, sizeof(uint8_t), 0) != sizeof(uint8_t)) { + LOG_ERRNO("failed to send fullscreen"); + goto err; + } + if (send(fd, &(uint8_t){login_shell}, sizeof(uint8_t), 0) != sizeof(uint8_t)) { LOG_ERRNO("failed to send login-shell"); goto err; diff --git a/completions/zsh/_foot b/completions/zsh/_foot index 7cef2646..95e8d98e 100644 --- a/completions/zsh/_foot +++ b/completions/zsh/_foot @@ -5,6 +5,8 @@ _arguments \ '(-c --config)'{-c,--config}'[path to configuration file (XDG_CONFIG_HOME/footrc)]:config:_files' \ '(-f --font)'{-f,--font}'[font name and style in fontconfig format (monospace)]:font:->fonts' \ '(-t --term)'{-t,--term}'[value to set the environment variable TERM to (foot)]:term:->terms' \ + '--maximized[start in maximized mode]' \ + '--fullscreen[start in fullscreen mode]' \ '--login-shell[start shell as a login shell]' \ '(-g --geometry)'{-g,--geometry}'[window WIDTHxHEIGHT, in pixels (700x50)]:geometry:()' \ '(-s --server)'{-s,--server}'[run as server; open terminals by running footclient]:server:_files' \ diff --git a/completions/zsh/_footclient b/completions/zsh/_footclient index 75a99b95..7f8c8009 100644 --- a/completions/zsh/_footclient +++ b/completions/zsh/_footclient @@ -3,6 +3,8 @@ _arguments \ -s \ '(-t --term)'{-t,--term}'[value to set the environment variable TERM to (foot)]:term:->terms' \ + '--maximized[start in maximized mode]' \ + '--fullscreen[start in fullscreen mode]' \ '--login-shell[start shell as a login shell]' \ '(-s --server-socket)'{-s,--server-socket}'[override the default path to the foot server socket (XDG_RUNTIME_DIR/foot.sock)]:server:_files' \ '(-l --log-colorize)'{-l,--log-colorize}'[enable or disable colorization of log output on stderr]:logcolor:(never always auto)' \ diff --git a/config.c b/config.c index 16831248..b86eaf69 100644 --- a/config.c +++ b/config.c @@ -226,7 +226,7 @@ parse_section_main(const char *key, const char *value, struct config *conf, unsigned x, y; if (sscanf(value, "%ux%u", &x, &y) != 2) { LOG_ERR( - "%s: %d: expected PAD_XxPAD_Y, where both are positive integers: %s", + "%s:%d: expected PAD_XxPAD_Y, where both are positive integers: %s", path, lineno, value); return false; } @@ -235,6 +235,21 @@ parse_section_main(const char *key, const char *value, struct config *conf, conf->pad_y = y; } + else if (strcmp(key, "startup-mode") == 0) { + if (strcmp(value, "windowed") == 0) + conf->startup_mode = STARTUP_WINDOWED; + else if (strcmp(value, "maximized") == 0) + conf->startup_mode = STARTUP_MAXIMIZED; + else if (strcmp(value, "fullscreen") == 0) + conf->startup_mode = STARTUP_FULLSCREEN; + else { + LOG_ERR( + "%s:%d: expected either 'windowed', 'maximized' or 'fullscreen'", + path, lineno); + return false; + } + } + else if (strcmp(key, "font") == 0) { char *copy = strdup(value); for (const char *font = strtok(copy, ","); font != NULL; font = strtok(NULL, ",")) { @@ -816,6 +831,7 @@ config_load(struct config *conf, const char *conf_path) .height = 500, .pad_x = 2, .pad_y = 2, + .startup_mode = STARTUP_WINDOWED, .fonts = tll_init(), .scrollback_lines = 1000, diff --git a/config.h b/config.h index f53a1b7b..32e381eb 100644 --- a/config.h +++ b/config.h @@ -15,6 +15,7 @@ struct config { unsigned height; unsigned pad_x; unsigned pad_y; + enum { STARTUP_WINDOWED, STARTUP_MAXIMIZED, STARTUP_FULLSCREEN } startup_mode; tll(char *) fonts; diff --git a/doc/foot.1.scd b/doc/foot.1.scd index bedd541c..ccc0bd3c 100644 --- a/doc/foot.1.scd +++ b/doc/foot.1.scd @@ -36,6 +36,14 @@ execute (instead of the shell). *-t*,*--term*=_TERM_ Value to set the environment variable *TERM* to. Default: *foot*. +*--maximized* + Start in maximized mode. If both *--maximized* and *--fullscreen* + are specified, the _last_ one takes precedence. + +*--fullscreen* + Start in fullscreen mode. If both *--maximized* and *--fullscreen* + are specified, the _last_ one takes precedence. + *--login-shell* Start a login shell, by prepending a '-' to argv[0]. diff --git a/doc/foot.5.scd b/doc/foot.5.scd index 96036ce3..de32f712 100644 --- a/doc/foot.5.scd +++ b/doc/foot.5.scd @@ -40,6 +40,10 @@ in this order: Padding between border and glyphs, in pixels, on the form _XxY_ (-padding). Default: _2x2_. +*startup-mode* + Initial window mode: *windowed*, *maximized* or + *fullscreen*. Default: _windowed_. + *shell* Executable to launch. Typically a shell. Default: _$SHELL_ if set, otherwise the user's default shell (as specified in diff --git a/doc/footclient.1.scd b/doc/footclient.1.scd index d6115906..a4de1089 100644 --- a/doc/footclient.1.scd +++ b/doc/footclient.1.scd @@ -15,6 +15,14 @@ execute (instead of the shell). *-t*,*--term*=_TERM_ Value to set the environment variable _TERM_ to. Default: _foot_. +*--maximized* + Start in maximized mode. If both *--maximized* and *--fullscreen* + are specified, the _last_ one takes precedence. + +*--fullscreen* + Start in fullscreen mode. If both *--maximized* and *--fullscreen* + are specified, the _last_ one takes precedence. + *--login-shell* Start a login shell, by prepending a '-' to argv[0]. diff --git a/footrc b/footrc index 2575b58a..0254c31a 100644 --- a/footrc +++ b/footrc @@ -4,6 +4,7 @@ # scrollback=1000 # geometry=700x500 # pad=2x2 +# startup-mode=windowed # shell=$SHELL (if set, otherwise user's default shell from /etc/passwd) # term=foot # login-shell=no diff --git a/main.c b/main.c index b7dbef13..06497cbe 100644 --- a/main.c +++ b/main.c @@ -46,6 +46,8 @@ print_usage(const char *prog_name) " -c,--config=PATH load configuration from PATH (XDG_CONFIG_HOME/footrc)\n" " -f,--font=FONT comma separated list of fonts in fontconfig format (monospace)\n" " -t,--term=TERM value to set the environment variable TERM to (foot)\n" + " --maximized start in maximized mode\n" + " --fullscreen start in fullscreen mode\n" " --login-shell start shell as a login shell\n" " -g,--geometry=WIDTHxHEIGHT set initial width and height\n" " -s,--server[=PATH] run as a server (use 'footclient' to start terminals).\n" @@ -142,6 +144,8 @@ main(int argc, char *const *argv) {"geometry", required_argument, NULL, 'g'}, {"server", optional_argument, NULL, 's'}, {"hold", no_argument, NULL, 'H'}, + {"maximized", no_argument, NULL, 'm'}, + {"fullscreen", no_argument, NULL, 'F'}, {"presentation-timings", no_argument, NULL, 'P'}, /* Undocumented */ {"print-pid", required_argument, NULL, 'p'}, {"log-colorize", optional_argument, NULL, 'l'}, @@ -161,6 +165,8 @@ main(int argc, char *const *argv) const char *conf_server_socket_path = NULL; bool presentation_timings = false; bool hold = false; + bool maximized = false; + bool fullscreen = false; bool unlink_pid_file = false; const char *pid_file = NULL; enum log_colorize log_colorize = LOG_COLORIZE_AUTO; @@ -232,6 +238,16 @@ main(int argc, char *const *argv) hold = true; break; + case 'm': + maximized = true; + fullscreen = false; + break; + + case 'F': + fullscreen = true; + maximized = false; + break; + case 'p': pid_file = optarg; break; @@ -306,6 +322,10 @@ main(int argc, char *const *argv) free(conf.server_socket_path); conf.server_socket_path = strdup(conf_server_socket_path); } + if (maximized) + conf.startup_mode = STARTUP_MAXIMIZED; + else if (fullscreen) + conf.startup_mode = STARTUP_FULLSCREEN; conf.presentation_timings = presentation_timings; conf.hold_at_exit = hold; @@ -342,8 +362,7 @@ main(int argc, char *const *argv) goto out; if (!as_server && (term = term_init( - &conf, fdm, wayl, conf.term, conf.login_shell, - "foot", cwd, argc, argv, + &conf, fdm, wayl, "foot", cwd, argc, argv, &term_shutdown_cb, &shutdown_ctx)) == NULL) { free(cwd); goto out; diff --git a/server.c b/server.c index 710e7e9d..42116f27 100644 --- a/server.c +++ b/server.c @@ -42,6 +42,7 @@ struct client { size_t idx; } buffer; + struct config conf; struct terminal *term; }; @@ -69,6 +70,11 @@ client_destroy(struct client *client) } free(client->buffer.data); + + /* TODO: clone server conf completely, so that we can just call + * conf_destroy() here */ + free(client->conf.term); + free(client); } @@ -218,6 +224,12 @@ fdm_client(struct fdm *fdm, int fd, int events, void *data) goto shutdown; } + CHECK_BUF(sizeof(uint8_t)); + const uint8_t maximized = *(const uint8_t *)p; p += sizeof(maximized); + + CHECK_BUF(sizeof(uint8_t)); + const uint8_t fullscreen = *(const uint8_t *)p; p += sizeof(fullscreen); + CHECK_BUF(sizeof(uint8_t)); const uint8_t login_shell = *(const uint8_t *)p; p += sizeof(login_shell); @@ -244,9 +256,18 @@ fdm_client(struct fdm *fdm, int fd, int events, void *data) #undef CHECK_BUF + client->conf = *server->conf; + client->conf.term = strlen(term_env) > 0 + ? strdup(term_env) : strdup(server->conf->term); + client->conf.login_shell = login_shell; + + if (maximized) + client->conf.startup_mode = STARTUP_MAXIMIZED; + else if (fullscreen) + client->conf.startup_mode = STARTUP_FULLSCREEN; + client->term = term_init( - server->conf, server->fdm, server->wayl, - strlen(term_env) > 0 ? term_env : server->conf->term, login_shell, + &client->conf, server->fdm, server->wayl, "footclient", cwd, argc, argv, &term_shutdown_handler, client); if (client->term == NULL) { diff --git a/terminal.c b/terminal.c index 9352e5df..14f1666a 100644 --- a/terminal.c +++ b/terminal.c @@ -13,6 +13,7 @@ #include #include #include +#include #define LOG_MODULE "terminal" #define LOG_ENABLE_DBG 0 @@ -615,8 +616,7 @@ load_fonts_from_conf(const struct terminal *term, const struct config *conf, struct terminal * term_init(const struct config *conf, struct fdm *fdm, struct wayland *wayl, - const char *term_env, bool login_shell, const char *foot_exe, - const char *cwd, int argc, char *const *argv, + const char *foot_exe, const char *cwd, int argc, char *const *argv, void (*shutdown_cb)(void *data, int exit_code), void *shutdown_data) { int ptmx = -1; @@ -800,9 +800,26 @@ term_init(const struct config *conf, struct fdm *fdm, struct wayland *wayl, /* Let the Wayland backend know we exist */ tll_push_back(wayl->terms, term); + switch (conf->startup_mode) { + case STARTUP_WINDOWED: + break; + + case STARTUP_MAXIMIZED: + xdg_toplevel_set_maximized(term->window->xdg_toplevel); + break; + + case STARTUP_FULLSCREEN: + xdg_toplevel_set_fullscreen(term->window->xdg_toplevel, NULL); + break; + } + /* Start the slave/client */ - if ((term->slave = slave_spawn(term->ptmx, argc, term->cwd, argv, term_env, conf->shell, login_shell)) == -1) + if ((term->slave = slave_spawn( + term->ptmx, argc, term->cwd, argv, + conf->term, conf->shell, conf->login_shell)) == -1) + { goto err; + } return term; diff --git a/terminal.h b/terminal.h index 9b97cf4e..40088b04 100644 --- a/terminal.h +++ b/terminal.h @@ -432,8 +432,7 @@ struct terminal { struct config; struct terminal *term_init( const struct config *conf, struct fdm *fdm, struct wayland *wayl, - const char *term_env, bool login_shell, const char *foot_exe, - const char *cwd, int argc, char *const *argv, + const char *foot_exe, const char *cwd, int argc, char *const *argv, void (*shutdown_cb)(void *data, int exit_code), void *shutdown_data); bool term_shutdown(struct terminal *term);