From 92f765fe5250523da50c796b2271dd747544794b Mon Sep 17 00:00:00 2001
From: Dante Ruiz <dante@AD.HIGHFIDELITY.IO>
Date: Tue, 24 Oct 2017 13:53:50 -0700
Subject: [PATCH] property set echomode for keyboard for wallet and webviews

---
 .../resources/html/raiseAndLowerKeyboard.js   | 13 ++++++++--
 .../qml/LoginDialog/LinkAccountBody.qml       |  1 -
 .../resources/qml/controls/TabletWebView.qml  | 10 ++++++--
 interface/resources/qml/controls/WebView.qml  |  2 ++
 .../hifi/commerce/wallet/PassphraseModal.qml  |  4 ++++
 .../commerce/wallet/PassphraseSelection.qml   | 24 ++++++++++++-------
 .../qml/hifi/commerce/wallet/Wallet.qml       |  5 ++++
 libraries/ui/src/ui/OffscreenQmlSurface.cpp   | 12 ++++++++--
 libraries/ui/src/ui/OffscreenQmlSurface.h     |  2 +-
 9 files changed, 56 insertions(+), 17 deletions(-)

diff --git a/interface/resources/html/raiseAndLowerKeyboard.js b/interface/resources/html/raiseAndLowerKeyboard.js
index 2535416fd8..23f3a7e9a8 100644
--- a/interface/resources/html/raiseAndLowerKeyboard.js
+++ b/interface/resources/html/raiseAndLowerKeyboard.js
@@ -14,6 +14,12 @@
     var isWindowFocused = true;
     var isKeyboardRaised = false;
     var isNumericKeyboard = false;
