hbspbar

[WIP] bspwm status bar
git clone https://hhvn.uk/hbspbar
git clone git://hhvn.uk/hbspbar
Log | Files | Refs

commit 0064d3f30cb971cde1ec8214224497a158bc2649
parent 50e8e54ec6f7342fdf0a90c8e3cd652e4a1ac8b9
Author: hhvn <dev@hhvn.uk>
Date:   Sat, 27 Jan 2024 15:17:35 +0000

Each bar has drawing goroutine. Mutexes eliminated.

Diffstat:
Mbar/bar.go | 54+++++++++++++++++++++++++++++++++++-------------------
Mstatus/00-status.go | 49++++++++++++++++++++++++-------------------------
2 files changed, 59 insertions(+), 44 deletions(-)

diff --git a/bar/bar.go b/bar/bar.go @@ -2,7 +2,6 @@ package bar // import "hhvn.uk/hbspbar/bar" import ( "fmt" - "sync" "image" "errors" "image/color" @@ -17,11 +16,16 @@ import ( var bars map[int]*bar +type drawinfo struct { + State *bspc.State + Blocks *status.Blocks +} + type bar struct { id int w *drw.Window i *image.RGBA - drawing sync.Mutex + redraw chan drawinfo } func (b *bar) init(state *bspc.State) error { @@ -38,10 +42,26 @@ func (b *bar) init(state *bspc.State) error { rect := image.Rect(0, 0, int(mon.Rectangle.Width), int(config.H)) b.i = image.NewRGBA(rect) + b.redraw = make(chan drawinfo, 20) + + go func(){ + for d := range b.redraw { + // Gobble up excess redraws + gobble: for { + select { + case d = <- b.redraw: + default: break gobble + } + } + + b.draw(d) + } + }() + return nil } -func (b *bar) getmon(state *bspc.State) (*bspc.Monitor, error) { +func (b bar) getmon(state *bspc.State) (*bspc.Monitor, error) { return state.GetMon(b.id) } @@ -53,12 +73,12 @@ func (b *bar) drawRect(x, y, w, h int, c color.Color, fill bool) { drw.DrawRect(b.i, x, y, w, h, c, fill) } -func (b *bar) draw(state *bspc.State) { +func (b bar) draw(d drawinfo) { var bg color.Color var filled bool - b.drawing.Lock() - defer b.drawing.Unlock() + state := d.State + blocks := d.Blocks mon, err := b.getmon(state) if err != nil { @@ -117,10 +137,9 @@ func (b *bar) draw(state *bspc.State) { cx += ax + 2 } - status.Mutex.Lock() cx = int(mon.Rectangle.Width) - 6 - for i := len(status.Status) - 1; i >= 0; i -= 1 { - s, ok := status.Status[i] + for i := blocks.Len() - 1; i >= 0; i -= 1 { + s, ok := blocks.Get(i) if ok { cx -= s.W cx -= config.StatusPad @@ -133,8 +152,8 @@ func (b *bar) draw(state *bspc.State) { config.Status, true) cx = int(mon.Rectangle.Width) - 6 - for i := len(status.Status) - 1; i >= 0; i -= 1 { - s, ok := status.Status[i] + for i := blocks.Len() - 1; i >= 0; i -= 1 { + s, ok := blocks.Get(i) if ok { cx -= s.W @@ -143,7 +162,6 @@ func (b *bar) draw(state *bspc.State) { cx -= config.StatusPad } } - status.Mutex.Unlock() b.w.Paint(b.i) } @@ -170,8 +188,8 @@ var Handle handle var finalstate *bspc.State = nil func init() { - var state *bspc.State - state = nil + var state *bspc.State = nil + var blocks *status.Blocks = nil Handle.Create = make(chan int) Handle.Destroy = make(chan int) @@ -218,14 +236,14 @@ func init() { Handle.Err <- fmt.Errorf("Couldn't create window: %s\n", err) return } - case <- status.Updated: + case blocks = <- status.NewBlocks: for _, b := range bars { - go b.draw(state) + b.redraw <- drawinfo{state, blocks} } case state = <- Handle.NewState: finalstate = state for _, b := range bars { - go b.draw(state) + b.redraw <- drawinfo{state, blocks} } } } @@ -242,8 +260,6 @@ func create(state *bspc.State, id int) (error) { return err } - go b.draw(state) - if bars == nil { bars = make(map[int]*bar) } diff --git a/status/00-status.go b/status/00-status.go @@ -3,7 +3,6 @@ package status // import "hhvn.uk/hbspbar/status" import ( "fmt" "time" - "sync" "image" "image/color" @@ -12,32 +11,38 @@ import ( "hhvn.uk/hbspbar/common" ) -var Status map[int]*status -var Mutex sync.Mutex -var statusid map[string]int -var Updated chan bool -var updates chan *status +var NewBlocks = make(chan *Blocks) +var updates = make(chan *status) +var statusid = make(map[string]int) -const ( -) +type Blocks map[int]*status + +func (b *Blocks) Len() int { + return len(map[int]*status(*b)) +} + +func (b *Blocks) Get(i int) (s *status, ok bool) { + s, ok = (map[int]*status(*b))[i] + return +} + +type status struct { + Name string + I *image.RGBA + W int +} func init() { - Status = make(map[int]*status) - statusid = make(map[string]int) - Updated = make(chan bool) - updates = make(chan *status) + status := make(map[int]*status) go func() { - for { - s := <- updates - + for s := range updates { id := statusid[s.Name] - Mutex.Lock() - Status[id] = s - Mutex.Unlock() + status[id] = s - Updated <- true + b := Blocks(status) + NewBlocks <- &b } }() } @@ -52,12 +57,6 @@ func register(name string) { statusid[name] = nid } -type status struct { - Name string - I *image.RGBA - W int -} - func newUpdate(name string) (*status) { var s status