aboutsummaryrefslogtreecommitdiffstats

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.