Skip to content

Commit

Permalink
Merge pull request #12632 from jordan-woyak/input-backend-impls
Browse files Browse the repository at this point in the history
Implement missing InputBackend classes.
  • Loading branch information
Tilka committed Apr 13, 2024
2 parents 1bfeeb8 + a9a9fdd commit e62d8ec
Show file tree
Hide file tree
Showing 15 changed files with 176 additions and 86 deletions.
30 changes: 24 additions & 6 deletions Source/Core/InputCommon/ControllerInterface/Android/Android.cpp
Expand Up @@ -23,6 +23,7 @@

#include "InputCommon/ControllerInterface/ControllerInterface.h"

#include "InputCommon/ControllerInterface/InputBackend.h"
#include "jni/AndroidCommon/AndroidCommon.h"
#include "jni/AndroidCommon/IDCache.h"
#include "jni/Input/CoreDevice.h"
Expand Down Expand Up @@ -444,6 +445,23 @@ std::shared_ptr<ciface::Core::Device> FindDevice(jint device_id)

namespace ciface::Android
{
class InputBackend final : public ciface::InputBackend
{
public:
using ciface::InputBackend::InputBackend;
~InputBackend();
void PopulateDevices() override;

private:
void AddDevice(JNIEnv* env, int device_id);
void AddSensorDevice(JNIEnv* env);
};

std::unique_ptr<ciface::InputBackend> CreateInputBackend(ControllerInterface* controller_interface)
{
return std::make_unique<InputBackend>(controller_interface);
}

class AndroidInput : public Core::Device::Input
{
public:
Expand Down Expand Up @@ -885,7 +903,7 @@ void Init()
s_controller_interface_register_input_device_listener);
}

void Shutdown()
InputBackend::~InputBackend()
{
JNIEnv* env = IDCache::GetEnvForThread();

Expand All @@ -903,7 +921,7 @@ void Shutdown()
env->DeleteGlobalRef(s_keycodes_array);
}

static void AddDevice(JNIEnv* env, int device_id)
void InputBackend::AddDevice(JNIEnv* env, int device_id)
{
jobject input_device =
env->CallStaticObjectMethod(s_input_device_class, s_input_device_get_device, device_id);
Expand All @@ -921,7 +939,7 @@ static void AddDevice(JNIEnv* env, int device_id)
if (device->Inputs().empty() && device->Outputs().empty())
return;

g_controller_interface.AddDevice(device);
GetControllerInterface().AddDevice(device);

Core::DeviceQualifier qualifier;
qualifier.FromDevice(device.get());
Expand All @@ -936,7 +954,7 @@ static void AddDevice(JNIEnv* env, int device_id)
env->DeleteLocalRef(j_qualifier);
}

static void AddSensorDevice(JNIEnv* env)
void InputBackend::AddSensorDevice(JNIEnv* env)
{
// Device sensors (accelerometer, etc.) aren't associated with any Android InputDevice.
// Create an otherwise empty Dolphin input device so that they have somewhere to live.
Expand All @@ -946,7 +964,7 @@ static void AddSensorDevice(JNIEnv* env)
if (device->Inputs().empty() && device->Outputs().empty())
return;

g_controller_interface.AddDevice(device);
GetControllerInterface().AddDevice(device);

Core::DeviceQualifier qualifier;
qualifier.FromDevice(device.get());
Expand All @@ -959,7 +977,7 @@ static void AddSensorDevice(JNIEnv* env)
env->DeleteLocalRef(j_qualifier);
}

