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 `foot` and `footclient`), allowing you to set a custom toplevel
tag. The compositor must implement the new `xdg-toplevel-tag-v1` tag. The compositor must implement the new `xdg-toplevel-tag-v1`
Wayland protocol ([#2212][2212]). Wayland protocol ([#2212][2212]).
* `pad` option now supports 4-directional padding format:
`RIGHTxTOPxLEFTxBOTTOM` (e.g., `20x10x20x10`).
[2212]: https://codeberg.org/dnkl/foot/issues/2212 [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")) { else if (streq(key, "pad")) {
unsigned x, y; unsigned x, y, t, r, b, l;
char mode[64] = {0}; 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; enum center_when center = CENTER_NEVER;
if (ret == 3) { if (ret == 5) {
if (strcasecmp(mode, "center") == 0) if (strcasecmp(mode, "center") == 0)
center = CENTER_ALWAYS; center = CENTER_ALWAYS;
else if (strcasecmp(mode, "center-when-fullscreen") == 0) else if (strcasecmp(mode, "center-when-fullscreen") == 0)
@ -958,20 +957,38 @@ parse_section_main(struct context *ctx)
center = CENTER_MAXIMIZED_AND_FULLSCREEN; center = CENTER_MAXIMIZED_AND_FULLSCREEN;
else else
center = CENTER_INVALID; 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( 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|"
"center-when-fullscreen|" "center-when-fullscreen|"
"center-when-maximized-and-fullscreen])"); "center-when-maximized-and-fullscreen])");
return false; return false;
} }
conf->pad_x = x; conf->pad_top = t;
conf->pad_y = y; conf->pad_right = r;
conf->center_when = ret == 2 ? CENTER_NEVER : center; conf->pad_bottom = b;
conf->pad_left = l;
conf->center_when = (ret == 4 || ret == 2) ? CENTER_NEVER : center;
return true; return true;
} }
@ -3381,8 +3398,10 @@ config_load(struct config *conf, const char *conf_path,
.width = 700, .width = 700,
.height = 500, .height = 500,
}, },
.pad_x = 0, .pad_top = 0,
.pad_y = 0, .pad_right = 0,
.pad_bottom = 0,
.pad_left = 0,
.center_when = CENTER_MAXIMIZED_AND_FULLSCREEN, .center_when = CENTER_MAXIMIZED_AND_FULLSCREEN,
.resize_by_cells = true, .resize_by_cells = true,
.resize_keep_grid = true, .resize_keep_grid = true,

View file

@ -230,8 +230,10 @@ struct config {
uint32_t height; uint32_t height;
} size; } size;
unsigned pad_x; unsigned pad_top;
unsigned pad_y; unsigned pad_right;
unsigned pad_bottom;
unsigned pad_left;
enum center_when center_when; enum center_when center_when;
bool resize_by_cells; 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] _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 - `_XxY_` adds _at least_:
sides, and Y pixels on the top and bottom sides. - 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 When no centering is specified, the grid content is anchored to
the top left corner. I.e. if the window manager forces an odd 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-size-chars=<COLSxROWS>
# initial-window-mode=windowed # initial-window-mode=windowed
# pad=0x0 center-when-maximized-and-fullscreen # pad=0x0 center-when-maximized-and-fullscreen
# pad=0x0x0x0 center-when-maximized-and-fullscreen
# resize-by-cells=yes # resize-by-cells=yes
# resize-keep-grid=yes # resize-keep-grid=yes
# resize-delay-ms=100 # 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; new_height = rows * term->cell_height;
/* Include any configured padding */ /* Include any configured padding */
new_width += 2 * term->conf->pad_x * term->scale; new_width += (term->conf->pad_left + term->conf->pad_right) * term->scale;
new_height += 2 * term->conf->pad_y * term->scale; new_height += (term->conf->pad_top + term->conf->pad_bottom) * term->scale;
/* Round to multiples of scale */ /* Round to multiples of scale */
new_width = round(term->scale * round(new_width / term->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 */ /* Padding */
const int max_pad_x = (width - min_width) / 2; const int max_pad_x = (width - min_width) / 2;
const int max_pad_y = (height - min_height) / 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_left = min(max_pad_x, scale * term->conf->pad_left);
const int pad_y = min(max_pad_y, scale * term->conf->pad_y); 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 && if (is_floating &&
(opts & RESIZE_BY_CELLS) && (opts & RESIZE_BY_CELLS) &&
term->conf->resize_by_cells) term->conf->resize_by_cells)
{ {
/* If resizing in cell increments, restrict the width and height */ /* 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))); 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))); 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; int old_rows = term->rows;
/* Screen rows/cols after resize */ /* Screen rows/cols after resize */
const int new_cols = (term->width - 2 * pad_x) / term->cell_width; const int new_cols =
const int new_rows = (term->height - 2 * pad_y) / term->cell_height; (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: * 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.left = total_x_pad / 2;
term->margins.top = total_y_pad / 2; term->margins.top = total_y_pad / 2;
} else { } else {
term->margins.left = pad_x; term->margins.left = pad_left;
term->margins.top = pad_y; term->margins.top = pad_top;
} }
term->margins.right = total_x_pad - term->margins.left; term->margins.right = total_x_pad - term->margins.left;
term->margins.bottom = total_y_pad - term->margins.top; term->margins.bottom = total_y_pad - term->margins.top;
xassert(term->margins.left >= pad_x); xassert(term->margins.left >= pad_left);
xassert(term->margins.right >= pad_x); xassert(term->margins.right >= pad_right);
xassert(term->margins.top >= pad_y); xassert(term->margins.top >= pad_top);
xassert(term->margins.bottom >= pad_y); xassert(term->margins.bottom >= pad_bottom);
if (new_cols == old_cols && new_rows == old_rows) { if (new_cols == old_cols && new_rows == old_rows) {
LOG_DBG("grid layout unaffected; skipping reflow"); LOG_DBG("grid layout unaffected; skipping reflow");