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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -9,6 +9,7 @@
#include <QFormLayout>
#include <QGroupBox>
#include <QLabel>
#include <QRadioButton>
#include <QVBoxLayout>
#include <QWidget>
@ -169,23 +170,36 @@ void InterfacePane::CreateInGame()
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_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(
tr("Will immediately hide the Mouse Cursor when it hovers on top of the Render Widget, "
"otherwise "
"there is a delay.\nIf \"Lock Mouse Cursor\" is enabled, it will hide on Mouse locked"));
auto* mouse_groupbox = new QGroupBox(tr("Mouse Cursor Visibility"));
auto* m_vboxlayout_hide_mouse = new QVBoxLayout;
mouse_groupbox->setLayout(m_vboxlayout_hide_mouse);
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 "
"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_confirm_on_stop);
groupbox_layout->addWidget(m_checkbox_use_panic_handlers);
groupbox_layout->addWidget(m_checkbox_enable_osd);
groupbox_layout->addWidget(m_checkbox_show_active_title);
groupbox_layout->addWidget(m_checkbox_pause_on_focus_lost);
groupbox_layout->addWidget(m_checkbox_hide_mouse);
groupbox_layout->addWidget(mouse_groupbox);
#ifdef _WIN32
groupbox_layout->addWidget(m_checkbox_lock_mouse);
#endif
@ -211,8 +225,12 @@ void InterfacePane::ConnectLayout()
connect(m_checkbox_show_active_title, &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_hide_mouse, &QCheckBox::toggled, &Settings::Instance(),
&Settings::SetHideCursor);
connect(m_radio_cursor_visible_movement, &QRadioButton::toggled, this,
&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(),
&Settings::SetLockCursor);
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_use_covers->setChecked(Config::Get(Config::MAIN_USE_GAME_COVERS));
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_disable_screensaver->setChecked(Config::Get(Config::MAIN_DISABLE_SCREENSAVER));
}
@ -300,3 +324,18 @@ void InterfacePane::OnSaveConfig()
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 QComboBox;
class QLabel;
class QRadioButton;
class QVBoxLayout;
class InterfacePane final : public QWidget
@ -23,6 +24,9 @@ private:
void ConnectLayout();
void LoadConfig();
void OnSaveConfig();
void OnCursorVisibleMovement();
void OnCursorVisibleNever();
void OnCursorVisibleAlways();
QVBoxLayout* m_main_layout;
QComboBox* m_combobox_language;
@ -43,6 +47,8 @@ private:
QCheckBox* m_checkbox_enable_osd;
QCheckBox* m_checkbox_show_active_title;
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;
};