Polling joyGetCaps is very very slow, so we should not do that every
time GetCapabilities is called. Instead, we should call joyGetCaps once
and cache the results.
We need to find a different way to implement hotplugging.
Since we do not use Raw Input for joystick devices, it does not make
sense to expose the IJoystickDriver2 interface through WinRawInput. This
keeps allows joystick and keyboard/mouse implementations to reside in
distinct, modular classes, instantiated separately through WinFactory.
The IGamePadDriver interface is now implemented using
MappedGamePadDriver on all platforms. This minimizes code duplication
and simplifies all input driver implementations, since we only need
backends for IJoystickDriver2.
These valuators are not available on all systems. We now check
explicitly for support, instead of returning invalid results.
Additionally, unknown valuator names are now printed to the
debug log.
It appears that Mono 3.4.0 fails to marshal SDL_JoystickGUID
correctly when used as a return value. Changing the fixed buffer
to a couple of long fields allows the struct to be marshalled
correctly.
On SDL, DPad inputs were not correctly translated from joystick
hat inputs.
Updated MappedGamePadDriver so that it will correctly recognize
combined joystick hat directions e.g. DPadLeft should be true when
DownLeft, Left, or UpLeft are returned from the joystick hat.
The stored delegate list would store delegates indefinitely, causing a
memory leak. It is now the responsibility of each class to maintain
references to any callback functions it defines.
Devices are now explicitly closed when they a DeviceRemoved event is
received. Additionally, exceptions are no longer allowed to escape into
unmanaged code, where they might crash the runtime.
Callbacks are now explicitly marked as unmanaged pointers with the
correct (platform-defined) calling convention. Exceptions raised inside
these callbacks are no longer allowed to escape into unmanaged code,
where they will crash the runtime.
Additionally, the window is now only closed on the UI thread, and only
if it is actually open.
CocoaNativeWindow now checks for and reports failures to allocate
resources in its constructor. Additionally, it no longer calls UI
methods in the finalizer thread, as those methods will crash on Cocoa.