mirror of https://github.com/mum4k/termdash.git
Also throttling repetitive events to focus and widgets.
This commit is contained in:
parent
60aaa7d8bb
commit
006c021f63
|
@ -250,11 +250,15 @@ func (c *Container) Subscribe(eds *event.DistributionSystem) {
|
|||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
// maxReps is the maximum number of repetitive events towards widgets
|
||||
// before we throttle them.
|
||||
const maxReps = 10
|
||||
|
||||
root := rootCont(c)
|
||||
// Subscriber the container itself in order to track keyboard focus.
|
||||
eds.Subscribe([]terminalapi.Event{&terminalapi.Mouse{}}, func(ev terminalapi.Event) {
|
||||
root.updateFocus(ev.(*terminalapi.Mouse))
|
||||
})
|
||||
}, event.MaxRepetitive(0)) // One event is enough to change the focus.
|
||||
|
||||
// Subscribe any widgets that specify Keyboard or Mouse in their options.
|
||||
var errStr string
|
||||
|
@ -266,7 +270,7 @@ func (c *Container) Subscribe(eds *event.DistributionSystem) {
|
|||
if err := c.keyboardToWidget(ev.(*terminalapi.Keyboard)); err != nil {
|
||||
eds.Event(terminalapi.NewErrorf("failed to send keyboard event %v to widget %T: %v", ev, c.opts.widget, err))
|
||||
}
|
||||
})
|
||||
}, event.MaxRepetitive(maxReps))
|
||||
}
|
||||
|
||||
if wOpt.WantMouse {
|
||||
|
@ -274,7 +278,7 @@ func (c *Container) Subscribe(eds *event.DistributionSystem) {
|
|||
if err := c.mouseToWidget(ev.(*terminalapi.Mouse)); err != nil {
|
||||
eds.Event(terminalapi.NewErrorf("failed to send mouse event %v to widget %T: %v", ev, c.opts.widget, err))
|
||||
}
|
||||
})
|
||||
}, event.MaxRepetitive(maxReps))
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
|
|
@ -294,8 +294,9 @@ func TestFocusTrackerMouse(t *testing.T) {
|
|||
tests := []struct {
|
||||
desc string
|
||||
// Can be either the mouse event or a time.Duration to pause for.
|
||||
events []*terminalapi.Mouse
|
||||
wantFocused contLoc
|
||||
events []*terminalapi.Mouse
|
||||
wantFocused contLoc
|
||||
wantProcessed int
|
||||
}{
|
||||
{
|
||||
desc: "initially the root is focused",
|
||||
|
@ -307,7 +308,8 @@ func TestFocusTrackerMouse(t *testing.T) {
|
|||
{Position: image.Point{0, 0}, Button: mouse.ButtonLeft},
|
||||
{Position: image.Point{1, 1}, Button: mouse.ButtonRelease},
|
||||
},
|
||||
wantFocused: contLocLeft,
|
||||
wantFocused: contLocLeft,
|
||||
wantProcessed: 2,
|
||||
},
|
||||
{
|
||||
desc: "click and release moves focus to the right",
|
||||
|
@ -315,7 +317,8 @@ func TestFocusTrackerMouse(t *testing.T) {
|
|||
{Position: image.Point{5, 5}, Button: mouse.ButtonLeft},
|
||||
{Position: image.Point{6, 6}, Button: mouse.ButtonRelease},
|
||||
},
|
||||
wantFocused: contLocRight,
|
||||
wantFocused: contLocRight,
|
||||
wantProcessed: 2,
|
||||
},
|
||||
{
|
||||
desc: "click in the same container is a no-op",
|
||||
|
@ -325,7 +328,8 @@ func TestFocusTrackerMouse(t *testing.T) {
|
|||
{Position: insideRight, Button: mouse.ButtonLeft},
|
||||
{Position: insideRight, Button: mouse.ButtonRelease},
|
||||
},
|
||||
wantFocused: contLocRight,
|
||||
wantFocused: contLocRight,
|
||||
wantProcessed: 4,
|
||||
},
|
||||
{
|
||||
desc: "click in the same container and release never happens",
|
||||
|
@ -334,7 +338,8 @@ func TestFocusTrackerMouse(t *testing.T) {
|
|||
{Position: insideLeft, Button: mouse.ButtonLeft},
|
||||
{Position: insideLeft, Button: mouse.ButtonRelease},
|
||||
},
|
||||
wantFocused: contLocLeft,
|
||||
wantFocused: contLocLeft,
|
||||
wantProcessed: 3,
|
||||
},
|
||||
{
|
||||
desc: "click in the same container, release elsewhere",
|
||||
|
@ -342,7 +347,8 @@ func TestFocusTrackerMouse(t *testing.T) {
|
|||
{Position: insideRight, Button: mouse.ButtonLeft},
|
||||
{Position: insideLeft, Button: mouse.ButtonRelease},
|
||||
},
|
||||
wantFocused: contLocRoot,
|
||||
wantFocused: contLocRoot,
|
||||
wantProcessed: 2,
|
||||
},
|
||||
{
|
||||
desc: "other buttons are ignored",
|
||||
|
@ -354,7 +360,8 @@ func TestFocusTrackerMouse(t *testing.T) {
|
|||
{Position: insideLeft, Button: mouse.ButtonWheelUp},
|
||||
{Position: insideLeft, Button: mouse.ButtonWheelDown},
|
||||
},
|
||||
wantFocused: contLocRoot,
|
||||
wantFocused: contLocRoot,
|
||||
wantProcessed: 6,
|
||||
},
|
||||
{
|
||||
desc: "moving mouse with pressed button and then releasing moves focus",
|
||||
|
@ -363,7 +370,8 @@ func TestFocusTrackerMouse(t *testing.T) {
|
|||
{Position: image.Point{1, 1}, Button: mouse.ButtonLeft},
|
||||
{Position: image.Point{2, 2}, Button: mouse.ButtonRelease},
|
||||
},
|
||||
wantFocused: contLocLeft,
|
||||
wantFocused: contLocLeft,
|
||||
wantProcessed: 3,
|
||||
},
|
||||
{
|
||||
desc: "click ignored if followed by another click of the same button elsewhere",
|
||||
|
@ -371,9 +379,9 @@ func TestFocusTrackerMouse(t *testing.T) {
|
|||
{Position: insideRight, Button: mouse.ButtonLeft},
|
||||
{Position: insideLeft, Button: mouse.ButtonLeft},
|
||||
{Position: insideRight, Button: mouse.ButtonRelease},
|
||||
{Position: insideRight, Button: mouse.ButtonRelease},
|
||||
},
|
||||
wantFocused: contLocRoot,
|
||||
wantFocused: contLocRoot,
|
||||
wantProcessed: 3,
|
||||
},
|
||||
{
|
||||
desc: "click ignored if followed by another click of a different button",
|
||||
|
@ -381,9 +389,9 @@ func TestFocusTrackerMouse(t *testing.T) {
|
|||
{Position: insideRight, Button: mouse.ButtonLeft},
|
||||
{Position: insideRight, Button: mouse.ButtonMiddle},
|
||||
{Position: insideRight, Button: mouse.ButtonRelease},
|
||||
{Position: insideRight, Button: mouse.ButtonRelease},
|
||||
},
|
||||
wantFocused: contLocRoot,
|
||||
wantFocused: contLocRoot,
|
||||
wantProcessed: 3,
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -406,7 +414,7 @@ func TestFocusTrackerMouse(t *testing.T) {
|
|||
eds.Event(ev)
|
||||
}
|
||||
if err := testevent.WaitFor(5*time.Second, func() error {
|
||||
if got, want := eds.Processed(), len(tc.events); got != want {
|
||||
if got, want := eds.Processed(), tc.wantProcessed; got != want {
|
||||
return fmt.Errorf("the event distribution system processed %d events, want %d", got, want)
|
||||
}
|
||||
return nil
|
||||
|
|
|
@ -37,6 +37,10 @@ const (
|
|||
|
||||
// receiverModeBlock tells the receiver to block on the call to receive.
|
||||
receiverModeBlock
|
||||
|
||||
// receiverModePause tells the receiver to pause before starting to
|
||||
// receive.
|
||||
receiverModePause
|
||||
)
|
||||
|
||||
// receiver receives events from the distribution system.
|
||||
|
@ -48,6 +52,9 @@ type receiver struct {
|
|||
|
||||
// events are the received events.
|
||||
events []terminalapi.Event
|
||||
|
||||
// resumed indicates if the receiver was resumed.
|
||||
resumed bool
|
||||
}
|
||||
|
||||
// newReceiver returns a new event receiver.
|
||||
|
@ -64,12 +71,14 @@ func (r *receiver) receive(ev terminalapi.Event) {
|
|||
for {
|
||||
time.Sleep(1 * time.Minute)
|
||||
}
|
||||
default:
|
||||
r.mu.Lock()
|
||||
defer r.mu.Unlock()
|
||||
|
||||
r.events = append(r.events, ev)
|
||||
case receiverModePause:
|
||||
time.Sleep(3 * time.Second)
|
||||
}
|
||||
|
||||
r.mu.Lock()
|
||||
defer r.mu.Unlock()
|
||||
|
||||
r.events = append(r.events, ev)
|
||||
}
|
||||
|
||||
// getEvents returns the received events.
|
||||
|
@ -273,7 +282,7 @@ func TestDistributionSystem(t *testing.T) {
|
|||
opts: []SubscribeOption{
|
||||
MaxRepetitive(0),
|
||||
},
|
||||
rec: newReceiver(receiverModeReceive),
|
||||
rec: newReceiver(receiverModePause),
|
||||
want: map[terminalapi.Event]bool{
|
||||
&terminalapi.Keyboard{Key: keyboard.KeyEsc}: true,
|
||||
&terminalapi.Keyboard{Key: keyboard.KeyEnter}: true,
|
||||
|
@ -301,7 +310,7 @@ func TestDistributionSystem(t *testing.T) {
|
|||
|
||||
for i, sc := range tc.subCase {
|
||||
gotEv := map[terminalapi.Event]bool{}
|
||||
err := testevent.WaitFor(5*time.Second, func() error {
|
||||
err := testevent.WaitFor(10*time.Second, func() error {
|
||||
ev := sc.rec.getEvents()
|
||||
want := len(sc.want)
|
||||
switch got := len(ev); {
|
||||
|
|
Loading…
Reference in New Issue