diff options
| author | Paul Buetow <paul@buetow.org> | 2026-02-16 22:53:17 +0200 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-02-16 22:53:17 +0200 |
| commit | 6798b669464d828c241554647b4fff68a62ca91d (patch) | |
| tree | 706fc2da37b27b89649afe650ec699170191ecb1 /internal/display/display.go | |
| parent | 971928faff0c100ef591c2d0e92e94b9f46ae71a (diff) | |
Add global I/O avg line (hotkey i) and m/n hotkey aliases
Add a pink 1px line drawn from the top showing mean iowait+IRQ+softIRQ
across all hosts, toggled with hotkey i and persistable to ~/.loadbarsrc.
Also add m as alias for 2 (memory toggle) and n as alias for 3 (network
toggle) for easier single-hand operation.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Diffstat (limited to 'internal/display/display.go')
| -rw-r--r-- | internal/display/display.go | 61 |
1 files changed, 53 insertions, 8 deletions
diff --git a/internal/display/display.go b/internal/display/display.go index 649f636..fe5340e 100644 --- a/internal/display/display.go +++ b/internal/display/display.go @@ -21,8 +21,9 @@ const smoothFactor = 0.12 // blend toward target each frame; lower = smoother // runState holds mutable state across the display loop (hotkeys, window size, smoothed data). type runState struct { - showAvgLine bool - showCores bool + showAvgLine bool + showIOAvgLine bool + showCores bool showMem bool showNet bool extended bool @@ -39,8 +40,9 @@ type runState struct { // newRunState builds initial run state from config. func newRunState(cfg *config.Config, winW, winH int32) *runState { return &runState{ - showAvgLine: cfg.ShowAvgLine, - showCores: cfg.ShowCores, + showAvgLine: cfg.ShowAvgLine, + showIOAvgLine: cfg.ShowIOAvgLine, + showCores: cfg.ShowCores, showMem: cfg.ShowMem, showNet: cfg.ShowNet, extended: cfg.Extended, @@ -143,10 +145,10 @@ func handleKey(sym sdl.Keycode, window *sdl.Window, cfg *config.Config, state *r case sdl.K_1: state.showCores = !state.showCores fmt.Println("==> Toggled show cores:", state.showCores) - case sdl.K_2: + case sdl.K_2, sdl.K_m: state.showMem = !state.showMem fmt.Println("==> Toggled show mem:", state.showMem) - case sdl.K_3: + case sdl.K_3, sdl.K_n: state.showNet = !state.showNet fmt.Println("==> Toggled show net:", state.showNet) case sdl.K_e: @@ -155,6 +157,9 @@ func handleKey(sym sdl.Keycode, window *sdl.Window, cfg *config.Config, state *r case sdl.K_g: state.showAvgLine = !state.showAvgLine fmt.Println("==> Toggled global avg line:", state.showAvgLine) + case sdl.K_i: + state.showIOAvgLine = !state.showIOAvgLine + fmt.Println("==> Toggled global I/O avg line:", state.showIOAvgLine) case sdl.K_a: cfg.CPUAverage++ fmt.Println("==> CPU average samples:", cfg.CPUAverage) @@ -179,6 +184,7 @@ func handleKey(sym sdl.Keycode, window *sdl.Window, cfg *config.Config, state *r printHotkeys() case sdl.K_w: cfg.ShowAvgLine = state.showAvgLine + cfg.ShowIOAvgLine = state.showIOAvgLine cfg.ShowCores = state.showCores cfg.ShowMem = state.showMem cfg.ShowNet = state.showNet @@ -226,7 +232,7 @@ func barBounds(winW int32, numBars int, barIndex int) (x int32, width int32) { } // drawFrame updates state from snapshot, clears if layout changed, and draws all bars. -// When showAvgLine is enabled, a global average CPU line is drawn on top. +// When showAvgLine/showIOAvgLine are enabled, global average lines are drawn on top. func drawFrame(renderer *sdl.Renderer, src stats.Source, cfg *config.Config, state *runState) { snap := src.Snapshot() numBars := countBars(snap, state.showCores, state.showMem, state.showNet) @@ -238,6 +244,9 @@ func drawFrame(renderer *sdl.Renderer, src stats.Source, cfg *config.Config, sta if state.showAvgLine { drawGlobalAvgLine(renderer, snap, state) } + if state.showIOAvgLine { + drawGlobalIOAvgLine(renderer, snap, state) + } } func countBars(snap map[string]*stats.HostStats, showCores, showMem, showNet bool) int { @@ -312,6 +321,42 @@ func drawGlobalAvgLine(renderer *sdl.Renderer, snap map[string]*stats.HostStats, renderer.FillRect(&sdl.Rect{X: 0, Y: lineY, W: state.winW, H: 1}) } +// drawGlobalIOAvgLine draws a 1px pink horizontal line from the top of the window +// at the Y position corresponding to the mean I/O overhead (iowait + IRQ + softIRQ, +// indices 4, 5, 6 in the smoothed CPU array) across all hosts. +func drawGlobalIOAvgLine(renderer *sdl.Renderer, snap map[string]*stats.HostStats, state *runState) { + var totalIO float64 + var hostCount int + for _, host := range sortedHosts(snap) { + h := snap[host] + if h == nil { + continue + } + key := host + ";cpu" + s := state.smoothedCPU[key] + if s == nil { + continue + } + // Sum iowait (4) + IRQ (5) + softIRQ (6) for I/O overhead + totalIO += (*s)[4] + (*s)[5] + (*s)[6] + hostCount++ + } + if hostCount == 0 { + return + } + avgPct := totalIO / float64(hostCount) + // Draw from top: lineY = percentage of window height from the top + lineY := int32(avgPct * float64(state.winH) / 100) + if lineY < 0 { + lineY = 0 + } + if lineY >= state.winH { + lineY = state.winH - 1 + } + renderer.SetDrawColor(constants.Pink.R, constants.Pink.G, constants.Pink.B, 255) + renderer.FillRect(&sdl.Rect{X: 0, Y: lineY, W: state.winW, H: 1}) +} + // drawHostBars draws CPU, mem, and net bars for one host and advances barIndex. func drawHostBars(renderer *sdl.Renderer, h *stats.HostStats, host string, cfg *config.Config, state *runState, numBars int, barIndex *int) { winH := state.winH @@ -564,7 +609,7 @@ func drawMemBarSmoothed(renderer *sdl.Renderer, h *stats.HostStats, smoothed *st } func printHotkeys() { - fmt.Println("=> Hotkeys: 1=cores 2=mem 3=net e=extended g=avg line h=help q=quit w=write config a/y=cpu avg d/c=net avg f/v=link scale arrows=resize") + fmt.Println("=> Hotkeys: 1=cores 2/m=mem 3/n=net e=extended g=avg line i=io avg h=help q=quit w=write config a/y=cpu avg d/c=net avg f/v=link scale arrows=resize") } |
