diff --git a/rpcs3/Emu/Io/KeyboardHandler.cpp b/rpcs3/Emu/Io/KeyboardHandler.cpp index 8b2a13498..73ef8d069 100644 --- a/rpcs3/Emu/Io/KeyboardHandler.cpp +++ b/rpcs3/Emu/Io/KeyboardHandler.cpp @@ -312,6 +312,8 @@ void KeyboardHandlerBase::ReleaseAllKeys() { consumer.ReleaseAllKeys(); } + + m_keys_released = true; } void keyboard_consumer::ReleaseAllKeys() diff --git a/rpcs3/Emu/Io/KeyboardHandler.h b/rpcs3/Emu/Io/KeyboardHandler.h index 51404b72c..594f7be3f 100644 --- a/rpcs3/Emu/Io/KeyboardHandler.h +++ b/rpcs3/Emu/Io/KeyboardHandler.h @@ -169,5 +169,6 @@ public: protected: void ReleaseAllKeys(); + bool m_keys_released = false; std::unordered_map m_consumers; }; diff --git a/rpcs3/Emu/Io/interception.cpp b/rpcs3/Emu/Io/interception.cpp index eb0141fdf..dab9dbe3e 100644 --- a/rpcs3/Emu/Io/interception.cpp +++ b/rpcs3/Emu/Io/interception.cpp @@ -4,18 +4,36 @@ #include "MouseHandler.h" #include "Input/pad_thread.h" #include "Emu/IdManager.h" +#include "Emu/RSX/Overlays/overlay_message.h" +#include "Emu/system_config.h" LOG_CHANNEL(input_log, "Input"); +template <> +void fmt_class_string::format(std::string& out, u64 arg) +{ + format_enum(out, arg, [](input::active_mouse_and_keyboard value) + { + switch (value) + { + case input::active_mouse_and_keyboard::emulated: return "emulated"; + case input::active_mouse_and_keyboard::pad: return "pad"; + } + + return unknown; + }); +} + namespace input { + atomic_t g_active_mouse_and_keyboard{active_mouse_and_keyboard::emulated}; atomic_t g_pads_intercepted{false}; atomic_t g_keyboards_intercepted{false}; atomic_t g_mice_intercepted{false}; void SetIntercepted(bool pads_intercepted, bool keyboards_intercepted, bool mice_intercepted, const char* func) { - input_log.warning("SetIntercepted: pads=%d, keyboards=%d, mice=%d, src=%s)", pads_intercepted, keyboards_intercepted, mice_intercepted, func); + input_log.notice("SetIntercepted: pads=%d, keyboards=%d, mice=%d, src=%s)", pads_intercepted, keyboards_intercepted, mice_intercepted, func); g_pads_intercepted = pads_intercepted; g_keyboards_intercepted = keyboards_intercepted; @@ -38,4 +56,34 @@ namespace input { SetIntercepted(all_intercepted, all_intercepted, all_intercepted, func); } + + static void show_mouse_and_keyboard_overlay() + { + if (!g_cfg.misc.show_mouse_and_keyboard_toggle_hint) + return; + + const localized_string_id id = g_active_mouse_and_keyboard == active_mouse_and_keyboard::emulated + ? localized_string_id::RSX_OVERLAYS_MOUSE_AND_KEYBOARD_EMULATED + : localized_string_id::RSX_OVERLAYS_MOUSE_AND_KEYBOARD_PAD; + rsx::overlays::queue_message(get_localized_string(id), 3'000'000); + } + + void set_mouse_and_keyboard(active_mouse_and_keyboard device) + { + // Always log + input_log.notice("set_mouse_and_keyboard: device=%s", device); + + if (g_active_mouse_and_keyboard != device) + { + g_active_mouse_and_keyboard = device; + show_mouse_and_keyboard_overlay(); + } + } + + void toggle_mouse_and_keyboard() + { + g_active_mouse_and_keyboard = g_active_mouse_and_keyboard == active_mouse_and_keyboard::emulated ? active_mouse_and_keyboard::pad : active_mouse_and_keyboard::emulated; + input_log.notice("toggle_mouse_and_keyboard: device=%s", g_active_mouse_and_keyboard.load()); + show_mouse_and_keyboard_overlay(); + } } diff --git a/rpcs3/Emu/Io/interception.h b/rpcs3/Emu/Io/interception.h index e5653b96e..16a407b8e 100644 --- a/rpcs3/Emu/Io/interception.h +++ b/rpcs3/Emu/Io/interception.h @@ -4,10 +4,20 @@ namespace input { + enum class active_mouse_and_keyboard : u32 + { + pad, + emulated + }; + extern atomic_t g_active_mouse_and_keyboard; + extern atomic_t g_pads_intercepted; extern atomic_t g_keyboards_intercepted; extern atomic_t g_mice_intercepted; void SetIntercepted(bool pads_intercepted, bool keyboards_intercepted, bool mice_intercepted, const char* func = __builtin_FUNCTION()); void SetIntercepted(bool all_intercepted, const char* func = __builtin_FUNCTION()); + + void set_mouse_and_keyboard(active_mouse_and_keyboard device); + void toggle_mouse_and_keyboard(); } diff --git a/rpcs3/Emu/localized_string_id.h b/rpcs3/Emu/localized_string_id.h index 2012730f1..389de5606 100644 --- a/rpcs3/Emu/localized_string_id.h +++ b/rpcs3/Emu/localized_string_id.h @@ -35,6 +35,8 @@ enum class localized_string_id RSX_OVERLAYS_PRESSURE_INTENSITY_TOGGLED_ON, RSX_OVERLAYS_ANALOG_LIMITER_TOGGLED_OFF, RSX_OVERLAYS_ANALOG_LIMITER_TOGGLED_ON, + RSX_OVERLAYS_MOUSE_AND_KEYBOARD_EMULATED, + RSX_OVERLAYS_MOUSE_AND_KEYBOARD_PAD, CELL_GAME_ERROR_BROKEN_GAMEDATA, CELL_GAME_ERROR_BROKEN_HDDGAME, diff --git a/rpcs3/Emu/system_config.h b/rpcs3/Emu/system_config.h index a3926102a..03a0a317e 100644 --- a/rpcs3/Emu/system_config.h +++ b/rpcs3/Emu/system_config.h @@ -342,6 +342,7 @@ struct cfg_root : cfg::node cfg::_bool show_ppu_compilation_hint{ this, "Show PPU compilation hint", true, true }; cfg::_bool show_pressure_intensity_toggle_hint{ this, "Show pressure intensity toggle hint", true, true }; cfg::_bool show_analog_limiter_toggle_hint{ this, "Show analog limiter toggle hint", true, true }; + cfg::_bool show_mouse_and_keyboard_toggle_hint{ this, "Show mouse and keyboard toggle hint", true, true }; cfg::_bool use_native_interface{ this, "Use native user interface", true }; cfg::string gdb_server{ this, "GDB Server", "127.0.0.1:2345" }; cfg::_bool silence_all_logs{ this, "Silence All Logs", false, true }; diff --git a/rpcs3/Input/basic_keyboard_handler.cpp b/rpcs3/Input/basic_keyboard_handler.cpp index 50ee435ea..3fa7acf87 100644 --- a/rpcs3/Input/basic_keyboard_handler.cpp +++ b/rpcs3/Input/basic_keyboard_handler.cpp @@ -60,11 +60,22 @@ void basic_keyboard_handler::SetTargetWindow(QWindow* target) bool basic_keyboard_handler::eventFilter(QObject* watched, QEvent* event) { - if (!event) + if (!event) [[unlikely]] { return false; } + if (input::g_active_mouse_and_keyboard != input::active_mouse_and_keyboard::emulated) + { + if (!m_keys_released) + { + ReleaseAllKeys(); + } + return false; + } + + m_keys_released = false; + // !m_target is for future proofing when gsrender isn't automatically initialized on load. // !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() || watched == m_target) @@ -97,7 +108,7 @@ bool basic_keyboard_handler::eventFilter(QObject* watched, QEvent* event) void basic_keyboard_handler::keyPressEvent(QKeyEvent* keyEvent) { - if (!keyEvent) + if (!keyEvent) [[unlikely]] { return; } @@ -118,7 +129,7 @@ void basic_keyboard_handler::keyPressEvent(QKeyEvent* keyEvent) void basic_keyboard_handler::keyReleaseEvent(QKeyEvent* keyEvent) { - if (!keyEvent) + if (!keyEvent) [[unlikely]] { return; } @@ -141,7 +152,7 @@ void basic_keyboard_handler::keyReleaseEvent(QKeyEvent* keyEvent) // key() only shows the modifiers and the modified key (e.g. no easy way of knowing that - was pressed in 'SHIFT+-' in order to get _) s32 basic_keyboard_handler::getUnmodifiedKey(QKeyEvent* keyEvent) { - if (!keyEvent) + if (!keyEvent) [[unlikely]] { return -1; } diff --git a/rpcs3/Input/basic_mouse_handler.cpp b/rpcs3/Input/basic_mouse_handler.cpp index a948c034c..d9435ef95 100644 --- a/rpcs3/Input/basic_mouse_handler.cpp +++ b/rpcs3/Input/basic_mouse_handler.cpp @@ -86,7 +86,12 @@ bool basic_mouse_handler::eventFilter(QObject* target, QEvent* ev) return false; } - if (!ev) + if (!ev) [[unlikely]] + { + return false; + } + + if (input::g_active_mouse_and_keyboard != input::active_mouse_and_keyboard::emulated) { return false; } @@ -123,7 +128,10 @@ bool basic_mouse_handler::eventFilter(QObject* target, QEvent* ev) void basic_mouse_handler::MouseButtonDown(QMouseEvent* event) { - if (!event) return; + if (!event) [[unlikely]] + { + return; + } const int button = event->button(); if (const auto it = std::find_if(m_buttons.cbegin(), m_buttons.cend(), [button](const auto& entry){ return entry.second == button; }); @@ -135,7 +143,10 @@ void basic_mouse_handler::MouseButtonDown(QMouseEvent* event) void basic_mouse_handler::MouseButtonUp(QMouseEvent* event) { - if (!event) return; + if (!event) [[unlikely]] + { + return; + } const int button = event->button(); if (const auto it = std::find_if(m_buttons.cbegin(), m_buttons.cend(), [button](const auto& entry){ return entry.second == button; }); @@ -147,7 +158,10 @@ void basic_mouse_handler::MouseButtonUp(QMouseEvent* event) void basic_mouse_handler::MouseScroll(QWheelEvent* event) { - if (!event) return; + if (!event) [[unlikely]] + { + return; + } const QPoint delta = event->angleDelta(); const s8 x = std::clamp(delta.x() / 120, -128, 127); @@ -177,7 +191,10 @@ int basic_mouse_handler::get_mouse_button(const cfg::string& button) void basic_mouse_handler::MouseMove(QMouseEvent* event) { - if (!event) return; + if (!event) [[unlikely]] + { + return; + } if (is_time_for_update()) { diff --git a/rpcs3/Input/keyboard_pad_handler.cpp b/rpcs3/Input/keyboard_pad_handler.cpp index 943969bbd..e87b5ff9c 100644 --- a/rpcs3/Input/keyboard_pad_handler.cpp +++ b/rpcs3/Input/keyboard_pad_handler.cpp @@ -2,6 +2,7 @@ #include "pad_thread.h" #include "Emu/Io/pad_config.h" #include "Emu/Io/KeyboardHandler.h" +#include "Emu/Io/interception.h" #include "Input/product_info.h" #include "rpcs3qt/gs_frame.h" @@ -324,10 +325,28 @@ void keyboard_pad_handler::release_all_keys() pad.m_sticks[i].m_value = 128; } } + + m_keys_released = true; } bool keyboard_pad_handler::eventFilter(QObject* target, QEvent* ev) { + if (!ev) [[unlikely]] + { + return false; + } + + if (input::g_active_mouse_and_keyboard != input::active_mouse_and_keyboard::pad) + { + if (!m_keys_released) + { + release_all_keys(); + } + return false; + } + + m_keys_released = false; + // !m_target is for future proofing when gsrender isn't automatically initialized on load. // !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) @@ -381,6 +400,11 @@ void keyboard_pad_handler::SetTargetWindow(QWindow* target) void keyboard_pad_handler::processKeyEvent(QKeyEvent* event, bool pressed) { + if (!event) [[unlikely]] + { + return; + } + if (event->isAutoRepeat()) { event->ignore(); @@ -444,6 +468,11 @@ void keyboard_pad_handler::processKeyEvent(QKeyEvent* event, bool pressed) void keyboard_pad_handler::keyPressEvent(QKeyEvent* event) { + if (!event) [[unlikely]] + { + return; + } + if (event->modifiers() & Qt::AltModifier) { switch (event->key()) @@ -502,12 +531,22 @@ void keyboard_pad_handler::keyReleaseEvent(QKeyEvent* event) void keyboard_pad_handler::mousePressEvent(QMouseEvent* event) { + if (!event) [[unlikely]] + { + return; + } + Key(event->button(), true); event->ignore(); } void keyboard_pad_handler::mouseReleaseEvent(QMouseEvent* event) { + if (!event) [[unlikely]] + { + return; + } + Key(event->button(), false, 0); event->ignore(); } @@ -521,7 +560,7 @@ bool keyboard_pad_handler::get_mouse_lock_state() const void keyboard_pad_handler::mouseMoveEvent(QMouseEvent* event) { - if (!m_mouse_move_used) + if (!m_mouse_move_used || !event) { event->ignore(); return; @@ -659,7 +698,7 @@ void keyboard_pad_handler::mouseMoveEvent(QMouseEvent* event) void keyboard_pad_handler::mouseWheelEvent(QWheelEvent* event) { - if (!m_mouse_wheel_used) + if (!m_mouse_wheel_used || !event) { return; } diff --git a/rpcs3/Input/keyboard_pad_handler.h b/rpcs3/Input/keyboard_pad_handler.h index 9185c299b..2f1d8a666 100644 --- a/rpcs3/Input/keyboard_pad_handler.h +++ b/rpcs3/Input/keyboard_pad_handler.h @@ -105,6 +105,7 @@ protected: private: QWindow* m_target = nullptr; mouse_movement_mode m_mouse_movement_mode = mouse_movement_mode::relative; + bool m_keys_released = false; bool m_mouse_move_used = false; bool m_mouse_wheel_used = false; bool get_mouse_lock_state() const; diff --git a/rpcs3/Input/pad_thread.cpp b/rpcs3/Input/pad_thread.cpp index bc294ea73..cb85fbcfc 100644 --- a/rpcs3/Input/pad_thread.cpp +++ b/rpcs3/Input/pad_thread.cpp @@ -16,6 +16,7 @@ #endif #include "keyboard_pad_handler.h" #include "Emu/Io/Null/NullPadHandler.h" +#include "Emu/Io/interception.h" #include "Emu/Io/PadHandler.h" #include "Emu/Io/pad_config.h" #include "Emu/System.h" @@ -200,6 +201,9 @@ void pad_thread::Init() || (pad->m_class_type >= CELL_PAD_FAKE_TYPE_FIRST && pad->m_class_type < CELL_PAD_FAKE_TYPE_LAST); connect_usb_controller(i, input::get_product_by_vid_pid(pad->m_vendor_id, pad->m_product_id)); } + + // Initialize active mouse and keyboard. Activate pad handler if one exists. + input::set_mouse_and_keyboard(m_handlers.contains(pad_handler::keyboard) ? input::active_mouse_and_keyboard::pad : input::active_mouse_and_keyboard::emulated); } void pad_thread::SetRumble(const u32 pad, u8 large_motor, bool small_motor) diff --git a/rpcs3/Input/raw_mouse_handler.cpp b/rpcs3/Input/raw_mouse_handler.cpp index 90323f762..33e0410c1 100644 --- a/rpcs3/Input/raw_mouse_handler.cpp +++ b/rpcs3/Input/raw_mouse_handler.cpp @@ -432,7 +432,7 @@ void raw_mouse_handler::register_raw_input_devices() m_registered_raw_input_devices = true; } -void raw_mouse_handler::unregister_raw_input_devices() +void raw_mouse_handler::unregister_raw_input_devices() const { if (!m_registered_raw_input_devices) { diff --git a/rpcs3/Input/raw_mouse_handler.h b/rpcs3/Input/raw_mouse_handler.h index 9cba938be..155587f11 100644 --- a/rpcs3/Input/raw_mouse_handler.h +++ b/rpcs3/Input/raw_mouse_handler.h @@ -108,7 +108,7 @@ private: #ifdef _WIN32 void register_raw_input_devices(); - void unregister_raw_input_devices(); + void unregister_raw_input_devices() const; bool m_registered_raw_input_devices = false; #endif diff --git a/rpcs3/rpcs3qt/emu_settings_type.h b/rpcs3/rpcs3qt/emu_settings_type.h index c28306551..8a208c07d 100644 --- a/rpcs3/rpcs3qt/emu_settings_type.h +++ b/rpcs3/rpcs3qt/emu_settings_type.h @@ -175,6 +175,7 @@ enum class emu_settings_type ShowPPUCompilationHint, ShowPressureIntensityToggleHint, ShowAnalogLimiterToggleHint, + ShowMouseAndKeyboardToggleHint, WindowTitleFormat, PauseDuringHomeMenu, @@ -366,6 +367,7 @@ inline static const QMap settings_location = { emu_settings_type::ShowPPUCompilationHint, { "Miscellaneous", "Show PPU compilation hint"}}, { emu_settings_type::ShowPressureIntensityToggleHint, { "Miscellaneous", "Show pressure intensity toggle hint"}}, { emu_settings_type::ShowAnalogLimiterToggleHint, { "Miscellaneous", "Show analog limiter toggle hint"}}, + { emu_settings_type::ShowMouseAndKeyboardToggleHint, { "Miscellaneous", "Show mouse and keyboard toggle hint"}}, { emu_settings_type::SilenceAllLogs, { "Miscellaneous", "Silence All Logs" }}, { emu_settings_type::WindowTitleFormat, { "Miscellaneous", "Window Title Format" }}, { emu_settings_type::PauseDuringHomeMenu, { "Miscellaneous", "Pause Emulation During Home Menu" }}, diff --git a/rpcs3/rpcs3qt/gs_frame.cpp b/rpcs3/rpcs3qt/gs_frame.cpp index c172b11d1..30e96189d 100644 --- a/rpcs3/rpcs3qt/gs_frame.cpp +++ b/rpcs3/rpcs3qt/gs_frame.cpp @@ -16,6 +16,7 @@ #include "Emu/Cell/lv2/sys_rsxaudio.h" #include "Emu/RSX/rsx_utils.h" #include "Emu/RSX/Overlays/overlay_message.h" +#include "Emu/Io/interception.h" #include "Emu/Io/recording_config.h" #include @@ -295,7 +296,10 @@ void gs_frame::keyPressEvent(QKeyEvent *keyEvent) } case Qt::Key_F11: { - handle_shortcut(gui::shortcuts::shortcut::gw_toggle_recording, {}); + if (keyEvent->modifiers() == Qt::ControlModifier) + handle_shortcut(gui::shortcuts::shortcut::gw_toggle_mouse_and_keyboard, {}); + else + handle_shortcut(gui::shortcuts::shortcut::gw_toggle_recording, {}); break; } case Qt::Key_F12: @@ -421,6 +425,11 @@ void gs_frame::handle_shortcut(gui::shortcuts::shortcut shortcut_key, const QKey gui_log.warning("%s boost mode", g_disable_frame_limit.load() ? "Enabled" : "Disabled"); break; } + case gui::shortcuts::shortcut::gw_toggle_mouse_and_keyboard: + { + input::toggle_mouse_and_keyboard(); + break; + } default: { break; diff --git a/rpcs3/rpcs3qt/localized_emu.h b/rpcs3/rpcs3qt/localized_emu.h index e95e2b170..20b8eb6e2 100644 --- a/rpcs3/rpcs3qt/localized_emu.h +++ b/rpcs3/rpcs3qt/localized_emu.h @@ -69,6 +69,8 @@ private: case localized_string_id::RSX_OVERLAYS_PRESSURE_INTENSITY_TOGGLED_ON: return tr("Pressure intensity mode of player %0 enabled", "Pressure intensity toggled on").arg(std::forward(args)...); case localized_string_id::RSX_OVERLAYS_ANALOG_LIMITER_TOGGLED_OFF: return tr("Analog limiter of player %0 disabled", "Analog limiter toggled off").arg(std::forward(args)...); case localized_string_id::RSX_OVERLAYS_ANALOG_LIMITER_TOGGLED_ON: return tr("Analog limiter of player %0 enabled", "Analog limiter toggled on").arg(std::forward(args)...); + case localized_string_id::RSX_OVERLAYS_MOUSE_AND_KEYBOARD_EMULATED: return tr("Mouse and keyboard are now used as emulated devices.", "Mouse and keyboard emulated"); + case localized_string_id::RSX_OVERLAYS_MOUSE_AND_KEYBOARD_PAD: return tr("Mouse and keyboard are now used as pad.", "Mouse and keyboard pad"); case localized_string_id::CELL_GAME_ERROR_BROKEN_GAMEDATA: return tr("ERROR: Game data is corrupted. The application will continue.", "Game Error"); case localized_string_id::CELL_GAME_ERROR_BROKEN_HDDGAME: return tr("ERROR: HDD boot game is corrupted. The application will continue.", "Game Error"); case localized_string_id::CELL_GAME_ERROR_BROKEN_EXIT_GAMEDATA: return tr("ERROR: Game data is corrupted. The application will be terminated.", "Game Error"); diff --git a/rpcs3/rpcs3qt/settings_dialog.cpp b/rpcs3/rpcs3qt/settings_dialog.cpp index 14836e7fc..4b76699e3 100644 --- a/rpcs3/rpcs3qt/settings_dialog.cpp +++ b/rpcs3/rpcs3qt/settings_dialog.cpp @@ -1817,6 +1817,9 @@ settings_dialog::settings_dialog(std::shared_ptr gui_settings, std m_emu_settings->EnhanceCheckBox(ui->showAnalogLimiterToggleHint, emu_settings_type::ShowAnalogLimiterToggleHint); SubscribeTooltip(ui->showAnalogLimiterToggleHint, tooltips.settings.show_analog_limiter_toggle_hint); + m_emu_settings->EnhanceCheckBox(ui->showMouseAndKeyboardToggleHint, emu_settings_type::ShowMouseAndKeyboardToggleHint); + SubscribeTooltip(ui->showMouseAndKeyboardToggleHint, tooltips.settings.show_mouse_and_keyboard_toggle_hint); + m_emu_settings->EnhanceCheckBox(ui->pauseDuringHomeMenu, emu_settings_type::PauseDuringHomeMenu); SubscribeTooltip(ui->pauseDuringHomeMenu, tooltips.settings.pause_during_home_menu); diff --git a/rpcs3/rpcs3qt/settings_dialog.ui b/rpcs3/rpcs3qt/settings_dialog.ui index 13bff3c43..aaf34c8d3 100644 --- a/rpcs3/rpcs3qt/settings_dialog.ui +++ b/rpcs3/rpcs3qt/settings_dialog.ui @@ -2277,17 +2277,17 @@ - - Country - - - - - - - - - + + Country + + + + + + + + + Qt::Vertical @@ -2993,6 +2993,13 @@ + + + + Show mouse and keyboard toggle hint + + + diff --git a/rpcs3/rpcs3qt/shortcut_settings.cpp b/rpcs3/rpcs3qt/shortcut_settings.cpp index b90daa494..5a6c9e3b1 100644 --- a/rpcs3/rpcs3qt/shortcut_settings.cpp +++ b/rpcs3/rpcs3qt/shortcut_settings.cpp @@ -27,8 +27,9 @@ void fmt_class_string::format(std::string& out, u64 ar case shortcut::gw_restart: return "gw_restart"; case shortcut::gw_rsx_capture: return "gw_rsx_capture"; case shortcut::gw_frame_limit: return "gw_frame_limit"; + case shortcut::gw_toggle_mouse_and_keyboard: return "gw_toggle_mouse_and_keyboard"; case shortcut::count: return "count"; - }; + } return unknown; }); @@ -53,7 +54,8 @@ shortcut_settings::shortcut_settings() { shortcut::gw_savestate, shortcut_info{ "game_window_savestate", tr("Savestate"), "Ctrl+S", shortcut_handler_id::game_window } }, { shortcut::gw_restart, shortcut_info{ "game_window_restart", tr("Restart"), "Ctrl+R", shortcut_handler_id::game_window } }, { shortcut::gw_rsx_capture, shortcut_info{ "game_window_rsx_capture", tr("RSX Capture"), "Alt+C", shortcut_handler_id::game_window } }, - { shortcut::gw_frame_limit, shortcut_info{ "game_window_gw_frame_limit", tr("Toggle Framelimit"), "Ctrl+F10", shortcut_handler_id::game_window } }, + { shortcut::gw_frame_limit, shortcut_info{ "game_window_frame_limit", tr("Toggle Framelimit"), "Ctrl+F10", shortcut_handler_id::game_window } }, + { shortcut::gw_toggle_mouse_and_keyboard, shortcut_info{ "game_window_toggle_mouse_and_keyboard", tr("Toggle Keyboard"), "Ctrl+F11", shortcut_handler_id::game_window } }, }) { } diff --git a/rpcs3/rpcs3qt/shortcut_settings.h b/rpcs3/rpcs3qt/shortcut_settings.h index cd87fd5df..8e5094b80 100644 --- a/rpcs3/rpcs3qt/shortcut_settings.h +++ b/rpcs3/rpcs3qt/shortcut_settings.h @@ -35,6 +35,7 @@ namespace gui gw_restart, gw_rsx_capture, gw_frame_limit, + gw_toggle_mouse_and_keyboard, count }; diff --git a/rpcs3/rpcs3qt/tooltips.h b/rpcs3/rpcs3qt/tooltips.h index e06f6231a..c83360cc6 100644 --- a/rpcs3/rpcs3qt/tooltips.h +++ b/rpcs3/rpcs3qt/tooltips.h @@ -142,6 +142,7 @@ public: const QString show_ppu_compilation_hint = tr("Shows 'Compiling PPU modules' hint using the native overlay."); const QString show_pressure_intensity_toggle_hint = tr("Shows pressure intensity toggle hint using the native overlay."); const QString show_analog_limiter_toggle_hint = tr("Shows analog limiter toggle hint using the native overlay."); + const QString show_mouse_and_keyboard_toggle_hint = tr("Shows mouse and keyboard toggle hint using the native overlay."); const QString use_native_interface = tr("Enables use of native HUD within the game window that can interact with game controllers.\nWhen disabled, regular Qt dialogs are used instead.\nCurrently, the on-screen keyboard only supports the English key layout."); const QString pause_during_home_menu = tr("When enabled, opening the home menu will also pause emulation.\nWhile most games pause themselves while the home menu is shown, some do not.\nIn that case it can be helpful to pause the emulation whenever the home menu is open."); @@ -247,7 +248,7 @@ public: const QString dns_swap = tr("DNS Swap List.\nOnly available in custom configurations."); const QString bind = tr("Interface IP Address to bind to.\nOnly available in custom configurations."); const QString enable_upnp = tr("Enable UPNP.\nThis will automatically forward ports bound on 0.0.0.0 if your router has UPNP enabled."); - const QString psn_country = tr("Changes the RPCN country."); + const QString psn_country = tr("Changes the RPCN country."); // system