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 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};