summaryrefslogtreecommitdiff
path: root/src/surface.zig
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-09-28 13:42:03 -0300
committerGabriel Schneider <[email protected]>2026-10-01 00:12:14 -0300
commit29e734cf91ffe5f4cca8b40a54aad91fff464a82 (patch)
tree384056b816943fcff95a45d42cd1fd4be1fe6f1d /src/surface.zig
parente11048c20a50b67841e648a4d5ddd7490bc9c9b7 (diff)
downloadpardes-29e734cf91ffe5f4cca8b40a54aad91fff464a82.tar.gz
pardes-29e734cf91ffe5f4cca8b40a54aad91fff464a82.zip
Place every part of the frame once, before painting it
draw.place builds the Surface's region list at the head of render: the page; each pane's grip, tag rows, body, rail with its thumb, and notice chips; each column's grip and tag; the workspace tag. The painters read their geometry from it instead of working it out again: the grid's notice chips and the notice layers share one chip rectangle, the rails (file, terminal, image, PDF page) paint the placed thumb (a native PDF measures its own into the region as it places its pages), and the body, tag, notice and column layers take their viewports from their regions. A collapsed pane places only its grip and tag. The column-move rail's one-cell clip of the layers under it is now a region field set in place, not a mutation of the built layers. No behaviour change; a test checks every region against the old geometry, the painted rail and the layer viewports across tag bottom, column tags, notices, a collapsed pane and a multi-line tag.
Diffstat (limited to 'src/surface.zig')
-rw-r--r--src/surface.zig57
1 files changed, 57 insertions, 0 deletions
diff --git a/src/surface.zig b/src/surface.zig
index eef787b4..b19c24c7 100644
--- a/src/surface.zig
+++ b/src/surface.zig
@@ -324,6 +324,51 @@ test "pixel attachment fit and pan do not invalidate cached pixels" {
try std.testing.expect(key.eql(place.cacheKey()));
}
+/// One part of the frame and where it is, placed once by `draw.place`
+/// before anything is painted: every painter and every shell reads the
+/// geometry here instead of working it out again. `rect` is in grid cells
+/// and is the hit-test geometry.
+pub const Region = struct {
+ pub const Kind = enum(u8) {
+ /// The frame-wide border fill every other part is painted over.
+ page,
+ /// A pane's grip: the mode mark at the head of its tag rows.
+ grip,
+ /// A pane's tag rows, right of its grip.
+ tag,
+ /// A pane's body, right of its rail: absent while it is collapsed.
+ body,
+ /// The scroll rail down a pane's left edge, beside its body.
+ rail,
+ /// A transient band over the body's top rows (a message, a prompt).
+ notice,
+ column_grip,
+ column_tag,
+ workspace_tag,
+ };
+ pub const none = std.math.maxInt(u8);
+
+ kind: Kind,
+ /// The pane slot, or the column, the part belongs to; `none` for the
+ /// page and the workspace tag.
+ owner: u8 = none,
+ serial: u32 = 0,
+ rect: layout.Rect,
+ /// The pane or column has the keyboard's focus.
+ active: bool = false,
+ /// A rail's thumb: rows from the rail's top, and how many. Zero rows is
+ /// a rail with no thumb (an image).
+ thumb_y: u16 = 0,
+ thumb_h: u16 = 0,
+ /// A notice's index in its pane's `notices`.
+ notice: u8 = 0,
+ /// Cells the column-move rail takes off the right edge while it runs
+ /// there: layers and pixel shells stop short of them, the grid does not.
+ clip: u16 = 0,
+};
+
+pub const MAX_REGIONS = 1 + MAX_PANES * (4 + panes.Pane.Notices.max) + pardes.MAX_COLS * 2 + 1;
+
/// The canonical interface: what a frame of pardes IS. The tty shell writes
/// these cells to vaxis one-to-one; the SDL shells rasterize them.
pub const Surface = struct {
@@ -337,6 +382,8 @@ pub const Surface = struct {
tag_layers: [MAX_TAG_LAYERS]TagLayer = @splat(.{}),
cols: u16 = 0,
rows: u16 = 0,
+ regions: [MAX_REGIONS]Region = undefined,
+ nregions: u16 = 0,
cells: []Cell = &.{},
/// bar: draw an insert-style thin cursor instead of the block
cursor: ?struct { x: u16, y: u16, bar: bool = false } = null,
@@ -357,6 +404,16 @@ pub const Surface = struct {
return &s.body_layers;
}
+ pub fn regionList(s: *const Surface) []const Region {
+ return s.regions[0..s.nregions];
+ }
+
+ /// The first part of `kind` that `owner` has: its tag, its rail.
+ pub fn region(s: *Surface, kind: Region.Kind, owner: usize) ?*Region {
+ for (s.regions[0..s.nregions]) |*r| if (r.kind == kind and r.owner == owner) return r;
+ return null;
+ }
+
pub fn panelTracks(s: *const Surface) []const animation.Track {
return s.panel_tracks[0..s.npanel_tracks];
}