feat: global rom search in the quick menu - #2
Open
lepht wants to merge 3 commits into
Open
Conversation
This was referenced Aug 8, 2026
This was referenced Aug 11, 2026
A new quick menu entry opens an on-screen keyboard over a live result list, in the spirit of the stock TrimUI OS. It indexes every rom under Roms/ for which an emulator pak exists, honouring the same hidden-file and map.txt alias rules the browser uses, and treating a multi-disc folder as one game rather than as a pile of discs. The index is built once, on the first visit. The two halves of the screen hand focus back and forth: walking off the top of the keyboard moves into the results, which then take the keyboard's space so a long list can be browsed full-screen, and walking off the bottom of the results gives it back. A launches, X resumes a save state, and Y opens the same context menu the game lists use, so a game can be favorited straight out of a search. Games that exist under two systems are tagged with the emulator they belong to, exactly like a directory listing does. Adds a Search icon to the shared res folder. Refs LoveRetro#110, LoveRetro#589
Carries the main merge (and with it #26, #27, #28) up the stack. Same single conflict as one level down, in the same two lines of nextui.c: this branch had added SCREEN_SEARCH to the outer screen exclusion list on top of SCREEN_CONTEXTMENU, while #27 added a total>0 guard to the inner condition. Resolved as the union again - all four screen exclusions kept, total>0 kept. Verified after the merge: no assert(entry) remains, every read of entries->items[top->selected] is guarded, nextui.c is syntax-clean against the desktop platform headers, and make test passes.
Search opened on a blank field every time, so running a variant of the search you just ran meant retyping the whole thing on an on-screen keyboard. Reopening now starts on the previous query with the whole thing selected, the way a desktop text field behaves: START runs it again as-is, and typing replaces it outright. Moving into the results, by START or by walking up off the keyboard, accepts the query and drops the selection. The query also outlives the process, in /tmp alongside last.txt. That is the case that matters - launching a game is what exits nextui, so without it the carried-over query would almost never be there when you came back. Transient on purpose: a reboot starts clean. The caret is a real cursor now rather than a fixed end-of-line marker. L/R move it a character at a time, typing inserts there and delete takes the character before it, so a typo in the middle of a query no longer means backspacing over everything after it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NVCcQ2X3F6F4pDb8ykQR33
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A global ROM search reachable from the quick menu, in the spirit of the stock TrimUI OS.
What this does
A Search entry in the quick menu opens an on-screen keyboard over a live result list. It indexes every ROM under
Roms/for which an emulator pak exists, honouring the same hidden-file andmap.txtalias rules the browser uses, and treating a multi-disc folder as one game rather than a pile of discs. The index is built once, on the first visit.The two halves hand focus back and forth: walking off the top of the keyboard moves into the results, which then take the keyboard's space so a long list can be browsed full-screen; walking off the bottom of the results gives it back. A launches, X resumes a save state, Y opens the same context menu the game lists use — so a game can be favorited straight out of a search.
Games that exist under two systems are tagged with the emulator they belong to, exactly like a directory listing does.
The query field behaves like a text field rather than an append-only buffer. L/R move a cursor through it a character at a time, typing inserts at the cursor, and X deletes the character before it — so a typo in the middle of a query doesn't mean backspacing over everything after it.
Reopening search starts on the previous query with the whole thing selected, the way a desktop text field does: START runs it again as-is, and typing replaces it outright. Moving into the results, by START or by walking up off the keyboard, accepts the query and drops the selection. The query lives in
/tmpnext tolast.txt, so it survives launching a game — which is what exits nextui, and therefore the case that matters — but not a reboot.Layout decision
At the Brick's 341×256 logical space there isn't room for a query field, a full result list, a keyboard, and the button hints at once. Rather than shrink everything, the result list and keyboard trade space based on focus: ~3 preview rows while typing, ~5 with the keyboard hidden. Row counts are computed from the actual screen height rather than hardcoded, so this adapts to other panels.
A button-hint group fits two hints at most, so the hints are contextual rather than crowded: a carried-over query spends them on the choice it presents (START SEARCH, A REPLACE), and the editing hints (Y SPACE, X DELETE, A TYPE) come back as soon as the selection is gone.
Testing
Built the desktop target and drove it under Xvfb against a fake SD card (~25 ROMs across 7 systems), verifying by screenshot:
Type to searchvsNo matches)The query field was verified the same way, against a generated library of ~200 ROMs across 14 systems:
Also exercised under AddressSanitizer with zero errors. Passes
-fsyntax-onlyagainst both the tg5040 and tg5050 platform headers.Not tested on hardware.
One note for anyone else driving the desktop build:
PAD_polldrains the whole SDL event queue per call, so a synthetic instant keytap can have its press and release land in the same poll, which clearsjust_repeatedwhile leavingjust_pressedset — silently swallowing every d-pad and L/R input. Holding each key ~150ms avoids it. Real buttons are held across many polls, so this is a harness artifact only.Performance note
The index is built synchronously on first open. On this test library it's imperceptible; on a card with thousands of ROMs it's a
readdir/statwalk that could produce a brief hitch on that first visit. Capped at 8192 entries. If it turns out to matter on a real card, the walk is self-contained enough to move onto the existing loader thread.Refs LoveRetro#110, LoveRetro#589