summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/frontend/emu_window.h10
-rw-r--r--src/core/hle/service/am/applets/applet_cabinet.cpp2
-rw-r--r--src/core/hle/service/mii/types/ver3_store_data.cpp2
-rw-r--r--src/core/hle/service/nfc/common/device.cpp68
-rw-r--r--src/core/hle/service/nfc/common/device.h1
-rw-r--r--src/yuzu/bootmanager.cpp56
-rw-r--r--src/yuzu/bootmanager.h6
-rw-r--r--src/yuzu/main.cpp44
-rw-r--r--src/yuzu/main.h3
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
100void Ver3StoreData::BuildFromStoreData(const StoreData& store_data) { 100void 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
403Result NfcDevice::Mount(NFP::ModelType model_type, NFP::MountTarget mount_target_) { 403Result 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
854Result 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
873Result NfcDevice::Format() { 877Result 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;
66class QPaintEngine; 65class QPaintEngine;
67class QSurface; 66class QSurface;
68 67
68constexpr int default_mouse_constrain_timeout = 10;
69
69EmuThread::EmuThread(Core::System& system) : m_system{system} {} 70EmuThread::EmuThread(Core::System& system) : m_system{system} {}
70 71
71EmuThread::~EmuThread() = default; 72EmuThread::~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
309void GRenderWindow::ExecuteProgram(std::size_t program_index) { 313void 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
400void 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
396int GRenderWindow::QtKeyToSwitchKey(Qt::Key qt_key) { 416int 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
707void 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
678void GRenderWindow::wheelEvent(QWheelEvent* event) { 732void 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;
38class QObject; 39class QObject;
39class QResizeEvent; 40class QResizeEvent;
40class QShowEvent; 41class QShowEvent;
41class QTimer;
42class QTouchEvent; 42class QTouchEvent;
43class QWheelEvent; 43class 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
273protected: 277protected:
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
189constexpr int default_mouse_hide_timeout = 2500; 189constexpr int default_mouse_hide_timeout = 2500;
190constexpr int default_mouse_center_timeout = 10;
191constexpr int default_input_update_timeout = 1; 190constexpr int default_input_update_timeout = 1;
192 191
193constexpr size_t CopyBufferSize = 1_MiB; 192constexpr 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
4714void 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
4729void GMainWindow::OnMouseActivity() { 4702void 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
4736void GMainWindow::OnReinitializeKeys(ReinitializeKeyBehavior behavior) { 4708void GMainWindow::OnReinitializeKeys(ReinitializeKeyBehavior behavior) {
@@ -5031,22 +5003,6 @@ void GMainWindow::dragMoveEvent(QDragMoveEvent* event) {
5031 AcceptDropEvent(event); 5003 AcceptDropEvent(event);
5032} 5004}
5033 5005
5034void 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
5050bool GMainWindow::ConfirmChangeGame() { 5006bool 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};