void PopulateDevices()
void InputBackend::PopulateDevices()
{
INFO_LOG_FMT(CONTROLLERINTERFACE, "Android populating devices");

Expand Down
7 changes: 3 additions & 4 deletions Source/Core/InputCommon/ControllerInterface/Android/Android.h
Expand Up @@ -3,11 +3,10 @@

#pragma once

#include "InputCommon/ControllerInterface/InputBackend.h"

namespace ciface::Android
{
void Init();
void Shutdown();

void PopulateDevices();
std::unique_ptr<ciface::InputBackend> CreateInputBackend(ControllerInterface* controller_interface);

} // namespace ciface::Android
56 changes: 13 additions & 43 deletions Source/Core/InputCommon/ControllerInterface/ControllerInterface.cpp
Expand Up @@ -59,25 +59,25 @@ void ControllerInterface::Initialize(const WindowSystemInfo& wsi)
m_populating_devices_counter = 1;

#ifdef CIFACE_USE_WIN32
ciface::Win32::Init(wsi.render_window);
m_input_backends.emplace_back(ciface::Win32::CreateInputBackend(this));
#endif
#ifdef CIFACE_USE_XLIB
// nothing needed
m_input_backends.emplace_back(ciface::XInput2::CreateInputBackend(this));
#endif
#ifdef CIFACE_USE_OSX
// nothing needed for Quartz
m_input_backends.emplace_back(ciface::Quartz::CreateInputBackend(this));
#endif
#ifdef CIFACE_USE_SDL
m_input_backends.emplace_back(ciface::SDL::CreateInputBackend(this));
#endif
#ifdef CIFACE_USE_ANDROID
ciface::Android::Init();
m_input_backends.emplace_back(ciface::Android::CreateInputBackend(this));
#endif
#ifdef CIFACE_USE_EVDEV
m_input_backends.emplace_back(ciface::evdev::CreateInputBackend(this));
#endif
#ifdef CIFACE_USE_PIPES
// nothing needed
m_input_backends.emplace_back(ciface::Pipes::CreateInputBackend(this));
#endif
#ifdef CIFACE_USE_DUALSHOCKUDPCLIENT
m_input_backends.emplace_back(ciface::DualShockUDPClient::CreateInputBackend(this));
Expand Down Expand Up @@ -128,22 +128,20 @@ void ControllerInterface::RefreshDevices(RefreshReason reason)
// or removing them as we are populating them (causing missing or duplicate devices).
std::lock_guard lk_population(m_devices_population_mutex);

#if defined(CIFACE_USE_WIN32) && !defined(CIFACE_USE_XLIB) && !defined(CIFACE_USE_OSX)
// If only the window changed, avoid removing and re-adding all devices.
// Instead only refresh devices that require the window handle.
if (reason == RefreshReason::WindowChangeOnly)
{
m_populating_devices_counter.fetch_add(1);

// No need to do anything else in this case.
// Only (Win32) DInput needs the window handle to be updated.
ciface::Win32::ChangeWindow(m_wsi.render_window);
for (auto& backend : m_input_backends)
backend->HandleWindowChange();

if (m_populating_devices_counter.fetch_sub(1) == 1)
InvokeDevicesChangedCallbacks();

return;
}
#endif

m_populating_devices_counter.fetch_add(1);

Expand All @@ -159,26 +157,6 @@ void ControllerInterface::RefreshDevices(RefreshReason reason)
// do it async, to not risk the emulated controllers default config loading not finding a default
// device.

#ifdef CIFACE_USE_WIN32
ciface::Win32::PopulateDevices(m_wsi.render_window);
#endif
#ifdef CIFACE_USE_XLIB
if (m_wsi.type == WindowSystemType::X11)
ciface::XInput2::PopulateDevices(m_wsi.render_window);
#endif
#ifdef CIFACE_USE_OSX
if (m_wsi.type == WindowSystemType::MacOS)
{
ciface::Quartz::PopulateDevices(m_wsi.render_window);
}
#endif
#ifdef CIFACE_USE_ANDROID
ciface::Android::PopulateDevices();
#endif
#ifdef CIFACE_USE_PIPES
ciface::Pipes::PopulateDevices();
#endif

for (auto& backend : m_input_backends)
backend->PopulateDevices();

Expand Down Expand Up @@ -217,19 +195,6 @@ void ControllerInterface::Shutdown()
// Update control references so shared_ptr<Device>s are freed up BEFORE we shutdown the backends.
ClearDevices();

#ifdef CIFACE_USE_WIN32
ciface::Win32::DeInit();
#endif
#ifdef CIFACE_USE_XLIB
// nothing needed
#endif
#ifdef CIFACE_USE_OSX
ciface::Quartz::DeInit();
#endif
#ifdef CIFACE_USE_ANDROID
ciface::Android::Shutdown();
#endif

// Empty the container of input backends to deconstruct and deinitialize them.
m_input_backends.clear();

Expand Down Expand Up @@ -423,6 +388,11 @@ ciface::InputChannel ControllerInterface::GetCurrentInputChannel()
return tls_input_channel;
}

WindowSystemInfo ControllerInterface::GetWindowSystemInfo() const
{
return m_wsi;
}

