This reads Steam Deck controls bypassing Steam Input. This allows for access to
motion controls as well as independent access to thumb sticks, trackpads, and
back grip buttons.
XInput2 was created to support multiple pointer/keyboard pairs (often
called MPX for multi-pointer X). Dolphin's XInput2 implementation has
always supported MPX by creating a KeyboardMouse object per master
pointer. Since commit bbb12a7, Dolphin's keyboard state is filtered by
the output of XQueryKeymap. As a core X function, XQueryKeymap queries
"the" keyboard, which by default is the first master keyboard. As a
result, Dolphin will ignore keys pressed on other master keyboards
unless the first master is simultaneously pressing the same keys.
XInput2 doesn't provide a function to query the keyboard state. There
is no XIQueryKeymap and the current state is not a member of the
XIKeyClassInfo returned by XIQueryDevice. Instead, XInput2 allows a
master pointer to be nominated as "the" pointer on a per-client basis,
with "the" keyboard automatically becoming the associated master
keyboard. The "documentation" [1] says passing None for the window is
only for debugging purposes, but it is documented in the
XISetClientPointer man page and seems to be the only way to query
keyboards beyond the first.
With this commit, Dolphin correctly reads keys from keyboards other than
the first master keyboard. To test, use the xinput command-line utility
to create a master pointer and reattach a keyboard to the associated
master keyboard.
[1]: https://who-t.blogspot.com/2009/07/xi2-recipes-part-6.html
(the XInput2 developer's blog)
In UpdateInput, lock m_devices_population_mutex before m_devices_mutex
to be consistent with other ControllerInterface functions. Normally the
former lock isn't needed in UpdateInput, but when a Wii Remote
disconnects it calls RemoveDevice which results in the mutexes being
locked in the wrong order.
Up until now, there have been two settings on Android that stored the
selected Wii Remote extension: the normal one that's also used on PC,
and a SharedPreferences one that's used by the overlay controls to
determine what controls to show. It is possible for these two to end up
out of sync, and my input changes have made that more likely to happen.
To fix this, let's rework how the overlay controller setting works.
We don't want it to encode the currently selected Wii Remote extension.
However, we can't simply get rid of the setting, because for some Wii
games we need the ability to switch between a GameCube controller and a
Wii Remote. What this commit does is give the user the option to select
any of the 4 GameCube controllers and any of the 4 Wii Remotes. (Before,
controllers 2-4 weren't available in the overlay.) Could be useful for
things like the Psycho Mantis fight in Metal Gear Solid. I'm also
switching from SharedPreferences to Dolphin.ini while I'm at it.
It's missing a lot of features from the PC version for now, like
buttons for inserting functions and the ability to see what the
expression evaluates to. I mostly just wanted to get something in
place so you can set up rumble.
Co-authored-by: Charles Lombardo <clombardo169@gmail.com>
This is a battery-saving measure. Whether a sensor should be suspended
is determined in the same way as whether key events and motion events
should be handled by the OS rather than consumed by Dolphin.
When Android presents an input event to an app, it wants the app to
return true or false depending on whether the app handled the event or
not. If the event wasn't handled by the app, it will be passed on to
the system, which may decide to take an action depending on what kind
of input event it is. For instance, if a B button press is passed on to
the system, it will be turned into a Back press. But if an R1 press is
passed on to the system, nothing in particular happens.
It's important that we get this return value right in Dolphin. For
instance, the user generally wouldn't want a B button press to open
the EmulationActivity menu, so B button presses usually shouldn't be
passed on to the system - but volume button presses usually should be
passed on to the system, since it would be hard to adjust the volume
otherwise. What ButtonManager did was to pass on input events that are
for a button which the user has not mapped, which I think makes sense.
But exactly how to implement that is more complicated in the new input
backend than in ButtonManager, because now we have a separation between
the input backend and the code that keeps track of the user's mappings.
What I'm going with in this commit is to treat an input as mapped if
it has been polled recently. In part I chose this because it seemed
like a simple way of implementing it that wouldn't cause too many
layering violations, but it also has two useful side effects:
1. If a controller is not being polled (e.g. GameCube controllers in
Wii games that don't use them), its mappings will not be considered.
2. Once sensor input is implemented in the Android input backend,
we will be able to use this "polled recently" tracking to power down
the sensors at times when the game is using a Wii Remote reporting
mode that doesn't include motion data. (Assuming that the sensor
inputs only are mapped to Wii Remote motion controls, that is.)
Android doesn't let us poll inputs whenever we want. Instead, we
listen to input events (activities will have to forward them to the
input backend), and store the received values in atomic variables
in the Input classes. This is similar in concept to how ButtonManager
worked, but without its homegrown second input mapping system.
ButtonManager is very different from how a normal input backend works,
and is making it hard for us to improve controller support on Android.
The following commits will add a new input backend in its place.
I also changed LoadConfig, but that change doesn't affect correctness,
it's only so it looks neat by matching SaveConfig.
This bug was added in 18a4afb053, the
commit that introduced DefaultValue::Disabled. The bug can't actually be
triggered in master, but it can be triggered in the Android input
overhaul PR.
This is the first step of getting rid of the controller indirection
on Android. (Needing a way for touch controls to provide input
to the emulator core is the reason why the controller indirection
exists to begin with as far as I understand it.)
This lets the TAS input code use a higher-level interface for
overriding inputs instead of having to fiddle with raw bits.
WiiTASInputWindow in particular was messy with how much
controller code it had to re-implement.
This hack was added in 8f0cbefbe5, and the part of it in SI_DeviceGCAdapter is present on Android already, so I don't see any reason why this part doesn't apply to Android.
This is mostly a brainless merge, #ifdef-ing anything that doesn't match between the two while preserving common logic. I didn't rename any variables (although similar ones do exist), but I did change one log that was ERROR on android and NOTICE elsewhere to just always be NOTICE. Further merging will follow.
Loading configs while another thread is messing with stuff just doesn't feel like a good idea
Hopefully fixes Wiimote Scanning Thread crashes on startup
I am not confident there are no race conditions between s_write_mutex,
s_controller_write_payload_size, and s_controller_write_payload. But
this code should be safer than before.
s_controller_write_payload_size needs to remain an atomic because Read()
loads and stores without holding a mutex, Output() stores while holding
s_write_mutex, and ResetRumble() stores while holding s_read_mutex! I'm
pretty sure this code is wrong, specifically ResetRumble().
You can safely read or write non-atomic integers on multiple threads,
as long as every thread reading or writing it holds the same mutex
while doing so (here, s_mutex).
Removing the atomic accesses makes the code faster, but the actual
performance difference is probably negligible.
If libusb fails to initialize, an assertion fails, but if that happens before the main window is created, then Dolphin just dies. Now, the panic alert is properly shown and the user can ignore it.
If InputConfig::LoadConfig() was called once with a non empty/customized config,
then called again after manually deleting the config (dolphin calls LoadConfig() every time it opens the mapping widget),
the second load would fail to clear the values on any non first EmulatedController and would instead keep the
previous config values despite it being deleted (while it would instead correctly default the first EmulatedController).
This is not a big bug though the code is better now.
Fixes bug: https://bugs.dolphin-emu.org/issues/12744
Before e1e3db13ba
the ControllerInterface m_devices_mutex was "wrongfully" locked for the whole Initialize() call, which included the first device population refresh,
this has the unwanted (accidental) consequence of often preventing the different pads (GC Pad, Wii Contollers, ...) input configs from loading
until that mutex was released (the input config defaults loading was blocked in EmulatedController::LoadDefaults()), which meant that the devices
population would often have the time to finish adding its first device, which would then be selected as default device (by design, the first device
added to the CI is the default default device, usually the "Keyboard and Mouse" device).
After the commit mentioned above removed the unnecessary m_devices_mutex calls, the default default device would fail to load (be found)
causing the default input mappings, which are specifically written for the default default device on every platform, to not be bound to any
physical device input, breaking input on new dolphin installations (until a user tried to customize the default device manually).
Default devices are now always added synchronously to avoid the problem, and so they should in the future (I added comments and warnings to help with that)
Removed useless locks to DeviceContainer::m_devices_mutex, as they were all already protected by m_devices_population_mutex.
We have no interest in blocking other threads that were potentially reading devices at the same time so this seems fine.
This simplifies the code, and I've adjusted a few comments which mentioned possible deadlock that should now be totally gone.
The deadlock could have happen if a thread directly called EmulatedController::UpdateReferences(), while another another thread also reached EmulatedController::UpdateReferences() within a call to ControllerInterface::UpdateDevices(), as the mentioned function locked both the DeviceContainer::m_devices_mutex and s_get_state_mutex at the same time.
The deadlock was frequent on game emulation startup on Android, due to the UpdateReferences() call in InputConfig::LoadConfig() and the UI thread triggering calls to ControllerInterface::UpdateDevices().
It could also have happened on Desktop if a user pressed "Refresh Devices" manually in the UI while the input config was loading.
Also brought some UpdateReferences() comments and thread safety fixes from https://github.com/dolphin-emu/dolphin/pull/9489
SPDX standardizes how source code conveys its copyright and licensing
information. See https://spdx.github.io/spdx-spec/1-rationale/ . SPDX
tags are adopted in many large projects, including things like the Linux
kernel.