From 5e842843c61c3103264939bfd4a7784ef5a6e9e7 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Fri, 30 Sep 2016 11:54:32 +1300 Subject: [PATCH] Set alphabetic/numeric keyboard per field entered --- .../resources/html/raiseAndLowerKeyboard.js | 38 +++++++++++++------ libraries/gl/src/gl/OffscreenQmlSurface.cpp | 22 ++++++++--- libraries/gl/src/gl/OffscreenQmlSurface.h | 2 +- libraries/ui/src/QmlWebWindowClass.cpp | 17 ++++++--- libraries/ui/src/QmlWebWindowClass.h | 2 +- scripts/system/html/js/keyboardControl.js | 19 ++++------ 6 files changed, 64 insertions(+), 36 deletions(-) diff --git a/interface/resources/html/raiseAndLowerKeyboard.js b/interface/resources/html/raiseAndLowerKeyboard.js index a4138d1627..aeca4dc112 100644 --- a/interface/resources/html/raiseAndLowerKeyboard.js +++ b/interface/resources/html/raiseAndLowerKeyboard.js @@ -12,10 +12,11 @@ var MAX_WARNINGS = 3; var numWarnings = 0; var isKeyboardRaised = false; + var isNumericKeyboard = false; var KEYBOARD_HEIGHT = 200; function shouldRaiseKeyboard() { - if (document.activeElement.nodeName == "INPUT" || document.activeElement.nodeName == "TEXTAREA") { + if (document.activeElement.nodeName === "INPUT" || document.activeElement.nodeName === "TEXTAREA") { return true; } else { // check for contenteditable attribute @@ -29,26 +30,39 @@ } }; + function shouldSetNumeric() { + return document.activeElement.type === "number"; + }; + setInterval(function () { - if (isKeyboardRaised !== shouldRaiseKeyboard()) { - isKeyboardRaised = !isKeyboardRaised; + var keyboardRaised = shouldRaiseKeyboard(); + var numericKeyboard = shouldSetNumeric(); - if (isKeyboardRaised) { - var delta = document.activeElement.getBoundingClientRect().bottom + 10 - - (document.body.clientHeight - KEYBOARD_HEIGHT); - if (delta > 0) { - document.body.scrollTop += delta; - } - } + if (keyboardRaised !== isKeyboardRaised || numericKeyboard !== isNumericKeyboard) { - if (typeof EventBridge != "undefined") { - EventBridge.emitWebEvent(isKeyboardRaised ? "_RAISE_KEYBOARD" : "_LOWER_KEYBOARD"); + if (typeof EventBridge !== "undefined") { + EventBridge.emitWebEvent( + keyboardRaised ? ("_RAISE_KEYBOARD" + (numericKeyboard ? "_NUMERIC" : "")) : "_LOWER_KEYBOARD" + ); } else { if (numWarnings < MAX_WARNINGS) { console.log("WARNING: no global EventBridge object found"); numWarnings++; } } + + if (!isKeyboardRaised) { + var delta = document.activeElement.getBoundingClientRect().bottom + 10 + - (document.body.clientHeight - KEYBOARD_HEIGHT); + if (delta > 0) { + setTimeout(function () { + document.body.scrollTop += delta; + }, 500); // Allow time for keyboard to be raised in QML. + } + } + + isKeyboardRaised = keyboardRaised; + isNumericKeyboard = numericKeyboard; } }, POLL_FREQUENCY); })(); diff --git a/libraries/gl/src/gl/OffscreenQmlSurface.cpp b/libraries/gl/src/gl/OffscreenQmlSurface.cpp index ad7561e9f7..2112288db1 100644 --- a/libraries/gl/src/gl/OffscreenQmlSurface.cpp +++ b/libraries/gl/src/gl/OffscreenQmlSurface.cpp @@ -857,7 +857,7 @@ void OffscreenQmlSurface::onFocusObjectChanged(QObject* object) { } // Handle QML text fields' focus and unfocus - testing READ_ONLY_PROPERTY prevents action for HTML files. - // HTML text fields are handled via emitWebEvent(). + // HTML text fields are handled in emitWebEvent() methods. const char* READ_ONLY_PROPERTY = "readOnly"; setKeyboardRaised(item, item->hasActiveFocus() && item->property(READ_ONLY_PROPERTY) == false); _currentFocusItem = item; @@ -919,14 +919,20 @@ void OffscreenQmlSurface::synthesizeKeyPress(QString key) { QCoreApplication::postEvent(getEventHandler(), releaseEvent); } -void OffscreenQmlSurface::setKeyboardRaised(QObject* object, bool raised) { +void OffscreenQmlSurface::setKeyboardRaised(QObject* object, bool raised, bool numeric) { if (!object) { return; } QQuickItem* item = dynamic_cast(object); 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"; + if (item->property("keyboardRaised").isValid()) { + if (item->property("punctuationMode").isValid()) { + item->setProperty("punctuationMode", QVariant(numeric)); + } item->setProperty("keyboardRaised", QVariant(raised)); return; } @@ -946,10 +952,14 @@ void OffscreenQmlSurface::emitWebEvent(const QVariant& message) { if (QThread::currentThread() != thread()) { QMetaObject::invokeMethod(this, "emitWebEvent", Qt::QueuedConnection, Q_ARG(QVariant, message)); } else { - // special case to handle raising and lowering the virtual keyboard - if (message.type() == QVariant::String && message.toString() == "_RAISE_KEYBOARD") { - setKeyboardRaised(_currentFocusItem, true); - } else if (message.type() == QVariant::String && message.toString() == "_LOWER_KEYBOARD") { + // Special case to handle raising and lowering the virtual keyboard. + const QString RAISE_KEYBOARD = "_RAISE_KEYBOARD"; + const QString RAISE_KEYBOARD_NUMERIC = "_RAISE_KEYBOARD_NUMERIC"; + const QString LOWER_KEYBOARD = "_LOWER_KEYBOARD"; + QString messageString = message.type() == QVariant::String ? message.toString() : ""; + if (messageString.left(RAISE_KEYBOARD.length()) == RAISE_KEYBOARD) { + setKeyboardRaised(_currentFocusItem, true, messageString == RAISE_KEYBOARD_NUMERIC); + } else if (messageString == LOWER_KEYBOARD) { setKeyboardRaised(_currentFocusItem, false); } else { emit webEventReceived(message); diff --git a/libraries/gl/src/gl/OffscreenQmlSurface.h b/libraries/gl/src/gl/OffscreenQmlSurface.h index 46abef272f..31741b09d5 100644 --- a/libraries/gl/src/gl/OffscreenQmlSurface.h +++ b/libraries/gl/src/gl/OffscreenQmlSurface.h @@ -70,7 +70,7 @@ public: QPointF mapToVirtualScreen(const QPointF& originalPoint, QObject* originalWidget); bool eventFilter(QObject* originalDestination, QEvent* event) override; - void setKeyboardRaised(QObject* object, bool raised); + void setKeyboardRaised(QObject* object, bool raised, bool numeric = false); Q_INVOKABLE void synthesizeKeyPress(QString key); diff --git a/libraries/ui/src/QmlWebWindowClass.cpp b/libraries/ui/src/QmlWebWindowClass.cpp index 5a357a83d4..84d0aa0489 100644 --- a/libraries/ui/src/QmlWebWindowClass.cpp +++ b/libraries/ui/src/QmlWebWindowClass.cpp @@ -43,10 +43,14 @@ void QmlWebWindowClass::emitWebEvent(const QVariant& webMessage) { if (QThread::currentThread() != thread()) { QMetaObject::invokeMethod(this, "emitWebEvent", Qt::QueuedConnection, Q_ARG(QVariant, webMessage)); } else { - // Special cases for raising and lowering the virtual keyboard. - if (webMessage.type() == QVariant::String && webMessage.toString() == "_RAISE_KEYBOARD") { - setKeyboardRaised(asQuickItem(), true); - } else if (webMessage.type() == QVariant::String && webMessage.toString() == "_LOWER_KEYBOARD") { + // Special case to handle raising and lowering the virtual keyboard. + const QString RAISE_KEYBOARD = "_RAISE_KEYBOARD"; + const QString RAISE_KEYBOARD_NUMERIC = "_RAISE_KEYBOARD_NUMERIC"; + const QString LOWER_KEYBOARD = "_LOWER_KEYBOARD"; + QString messageString = webMessage.type() == QVariant::String ? webMessage.toString() : ""; + if (messageString.left(RAISE_KEYBOARD.length()) == RAISE_KEYBOARD) { + setKeyboardRaised(asQuickItem(), true, messageString == RAISE_KEYBOARD_NUMERIC); + } else if (messageString == LOWER_KEYBOARD) { setKeyboardRaised(asQuickItem(), false); } else { emit webEventReceived(webMessage); @@ -54,7 +58,7 @@ void QmlWebWindowClass::emitWebEvent(const QVariant& webMessage) { } } -void QmlWebWindowClass::setKeyboardRaised(QObject* object, bool raised) { +void QmlWebWindowClass::setKeyboardRaised(QObject* object, bool raised, bool numeric) { if (!object) { return; } @@ -62,6 +66,9 @@ void QmlWebWindowClass::setKeyboardRaised(QObject* object, bool raised) { QQuickItem* item = dynamic_cast(object); while (item) { if (item->property("keyboardRaised").isValid()) { + if (item->property("punctuationMode").isValid()) { + item->setProperty("punctuationMode", QVariant(numeric)); + } item->setProperty("keyboardRaised", QVariant(raised)); return; } diff --git a/libraries/ui/src/QmlWebWindowClass.h b/libraries/ui/src/QmlWebWindowClass.h index 95851d2857..e32c6d5a04 100644 --- a/libraries/ui/src/QmlWebWindowClass.h +++ b/libraries/ui/src/QmlWebWindowClass.h @@ -35,7 +35,7 @@ protected: QString qmlSource() const override { return "QmlWebWindow.qml"; } private: - void setKeyboardRaised(QObject* object, bool raised); + void setKeyboardRaised(QObject* object, bool raised, bool numeric = false); }; #endif diff --git a/scripts/system/html/js/keyboardControl.js b/scripts/system/html/js/keyboardControl.js index b19b8953c0..291330e8de 100644 --- a/scripts/system/html/js/keyboardControl.js +++ b/scripts/system/html/js/keyboardControl.js @@ -20,18 +20,15 @@ function setUpKeyboardControl() { lowerTimer = null; } - if (isRaised) { - return; - } + EventBridge.emitWebEvent("_RAISE_KEYBOARD" + (this.type === "number" ? "_NUMERIC" : "")); - var delta = this.getBoundingClientRect().bottom + 10 - (document.body.clientHeight - KEYBOARD_HEIGHT); - - EventBridge.emitWebEvent("_RAISE_KEYBOARD"); - - if (delta > 0) { - setTimeout(function () { - document.body.scrollTop += delta; - }, 500); // Allow time for keyboard to be raised in QML. + if (!isRaised) { + var delta = this.getBoundingClientRect().bottom + 10 - (document.body.clientHeight - KEYBOARD_HEIGHT); + if (delta > 0) { + setTimeout(function () { + document.body.scrollTop += delta; + }, 500); // Allow time for keyboard to be raised in QML. + } } isRaised = true;