Get rid of dirty sleep hack

This commit is contained in:
Camille Scholtz 2018-12-26 21:24:04 +01:00
parent e4b37decfa
commit e9c66c7bba
6 changed files with 67 additions and 45 deletions

@ -56,8 +56,6 @@ example `block.bg = "#FF0000"` or `block.txt = "Hello World!"` and executing
## TODO ## 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. * Add popups.

23
bar.go

@ -42,6 +42,10 @@ type Bar struct {
// A channel where the block should be send to to once its ready to be // A channel where the block should be send to to once its ready to be
// redrawn. // redrawn.
redraw chan *Block 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) { func initBar(x, y, w, h int, fp string) (*Bar, error) {
@ -202,3 +206,22 @@ func (bar *Bar) draw(block *Block) error {
return nil 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)
}
}
}

@ -63,6 +63,9 @@ func (bar *Bar) initBlock(name, txt string, w int, align rune, xoff int, bg,
// Store the block in map. // Store the block in map.
bar.block.Store(name, block) bar.block.Store(name, block)
// Draw block.
bar.redraw <- block
return block return block
} }
@ -72,7 +75,6 @@ func (block *Block) diff(txt string) bool {
if block.txt == txt { if block.txt == txt {
return false return false
} }
block.txt = txt block.txt = txt
return true return true
} }