void ControllerInterface::SetAspectRatioAdjustment(float value)
{
m_aspect_ratio_adjustment = value;
Expand Down
Expand Up @@ -122,6 +122,8 @@ class ControllerInterface : public ciface::Core::DeviceContainer
static void SetCurrentInputChannel(ciface::InputChannel);
static ciface::InputChannel GetCurrentInputChannel();

WindowSystemInfo GetWindowSystemInfo() const;

private:
void ClearDevices();

Expand Down
4 changes: 4 additions & 0 deletions Source/Core/InputCommon/ControllerInterface/InputBackend.cpp
Expand Up @@ -16,6 +16,10 @@ void InputBackend::UpdateInput(std::vector<std::weak_ptr<ciface::Core::Device>>&
{
}

void InputBackend::HandleWindowChange()
{
}

ControllerInterface& InputBackend::GetControllerInterface()
{
return m_controller_interface;
Expand Down
2 changes: 2 additions & 0 deletions Source/Core/InputCommon/ControllerInterface/InputBackend.h
Expand Up @@ -28,6 +28,8 @@ class InputBackend
// just add them to the removal list if necessary.
virtual void UpdateInput(std::vector<std::weak_ptr<ciface::Core::Device>>& devices_to_remove);

virtual void HandleWindowChange();

ControllerInterface& GetControllerInterface();

private:
Expand Down
14 changes: 13 additions & 1 deletion Source/Core/InputCommon/ControllerInterface/Pipes/Pipes.cpp
Expand Up @@ -39,7 +39,19 @@ static double StringToDouble(const std::string& text)
return result;
}

void PopulateDevices()
class InputBackend final : public ciface::InputBackend
{
public:
using ciface::InputBackend::InputBackend;
void PopulateDevices() override;
};

std::unique_ptr<ciface::InputBackend> CreateInputBackend(ControllerInterface* controller_interface)
{
return std::make_unique<InputBackend>(controller_interface);
}

void InputBackend::PopulateDevices()
{
// Search the Pipes directory for files that we can open in read-only,
// non-blocking mode. The device name is the virtual name of the file.
Expand Down
2 changes: 1 addition & 1 deletion Source/Core/InputCommon/ControllerInterface/Pipes/Pipes.h
Expand Up @@ -21,7 +21,7 @@ namespace ciface::Pipes
// SET {L, R} [0, 1]
// SET {MAIN, C} [0, 1] [0, 1]

void PopulateDevices();
std::unique_ptr<ciface::InputBackend> CreateInputBackend(ControllerInterface* controller_interface);

class PipeDevice : public Core::Device
{
Expand Down
9 changes: 7 additions & 2 deletions Source/Core/InputCommon/ControllerInterface/Quartz/Quartz.h
Expand Up @@ -3,8 +3,13 @@

#pragma once

#include <string>

#include "InputCommon/ControllerInterface/InputBackend.h"

namespace ciface::Quartz
{
void PopulateDevices(void* window);
void DeInit();
std::string GetSourceName();

std::unique_ptr<ciface::InputBackend> CreateInputBackend(ControllerInterface* controller_interface);
} // namespace ciface::Quartz
35 changes: 30 additions & 5 deletions Source/Core/InputCommon/ControllerInterface/Quartz/Quartz.mm
Expand Up @@ -7,15 +7,40 @@

namespace ciface::Quartz
{
void PopulateDevices(void* window)
std::string GetSourceName()
{
if (!window)
return;
return "Quartz";
}

class InputBackend final : public ciface::InputBackend
{
public:
using ciface::InputBackend::InputBackend;
void PopulateDevices() override;
void HandleWindowChange() override;
};

std::unique_ptr<ciface::InputBackend> CreateInputBackend(ControllerInterface* controller_interface)
{
return std::make_unique<InputBackend>(controller_interface);
}

void InputBackend::HandleWindowChange()
{
const std::string source_name = GetSourceName();
GetControllerInterface().RemoveDevice(
[&](const auto* dev) { return dev->GetSource() == source_name; }, true);

g_controller_interface.AddDevice(std::make_shared<KeyboardAndMouse>(window));
PopulateDevices();
}

void DeInit()
void InputBackend::PopulateDevices()
{
const WindowSystemInfo wsi = GetControllerInterface().GetWindowSystemInfo();
if (wsi.type != WindowSystemType::MacOS)
return;

GetControllerInterface().AddDevice(std::make_shared<KeyboardAndMouse>(wsi.render_window));
}

} // namespace ciface::Quartz
Expand Up @@ -12,6 +12,7 @@
#include "Core/Host.h"

#include "InputCommon/ControllerInterface/ControllerInterface.h"
#include "InputCommon/ControllerInterface/Quartz/Quartz.h"

/// Helper class to get window position data from threads other than the main thread
@interface DolWindowPositionObserver : NSObject
Expand Down Expand Up @@ -279,7 +280,7 @@ - (void)dealloc

std::string KeyboardAndMouse::GetSource() const
{
return "Quartz";
return Quartz::GetSourceName();
}

ControlState KeyboardAndMouse::Cursor::GetState() const
Expand Down

0 comments on commit e62d8ec

Please sign in to comment.