aboutsummaryrefslogtreecommitdiffstats
path: root/win
diff options
context:
space:
mode:
authorfaiface <faiface@ksp.sk>2017-08-29 00:35:28 +0200
committerfaiface <faiface@ksp.sk>2017-08-29 00:35:28 +0200
commit09db3d0b721685fda1cee71833ec4dd0fe1b4c9a (patch)
tree7473dfeb9d1b4664c25be1e7cc939a804855c650 /win
parent0c433c89a218c428cbc6dc093d4b4d6dd8174114 (diff)
downloadgui-09db3d0b721685fda1cee71833ec4dd0fe1b4c9a.zip
start over, concurrency full on
Diffstat (limited to 'win')
-rw-r--r--win/win.go187
1 files changed, 59 insertions, 128 deletions
diff --git a/win/win.go b/win/win.go
index 8b5f917..ccecc94 100644
--- a/win/win.go
+++ b/win/win.go
@@ -6,7 +6,7 @@ import (
"runtime"
"time"
- "github.com/faiface/gui/event"
+ "github.com/faiface/gui/layout"
"github.com/faiface/mainthread"
"github.com/go-gl/gl/v2.1/gl"
"github.com/go-gl/glfw/v3.2/glfw"
@@ -51,14 +51,10 @@ func New(opts ...Option) (*Win, error) {
}
w := &Win{
- events: make(chan struct {
- event string
- result chan<- bool
- }),
- flushes: make(chan struct {
- r image.Rectangle
- flushed chan<- struct{}
- }),
+ event: make(chan layout.EventConsume),
+ draw: make(chan layout.ImageFlush),
+ newSize: make(chan image.Rectangle),
+ finish: make(chan struct{}),
}
var err error
@@ -69,29 +65,15 @@ func New(opts ...Option) (*Win, error) {
return nil, err
}
- var (
- cancelOpenGLThread = make(chan chan<- struct{})
- cancelEventDispatch = make(chan chan<- struct{})
- cancelEventThread = make(chan chan<- struct{})
- )
-
- w.cancels = []chan<- chan<- struct{}{
- cancelEventThread,
- cancelEventDispatch,
- cancelOpenGLThread,
- }
+ bounds := image.Rect(0, 0, o.width, o.height)
+ w.img = image.NewRGBA(bounds)
go func() {
runtime.LockOSThread()
- openGLThread(w, cancelOpenGLThread, w.flushes)
+ w.openGLThread()
}()
- w.resize(o.width, o.height)
-
- go eventDispatch(w, cancelEventDispatch, w.events)
- mainthread.CallNonBlock(func() {
- eventThread(w, cancelEventThread)
- })
+ mainthread.CallNonBlock(w.eventThread)
return w, nil
}
@@ -115,135 +97,79 @@ func makeGLFWWin(o *options) (*glfw.Window, error) {
}
type Win struct {
- dispatch event.Dispatch
- w *glfw.Window
- front *image.RGBA
- back *image.RGBA
- events chan struct {
- event string
- result chan<- bool
- }
- flushes chan struct {
- r image.Rectangle
- flushed chan<- struct{}
- }
- cancels []chan<- chan<- struct{}
-}
+ event chan layout.EventConsume
+ draw chan layout.ImageFlush
-func (w *Win) Event(pattern string, handler func(evt string) bool) {
- w.dispatch.Event(pattern, handler)
-}
+ newSize chan image.Rectangle
+ finish chan struct{}
-func (w *Win) Happen(evt string) bool {
- result := make(chan bool)
- w.events <- struct {
- event string
- result chan<- bool
- }{evt, result}
- return <-result
+ w *glfw.Window
+ img *image.RGBA
}
-func (w *Win) Close() error {
+func (w *Win) Cancel() {
go func() {
- for _, cancel := range w.cancels {
- confirm := make(chan struct{})
- cancel <- confirm
- <-confirm
- }
+ <-layout.SendEvent(w.event, "cancel")
+ <-layout.SendEvent(w.event, "return")
+ close(w.event)
+ close(w.finish)
}()
- return nil
}
-func (w *Win) Image() *image.RGBA {
- return w.front
+func (w *Win) Event() <-chan layout.EventConsume {
+ return w.event
}
-func (w *Win) Flush(r image.Rectangle) {
- flushed := make(chan struct{})
- w.flushes <- struct {
- r image.Rectangle
- flushed chan<- struct{}
- }{r, flushed}
- <-flushed
+func (w *Win) Draw() chan<- layout.ImageFlush {
+ return w.draw
}
-func (w *Win) resize(width, height int) {
- bounds := image.Rect(0, 0, width, height)
- front := image.NewRGBA(bounds)
- if w.front != nil {
- draw.Draw(front, w.front.Bounds(), w.front, w.front.Bounds().Min, draw.Src)
- }
- w.front = front
- back := image.NewRGBA(bounds)
- if w.back != nil {
- draw.Draw(back, w.back.Bounds(), w.back, w.back.Bounds().Min, draw.Src)
- }
- w.back = back
- w.Flush(bounds)
-}
-
-func eventDispatch(w *Win, cancel <-chan chan<- struct{}, events chan struct {
- event string
- result chan<- bool
-}) {
-loop:
- for {
- select {
- case evt := <-events:
- evt.result <- w.dispatch.Happen(evt.event)
- case confirm := <-cancel:
- close(confirm)
- break loop
- }
- }
-}
-
-func eventThread(w *Win, cancel <-chan chan<- struct{}) {
+func (w *Win) eventThread() {
var moX, moY int
w.w.SetMouseButtonCallback(func(_ *glfw.Window, button glfw.MouseButton, action glfw.Action, mod glfw.ModifierKey) {
switch action {
case glfw.Press:
- w.Happen(event.Sprint("mo", "down", moX, moY))
+ <-layout.SendEvent(w.event, "mo/down/%d/%d", moX, moY)
case glfw.Release:
- w.Happen(event.Sprint("mo", "up", moX, moY))
+ <-layout.SendEvent(w.event, "mo/up/%d/%d", moX, moY)
}
})
w.w.SetCursorPosCallback(func(_ *glfw.Window, x, y float64) {
moX, moY = int(x), int(y)
- w.Happen(event.Sprint("mo", "move", moX, moY))
+ <-layout.SendEvent(w.event, "mo/move/%d/%d", moX, moY)
})
w.w.SetCharCallback(func(_ *glfw.Window, r rune) {
- w.Happen(event.Sprint("kb", "type", r))
+ <-layout.SendEvent(w.event, "kb/type/%d", r)
})
w.w.SetSizeCallback(func(_ *glfw.Window, width, height int) {
- w.resize(width, height)
- w.Happen(event.Sprint("resize", 0, 0, width, height))
+ r := image.Rect(0, 0, width, height)
+ w.newSize <- r
+ <-layout.SendEvent(w.event, "resize/%d/%d/%d/%d", r.Min.X, r.Min.Y, r.Max.X, r.Max.Y)
})
w.w.SetCloseCallback(func(_ *glfw.Window) {
- w.Happen(event.Sprint("wi", "close"))
+ <-layout.SendEvent(w.event, "wi/close")
})
-loop:
+ r := w.img.Bounds()
+ <-layout.SendEvent(w.event, "resize/%d/%d/%d/%d", r.Min.X, r.Min.Y, r.Max.X, r.Max.Y)
+
for {
select {
+ case <-w.finish:
+ w.w.Destroy()
+ return
default:
- glfw.WaitEvents()
- case confirm := <-cancel:
- close(confirm)
- break loop
+ glfw.WaitEventsTimeout(1.0 / 30)
}
}
}
-func openGLThread(w *Win, cancel <-chan chan<- struct{}, flushes <-chan struct {
- r image.Rectangle
- flushed chan<- struct{}
-}) {
+func (w *Win) openGLThread() {
w.w.MakeContextCurrent()
gl.Init()
@@ -253,25 +179,34 @@ func openGLThread(w *Win, cancel <-chan chan<- struct{}, flushes <-chan struct {
)
defer openGLFlush.Stop()
-loop:
for {
select {
- case flush := <-w.flushes:
- draw.Draw(w.back, flush.r, w.front, flush.r.Min, draw.Src)
- openGLFlushR = openGLFlushR.Union(flush.r)
- close(flush.flushed)
+ case <-w.finish:
+ return
+
+ case r := <-w.newSize:
+ img := image.NewRGBA(r)
+ draw.Draw(img, w.img.Bounds(), w.img, w.img.Bounds().Min, draw.Src)
+ w.img = img
+ openGLFlushR = r
+
+ case imfl := <-w.draw:
+ imfl.Image <- w.img
+ r := <-imfl.Flush
+ openGLFlushR = openGLFlushR.Union(r)
+
case <-openGLFlush.C:
r := openGLFlushR
+ openGLFlushR = image.Rectangle{}
- back := w.back
- bounds := back.Bounds()
+ bounds := w.img.Bounds()
r = r.Intersect(bounds)
if r.Empty() {
- return
+ continue
}
tmp := image.NewRGBA(r)
- draw.Draw(tmp, r, back, r.Min, draw.Src)
+ draw.Draw(tmp, r, w.img, r.Min, draw.Src)
gl.DrawBuffer(gl.FRONT)
gl.Viewport(
@@ -293,10 +228,6 @@ loop:
gl.Ptr(tmp.Pix),
)
gl.Flush()
- case confirm := <-cancel:
- w.w.Destroy()
- close(confirm)
- break loop
}
}
}