Did I really write this 2 years ago??? Anyways, some small updates
This commit is contained in:
parent
a9daf23fbe
commit
67c68f8a98
@ -55,8 +55,8 @@ specified before the `for` loop. For example setting up a connection
|
|||||||
to `mpd`.
|
to `mpd`.
|
||||||
|
|
||||||
If you want something to only be done *after* the very first loop - an
|
If you want something to only be done *after* the very first loop - an
|
||||||
example of this would be not waiting for a workspace chance event, but
|
example of this would be not waiting for a workspace change event, but
|
||||||
immediately checking the current workspace. - use:
|
immediately checking the current workspace - use:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
init := true
|
init := true
|
||||||
@ -75,8 +75,8 @@ the user changes his workspace for the first time.
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
When you've gathered all needed information you can update the block
|
When you've gathered all information you can update the block values
|
||||||
values using for example `block.bg = value` and running
|
using for example `block.bg = value` and running
|
||||||
`bar.redraw <- block`.
|
`bar.redraw <- block`.
|
||||||
|
|
||||||
|
|
||||||
|
100
bar.go
100
bar.go
@ -23,27 +23,26 @@ type Bar struct {
|
|||||||
win *xwindow.Window
|
win *xwindow.Window
|
||||||
img *xgraphics.Image
|
img *xgraphics.Image
|
||||||
|
|
||||||
// The font and fontsize that should be used.
|
|
||||||
font *truetype.Font
|
|
||||||
fsize float64
|
|
||||||
|
|
||||||
// The width and height of the bar.
|
// The width and height of the bar.
|
||||||
w, h int
|
w, h int
|
||||||
|
|
||||||
// This is a sum of all of the block widths, used to draw a block
|
// This is a sum of all of the block widths, used to draw a block to the
|
||||||
// to the right of the last block.
|
// right of the last block.
|
||||||
xsum int
|
xsum int
|
||||||
|
|
||||||
|
// The font that should be used.
|
||||||
|
font *truetype.Font
|
||||||
|
size float64
|
||||||
|
|
||||||
// A map with information about the block, see the `Block` type.
|
// A map with information about the block, see the `Block` type.
|
||||||
block *sync.Map
|
block *sync.Map
|
||||||
|
|
||||||
// A channel where the block should be send to to once its ready
|
// A channel where the block should be send to to once its ready to be
|
||||||
// to be redrawn.
|
// redrawn.
|
||||||
redraw chan *Block
|
redraw chan *Block
|
||||||
}
|
}
|
||||||
|
|
||||||
func initBar(x, y, w, h int, font string, fsize float64) (*Bar,
|
func initBar(x, y, w, h int, font string, size float64) (*Bar, error) {
|
||||||
error) {
|
|
||||||
bar := new(Bar)
|
bar := new(Bar)
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
@ -56,27 +55,26 @@ func initBar(x, y, w, h int, font string, fsize float64) (*Bar,
|
|||||||
// Run the main X event loop, this is uses to catch events.
|
// Run the main X event loop, this is uses to catch events.
|
||||||
go xevent.Main(bar.xu)
|
go xevent.Main(bar.xu)
|
||||||
|
|
||||||
// Listen to the root window for property change events, used to
|
// Listen to the root window for property change events, used to check if
|
||||||
// check if the user changed the focused window or active
|
// the user changed the focused window or active workspace for example.
|
||||||
// workspace for example.
|
if err := xwindow.New(bar.xu, bar.xu.RootWin()).Listen(xproto.
|
||||||
if err := xwindow.New(bar.xu, bar.xu.RootWin()).Listen(
|
EventMaskPropertyChange); err != nil {
|
||||||
xproto.EventMaskPropertyChange); err != nil {
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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.
|
||||||
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|xproto.
|
||||||
xproto.CwEventMask, 0x000000, xproto.EventMaskButtonPress)
|
CwEventMask, 0x000000, xproto.EventMaskButtonPress)
|
||||||
|
|
||||||
// EWMH stuff to make the window behave like an actuale bar.
|
// EWMH stuff to make the window behave like an actual bar.
|
||||||
// TODO: `WmStateSet` and `WmDesktopSet` are basically here to
|
// XXX: `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, 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
|
||||||
@ -85,29 +83,34 @@ func initBar(x, y, w, h int, font string, fsize float64) (*Bar,
|
|||||||
"_NET_WM_STATE_STICKY"}); err != nil {
|
"_NET_WM_STATE_STICKY"}); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if err := ewmh.WmDesktopSet(bar.xu, bar.win.Id, ^uint(0)); err !=
|
if err := ewmh.WmDesktopSet(bar.xu, bar.win.Id, ^uint(0)); err != nil {
|
||||||
nil {
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if err := ewmh.WmNameSet(bar.xu, bar.win.Id, "melonbar"); err !=
|
if err := ewmh.WmNameSet(bar.xu, bar.win.Id, "melonbar"); err != nil {
|
||||||
nil {
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Map window.
|
// Map window.
|
||||||
bar.win.Map()
|
bar.win.Map()
|
||||||
|
|
||||||
// TODO: Moving the window is again a hack to keep OpenBox happy.
|
// XXX: Moving the window is again a hack to keep OpenBox happy.
|
||||||
bar.win.Move(x, y)
|
bar.win.Move(x, y)
|
||||||
|
|
||||||
// Create the bar image.
|
// Create the 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))
|
||||||
bar.img.XSurfaceSet(bar.win.Id)
|
if err := bar.img.XSurfaceSet(bar.win.Id); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
bar.img.XDraw()
|
bar.img.XDraw()
|
||||||
|
|
||||||
|
bar.w = w
|
||||||
|
bar.h = h
|
||||||
|
|
||||||
// Load font.
|
// Load font.
|
||||||
// TODO: I don't *really* want to use `ttf` fonts but there
|
// TODO: I don't *really* want to use `ttf` fonts but there doesn't seem to
|
||||||
// doesn't seem to be any `pcf` Go library at the moment.
|
// be any `pcf` Go library at the moment. I have tried the plan9 fonts,
|
||||||
|
// which do work, but honestly it's a pain in the ass (read: impossible) to
|
||||||
|
// convert muh cure font.
|
||||||
f, err := os.Open(font)
|
f, err := os.Open(font)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -116,36 +119,30 @@ func initBar(x, y, w, h int, font string, fsize float64) (*Bar,
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
bar.fsize = fsize
|
bar.size = size
|
||||||
|
|
||||||
bar.w = w
|
|
||||||
bar.h = h
|
|
||||||
|
|
||||||
bar.block = new(sync.Map)
|
bar.block = new(sync.Map)
|
||||||
bar.redraw = make(chan *Block)
|
bar.redraw = make(chan *Block)
|
||||||
|
|
||||||
// Listen to mouse events and execute the required function.
|
// Listen to mouse events and execute the required function.
|
||||||
xevent.ButtonPressFun(func(_ *xgbutil.XUtil,
|
xevent.ButtonPressFun(func(_ *xgbutil.XUtil, ev xevent.ButtonPressEvent) {
|
||||||
ev xevent.ButtonPressEvent) {
|
|
||||||
// Determine what block the cursor is in.
|
// Determine what block the cursor is in.
|
||||||
// TODO: This feels a bit slow at the moment, can I improve
|
// TODO: This feels a bit slow at the moment, can I improve it?
|
||||||
// it?
|
|
||||||
var block *Block
|
var block *Block
|
||||||
bar.block.Range(func(name, i interface{}) bool {
|
bar.block.Range(func(name, i interface{}) bool {
|
||||||
block = i.(*Block)
|
block = i.(*Block)
|
||||||
// XXX: Hack for music block.
|
// XXX: Hack for music block.
|
||||||
if name == "music" {
|
if name == "music" {
|
||||||
tw, _ := xgraphics.Extents(bar.font, bar.fsize,
|
tw, _ := xgraphics.Extents(bar.font, bar.size, block.txt)
|
||||||
block.txt)
|
if ev.EventX > int16(block.x+(block.w-tw+(block.xoff*2))) && ev.
|
||||||
if ev.EventX > int16(block.x+(block.w-tw+(block.xoff*
|
EventX < int16(block.x+block.w) {
|
||||||
2))) && ev.EventX < int16(block.x+block.w) {
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
if ev.EventX > int16(block.x) && ev.EventX < int16(
|
if ev.EventX > int16(block.x) && ev.EventX < int16(block.x+block.
|
||||||
block.x+block.w) {
|
w) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
@ -159,9 +156,8 @@ func initBar(x, y, w, h int, font string, fsize float64) (*Bar,
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (bar *Bar) draw(block *Block) error {
|
func (bar *Bar) draw(block *Block) error {
|
||||||
// Calculate the required x coordinate for the different
|
// Calculate the required x coordinate for the different aligments.
|
||||||
// aligments.
|
tw, _ := xgraphics.Extents(bar.font, bar.size, block.txt)
|
||||||
tw, _ := xgraphics.Extents(bar.font, bar.fsize, block.txt)
|
|
||||||
var x int
|
var x int
|
||||||
switch block.align {
|
switch block.align {
|
||||||
case 'l':
|
case 'l':
|
||||||
@ -173,8 +169,7 @@ func (bar *Bar) draw(block *Block) error {
|
|||||||
case 'a':
|
case 'a':
|
||||||
x = (bar.w / 2) - (tw / 2)
|
x = (bar.w / 2) - (tw / 2)
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("draw %#U: Not a valid aligment rune",
|
return fmt.Errorf("draw %#U: Not a valid aligment rune", block.align)
|
||||||
block.align)
|
|
||||||
}
|
}
|
||||||
x += block.xoff
|
x += block.xoff
|
||||||
|
|
||||||
@ -193,12 +188,13 @@ func (bar *Bar) draw(block *Block) error {
|
|||||||
|
|
||||||
// Draw the text.
|
// Draw the text.
|
||||||
// TODO: Center text vertically automatically.
|
// TODO: Center text vertically automatically.
|
||||||
if _, _, err := block.img.Text(x, 6, hexToBGRA(block.fg),
|
if _, _, err := block.img.Text(x, 6, hexToBGRA(block.fg), bar.size, bar.
|
||||||
bar.fsize, bar.font, block.txt); err != nil {
|
font, block.txt); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
block.img.XDraw()
|
block.img.XDraw()
|
||||||
bar.img.XPaint(bar.win.Id)
|
bar.img.XPaint(bar.win.Id)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
27
block.go
27
block.go
@ -14,9 +14,9 @@ type Block struct {
|
|||||||
// The x coordinate and width of the block.
|
// The x coordinate and width of the block.
|
||||||
x, w int
|
x, w int
|
||||||
|
|
||||||
/// The aligment of the text, this can be `l` for left aligment,
|
// The aligment of the text, this can be `l` for left aligment, `c` for
|
||||||
// `c` for center aligment, `r` for right aligment and `a` for
|
// center aligment, `r` for right aligment and `a` for absolute center
|
||||||
// absolute center aligment.
|
// aligment.
|
||||||
align rune
|
align rune
|
||||||
|
|
||||||
// Additional x offset to further tweak the location of the text.
|
// Additional x offset to further tweak the location of the text.
|
||||||
@ -25,25 +25,33 @@ type Block struct {
|
|||||||
// The foreground and background colors in hex.
|
// The foreground and background colors in hex.
|
||||||
bg, fg string
|
bg, fg string
|
||||||
|
|
||||||
// A map with functions to execute on button events. Accepted
|
// A map with functions to execute on button events. Accepted button strings
|
||||||
// button strings are `button0` to `button5`
|
// are `button0` to `button5`
|
||||||
actions map[string]func()
|
actions map[string]func()
|
||||||
|
|
||||||
|
// The popup.
|
||||||
|
popup *Popup
|
||||||
|
|
||||||
// The sub-image that represents the block.
|
// The sub-image that represents the block.
|
||||||
img *xgraphics.Image
|
img *xgraphics.Image
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bar *Bar) initBlock(name, txt string, w int, align rune,
|
func (bar *Bar) initBlock(name, txt string, w int, align rune, xoff int, bg,
|
||||||
xoff int, bg, fg string) *Block {
|
fg string) *Block {
|
||||||
block := new(Block)
|
block := new(Block)
|
||||||
|
|
||||||
block.txt = txt
|
block.txt = txt
|
||||||
|
|
||||||
block.x = bar.xsum
|
block.x = bar.xsum
|
||||||
block.w = w
|
block.w = w
|
||||||
|
|
||||||
block.align = align
|
block.align = align
|
||||||
|
|
||||||
block.xoff = xoff
|
block.xoff = xoff
|
||||||
|
|
||||||
block.bg = bg
|
block.bg = bg
|
||||||
block.fg = fg
|
block.fg = fg
|
||||||
|
|
||||||
block.actions = map[string]func(){
|
block.actions = map[string]func(){
|
||||||
"button1": func() {},
|
"button1": func() {},
|
||||||
"button2": func() {},
|
"button2": func() {},
|
||||||
@ -51,8 +59,9 @@ func (bar *Bar) initBlock(name, txt string, w int, align rune,
|
|||||||
"button4": func() {},
|
"button4": func() {},
|
||||||
"button5": func() {},
|
"button5": func() {},
|
||||||
}
|
}
|
||||||
block.img = bar.img.SubImage(image.Rect(bar.xsum, 0, bar.xsum+w,
|
|
||||||
bar.h)).(*xgraphics.Image)
|
block.img = bar.img.SubImage(image.Rect(bar.xsum, 0, bar.xsum+w, bar.
|
||||||
|
h)).(*xgraphics.Image)
|
||||||
|
|
||||||
// Add the width of this block to the xsum.
|
// Add the width of this block to the xsum.
|
||||||
bar.xsum += w
|
bar.xsum += w
|
||||||
|
143
blocks.go
143
blocks.go
@ -17,8 +17,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func (bar *Bar) clockFun() {
|
func (bar *Bar) clockFun() {
|
||||||
block := bar.initBlock("clock", "?", 800, 'a', 0, "#445967",
|
block := bar.initBlock("clock", "?", 800, 'a', 0, "#445967", "#CCCCCC")
|
||||||
"#CCCCCC")
|
|
||||||
|
|
||||||
init := true
|
init := true
|
||||||
for {
|
for {
|
||||||
@ -38,23 +37,36 @@ func (bar *Bar) clockFun() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (bar *Bar) musicFun() error {
|
func (bar *Bar) musicFun() error {
|
||||||
block := bar.initBlock("music", "?", 660, 'r', -10, "#3C4F5B",
|
block := bar.initBlock("music", "?", 660, 'r', -13, "#3C4F5B", "#CCCCCC")
|
||||||
"#CCCCCC")
|
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
|
//popup.draw()
|
||||||
|
} else {
|
||||||
|
block.popup = block.popup.destroy()
|
||||||
|
}
|
||||||
|
}
|
||||||
block.actions["button3"] = func() {
|
block.actions["button3"] = func() {
|
||||||
conn, err := mpd.Dial("tcp", ":6600")
|
conn, err := mpd.Dial("tcp", ":6600")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Print(err)
|
log.Print(err)
|
||||||
}
|
}
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
status, err := conn.Status()
|
status, err := conn.Status()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Print(err)
|
log.Print(err)
|
||||||
}
|
}
|
||||||
if status["state"] == "pause" {
|
|
||||||
conn.Pause(false)
|
if err := conn.Pause(status["state"] != "pause"); err != nil {
|
||||||
} else {
|
log.Print(err)
|
||||||
conn.Pause(true)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
block.actions["button4"] = func() {
|
block.actions["button4"] = func() {
|
||||||
@ -62,16 +74,22 @@ func (bar *Bar) musicFun() error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
log.Print(err)
|
log.Print(err)
|
||||||
}
|
}
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
conn.Previous()
|
if err := conn.Previous(); err != nil {
|
||||||
|
log.Print(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
block.actions["button5"] = func() {
|
block.actions["button5"] = func() {
|
||||||
conn, err := mpd.Dial("tcp", ":6600")
|
conn, err := mpd.Dial("tcp", ":6600")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Print(err)
|
log.Print(err)
|
||||||
}
|
}
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
conn.Next()
|
if err := conn.Next(); err != nil {
|
||||||
|
log.Print(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
watcher, err := mpd.NewWatcher("tcp", ":6600", "", "player")
|
watcher, err := mpd.NewWatcher("tcp", ":6600", "", "player")
|
||||||
@ -87,8 +105,7 @@ func (bar *Bar) musicFun() error {
|
|||||||
}
|
}
|
||||||
init = false
|
init = false
|
||||||
|
|
||||||
// TODO: Is it maybe possible to not create a new connection
|
// TODO: Is it maybe possible to not create a new connection each loop?
|
||||||
// each loop?
|
|
||||||
conn, err = mpd.Dial("tcp", ":6600")
|
conn, err = mpd.Dial("tcp", ":6600")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Print(err)
|
log.Print(err)
|
||||||
@ -106,6 +123,7 @@ func (bar *Bar) musicFun() error {
|
|||||||
log.Print(err)
|
log.Print(err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
var state string
|
var state string
|
||||||
if status["state"] == "pause" {
|
if status["state"] == "pause" {
|
||||||
state = "[paused] "
|
state = "[paused] "
|
||||||
@ -122,17 +140,16 @@ func (bar *Bar) musicFun() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (bar *Bar) todoFun() {
|
func (bar *Bar) todoFun() {
|
||||||
block := bar.initBlock("todo", "?", 29, 'c', 0, "#5394C9",
|
block := bar.initBlock("todo", "?", 29, 'c', 0, "#5394C9", "#FFFFFF")
|
||||||
"#FFFFFF")
|
|
||||||
|
|
||||||
watcher, err := fsnotify.NewWatcher()
|
watcher, err := fsnotify.NewWatcher()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
if err := watcher.Add("/home/onodera/todo"); err != nil {
|
if err := watcher.Add("/home/onodera/.todo"); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
file, err := os.Open("/home/onodera/todo")
|
file, err := os.Open("/home/onodera/.todo")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -218,12 +235,11 @@ func (bar *Bar) weatherFun() {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
func (bar *Bar) windowFun() {
|
func (bar *Bar) windowFun() {
|
||||||
block := bar.initBlock("window", "?", 220, 'c', 0, "#37BF8D",
|
block := bar.initBlock("window", "?", 220, 'c', 0, "#37BF8D", "#FFFFFF")
|
||||||
"#FFFFFF")
|
|
||||||
|
|
||||||
// TODO: I'm not sure how I can use init here?
|
// TODO: I'm not sure how I can use init (to prevent a black bar) here?
|
||||||
xevent.PropertyNotifyFun(func(_ *xgbutil.XUtil,
|
xevent.PropertyNotifyFun(func(_ *xgbutil.XUtil, ev xevent.
|
||||||
ev xevent.PropertyNotifyEvent) {
|
PropertyNotifyEvent) {
|
||||||
atom, err := xprop.Atm(bar.xu, "_NET_ACTIVE_WINDOW")
|
atom, err := xprop.Atm(bar.xu, "_NET_ACTIVE_WINDOW")
|
||||||
if ev.Atom != atom {
|
if ev.Atom != atom {
|
||||||
return
|
return
|
||||||
@ -256,34 +272,32 @@ func (bar *Bar) windowFun() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (bar *Bar) workspaceFun() {
|
func (bar *Bar) workspaceFun() {
|
||||||
blockwww := bar.initBlock("www", "www", 74, 'c', 0, "#5394C9",
|
blockWWW := bar.initBlock("www", "www", 74, 'c', 0, "#5394C9", "#FFFFFF")
|
||||||
"#FFFFFF")
|
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 {
|
||||||
log.Println(err)
|
log.Println(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
blockirc := bar.initBlock("irc", "irc", 67, 'c', 0, "#5394C9",
|
blockIRC := bar.initBlock("irc", "irc", 67, 'c', 0, "#5394C9", "#FFFFFF")
|
||||||
"#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 {
|
||||||
log.Println(err)
|
log.Println(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
blocksrc := bar.initBlock("src", "src", 70, 'c', 0, "#5394C9",
|
blockSRC := bar.initBlock("src", "src", 70, 'c', 0, "#5394C9", "#FFFFFF")
|
||||||
"#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 {
|
||||||
log.Println(err)
|
log.Println(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: I'm not sure how I can use init here?
|
// TODO: I'm not sure how I can use init (to prevent a black bar) here?
|
||||||
var owsp uint
|
var owsp uint
|
||||||
xevent.PropertyNotifyFun(func(_ *xgbutil.XUtil,
|
var pwsp, nwsp int
|
||||||
ev xevent.PropertyNotifyEvent) {
|
xevent.PropertyNotifyFun(func(_ *xgbutil.XUtil, ev xevent.
|
||||||
|
PropertyNotifyEvent) {
|
||||||
atom, err := xprop.Atm(bar.xu, "_NET_CURRENT_DESKTOP")
|
atom, err := xprop.Atm(bar.xu, "_NET_CURRENT_DESKTOP")
|
||||||
if ev.Atom != atom {
|
if ev.Atom != atom {
|
||||||
return
|
return
|
||||||
@ -298,27 +312,56 @@ func (bar *Bar) workspaceFun() {
|
|||||||
log.Print(err)
|
log.Print(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch wsp {
|
||||||
|
case 0:
|
||||||
|
blockWWW.bg = "#72A7D3"
|
||||||
|
blockIRC.bg = "#5394C9"
|
||||||
|
blockSRC.bg = "#5394C9"
|
||||||
|
|
||||||
|
pwsp = 2
|
||||||
|
nwsp = 1
|
||||||
|
case 1:
|
||||||
|
blockWWW.bg = "#5394C9"
|
||||||
|
blockIRC.bg = "#72A7D3"
|
||||||
|
blockSRC.bg = "#5394C9"
|
||||||
|
|
||||||
|
pwsp = 0
|
||||||
|
nwsp = 2
|
||||||
|
case 2:
|
||||||
|
blockWWW.bg = "#5394C9"
|
||||||
|
blockIRC.bg = "#5394C9"
|
||||||
|
blockSRC.bg = "#72A7D3"
|
||||||
|
|
||||||
|
pwsp = 1
|
||||||
|
nwsp = 0
|
||||||
|
}
|
||||||
|
|
||||||
if owsp == wsp {
|
if owsp == wsp {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
owsp = wsp
|
owsp = wsp
|
||||||
|
|
||||||
switch wsp {
|
bar.redraw <- blockWWW
|
||||||
case 0:
|
bar.redraw <- blockIRC
|
||||||
blockwww.bg = "#72A7D3"
|
bar.redraw <- blockSRC
|
||||||
blockirc.bg = "#5394C9"
|
|
||||||
blocksrc.bg = "#5394C9"
|
|
||||||
case 1:
|
|
||||||
blockwww.bg = "#5394C9"
|
|
||||||
blockirc.bg = "#72A7D3"
|
|
||||||
blocksrc.bg = "#5394C9"
|
|
||||||
case 2:
|
|
||||||
blockwww.bg = "#5394C9"
|
|
||||||
blockirc.bg = "#5394C9"
|
|
||||||
blocksrc.bg = "#72A7D3"
|
|
||||||
}
|
|
||||||
bar.redraw <- blockwww
|
|
||||||
bar.redraw <- blockirc
|
|
||||||
bar.redraw <- blocksrc
|
|
||||||
}).Connect(bar.xu, bar.xu.RootWin())
|
}).Connect(bar.xu, bar.xu.RootWin())
|
||||||
|
|
||||||
|
prevFun := func() {
|
||||||
|
if err := ewmh.CurrentDesktopReq(bar.xu, pwsp); err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
nextFun := func() {
|
||||||
|
if err := ewmh.CurrentDesktopReq(bar.xu, nwsp); err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
blockWWW.actions["button4"] = prevFun
|
||||||
|
blockWWW.actions["button5"] = nextFun
|
||||||
|
blockIRC.actions["button4"] = prevFun
|
||||||
|
blockIRC.actions["button5"] = nextFun
|
||||||
|
blockSRC.actions["button4"] = prevFun
|
||||||
|
blockSRC.actions["button5"] = nextFun
|
||||||
}
|
}
|
||||||
|
3
main.go
3
main.go
@ -6,8 +6,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
bar, err := initBar(0, 0, 1920, 29,
|
bar, err := initBar(0, 0, 1920, 29, "/home/onodera/.fonts/cure.tff.bak", 11)
|
||||||
"/home/onodera/.fonts/cure.ttf", 11)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
98
popup.go
Normal file
98
popup.go
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"image"
|
||||||
|
|
||||||
|
"github.com/BurntSushi/xgb/xproto"
|
||||||
|
"github.com/BurntSushi/xgbutil/ewmh"
|
||||||
|
"github.com/BurntSushi/xgbutil/xgraphics"
|
||||||
|
"github.com/BurntSushi/xgbutil/xwindow"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Popup is a struct with information about the popup.
|
||||||
|
type Popup struct {
|
||||||
|
// The popup window and image.
|
||||||
|
win *xwindow.Window
|
||||||
|
img *xgraphics.Image
|
||||||
|
|
||||||
|
// The width and height of the popup.
|
||||||
|
w, h int
|
||||||
|
|
||||||
|
// The foreground and background colors in hex.
|
||||||
|
bg, fg string
|
||||||
|
|
||||||
|
// A channel where the popup should be send to to once its ready
|
||||||
|
// to be redrawn.
|
||||||
|
redraw chan *Popup
|
||||||
|
}
|
||||||
|
|
||||||
|
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.
|
||||||
|
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)
|
||||||
|
|
||||||
|
// 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?
|
||||||
|
if err := ewmh.WmWindowTypeSet(bar.xu, popup.win.Id, []string{
|
||||||
|
"_NET_WM_WINDOW_TYPE_DOCK"}); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := ewmh.WmStateSet(bar.xu, popup.win.Id, []string{
|
||||||
|
"_NET_WM_STATE_STICKY"}); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
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 {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Map window.
|
||||||
|
popup.win.Map()
|
||||||
|
|
||||||
|
// TODO: Moving the window is again a hack to keep OpenBox happy.
|
||||||
|
popup.win.Move(x, y)
|
||||||
|
|
||||||
|
// Create the bar image.
|
||||||
|
popup.img = xgraphics.New(bar.xu, image.Rect(0, 0, w, h))
|
||||||
|
popup.img.XSurfaceSet(popup.win.Id)
|
||||||
|
popup.img.XDraw()
|
||||||
|
|
||||||
|
popup.w = w
|
||||||
|
popup.h = h
|
||||||
|
|
||||||
|
popup.bg = bg
|
||||||
|
popup.fg = fg
|
||||||
|
|
||||||
|
popup.redraw = make(chan *Popup)
|
||||||
|
|
||||||
|
return popup, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//func (popup *Popup) draw() error {
|
||||||
|
|
||||||
|
//}
|
||||||
|
|
||||||
|
// TODO: I don't know if this actually frees memory and shit.
|
||||||
|
func (popup *Popup) destroy() *Popup {
|
||||||
|
popup.win.Destroy()
|
||||||
|
popup.img.Destroy()
|
||||||
|
|
||||||
|
close(popup.redraw)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
1
popups.go
Normal file
1
popups.go
Normal file
@ -0,0 +1 @@
|
|||||||
|
package main
|
Loading…
Reference in New Issue
Block a user