From e197368c0ffc2235da9b6b41a0d16cdb5b0b61bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 26 Mar 2020 19:39:12 +0100 Subject: [PATCH 1/3] config: add 'startup-mode' option This option controls the initial window mode: windowed, maximized or fullscreen. The default is windowed. --- CHANGELOG.md | 2 ++ config.c | 18 +++++++++++++++++- config.h | 1 + doc/foot.5.scd | 4 ++++ footrc | 1 + terminal.c | 14 ++++++++++++++ 6 files changed, 39 insertions(+), 1 deletion(-) 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/config.c b/config.c index 80163e2e..93b536cb 100644 --- a/config.c +++ b/config.c @@ -225,7 +225,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; } @@ -234,6 +234,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, ",")) { @@ -803,6 +818,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 596aa368..635abb20 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.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/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/terminal.c b/terminal.c index 36f0e42b..41b0ccd9 100644 --- a/terminal.c +++ b/terminal.c @@ -13,6 +13,7 @@ #include #include #include +#include #define LOG_MODULE "terminal" #define LOG_ENABLE_DBG 0 @@ -800,6 +801,19 @@ 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) goto err; From 728e23863c301bce84b3000987e34f3de2c41f1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 26 Mar 2020 19:47:00 +0100 Subject: [PATCH 2/3] foot: add --maximized and --fullscreen command line options --- completions/zsh/_foot | 2 ++ doc/foot.1.scd | 8 ++++++++ main.c | 20 ++++++++++++++++++++ 3 files changed, 30 insertions(+) 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/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/main.c b/main.c index b6ca0fa4..bf73c199 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; From 758fd9fd58b25ab285868db7f36afdf9378df733 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Fri, 27 Mar 2020 21:14:49 +0100 Subject: [PATCH 3/3] client: add --maximized and --fullscreen We now create a copy of the config for each client, and updates it with the values passed from the client. Since we're not actually cloning it (and e.g. strdup() all strings etc) we can't call conf_destroy() to free it, but need to free just the strings we've replaced. --- client.c | 28 ++++++++++++++++++++++++++++ completions/zsh/_footclient | 2 ++ doc/footclient.1.scd | 8 ++++++++ main.c | 3 +-- server.c | 25 +++++++++++++++++++++++-- terminal.c | 9 ++++++--- terminal.h | 3 +-- 7 files changed, 69 insertions(+), 9 deletions(-) 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/_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/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/main.c b/main.c index bf73c199..0d8dc139 100644 --- a/main.c +++ b/main.c @@ -360,8 +360,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 41b0ccd9..73c5d943 100644 --- a/terminal.c +++ b/terminal.c @@ -616,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; @@ -815,8 +814,12 @@ term_init(const struct config *conf, struct fdm *fdm, struct wayland *wayl, } /* 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 3685c0d7..d7d4d705 100644 --- a/terminal.h +++ b/terminal.h @@ -430,8 +430,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);