From 9ebc27234d1f79516ea1a785c31551c26118997d Mon Sep 17 00:00:00 2001
From: ReinUsesLisp <reinuseslisp@airmail.cc>
Date: Mon, 25 Mar 2019 17:01:11 -0300
Subject: [PATCH] bootmanager: Bypass input focus issues

---
 src/yuzu/bootmanager.cpp | 101 ++++++++++++++++++++++-----------------
 src/yuzu/bootmanager.h   |  16 ++-----
 src/yuzu/main.cpp        |  12 +++++
 src/yuzu/main.h          |   4 ++
 4 files changed, 78 insertions(+), 55 deletions(-)

diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp
index 8b4e59eb39..e1825e6072 100644
--- a/src/yuzu/bootmanager.cpp
+++ b/src/yuzu/bootmanager.cpp
@@ -122,9 +122,51 @@ public:
         parent->OnFramebufferSizeChanged();
     }
 
+    void keyPressEvent(QKeyEvent* event) override {
+        InputCommon::GetKeyboard()->PressKey(event->key());
+    }
+
+    void keyReleaseEvent(QKeyEvent* event) override {
+        InputCommon::GetKeyboard()->ReleaseKey(event->key());
+    }
+
+    void mousePressEvent(QMouseEvent* event) override {
+        if (event->source() == Qt::MouseEventSynthesizedBySystem)
+            return; // touch input is handled in TouchBeginEvent
+
+        const auto pos{event->pos()};
+        if (event->button() == Qt::LeftButton) {
+            const auto [x, y] = parent->ScaleTouch(pos);
+            parent->TouchPressed(x, y);
+        } else if (event->button() == Qt::RightButton) {
+            InputCommon::GetMotionEmu()->BeginTilt(pos.x(), pos.y());
+        }
+    }
+
+    void mouseMoveEvent(QMouseEvent* event) override {
+        if (event->source() == Qt::MouseEventSynthesizedBySystem)
+            return; // touch input is handled in TouchUpdateEvent
+
+        const auto pos{event->pos()};
+        const auto [x, y] = parent->ScaleTouch(pos);
+        parent->TouchMoved(x, y);
+        InputCommon::GetMotionEmu()->Tilt(pos.x(), pos.y());
+    }
+
+    void mouseReleaseEvent(QMouseEvent* event) override {
+        if (event->source() == Qt::MouseEventSynthesizedBySystem)
+            return; // touch input is handled in TouchEndEvent
+
+        if (event->button() == Qt::LeftButton)
+            parent->TouchReleased();
+        else if (event->button() == Qt::RightButton)
+            InputCommon::GetMotionEmu()->EndTilt();
+    }
+
     void DisablePainting() {
         do_painting = false;
     }
+
     void EnablePainting() {
         do_painting = true;
     }
@@ -196,12 +238,24 @@ void GRenderWindow::PollEvents() {}
 void GRenderWindow::OnFramebufferSizeChanged() {
     // Screen changes potentially incur a change in screen DPI, hence we should update the
     // framebuffer size
-    qreal pixelRatio = windowPixelRatio();
+    qreal pixelRatio = GetWindowPixelRatio();
     unsigned width = child->QPaintDevice::width() * pixelRatio;
     unsigned height = child->QPaintDevice::height() * pixelRatio;
     UpdateCurrentFramebufferLayout(width, height);
 }
 
+void GRenderWindow::ForwardKeyPressEvent(QKeyEvent* event) {
+    if (child) {
+        child->keyPressEvent(event);
+    }
+}
+
+void GRenderWindow::ForwardKeyReleaseEvent(QKeyEvent* event) {
+    if (child) {
+        child->keyReleaseEvent(event);
+    }
+}
+
 void GRenderWindow::BackupGeometry() {
     geometry = ((QWidget*)this)->saveGeometry();
 }
@@ -226,13 +280,13 @@ QByteArray GRenderWindow::saveGeometry() {
         return geometry;
 }
 
