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() } }