diff options
| author | user <user@clank> | 2026-08-22 18:30:18 +0200 |
|---|---|---|
| committer | user <user@clank> | 2026-08-22 18:30:18 +0200 |
| commit | f5ce221ee853d430113063cb85c43bbea078818e (patch) | |
| tree | 691a77196558e0d5f15aaed6dab889abc725a12e | |
| parent | slosh: put-away panes are miniature pane frames (diff) | |
| download | slosh-f5ce221ee853d430113063cb85c43bbea078818e.tar.gz slosh-f5ce221ee853d430113063cb85c43bbea078818e.tar.xz slosh-f5ce221ee853d430113063cb85c43bbea078818e.zip | |
slosh: paint the padding ring, so a float cannot be seen through
A tiled pane sits on a cleared screen, so unpainted padding looked fine by
accident; a float sits on whatever was composited under it, and every
unpainted cell let that show through. draw_frame now fills the ring between
border and contents with exactly what screen_clear leaves, and a suspended
pane's never-composed content rect gets the same treatment.
| -rw-r--r-- | src/app_draw.c | 25 | ||||
| -rw-r--r-- | tests/test_float.py | 27 |
2 files changed, 52 insertions, 0 deletions
diff --git a/src/app_draw.c b/src/app_draw.c index 24cc50d..04e8264 100644 --- a/src/app_draw.c +++ b/src/app_draw.c @@ -573,6 +573,25 @@ static void draw_frame(app_t *a, screen_t *s, node_t *leaf) { screen_text(s, x1, y, vbar, fg, NO_COLOR, attrs); } + /* The padding ring between the border and the contents, painted blank + * rather than left alone. A tiled pane sits on a cleared screen, so leaving + * it unpainted used to look the same by accident — but a float sits on + * whatever was composited under it, and every unpainted cell lets that show + * through. Blank-with-no-colour is exactly what screen_clear leaves, so a + * tiled pane looks as it always did, and with no padding configured the + * ring is empty and this writes nothing. */ + { + rect_t c = leaf->content; + for (uint16_t y = (uint16_t)(r.y + 1); y < y1; y++) + for (uint16_t x = (uint16_t)(r.x + 1); x < x1; x++) { + if (x >= c.x && x < c.x + c.w && y >= c.y && y < c.y + c.h) { + x = (uint16_t)(c.x + c.w - 1); /* jump past the contents */ + continue; + } + screen_text(s, x, y, " ", NO_COLOR, NO_COLOR, 0); + } + } + /* A pane that rang, marked just inside its corner: the same place on every * pane, whatever its title is doing. */ if (CFG.bell_indicator && pane_bell(leaf->pane) && r.w > 4) @@ -1360,6 +1379,12 @@ static void draw_cb(node_t *n, void *ud) { /* Falls through to the shader pass rather than returning: a pane that has * not started is a state you can want to colour, and its label is the only * content it has. */ + /* Nothing has ever composed into this content rect, so paint it blank + * first — for the same reason draw_frame paints the padding ring: a + * floating suspended pane must not show what is under it. */ + for (uint16_t y = n->content.y; y < n->content.y + n->content.h; y++) + for (uint16_t x = n->content.x; x < n->content.x + n->content.w; x++) + screen_text(d->s, x, y, " ", NO_COLOR, NO_COLOR, 0); /* The pane exists, is laid out, and has run nothing. Say what it would. */ const char *label = pane_label(n->pane); char line[256]; diff --git a/tests/test_float.py b/tests/test_float.py index 1745ef7..b9e3233 100644 --- a/tests/test_float.py +++ b/tests/test_float.py @@ -912,6 +912,32 @@ def test_the_key_and_the_palette_both_run_it(): check("running it floats the pane", len(floats(s)) == 1, str(here(s))) +def test_the_padding_ring_hides_what_is_under_it(): + """A float's padding is painted blank, not left unpainted. A tiled pane + sits on a cleared screen, so an unpainted ring looked fine by accident — + a float sits on whatever was composited below it, and every unpainted + cell let that show through.""" + conf = cfg("padding 2\n") + filler = ["/bin/sh", "-c", 'printf "X%.0s" $(seq 1 4000); stty raw -echo; cat'] + with Session(filler, cols=90, rows=24, config=conf) as s: + s.settle(50) + s.api("split", dir="cols") + s.settle(50) + s.api("float") + s.settle(100) + fl = floats(s)[0] + snap = s.snapshot() + # the ring between the border and the content, on a content row and + # on a padding row: all of it over the X-filled backdrop, all blank + row = snap.line(fl["content_y"]) + left = row[fl["x"] + 1 : fl["content_x"]] + right = row[fl["content_x"] + fl["content_w"] : fl["x"] + fl["w"] - 1] + top = snap.line(fl["y"] + 1)[fl["x"] + 1 : fl["x"] + fl["w"] - 1] + check("the left padding is blank", set(left) <= {" "}, repr(left)) + check("the right padding is blank", set(right) <= {" "}, repr(right)) + check("a full padding row is blank", set(top) <= {" "}, repr(top)) + + if __name__ == "__main__": test_floating_lifts_a_pane_out_of_the_layout() test_the_overlap_belongs_to_the_float() @@ -946,4 +972,5 @@ if __name__ == "__main__": test_a_layout_of_only_floats_self_heals() test_a_float_is_not_a_drop_target() test_the_key_and_the_palette_both_run_it() + test_the_padding_ring_hides_what_is_under_it() sys.exit(report()) |
