crates/veilvoice-gui/src/soundbar.rs
veilvoice-gui · 779 lines · read the source here · or on GitHub
The animated mark: a row of bars that rise and fall.
The same mark as the website
website/index.html draws this in CSS as .veil -- a row of <span>s with @keyframes pulse taking each between 16% and 82% of the height over 1.9 seconds, each with its own delay so the row ripples rather than pumping in unison. The left half is drawn in the accent colour and the right half in the "veiled" secondary, which is the product in one picture and matches the icon.
This is that, in egui, with the same period, the same height range and the same delays. Two front-ends showing visibly different marks would be worse than one showing none.
Why it is drawn rather than rendered from a GIF
An animated image would be a committed binary blob, and this project's artwork is generated from source precisely so that nothing in the repository has to be taken on trust. Sixty lines of shape drawing is auditable; a GIF is not.
Cost when it is switched off
With motion disabled the bars are drawn once, at rest, and no repaint is requested. That is the part that matters: an "off" switch that still schedules a frame every 16 ms has turned the animation off visually and left the battery cost behind. The caller decides by passing a Motion, and the only way to animate is to ask for it.
Cost when it is switched on, which is the interesting one
Motion is on by default, and this is the only thing in the application that moves without being asked to. Everything else draws when something happens. So with the default settings, on the file tab, doing nothing, the window was redrawing about sixty times a second for ever, and it was this: measured with Context::repaint_causes, which named line 117 of this file as the reason for 559 of 566 frames.
An animated logo is not worth a permanently busy window, and two of the costs are ones a user actually notices rather than ones a profiler does. A laptop lid left open at this screen never lets the processor idle. And a window being dragged is competing, every frame, with a full redraw it did not need, which is what "it lags when I move it" is made of.
So the mark now moves in the three circumstances where somebody can see it moving, and rests otherwise:
- Not while the window is unfocused. A background window is still.
- Not while the window is being moved or resized. Detected from the window's own rectangle changing between frames, and resumed a quarter of a second after it stops. This is the drag case specifically.
- Not faster than the window's frame target.
crate::paceowns that number: the display's own rate by default, or whatever was chosen in Settings. This module carried its own constant of twenty a second, which made the mark the slowest-moving thing on any modern display and was the judder people reported (finding F-179).
Resting is not the same as resetting. Freezing at the midpoint would make every click into another window snap the row flat, so a paused mark holds the shape it had when it paused and picks the cycle up from there.
In plain words
The little row of bars in the corner that rises and falls.
It is the same mark the website uses, drawn rather than loaded as a picture, so it takes the colours of whichever scheme you have chosen.
It stops moving if your system is set to reduce motion. That setting is a request from somebody who has a reason for making it, and animation that ignores it is animation that makes an application unusable for them.
WHAT THIS FILE CONTAINS
779 lines defining 6 functions (2 public), 0 types and 5 constants. Everything below is read out of the source, so it cannot disagree with the code.
What happens when it runs. These are the ways in: public, and nothing else in this file calls them, so they are what an outside caller reaches first.
badgeline 196 · Draw the mark at size, returning the response so it can carry a tooltip.
reachesdraw,animation_clock,colour_for,height_fraction,window_is_settled
WHAT CALLS WHAT
The functions this file defines, and the calls between them. An edge means the callee's name appears, called, inside the caller's body. This is a syntactic reading, not a type-resolved one.
The same graph as Mermaid source
%%{init: {"theme":"base","themeVariables":{"background":"#1a1b26","primaryColor":"#1f2335","primaryTextColor":"#c0caf5","primaryBorderColor":"#7aa2f7","secondaryColor":"#16161e","tertiaryColor":"#16161e","lineColor":"#737aa2","textColor":"#c0caf5","mainBkg":"#1f2335","nodeBorder":"#7aa2f7","clusterBkg":"#16161e","clusterBorder":"#2f3549","fontFamily":"ui-monospace, SFMono-Regular, Consolas, monospace","fontSize":"14px"}}}%%
flowchart TD
n_height_fraction["height_fraction<br/>line 103"]
n_window_is_settled["window_is_settled<br/>line 130"]
n_animation_clock["animation_clock<br/>line 168"]
n_badge(["badge<br/>line 196"])
n_draw["draw<br/>line 228"]
n_colour_for["colour_for<br/>line 281"]
n_badge --> n_draw
n_draw --> n_animation_clock
n_draw --> n_colour_for
n_draw --> n_height_fraction
n_draw --> n_window_is_settled
click n_height_fraction href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-gui/src/soundbar.rs#L103" "open the source"
click n_window_is_settled href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-gui/src/soundbar.rs#L130" "open the source"
click n_animation_clock href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-gui/src/soundbar.rs#L168" "open the source"
click n_badge href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-gui/src/soundbar.rs#L196" "open the source"
click n_draw href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-gui/src/soundbar.rs#L228" "open the source"
click n_colour_for href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-gui/src/soundbar.rs#L281" "open the source"
classDef entry fill:#1f2335,stroke:#7aa2f7,color:#c0caf5
class n_badge entry
classDef api fill:#1f2335,stroke:#7dcfff,color:#c0caf5
class n_draw api
classDef helper fill:#1f2335,stroke:#bb9af7,color:#c0caf5
class n_height_fraction,n_window_is_settled,n_animation_clock,n_colour_for helper
This site loads no third-party script, so it cannot run Mermaid; the diagram above is the same nodes and edges drawn by the generator instead. GitHub renders the source below directly.
ITEMS
| Item | Line | Documentation |
|---|---|---|
PERIOD const | 80 | Seconds for one full rise and fall. |
SETTLE const | 88 | How long the window must hold still before the mark starts moving again. |
DELAYS const | 93 | Per-bar phase offsets in seconds, matching the animation-delay values in website/index.html. |
MIN_FRACTION const | 98 | Height as a fraction of the available box, matching 16% and 82%. |
MAX_FRACTION const | 99 | |
height_fraction fn | 103 | How far along its cycle a bar is, in 0..=1, eased the way CSS ease-in-out eases. |
window_is_settled fn | 130 | Whether the window is holding still enough for the mark to move. |
animation_clock fn | 168 | The clock the bars are drawn against, which is not always the real one. |
badge pub fn | 196 | Draw the mark at size, returning the response so it can carry a tooltip. |
draw pub fn | 228 | Draw the mark at size, returning the response so it can carry a tooltip. |
colour_for fn | 281 | The left half in the accent colour, the right in the veiled secondary -- the same split the website and the icon use. |