summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
Diffstat (limited to 'docs')
-rw-r--r--docs/config.md20
-rw-r--r--docs/effects.md124
-rw-r--r--docs/render-pipeline.md4
-rw-r--r--docs/themes.md9
4 files changed, 150 insertions, 7 deletions
diff --git a/docs/config.md b/docs/config.md
index ebedc4d0..96281cd5 100644
--- a/docs/config.md
+++ b/docs/config.md
@@ -129,7 +129,7 @@ such a shell there when it is the column's only one and nobody has typed
into it (no scrollback, cursor still on the first prompt line), the boot's
placeholder giving its rows to the document. Bare `BootShell` flips it, as
bare `Placement` does: a setting that chooses among words (`on`/`off`
-switches, `Placement`, `BootShell`, `Crt`, `Lift`, `Motion`,
+switches, `Placement`, `BootShell`, `Crt`, `Bloom`, `Vignette`, `Grain`, `Lift`, `Motion`,
`ShaderAnimation`) steps to its
next value when written bare, as its word clicked in a tag does, and a value
it does not take is refused with the values it takes, which `/commands` also
@@ -144,7 +144,7 @@ colour whole by half way (graphical frontends slide it out from under the
tagline as it fades up; a terminal only fades it in), stays until the next key or click as it
always has, then lingers for `MessageLinger` milliseconds (default 800) before
it dissolves into the page. `MessageFall` (default 180) and `MessageDissolve`
-(default 300) set how long the fall and the dissolve take, also in
+(default 150: leaving is quicker than arriving) set how long the fall and the dissolve take, also in
milliseconds; each timing is at most 60000, and `Config` reports all three. `MessageLinger 0` with
`MessageAnimation off` restores the old behaviour, a message cleared by the
very input that follows it. An updated line on a row already showing one swaps
@@ -549,6 +549,20 @@ the chain empty the pass is bypassed. CRT works in linear light with restrained
scanlines, mask, bloom and vignette, and no curvature, so clicks land where
they are drawn.
+Three more bundled passes take the same levels, each off by default and
+each costing nothing while off:
+
+```text
+Bloom 2 the brightest ink glows a little (only what is brighter than
+ the page; a dual Kawase blur at half size and down)
+Vignette 2 the window's corners fall a little into shade
+Grain 2 the page's own ground takes a fine, still grain, like paper
+```
+
+None of them touches a tag, a grip, a notice or the cursor, and each is
+capped per theme so text and the selection keep their own contrast or 4.5
+(docs/effects.md).
+
The focused pane can stand off the page (SDL GUI, off by default):
```text
@@ -558,6 +572,8 @@ Lift auto a shadow on a light page; on a dark one the others recede
Lift off
InactiveDim 30 the unfocused panes' text fades 30% toward its ground
Motion smooth off, crisp, smooth (the default), bouncy or playful
+SelectionGlow on a soft halo of the selection's colour round it in the body,
+ fading in over 100 ms, never over a tag, a grip or the cursor
CursorBlink on the cursor blinks, solid while typing and half a second
after, eased at each edge, solid after 10 idle seconds
GripWidth 150 the grip's button and the scrollbar under it, percent of the
diff --git a/docs/effects.md b/docs/effects.md
index 08fd3d88..0e0ad51a 100644
--- a/docs/effects.md
+++ b/docs/effects.md
@@ -13,6 +13,19 @@ its text. A dim touches only the unfocused
panes, with the same floor, and the focused pane's text is never at less
contrast than theirs (tests in src/draw.zig).
+**Density.** A pixel shell draws every size given in pixels in logical
+pixels, `dp()` in gui.zig (SDL's window display scale, rounded, at least
+one; `PARDES_TEST_SCALE` forces one in a harness, and a test window is 1x
+otherwise): the rules (`rule_px`), the tag rule, the grip's ring and its
+dirty gap and mode bars, the rail's gap to the text and its minimum, the
+thumb's inset, the rim, a bar cursor's minimum width, underline and
+strikethrough thickness, the rule-grab margin, and the Crt's scanline and
+mask periods (`pardesScale`). Left as they are: what is measured in cells
+or the tagline (the rail's width, `rail_px` scaled with the tagline; Lift's
+blur and offsets; every motion, in cells), Shadertoy's iResolution,
+fragCoord and iMouse (the display's pixels, as ghostty's), and the pet and
+touch debug overlays.
+
Each effect of docs/render-pipeline.md §9 lands behind its own switch, off,
and is kept only after a feel review (§8.4): a frame series on the virtual
clock, a recording, and a verdict — keep, polish or drop — with one line of
@@ -24,6 +37,13 @@ why. The verdict is the user's.
| Ripple, Glitch | — | removed | live window | dropped by the user after a live look |
| G1 lift | `Lift shadow\|rim\|auto` (off), `InactiveDim <percent>` | opt-in until the focus-lift default is decided | lift-shots-2 (off, shadow, rim, auto on acme, dusk, forge); frame series + mp4 per Motion flavour | shadow on acme: keep as is. Round 1 dropped glow and surface (surface lowered the focused text's contrast) and made rim a hairline just above the focused tag (light on a dark page, shade on a light one). auto on a dark page recedes the others (InactiveDim 30) |
| G3 cursor | follows `Motion`; `CursorBlink on\|off` (on) | glide on by default through the default flavour (smooth); blink on (decision 6) | .scratch/render/cursor/cursor-flavours-grid.mp4 (and quarter speed), raw/<flavour>/<motion>/ | pending |
+| G4 bloom, vignette, grain | `Bloom`, `Vignette`, `Grain` `0..3` (off) | bundled post passes; none touches a tag, grip, notice or the cursor (pardesSpare); each capped per theme (pardesCap) | .scratch/render/{bloom,vignette,grain}/ (levels 0-3 on forge, dusk, acme; crops; mp4 stepping through the levels) | pending |
+| G5 lapis | `Theme lapis` (its `decor`) | a native theme with ornament: tag plaques with hard shadows inside their bands (the focused one striped), dots, rail checker, title shadow | .scratch/render/lapis/ (whole window at 1x and 2x, crops, a slide mp4) | pending |
+| G6 smooth scroll | follows `Motion` (on through the default smooth; `Motion off` lands at once) | a mouse wheel's notch glides, a touchpad follows the finger | .scratch/render/scroll/ (glide-<flavour>.mp4, quarter speed, strips) | pending |
+| G7 panel transitions | `PanelSlide`, `PanelZoom`, `PanelVertical`, `PanelDissolve` (off) with `Motion` | a moving pane casts a shadow; a retargeted move keeps its speed; the GUI's dissolve is a crossfade | .scratch/render/transitions/ (slide smooth, bouncy, retargeted; dissolve) | pending |
+| G8 notice chips | follows `Motion` and `Lift` | a notice floats in tier 4 on a lift (shadow) while Lift is on, drops in easing out and dissolves easing in, quicker than it came (150 ms against 180) | .scratch/render/notices/ (acme, forge) | pending |
+| G9 selection glow | `SelectionGlow on\|off` (off) | a soft halo of the selection's colour round each block of it in a body, fading in over 100 ms | .scratch/render/selection/ (forge, acme, lapis; lapis-glow-zoom.png) | pending |
+| G10 theme crossfade | always (a theme change) | the chrome's colours fade through OKLab, easing in and out (out when retargeted) | .scratch/render/crossfade/ (forge, lapis, acme cut short by dusk) | pending |
## Motion flavours
@@ -83,3 +103,107 @@ forge's text goes from 15.5:1 to 11.2:1 and dusk's from 6.4:1 to 4.8:1,
plainly quieter and still easy reading; at 10 forge barely moves (14.1:1).
On a light page the same percent bites far harder (acme: 7.0:1 at 10, the
4.5 floor at 30), which is why `auto` shades there instead of dimming.
+
+Notes on G4: the three are post passes, so each is a frame of cost only
+when it is in the chain. None moves (grain is still, by choice: moving
+grain would redraw every frame for a texture), so none asks for frames.
+The focus rule is kept by construction: the shell hands every pass the
+rectangles of the tags (with their grips), the column and workspace tags,
+the notices and the cursor, and a bundled pass leaves them as they are; its
+strength is capped per theme so the text on the page and the selection's
+text keep min(their contrast, 4.5) (Post.capsOf, tested over the native
+themes). Bloom takes only what is brighter than the page, so a light page
+does not bloom at all; its glow is a dual Kawase blur in float textures at
+half size and down (3 to 5 steps by level), within §8.2's 5%. The vignette
+is round, starts halfway to a corner and reaches 10, 18 and 28%. Grain is
+1.5, 3 and 5 of 255 on page-coloured pixels only, a logical pixel big.
+Found on the way: SDL GPU binds at most 4 KiB of a uniform block, so every
+Shadertoy colour after the palette (iBackgroundColor and on) read zero; the
+block is now cut in three with ghostty's names and order kept.
+
+Notes on G5: lapis (src/themes/lapis.zig) is 0x4200.cafe's lapis.css in
+pardes's chrome, drawn inside it (decision 1). The tags are the site's
+trail and title bars: every tag a plaque in its own band, framed in gold
+(2 px, the trail's border) with the trail's hard vermilion shadow (5 px)
+down and right, the frame and the shadow both inside the band's rows and
+columns, so no shadow reaches a body, a grip or the next pane; down, the
+shadow gets what the band's slack under the text leaves (a pixel or three
+at a tagline under the body's size, more at a larger one), to the right
+its full offset. The focused pane's plaque is the code window's title bar,
+gold and lapis stripes of 2 px, its words on plates of the focused ground
+(the words' cells stay opaque, the blanks between let the stripes show),
+so the focus indicator is plainer to see than any theme's tint, never
+less; the unfocused ones are plain. Column and workspace tags take the
+quieter object-label language: a 1 px frame and a 2 px shadow of vermilion
+toward the page. The plaques are decor drawn under their cells (a group's
+under range) with the cells blended premultiplied over them; blank tag
+cells on the tag's ground are see-through there. They need an opaque
+window: under WindowOpacity 100 the tags are plain. Also from the site:
+the colours (lapis-deep page, vellum text, gold names and rules,
+vermilion rubrics and tag rule, gold selection in lapis ink), the page's
+gold dot grid (22 px, #e8c46a22) on page-coloured cells only, fixed to the
+window; the dither frame's checker in the scroll track, anchored to its
+rail (the thumb solid gold); the titles' vermilion offset shadow under a
+file name's letters. Left out: Crimson Pro and Departure Mono, the
+ornaments, a decor crossfade (it snaps while the colours fade). The tty
+shows the colours alone: a tag row abuts its body and its neighbour, so
+there is no cell for a shadow row or column.
+
+Notes on G6: a mouse wheel's notch (SDL's whole-number step) scrolls the
+core by its lines at once, so keys and clicks act where the text is, and
+the picture follows on the Motion flavour's spring at half again its pace,
+critically damped whatever the flavour (text never passes its mark; §8.1),
+from its current speed, so notches in a row carry on without a stall. How
+far the rows moved is measured on the next frame against the last (a
+wrapped line's rows, a terminal's output), within a couple of rows' slack
+for the cursor's line and its number moving with the scroll; the rows that
+left are kept and drawn in the gap the lag opens, and a lag is never more
+than the body's height (a flick past that jumps). A touchpad's fractions
+keep moving the picture under the finger, as before; there is no momentum
+(SDL reports no finger lift on a wheel). The glide runs on the core's
+continuous path (Pardes.shell_continuous), so the shell draws every loop
+while it moves and a virtual clock moves with it; idle, it costs nothing.
+A PDF page scrolls as before. The test feed takes wheel events
+(ESC]777;mouse;wheel;<amount>;<x>;<y>BEL).
+
+Notes on G7: the geometry already followed the Motion flavour's spring
+(sxrrwplk); a move retargeted mid-way now carries its speed on
+(Track.launch, from the old move's speed along the new one's longest
+side), so a second Newcol during a slide bends the motion instead of
+stopping it dead. A pane that slides, zooms or rises stands off the page
+while it moves: a soft shadow as Lift's, at sin(pi x progress) of its
+strength (none as it sets out or lands), on the other panes' bodies and
+rails alone and under the same contrast ceiling, moving with the pane. The
+GUI's PanelDissolve is a crossfade: a changed cell's new form drawn whole,
+its old one over it at 1 - progress; the blend is in sRGB, not linear
+light (a two-colour mix in linear light needs both in one shader; open
+point 3). The tty keeps its per-cell swap. GUI golden 18-mid-transition
+changes (the slide's shadow at frame 6).
+
+Notes on G8: most of it was there: the drop eases out on the Motion
+flavour's spring (sxrrwplk), the dissolve eases in, and a notice floats in
+tier 4 with Lift's shadow at its fade while Lift is on, on the bodies
+alone. What G8 changed: leaving was slower than arriving (a 300 ms
+dissolve against a 180 ms fall); §8.1 wants leaving the quicker, in 100 to
+160 ms, so MessageDissolve now defaults to 150 (a test holds both bands).
+
+Notes on G9: the halo is Lift's soft kind in the selection's own colour,
+cast by each block of selected rows in a pane body (the rows that touch),
+with the block as its caster, so the selection itself is never touched;
+a cursor beside a block joins the caster, so it is never glowed over
+either. It stays on bodies (never a tag or a grip), is at most 22% (§8.2:
+coloured glows at most 25%) and less where the text round it would drop
+below min(its contrast, 4.5); it comes up over 100 ms with an ease-out
+(micro-feedback), on the core's continuous path, and is not drawn while
+panes move. The blocks are read from the cells painted in the theme's
+selection colour, a pixel shell's inference (§1.5, smell 4) until
+selections are regions.
+
+Notes on G10: a theme change already faded the chrome (tags, rules, grips,
+rails) over 10 frames (160 ms, in §8.1's 150 to 250 for a state change),
+mixing sRGB bytes linearly in time. Now each colour goes through OKLab, so
+a fade between two hues keeps its lightness instead of dipping dark and
+muddy, on a smooth ease-in-out; a change made mid-fade sets off from where
+it shows and eases out, so it moves at once instead of stalling. The page,
+its text and the syntax colours still change at once with the theme, as
+before: fading them would re-resolve every cell each frame.
diff --git a/docs/render-pipeline.md b/docs/render-pipeline.md
index 7c94fbea..b8f735d9 100644
--- a/docs/render-pipeline.md
+++ b/docs/render-pipeline.md
@@ -460,7 +460,9 @@ Mirror ghostty 1.3.2 (`zig-pkg/ghostty-*/src/renderer/shadertoy.zig`,
iBackgroundColor, iForegroundColor, iCursorColor, iCursorText,
iSelectionForegroundColor, iSelectionBackgroundColor; CURSORSTYLE_* defines;
`#define texture2D texture`), but SDL GPU bindings: `iChannel0` at set 2
- binding 0, the block at set 3 binding 0. `main()` calls
+ binding 0, the block at set 3 bindings 0 to 2 (cut before and after
+ iPalette: SDL GPU binds at most 4 KiB of a block, so one block left
+ the colours after the palette at zero until G4), pardes's own at 3. `main()` calls
`mainImage(_fragColor, gl_FragCoord.xy)`. Trap found: ghostty's Zig
`Uniforms` (shadertoy.zig:13) orders selection_background before
selection_foreground while its GLSL block orders Foreground before Background,
diff --git a/docs/themes.md b/docs/themes.md
index e028e806..38596819 100644
--- a/docs/themes.md
+++ b/docs/themes.md
@@ -102,13 +102,13 @@ so existing exported themes remain valid.
| Optional role | Purpose | When absent |
| --- | --- | --- |
-| `tag_active_bg`, `tag_active_fg` | Focused pane tag surface and text | `tag_bg`, `tag_fg` |
+| `tag_active_bg`, `tag_active_fg` | Focused pane tag surface and text; a surface closer than 1.25:1 to `tag_bg` is pushed further the way it already leans, as far as its text keeps its own contrast (or 4.5). Every dark native theme sets one | `tag_bg`, `tag_fg` |
| `tag_name_fg` | Filename or terminal `Tty` command tint | The corresponding normal or active tag foreground |
| `tag_active_name_fg` | Filename or terminal `Tty` tint in active tags | `tag_name_fg`, then the active tag foreground |
| `column_box` | Column grip while held, and its drag rail | `num` |
| `column_box_dim` | Column drag grip at rest, in every focus state | Equal mix of `column_box` and `tag_bg` |
-| `border` | Quiet separators | `scroll_track` |
-| `empty_col` | A column with no pane, under its tag (acme: white) | `border` |
+| `border` | Quiet separators; one that stands off the page by less than 1.5:1 (a dark rule on a near-black page) is lifted toward the text to 1.6:1. A theme with no page is judged against #121212 | `scroll_track` |
+| `empty_col` | A column with no pane, under its tag (acme: white) | `border`, as drawn |
| `lineno_active` | Restrained current line number foreground | `lineno` |
| `search_bg`, `search_fg` | Search matches, independent of selection | `sel_bg`, `sel_fg` |
| `diagnostic_error` | Error text | `fg`, or `tag_fg` for an inherited foreground |
@@ -118,9 +118,10 @@ so existing exported themes remain valid.
| `tag_sel_bg` | A tag's selection ground | `sel_bg` |
| `sweep_bg`, `sweep_fg` | Three triples each: the select, exec and look sweeps' ground and ink | `sel_bg` tinted toward `kw`, `str` and `num`, in `sel_fg` |
| `tag_rule` | The one-pixel rule between a pane's tag and its body, quieter than the `rule_px` rules between panes and columns | Halfway between `tag_bg` and the page the shell draws |
-| `rule_px` | Pixel shells: the width of the rules between columns, between panes stacked in a column, and under the workspace and column tags, in `border` (the rule between a tag and its body is always one pixel) | 2 |
+| `rule_px` | Pixel shells: the width of the rules between columns, between panes stacked in a column, and under the workspace and column tags, in `border` (the rule between a tag and its body is always one pixel), in logical pixels: doubled on a 2x display, as acme scales its Border | 2 |
| `box_border`, `box_dirty` | The grip is acme's button: `box` filled when focused, else a two-pixel ring of `box_border` round the tag's ground; `box_dirty` fills it inside either ring while its file is unsaved (a grid, which has no ring, shows a bold `*` on `box_dirty` in the grip's second cell) | `box_dim`; `diagnostic_warning`, then `num` |
| `rail_px` | Pixel shells: the scroll column's width, the grip's button over the scrollbar (thumb a pixel narrower), in pixels at a 17px tagline, scaled with it | 12, acme's Scrollwid |
+| `decor` | Pixel shells: a theme's ornament, drawn inside the chrome it has (lapis's): `page_dots` (a dot grid on the page's own ground, `page_dot_alpha` strong every `page_dot_px`), `rail_checker` (a checker in the scroll track, squares of `rail_checker_px`), `tag_border`, `tag_shadow`, `tag_stripe` (every tag a raised plaque inside its own band: a `tag_border_px` frame round its text and a hard `tag_shadow_px` shadow down and right, both inside the band's rows and columns; the focused pane's plaque striped `tag_stripe_px` with its words on plates of the tag's ground; column and workspace tags a quieter one; opaque windows only) and `title_shadow` (the file name's offset shadow, `title_shadow_px`), sizes in logical pixels. None of it touches a focus indicator | none |
Native palettes give filenames a distinct hue at approximately the same
brightness as the surrounding tag text. This also applies to output names