summaryrefslogtreecommitdiff
path: root/bar
diff options
context:
space:
mode:
Diffstat (limited to 'bar')
-rw-r--r--bar/bar.go146
-rw-r--r--bar/x.go79
2 files changed, 202 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 }
}
diff --git a/bar/x.go b/bar/x.go
new file mode 100644
index 0000000..4d77bfd
--- /dev/null
+++ b/bar/x.go
@@ -0,0 +1,79 @@
+package bar
+
+import (
+ "os"
+ "image"
+
+ "hhvn.uk/hbspbar/common"
+
+ "github.com/jezek/xgbutil/xgraphics"
+ "github.com/BurntSushi/freetype-go/freetype/truetype"
+)
+
+func getFont(path string) (*truetype.Font, error) {
+ read, err := os.Open(path)
+ if err != nil {
+ return nil, common.Perror("os.Open", err)
+ }
+
+ font, err := xgraphics.ParseFont(read)
+ if err != nil {
+ return nil, common.Perror("xgraphics.ParseFont", err)
+ }
+
+ return font, nil
+}
+
+func int2BGRA(argb uint32) (xgraphics.BGRA) {
+ return xgraphics.BGRA{
+ B: uint8( argb & 0x000000ff),
+ G: uint8((argb & 0x0000ff00) >> 8),
+ R: uint8((argb & 0x00ff0000) >> 16),
+ A: uint8((argb & 0xff000000) >> 24) }
+}
+
+func (b *bar) rect() image.Rectangle {
+ return image.Rect( 0, 0,
+ int(b.Mon.Rectangle.Width), int(conf.H))
+}
+
+func (b *bar) drawReInit() {
+ if b.i != nil {
+ b.i.Destroy()
+ }
+
+ b.i = xgraphics.New(b.Xu, b.rect())
+}
+
+func (b *bar) drawText(x int, col uint32, text string) (int, error) {
+ nx, _, err := b.i.Text(x, conf.FontYPad,
+ int2BGRA(col), conf.FontSize, font, text)
+ return nx - x, err
+}
+
+func (b *bar) textWidth(str string) int {
+ return len(str) * b.tw
+}
+
+func pointInRect(px, py, x, y, w, h int) bool {
+ if px >= x && px <= x + w && py >= x && py <= y + h {
+ return true
+ } else {
+ return false
+ }
+}
+
+func (b *bar) drawRect(x, y, w, h int, c uint32, fill bool) {
+ col := int2BGRA(c)
+
+ var ix, iy int
+
+ for ix = x; ix < x + w; ix++ {
+ for iy = y; iy < y + h; iy++ {
+ if fill || ix == x || ix == x + w - 1 ||
+ iy == y || iy == y + h - 1 {
+ b.i.Set(ix, iy, col)
+ }
+ }
+ }
+}