diff --git a/CHANGELOG.md b/CHANGELOG.md index 70ab43b3..031a4631 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -74,6 +74,8 @@ `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]). +* `pad` option now supports 4-directional padding format: + `RIGHTxTOPxLEFTxBOTTOM` (e.g., `20x10x20x10`). [2212]: https://codeberg.org/dnkl/foot/issues/2212 diff --git a/config.c b/config.c index 515b088c..b6335c4e 100644 --- a/config.c +++ b/config.c @@ -943,13 +943,12 @@ parse_section_main(struct context *ctx) } else if (streq(key, "pad")) { - unsigned x, y; + unsigned x, y, t, r, b, l; char mode[64] = {0}; - int ret = sscanf(value, "%ux%u %63s", &x, &y, mode); - + int ret = sscanf(value, "%ux%ux%ux%u %63s", &r, &t, &l, &b, mode); enum center_when center = CENTER_NEVER; - if (ret == 3) { + if (ret == 5) { if (strcasecmp(mode, "center") == 0) center = CENTER_ALWAYS; else if (strcasecmp(mode, "center-when-fullscreen") == 0) @@ -958,20 +957,38 @@ parse_section_main(struct context *ctx) center = CENTER_MAXIMIZED_AND_FULLSCREEN; else center = CENTER_INVALID; + } else if (ret < 4) { + ret = sscanf(value, "%ux%u %63s", &x, &y, mode); + if (ret >= 2) { + t = b = y; + l = r = x; + if (ret == 3) { + if (strcasecmp(mode, "center") == 0) + center = CENTER_ALWAYS; + else if (strcasecmp(mode, "center-when-fullscreen") == 0) + center = CENTER_FULLSCREEN; + else if (strcasecmp(mode, "center-when-maximized-and-fullscreen") == 0) + center = CENTER_MAXIMIZED_AND_FULLSCREEN; + else + center = CENTER_INVALID; + } + } } - if ((ret != 2 && ret != 3) || center == CENTER_INVALID) { + if ((ret < 2 || ret > 5) || center == CENTER_INVALID) { LOG_CONTEXTUAL_ERR( - "invalid padding (must be in the form PAD_XxPAD_Y " + "invalid padding (must be in the form RIGHTxTOPxLEFTxBOTTOM or XxY " "[center|" "center-when-fullscreen|" "center-when-maximized-and-fullscreen])"); return false; } - conf->pad_x = x; - conf->pad_y = y; - conf->center_when = ret == 2 ? CENTER_NEVER : center; + conf->pad_top = t; + conf->pad_right = r; + conf->pad_bottom = b; + conf->pad_left = l; + conf->center_when = (ret == 4 || ret == 2) ? CENTER_NEVER : center; return true; } @@ -3381,8 +3398,10 @@ config_load(struct config *conf, const char *conf_path, .width = 700, .height = 500, }, - .pad_x = 0, - .pad_y = 0, + .pad_top = 0, + .pad_right = 0, + .pad_bottom = 0, + .pad_left = 0, .center_when = CENTER_MAXIMIZED_AND_FULLSCREEN, .resize_by_cells = true, .resize_keep_grid = true, diff --git a/config.h b/config.h index fc5e290e..d5d870da 100644 --- a/config.h +++ b/config.h @@ -230,8 +230,10 @@ struct config { uint32_t height; } size; - unsigned pad_x; - unsigned pad_y; + unsigned pad_top; + unsigned pad_right; + unsigned pad_bottom; + unsigned pad_left; enum center_when center_when; bool resize_by_cells; diff --git a/doc/foot.ini.5.scd b/doc/foot.ini.5.scd index c9782895..54c6402f 100644 --- a/doc/foot.ini.5.scd +++ b/doc/foot.ini.5.scd @@ -301,9 +301,20 @@ empty string to be set, but it must be quoted: *KEY=""*) ``` _XxY_ [center | center-when-fullscreen | center-when-maximized-and-fullscreen] ``` + or + ``` + RIGHTxTOPxLEFTxBOTTOM [center | center-when-fullscreen | center-when-maximized-and-fullscreen] + ``` - This will add _at least_ X pixels on both the left and right - sides, and Y pixels on the top and bottom sides. + - `_XxY_` adds _at least_: + - X pixels on the left and right sides. + - Y pixels on the top and bottom sides. + + - `RIGHTxTOPxLEFTxBOTTOM` adds **at least**: + - TOP pixels to the top + - BOTTOM pixels to the bottom + - LEFT pixels to the left + - RIGHT pixels to the right When no centering is specified, the grid content is anchored to the top left corner. I.e. if the window manager forces an odd diff --git a/foot.ini b/foot.ini index 2d170489..4bd6fb9e 100644 --- a/foot.ini +++ b/foot.ini @@ -29,6 +29,7 @@ # initial-window-size-chars= # initial-window-mode=windowed # pad=0x0 center-when-maximized-and-fullscreen +# pad=0x0x0x0 center-when-maximized-and-fullscreen # resize-by-cells=yes # resize-keep-grid=yes # resize-delay-ms=100 diff --git a/render.c b/render.c index 1d0f08af..75fb35e0 100644 --- a/render.c +++ b/render.c @@ -4507,8 +4507,8 @@ set_size_from_grid(struct terminal *term, int *width, int *height, int cols, int new_height = rows * term->cell_height; /* Include any configured padding */ - new_width += 2 * term->conf->pad_x * term->scale; - new_height += 2 * term->conf->pad_y * term->scale; + new_width += (term->conf->pad_left + term->conf->pad_right) * term->scale; + new_height += (term->conf->pad_top + term->conf->pad_bottom) * term->scale; /* Round to multiples of scale */ new_width = round(term->scale * round(new_width / term->scale)); @@ -4616,18 +4616,22 @@ render_resize(struct terminal *term, int width, int height, uint8_t opts) /* Padding */ const int max_pad_x = (width - min_width) / 2; const int max_pad_y = (height - min_height) / 2; - const int pad_x = min(max_pad_x, scale * term->conf->pad_x); - const int pad_y = min(max_pad_y, scale * term->conf->pad_y); + const int pad_left = min(max_pad_x, scale * term->conf->pad_left); + const int pad_right = min(max_pad_x, scale * term->conf->pad_right); + const int pad_top = min(max_pad_y, scale * term->conf->pad_top); + const int pad_bottom= min(max_pad_y, scale * term->conf->pad_bottom); if (is_floating && (opts & RESIZE_BY_CELLS) && term->conf->resize_by_cells) { /* If resizing in cell increments, restrict the width and height */ - width = ((width - 2 * pad_x) / term->cell_width) * term->cell_width + 2 * pad_x; + width = ((width - (pad_left + pad_right)) / term->cell_width) + * term->cell_width + (pad_left + pad_right); width = max(min_width, roundf(scale * roundf(width / scale))); - height = ((height - 2 * pad_y) / term->cell_height) * term->cell_height + 2 * pad_y; + height = ((height - (pad_top + pad_bottom)) / term->cell_height) + * term->cell_height + (pad_top + pad_bottom); height = max(min_height, roundf(scale * roundf(height / scale))); } @@ -4654,8 +4658,10 @@ render_resize(struct terminal *term, int width, int height, uint8_t opts) int old_rows = term->rows; /* Screen rows/cols after resize */ - const int new_cols = (term->width - 2 * pad_x) / term->cell_width; - const int new_rows = (term->height - 2 * pad_y) / term->cell_height; + const int new_cols = + (term->width - (pad_left + pad_right)) / term->cell_width; + const int new_rows = + (term->height - (pad_top + pad_bottom)) / term->cell_height; /* * Requirements for scrollback: @@ -4708,16 +4714,16 @@ render_resize(struct terminal *term, int width, int height, uint8_t opts) term->margins.left = total_x_pad / 2; term->margins.top = total_y_pad / 2; } else { - term->margins.left = pad_x; - term->margins.top = pad_y; + term->margins.left = pad_left; + term->margins.top = pad_top; } term->margins.right = total_x_pad - term->margins.left; term->margins.bottom = total_y_pad - term->margins.top; - xassert(term->margins.left >= pad_x); - xassert(term->margins.right >= pad_x); - xassert(term->margins.top >= pad_y); - xassert(term->margins.bottom >= pad_y); + xassert(term->margins.left >= pad_left); + xassert(term->margins.right >= pad_right); + xassert(term->margins.top >= pad_top); + xassert(term->margins.bottom >= pad_bottom); if (new_cols == old_cols && new_rows == old_rows) { LOG_DBG("grid layout unaffected; skipping reflow");