1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
|
# Chrome shaders
A frame is a rect too, so it is a pass too. `where="chrome"` on any entry in
`shaders` or in a `states` block runs that pass over a pane's **frame** (border,
padding, title, buttons) instead of its contents.
```kdl
states {
// a bell nobody has answered: a quarter-second flash, then gone
bell { tint where="chrome" channel="fg" color="#ffcc00" amount="(since < 250) * 255" }
}
```
Nothing else changes: same shaders, same `amount`, same
[expressions](shaders.md#strength-as-an-expression), same chain order. One new
word.
## Positions are the whole frame's
`x`/`y` are counted from the frame's top-left corner, with `cols`/`rows` the size
of the pane's rect, not of one side. One pass over the whole ring, so an effect
can travel round a border instead of restarting at every corner.
For anything that _travels_, though, the coordinate you want is distance along
the ring, which the language can work out. Clockwise from the top-left:
```
(y == 0 ? x : x == cols-1 ? cols - 1 + y
: y == rows-1 ? 2 * cols + rows - 3 - x : 2 * cols + 2 * rows - 4 - y)
```
There is no way to name a subexpression, so the formula is written out in full,
which is why a small effect is a long line.
Thirteen of them are ready to paste in
`contrib/chrome`:
a shine running round the border, a sine comet with softer shoulders, marching
ants, a standing wave, drifting sparkles, ripples leaving a corner in both
directions, etc.
## A border that says something
Depending on a pane's [state](config.md#pane-states), we can visually communicate
through it's chrome:
```kdl
states {
// a dead pane's frame breathes red until you deal with it
dead { tint where="chrome" channel="fg" color="#ff0033" amount="abs(t/8%510-255)" }
// one that has not started yet is outlined, not filled
suspended { tint where="chrome" channel="fg" color="#8a8a95" amount=160 }
// and the panes you are not in recede, frame and contents together
unfocused { dim amount=60; dim where="chrome" channel="fg" amount=90 }
}
```
`since` is what makes a _flash_ possible: it is how long the pane has been in
this state, where `t` only knows what time it is. The `bell` state ends when you
look at the pane, because that is what answering a bell is. :-)
## Animation costs a clock
Anything that reads `t` or `since` asks the session to keep painting, at
`anim_ms` (50ms, so 20fps) and only while such a pass is actually on screen.
`anim_ms 0` turns the clock off, which leaves an animated shader advancing only
when something else causes a frame.
|