Open
Conversation
Shows the LR shoulder button pair as a "page" action in the help bar for Basic, Detailed, and Video game list views (which all inherit BasicGameListView::getHelpPrompts). GridGameListView already uses LR for quick system select so it is left unchanged. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds a new full-screen search popup accessible from any game list view.
The popup allows players to search across all systems (or a single
system) in real time using either a physical keyboard or a gamepad.
Results are displayed with rich metadata, and games can be launched
directly from the results list.
The search popup is opened by pressing the Right Trigger (RT) button
from any game list view. The trigger binding is configurable — whatever
input is mapped to "righttrigger" opens the overlay. When opened using a
physical keyboard key bound to RT (e.g. the '2' key), any SDL_TEXTINPUT
event queued by that same keypress is flushed immediately so the
triggering character does not appear in the search bar.
The popup fills the entire screen with a translucent dark background
panel drawn in render(). It is divided into three main areas:
- Top bar: a search text field showing the current query with a cursor
position indicator (pipe '|'), and below it a character selection row
for gamepad text entry.
- Left column: a scrollable result list (TextListComponent) showing
matching game names. In all-systems mode each entry is suffixed with
the system name in brackets. A status/placeholder message overlays
the list when it is empty.
- Right column: a metadata panel showing cover image or thumbnail,
description, rating, developer, publisher, genre, players, release
date, last played, play count, marquee, and optionally a video
preview. All metadata panel components are fully theme-driven (see
Theme Support below).
The character row is a single horizontal strip of selectable character
cells used for gamepad text entry. It supports three modes:
- LETTERS — mode-switch key "123", space, A–Z, backspace, ← →
- NUMBERS — mode-switch key "!@#", space, 1–9, 0, backspace, ← →
- SYMBOLS — mode-switch key "ABC", space, punctuation set, backspace, ← →
The ← and → cells move the text cursor within the search query (not the
char row selection). The backspace cell deletes the character to the left
of the cursor.
Cell widths are computed from the font metrics plus padding. If the
combined width of all cells exceeds the component width (e.g. after
adding many symbols), the per-cell padding is uniformly reduced so that
all characters remain visible without scrolling or clipping.
When focus is on the char row:
- D-pad / left-stick left/right — move the char row selection cursor
left or right. Holding the direction triggers auto-scroll repeat
after an initial delay (500 ms) at a fixed period (100 ms).
- A button — activate the selected cell: type the character, switch
mode, trigger backspace, or move the text cursor.
- X button — immediate backspace. Holding X triggers hold-to-repeat
after 500 ms at 80 ms intervals (same timing as keyboard held keys).
- L shoulder / R shoulder — move the text cursor left or right within
the query string. Holding triggers repeat after 500 ms at 80 ms.
- D-pad / left-stick down — move focus to the result list (only if
results are present).
- B button — close the popup.
- Start — open the main menu.
- RT — no-op when already in char row (focus is already here).
When a physical keyboard is in use and focus is on the char row, all
keyboard events are intercepted before the button map is consulted. This
prevents conflicts where a printable key (e.g. 's') is also mapped to a
gamepad button action (e.g. 'x' = backspace). The interception rules:
- Printable characters — handled via SDL_TEXTINPUT events, which fire
after SDL_KEYDOWN. Control characters and space are excluded from
SDL_TEXTINPUT; space is handled directly in the SDLK_SPACE case.
- Backspace — deletes the character left of the cursor. Holding
triggers repeat after 500 ms at 80 ms intervals using a software
timer (mKeyRepeatKey / mKeyRepeatTimer), since SDL filters key.repeat
for non-printable keys before they reach input().
- Delete — deletes the character right of the cursor. Same hold-to-
repeat behaviour as backspace.
- Left / Right arrow — move the text cursor. Hold-to-repeat applies.
- Home — jump the text cursor to the start of the query.
- End — jump the text cursor to the end of the query.
- Down arrow — move focus to the result list (only if results exist).
- Escape — close the popup.
- All other keys — fall through (return false) so SDL_TEXTINPUT fires
for printable characters.
The help bar switches between keyboard hints ("esc=close") and gamepad
hints immediately whenever the active input device type changes.
Pressing down (gamepad) or the down arrow (keyboard) from the char row
moves focus to the result list. The char row selection highlight dims
and the result list selector becomes visible.
While focus is on the result list:
- Up / Down — scroll through results. Reaching the top wraps focus
back to the char row; reaching the bottom also wraps back to the
char row.
- A button — launch the selected game.
- X button — jump to a random result.
- Y button — toggle the selected game in/out of the current collection
(not shown in Kid UI mode).
- Select — open GuiGamelistOptions with a jump-to callback so the
options dialog can reposition the result list cursor.
- RT — return focus to the char row. Any SDL_TEXTINPUT events queued
by the RT keypress are flushed so the triggering character is not
inserted.
- B button / Escape — close the popup.
- Start — open the main menu.
- L / R shoulder — page through the result list.
Searching runs on a background thread to avoid blocking the render loop.
Each keystroke cancels any in-progress search (sets mCancelFlag), joins
the previous thread, then starts a new std::thread that:
1. Iterates mAllGames / mLowerNames (built once at popup open).
2. Checks mCancelFlag after each game so a superseded search exits
early.
3. Sorts the matches alphabetically.
4. Stores results in mPendingResults under mResultMutex and sets
mResultsReady.
The main thread polls mResultsReady in update() and applies the results
to the TextListComponent on the next frame.
When the result list cursor moves to a game belonging to a different
system than the one currently themed, applyTheme() is called with the
new system's theme. The result list itself is intentionally excluded from
this re-application to avoid flickering the favorite indicator icon on
every cursor movement — its theme is applied exactly once in the
constructor.
The search view ("search") is fully documented in THEMES.md. Supported
elements:
Layout:
background — image, optional, rendered behind everything (z=0)
searchtext — text, the query bar (pos/size/font/color; text managed
by engine — use ALL ^ TEXT)
listmessage — text, status overlay on the result list
gamelist — textlist, the result list
Metadata values:
md_image, md_thumbnail, md_video, md_marquee, md_name
md_description, md_rating, md_releasedate, md_developer,
md_publisher, md_genre, md_players, md_lastplayed, md_playcount
Metadata labels (text):
md_lbl_rating, md_lbl_releasedate, md_lbl_developer,
md_lbl_publisher, md_lbl_genre, md_lbl_players,
md_lbl_lastplayed, md_lbl_playcount
md_video defaults to invisible (setVisible(false)) — a theme must
explicitly set <visible>true</visible> to enable video playback. All
other metadata components default to off-screen positions so they are
invisible unless the theme positions them.
- ThemeData: registers "search" in sSupportedViews.
- HelpComponent: unknown icon names return nullptr silently (no
LogError) so text-only help prompts (e.g. "esc") render without
spamming the log. Adds "esc" → button_esc_key.svg icon mapping.
- IList: adds getCursorIndex() / setCursorIndex(int) accessors.
- InputManager: SDL2 GameController axis/button events are translated
to the legacy SDL_JOYSTICK format used by the rest of the input
pipeline, enabling controllers that are recognised by SDL2's
GameController API but not the raw joystick API to work correctly.
- ViewController / SystemView: wires RT to open GuiSearchPopup from
the game list.
- Window: passes SDL_TEXTINPUT events through to the top-of-stack GUI
via the existing textInput() path.
- GuiGamelistOptions: extended to accept an optional jump-to callback
and an optional pre-filtered game list for use from search context.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Author
|
This does currently use "RT" by default, but I'm very open to any other suggestions here (as it appears all buttons are in use) depends on: RetroPie/RetroPie-Setup#4174 to allow use of the extra buttons from the wizard configurator to be used in emulation station |
|
@XenuIsWatching it's an interesting addition for sure. I have some notes about the implementation, but for now I'm just interested in testing it: do you have a modified ES theme with a 'search' view that I can use ? Some notes about the implementation (I only tested it with a keyboard):
I have other thoughts, but I think the biggest challenge would be (IMHO) how to create a 'search' view for themes that don't implement one. |
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.
Adds a new full-screen search popup accessible from any game list view.
The popup allows players to search across all systems (or a single
system) in real time using either a physical keyboard or a gamepad.
Results are displayed with rich metadata, and games can be launched
directly from the results list.
The search popup is opened by pressing the Right Trigger (RT) button
from any game list view. The trigger binding is configurable — whatever
input is mapped to "righttrigger" opens the overlay. When opened using a
physical keyboard key bound to RT (e.g. the '2' key), any SDL_TEXTINPUT
event queued by that same keypress is flushed immediately so the
triggering character does not appear in the search bar.
The popup fills the entire screen with a translucent dark background
panel drawn in render(). It is divided into three main areas:
position indicator (pipe '|'), and below it a character selection row
for gamepad text entry.
matching game names. In all-systems mode each entry is suffixed with
the system name in brackets. A status/placeholder message overlays
the list when it is empty.
description, rating, developer, publisher, genre, players, release
date, last played, play count, marquee, and optionally a video
preview. All metadata panel components are fully theme-driven (see
Theme Support below).
The character row is a single horizontal strip of selectable character
cells used for gamepad text entry. It supports three modes:
The ← and → cells move the text cursor within the search query (not the
char row selection). The backspace cell deletes the character to the left
of the cursor.
Cell widths are computed from the font metrics plus padding. If the
combined width of all cells exceeds the component width (e.g. after
adding many symbols), the per-cell padding is uniformly reduced so that
all characters remain visible without scrolling or clipping.
When focus is on the char row:
left or right. Holding the direction triggers auto-scroll repeat
after an initial delay (500 ms) at a fixed period (100 ms).
mode, trigger backspace, or move the text cursor.
after 500 ms at 80 ms intervals (same timing as keyboard held keys).
the query string. Holding triggers repeat after 500 ms at 80 ms.
results are present).
When a physical keyboard is in use and focus is on the char row, all
keyboard events are intercepted before the button map is consulted. This
prevents conflicts where a printable key (e.g. 's') is also mapped to a
gamepad button action (e.g. 'x' = backspace). The interception rules:
after SDL_KEYDOWN. Control characters and space are excluded from
SDL_TEXTINPUT; space is handled directly in the SDLK_SPACE case.
triggers repeat after 500 ms at 80 ms intervals using a software
timer (mKeyRepeatKey / mKeyRepeatTimer), since SDL filters key.repeat
for non-printable keys before they reach input().
repeat behaviour as backspace.
for printable characters.
The help bar switches between keyboard hints ("esc=close") and gamepad
hints immediately whenever the active input device type changes.
Pressing down (gamepad) or the down arrow (keyboard) from the char row
moves focus to the result list. The char row selection highlight dims
and the result list selector becomes visible.
While focus is on the result list:
back to the char row; reaching the bottom also wraps back to the
char row.
(not shown in Kid UI mode).
options dialog can reposition the result list cursor.
by the RT keypress are flushed so the triggering character is not
inserted.
Searching runs on a background thread to avoid blocking the render loop.
Each keystroke cancels any in-progress search (sets mCancelFlag), joins
the previous thread, then starts a new std::thread that:
early.
mResultsReady.
The main thread polls mResultsReady in update() and applies the results
to the TextListComponent on the next frame.
When the result list cursor moves to a game belonging to a different
system than the one currently themed, applyTheme() is called with the
new system's theme. The result list itself is intentionally excluded from
this re-application to avoid flickering the favorite indicator icon on
every cursor movement — its theme is applied exactly once in the
constructor.
The search view ("search") is fully documented in THEMES.md. Supported
elements:
Layout:
background — image, optional, rendered behind everything (z=0)
searchtext — text, the query bar (pos/size/font/color; text managed
by engine — use ALL ^ TEXT)
listmessage — text, status overlay on the result list
gamelist — textlist, the result list
Metadata values:
md_image, md_thumbnail, md_video, md_marquee, md_name
md_description, md_rating, md_releasedate, md_developer,
md_publisher, md_genre, md_players, md_lastplayed, md_playcount
Metadata labels (text):
md_lbl_rating, md_lbl_releasedate, md_lbl_developer,
md_lbl_publisher, md_lbl_genre, md_lbl_players,
md_lbl_lastplayed, md_lbl_playcount
md_video defaults to invisible (setVisible(false)) — a theme must
explicitly set true to enable video playback. All
other metadata components default to off-screen positions so they are
invisible unless the theme positions them.
LogError) so text-only help prompts (e.g. "esc") render without
spamming the log. Adds "esc" → button_esc_key.svg icon mapping.
to the legacy SDL_JOYSTICK format used by the rest of the input
pipeline, enabling controllers that are recognised by SDL2's
GameController API but not the raw joystick API to work correctly.
the game list.
via the existing textInput() path.
and an optional pre-filtered game list for use from search context.
Video.Project.10.mp4