mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-07 07:21:25 +12:00
Perform refactoring of pads to remove the ugly pad initialization.
This commit is contained in:
parent
b01e7e3362
commit
d1cde4d0a7
8 changed files with 127 additions and 53 deletions
|
@ -1,5 +1,6 @@
|
||||||
#include "basic_keyboard_handler.h"
|
#include "basic_keyboard_handler.h"
|
||||||
|
|
||||||
|
#include <QApplication>
|
||||||
#include <QKeyEvent>
|
#include <QKeyEvent>
|
||||||
|
|
||||||
void basic_keyboard_handler::Init(const u32 max_connect)
|
void basic_keyboard_handler::Init(const u32 max_connect)
|
||||||
|
@ -17,16 +18,33 @@ void basic_keyboard_handler::Init(const u32 max_connect)
|
||||||
m_info.status[0] = CELL_KB_STATUS_CONNECTED; // (TODO: Support for more keyboards)
|
m_info.status[0] = CELL_KB_STATUS_CONNECTED; // (TODO: Support for more keyboards)
|
||||||
}
|
}
|
||||||
|
|
||||||
basic_keyboard_handler::basic_keyboard_handler(QObject* target, QObject* parent) : QObject(parent), m_target(target)
|
basic_keyboard_handler::basic_keyboard_handler() : QObject()
|
||||||
{
|
{
|
||||||
// Adds event filter to the target to filter keyevents.
|
|
||||||
target->installEventFilter(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Sets the target window for the event handler, and also installs an event filter on the target. */
|
||||||
|
void basic_keyboard_handler::SetTargetWindow(QWindow* target)
|
||||||
|
{
|
||||||
|
if (target != nullptr)
|
||||||
|
{
|
||||||
|
m_target = target;
|
||||||
|
target->installEventFilter(this);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// If this is hit, it probably means that some refactoring occurs because currently a gsframe is created in Load.
|
||||||
|
// We still want events so filter from application instead since target is null.
|
||||||
|
QApplication::instance()->installEventFilter(this);
|
||||||
|
LOG_ERROR(GENERAL, "Trying to set keyboard handler to a null target window.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool basic_keyboard_handler::eventFilter(QObject* target, QEvent* ev)
|
bool basic_keyboard_handler::eventFilter(QObject* target, QEvent* ev)
|
||||||
{
|
{
|
||||||
// Commenting target since I don't know how to target game window yet.
|
// !m_target is for future proofing when gsrender isn't automatically initialized on load.
|
||||||
//if (target == m_target)
|
// !m_target->isVisible() is a hack since currently a guiless application will STILL inititialize a gsrender (providing a valid target)
|
||||||
|
if (!m_target || !m_target->isVisible() || target == m_target)
|
||||||
{
|
{
|
||||||
if (ev->type() == QEvent::KeyPress)
|
if (ev->type() == QEvent::KeyPress)
|
||||||
{
|
{
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "Emu/Io/KeyboardHandler.h"
|
#include "Emu/Io/KeyboardHandler.h"
|
||||||
|
|
||||||
#include <QObject>
|
|
||||||
#include <QKeyEvent>
|
#include <QKeyEvent>
|
||||||
|
#include <QWindow>
|
||||||
|
|
||||||
class basic_keyboard_handler final : public QObject, public KeyboardHandlerBase
|
class basic_keyboard_handler final : public QObject, public KeyboardHandlerBase
|
||||||
{
|
{
|
||||||
|
@ -12,12 +12,13 @@ class basic_keyboard_handler final : public QObject, public KeyboardHandlerBase
|
||||||
public:
|
public:
|
||||||
virtual void Init(const u32 max_connect) override;
|
virtual void Init(const u32 max_connect) override;
|
||||||
|
|
||||||
explicit basic_keyboard_handler(QObject* target = nullptr, QObject* parent = nullptr);
|
explicit basic_keyboard_handler();
|
||||||
|
|
||||||
|
void SetTargetWindow(QWindow* target);
|
||||||
bool eventFilter(QObject* obj, QEvent* ev);
|
bool eventFilter(QObject* obj, QEvent* ev);
|
||||||
void keyPressEvent(QKeyEvent* event);
|
void keyPressEvent(QKeyEvent* event);
|
||||||
void keyReleaseEvent(QKeyEvent* event);
|
void keyReleaseEvent(QKeyEvent* event);
|
||||||
void LoadSettings();
|
void LoadSettings();
|
||||||
private:
|
private:
|
||||||
QObject* m_target;
|
QWindow* m_target = nullptr;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
#include "basic_mouse_handler.h"
|
#include "basic_mouse_handler.h"
|
||||||
|
|
||||||
|
#include <QApplication>
|
||||||
|
|
||||||
void basic_mouse_handler::Init(const u32 max_connect)
|
void basic_mouse_handler::Init(const u32 max_connect)
|
||||||
{
|
{
|
||||||
m_mice.emplace_back(Mouse());
|
m_mice.emplace_back(Mouse());
|
||||||
|
@ -13,15 +15,31 @@ void basic_mouse_handler::Init(const u32 max_connect)
|
||||||
m_info.product_id[0] = 0x1234;
|
m_info.product_id[0] = 0x1234;
|
||||||
}
|
}
|
||||||
|
|
||||||
basic_mouse_handler::basic_mouse_handler(QObject* target, QObject* parent) : QObject(parent), m_target(target)
|
basic_mouse_handler::basic_mouse_handler() : QObject()
|
||||||
|
{}
|
||||||
|
|
||||||
|
/* Sets the target window for the event handler, and also installs an event filter on the target. */
|
||||||
|
void basic_mouse_handler::SetTargetWindow(QWindow* target)
|
||||||
{
|
{
|
||||||
target->installEventFilter(this);
|
if (target != nullptr)
|
||||||
|
{
|
||||||
|
m_target = target;
|
||||||
|
target->installEventFilter(this);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// If this is hit, it probably means that some refactoring occurs because currently a gsframe is created in Load.
|
||||||
|
// We still want events so filter from application instead since target is null.
|
||||||
|
QApplication::instance()->installEventFilter(this);
|
||||||
|
LOG_ERROR(GENERAL, "Trying to set mouse handler to a null target window.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool basic_mouse_handler::eventFilter(QObject* obj, QEvent* ev)
|
bool basic_mouse_handler::eventFilter(QObject* target, QEvent* ev)
|
||||||
{
|
{
|
||||||
// Commenting target since I don't know how to target game window yet.
|
// !m_target is for future proofing when gsrender isn't automatically initialized on load to ensure events still occur
|
||||||
//if (m_target == obj)
|
// !m_target->isVisible() is a hack since currently a guiless application will STILL inititialize a gsrender (providing a valid target)
|
||||||
|
if (!m_target || !m_target->isVisible() || target == m_target)
|
||||||
{
|
{
|
||||||
switch (ev->type())
|
switch (ev->type())
|
||||||
{
|
{
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "Emu/Io/MouseHandler.h"
|
#include "Emu/Io/MouseHandler.h"
|
||||||
|
|
||||||
|
#include <QWindow>
|
||||||
#include <QMouseEvent>
|
#include <QMouseEvent>
|
||||||
#include <QWheelEvent>
|
#include <QWheelEvent>
|
||||||
|
|
||||||
|
@ -12,8 +13,9 @@ class basic_mouse_handler final : public QObject, public MouseHandlerBase
|
||||||
public:
|
public:
|
||||||
virtual void Init(const u32 max_connect) override;
|
virtual void Init(const u32 max_connect) override;
|
||||||
|
|
||||||
basic_mouse_handler(QObject* target, QObject* parent);
|
basic_mouse_handler();
|
||||||
|
|
||||||
|
void SetTargetWindow(QWindow* target);
|
||||||
void MouseButtonDown(QMouseEvent* event);
|
void MouseButtonDown(QMouseEvent* event);
|
||||||
void MouseButtonUp(QMouseEvent* event);
|
void MouseButtonUp(QMouseEvent* event);
|
||||||
void MouseScroll(QWheelEvent* event);
|
void MouseScroll(QWheelEvent* event);
|
||||||
|
@ -21,5 +23,5 @@ public:
|
||||||
|
|
||||||
bool eventFilter(QObject* obj, QEvent* ev);
|
bool eventFilter(QObject* obj, QEvent* ev);
|
||||||
private:
|
private:
|
||||||
QObject* m_target;
|
QWindow* m_target = nullptr;
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
#include "keyboard_pad_handler.h"
|
#include "keyboard_pad_handler.h"
|
||||||
|
|
||||||
|
#include <QApplication>
|
||||||
|
|
||||||
keyboard_pad_config g_kbpad_config;
|
keyboard_pad_config g_kbpad_config;
|
||||||
|
|
||||||
void keyboard_pad_handler::Init(const u32 max_connect)
|
void keyboard_pad_handler::Init(const u32 max_connect)
|
||||||
|
@ -12,15 +14,15 @@ void keyboard_pad_handler::Init(const u32 max_connect)
|
||||||
m_info.now_connect = std::min(m_pads.size(), (size_t)max_connect);
|
m_info.now_connect = std::min(m_pads.size(), (size_t)max_connect);
|
||||||
}
|
}
|
||||||
|
|
||||||
keyboard_pad_handler::keyboard_pad_handler(QObject* target, QObject* parent) : QObject(parent), m_target(target)
|
keyboard_pad_handler::keyboard_pad_handler() : QObject()
|
||||||
{
|
{
|
||||||
target->installEventFilter(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool keyboard_pad_handler::eventFilter(QObject* target, QEvent* ev)
|
bool keyboard_pad_handler::eventFilter(QObject* target, QEvent* ev)
|
||||||
{
|
{
|
||||||
// Commenting target since I don't know how to target game window yet.
|
// !m_target is for future proofing when gsrender isn't automatically initialized on load.
|
||||||
//if (target == m_target)
|
// !m_target->isVisible() is a hack since currently a guiless application will STILL inititialize a gsrender (providing a valid target)
|
||||||
|
if (!m_target || !m_target->isVisible()|| target == m_target)
|
||||||
{
|
{
|
||||||
if (ev->type() == QEvent::KeyPress)
|
if (ev->type() == QEvent::KeyPress)
|
||||||
{
|
{
|
||||||
|
@ -34,6 +36,23 @@ bool keyboard_pad_handler::eventFilter(QObject* target, QEvent* ev)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Sets the target window for the event handler, and also installs an event filter on the target. */
|
||||||
|
void keyboard_pad_handler::SetTargetWindow(QWindow* target)
|
||||||
|
{
|
||||||
|
if (target != nullptr)
|
||||||
|
{
|
||||||
|
m_target = target;
|
||||||
|
target->installEventFilter(this);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
QApplication::instance()->installEventFilter(this);
|
||||||
|
// If this is hit, it probably means that some refactoring occurs because currently a gsframe is created in Load.
|
||||||
|
// We still want events so filter from application instead since target is null.
|
||||||
|
LOG_ERROR(GENERAL, "Trying to set pad handler to a null target window.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void keyboard_pad_handler::keyPressEvent(QKeyEvent* event)
|
void keyboard_pad_handler::keyPressEvent(QKeyEvent* event)
|
||||||
{
|
{
|
||||||
if (event->isAutoRepeat())
|
if (event->isAutoRepeat())
|
||||||
|
|
|
@ -5,8 +5,8 @@
|
||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "Emu/System.h"
|
#include "Emu/System.h"
|
||||||
|
|
||||||
|
#include <QWindow>
|
||||||
#include <QKeyEvent>
|
#include <QKeyEvent>
|
||||||
#include <QObject>
|
|
||||||
|
|
||||||
struct keyboard_pad_config final : cfg::node
|
struct keyboard_pad_config final : cfg::node
|
||||||
{
|
{
|
||||||
|
@ -58,13 +58,14 @@ class keyboard_pad_handler final : public QObject, public PadHandlerBase
|
||||||
public:
|
public:
|
||||||
virtual void Init(const u32 max_connect) override;
|
virtual void Init(const u32 max_connect) override;
|
||||||
|
|
||||||
keyboard_pad_handler(QObject* target, QObject* parent);
|
keyboard_pad_handler();
|
||||||
|
|
||||||
|
void SetTargetWindow(QWindow* target);
|
||||||
void keyPressEvent(QKeyEvent* event);
|
void keyPressEvent(QKeyEvent* event);
|
||||||
void keyReleaseEvent(QKeyEvent* event);
|
void keyReleaseEvent(QKeyEvent* event);
|
||||||
void LoadSettings();
|
void LoadSettings();
|
||||||
|
|
||||||
bool eventFilter(QObject* obj, QEvent* ev);
|
bool eventFilter(QObject* obj, QEvent* ev);
|
||||||
private:
|
private:
|
||||||
QObject* m_target;
|
QWindow* m_target = nullptr;
|
||||||
};
|
};
|
||||||
|
|
|
@ -63,9 +63,6 @@ void rpcs3_app::Init()
|
||||||
// Create the main window
|
// Create the main window
|
||||||
RPCS3MainWin = new main_window(guiSettings, nullptr);
|
RPCS3MainWin = new main_window(guiSettings, nullptr);
|
||||||
|
|
||||||
// Reset the pads -- see the method for why this is currently needed.
|
|
||||||
ResetPads();
|
|
||||||
|
|
||||||
// Create callbacks from the emulator, which reference the handlers.
|
// Create callbacks from the emulator, which reference the handlers.
|
||||||
InitializeCallbacks();
|
InitializeCallbacks();
|
||||||
|
|
||||||
|
@ -113,7 +110,13 @@ void rpcs3_app::InitializeCallbacks()
|
||||||
switch (keyboard_handler type = g_cfg.io.keyboard)
|
switch (keyboard_handler type = g_cfg.io.keyboard)
|
||||||
{
|
{
|
||||||
case keyboard_handler::null: return std::make_shared<NullKeyboardHandler>();
|
case keyboard_handler::null: return std::make_shared<NullKeyboardHandler>();
|
||||||
case keyboard_handler::basic: return m_basicKeyboardHandler;
|
case keyboard_handler::basic:
|
||||||
|
{
|
||||||
|
basic_keyboard_handler* ret = new basic_keyboard_handler();
|
||||||
|
ret->moveToThread(thread());
|
||||||
|
ret->SetTargetWindow(gameWindow);
|
||||||
|
return std::shared_ptr<KeyboardHandlerBase>(ret);
|
||||||
|
}
|
||||||
default: fmt::throw_exception("Invalid keyboard handler: %s", type);
|
default: fmt::throw_exception("Invalid keyboard handler: %s", type);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -123,7 +126,13 @@ void rpcs3_app::InitializeCallbacks()
|
||||||
switch (mouse_handler type = g_cfg.io.mouse)
|
switch (mouse_handler type = g_cfg.io.mouse)
|
||||||
{
|
{
|
||||||
case mouse_handler::null: return std::make_shared<NullMouseHandler>();
|
case mouse_handler::null: return std::make_shared<NullMouseHandler>();
|
||||||
case mouse_handler::basic: return m_basicMouseHandler;
|
case mouse_handler::basic:
|
||||||
|
{
|
||||||
|
basic_mouse_handler* ret = new basic_mouse_handler();
|
||||||
|
ret->moveToThread(thread());
|
||||||
|
ret->SetTargetWindow(gameWindow);
|
||||||
|
return std::shared_ptr<MouseHandlerBase>(ret);
|
||||||
|
}
|
||||||
default: fmt::throw_exception("Invalid mouse handler: %s", type);
|
default: fmt::throw_exception("Invalid mouse handler: %s", type);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -133,7 +142,13 @@ void rpcs3_app::InitializeCallbacks()
|
||||||
switch (pad_handler type = g_cfg.io.pad)
|
switch (pad_handler type = g_cfg.io.pad)
|
||||||
{
|
{
|
||||||
case pad_handler::null: return std::make_shared<NullPadHandler>();
|
case pad_handler::null: return std::make_shared<NullPadHandler>();
|
||||||
case pad_handler::keyboard: return m_keyboardPadHandler;
|
case pad_handler::keyboard:
|
||||||
|
{
|
||||||
|
keyboard_pad_handler* ret = new keyboard_pad_handler();
|
||||||
|
ret->moveToThread(thread());
|
||||||
|
ret->SetTargetWindow(gameWindow);
|
||||||
|
return std::shared_ptr<PadHandlerBase>(ret);
|
||||||
|
}
|
||||||
case pad_handler::ds4: return std::make_shared<ds4_pad_handler>();
|
case pad_handler::ds4: return std::make_shared<ds4_pad_handler>();
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
case pad_handler::xinput: return std::make_shared<xinput_pad_handler>();
|
case pad_handler::xinput: return std::make_shared<xinput_pad_handler>();
|
||||||
|
@ -166,11 +181,31 @@ void rpcs3_app::InitializeCallbacks()
|
||||||
|
|
||||||
switch (video_renderer type = g_cfg.video.renderer)
|
switch (video_renderer type = g_cfg.video.renderer)
|
||||||
{
|
{
|
||||||
case video_renderer::null: return std::make_unique<gs_frame>("Null", w, h, RPCS3MainWin->GetAppIcon(), disableMouse);
|
case video_renderer::null:
|
||||||
case video_renderer::opengl: return std::make_unique<gl_gs_frame>(w, h, RPCS3MainWin->GetAppIcon(), disableMouse);
|
{
|
||||||
case video_renderer::vulkan: return std::make_unique<gs_frame>("Vulkan", w, h, RPCS3MainWin->GetAppIcon(), disableMouse);
|
gs_frame* ret = new gs_frame("Null", size.first, size.second, RPCS3MainWin->GetAppIcon(), disableMouse);
|
||||||
|
gameWindow = ret;
|
||||||
|
return std::unique_ptr<gs_frame>(ret);
|
||||||
|
}
|
||||||
|
case video_renderer::opengl:
|
||||||
|
{
|
||||||
|
gl_gs_frame* ret = new gl_gs_frame(size.first, size.second, RPCS3MainWin->GetAppIcon(), disableMouse);
|
||||||
|
gameWindow = ret;
|
||||||
|
return std::unique_ptr<gl_gs_frame>(ret);
|
||||||
|
}
|
||||||
|
case video_renderer::vulkan:
|
||||||
|
{
|
||||||
|
gs_frame* ret = new gs_frame("Vulkan", size.first, size.second, RPCS3MainWin->GetAppIcon(), disableMouse);
|
||||||
|
gameWindow = ret;
|
||||||
|
return std::unique_ptr<gs_frame>(ret);
|
||||||
|
}
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
case video_renderer::dx12: return std::make_unique<gs_frame>("DirectX 12", w, h, RPCS3MainWin->GetAppIcon(), disableMouse);
|
case video_renderer::dx12:
|
||||||
|
{
|
||||||
|
gs_frame* ret = new gs_frame("DirectX 12", size.first, size.second, RPCS3MainWin->GetAppIcon(), disableMouse);
|
||||||
|
gameWindow = ret;
|
||||||
|
return std::unique_ptr<gs_frame>(ret);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
default: fmt::throw_exception("Invalid video renderer: %s" HERE, type);
|
default: fmt::throw_exception("Invalid video renderer: %s" HERE, type);
|
||||||
}
|
}
|
||||||
|
@ -237,7 +272,6 @@ void rpcs3_app::InitializeConnects()
|
||||||
connect(this, &rpcs3_app::RequestCallAfter, this, &rpcs3_app::HandleCallAfter);
|
connect(this, &rpcs3_app::RequestCallAfter, this, &rpcs3_app::HandleCallAfter);
|
||||||
|
|
||||||
connect(this, &rpcs3_app::OnEmulatorRun, RPCS3MainWin, &main_window::OnEmuRun);
|
connect(this, &rpcs3_app::OnEmulatorRun, RPCS3MainWin, &main_window::OnEmuRun);
|
||||||
connect(this, &rpcs3_app::OnEmulatorStop, this, &rpcs3_app::ResetPads);
|
|
||||||
connect(this, &rpcs3_app::OnEmulatorStop, RPCS3MainWin, &main_window::OnEmuStop);
|
connect(this, &rpcs3_app::OnEmulatorStop, RPCS3MainWin, &main_window::OnEmuStop);
|
||||||
connect(this, &rpcs3_app::OnEmulatorPause, RPCS3MainWin, &main_window::OnEmuPause);
|
connect(this, &rpcs3_app::OnEmulatorPause, RPCS3MainWin, &main_window::OnEmuPause);
|
||||||
connect(this, &rpcs3_app::OnEmulatorResume, RPCS3MainWin, &main_window::OnEmuResume);
|
connect(this, &rpcs3_app::OnEmulatorResume, RPCS3MainWin, &main_window::OnEmuResume);
|
||||||
|
@ -269,17 +303,3 @@ void rpcs3_app::HandleCallAfter(const std::function<void()>& func)
|
||||||
{
|
{
|
||||||
func();
|
func();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* We need to make this in the main thread to receive events from the main thread.
|
|
||||||
* This leads to the tricky situation. Creating it while booting leads to deadlock with a blocking connection.
|
|
||||||
* So, I need to make them before, but when?
|
|
||||||
* I opted to reset them when the Emu stops and on first init. Potentially a race condition on restart? Never encountered issues.
|
|
||||||
* The other tricky issue is that I don't want Init to be called twice on the same object. Reseting the pointer on emu stop should handle this as well!
|
|
||||||
*/
|
|
||||||
void rpcs3_app::ResetPads()
|
|
||||||
{
|
|
||||||
m_basicKeyboardHandler.reset(new basic_keyboard_handler(this, this));
|
|
||||||
m_basicMouseHandler.reset(new basic_mouse_handler(this, this));
|
|
||||||
m_keyboardPadHandler.reset(new keyboard_pad_handler(this, this));
|
|
||||||
}
|
|
||||||
|
|
|
@ -41,17 +41,12 @@ Q_SIGNALS:
|
||||||
private Q_SLOTS:
|
private Q_SLOTS:
|
||||||
void OnChangeStyleSheetRequest(const QString& path);
|
void OnChangeStyleSheetRequest(const QString& path);
|
||||||
void HandleCallAfter(const std::function<void()>& func);
|
void HandleCallAfter(const std::function<void()>& func);
|
||||||
void ResetPads();
|
|
||||||
private:
|
private:
|
||||||
void InitializeCallbacks();
|
void InitializeCallbacks();
|
||||||
void InitializeConnects();
|
void InitializeConnects();
|
||||||
|
|
||||||
// See ResetPads() for why these shared pointers exist.
|
|
||||||
std::shared_ptr<keyboard_pad_handler> m_keyboardPadHandler;
|
|
||||||
std::shared_ptr<basic_keyboard_handler> m_basicKeyboardHandler;
|
|
||||||
std::shared_ptr<basic_mouse_handler> m_basicMouseHandler;
|
|
||||||
|
|
||||||
main_window* RPCS3MainWin;
|
main_window* RPCS3MainWin;
|
||||||
|
|
||||||
std::shared_ptr<gui_settings> guiSettings;
|
std::shared_ptr<gui_settings> guiSettings;
|
||||||
|
QWindow* gameWindow = nullptr; //! (Currently) only needed so that pad handlers have a valid target for event filtering.
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue