mirror of
https://github.com/mineracks/seedhammer-v1-companion.git
synced 2026-06-26 20:51:06 +10:00
emulator: wake the Events() select on SDCard push
Eject button wasn't taking effect immediately because Platform.Events() was blocked in a select that only woke on button-channel input or timer expiry. SDCardEvents go through a separate pending queue and the select had no way to notice when they arrived — the eject sat in pending until the next button press or timer expiry, both of which could take seconds. Fix: 1-buffered wake channel. signalWake() pokes it (non-blocking), the select now reads from it as a third case, and the drain-loop at the end re-drains pending so any event pushed while we waited gets returned in the same call. exportSetSDCard() calls signalWake() after appending to pending. Wakeup() (gui.Platform method, previously no-op) now also calls it, so any future gui-side wake request works the same way. The bug was specific to non-button events — button events go through the events chan directly so they always woke the select. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
b4635f4efc
commit
cf68d6c451
@ -41,6 +41,11 @@ const (
|
||||
type browserPlatform struct {
|
||||
frame *image.RGBA
|
||||
events chan v1.Event
|
||||
// wake is a 1-buffered channel that the select in Events() reads
|
||||
// from. exportSetSDCard, exportCameraFrame (future), and any other
|
||||
// non-button event source pokes wake after appending to pending so
|
||||
// the Events() wait returns immediately and drains the new event.
|
||||
wake chan struct{}
|
||||
|
||||
mu sync.Mutex
|
||||
pending []gui.Event
|
||||
@ -52,6 +57,14 @@ func newBrowserPlatform() *browserPlatform {
|
||||
return &browserPlatform{
|
||||
frame: image.NewRGBA(image.Rect(0, 0, lcdWidth, lcdHeight)),
|
||||
events: make(chan v1.Event, 64),
|
||||
wake: make(chan struct{}, 1),
|
||||
}
|
||||
}
|
||||
|
||||
func (p *browserPlatform) signalWake() {
|
||||
select {
|
||||
case p.wake <- struct{}{}:
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
@ -76,14 +89,20 @@ func (p *browserPlatform) Events(deadline time.Time) []gui.Event {
|
||||
select {
|
||||
case ev := <-p.events:
|
||||
out = append(out, p.toGuiEvent(ev))
|
||||
case <-p.wake:
|
||||
// Non-button event arrived (e.g. SDCardEvent). Fall through to
|
||||
// the pending drain at the bottom.
|
||||
case <-timer.C:
|
||||
}
|
||||
// Drain any extras that piled up while we were waiting.
|
||||
// Drain any extras (button events) that piled up while we waited.
|
||||
for {
|
||||
select {
|
||||
case ev := <-p.events:
|
||||
out = append(out, p.toGuiEvent(ev))
|
||||
default:
|
||||
// Also re-drain pending — if signalWake fired, the SDCard
|
||||
// or other event is sitting there now.
|
||||
out = append(out, p.drainPending()...)
|
||||
return out
|
||||
}
|
||||
}
|
||||
@ -113,7 +132,7 @@ func (p *browserPlatform) push(button v1.Button, pressed bool) {
|
||||
}
|
||||
|
||||
func (p *browserPlatform) Wakeup() {
|
||||
// no-op — JS-driven runtime; nothing to wake from.
|
||||
p.signalWake()
|
||||
}
|
||||
|
||||
func (p *browserPlatform) PlateSizes() []backup.PlateSize {
|
||||
@ -274,6 +293,7 @@ func exportSetSDCard(this js.Value, args []js.Value) any {
|
||||
plat.mu.Lock()
|
||||
plat.pending = append(plat.pending, gui.SDCardEvent{Inserted: inserted}.Event())
|
||||
plat.mu.Unlock()
|
||||
plat.signalWake() // unblock any in-flight Events() wait
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user