Files
RetroArch/input/input_driver.h
T
Davey Hughesandlibretroadmin 6ebf66b643 OpenXR: per-screen placement for headset screens, and Edit Screens to arrange them by hand (#19945)
* video: per-screen geometry for the headset's floating screens

Each floating screen, by the core's logical screen id, gets its own
offsets, yaw, pitch, roll, scale and visibility (video_screen_xr_t),
applied on top of where the layout puts it. video_views_xr_reset gives
the defaults and video_views_xr_normalize clamps each value to its
range: offsets to 10 m either way, angles to 180 degrees, scale from 0.1
to 10. A planner given no screens uses the defaults, so nothing moves
until a setting does.

* configuration: save per-screen headset geometry

video_screen<N>_xr_x, _y, _z, _yaw, _pitch, _roll, _scale and _visible
keep each floating screen's adjustments for screen ids 1 to 8, and
survive configuration overrides like the other video settings. A minimal
save writes only the values that differ from the defaults.

The video_screens settings sample checks the round trip and the override
cases, and runs in the OpenXR input and Wine views jobs. The defaults
fixture now links video_views.c, which the reset uses.

* menu: per-screen controls for the headset's floating screens

Stereo 3D & Screens gains Screen, which picks a floating screen by its
logical id among those in the current frame's map, and for it
Horizontal, Vertical and Depth Offset, Yaw, Pitch, Roll, Scale and
Visible, with Reset Screen and Reset All Screens. The rows apply live
and are hidden where they cannot apply, such as a tracked projection's
eyes. Stepping between screens reads one snapshot of the map and is
bounded, so a tracking change mid-step cannot leave it walking an empty
map.

docs/openxr.md describes the controls; the video_screens sample drives
them through the shipping menu actions.

* video: apply per-screen headset geometry to the frame snapshots

Each XR planner, Vulkan's and GL's, takes the normalized screen settings
with the frame snapshot, so a screen moves, turns, scales or hides as
its rows change, while paused too; recentering and tracked projections
are unaffected. Screen images are kept between frames, so shader
feedback survives a placement change.

A retained XR target that cannot be allocated is skipped quietly,
remembered by its size so it is not retried every frame; only the
desktop UI and canvas targets log the failure.

Covered by openxr_core_test, the video_screens sample, the e2e runner's
feedback shader case and the new vulkan_views_target sample.

* android: keep the OpenXR EGL context C89

gl_xr_egl_init declared its extension string after statements.

* video: pose inverse, layout spots and grab maths for headset edit mode

Each item's layout spot comes from one helper that placement uses and
the quad set records per slot, so a shown pose turns back into the
settings that placed it. Grab maths: the item follows the aim, level
unless tilting, offsets clamped to the settings' range; the stick pushes
along the ray and resizes. Edit picking sees every item and takes the
menu by a handle bar under it.

* video: a frame without a view map is screen 1 in the headset

A core without a views map (SNES, say) had no screen to select, so its
frame could not be moved. Its whole frame now takes screen 1's offsets,
turn, scale and visibility, and the selector lists Screen 1. gl's window
stays as laid out while the menu is open over it.

* video: the headset's menu in front of screen 1, or where it was put

The menu sat at a fixed spot, so moving screen 1 closer left the menu
behind it. It now floats 10 cm in front of screen 1, facing as it does,
at its default angular size and never nearer than 0.4 m, while screen 1
floats and shows, and is still submitted after the screens. A menu place
(video_openxr_menu_xr_* with video_openxr_menu_placed) overrides that;
it is saved like the per-screen keys, and Reset All Screens clears it.

* input: Edit Headset Screens mode for the OpenXR controllers

Edit Screens starts from a hotkey, a headset action, the
HEADSET_EDIT_SCREENS command or a Stereo 3D & Screens row, and stops on
the same, on opening the menu, on a video reinit or when the session
ends. It syncs its own action set in place of the game's, points the
lasers at every item whatever the Laser Pointer setting, keeps the
menu's quad up while editing, and with While Editing Screens set to
Pause pauses only content that was running. A runtime that refuses its
bindings keeps the game's and leaves edit mode unavailable.

The setting reaches the headset's poll with the others, and the pause
and resume are asked of the frontend as platform requests, so the input
driver issues no command and takes no settings itself. A Laser Pointer
value past its choices, which a hand-edited config can hold, reads as
Auto rather than as edit mode's.

* input: grab, tilt, push and resize headset screens in edit mode

A grip on an item takes it in the screens' frame: it keeps its pose
relative to the hand, stays level unless the trigger is held, and the
stick pushes it along the laser and resizes it, past a deadzone. Each
poll writes the item's offsets, turn and scale where the menu's rows
write them, through named frontend calls, clamped so it waits at a limit
and resumes from there. The menu is taken by its handle; a menu that
follows screen 1 is placed as large as it shows. The main button resets
a free item as Reset Screen does, or puts the menu back in front of
screen 1. A recenter, a screen leaving the map and leaving edit mode let
go, counted for the frame snapshot; an untracked hand holds its item
still.

* openxr: held screens follow the hand at the headset's rate

The main thread publishes what each hand holds through a seqlock; each
headset frame re-places a held item, both eyes of a stereo screen, from
that frame's own aim, so it no longer waits for the next video frame. An
item let go stays where the hand left it until a quad set planned at or
after its release (an edit count carried in the frame snapshot) shows
it, even once the hand holds another item, so nothing steps back. Lazy
Follow holds its glide while anything is held.

Edit mode outlines every item, brightly the one under a laser, and draws
the menu's handle bar under it, from the laser's image, now an atlas of
the dot, two outlines and two handle bars. They take only the layers the
screens leave after the dots.

* openxr: edit mode end-to-end cases and documentation

The test layer's aim can roll, and the e2e runner drives edit mode
against Monado: grabs that follow the hand on every headset frame and
stay where they are let go, level and tilt, the stick, resets of a
screen and of the menu, the menu taken by its handle and following
Screen 1 at its size, outlines and the handle, a no-map core, a views
core's fallback frame, Follow Head, Lazy Follow, recentering, two hands,
pausing, and what starts and ends edit mode, including the headset's
hotkey bits with no command interface. The cases whose work is a host's
or driver's own run on glcore and gl too. docs/openxr.md explains
editing screens in the headset and where the menu goes.

* openxr: a laser beam from each controller to its dot

A thin strip runs from each hand's aim to its dot, or 1.5 m into
nothing, turned about its own axis each headset frame to face the head
so it never shows edge on. It comes from the laser's image, so it needs
no new swapchain, and uses layers left after the dots and edit mode's
outlines, so it is the first to go when the runtime has few. The new
Laser Beam setting shows it in edit mode only (the default), always, or
never; outside edit mode, Laser Pointer and its hotkey hide it with the
dot.

* openxr: edit mode outlines in three bands, outside the item

A light band between two dark ones shows on white, black and busy
borders alike. The rim now sits wholly outside its item, 5 mm clear of
it even after filtering, so it never covers the picture; its region
grows to keep two texels a band at about the old thickness. Screens'
outlines are submitted before the screens, so a neighbour placed flush
covers the part of a rim over its picture, while the menu's outline and
handle bar stay on top. The handle bar moves 5 mm below the menu's
outline, which it would otherwise cover, and gets the same bands, faint
and bright.

* input: choose a headset edit item with Select Next and Previous

Edit mode steps from the laser through the screens it can move and the
menu. A chosen item is the one lit, either hand's grip takes it from
wherever the hand is, and Reset resets it, so a screen hidden behind
another can be moved. Whatever a hand holds stays lit.

A ray on the menu's handle bar takes the menu before any screen in front
of it. Within 3 cm of the bar, a ray that came from the bar keeps the
menu even over a screen, and one that came from elsewhere takes it only
where no screen is hit.

* openxr: snap a held headset screen to the screens near it

Snap to Screens, on by default, turns a held screen parallel or square
to a nearby screen and lines up its plane, edges or centre. Each pull is
exact within 3 cm or 5 degrees and fades out over as far again, so the
screen catches up with the hand rather than jumping, and snapping fades
in over the first 5 cm or 10 degrees after a grab, so taking a screen
never moves it. With several screens near, the snap that leaves the
least error wins, so a near screen's exact pull beats a far one's fading
pull whatever their order.

One stateless function inside the grab serves the main thread and the
headset's thread, so a screen is saved where it was shown. The holding
hand buzzes as a snap takes hold, once, and not again until the screen
has left that pull.

* input: turn a held headset item with the free hand's stick

A quarter turn of a held screen needed the controller turned a quarter
turn, which swung the screen round the hand on its long reach, so a
square snap could not be reached. Now the stick of the hand holding
nothing turns what the other hand holds about the vertical through its
middle, faster the further it is pushed, and snapping still catches it
parallel or square.

A carried item keeps its pitch and roll and its angle to the way the
hand points across the floor, so raising, lowering or twisting the hand
no longer tips or swivels it; the trigger lets it ride the hand rigidly.

* openxr: smooth the controller aim in edit mode

A screen held about 2 m out on the laser magnified every tremor of the
hand. In edit mode each hand's aim now goes through a One Euro filter,
which smooths a slow hand hard and a fast one little, with its rate
taken from the headset frame's own time step. The headset's thread
filters once a frame and hands the result to the main thread, which
grabs, moves and lets go from it, so a screen is saved where it was
shown. The new Edit Smoothing setting picks Off, Low, Medium (the
default) or High; outside edit mode the lasers are never smoothed.

* openxr: name the chosen edit item beside the controller

Edit mode now shows a faint tag just above the hand that last pressed
Select Next or Previous, reading Laser, Screen N or Menu, so what the
grip will take is plain without a notice. The words are drawn once into
the laser's image in the default font and the interface language, light
over a dark halo like the outlines so they read on any background, and
the tag is one more headset layer; when the runtime is short of layers
the beams are dropped before it.

On a runtime whose swapchains are too narrow for the words, the laser's
image keeps its old width and there is no tag.

* input: tilt a held headset item with the free hand's stick

In edit mode the free hand's stick already turns the item the other hand
holds. Its up and down now tilt that item too, about the item's own
left-right line through its middle, at the turn's rate and with no
limit: up tips the top back, as when pushing a monitor's top back. It
works whether the item is carried or rides the hand with the trigger
held, and snaps as the turn does.

Within about 25 degrees of left or right the stick only turns, and
within about 25 degrees of up or down it only tilts, so a push meant for
one does not drift into the other. Edit mode's starting notice lists the
turn and tilt and stays about 8 seconds.

* input: snap a turned or tilted headset item to angle steps

While the free hand's stick turns or tilts a held item in edit mode, the
item clicks into steps of the new Snap to Angles setting (15 degrees by
default; 30, 45, 90 or Off), so it is easy to set straight. The turn
counts from facing the user's head across the floor, the tilt from
upright. Within about 2 degrees of a step the item holds there and the
holding hand buzzes once; the stick's own angle keeps adding up, so
pushing on leaves the step.

Only the stick steps: carrying an item or tilting it with the trigger
never clicks, and a snap to another screen that would engage wins over a
step.

* openxr: show the back of a headset screen turned away

Runtimes draw only the front of a quad layer, so a screen or the menu
turned away from the head vanished. When the head is behind a quad's
plane, the frame now submits a plain dark panel in that quad's place: a
solid grey cell of the laser's image, at the quad's size, turned to
face the head. It takes the quad's own layer, so the layer count and
cap are unchanged. Edit mode picks either face, so an item turned away
stays grabbable, and its outline, handle and dot turn with its back.

* input: keep a screen snap's angle once the free stick lets go

A snap to another screen shows a held screen square or parallel to it,
but the item's own angle stays where the stick or the hand took it, up
to several degrees off. The next turn with the free hand's stick started
from that hidden angle, so the screen left the snap early on one side,
late on the other, and caught up with a lurch.

Now, as the free stick returns to its deadzone and as a push starts, a
snap engaged on the turn becomes the item's own angle: the carried turn,
or the orientation the trigger tilts. A snap still fading in never does,
since that would hop the screen into it. The place is left to the hand,
and carrying alone never keeps the angle, so pointing still pulls a
screen out of a snap. Letting go of the grip leaves the item where it
shows, as before.

* openxr: hinge a held headset screen to a neighbour's edge

Snap to Screens now also hinges a held screen to another along a
shared edge at any angle between them, so a DS or 3DS pair can be
opened at a slant: an edge within 5 degrees of parallel to one of the
other's, within 3 cm of its line and sharing some length with it,
turns exactly parallel and moves onto it, centres or ends level, its
angle left free. The pull fades in over the first 3 cm of shared
length, so a screen slides off the end of the other's edge without a
jump, and a diagonal neighbour never hinges. Screens that would
overlap do not hinge; the pull is whole from flat to square and fades
out folded shut.

Flat and square snap as before and report a hinge at 0 and 90. A turn
to the same screen pivots on the shared edge, so the edge stays on the
line as the screen leaves flat or square. The snap still keeps nothing
between calls; its result carries a hinge bit, and video_xr_snap_hinge
also says which edge and line, for the stick to swing about.

* input: swing a hinged headset screen about the shared edge

While a held screen is hinged to another, the free hand's stick axis
that turns nearest the shared edge, the tilt for a top or bottom edge
and the turn for a side one, now swings it about that edge, so it stays
attached; the other axis still turns or tilts it and can pull it off.
Where the swing leaves it, angle and place, it stays as the stick lets
go. Snap to Angles counts a hinged screen's steps from flat with the
other screen.

A hinge counts only while the screen's own edge is within its range,
not when other snaps alone hold it on the line, so a swing never
carries a screen round a line it is far from.

A square corner is a side hinge at 90 degrees, so the turn stick there
now swings the screen about the corner's edge. Main thread only;
nothing new reaches the frame loop, which still shows the grab through
video_xr_grab_pose.

* openxr: leave a gap between hinged headset screens

Edges that meet in edit mode, side by side, at a corner or hinged at any
angle, now click to a set gap from within 1 cm and otherwise keep the
gap the hand gives them, still hinged, up to 10 cm (letting go by 13).
Screens no longer have to touch, which made them overlap. Each grab
carries the gap, so the edit poll and the frame loop snap alike; until a
setting sets it, it is 0.

Pushed past touching, a hinged edge stops there for the first centimetre
of the push, the stop fading out by 3 cm, and ticks once per push.

A swing pivots on the held screen's own edge, so the gap keeps through
it, and a commit keeps the hand's gap unless the click holds it. After a
swing lets go past square, that stick axis and its steps keep pivoting
on the same edge until the edge leaves the hinge's reach, so a flick
past square and back does not creep.

Of two neighbours within the 5 degree turn snap, the nearer edge wins
the turn and the hinge, by one measure for every screen, so a screen
stacked behind, one off the ends of the edge or a side wall at a corner
never outranks a hinge the turn holds.

* menu: add Hinge Gap for headset screens

Hinge Gap (0, 1, 2, 3, 5 or 10 cm, default 2) sets the gap edit mode's
Snap to Screens leaves between screens that meet edge to edge, side by
side, at a corner or hinged. Edit mode takes it as it starts and gives
it to each grab; the click to it buzzes like the other snaps.

* menu: put Edit Screens under Headset Output

Stereo 3D & Screens now lists Edit Screens and its snaps right under the
switch that reveals them, then the headset's own setup, then where the
screens go, with the per-screen rows last and Visible first among them.

* openxr: track each held screen's hinge on the frame loop

The frame loop already re-snaps each held screen every frame. It now
also keeps, per hand, the hinge that snap holds whole, until the edge
leaves the hinge's 4.5 cm reach, where the frame draws it, so edit mode
can mark it. A kept hinge whose target no longer matches is dropped.

video_xr gains the hinge line's ends, along the overlap of the two real
edges and midway across the gap, an outline cut that drops one edge's
rim, and a green strip in the laser's image, before the tags.

* openxr: mark a hinged headset screen with a green line

While a held screen's hinge holds, the two edges that meet drop their
outline rim and a 6 mm green line runs along the hinge where they
overlap, midway across the gap, so it is clear when the hinge has taken
hold.

The line is drawn as the beam is, a centimetre nearer the eye than the
edges, since SteamVR does not keep the order of overlapping quad layers,
and comes after the outlines in the layer budget; hidden rims cost no
layer.

* input: buzz longer as a headset screen hinges

A hinge taking hold now gets one 150 ms buzz at 0.8 on the hand carrying
the screen, against the 20 ms snap tick, so the attach can be felt. It
fires again only after the edge leaves the hinge's reach, hinges
elsewhere, or the other hand takes the screen it hinges on, so a swing
past square and back does not repeat it. Ticks due while it plays are
skipped rather than cutting it short.

* openxr: find headset screens resting in a hinge

Two screens no hand holds rest in a hinge when their poses pass the
test that engages a carried screen's hinge, with either one carried,
and the hinge, held whole with nothing else pulling, leaves the carried
one where it is. So a hinge found at rest stays hinged when its screen
is taken. The engaged test moves into its own function so both use the
same one, and one target can pull whole whatever the grab's fade.

* openxr: keep a headset screen's hinge shown at rest

In Edit Screens, two screens no hand holds that rest in a hinge keep
the green line and their hidden rims, whether let go hinged or loaded
that way. The main thread counts them only when a resting screen
changes and sends them with the hands' record, so a release and its
resting pair arrive together; the frame loop places each line from
the screens it shows. A screen hinged at rest on two adjacent edges
still keeps one of those rims.

The hands' record now outgrows the quads, so the seqlock's copy is
sized to the larger of the two.

* openxr: pick up a hinged headset screen still hinged

Taking up a screen that rests in a hinge starts the carry on that hinge,
whole from the first poll, with no buzz and no jump, until it leaves the
hinge's reach, another hinge takes hold, or the other hand takes the
screen it hinges on. Until the grab's own snapping has faded in, the
kept hinge's target still pulls whole, so a straight pull out does not
hop.

The grab carries the hinge so both threads hold it the same; of several,
the one the snap ranks best carries over, and only where holding it
moves nothing. While the other screens fade in, the hinge's screen also
leads the turn, so a nearer one still fading does not take it.

* openxr: end a headset screen's hinge where a push passes the stop

Pushing a hinged screen into its neighbour holds the edge at touching
for 3 cm of push, fading out by 5.5 cm. Where it stops holding, the
hinge ends: the line goes, the rims come back, and the lid and buzz are
cleared, so screens pushed into each other show no hinge that a let-go
there would not rest in. Pulled back, the hinge takes hold again 5 mm
short of where it ended, with the long buzz, so a tremor there does not
flicker it.

The grab carries that through flag, and the frame loop keeps its line
until the main thread sets it, so the two threads never disagree for
more than a poll.

At Hinge Gap 1 a pair let go touching rests hinged and is taken up
hinged, as at every other gap. A screen swung into a square corner gets
the long buzz on arrival, and the other hand taking the target does not
hop the carried screen by the push's depth.

* input: let go of a headset screen where it was before the grip opened

Opening the grip twitches the hand, and the poll that sees the grip
open would move the screen by that twitched aim. Half a degree of pitch
moves a screen 1.8 m out by 1.6 cm, enough to knock it off its hinge's
gap or out of level, so it would not rest hinged.

Each hand keeps a short trail of where, turned and as large as its
screen showed, entries at least 10 ms apart, and a grip let go puts the
screen as it showed 80 ms before (INPUT_OPENXR_EDIT_REWIND_US), or as it
was taken if held for less. Edit mode's end and a recenter let go where
the screen shows.

* openxr: find where a let-go headset screen settles in its hinge

A screen let go while its hinge shows should land exactly in that hinge,
so the hinge still shows at rest and a pick-up is hinged.
video_xr_hinge_settle holds the hinge whole from the hand's pose, then
moves the edge to the set gap from within 3 cm of it (touching stays
where the stop holds it) and levels it along the edge within the level
pull's reach. Its result must pass the rest test, and it turns no
further than a grab's hinge engages, which shares that test.

A pair resting inside a settle band but off its point is no longer
listed at rest, since a pick-up and let-go would move it. A touching
rest is taken 5 mm deeper into the push stop, at every Hinge Gap, so a
hand that drifts less than that apart before letting go settles touching
rather than at the gap.

* openxr: settle a let-go headset screen into its hinge

A screen let go while its hinge shows now goes exactly into that hinge:
to the set gap from within 3 cm of it, touching from the stop's hold,
and level along the edge from within the level pull's reach. It then
rests there, listed and green, in the same publish, and is saved
there. Elsewhere it stays where it shows, as before.

Each trail entry also records where the hand put the screen with no
snap and whether a let-go there settles. At the let-go the rewound
entry is settled again against the screens as they are now, at that
entry's size, and put in one go.

* openxr: let a hinged headset screen rest at any fold

Snap to Screens' turn to flat, and its turn to square at a corner, is
whole within 5 degrees and fades out by 10, so a hinged screen held
there shows at twice its angle off less 10. No fold shown in that fade
read as a rest: the pair was not listed, a let-go there did not settle
into its hinge, and taking it up would have moved it.

Where a hand takes a rest, it now holds the screen at the angle the
turn's fade shows it from, the inverse of the turn's pull, so every
fold rests, is listed and is taken up unmoved. Held snapping is
unchanged.

* input: keep a headset screen's hinge through a shaking hand

Edit Screens' hinge buzz, lid and push stop followed the snap's own
engage and reach on every poll. A hand shaking half a degree (1.6 cm at
the screen) about a hinge's edge flipped them many times a second, each
flip a long buzz.

Each hold now keeps one mark: the hinge a let-go would settle into. It
takes hold at once, with the long buzz, and lets go only once polls have
seen the hand out of where a let-go would settle for 150 ms, each poll
counting at most 50 ms, so a stalled main thread or a spell untracked
never lets it go alone. The other hand taking its target, hinged
elsewhere or not, the target leaving and the let-go end it at once. The
lid waits for the mark to go, the push stop follows it, and a let-go
while it shows settles into it from where the hand last would have, edit
mode's end and a recenter included.

* openxr: draw a held screen's hinge as the main thread marks it

The grab carries the main thread's hinge mark, and the frame loop draws
a held screen's green line and cuts its rims from that mark alone,
through video_xr_grab_marked, while it snaps the screen every frame. A
frame loop taking the hinge by itself between polls would flicker the
line for a hand shaking at the edge of the hinge's range while the mark
held. A mark whose target the frame does not show cuts no rim.

The other hand taking the mark's target ends it, and the lid, on any
poll, tracked or not, so a lost hand's line does not come back when that
hand lets go.

video_xr_grab_near_hinge loses its past argument, which only the frame
loop's keep used.

* openxr: keep edit mode's hinge layers in place

SteamVR does not keep submission order for overlapping quad layers, so
a layer added, dropped or moved to another index can pop the edit
outlines in front of the screens, as a wobble at a hinge would do to
its line's layer.

The hinge lines are fixed slots: one for each hand holding a
screen, hand 0 first, then one for each pair at rest. A slot with no
line to show is drawn in place from its screen's middle, at rows of
the laser image that are empty either way up. The layer count and
every index change only at a grab, a let-go or a re-count of the pairs
at rest; a mark only changes crops and which rows a slot shows.

* input: date a let-go's trail by frame and stop it at a stall

Each trail entry is dated by the frame its aims are from, one a frame
and per hand, and the release poll records a new frame's aims first.
The rewind stops at a stall, entries more than 2.5 frames apart, a
frame counted as at least 20 ms so a fast headset's close entries never
read as one. Under load a stall of 0.1 to 0.3 s can come just before
the release; the entry from 80 ms back would then hold the pose from
before it and step the let-go back across all the stall's motion.

With Edit Smoothing on, which damps the twitch, a let-go that does not
settle into a hinge stays where and as large as it shows: a rewind there
would step back by what the smoothed aim still lags. The hinge decision
and the settle use the trail either way.

* openxr: cut edit outlines from cells instead of turning them

Cutting a top or bottom rim from the one outline image turns both
outline quads a quarter turn and swaps their width and height, and on
SteamVR that can blink every edit outline as the hinge takes hold or
lets go; side cuts, which never turn, do not.

The laser's image carries twelve pre-cut outline cells after the
tags, faint and bright, for a cut top, bottom, left, right, top and
bottom, or left and right, so a cut only picks a cell and the quads keep
their pose and size. The image is then 5582 texels wide. A runtime whose
swapchains are narrower, or that does not say how wide they can be,
keeps the turned and cropped outline at 2498 or 1208 wide. One log line
at the laser's creation gives the width chosen and the runtime's limit.
GL writes the top and bottom cells swapped for its bottom-up rows, and
Android's copy of the image is allocated rather than static.

The edit-hinge-3ds-narrow e2e case runs the turned cut at
RA_XR_LAYER_MAX_WIDTH=4096, on Vulkan and the GL EGL lanes.

* video: draw headset screens straight into the runtime's images

Each headset screen was drawn into an image of the driver's own and
copied from it into the runtime's on every new frame, Vulkan with a
render pass and GL3 with a blit. Screens are now drawn into the
runtime's image itself, as before per-screen placement, with no image
of the driver's and no copy.

A screen drawn again with no new frame - resized, made again or moved
while paused - replays the last frame's final pass from the chain:
build_viewport_pass_replay draws it at the new size from what it read
then, the passes' outputs, their feedback and the history that frame
saw, with that frame's count. Nothing else runs, feedback does not
swap and history stays, so a feedback or history preset holds still
while paused. A chain made to replay keeps one more history image, so
the frame's end writes where the last frame did not read; the window's
chains keep what they did. This also has movie frames reach the
headset, which the copy held at the first one, and draws a screen
resized while paused at its new size rather than stretching the old
image.

* openxr: leave what users who never edit see as it was

Screens seen from behind turn to their grey backs only while Edit
Screens is on, where screens are turned around; outside it nothing
changes and no head is located for them. The grabs carry whether
editing is on.

The menu opens at its own spot, straight ahead of the anchor, as it
did. Menu in Front of Screen 1, off by default, keeps it just in front
of screen 1 and moving with it.

The frame loop copies the main thread's grabs only once their stamp
moves, so outside edit mode no frame copies them. A new session clears
the frame loop's own copy and passes over what was published before
it, rather than publishing itself: the main thread stays the grabs'
one writer.

On Touch, the left menu button that opens the menu from edit mode is
spent until let go: held on as edit mode ends, it is no Start and does
not toggle the menu again after a second.

---------

Co-authored-by: libretroadmin <[email protected]>
2026-10-30 05:40:25 +01:00

2633 lines
103 KiB
C

/* RetroArch - A frontend for libretro.
* Copyright (C) 2010-2014 - Hans-Kristian Arntzen
* Copyright (C) 2011-2017 - Daniel De Matteis
*
* RetroArch is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with RetroArch.
* If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __INPUT_DRIVER__H
#define __INPUT_DRIVER__H
#include <string.h>
#include <stdint.h>
#include <stdlib.h>
#include <stddef.h>
#include <sys/types.h>
#include <boolean.h>
#include <retro_common_api.h>
#include <retro_atomic.h>
#include <retro_inline.h>
#include <libretro.h>
#include <retro_miscellaneous.h>
#include <streams/interface_stream.h>
#include "../tasks/task_notify.h"
#ifdef HAVE_CONFIG_H
#include "../config.h"
#endif /* HAVE_CONFIG_H */
#include "input_defines.h"
#include "../gfx/video_defines.h"
#include "input_types.h"
#include "input_sensor_snap.h"
#ifdef HAVE_OVERLAY
#include "input_overlay.h"
#endif
#include "input_osk.h"
#include "../msg_hash.h"
#ifdef HAVE_HID
#include "include/hid_types.h"
#include "include/hid_driver.h"
#endif
#include "include/gamepad.h"
#include "../configuration.h"
#include "../performance_counters.h"
#ifdef HAVE_COMMAND
#include "../command.h"
#endif
#ifdef HAVE_BSV_MOVIE
#include "bsv/uint32s_index.h"
#endif
#if defined(ANDROID)
#define DEFAULT_MAX_PADS 8
#define ANDROID_KEYBOARD_PORT DEFAULT_MAX_PADS
#elif defined(_3DS)
#define DEFAULT_MAX_PADS 1
#elif defined(SWITCH) || defined(HAVE_LIBNX)
#define DEFAULT_MAX_PADS 8
#elif defined(WIIU)
#ifdef WIIU_HID
#define DEFAULT_MAX_PADS 16
#else
#define DEFAULT_MAX_PADS 5
#endif /* WIIU_HID */
#elif defined(DJGPP)
#define DEFAULT_MAX_PADS 1
#define DOS_KEYBOARD_PORT DEFAULT_MAX_PADS
#elif defined(XENON)
#define DEFAULT_MAX_PADS 4
#elif defined(VITA) || defined(SN_TARGET_PSP2) || defined(ORBIS)
#define DEFAULT_MAX_PADS 4
#elif defined(PSP)
#define DEFAULT_MAX_PADS 1
#elif defined(PS2)
#define DEFAULT_MAX_PADS 8
#elif defined(GEKKO) || defined(HW_RVL)
#define DEFAULT_MAX_PADS 4
#elif defined(HAVE_ODROIDGO2)
#define DEFAULT_MAX_PADS 8
#elif (defined(BSD) && !defined(__MACH__))
#define DEFAULT_MAX_PADS 8
#elif defined(__QNX__)
#define DEFAULT_MAX_PADS 8
#elif defined(__PS3__)
#define DEFAULT_MAX_PADS 7
#elif defined(_XBOX)
#define DEFAULT_MAX_PADS 4
#elif defined(HAVE_XINPUT) && !defined(HAVE_DINPUT)
#define DEFAULT_MAX_PADS 4
#elif defined(DINGUX)
#define DEFAULT_MAX_PADS 2
#elif defined(__EMSCRIPTEN__)
#define DEFAULT_MAX_PADS 4
#else
#define DEFAULT_MAX_PADS 16
#endif /* defined(ANDROID) */
#define MAPPER_GET_KEY(state, key) (((state)->keys[(key) / 32] >> ((key) % 32)) & 1)
#define MAPPER_SET_KEY(state, key) (state)->keys[(key) / 32] |= 1 << ((key) % 32)
#define MAPPER_UNSET_KEY(state, key) (state)->keys[(key) / 32] &= ~(1 << ((key) % 32))
/*
INVALID: should never arise.
REGULAR: just key and button inputs, nothing else
CHECKPOINT: an 8-byte size and serialized raw state follow the actions.
CHECKPOINT2: a state follows the actions, but it is encoded and/or
compressed in some way. The next two bytes are the compression
type and the encoding type, followed by the 4-byte uncompressed,
unencoded size; the 4-byte uncompressed, encoded size; the 4-byte
compressed, encoeded, size; and the compressed, encoded data.
If either the encoding or the compression codec are not supported,
the checkpoint will be skipped.
*/
#define REPLAY_TOKEN_INVALID '\0'
#define REPLAY_TOKEN_REGULAR_FRAME 'f'
#define REPLAY_TOKEN_CHECKPOINT_FRAME 'c'
#define REPLAY_TOKEN_CHECKPOINT2_FRAME 'C'
/* Which compression codec to use. */
#define REPLAY_CHECKPOINT2_COMPRESSION_NONE 0
#define REPLAY_CHECKPOINT2_COMPRESSION_ZLIB 1
#define REPLAY_CHECKPOINT2_COMPRESSION_ZSTD 2
/* Which encoding to use.
RAW: Just raw checkpoint data, possibly compressed.
STATESTREAM: Incremental, block-deduplicated encoding per
https://github.com/sumitshetye2/v86_savestreams
*/
#define REPLAY_CHECKPOINT2_ENCODING_RAW 0
#define REPLAY_CHECKPOINT2_ENCODING_STATESTREAM 1
RETRO_BEGIN_DECLS
enum rarch_movie_type
{
RARCH_MOVIE_PLAYBACK = 0,
RARCH_MOVIE_RECORD
};
enum input_driver_state_flags
{
INP_FLAG_NONBLOCKING = (1 << 0),
INP_FLAG_KB_LINEFEED_ENABLE = (1 << 1),
INP_FLAG_KB_MAPPING_BLOCKED = (1 << 2),
INP_FLAG_BLOCK_HOTKEY = (1 << 3),
INP_FLAG_BLOCK_LIBRETRO_INPUT = (1 << 4),
INP_FLAG_BLOCK_POINTER_INPUT = (1 << 5),
INP_FLAG_GRAB_MOUSE_STATE = (1 << 6),
INP_FLAG_REMAPPING_CACHE_ACTIVE = (1 << 7),
INP_FLAG_DEFERRED_WAIT_KEYS = (1 << 8),
INP_FLAG_WAIT_INPUT_RELEASE = (1 << 9),
INP_FLAG_MENU_PRESS_PENDING = (1 << 10),
INP_FLAG_MENU_PRESS_CANCEL = (1 << 11),
/* A system-provided keyboard panel is on screen and owns text
* entry. Set and cleared by whichever input driver put it there,
* once per poll; read through input_osk_native_active(). */
INP_FLAG_NATIVE_KB_SHOWN = (1 << 12),
/* This device has a native keyboard panel the frontend could use
* in place of the built-in OSK. Published the same way; read
* through input_osk_native_available(). */
INP_FLAG_NATIVE_KB_AVAIL = (1 << 13),
/* Background controller input is off and the window is not
* focused: the joypad read paths see an idle controller. Set once
* per poll; read through input_driver_joypad_for_read(). */
INP_FLAG_JOYPAD_UNFOCUSED = (1 << 14),
/* led_driver is "overlay": the overlay shows the LEDs'
* state (overlay_leds_lit). */
INP_FLAG_OVERLAY_LEDS = (1 << 15)
};
#ifdef HAVE_BSV_MOVIE
enum bsv_flags
{
BSV_FLAG_MOVIE_START_RECORDING = (1 << 0),
BSV_FLAG_MOVIE_START_PLAYBACK = (1 << 1),
BSV_FLAG_MOVIE_PLAYBACK = (1 << 2),
BSV_FLAG_MOVIE_RECORDING = (1 << 3),
BSV_FLAG_MOVIE_END = (1 << 4),
BSV_FLAG_MOVIE_EOF_EXIT = (1 << 5),
BSV_FLAG_MOVIE_FORCE_CHECKPOINT = (1 << 6),
BSV_FLAG_MOVIE_PREV_CHECKPOINT = (1 << 7),
BSV_FLAG_MOVIE_NEXT_CHECKPOINT = (1 << 8),
BSV_FLAG_MOVIE_SEEK_TO_FRAME = (1 << 9),
BSV_FLAG_MOVIE_SEEKING = (1 << 10)
};
struct bsv_state
{
uint16_t flags;
/* Movie playback/recording support. */
char movie_auto_path[PATH_MAX_LENGTH];
/* Immediate playback/recording. */
char movie_start_path[PATH_MAX_LENGTH];
/* Target frame/position to seek to next iteration. */
int64_t seek_target_frame, seek_target_pos;
};
/* These data are always little-endian. */
struct bsv_key_data
{
uint8_t down;
uint8_t _padding;
uint16_t mod;
uint32_t code;
uint32_t character;
};
typedef struct bsv_key_data bsv_key_data_t;
struct bsv_input_data
{
uint8_t port;
uint8_t device;
uint8_t idx;
uint8_t _padding;
/* little-endian numbers */
uint16_t id;
int16_t value;
};
typedef struct bsv_input_data bsv_input_data_t;
#define BSV_MOVIE_MAX_INPUT_EVENTS 512
enum bsv_netplay_flags
{
BSV_NETPLAY_FLAG_ACTIVE = (1 << 0),
BSV_NETPLAY_FLAG_ARMED = (1 << 1),
BSV_NETPLAY_FLAG_COMMITTED = (1 << 2)
};
#define BSV_MOVIE_IS_NETPLAY(m) (((m)->netplay_flags & BSV_NETPLAY_FLAG_ACTIVE) != 0)
struct bsv_movie
{
intfstream_t *file;
int64_t identifier;
uint32_t version;
size_t min_file_pos;
/* A ring buffer keeping track of positions
* in the file for each frame. */
size_t *frame_pos;
size_t frame_mask;
uint64_t frame_counter;
/* Staging variables for events */
uint8_t key_event_count;
uint16_t input_event_count;
bsv_key_data_t key_events[128];
bsv_input_data_t input_events[BSV_MOVIE_MAX_INPUT_EVENTS];
/* Rewind state */
bool playback;
bool first_rewind;
bool did_rewind;
bool checkpoint_ready;
/* Netplay stages frames until their inputs have been confirmed. */
const char *netplay_error;
size_t netplay_next_ptr;
uint32_t netplay_start_frame;
uint32_t netplay_next_frame;
uint8_t netplay_flags; /* enum bsv_netplay_flags */
#ifdef HAVE_STATESTREAM
/* Block index and superblock index for incremental checkpoints */
uint32s_index_t *superblocks;
uint32s_index_t *blocks;
uint32_t *superblock_seq;
size_t superblock_seq_len;
uint8_t commit_interval, commit_threshold;
#endif
uint8_t checkpoint_compression, checkpoint_encoding;
uint8_t *last_save, *cur_save;
size_t last_save_size, cur_save_size;
bool cur_save_valid;
};
typedef struct bsv_movie bsv_movie_t;
enum replay_checkpoint_behavior_ {
REPLAY_CPBEHAVIOR_SKIP,
REPLAY_CPBEHAVIOR_UPDATE,
REPLAY_CPBEHAVIOR_DESERIALIZE
};
typedef enum replay_checkpoint_behavior_ replay_checkpoint_behavior;
#endif
/**
* line_complete callback (when carriage return is pressed)
*
* @param userdata User data which will be passed to subsequent callbacks.
* @param line the line of input, which can be NULL.
**/
#ifndef INPUT_KEYBOARD_LINE_COMPLETE_T_DEFINED
#define INPUT_KEYBOARD_LINE_COMPLETE_T_DEFINED
typedef void (*input_keyboard_line_complete_t)(void *userdata,
const char *line);
#endif
struct input_keyboard_line
{
char *buffer;
void *userdata;
/** Line complete callback.
* Calls back after return is
* pressed with the completed line.
* Line can be NULL.
**/
input_keyboard_line_complete_t cb;
size_t ptr;
size_t size;
size_t capacity; /* Allocated size of buffer (excluding NUL) */
bool enabled;
bool select_all;
bool fixed; /* a native keyboard owns the buffer: it cannot move */
};
/* The buffer a native (Android, iOS) keyboard puts under the line */
#define INPUT_NATIVE_KEYBOARD_BUFFER_SIZE 512
struct rarch_joypad_info
{
const struct retro_keybind *auto_binds;
float axis_threshold;
uint16_t joy_idx;
};
typedef struct
{
unsigned name_index;
uint16_t vid;
uint16_t pid;
char joypad_driver[32];
char name[128];
char display_name[128];
char phys[NAME_MAX_LENGTH];
char config_name[NAME_MAX_LENGTH]; /* Base name of the RetroArch config file */
/* The controller's own deadzones, from its profile, in hundredths
* plus one: 0 is none of its own - the global setting goes - so
* that a cleared entry has none. [0] the sticks', [1] the analog
* buttons'. */
uint8_t deadzone[2];
bool autoconfigured;
} input_device_info_t;
struct remote_message
{
int port;
int device;
int index;
int id;
uint16_t state;
};
typedef struct
{
char display_name[NAME_MAX_LENGTH];
/* For the menu's Input Information, where the driver says: which
* device on the desk this mouse is part of ("" if not known), its
* USB ids (both 0 if not known), and whether it is one to leave
* out - an index with no mouse behind it. */
char device[64];
uint16_t vid;
uint16_t pid;
bool hidden;
} input_mouse_info_t;
/* A keyboard the input driver can tell from the others: its name, for
* the menu. In the order the driver lists them. */
typedef struct
{
char display_name[NAME_MAX_LENGTH];
uint16_t vid; /* 0 with pid 0: not known */
uint16_t pid;
} input_keyboard_info_t;
typedef struct
{
int8_t source; /* RETRO_SENSOR_* ID to read from (0-5), -1 = unmapped */
int8_t sign; /* +1 or -1 */
} input_sensor_axis_t;
typedef struct
{
/* indexed by RETRO_SENSOR_ACCELEROMETER_X..RETRO_SENSOR_GYROSCOPE_Z */
input_sensor_axis_t axes[6];
} input_sensor_map_t;
typedef struct input_remote input_remote_t;
typedef struct input_remote_state
{
/* This is a bitmask of (1 << key_bind_id). */
uint64_t buttons[MAX_USERS];
/* Left X, Left Y, Right X, Right Y */
int16_t analog[4][MAX_USERS];
} input_remote_state_t;
/**
* Organizes the functions and data structures of each driver that are accessed
* by other parts of the input code. The input_driver structs are the "interface"
* between RetroArch and the input driver.
*
* Every driver must establish an input_driver struct with pointers to its own
* implementations of these functions, and each of those input_driver structs is
* declared below.
*/
struct input_driver
{
/**
* Initializes input driver.
*
* @param joypad_driver Name of the joypad driver associated with the
* input driver
*/
void *(*init)(const char *joypad_driver);
/**
* Called once every frame to poll input. This function pointer can be set
* to NULL if not supported by the input driver, for example if a joypad
* driver is responsible for polling on a particular driver/platform.
*
* @param data the input state struct
*/
void (*poll)(void *data);
/**
* Queries state for a specified control on a specified input port. This
* function pointer can be set to NULL if not supported by the input driver,
* for example if a joypad driver is responsible for querying state for a
* particular driver/platform.
*
* @param joypad_data Input state struct, defined by the input driver
* @param joypad_info Info struct for the controller to be queried,
* with hardware device ID and autoconfig mapping.
* @param retro_keybinds Structure for control mappings for all libretro
* input device abstractions
* @param port Which RetroArch port is being polled
* @param device Which libretro abstraction is being polled
* (RETRO_DEVICE_ID_RETROPAD, RETRO_DEVICE_ID_MOUSE)
* @param index For controls with more than one axis or multiple
* simultaneous inputs, such as an analog joystick
* or touchpad.
* @param id Which control is being polled
* (eg RETRO_DEVICE_ID_JOYPAD_START)
*
* @return 1 for pressed digital control, 0 for non-pressed digital control.
* Values in the range of a signed 16-bit integer,[-0x8000, 0x7fff]
*/
int16_t (*input_state)(void *data,
const input_device_driver_t *joypad_data,
rarch_joypad_info_t *joypad_info,
const retro_keybind_set *retro_keybinds,
unsigned port, unsigned device, unsigned index, unsigned id);
/**
* Frees the input struct.
*
* @param data The input state struct.
*/
void (*free)(void *data);
/**
* Sets the state related for sensors, such as polling rate or to deactivate
* the sensor entirely, etc. This function pointer may be set to NULL if
* setting sensor values is not supported.
*
* @param data
* The input state struct
* @param port
* The port of the device
* @param effect
* Sensor action
* @param rate
* Sensor rate update
*
* @return true if the operation is successful.
**/
bool (*set_sensor_state)(void *data, unsigned port,
enum retro_sensor_action action, unsigned rate);
/**
* Retrieves the sensor state associated with the provided port and ID. This
* function pointer may be set to NULL if retrieving sensor state is not
* supported.
*
* @param data
* The input state struct
* @param port
* The port of the device
* @param id
* Sensor ID
*
* @return The current state associated with the port and ID as a float
**/
float (*get_sensor_input)(void *data, unsigned port, unsigned id);
/**
* The means for an input driver to indicate to RetroArch which libretro
* input abstractions the driver supports.
*
* @param data The input state struct.
*
* @return A unit64_t composed via bitwise operators.
*/
uint64_t (*get_capabilities)(void *data);
/**
* The human-readable name of the input driver.
*/
const char *ident;
/**
* Grab or ungrab the mouse according to the value of `state`. This function
* pointer can be set to NULL if the driver does not support grabbing the
* mouse.
*
* @param data The input state struct
* @param state True to grab the mouse, false to ungrab
*/
void (*grab_mouse)(void *data, bool state);
/**
* Check to see if the input driver has claimed stdin, and therefore it is
* not available for other input. This function pointercan be set to NULL if
* the driver does not support claiming stdin.
*
* @param data The input state struct
*
* @return True if the input driver has claimed stdin.
*/
bool (*grab_stdin)(void *data);
/**
* Haptic feedback for touchscreen key presses. This function pointer can be
* set to NULL if haptic feedback / vibration is not supported.
*/
void (*keypress_vibrate)(void);
/**
* Whether the driver, as it is running now, can be left running while
* the video driver is restarted: nothing it holds belongs to the video
* driver, its window or its thread, and it needs no restart to notice
* anything a restart used to make it notice. The joypad driver in use
* is kept or restarted with it, and answers for itself
* (rarch_joypad_driver::survives_video). NULL, which every driver
* that does not name it has, means no: the driver is freed with the
* video driver and started again, as it always was. See
* input_driver_keep_for_video_restart().
*
* @param data The input state struct
*
* @return True if the driver can stay.
*/
bool (*survives_video)(void *data);
/**
* Which of some keys are down on a port's keyboard.
*
* A driver that has this no longer works out the controls bound to
* keys itself: the frontend keeps the keys a port's binds name,
* compiled when the binds change, asks for them all at once, once a
* poll, and answers every RetroPad button and hotkey from that. A
* driver without it (NULL) is asked for each bind as before. A driver that has it also publishes its mice
* (input_driver_publish_pointers()): binds to mouse buttons are
* read from those, from the mouse a port has.
*
* @param data The input state struct
* @param port The port whose keyboard is asked
* @param keys @count key codes (enum retro_key)
* @param bind The bind each key is for: a driver whose hotkeys
* answer to other keyboards than a port's own needs
* to tell them from the port's controls
* (RARCH_FIRST_META_KEY and up are hotkeys)
* @param down Bit n is set for keys[n] if it is down; the caller
* has cleared it
*/
void (*keys_down)(void *data, unsigned port,
const uint16_t *keys, const uint8_t *bind, unsigned count,
uint32_t *down);
/**
* The buttons of the mouse a port's controls bound to mouse buttons
* read, as INPUT_POINTER_* bits.
*
* For a driver that has keys_down and does not publish its mice:
* which mouse a port has, and when it counts, stay the driver's own
* rule. Asked once a poll, and only of a port with such a bind.
* NULL - and now the last member - reads the published mice.
* A driver that has this has its lightgun's bound buttons answered
* by the frontend as well, with this for the mouse buttons among
* them.
*
* @param data The input state struct
* @param port The port asked for
*/
unsigned (*bind_mouse_buttons)(void *data, unsigned port);
};
/* A pad's state as a joypad driver keeps it, for a driver whose state
* changes only in its own poll: lent to the readers between two polls
* in place of a copy (input_driver.c, the snapshot bridge). What each
* field holds is what button(), axis() and get_buttons() answer. */
/* sensor sub-devices a core may address (RETRO_SENSOR_SUBDEVICE),
* after the controller itself */
#define INPUT_SENSOR_SUBDEVICES 4
#define INPUT_PAD_VIEW_AXES 16
#define INPUT_PAD_VIEW_HATS 4
#define INPUT_PAD_VIEW_TOUCHES 2
/* touch_down's bit for the touchpad pressed in, beside its fingers' */
#define INPUT_PAD_TOUCH_PRESS 0x80
typedef struct input_pad_view
{
input_bits_t buttons;
/* each axis signed, as axis() gives its two directions */
int16_t axes[INPUT_PAD_VIEW_AXES];
/* four bits a hat, from bit 0: up, down, left, right */
uint16_t hats;
/* A touchpad's fingers where the pointer device puts a place: x in
* the low half of each word, y in the high, -0x7fff to 0x7fff across
* the pad. Bit n of touch_down is finger n on it. */
uint32_t touch[INPUT_PAD_VIEW_TOUCHES];
uint8_t touch_down;
bool touchpad; /* the pad has one */
} input_pad_view_t;
struct rarch_joypad_driver
{
void *(*init)(void *data);
bool (*query_pad)(unsigned);
void (*destroy)(void);
int32_t (*button)(unsigned, uint16_t);
/* The RetroPad's sixteen as a mask, from what is behind each on this
* pad: @joykeys[n] the pad's button for the n-th (NO_BTN for none)
* and @joyaxes[n] its axis (AXIS_NONE for none), sixteen of each.
* They are resolved by the frontend - the port's own bind, or its
* controller's profile's: a driver is not handed binds, and has none
* to choose between. */
int16_t (*state)(rarch_joypad_info_t *joypad_info,
const uint16_t *joykeys, const uint32_t *joyaxes, unsigned port);
void (*get_buttons)(unsigned, input_bits_t *);
int16_t (*axis)(unsigned, uint32_t);
void (*poll)(void);
bool (*set_rumble)(unsigned, enum retro_rumble_effect, uint16_t);
bool (*set_rumble_gain)(unsigned, unsigned);
bool (*set_sensor_state)(unsigned port,
enum retro_sensor_action action, unsigned rate);
/* return true if handled; false to fall back to input driver */
bool (*get_sensor_input)(unsigned port, unsigned id, float *value);
const char *(*name)(unsigned);
const char *ident;
/* The Bluetooth address a pad that keeps one connects to - a
* DualShock 3, on USB - read and written as shown, most significant
* byte first. NULL, or false, where the pad has none. */
bool (*get_bt_host)(unsigned pad, uint8_t *addr);
bool (*set_bt_host)(unsigned pad, const uint8_t *addr);
/* Whether the driver, as it runs now, can be left running with the
* input driver across a video driver restart: it holds nothing of
* the video driver's. NULL means no, and both are restarted. */
bool (*survives_video)(void);
/* The player pad @pad's lights are to show, from 1; 0 for none, no
* port reading it. Told by the frontend now and then, whether or not
* it changed; the driver acts on a change. NULL where the driver
* lights nothing, or lights by its own lights. */
void (*set_player)(unsigned pad, unsigned player);
/* Pad @pad's state, unchanged until the driver's next poll; NULL
* where the driver cannot say that, which then gets copied. Asked
* once a poll per pad read. */
const input_pad_view_t *(*view)(unsigned pad);
/* Pad @pad's touchpad now, into @view's touch and touch_down; false
* where it has none. For a driver without view(), whose pads are
* copied; NULL where the driver reads no touchpad. */
bool (*get_touchpad)(unsigned pad, input_pad_view_t *view);
};
/**
* Callback for keypress events
*
* @param userdata The user data that was passed through from the keyboard press callback.
* @param code keycode
**/
typedef bool (*input_keyboard_press_t)(void *userdata, unsigned code);
struct input_keyboard_ctx_wait
{
void *userdata;
input_keyboard_press_t cb;
};
/* input_driver_state_t.held_bits_phase: the hold's phase, and beside it
* two bits for a hotkey found down while input waits to be let go -
* found this frame, and found the frame before. The first becomes the
* second each frame (input_driver_hold_bits()), so the mark lasts as
* long as the hotkey is found, and one frame more. */
#define INPUT_HELD_PHASE 0x3f
#define INPUT_HELD_HOTKEY 0x80
#define INPUT_HELD_HOTKEY_WAS 0x40
typedef struct
{
#if defined(HAVE_NETWORKING) && defined(HAVE_NETWORKGAMEPAD)
input_remote_state_t remote_st_ptr; /* uint64_t alignment */
#endif
/* pointers */
#ifdef HAVE_HID
const void *hid_data;
#endif
void *keyboard_press_data;
input_keyboard_line_t keyboard_line; /* ptr alignment */
input_keyboard_press_t keyboard_press_cb; /* ptr alignment */
input_driver_t *current_driver;
void *current_data;
const input_device_driver_t *primary_joypad; /* ptr alignment */
/* When the devices were last read, on cpu_features_get_time_usec()'s
* clock; 0 while nothing asks for it. See input_driver_poll(). */
retro_time_t poll_time_us;
/* The input driver left running across a video driver restart, from
* the video driver's teardown until its start-up hands it back.
* input_driver_keep_for_video_restart(). */
input_driver_t *kept_driver;
void *kept_data;
/* The joypad driver setting the joypad driver was started with. */
char joypad_setting_at_init[32];
/* The settings that decide which port a controller gets, as they
* were then (input_driver_detect_settings()). */
uint32_t detect_settings_at_init;
/* Something has thrown away what the drivers' start gives - the
* controllers' configuration - so the next restart is a restart of
* the input driver too, whatever it says.
* input_driver_restart_with_next_video_restart(). */
bool kept_not_next;
#ifdef HAVE_COMMAND
/* Bumped whenever the command interfaces below are torn down. A
* command that has them remade - LOAD_CONTENT, when the new
* session's settings for them differ - frees the very object whose
* poll dispatched it;
* the dispatcher compares this before and after and stops when it
* has changed rather than touch that object again. */
unsigned command_generation;
command_t *command[MAX_CMD_DRIVERS];
/* The settings the interfaces above were made from */
char command_config[NAME_MAX_LENGTH * 3 + 64];
#endif
#ifdef HAVE_BSV_MOVIE
bsv_movie_t *bsv_movie_state_handle; /* ptr alignment */
bsv_movie_t *bsv_movie_state_next_handle; /* ptr alignment */
/* told once the checkpoint or seek asked for has run */
task_notify_t bsv_movie_op;
#endif
#ifdef HAVE_OVERLAY
input_overlay_t *overlay_ptr;
input_overlay_t *overlay_cache_ptr;
float overlay_eightway_dpad_slopes[2];
float overlay_eightway_abxy_slopes[2];
/* touch pointer indexes from previous poll */
int old_touch_index_lut[OVERLAY_MAX_TOUCH];
/* Bit n: LED n + 1 is lit, for the overlay LED driver. */
uint32_t overlay_leds_lit;
#endif
uint16_t flags;
/* Read and written every poll; kept beside flags so the per-poll
* bookkeeping shares a cacheline with the hot pointer block above,
* rather than sitting past the input_device_info string tables
* (~17 KB of cold data) as it used to. */
unsigned input_hotkey_block_counter;
/* the users the poll's remap work ran for last time, one bit each:
* what it left in the mapper is cleared when it stops running */
uint32_t remap_worked;
#ifdef HAVE_ACCESSIBILITY
unsigned gamepad_input_override;
#endif
#ifdef HAVE_NETWORKGAMEPAD
input_remote_t *remote;
#endif
#if defined(HAVE_TRANSLATE)
#if defined(HAVE_ACCESSIBILITY)
/* RetroPad buttons the AI service presses for user 1, one bit each,
* for the next poll: set by its reply, taken whole by the poll. */
retro_atomic_int_t ai_press_pending;
#endif
#endif
bool osk_textbox_focus;
turbo_buttons_t turbo_btns; /* int32_t alignment */
hold_buttons_t hold_btns; /* int32_t alignment */
input_mapper_t mapper; /* uint32_t alignment */
input_remap_cache_t remapping_cache;
input_device_info_t input_device_info[MAX_INPUT_DEVICES]; /* unsigned alignment */
/* Each controller's own deadzones, as input_device_info_t.deadzone
* has them, kept two bytes apiece where a stick read looks them up:
* the device info's stride is hundreds of bytes. */
uint8_t device_deadzone[MAX_INPUT_DEVICES][2];
/* Each user port's deadzones as its reads take them - [0] the
* sticks', [1] the analog buttons' - worked out by
* input_driver_deadzones_refresh() when what they come from changes. */
float port_deadzone[MAX_USERS][2];
/* the sticks' outer deadzone and anti-deadzone, from the settings */
float stick_outer;
float stick_anti;
float stick_curve; /* the response curve's power: 1 a straight line */
input_mouse_info_t input_mouse_info[MAX_INPUT_DEVICES];
input_keyboard_info_t input_keyboard_info[MAX_INPUT_DEVICES];
/* the listed keyboards' identities, and what each port reads */
char keyboard_identity[MAX_INPUT_DEVICES][64];
unsigned keyboard_identities;
int8_t keyboard_choice[MAX_USERS];
uint16_t keyboard_absent; /* a bit a port: pinned, not there */
/* the same for the mice */
char mouse_identity[MAX_INPUT_DEVICES][64];
unsigned mouse_identities;
int16_t mouse_choice[MAX_USERS];
uint16_t mouse_pinned; /* a bit a port: mouse_choice holds */
uint16_t mouse_absent;
input_sensor_map_t input_sensor_map[MAX_INPUT_DEVICES];
/**
* Array of timers, one for each entry in enum input_combo_type.
* One indexed entry is read per frame, and only while a button
* combo is bound; cold enough that it has no business occupying
* the first six cachelines of this struct, which it used to.
* (rarch_timer_t is int64-aligned; the compiler pads as needed
* here, which costs at most 4 bytes.)
*/
rarch_timer_t combo_timers[INPUT_COMBO_LAST];
/* The hold combinations that have reported for the hold they are
* in, a bit each: see input_driver_button_combo_hold(). */
uint16_t combo_hold_reported;
unsigned osk_last_codepoint;
unsigned osk_last_codepoint_len;
#ifdef HAVE_BSV_MOVIE
struct bsv_state bsv_movie_state; /* char alignment */
#endif
/* primitives */
bool analog_requested[MAX_USERS];
/* the core reads the port's controller touchpad itself */
bool touchpad_requested[MAX_USERS];
/* Per-port joypad state bitmask cache.
* Populated lazily on the first JOYPAD query for each mapped_port
* within a frame, then reused for subsequent individual button
* queries to the same port. Avoids up to 32 indirect
* joypad->button()/axis() calls per port when cores use the
* old per-button query pattern instead of JOYPAD_MASK.
* Invalidated at the start of each input_driver_poll(). */
int32_t joypad_state_cache[MAX_USERS];
/* Per-port set of RetroPad buttons (bits 0..RARCH_FIRST_CUSTOM_BIND-1)
* that INP_FLAG_WAIT_INPUT_RELEASE is still waiting on. Captured
* from whatever is held on the frame the wait is armed and pruned
* as those buttons are released; a button pressed after the wait
* was armed is never in the set, so it is delivered normally.
* While the flag is clear it simply tracks what is held, so a wait
* armed outside input_keys_pressed() starts from the previous
* frame's held set. */
uint16_t wait_release_mask[MAX_USERS];
/* The core's buttons held back after the menu closes: those that
* were down, each until it is let go (input_driver_hold_held_input()).
* One bit per RetroPad button, per port; core_hold_armed while any
* is set. */
uint16_t core_hold_mask[MAX_USERS];
/* and the keyboard's keys, one bit per RETROK_ code */
uint32_t core_hold_keys[(RETROK_LAST + 31) / 32];
/* and per port, the mouse's buttons and the lightgun's, one bit per
* RETRO_DEVICE_ID_, and the pointer being pressed (bit 0) */
uint16_t core_hold_mouse[MAX_USERS];
uint32_t core_hold_gun[MAX_USERS];
uint8_t core_hold_pointer[MAX_USERS];
bool core_hold_armed;
/* tested with core_hold_armed in the core's read */
bool enabler_tap_active;
/* any of cmd_buttons or cmd_analog is held */
bool cmd_input;
/* The same for what the run loop and the menu see - the RetroPad
* bits and the hotkeys: 1 takes what is down at the next frame, 2
* holds it back, 0 is no hold. */
input_bits_t held_bits;
/* The hold's phase in the low bits (INPUT_HELD_PHASE), and the mark
* of a hotkey found down while input waited to be let go
* (INPUT_HELD_HOTKEY): either keeps the wait up, and the one test
* there is for the phase sees both. */
uint8_t held_bits_phase;
/* The frame's view of each port's RetroPad buttons, as a core is
* given them: after port mapping, remaps, turbo, hold, overlays and
* analog-to-d-pad. Compiled when a core asks for the port's mask,
* or for a second button in the frame; from then on every button
* and mask query for the port reads this word. Invalidated by
* input_driver_poll(), and when the core's first analog request
* changes analog-to-d-pad for the port. */
int16_t frame_view_joypad[MAX_USERS];
/* What SET_INPUT holds for each port: stick axes (left X and Y,
* right X and Y) standing in for the port's own while not 0, and
* RetroPad buttons added to its own. */
int16_t cmd_analog[MAX_USERS][4];
uint16_t cmd_buttons[MAX_USERS];
/* Full-range triggers, per controller, as bits by axis: axes bound
* to L2 or R2 that were seen resting at the far end from their
* bind (the pull is counted from there), and axes not to be looked
* at again because both their directions are bound. */
uint16_t trigger_rest[MAX_USERS];
/* Pointer capture: the reasons held (enum input_capture_reason),
* and whether the cursor was last hidden for them. */
uint8_t capture_reasons;
/* The RetroPad buttons something other than the overlay held when
* the system's input was last collected: a controller, a key, a
* command, a network pad. What is pressed and not in here came from
* the overlay alone. */
uint16_t system_buttons_not_overlay;
bool capture_cursor_hidden;
uint16_t trigger_two_way[MAX_USERS];
/* SOCD cleaning, per core port: the D-Pad as it was held when the
* port's view was last compiled, and for each axis the direction
* (as its RetroPad button bit) that has the say while both are held. */
uint8_t socd_held[MAX_USERS];
uint8_t socd_winner[MAX_USERS][2];
/* What input_driver_poll() invalidates, a bit per port in each
* word, kept together so that invalidating all of it is one store:
* joypad_cache - joypad_state_cache[port] holds this frame's mask
* view - frame_view_joypad[port] has been compiled
* asked - the port's first button of the frame was read
* sticks - stick_cache[port][n] holds this frame's read of a
* stick; n is the stick (left, right) */
struct
{
uint16_t joypad_cache;
uint16_t view;
uint16_t asked;
uint16_t snapshot; /* pads snapshotted */
uint16_t sticks[2];
uint16_t pad_state; /* pad_state_cache[port] holds this poll's mask */
uint16_t pad_state_full; /* ... worked out with full-range triggers on */
uint16_t dpad; /* dpad_cache[port] holds this frame's buttons from its sticks */
} frame_valid;
/* A port's RetroPad mask as its controller holds it, worked out
* from the frontend's per-poll copy of the pad: once a poll. It was
* worked out again for every reader of the port's mask - the
* hotkeys, the frame's view for the core, the poll's own - three or
* four times a frame from a copy that does not change between
* them. By port; the threshold is the one it was worked out with. */
int16_t pad_state_cache[MAX_USERS];
float pad_state_thr[MAX_USERS];
/* A port's sticks as the core is given them, each read whole once a
* frame: x and y, for each stick as in
* frame_valid.sticks. A core asks for an axis at a time, and each
* axis asked for was its own reads of the pad - six, with a
* deadzone. The mode is the stick-drives-the-D-pad mode the read was
* made under: a read under another is made again. */
int16_t stick_cache[MAX_USERS][2][2];
uint8_t stick_cache_mode[MAX_USERS];
/* The RetroPad buttons a port's sticks press in a stick-drives-the-
* D-pad mode, worked out once a frame (frame_valid.dpad), and the
* mode they were worked out under. */
uint16_t dpad_cache[MAX_USERS];
uint8_t dpad_cache_mode[MAX_USERS];
retro_bits_512_t keyboard_mapping_bits; /* bool alignment */
input_game_focus_state_t game_focus_state; /* bool alignment */
/* Cached sensor values — written once per frame in input_driver_poll()
* on the main thread, read by shader backends on the video thread.
* Not formally synchronized; relies on single-writer/single-reader
* float stores being practically atomic on ARM/x86. Worst case is
* a single stale frame of sensor data. */
float sensor_gyroscope_cache[3];
float sensor_accelerometer_cache[3];
/* Accelerometer rest position capture state.
* Same thread-safety model as the caches above:
* written on the main thread, read by shader backends
* on the video thread. */
float sensor_accelerometer_rest[3];
float rest_accum[3];
unsigned rest_sample_count;
bool rest_capturing;
/* Set from the shader backends' pass builders (video thread under
* the threaded wrapper) through
* input_driver_set_shader_uses_sensors(), read by the poll's
* demand check on the main thread: atomic with release/acquire,
* not a plain bool. */
retro_atomic_int_t shader_uses_sensors;
/* The sensor caches below, as the shader backends read them each
* frame from the video thread (input_sensor_snap.h). */
input_sensor_snap_t sensor_snap;
bool frontend_sensors_enabled;
/* The snapshot shaders read holds noughts and no shader reads
* sensors: the poll has nothing to publish. The poll's own. */
bool sensor_snap_quiet;
/* the platform's own menu button is held
* (input_driver_set_platform_menu_button()) */
bool platform_menu_button;
unsigned core_accel_rate; /* >0 means core wants accel at this rate */
unsigned core_gyro_rate; /* >0 means core wants gyro at this rate */
/* the sub-devices' sensors the core has enabled: bit 2(i-1) the
* accelerometer of sub-device i, bit 2(i-1)+1 its gyroscope */
uint8_t core_sub_sensors;
/* First-press port assignment, see input_first_press_apply():
* buttons seen released on a user with no core port, the users to
* map at the next frame boundary, and whether any of it is live. */
uint32_t first_press_released[MAX_USERS];
uint32_t first_press_pending;
/* users whose core port a press gave them, not the user */
uint32_t first_press_assigned;
/* the policy, as it stood when the remap defaults were last set */
bool first_press_on;
bool first_press_live;
} input_driver_state_t;
/**
* input_driver_joypad_for_read:
* @drv : primary or secondary joypad driver, or NULL.
*
* The joypad driver to read controller state from. While background
* controller input is off and RetroArch is unfocused this is a stand-in
* that reports every button released and every axis centred, so the
* menu, hotkeys and the core all see an idle controller. Rumble,
* sensors, device names and driver lifetime keep using @drv directly.
*
* Returns: @drv, or the idle stand-in; NULL if @drv is NULL.
**/
const input_device_driver_t *input_driver_joypad_for_read(
const input_device_driver_t *drv);
void input_driver_init_joypads(void);
/**
* Get an enumerated list of all input driver names
*
* @return string listing of all input driver names, separated by '|'.
**/
const char* config_get_input_driver_options(void);
/**
* Sets the rumble state.
*
* @param port
* User number.
* @param joy_idx
* TODO/FIXME ???
* @param effect
* Rumble effect.
* @param strength
* Strength of rumble effect.
*
* @return true if the rumble state has been successfully set
**/
bool input_driver_set_rumble(
unsigned port, unsigned joy_idx,
enum retro_rumble_effect effect, uint16_t strength);
/**
* Sets the rumble gain.
*
* @param gain
* Rumble gain, 0-100 [%]
* @param input_max_users
* TODO/FIXME - ???
*
* @return true if the rumble gain has been successfully set
**/
bool input_driver_set_rumble_gain(
unsigned gain,
unsigned input_max_users);
/**
* Sets the sensor state.
*
* @param port
* User number.
* @param sensors_enable
* TODO/FIXME - ???
* @param effect
* Sensor action
* @param rate
* Sensor rate update
*
* @return true if the sensor state has been successfully set
**/
/* Release-stores the shader-demand latch; callable from the shader
* backends on the video thread. */
void input_driver_set_shader_uses_sensors(bool uses);
/* Seqlock read of the poll-published sensor snapshot: gyroscope,
* accelerometer and accelerometer-rest vec3s, coherent as a set.
* For the shader backends' per-frame uniform uploads on the video
* thread; converges immediately on the main thread. */
void input_driver_read_sensor_snapshot(float *gyro3,
float *accel3, float *rest3);
bool input_driver_set_sensor(
unsigned port, bool sensors_enable,
enum retro_sensor_action action, unsigned rate);
/**
* Retrieves the sensor state associated with the provided port and ID.
*
* @param port
* Port of the device
* @param sensors_enable
* TODO/FIXME - ???
* @param id
* Sensor ID
*
* @return The current state associated with the port and ID as a float
**/
float input_driver_get_sensor(
unsigned port, bool sensors_enable, unsigned id);
uint64_t input_driver_get_capabilities(void);
/* A port's keyboard, kept by what the keyboard is
* (input/common/input_device_pins.h).
*
* An input driver that lists keyboards tells what it knows each by -
* its USB ids, or its name where it has none - whenever it has made
* its list, in the list's order: */
void input_keyboard_pins_set_devices(const char (*base)[64], unsigned n);
/* What a port reads now: 0 for every keyboard as one, a keyboard's
* number in the list, or -1 for none. Read on the input path. */
int input_keyboard_port_choice(unsigned port);
/* The port's Keyboard Index was changed by hand: the port is pinned
* to the keyboard that number names, or to none. */
void input_keyboard_pin_from_index(unsigned port);
/* The port is pinned to a keyboard that is not there. */
bool input_keyboard_pin_absent(unsigned port);
/* The same for a port's mouse. An input driver that lists mice tells
* what it knows each by, in the order of their Mouse Index: */
void input_mouse_pins_set_devices(const char (*base)[64], unsigned n);
/* The mouse a port reads now, as a Mouse Index: the port's own
* setting, the place its pinned mouse has in the list, or
* MAX_INPUT_DEVICES for none. Read on the input path, in place of
* the setting. */
unsigned input_mouse_port_index(unsigned port);
/* The port's Mouse Index was changed by hand: the port is pinned to
* the mouse that number names. @pin false removes the pin. */
void input_mouse_pin_from_index(unsigned port, bool pin);
bool input_mouse_pin_absent(unsigned port);
/* The running input driver's name ("raw", "udev", "wayland"...), or
* an empty string when there is none. */
const char *input_driver_get_ident(void);
/* Whether the input driver can make the device vibrate on a key
* press. */
bool input_driver_has_keypress_vibrate(void);
/* Which input driver a window gets: input_driver_choice.c. */
#if defined(_WIN32) || defined(_XBOX) || defined(__WINRT__)
void input_driver_init_windows(const char *joypad_name,
input_driver_t **input, void **input_data);
#endif
#ifdef HAVE_X11
void input_driver_init_x11(const char *joypad_name,
input_driver_t **input, void **input_data);
#endif
void input_driver_init_kms(const char *joypad_name,
input_driver_t **input, void **input_data);
#ifdef HAVE_WAYLAND
void input_driver_init_wayland(const char *joypad_name, void *window_data,
input_driver_t **input, void **input_data);
#endif
#if defined(HAVE_SDL) && !defined(HAVE_SDL2) && !defined(HAVE_SDL3)
void input_driver_init_sdl1(const char *joypad_name,
input_driver_t **input, void **input_data);
#endif
/* The settings a driver reads, by name: a driver does not take the
* settings (config_get_ptr()) and pick a field out. */
unsigned input_config_get_mouse_index(unsigned port);
unsigned input_config_get_joypad_index(unsigned port);
unsigned input_config_get_rumble_gain(void);
bool input_config_get_nowinkey_enable(void);
bool input_config_get_keyboard_background(void);
bool input_config_get_winraw_xinput_enable(void);
bool input_config_get_winraw_player_lights(void);
bool input_config_get_sdl3_system_keyboard(void);
bool input_config_overlay_configured(void);
unsigned input_config_get_split_joycon(unsigned port);
bool input_config_get_backtouch_enable(void);
bool input_config_get_backtouch_toggle(void);
bool input_config_get_keyboard_gamepad_enable(void);
bool input_config_get_small_keyboard_enable(void);
unsigned input_config_get_keyboard_gamepad_mapping_type(void);
bool input_config_get_suspend_screensaver_enable(void);
unsigned input_config_get_mouse_scale(void);
bool input_config_get_touch_vmouse_pointer(void);
bool input_config_get_touch_vmouse_mouse(void);
bool input_config_get_touch_vmouse_touchpad(void);
bool input_config_get_touch_vmouse_trackball(void);
bool input_config_get_touch_vmouse_gesture(void);
/* The two things a driver changes in the settings, each by name. */
void input_config_set_joypad_index(unsigned port, unsigned idx);
bool input_driver_first_start_fallback(const char *ident);
bool input_config_get_sensors_enable(void);
unsigned input_config_get_block_timeout(void);
bool input_config_get_device_vibration(void);
bool input_config_get_stylus_enable(void);
bool input_config_get_stylus_require_contact_for_click(void);
bool input_config_get_stylus_hover_moves_pointer(void);
unsigned input_config_get_stylus_pressure_sensitivity(void);
/* This computer's Bluetooth address, most significant byte first, and
* its adapter's name; false where there is none or it cannot be read. */
bool input_bluetooth_host_address(uint8_t *addr, char *name, size_t len);
/* The Bluetooth address a controller connects to, read and set where
* its driver can (see input_device_driver_t's get_bt_host). */
/* A device number for a pad of a source beside the joypad driver
* (input_device_pool.h), or -1; and giving it back. */
int input_driver_device_claim(unsigned source, unsigned slot);
void input_driver_device_release(unsigned source, unsigned slot);
bool input_driver_get_bt_host(unsigned pad, uint8_t *addr);
bool input_driver_set_bt_host(unsigned pad, const uint8_t *addr);
bool input_config_get_android_disconnect_workaround(void);
const char *input_config_get_android_physical_keyboard(void);
const char *input_config_get_joypad_driver(void);
const char *input_config_get_keyboard_layout(void);
const char *input_config_get_autoconfig_dir(void);
const char *input_config_get_test_input_file(bool joypad);
/* What a driver may ask the frontend, and tell it, without taking its
* state (input_state_get_ptr()): each is one thing, by name. */
void input_driver_set_native_keyboard_available(bool available);
/* What a command holds for a port's RetroPad, over the player's own
* input: control below 16 is a button, down for any value but 0, and
* 16 to 19 the sticks' axes at the value. */
void input_driver_command_hold(unsigned port, unsigned control,
int16_t value);
/* Lets go of what a command holds for a port, or with MAX_USERS for
* every port. */
void input_driver_command_release(unsigned port);
/* The buttons a command holds for a port, one bit each, and the four
* axes into analog. */
uint16_t input_driver_command_held(unsigned port, int16_t *analog);
/* Whether a replay is being recorded: what a state restored outside
* the replay's own data would break. */
bool input_driver_replay_recording(void);
void input_driver_set_native_keyboard_shown(bool shown);
bool input_driver_native_keyboard_shown(void);
bool input_driver_keyboard_mapping_blocked(void);
bool input_driver_keyboard_line_enabled(void);
void input_driver_keyboard_line_set(const char *utf8, size_t len);
/* Text entry, for the menu: a line is opened for a callback and the
* keys go to it until it is closed; the platform keyboards edit it in
* place; the on-screen keyboard and the touch keyboards type into it. */
/* What a line of text is for: the platform keyboards show a matching
* layout. In the order of the menu's own. */
enum input_text_type
{
INPUT_TEXT_TYPE_TEXT = 0,
INPUT_TEXT_TYPE_PASSWORD,
INPUT_TEXT_TYPE_NUMBER
};
const char **input_driver_text_entry_open(void *userdata,
input_keyboard_line_complete_t cb,
const char *label, enum input_text_type type, const char *initial_text);
/* The open line's label and type, for a platform's keyboard that shows
* them; whether a line is open is input_driver_keyboard_line_enabled(). */
const char *input_driver_text_entry_label(void);
enum input_text_type input_driver_text_entry_type(void);
size_t input_driver_keyboard_line_length(void);
void input_driver_keyboard_line_clear(void);
void input_driver_osk_press(enum osk_type *osk_idx, int ptr,
bool show_symbol_pages, const char *word, size_t len);
void input_driver_keyboard_line_type(const char *word, size_t len);
void input_driver_set_keyboard_textbox_focus(bool focus);
/* The capture of a bind and text entry: keys kept from the binds, a
* wait for everything to be let go, a callback for each key. */
void input_driver_set_keyboard_mapping_blocked(bool blocked);
/* Who has the keyboard in place of the binds and the hotkeys. Each
* holds and releases under its own name; the keys are the binds' again
* when nobody holds. See input_keyboard_capture_hold(). */
enum input_keyboard_capture
{
/* Game Focus: the keys are the core's alone */
INPUT_KEYBOARD_CAPTURE_GAME_FOCUS = (1 << 0),
/* a line of text is being typed */
INPUT_KEYBOARD_CAPTURE_TEXT = (1 << 1),
/* the menu is waiting for the key to bind */
INPUT_KEYBOARD_CAPTURE_BIND = (1 << 2),
INPUT_KEYBOARD_CAPTURE_ALL = (1 << 3) - 1
};
void input_keyboard_capture_hold(unsigned reasons);
void input_keyboard_capture_release(unsigned reasons);
/* A line of text is being typed (and not merely the keys kept from
* the binds, which Game Focus does too). */
bool input_driver_text_entry_active(void);
void input_driver_set_wait_input_release(bool wait);
bool input_driver_waiting_input_release(void);
void input_driver_set_keyboard_press_cb(input_keyboard_press_t cb,
void *data);
bool input_driver_libretro_input_blocked(void);
bool input_driver_hotkey_blocked(void);
bool input_driver_game_focus_core_requested(void);
bool input_driver_overlay_alive(void);
bool input_driver_overlay_takes_input(void);
bool input_driver_overlay_active_page(void);
/* Whatever is down now is held back, control by control, until each is
* let go: from the core (its buttons, keys, mouse and lightgun buttons
* and the pointer press) and from what the run loop and the menu see
* (the RetroPad bits and the hotkeys). Everything else gets through at
* once. For the menu as it opens and closes, a bind or a text entry
* ends, or the mouse clicks: the press that did it does nothing more. */
void input_driver_hold_held_input(void);
/* The window has changed - fullscreen toggled, the video driver
* restarted: what is down is not to count again until it has been let
* go. See the definition. */
void input_driver_hold_over_window_change(void);
/* Nothing is held back any more: for the menu going away. */
void input_driver_hold_clear(void);
/* The run loop's bits for the frame: what the hold holds back is taken
* out. True while it is holding something back. */
bool input_driver_hold_bits(input_bits_t *bits);
void input_driver_set_nonblocking(bool on);
/* What a platform asks of the frontend through its input driver: the
* home or power button, a panic combination, the system closing the
* app, its window going away and coming back, the content paused and
* resumed. The driver says what happened; the frontend decides what is
* done. */
enum input_platform_request
{
INPUT_PLATFORM_QUIT = 0, /* quit as the Quit hotkey does */
INPUT_PLATFORM_SHUTDOWN, /* the system is closing the app */
INPUT_PLATFORM_MENU_TOGGLE, /* the platform's menu gesture */
INPUT_PLATFORM_REINIT_VIDEO, /* the window's surface was lost */
INPUT_PLATFORM_FOCUS_LOST, /* game focus off, mouse let go */
INPUT_PLATFORM_PAUSE, /* pause the content */
INPUT_PLATFORM_UNPAUSE, /* resume it */
INPUT_PLATFORM_REQUEST_LAST
};
void input_driver_platform_request(enum input_platform_request req);
void input_driver_set_remapping_cache_active(void);
void input_driver_set_sensor_map(unsigned port, const input_sensor_map_t *map);
#ifdef HAVE_OVERLAY
float *input_driver_overlay_eightway_slopes(bool abxy);
#endif
#if defined(HAVE_TRANSLATE) && defined(HAVE_ACCESSIBILITY)
/* The AI service: presses RetroPad button @id for user 1 for one poll;
* and the RetroPad buttons user 1 holds now, as bound, for its
* request. */
void input_driver_ai_gamepad_press(unsigned id);
uint16_t input_driver_ai_gamepad_held(void);
#endif
void input_driver_keyboard_line_append(const char *utf8, size_t len);
/* The line of text being typed, for whoever draws it: its bytes or
* NULL, and where the cursor stands in them. And whether the text box
* has the focus, and not the on-screen keyboard. */
const char *input_driver_keyboard_line_view(size_t *cursor);
bool input_driver_keyboard_line_selected(void);
bool input_driver_keyboard_textbox_focus(void);
void input_driver_keyboard_line_end(void);
bool input_driver_pointer_input_blocked(void);
bool input_driver_game_focus_enabled(void);
bool input_driver_mouse_grabbed(void);
void *input_driver_current_data(void);
/* The platform's own menu button - one that is not a controller's and
* has no bind - is held, or is not. Held, it counts as the Menu Toggle
* hotkey held. For the driver that reads the button, on the frontend's
* thread. */
void input_driver_set_platform_menu_button(bool held);
/* Reads of the input driver for a consumer that is not the core - the
* menu. It asks here and holds neither the driver nor its data nor a
* joypad. The two reads are valid only while there is a driver to
* read, input_driver_has_device_state().
*
* input_driver_device_state(): a mouse, a pointer or a key; no binds
* go to the driver.
* input_driver_bind_capture_state(): the same with the frontend's
* binds and the pad @joy_idx, as the capture of a bind reads them. */
bool input_driver_has_device_state(void);
/* A device's position in one call, packed with VIDEO_POS_PACK: the X and Y of a mouse
* (RARCH_DEVICE_MOUSE_SCREEN, RETRO_DEVICE_MOUSE) or a pointer
* (RETRO_DEVICE_POINTER, RARCH_DEVICE_POINTER_SCREEN). Needs a driver
* that can be read, as input_driver_device_state() does. */
uint32_t input_driver_device_pos(unsigned port, unsigned device,
unsigned idx);
int16_t input_driver_device_state(unsigned port,
unsigned device, unsigned idx, unsigned id);
int16_t input_driver_bind_capture_state(unsigned joy_idx, unsigned port,
unsigned device, unsigned idx, unsigned id);
/* Port 0's mouse and first touch, read from the driver once per poll,
* so every reader in a frame sees one state and a wheel notch once. */
enum input_pointer_view_flags
{
INPUT_PTR_VIEW_VALID = (1 << 0), /* there was a driver to read */
INPUT_PTR_VIEW_MOUSE_LEFT = (1 << 1),
INPUT_PTR_VIEW_MOUSE_RIGHT = (1 << 2),
INPUT_PTR_VIEW_WHEEL_UP = (1 << 3),
INPUT_PTR_VIEW_WHEEL_DOWN = (1 << 4),
INPUT_PTR_VIEW_HWHEEL_UP = (1 << 5),
INPUT_PTR_VIEW_HWHEEL_DOWN = (1 << 6),
INPUT_PTR_VIEW_PTR_PRESSED = (1 << 7), /* RETRO_DEVICE_POINTER */
INPUT_PTR_VIEW_PTR_BACK = (1 << 8),
INPUT_PTR_VIEW_SCR_PRESSED = (1 << 9), /* RARCH_DEVICE_POINTER_SCREEN */
INPUT_PTR_VIEW_SCR_BACK = (1 << 10)
};
/* A pointing device's state for one frame. An input driver that keeps
* its mice says so by publishing each one once a poll
* (input_driver_publish_pointers()); the frontend then answers for the
* mouse, the pointer and the lightgun's aim itself - translating to the
* viewport once a poll, not once a value - and the driver has no code
* for them. A driver that publishes nothing is asked as before.
* A wheel bit is set for the one frame its notch came in. */
enum input_pointer_buttons
{
INPUT_POINTER_LEFT = (1 << 0),
INPUT_POINTER_RIGHT = (1 << 1),
INPUT_POINTER_MIDDLE = (1 << 2),
INPUT_POINTER_BUTTON_4 = (1 << 3),
INPUT_POINTER_BUTTON_5 = (1 << 4),
INPUT_POINTER_WHEEL_UP = (1 << 5),
INPUT_POINTER_WHEEL_DOWN = (1 << 6),
INPUT_POINTER_HWHEEL_UP = (1 << 7),
INPUT_POINTER_HWHEEL_DOWN = (1 << 8)
};
typedef struct input_pointer_frame
{
uint32_t pos; /* in the window: VIDEO_POS_PACK */
uint32_t rel; /* motion since the last poll: VIDEO_POS_PACK */
uint16_t buttons; /* enum input_pointer_buttons */
} input_pointer_frame_t;
enum input_pointers_flags
{
/* Read as a pointer with no real touch in a place, a mouse stands
* for three touches - any button; the right or the middle; the
* middle. Without this it stands for one: its left button. */
INPUT_POINTERS_MOUSE_3_TOUCHES = (1 << 0),
/* A port reads the device at its Mouse Index, or where its pinned
* mouse is (input_mouse_port_index()). Without this port n reads
* device n, and one device is every port's. */
INPUT_POINTERS_BY_MOUSE_INDEX = (1 << 1),
/* With BY_MOUSE_INDEX: only the mouse goes by the port's index. The
* pointer and the lightgun's aim are every port's, from the first
* device. */
INPUT_POINTERS_AIM_EVERY_PORT = (1 << 2),
/* The lightgun aims where the first touch is, when there is one. */
INPUT_POINTERS_GUN_AT_TOUCH = (1 << 3),
/* The pointer is placed as the lightgun is: -0x8000 outside the
* viewport, where it is otherwise held to the viewport's edge. */
INPUT_POINTERS_POINTER_OFFSCREEN = (1 << 4),
/* A place with a touch reads the touch alone: lifted - a pen in the
* air - it is not pressed, whatever the mouse's buttons say. */
INPUT_POINTERS_TOUCH_ALONE = (1 << 5),
/* The lightgun's buttons are what they are bound to - a pad's
* button or axis, a key, a mouse button - and the frontend answers
* them. Without this the driver answers them itself (the Wayland and
* SDL1 and 2 drivers give them the mouse's buttons, bound or not). */
INPUT_POINTERS_GUN_BUTTONS_BOUND = (1 << 6),
/* ... and one bound to a mouse button reads the one mouse at every
* port, whatever each port's Mouse Index */
INPUT_POINTERS_GUN_BUTTONS_EVERY_PORT = (1 << 7)
};
/* From the driver's poll. @count devices, at most MAX_USERS.
* @flags: enum input_pointers_flags. */
void input_driver_publish_pointers(const input_pointer_frame_t *frames,
unsigned count, unsigned flags);
/* The window a device or a touch is in: 0 the main window, else a
* screen's own, with the generation it was made with. */
typedef struct input_video_window
{
unsigned window;
unsigned generation;
} input_video_window_t;
#ifdef HAVE_VIDEO_WINDOWS
/* input_driver_publish_pointers() with each device's window. Its place
* is in that window, through the layout the window last published; a
* screen's window has no place on the main window's screen, and one
* that is gone places it off-screen. Motion and buttons are as they
* were. NULL @windows: all in the main window. */
void input_driver_publish_window_pointers(
const input_pointer_frame_t *frames,
const input_video_window_t *windows,
unsigned count, unsigned flags);
#endif
/* The viewport as of this poll: asked of the video driver the first
* time it is wanted after a poll, and that answer given until the
* next. For a driver that places its own touches or mouse, in its poll
* or as it is read - on the frontend's thread only. */
bool input_driver_poll_viewport(struct video_viewport *vp);
/* video_driver_translate_coord_viewport_wrap() and its confined twin,
* with the poll's viewport in place of one asked for each time. */
#define input_driver_translate_coord_viewport_wrap(vp, mouse_x, mouse_y, res_pos, res_screen_pos) \
(input_driver_poll_viewport(vp) ? video_driver_translate_coord_viewport(vp, mouse_x, mouse_y, res_pos, res_screen_pos, true) : false)
#define input_driver_translate_coord_viewport_confined_wrap(vp, mouse_x, mouse_y, res_pos, res_screen_pos) \
(input_driver_poll_viewport(vp) ? video_driver_translate_coord_viewport(vp, mouse_x, mouse_y, res_pos, res_screen_pos, false) : false)
/* The kind of device (RETRO_DEVICE_MOUSE, RETRO_DEVICE_POINTER, ...)
* published device @i was last read as, or 0: for a driver whose
* handling of a mouse depends on how it is used. */
unsigned input_driver_pointer_read_as(unsigned i);
/* A driver with a touchscreen, with the mice, in its poll. For each of
* @count places, at most 16: where the contact is in the window, as
* VIDEO_POS_PACK; a bit in @present if there is a contact there at
* all; a bit in @down if it is pressed. The three are separate: a
* contact at 0,0 is a contact, and one that has lifted may keep its
* place (@present without @down). */
/* Each touch's contact, as the touchscreen reports it, for touch @i
* of the driver's pointer: @contacts as OVERLAY_CONTACT_PACK(major,
* minor) in pixels, @angles its orientation in ten-thousandths of a
* radian, 0 upright and positive clockwise. From the driver's poll;
* none is had again until the next. For the overlay's D-pad and face
* buttons (input/common/overlay_contact.h). */
void input_driver_publish_touch_contacts(const uint32_t *contacts,
const int16_t *angles, unsigned count);
void input_driver_publish_touches(const uint32_t *pos, unsigned count,
unsigned present, unsigned down);
#ifdef HAVE_VIDEO_WINDOWS
/* The same with each place's window, as for the devices. */
void input_driver_publish_window_touches(const uint32_t *pos,
const input_video_window_t *windows, unsigned count,
unsigned present, unsigned down);
#endif
typedef struct input_pointer_view
{
uint32_t mouse_pos; /* RARCH_DEVICE_MOUSE_SCREEN, VIDEO_POS_PACK */
uint32_t ptr_pos; /* RETRO_DEVICE_POINTER */
uint32_t scr_pos; /* RARCH_DEVICE_POINTER_SCREEN */
uint16_t flags; /* enum input_pointer_view_flags */
} input_pointer_view_t;
const input_pointer_view_t *input_driver_pointer_view(void);
/* A controller as the controller has it, for the capture of a bind:
* each array that is given is filled - @buttons with whether each is
* down, @axes with each axis's position, @hats with the directions
* held OR-ed in. @poll polls the joypad drivers first. */
void input_driver_capture_pad(unsigned pad, bool poll,
bool *buttons, unsigned num_buttons,
int16_t *axes, unsigned num_axes,
uint16_t *hats, unsigned num_hats);
/* The device drivers are polled and nothing else of a poll is done. */
void input_driver_poll_devices(void);
/* A controller's profile is looked up again, as if just connected. */
void input_driver_autoconfigure_pad(unsigned pad);
/* The RetroPad controls a user's controller and keys hold right now, as
* bound and before remaps: a bit each for the sixteen buttons, then
* for the sticks' eight directions (RARCH_ANALOG_LEFT_X_PLUS on).
* Reads the devices; for the menu while it waits for a press. */
uint32_t input_driver_user_controls_bound(unsigned user);
void input_driver_init_platform(const char *joypad_name,
input_driver_t **input, void **input_data);
#ifdef HAVE_SDL3
void input_driver_init_sdl3(const char *joypad_name,
input_driver_t **input, void **input_data);
/* Whether the input driver in use is the SDL 3 one, which reads the
* SDL window's event queue. For the code that pumps that queue. */
bool input_driver_is_sdl3(void);
#endif
/* Leaving the input driver running across a video driver restart: see
* input_driver.c. */
void input_driver_keep_for_video_restart(bool restart, const void *video_data);
bool input_driver_take_kept(input_driver_t **input, void **input_data);
void input_driver_drop_kept(void);
void input_driver_restart_with_next_video_restart(void);
/* For the video driver: see input_driver.c. */
retro_time_t input_driver_get_poll_time(void);
uint32_t input_driver_get_flags(void);
input_driver_t *input_driver_get_current(void);
/* For the video driver's start-up, before the driver's init: the
* window kind is not yet known and no input driver is current. */
void input_driver_video_init_begin(void);
void input_driver_free_with_video(const void *video_data);
/* Why the pointer is captured. It used to be one flag that about ten
* places toggled or rewrote, each after looking at it, so what it
* ended up as went by the order they ran in: leaving fullscreen let
* go of a grab game focus still wanted, and game focus going off let
* go of one the user had asked for.
*
* Now each of them holds or releases its own reason, and the pointer
* is captured while any is held. INP_FLAG_GRAB_MOUSE_STATE is what
* that comes to, and is only written by input_pointer_capture_apply().
* The reasons are kept above the drivers, so a driver that restarts
* has them applied to it again. */
enum input_capture_reason
{
/* the hotkey, or a menu's entry */
INPUT_CAPTURE_USER = (1 << 0),
/* "Automatic Mouse Grab", taken when the window gains focus */
INPUT_CAPTURE_AUTO_FOCUS = (1 << 1),
INPUT_CAPTURE_GAME_FOCUS = (1 << 2),
/* exclusive fullscreen */
INPUT_CAPTURE_FULLSCREEN = (1 << 3),
/* any fullscreen: this one hides the cursor and grabs nothing */
INPUT_CAPTURE_FULLSCREEN_CURSOR = (1 << 4)
};
void input_pointer_capture_hold(unsigned reasons);
void input_pointer_capture_release(unsigned reasons);
/* What exclusive fullscreen adds, for the video mode there is now.
* Nothing is applied: input_pointer_capture_apply() follows. */
void input_pointer_capture_set_fullscreen(bool fullscreen, bool exclusive);
/* The user's toggle: captured, every reason is let go; not captured,
* the user's is held. False, and nothing changed, if the input driver
* cannot grab. */
bool input_pointer_capture_toggle(void);
/* Makes the grab and the cursor what the reasons come to. @force is
* for a driver that has just started and has been told nothing yet. */
void input_pointer_capture_apply(bool force);
/* The reasons held, for the tests. */
unsigned input_pointer_capture_reasons(void);
/* For a combination of RetroPad buttons that opens the menu: buttons
* held on the overlay alone are taken out of @bits when the overlay
* shown has a menu button of its own. A thumb resting on two overlay
* buttons otherwise opens the menu by accident, on an overlay that
* has a button for that anyway (issue #19472). An overlay with no
* menu button is left alone: the combination is its only way in. */
void input_driver_menu_combo_source_gate(input_bits_t *bits);
/* What kind of window a video driver put up, for the input driver that
* goes with it. */
enum input_window_kind
{
INPUT_WINDOW_OTHER = 0,
/* a Windows window (or UWP, or Xbox): input_driver_init_windows() */
INPUT_WINDOW_WINDOWS,
/* an X11 window: input_driver_init_x11() */
INPUT_WINDOW_X11,
/* no window system - KMS/DRM, a Vulkan display:
* input_driver_init_kms() */
INPUT_WINDOW_KMS,
/* a Wayland surface, whose seat's state the video context holds
* and hands over (input_driver_video_window()):
* input_driver_init_wayland() */
INPUT_WINDOW_WAYLAND,
/* an SDL 3 window: input_driver_init_sdl3() */
INPUT_WINDOW_SDL3,
/* an SDL 1.2 window: input_driver_init_sdl1() */
INPUT_WINDOW_SDL1,
/* a platform with one input driver of its own - a console,
* Android, the web: input_driver_init_platform() */
INPUT_WINDOW_PLATFORM
};
/* For a video driver's or a context's start-up: what kind of window it
* made, so that the frontend starts the input driver that goes with
* it. A video driver starts no input driver itself and is handed no
* slots to put one in. @window_data is, for a window system whose
* input state lives with the window in the video driver's own data
* (Wayland), that state - what the input driver the frontend starts is
* given; NULL otherwise. A driver that says nothing gets the input
* driver the setting names, as ever. */
void input_driver_video_window(enum input_window_kind window,
void *window_data);
/* Called once the video driver is up. If it brought an input driver of
* its own, that is the input driver. Otherwise one is started here:
* the one kept from before the restart; the one that goes with the
* kind of window the video driver named
* (input_driver_video_window()); failing those, the one the
* setting names. */
bool video_driver_init_input(
input_driver_t *tmp,
settings_t *settings,
bool verbosity_enabled);
bool input_driver_grab_mouse(void);
bool input_driver_ungrab_mouse(void);
/**
* Get an enumerated list of all joypad driver names
*
* @return String listing of all joypad driver names, separated by '|'.
**/
const char* config_get_joypad_driver_options(void);
/**
* Initialize a joypad driver of name ident. If ident points to NULL or a
* zero-length string, equivalent to calling input_joypad_init_first().
*
* @param ident identifier of driver to initialize.
* @param data joypad state data pointer, which can be NULL and will be
* initialized by the new joypad driver, if one is found.
*
* @return The joypad driver if found, otherwise NULL.
**/
const input_device_driver_t *input_joypad_init_driver(
const char *ident, void *data);
/**
* Registers a newly connected pad with RetroArch.
*
* @param port
* Joystick number
* @param driver
* Handle for joypad driver handling joystick's input
**/
void input_pad_connect(unsigned port, input_device_driver_t *driver);
/**
* Called by drivers when keyboard events are fired. Interfaces with the global
* driver struct and libretro callbacks.
*
* @param down
* Was Keycode pressed down?
* @param code
* Keycode.
* @param character
* Character inputted.
* @param mod
* TODO/FIXME/???
**/
void input_keyboard_event(bool down, unsigned code, uint32_t character,
uint16_t mod, unsigned device);
/* Keyboard events reported from another thread wait for the poll in a
* queue (see input_keyboard_event() in input_driver.c); this is how
* many were dropped because it was full. */
unsigned input_driver_key_events_dropped(void);
input_driver_state_t *input_state_get_ptr(void);
/*************************************/
#ifdef HAVE_HID
/**
* Get an enumerated list of all HID driver names
*
* @return String listing of all HID driver names, separated by '|'.
**/
const char* config_get_hid_driver_options(void);
/**
* Finds first suitable HID driver and initializes.
*
* @return HID driver if found, otherwise NULL.
**/
const hid_driver_t *input_hid_init_first(void);
/* The device number a HID driver's pad in @slot is known by: the slot
* itself where the HID driver is the joypad driver's, a number from
* the shared pool where it is a source beside it; -1 when there is
* none. Released when the pad goes. */
int input_driver_hid_claim(const void *hid_data, unsigned slot,
const char *name, uint16_t vid, uint16_t pid);
int input_driver_hid_number(const void *hid_data, unsigned slot);
void input_driver_hid_release(const void *hid_data, unsigned slot);
/* Whether the HID driver runs beside another joypad driver, which sees
* every pad Windows' own HID driver has: it takes only the pads nothing
* else can reach. */
bool input_driver_hid_beside(const void *hid_data);
/* A test's source beside the joypad driver, in place of the platform's. */
void input_driver_beside_override(const hid_driver_t *drv);
/**
* Get a pointer to the HID driver data structure
*
* @return Pointer to hid_data struct
**/
void *hid_driver_get_data(void);
/**
* This should be called after we've invoked free() on the HID driver; the
* memory will have already been freed so we need to reset the pointer.
*/
void hid_driver_reset_data(void);
#endif /* HAVE_HID */
/*************************************/
/**
* Set the name of the device in the specified port
*
* @param port
* The port of the device to be assigned to
*/
void input_config_set_device_name(unsigned port, const char *name);
/**
* Set the formatted "display name" of the device in the specified port
*
* @param port
* The port of the device to be assigned to
*/
void input_config_set_device_display_name(unsigned port, const char *name);
/* A controller's own stick and trigger deadzones, from its profile
* (each 0 to 0.95, or below 0 for none of its own), and what they are:
* below 0 for none. */
void input_config_set_device_deadzones(unsigned port, float stick, float trigger);
float input_config_get_device_deadzone(unsigned port, unsigned which);
/* Each user port's deadzones worked out again from its controller's
* own and the settings: called when any of those changes. */
void input_driver_deadzones_refresh(void);
void input_config_set_mouse_display_name(unsigned port, const char *name);
/* The mice, for the menu (Information > Input Information). A mouse is
* numbered by its Mouse Index, which is the input driver's own index
* and is not changed by any of this. A driver that knows more says it
* here: @device is what tells one device on the desk from another,
* the same for every part of it ("" if not known) - one mouse is
* often two or three of the system's mice, and they are listed on
* one line; @hidden is an index nothing on the desk is behind.
* Cleared, names included, whenever an input driver starts. Main
* thread. */
void input_config_clear_mouse_info(void);
void input_config_set_mouse_device(unsigned idx, const char *device,
uint16_t vid, uint16_t pid, bool hidden);
const char *input_config_get_mouse_device(unsigned idx);
/* Whether Mouse Index offers this index. Where the input driver
* lists its mice, the ones on the desk are offered - not an index
* with no mouse, and not one the driver says to leave out (a keyboard
* that can send pointer events, a mouse a program made). Under a
* driver that names no mice every index is offered, as it always
* was. */
bool input_config_mouse_offered(unsigned idx);
uint16_t input_config_get_mouse_vid(unsigned idx);
uint16_t input_config_get_mouse_pid(unsigned idx);
bool input_config_get_mouse_hidden(unsigned idx);
/* The keyboards the input driver can tell apart, for the menu
* (Information > Input Information). A driver that lists its
* keyboards clears the names and sets one for each, in its own order,
* when it starts and whenever its list changes; a name that would be
* empty is stored as "N/A". Under a driver that cannot tell keyboards
* apart there are none. Main thread. */
void input_config_clear_keyboard_display_names(void);
void input_config_set_keyboard_display_name(unsigned idx, const char *name);
/* NULL if there is no keyboard at that index */
const char *input_config_get_keyboard_display_name(unsigned idx);
/* a listed keyboard's USB ids, where the driver knows them; both 0
* where it does not */
void input_config_set_keyboard_ids(unsigned idx, uint16_t vid, uint16_t pid);
uint16_t input_config_get_keyboard_vid(unsigned idx);
uint16_t input_config_get_keyboard_pid(unsigned idx);
/**
* Set the configuration name for the device in the specified port
*
* @param port
* The port of the device to be assigned to
* @param name
* The name of the config to set.
*/
void input_config_set_device_config_name(unsigned port, const char *name);
/**
* Set the joypad driver for the device in the specified port
*
* @param port
* The port of the device to be assigned to
* @param driver
* The driver to set the given port to.
*/
void input_config_set_device_joypad_driver(unsigned port, const char *driver);
/**
* Set the physical location of the device in the specified port
*
* A NULL or empty location clears the stored one, so that a port
* whose device reports no location cannot inherit the location of
* whatever occupied it before.
*
* @param port
* The port of the device to be assigned to
* @param phys
* The physical location to set the given port to.
*/
void input_config_set_device_phys(unsigned port, const char *phys);
/**
* Set the vendor ID (vid) for the device in the specified port
*
* @param port
* The port of the device to be assigned to
* @param vid
* The VID to set the given device port to.
*/
void input_config_set_device_vid(unsigned port, uint16_t vid);
/**
* Set the pad ID (pid) for the device in the specified port
*
* @param port
* The port of the device to be assigned to
* @param pid
* The PID to set the given device port to.
*/
void input_config_set_device_pid(unsigned port, uint16_t pid);
/**
* Sets the autoconfigured flag for the device in the specified port
*
* @param port
* The port of the device to be assigned to
* @param autoconfigured
* Whether or nor the device is configured automatically.
*/
void input_config_set_device_autoconfigured(unsigned port, bool autoconfigured);
/**
* Sets the name index number for the device in the specified port
*
* @param port
* The port of the device to be assigned to
* @param name_index
* The name index to set the device to use.
*/
void input_config_set_device_name_index(unsigned port, unsigned name_index);
/**
* Sets the device type of the specified port
*
* @param port
* The port of the device to be assigned to
* @param id
* The device type (RETRO_DEVICE_JOYPAD, RETRO_DEVICE_MOUSE, etc)
*/
void input_config_set_device(unsigned port, unsigned id);
/* Clear input_device_info */
void input_config_clear_device_name(unsigned port);
void input_config_clear_device_display_name(unsigned port);
void input_config_clear_device_config_name(unsigned port);
void input_config_clear_device_joypad_driver(unsigned port);
unsigned input_config_get_device_count(void);
/**
* input_config_sanitize_joypad_indices:
*
* Puts a player whose pad index is out of range on an index no player
* holds. Players sharing an index are left as they are.
*
* Returns true if the mapping had to be corrected.
**/
bool input_config_sanitize_joypad_indices(void);
/* A port whose pad index a lower port also holds follows that port:
* @leader gets, for each of the MAX_USERS ports, the lowest port on
* its index. Code that moves controllers between ports moves only the
* leaders and then calls input_config_follow_shared_ports(). Returns
* how many ports follow another. */
unsigned input_config_shared_ports(uint8_t *leader);
void input_config_follow_shared_ports(const uint8_t *leader);
unsigned *input_config_get_device_ptr(unsigned port);
unsigned input_config_get_device(unsigned port);
/* Get input_device_info */
const char *input_config_get_device_name(unsigned port);
const char *input_config_get_device_display_name(unsigned port);
const char *input_config_get_mouse_display_name(unsigned port);
const char *input_config_get_device_config_name(unsigned port);
const char *input_config_get_device_joypad_driver(unsigned port);
const char *input_config_get_device_phys(unsigned port);
/**
* Retrieves the vendor id (vid) of a connected controller
*
* @param port
* The port of the device
*
* @return the vendor id VID of the device
*/
uint16_t input_config_get_device_vid(unsigned port);
/**
* Retrieves the pad id (pad) of a connected controller
*
* @param port
* The port of the device
*
* @return the port id PID of the device
*/
uint16_t input_config_get_device_pid(unsigned port);
/**
* Returns the value of the autoconfigured flag for the specified device
*
* @param port
* The port of the device
*
* @return the autoconfigured flag
*/
bool input_config_get_device_autoconfigured(unsigned port);
/**
* Get the name index number for the device in this port
*
* @param port
* The port of the device
*
* @return the name index for this device
*/
unsigned input_config_get_device_name_index(unsigned port);
/*****************************************************************************/
/**
* Retrieve the device name char pointer.
*
* @deprecated input_config_get_device_name_ptr is required by linuxraw_joypad
* and parport_joypad. These drivers should be refactored such that this
* low-level access is not required.
*
* @param port
* The port of the device
*
* @return a pointer to the device name on the specified port
*/
char *input_config_get_device_name_ptr(unsigned port);
/**
* Get the size of the device name.
*
* @deprecated input_config_get_device_name_size is required by linuxraw_joypad
* and parport_joypad. These drivers should be refactored such that this
* low-level access is not required.
*
* @param port
* The port of the device
*
* @return the size of the device name on the specified port
*/
size_t input_config_get_device_name_size(unsigned port);
unsigned input_driver_lightgun_id_convert(unsigned id);
#ifdef HAVE_OPENXR
/* The ports that read slot @a read slot @b, and the other way round,
* for this run only: the config file keeps what the user set. */
void input_driver_exchange_ports(unsigned a, unsigned b);
#endif
bool input_driver_pointer_is_offscreen(int16_t x, int16_t y);
bool input_driver_button_combo(
unsigned mode,
retro_time_t current_time,
input_bits_t* p_input);
bool input_driver_find_driver(
settings_t *settings,
const char *prefix,
bool verbosity_enabled);
void input_keyboard_line_append(
struct input_keyboard_line *keyboard_line,
const char *word, size_t len);
void input_keyboard_line_clear(input_driver_state_t *input_st);
void input_keyboard_line_free(input_driver_state_t *input_st);
#ifdef ANDROID
/**
* android_keyboard_start:
* @buffer_ptr : Pointer to the keyboard line buffer.
* @size_ptr : Pointer to the keyboard line size.
* @ptr_ptr : Pointer to the keyboard line cursor.
* @label : Hint shown on the keyboard, or NULL.
* @cb : Line complete callback function.
* @userdata : Userdata passed to the callback.
*
* Raises the native Android (IME) keyboard for menu text entry, made to
* mirror the iOS ios_keyboard_* hooks. Swaps the custom on-screen keyboard
* for the system soft keyboard, enabling paste and password managers.
* Implemented in input/drivers/android_input.c.
*
* Returns: true if the keyboard was shown.
**/
bool android_keyboard_start(char **buffer_ptr, size_t *size_ptr,
size_t *ptr_ptr, const char *label,
input_keyboard_line_complete_t cb, void *userdata);
bool android_keyboard_active(void);
void android_keyboard_end(void);
#endif
/**
* input_keyboard_start_line:
* @userdata : Userdata.
* @cb : Line complete callback function.
*
* Sets function pointer for keyboard line handle.
*
* The underlying buffer can be reallocated at any time
* (or be NULL), but the pointer to it remains constant
* throughout the objects lifetime.
*
* Returns: underlying buffer of the keyboard line.
**/
const char **input_keyboard_start_line(
void *userdata,
struct input_keyboard_line *keyboard_line,
input_keyboard_line_complete_t cb);
#if defined(HAVE_NETWORKING) && defined(HAVE_NETWORKGAMEPAD)
input_remote_t *input_driver_init_remote(
settings_t *settings,
unsigned num_active_users);
void input_remote_free(input_remote_t *handle, unsigned max_users);
/* For Information > Input Information: whether @user has a Network
* RetroPad listening, the port it listens on, and the address of the
* device last heard from it (@heard false while there has been none). */
bool input_remote_info(unsigned user, unsigned *port,
uint32_t *address, bool *heard);
#endif
void input_game_focus_free(void);
/**
* Converts a retro_keybind to a human-readable string, optionally allowing a
* fallback auto_bind to be used as the source for the string.
*
* @param buf A string which will be overwritten with the returned value
* @param bind A binding to convert to a string
* @param auto_bind A default binding which will be used after `bind`. Can be NULL.
* @param size The maximum length that will be written to `buf`
*/
size_t input_config_get_bind_string(void *settings_data,
char *s, const struct retro_keybind *bind,
const struct retro_keybind *auto_bind,
const struct input_bind_label *label,
const struct input_bind_label *auto_label, size_t len);
size_t input_config_get_bind_string_joyaxis(
bool input_descriptor_label_show,
char *s, const char *prefix,
const struct retro_keybind *bind,
const struct input_bind_label *label, size_t len);
size_t input_config_get_bind_string_joykey(
bool input_descriptor_label_show,
char *s, const char *prefix,
const struct retro_keybind *bind,
const struct input_bind_label *label, size_t len);
bool input_key_pressed(int key, bool keyboard_pressed);
bool input_set_rumble_state(unsigned port,
enum retro_rumble_effect effect, uint16_t strength);
/* The device registry (input_registry.h): which controllers there are
* and which have been here before. It mirrors what the joypad drivers
* report; nothing is assigned from it yet. Main thread only. */
const struct input_registry *input_driver_get_registry(void);
/* A joypad driver's connect or disconnect has been applied to @slot. */
void input_driver_registry_connect(unsigned slot, const char *provider,
const char *name, const char *phys, uint16_t vid, uint16_t pid);
void input_driver_registry_disconnect(unsigned slot);
/* The joypad driver is about to start over and report its controllers
* again. If it reports the ones it had, each goes back to the port it
* was on. */
void input_driver_registry_restart(void);
/* Read controllers through a snapshot taken once a poll, in place of
* calls into the joypad driver, whatever the driver. For the harness:
* drivers are switched over one at a time as each is checked. */
void input_driver_set_snapshot_bridge(bool on);
/* The pad index to write to the config file for @port: what the user
* configured, which is not what the setting holds while controllers
* have been put back on their ports after a driver restart. */
unsigned input_config_get_saved_joypad_index(unsigned port);
/* Write the rumble strengths a core's calls left this frame. Main
* thread, once the core has run. */
void input_driver_flush_rumble(void);
/* Stop every motor now and drop what was waiting to be written. */
void input_driver_stop_rumble(void);
bool input_set_rumble_gain(unsigned gain);
float input_get_sensor_state(unsigned port, unsigned id);
void input_sensor_start_rest_capture(void);
bool input_set_sensor_state(unsigned port,
enum retro_sensor_action action, unsigned rate);
/* Core-facing sensor callbacks that track core enable/disable state */
bool input_core_set_sensor_state(unsigned port,
enum retro_sensor_action action, unsigned rate);
float input_core_get_sensor_state(unsigned port, unsigned id);
void *input_driver_init_wrap(input_driver_t *input, const char *name);
const struct retro_keybind *input_config_get_bind_auto(unsigned port, unsigned id);
void input_config_reset_autoconfig_binds(unsigned port);
const input_sensor_map_t *input_config_get_sensor_map(unsigned port);
/* The configured binds, every user's, as their defaults. */
void input_config_reset_binds(void);
/* Every connected controller is forgotten, until the joypad driver
* next starts and finds it again. */
void input_config_forget_controllers(void);
const char *joypad_driver_name(unsigned i);
void joypad_driver_reinit(void *data, const char *joypad_driver_name);
#ifdef HAVE_COMMAND
/* See command_generation in input_driver_state_t. */
unsigned input_driver_command_generation(void);
void input_driver_init_command(
input_driver_state_t *input_st,
settings_t *settings);
void input_driver_deinit_command(input_driver_state_t *input_st);
/* Remakes the command interfaces only if their settings changed, so
* that they, and the replies they owe, outlive a content load. */
void input_driver_refresh_command(input_driver_state_t *input_st,
settings_t *settings);
#endif
#ifdef HAVE_OVERLAY
void input_overlay_unload(void);
void input_overlay_init(void);
void input_overlay_check_mouse_cursor(void);
#endif
#ifdef HAVE_BSV_MOVIE
void bsv_movie_frame_rewind(input_driver_state_t *input_st);
/* The replay is over: said by the code that reads it, which is handed
* the replay and not the input state. */
void bsv_movie_set_end(void);
#ifdef HAVE_NETWORKING
bsv_movie_t *input_driver_netplay_bsv_recording(void);
void input_driver_netplay_bsv_stop(const char *reason, bool checkpoint_failed);
bool input_driver_netplay_bsv_take_checkpoint(void);
bool input_driver_netplay_bsv_next_frame(const void *state, size_t size,
bool forced);
bool input_driver_bsv_stop_recording(void);
#endif
/* @checkpoint_interval and @checkpoint_deserialize are the two replay
* settings, handed over by the run loop, which has them. */
void bsv_movie_next_frame(input_driver_state_t *input_st,
unsigned checkpoint_interval, bool checkpoint_deserialize);
bool bsv_movie_read_next_events(bsv_movie_t *handle, replay_checkpoint_behavior checkpoint_behavior, bool end_movie_on_eof);
bool bsv_movie_reset_playback(bsv_movie_t *handle);
bool bsv_movie_reset_recording(bsv_movie_t *handle);
void bsv_movie_finish_rewind(input_driver_state_t *input_st);
void bsv_movie_deinit(input_driver_state_t *input_st);
void bsv_movie_deinit_full(input_driver_state_t *input_st);
void bsv_movie_enqueue(input_driver_state_t *input_st, bsv_movie_t *state, enum bsv_flags flags);
void bsv_movie_dequeue_next(input_driver_state_t *input_st);
bool movie_commit_checkpoint(input_driver_state_t *input_st);
bool movie_skip_to_prev_checkpoint(input_driver_state_t *input_st);
bool movie_skip_to_next_checkpoint(input_driver_state_t *input_st);
bool movie_seek_to_frame(input_driver_state_t *input_st, int64_t frame);
bool movie_start_playback(input_driver_state_t *input_st, char *path);
/* @cb, when this returns true, is told once playback has started:
* task_data is the replay's identifier, as text, and error is set if it
* did not start. */
bool movie_start_playback_notify(input_driver_state_t *input_st, char *path,
retro_task_callback_t cb, void *user_data);
/* True while a playback-start task is pending, i.e. until its
* callback has installed the replay handle. */
bool movie_playback_start_in_progress(void *data);
bool movie_start_record(input_driver_state_t *input_st, char *path);
/* As movie_start_playback_notify(), told once recording has started:
* task_data is the replay's path. */
bool movie_start_record_notify(input_driver_state_t *input_st, char *path,
retro_task_callback_t cb, void *user_data);
bool movie_stop_playback(input_driver_state_t *input_st);
bool movie_stop_record(input_driver_state_t *input_st);
bool movie_stop(input_driver_state_t *input_st);
size_t replay_get_serialize_size(input_driver_state_t *input_st);
bool replay_get_serialized_data(input_driver_state_t *input_st, void* buffer);
bool replay_set_serialized_data(input_driver_state_t *input_st,
void *buffer, size_t len);
#endif
/**
* input_poll:
*
* Input polling callback function.
**/
void input_driver_poll(void);
/**
* input_state_wrapper:
* @port : user number.
* @device : device identifier of user.
* @idx : index value of user.
* @id : identifier of key pressed by user.
*
* Input state callback function.
*
* Returns: Non-zero if the given key (identified by @id)
* was pressed by the user (assigned to @port).
**/
int16_t input_driver_state_wrapper(unsigned port, unsigned device,
unsigned idx, unsigned id);
void input_driver_collect_system_input(input_driver_state_t *input_st,
settings_t *settings, input_bits_t *current_bits);
/**
* input_keyboard_event:
* @down : Keycode was pressed down?
* @code : Keycode.
* @character : Character inputted.
* @mod : TODO/FIXME: ???
*
* Keyboard event utils. Called by drivers when keyboard events
* are fired.
* This interfaces with the global system driver struct
* and libretro callbacks.
**/
void input_keyboard_event(bool down, unsigned code,
uint32_t character, uint16_t mod, unsigned device);
extern const unsigned input_config_bind_order[24];
extern input_device_driver_t *joypad_drivers[];
extern input_driver_t *input_drivers[];
#ifdef HAVE_HID
extern hid_driver_t *hid_drivers[];
#endif
extern input_driver_t input_android;
extern input_driver_t input_sdl1;
extern input_driver_t input_sdl2;
extern input_driver_t input_sdl3;
extern input_driver_t input_sdl_dingux;
extern input_driver_t input_dinput;
extern input_driver_t input_win32;
extern input_driver_t input_x;
extern input_driver_t input_ps4;
extern input_driver_t input_ps3;
extern input_driver_t input_psp;
extern input_driver_t input_ps2;
extern input_driver_t input_ctr;
extern input_driver_t input_switch;
extern input_driver_t input_xenon360;
extern input_driver_t input_gx;
extern input_driver_t input_wiiu;
extern input_driver_t input_xinput;
extern input_driver_t input_uwp;
extern input_driver_t input_linuxraw;
extern input_driver_t input_udev;
extern input_driver_t input_cocoa;
extern input_driver_t input_qnx;
extern input_driver_t input_rwebinput;
extern input_driver_t input_dos;
extern input_driver_t input_winraw;
extern input_driver_t input_wayland;
extern input_driver_t input_test;
extern input_device_driver_t dinput_joypad;
extern input_device_driver_t winmm_joypad;
extern input_device_driver_t linuxraw_joypad;
extern input_device_driver_t parport_joypad;
extern input_device_driver_t udev_joypad;
extern input_device_driver_t xinput_joypad;
extern input_device_driver_t sdl1_joypad; /** SDL1. @see sdl1_joypad.c */
extern input_device_driver_t sdl2_joypad; /** SDL2. @see sdl2_joypad.c */
extern input_device_driver_t sdl_dingux_joypad;
extern input_device_driver_t sdl3_joypad; /** SDL3. @see sdl3_joypad.c */
extern input_device_driver_t ps4_joypad;
extern input_device_driver_t ps3_joypad;
extern input_device_driver_t psp_joypad;
extern input_device_driver_t ps2_joypad;
extern input_device_driver_t ctr_joypad;
extern input_device_driver_t switch_joypad;
extern input_device_driver_t xdk_joypad;
extern input_device_driver_t gx_joypad;
extern input_device_driver_t wiiu_joypad;
extern input_device_driver_t hid_joypad;
extern input_device_driver_t android_joypad;
extern input_device_driver_t qnx_joypad;
extern input_device_driver_t mfi_joypad;
extern input_device_driver_t dos_joypad;
extern input_device_driver_t rwebpad_joypad;
extern input_device_driver_t winraw_joypad;
extern input_device_driver_t test_joypad;
#ifdef HAVE_HID
extern hid_driver_t iohidmanager_hid;
extern hid_driver_t btstack_hid;
extern hid_driver_t libusb_hid;
extern hid_driver_t hidraw_hid;
extern hid_driver_t winusb_hid;
extern hid_driver_t wiiusb_hid;
extern hid_driver_t gekko_hid;
extern hid_driver_t wiiu_hid;
#endif /* HAVE_HID */
extern struct retro_keybind *input_config_binds[MAX_USERS];
extern struct retro_keybind *input_autoconf_binds[MAX_USERS];
/* What a port's mapping is made from - the users' binds, the binds a
* pad's autoconfig profile gave it, which pad, mouse and kind of device
* a port has, the remaps - is counted each time it changes. Anything
* compiled from them keeps the count it was compiled at, and is made
* again when the count has moved; nothing has to look at the binds to
* know. A change that is not counted is a mapping that goes stale, so
* the ways to change them are few and each counts:
* - the calls below that hand out a bind to be written;
* - the input code's own setters, and the configuration's loads;
* - every frame the menu is open, which covers whatever the menu and
* its settings write through pointers they hold.
* The frontend harness watches for a change the count missed. */
extern retro_atomic_int_t input_binds_generation;
void input_binds_kept_invalidate(void);
/* Entries: a hotkey or a command reached by buttons of the RetroPad
* and a key held together, read from the configuration's input_combo_N
* (see input_driver.c). Up to sixteen. */
void input_entries_clear(void);
unsigned input_entries_count(void);
bool input_entry_add(unsigned number, const char *spec);
void input_entries_read(void *conf);
/* An entry by its number: taken out; and as the configuration writes
* it (its length, 0 for none). input_entry_add() with a number there
* is an entry of replaces that entry. */
bool input_entry_remove(unsigned number);
/* Entry @number's buttons set by holding them (see input_driver.c).
* False if there is no such entry. */
bool input_entry_capture_start(unsigned number);
bool input_entry_capture_running(void);
unsigned input_entry_capture_seconds_left(void);
/* The buttons held on a row with no entry, once let go: true once. */
bool input_entry_capture_take_fresh(unsigned *number, unsigned *pad);
/* What an entry can be, | between them; what one is called in the
* menu; an entry made of buttons and a target; an entry's target
* changed; and what an entry's target is. */
size_t input_entry_targets(char *s, size_t len);
size_t input_entry_target_desc(const char *target, char *s, size_t len);
bool input_entry_set_from_pad(unsigned number, unsigned pad, const char *target);
bool input_entry_set_target(unsigned number, const char *target);
size_t input_entry_target(unsigned number, char *s, size_t len);
/* How long an entry's buttons must be held first, in tenths of a
* second (0: at once); and set. */
unsigned input_entry_hold(unsigned number);
bool input_entry_set_hold(unsigned number, unsigned tenths);
unsigned input_entry_depth(unsigned number);
bool input_entry_set_depth(unsigned number, unsigned percent);
size_t input_entry_spec(unsigned number, char *s, size_t len);
/* The entries and macros written into a configuration to be saved. */
void input_entries_write(void *conf);
/* Macros: buttons of the RetroPad pressed for a user a step at a time,
* a step lasting a number of the core's frames; read from the
* configuration's input_macro_N and started by an entry, "macro_N" or
* "macro_N@user" (see input_driver.c). Up to sixteen, of thirty-two
* steps at most. */
void input_macros_clear(void);
unsigned input_macros_count(void);
bool input_macro_add(unsigned number, const char *spec);
/* A macro by its number: set, whether or not there was one; taken
* out; and as the configuration writes it (its length, 0 for none). */
bool input_macro_set(unsigned number, const char *spec);
bool input_macro_remove(unsigned number);
size_t input_macro_spec(unsigned number, char *s, size_t len);
bool input_macro_start(unsigned number, unsigned user);
bool input_macro_playing(unsigned user);
/* A poll made with no frame of the core to follow it: @poll is called,
* and what goes by the core's frames stands still for it. */
void input_driver_poll_between_frames(void (*poll)(void));
/* One of a user's controls is remapped to @remap. A remap is set
* through here and not written into the settings directly: it is
* counted as a change, which is what has the frontend look at the
* remaps again. */
void input_config_set_remap_id(unsigned user, unsigned id, unsigned remap);
static INLINE void input_config_binds_changed(void)
{
retro_atomic_fetch_add_int(&input_binds_generation, 1);
/* what is kept by port and made from the binds is no longer
* current: a port's keys, its resolved pads, its hotkey facts */
input_binds_kept_invalidate();
}
static INLINE unsigned input_config_binds_generation(void)
{
return (unsigned)retro_atomic_load_acquire_int(&input_binds_generation);
}
/* How everything outside input/ gets at a bind: a user's, and the one
* a pad's autoconfig profile gave it. The arrays are the input code's
* own, and how the binds are kept is its to change; a check holds that
* nothing else names them (tools/input_state_grab_check.c). To read
* one, these; to write one, the _edit calls, which count the change. */
static INLINE const struct retro_keybind *input_config_bind(
unsigned user, unsigned id)
{
return &input_config_binds[user][id];
}
static INLINE const struct retro_keybind *input_autoconf_bind(
unsigned pad, unsigned id)
{
return &input_autoconf_binds[pad][id];
}
/* What a user's bind starts as (never NULL), what a bind is called,
* and a bind set to a default. See input_config_bind_def(). */
const struct retro_keybind_def *input_config_bind_def(
unsigned user, unsigned id);
enum msg_hash_enums input_config_bind_label(unsigned id);
void input_config_bind_from_def(struct retro_keybind *bind,
const struct retro_keybind_def *def);
/* A bind to be written, now: counted as a change, and the row it is
* in becomes the user's or the port's own if it was a shared one (see
* input_config_binds in input_driver.c). Never NULL. Write through
* these and not through the arrays, which may be pointing at a row
* that is shared. */
struct retro_keybind *input_config_bind_edit(unsigned user, unsigned id);
struct retro_keybind *input_autoconf_bind_edit(unsigned pad, unsigned id);
/* Nothing is behind any bind of the controller on @port. */
void input_autoconf_binds_none(unsigned port);
/* Every user's binds, copied out to and back from @sets[MAX_USERS]. */
/* A copy of the configured binds: to compare the binds with, or to
* put back. The configuration takes one before it loads the defaults
* or an override over the binds, asks it for a user's bind, and has it
* put back. What a copy is made of is the input file's business; it
* was a table the size and shape of the binds', which the callers
* allocated and indexed for themselves. */
typedef struct input_config_binds_copy input_config_binds_copy_t;
/* A copy of the binds as they are. NULL if there is no memory for it. */
input_config_binds_copy_t *input_config_binds_copy_new(void);
/* The copy is made again, of the binds as they are now. */
void input_config_binds_copy_take(input_config_binds_copy_t *copy);
/* @user's bind @id as the copy has it. */
const struct retro_keybind *input_config_binds_copy_bind(
const input_config_binds_copy_t *copy, unsigned user, unsigned id);
/* The binds are made what the copy has: a change to every one. */
void input_config_binds_copy_restore(const input_config_binds_copy_t *copy);
void input_config_binds_copy_free(input_config_binds_copy_t *copy);
/* What a bind's button and its axis are called: a user's own bind,
* and what the profile of the controller on a port calls it. Never
* NULL; both names are NULL for a bind that is called nothing, which
* is most. Good until the same user's or port's names are next
* changed. */
const struct input_bind_label *input_config_bind_names(
unsigned user, unsigned id);
const struct input_bind_label *input_autoconf_bind_names(
unsigned port, unsigned id);
/* A bind is given names. Each name @got has - a string from malloc() -
* replaces the bind's and belongs to the input from here; a name it
* has not leaves the bind's as it was. @got is left empty. */
void input_config_bind_names_take(unsigned user, unsigned id,
struct input_bind_label *got);
void input_autoconf_bind_names_take(unsigned port, unsigned id,
struct input_bind_label *got);
/* One of a user's binds is called nothing again. */
void input_config_bind_names_drop(unsigned user, unsigned id);
/* Nothing of what the controller on @port has is called anything. */
void input_autoconf_bind_names_free(unsigned port);
RETRO_END_DECLS
#endif /* __INPUT_DRIVER__H */