summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/core/frontend/emu_window.h10
-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
5 files changed, 65 insertions, 54 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/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 f22db233b..e4b782fea 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -185,7 +185,6 @@ __declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1;
185#endif 185#endif
186 186
187constexpr int default_mouse_hide_timeout = 2500; 187constexpr int default_mouse_hide_timeout = 2500;
188constexpr int default_mouse_center_timeout = 10;
189constexpr int default_input_update_timeout = 1; 188constexpr int default_input_update_timeout = 1;
190 189
191constexpr size_t CopyBufferSize = 1_MiB; 190constexpr size_t CopyBufferSize = 1_MiB;
@@ -435,9 +434,6 @@ GMainWindow::GMainWindow(std::unique_ptr<Config> config_, bool has_broken_vulkan
435 connect(&mouse_hide_timer, &QTimer::timeout, this, &GMainWindow::HideMouseCursor); 434 connect(&mouse_hide_timer, &QTimer::timeout, this, &GMainWindow::HideMouseCursor);
436 connect(ui->menubar, &QMenuBar::hovered, this, &GMainWindow::ShowMouseCursor); 435 connect(ui->menubar, &QMenuBar::hovered, this, &GMainWindow::ShowMouseCursor);
437 436
438 mouse_center_timer.setInterval(default_mouse_center_timeout);
439 connect(&mouse_center_timer, &QTimer::timeout, this, &GMainWindow::CenterMouseCursor);
440
441 update_input_timer.setInterval(default_input_update_timeout); 437 update_input_timer.setInterval(default_input_update_timeout);
442 connect(&update_input_timer, &QTimer::timeout, this, &GMainWindow::UpdateInputDrivers); 438 connect(&update_input_timer, &QTimer::timeout, this, &GMainWindow::UpdateInputDrivers);
443 update_input_timer.start(); 439 update_input_timer.start();
@@ -1366,14 +1362,6 @@ void GMainWindow::InitializeHotkeys() {
1366 } 1362 }
1367 }); 1363 });
1368 connect_shortcut(QStringLiteral("Toggle Mouse Panning"), [&] { 1364 connect_shortcut(QStringLiteral("Toggle Mouse Panning"), [&] {
1369 if (Settings::values.mouse_enabled) {
1370 Settings::values.mouse_panning = false;
1371 QMessageBox::warning(
1372 this, tr("Emulated mouse is enabled"),
1373 tr("Real mouse input and mouse panning are incompatible. Please disable the "
1374 "emulated mouse in input advanced settings to allow mouse panning."));
1375 return;
1376 }
1377 Settings::values.mouse_panning = !Settings::values.mouse_panning; 1365 Settings::values.mouse_panning = !Settings::values.mouse_panning;
1378 if (Settings::values.mouse_panning) { 1366 if (Settings::values.mouse_panning) {
1379 render_window->installEventFilter(render_window); 1367 render_window->installEventFilter(render_window);
@@ -4693,26 +4681,10 @@ void GMainWindow::ShowMouseCursor() {
4693 } 4681 }
4694} 4682}
4695 4683
4696void GMainWindow::CenterMouseCursor() {
4697 if (emu_thread == nullptr || !Settings::values.mouse_panning) {
4698 mouse_center_timer.stop();
4699 return;
4700 }
4701 if (!this->isActiveWindow()) {
4702 mouse_center_timer.stop();
4703 return;
4704 }
4705 const int center_x = render_window->width() / 2;
4706 const int center_y = render_window->height() / 2;
4707
4708 QCursor::setPos(mapToGlobal(QPoint{center_x, center_y}));
4709}
4710
4711void GMainWindow::OnMouseActivity() { 4684void GMainWindow::OnMouseActivity() {
4712 if (!Settings::values.mouse_panning) { 4685 if (!Settings::values.mouse_panning) {
4713 ShowMouseCursor(); 4686 ShowMouseCursor();
4714 } 4687 }
4715 mouse_center_timer.stop();
4716} 4688}
4717 4689
4718void GMainWindow::OnReinitializeKeys(ReinitializeKeyBehavior behavior) { 4690void GMainWindow::OnReinitializeKeys(ReinitializeKeyBehavior behavior) {
@@ -4988,22 +4960,6 @@ void GMainWindow::dragMoveEvent(QDragMoveEvent* event) {
4988 AcceptDropEvent(event); 4960 AcceptDropEvent(event);
4989} 4961}
4990 4962
4991void GMainWindow::leaveEvent(QEvent* event) {
4992 if (Settings::values.mouse_panning) {
4993 const QRect& rect = geometry();
4994 QPoint position = QCursor::pos();
4995
4996 qint32 x = qBound(rect.left(), position.x(), rect.right());
4997 qint32 y = qBound(rect.top(), position.y(), rect.bottom());
4998 // Only start the timer if the mouse has left the window bound.
4999 // The leave event is also triggered when the window looses focus.
5000 if (x != position.x() || y != position.y()) {
5001 mouse_center_timer.start();
5002 }
5003 event->accept();
5004 }
5005}
5006
5007bool GMainWindow::ConfirmChangeGame() { 4963bool GMainWindow::ConfirmChangeGame() {
5008 if (emu_thread == nullptr) 4964 if (emu_thread == nullptr)
5009 return true; 4965 return true;
diff --git a/src/yuzu/main.h b/src/yuzu/main.h
index 49ee1e1d2..eea39815a 100644
--- a/src/yuzu/main.h
+++ b/src/yuzu/main.h
@@ -450,7 +450,6 @@ private:
450 void UpdateInputDrivers(); 450 void UpdateInputDrivers();
451 void HideMouseCursor(); 451 void HideMouseCursor();
452 void ShowMouseCursor(); 452 void ShowMouseCursor();
453 void CenterMouseCursor();
454 void OpenURL(const QUrl& url); 453 void OpenURL(const QUrl& url);
455 void LoadTranslation(); 454 void LoadTranslation();
456 void OpenPerGameConfiguration(u64 title_id, const std::string& file_name); 455 void OpenPerGameConfiguration(u64 title_id, const std::string& file_name);
@@ -532,7 +531,6 @@ private:
532 bool auto_paused = false; 531 bool auto_paused = false;
533 bool auto_muted = false; 532 bool auto_muted = false;
534 QTimer mouse_hide_timer; 533 QTimer mouse_hide_timer;
535 QTimer mouse_center_timer;
536 QTimer update_input_timer; 534 QTimer update_input_timer;
537 535
538 QString startup_icon_theme; 536 QString startup_icon_theme;
@@ -589,5 +587,4 @@ protected:
589 void dropEvent(QDropEvent* event) override; 587 void dropEvent(QDropEvent* event) override;
590 void dragEnterEvent(QDragEnterEvent* event) override; 588 void dragEnterEvent(QDragEnterEvent* event) override;
591 void dragMoveEvent(QDragMoveEvent* event) override; 589 void dragMoveEvent(QDragMoveEvent* event) override;
592 void leaveEvent(QEvent* event) override;
593}; 590};