summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/core/settings.h5
-rw-r--r--src/input_common/mouse/mouse_input.cpp32
-rw-r--r--src/input_common/mouse/mouse_input.h7
-rw-r--r--src/input_common/mouse/mouse_poller.cpp3
-rw-r--r--src/yuzu/bootmanager.cpp14
-rw-r--r--src/yuzu/configuration/config.cpp10
-rw-r--r--src/yuzu/configuration/config.h2
-rw-r--r--src/yuzu/configuration/configure_input_advanced.cpp5
-rw-r--r--src/yuzu/configuration/configure_input_advanced.ui82
-rw-r--r--src/yuzu/main.cpp24
-rw-r--r--src/yuzu_cmd/emu_window/emu_window_sdl2.cpp3
11 files changed, 149 insertions, 38 deletions
diff --git a/src/core/settings.h b/src/core/settings.h
index a324530bd..d849dded3 100644
--- a/src/core/settings.h
+++ b/src/core/settings.h
@@ -181,12 +181,13 @@ struct Values {
181 std::string motion_device; 181 std::string motion_device;
182 std::string udp_input_servers; 182 std::string udp_input_servers;
183 183
184 bool emulate_analog_keyboard; 184 bool mouse_panning;
185 185 float mouse_panning_sensitivity;
186 bool mouse_enabled; 186 bool mouse_enabled;
187 std::string mouse_device; 187 std::string mouse_device;
188 MouseButtonsRaw mouse_buttons; 188 MouseButtonsRaw mouse_buttons;
189 189
190 bool emulate_analog_keyboard;
190 bool keyboard_enabled; 191 bool keyboard_enabled;
191 KeyboardKeysRaw keyboard_keys; 192 KeyboardKeysRaw keyboard_keys;
192 KeyboardModsRaw keyboard_mods; 193 KeyboardModsRaw keyboard_mods;
diff --git a/src/input_common/mouse/mouse_input.cpp b/src/input_common/mouse/mouse_input.cpp
index 10786a541..67a584d53 100644
--- a/src/input_common/mouse/mouse_input.cpp
+++ b/src/input_common/mouse/mouse_input.cpp
@@ -2,6 +2,7 @@
2// Licensed under GPLv2+ 2// Licensed under GPLv2+
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "core/settings.h"
5#include "input_common/mouse/mouse_input.h" 6#include "input_common/mouse/mouse_input.h"
6 7
7namespace MouseInput { 8namespace MouseInput {
@@ -36,6 +37,9 @@ void Mouse::UpdateThread() {
36 if (configuring) { 37 if (configuring) {
37 UpdateYuzuSettings(); 38 UpdateYuzuSettings();
38 } 39 }
40 if (mouse_panning_timout++ > 8) {
41 StopPanning();
42 }
39 std::this_thread::sleep_for(std::chrono::milliseconds(update_time)); 43 std::this_thread::sleep_for(std::chrono::milliseconds(update_time));
40 } 44 }
41} 45}
@@ -65,8 +69,34 @@ void Mouse::PressButton(int x, int y, int button_) {
65 mouse_info[button_index].data.pressed = true; 69 mouse_info[button_index].data.pressed = true;
66} 70}
67 71
68void Mouse::MouseMove(int x, int y) { 72void Mouse::StopPanning() {
73 for (MouseInfo& info : mouse_info) {
74 if (Settings::values.mouse_panning) {
75 info.data.axis = {};
76 info.tilt_speed = 0;
77 info.last_mouse_change = {};
78 }
79 }
80}
81
82void Mouse::MouseMove(int x, int y, int center_x, int center_y) {
69 for (MouseInfo& info : mouse_info) { 83 for (MouseInfo& info : mouse_info) {
84 if (Settings::values.mouse_panning) {
85 const auto mouse_change = Common::MakeVec(x, y) - Common::MakeVec(center_x, center_y);
86 mouse_panning_timout = 0;
87
88 if (mouse_change.y == 0 && mouse_change.x == 0) {
89 continue;
90 }
91
92 info.last_mouse_change = (info.last_mouse_change * 0.8f) + (mouse_change * 0.2f);
93 info.data.axis = {static_cast<int>(16 * info.last_mouse_change.x),
94 static_cast<int>(16 * -info.last_mouse_change.y)};
95 info.tilt_direction = info.last_mouse_change;
96 info.tilt_speed = info.tilt_direction.Normalize() * info.sensitivity;
97 continue;
98 }
99
70 if (info.data.pressed) { 100 if (info.data.pressed) {
71 const auto mouse_move = Common::MakeVec(x, y) - info.mouse_origin; 101 const auto mouse_move = Common::MakeVec(x, y) - info.mouse_origin;
72 const auto mouse_change = Common::MakeVec(x, y) - info.last_mouse_position; 102 const auto mouse_change = Common::MakeVec(x, y) - info.last_mouse_position;
diff --git a/src/input_common/mouse/mouse_input.h b/src/input_common/mouse/mouse_input.h
index 58803c1bf..46aa676c1 100644
--- a/src/input_common/mouse/mouse_input.h
+++ b/src/input_common/mouse/mouse_input.h
@@ -57,8 +57,10 @@ public:
57 * Signals that mouse has moved. 57 * Signals that mouse has moved.
58 * @param x the x-coordinate of the cursor 58 * @param x the x-coordinate of the cursor
59 * @param y the y-coordinate of the cursor 59 * @param y the y-coordinate of the cursor
60 * @param center_x the x-coordinate of the middle of the screen
61 * @param center_y the y-coordinate of the middle of the screen
60 */ 62 */
61 void MouseMove(int x, int y); 63 void MouseMove(int x, int y, int center_x, int center_y);
62 64
63 /** 65 /**
64 * Signals that a motion sensor tilt has ended. 66 * Signals that a motion sensor tilt has ended.
@@ -74,11 +76,13 @@ public:
74private: 76private:
75 void UpdateThread(); 77 void UpdateThread();
76 void UpdateYuzuSettings(); 78 void UpdateYuzuSettings();
79 void StopPanning();
77 80
78 struct MouseInfo { 81 struct MouseInfo {
79 InputCommon::MotionInput motion{0.0f, 0.0f, 0.0f}; 82 InputCommon::MotionInput motion{0.0f, 0.0f, 0.0f};
80 Common::Vec2<int> mouse_origin; 83 Common::Vec2<int> mouse_origin;
81 Common::Vec2<int> last_mouse_position; 84 Common::Vec2<int> last_mouse_position;
85 Common::Vec2<float> last_mouse_change;
82 bool is_tilting = false; 86 bool is_tilting = false;
83 float sensitivity{0.120f}; 87 float sensitivity{0.120f};
84 88
@@ -94,5 +98,6 @@ private:
94 Common::SPSCQueue<MouseStatus> mouse_queue; 98 Common::SPSCQueue<MouseStatus> mouse_queue;
95 bool configuring{false}; 99 bool configuring{false};
96 bool update_thread_running{true}; 100 bool update_thread_running{true};
101 int mouse_panning_timout{};
97}; 102};
98} // namespace MouseInput 103} // namespace MouseInput
diff --git a/src/input_common/mouse/mouse_poller.cpp b/src/input_common/mouse/mouse_poller.cpp
index 3d799b293..bb56787ee 100644
--- a/src/input_common/mouse/mouse_poller.cpp
+++ b/src/input_common/mouse/mouse_poller.cpp
@@ -6,6 +6,7 @@
6#include <utility> 6#include <utility>
7 7
8#include "common/threadsafe_queue.h" 8#include "common/threadsafe_queue.h"
9#include "core/settings.h"
9#include "input_common/mouse/mouse_input.h" 10#include "input_common/mouse/mouse_input.h"
10#include "input_common/mouse/mouse_poller.h" 11#include "input_common/mouse/mouse_poller.h"
11 12
@@ -71,7 +72,7 @@ public:
71 std::lock_guard lock{mutex}; 72 std::lock_guard lock{mutex};
72 const auto axis_value = 73 const auto axis_value =
73 static_cast<float>(mouse_input->GetMouseState(button).axis.at(axis)); 74 static_cast<float>(mouse_input->GetMouseState(button).axis.at(axis));
74 return axis_value / (100.0f * range); 75 return axis_value * Settings::values.mouse_panning_sensitivity / (100.0f * range);
75 } 76 }
76 77
77 std::pair<float, float> GetAnalog(u32 analog_axis_x, u32 analog_axis_y) const { 78 std::pair<float, float> GetAnalog(u32 analog_axis_x, u32 analog_axis_y) const {
diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp
index ffdf34a4a..d9a3035cb 100644
--- a/src/yuzu/bootmanager.cpp
+++ b/src/yuzu/bootmanager.cpp
@@ -405,12 +405,17 @@ void GRenderWindow::mouseMoveEvent(QMouseEvent* event) {
405 if (event->source() == Qt::MouseEventSynthesizedBySystem) { 405 if (event->source() == Qt::MouseEventSynthesizedBySystem) {
406 return; 406 return;
407 } 407 }
408
409 auto pos = event->pos(); 408 auto pos = event->pos();
410 const auto [x, y] = ScaleTouch(pos); 409 const auto [x, y] = ScaleTouch(pos);
411 input_subsystem->GetMouse()->MouseMove(x, y); 410 const int center_x = width() / 2;
411 const int center_y = height() / 2;
412 input_subsystem->GetMouse()->MouseMove(x, y, center_x, center_y);
412 this->TouchMoved(x, y, 0); 413 this->TouchMoved(x, y, 0);
413 414
415 if (Settings::values.mouse_panning) {
416 QCursor::setPos(mapToGlobal({center_x, center_y}));
417 }
418
414 emit MouseActivity(); 419 emit MouseActivity();
415} 420}
416 421
@@ -714,6 +719,11 @@ void GRenderWindow::showEvent(QShowEvent* event) {
714 719
715bool GRenderWindow::eventFilter(QObject* object, QEvent* event) { 720bool GRenderWindow::eventFilter(QObject* object, QEvent* event) {
716 if (event->type() == QEvent::HoverMove) { 721 if (event->type() == QEvent::HoverMove) {
722 if (Settings::values.mouse_panning) {
723 auto* hover_event = static_cast<QMouseEvent*>(event);
724 mouseMoveEvent(hover_event);
725 return false;
726 }
717 emit MouseActivity(); 727 emit MouseActivity();
718 } 728 }
719 return false; 729 return false;
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp
index 8d85a1986..8f7458119 100644
--- a/src/yuzu/configuration/config.cpp
+++ b/src/yuzu/configuration/config.cpp
@@ -220,7 +220,7 @@ const std::array<int, Settings::NativeKeyboard::NumKeyboardMods> Config::default
220// This must be in alphabetical order according to action name as it must have the same order as 220// This must be in alphabetical order according to action name as it must have the same order as
221// UISetting::values.shortcuts, which is alphabetically ordered. 221// UISetting::values.shortcuts, which is alphabetically ordered.
222// clang-format off 222// clang-format off
223const std::array<UISettings::Shortcut, 16> Config::default_hotkeys{{ 223const std::array<UISettings::Shortcut, 17> Config::default_hotkeys{{
224 {QStringLiteral("Capture Screenshot"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+P"), Qt::WidgetWithChildrenShortcut}}, 224 {QStringLiteral("Capture Screenshot"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+P"), Qt::WidgetWithChildrenShortcut}},
225 {QStringLiteral("Change Docked Mode"), QStringLiteral("Main Window"), {QStringLiteral("F10"), Qt::ApplicationShortcut}}, 225 {QStringLiteral("Change Docked Mode"), QStringLiteral("Main Window"), {QStringLiteral("F10"), Qt::ApplicationShortcut}},
226 {QStringLiteral("Continue/Pause Emulation"), QStringLiteral("Main Window"), {QStringLiteral("F4"), Qt::WindowShortcut}}, 226 {QStringLiteral("Continue/Pause Emulation"), QStringLiteral("Main Window"), {QStringLiteral("F4"), Qt::WindowShortcut}},
@@ -235,6 +235,7 @@ const std::array<UISettings::Shortcut, 16> Config::default_hotkeys{{
235 {QStringLiteral("Restart Emulation"), QStringLiteral("Main Window"), {QStringLiteral("F6"), Qt::WindowShortcut}}, 235 {QStringLiteral("Restart Emulation"), QStringLiteral("Main Window"), {QStringLiteral("F6"), Qt::WindowShortcut}},
236 {QStringLiteral("Stop Emulation"), QStringLiteral("Main Window"), {QStringLiteral("F5"), Qt::WindowShortcut}}, 236 {QStringLiteral("Stop Emulation"), QStringLiteral("Main Window"), {QStringLiteral("F5"), Qt::WindowShortcut}},
237 {QStringLiteral("Toggle Filter Bar"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+F"), Qt::WindowShortcut}}, 237 {QStringLiteral("Toggle Filter Bar"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+F"), Qt::WindowShortcut}},
238 {QStringLiteral("Toggle Mouse Panning"), QStringLiteral("Main Window"), {QStringLiteral("F9"), Qt::ApplicationShortcut}},
238 {QStringLiteral("Toggle Speed Limit"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+Z"), Qt::ApplicationShortcut}}, 239 {QStringLiteral("Toggle Speed Limit"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+Z"), Qt::ApplicationShortcut}},
239 {QStringLiteral("Toggle Status Bar"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+S"), Qt::WindowShortcut}}, 240 {QStringLiteral("Toggle Status Bar"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+S"), Qt::WindowShortcut}},
240}}; 241}};
@@ -507,6 +508,9 @@ void Config::ReadControlValues() {
507 508
508 Settings::values.emulate_analog_keyboard = 509 Settings::values.emulate_analog_keyboard =
509 ReadSetting(QStringLiteral("emulate_analog_keyboard"), false).toBool(); 510 ReadSetting(QStringLiteral("emulate_analog_keyboard"), false).toBool();
511 Settings::values.mouse_panning = ReadSetting(QStringLiteral("mouse_panning"), false).toBool();
512 Settings::values.mouse_panning_sensitivity =
513 ReadSetting(QStringLiteral("mouse_panning_sensitivity"), 1).toFloat();
510 514
511 ReadSettingGlobal(Settings::values.use_docked_mode, QStringLiteral("use_docked_mode"), true); 515 ReadSettingGlobal(Settings::values.use_docked_mode, QStringLiteral("use_docked_mode"), true);
512 ReadSettingGlobal(Settings::values.vibration_enabled, QStringLiteral("vibration_enabled"), 516 ReadSettingGlobal(Settings::values.vibration_enabled, QStringLiteral("vibration_enabled"),
@@ -1184,7 +1188,9 @@ void Config::SaveControlValues() {
1184 WriteSetting(QStringLiteral("keyboard_enabled"), Settings::values.keyboard_enabled, false); 1188 WriteSetting(QStringLiteral("keyboard_enabled"), Settings::values.keyboard_enabled, false);
1185 WriteSetting(QStringLiteral("emulate_analog_keyboard"), 1189 WriteSetting(QStringLiteral("emulate_analog_keyboard"),
1186 Settings::values.emulate_analog_keyboard, false); 1190 Settings::values.emulate_analog_keyboard, false);
1187 1191 WriteSetting(QStringLiteral("mouse_panning"), Settings::values.mouse_panning, false);
1192 WriteSetting(QStringLiteral("mouse_panning_sensitivity"),
1193 Settings::values.mouse_panning_sensitivity, 1.0f);
1188 qt_config->endGroup(); 1194 qt_config->endGroup();
1189} 1195}
1190 1196
diff --git a/src/yuzu/configuration/config.h b/src/yuzu/configuration/config.h
index 8a600e19d..949c4eb13 100644
--- a/src/yuzu/configuration/config.h
+++ b/src/yuzu/configuration/config.h
@@ -42,7 +42,7 @@ public:
42 default_mouse_buttons; 42 default_mouse_buttons;
43 static const std::array<int, Settings::NativeKeyboard::NumKeyboardKeys> default_keyboard_keys; 43 static const std::array<int, Settings::NativeKeyboard::NumKeyboardKeys> default_keyboard_keys;
44 static const std::array<int, Settings::NativeKeyboard::NumKeyboardMods> default_keyboard_mods; 44 static const std::array<int, Settings::NativeKeyboard::NumKeyboardMods> default_keyboard_mods;
45 static const std::array<UISettings::Shortcut, 16> default_hotkeys; 45 static const std::array<UISettings::Shortcut, 17> default_hotkeys;
46 46
47private: 47private:
48 void Initialize(const std::string& config_name); 48 void Initialize(const std::string& config_name);
diff --git a/src/yuzu/configuration/configure_input_advanced.cpp b/src/yuzu/configuration/configure_input_advanced.cpp
index 4e557bc6f..a1a0eb676 100644
--- a/src/yuzu/configuration/configure_input_advanced.cpp
+++ b/src/yuzu/configuration/configure_input_advanced.cpp
@@ -122,6 +122,9 @@ void ConfigureInputAdvanced::ApplyConfiguration() {
122 Settings::values.mouse_enabled = ui->mouse_enabled->isChecked(); 122 Settings::values.mouse_enabled = ui->mouse_enabled->isChecked();
123 Settings::values.keyboard_enabled = ui->keyboard_enabled->isChecked(); 123 Settings::values.keyboard_enabled = ui->keyboard_enabled->isChecked();
124 Settings::values.emulate_analog_keyboard = ui->emulate_analog_keyboard->isChecked(); 124 Settings::values.emulate_analog_keyboard = ui->emulate_analog_keyboard->isChecked();
125 Settings::values.mouse_panning = ui->mouse_panning->isChecked();
126 Settings::values.mouse_panning_sensitivity =
127 static_cast<float>(ui->mouse_panning_sensitivity->value());
125 Settings::values.touchscreen.enabled = ui->touchscreen_enabled->isChecked(); 128 Settings::values.touchscreen.enabled = ui->touchscreen_enabled->isChecked();
126} 129}
127 130
@@ -149,6 +152,8 @@ void ConfigureInputAdvanced::LoadConfiguration() {
149 ui->mouse_enabled->setChecked(Settings::values.mouse_enabled); 152 ui->mouse_enabled->setChecked(Settings::values.mouse_enabled);
150 ui->keyboard_enabled->setChecked(Settings::values.keyboard_enabled); 153 ui->keyboard_enabled->setChecked(Settings::values.keyboard_enabled);
151 ui->emulate_analog_keyboard->setChecked(Settings::values.emulate_analog_keyboard); 154 ui->emulate_analog_keyboard->setChecked(Settings::values.emulate_analog_keyboard);
155 ui->mouse_panning->setChecked(Settings::values.mouse_panning);
156 ui->mouse_panning_sensitivity->setValue(Settings::values.mouse_panning_sensitivity);
152 ui->touchscreen_enabled->setChecked(Settings::values.touchscreen.enabled); 157 ui->touchscreen_enabled->setChecked(Settings::values.touchscreen.enabled);
153 158
154 UpdateUIEnabled(); 159 UpdateUIEnabled();
diff --git a/src/yuzu/configuration/configure_input_advanced.ui b/src/yuzu/configuration/configure_input_advanced.ui
index f207e5d3b..173130d8d 100644
--- a/src/yuzu/configuration/configure_input_advanced.ui
+++ b/src/yuzu/configuration/configure_input_advanced.ui
@@ -2546,27 +2546,65 @@
2546 </property> 2546 </property>
2547 </widget> 2547 </widget>
2548 </item> 2548 </item>
2549 <item row="1" column="0"> 2549 <item row="1" column="0">
2550 <widget class="QCheckBox" name="emulate_analog_keyboard"> 2550 <widget class="QCheckBox" name="emulate_analog_keyboard">
2551 <property name="minimumSize"> 2551 <property name="minimumSize">
2552 <size> 2552 <size>
2553 <width>0</width> 2553 <width>0</width>
2554 <height>23</height> 2554 <height>23</height>
2555 </size> 2555 </size>
2556 </property> 2556 </property>
2557 <property name="text"> 2557 <property name="text">
2558 <string>Emulate Analog with Keyboard Input</string> 2558 <string>Emulate Analog with Keyboard Input</string>
2559 </property> 2559 </property>
2560 </widget> 2560 </widget>
2561 </item> 2561 </item>
2562 <item row="5" column="2"> 2562 <item row="2" column="0">
2563 <widget class="QCheckBox" name="mouse_panning">
2564 <property name="minimumSize">
2565 <size>
2566 <width>0</width>
2567 <height>23</height>
2568 </size>
2569 </property>
2570 <property name="text">
2571 <string>Enable mouse panning</string>
2572 </property>
2573 </widget>
2574 </item>
2575 <item row="2" column="2">
2576 <widget class="QDoubleSpinBox" name="mouse_panning_sensitivity">
2577 <property name="toolTip">
2578 <string>Mouse sensitivity</string>
2579 </property>
2580 <property name="alignment">
2581 <set>Qt::AlignCenter</set>
2582 </property>
2583 <property name="decimals">
2584 <number>2</number>
2585 </property>
2586 <property name="minimum">
2587 <double>0.100000000000000</double>
2588 </property>
2589 <property name="maximum">
2590 <double>16.000000000000000</double>
2591 </property>
2592 <property name="singleStep">
2593 <double>0.010000000000000</double>
2594 </property>
2595 <property name="value">
2596 <double>1.000000000000000</double>
2597 </property>
2598 </widget>
2599 </item>
2600 <item row="6" column="2">
2563 <widget class="QPushButton" name="touchscreen_advanced"> 2601 <widget class="QPushButton" name="touchscreen_advanced">
2564 <property name="text"> 2602 <property name="text">
2565 <string>Advanced</string> 2603 <string>Advanced</string>
2566 </property> 2604 </property>
2567 </widget> 2605 </widget>
2568 </item> 2606 </item>
2569 <item row="2" column="1"> 2607 <item row="3" column="1">
2570 <spacer name="horizontalSpacer_8"> 2608 <spacer name="horizontalSpacer_8">
2571 <property name="orientation"> 2609 <property name="orientation">
2572 <enum>Qt::Horizontal</enum> 2610 <enum>Qt::Horizontal</enum>
@@ -2582,21 +2620,21 @@
2582 </property> 2620 </property>
2583 </spacer> 2621 </spacer>
2584 </item> 2622 </item>
2585 <item row="2" column="2"> 2623 <item row="3" column="2">
2586 <widget class="QPushButton" name="mouse_advanced"> 2624 <widget class="QPushButton" name="mouse_advanced">
2587 <property name="text"> 2625 <property name="text">
2588 <string>Advanced</string> 2626 <string>Advanced</string>
2589 </property> 2627 </property>
2590 </widget> 2628 </widget>
2591 </item> 2629 </item>
2592 <item row="5" column="0"> 2630 <item row="6" column="0">
2593 <widget class="QCheckBox" name="touchscreen_enabled"> 2631 <widget class="QCheckBox" name="touchscreen_enabled">
2594 <property name="text"> 2632 <property name="text">
2595 <string>Touchscreen</string> 2633 <string>Touchscreen</string>
2596 </property> 2634 </property>
2597 </widget> 2635 </widget>
2598 </item> 2636 </item>
2599 <item row="2" column="0"> 2637 <item row="3" column="0">
2600 <widget class="QCheckBox" name="mouse_enabled"> 2638 <widget class="QCheckBox" name="mouse_enabled">
2601 <property name="minimumSize"> 2639 <property name="minimumSize">
2602 <size> 2640 <size>
@@ -2609,28 +2647,28 @@
2609 </property> 2647 </property>
2610 </widget> 2648 </widget>
2611 </item> 2649 </item>
2612 <item row="7" column="0"> 2650 <item row="8" column="0">
2613 <widget class="QLabel" name="motion_touch"> 2651 <widget class="QLabel" name="motion_touch">
2614 <property name="text"> 2652 <property name="text">
2615 <string>Motion / Touch</string> 2653 <string>Motion / Touch</string>
2616 </property> 2654 </property>
2617 </widget> 2655 </widget>
2618 </item> 2656 </item>
2619 <item row="7" column="2"> 2657 <item row="8" column="2">
2620 <widget class="QPushButton" name="buttonMotionTouch"> 2658 <widget class="QPushButton" name="buttonMotionTouch">
2621 <property name="text"> 2659 <property name="text">
2622 <string>Configure</string> 2660 <string>Configure</string>
2623 </property> 2661 </property>
2624 </widget> 2662 </widget>
2625 </item> 2663 </item>
2626 <item row="6" column="0"> 2664 <item row="7" column="0">
2627 <widget class="QCheckBox" name="debug_enabled"> 2665 <widget class="QCheckBox" name="debug_enabled">
2628 <property name="text"> 2666 <property name="text">
2629 <string>Debug Controller</string> 2667 <string>Debug Controller</string>
2630 </property> 2668 </property>
2631 </widget> 2669 </widget>
2632 </item> 2670 </item>
2633 <item row="6" column="2"> 2671 <item row="7" column="2">
2634 <widget class="QPushButton" name="debug_configure"> 2672 <widget class="QPushButton" name="debug_configure">
2635 <property name="text"> 2673 <property name="text">
2636 <string>Configure</string> 2674 <string>Configure</string>
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index ef92c25bc..52218eb70 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -850,6 +850,16 @@ void GMainWindow::InitializeHotkeys() {
850 connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Mute Audio"), this), 850 connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Mute Audio"), this),
851 &QShortcut::activated, this, 851 &QShortcut::activated, this,
852 [] { Settings::values.audio_muted = !Settings::values.audio_muted; }); 852 [] { Settings::values.audio_muted = !Settings::values.audio_muted; });
853
854 connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Toggle Mouse Panning"), this),
855 &QShortcut::activated, this, [&] {
856 Settings::values.mouse_panning = !Settings::values.mouse_panning;
857 if (UISettings::values.hide_mouse || Settings::values.mouse_panning) {
858 mouse_hide_timer.start();
859 render_window->installEventFilter(render_window);
860 render_window->setAttribute(Qt::WA_Hover, true);
861 }
862 });
853} 863}
854 864
855void GMainWindow::SetDefaultUIGeometry() { 865void GMainWindow::SetDefaultUIGeometry() {
@@ -1197,7 +1207,7 @@ void GMainWindow::BootGame(const QString& filename, std::size_t program_index) {
1197 multicore_status_button->setDisabled(true); 1207 multicore_status_button->setDisabled(true);
1198 renderer_status_button->setDisabled(true); 1208 renderer_status_button->setDisabled(true);
1199 1209
1200 if (UISettings::values.hide_mouse) { 1210 if (UISettings::values.hide_mouse || Settings::values.mouse_panning) {
1201 mouse_hide_timer.start(); 1211 mouse_hide_timer.start();
1202 render_window->installEventFilter(render_window); 1212 render_window->installEventFilter(render_window);
1203 render_window->setAttribute(Qt::WA_Hover, true); 1213 render_window->setAttribute(Qt::WA_Hover, true);
@@ -2359,7 +2369,7 @@ void GMainWindow::OnConfigure() {
2359 2369
2360 config->Save(); 2370 config->Save();
2361 2371
2362 if (UISettings::values.hide_mouse && emulation_running) { 2372 if ((UISettings::values.hide_mouse || Settings::values.mouse_panning) && emulation_running) {
2363 render_window->installEventFilter(render_window); 2373 render_window->installEventFilter(render_window);
2364 render_window->setAttribute(Qt::WA_Hover, true); 2374 render_window->setAttribute(Qt::WA_Hover, true);
2365 mouse_hide_timer.start(); 2375 mouse_hide_timer.start();
@@ -2600,7 +2610,8 @@ void GMainWindow::UpdateUISettings() {
2600} 2610}
2601 2611
2602void GMainWindow::HideMouseCursor() { 2612void GMainWindow::HideMouseCursor() {
2603 if (emu_thread == nullptr || UISettings::values.hide_mouse == false) { 2613 if (emu_thread == nullptr ||
2614 (!UISettings::values.hide_mouse && !Settings::values.mouse_panning)) {
2604 mouse_hide_timer.stop(); 2615 mouse_hide_timer.stop();
2605 ShowMouseCursor(); 2616 ShowMouseCursor();
2606 return; 2617 return;
@@ -2610,13 +2621,16 @@ void GMainWindow::HideMouseCursor() {
2610 2621
2611void GMainWindow::ShowMouseCursor() { 2622void GMainWindow::ShowMouseCursor() {
2612 render_window->unsetCursor(); 2623 render_window->unsetCursor();
2613 if (emu_thread != nullptr && UISettings::values.hide_mouse) { 2624 if (emu_thread != nullptr &&
2625 (UISettings::values.hide_mouse || Settings::values.mouse_panning)) {
2614 mouse_hide_timer.start(); 2626 mouse_hide_timer.start();
2615 } 2627 }
2616} 2628}
2617 2629
2618void GMainWindow::OnMouseActivity() { 2630void GMainWindow::OnMouseActivity() {
2619 ShowMouseCursor(); 2631 if (!Settings::values.mouse_panning) {
2632 ShowMouseCursor();
2633 }
2620} 2634}
2621 2635
2622void GMainWindow::OnCoreError(Core::System::ResultStatus result, std::string details) { 2636void GMainWindow::OnCoreError(Core::System::ResultStatus result, std::string details) {
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp
index 7843d5167..39841aa28 100644
--- a/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp
+++ b/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp
@@ -30,7 +30,8 @@ EmuWindow_SDL2::~EmuWindow_SDL2() {
30 30
31void EmuWindow_SDL2::OnMouseMotion(s32 x, s32 y) { 31void EmuWindow_SDL2::OnMouseMotion(s32 x, s32 y) {
32 TouchMoved((unsigned)std::max(x, 0), (unsigned)std::max(y, 0), 0); 32 TouchMoved((unsigned)std::max(x, 0), (unsigned)std::max(y, 0), 0);
33 input_subsystem->GetMouse()->MouseMove(x, y); 33
34 input_subsystem->GetMouse()->MouseMove(x, y, 0, 0);
34} 35}
35 36
36void EmuWindow_SDL2::OnMouseButton(u32 button, u8 state, s32 x, s32 y) { 37void EmuWindow_SDL2::OnMouseButton(u32 button, u8 state, s32 x, s32 y) {