Merge pull request #10121 from malleoz/game-window-cursor-always-on

DolphinQt: Add option to always show Mouse Cursor
This commit is contained in:
Léo Lam 2021-10-13 12:22:10 +02:00 committed by GitHub
commit 4541abd1c0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 107 additions and 42 deletions

View File

@ -145,7 +145,7 @@ void SConfig::SaveInterfaceSettings(IniFile& ini)
IniFile::Section* interface = ini.GetOrCreateSection("Interface"); IniFile::Section* interface = ini.GetOrCreateSection("Interface");
interface->Set("ConfirmStop", bConfirmStop); interface->Set("ConfirmStop", bConfirmStop);
interface->Set("HideCursor", bHideCursor); interface->Set("CursorVisibility", m_show_cursor);
interface->Set("LockCursor", bLockCursor); interface->Set("LockCursor", bLockCursor);
interface->Set("LanguageCode", m_InterfaceLanguage); interface->Set("LanguageCode", m_InterfaceLanguage);
interface->Set("ExtendedFPSInfo", m_InterfaceExtendedFPSInfo); interface->Set("ExtendedFPSInfo", m_InterfaceExtendedFPSInfo);
@ -399,7 +399,7 @@ void SConfig::LoadInterfaceSettings(IniFile& ini)
IniFile::Section* interface = ini.GetOrCreateSection("Interface"); IniFile::Section* interface = ini.GetOrCreateSection("Interface");
interface->Get("ConfirmStop", &bConfirmStop, true); interface->Get("ConfirmStop", &bConfirmStop, true);
interface->Get("HideCursor", &bHideCursor, false); interface->Get("CursorVisibility", &m_show_cursor, ShowCursor::OnMovement);
interface->Get("LockCursor", &bLockCursor, false); interface->Get("LockCursor", &bLockCursor, false);
interface->Get("LanguageCode", &m_InterfaceLanguage, ""); interface->Get("LanguageCode", &m_InterfaceLanguage, "");
interface->Get("ExtendedFPSInfo", &m_InterfaceExtendedFPSInfo, false); interface->Get("ExtendedFPSInfo", &m_InterfaceExtendedFPSInfo, false);

View File

@ -146,7 +146,14 @@ struct SConfig
// Interface settings // Interface settings
bool bConfirmStop = false; bool bConfirmStop = false;
bool bHideCursor = false;
enum class ShowCursor
{
Never,
Constantly,
OnMovement,
} m_show_cursor;
bool bLockCursor = false; bool bLockCursor = false;
std::string theme_name; std::string theme_name;

View File

