From c31aa6bcdb408e28fba0b2ab151da428ad420ba5 Mon Sep 17 00:00:00 2001 From: beholder Date: Thu, 12 Oct 2017 21:56:59 +0300 Subject: [PATCH 1/2] 8213 Keyboard Input Field: Reveals Passwords --- .../resources/qml/controls-uit/Keyboard.qml | 13 ++++-- libraries/ui/src/ui/OffscreenQmlSurface.cpp | 46 +++++++++++++++++++ 2 files changed, 56 insertions(+), 3 deletions(-) diff --git a/interface/resources/qml/controls-uit/Keyboard.qml b/interface/resources/qml/controls-uit/Keyboard.qml index 81579d9f71..5b3a69e487 100644 --- a/interface/resources/qml/controls-uit/Keyboard.qml +++ b/interface/resources/qml/controls-uit/Keyboard.qml @@ -13,6 +13,7 @@ import "." Rectangle { id: keyboardBase + objectName: "keyboard" anchors.left: parent.left anchors.right: parent.right @@ -27,6 +28,8 @@ Rectangle { readonly property int mirrorTextHeight: keyboardRowHeight + property bool password: false + property alias mirroredText: mirrorText.text property bool showMirrorText: true readonly property int raisedHeight: 200 @@ -112,16 +115,20 @@ Rectangle { color: "#252525" anchors.horizontalCenter: parent.horizontalCenter - TextEdit { + TextInput { id: mirrorText visible: showMirrorText - size: 13.5 + FontLoader { id: ralewaySemiBold; source: "../../fonts/Raleway-SemiBold.ttf"; } + font.family: ralewaySemiBold.name + font.pointSize: 13.5 + verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignHCenter color: "#FFFFFF"; anchors.fill: parent wrapMode: Text.WordWrap - readOnly: false // we need to leave this property read-only to allow control to accept QKeyEvent + readOnly: false // we need this to allow control to accept QKeyEvent selectByMouse: false + echoMode: password ? TextInput.Password : TextInput.Normal Keys.onPressed: { if (event.key == Qt.Key_Return) { diff --git a/libraries/ui/src/ui/OffscreenQmlSurface.cpp b/libraries/ui/src/ui/OffscreenQmlSurface.cpp index 6cf8a927ff..69d6b8d6ab 100644 --- a/libraries/ui/src/ui/OffscreenQmlSurface.cpp +++ b/libraries/ui/src/ui/OffscreenQmlSurface.cpp @@ -1030,6 +1030,52 @@ void OffscreenQmlSurface::setKeyboardRaised(QObject* object, bool raised, bool n // if HMD is being worn, allow keyboard to open. allow it to close, HMD or not. if (!raised || qApp->property(hifi::properties::HMD).toBool()) { QQuickItem* item = dynamic_cast(object); + if (!item) + return; + + auto echoMode = item->property("echoMode"); + bool isPasswordField = echoMode.isValid() && echoMode.toInt() == 2 /* 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 + struct Local { + static void forEachKeyboard(QQuickItem* item, std::function function) { + QObject* itemObject = item; + while (itemObject) { + if (itemObject->parent()) { + itemObject = itemObject->parent(); + } + else { + break; + } + } + + auto keyboards = itemObject->findChildren("keyboard"); + + for (auto keyboardObject : keyboards) { + auto keyboard = qobject_cast(keyboardObject); + if (keyboard == nullptr) { + continue; + } + + if (function) { + function(keyboard); + } + } + } + }; + + Local::forEachKeyboard(item, [&](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 + // any of above should also eliminate need in duplicated properties and code below + while (item) { // Numeric value may be set in parameter from HTML UI; for QML UI, detect numeric fields here. numeric = numeric || QString(item->metaObject()->className()).left(7) == "SpinBox"; From f83040c572249d9a823d7b3f50b8f8f043ddda13 Mon Sep 17 00:00:00 2001 From: beholder Date: Fri, 13 Oct 2017 22:23:38 +0300 Subject: [PATCH 2/2] updating code accordingly to the comments --- libraries/ui/src/ui/OffscreenQmlSurface.cpp | 60 ++++++++++----------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/libraries/ui/src/ui/OffscreenQmlSurface.cpp b/libraries/ui/src/ui/OffscreenQmlSurface.cpp index 69d6b8d6ab..01026ae5ff 100644 --- a/libraries/ui/src/ui/OffscreenQmlSurface.cpp +++ b/libraries/ui/src/ui/OffscreenQmlSurface.cpp @@ -1018,6 +1018,32 @@ void OffscreenQmlSurface::synthesizeKeyPress(QString key, QObject* targetOverrid } } +static void forEachKeyboard(QQuickItem* item, std::function function) { + QObject* itemObject = item; + while (itemObject) { + if (itemObject->parent()) { + itemObject = itemObject->parent(); + } else { + break; + } + } + + auto keyboards = itemObject->findChildren("keyboard"); + + for (auto keyboardObject : keyboards) { + auto keyboard = qobject_cast(keyboardObject); + if (keyboard == nullptr) { + continue; + } + + if (function) { + function(keyboard); + } + } +} + +static const int TEXTINPUT_PASSWORD = 2; + void OffscreenQmlSurface::setKeyboardRaised(QObject* object, bool raised, bool numeric) { #if Q_OS_ANDROID return; @@ -1030,43 +1056,17 @@ void OffscreenQmlSurface::setKeyboardRaised(QObject* object, bool raised, bool n // if HMD is being worn, allow keyboard to open. allow it to close, HMD or not. if (!raised || qApp->property(hifi::properties::HMD).toBool()) { QQuickItem* item = dynamic_cast(object); - if (!item) + if (!item) { return; + } auto echoMode = item->property("echoMode"); - bool isPasswordField = echoMode.isValid() && echoMode.toInt() == 2 /* TextInput.Password */; + 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 - struct Local { - static void forEachKeyboard(QQuickItem* item, std::function function) { - QObject* itemObject = item; - while (itemObject) { - if (itemObject->parent()) { - itemObject = itemObject->parent(); - } - else { - break; - } - } - - auto keyboards = itemObject->findChildren("keyboard"); - - for (auto keyboardObject : keyboards) { - auto keyboard = qobject_cast(keyboardObject); - if (keyboard == nullptr) { - continue; - } - - if (function) { - function(keyboard); - } - } - } - }; - - Local::forEachKeyboard(item, [&](QQuickItem* keyboard) { + forEachKeyboard(item, [&](QQuickItem* keyboard) { keyboard->setProperty("mirroredText", QVariant::fromValue(QString(""))); keyboard->setProperty("password", isPasswordField); });