thread safety for event loop and redraw loop
This commit is contained in:
parent
8be528e57a
commit
45c636ec33
86
screen.go
86
screen.go
@ -9,10 +9,14 @@ import (
|
||||
)
|
||||
|
||||
type Screen struct {
|
||||
scr tcell.Screen
|
||||
buf *ViewBuffer
|
||||
stopCh chan error
|
||||
Root View
|
||||
scr tcell.Screen
|
||||
buf *ViewBuffer
|
||||
|
||||
stopCh chan error
|
||||
redrawCh chan struct{}
|
||||
|
||||
// Root is the root view which is currently shown on screen
|
||||
Root View
|
||||
|
||||
// KeyPressed is called every time a key or key-combination is pressed.
|
||||
KeyPressed func(event *KeyEvent) (consumed bool)
|
||||
@ -28,32 +32,18 @@ func NewScreen(root View) (*Screen, error) {
|
||||
}
|
||||
|
||||
s := &Screen{
|
||||
Root: root,
|
||||
scr: scr,
|
||||
stopCh: make(chan error, 1),
|
||||
Root: root,
|
||||
scr: scr,
|
||||
stopCh: make(chan error, 1),
|
||||
redrawCh: make(chan struct{}, 1),
|
||||
}
|
||||
|
||||
go s.eventloop()
|
||||
go s.drawloop()
|
||||
|
||||
return s, nil
|
||||
}
|
||||
|
||||
func (s *Screen) eventloop() {
|
||||
for evt := s.scr.PollEvent(); evt != nil; evt = s.scr.PollEvent() {
|
||||
switch event := evt.(type) {
|
||||
case *tcell.EventResize:
|
||||
go s.Redraw()
|
||||
case *tcell.EventKey:
|
||||
go s.onKeyPressed(event)
|
||||
case *tcell.EventMouse:
|
||||
go s.onMouseClicked(convertMouseEvent(event))
|
||||
default:
|
||||
s.StopWithError(errors.New(fmt.Sprintf("%#v", event)))
|
||||
}
|
||||
}
|
||||
s.StopWithError(errors.New("unknown error occured"))
|
||||
}
|
||||
|
||||
func (s *Screen) Start() error {
|
||||
err := s.scr.Init()
|
||||
if err != nil {
|
||||
@ -99,13 +89,45 @@ func convertMouseEvent(original *tcell.EventMouse) *MouseEvent {
|
||||
}
|
||||
|
||||
func (s *Screen) Redraw() {
|
||||
w, h := s.scr.Size()
|
||||
|
||||
if s.buf == nil || s.buf.Width() != w || s.buf.Height() != h {
|
||||
s.buf = buf2d.NewBuffer(w, h, DefaultRune)
|
||||
}
|
||||
|
||||
rw, rh := s.Root.Layout()
|
||||
s.Root.Draw(truncateBuffer(s.buf, rw, rh))
|
||||
drawBuffer(s.scr, s.buf)
|
||||
s.redrawCh <- struct{}{}
|
||||
}
|
||||
|
||||
func (s *Screen) eventloop() {
|
||||
defer s.stopOnPanic()
|
||||
|
||||
for evt := s.scr.PollEvent(); evt != nil; evt = s.scr.PollEvent() {
|
||||
switch event := evt.(type) {
|
||||
case *tcell.EventResize:
|
||||
go s.Redraw()
|
||||
case *tcell.EventKey:
|
||||
go s.onKeyPressed(event)
|
||||
case *tcell.EventMouse:
|
||||
go s.onMouseClicked(convertMouseEvent(event))
|
||||
default:
|
||||
s.StopWithError(errors.New(fmt.Sprintf("%#v", event)))
|
||||
}
|
||||
}
|
||||
s.StopWithError(errors.New("unknown error occured"))
|
||||
}
|
||||
|
||||
func (s *Screen) drawloop() {
|
||||
defer s.stopOnPanic()
|
||||
|
||||
for range s.redrawCh {
|
||||
w, h := s.scr.Size()
|
||||
|
||||
if s.buf == nil || s.buf.Width() != w || s.buf.Height() != h {
|
||||
s.buf = buf2d.NewBuffer(w, h, DefaultRune)
|
||||
}
|
||||
|
||||
rw, rh := s.Root.Layout()
|
||||
s.Root.Draw(truncateBuffer(s.buf, rw, rh))
|
||||
drawBuffer(s.scr, s.buf)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Screen) stopOnPanic() {
|
||||
if err := recover(); err != nil {
|
||||
s.StopWithError(fmt.Errorf("%v", err))
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user