Merge pull request 'redo-event-system' (#1) from redo-event-system into main
Reviewed-on: #1
This commit is contained in:
commit
acbf2a3954
@ -1,6 +1,5 @@
|
|||||||
package stone
|
package stone
|
||||||
|
|
||||||
import "time"
|
|
||||||
import "image/color"
|
import "image/color"
|
||||||
|
|
||||||
// Application represents an application.
|
// Application represents an application.
|
||||||
@ -12,12 +11,6 @@ type Application struct {
|
|||||||
config Config
|
config Config
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetSize sets the application's buffer size. This may or may not change the
|
|
||||||
// size of the window, depending on the backend used.
|
|
||||||
func (application *Application) SetSize (width, height int) {
|
|
||||||
application.DamageBuffer.SetSize(width, height)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetTitle sets the application's title. If in a window, it will appear as the
|
// SetTitle sets the application's title. If in a window, it will appear as the
|
||||||
// window's name.
|
// window's name.
|
||||||
func (application *Application) SetTitle (title string) {
|
func (application *Application) SetTitle (title string) {
|
||||||
@ -25,12 +18,10 @@ func (application *Application) SetTitle (title string) {
|
|||||||
application.backend.SetTitle(title)
|
application.backend.SetTitle(title)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run initializes the application, and then calls callback. Operations inside
|
// Run initializes the application, starts it, and then returns a channel that
|
||||||
// of callback are allowed to interact with the application. Depending on the
|
// broadcasts events. If no suitable backend can be found, an error is returned.
|
||||||
// backend used, this function may bind to the main thread.
|
func (application *Application) Run () (
|
||||||
func (application *Application) Run (
|
channel chan(Event),
|
||||||
callback func (application *Application),
|
|
||||||
) (
|
|
||||||
err error,
|
err error,
|
||||||
) {
|
) {
|
||||||
// default values for certain parameters
|
// default values for certain parameters
|
||||||
@ -51,29 +42,10 @@ func (application *Application) Run (
|
|||||||
|
|
||||||
application.backend, err = instantiateBackend(application)
|
application.backend, err = instantiateBackend(application)
|
||||||
if err != nil { return }
|
if err != nil { return }
|
||||||
application.backend.Run(callback)
|
|
||||||
|
|
||||||
return
|
channel = make(chan(Event))
|
||||||
}
|
go application.backend.Run(channel)
|
||||||
|
|
||||||
// Await blocks until an event is recieved, or until the specified timeout has
|
|
||||||
// elapsed. If the timeout is zero, it will wait forever. This function returns
|
|
||||||
// true if the backend is still active, and false if it has closed.
|
|
||||||
func (application *Application) Await (timeout time.Duration) (keepRunning bool) {
|
|
||||||
keepRunning = application.backend.Await(timeout)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Poll updates the window and checks for new events. This function returns true
|
|
||||||
// if the backend is still active, and false if it has closed.
|
|
||||||
func (application *Application) Poll () (keepRunning bool) {
|
|
||||||
keepRunning = application.backend.Poll()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Title returns the application's title.
|
|
||||||
func (application *Application) Title () (title string) {
|
|
||||||
title = application.title
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,41 +54,3 @@ func (application *Application) Config () (config *Config) {
|
|||||||
config = &application.config
|
config = &application.config
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// JustPressed returns true if the specified button is pressed, but was not
|
|
||||||
// pressed the last time events were checked.
|
|
||||||
func (application *Application) JustPressed (button Button) (pressed bool) {
|
|
||||||
pressed = application.backend.JustPressed(button)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// JustReleased returns true if the specified button
|
|
||||||
func (application *Application) JustReleased (button Button) (released bool) {
|
|
||||||
released = application.backend.JustReleased(button)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (application *Application) Pressed (button Button) (pressed bool) {
|
|
||||||
pressed = application.backend.Pressed(button)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (application *Application) Repeated (button Button) (repeated bool) {
|
|
||||||
repeated = application.backend.Repeated(button)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (application *Application) Typed () (text string) {
|
|
||||||
text = application.backend.Typed()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (application *Application) Resized () (resized bool) {
|
|
||||||
resized = application.backend.Resized()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (application *Application) MousePosition () (x, y int) {
|
|
||||||
x, y = application.backend.MousePosition()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
14
backend.go
14
backend.go
@ -1,20 +1,12 @@
|
|||||||
package stone
|
package stone
|
||||||
|
|
||||||
import "time"
|
import "image"
|
||||||
import "errors"
|
import "errors"
|
||||||
|
|
||||||
type Backend interface {
|
type Backend interface {
|
||||||
Run (callback func (application *Application)) ()
|
Run (channel chan(Event))
|
||||||
Await (timeout time.Duration) (keepRunning bool)
|
|
||||||
Poll () (keepRunning bool)
|
|
||||||
SetTitle (title string)
|
SetTitle (title string)
|
||||||
JustPressed (button Button) (pressed bool)
|
SetIcon (icons []image.Image)
|
||||||
JustReleased (button Button) (released bool)
|
|
||||||
Pressed (button Button) (pressed bool)
|
|
||||||
Repeated (button Button) (repeated bool)
|
|
||||||
Typed () (text string)
|
|
||||||
Resized () (resized bool)
|
|
||||||
MousePosition () (x, y int)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type BackendFactory func (application *Application) (backend Backend, err error)
|
type BackendFactory func (application *Application) (backend Backend, err error)
|
||||||
|
127
backends/x/x.go
Normal file
127
backends/x/x.go
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
}
|
12
event.go
Normal file
12
event.go
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
package stone
|
||||||
|
|
||||||
|
type Event interface { }
|
||||||
|
|
||||||
|
type EventQuit struct { }
|
||||||
|
type EventPress Button
|
||||||
|
type EventRelease Button
|
||||||
|
type EventResize struct { }
|
||||||
|
type EventMouseMove struct {
|
||||||
|
X int
|
||||||
|
Y int
|
||||||
|
}
|
@ -1,31 +1,25 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
|
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/pixel"
|
import _ "git.tebibyte.media/sashakoshka/stone/backends/x"
|
||||||
|
|
||||||
func main () {
|
func main () {
|
||||||
application := stone.Application { }
|
application := &stone.Application { }
|
||||||
err := application.Run(run)
|
channel, err := application.Run()
|
||||||
if err != nil { panic(err) }
|
if err != nil { panic(err) }
|
||||||
}
|
|
||||||
|
|
||||||
func run (application *stone.Application) {
|
|
||||||
currentTime := time.Time { }
|
currentTime := time.Time { }
|
||||||
frameDelay := time.Second / 2
|
|
||||||
textBuffer := ""
|
|
||||||
|
|
||||||
for {
|
for {
|
||||||
typed := application.Typed()
|
event := <- channel
|
||||||
textBuffer += typed
|
switch event.(type) {
|
||||||
|
case stone.EventQuit:
|
||||||
|
os.Exit(0)
|
||||||
|
|
||||||
shouldRender :=
|
case stone.EventResize:
|
||||||
application.Resized() ||
|
|
||||||
time.Since(currentTime) > frameDelay ||
|
|
||||||
len(typed) > 0
|
|
||||||
|
|
||||||
if shouldRender {
|
|
||||||
currentTime = time.Now()
|
currentTime = time.Now()
|
||||||
|
|
||||||
application.ResetDot()
|
application.ResetDot()
|
||||||
@ -43,18 +37,6 @@ func run (application *stone.Application) {
|
|||||||
application.SetRune(5, 1, ':')
|
application.SetRune(5, 1, ':')
|
||||||
application.SetRune(6, 1, rune(second / 10 + 48))
|
application.SetRune(6, 1, rune(second / 10 + 48))
|
||||||
application.SetRune(7, 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 }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
4
go.mod
4
go.mod
@ -4,14 +4,18 @@ go 1.18
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/faiface/pixel v0.10.0
|
github.com/faiface/pixel v0.10.0
|
||||||
|
github.com/jezek/xgbutil v0.0.0-20210302171758-530099784e66
|
||||||
golang.org/x/image v0.0.0-20190523035834-f03afa92d3ff
|
golang.org/x/image v0.0.0-20190523035834-f03afa92d3ff
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/BurntSushi/freetype-go v0.0.0-20160129220410-b763ddbfe298 // indirect
|
||||||
|
github.com/BurntSushi/graphics-go v0.0.0-20160129215708-b43f31a4a966 // indirect
|
||||||
github.com/faiface/glhf v0.0.0-20181018222622-82a6317ac380 // indirect
|
github.com/faiface/glhf v0.0.0-20181018222622-82a6317ac380 // indirect
|
||||||
github.com/faiface/mainthread v0.0.0-20171120011319-8b78f0a41ae3 // indirect
|
github.com/faiface/mainthread v0.0.0-20171120011319-8b78f0a41ae3 // indirect
|
||||||
github.com/go-gl/gl v0.0.0-20190320180904-bf2b1f2f34d7 // indirect
|
github.com/go-gl/gl v0.0.0-20190320180904-bf2b1f2f34d7 // indirect
|
||||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72 // indirect
|
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72 // indirect
|
||||||
github.com/go-gl/mathgl v0.0.0-20190416160123-c4601bc793c7 // indirect
|
github.com/go-gl/mathgl v0.0.0-20190416160123-c4601bc793c7 // indirect
|
||||||
|
github.com/jezek/xgb v1.1.0 // indirect
|
||||||
github.com/pkg/errors v0.8.1 // indirect
|
github.com/pkg/errors v0.8.1 // indirect
|
||||||
)
|
)
|
||||||
|
9
go.sum
9
go.sum
@ -1,3 +1,7 @@
|
|||||||
|
github.com/BurntSushi/freetype-go v0.0.0-20160129220410-b763ddbfe298 h1:1qlsVAQJXZHsaM8b6OLVo6muQUQd4CwkH/D3fnnbHXA=
|
||||||
|
github.com/BurntSushi/freetype-go v0.0.0-20160129220410-b763ddbfe298/go.mod h1:D+QujdIlUNfa0igpNMk6UIvlb6C252URs4yupRUV4lQ=
|
||||||
|
github.com/BurntSushi/graphics-go v0.0.0-20160129215708-b43f31a4a966 h1:lTG4HQym5oPKjL7nGs+csTgiDna685ZXjxijkne828g=
|
||||||
|
github.com/BurntSushi/graphics-go v0.0.0-20160129215708-b43f31a4a966/go.mod h1:Mid70uvE93zn9wgF92A/r5ixgnvX8Lh68fxp9KQBaI0=
|
||||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/faiface/glhf v0.0.0-20181018222622-82a6317ac380 h1:FvZ0mIGh6b3kOITxUnxS3tLZMh7yEoHo75v3/AgUqg0=
|
github.com/faiface/glhf v0.0.0-20181018222622-82a6317ac380 h1:FvZ0mIGh6b3kOITxUnxS3tLZMh7yEoHo75v3/AgUqg0=
|
||||||
@ -12,7 +16,12 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72 h1:b+9H1GAsx5
|
|||||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||||
github.com/go-gl/mathgl v0.0.0-20190416160123-c4601bc793c7 h1:THttjeRn1iiz69E875U6gAik8KTWk/JYAHoSVpUxBBI=
|
github.com/go-gl/mathgl v0.0.0-20190416160123-c4601bc793c7 h1:THttjeRn1iiz69E875U6gAik8KTWk/JYAHoSVpUxBBI=
|
||||||
github.com/go-gl/mathgl v0.0.0-20190416160123-c4601bc793c7/go.mod h1:yhpkQzEiH9yPyxDUGzkmgScbaBVlhC06qodikEM0ZwQ=
|
github.com/go-gl/mathgl v0.0.0-20190416160123-c4601bc793c7/go.mod h1:yhpkQzEiH9yPyxDUGzkmgScbaBVlhC06qodikEM0ZwQ=
|
||||||
|
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
|
||||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
|
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
|
||||||
|
github.com/jezek/xgb v1.1.0 h1:wnpxJzP1+rkbGclEkmwpVFQWpuE2PUGNUzP8SbfFobk=
|
||||||
|
github.com/jezek/xgb v1.1.0/go.mod h1:nrhwO0FX/enq75I7Y7G8iN1ubpSGZEiA3v9e9GyRFlk=
|
||||||
|
github.com/jezek/xgbutil v0.0.0-20210302171758-530099784e66 h1:+wPhoJD8EH0/bXipIq8Lc2z477jfox9zkXPCJdhvHj8=
|
||||||
|
github.com/jezek/xgbutil v0.0.0-20210302171758-530099784e66/go.mod h1:KACeV+k6b+aoLTVrrurywEbu3UpqoQcQywj4qX8aQKM=
|
||||||
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
|
Loading…
Reference in New Issue
Block a user