summaryrefslogtreecommitdiff
path: root/bar/bar.go
diff options
context:
space:
mode:
authorhhvn <dev@hhvn.uk>2023-08-14 14:04:41 +0100
committerhhvn <dev@hhvn.uk>2023-08-14 14:47:38 +0100
commit79a80fbbf278e0eb743a79e2c0c252817537434f (patch)
tree7704e968ec2071a931140b43f6ec2ea61ed1d527 /bar/bar.go
parent0543020038edb5de1162863e7401ea36f8a8584c (diff)
Creating and destroying the windows
Diffstat (limited to 'bar/bar.go')
-rw-r--r--bar/bar.go200
1 files changed, 200 insertions, 0 deletions
diff --git a/bar/bar.go b/bar/bar.go
new file mode 100644
index 0000000..6ab7f35
--- /dev/null
+++ b/bar/bar.go
@@ -0,0 +1,200 @@
+package bar
+
+import (
+ "fmt"
+ "container/list"
+
+ "hhvn.uk/hbspbar/common"
+ "hhvn.uk/hbspbar/bspc"
+
+ "github.com/jezek/xgb"
+ "github.com/jezek/xgb/xproto"
+
+ "github.com/jezek/xgbutil"
+ "github.com/jezek/xgbutil/icccm"
+ "github.com/jezek/xgbutil/ewmh"
+)
+
+var conf = struct {
+ H uint
+ Bg uint32
+ Fg uint32
+ Sel uint32
+ Urg uint32
+} { 16,
+ 0xff050a10,
+ 0xffeeeeee,
+ 0xff1b364b,
+ 0xff90222b }
+
+var bars *list.List
+
+type bar struct {
+ X *xgb.Conn
+ Xu *xgbutil.XUtil
+ Scr *xproto.ScreenInfo
+ Mon *bspc.Monitor
+ w xproto.Window
+}
+
+func (b *bar) Init() error {
+ var err error
+
+ b.w, err = xproto.NewWindowId(b.X)
+ if err != nil {
+ return common.Perror("xproto.NewWindowId", err)
+ }
+
+ 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.CwBackPixel|xproto.CwEventMask, []uint32{
+ conf.Bg,
+ xproto.EventMaskStructureNotify })
+
+ class := icccm.WmClass{"hbspbar", "hbspbar"}
+ icccm.WmClassSet(b.Xu, b.w, &class)
+
+ ewmh.WmWindowTypeSet(b.Xu, b.w, []string{"_NET_WM_WINDOW_TYPE_DOCK"})
+ ewmh.WmStateSet(b.Xu, b.w, []string{"_NET_WM_STATE_STICKY", "_NET_WM_STATE_ABOVE"})
+
+ err = xproto.MapWindowChecked(b.X, b.w).Check()
+ if err != nil {
+ return common.Perror("xproto.MapWindow", err)
+ }
+
+ go b.Mon.TopPadding(conf.H)
+
+ return nil
+}
+
+func (b *bar) Destroy() {
+ b.Mon.TopPadding(0)
+}
+
+type eventwrap struct {
+ Ev xgb.Event
+ Err error
+}
+
+// External interface
+type Handle struct {
+ Create chan int
+ Destroy chan int
+ NewState chan *bspc.State
+ Err chan error
+}
+
+func Init(state *bspc.State) (*Handle, error) {
+ bars = list.New()
+
+ x, err := xgb.NewConn()
+ if err != nil { return nil, err }
+
+ xu, err := xgbutil.NewConnXgb(x)
+ if err != nil { return nil, err }
+
+ setup := xproto.Setup(x)
+ screen := setup.DefaultScreen(x)
+
+ var h Handle
+ h.Create = make(chan int)
+ h.Destroy = make(chan int)
+ h.NewState = make(chan *bspc.State)
+ h.Err = make(chan error)
+
+ events := make(chan *eventwrap)
+
+ go func() { for {
+ ev, err := x.WaitForEvent()
+ w := eventwrap{ev, err}
+ events <- &w
+
+ select {
+ case <- events: return
+ default:
+ }
+ }}()
+
+ go func() {
+ defer func() { events <- nil }()
+
+ for {
+ select {
+ case e := <- events:
+ if e.Ev == nil && e.Err == nil {
+ h.Err <- fmt.Errorf("X connection clossed")
+ return
+ }
+
+ if e.Err != nil {
+ common.Perror("x.WaitForEvents", err)
+ continue
+ }
+
+ switch e.Ev.(type) {
+ case xproto.DestroyNotifyEvent:
+ h.Err <- fmt.Errorf("Window destroyed")
+ return
+ }
+ case id := <- h.Destroy:
+ destroy(id)
+ case id := <- h.Create:
+ if err := create(x, xu, screen, state.GetMon(id)); err != nil {
+ h.Err <- fmt.Errorf("Couldn't create window: %s\n", err)
+ return
+ }
+ case state := <- h.NewState:
+ for e := bars.Front(); e != nil; e = e.Next() {
+ v := e.Value.(*bar)
+ v.Mon = state.GetMon(v.Mon.ID)
+ }
+ default:
+ }
+ }
+ }()
+
+ return &h, nil
+}
+
+func create(x *xgb.Conn, xu *xgbutil.XUtil,
+ scr *xproto.ScreenInfo, m *bspc.Monitor) (error) {
+ var b bar
+
+ b.X = x
+ b.Xu = xu
+ b.Scr = scr
+ b.Mon = m
+
+ if err := b.Init(); err != nil {
+ return err
+ }
+
+ bars.PushBack(&b)
+ return nil
+}
+
+func destroy(monid int) (bool) {
+ var next *list.Element
+
+ for e := bars.Front(); e != nil; e = next {
+ next = e.Next()
+ v := e.Value.(*bar)
+
+ /* 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()
+ bars.Remove(e)
+ if monid != -1 { return true }
+ }
+ }
+
+ if monid == -1 { return true }
+ return false
+}
+
+func Cleanup() {
+ destroy(-1)
+}