early-access version 3992
This commit is contained in:
@@ -30,7 +30,6 @@
|
||||
#include <QSize>
|
||||
#include <QStringLiteral>
|
||||
#include <QSurfaceFormat>
|
||||
#include <QTimer>
|
||||
#include <QWindow>
|
||||
#include <QtCore/qobjectdefs.h>
|
||||
|
||||
@@ -66,6 +65,8 @@ class QObject;
|
||||
class QPaintEngine;
|
||||
class QSurface;
|
||||
|
||||
constexpr int default_mouse_constrain_timeout = 10;
|
||||
|
||||
EmuThread::EmuThread(Core::System& system) : m_system{system} {}
|
||||
|
||||
EmuThread::~EmuThread() = default;
|
||||
@@ -304,6 +305,9 @@ GRenderWindow::GRenderWindow(GMainWindow* parent, EmuThread* emu_thread_,
|
||||
Qt::QueuedConnection);
|
||||
connect(this, &GRenderWindow::ExitSignal, parent, &GMainWindow::OnExit, Qt::QueuedConnection);
|
||||
connect(this, &GRenderWindow::TasPlaybackStateChanged, parent, &GMainWindow::OnTasStateChanged);
|
||||
|
||||
mouse_constrain_timer.setInterval(default_mouse_constrain_timeout);
|
||||
connect(&mouse_constrain_timer, &QTimer::timeout, this, &GRenderWindow::ConstrainMouse);
|
||||
}
|
||||
|
||||
void GRenderWindow::ExecuteProgram(std::size_t program_index) {
|
||||
@@ -393,6 +397,22 @@ void GRenderWindow::closeEvent(QCloseEvent* event) {
|
||||
QWidget::closeEvent(event);
|
||||
}
|
||||
|
||||
void GRenderWindow::leaveEvent(QEvent* event) {
|
||||
if (Settings::values.mouse_panning) {
|
||||
const QRect& rect = QWidget::geometry();
|
||||
QPoint position = QCursor::pos();
|
||||
|
||||
qint32 x = qBound(rect.left(), position.x(), rect.right());
|
||||
qint32 y = qBound(rect.top(), position.y(), rect.bottom());
|
||||
// Only start the timer if the mouse has left the window bound.
|
||||
// The leave event is also triggered when the window looses focus.
|
||||
if (x != position.x() || y != position.y()) {
|
||||
mouse_constrain_timer.start();
|
||||
}
|
||||
event->accept();
|
||||
}
|
||||
}
|
||||
|
||||
int GRenderWindow::QtKeyToSwitchKey(Qt::Key qt_key) {
|
||||
static constexpr std::array<std::pair<Qt::Key, Settings::NativeKeyboard::Keys>, 106> key_map = {
|
||||
std::pair<Qt::Key, Settings::NativeKeyboard::Keys>{Qt::Key_A, Settings::NativeKeyboard::A},
|
||||
@@ -658,10 +678,19 @@ void GRenderWindow::mouseMoveEvent(QMouseEvent* event) {
|
||||
input_subsystem->GetMouse()->TouchMove(touch_x, touch_y);
|
||||
input_subsystem->GetMouse()->Move(pos.x(), pos.y(), center_x, center_y);
|
||||
|
||||
// Center mouse for mouse panning
|
||||
if (Settings::values.mouse_panning && !Settings::values.mouse_enabled) {
|
||||
QCursor::setPos(mapToGlobal(QPoint{center_x, center_y}));
|
||||
}
|
||||
|
||||
// Constrain mouse for mouse emulation with mouse panning
|
||||
if (Settings::values.mouse_panning && Settings::values.mouse_enabled) {
|
||||
const auto [clamped_mouse_x, clamped_mouse_y] = ClipToTouchScreen(x, y);
|
||||
QCursor::setPos(mapToGlobal(
|
||||
QPoint{static_cast<int>(clamped_mouse_x), static_cast<int>(clamped_mouse_y)}));
|
||||
}
|
||||
|
||||
mouse_constrain_timer.stop();
|
||||
emit MouseActivity();
|
||||
}
|
||||
|
||||
@@ -675,6 +704,31 @@ void GRenderWindow::mouseReleaseEvent(QMouseEvent* event) {
|
||||
input_subsystem->GetMouse()->ReleaseButton(button);
|
||||
}
|
||||
|
||||
void GRenderWindow::ConstrainMouse() {
|
||||
if (emu_thread == nullptr || !Settings::values.mouse_panning) {
|
||||
mouse_constrain_timer.stop();
|
||||
return;
|
||||
}
|
||||
if (!this->isActiveWindow()) {
|
||||
mouse_constrain_timer.stop();
|
||||
return;
|
||||
}
|
||||
|
||||
if (Settings::values.mouse_enabled) {
|
||||
const auto pos = mapFromGlobal(QCursor::pos());
|
||||
const int new_pos_x = std::clamp(pos.x(), 0, width());
|
||||
const int new_pos_y = std::clamp(pos.y(), 0, height());
|
||||
|
||||
QCursor::setPos(mapToGlobal(QPoint{new_pos_x, new_pos_y}));
|
||||
return;
|
||||
}
|
||||
|
||||
const int center_x = width() / 2;
|
||||
const int center_y = height() / 2;
|
||||
|
||||
QCursor::setPos(mapToGlobal(QPoint{center_x, center_y}));
|
||||
}
|
||||
|
||||
void GRenderWindow::wheelEvent(QWheelEvent* event) {
|
||||
const int x = event->angleDelta().x();
|
||||
const int y = event->angleDelta().y();
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
#include <QThread>
|
||||
#include <QTimer>
|
||||
#include <QWidget>
|
||||
#include <qglobal.h>
|
||||
#include <qnamespace.h>
|
||||
@@ -38,7 +39,6 @@ class QMouseEvent;
|
||||
class QObject;
|
||||
class QResizeEvent;
|
||||
class QShowEvent;
|
||||
class QTimer;
|
||||
class QTouchEvent;
|
||||
class QWheelEvent;
|
||||
|
||||
@@ -166,6 +166,7 @@ public:
|
||||
std::pair<u32, u32> ScaleTouch(const QPointF& pos) const;
|
||||
|
||||
void closeEvent(QCloseEvent* event) override;
|
||||
void leaveEvent(QEvent* event) override;
|
||||
|
||||
void resizeEvent(QResizeEvent* event) override;
|
||||
|
||||
@@ -229,6 +230,7 @@ private:
|
||||
void TouchBeginEvent(const QTouchEvent* event);
|
||||
void TouchUpdateEvent(const QTouchEvent* event);
|
||||
void TouchEndEvent();
|
||||
void ConstrainMouse();
|
||||
|
||||
void RequestCameraCapture();
|
||||
void OnCameraCapture(int requestId, const QImage& img);
|
||||
@@ -268,6 +270,8 @@ private:
|
||||
std::unique_ptr<QTimer> camera_timer;
|
||||
#endif
|
||||
|
||||
QTimer mouse_constrain_timer;
|
||||
|
||||
Core::System& system;
|
||||
|
||||
protected:
|
||||
|
||||
+37
-46
@@ -47,6 +47,7 @@
|
||||
#include "core/hle/service/am/applet_ae.h"
|
||||
#include "core/hle/service/am/applet_oe.h"
|
||||
#include "core/hle/service/am/applets/applets.h"
|
||||
#include "core/hle/service/set/set_sys.h"
|
||||
#include "yuzu/multiplayer/state.h"
|
||||
#include "yuzu/util/controller_navigation.h"
|
||||
|
||||
@@ -186,7 +187,6 @@ __declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1;
|
||||
#endif
|
||||
|
||||
constexpr int default_mouse_hide_timeout = 2500;
|
||||
constexpr int default_mouse_center_timeout = 10;
|
||||
constexpr int default_input_update_timeout = 1;
|
||||
|
||||
constexpr size_t CopyBufferSize = 1_MiB;
|
||||
@@ -436,9 +436,6 @@ GMainWindow::GMainWindow(std::unique_ptr<QtConfig> config_, bool has_broken_vulk
|
||||
connect(&mouse_hide_timer, &QTimer::timeout, this, &GMainWindow::HideMouseCursor);
|
||||
connect(ui->menubar, &QMenuBar::hovered, this, &GMainWindow::ShowMouseCursor);
|
||||
|
||||
mouse_center_timer.setInterval(default_mouse_center_timeout);
|
||||
connect(&mouse_center_timer, &QTimer::timeout, this, &GMainWindow::CenterMouseCursor);
|
||||
|
||||
update_input_timer.setInterval(default_input_update_timeout);
|
||||
connect(&update_input_timer, &QTimer::timeout, this, &GMainWindow::UpdateInputDrivers);
|
||||
update_input_timer.start();
|
||||
@@ -1048,7 +1045,12 @@ void GMainWindow::InitializeWidgets() {
|
||||
statusBar()->addPermanentWidget(label);
|
||||
}
|
||||
|
||||
// TODO (flTobi): Add the widget when multiplayer is fully implemented
|
||||
firmware_label = new QLabel();
|
||||
firmware_label->setObjectName(QStringLiteral("FirmwareLabel"));
|
||||
firmware_label->setVisible(false);
|
||||
firmware_label->setFocusPolicy(Qt::NoFocus);
|
||||
statusBar()->addPermanentWidget(firmware_label);
|
||||
|
||||
statusBar()->addPermanentWidget(multiplayer_state->GetStatusText(), 0);
|
||||
statusBar()->addPermanentWidget(multiplayer_state->GetStatusIcon(), 0);
|
||||
|
||||
@@ -1370,14 +1372,6 @@ void GMainWindow::InitializeHotkeys() {
|
||||
}
|
||||
});
|
||||
connect_shortcut(QStringLiteral("Toggle Mouse Panning"), [&] {
|
||||
if (Settings::values.mouse_enabled) {
|
||||
Settings::values.mouse_panning = false;
|
||||
QMessageBox::warning(
|
||||
this, tr("Emulated mouse is enabled"),
|
||||
tr("Real mouse input and mouse panning are incompatible. Please disable the "
|
||||
"emulated mouse in input advanced settings to allow mouse panning."));
|
||||
return;
|
||||
}
|
||||
Settings::values.mouse_panning = !Settings::values.mouse_panning;
|
||||
if (Settings::values.mouse_panning) {
|
||||
render_window->installEventFilter(render_window);
|
||||
@@ -2165,6 +2159,10 @@ void GMainWindow::OnEmulationStopped() {
|
||||
emu_frametime_label->setVisible(false);
|
||||
renderer_status_button->setEnabled(!UISettings::values.has_broken_vulkan);
|
||||
|
||||
if (!firmware_label->text().isEmpty()) {
|
||||
firmware_label->setVisible(true);
|
||||
}
|
||||
|
||||
current_game_path.clear();
|
||||
|
||||
// When closing the game, destroy the GLWindow to clear the context after the game is closed
|
||||
@@ -4591,6 +4589,7 @@ void GMainWindow::UpdateStatusBar() {
|
||||
emu_speed_label->setVisible(!Settings::values.use_multi_core.GetValue());
|
||||
game_fps_label->setVisible(true);
|
||||
emu_frametime_label->setVisible(true);
|
||||
firmware_label->setVisible(false);
|
||||
}
|
||||
|
||||
void GMainWindow::UpdateGPUAccuracyButton() {
|
||||
@@ -4700,26 +4699,10 @@ void GMainWindow::ShowMouseCursor() {
|
||||
}
|
||||
}
|
||||
|
||||
void GMainWindow::CenterMouseCursor() {
|
||||
if (emu_thread == nullptr || !Settings::values.mouse_panning) {
|
||||
mouse_center_timer.stop();
|
||||
return;
|
||||
}
|
||||
if (!this->isActiveWindow()) {
|
||||
mouse_center_timer.stop();
|
||||
return;
|
||||
}
|
||||
const int center_x = render_window->width() / 2;
|
||||
const int center_y = render_window->height() / 2;
|
||||
|
||||
QCursor::setPos(mapToGlobal(QPoint{center_x, center_y}));
|
||||
}
|
||||
|
||||
void GMainWindow::OnMouseActivity() {
|
||||
if (!Settings::values.mouse_panning) {
|
||||
ShowMouseCursor();
|
||||
}
|
||||
mouse_center_timer.stop();
|
||||
}
|
||||
|
||||
void GMainWindow::OnReinitializeKeys(ReinitializeKeyBehavior behavior) {
|
||||
@@ -4810,6 +4793,8 @@ void GMainWindow::OnReinitializeKeys(ReinitializeKeyBehavior behavior) {
|
||||
"games."));
|
||||
}
|
||||
|
||||
SetFirmwareVersion();
|
||||
|
||||
if (behavior == ReinitializeKeyBehavior::Warning) {
|
||||
game_list->PopulateAsync(UISettings::values.game_dirs);
|
||||
}
|
||||
@@ -4837,7 +4822,7 @@ bool GMainWindow::CheckSystemArchiveDecryption() {
|
||||
}
|
||||
|
||||
bool GMainWindow::CheckFirmwarePresence() {
|
||||
constexpr u64 MiiEditId = 0x0100000000001009ull;
|
||||
constexpr u64 MiiEditId = static_cast<u64>(Service::AM::Applets::AppletProgramId::MiiEdit);
|
||||
|
||||
auto bis_system = system->GetFileSystemController().GetSystemNANDContents();
|
||||
if (!bis_system) {
|
||||
@@ -4852,6 +4837,28 @@ bool GMainWindow::CheckFirmwarePresence() {
|
||||
return true;
|
||||
}
|
||||
|
||||
void GMainWindow::SetFirmwareVersion() {
|
||||
Service::Set::FirmwareVersionFormat firmware_data{};
|
||||
const auto result = Service::Set::GetFirmwareVersionImpl(
|
||||
firmware_data, *system, Service::Set::GetFirmwareVersionType::Version2);
|
||||
|
||||
if (result.IsError() || !CheckFirmwarePresence()) {
|
||||
LOG_INFO(Frontend, "Installed firmware: No firmware available");
|
||||
firmware_label->setVisible(false);
|
||||
return;
|
||||
}
|
||||
|
||||
firmware_label->setVisible(true);
|
||||
|
||||
const std::string display_version(firmware_data.display_version.data());
|
||||
const std::string display_title(firmware_data.display_title.data());
|
||||
|
||||
LOG_INFO(Frontend, "Installed firmware: {}", display_title);
|
||||
|
||||
firmware_label->setText(QString::fromStdString(display_version));
|
||||
firmware_label->setToolTip(QString::fromStdString(display_title));
|
||||
}
|
||||
|
||||
bool GMainWindow::SelectRomFSDumpTarget(const FileSys::ContentProvider& installed, u64 program_id,
|
||||
u64* selected_title_id, u8* selected_content_record_type) {
|
||||
using ContentInfo = std::tuple<u64, FileSys::TitleType, FileSys::ContentRecordType>;
|
||||
@@ -4996,22 +5003,6 @@ void GMainWindow::dragMoveEvent(QDragMoveEvent* event) {
|
||||
AcceptDropEvent(event);
|
||||
}
|
||||
|
||||
void GMainWindow::leaveEvent(QEvent* event) {
|
||||
if (Settings::values.mouse_panning) {
|
||||
const QRect& rect = geometry();
|
||||
QPoint position = QCursor::pos();
|
||||
|
||||
qint32 x = qBound(rect.left(), position.x(), rect.right());
|
||||
qint32 y = qBound(rect.top(), position.y(), rect.bottom());
|
||||
// Only start the timer if the mouse has left the window bound.
|
||||
// The leave event is also triggered when the window looses focus.
|
||||
if (x != position.x() || y != position.y()) {
|
||||
mouse_center_timer.start();
|
||||
}
|
||||
event->accept();
|
||||
}
|
||||
}
|
||||
|
||||
bool GMainWindow::ConfirmChangeGame() {
|
||||
if (emu_thread == nullptr)
|
||||
return true;
|
||||
|
||||
+2
-3
@@ -451,13 +451,13 @@ private:
|
||||
void UpdateInputDrivers();
|
||||
void HideMouseCursor();
|
||||
void ShowMouseCursor();
|
||||
void CenterMouseCursor();
|
||||
void OpenURL(const QUrl& url);
|
||||
void LoadTranslation();
|
||||
void OpenPerGameConfiguration(u64 title_id, const std::string& file_name);
|
||||
bool CheckDarkMode();
|
||||
bool CheckSystemArchiveDecryption();
|
||||
bool CheckFirmwarePresence();
|
||||
void SetFirmwareVersion();
|
||||
void ConfigureFilesystemProvider(const std::string& filepath);
|
||||
/**
|
||||
* Open (or not) the right confirm dialog based on current setting and game exit lock
|
||||
@@ -512,6 +512,7 @@ private:
|
||||
QLabel* game_fps_label = nullptr;
|
||||
QLabel* emu_frametime_label = nullptr;
|
||||
QLabel* tas_label = nullptr;
|
||||
QLabel* firmware_label = nullptr;
|
||||
QPushButton* gpu_accuracy_button = nullptr;
|
||||
QPushButton* renderer_status_button = nullptr;
|
||||
QPushButton* dock_status_button = nullptr;
|
||||
@@ -533,7 +534,6 @@ private:
|
||||
bool auto_paused = false;
|
||||
bool auto_muted = false;
|
||||
QTimer mouse_hide_timer;
|
||||
QTimer mouse_center_timer;
|
||||
QTimer update_input_timer;
|
||||
|
||||
QString startup_icon_theme;
|
||||
@@ -590,5 +590,4 @@ protected:
|
||||
void dropEvent(QDropEvent* event) override;
|
||||
void dragEnterEvent(QDragEnterEvent* event) override;
|
||||
void dragMoveEvent(QDragMoveEvent* event) override;
|
||||
void leaveEvent(QEvent* event) override;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user