+    var isPasswordField = false;
+
+    function shouldSetPasswordField() {
+        var nodeType = document.activeElement.type;
+        return nodeType === "password";
+    }
 
     function shouldRaiseKeyboard() {
         var nodeName = document.activeElement.nodeName;
@@ -53,12 +59,14 @@
     setInterval(function () {
         var keyboardRaised = shouldRaiseKeyboard();
         var numericKeyboard = shouldSetNumeric();
+        var passwordField = shouldSetPasswordField();
 
-        if (isWindowFocused && (keyboardRaised !== isKeyboardRaised || numericKeyboard !== isNumericKeyboard)) {
+        if (isWindowFocused &&
+            (keyboardRaised !== isKeyboardRaised || numericKeyboard !== isNumericKeyboard || passwordField !== isPasswordField)) {
 
             if (typeof EventBridge !== "undefined" && EventBridge !== null) {
                 EventBridge.emitWebEvent(
-                    keyboardRaised ? ("_RAISE_KEYBOARD" + (numericKeyboard ? "_NUMERIC" : "")) : "_LOWER_KEYBOARD"
+                    keyboardRaised ? ("_RAISE_KEYBOARD" + (numericKeyboard ? "_NUMERIC" : "") + (passwordField ? "_PASSWORD" : "")) : "_LOWER_KEYBOARD"
                 );
             } else {
                 if (numWarnings < MAX_WARNINGS) {
@@ -74,6 +82,7 @@
 
             isKeyboardRaised = keyboardRaised;
             isNumericKeyboard = numericKeyboard;
+            isPasswordField = passwordField;
         }
     }, POLL_FREQUENCY);
 
diff --git a/interface/resources/qml/LoginDialog/LinkAccountBody.qml b/interface/resources/qml/LoginDialog/LinkAccountBody.qml
index a710c76477..300bcd46f0 100644
--- a/interface/resources/qml/LoginDialog/LinkAccountBody.qml
+++ b/interface/resources/qml/LoginDialog/LinkAccountBody.qml
@@ -137,7 +137,6 @@ Item {
                 onLinkActivated: loginDialog.openUrl(link)
             }
             onFocusChanged: {
-                console.log("-------> setting variable <-------");
                 root.text = "";
             }
         }
diff --git a/interface/resources/qml/controls/TabletWebView.qml b/interface/resources/qml/controls/TabletWebView.qml
index 23143db3ba..8cd61bc90b 100644
--- a/interface/resources/qml/controls/TabletWebView.qml
+++ b/interface/resources/qml/controls/TabletWebView.qml
@@ -16,6 +16,7 @@ Item {
     property bool keyboardEnabled: false
     property bool keyboardRaised: false
     property bool punctuationMode: false
+    property bool passwordField: false
     property bool isDesktop: false
     property alias webView: web.webViewCore
     property alias profile: web.webViewCoreProfile
@@ -41,7 +42,7 @@ Item {
                 horizontalCenter: parent.horizontalCenter
             }
             spacing: 120
-            
+
             TabletWebButton {
                 id: back
                 enabledColor: hifi.colors.darkGray
@@ -165,6 +166,11 @@ Item {
         id: keyboard
         raised: parent.keyboardEnabled && parent.keyboardRaised
         numeric: parent.punctuationMode
+        password: parent.passwordField
+
+        onPasswordChanged: {
+            keyboard.mirroredText = "";
+        }
 
         anchors {
             left: parent.left
@@ -172,7 +178,7 @@ Item {
             bottom: parent.bottom
         }
     }
-    
+
     Component.onCompleted: {
         root.isDesktop = (typeof desktop !== "undefined");
         keyboardEnabled = HMD.active;
diff --git a/interface/resources/qml/controls/WebView.qml b/interface/resources/qml/controls/WebView.qml
index c38c5df9cf..923c8f3fa1 100644
--- a/interface/resources/qml/controls/WebView.qml
+++ b/interface/resources/qml/controls/WebView.qml
@@ -13,6 +13,7 @@ Item {
     property bool keyboardEnabled: true  // FIXME - Keyboard HMD only: Default to false
     property bool keyboardRaised: false
     property bool punctuationMode: false
+    property bool passwordField: false
     property alias flickable: webroot.interactive
 
     // FIXME - Keyboard HMD only: Make Interface either set keyboardRaised property directly in OffscreenQmlSurface
@@ -50,6 +51,7 @@ Item {
         id: keyboard
         raised: parent.keyboardEnabled && parent.keyboardRaised
         numeric: parent.punctuationMode
+        password: parent.passwordField
         anchors {
             left: parent.left
             right: parent.right
diff --git a/interface/resources/qml/hifi/commerce/wallet/PassphraseModal.qml b/interface/resources/qml/hifi/commerce/wallet/PassphraseModal.qml
index 2243143906..d967a36b68 100644
--- a/interface/resources/qml/hifi/commerce/wallet/PassphraseModal.qml
+++ b/interface/resources/qml/hifi/commerce/wallet/PassphraseModal.qml
@@ -27,6 +27,7 @@ Item {
     id: root;
     z: 997;
     property bool keyboardRaised: false;
+    property bool isPasswordField: false;
     property string titleBarIcon: "";
     property string titleBarText: "";
 
@@ -202,6 +203,7 @@ Item {
 
             onFocusChanged: {
                 root.keyboardRaised = focus;
+                root.isPasswordField = (focus && passphraseField.echoMode === TextInput.Password);
             }
 
             MouseArea {
@@ -209,6 +211,7 @@ Item {
 
                 onClicked: {
                     root.keyboardRaised = true;
+                    root.isPasswordField = (passphraseField.echoMode === TextInput.Password);
                     mouse.accepted = false;
                 }
             }
@@ -382,6 +385,7 @@ Item {
             id: keyboard;
             raised: HMD.mounted && root.keyboardRaised;
             numeric: parent.punctuationMode;
+            password: root.isPasswordField;
             anchors {
                 bottom: parent.bottom;
                 left: parent.left;
diff --git a/interface/resources/qml/hifi/commerce/wallet/PassphraseSelection.qml b/interface/resources/qml/hifi/commerce/wallet/PassphraseSelection.qml
index 7c0cecd98d..ffeedde8f0 100644
--- a/interface/resources/qml/hifi/commerce/wallet/PassphraseSelection.qml
+++ b/interface/resources/qml/hifi/commerce/wallet/PassphraseSelection.qml
@@ -80,16 +80,18 @@ Item {
 
         onFocusChanged: {
             if (focus) {
-                sendSignalToWallet({method: 'walletSetup_raiseKeyboard'});
+                var hidePassword = (currentPassphraseField.echoMode === TextInput.Password);
+                sendSignalToWallet({method: 'walletSetup_raiseKeyboard', isPasswordField: hidePassword});
             } else if (!passphraseFieldAgain.focus) {
-                sendSignalToWallet({method: 'walletSetup_lowerKeyboard'});
+                sendSignalToWallet({method: 'walletSetup_lowerKeyboard', isPasswordField: false});
             }
         }
 
         MouseArea {
             anchors.fill: parent;
             onPressed: {
-                sendSignalToWallet({method: 'walletSetup_raiseKeyboard'});
+                var hidePassword = (currentPassphraseField.echoMode === TextInput.Password);
+                sendSignalToWallet({method: 'walletSetup_raiseKeyboard', isPasswordField: hidePassword});
                 mouse.accepted = false;
             }
         }
@@ -116,16 +118,18 @@ Item {
         MouseArea {
             anchors.fill: parent;
             onPressed: {
-                sendSignalToWallet({method: 'walletSetup_raiseKeyboard'});
+                var hidePassword = (passphraseField.echoMode === TextInput.Password);
+                sendSignalToWallet({method: 'walletSetup_raiseKeyboard', isPasswordField: hidePassword});
                 mouse.accepted = false;
             }
         }
 
         onFocusChanged: {
             if (focus) {
-                sendMessageToLightbox({method: 'walletSetup_raiseKeyboard'});
+                var hidePassword = (passphraseField.echoMode === TextInput.Password);
+                sendMessageToLightbox({method: 'walletSetup_raiseKeyboard', isPasswordField: hidePassword});
             } else if (!passphraseFieldAgain.focus) {
-                sendMessageToLightbox({method: 'walletSetup_lowerKeyboard'});
+                sendMessageToLightbox({method: 'walletSetup_lowerKeyboard', isPasswordField: false});
             }
         }
 
@@ -150,16 +154,18 @@ Item {
         MouseArea {
             anchors.fill: parent;
             onPressed: {
-                sendSignalToWallet({method: 'walletSetup_raiseKeyboard'});
+                var hidePassword = (passphraseFieldAgain.echoMode === TextInput.Password);
+                sendSignalToWallet({method: 'walletSetup_raiseKeyboard', isPasswordField: hidePassword});
                 mouse.accepted = false;
             }
         }
 
         onFocusChanged: {
             if (focus) {
-                sendMessageToLightbox({method: 'walletSetup_raiseKeyboard'});
+                var hidePassword = (passphraseFieldAgain.echoMode === TextInput.Password);
+                sendMessageToLightbox({method: 'walletSetup_raiseKeyboard', isPasswordField: hidePassword});
             } else if (!passphraseField.focus) {
-                sendMessageToLightbox({method: 'walletSetup_lowerKeyboard'});
+                sendMessageToLightbox({method: 'walletSetup_lowerKeyboard', isPasswordField: false});
             }
         }
 
diff --git a/interface/resources/qml/hifi/commerce/wallet/Wallet.qml b/interface/resources/qml/hifi/commerce/wallet/Wallet.qml
index 472dd50b7d..759d7a37eb 100644
--- a/interface/resources/qml/hifi/commerce/wallet/Wallet.qml
+++ b/interface/resources/qml/hifi/commerce/wallet/Wallet.qml
@@ -29,6 +29,7 @@ Rectangle {
 
     property string activeView: "initialize";
     property bool keyboardRaised: false;
+    property bool isPassword: false;
 
     Image {
         anchors.fill: parent;
@@ -181,8 +182,10 @@ Rectangle {
                     }
                 } else if (msg.method === 'walletSetup_raiseKeyboard') {
                     root.keyboardRaised = true;
+                    root.isPassword = msg.isPasswordField;
                 } else if (msg.method === 'walletSetup_lowerKeyboard') {
                     root.keyboardRaised = false;
+                    root.isPassword = msg.isPasswordField;
                 } else {
                     sendToScript(msg);
                 }
@@ -202,6 +205,7 @@ Rectangle {
             onSendSignalToWallet: {
                 if (msg.method === 'walletSetup_raiseKeyboard') {
                     root.keyboardRaised = true;
+                    root.isPassword = msg.isPasswordField;
                 } else if (msg.method === 'walletSetup_lowerKeyboard') {
                     root.keyboardRaised = false;
                 } else if (msg.method === 'walletSecurity_changePassphraseCancelled') {
@@ -685,6 +689,7 @@ Rectangle {
             id: keyboard;
             raised: HMD.mounted && root.keyboardRaised;
             numeric: parent.punctuationMode;
+            password: root.isPassword;
             anchors {
                 bottom: parent.bottom;
                 left: parent.left;
diff --git a/libraries/ui/src/ui/OffscreenQmlSurface.cpp b/libraries/ui/src/ui/OffscreenQmlSurface.cpp
index ddc9c2e5f3..ecd07a5874 100644
--- a/libraries/ui/src/ui/OffscreenQmlSurface.cpp
+++ b/libraries/ui/src/ui/OffscreenQmlSurface.cpp
@@ -1082,7 +1082,7 @@ void OffscreenQmlSurface::synthesizeKeyPress(QString key, QObject* targetOverrid
     }
 }
 
-void OffscreenQmlSurface::setKeyboardRaised(QObject* object, bool raised, bool numeric) {
+void OffscreenQmlSurface::setKeyboardRaised(QObject* object, bool raised, bool numeric, bool passwordField) {
 #if Q_OS_ANDROID
     return;
 #endif
@@ -1113,6 +1113,10 @@ void OffscreenQmlSurface::setKeyboardRaised(QObject* object, bool raised, bool n
                 if (item->property("punctuationMode").isValid()) {
                     item->setProperty("punctuationMode", QVariant(numeric));
                 }
+                if (item->property("passwordField").isValid()) {
+                    item->setProperty("passwordField", QVariant(passwordField));
+                }
+
                 item->setProperty("keyboardRaised", QVariant(raised));
                 return;
             }
@@ -1137,9 +1141,13 @@ void OffscreenQmlSurface::emitWebEvent(const QVariant& message) {
         const QString RAISE_KEYBOARD = "_RAISE_KEYBOARD";
         const QString RAISE_KEYBOARD_NUMERIC = "_RAISE_KEYBOARD_NUMERIC";
         const QString LOWER_KEYBOARD = "_LOWER_KEYBOARD";
+        const QString RAISE_KEYBOARD_NUMERIC_PASSWORD = "_RAISE_KEYBOARD_NUMERIC_PASSWORD";
+        const QString RAISE_KEYBOARD_PASSWORD = "_RAISE_KEYBOARD_PASSWORD";
         QString messageString = message.type() == QVariant::String ? message.toString() : "";
         if (messageString.left(RAISE_KEYBOARD.length()) == RAISE_KEYBOARD) {
-            setKeyboardRaised(_currentFocusItem, true, messageString == RAISE_KEYBOARD_NUMERIC);
+            bool numeric = (messageString == RAISE_KEYBOARD_NUMERIC || messageString == RAISE_KEYBOARD_NUMERIC_PASSWORD);
+            bool passwordField = (messageString == RAISE_KEYBOARD_PASSWORD || messageString == RAISE_KEYBOARD_NUMERIC_PASSWORD);
+            setKeyboardRaised(_currentFocusItem, true, numeric, passwordField);
         } else if (messageString == LOWER_KEYBOARD) {
             setKeyboardRaised(_currentFocusItem, false);
         } else {
diff --git a/libraries/ui/src/ui/OffscreenQmlSurface.h b/libraries/ui/src/ui/OffscreenQmlSurface.h
index 74eafe9f13..12ee9e59a1 100644
--- a/libraries/ui/src/ui/OffscreenQmlSurface.h
+++ b/libraries/ui/src/ui/OffscreenQmlSurface.h
@@ -82,7 +82,7 @@ public:
     QPointF mapToVirtualScreen(const QPointF& originalPoint, QObject* originalWidget);
     bool eventFilter(QObject* originalDestination, QEvent* event) override;
 
-    void setKeyboardRaised(QObject* object, bool raised, bool numeric = false);
+    void setKeyboardRaised(QObject* object, bool raised, bool numeric = false, bool passwordField = false);
     Q_INVOKABLE void synthesizeKeyPress(QString key, QObject* targetOverride = nullptr);
 
     using TextureAndFence = std::pair<uint32_t, void*>;