From 4738e14cb052a44c53e47379e595f00cef034dca Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Tue, 23 Feb 2021 20:39:02 -0600
Subject: [PATCH] inputCommon: Mouse fixes

---
 src/input_common/mouse/mouse_input.cpp        | 11 +++++---
 src/input_common/mouse/mouse_input.h          | 12 +++++----
 src/yuzu/bootmanager.cpp                      | 25 +++++++++++++++++--
 src/yuzu/bootmanager.h                        |  7 ++++++
 src/yuzu/configuration/config.cpp             |  5 ++--
 .../configuration/configure_input_player.cpp  |  4 ++-
 src/yuzu/main.cpp                             | 19 ++++++++------
 src/yuzu_cmd/emu_window/emu_window_sdl2.cpp   | 24 +++++++++++++++---
 src/yuzu_cmd/emu_window/emu_window_sdl2.h     |  7 ++++++
 9 files changed, 89 insertions(+), 25 deletions(-)

diff --git a/src/input_common/mouse/mouse_input.cpp b/src/input_common/mouse/mouse_input.cpp
index b864d26f2..d81e790ee 100644
--- a/src/input_common/mouse/mouse_input.cpp
+++ b/src/input_common/mouse/mouse_input.cpp
@@ -59,7 +59,7 @@ void Mouse::UpdateYuzuSettings() {
     });
 }
 
