hbspbar

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

commit ec83d2780491159c4425ee1a5816c2bd4d6e6245
parent 0e385d244de19900df25f1c88f29c3cece6106cb
Author: hhvn <dev@hhvn.uk>
Date:   Sat, 30 Dec 2023 14:16:56 +0000

Make bar run state.GetMon itself

Diffstat:
Mbar/bar.go | 88++++++++++++++++++++++++++++++++++++++++++++-----------------------------------
Mbspc/bspc.go | 9++++++---
Mmain.go | 22+++++++++++-----------
Mstatus/02-cpu.go | 5+++--
4 files changed, 69 insertions(+), 55 deletions(-)

diff --git a/bar/bar.go b/bar/bar.go @@ -18,29 +18,31 @@ import ( var bars map[int]*bar type bar struct { - Mon *bspc.Monitor + id int w *drw.Window i *image.RGBA drawing sync.Mutex } -func (b *bar) init() error { - var err error +func (b *bar) init(state *bspc.State) error { + mon, err := b.getmon(state) + if err != nil { return err } - go b.Mon.TopPadding(config.H) + go mon.TopPadding(config.H) - geom := b.Mon.Rectangle + geom := mon.Rectangle b.w, err = drw.WindowCreate(geom.X, geom.Y, geom.Width, config.H) if err != nil { return err } - b.i = image.NewRGBA(b.rect()) + rect := image.Rect(0, 0, int(mon.Rectangle.Width), int(config.H)) + b.i = image.NewRGBA(rect) return nil } -func (b *bar) rect() image.Rectangle { - return image.Rect(0, 0, int(b.Mon.Rectangle.Width), int(config.H)) +func (b *bar) getmon(state *bspc.State) (*bspc.Monitor, error) { + return state.GetMon(b.id) } func (b *bar) drawText(x int, col color.Color, text string) (int, error) { @@ -51,15 +53,21 @@ 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() { +func (b *bar) draw(state *bspc.State) { var bg color.Color var filled bool b.drawing.Lock() + defer b.drawing.Unlock() + + mon, err := b.getmon(state) + if err != nil { + return + } // Dimensions of drawing space cx := 0 - w := int(b.Mon.Rectangle.Width) + w := int(mon.Rectangle.Width) h := int(config.H) @@ -67,10 +75,10 @@ func (b *bar) draw() { b.drawRect(0, 0, w, h, config.Bg, true) // Monitor - montext := b.Mon.Name + montext := mon.Name monw := 6 + drw.TextWidth(montext) + 8 - if b.Mon.Focused { + if mon.Focused { bg = config.Sel } else { bg = config.UnselMon @@ -82,16 +90,16 @@ func (b *bar) draw() { // Desktops boxw := 4 - ds := len(b.Mon.Desktops) + ds := len(mon.Desktops) dw := 4 + (4 + boxw + 2 + 3) * ds + 5 for i := 0; i < ds; i++ { - dw += drw.TextWidth(b.Mon.Desktops[i].Name) + dw += drw.TextWidth(mon.Desktops[i].Name) } cx += 4 for i := 0; i < ds; i++ { - d := b.Mon.Desktops[i] + d := mon.Desktops[i] cx += 5 @@ -110,7 +118,7 @@ func (b *bar) draw() { } status.Mutex.Lock() - cx = int(b.Mon.Rectangle.Width) - 6 + cx = int(mon.Rectangle.Width) - 6 for i := len(status.Status) - 1; i >= 0; i -= 1 { s, ok := status.Status[i] if ok { @@ -121,10 +129,10 @@ func (b *bar) draw() { cx += config.StatusPad cx -= 6 - b.drawRect(cx, 0, int(b.Mon.Rectangle.Width) - cx, int(config.H), + b.drawRect(cx, 0, int(mon.Rectangle.Width) - cx, int(config.H), config.Status, true) - cx = int(b.Mon.Rectangle.Width) - 6 + cx = int(mon.Rectangle.Width) - 6 for i := len(status.Status) - 1; i >= 0; i -= 1 { s, ok := status.Status[i] if ok { @@ -138,13 +146,12 @@ func (b *bar) draw() { status.Mutex.Unlock() b.w.Paint(b.i) - - b.drawing.Unlock() } -func (b *bar) destroy() { - if (b.Mon != nil) { - b.Mon.TopPadding(0) +func (b *bar) destroy(state *bspc.State) { + mon, _ := b.getmon(state) + if (mon != nil) { + mon.TopPadding(0) } } @@ -156,6 +163,8 @@ type handle struct { Err chan error } +var cleanup chan bool + var Handle handle func init() { @@ -166,6 +175,7 @@ func init() { Handle.Destroy = make(chan int) Handle.NewState = make(chan *bspc.State) Handle.Err = make(chan error) + cleanup = make(chan bool) go func() { defer func() { @@ -195,7 +205,7 @@ func init() { // default: // } case id := <- Handle.Destroy: - bars[id].destroy() + bars[id].destroy(state) delete(bars, id) case id := <- Handle.Create: if state == nil { @@ -203,48 +213,48 @@ func init() { return } if _, ok := bars[id]; ok { break } - if err := create(state.GetMon(id)); err != nil { + if err := create(state, id); err != nil { Handle.Err <- fmt.Errorf("Couldn't create window: %s\n", err) return } + case <- cleanup: + for _, b := range bars { + go b.destroy(state) + } + return case <- status.Updated: for _, b := range bars { - go b.draw() + go b.draw(state) } case state = <- Handle.NewState: for _, b := range bars { - b.Mon = state.GetMon(b.Mon.ID) - if b.Mon != nil { - go b.draw() - } + go b.draw(state) } } } }() } -func create(m *bspc.Monitor) (error) { +func create(state *bspc.State, id int) (error) { var b bar - b.Mon = m - b.i = nil + b.id = id + b.i = nil - if err := b.init(); err != nil { + if err := b.init(state); err != nil { return err } - go b.draw() + go b.draw(state) if bars == nil { bars = make(map[int]*bar) } - bars[b.Mon.ID] = &b + bars[b.id] = &b return nil } func Cleanup() { - for _, b := range bars { - b.destroy() - } + cleanup <- true } diff --git a/bspc/bspc.go b/bspc/bspc.go @@ -5,6 +5,7 @@ import ( "fmt" "time" "bufio" + "errors" "strings" "os/exec" "encoding/json" @@ -12,19 +13,21 @@ import ( "hhvn.uk/hbspbar/common" ) +var ErrMonNotFound = errors.New("monitor not found") + type State struct { Monitors []*Monitor FocusedMonitorID int } -func (s *State) GetMon(id int) (*Monitor) { +func (s *State) GetMon(id int) (*Monitor, error) { for _, m := range s.Monitors { if m.ID == id { - return m + return m, nil } } - return nil + return nil, ErrMonNotFound } type Monitor struct { diff --git a/main.go b/main.go @@ -2,14 +2,14 @@ package main // import "hhvn.uk/hbspbar" import ( "os" + "os/signal" "strings" "syscall" - "os/signal" - "hhvn.uk/hbspbar/common" - "hhvn.uk/hbspbar/drw" "hhvn.uk/hbspbar/bar" "hhvn.uk/hbspbar/bspc" + "hhvn.uk/hbspbar/common" + "hhvn.uk/hbspbar/drw" ) func main() { @@ -20,7 +20,7 @@ func main() { syscall.SIGTERM) defer bar.Cleanup() - + if drw.InitErr != nil { common.Error("Couldn't initialize X: %s\n", drw.InitErr) return @@ -39,20 +39,20 @@ func main() { for { select { - case s := <- signals: + case s := <-signals: common.Error("%s\n", s) return - case err := <- bar.Handle.Err: + case err := <-bar.Handle.Err: common.Error("%s\n", err) return - case err := <- bspc.Handle.EvErr: + case err := <-bspc.Handle.EvErr: common.Error("Couldn't read event: %s\n", err) return - case event := <- bspc.Handle.Event: + case event := <-bspc.Handle.Event: if strings.HasPrefix(event.Name, "monitor_") { id, err := common.Intify(event.Tokens[0]) if err == nil { - switch (event.Name) { + switch event.Name { case "monitor_add": case "monitor_geometry": bar.Handle.Create <- id @@ -61,10 +61,10 @@ func main() { } } } - case err := <- bspc.Handle.StErr: + case err := <-bspc.Handle.StErr: common.Error("Couldn't load bspwm state: %s\n", err) return - case <- bspc.Handle.StateUpdate: + case <-bspc.Handle.StateUpdate: bar.Handle.NewState <- bspc.Handle.State } } diff --git a/status/02-cpu.go b/status/02-cpu.go @@ -37,8 +37,9 @@ func getcpus(c chan [][]string, e chan error) { c <- ret - // This is only used if ret == nil - e <- errors.New("apparently this computer has no cores") + if ret == nil { + e <- errors.New("apparently this computer has no cores") + } } func cpu(name string) error {