@ -20,7 +20,9 @@ import (
func (bar *Bar) clockFun() { func (bar *Bar) clockFun() {
// Initialize block. // Initialize block.
block := bar.initBlock("clock", "?", 800, 'a', 0, "#445967", "#CCCCCC") block := bar.initBlock("clock", "?", 800, 'a', 0, "#445967", "#CCCCCC")
bar.redraw <- block
// Notify that the next block can be initialized.
bar.ready <- true
for { for {
// Compose block text. // Compose block text.
@ -39,7 +41,9 @@ func (bar *Bar) clockFun() {
func (bar *Bar) musicFun() { func (bar *Bar) musicFun() {
// Initialize block. // Initialize block.
block := bar.initBlock("music", "» ", 660, 'r', -12, "#3C4F5B", "#CCCCCC") 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. // Connect to MPD.
c, err := mpd.Dial("tcp", ":6600") c, err := mpd.Dial("tcp", ":6600")
@ -62,20 +66,20 @@ func (bar *Bar) musicFun() {
}() }()
// Show popup on clicking the left mouse button. // Show popup on clicking the left mouse button.
/*block.actions["button1"] = func() { block.actions["button1"] = func() {
if block.popup == nil { if block.popup == nil {
var err error var err error
block.popup, err = bar.initPopup(1920-304-29, 29, 304, 148, block.popup, err = bar.initPopup(1920-304-29, 29, 304, 148,
"#3C4F5B", "#CCCCCC") "#3C4F5B", "#CCCCCC")
if err != nil { if err != nil {
log.Print(err) panic(err)
} }
//popup.draw() //popup.draw()
} else { } else {
block.popup = block.popup.destroy() block.popup = block.popup.destroy()
} }
}*/ }
// Toggle play/pause on clicking the right mouse button. // Toggle play/pause on clicking the right mouse button.
block.actions["button3"] = func() { block.actions["button3"] = func() {
@ -138,7 +142,9 @@ func (bar *Bar) musicFun() {
func (bar *Bar) todoFun() { func (bar *Bar) todoFun() {
// Initialize block. // Initialize block.
block := bar.initBlock("todo", "¢", 29, 'c', 0, "#5394C9", "#FFFFFF") 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. // Find `.todo` file.
hd, err := homedir.Dir() hd, err := homedir.Dir()
@ -192,10 +198,11 @@ func (bar *Bar) todoFun() {
func (bar *Bar) windowFun() { func (bar *Bar) windowFun() {
// Initialize blocks. // 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") 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. // TODO: This doesn't check for window title changes.
xevent.PropertyNotifyFun(func(_ *xgbutil.XUtil, ev xevent. xevent.PropertyNotifyFun(func(_ *xgbutil.XUtil, ev xevent.
@ -245,9 +252,9 @@ func (bar *Bar) workspaceFun() {
"#FFFFFF") "#FFFFFF")
blockSRC := bar.initBlock("src", "¾ src", 70, 'l', 10, "#5394C9", blockSRC := bar.initBlock("src", "¾ src", 70, 'l', 10, "#5394C9",
"#FFFFFF") "#FFFFFF")
bar.redraw <- blockWWW
bar.redraw <- blockIRC // Notify that the next block can be initialized.
bar.redraw <- blockSRC bar.ready <- true
// Change active workspace on clicking on one of the blocks. // Change active workspace on clicking on one of the blocks.
blockWWW.actions["button1"] = func() { blockWWW.actions["button1"] = func() {

25
main.go

@ -2,7 +2,6 @@ package main
import ( import (
"path" "path"
"time"
homedir "github.com/mitchellh/go-homedir" homedir "github.com/mitchellh/go-homedir"
) )
@ -19,20 +18,14 @@ func main() {
} }
// Run bar block functions. // Run bar block functions.
runBlock(bar.windowFun) go bar.initBlocks([]func(){
runBlock(bar.workspaceFun) bar.windowFun,
runBlock(bar.clockFun) bar.workspaceFun,
runBlock(bar.musicFun) bar.clockFun,
runBlock(bar.todoFun) bar.musicFun,
bar.todoFun,
})
for { // Listen for redraw events.
if err := bar.draw(<-bar.redraw); err != nil { bar.listen()
panic(err)
}
}
}
func runBlock(f func()) {
go f()
time.Sleep(time.Millisecond * 10)
} }

@ -26,24 +26,23 @@ type Popup struct {
redraw chan *Popup redraw chan *Popup
} }
func (bar *Bar) initPopup(x, y, w, h int, bg, fg string) (*Popup, func (bar *Bar) initPopup(x, y, w, h int, bg, fg string) (*Popup, error) {
error) {
popup := new(Popup) popup := new(Popup)
var err error var err error
// Create a window for the bar. This window listens to button // Create a window for the bar. This window listens to button press events
// press events in order to respond to them. // in order to respond to them.
popup.win, err = xwindow.Generate(bar.xu) popup.win, err = xwindow.Generate(bar.xu)
if err != nil { if err != nil {
return nil, err return nil, err
} }
popup.win.Create(bar.xu.RootWin(), x, y, w, h, xproto.CwBackPixel| popup.win.Create(bar.xu.RootWin(), x, y, w, h, xproto.CwBackPixel|xproto.
xproto.CwEventMask, 0x000000, xproto.EventMaskButtonPress) CwEventMask, 0x000000, xproto.EventMaskButtonPress)
// EWMH stuff. // EWMH stuff.
// TODO: `WmStateSet` and `WmDesktopSet` are basically here to // TODO: `WmStateSet` and `WmDesktopSet` are basically here to keep OpenBox
// keep OpenBox happy, can I somehow remove them and just use // happy, can I somehow remove them and just use `_NET_WM_WINDOW_TYPE_DOCK`
// `_NET_WM_WINDOW_TYPE_DOCK` like I can with WindowChef? // like I can with WindowChef?
if err := ewmh.WmWindowTypeSet(bar.xu, popup.win.Id, []string{ if err := ewmh.WmWindowTypeSet(bar.xu, popup.win.Id, []string{
"_NET_WM_WINDOW_TYPE_DOCK"}); err != nil { "_NET_WM_WINDOW_TYPE_DOCK"}); err != nil {
return nil, err 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 { "_NET_WM_STATE_STICKY"}); err != nil {
return nil, err return nil, err
} }
if err := ewmh.WmDesktopSet(bar.xu, popup.win.Id, ^uint( if err := ewmh.WmDesktopSet(bar.xu, popup.win.Id, ^uint(0)); err != nil {
0)); err != nil {
return nil, err return nil, err
} }
if err := ewmh.WmNameSet(bar.xu, popup.win.Id, "melonbar"); err != if err := ewmh.WmNameSet(bar.xu, popup.win.Id, "melonbar"); err != nil {
nil {
return nil, err return nil, err
} }
@ -69,7 +66,9 @@ func (bar *Bar) initPopup(x, y, w, h int, bg, fg string) (*Popup,
// Create the bar image. // Create the bar image.
popup.img = xgraphics.New(bar.xu, image.Rect(0, 0, w, h)) 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.img.XDraw()
popup.w = w popup.w = w