// Used to send screen events from separate goroutine to main event loop
eventschantcell.Event
// Used to send primitive updates from separate goroutines to the main event loop
updateschanfunc()
}
// NewApplication creates and returns a new application.
funcNewApplication()*Application{
return&Application{}
return&Application{
events:make(chantcell.Event,100),
updates:make(chanfunc(),100),
}
}
// SetInputCapture sets a function which captures all key events before they are
@ -136,61 +145,78 @@ func (a *Application) Run() error {
a.Unlock()
a.Draw()
// Start event loop.
for{
// Do not poll events during suspend mode
a.suspendMutex.Lock()
a.RLock()
screen:=a.screen
a.RUnlock()
ifscreen==nil{
a.suspendMutex.Unlock()
break
}
// Separate loop to wait for screen events
gofunc(){
for{
// Do not poll events during suspend mode
a.suspendMutex.Lock()
a.RLock()
screen:=a.screen
a.RUnlock()
ifscreen==nil{
a.suspendMutex.Unlock()
// send signal to stop main event loop
a.QueueEvent(nil)
break
}
// Wait for next event.
event:=a.screen.PollEvent()
a.suspendMutex.Unlock()
ifevent==nil{
// The screen was finalized. Exit the loop.
break
// Wait for next event.
a.QueueEvent(screen.PollEvent())
a.suspendMutex.Unlock()
}
}()
switchevent:=event.(type){
case*tcell.EventKey:
a.RLock()
p:=a.focus
a.RUnlock()
// Start event loop.
loop:
for{
select{
caseevent:=<-a.events:
ifevent==nil{
// The screen was finalized. Exit the loop.
breakloop
}
// Intercept keys.
ifa.inputCapture!=nil{
event=a.inputCapture(event)
ifevent==nil{
break// Don't forward event.
switchevent:=event.(type){
case*tcell.EventKey:
a.RLock()
p:=a.focus
a.RUnlock()
// Intercept keys.
ifa.inputCapture!=nil{
event=a.inputCapture(event)
ifevent==nil{
breakloop// Don't forward event.
}
}
}
// Ctrl-C closes the application.
ifevent.Key()==tcell.KeyCtrlC{
a.Stop()
}
// Ctrl-C closes the application.
ifevent.Key()==tcell.KeyCtrlC{
a.Stop()
}
// Pass other key events to the currently focused primitive.
ifp!=nil{
ifhandler:=p.InputHandler();handler!=nil{
handler(event,func(pPrimitive){
a.SetFocus(p)
})
a.Draw()
// Pass other key events to the currently focused primitive.
ifp!=nil{
ifhandler:=p.InputHandler();handler!=nil{
handler(event,func(pPrimitive){
a.SetFocus(p)
})
a.Draw()
}
}
case*tcell.EventResize:
a.RLock()
screen:=a.screen
a.RUnlock()
screen.Clear()
a.Draw()
}
case*tcell.EventResize:
a.RLock()
screen:=a.screen
a.RUnlock()
screen.Clear()
caseupdater:=<-a.updates:
updater()
a.Draw()
}
}
returnnil
@ -404,3 +430,15 @@ func (a *Application) GetFocus() Primitive {
defera.RUnlock()
returna.focus
}
// QueueUpdate is used to synchronize changes to primitives by carrying an update function from separate goroutine to the Application event loop via channel