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 c73aab08c3..300bcd46f0 100644 --- a/interface/resources/qml/LoginDialog/LinkAccountBody.qml +++ b/interface/resources/qml/LoginDialog/LinkAccountBody.qml @@ -119,6 +119,7 @@ Item { width: parent.width focus: true label: "Username or Email" + activeFocusOnPress: true ShortcutText { anchors { @@ -135,6 +136,9 @@ Item { onLinkActivated: loginDialog.openUrl(link) } + onFocusChanged: { + root.text = ""; + } } TextField { @@ -143,6 +147,7 @@ Item { label: "Password" echoMode: showPassword.checked ? TextInput.Normal : TextInput.Password + activeFocusOnPress: true ShortcutText { anchors { @@ -159,6 +164,10 @@ Item { onLinkActivated: loginDialog.openUrl(link) } + onFocusChanged: { + root.text = ""; + root.isPassword = true; + } } CheckBoxQQC2 { @@ -233,18 +242,6 @@ Item { } } - // Override ScrollingWindow's keyboard that would be at very bottom of dialog. - Keyboard { - raised: keyboardEnabled && keyboardRaised - numeric: punctuationMode - anchors { - left: parent.left - right: parent.right - bottom: parent.bottom - bottomMargin: keyboardRaised ? 2 * hifi.dimensions.contentSpacing.y : 0 - } - } - Component.onCompleted: { root.title = qsTr("Sign Into High Fidelity") root.iconText = "<" diff --git a/interface/resources/qml/LoginDialog/SignUpBody.qml b/interface/resources/qml/LoginDialog/SignUpBody.qml index f6cf40db8e..9d55998b40 100644 --- a/interface/resources/qml/LoginDialog/SignUpBody.qml +++ b/interface/resources/qml/LoginDialog/SignUpBody.qml @@ -108,12 +108,17 @@ Item { id: emailField width: parent.width label: "Email" + activeFocusOnPress: true + onFocusChanged: { + root.text = ""; + } } TextField { id: usernameField width: parent.width label: "Username" + activeFocusOnPress: true ShortcutText { anchors { @@ -128,6 +133,9 @@ Item { horizontalAlignment: Text.AlignHCenter color: hifi.colors.blueAccent + onFocusChanged: { + root.text = ""; + } } } @@ -136,6 +144,7 @@ Item { width: parent.width label: "Password" echoMode: TextInput.Password + activeFocusOnPress: true ShortcutText { anchors { @@ -151,6 +160,11 @@ Item { color: hifi.colors.blueAccent } + + onFocusChanged: { + root.text = ""; + root.isPassword = focus + } } Row { @@ -202,18 +216,6 @@ Item { } } - // Override ScrollingWindow's keyboard that would be at very bottom of dialog. - Keyboard { - raised: keyboardEnabled && keyboardRaised - numeric: punctuationMode - anchors { - left: parent.left - right: parent.right - bottom: parent.bottom - bottomMargin: keyboardRaised ? 2 * hifi.dimensions.contentSpacing.y : 0 - } - } - Component.onCompleted: { root.title = qsTr("Create an Account") root.iconText = "<" diff --git a/interface/resources/qml/controls-uit/Keyboard.qml b/interface/resources/qml/controls-uit/Keyboard.qml index 8d6634c9b4..66a61742c9 100644 --- a/interface/resources/qml/controls-uit/Keyboard.qml +++ b/interface/resources/qml/controls-uit/Keyboard.qml @@ -39,6 +39,10 @@ Rectangle { property bool shiftMode: false property bool numericShiftMode: false + onRaisedChanged: { + mirroredText = ""; + } + function resetShiftMode(mode) { shiftMode = mode; shiftKey.resetToggledMode(mode); 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/dialogs/TabletLoginDialog.qml b/interface/resources/qml/dialogs/TabletLoginDialog.qml index 9722f31144..269788a808 100644 --- a/interface/resources/qml/dialogs/TabletLoginDialog.qml +++ b/interface/resources/qml/dialogs/TabletLoginDialog.qml @@ -37,6 +37,8 @@ TabletModalWindow { property bool keyboardEnabled: false property bool keyboardRaised: false property bool punctuationMode: false + property bool isPassword: false + property alias text: loginKeyboard.mirroredText readonly property bool isTablet: true @@ -130,6 +132,7 @@ TabletModalWindow { id: loginKeyboard raised: root.keyboardEnabled && root.keyboardRaised numeric: root.punctuationMode + password: root.isPassword 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 8646bee3ca..ecd07a5874 100644 --- a/libraries/ui/src/ui/OffscreenQmlSurface.cpp +++ b/libraries/ui/src/ui/OffscreenQmlSurface.cpp @@ -1082,37 +1082,7 @@ void OffscreenQmlSurface::synthesizeKeyPress(QString key, QObject* targetOverrid } } -static void forEachKeyboard(QQuickItem* parent, std::function function) { - if (!function) { - return; - } - - auto keyboards = parent->findChildren("keyboard"); - - for (auto keyboardObject : keyboards) { - auto keyboard = qobject_cast(keyboardObject); - if (keyboard) { - function(keyboard); - } - } -} - -static const int TEXTINPUT_PASSWORD = 2; - -static QQuickItem* getTopmostParent(QQuickItem* item) { - QObject* itemObject = item; - while (itemObject) { - if (itemObject->parent()) { - itemObject = itemObject->parent(); - } else { - break; - } - } - - return qobject_cast (itemObject); -} - -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 @@ -1128,21 +1098,6 @@ void OffscreenQmlSurface::setKeyboardRaised(QObject* object, bool raised, bool n return; } - auto echoMode = item->property("echoMode"); - bool isPasswordField = echoMode.isValid() && echoMode.toInt() == TEXTINPUT_PASSWORD; - - // we need to somehow pass 'isPasswordField' to visible keyboard so it will change its 'mirror text' to asterixes - // the issue in some cases there might be more than one keyboard in object tree and it is hard to understand which one is being used at the moment - // unfortunately attempts to check for visibility failed becuase visibility is not updated yet. So... I don't see other way than just update properties for all the keyboards - - auto topmostParent = getTopmostParent(item); - if (topmostParent) { - forEachKeyboard(topmostParent, [&](QQuickItem* keyboard) { - keyboard->setProperty("mirroredText", QVariant::fromValue(QString(""))); - keyboard->setProperty("password", isPasswordField); - }); - } - // for future probably makes sense to consider one of the following: // 1. make keyboard a singleton, which will be dynamically re-parented before showing // 2. track currently visible keyboard somewhere, allow to subscribe for this signal @@ -1153,15 +1108,15 @@ void OffscreenQmlSurface::setKeyboardRaised(QObject* object, bool raised, bool n numeric = numeric || QString(item->metaObject()->className()).left(7) == "SpinBox"; if (item->property("keyboardRaised").isValid()) { - forEachKeyboard(item, [&](QQuickItem* keyboard) { - keyboard->setProperty("mirroredText", QVariant::fromValue(QString(""))); - keyboard->setProperty("password", isPasswordField); - }); // FIXME - HMD only: Possibly set value of "keyboardEnabled" per isHMDMode() for use in WebView.qml. 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; } @@ -1186,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;