-void Mouse::PressButton(int x, int y, int button_) {
+void Mouse::PressButton(int x, int y, MouseButton button_) {
     const auto button_index = static_cast<std::size_t>(button_);
     if (button_index >= mouse_info.size()) {
         return;
@@ -67,7 +67,7 @@ void Mouse::PressButton(int x, int y, int button_) {
 
     const auto button = 1U << button_index;
     buttons |= static_cast<u16>(button);
-    last_button = static_cast<MouseButton>(button_index);
+    last_button = button_;
 
     mouse_info[button_index].mouse_origin = Common::MakeVec(x, y);
     mouse_info[button_index].last_mouse_position = Common::MakeVec(x, y);
@@ -129,7 +129,7 @@ void Mouse::MouseMove(int x, int y, int center_x, int center_y) {
     }
 }
 
-void Mouse::ReleaseButton(int button_) {
+void Mouse::ReleaseButton(MouseButton button_) {
     const auto button_index = static_cast<std::size_t>(button_);
     if (button_index >= mouse_info.size()) {
         return;
@@ -152,6 +152,11 @@ void Mouse::BeginConfiguration() {
 
 void Mouse::EndConfiguration() {
     buttons = 0;
+    for (MouseInfo& info : mouse_info) {
+        info.tilt_speed = 0;
+        info.data.pressed = false;
+        info.data.axis = {0, 0};
+    }
     last_button = MouseButton::Undefined;
     mouse_queue.Clear();
     configuring = false;
diff --git a/src/input_common/mouse/mouse_input.h b/src/input_common/mouse/mouse_input.h
index 46aa676c1..3622fe080 100644
--- a/src/input_common/mouse/mouse_input.h
+++ b/src/input_common/mouse/mouse_input.h
@@ -18,10 +18,12 @@ namespace MouseInput {
 
 enum class MouseButton {
     Left,
-    Wheel,
     Right,
-    Forward,
+    Wheel,
     Backward,
+    Forward,
+    Task,
+    Extra,
     Undefined,
 };
 
@@ -51,7 +53,7 @@ public:
      * @param y the y-coordinate of the cursor
      * @param button_ the button pressed
      */
-    void PressButton(int x, int y, int button_);
+    void PressButton(int x, int y, MouseButton button_);
 
     /**
      * Signals that mouse has moved.
@@ -65,7 +67,7 @@ public:
     /**
      * Signals that a motion sensor tilt has ended.
      */
-    void ReleaseButton(int button_);
+    void ReleaseButton(MouseButton button_);
 
     [[nodiscard]] Common::SPSCQueue<MouseStatus>& GetMouseQueue();
     [[nodiscard]] const Common::SPSCQueue<MouseStatus>& GetMouseQueue() const;
@@ -94,7 +96,7 @@ private:
     u16 buttons{};
     std::thread update_thread;
     MouseButton last_button{MouseButton::Undefined};
-    std::array<MouseInfo, 5> mouse_info;
+    std::array<MouseInfo, 7> mouse_info;
     Common::SPSCQueue<MouseStatus> mouse_queue;
     bool configuring{false};
     bool update_thread_running{true};
diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp
index 1c61d419d..ae49cbb45 100644
--- a/src/yuzu/bootmanager.cpp
+++ b/src/yuzu/bootmanager.cpp
@@ -383,6 +383,25 @@ void GRenderWindow::keyReleaseEvent(QKeyEvent* event) {
     input_subsystem->GetKeyboard()->ReleaseKey(event->key());
 }
 
+MouseInput::MouseButton GRenderWindow::QtButtonToMouseButton(Qt::MouseButton button) {
+    switch (button) {
+    case Qt::LeftButton:
+        return MouseInput::MouseButton::Left;
+    case Qt::RightButton:
+        return MouseInput::MouseButton::Right;
+    case Qt::MiddleButton:
+        return MouseInput::MouseButton::Wheel;
+    case Qt::BackButton:
+        return MouseInput::MouseButton::Backward;
+    case Qt::ForwardButton:
+        return MouseInput::MouseButton::Forward;
+    case Qt::TaskButton:
+        return MouseInput::MouseButton::Task;
+    default:
+        return MouseInput::MouseButton::Extra;
+    }
+}
+
 void GRenderWindow::mousePressEvent(QMouseEvent* event) {
     // Touch input is handled in TouchBeginEvent
     if (event->source() == Qt::MouseEventSynthesizedBySystem) {
@@ -391,7 +410,8 @@ void GRenderWindow::mousePressEvent(QMouseEvent* event) {
 
     auto pos = event->pos();
     const auto [x, y] = ScaleTouch(pos);
-    input_subsystem->GetMouse()->PressButton(x, y, event->button());
+    const auto button = QtButtonToMouseButton(event->button());
+    input_subsystem->GetMouse()->PressButton(x, y, button);
 
     if (event->button() == Qt::LeftButton) {
         this->TouchPressed(x, y, 0);
@@ -425,7 +445,8 @@ void GRenderWindow::mouseReleaseEvent(QMouseEvent* event) {
         return;
     }
 
-    input_subsystem->GetMouse()->ReleaseButton(event->button());
+    const auto button = QtButtonToMouseButton(event->button());
+    input_subsystem->GetMouse()->ReleaseButton(button);
 
     if (event->button() == Qt::LeftButton) {
         this->TouchReleased(0);
diff --git a/src/yuzu/bootmanager.h b/src/yuzu/bootmanager.h
index b5ec7de07..acfe2bc8c 100644
--- a/src/yuzu/bootmanager.h
+++ b/src/yuzu/bootmanager.h
@@ -28,6 +28,10 @@ namespace InputCommon {
 class InputSubsystem;
 }
 
+namespace MouseInput {
+enum class MouseButton;
+}
+
 namespace VideoCore {
 enum class LoadCallbackStage;
 }
@@ -149,6 +153,9 @@ public:
     void keyPressEvent(QKeyEvent* event) override;
     void keyReleaseEvent(QKeyEvent* event) override;
 
+    /// Converts a Qt mouse button into MouseInput mouse button
+    static MouseInput::MouseButton QtButtonToMouseButton(Qt::MouseButton button);
+
     void mousePressEvent(QMouseEvent* event) override;
     void mouseMoveEvent(QMouseEvent* event) override;
     void mouseReleaseEvent(QMouseEvent* event) override;
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp
index 3d6f64300..e6537d295 100644
--- a/src/yuzu/configuration/config.cpp
+++ b/src/yuzu/configuration/config.cpp
@@ -235,7 +235,7 @@ const std::array<UISettings::Shortcut, 17> Config::default_hotkeys{{
     {QStringLiteral("Restart Emulation"),        QStringLiteral("Main Window"), {QStringLiteral("F6"), Qt::WindowShortcut}},
     {QStringLiteral("Stop Emulation"),           QStringLiteral("Main Window"), {QStringLiteral("F5"), Qt::WindowShortcut}},
     {QStringLiteral("Toggle Filter Bar"),        QStringLiteral("Main Window"), {QStringLiteral("Ctrl+F"), Qt::WindowShortcut}},
-    {QStringLiteral("Toggle Mouse Panning"),     QStringLiteral("Main Window"), {QStringLiteral("F9"), Qt::ApplicationShortcut}},
+    {QStringLiteral("Toggle Mouse Panning"),     QStringLiteral("Main Window"), {QStringLiteral("Ctrl+F9"), Qt::ApplicationShortcut}},
     {QStringLiteral("Toggle Speed Limit"),       QStringLiteral("Main Window"), {QStringLiteral("Ctrl+Z"), Qt::ApplicationShortcut}},
     {QStringLiteral("Toggle Status Bar"),        QStringLiteral("Main Window"), {QStringLiteral("Ctrl+S"), Qt::WindowShortcut}},
 }};
@@ -508,7 +508,7 @@ void Config::ReadControlValues() {
 
     Settings::values.emulate_analog_keyboard =
         ReadSetting(QStringLiteral("emulate_analog_keyboard"), false).toBool();
-    Settings::values.mouse_panning = ReadSetting(QStringLiteral("mouse_panning"), false).toBool();
+    Settings::values.mouse_panning = false;
     Settings::values.mouse_panning_sensitivity =
         ReadSetting(QStringLiteral("mouse_panning_sensitivity"), 1).toFloat();
 
@@ -1182,7 +1182,6 @@ void Config::SaveControlValues() {
     WriteSetting(QStringLiteral("keyboard_enabled"), Settings::values.keyboard_enabled, false);
     WriteSetting(QStringLiteral("emulate_analog_keyboard"),
                  Settings::values.emulate_analog_keyboard, false);
-    WriteSetting(QStringLiteral("mouse_panning"), Settings::values.mouse_panning, false);
     WriteSetting(QStringLiteral("mouse_panning_sensitivity"),
                  Settings::values.mouse_panning_sensitivity, 1.0f);
     qt_config->endGroup();
diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp
index 21d0d3449..bc572d319 100644
--- a/src/yuzu/configuration/configure_input_player.cpp
+++ b/src/yuzu/configuration/configure_input_player.cpp
@@ -21,6 +21,7 @@
 #include "input_common/mouse/mouse_poller.h"
 #include "input_common/udp/udp.h"
 #include "ui_configure_input_player.h"
+#include "yuzu/bootmanager.h"
 #include "yuzu/configuration/config.h"
 #include "yuzu/configuration/configure_input_player.h"
 #include "yuzu/configuration/configure_input_player_widget.h"
@@ -1345,7 +1346,8 @@ void ConfigureInputPlayer::mousePressEvent(QMouseEvent* event) {
         return;
     }
 
-    input_subsystem->GetMouse()->PressButton(0, 0, event->button());
+    const auto button = GRenderWindow::QtButtonToMouseButton(event->button());
+    input_subsystem->GetMouse()->PressButton(0, 0, button);
 }
 
 void ConfigureInputPlayer::keyPressEvent(QKeyEvent* event) {
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 0ba7c07cc..56d892a31 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -854,8 +854,7 @@ void GMainWindow::InitializeHotkeys() {
     connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Toggle Mouse Panning"), this),
             &QShortcut::activated, this, [&] {
                 Settings::values.mouse_panning = !Settings::values.mouse_panning;
-                if (UISettings::values.hide_mouse || Settings::values.mouse_panning) {
-                    mouse_hide_timer.start();
+                if (Settings::values.mouse_panning) {
                     render_window->installEventFilter(render_window);
                     render_window->setAttribute(Qt::WA_Hover, true);
                 }
@@ -1208,11 +1207,14 @@ void GMainWindow::BootGame(const QString& filename, std::size_t program_index) {
     renderer_status_button->setDisabled(true);
 
     if (UISettings::values.hide_mouse || Settings::values.mouse_panning) {
-        mouse_hide_timer.start();
         render_window->installEventFilter(render_window);
         render_window->setAttribute(Qt::WA_Hover, true);
     }
 
+    if (UISettings::values.hide_mouse) {
+        mouse_hide_timer.start();
+    }
+
     std::string title_name;
     std::string title_version;
     const auto res = system.GetGameName(title_name);
@@ -2372,12 +2374,15 @@ void GMainWindow::OnConfigure() {
     if ((UISettings::values.hide_mouse || Settings::values.mouse_panning) && emulation_running) {
         render_window->installEventFilter(render_window);
         render_window->setAttribute(Qt::WA_Hover, true);
-        mouse_hide_timer.start();
     } else {
         render_window->removeEventFilter(render_window);
         render_window->setAttribute(Qt::WA_Hover, false);
     }
 
+    if (UISettings::values.hide_mouse) {
+        mouse_hide_timer.start();
+    }
+
     UpdateStatusButtons();
 }
 
@@ -2615,8 +2620,7 @@ void GMainWindow::UpdateUISettings() {
 }
 
 void GMainWindow::HideMouseCursor() {
-    if (emu_thread == nullptr ||
-        (!UISettings::values.hide_mouse && !Settings::values.mouse_panning)) {
+    if (emu_thread == nullptr && UISettings::values.hide_mouse) {
         mouse_hide_timer.stop();
         ShowMouseCursor();
         return;
@@ -2626,8 +2630,7 @@ void GMainWindow::HideMouseCursor() {
 
 void GMainWindow::ShowMouseCursor() {
     render_window->unsetCursor();
-    if (emu_thread != nullptr &&
-        (UISettings::values.hide_mouse || Settings::values.mouse_panning)) {
+    if (emu_thread != nullptr && UISettings::values.hide_mouse) {
         mouse_hide_timer.start();
     }
 }
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp
index 7e391ab89..ce8b7c218 100644
--- a/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp
+++ b/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp
@@ -35,18 +35,36 @@ void EmuWindow_SDL2::OnMouseMotion(s32 x, s32 y) {
     input_subsystem->GetMouse()->MouseMove(x, y, 0, 0);
 }
 
+MouseInput::MouseButton EmuWindow_SDL2::SDLButtonToMouseButton(u32 button) const {
+    switch (button) {
+    case SDL_BUTTON_LEFT:
+        return MouseInput::MouseButton::Left;
+    case SDL_BUTTON_RIGHT:
+        return MouseInput::MouseButton::Right;
+    case SDL_BUTTON_MIDDLE:
+        return MouseInput::MouseButton::Wheel;
+    case SDL_BUTTON_X1:
+        return MouseInput::MouseButton::Backward;
+    case SDL_BUTTON_X2:
+        return MouseInput::MouseButton::Forward;
+    default:
+        return MouseInput::MouseButton::Undefined;
+    }
+}
+
 void EmuWindow_SDL2::OnMouseButton(u32 button, u8 state, s32 x, s32 y) {
+    const auto mouse_button = SDLButtonToMouseButton(button);
     if (button == SDL_BUTTON_LEFT) {
         if (state == SDL_PRESSED) {
             TouchPressed((unsigned)std::max(x, 0), (unsigned)std::max(y, 0), 0);
         } else {
             TouchReleased(0);
         }
-    } else if (button == SDL_BUTTON_RIGHT) {
+    } else {
         if (state == SDL_PRESSED) {
-            input_subsystem->GetMouse()->PressButton(x, y, button);
+            input_subsystem->GetMouse()->PressButton(x, y, mouse_button);
         } else {
-            input_subsystem->GetMouse()->ReleaseButton(button);
+            input_subsystem->GetMouse()->ReleaseButton(mouse_button);
         }
     }
 }
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2.h b/src/yuzu_cmd/emu_window/emu_window_sdl2.h
index 51a12a6a9..0e17bbca7 100644
--- a/src/yuzu_cmd/emu_window/emu_window_sdl2.h
+++ b/src/yuzu_cmd/emu_window/emu_window_sdl2.h
@@ -18,6 +18,10 @@ namespace InputCommon {
 class InputSubsystem;
 }
 
+namespace MouseInput {
+enum class MouseButton;
+}
+
 class EmuWindow_SDL2 : public Core::Frontend::EmuWindow {
 public:
     explicit EmuWindow_SDL2(InputCommon::InputSubsystem* input_subsystem);
@@ -42,6 +46,9 @@ protected:
     /// Called by WaitEvent when the mouse moves.
     void OnMouseMotion(s32 x, s32 y);
 
+    /// Converts a SDL mouse button into MouseInput mouse button
+    MouseInput::MouseButton SDLButtonToMouseButton(u32 button) const;
+
     /// Called by WaitEvent when a mouse button is pressed or released
     void OnMouseButton(u32 button, u8 state, s32 x, s32 y);