From 26de05ad1b9884e2aa8607b8a4aabbac6f9e7276 Mon Sep 17 00:00:00 2001
From: ksuprynowicz <ksuprynowicz@post.pl>
Date: Tue, 25 Jun 2024 21:13:49 +0200
Subject: [PATCH] Add QML API function to show VR keyboard

---
 interface/src/Application.cpp |  8 ++++++++
 interface/src/Application.h   | 10 ++++++++++
 interface/src/ui/Keyboard.cpp | 14 +++++++++++---
 interface/src/ui/Keyboard.h   |  4 +++-
 4 files changed, 32 insertions(+), 4 deletions(-)

diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp
index 8d99e41668..04e39e7a06 100644
--- a/interface/src/Application.cpp
+++ b/interface/src/Application.cpp
@@ -8598,6 +8598,14 @@ SharedSoundPointer Application::getSampleSound() const {
     return _sampleSound;
 }
 
+void Application::showVRKeyboardForHudUI(bool show) {
+    if (show) {
+        DependencyManager::get<Keyboard>()->setRaised(true, true);
+    } else {
+        DependencyManager::get<Keyboard>()->setRaised(false);
+    }
+}
+
 void Application::loadLODToolsDialog() {
     auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>();
     auto tablet = dynamic_cast<TabletProxy*>(tabletScriptingInterface->getTablet(SYSTEM_TABLET));
diff --git a/interface/src/Application.h b/interface/src/Application.h
index 63a035dd45..53b827fdb8 100644
--- a/interface/src/Application.h
+++ b/interface/src/Application.h
@@ -431,6 +431,16 @@ public slots:
     Q_INVOKABLE void loadAddAvatarBookmarkDialog() const;
     Q_INVOKABLE void loadAvatarBrowser() const;
     Q_INVOKABLE SharedSoundPointer getSampleSound() const;
+    /**
+     * @brief Shows/hides VR keyboard input for Overlay windows
+     *
+     * This is used by QML scripts to show and hide VR keyboard. Unlike JS API Keyboard.raised = true,
+     * with showVRKeyboardForHudUI the input is passed to the active window on the overlay first.
+     *
+     * @param show
+     * If set to true, then keyboard is shown, for false it's hidden.
+     */
+    Q_INVOKABLE void showVRKeyboardForHudUI(bool show);
 
     void showDialog(const QUrl& widgetUrl, const QUrl& tabletUrl, const QString& name) const;
 
diff --git a/interface/src/ui/Keyboard.cpp b/interface/src/ui/Keyboard.cpp
index eba1bcec3f..b856f08775 100644
--- a/interface/src/ui/Keyboard.cpp
+++ b/interface/src/ui/Keyboard.cpp
@@ -303,10 +303,13 @@ bool Keyboard::isRaised() const {
     return resultWithReadLock<bool>([&] { return _raised; });
 }
 
-void Keyboard::setRaised(bool raised) {
+void Keyboard::setRaised(bool raised, bool inputToHudUI) {
 
     bool isRaised;
     withReadLock([&] { isRaised = _raised; });
+
+    _inputToHudUI = inputToHudUI;
+
     if (isRaised != raised) {
         raiseKeyboardAnchor(raised);
         raiseKeyboard(raised);
@@ -585,8 +588,13 @@ void Keyboard::handleTriggerBegin(const QUuid& id, const PointerEvent& event) {
 
         QKeyEvent* pressEvent = new QKeyEvent(QEvent::KeyPress, scanCode, Qt::NoModifier, keyString);
         QKeyEvent* releaseEvent = new QKeyEvent(QEvent::KeyRelease, scanCode, Qt::NoModifier, keyString);
-        QCoreApplication::postEvent(qApp->getPrimaryWidget(), pressEvent);
-        QCoreApplication::postEvent(qApp->getPrimaryWidget(), releaseEvent);
+        if (_inputToHudUI) {
+            QCoreApplication::postEvent(qApp->getPrimaryWidget(), pressEvent);
+            QCoreApplication::postEvent(qApp->getPrimaryWidget(), releaseEvent);
+        } else {
+            QCoreApplication::postEvent(QCoreApplication::instance(), pressEvent);
+            QCoreApplication::postEvent(QCoreApplication::instance(), releaseEvent);
+        }
 
         if (!getPreferMalletsOverLasers()) {
             key.startTimer(KEY_PRESS_TIMEOUT_MS);
diff --git a/interface/src/ui/Keyboard.h b/interface/src/ui/Keyboard.h
index 7f7944e646..44fddd9e42 100644
--- a/interface/src/ui/Keyboard.h
+++ b/interface/src/ui/Keyboard.h
@@ -93,7 +93,7 @@ public:
     void createKeyboard();
     void registerKeyboardHighlighting();
     bool isRaised() const;
-    void setRaised(bool raised);
+    void setRaised(bool raised, bool inputToHudUI = false);
     void setResetKeyboardPositionOnRaise(bool reset);
     bool isPassword() const;
     void setPassword(bool password);
@@ -190,6 +190,8 @@ private:
     QSet<QUuid> _itemsToIgnore;
     std::vector<QHash<QUuid, Key>> _keyboardLayers;
 
+    // Send keyboard events to hud UI if true
+    std::atomic<bool> _inputToHudUI { false };
     bool _created { false };
 };