editor/search: fix nil-handler click crash and '1 / 0' match counter
Tapping the find-bar/browser search input (MAIN-owned GioEditors with no tap interaction) registered a click region with a nil handler; the logic loop called the nil handler and panicked the goroutine. Skip nil-handler clicks in CheckGestures (the widget handles its own click for focus/caret) and guard the input loop so a malformed event can never panic. Fix the '1 / 0' counter on session restore with an empty query: FindState.Cur is documented '-1 when none selected' but its Go zero value is 0, so a restored/reset state with no matches read as 'match 1 of 0'. Only print 'N / M' when Cur is a valid index, and reset Cur=-1 in findReset and the restore path.
This commit is contained in:
parent
348895eb7e
commit
ebd264150d
|
|
@ -377,6 +377,12 @@ func (l *Logic) Run() {
|
|||
}
|
||||
case events := <-l.inputChan:
|
||||
for _, evt := range events {
|
||||
// Invariant: every input event carries a handler. A nil handler
|
||||
// would panic the moment it is dispatched; skip it defensively so
|
||||
// a malformed event can never take down the logic goroutine.
|
||||
if evt.Handler == nil {
|
||||
continue
|
||||
}
|
||||
evt.Handler(evt.Data)
|
||||
}
|
||||
l.emitFrame()
|
||||
|
|
@ -857,6 +863,13 @@ func (l *Logic) handleWorkerResult(res pool.Result) {
|
|||
// with the content, the query re-scans against the new file).
|
||||
if res.FilePath == l.restoreFile && l.restoreFile != "" {
|
||||
f := &l.state.Editor.Find
|
||||
// Start from a clean find state: the re-scan (dispatched when the
|
||||
// content lands, and only for a non-empty query) selects the
|
||||
// restored match via RestoreMatch. Clearing Matches and setting
|
||||
// Cur=-1 avoids the int zero value 0 reading as "match 1 of 0"
|
||||
// when the restored query is empty (no scan is dispatched then).
|
||||
f.Matches = nil
|
||||
f.Cur = -1
|
||||
f.Query = l.session.FindQuery
|
||||
f.Visible = l.session.FindVisible
|
||||
f.RestoreMatch = l.session.FindCurByte
|
||||
|
|
|
|||
|
|
@ -143,7 +143,10 @@ func (e *EditorState) findReset() {
|
|||
// ClearSeq is preserved: main tracks it monotonically, so resetting it
|
||||
// to 0 would make a later clear (seq 1) indistinguishable from an old
|
||||
// one already mirrored.
|
||||
e.Find = FindState{Query: e.Find.Query, Gen: e.Find.Gen + 1, ClearSeq: e.Find.ClearSeq, SettleByte: -1}
|
||||
// Cur is reset to -1 (not the int zero value 0): a fresh find state selects
|
||||
// no match, and a stale Cur=0 against an empty Matches would otherwise read
|
||||
// as "match 1 of 0" in the counter.
|
||||
e.Find = FindState{Query: e.Find.Query, Gen: e.Find.Gen + 1, ClearSeq: e.Find.ClearSeq, SettleByte: -1, Cur: -1}
|
||||
}
|
||||
|
||||
// findSetQuery processes a query forwarded from the main-owned "find_bar"
|
||||
|
|
|
|||
|
|
@ -2596,7 +2596,7 @@ func buildFindBar(screenWidth ui.Dp) ui.Element {
|
|||
counter = "…"
|
||||
case f.Query != "" && len(f.Matches) == 0:
|
||||
counter = "No matches"
|
||||
case f.Cur >= 0:
|
||||
case f.Cur >= 0 && f.Cur < len(f.Matches):
|
||||
counter = fmt.Sprintf("%d / %d", f.Cur+1, len(f.Matches))
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -685,6 +685,14 @@ func (r *Renderer) CheckGestures(q input.Source, m unit.Metric) []InputEvent {
|
|||
// nothing.)
|
||||
break
|
||||
}
|
||||
// A click region registered without a tap handler (the
|
||||
// MAIN-owned GioEditor inputs, find_bar/search_bar) must not
|
||||
// emit an input event: the widget handles its own click for
|
||||
// focus/caret, and forwarding a nil handler would panic the
|
||||
// logic goroutine. Skip it.
|
||||
if reg.handler == nil {
|
||||
break
|
||||
}
|
||||
if evt.NumClicks >= 2 {
|
||||
events = append(events, InputEvent{
|
||||
Handler: reg.handler,
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user