summaryrefslogtreecommitdiff
path: root/bar/bar.go
diff options
context:
space:
mode:
Diffstat (limited to 'bar/bar.go')
-rw-r--r--bar/bar.go146
1 files changed, 123 insertions, 23 deletions
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 }
}