Skip to content

Add conditional overlay profiles (FR #18178)#19077

Draft
f4mrfaux wants to merge 4 commits into
libretro:masterfrom
f4mrfaux:conditional-overlay-profiles
Draft

Add conditional overlay profiles (FR #18178)#19077
f4mrfaux wants to merge 4 commits into
libretro:masterfrom
f4mrfaux:conditional-overlay-profiles

Conversation

@f4mrfaux
Copy link
Copy Markdown

@f4mrfaux f4mrfaux commented May 29, 2026

Status: DRAFT / work-in-progress.

Summary

Implements the required behaviour of #18178 (controller-aware overlay switching).

Adds an Overlay Behavior mode under Settings → On-Screen Display → On-Screen Overlay:

  • Static – overlay never changes.
  • Hide When Controller Is Connected – existing behaviour, preserved.
  • Conditional Profiles – when a controller is connected, the on-screen overlay swaps to a user-selected Minimal Overlay Preset instead of hiding entirely, with a configurable Overlay Switch Delay (default 800 ms) to prevent flicker on rapid hotplug.

A small pure resolver overlay_resolve_profile() maps (behaviour, controller state) to the active profile and is consulted by input_overlay_path(), input_overlay_want_hidden() and the runloop edge-trigger. The legacy input_overlay_hide_when_gamepad_connected bool is migrated into the new enum on config load and kept registered for downgrade safety.

Related Issues

Related Pull Requests

Test plan

  • Static / Hide / Conditional modes behave correctly on controller connect/disconnect
  • Switch delay debounces rapid hotplug
  • Empty minimal preset falls back to the full preset
  • Legacy configs (hide-when-gamepad=true) migrate to Hide mode
  • Builds clean (desktop + Android aarch64)

f4mrfaux and others added 3 commits June 1, 2026 08:01
Generalize the existing "hide overlay when controller connected" toggle
into a cross-platform overlay-profile resolver. A new tri-state setting
input_overlay_behavior selects Static / Hide-when-controller / Conditional
profiles; in Conditional mode the overlay swaps to a user-selected minimal
preset (input_overlay_minimal) instead of hiding entirely, with a debounce
window (input_overlay_switch_delay_ms, default 800 ms) that prevents
flicker on rapid controller hotplug.

overlay_resolve_profile() maps (behavior, controller_connected) to a
profile and is consulted by input_overlay_path(), input_overlay_want_hidden()
and the runloop edge-trigger. The legacy
input_overlay_hide_when_gamepad_connected bool is migrated into the new
enum on config load and kept registered for downgrade safety.

Implements the required behaviour of libretro#18178.
Add the On-Screen Overlay menu entries for the new overlay behaviour mode
(Static / Hide When Controller Is Connected / Conditional Profiles), the
Minimal Overlay Preset file picker, and the Overlay Switch Delay, including
labels, sublabels and English strings. The Minimal Preset and Switch Delay
entries are shown only in the modes where they apply.

The legacy hide-when-gamepad toggle is removed from the overlay menu
(superseded by the behaviour enum) but kept registered so existing configs
still round-trip.
)

Wire up the minimal-preset path that the conditional resolver was
already returning OVERLAY_PROFILE_MINIMAL for. Before this commit the
master enum + English strings existed but the menu entry, file
browser, default constant, and resolver fallback were not connected.

- file_path_special.h: FILE_PATH_DEFAULT_OVERLAY_MINIMAL =
  "gamepads/neo-retropad/neo-retropad_collapsed.cfg".
- configuration.c: fill settings->paths.path_overlay_minimal with the
  default at config-defaults time (mirrors path_overlay).
- menu/menu_setting.c: CONFIG_PATH for path_overlay_minimal under the
  overlay group; emits CMD_EVENT_OVERLAY_INIT on change. Also remove
  the obsolete "Hide When Controller Connected" bool menu entry - it
  is superseded by input_overlay_behavior. cfg key + migration remain
  for downgrade safety.
- menu/cbs/menu_cbs.h, menu_cbs_ok.c: ACTION_OK_DL_INPUT_OVERLAY_MINIMAL_PRESET
  with the same expansion+archive-delim handling the main preset uses.
- intl/msg_hash_lbl.h, msg_hash_lbl_str.h: register the label enum and
  cfg key "input_overlay_minimal".
- input/input_driver.{h,c}: extend overlay_resolve_profile() with a
  minimal_available parameter. When CONDITIONAL is selected and the
  user has not set a minimal preset, downgrade MINIMAL to FULL so the
  caller's state machine stays consistent with what input_overlay_path()
  will actually return. Removes the runtime fallback inside
  input_overlay_path() (the resolver handles it now). Three call sites
  updated (input_overlay_want_hidden, input_overlay_loaded, input_overlay_path).
- runloop.c: pass minimal_available into the runloop resolver call.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@f4mrfaux f4mrfaux force-pushed the conditional-overlay-profiles branch 2 times, most recently from 44bf681 to cde459b Compare June 1, 2026 12:17
…bretro#18178)

When a wireless controller is powered off or otherwise vanishes,
Android's InputManager fires onInputDeviceRemoved on the activity, but
RetroArch's input config layer kept the cached device-name binding, so
input_config_get_device_name(port) continued to report the controller
as present until the next autoconf event. For consumers that drive
behaviour off that check - notably the Conditional Overlay Profile
resolver added in this PR, which switches the on-screen overlay between
full and minimal presets based on hotplug state - the controller
appeared bonded indefinitely and the overlay never returned to its
full preset after disconnect.

Wire RetroActivityCommon.onInputDeviceRemoved through to
android_input.c via a JNI bridge:

  Java onInputDeviceRemoved(id)
    -> RetroActivityCommon.inputDeviceRemoved(id)    [native]
       -> push id into g_android_removed_ids[]       [mutex queue]

  android_input_poll()
    -> android_input_drain_pending_removed(android)
       -> find pad_states[port].id == removed_id
       -> clear pad_states[port].id and .name[0]
       -> input_config_clear_device_name(port)

8-slot queue guarded by android_app->mutex (the lock already used by
APP_CMD_* handlers in this file) so multi-device disconnect bursts (two
BT controllers powered off together) are not dropped, and the read +
drain is atomic. pad_states[port].id is cleared with -1 rather than 0
since Android InputDevice.getDeviceId() can legitimately return 0 for
internal/virtual devices.

The Conditional Overlay resolver fires the FULL transition naturally on
the next poll once the port slot is clear, with the existing debounce
(input_overlay_switch_delay_ms) in effect.

C89-compliant (variables declared at top of block, /* */ comments,
Allman braces, 3-space indent); additive only - if Android never
delivers onInputDeviceRemoved the existing behaviour is unchanged.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant