Make openbox compatible

This commit is contained in:
Camille Scholtz 2017-07-12 18:21:51 +02:00
parent 0e0e4f0f55
commit 2bfbc2bc4a
3 changed files with 77 additions and 57 deletions

@ -25,8 +25,8 @@ On top of each block function you should run `bar.initBlock()`, this
is where most of the configuration happens. Here is a short is where most of the configuration happens. Here is a short
explanation of each parameter from left to right: explanation of each parameter from left to right:
* The name of the block, this is and gets used as the name * The name of the block, this is gets used as the name of the block
of the block map key. (`string`) map key. (`string`)
* The initial string the block should display. (`string`) * The initial string the block should display. (`string`)
* The width of the block. (`int`) * The width of the block. (`int`)
* The aligment of the text, this can be `'l'` for left aligment, `'c'` * The aligment of the text, this can be `'l'` for left aligment, `'c'`

54
bar.go

@ -1,6 +1,7 @@
package main package main
import ( import (
"fmt"
"image" "image"
"os" "os"
"sync" "sync"
@ -10,6 +11,7 @@ import (
"github.com/BurntSushi/xgb/xproto" "github.com/BurntSushi/xgb/xproto"
"github.com/BurntSushi/xgbutil" "github.com/BurntSushi/xgbutil"
"github.com/BurntSushi/xgbutil/ewmh" "github.com/BurntSushi/xgbutil/ewmh"
"github.com/BurntSushi/xgbutil/xevent"
"github.com/BurntSushi/xgbutil/xgraphics" "github.com/BurntSushi/xgbutil/xgraphics"
"github.com/BurntSushi/xgbutil/xwindow" "github.com/BurntSushi/xgbutil/xwindow"
) )
@ -72,27 +74,46 @@ func initBar(x, y, w, h int, font string, fontSize float64) (*Bar,
if err != nil { if err != nil {
return nil, err return nil, err
} }
go xevent.Main(bar.xu)
// Listen to the root window for events. // Listen to the root window for property change event, used to
xwindow.New(bar.xu, bar.xu.RootWin()).Listen( // check if the user changed the focused window or active
xproto.EventMaskPropertyChange) // workspace.
if err := xwindow.New(bar.xu, bar.xu.RootWin()).Listen(
xproto.EventMaskPropertyChange); err != nil {
return nil, err
}
// Create a window. // Create a window.
bar.win, err = xwindow.Generate(bar.xu) bar.win, err = xwindow.Generate(bar.xu)
if err != nil { if err != nil {
return nil, err return nil, err
} }
bar.win.Create(bar.xu.RootWin(), x, y, w, h, xproto.CwBackPixel, bar.win.Create(bar.xu.RootWin(), x, y, w, h, xproto.CwBackPixel|
0x000000) xproto.CwEventMask, 0x000000, xproto.EventMaskPropertyChange)
// TODO: `WmStateSet` and `WmDesktopSet` are basically here to
// keep OpenBox happy, can I somehow remove them and just use
// `_NET_WM_WINDOW_TYPE_DOCK`?
// EWMH stuff. // EWMH stuff.
if err := ewmh.WmWindowTypeSet(bar.xu, bar.win.Id, []string{ if err := ewmh.WmWindowTypeSet(bar.xu, bar.win.Id, []string{
"_NET_WM_WINDOW_TYPE_DOCK"}); err != nil { "_NET_WM_WINDOW_TYPE_DOCK"}); err != nil {
return nil, err return nil, err
} }
if err := ewmh.WmStateSet(bar.xu, bar.win.Id, []string{
"_NET_WM_STATE_STICKY"}); err != nil {
return nil, err
}
if err := ewmh.WmDesktopSet(bar.xu, bar.win.Id, ^uint(0)); err != nil {
return nil, err
}
if err := ewmh.WmNameSet(bar.xu, bar.win.Id, "melonbar"); err != nil {
return nil, err
}
// Map window. // Map window.
bar.win.Map() bar.win.Map()
bar.win.Move(x, y)
// Create bar image. // Create bar image.
bar.img = xgraphics.New(bar.xu, image.Rect(0, 0, w, h)) bar.img = xgraphics.New(bar.xu, image.Rect(0, 0, w, h))
@ -178,14 +199,9 @@ func (bar *Bar) draw(name string) error {
i, _ := bar.block.Load(name) i, _ := bar.block.Load(name)
block := i.(*Block) block := i.(*Block)
// Color the backround.
tw, _ := xgraphics.Extents(bar.font, bar.fontSize, block.txt)
block.img.For(func(x, y int) xgraphics.BGRA {
return block.bg
})
// Calculate the required x coordinate for the different // Calculate the required x coordinate for the different
// aligments. // aligments.
tw, _ := xgraphics.Extents(bar.font, bar.fontSize, block.txt)
var x int var x int
switch block.align { switch block.align {
case 'l': case 'l':
@ -194,8 +210,24 @@ func (bar *Bar) draw(name string) error {
x = block.x + ((block.w / 2) - (tw / 2)) + block.xoff x = block.x + ((block.w / 2) - (tw / 2)) + block.xoff
case 'r': case 'r':
x = (block.x + block.w) - tw + block.xoff x = (block.x + block.w) - tw + block.xoff
default:
return fmt.Errorf("draw %#U: Not a valid aligment rune",
block.align)
} }
// Color the backround.
block.img.For(func(cx, cy int) xgraphics.BGRA {
// Hack for music block background.
if name == "music" {
if cx < x+block.xoff {
return hexToBGRA("#445967")
}
return block.bg
}
return block.bg
})
// TODO: Center vertically automatically. // TODO: Center vertically automatically.
// Draw the text. // Draw the text.
if _, _, err := block.img.Text(x, 6, block.fg, bar.fontSize, if _, _, err := block.img.Text(x, 6, block.fg, bar.fontSize,

@ -7,8 +7,10 @@ import (
"strconv" "strconv"
"time" "time"
"github.com/BurntSushi/xgb/xproto" "github.com/BurntSushi/xgbutil"
"github.com/BurntSushi/xgbutil/ewmh" "github.com/BurntSushi/xgbutil/ewmh"
"github.com/BurntSushi/xgbutil/icccm"
"github.com/BurntSushi/xgbutil/xevent"
"github.com/BurntSushi/xgbutil/xprop" "github.com/BurntSushi/xgbutil/xprop"
owm "github.com/briandowns/openweathermap" owm "github.com/briandowns/openweathermap"
"github.com/fhs/gompd/mpd" "github.com/fhs/gompd/mpd"
@ -170,39 +172,33 @@ func (bar *Bar) weatherFun() {
func (bar *Bar) windowFun() { func (bar *Bar) windowFun() {
bar.initBlock("window", "?", 220, 'c', 0, "#37BF8D", "#FFFFFF") bar.initBlock("window", "?", 220, 'c', 0, "#37BF8D", "#FFFFFF")
init := true // TODO: I'm not sure how I can use init here?
for { xevent.PropertyNotifyFun(func(xu *xgbutil.XUtil,
if !init { ev xevent.PropertyNotifyEvent) {
ev, xgbErr := bar.xu.Conn().WaitForEvent() atom, err := xprop.Atm(bar.xu, "_NET_ACTIVE_WINDOW")
if xgbErr != nil { if ev.Atom != atom {
log.Print(xgbErr) return
continue }
} if err != nil {
log.Print(err)
atom, err := xprop.Atm(bar.xu, "_NET_ACTIVE_WINDOW") return
if ev.(xproto.PropertyNotifyEvent).Atom != atom {
continue
}
if err != nil {
log.Print(err)
continue
}
} }
init = false
id, err := ewmh.ActiveWindowGet(bar.xu) id, err := ewmh.ActiveWindowGet(bar.xu)
if err != nil { if err != nil {
log.Print(err) log.Print(err)
continue return
} }
win, err := ewmh.WmNameGet(bar.xu, id) win, err := ewmh.WmNameGet(bar.xu, id)
if err != nil { if err != nil || len(win) == 0 {
log.Print(err) win, err = icccm.WmNameGet(bar.xu, id)
continue if err != nil || len(win) == 0 {
win = "?"
}
} }
bar.updateBlockTxt("window", win) bar.updateBlockTxt("window", win)
} }).Connect(bar.xu, bar.xu.RootWin())
} }
func (bar *Bar) workspaceFun() { func (bar *Bar) workspaceFun() {
@ -210,30 +206,22 @@ func (bar *Bar) workspaceFun() {
bar.initBlock("irc", "irc", 67, 'c', 0, "#5394C9", "#FFFFFF") bar.initBlock("irc", "irc", 67, 'c', 0, "#5394C9", "#FFFFFF")
bar.initBlock("src", "src", 70, 'c', 0, "#5394C9", "#FFFFFF") bar.initBlock("src", "src", 70, 'c', 0, "#5394C9", "#FFFFFF")
init := true // TODO: I'm not sure how I can use init here?
for { xevent.PropertyNotifyFun(func(xu *xgbutil.XUtil,
if !init { ev xevent.PropertyNotifyEvent) {
ev, xgbErr := bar.xu.Conn().WaitForEvent() atom, err := xprop.Atm(bar.xu, "_NET_CURRENT_DESKTOP")
if xgbErr != nil { if ev.Atom != atom {
log.Print(xgbErr) return
continue }
} if err != nil {
log.Print(err)
atom, err := xprop.Atm(bar.xu, "WINDOWCHEF_ACTIVE_GROUPS") return
if ev.(xproto.PropertyNotifyEvent).Atom != atom {
continue
}
if err != nil {
log.Print(err)
continue
}
} }
init = false
wsp, err := ewmh.CurrentDesktopGet(bar.xu) wsp, err := ewmh.CurrentDesktopGet(bar.xu)
if err != nil { if err != nil {
log.Print(err) log.Print(err)
continue return
} }
switch wsp { switch wsp {
@ -250,5 +238,5 @@ func (bar *Bar) workspaceFun() {
bar.updateBlockBg("irc", "#5394C9") bar.updateBlockBg("irc", "#5394C9")
bar.updateBlockBg("src", "#72A7D3") bar.updateBlockBg("src", "#72A7D3")
} }
} }).Connect(bar.xu, bar.xu.RootWin())
} }