little improvements

This commit is contained in:
Camille Scholtz 2018-12-26 15:00:07 +01:00
parent 874e54d240
commit 1dad89fe67
4 changed files with 150 additions and 179 deletions

2
bar.go

@ -54,7 +54,7 @@ func initBar(x, y, w, h int, fp string) (*Bar, error) {
return nil, err return nil, err
} }
// Run the main X event loop, this is uses to catch events. // Run the main X event loop, this is used to catch events.
go xevent.Main(bar.xu) go xevent.Main(bar.xu)
// Listen to the root window for property change events, used to check if // Listen to the root window for property change events, used to check if

@ -71,3 +71,14 @@ func (bar *Bar) initBlock(name, txt string, w int, align rune, xoff int, bg,
return block return block
} }
// TODO: Make this function more versatile by allowing different and multiple
// properties to be checked.
func (block *Block) diff(txt string) bool {
if block.txt == txt {
return false
}
block.txt = txt
return true
}

280
blocks.go

@ -3,6 +3,7 @@ package main
import ( import (
"bufio" "bufio"
"os" "os"
"path"
"strconv" "strconv"
"time" "time"
@ -13,31 +14,54 @@ import (
"github.com/BurntSushi/xgbutil/xprop" "github.com/BurntSushi/xgbutil/xprop"
"github.com/fhs/gompd/mpd" "github.com/fhs/gompd/mpd"
"github.com/fsnotify/fsnotify" "github.com/fsnotify/fsnotify"
homedir "github.com/mitchellh/go-homedir"
) )
func (bar *Bar) clockFun() { func (bar *Bar) clockFun() {
// Initialize block.
block := bar.initBlock("clock", "?", 800, 'a', 0, "#445967", "#CCCCCC") block := bar.initBlock("clock", "?", 800, 'a', 0, "#445967", "#CCCCCC")
bar.redraw <- block
init := true
for { for {
if !init { // Compose block text.
time.Sleep(20 * time.Second)
}
init = false
txt := time.Now().Format("Monday, January 2th 03:04 PM") txt := time.Now().Format("Monday, January 2th 03:04 PM")
if block.txt == txt {
continue // Redraw block.
if block.diff(txt) {
bar.redraw <- block
} }
block.txt = txt // Update every 45 seconds.
bar.redraw <- block time.Sleep(45 * time.Second)
} }
} }
func (bar *Bar) musicFun() { func (bar *Bar) musicFun() {
block := bar.initBlock("music", "?", 660, 'r', -12, "#3C4F5B", "#CCCCCC") // Initialize block.
block := bar.initBlock("music", "» ", 660, 'r', -12, "#3C4F5B", "#CCCCCC")
bar.redraw <- block
// Connect to MPD.
c, err := mpd.Dial("tcp", ":6600")
if err != nil {
panic(err)
}
// Keep connection alive by pinging ever 45 seconds.
go func() {
for {
time.Sleep(time.Second * 45)
if err := c.Ping(); err != nil {
c, err = mpd.Dial("tcp", ":6600")
if err != nil {
panic(err)
}
}
}
}()
// 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
@ -52,191 +76,131 @@ func (bar *Bar) musicFun() {
block.popup = block.popup.destroy() block.popup = block.popup.destroy()
} }
}*/ }*/
// Toggle play/pause on clicking the right mouse button.
block.actions["button3"] = func() { block.actions["button3"] = func() {
conn, err := mpd.Dial("tcp", ":6600") status, err := c.Status()
if err != nil {
panic(err)
}
defer conn.Close()
status, err := conn.Status()
if err != nil { if err != nil {
panic(err) panic(err)
} }
if err := conn.Pause(status["state"] != "pause"); err != nil { if err := c.Pause(status["state"] != "pause"); err != nil {
panic(err) panic(err)
} }
} }
// Previous song on scrolling up.
block.actions["button4"] = func() { block.actions["button4"] = func() {
conn, err := mpd.Dial("tcp", ":6600") if err := c.Previous(); err != nil {
if err != nil {
panic(err)
}
defer conn.Close()
if err := conn.Previous(); err != nil {
panic(err) panic(err)
} }
} }
// Next song on on scrolling down..
block.actions["button5"] = func() { block.actions["button5"] = func() {
conn, err := mpd.Dial("tcp", ":6600") if err := c.Next(); err != nil {
if err != nil {
panic(err)
}
defer conn.Close()
if err := conn.Next(); err != nil {
panic(err) panic(err)
} }
} }
watcher, err := mpd.NewWatcher("tcp", ":6600", "", "player") // Watch MPD for events.
w, err := mpd.NewWatcher("tcp", ":6600", "", "player")
if err != nil { if err != nil {
panic(err) panic(err)
} }
var conn *mpd.Client
init := true
for { for {
if !init { cur, err := c.CurrentSong()
conn.Close() if err != nil {
<-watcher.Event panic(err)
} }
init = false sts, err := c.Status()
// TODO: Is it maybe possible to not create a new connection each loop?
conn, err = mpd.Dial("tcp", ":6600")
if err != nil { if err != nil {
panic(err) panic(err)
} }
cur, err := conn.CurrentSong() // Compose text.
if err != nil { var s string
panic(err) if sts["state"] == "pause" {
s = "[paused] "
}
txt := "» " + s + cur["Artist"] + " - " + cur["Title"]
// Redraw block.
if block.diff(txt) {
bar.redraw <- block
} }
status, err := conn.Status() <-w.Event
if err != nil {
panic(err)
}
var state string
if status["state"] == "pause" {
state = "[paused] "
}
txt := "» " + state + cur["Artist"] + " - " + cur["Title"]
if block.txt == txt {
continue
}
block.txt = txt
bar.redraw <- block
} }
} }
func (bar *Bar) todoFun() { func (bar *Bar) todoFun() {
block := bar.initBlock("todo", "?", 29, 'c', 0, "#5394C9", "#FFFFFF") // Initialize block.
block := bar.initBlock("todo", "¢", 29, 'c', 0, "#5394C9", "#FFFFFF")
bar.redraw <- block
watcher, err := fsnotify.NewWatcher() // Find `.todo` file.
hd, err := homedir.Dir()
if err != nil { if err != nil {
panic(err) panic(err)
} }
if err := watcher.Add("/home/onodera/.todo"); err != nil { fp := path.Join(hd, ".todo")
panic(err)
} // Watch file for events.
file, err := os.Open("/home/onodera/.todo") w, err := fsnotify.NewWatcher()
if err != nil { if err != nil {
panic(err) panic(err)
} }
init := true if err := w.Add(fp); err != nil {
panic(err)
}
f, err := os.Open(fp)
if err != nil {
panic(err)
}
for { for {
if !init { // Count file lines.
ev := <-watcher.Events s := bufio.NewScanner(f)
if ev.Op&fsnotify.Write != fsnotify.Write {
continue
}
}
init = false
s := bufio.NewScanner(file)
s.Split(bufio.ScanLines) s.Split(bufio.ScanLines)
var c int var c int
for s.Scan() { for s.Scan() {
c++ c++
} }
if _, err := file.Seek(0, 0); err != nil {
// Rewind file.
if _, err := f.Seek(0, 0); err != nil {
panic(err) panic(err)
} }
// Compose block text.
txt := "¢ " + strconv.Itoa(c) txt := "¢ " + strconv.Itoa(c)
if block.txt == txt {
// Redraw block.
if block.diff(txt) {
bar.redraw <- block
}
// Listen for next write event.
ev := <-w.Events
if ev.Op&fsnotify.Write != fsnotify.Write {
continue continue
} }
block.txt = txt
bar.redraw <- block
} }
} }
/*
func (bar *Bar) weatherFun() {
block := bar.initBlock("weather", "?", 29, 'r', 0, "#5394C9",
"#FFFFFF")
w, err := owm.NewCurrent("C", "en")
if err != nil {
log.Fatalln(err)
}
init := true
for {
if !init {
time.Sleep(200 * time.Second)
}
init = false
if err := w.CurrentByID(2758106); err != nil {
log.Print(err)
continue
}
var state uint
switch w.Weather[0].Icon[0:2] {
case "01":
state = 0
case "02":
state = 1
case "03":
state = 2
case "04":
state = 3
case "09":
state = 4
case "10":
state = 5
case "11":
state = 6
case "13":
state = 7
case "50":
state = 8
}
block.txt = strconv.FormatFloat(w.Main.Temp, 'f', 0, 64) +
" °C"
bar.redraw <- block
}
}
*/
func (bar *Bar) windowFun() { func (bar *Bar) windowFun() {
// Initialize blocks.
blockIcon := bar.initBlock("window", "º", 21, 'l', 12, "#37BF8D", "#FFFFFF") blockIcon := 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
// TODO: I'm not sure how I can use init (to prevent a black bar) here?
// 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.
PropertyNotifyEvent) { PropertyNotifyEvent) {
// Only listen to `_NET_ACTIVE_WINDOW` events.
atom, err := xprop.Atm(bar.xu, "_NET_ACTIVE_WINDOW") atom, err := xprop.Atm(bar.xu, "_NET_ACTIVE_WINDOW")
if err != nil { if err != nil {
panic(err) panic(err)
@ -245,6 +209,7 @@ func (bar *Bar) windowFun() {
return return
} }
// Get active window.
id, err := ewmh.ActiveWindowGet(bar.xu) id, err := ewmh.ActiveWindowGet(bar.xu)
if err != nil { if err != nil {
panic(err) panic(err)
@ -253,6 +218,7 @@ func (bar *Bar) windowFun() {
return return
} }
// Compose block text.
txt, err := ewmh.WmNameGet(bar.xu, id) txt, err := ewmh.WmNameGet(bar.xu, id)
if err != nil || len(txt) == 0 { if err != nil || len(txt) == 0 {
txt, err = icccm.WmNameGet(bar.xu, id) txt, err = icccm.WmNameGet(bar.xu, id)
@ -263,47 +229,48 @@ func (bar *Bar) windowFun() {
if len(txt) > 38 { if len(txt) > 38 {
txt = txt[0:38] + "..." txt = txt[0:38] + "..."
} }
if block.txt == txt {
return // Redraw block.
if block.diff(txt) {
bar.redraw <- block
} }
block.txt = txt
bar.redraw <- block
}).Connect(bar.xu, bar.xu.RootWin()) }).Connect(bar.xu, bar.xu.RootWin())
bar.redraw <- blockIcon
} }
func (bar *Bar) workspaceFun() { func (bar *Bar) workspaceFun() {
// Initialize block.
blockWWW := bar.initBlock("www", "¼ www", 74, 'l', 10, "#5394C9", blockWWW := bar.initBlock("www", "¼ www", 74, 'l', 10, "#5394C9",
"#FFFFFF") "#FFFFFF")
blockIRC := bar.initBlock("irc", "½ irc", 67, 'l', 10, "#5394C9",
"#FFFFFF")
blockSRC := bar.initBlock("src", "¾ src", 70, 'l', 10, "#5394C9",
"#FFFFFF")
bar.redraw <- blockWWW
bar.redraw <- blockIRC
bar.redraw <- blockSRC
// Change active workspace on clicking on one of the blocks.
blockWWW.actions["button1"] = func() { blockWWW.actions["button1"] = func() {
if err := ewmh.CurrentDesktopReq(bar.xu, 0); err != nil { if err := ewmh.CurrentDesktopReq(bar.xu, 0); err != nil {
panic(err) panic(err)
} }
} }
blockIRC := bar.initBlock("irc", "½ irc", 67, 'l', 10, "#5394C9",
"#FFFFFF")
blockIRC.actions["button1"] = func() { blockIRC.actions["button1"] = func() {
if err := ewmh.CurrentDesktopReq(bar.xu, 1); err != nil { if err := ewmh.CurrentDesktopReq(bar.xu, 1); err != nil {
panic(err) panic(err)
} }
} }
blockSRC := bar.initBlock("src", "¾ src", 70, 'l', 10, "#5394C9",
"#FFFFFF")
blockSRC.actions["button1"] = func() { blockSRC.actions["button1"] = func() {
if err := ewmh.CurrentDesktopReq(bar.xu, 2); err != nil { if err := ewmh.CurrentDesktopReq(bar.xu, 2); err != nil {
panic(err) panic(err)
} }
} }
// TODO: I'm not sure how I can use init (to prevent a black bar) here?
var owsp uint var owsp uint
var pwsp, nwsp int var pwsp, nwsp int
xevent.PropertyNotifyFun(func(_ *xgbutil.XUtil, ev xevent. xevent.PropertyNotifyFun(func(_ *xgbutil.XUtil, ev xevent.
PropertyNotifyEvent) { PropertyNotifyEvent) {
// Only listen to `_NET_ACTIVE_WINDOW` events.
atom, err := xprop.Atm(bar.xu, "_NET_CURRENT_DESKTOP") atom, err := xprop.Atm(bar.xu, "_NET_CURRENT_DESKTOP")
if err != nil { if err != nil {
panic(err) panic(err)
@ -312,11 +279,13 @@ func (bar *Bar) workspaceFun() {
return return
} }
// Get the current active desktop.
wsp, err := ewmh.CurrentDesktopGet(bar.xu) wsp, err := ewmh.CurrentDesktopGet(bar.xu)
if err != nil { if err != nil {
panic(err) panic(err)
} }
// Set colors accordingly.
switch wsp { switch wsp {
case 0: case 0:
blockWWW.bg = "#72A7D3" blockWWW.bg = "#72A7D3"
@ -341,14 +310,13 @@ func (bar *Bar) workspaceFun() {
nwsp = 0 nwsp = 0
} }
if owsp == wsp { if owsp != wsp {
return bar.redraw <- blockWWW
} bar.redraw <- blockIRC
owsp = wsp bar.redraw <- blockSRC
bar.redraw <- blockWWW owsp = wsp
bar.redraw <- blockIRC }
bar.redraw <- blockSRC
}).Connect(bar.xu, bar.xu.RootWin()) }).Connect(bar.xu, bar.xu.RootWin())
prevFun := func() { prevFun := func() {

36
main.go

@ -1,36 +1,28 @@
package main package main
import ( import "time"
"log"
"time"
)
func main() { func main() {
bar, err := initBar(0, 0, 1920, 29, "./vendor/font/cure.font") bar, err := initBar(0, 0, 1920, 29, "./vendor/font/cure.font")
if err != nil { if err != nil {
log.Fatal(err) panic(err)
} }
// Run bar block functions. Make sure to sleep a millisecond after each // Run bar block functions.
// block, else they won't appear in the right order. runBlock(bar.windowFun)
go bar.windowFun() runBlock(bar.workspaceFun)
time.Sleep(time.Millisecond * 5) runBlock(bar.clockFun)
runBlock(bar.musicFun)
go bar.workspaceFun() runBlock(bar.todoFun)
time.Sleep(time.Millisecond * 5)
go bar.clockFun()
time.Sleep(time.Millisecond * 5)
go bar.musicFun()
time.Sleep(time.Millisecond * 5)
go bar.todoFun()
time.Sleep(time.Millisecond * 5)
for { for {
if err := bar.draw(<-bar.redraw); err != nil { if err := bar.draw(<-bar.redraw); err != nil {
log.Fatal(err) panic(err)
} }
} }
} }
func runBlock(f func()) {
go f()
time.Sleep(time.Millisecond * 10)
}