-qreal GRenderWindow::windowPixelRatio() const {
+qreal GRenderWindow::GetWindowPixelRatio() const {
     // windowHandle() might not be accessible until the window is displayed to screen.
     return windowHandle() ? windowHandle()->screen()->devicePixelRatio() : 1.0f;
 }
 
 std::pair<unsigned, unsigned> GRenderWindow::ScaleTouch(const QPointF pos) const {
-    const qreal pixel_ratio = windowPixelRatio();
+    const qreal pixel_ratio = GetWindowPixelRatio();
     return {static_cast<unsigned>(std::max(std::round(pos.x() * pixel_ratio), qreal{0.0})),
             static_cast<unsigned>(std::max(std::round(pos.y() * pixel_ratio), qreal{0.0}))};
 }
@@ -242,47 +296,6 @@ void GRenderWindow::closeEvent(QCloseEvent* event) {
     QWidget::closeEvent(event);
 }
 
-void GRenderWindow::keyPressEvent(QKeyEvent* event) {
-    InputCommon::GetKeyboard()->PressKey(event->key());
-}
-
-void GRenderWindow::keyReleaseEvent(QKeyEvent* event) {
-    InputCommon::GetKeyboard()->ReleaseKey(event->key());
-}
-
-void GRenderWindow::mousePressEvent(QMouseEvent* event) {
-    if (event->source() == Qt::MouseEventSynthesizedBySystem)
-        return; // touch input is handled in TouchBeginEvent
-
-    auto pos = event->pos();
-    if (event->button() == Qt::LeftButton) {
-        const auto [x, y] = ScaleTouch(pos);
-        this->TouchPressed(x, y);
-    } else if (event->button() == Qt::RightButton) {
-        InputCommon::GetMotionEmu()->BeginTilt(pos.x(), pos.y());
-    }
-}
-
-void GRenderWindow::mouseMoveEvent(QMouseEvent* event) {
-    if (event->source() == Qt::MouseEventSynthesizedBySystem)
-        return; // touch input is handled in TouchUpdateEvent
-
-    auto pos = event->pos();
-    const auto [x, y] = ScaleTouch(pos);
-    this->TouchMoved(x, y);
-    InputCommon::GetMotionEmu()->Tilt(pos.x(), pos.y());
-}
-
-void GRenderWindow::mouseReleaseEvent(QMouseEvent* event) {
-    if (event->source() == Qt::MouseEventSynthesizedBySystem)
-        return; // touch input is handled in TouchEndEvent
-
-    if (event->button() == Qt::LeftButton)
-        this->TouchReleased();
-    else if (event->button() == Qt::RightButton)
-        InputCommon::GetMotionEmu()->EndTilt();
-}
-
 void GRenderWindow::TouchBeginEvent(const QTouchEvent* event) {
     // TouchBegin always has exactly one touch point, so take the .first()
     const auto [x, y] = ScaleTouch(event->touchPoints().first().pos());
diff --git a/src/yuzu/bootmanager.h b/src/yuzu/bootmanager.h
index c2f2fe87e9..288ce15726 100644
--- a/src/yuzu/bootmanager.h
+++ b/src/yuzu/bootmanager.h
@@ -119,24 +119,19 @@ public:
     void PollEvents() override;
     std::unique_ptr<Core::Frontend::GraphicsContext> CreateSharedContext() const override;
 
+    void ForwardKeyPressEvent(QKeyEvent* event);
+    void ForwardKeyReleaseEvent(QKeyEvent* event);
+
     void BackupGeometry();
     void RestoreGeometry();
     void restoreGeometry(const QByteArray& geometry); // overridden
     QByteArray saveGeometry();                        // overridden
 
-    qreal windowPixelRatio() const;
+    qreal GetWindowPixelRatio() const;
+    std::pair<unsigned, unsigned> ScaleTouch(const QPointF pos) const;
 
     void closeEvent(QCloseEvent* event) override;
-
-    void keyPressEvent(QKeyEvent* event) override;
-    void keyReleaseEvent(QKeyEvent* event) override;
-
-    void mousePressEvent(QMouseEvent* event) override;
-    void mouseMoveEvent(QMouseEvent* event) override;
-    void mouseReleaseEvent(QMouseEvent* event) override;
-
     bool event(QEvent* event) override;
-
     void focusOutEvent(QFocusEvent* event) override;
 
     void OnClientAreaResized(unsigned width, unsigned height);
@@ -158,7 +153,6 @@ signals:
     void FirstFrameDisplayed();
 
 private:
-    std::pair<unsigned, unsigned> ScaleTouch(const QPointF pos) const;
     void TouchBeginEvent(const QTouchEvent* event);
     void TouchUpdateEvent(const QTouchEvent* event);
     void TouchEndEvent();
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index c8db7b907a..ae3b497095 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -1965,6 +1965,18 @@ void GMainWindow::dragMoveEvent(QDragMoveEvent* event) {
     event->acceptProposedAction();
 }
 
+void GMainWindow::keyPressEvent(QKeyEvent* event) {
+    if (render_window) {
+        render_window->ForwardKeyPressEvent(event);
+    }
+}
+
+void GMainWindow::keyReleaseEvent(QKeyEvent* event) {
+    if (render_window) {
+        render_window->ForwardKeyReleaseEvent(event);
+    }
+}
+
 bool GMainWindow::ConfirmChangeGame() {
     if (emu_thread == nullptr)
         return true;
diff --git a/src/yuzu/main.h b/src/yuzu/main.h
index e07c892cf2..0804849954 100644
--- a/src/yuzu/main.h
+++ b/src/yuzu/main.h
@@ -251,4 +251,8 @@ protected:
     void dropEvent(QDropEvent* event) override;
     void dragEnterEvent(QDragEnterEvent* event) override;
     void dragMoveEvent(QDragMoveEvent* event) override;
+
+    // Overrides used to forward signals to the render window when the focus moves out.
+    void keyPressEvent(QKeyEvent* event) override;
+    void keyReleaseEvent(QKeyEvent* event) override;
 };
-- 
GitLab