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.
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, 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, we can visually communicate through it's chrome:
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.