x/backend.go

85 lines
1.7 KiB
Go

package x
import "git.tebibyte.media/tomo/tomo"
import "git.tebibyte.media/tomo/xgbkb"
import "github.com/jezek/xgbutil"
import "github.com/jezek/xgb/xproto"
import "github.com/jezek/xgbutil/xevent"
import "github.com/jezek/xgbutil/keybind"
import "github.com/jezek/xgbutil/mousebind"
type Backend struct {
x *xgbutil.XUtil
doChannel chan func()
windows map[xproto.Window] *window
open bool
}
func NewBackend () (tomo.Backend, error) {
backend := &Backend {
doChannel: make(chan func (), 32),
windows: make(map[xproto.Window] *window),
open: true,
}
var err error
backend.x, err = xgbutil.NewConn()
if err != nil { return nil, err }
keybind .Initialize(backend.x)
xgbkb .Initialize(backend.x)
mousebind.Initialize(backend.x)
return backend, nil
}
func (backend *Backend) Run () error {
backend.assert()
pingBefore,
pingAfter,
pingQuit := xevent.MainPing(backend.x)
for {
select {
case <- pingBefore:
<- pingAfter
case callback := <- backend.doChannel:
callback()
case <- pingQuit:
return nil // FIXME: if we exited due to an error say so
}
backend.afterEvent()
}
}
func (backend *Backend) Stop () {
backend.assert()
if !backend.open { return }
backend.open = false
toClose := []*window { }
for _, panel := range backend.windows {
toClose = append(toClose, panel)
}
for _, panel := range toClose {
panel.Close()
}
xevent.Quit(backend.x)
backend.x.Conn().Close()
}
func (backend *Backend) Do (callback func ()) {
backend.assert()
backend.doChannel <- callback
}
func (backend *Backend) assert () {
if backend == nil { panic("nil backend") }
}
func (backend *Backend) afterEvent () {
for _, window := range backend.windows {
window.afterEvent()
}
}