From 1dac01498c82545956b979874763b50aeb8661a5 Mon Sep 17 00:00:00 2001 From: Megamouse Date: Mon, 31 Aug 2020 14:47:47 +0200 Subject: [PATCH] Update mouse lock logic - fix headers - update cursor whenever the mouse is moved - unify cursor logic - move m_mouse_hide_and_lock logic to handle_cursor (toggle_fullscreen is the trigger, not the handler) - disable mouse lock and idle timer if the window is inactive --- rpcs3/Input/basic_mouse_handler.cpp | 7 ++- rpcs3/Input/basic_mouse_handler.h | 1 - rpcs3/rpcs3qt/gs_frame.cpp | 88 ++++++++++++++++++++--------- rpcs3/rpcs3qt/gs_frame.h | 8 ++- 4 files changed, 72 insertions(+), 32 deletions(-) diff --git a/rpcs3/Input/basic_mouse_handler.cpp b/rpcs3/Input/basic_mouse_handler.cpp index 4d1464601a..7f029a06c4 100644 --- a/rpcs3/Input/basic_mouse_handler.cpp +++ b/rpcs3/Input/basic_mouse_handler.cpp @@ -1,8 +1,9 @@ -#include "basic_mouse_handler.h" - -#include +#include #include +#include "basic_mouse_handler.h" +#include "rpcs3qt/gs_frame.h" + LOG_CHANNEL(input_log, "Input"); void basic_mouse_handler::Init(const u32 max_connect) diff --git a/rpcs3/Input/basic_mouse_handler.h b/rpcs3/Input/basic_mouse_handler.h index 791875148e..06cea8ab24 100644 --- a/rpcs3/Input/basic_mouse_handler.h +++ b/rpcs3/Input/basic_mouse_handler.h @@ -2,7 +2,6 @@ #include "stdafx.h" #include "Emu/Io/MouseHandler.h" -#include "rpcs3qt/gs_frame.h" #include #include diff --git a/rpcs3/rpcs3qt/gs_frame.cpp b/rpcs3/rpcs3qt/gs_frame.cpp index 370c4b9d27..a1906967ab 100644 --- a/rpcs3/rpcs3qt/gs_frame.cpp +++ b/rpcs3/rpcs3qt/gs_frame.cpp @@ -70,15 +70,15 @@ gs_frame::gs_frame(const QRect& geometry, const QIcon& appIcon, const std::share create(); // Change cursor when in fullscreen. - connect(this, &QWindow::visibilityChanged, this, &gs_frame::HandleCursor); + connect(this, &QWindow::visibilityChanged, this, [this](QWindow::Visibility visibility) + { + handle_cursor(visibility, true, true); + }); // Configure the mouse hide on idle timer connect(&m_mousehide_timer, &QTimer::timeout, this, &gs_frame::MouseHideTimeout); m_mousehide_timer.setSingleShot(true); - // We default the mouse lock to being off - m_mouse_hide_and_lock = false; - #ifdef _WIN32 m_tb_button = new QWinTaskbarButton(); m_tb_progress = m_tb_button->progress(); @@ -209,15 +209,10 @@ void gs_frame::toggle_fullscreen() if (visibility() == FullScreen) { setVisibility(Windowed); - // in windowed mode we default to not hiding / locking the mouse - m_mouse_hide_and_lock = false; } else { setVisibility(FullScreen); - // in fullscreen (unless we want to show mouse) then we default to hiding and locking - if (!m_show_mouse_in_fullscreen) - m_mouse_hide_and_lock = true; } }); } @@ -228,12 +223,46 @@ void gs_frame::toggle_mouselock() m_mouse_hide_and_lock = !m_mouse_hide_and_lock; // and update the cursor - HandleCursor(this->visibility()); + handle_cursor(visibility(), false, true); +} + +void gs_frame::update_cursor() +{ + bool show_mouse; + + if (!isActive()) + { + // Show the mouse by default if this is not the active window + show_mouse = true; + } + else if (m_hide_mouse_after_idletime && !m_mousehide_timer.isActive()) + { + // Hide the mouse if the idle timeout was reached (which means that the timer isn't running) + show_mouse = false; + } + else if (visibility() == QWindow::Visibility::FullScreen) + { + // Fullscreen: Show or hide the mouse depending on the settings. + show_mouse = m_show_mouse_in_fullscreen; + } + else + { + // Windowed: Hide the mouse if it was locked by the user + show_mouse = !m_mouse_hide_and_lock; + } + + // Update Cursor if necessary + if (show_mouse != m_show_mouse.exchange(show_mouse)) + { + setCursor(m_show_mouse ? Qt::ArrowCursor : Qt::BlankCursor); + } } bool gs_frame::get_mouse_lock_state() { - return m_mouse_hide_and_lock; + update_cursor(); + + return isActive() && m_mouse_hide_and_lock; } void gs_frame::close() @@ -490,30 +519,35 @@ void gs_frame::mouseDoubleClickEvent(QMouseEvent* ev) } } -void gs_frame::HandleCursor(QWindow::Visibility /*visibility*/) +void gs_frame::handle_cursor(QWindow::Visibility visibility, bool from_event, bool start_idle_timer) { - if (m_mouse_hide_and_lock) + // Update the mouse lock state if the visibility changed. + if (from_event) { - setCursor(Qt::BlankCursor); - m_mousehide_timer.stop(); + // In fullscreen we default to hiding and locking. In windowed mode we do not want the lock by default. + m_mouse_hide_and_lock = visibility == QWindow::Visibility::FullScreen; + } + + // Update the cursor visibility + update_cursor(); + + // Update the mouse hide timer + if (m_hide_mouse_after_idletime && start_idle_timer) + { + m_mousehide_timer.start(m_hide_mouse_idletime); } else { - setCursor(Qt::ArrowCursor); - - if (m_hide_mouse_after_idletime) - { - m_mousehide_timer.start(m_hide_mouse_idletime); - } + m_mousehide_timer.stop(); } } void gs_frame::MouseHideTimeout() { - // our idle timeout occured, so we blank the cursor - if (m_hide_mouse_after_idletime) + // Our idle timeout occured, so we update the cursor + if (m_hide_mouse_after_idletime && m_show_mouse.exchange(false)) { - setCursor(Qt::BlankCursor); + handle_cursor(visibility(), false, false); } } @@ -550,10 +584,10 @@ bool gs_frame::event(QEvent* ev) } close(); } - else if (ev->type() == QEvent::MouseMove) + else if (ev->type() == QEvent::MouseMove && !m_show_mouse) { - // this will make the cursor visible again if it was hidden by the mouse idle timeout - gs_frame::HandleCursor(visibility()); + // This will make the cursor visible again if it was hidden by the mouse idle timeout + handle_cursor(visibility(), false, true); } return QWindow::event(ev); } diff --git a/rpcs3/rpcs3qt/gs_frame.h b/rpcs3/rpcs3qt/gs_frame.h index f2e02c7a29..4dfff46551 100644 --- a/rpcs3/rpcs3qt/gs_frame.h +++ b/rpcs3/rpcs3qt/gs_frame.h @@ -34,6 +34,7 @@ private: u64 m_frames = 0; QString m_window_title; + std::atomic m_show_mouse = true; bool m_disable_mouse = false; bool m_disable_kb_hotkeys = false; bool m_mouse_hide_and_lock = false; @@ -55,6 +56,10 @@ public: void progress_increment(int delta); void progress_set_limit(int limit); + /* + Returns true if the mouse is locked inside the game window. + Also conveniently updates the cursor visibility, because using it from a mouse handler indicates mouse emulation. + */ bool get_mouse_lock_state(); void take_screenshot(const std::vector sshot_data, const u32 sshot_width, const u32 sshot_height, bool is_bgra) override; @@ -82,8 +87,9 @@ protected: private: void toggle_mouselock(); + void update_cursor(); + void handle_cursor(QWindow::Visibility visibility, bool from_event, bool start_idle_timer); private Q_SLOTS: - void HandleCursor(QWindow::Visibility visibility); void MouseHideTimeout(); };