stone/backends/x/x.go

142 lines
3.0 KiB
Go

package x
import "image"
import "github.com/jezek/xgbutil"
// import "github.com/jezek/xgbutil/ewmh"
import "github.com/jezek/xgbutil/xevent"
import "github.com/jezek/xgbutil/xwindow"
import "github.com/jezek/xgbutil/xgraphics"
import "git.tebibyte.media/sashakoshka/stone"
type Backend struct {
application *stone.Application
config *stone.Config
connection *xgbutil.XUtil
window *xwindow.Window
canvas *xgraphics.Image
channel chan(stone.Event)
ping struct {
before chan(struct { })
after chan(struct { })
quit chan(struct { })
}
metrics struct {
cellWidth int
cellHeight int
padding int
paddingX int
paddingY int
descent int
}
}
func (backend *Backend) Run (channel chan(stone.Event)) {
backend.channel = channel
for {
select {
case <- backend.ping.before:
<- backend.ping.after
case <- backend.ping.quit:
backend.shutDown()
return
}
}
}
func (backend *Backend) SetTitle (title string) {
}
func (backend *Backend) SetIcon (icons []image.Image) {
}
func (backend *Backend) shutDown () {
backend.channel <- stone.EventQuit { }
}
// calculateWindowSize calculates window bounds based on the internal buffer
// size.
func (backend *Backend) calculateWindowSize () (x, y int) {
width, height := backend.application.Size()
x =
width * backend.metrics.cellWidth +
backend.metrics.padding * 2
y =
height * backend.metrics.cellHeight +
backend.metrics.padding * 2
return
}
func (backend *Backend) bindCanvas () {
backend.canvas.XSurfaceSet(backend.window.Id)
backend.canvas.XDraw()
backend.canvas.XPaint(backend.window.Id)
}
// factory instantiates an X backend.
func factory (application *stone.Application) (output stone.Backend, err error) {
backend := &Backend {
application: application,
config: application.Config(),
}
// calculate metrics
// TODO: base these off of font metrics
backend.metrics.cellWidth = 8
backend.metrics.cellHeight = 16
backend.metrics.padding =
backend.config.Padding() *
backend.metrics.cellHeight
backend.metrics.paddingX = backend.metrics.padding
backend.metrics.paddingY = backend.metrics.padding
// connect to X
backend.connection, err = xgbutil.NewConn()
if err != nil { return }
backend.window, err = xwindow.Generate(backend.connection)
if err != nil { return }
// create the window
windowWidth, windowHeight := backend.calculateWindowSize()
backend.window.Create (
backend.connection.RootWin(),
0, 0, windowWidth, windowHeight,
0)
backend.window.Map()
// create a canvas
backend.canvas = xgraphics.New (
backend.connection,
image.Rect (
0, 0,
windowWidth,
windowHeight))
backend.bindCanvas()
// attatch graceful close handler
backend.window.WMGracefulClose (func (window *xwindow.Window) {
backend.window.Destroy()
backend.shutDown()
})
// start event loop
backend.ping.before,
backend.ping.after,
backend.ping.quit = xevent.MainPing(backend.connection)
output = backend
return
}
// init registers this backend when the program starts.
func init () {
stone.RegisterBackend(factory)
}