From e9c66c7bba3e4f848c567f3ebe570b7cbfbcac94 Mon Sep 17 00:00:00 2001 From: Camille Scholtz Date: Wed, 26 Dec 2018 21:24:04 +0100 Subject: [PATCH] Get rid of dirty sleep hack --- README.md | 2 -- bar.go | 23 +++++++++++++++++++++++ block.go | 4 +++- blocks.go | 31 +++++++++++++++++++------------ main.go | 25 +++++++++---------------- popup.go | 27 +++++++++++++-------------- 6 files changed, 67 insertions(+), 45 deletions(-) diff --git a/README.md b/README.md index 4558fd3..6de577e 100644 --- a/README.md +++ b/README.md @@ -56,8 +56,6 @@ example `block.bg = "#FF0000"` or `block.txt = "Hello World!"` and executing ## TODO -* Create some kind of easy to use init function for blocks (instead of - the `if !init` stuff I use at the moment). * Add popups. diff --git a/bar.go b/bar.go index 3c99bae..a248737 100644 --- a/bar.go +++ b/bar.go @@ -42,6 +42,10 @@ type Bar struct { // A channel where the block should be send to to once its ready to be // redrawn. redraw chan *Block + + // A channel where a boolean should be send once a block has initizalized, + // notifying that the next block can intialize. + ready chan bool } func initBar(x, y, w, h int, fp string) (*Bar, error) { @@ -202,3 +206,22 @@ func (bar *Bar) draw(block *Block) error { return nil } + +func (bar *Bar) initBlocks(blocks []func()) { + bar.ready = make(chan bool) + + for _, f := range blocks { + go f() + <-bar.ready + } + + close(bar.ready) +} + +func (bar *Bar) listen() { + for { + if err := bar.draw(<-bar.redraw); err != nil { + panic(err) + } + } +} diff --git a/block.go b/block.go index 053ad9a..d99ba0f 100644 --- a/block.go +++ b/block.go @@ -63,6 +63,9 @@ func (bar *Bar) initBlock(name, txt string, w int, align rune, xoff int, bg, // Store the block in map. bar.block.Store(name, block) + // Draw block. + bar.redraw <- block + return block } @@ -72,7 +75,6 @@ func (block *Block) diff(txt string) bool { if block.txt == txt { return false } - block.txt = txt return true } diff --git a/blocks.go b/blocks.go index 9e564d6..3058d5e 100644 --- a/blocks.go +++ b/blocks.go @@ -20,7 +20,9 @@ import ( func (bar *Bar) clockFun() { // Initialize block. block := bar.initBlock("clock", "?", 800, 'a', 0, "#445967", "#CCCCCC") - bar.redraw <- block + + // Notify that the next block can be initialized. + bar.ready <- true for { // Compose block text. @@ -39,7 +41,9 @@ func (bar *Bar) clockFun() { func (bar *Bar) musicFun() { // Initialize block. block := bar.initBlock("music", "» ", 660, 'r', -12, "#3C4F5B", "#CCCCCC") - bar.redraw <- block + + // Notify that the next block can be initialized. + bar.ready <- true // Connect to MPD. c, err := mpd.Dial("tcp", ":6600") @@ -62,20 +66,20 @@ func (bar *Bar) musicFun() { }() // Show popup on clicking the left mouse button. - /*block.actions["button1"] = func() { + block.actions["button1"] = func() { if block.popup == nil { var err error block.popup, err = bar.initPopup(1920-304-29, 29, 304, 148, "#3C4F5B", "#CCCCCC") if err != nil { - log.Print(err) + panic(err) } //popup.draw() } else { block.popup = block.popup.destroy() } - }*/ + } // Toggle play/pause on clicking the right mouse button. block.actions["button3"] = func() { @@ -138,7 +142,9 @@ func (bar *Bar) musicFun() { func (bar *Bar) todoFun() { // Initialize block. block := bar.initBlock("todo", "¢", 29, 'c', 0, "#5394C9", "#FFFFFF") - bar.redraw <- block + + // Notify that the next block can be initialized. + bar.ready <- true // Find `.todo` file. hd, err := homedir.Dir() @@ -192,10 +198,11 @@ func (bar *Bar) todoFun() { func (bar *Bar) windowFun() { // Initialize blocks. - blockIcon := bar.initBlock("window", "º", 21, 'l', 12, "#37BF8D", "#FFFFFF") + bar.initBlock("window", "º", 21, 'l', 12, "#37BF8D", "#FFFFFF") block := bar.initBlock("window", "?", 200, 'c', 0, "#37BF8D", "#FFFFFF") - bar.redraw <- blockIcon - bar.redraw <- block + + // Notify that the next block can be initialized. + bar.ready <- true // TODO: This doesn't check for window title changes. xevent.PropertyNotifyFun(func(_ *xgbutil.XUtil, ev xevent. @@ -245,9 +252,9 @@ func (bar *Bar) workspaceFun() { "#FFFFFF") blockSRC := bar.initBlock("src", "¾ src", 70, 'l', 10, "#5394C9", "#FFFFFF") - bar.redraw <- blockWWW - bar.redraw <- blockIRC - bar.redraw <- blockSRC + + // Notify that the next block can be initialized. + bar.ready <- true // Change active workspace on clicking on one of the blocks. blockWWW.actions["button1"] = func() { diff --git a/main.go b/main.go index 6f10fad..e9ed1f3 100644 --- a/main.go +++ b/main.go @@ -2,7 +2,6 @@ package main import ( "path" - "time" homedir "github.com/mitchellh/go-homedir" ) @@ -19,20 +18,14 @@ func main() { } // Run bar block functions. - runBlock(bar.windowFun) - runBlock(bar.workspaceFun) - runBlock(bar.clockFun) - runBlock(bar.musicFun) - runBlock(bar.todoFun) + go bar.initBlocks([]func(){ + bar.windowFun, + bar.workspaceFun, + bar.clockFun, + bar.musicFun, + bar.todoFun, + }) - for { - if err := bar.draw(<-bar.redraw); err != nil { - panic(err) - } - } -} - -func runBlock(f func()) { - go f() - time.Sleep(time.Millisecond * 10) + // Listen for redraw events. + bar.listen() } diff --git a/popup.go b/popup.go index 595c732..eb3626e 100644 --- a/popup.go +++ b/popup.go @@ -26,24 +26,23 @@ type Popup struct { redraw chan *Popup } -func (bar *Bar) initPopup(x, y, w, h int, bg, fg string) (*Popup, - error) { +func (bar *Bar) initPopup(x, y, w, h int, bg, fg string) (*Popup, error) { popup := new(Popup) var err error - // Create a window for the bar. This window listens to button - // press events in order to respond to them. + // Create a window for the bar. This window listens to button press events + // in order to respond to them. popup.win, err = xwindow.Generate(bar.xu) if err != nil { return nil, err } - popup.win.Create(bar.xu.RootWin(), x, y, w, h, xproto.CwBackPixel| - xproto.CwEventMask, 0x000000, xproto.EventMaskButtonPress) + popup.win.Create(bar.xu.RootWin(), x, y, w, h, xproto.CwBackPixel|xproto. + CwEventMask, 0x000000, xproto.EventMaskButtonPress) // EWMH stuff. - // TODO: `WmStateSet` and `WmDesktopSet` are basically here to - // keep OpenBox happy, can I somehow remove them and just use - // `_NET_WM_WINDOW_TYPE_DOCK` like I can with WindowChef? + // TODO: `WmStateSet` and `WmDesktopSet` are basically here to keep OpenBox + // happy, can I somehow remove them and just use `_NET_WM_WINDOW_TYPE_DOCK` + // like I can with WindowChef? if err := ewmh.WmWindowTypeSet(bar.xu, popup.win.Id, []string{ "_NET_WM_WINDOW_TYPE_DOCK"}); err != nil { return nil, err @@ -52,12 +51,10 @@ func (bar *Bar) initPopup(x, y, w, h int, bg, fg string) (*Popup, "_NET_WM_STATE_STICKY"}); err != nil { return nil, err } - if err := ewmh.WmDesktopSet(bar.xu, popup.win.Id, ^uint( - 0)); err != nil { + if err := ewmh.WmDesktopSet(bar.xu, popup.win.Id, ^uint(0)); err != nil { return nil, err } - if err := ewmh.WmNameSet(bar.xu, popup.win.Id, "melonbar"); err != - nil { + if err := ewmh.WmNameSet(bar.xu, popup.win.Id, "melonbar"); err != nil { return nil, err } @@ -69,7 +66,9 @@ func (bar *Bar) initPopup(x, y, w, h int, bg, fg string) (*Popup, // Create the bar image. popup.img = xgraphics.New(bar.xu, image.Rect(0, 0, w, h)) - popup.img.XSurfaceSet(popup.win.Id) + if err := popup.img.XSurfaceSet(popup.win.Id); err != nil { + panic(err) + } popup.img.XDraw() popup.w = w