Files
RetroArch/samples/input/android_focus
Davey Hughes 56952c9a25 Android: follow-up fixes for screens on other displays (gl and vulkan) (#20044)
* rgui: upload the menu again to the video driver a reinit makes

Closing content with RGUI up left the screen black until a key press.
The staged content load presents frames between its stages, so RGUI
can upload its framebuffer to the old video driver and clear FB_DIRTY
just before the driver stage replaces that driver. The new one has no
menu texture, nothing in the menu changes, and RGUI never uploads
again.

command_event_reinit sets FB_DIRTY after its reinit, but the staged
load and video-only resets reach the menu only through context_reset,
so RGUI marks its framebuffer dirty there. The menu_icon_ownership
harness gets an rgui lane that reinits the video driver and checks
the next upload reaches the new one.

* video: draw a frame queued before a view count shrink with its views

Under threaded video the wrapper ran SET_VIEW_COUNT ahead of the frame
it had already claimed, so a closing core's last queued frame drew
after its view chains were gone: whole, both screens stacked, until the
menu's first frame replaced it.

The wrapper still answers at once, but a smaller count reaches the
driver only once the frames queued before it have drawn. A grow applies
at once as before, with the main thread waiting for the preset parse.
Vulkan and glcore therefore build view chains only when the count
grows, so a deferred shrink never parses a preset. They also keep the
headset's whole-frame chain across a count change: it does not depend
on the count, and with chains built only on a grow nothing would
rebuild it after a shrink to 0.

* android: don't make a second screen's EGL surface once Java took it back

Java can take the second screen's surface back between the poll that
hands it over and the frame that makes its EGL surface. Skip making one
then; the screens go back to the main window as they do when a make
fails. Java can still take the surface back during the make itself; the
node's own ANativeWindow reference keeps the window alive through that.

* android: ask a display move by display id and number it

A move named its display by its place in the list, and Java looked
that up later on the UI thread against whatever list was newest, so a
display coming or going in between could send RetroArch elsewhere.
Java now gets the display id and fails the move when that display is
gone. Native code now counts the ids when it compares display lists,
so a display unplugged and plugged back is a new list and its failures
clear.

A failure was a bare flag, so one move's failure could end the next
move and mark its display unable. Each move now carries a number and a
failure counts only for the move it names. The move code also loses
two stores that were always overwritten.

* android: end the refocus hold after a move only when it is done

A move onto a display that is no longer valid now fails at once
instead of waiting out its timeout. The hold that keeps RetroArch's
window unfocusable after a move ends only on the focus loss Android
answers it with, not on a gain that was already queued; an earlier
hold ends only once the new move has started; and onStop() ends a
running hold rather than leaving it to its timer.

* video_windows: tell an external monitor by its display type

Android lists the AYN Thor's two panels and a DP monitor with the same
unknown connection type, so Auto took the monitor for a second panel:
on a one-screen phone Game Screen 2 went to it. Java now reads the
hidden Display.getType() by reflection where it can and passes
internal or external with each display. A display typed internal is
never a monitor; where the type is unknown, a non-default display with
an unknown connection and a product name now counts as one.

* video: give a Presentation on another display its own UI wait

The menu waits up to a second for the Presentation it is laid out for
to show, but the wait was only counted from the first one. Once a
Presentation had shown, one made on another display had no wait left
and the menu fell back to the main window at once.

* input: keep the menu's mouse where it was while the menu is in a window

With Mouse Support on, the menu moving into the Presentation read as a
mouse move to (0,0) for a frame, which marks the pointer active there.
The view keeps the main window's last mouse position instead.

* input: match a window's touches only from a windowed publication

A publication without windows after one with them left the old window
ids in place, so a window's touch lookup could still match them. Only
touches published in a window match now. No Android path publishes
that way today.

* vulkan: copy a waiting window's views on a new frame

A screen window that was up but had no free image on a new frame did
not get its views copied, so a later repeat that drew it, as a pause
with the menu there does, left black areas where those views go. They
are copied on every new frame now.

* video: load the idle logo from the assets directory without widgets

The idle logo's path came from the widgets, which only start with
On-Screen Notifications on, so with them off the idle window stayed
black. Without the widgets' path it is built from the assets
directory the way the widgets build it.

* android: hold the focus when Android moves RetroArch between displays

When the display RetroArch is on, or moving to, goes away, Android
moves the Activity to the default display and can send that display's
focus gain before the removed display's loss. A task moved to another
display and straight back gets no configuration change, and can read
the old display's loss last too. With the loss last, RetroArch pauses
while Android keeps it focused, and no later focus event wakes it.

Count these as moves, as RetroArch's own moves are: a removal, and any
change of RetroArch's display it did not ask for. From Android 10, with
more than one display, so is losing and regaining the top-resumed place
while focused, or regaining it unfocused within a second of losing it
after a loss no hold asked for. The refocus hold that covers a move's
late loss then covers these too: the window is made unfocusable until
Android has taken the focus, then gets the gain again. A gain already on
its way skips the hold, and a move marked while RetroArch is focused
ends after a second with no focus event.

* samples: close test gaps in video_windows and android_focus

The is_default check set the flag and read it back, so it could not
fail; Auto's fallback to the default display now shows the flag at
work. Cover a display listed without an ordinal, and display keys at
sizes 0 to 3, two unnamed displays and a 63-character name. Drop a
stale note from android_focus_test's header.

* video: fix wording left over from the display rows

The Screen Display sublabel still named the Separate mode, a setting
the display rows removed; it now says "when it has a window of its
own". The warnings for a screen window that can't be drawn, or whose
surface is gone, said its screens go back to the main window, but a
window that shows only the menu reaches them too. They now read like
the one for a window that can't be made: what it shows stays in the
main window.

Comments that no longer matched the code are reworded. pointer_frame's
model of the driver before the publication is named was_* rather than
today_*, and a wrong commit hash and a plan tag go from the tests.
video_driver_free_internal() uses VIDEO_ANDROID_RELEASE_KEPT_WINDOWS()
rather than open-coding it, with no change in behaviour.
2026-11-09 18:59:16 +01:00
..