support four-sided padding (top/right/bottom/left)

This commit is contained in:
pi66 2025-12-19 12:17:29 +01:00
parent 4e96780eef
commit e133122147
6 changed files with 70 additions and 29 deletions

View file

@ -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

View file

@ -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,

View file

@ -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;

View file

@ -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

View file

@ -29,6 +29,7 @@
# initial-window-size-chars=<COLSxROWS>
# 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

View file

@ -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");