x backend has an event loop
This commit is contained in:
parent
0c5118b59a
commit
c93ca17fe5
@ -44,7 +44,13 @@ func (application *Application) Run () (
|
|||||||
if err != nil { return }
|
if err != nil { return }
|
||||||
|
|
||||||
channel = make(chan(Event))
|
channel = make(chan(Event))
|
||||||
application.backend.Run(channel)
|
go application.backend.Run(channel)
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Config returns a pointer to the application's configuration.
|
||||||
|
func (application *Application) Config () (config *Config) {
|
||||||
|
config = &application.config
|
||||||
|
return
|
||||||
|
}
|
||||||
|
109
backends/x/x.go
109
backends/x/x.go
@ -4,25 +4,49 @@ import "image"
|
|||||||
|
|
||||||
import "github.com/jezek/xgbutil"
|
import "github.com/jezek/xgbutil"
|
||||||
// import "github.com/jezek/xgbutil/ewmh"
|
// import "github.com/jezek/xgbutil/ewmh"
|
||||||
// import "github.com/jezek/xgbutil/xevent"
|
import "github.com/jezek/xgbutil/xevent"
|
||||||
import "github.com/jezek/xgbutil/xwindow"
|
import "github.com/jezek/xgbutil/xwindow"
|
||||||
import "github.com/jezek/xgbutil/xgraphics"
|
import "github.com/jezek/xgbutil/xgraphics"
|
||||||
|
|
||||||
import "git.tebibyte.media/sashakoshka/stone"
|
import "git.tebibyte.media/sashakoshka/stone"
|
||||||
|
|
||||||
type Backend struct {
|
type Backend struct {
|
||||||
connection *xgbutil.Conn
|
application *stone.Application
|
||||||
window *xwindow.Window
|
config *stone.Config
|
||||||
canvas *xgraphics.Image
|
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)) {
|
func (backend *Backend) Run (channel chan(stone.Event)) {
|
||||||
// TODO: setup
|
backend.channel = channel
|
||||||
go backend.mainLoop(channel)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (backend *Backend) mainLoop (channel chan(stone.Event)) {
|
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) SetTitle (title string) {
|
||||||
@ -32,3 +56,72 @@ func (backend *Backend) SetTitle (title string) {
|
|||||||
func (backend *Backend) SetIcon (icons []image.Image) {
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 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()
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
}
|
||||||
|
@ -4,7 +4,7 @@ import "os"
|
|||||||
import "fmt"
|
import "fmt"
|
||||||
import "time"
|
import "time"
|
||||||
import "git.tebibyte.media/sashakoshka/stone"
|
import "git.tebibyte.media/sashakoshka/stone"
|
||||||
// import _ "git.tebibyte.media/sashakoshka/stone/backends/x"
|
import _ "git.tebibyte.media/sashakoshka/stone/backends/x"
|
||||||
|
|
||||||
func main () {
|
func main () {
|
||||||
application := &stone.Application { }
|
application := &stone.Application { }
|
||||||
@ -40,51 +40,3 @@ func main () {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// func run (application *stone.Application) {
|
|
||||||
// currentTime := time.Time { }
|
|
||||||
// frameDelay := time.Second / 2
|
|
||||||
// textBuffer := ""
|
|
||||||
//
|
|
||||||
// for {
|
|
||||||
// typed := application.Typed()
|
|
||||||
// textBuffer += typed
|
|
||||||
//
|
|
||||||
// shouldRender :=
|
|
||||||
// application.Resized() ||
|
|
||||||
// time.Since(currentTime) > frameDelay ||
|
|
||||||
// len(typed) > 0
|
|
||||||
//
|
|
||||||
// if shouldRender {
|
|
||||||
// currentTime = time.Now()
|
|
||||||
//
|
|
||||||
// application.ResetDot()
|
|
||||||
// fmt.Fprintln(application, "hellorld!")
|
|
||||||
//
|
|
||||||
// hour := currentTime.Hour()
|
|
||||||
// minute := currentTime.Minute()
|
|
||||||
// second := currentTime.Second()
|
|
||||||
//
|
|
||||||
// application.SetRune(0, 1, rune(hour / 10 + 48))
|
|
||||||
// application.SetRune(1, 1, rune(hour % 10 + 48))
|
|
||||||
// application.SetRune(2, 1, ':')
|
|
||||||
// application.SetRune(3, 1, rune(minute / 10 + 48))
|
|
||||||
// application.SetRune(4, 1, rune(minute % 10 + 48))
|
|
||||||
// application.SetRune(5, 1, ':')
|
|
||||||
// application.SetRune(6, 1, rune(second / 10 + 48))
|
|
||||||
// application.SetRune(7, 1, rune(second % 10 + 48))
|
|
||||||
//
|
|
||||||
// application.Dot.X = 0
|
|
||||||
// application.Dot.Y = 2
|
|
||||||
// fmt.Fprintln(application, textBuffer)
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if application.Pressed(stone.MouseButtonLeft) {
|
|
||||||
// x, y := application.MousePosition()
|
|
||||||
// application.SetRune(x, y, '#')
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if !application.Await(frameDelay) { break }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
Loading…
Reference in New Issue
Block a user