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
explanation of each parameter from left to right:
* The name of the block, this is and gets used as the name
of the block map key. (`string`)
* The name of the block, this is gets used as the name of the block
map key. (`string`)
* The initial string the block should display. (`string`)
* The width of the block. (`int`)
* The aligment of the text, this can be `'l'` for left aligment, `'c'`

54
bar.go

@ -1,6 +1,7 @@
package main
import (
"fmt"
"image"
"os"
"sync"
@ -10,6 +11,7 @@ import (
"github.com/BurntSushi/xgb/xproto"
"github.com/BurntSushi/xgbutil"
"github.com/BurntSushi/xgbutil/ewmh"
"github.com/BurntSushi/xgbutil/xevent"
"github.com/BurntSushi/xgbutil/xgraphics"
"github.com/BurntSushi/xgbutil/xwindow"
)
@ -72,27 +74,46 @@ func initBar(x, y, w, h int, font string, fontSize float64) (*Bar,
if err != nil {
return nil, err
}
go xevent.Main(bar.xu)
// Listen to the root window for events.
xwindow.New(bar.xu, bar.xu.RootWin()).Listen(
xproto.EventMaskPropertyChange)
// Listen to the root window for property change event, used to
// check if the user changed the focused window or active
// workspace.
if err := xwindow.New(bar.xu, bar.xu.RootWin()).Listen(
xproto.EventMaskPropertyChange); err != nil {
return nil, err
}
// Create a window.
bar.win, err = xwindow.Generate(bar.xu)
if err != nil {
return nil, err
}
bar.win.Create(bar.xu.RootWin(), x, y, w, h, xproto.CwBackPixel,
0x000000)
bar.win.Create(bar.xu.RootWin(), x, y, w, h, xproto.CwBackPixel|
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.
if err := ewmh.WmWindowTypeSet(bar.xu, bar.win.Id, []string{
"_NET_WM_WINDOW_TYPE_DOCK"}); err != nil {
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.
bar.win.Map()
bar.win.Move(x, y)
// Create bar image.
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)
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
// aligments.
tw, _ := xgraphics.Extents(bar.font, bar.fontSize, block.txt)
var x int
switch block.align {
case 'l':
@ -194,8 +210,24 @@ func (bar *Bar) draw(name string) error {
x = block.x + ((block.w / 2) - (tw / 2)) + block.xoff
case 'r':
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.
// Draw the text.
if _, _, err := block.img.Text(x, 6, block.fg, bar.fontSize,

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