From 7adfd6e5c641f7543fcf87e4c558579dc652fdf7 Mon Sep 17 00:00:00 2001 From: hhvn Date: Tue, 22 Aug 2023 12:50:03 +0100 Subject: Drawing desktops --- bar/bar.go | 146 +++++++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 123 insertions(+), 23 deletions(-) (limited to 'bar/bar.go') diff --git a/bar/bar.go b/bar/bar.go index 6ab7f35..aa2432d 100644 --- a/bar/bar.go +++ b/bar/bar.go @@ -2,6 +2,7 @@ package bar import ( "fmt" + "sync" "container/list" "hhvn.uk/hbspbar/common" @@ -13,33 +14,54 @@ import ( "github.com/jezek/xgbutil" "github.com/jezek/xgbutil/icccm" "github.com/jezek/xgbutil/ewmh" + "github.com/jezek/xgbutil/xgraphics" + + "github.com/BurntSushi/freetype-go/freetype/truetype" ) var conf = struct { - H uint - Bg uint32 - Fg uint32 - Sel uint32 - Urg uint32 -} { 16, + H uint + Bg uint32 + Bg2 uint32 + Bg3 uint32 + Fg uint32 + FgDark uint32 + Sel uint32 + Urg uint32 + Font string + FontSize float64 + FontYPad int +} { 17, 0xff050a10, + 0xff0c1726, + 0xff14283c, 0xffeeeeee, + 0xff444444, 0xff1b364b, - 0xff90222b } + 0xff90222b, + "/usr/share/fonts/TTF/DejaVuSansMono.ttf", + 11.0, 1 } var bars *list.List +var font *truetype.Font type bar struct { - X *xgb.Conn - Xu *xgbutil.XUtil - Scr *xproto.ScreenInfo - Mon *bspc.Monitor - w xproto.Window + X *xgb.Conn + Xu *xgbutil.XUtil + Scr *xproto.ScreenInfo + Mon *bspc.Monitor + w xproto.Window + i *xgraphics.Image + tw, th int + tbpad int + drawing sync.Mutex } -func (b *bar) Init() error { +func (b *bar) init() error { var err error + go b.Mon.TopPadding(conf.H) + b.w, err = xproto.NewWindowId(b.X) if err != nil { return common.Perror("xproto.NewWindowId", err) @@ -48,7 +70,7 @@ func (b *bar) Init() error { geom := b.Mon.Rectangle xproto.CreateWindow(b.X, b.Scr.RootDepth, b.w, b.Scr.Root, int16(geom.X), int16(geom.Y), uint16(geom.Width), uint16(conf.H), 0, - xproto.WindowClassInputOutput, b.Scr.RootVisual, + xproto.WindowClassInputOutput, b.Scr.RootVisual, xproto.CwBackPixel|xproto.CwEventMask, []uint32{ conf.Bg, xproto.EventMaskStructureNotify }) @@ -64,12 +86,81 @@ func (b *bar) Init() error { return common.Perror("xproto.MapWindow", err) } - go b.Mon.TopPadding(conf.H) + b.drawReInit() + b.tw, b.th, _ = b.i.Text(0, 0, int2BGRA(conf.Fg), conf.FontSize, font, "X") + b.tbpad = (int(conf.H) - b.th) / 2 return nil } -func (b *bar) Destroy() { +func (b *bar) draw() { + var bg uint32 + var filled bool + + b.drawing.Lock() + b.drawReInit() + + // Dimensions of drawing space + cx := 0 + w := int(b.Mon.Rectangle.Width) + h := int(conf.H) + + + // Draw background + b.drawRect(0, 0, w, h, conf.Bg, true) + + // Monitor + montext := b.Mon.Name + monw := 6 + b.textWidth(montext) + 8 + + if b.Mon.Focused { + bg = conf.Sel + } else { + bg = conf.Bg2 + } + + b.drawRect(cx, 0, monw, h, bg, true) + b.drawText(cx + 6, conf.Fg, montext) + cx += monw + + // Desktops + boxw := 4 + ds := len(b.Mon.Desktops) + dw := 4 + (4 + boxw + 2 + 3) * ds + 5 + + for i := 0; i < ds; i++ { + dw += b.textWidth(b.Mon.Desktops[i].Name) + } + + cx += 4 + for i := 0; i < ds; i++ { + d := b.Mon.Desktops[i] + + cx += 5 + + if d.Focused { + bg = conf.Sel + } else { + bg = conf.FgDark + } + + filled = d.Root != nil + + b.drawRect(cx, 3, boxw, h - 7, bg, filled) + cx += boxw + 2 + ax, _ := b.drawText(cx, conf.Fg, d.Name) + cx += ax + 2 + } + cx += 5 + + b.i.XSurfaceSet(b.w) + b.i.XDraw() + b.i.XPaint(b.w) + + b.drawing.Unlock() +} + +func (b *bar) destroy() { b.Mon.TopPadding(0) } @@ -95,6 +186,9 @@ func Init(state *bspc.State) (*Handle, error) { xu, err := xgbutil.NewConnXgb(x) if err != nil { return nil, err } + font, err = getFont(conf.Font) + if err != nil { return nil, err } + setup := xproto.Setup(x) screen := setup.DefaultScreen(x) @@ -105,20 +199,22 @@ func Init(state *bspc.State) (*Handle, error) { h.Err = make(chan error) events := make(chan *eventwrap) + xstop := make(chan bool, 1) go func() { for { ev, err := x.WaitForEvent() w := eventwrap{ev, err} - events <- &w select { - case <- events: return + case <- xstop: + return default: + events <- &w } }}() go func() { - defer func() { events <- nil }() + defer func() { xstop <- true }() for { select { @@ -137,6 +233,7 @@ func Init(state *bspc.State) (*Handle, error) { case xproto.DestroyNotifyEvent: h.Err <- fmt.Errorf("Window destroyed") return + default: } case id := <- h.Destroy: destroy(id) @@ -149,12 +246,12 @@ func Init(state *bspc.State) (*Handle, error) { for e := bars.Front(); e != nil; e = e.Next() { v := e.Value.(*bar) v.Mon = state.GetMon(v.Mon.ID) + go v.draw() } - default: } } }() - + return &h, nil } @@ -166,11 +263,14 @@ func create(x *xgb.Conn, xu *xgbutil.XUtil, b.Xu = xu b.Scr = scr b.Mon = m + b.i = nil - if err := b.Init(); err != nil { + if err := b.init(); err != nil { return err } + go b.draw() + bars.PushBack(&b) return nil } @@ -185,7 +285,7 @@ func destroy(monid int) (bool) { /* A monid of -1 means that we're doing the bar.Cleanup schermoodle today */ if monid == -1 || monid > 0 && v.Mon.ID == int(monid) { - v.Destroy() + v.destroy() bars.Remove(e) if monid != -1 { return true } } -- cgit v1.2.3