From 47ba8a159b5f6b3ef6d0232b94380d32f762c816 Mon Sep 17 00:00:00 2001 From: Gonzalosilvalde Date: Sun, 26 Jan 2025 17:20:59 +0100 Subject: [PATCH 1/2] Add mouse grab/lock feature when PCSX2 is in focus --- pcsx2-qt/MainWindow.cpp | 40 +++++++++++++++++++ pcsx2-qt/MainWindow.h | 15 ++++--- pcsx2-qt/Settings/InterfaceSettingsWidget.cpp | 5 +++ pcsx2-qt/Settings/InterfaceSettingsWidget.ui | 7 ++++ 4 files changed, 62 insertions(+), 5 deletions(-) diff --git a/pcsx2-qt/MainWindow.cpp b/pcsx2-qt/MainWindow.cpp index 7b3eaa8ec6..0fd7a042f3 100644 --- a/pcsx2-qt/MainWindow.cpp +++ b/pcsx2-qt/MainWindow.cpp @@ -107,6 +107,7 @@ MainWindow::MainWindow() #if !defined(_WIN32) && !defined(__APPLE__) s_use_central_widget = DisplayContainer::isRunningOnWayland(); #endif + createCheckMousePositionTimer(); } MainWindow::~MainWindow() @@ -1069,6 +1070,19 @@ bool MainWindow::shouldHideMainWindow() const QtHost::InNoGUIMode(); } +bool MainWindow::shouldMouseGrab() const +{ + if (!s_vm_valid || s_vm_paused) return false; + + if (!Host::GetBoolSettingValue("EmuCore", "EnableMouseGrab", false)) return false; + + bool windowsHidden = (!m_debugger_window || m_debugger_window->isHidden()) && + (!m_controller_settings_window || m_controller_settings_window->isHidden()) && + (!m_settings_window || m_settings_window->isHidden()); + + return windowsHidden && (isActiveWindow() || isRenderingFullscreen()); +} + bool MainWindow::shouldAbortForMemcardBusy(const VMLock& lock) { if (MemcardBusy::IsBusy() && !GSDumpReplayer::IsReplayingDump()) @@ -2529,6 +2543,32 @@ QWidget* MainWindow::getDisplayContainer() const return (m_display_container ? static_cast(m_display_container) : static_cast(m_display_widget)); } +void MainWindow::createCheckMousePositionTimer(){ + m_mouse_check_timer = new QTimer(this); + connect(m_mouse_check_timer, &QTimer::timeout, this, &MainWindow::checkMousePosition); + m_mouse_check_timer->start(16); +} + +void MainWindow::checkMousePosition() { + if (!shouldMouseGrab()) return; + + QPoint globalCursorPos = QCursor::pos(); + const QRect& windowBounds = isRenderingFullscreen() ? screen()->geometry() : geometry(); + + if (windowBounds.contains(globalCursorPos)) return; + + QCursor::setPos( + std::clamp(globalCursorPos.x(), windowBounds.left(), windowBounds.right()), + std::clamp(globalCursorPos.y(), windowBounds.top(), windowBounds.bottom()) + ); + +} + +void MainWindow::mouseMoveEvent(QMouseEvent *event){ + QWidget::mouseMoveEvent(event); +} + + void MainWindow::saveDisplayWindowGeometryToConfig() { QWidget* container = getDisplayContainer(); diff --git a/pcsx2-qt/MainWindow.h b/pcsx2-qt/MainWindow.h index 8c3d22d519..3241ff5202 100644 --- a/pcsx2-qt/MainWindow.h +++ b/pcsx2-qt/MainWindow.h @@ -60,8 +60,8 @@ public: /// Returns the parent widget, which can be used for any popup dialogs. __fi QWidget* getDialogParent() const { return m_dialog_parent; } - /// Cancels any pending unpause/fullscreen transition. - /// Call when you're going to destroy the VM anyway. + /// Cancels any pending unpause/fullscreen transition. + /// Call when you're going to destroy the VM anyway. void cancelResume(); private: @@ -128,7 +128,7 @@ private Q_SLOTS: void mouseModeRequested(bool relative_mode, bool hide_cursor); void releaseRenderWindow(); void focusDisplayWidget(); - + void createCheckMousePositionTimer(); void onGameListRefreshComplete(); void onGameListRefreshProgress(const QString& status, int current, int total); void onGameListSelectionChanged(); @@ -180,13 +180,14 @@ private Q_SLOTS: void onInputRecPlayActionTriggered(); void onInputRecStopActionTriggered(); void onInputRecOpenViewer(); - void onVMStarting(); void onVMStarted(); void onVMPaused(); void onVMResumed(); void onVMStopped(); + void checkMousePosition(); + void onGameChanged(const QString& title, const QString& elf_override, const QString& disc_path, const QString& serial, quint32 disc_crc, quint32 crc); @@ -204,6 +205,7 @@ protected: void dropEvent(QDropEvent* event) override; void moveEvent(QMoveEvent* event) override; void resizeEvent(QResizeEvent* event) override; + void mouseMoveEvent(QMouseEvent* event) override; #ifdef _WIN32 bool nativeEvent(const QByteArray& eventType, void* message, qintptr* result) override; @@ -238,6 +240,7 @@ private: bool isRenderingToMain() const; bool shouldHideMouseCursor() const; bool shouldHideMainWindow() const; + bool shouldMouseGrab() const; void switchToGameListView(); void switchToEmulationView(); @@ -307,9 +310,11 @@ private: bool m_was_disc_change_request = false; bool m_is_closing = false; bool m_is_temporarily_windowed = false; - + QString m_last_fps_status; + QTimer* m_mouse_check_timer = nullptr; + #ifdef _WIN32 void* m_device_notification_handle = nullptr; #endif diff --git a/pcsx2-qt/Settings/InterfaceSettingsWidget.cpp b/pcsx2-qt/Settings/InterfaceSettingsWidget.cpp index 9d5e57e6fa..7e1b0ee966 100644 --- a/pcsx2-qt/Settings/InterfaceSettingsWidget.cpp +++ b/pcsx2-qt/Settings/InterfaceSettingsWidget.cpp @@ -80,6 +80,8 @@ InterfaceSettingsWidget::InterfaceSettingsWidget(SettingsWindow* dialog, QWidget SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.pauseOnControllerDisconnection, "UI", "PauseOnControllerDisconnection", false); SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.discordPresence, "EmuCore", "EnableDiscordPresence", false); + SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.mouseGrab, "EmuCore", "EnableMouseGrab", false); + SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.startFullscreen, "UI", "StartFullscreen", false); SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.doubleClickTogglesFullscreen, "UI", "DoubleClickTogglesFullscreen", true); @@ -161,6 +163,9 @@ InterfaceSettingsWidget::InterfaceSettingsWidget(SettingsWindow* dialog, QWidget dialog->registerWidgetHelp( m_ui.discordPresence, tr("Enable Discord Presence"), tr("Unchecked"), tr("Shows the game you are currently playing as part of your profile in Discord.")); + dialog->registerWidgetHelp( + m_ui.mouseGrab, tr("Enable Mouse Grab"), tr("Unchecked"), + tr("Locks the mouse cursor to the windows when PCSX2 is in focus.")); dialog->registerWidgetHelp( m_ui.doubleClickTogglesFullscreen, tr("Double-Click Toggles Fullscreen"), tr("Checked"), tr("Allows switching in and out of fullscreen mode by double-clicking the game window.")); diff --git a/pcsx2-qt/Settings/InterfaceSettingsWidget.ui b/pcsx2-qt/Settings/InterfaceSettingsWidget.ui index f42b72f094..6fc709aa20 100644 --- a/pcsx2-qt/Settings/InterfaceSettingsWidget.ui +++ b/pcsx2-qt/Settings/InterfaceSettingsWidget.ui @@ -50,6 +50,13 @@ + + + + Enable Mouse Grab + + + From 15ffee7d8d29d7a50cfd3cce2255f29e3f01b36a Mon Sep 17 00:00:00 2001 From: Gonzalosilvalde Date: Sun, 26 Jan 2025 18:10:12 +0100 Subject: [PATCH 2/2] Apply clang-format to MainWindow --- pcsx2-qt/MainWindow.cpp | 53 ++++++++++++++++++++++------------------- pcsx2-qt/MainWindow.h | 16 ++++++------- 2 files changed, 37 insertions(+), 32 deletions(-) diff --git a/pcsx2-qt/MainWindow.cpp b/pcsx2-qt/MainWindow.cpp index 0fd7a042f3..f6c3488a01 100644 --- a/pcsx2-qt/MainWindow.cpp +++ b/pcsx2-qt/MainWindow.cpp @@ -107,7 +107,7 @@ MainWindow::MainWindow() #if !defined(_WIN32) && !defined(__APPLE__) s_use_central_widget = DisplayContainer::isRunningOnWayland(); #endif - createCheckMousePositionTimer(); + createCheckMousePositionTimer(); } MainWindow::~MainWindow() @@ -1071,16 +1071,18 @@ bool MainWindow::shouldHideMainWindow() const } bool MainWindow::shouldMouseGrab() const -{ - if (!s_vm_valid || s_vm_paused) return false; +{ + if (!s_vm_valid || s_vm_paused) + return false; - if (!Host::GetBoolSettingValue("EmuCore", "EnableMouseGrab", false)) return false; + if (!Host::GetBoolSettingValue("EmuCore", "EnableMouseGrab", false)) + return false; - bool windowsHidden = (!m_debugger_window || m_debugger_window->isHidden()) && - (!m_controller_settings_window || m_controller_settings_window->isHidden()) && - (!m_settings_window || m_settings_window->isHidden()); + bool windowsHidden = (!m_debugger_window || m_debugger_window->isHidden()) && + (!m_controller_settings_window || m_controller_settings_window->isHidden()) && + (!m_settings_window || m_settings_window->isHidden()); - return windowsHidden && (isActiveWindow() || isRenderingFullscreen()); + return windowsHidden && (isActiveWindow() || isRenderingFullscreen()); } bool MainWindow::shouldAbortForMemcardBusy(const VMLock& lock) @@ -2543,29 +2545,32 @@ QWidget* MainWindow::getDisplayContainer() const return (m_display_container ? static_cast(m_display_container) : static_cast(m_display_widget)); } -void MainWindow::createCheckMousePositionTimer(){ - m_mouse_check_timer = new QTimer(this); - connect(m_mouse_check_timer, &QTimer::timeout, this, &MainWindow::checkMousePosition); - m_mouse_check_timer->start(16); +void MainWindow::createCheckMousePositionTimer() +{ + m_mouse_check_timer = new QTimer(this); + connect(m_mouse_check_timer, &QTimer::timeout, this, &MainWindow::checkMousePosition); + m_mouse_check_timer->start(16); } -void MainWindow::checkMousePosition() { - if (!shouldMouseGrab()) return; +void MainWindow::checkMousePosition() +{ + if (!shouldMouseGrab()) + return; - QPoint globalCursorPos = QCursor::pos(); - const QRect& windowBounds = isRenderingFullscreen() ? screen()->geometry() : geometry(); + QPoint globalCursorPos = QCursor::pos(); + const QRect& windowBounds = isRenderingFullscreen() ? screen()->geometry() : geometry(); - if (windowBounds.contains(globalCursorPos)) return; + if (windowBounds.contains(globalCursorPos)) + return; - QCursor::setPos( - std::clamp(globalCursorPos.x(), windowBounds.left(), windowBounds.right()), - std::clamp(globalCursorPos.y(), windowBounds.top(), windowBounds.bottom()) - ); - + QCursor::setPos( + std::clamp(globalCursorPos.x(), windowBounds.left(), windowBounds.right()), + std::clamp(globalCursorPos.y(), windowBounds.top(), windowBounds.bottom())); } -void MainWindow::mouseMoveEvent(QMouseEvent *event){ - QWidget::mouseMoveEvent(event); +void MainWindow::mouseMoveEvent(QMouseEvent* event) +{ + QWidget::mouseMoveEvent(event); } diff --git a/pcsx2-qt/MainWindow.h b/pcsx2-qt/MainWindow.h index 3241ff5202..6cd1f81ad5 100644 --- a/pcsx2-qt/MainWindow.h +++ b/pcsx2-qt/MainWindow.h @@ -60,8 +60,8 @@ public: /// Returns the parent widget, which can be used for any popup dialogs. __fi QWidget* getDialogParent() const { return m_dialog_parent; } - /// Cancels any pending unpause/fullscreen transition. - /// Call when you're going to destroy the VM anyway. + /// Cancels any pending unpause/fullscreen transition. + /// Call when you're going to destroy the VM anyway. void cancelResume(); private: @@ -128,7 +128,7 @@ private Q_SLOTS: void mouseModeRequested(bool relative_mode, bool hide_cursor); void releaseRenderWindow(); void focusDisplayWidget(); - void createCheckMousePositionTimer(); + void createCheckMousePositionTimer(); void onGameListRefreshComplete(); void onGameListRefreshProgress(const QString& status, int current, int total); void onGameListSelectionChanged(); @@ -186,7 +186,7 @@ private Q_SLOTS: void onVMResumed(); void onVMStopped(); - void checkMousePosition(); + void checkMousePosition(); void onGameChanged(const QString& title, const QString& elf_override, const QString& disc_path, const QString& serial, quint32 disc_crc, quint32 crc); @@ -205,7 +205,7 @@ protected: void dropEvent(QDropEvent* event) override; void moveEvent(QMoveEvent* event) override; void resizeEvent(QResizeEvent* event) override; - void mouseMoveEvent(QMouseEvent* event) override; + void mouseMoveEvent(QMouseEvent* event) override; #ifdef _WIN32 bool nativeEvent(const QByteArray& eventType, void* message, qintptr* result) override; @@ -240,7 +240,7 @@ private: bool isRenderingToMain() const; bool shouldHideMouseCursor() const; bool shouldHideMainWindow() const; - bool shouldMouseGrab() const; + bool shouldMouseGrab() const; void switchToGameListView(); void switchToEmulationView(); @@ -310,10 +310,10 @@ private: bool m_was_disc_change_request = false; bool m_is_closing = false; bool m_is_temporarily_windowed = false; - + QString m_last_fps_status; - QTimer* m_mouse_check_timer = nullptr; + QTimer* m_mouse_check_timer = nullptr; #ifdef _WIN32 void* m_device_notification_handle = nullptr;