@ -70,7 +70,7 @@ PlatformX11::~PlatformX11()
if (m_display) if (m_display)
{ {
if (SConfig::GetInstance().bHideCursor) if (SConfig::GetInstance().m_show_cursor == SConfig::ShowCursor::Never)
XFreeCursor(m_display, m_blank_cursor); XFreeCursor(m_display, m_blank_cursor);
XCloseDisplay(m_display); XCloseDisplay(m_display);
@ -115,7 +115,7 @@ bool PlatformX11::Init()
m_xrr_config = new X11Utils::XRRConfiguration(m_display, m_window); m_xrr_config = new X11Utils::XRRConfiguration(m_display, m_window);
#endif #endif
if (SConfig::GetInstance().bHideCursor) if (SConfig::GetInstance().m_show_cursor == SConfig::ShowCursor::Never)
{ {
// make a blank cursor // make a blank cursor
Pixmap Blank; Pixmap Blank;
@ -200,13 +200,13 @@ void PlatformX11::ProcessEvents()
{ {
if (Core::GetState() == Core::State::Running) if (Core::GetState() == Core::State::Running)
{ {
if (SConfig::GetInstance().bHideCursor) if (SConfig::GetInstance().m_show_cursor == SConfig::ShowCursor::Never)
XUndefineCursor(m_display, m_window); XUndefineCursor(m_display, m_window);
Core::SetState(Core::State::Paused); Core::SetState(Core::State::Paused);
} }
else else
{ {
if (SConfig::GetInstance().bHideCursor) if (SConfig::GetInstance().m_show_cursor == SConfig::ShowCursor::Never)
XDefineCursor(m_display, m_window, m_blank_cursor); XDefineCursor(m_display, m_window, m_blank_cursor);
Core::SetState(Core::State::Running); Core::SetState(Core::State::Running);
} }
@ -243,14 +243,15 @@ void PlatformX11::ProcessEvents()
case FocusIn: case FocusIn:
{ {
m_window_focus = true; m_window_focus = true;
if (SConfig::GetInstance().bHideCursor && Core::GetState() != Core::State::Paused) if (SConfig::GetInstance().m_show_cursor == SConfig::ShowCursor::Never &&
Core::GetState() != Core::State::Paused)
XDefineCursor(m_display, m_window, m_blank_cursor); XDefineCursor(m_display, m_window, m_blank_cursor);
} }
break; break;
case FocusOut: case FocusOut:
{ {
m_window_focus = false; m_window_focus = false;
if (SConfig::GetInstance().bHideCursor) if (SConfig::GetInstance().m_show_cursor == SConfig::ShowCursor::Never)
XUndefineCursor(m_display, m_window); XUndefineCursor(m_display, m_window);
} }
break; break;

View File

@ -83,7 +83,7 @@ RenderWidget::RenderWidget(QWidget* parent) : QWidget(parent)
m_mouse_timer->setSingleShot(true); m_mouse_timer->setSingleShot(true);
setMouseTracking(true); setMouseTracking(true);
connect(&Settings::Instance(), &Settings::HideCursorChanged, this, connect(&Settings::Instance(), &Settings::CursorVisibilityChanged, this,
&RenderWidget::OnHideCursorChanged); &RenderWidget::OnHideCursorChanged);
connect(&Settings::Instance(), &Settings::LockCursorChanged, this, connect(&Settings::Instance(), &Settings::LockCursorChanged, this,
&RenderWidget::OnLockCursorChanged); &RenderWidget::OnLockCursorChanged);
@ -139,6 +139,7 @@ void RenderWidget::OnHideCursorChanged()
{ {
UpdateCursor(); UpdateCursor();
} }
void RenderWidget::OnLockCursorChanged() void RenderWidget::OnLockCursorChanged()
{ {
SetCursorLocked(false); SetCursorLocked(false);
@ -155,14 +156,16 @@ void RenderWidget::UpdateCursor()
// on top of the game window in the background // on top of the game window in the background
const bool keep_on_top = (windowFlags() & Qt::WindowStaysOnTopHint) != 0; const bool keep_on_top = (windowFlags() & Qt::WindowStaysOnTopHint) != 0;
const bool should_hide = const bool should_hide =
Settings::Instance().GetHideCursor() && (Settings::Instance().GetCursorVisibility() == SConfig::ShowCursor::Never) &&
(keep_on_top || SConfig::GetInstance().m_BackgroundInput || isActiveWindow()); (keep_on_top || SConfig::GetInstance().m_BackgroundInput || isActiveWindow());
setCursor(should_hide ? Qt::BlankCursor : Qt::ArrowCursor); setCursor(should_hide ? Qt::BlankCursor : Qt::ArrowCursor);
} }
else else
{ {
setCursor((m_cursor_locked && Settings::Instance().GetHideCursor()) ? Qt::BlankCursor : setCursor((m_cursor_locked &&
Qt::ArrowCursor); Settings::Instance().GetCursorVisibility() == SConfig::ShowCursor::Never) ?
Qt::BlankCursor :
Qt::ArrowCursor);
} }
} }
@ -185,7 +188,8 @@ void RenderWidget::HandleCursorTimer()
{ {
if (!isActiveWindow()) if (!isActiveWindow())
return; return;
if (!Settings::Instance().GetLockCursor() || m_cursor_locked) if ((!Settings::Instance().GetLockCursor() || m_cursor_locked) &&
Settings::Instance().GetCursorVisibility() == SConfig::ShowCursor::OnMovement)
{ {
setCursor(Qt::BlankCursor); setCursor(Qt::BlankCursor);
} }
@ -268,7 +272,7 @@ void RenderWidget::SetCursorLocked(bool locked, bool follow_aspect_ratio)
{ {
m_cursor_locked = true; m_cursor_locked = true;
if (Settings::Instance().GetHideCursor()) if (Settings::Instance().GetCursorVisibility() != SConfig::ShowCursor::Constantly)
{ {
setCursor(Qt::BlankCursor); setCursor(Qt::BlankCursor);
} }
@ -362,16 +366,18 @@ bool RenderWidget::event(QEvent* event)
{ {
// Lock the cursor with any mouse button click (behave the same as window focus change). // Lock the cursor with any mouse button click (behave the same as window focus change).
// This event is occasionally missed because isActiveWindow is laggy // This event is occasionally missed because isActiveWindow is laggy
if (Settings::Instance().GetLockCursor() && event->type() == QEvent::MouseButtonPress) if (Settings::Instance().GetLockCursor())
{ {
SetCursorLocked(true); SetCursorLocked(true);
} }
// Unhide on movement }
if (!Settings::Instance().GetHideCursor()) break;
{ case QEvent::MouseMove:
setCursor(Qt::ArrowCursor); // Unhide on movement
m_mouse_timer->start(MOUSE_HIDE_DELAY); if (Settings::Instance().GetCursorVisibility() == SConfig::ShowCursor::OnMovement)
} {
setCursor(Qt::ArrowCursor);
m_mouse_timer->start(MOUSE_HIDE_DELAY);
} }
break; break;
case QEvent::WinIdChange: case QEvent::WinIdChange:
@ -379,7 +385,8 @@ bool RenderWidget::event(QEvent* event)
break; break;
case QEvent::Show: case QEvent::Show:
// Don't do if "stay on top" changed (or was true) // Don't do if "stay on top" changed (or was true)
if (Settings::Instance().GetLockCursor() && Settings::Instance().GetHideCursor() && if (Settings::Instance().GetLockCursor() &&
Settings::Instance().GetCursorVisibility() != SConfig::ShowCursor::Constantly &&
!m_dont_lock_cursor_on_show) !m_dont_lock_cursor_on_show)
{ {
// Auto lock when this window is shown (it was hidden) // Auto lock when this window is shown (it was hidden)

View File

@ -35,6 +35,7 @@ signals:
private: private:
void HandleCursorTimer(); void HandleCursorTimer();
void OnHideCursorChanged(); void OnHideCursorChanged();
void OnNeverHideCursorChanged();
void OnLockCursorChanged(); void OnLockCursorChanged();
void OnKeepOnTopChanged(bool top); void OnKeepOnTopChanged(bool top);
void UpdateCursor(); void UpdateCursor();

View File

@ -10,6 +10,7 @@
#include <QFile> #include <QFile>
#include <QFileInfo> #include <QFileInfo>
#include <QFontDatabase> #include <QFontDatabase>
#include <QRadioButton>
#include <QSize> #include <QSize>
#include <QWidget> #include <QWidget>
@ -325,15 +326,16 @@ void Settings::SetStateSlot(int slot)
GetQSettings().setValue(QStringLiteral("Emulation/StateSlot"), slot); GetQSettings().setValue(QStringLiteral("Emulation/StateSlot"), slot);
} }
void Settings::SetHideCursor(bool hide_cursor) void Settings::SetCursorVisibility(SConfig::ShowCursor hideCursor)
{ {
SConfig::GetInstance().bHideCursor = hide_cursor; SConfig::GetInstance().m_show_cursor = hideCursor;
emit HideCursorChanged();
emit CursorVisibilityChanged();
} }
bool Settings::GetHideCursor() const SConfig::ShowCursor Settings::GetCursorVisibility() const
{ {
return SConfig::GetInstance().bHideCursor; return SConfig::GetInstance().m_show_cursor;
} }
void Settings::SetLockCursor(bool lock_cursor) void Settings::SetLockCursor(bool lock_cursor)

View File

@ -7,8 +7,10 @@
#include <QFont> #include <QFont>
#include <QObject> #include <QObject>
#include <QRadioButton>
#include <QSettings> #include <QSettings>
#include "Core/ConfigManager.h"
#include "DiscIO/Enums.h" #include "DiscIO/Enums.h"
namespace Core namespace Core
@ -97,8 +99,8 @@ public:
void SetUSBKeyboardConnected(bool connected); void SetUSBKeyboardConnected(bool connected);
// Graphics // Graphics
void SetHideCursor(bool hide_cursor); void SetCursorVisibility(SConfig::ShowCursor hideCursor);
bool GetHideCursor() const; SConfig::ShowCursor GetCursorVisibility() const;
void SetLockCursor(bool lock_cursor); void SetLockCursor(bool lock_cursor);
bool GetLockCursor() const; bool GetLockCursor() const;
void SetKeepWindowOnTop(bool top); void SetKeepWindowOnTop(bool top);
@ -168,7 +170,7 @@ signals:
void MetadataRefreshRequested(); void MetadataRefreshRequested();
void MetadataRefreshCompleted(); void MetadataRefreshCompleted();
void AutoRefreshToggled(bool enabled); void AutoRefreshToggled(bool enabled);
void HideCursorChanged(); void CursorVisibilityChanged();
void LockCursorChanged(); void LockCursorChanged();
void KeepWindowOnTopChanged(bool top); void KeepWindowOnTopChanged(bool top);
void VolumeChanged(int volume); void VolumeChanged(int volume);

View File

@ -9,6 +9,7 @@
#include <QFormLayout> #include <QFormLayout>
#include <QGroupBox> #include <QGroupBox>
#include <QLabel> #include <QLabel>
#include <QRadioButton>
#include <QVBoxLayout> #include <QVBoxLayout>
#include <QWidget> #include <QWidget>
@ -169,23 +170,36 @@ void InterfacePane::CreateInGame()
m_checkbox_enable_osd = new QCheckBox(tr("Show On-Screen Display Messages")); m_checkbox_enable_osd = new QCheckBox(tr("Show On-Screen Display Messages"));
m_checkbox_show_active_title = new QCheckBox(tr("Show Active Title in Window Title")); m_checkbox_show_active_title = new QCheckBox(tr("Show Active Title in Window Title"));
m_checkbox_pause_on_focus_lost = new QCheckBox(tr("Pause on Focus Loss")); m_checkbox_pause_on_focus_lost = new QCheckBox(tr("Pause on Focus Loss"));
m_checkbox_hide_mouse = new QCheckBox(tr("Always Hide Mouse Cursor"));
m_checkbox_lock_mouse = new QCheckBox(tr("Lock Mouse Cursor"));
m_checkbox_hide_mouse->setToolTip( auto* mouse_groupbox = new QGroupBox(tr("Mouse Cursor Visibility"));
tr("Will immediately hide the Mouse Cursor when it hovers on top of the Render Widget, " auto* m_vboxlayout_hide_mouse = new QVBoxLayout;
"otherwise " mouse_groupbox->setLayout(m_vboxlayout_hide_mouse);
"there is a delay.\nIf \"Lock Mouse Cursor\" is enabled, it will hide on Mouse locked"));
m_radio_cursor_visible_movement = new QRadioButton(tr("On Movement"));
m_radio_cursor_visible_movement->setToolTip(
tr("Mouse Cursor hides after inactivity and returns upon Mouse Cursor movement."));
m_radio_cursor_visible_never = new QRadioButton(tr("Never"));
m_radio_cursor_visible_never->setToolTip(
tr("Mouse Cursor will never be visible while a game is running."));
m_radio_cursor_visible_always = new QRadioButton(tr("Always"));
m_radio_cursor_visible_always->setToolTip(tr("Mouse Cursor will always be visible."));
m_vboxlayout_hide_mouse->addWidget(m_radio_cursor_visible_movement);
m_vboxlayout_hide_mouse->addWidget(m_radio_cursor_visible_never);
m_vboxlayout_hide_mouse->addWidget(m_radio_cursor_visible_always);
m_checkbox_lock_mouse = new QCheckBox(tr("Lock Mouse Cursor"));
m_checkbox_lock_mouse->setToolTip(tr("Will lock the Mouse Cursor to the Render Widget as long as " m_checkbox_lock_mouse->setToolTip(tr("Will lock the Mouse Cursor to the Render Widget as long as "
"it has focus. You can set a hotkey to unlock it.")); "it has focus. You can set a hotkey to unlock it."));
mouse_groupbox->setLayout(m_vboxlayout_hide_mouse);
groupbox_layout->addWidget(m_checkbox_top_window); groupbox_layout->addWidget(m_checkbox_top_window);
groupbox_layout->addWidget(m_checkbox_confirm_on_stop); groupbox_layout->addWidget(m_checkbox_confirm_on_stop);
groupbox_layout->addWidget(m_checkbox_use_panic_handlers); groupbox_layout->addWidget(m_checkbox_use_panic_handlers);
groupbox_layout->addWidget(m_checkbox_enable_osd); groupbox_layout->addWidget(m_checkbox_enable_osd);
groupbox_layout->addWidget(m_checkbox_show_active_title); groupbox_layout->addWidget(m_checkbox_show_active_title);
groupbox_layout->addWidget(m_checkbox_pause_on_focus_lost); groupbox_layout->addWidget(m_checkbox_pause_on_focus_lost);
groupbox_layout->addWidget(m_checkbox_hide_mouse); groupbox_layout->addWidget(mouse_groupbox);
#ifdef _WIN32 #ifdef _WIN32
groupbox_layout->addWidget(m_checkbox_lock_mouse); groupbox_layout->addWidget(m_checkbox_lock_mouse);
#endif #endif
@ -211,8 +225,12 @@ void InterfacePane::ConnectLayout()
connect(m_checkbox_show_active_title, &QCheckBox::toggled, this, &InterfacePane::OnSaveConfig); connect(m_checkbox_show_active_title, &QCheckBox::toggled, this, &InterfacePane::OnSaveConfig);
connect(m_checkbox_enable_osd, &QCheckBox::toggled, this, &InterfacePane::OnSaveConfig); connect(m_checkbox_enable_osd, &QCheckBox::toggled, this, &InterfacePane::OnSaveConfig);
connect(m_checkbox_pause_on_focus_lost, &QCheckBox::toggled, this, &InterfacePane::OnSaveConfig); connect(m_checkbox_pause_on_focus_lost, &QCheckBox::toggled, this, &InterfacePane::OnSaveConfig);
connect(m_checkbox_hide_mouse, &QCheckBox::toggled, &Settings::Instance(), connect(m_radio_cursor_visible_movement, &QRadioButton::toggled, this,
&Settings::SetHideCursor); &InterfacePane::OnCursorVisibleMovement);
connect(m_radio_cursor_visible_never, &QRadioButton::toggled, this,
&InterfacePane::OnCursorVisibleNever);
connect(m_radio_cursor_visible_always, &QRadioButton::toggled, this,
&InterfacePane::OnCursorVisibleAlways);
connect(m_checkbox_lock_mouse, &QCheckBox::toggled, &Settings::Instance(), connect(m_checkbox_lock_mouse, &QCheckBox::toggled, &Settings::Instance(),
&Settings::SetLockCursor); &Settings::SetLockCursor);
connect(m_checkbox_use_userstyle, &QCheckBox::toggled, this, &InterfacePane::OnSaveConfig); connect(m_checkbox_use_userstyle, &QCheckBox::toggled, this, &InterfacePane::OnSaveConfig);
@ -250,7 +268,13 @@ void InterfacePane::LoadConfig()
m_checkbox_pause_on_focus_lost->setChecked(startup_params.m_PauseOnFocusLost); m_checkbox_pause_on_focus_lost->setChecked(startup_params.m_PauseOnFocusLost);
m_checkbox_use_covers->setChecked(Config::Get(Config::MAIN_USE_GAME_COVERS)); m_checkbox_use_covers->setChecked(Config::Get(Config::MAIN_USE_GAME_COVERS));
m_checkbox_focused_hotkeys->setChecked(Config::Get(Config::MAIN_FOCUSED_HOTKEYS)); m_checkbox_focused_hotkeys->setChecked(Config::Get(Config::MAIN_FOCUSED_HOTKEYS));
m_checkbox_hide_mouse->setChecked(Settings::Instance().GetHideCursor()); m_radio_cursor_visible_movement->setChecked(Settings::Instance().GetCursorVisibility() ==
SConfig::ShowCursor::OnMovement);
m_radio_cursor_visible_always->setChecked(Settings::Instance().GetCursorVisibility() ==
SConfig::ShowCursor::Constantly);
m_radio_cursor_visible_never->setChecked(Settings::Instance().GetCursorVisibility() ==
SConfig::ShowCursor::Never);
m_checkbox_lock_mouse->setChecked(Settings::Instance().GetLockCursor()); m_checkbox_lock_mouse->setChecked(Settings::Instance().GetLockCursor());
m_checkbox_disable_screensaver->setChecked(Config::Get(Config::MAIN_DISABLE_SCREENSAVER)); m_checkbox_disable_screensaver->setChecked(Config::Get(Config::MAIN_DISABLE_SCREENSAVER));
} }
@ -300,3 +324,18 @@ void InterfacePane::OnSaveConfig()
settings.SaveSettings(); settings.SaveSettings();
} }
void InterfacePane::OnCursorVisibleMovement()
{
Settings::Instance().SetCursorVisibility(SConfig::ShowCursor::OnMovement);
}
void InterfacePane::OnCursorVisibleNever()
{
Settings::Instance().SetCursorVisibility(SConfig::ShowCursor::Never);
}
void InterfacePane::OnCursorVisibleAlways()
{
Settings::Instance().SetCursorVisibility(SConfig::ShowCursor::Constantly);
}

View File

@ -8,6 +8,7 @@
class QCheckBox; class QCheckBox;
class QComboBox; class QComboBox;
class QLabel; class QLabel;
class QRadioButton;
class QVBoxLayout; class QVBoxLayout;
class InterfacePane final : public QWidget class InterfacePane final : public QWidget
@ -23,6 +24,9 @@ private:
void ConnectLayout(); void ConnectLayout();
void LoadConfig(); void LoadConfig();
void OnSaveConfig(); void OnSaveConfig();
void OnCursorVisibleMovement();
void OnCursorVisibleNever();
void OnCursorVisibleAlways();
QVBoxLayout* m_main_layout; QVBoxLayout* m_main_layout;
QComboBox* m_combobox_language; QComboBox* m_combobox_language;
@ -43,6 +47,8 @@ private:
QCheckBox* m_checkbox_enable_osd; QCheckBox* m_checkbox_enable_osd;
QCheckBox* m_checkbox_show_active_title; QCheckBox* m_checkbox_show_active_title;
QCheckBox* m_checkbox_pause_on_focus_lost; QCheckBox* m_checkbox_pause_on_focus_lost;
QCheckBox* m_checkbox_hide_mouse; QRadioButton* m_radio_cursor_visible_movement;
QRadioButton* m_radio_cursor_visible_never;
QRadioButton* m_radio_cursor_visible_always;
QCheckBox* m_checkbox_lock_mouse; QCheckBox* m_checkbox_lock_mouse;
}; };