diff --git a/rpcs3/Emu/Io/KeyboardHandler.cpp b/rpcs3/Emu/Io/KeyboardHandler.cpp index 8b2a134986..73ef8d0696 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 51404b72c4..594f7be3f8 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 eb0141fdf4..dab9dbe3e8 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 e5653b96ec..16a407b8e7 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 2012730f1f..389de56069 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 a3926102ad..03a0a317e8 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 50ee435ead..3fa7acf876 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 a948c034c3..d9435ef95e 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 943969bbd9..e87b5ff9ca 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 9185c299bb..2f1d8a6669 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 bc294ea739..cb85fbcfce 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 90323f7625..33e0410c11 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 9cba938bec..155587f11e 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 c283065513..8a208c07d5 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 c172b11d12..30e96189d3 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 e95e2b1703..20b8eb6e2e 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 14836e7fc4..4b76699e36 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 13bff3c435..aaf34c8d32 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 b90daa494b..5a6c9e3b16 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 cd87fd5df4..8e5094b80a 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 e06f6231a2..c83360cc67 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