diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/frontend/emu_window.h | 10 | ||||
| -rw-r--r-- | src/core/hle/service/am/applets/applet_cabinet.cpp | 2 | ||||
| -rw-r--r-- | src/core/hle/service/mii/types/ver3_store_data.cpp | 2 | ||||
| -rw-r--r-- | src/core/hle/service/nfc/common/device.cpp | 68 | ||||
| -rw-r--r-- | src/core/hle/service/nfc/common/device.h | 1 | ||||
| -rw-r--r-- | src/yuzu/bootmanager.cpp | 56 | ||||
| -rw-r--r-- | src/yuzu/bootmanager.h | 6 | ||||
| -rw-r--r-- | src/yuzu/main.cpp | 44 | ||||
| -rw-r--r-- | src/yuzu/main.h | 3 |
9 files changed, 104 insertions, 88 deletions
diff --git a/src/core/frontend/emu_window.h b/src/core/frontend/emu_window.h index a72df034e..c7b48a58d 100644 --- a/src/core/frontend/emu_window.h +++ b/src/core/frontend/emu_window.h | |||
| @@ -167,6 +167,11 @@ protected: | |||
| 167 | */ | 167 | */ |
| 168 | std::pair<f32, f32> MapToTouchScreen(u32 framebuffer_x, u32 framebuffer_y) const; | 168 | std::pair<f32, f32> MapToTouchScreen(u32 framebuffer_x, u32 framebuffer_y) const; |
| 169 | 169 | ||
| 170 | /** | ||
| 171 | * Clip the provided coordinates to be inside the touchscreen area. | ||
| 172 | */ | ||
| 173 | std::pair<u32, u32> ClipToTouchScreen(u32 new_x, u32 new_y) const; | ||
| 174 | |||
| 170 | WindowSystemInfo window_info; | 175 | WindowSystemInfo window_info; |
| 171 | 176 | ||
| 172 | bool strict_context_required = false; | 177 | bool strict_context_required = false; |
| @@ -181,11 +186,6 @@ private: | |||
| 181 | // By default, ignore this request and do nothing. | 186 | // By default, ignore this request and do nothing. |
| 182 | } | 187 | } |
| 183 | 188 | ||
| 184 | /** | ||
| 185 | * Clip the provided coordinates to be inside the touchscreen area. | ||
| 186 | */ | ||
| 187 | std::pair<u32, u32> ClipToTouchScreen(u32 new_x, u32 new_y) const; | ||
| 188 | |||
| 189 | Layout::FramebufferLayout framebuffer_layout; ///< Current framebuffer layout | 189 | Layout::FramebufferLayout framebuffer_layout; ///< Current framebuffer layout |
| 190 | 190 | ||
| 191 | u32 client_area_width; ///< Current client width, should be set by window impl. | 191 | u32 client_area_width; ///< Current client width, should be set by window impl. |
diff --git a/src/core/hle/service/am/applets/applet_cabinet.cpp b/src/core/hle/service/am/applets/applet_cabinet.cpp index 9d1960cb7..3906c0fa4 100644 --- a/src/core/hle/service/am/applets/applet_cabinet.cpp +++ b/src/core/hle/service/am/applets/applet_cabinet.cpp | |||
| @@ -131,7 +131,7 @@ void Cabinet::DisplayCompleted(bool apply_changes, std::string_view amiibo_name) | |||
| 131 | nfp_device->DeleteApplicationArea(); | 131 | nfp_device->DeleteApplicationArea(); |
| 132 | break; | 132 | break; |
| 133 | case Service::NFP::CabinetMode::StartRestorer: | 133 | case Service::NFP::CabinetMode::StartRestorer: |
| 134 | nfp_device->RestoreAmiibo(); | 134 | nfp_device->Restore(); |
| 135 | break; | 135 | break; |
| 136 | case Service::NFP::CabinetMode::StartFormatter: | 136 | case Service::NFP::CabinetMode::StartFormatter: |
| 137 | nfp_device->Format(); | 137 | nfp_device->Format(); |
diff --git a/src/core/hle/service/mii/types/ver3_store_data.cpp b/src/core/hle/service/mii/types/ver3_store_data.cpp index a019cc9f7..c27646fcf 100644 --- a/src/core/hle/service/mii/types/ver3_store_data.cpp +++ b/src/core/hle/service/mii/types/ver3_store_data.cpp | |||
| @@ -98,7 +98,7 @@ void Ver3StoreData::BuildToStoreData(StoreData& out_store_data) const { | |||
| 98 | } | 98 | } |
| 99 | 99 | ||
| 100 | void Ver3StoreData::BuildFromStoreData(const StoreData& store_data) { | 100 | void Ver3StoreData::BuildFromStoreData(const StoreData& store_data) { |
| 101 | version = 1; | 101 | version = 3; |
| 102 | mii_information.gender.Assign(static_cast<u8>(store_data.GetGender())); | 102 | mii_information.gender.Assign(static_cast<u8>(store_data.GetGender())); |
| 103 | mii_information.favorite_color.Assign(static_cast<u8>(store_data.GetFavoriteColor())); | 103 | mii_information.favorite_color.Assign(static_cast<u8>(store_data.GetFavoriteColor())); |
| 104 | height = store_data.GetHeight(); | 104 | height = store_data.GetHeight(); |
diff --git a/src/core/hle/service/nfc/common/device.cpp b/src/core/hle/service/nfc/common/device.cpp index e7a00deb3..47516f883 100644 --- a/src/core/hle/service/nfc/common/device.cpp +++ b/src/core/hle/service/nfc/common/device.cpp | |||
| @@ -401,6 +401,12 @@ Result NfcDevice::SendCommandByPassThrough(const Time::Clock::TimeSpanType& time | |||
| 401 | } | 401 | } |
| 402 | 402 | ||
| 403 | Result NfcDevice::Mount(NFP::ModelType model_type, NFP::MountTarget mount_target_) { | 403 | Result NfcDevice::Mount(NFP::ModelType model_type, NFP::MountTarget mount_target_) { |
| 404 | bool is_corrupted = false; | ||
| 405 | |||
| 406 | if (model_type != NFP::ModelType::Amiibo) { | ||
| 407 | return ResultInvalidArgument; | ||
| 408 | } | ||
| 409 | |||
| 404 | if (device_state != DeviceState::TagFound) { | 410 | if (device_state != DeviceState::TagFound) { |
| 405 | LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); | 411 | LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); |
| 406 | return ResultWrongDeviceState; | 412 | return ResultWrongDeviceState; |
| @@ -420,26 +426,32 @@ Result NfcDevice::Mount(NFP::ModelType model_type, NFP::MountTarget mount_target | |||
| 420 | if (is_plain_amiibo) { | 426 | if (is_plain_amiibo) { |
| 421 | std::vector<u8> data(sizeof(NFP::NTAG215File)); | 427 | std::vector<u8> data(sizeof(NFP::NTAG215File)); |
| 422 | memcpy(data.data(), &tag_data, sizeof(tag_data)); | 428 | memcpy(data.data(), &tag_data, sizeof(tag_data)); |
| 423 | WriteBackupData(tag_data.uid, data); | 429 | } |
| 424 | 430 | ||
| 425 | device_state = DeviceState::TagMounted; | 431 | if (!is_plain_amiibo && !NFP::AmiiboCrypto::DecodeAmiibo(encrypted_tag_data, tag_data)) { |
| 426 | mount_target = mount_target_; | 432 | LOG_ERROR(Service_NFP, "Can't decode amiibo"); |
| 427 | return ResultSuccess; | 433 | is_corrupted = true; |
| 428 | } | 434 | } |
| 429 | 435 | ||
| 430 | if (!NFP::AmiiboCrypto::DecodeAmiibo(encrypted_tag_data, tag_data)) { | 436 | if (tag_data.settings.settings.amiibo_initialized && !tag_data.owner_mii.IsValid()) { |
| 431 | bool has_backup = HasBackup(encrypted_tag_data.uuid).IsSuccess(); | 437 | LOG_ERROR(Service_NFP, "Invalid mii data"); |
| 432 | LOG_ERROR(Service_NFP, "Can't decode amiibo, has_backup= {}", has_backup); | 438 | is_corrupted = true; |
| 433 | return has_backup ? ResultCorruptedDataWithBackup : ResultCorruptedData; | ||
| 434 | } | 439 | } |
| 435 | 440 | ||
| 436 | std::vector<u8> data(sizeof(NFP::EncryptedNTAG215File)); | 441 | if (!is_corrupted) { |
| 437 | memcpy(data.data(), &encrypted_tag_data, sizeof(encrypted_tag_data)); | 442 | std::vector<u8> data(sizeof(NFP::EncryptedNTAG215File)); |
| 438 | WriteBackupData(encrypted_tag_data.uuid, data); | 443 | memcpy(data.data(), &encrypted_tag_data, sizeof(encrypted_tag_data)); |
| 444 | WriteBackupData(encrypted_tag_data.uuid, data); | ||
| 445 | } | ||
| 439 | 446 | ||
| 440 | device_state = DeviceState::TagMounted; | 447 | device_state = DeviceState::TagMounted; |
| 441 | mount_target = mount_target_; | 448 | mount_target = mount_target_; |
| 442 | 449 | ||
| 450 | if (is_corrupted) { | ||
| 451 | bool has_backup = HasBackup(encrypted_tag_data.uuid).IsSuccess(); | ||
| 452 | return has_backup ? ResultCorruptedDataWithBackup : ResultCorruptedData; | ||
| 453 | } | ||
| 454 | |||
| 443 | return ResultSuccess; | 455 | return ResultSuccess; |
| 444 | } | 456 | } |
| 445 | 457 | ||
| @@ -606,6 +618,17 @@ Result NfcDevice::Restore() { | |||
| 606 | } | 618 | } |
| 607 | } | 619 | } |
| 608 | 620 | ||
| 621 | // Restore mii data in case is corrupted by previous instances of yuzu | ||
| 622 | if (tag_data.settings.settings.amiibo_initialized && !tag_data.owner_mii.IsValid()) { | ||
| 623 | LOG_ERROR(Service_NFP, "Regenerating mii data"); | ||
| 624 | Mii::StoreData new_mii{}; | ||
| 625 | new_mii.BuildRandom(Mii::Age::All, Mii::Gender::All, Mii::Race::All); | ||
| 626 | new_mii.SetNickname({u'y', u'u', u'z', u'u', u'\0'}); | ||
| 627 | |||
| 628 | tag_data.owner_mii.BuildFromStoreData(new_mii); | ||
| 629 | tag_data.mii_extension.SetFromStoreData(new_mii); | ||
| 630 | } | ||
| 631 | |||
| 609 | // Overwrite tag contents with backup and mount the tag | 632 | // Overwrite tag contents with backup and mount the tag |
| 610 | tag_data = temporary_tag_data; | 633 | tag_data = temporary_tag_data; |
| 611 | encrypted_tag_data = temporary_encrypted_tag_data; | 634 | encrypted_tag_data = temporary_encrypted_tag_data; |
| @@ -851,25 +874,6 @@ Result NfcDevice::SetRegisterInfoPrivate(const NFP::RegisterInfoPrivate& registe | |||
| 851 | return Flush(); | 874 | return Flush(); |
| 852 | } | 875 | } |
| 853 | 876 | ||
| 854 | Result NfcDevice::RestoreAmiibo() { | ||
| 855 | if (device_state != DeviceState::TagMounted) { | ||
| 856 | LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); | ||
| 857 | if (device_state == DeviceState::TagRemoved) { | ||
| 858 | return ResultTagRemoved; | ||
| 859 | } | ||
| 860 | return ResultWrongDeviceState; | ||
| 861 | } | ||
| 862 | |||
| 863 | if (mount_target == NFP::MountTarget::None || mount_target == NFP::MountTarget::Rom) { | ||
| 864 | LOG_ERROR(Service_NFP, "Amiibo is read only", device_state); | ||
| 865 | return ResultWrongDeviceState; | ||
| 866 | } | ||
| 867 | |||
| 868 | // TODO: Load amiibo from backup on system | ||
| 869 | LOG_ERROR(Service_NFP, "Not Implemented"); | ||
| 870 | return ResultSuccess; | ||
| 871 | } | ||
| 872 | |||
| 873 | Result NfcDevice::Format() { | 877 | Result NfcDevice::Format() { |
| 874 | Result result = ResultSuccess; | 878 | Result result = ResultSuccess; |
| 875 | 879 | ||
| @@ -877,7 +881,9 @@ Result NfcDevice::Format() { | |||
| 877 | result = Mount(NFP::ModelType::Amiibo, NFP::MountTarget::All); | 881 | result = Mount(NFP::ModelType::Amiibo, NFP::MountTarget::All); |
| 878 | } | 882 | } |
| 879 | 883 | ||
| 880 | if (result.IsError()) { | 884 | // We are formatting all data. Corruption is not an issue. |
| 885 | if (result.IsError() && | ||
| 886 | (result != ResultCorruptedData && result != ResultCorruptedDataWithBackup)) { | ||
| 881 | return result; | 887 | return result; |
| 882 | } | 888 | } |
| 883 | 889 | ||
diff --git a/src/core/hle/service/nfc/common/device.h b/src/core/hle/service/nfc/common/device.h index 0ed1ff34c..d8efe25ec 100644 --- a/src/core/hle/service/nfc/common/device.h +++ b/src/core/hle/service/nfc/common/device.h | |||
| @@ -68,7 +68,6 @@ public: | |||
| 68 | 68 | ||
| 69 | Result DeleteRegisterInfo(); | 69 | Result DeleteRegisterInfo(); |
| 70 | Result SetRegisterInfoPrivate(const NFP::RegisterInfoPrivate& register_info); | 70 | Result SetRegisterInfoPrivate(const NFP::RegisterInfoPrivate& register_info); |
| 71 | Result RestoreAmiibo(); | ||
| 72 | Result Format(); | 71 | Result Format(); |
| 73 | 72 | ||
| 74 | Result OpenApplicationArea(u32 access_id); | 73 | Result OpenApplicationArea(u32 access_id); |
diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp index 2afa72140..ed5750155 100644 --- a/src/yuzu/bootmanager.cpp +++ b/src/yuzu/bootmanager.cpp | |||
| @@ -30,7 +30,6 @@ | |||
| 30 | #include <QSize> | 30 | #include <QSize> |
| 31 | #include <QStringLiteral> | 31 | #include <QStringLiteral> |
| 32 | #include <QSurfaceFormat> | 32 | #include <QSurfaceFormat> |
| 33 | #include <QTimer> | ||
| 34 | #include <QWindow> | 33 | #include <QWindow> |
| 35 | #include <QtCore/qobjectdefs.h> | 34 | #include <QtCore/qobjectdefs.h> |
| 36 | 35 | ||
| @@ -66,6 +65,8 @@ class QObject; | |||
| 66 | class QPaintEngine; | 65 | class QPaintEngine; |
| 67 | class QSurface; | 66 | class QSurface; |
| 68 | 67 | ||
| 68 | constexpr int default_mouse_constrain_timeout = 10; | ||
| 69 | |||
| 69 | EmuThread::EmuThread(Core::System& system) : m_system{system} {} | 70 | EmuThread::EmuThread(Core::System& system) : m_system{system} {} |
| 70 | 71 | ||
| 71 | EmuThread::~EmuThread() = default; | 72 | EmuThread::~EmuThread() = default; |
| @@ -304,6 +305,9 @@ GRenderWindow::GRenderWindow(GMainWindow* parent, EmuThread* emu_thread_, | |||
| 304 | Qt::QueuedConnection); | 305 | Qt::QueuedConnection); |
| 305 | connect(this, &GRenderWindow::ExitSignal, parent, &GMainWindow::OnExit, Qt::QueuedConnection); | 306 | connect(this, &GRenderWindow::ExitSignal, parent, &GMainWindow::OnExit, Qt::QueuedConnection); |
| 306 | connect(this, &GRenderWindow::TasPlaybackStateChanged, parent, &GMainWindow::OnTasStateChanged); | 307 | connect(this, &GRenderWindow::TasPlaybackStateChanged, parent, &GMainWindow::OnTasStateChanged); |
| 308 | |||
| 309 | mouse_constrain_timer.setInterval(default_mouse_constrain_timeout); | ||
| 310 | connect(&mouse_constrain_timer, &QTimer::timeout, this, &GRenderWindow::ConstrainMouse); | ||
| 307 | } | 311 | } |
| 308 | 312 | ||
| 309 | void GRenderWindow::ExecuteProgram(std::size_t program_index) { | 313 | void GRenderWindow::ExecuteProgram(std::size_t program_index) { |
| @@ -393,6 +397,22 @@ void GRenderWindow::closeEvent(QCloseEvent* event) { | |||
| 393 | QWidget::closeEvent(event); | 397 | QWidget::closeEvent(event); |
| 394 | } | 398 | } |
| 395 | 399 | ||
| 400 | void GRenderWindow::leaveEvent(QEvent* event) { | ||
| 401 | if (Settings::values.mouse_panning) { | ||
| 402 | const QRect& rect = QWidget::geometry(); | ||
| 403 | QPoint position = QCursor::pos(); | ||
| 404 | |||
| 405 | qint32 x = qBound(rect.left(), position.x(), rect.right()); | ||
| 406 | qint32 y = qBound(rect.top(), position.y(), rect.bottom()); | ||
| 407 | // Only start the timer if the mouse has left the window bound. | ||
| 408 | // The leave event is also triggered when the window looses focus. | ||
| 409 | if (x != position.x() || y != position.y()) { | ||
| 410 | mouse_constrain_timer.start(); | ||
| 411 | } | ||
| 412 | event->accept(); | ||
| 413 | } | ||
| 414 | } | ||
| 415 | |||
| 396 | int GRenderWindow::QtKeyToSwitchKey(Qt::Key qt_key) { | 416 | int GRenderWindow::QtKeyToSwitchKey(Qt::Key qt_key) { |
| 397 | static constexpr std::array<std::pair<Qt::Key, Settings::NativeKeyboard::Keys>, 106> key_map = { | 417 | static constexpr std::array<std::pair<Qt::Key, Settings::NativeKeyboard::Keys>, 106> key_map = { |
| 398 | std::pair<Qt::Key, Settings::NativeKeyboard::Keys>{Qt::Key_A, Settings::NativeKeyboard::A}, | 418 | std::pair<Qt::Key, Settings::NativeKeyboard::Keys>{Qt::Key_A, Settings::NativeKeyboard::A}, |
| @@ -658,10 +678,19 @@ void GRenderWindow::mouseMoveEvent(QMouseEvent* event) { | |||
| 658 | input_subsystem->GetMouse()->TouchMove(touch_x, touch_y); | 678 | input_subsystem->GetMouse()->TouchMove(touch_x, touch_y); |
| 659 | input_subsystem->GetMouse()->Move(pos.x(), pos.y(), center_x, center_y); | 679 | input_subsystem->GetMouse()->Move(pos.x(), pos.y(), center_x, center_y); |
| 660 | 680 | ||
| 681 | // Center mouse for mouse panning | ||
| 661 | if (Settings::values.mouse_panning && !Settings::values.mouse_enabled) { | 682 | if (Settings::values.mouse_panning && !Settings::values.mouse_enabled) { |
| 662 | QCursor::setPos(mapToGlobal(QPoint{center_x, center_y})); | 683 | QCursor::setPos(mapToGlobal(QPoint{center_x, center_y})); |
| 663 | } | 684 | } |
| 664 | 685 | ||
| 686 | // Constrain mouse for mouse emulation with mouse panning | ||
| 687 | if (Settings::values.mouse_panning && Settings::values.mouse_enabled) { | ||
| 688 | const auto [clamped_mouse_x, clamped_mouse_y] = ClipToTouchScreen(x, y); | ||
| 689 | QCursor::setPos(mapToGlobal( | ||
| 690 | QPoint{static_cast<int>(clamped_mouse_x), static_cast<int>(clamped_mouse_y)})); | ||
| 691 | } | ||
| 692 | |||
| 693 | mouse_constrain_timer.stop(); | ||
| 665 | emit MouseActivity(); | 694 | emit MouseActivity(); |
| 666 | } | 695 | } |
| 667 | 696 | ||
| @@ -675,6 +704,31 @@ void GRenderWindow::mouseReleaseEvent(QMouseEvent* event) { | |||
| 675 | input_subsystem->GetMouse()->ReleaseButton(button); | 704 | input_subsystem->GetMouse()->ReleaseButton(button); |
| 676 | } | 705 | } |
| 677 | 706 | ||
| 707 | void GRenderWindow::ConstrainMouse() { | ||
| 708 | if (emu_thread == nullptr || !Settings::values.mouse_panning) { | ||
| 709 | mouse_constrain_timer.stop(); | ||
| 710 | return; | ||
| 711 | } | ||
| 712 | if (!this->isActiveWindow()) { | ||
| 713 | mouse_constrain_timer.stop(); | ||
| 714 | return; | ||
| 715 | } | ||
| 716 | |||
| 717 | if (Settings::values.mouse_enabled) { | ||
| 718 | const auto pos = mapFromGlobal(QCursor::pos()); | ||
| 719 | const int new_pos_x = std::clamp(pos.x(), 0, width()); | ||
| 720 | const int new_pos_y = std::clamp(pos.y(), 0, height()); | ||
| 721 | |||
| 722 | QCursor::setPos(mapToGlobal(QPoint{new_pos_x, new_pos_y})); | ||
| 723 | return; | ||
| 724 | } | ||
| 725 | |||
| 726 | const int center_x = width() / 2; | ||
| 727 | const int center_y = height() / 2; | ||
| 728 | |||
| 729 | QCursor::setPos(mapToGlobal(QPoint{center_x, center_y})); | ||
| 730 | } | ||
| 731 | |||
| 678 | void GRenderWindow::wheelEvent(QWheelEvent* event) { | 732 | void GRenderWindow::wheelEvent(QWheelEvent* event) { |
| 679 | const int x = event->angleDelta().x(); | 733 | const int x = event->angleDelta().x(); |
| 680 | const int y = event->angleDelta().y(); | 734 | const int y = event->angleDelta().y(); |
diff --git a/src/yuzu/bootmanager.h b/src/yuzu/bootmanager.h index 87b23df12..60edd464c 100644 --- a/src/yuzu/bootmanager.h +++ b/src/yuzu/bootmanager.h | |||
| @@ -17,6 +17,7 @@ | |||
| 17 | #include <QString> | 17 | #include <QString> |
| 18 | #include <QStringList> | 18 | #include <QStringList> |
| 19 | #include <QThread> | 19 | #include <QThread> |
| 20 | #include <QTimer> | ||
| 20 | #include <QWidget> | 21 | #include <QWidget> |
| 21 | #include <qglobal.h> | 22 | #include <qglobal.h> |
| 22 | #include <qnamespace.h> | 23 | #include <qnamespace.h> |
| @@ -38,7 +39,6 @@ class QMouseEvent; | |||
| 38 | class QObject; | 39 | class QObject; |
| 39 | class QResizeEvent; | 40 | class QResizeEvent; |
| 40 | class QShowEvent; | 41 | class QShowEvent; |
| 41 | class QTimer; | ||
| 42 | class QTouchEvent; | 42 | class QTouchEvent; |
| 43 | class QWheelEvent; | 43 | class QWheelEvent; |
| 44 | 44 | ||
| @@ -166,6 +166,7 @@ public: | |||
| 166 | std::pair<u32, u32> ScaleTouch(const QPointF& pos) const; | 166 | std::pair<u32, u32> ScaleTouch(const QPointF& pos) const; |
| 167 | 167 | ||
| 168 | void closeEvent(QCloseEvent* event) override; | 168 | void closeEvent(QCloseEvent* event) override; |
| 169 | void leaveEvent(QEvent* event) override; | ||
| 169 | 170 | ||
| 170 | void resizeEvent(QResizeEvent* event) override; | 171 | void resizeEvent(QResizeEvent* event) override; |
| 171 | 172 | ||
| @@ -229,6 +230,7 @@ private: | |||
| 229 | void TouchBeginEvent(const QTouchEvent* event); | 230 | void TouchBeginEvent(const QTouchEvent* event); |
| 230 | void TouchUpdateEvent(const QTouchEvent* event); | 231 | void TouchUpdateEvent(const QTouchEvent* event); |
| 231 | void TouchEndEvent(); | 232 | void TouchEndEvent(); |
| 233 | void ConstrainMouse(); | ||
| 232 | 234 | ||
| 233 | void RequestCameraCapture(); | 235 | void RequestCameraCapture(); |
| 234 | void OnCameraCapture(int requestId, const QImage& img); | 236 | void OnCameraCapture(int requestId, const QImage& img); |
| @@ -268,6 +270,8 @@ private: | |||
| 268 | std::unique_ptr<QTimer> camera_timer; | 270 | std::unique_ptr<QTimer> camera_timer; |
| 269 | #endif | 271 | #endif |
| 270 | 272 | ||
| 273 | QTimer mouse_constrain_timer; | ||
| 274 | |||
| 271 | Core::System& system; | 275 | Core::System& system; |
| 272 | 276 | ||
| 273 | protected: | 277 | protected: |
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index dcf68460a..31aabb78a 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp | |||
| @@ -187,7 +187,6 @@ __declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1; | |||
| 187 | #endif | 187 | #endif |
| 188 | 188 | ||
| 189 | constexpr int default_mouse_hide_timeout = 2500; | 189 | constexpr int default_mouse_hide_timeout = 2500; |
| 190 | constexpr int default_mouse_center_timeout = 10; | ||
| 191 | constexpr int default_input_update_timeout = 1; | 190 | constexpr int default_input_update_timeout = 1; |
| 192 | 191 | ||
| 193 | constexpr size_t CopyBufferSize = 1_MiB; | 192 | constexpr size_t CopyBufferSize = 1_MiB; |
| @@ -437,9 +436,6 @@ GMainWindow::GMainWindow(std::unique_ptr<QtConfig> config_, bool has_broken_vulk | |||
| 437 | connect(&mouse_hide_timer, &QTimer::timeout, this, &GMainWindow::HideMouseCursor); | 436 | connect(&mouse_hide_timer, &QTimer::timeout, this, &GMainWindow::HideMouseCursor); |
| 438 | connect(ui->menubar, &QMenuBar::hovered, this, &GMainWindow::ShowMouseCursor); | 437 | connect(ui->menubar, &QMenuBar::hovered, this, &GMainWindow::ShowMouseCursor); |
| 439 | 438 | ||
| 440 | mouse_center_timer.setInterval(default_mouse_center_timeout); | ||
| 441 | connect(&mouse_center_timer, &QTimer::timeout, this, &GMainWindow::CenterMouseCursor); | ||
| 442 | |||
| 443 | update_input_timer.setInterval(default_input_update_timeout); | 439 | update_input_timer.setInterval(default_input_update_timeout); |
| 444 | connect(&update_input_timer, &QTimer::timeout, this, &GMainWindow::UpdateInputDrivers); | 440 | connect(&update_input_timer, &QTimer::timeout, this, &GMainWindow::UpdateInputDrivers); |
| 445 | update_input_timer.start(); | 441 | update_input_timer.start(); |
| @@ -1376,14 +1372,6 @@ void GMainWindow::InitializeHotkeys() { | |||
| 1376 | } | 1372 | } |
| 1377 | }); | 1373 | }); |
| 1378 | connect_shortcut(QStringLiteral("Toggle Mouse Panning"), [&] { | 1374 | connect_shortcut(QStringLiteral("Toggle Mouse Panning"), [&] { |
| 1379 | if (Settings::values.mouse_enabled) { | ||
| 1380 | Settings::values.mouse_panning = false; | ||
| 1381 | QMessageBox::warning( | ||
| 1382 | this, tr("Emulated mouse is enabled"), | ||
| 1383 | tr("Real mouse input and mouse panning are incompatible. Please disable the " | ||
| 1384 | "emulated mouse in input advanced settings to allow mouse panning.")); | ||
| 1385 | return; | ||
| 1386 | } | ||
| 1387 | Settings::values.mouse_panning = !Settings::values.mouse_panning; | 1375 | Settings::values.mouse_panning = !Settings::values.mouse_panning; |
| 1388 | if (Settings::values.mouse_panning) { | 1376 | if (Settings::values.mouse_panning) { |
| 1389 | render_window->installEventFilter(render_window); | 1377 | render_window->installEventFilter(render_window); |
| @@ -4711,26 +4699,10 @@ void GMainWindow::ShowMouseCursor() { | |||
| 4711 | } | 4699 | } |
| 4712 | } | 4700 | } |
| 4713 | 4701 | ||
| 4714 | void GMainWindow::CenterMouseCursor() { | ||
| 4715 | if (emu_thread == nullptr || !Settings::values.mouse_panning) { | ||
| 4716 | mouse_center_timer.stop(); | ||
| 4717 | return; | ||
| 4718 | } | ||
| 4719 | if (!this->isActiveWindow()) { | ||
| 4720 | mouse_center_timer.stop(); | ||
| 4721 | return; | ||
| 4722 | } | ||
| 4723 | const int center_x = render_window->width() / 2; | ||
| 4724 | const int center_y = render_window->height() / 2; | ||
| 4725 | |||
| 4726 | QCursor::setPos(mapToGlobal(QPoint{center_x, center_y})); | ||
| 4727 | } | ||
| 4728 | |||
| 4729 | void GMainWindow::OnMouseActivity() { | 4702 | void GMainWindow::OnMouseActivity() { |
| 4730 | if (!Settings::values.mouse_panning) { | 4703 | if (!Settings::values.mouse_panning) { |
| 4731 | ShowMouseCursor(); | 4704 | ShowMouseCursor(); |
| 4732 | } | 4705 | } |
| 4733 | mouse_center_timer.stop(); | ||
| 4734 | } | 4706 | } |
| 4735 | 4707 | ||
| 4736 | void GMainWindow::OnReinitializeKeys(ReinitializeKeyBehavior behavior) { | 4708 | void GMainWindow::OnReinitializeKeys(ReinitializeKeyBehavior behavior) { |
| @@ -5031,22 +5003,6 @@ void GMainWindow::dragMoveEvent(QDragMoveEvent* event) { | |||
| 5031 | AcceptDropEvent(event); | 5003 | AcceptDropEvent(event); |
| 5032 | } | 5004 | } |
| 5033 | 5005 | ||
| 5034 | void GMainWindow::leaveEvent(QEvent* event) { | ||
| 5035 | if (Settings::values.mouse_panning) { | ||
| 5036 | const QRect& rect = geometry(); | ||
| 5037 | QPoint position = QCursor::pos(); | ||
| 5038 | |||
| 5039 | qint32 x = qBound(rect.left(), position.x(), rect.right()); | ||
| 5040 | qint32 y = qBound(rect.top(), position.y(), rect.bottom()); | ||
| 5041 | // Only start the timer if the mouse has left the window bound. | ||
| 5042 | // The leave event is also triggered when the window looses focus. | ||
| 5043 | if (x != position.x() || y != position.y()) { | ||
| 5044 | mouse_center_timer.start(); | ||
| 5045 | } | ||
| 5046 | event->accept(); | ||
| 5047 | } | ||
| 5048 | } | ||
| 5049 | |||
| 5050 | bool GMainWindow::ConfirmChangeGame() { | 5006 | bool GMainWindow::ConfirmChangeGame() { |
| 5051 | if (emu_thread == nullptr) | 5007 | if (emu_thread == nullptr) |
| 5052 | return true; | 5008 | return true; |
diff --git a/src/yuzu/main.h b/src/yuzu/main.h index e99d58995..733d6291e 100644 --- a/src/yuzu/main.h +++ b/src/yuzu/main.h | |||
| @@ -451,7 +451,6 @@ private: | |||
| 451 | void UpdateInputDrivers(); | 451 | void UpdateInputDrivers(); |
| 452 | void HideMouseCursor(); | 452 | void HideMouseCursor(); |
| 453 | void ShowMouseCursor(); | 453 | void ShowMouseCursor(); |
| 454 | void CenterMouseCursor(); | ||
| 455 | void OpenURL(const QUrl& url); | 454 | void OpenURL(const QUrl& url); |
| 456 | void LoadTranslation(); | 455 | void LoadTranslation(); |
| 457 | void OpenPerGameConfiguration(u64 title_id, const std::string& file_name); | 456 | void OpenPerGameConfiguration(u64 title_id, const std::string& file_name); |
| @@ -535,7 +534,6 @@ private: | |||
| 535 | bool auto_paused = false; | 534 | bool auto_paused = false; |
| 536 | bool auto_muted = false; | 535 | bool auto_muted = false; |
| 537 | QTimer mouse_hide_timer; | 536 | QTimer mouse_hide_timer; |
| 538 | QTimer mouse_center_timer; | ||
| 539 | QTimer update_input_timer; | 537 | QTimer update_input_timer; |
| 540 | 538 | ||
| 541 | QString startup_icon_theme; | 539 | QString startup_icon_theme; |
| @@ -592,5 +590,4 @@ protected: | |||
| 592 | void dropEvent(QDropEvent* event) override; | 590 | void dropEvent(QDropEvent* event) override; |
| 593 | void dragEnterEvent(QDragEnterEvent* event) override; | 591 | void dragEnterEvent(QDragEnterEvent* event) override; |
| 594 | void dragMoveEvent(QDragMoveEvent* event) override; | 592 | void dragMoveEvent(QDragMoveEvent* event) override; |
| 595 | void leaveEvent(QEvent* event) override; | ||
| 596 | }; | 593 | }; |