Add Screen.ChannelEvents v2 (#465)

This commit is contained in:
eNV25 2021-06-12 02:43:12 +00:00 committed by GitHub
parent 7946eb8e8d
commit b60a903b98
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 112 additions and 2 deletions

View File

@ -343,6 +343,26 @@ func (s *cScreen) PostEvent(ev Event) error {
} }
} }
func (s *cScreen) ChannelEvents(ch chan<- Event, quit <-chan struct{}) {
defer close(ch)
for {
select {
case <-quit:
return
case <-s.stopQ:
return
case ev := <-s.evch:
select {
case <-quit:
return
case <-s.stopQ:
return
case ch <- ev:
}
}
}
}
func (s *cScreen) PollEvent() Event { func (s *cScreen) PollEvent() Event {
select { select {
case <-s.stopQ: case <-s.stopQ:

View File

@ -68,3 +68,42 @@ func TestMouseEvents(t *testing.T) {
t.Errorf("Modifiers should be control") t.Errorf("Modifiers should be control")
} }
} }
func TestChannelMouseEvents(t *testing.T) {
s := mkTestScreen(t, "")
defer s.Fini()
s.EnableMouse()
s.InjectMouse(4, 9, Button1, ModCtrl)
evch := make(chan Event)
quit := make(chan struct{})
em := new(EventMouse)
go s.ChannelEvents(evch, quit)
loop:
for {
select {
case ev := <-evch:
if evm, ok := ev.(*EventMouse); ok {
em = evm
close(quit)
break loop
}
continue
case <-time.After(time.Second):
close(quit)
break loop
}
}
if x, y := em.Position(); x != 4 || y != 9 {
t.Errorf("Mouse position wrong (%v, %v)", x, y)
}
if em.Buttons() != Button1 {
t.Errorf("Should be Button1")
}
if em.Modifiers() != ModCtrl {
t.Errorf("Modifiers should be control")
}
}

View File

@ -78,6 +78,17 @@ type Screen interface {
// response to a call to Clear or Flush. // response to a call to Clear or Flush.
Size() (int, int) Size() (int, int)
// ChannelEvents is an infinite loop that waits for an event and
// channels it into the user provided channel ch. Closing the
// quit channel and calling the Fini method are cancellation
// signals. When a cancellation signal is received the method
// returns after closing ch.
//
// This method should be used as a goroutine.
//
// NOTE: PollEvent should not be called while this method is running.
ChannelEvents(ch chan<- Event, quit <-chan struct{})
// PollEvent waits for events to arrive. Main application loops // PollEvent waits for events to arrive. Main application loops
// must spin on this to prevent the application from stalling. // must spin on this to prevent the application from stalling.
// Furthermore, this will return nil if the Screen is finalized. // Furthermore, this will return nil if the Screen is finalized.

View File

@ -351,6 +351,26 @@ func (s *simscreen) Colors() int {
return 256 return 256
} }
func (s *simscreen) ChannelEvents(ch chan<- Event, quit <-chan struct{}) {
defer close(ch)
for {
select {
case <-quit:
return
case <-s.quit:
return
case ev := <-s.evch:
select {
case <-quit:
return
case <-s.quit:
return
case ch <- ev:
}
}
}
}
func (s *simscreen) PollEvent() Event { func (s *simscreen) PollEvent() Event {
select { select {
case <-s.quit: case <-s.quit:

View File

@ -941,6 +941,26 @@ func (t *tScreen) nColors() int {
return t.ti.Colors return t.ti.Colors
} }
func (t *tScreen) ChannelEvents(ch chan<- Event, quit <-chan struct{}) {
defer close(ch)
for {
select {
case <-quit:
return
case <-t.quit:
return
case ev := <-t.evch:
select {
case <-quit:
return
case <-t.quit:
return
case ch <- ev:
}
}
}
}
func (t *tScreen) PollEvent() Event { func (t *tScreen) PollEvent() Event {
select { select {
case <-t.quit: case <-t.quit: