diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp
index 1cac2f942f..3d759f77b2 100644
--- a/src/yuzu/bootmanager.cpp
+++ b/src/yuzu/bootmanager.cpp
@@ -292,6 +292,8 @@ GRenderWindow::GRenderWindow(GMainWindow* parent_, EmuThread* emu_thread_)
setLayout(layout);
InputCommon::Init();
+ this->setMouseTracking(true);
+
connect(this, &GRenderWindow::FirstFrameDisplayed, parent_, &GMainWindow::OnLoadComplete);
}
@@ -385,6 +387,7 @@ void GRenderWindow::mousePressEvent(QMouseEvent* event) {
} else if (event->button() == Qt::RightButton) {
InputCommon::GetMotionEmu()->BeginTilt(pos.x(), pos.y());
}
+ QWidget::mousePressEvent(event);
}
void GRenderWindow::mouseMoveEvent(QMouseEvent* event) {
@@ -397,6 +400,7 @@ void GRenderWindow::mouseMoveEvent(QMouseEvent* event) {
const auto [x, y] = ScaleTouch(pos);
this->TouchMoved(x, y);
InputCommon::GetMotionEmu()->Tilt(pos.x(), pos.y());
+ QWidget::mouseMoveEvent(event);
}
void GRenderWindow::mouseReleaseEvent(QMouseEvent* event) {
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp
index 3b9ab38dd3..946aa287ab 100644
--- a/src/yuzu/configuration/config.cpp
+++ b/src/yuzu/configuration/config.cpp
@@ -740,6 +740,8 @@ void Config::ReadUIValues() {
UISettings::values.profile_index = ReadSetting(QStringLiteral("profileIndex"), 0).toUInt();
UISettings::values.pause_when_in_background =
ReadSetting(QStringLiteral("pauseWhenInBackground"), false).toBool();
+ UISettings::values.hide_mouse =
+ ReadSetting(QStringLiteral("hideInactiveMouse"), false).toBool();
ApplyDefaultProfileIfInputInvalid();
@@ -1164,6 +1166,7 @@ void Config::SaveUIValues() {
WriteSetting(QStringLiteral("profileIndex"), UISettings::values.profile_index, 0);
WriteSetting(QStringLiteral("pauseWhenInBackground"),
UISettings::values.pause_when_in_background, false);
+ WriteSetting(QStringLiteral("hideInactiveMouse"), UISettings::values.hide_mouse, false);
qt_config->endGroup();
}
diff --git a/src/yuzu/configuration/configure_general.cpp b/src/yuzu/configuration/configure_general.cpp
index 5ef9271145..cb95423e09 100644
--- a/src/yuzu/configuration/configure_general.cpp
+++ b/src/yuzu/configuration/configure_general.cpp
@@ -26,6 +26,7 @@ void ConfigureGeneral::SetConfiguration() {
ui->toggle_check_exit->setChecked(UISettings::values.confirm_before_closing);
ui->toggle_user_on_boot->setChecked(UISettings::values.select_user_on_boot);
ui->toggle_background_pause->setChecked(UISettings::values.pause_when_in_background);
+ ui->toggle_hide_mouse->setChecked(UISettings::values.hide_mouse);
ui->toggle_frame_limit->setChecked(Settings::values.use_frame_limit);
ui->frame_limit->setEnabled(ui->toggle_frame_limit->isChecked());
@@ -36,6 +37,7 @@ void ConfigureGeneral::ApplyConfiguration() {
UISettings::values.confirm_before_closing = ui->toggle_check_exit->isChecked();
UISettings::values.select_user_on_boot = ui->toggle_user_on_boot->isChecked();
UISettings::values.pause_when_in_background = ui->toggle_background_pause->isChecked();
+ UISettings::values.hide_mouse = ui->toggle_hide_mouse->isChecked();
Settings::values.use_frame_limit = ui->toggle_frame_limit->isChecked();
Settings::values.frame_limit = ui->frame_limit->value();
diff --git a/src/yuzu/configuration/configure_general.ui b/src/yuzu/configuration/configure_general.ui
index 857119bb3b..fc3b7e65a5 100644
--- a/src/yuzu/configuration/configure_general.ui
+++ b/src/yuzu/configuration/configure_general.ui
@@ -72,6 +72,13 @@
+ -
+
+
+ Hide mouse on inactivity
+
+
+
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 05baec7e13..1e76f789c5 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -135,6 +135,8 @@ __declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1;
}
#endif
+constexpr int default_mouse_timeout = 2500;
+
constexpr u64 DLC_BASE_TITLE_ID_MASK = 0xFFFFFFFFFFFFE000;
/**
@@ -236,6 +238,14 @@ GMainWindow::GMainWindow()
// Show one-time "callout" messages to the user
ShowTelemetryCallout();
+ // make sure menubar has the arrow cursor instead of inheriting from this
+ ui.menubar->setCursor(QCursor());
+ statusBar()->setCursor(QCursor());
+
+ mouse_hide_timer.setInterval(default_mouse_timeout);
+ connect(&mouse_hide_timer, &QTimer::timeout, this, &GMainWindow::HideMouseCursor);
+ connect(ui.menubar, &QMenuBar::hovered, this, &GMainWindow::ShowMouseCursor);
+
QStringList args = QApplication::arguments();
if (args.length() >= 2) {
BootGame(args[1]);
@@ -1012,6 +1022,13 @@ void GMainWindow::BootGame(const QString& filename) {
async_status_button->setDisabled(true);
renderer_status_button->setDisabled(true);
+ if (UISettings::values.hide_mouse) {
+ mouse_hide_timer.start();
+ setMouseTracking(true);
+ ui.centralwidget->setMouseTracking(true);
+ ui.menubar->setMouseTracking(true);
+ }
+
const u64 title_id = Core::System::GetInstance().CurrentProcess()->GetTitleID();
std::string title_name;
@@ -1080,6 +1097,10 @@ void GMainWindow::ShutdownGame() {
game_list->show();
game_list->setFilterFocus();
+ setMouseTracking(false);
+ ui.centralwidget->setMouseTracking(false);
+ ui.menubar->setMouseTracking(false);
+
UpdateWindowTitle();
// Disable status bar updates
@@ -1835,6 +1856,17 @@ void GMainWindow::OnConfigure() {
config->Save();
+ if (UISettings::values.hide_mouse && emulation_running) {
+ setMouseTracking(true);
+ ui.centralwidget->setMouseTracking(true);
+ ui.menubar->setMouseTracking(true);
+ mouse_hide_timer.start();
+ } else {
+ setMouseTracking(false);
+ ui.centralwidget->setMouseTracking(false);
+ ui.menubar->setMouseTracking(false);
+ }
+
dock_status_button->setChecked(Settings::values.use_docked_mode);
async_status_button->setChecked(Settings::values.use_asynchronous_gpu_emulation);
#ifdef HAS_VULKAN
@@ -1968,6 +2000,30 @@ void GMainWindow::UpdateStatusBar() {
emu_frametime_label->setVisible(true);
}
+void GMainWindow::HideMouseCursor() {
+ if (emu_thread == nullptr || UISettings::values.hide_mouse == false) {
+ mouse_hide_timer.stop();
+ ShowMouseCursor();
+ return;
+ }
+ setCursor(QCursor(Qt::BlankCursor));
+}
+
+void GMainWindow::ShowMouseCursor() {
+ unsetCursor();
+ if (emu_thread != nullptr && UISettings::values.hide_mouse) {
+ mouse_hide_timer.start();
+ }
+}
+
+void GMainWindow::mouseMoveEvent(QMouseEvent* event) {
+ ShowMouseCursor();
+}
+
+void GMainWindow::mousePressEvent(QMouseEvent* event) {
+ ShowMouseCursor();
+}
+
void GMainWindow::OnCoreError(Core::System::ResultStatus result, std::string details) {
QMessageBox::StandardButton answer;
QString status_message;
diff --git a/src/yuzu/main.h b/src/yuzu/main.h
index 0b750689de..60b17c54a7 100644
--- a/src/yuzu/main.h
+++ b/src/yuzu/main.h
@@ -216,6 +216,8 @@ private:
std::optional SelectRomFSDumpTarget(const FileSys::ContentProvider&, u64 program_id);
void UpdateWindowTitle(const QString& title_name = {});
void UpdateStatusBar();
+ void HideMouseCursor();
+ void ShowMouseCursor();
Ui::MainWindow ui;
@@ -244,6 +246,7 @@ private:
QString game_path;
bool auto_paused = false;
+ QTimer mouse_hide_timer;
// FS
std::shared_ptr vfs;
@@ -265,4 +268,6 @@ protected:
void dropEvent(QDropEvent* event) override;
void dragEnterEvent(QDragEnterEvent* event) override;
void dragMoveEvent(QDragMoveEvent* event) override;
+ void mouseMoveEvent(QMouseEvent* event) override;
+ void mousePressEvent(QMouseEvent* event) override;
};
diff --git a/src/yuzu/uisettings.h b/src/yuzu/uisettings.h
index a675ecf4d7..830932d459 100644
--- a/src/yuzu/uisettings.h
+++ b/src/yuzu/uisettings.h
@@ -59,6 +59,7 @@ struct Values {
bool confirm_before_closing;
bool first_start;
bool pause_when_in_background;
+ bool hide_mouse;
bool select_user_on_boot;