From ef8c2a288847e951a750d4a4886b0b0b229447a5 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 9 Sep 2016 10:46:54 -0700 Subject: [PATCH 01/47] started to move WebEntityAPIHelper from RenderableWebEntityItem to OffscreenQmlSurface --- .../src/RenderableWebEntityItem.cpp | 29 ---------------- .../src/RenderableWebEntityItem.h | 23 ++----------- libraries/gl/src/gl/OffscreenQmlSurface.cpp | 33 +++++++++++++++++++ libraries/gl/src/gl/OffscreenQmlSurface.h | 25 ++++++++++++++ 4 files changed, 60 insertions(+), 50 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp index cc022d9df2..e821a3b582 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp @@ -38,35 +38,6 @@ static uint64_t MAX_NO_RENDER_INTERVAL = 30 * USECS_PER_SECOND; static int MAX_WINDOW_SIZE = 4096; static float OPAQUE_ALPHA_THRESHOLD = 0.99f; -void WebEntityAPIHelper::synthesizeKeyPress(QString key) { - if (_renderableWebEntityItem) { - _renderableWebEntityItem->synthesizeKeyPress(key); - } -} - -void WebEntityAPIHelper::emitScriptEvent(const QVariant& message) { - if (QThread::currentThread() != thread()) { - QMetaObject::invokeMethod(this, "emitScriptEvent", Qt::QueuedConnection, Q_ARG(QVariant, message)); - } else { - emit scriptEventReceived(message); - } -} - -void WebEntityAPIHelper::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" && _renderableWebEntityItem) { - _renderableWebEntityItem->setKeyboardRaised(true); - } else if (message.type() == QVariant::String && message.toString() == "_LOWER_KEYBOARD" && _renderableWebEntityItem) { - _renderableWebEntityItem->setKeyboardRaised(false); - } else { - emit webEventReceived(message); - } - } -} - EntityItemPointer RenderableWebEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) { EntityItemPointer entity{ new RenderableWebEntityItem(entityID) }; entity->setProperties(properties); diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.h b/libraries/entities-renderer/src/RenderableWebEntityItem.h index 47808c4262..3a4a5293e7 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.h +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.h @@ -13,36 +13,18 @@ #include #include #include +#include #include #include "RenderableEntityItem.h" -class OffscreenQmlSurface; + class QWindow; class QObject; class EntityTreeRenderer; class RenderableWebEntityItem; -class WebEntityAPIHelper : public QObject { - Q_OBJECT -public: - void setRenderableWebEntityItem(RenderableWebEntityItem* renderableWebEntityItem) { - _renderableWebEntityItem = renderableWebEntityItem; - } - Q_INVOKABLE void synthesizeKeyPress(QString key); - - // event bridge -public slots: - void emitScriptEvent(const QVariant& scriptMessage); - void emitWebEvent(const QVariant& webMessage); -signals: - void scriptEventReceived(const QVariant& message); - void webEventReceived(const QVariant& message); - -protected: - RenderableWebEntityItem* _renderableWebEntityItem{ nullptr }; -}; class RenderableWebEntityItem : public WebEntityItem { public: @@ -86,7 +68,6 @@ private: QTouchEvent _lastTouchEvent { QEvent::TouchUpdate }; uint64_t _lastRenderTime{ 0 }; QTouchDevice _touchDevice; - WebEntityAPIHelper* _webEntityAPIHelper; QMetaObject::Connection _mousePressConnection; QMetaObject::Connection _mouseReleaseConnection; diff --git a/libraries/gl/src/gl/OffscreenQmlSurface.cpp b/libraries/gl/src/gl/OffscreenQmlSurface.cpp index 5ab2678474..0dd0a4b13c 100644 --- a/libraries/gl/src/gl/OffscreenQmlSurface.cpp +++ b/libraries/gl/src/gl/OffscreenQmlSurface.cpp @@ -829,4 +829,37 @@ void OffscreenQmlSurface::setFocusText(bool newFocusText) { } } + +void WebEntityAPIHelper::synthesizeKeyPress(QString key) { + if (_renderableWebEntityItem) { + _renderableWebEntityItem->synthesizeKeyPress(key); + } +} + +void WebEntityAPIHelper::emitScriptEvent(const QVariant& message) { + if (QThread::currentThread() != thread()) { + QMetaObject::invokeMethod(this, "emitScriptEvent", Qt::QueuedConnection, Q_ARG(QVariant, message)); + } else { + emit scriptEventReceived(message); + } +} + +void WebEntityAPIHelper::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" && _renderableWebEntityItem) { + _renderableWebEntityItem->setKeyboardRaised(true); + } else if (message.type() == QVariant::String && message.toString() == "_LOWER_KEYBOARD" && _renderableWebEntityItem) { + _renderableWebEntityItem->setKeyboardRaised(false); + } else { + emit webEventReceived(message); + } + } +} + + + + #include "OffscreenQmlSurface.moc" diff --git a/libraries/gl/src/gl/OffscreenQmlSurface.h b/libraries/gl/src/gl/OffscreenQmlSurface.h index a4a5ecba7e..77ced00db6 100644 --- a/libraries/gl/src/gl/OffscreenQmlSurface.h +++ b/libraries/gl/src/gl/OffscreenQmlSurface.h @@ -28,6 +28,28 @@ class QQuickItem; class OffscreenQmlRenderThread; + +class WebEntityAPIHelper : public QObject { + Q_OBJECT +public: + void setRenderableWebEntityItem(RenderableWebEntityItem* renderableWebEntityItem) { + _renderableWebEntityItem = renderableWebEntityItem; + } + Q_INVOKABLE void synthesizeKeyPress(QString key); + + // event bridge +public slots: + void emitScriptEvent(const QVariant& scriptMessage); + void emitWebEvent(const QVariant& webMessage); +signals: + void scriptEventReceived(const QVariant& message); + void webEventReceived(const QVariant& message); + +protected: + RenderableWebEntityItem* _renderableWebEntityItem{ nullptr }; +}; + + class OffscreenQmlSurface : public QObject { Q_OBJECT Q_PROPERTY(bool focusText READ isFocusText NOTIFY focusTextChanged) @@ -69,6 +91,9 @@ public: QPointF mapToVirtualScreen(const QPointF& originalPoint, QObject* originalWidget); bool eventFilter(QObject* originalDestination, QEvent* event) override; + // XXX make private + WebEntityAPIHelper* _webEntityAPIHelper; + signals: void textureUpdated(unsigned int texture); void focusObjectChanged(QObject* newFocus); From 02dba2fe49fa3e099aefd5ea896b553ee60e4bbe Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 9 Sep 2016 11:23:37 -0700 Subject: [PATCH 02/47] started to move WebEntityAPIHelper from RenderableWebEntityItem to OffscreenQmlSurface --- .../src/RenderableWebEntityItem.cpp | 68 +--------------- .../src/RenderableWebEntityItem.h | 4 - libraries/gl/src/gl/OffscreenQmlSurface.cpp | 79 +++++++++++++++++-- libraries/gl/src/gl/OffscreenQmlSurface.h | 11 ++- 4 files changed, 83 insertions(+), 79 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp index e821a3b582..bcaafee862 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp @@ -53,20 +53,14 @@ RenderableWebEntityItem::RenderableWebEntityItem(const EntityItemID& entityItemI _touchDevice.setName("RenderableWebEntityItemTouchDevice"); _touchDevice.setMaximumTouchPoints(4); - _webEntityAPIHelper = new WebEntityAPIHelper; - _webEntityAPIHelper->setRenderableWebEntityItem(this); - _webEntityAPIHelper->moveToThread(qApp->thread()); - // forward web events to EntityScriptingInterface auto entities = DependencyManager::get(); - QObject::connect(_webEntityAPIHelper, &WebEntityAPIHelper::webEventReceived, [=](const QVariant& message) { + QObject::connect(_webSurface->_webEntityAPIHelper, &WebEntityAPIHelper::webEventReceived, [=](const QVariant& message) { emit entities->webEventReceived(entityItemID, message); }); } RenderableWebEntityItem::~RenderableWebEntityItem() { - _webEntityAPIHelper->setRenderableWebEntityItem(nullptr); - _webEntityAPIHelper->deleteLater(); destroyWebSurface(); qDebug() << "Destroyed web entity " << getID(); } @@ -103,10 +97,8 @@ bool RenderableWebEntityItem::buildWebSurface(EntityTreeRenderer* renderer) { context->setContextProperty("eventBridgeJavaScriptToInject", QVariant(javaScriptToInject)); }); _webSurface->resume(); - _webSurface->getRootItem()->setProperty("eventBridge", QVariant::fromValue(_webEntityAPIHelper)); _webSurface->getRootItem()->setProperty("url", _sourceUrl); _webSurface->getRootContext()->setContextProperty("desktop", QVariant()); - _webSurface->getRootContext()->setContextProperty("webEntity", _webEntityAPIHelper); _connection = QObject::connect(_webSurface, &OffscreenQmlSurface::textureUpdated, [&](GLuint textureId) { _texture = textureId; }); @@ -343,62 +335,6 @@ bool RenderableWebEntityItem::isTransparent() { return fadeRatio < OPAQUE_ALPHA_THRESHOLD; } -// UTF-8 encoded symbols -static const uint8_t UPWARDS_WHITE_ARROW_FROM_BAR[] = { 0xE2, 0x87, 0xAA, 0x00 }; // shift -static const uint8_t LEFT_ARROW[] = { 0xE2, 0x86, 0x90, 0x00 }; // backspace -static const uint8_t LEFTWARD_WHITE_ARROW[] = { 0xE2, 0x87, 0xA6, 0x00 }; // left arrow -static const uint8_t RIGHTWARD_WHITE_ARROW[] = { 0xE2, 0x87, 0xA8, 0x00 }; // right arrow -static const uint8_t ASTERISIM[] = { 0xE2, 0x81, 0x82, 0x00 }; // symbols -static const uint8_t RETURN_SYMBOL[] = { 0xE2, 0x8F, 0x8E, 0x00 }; // return -static const char PUNCTUATION_STRING[] = "&123"; -static const char ALPHABET_STRING[] = "abc"; - -static bool equals(const QByteArray& byteArray, const uint8_t* ptr) { - int i; - for (i = 0; i < byteArray.size(); i++) { - if ((char)ptr[i] != byteArray[i]) { - return false; - } - } - return ptr[i] == 0x00; -} - -void RenderableWebEntityItem::synthesizeKeyPress(QString key) { - auto utf8Key = key.toUtf8(); - - int scanCode = (int)utf8Key[0]; - QString keyString = key; - if (equals(utf8Key, UPWARDS_WHITE_ARROW_FROM_BAR) || equals(utf8Key, ASTERISIM) || - equals(utf8Key, (uint8_t*)PUNCTUATION_STRING) || equals(utf8Key, (uint8_t*)ALPHABET_STRING)) { - return; // ignore - } else if (equals(utf8Key, LEFT_ARROW)) { - scanCode = Qt::Key_Backspace; - keyString = "\x08"; - } else if (equals(utf8Key, RETURN_SYMBOL)) { - scanCode = Qt::Key_Return; - keyString = "\x0d"; - } else if (equals(utf8Key, LEFTWARD_WHITE_ARROW)) { - scanCode = Qt::Key_Left; - keyString = ""; - } else if (equals(utf8Key, RIGHTWARD_WHITE_ARROW)) { - scanCode = Qt::Key_Right; - keyString = ""; - } - - QKeyEvent* pressEvent = new QKeyEvent(QEvent::KeyPress, scanCode, Qt::NoModifier, keyString); - QKeyEvent* releaseEvent = new QKeyEvent(QEvent::KeyRelease, scanCode, Qt::NoModifier, keyString); - QCoreApplication::postEvent(getEventHandler(), pressEvent); - QCoreApplication::postEvent(getEventHandler(), releaseEvent); -} - void RenderableWebEntityItem::emitScriptEvent(const QVariant& message) { - _webEntityAPIHelper->emitScriptEvent(message); -} - -void RenderableWebEntityItem::setKeyboardRaised(bool raised) { - - // raise the keyboard only while in HMD mode and it's being requested. - bool value = AbstractViewStateInterface::instance()->isHMDMode() && raised; - - _webSurface->getRootItem()->setProperty("keyboardRaised", QVariant(value)); + _webSurface->_webEntityAPIHelper->emitScriptEvent(message); } diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.h b/libraries/entities-renderer/src/RenderableWebEntityItem.h index 3a4a5293e7..4ae771f24d 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.h +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.h @@ -46,15 +46,11 @@ public: bool needsToCallUpdate() const override { return _webSurface != nullptr; } virtual void emitScriptEvent(const QVariant& message) override; - void setKeyboardRaised(bool raised); SIMPLE_RENDERABLE(); virtual bool isTransparent() override; -public: - void synthesizeKeyPress(QString key); - private: bool buildWebSurface(EntityTreeRenderer* renderer); void destroyWebSurface(); diff --git a/libraries/gl/src/gl/OffscreenQmlSurface.cpp b/libraries/gl/src/gl/OffscreenQmlSurface.cpp index 0dd0a4b13c..6fcdee2812 100644 --- a/libraries/gl/src/gl/OffscreenQmlSurface.cpp +++ b/libraries/gl/src/gl/OffscreenQmlSurface.cpp @@ -419,6 +419,9 @@ bool OffscreenQmlRenderThread::allowNewFrame(uint8_t fps) { } OffscreenQmlSurface::OffscreenQmlSurface() { + _webEntityAPIHelper = new WebEntityAPIHelper; + _webEntityAPIHelper->setOffscreenQmlSurface(this); + _webEntityAPIHelper->moveToThread(qApp->thread()); } static const uint64_t MAX_SHUTDOWN_WAIT_SECS = 2; @@ -432,6 +435,9 @@ OffscreenQmlSurface::~OffscreenQmlSurface() { qWarning() << "Failed to shut down the QML Renderer Thread"; } + _webEntityAPIHelper->setOffscreenQmlSurface(nullptr); + _webEntityAPIHelper->deleteLater(); + delete _rootItem; delete _renderer; delete _qmlComponent; @@ -754,6 +760,9 @@ void OffscreenQmlSurface::pause() { void OffscreenQmlSurface::resume() { _paused = false; requestRender(); + + getRootItem()->setProperty("eventBridge", QVariant::fromValue(_webEntityAPIHelper)); + getRootContext()->setContextProperty("webEntity", _webEntityAPIHelper); } bool OffscreenQmlSurface::isPaused() const { @@ -829,10 +838,68 @@ void OffscreenQmlSurface::setFocusText(bool newFocusText) { } } +// UTF-8 encoded symbols +static const uint8_t UPWARDS_WHITE_ARROW_FROM_BAR[] = { 0xE2, 0x87, 0xAA, 0x00 }; // shift +static const uint8_t LEFT_ARROW[] = { 0xE2, 0x86, 0x90, 0x00 }; // backspace +static const uint8_t LEFTWARD_WHITE_ARROW[] = { 0xE2, 0x87, 0xA6, 0x00 }; // left arrow +static const uint8_t RIGHTWARD_WHITE_ARROW[] = { 0xE2, 0x87, 0xA8, 0x00 }; // right arrow +static const uint8_t ASTERISIM[] = { 0xE2, 0x81, 0x82, 0x00 }; // symbols +static const uint8_t RETURN_SYMBOL[] = { 0xE2, 0x8F, 0x8E, 0x00 }; // return +static const char PUNCTUATION_STRING[] = "&123"; +static const char ALPHABET_STRING[] = "abc"; + +static bool equals(const QByteArray& byteArray, const uint8_t* ptr) { + int i; + for (i = 0; i < byteArray.size(); i++) { + if ((char)ptr[i] != byteArray[i]) { + return false; + } + } + return ptr[i] == 0x00; +} + +void OffscreenQmlSurface::synthesizeKeyPress(QString key) { + auto utf8Key = key.toUtf8(); + + int scanCode = (int)utf8Key[0]; + QString keyString = key; + if (equals(utf8Key, UPWARDS_WHITE_ARROW_FROM_BAR) || equals(utf8Key, ASTERISIM) || + equals(utf8Key, (uint8_t*)PUNCTUATION_STRING) || equals(utf8Key, (uint8_t*)ALPHABET_STRING)) { + return; // ignore + } else if (equals(utf8Key, LEFT_ARROW)) { + scanCode = Qt::Key_Backspace; + keyString = "\x08"; + } else if (equals(utf8Key, RETURN_SYMBOL)) { + scanCode = Qt::Key_Return; + keyString = "\x0d"; + } else if (equals(utf8Key, LEFTWARD_WHITE_ARROW)) { + scanCode = Qt::Key_Left; + keyString = ""; + } else if (equals(utf8Key, RIGHTWARD_WHITE_ARROW)) { + scanCode = Qt::Key_Right; + keyString = ""; + } + + QKeyEvent* pressEvent = new QKeyEvent(QEvent::KeyPress, scanCode, Qt::NoModifier, keyString); + QKeyEvent* releaseEvent = new QKeyEvent(QEvent::KeyRelease, scanCode, Qt::NoModifier, keyString); + QCoreApplication::postEvent(getEventHandler(), pressEvent); + QCoreApplication::postEvent(getEventHandler(), releaseEvent); +} + +void OffscreenQmlSurface::setKeyboardRaised(bool raised) { + + // raise the keyboard only while in HMD mode and it's being requested. + // XXX + // bool value = AbstractViewStateInterface::instance()->isHMDMode() && raised; + // getRootItem()->setProperty("keyboardRaised", QVariant(value)); + + getRootItem()->setProperty("keyboardRaised", QVariant(raised)); + +} void WebEntityAPIHelper::synthesizeKeyPress(QString key) { - if (_renderableWebEntityItem) { - _renderableWebEntityItem->synthesizeKeyPress(key); + if (_offscreenQmlSurface) { + _offscreenQmlSurface->synthesizeKeyPress(key); } } @@ -849,10 +916,10 @@ void WebEntityAPIHelper::emitWebEvent(const QVariant& message) { 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" && _renderableWebEntityItem) { - _renderableWebEntityItem->setKeyboardRaised(true); - } else if (message.type() == QVariant::String && message.toString() == "_LOWER_KEYBOARD" && _renderableWebEntityItem) { - _renderableWebEntityItem->setKeyboardRaised(false); + if (message.type() == QVariant::String && message.toString() == "_RAISE_KEYBOARD" && _offscreenQmlSurface) { + _offscreenQmlSurface->setKeyboardRaised(true); + } else if (message.type() == QVariant::String && message.toString() == "_LOWER_KEYBOARD" && _offscreenQmlSurface) { + _offscreenQmlSurface->setKeyboardRaised(false); } else { emit webEventReceived(message); } diff --git a/libraries/gl/src/gl/OffscreenQmlSurface.h b/libraries/gl/src/gl/OffscreenQmlSurface.h index 77ced00db6..5c7444c947 100644 --- a/libraries/gl/src/gl/OffscreenQmlSurface.h +++ b/libraries/gl/src/gl/OffscreenQmlSurface.h @@ -27,13 +27,14 @@ class QQuickWindow; class QQuickItem; class OffscreenQmlRenderThread; +class OffscreenQmlSurface; class WebEntityAPIHelper : public QObject { Q_OBJECT public: - void setRenderableWebEntityItem(RenderableWebEntityItem* renderableWebEntityItem) { - _renderableWebEntityItem = renderableWebEntityItem; + void setOffscreenQmlSurface(OffscreenQmlSurface* renderableWebEntityItem) { + _offscreenQmlSurface = renderableWebEntityItem; } Q_INVOKABLE void synthesizeKeyPress(QString key); @@ -46,7 +47,7 @@ signals: void webEventReceived(const QVariant& message); protected: - RenderableWebEntityItem* _renderableWebEntityItem{ nullptr }; + OffscreenQmlSurface* _offscreenQmlSurface{ nullptr }; }; @@ -91,6 +92,10 @@ public: QPointF mapToVirtualScreen(const QPointF& originalPoint, QObject* originalWidget); bool eventFilter(QObject* originalDestination, QEvent* event) override; + void setKeyboardRaised(bool raised); + void synthesizeKeyPress(QString key); + + // XXX make private WebEntityAPIHelper* _webEntityAPIHelper; From 123ac541eaed95211f684cecb27e371a0f518363 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 9 Sep 2016 11:31:48 -0700 Subject: [PATCH 03/47] started to move WebEntityAPIHelper from RenderableWebEntityItem to OffscreenQmlSurface --- .../src/RenderableWebEntityItem.cpp | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp index bcaafee862..8ff9187adf 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp @@ -52,12 +52,6 @@ RenderableWebEntityItem::RenderableWebEntityItem(const EntityItemID& entityItemI _touchDevice.setType(QTouchDevice::TouchScreen); _touchDevice.setName("RenderableWebEntityItemTouchDevice"); _touchDevice.setMaximumTouchPoints(4); - - // forward web events to EntityScriptingInterface - auto entities = DependencyManager::get(); - QObject::connect(_webSurface->_webEntityAPIHelper, &WebEntityAPIHelper::webEventReceived, [=](const QVariant& message) { - emit entities->webEventReceived(entityItemID, message); - }); } RenderableWebEntityItem::~RenderableWebEntityItem() { @@ -102,6 +96,14 @@ bool RenderableWebEntityItem::buildWebSurface(EntityTreeRenderer* renderer) { _connection = QObject::connect(_webSurface, &OffscreenQmlSurface::textureUpdated, [&](GLuint textureId) { _texture = textureId; }); + + // forward web events to EntityScriptingInterface + auto entities = DependencyManager::get(); + const EntityItemID entityItemID = getID(); + QObject::connect(_webSurface->_webEntityAPIHelper, &WebEntityAPIHelper::webEventReceived, [=](const QVariant& message) { + emit entities->webEventReceived(entityItemID, message); + }); + // Restore the original GL context currentContext->makeCurrent(currentSurface); @@ -161,15 +163,10 @@ void RenderableWebEntityItem::render(RenderArgs* args) { #endif if (!_webSurface) { - #if defined(Q_OS_LINUX) - // these don't seem to work on Linux - return; - #else if (!buildWebSurface(static_cast(args->_renderer))) { return; } _fadeStartTime = usecTimestampNow(); - #endif } _lastRenderTime = usecTimestampNow(); From e5b56fec7c6b189937b03a17e826f1a9da7ffa4a Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 9 Sep 2016 11:32:17 -0700 Subject: [PATCH 04/47] put keyboard on location dialog --- interface/resources/qml/AddressBarDialog.qml | 38 ++++++++++++++++++-- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/interface/resources/qml/AddressBarDialog.qml b/interface/resources/qml/AddressBarDialog.qml index 2536fdade9..646c6bf2f0 100644 --- a/interface/resources/qml/AddressBarDialog.qml +++ b/interface/resources/qml/AddressBarDialog.qml @@ -18,6 +18,9 @@ import "hifi/toolbars" import "controls-uit" as HifiControls Window { + property bool keyboardRaised: true + property bool punctuationMode: false + id: root HifiConstants { id: hifi } @@ -68,7 +71,7 @@ Window { AddressBarDialog { id: addressBarDialog implicitWidth: backgroundImage.width - implicitHeight: backgroundImage.height + implicitHeight: backgroundImage.height + (keyboardRaised ? 200 : 0) // The buttons have their button state changed on hover, so we have to manually fix them up here onBackEnabledChanged: backArrow.buttonState = addressBarDialog.backEnabled ? 1 : 0; onForwardEnabledChanged: forwardArrow.buttonState = addressBarDialog.forwardEnabled ? 1 : 0; @@ -217,8 +220,8 @@ Window { } Window { - width: 938; - height: 625; + width: 938 + height: 625 scale: 0.8 // Reset scale of Window to 1.0 (counteract address bar's scale value of 1.25) HifiControls.WebView { anchors.fill: parent; @@ -235,6 +238,35 @@ Window { horizontalCenter: scroll.horizontalCenter; } } + + // virtual keyboard, letters + Keyboard { + id: keyboard1 + y: keyboardRaised ? parent.height : 0 + height: keyboardRaised ? 200 : 0 + visible: keyboardRaised && !punctuationMode + enabled: keyboardRaised && !punctuationMode + anchors.right: parent.right + anchors.rightMargin: 0 + anchors.left: parent.left + anchors.leftMargin: 0 + anchors.bottom: parent.bottom + anchors.bottomMargin: 0 + } + + KeyboardPunctuation { + id: keyboard2 + y: keyboardRaised ? parent.height : 0 + height: keyboardRaised ? 200 : 0 + visible: keyboardRaised && punctuationMode + enabled: keyboardRaised && punctuationMode + anchors.right: parent.right + anchors.rightMargin: 0 + anchors.left: parent.left + anchors.leftMargin: 0 + anchors.bottom: parent.bottom + anchors.bottomMargin: 0 + } } From f6398315b1aedaf80b9e1f714df17807bb9370cd Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 9 Sep 2016 11:48:14 -0700 Subject: [PATCH 05/47] avoid a crash-on-exit --- interface/src/Application.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 904a6c5b65..92ebd6b045 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -486,7 +486,7 @@ bool setupEssentials(int& argc, char** argv) { // FIXME move to header, or better yet, design some kind of UI manager // to take care of highlighting keyboard focused items, rather than // continuing to overburden Application.cpp -Cube3DOverlay* _keyboardFocusHighlight{ nullptr }; +std::shared_ptr _keyboardFocusHighlight{ nullptr }; int _keyboardFocusHighlightID{ -1 }; @@ -3587,7 +3587,7 @@ void Application::setKeyboardFocusEntity(EntityItemID entityItemID) { _keyboardFocusedItem.set(entityItemID); _lastAcceptedKeyPress = usecTimestampNow(); if (_keyboardFocusHighlightID < 0 || !getOverlays().isAddedOverlay(_keyboardFocusHighlightID)) { - _keyboardFocusHighlight = new Cube3DOverlay(); + _keyboardFocusHighlight = std::make_shared(); _keyboardFocusHighlight->setAlpha(1.0f); _keyboardFocusHighlight->setBorderSize(1.0f); _keyboardFocusHighlight->setColor({ 0xFF, 0xEF, 0x00 }); From dd39d468838fb46bad5192f6fae58c9d842ab6ee Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 9 Sep 2016 13:41:09 -0700 Subject: [PATCH 06/47] fold WebEntityAPIHelper members into OffscreenQmlSurface --- .../src/RenderableWebEntityItem.cpp | 8 ++-- libraries/gl/src/gl/OffscreenQmlSurface.cpp | 40 +++++++----------- libraries/gl/src/gl/OffscreenQmlSurface.h | 41 ++++++------------- 3 files changed, 29 insertions(+), 60 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp index 8ff9187adf..e6ebbf7668 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp @@ -100,7 +100,7 @@ bool RenderableWebEntityItem::buildWebSurface(EntityTreeRenderer* renderer) { // forward web events to EntityScriptingInterface auto entities = DependencyManager::get(); const EntityItemID entityItemID = getID(); - QObject::connect(_webSurface->_webEntityAPIHelper, &WebEntityAPIHelper::webEventReceived, [=](const QVariant& message) { + QObject::connect(_webSurface, &OffscreenQmlSurface::webEventReceived, [=](const QVariant& message) { emit entities->webEventReceived(entityItemID, message); }); @@ -308,7 +308,7 @@ void RenderableWebEntityItem::destroyWebSurface() { // The lifetime of the QML surface MUST be managed by the main thread // Additionally, we MUST use local variables copied by value, rather than - // member variables, since they would implicitly refer to a this that + // member variables, since they would implicitly refer to a this that // is no longer valid auto webSurface = _webSurface; AbstractViewStateInterface::instance()->postLambdaEvent([webSurface] { @@ -318,7 +318,6 @@ void RenderableWebEntityItem::destroyWebSurface() { } } - void RenderableWebEntityItem::update(const quint64& now) { auto interval = now - _lastRenderTime; if (interval > MAX_NO_RENDER_INTERVAL) { @@ -326,12 +325,11 @@ void RenderableWebEntityItem::update(const quint64& now) { } } - bool RenderableWebEntityItem::isTransparent() { float fadeRatio = _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) : 1.0f; return fadeRatio < OPAQUE_ALPHA_THRESHOLD; } void RenderableWebEntityItem::emitScriptEvent(const QVariant& message) { - _webSurface->_webEntityAPIHelper->emitScriptEvent(message); + _webSurface->emitScriptEvent(message); } diff --git a/libraries/gl/src/gl/OffscreenQmlSurface.cpp b/libraries/gl/src/gl/OffscreenQmlSurface.cpp index 6fcdee2812..fe25940198 100644 --- a/libraries/gl/src/gl/OffscreenQmlSurface.cpp +++ b/libraries/gl/src/gl/OffscreenQmlSurface.cpp @@ -419,9 +419,7 @@ bool OffscreenQmlRenderThread::allowNewFrame(uint8_t fps) { } OffscreenQmlSurface::OffscreenQmlSurface() { - _webEntityAPIHelper = new WebEntityAPIHelper; - _webEntityAPIHelper->setOffscreenQmlSurface(this); - _webEntityAPIHelper->moveToThread(qApp->thread()); + // moveToThread(qApp->thread()); } static const uint64_t MAX_SHUTDOWN_WAIT_SECS = 2; @@ -435,9 +433,6 @@ OffscreenQmlSurface::~OffscreenQmlSurface() { qWarning() << "Failed to shut down the QML Renderer Thread"; } - _webEntityAPIHelper->setOffscreenQmlSurface(nullptr); - _webEntityAPIHelper->deleteLater(); - delete _rootItem; delete _renderer; delete _qmlComponent; @@ -540,13 +535,13 @@ QObject* OffscreenQmlSurface::load(const QUrl& qmlSource, std::functionloadUrl(qmlSource, QQmlComponent::PreferSynchronous); if (_qmlComponent->isLoading()) { - connect(_qmlComponent, &QQmlComponent::statusChanged, this, + connect(_qmlComponent, &QQmlComponent::statusChanged, this, [this, f](QQmlComponent::Status){ finishQmlLoad(f); }); return nullptr; } - + return finishQmlLoad(f); } @@ -588,7 +583,7 @@ QObject* OffscreenQmlSurface::finishQmlLoad(std::function(newObject); if (newItem) { - // Make sure we make items focusable (critical for + // Make sure we make items focusable (critical for // supporting keyboard shortcuts) newItem->setFlag(QQuickItem::ItemIsFocusScope, true); } @@ -616,11 +611,11 @@ QObject* OffscreenQmlSurface::finishQmlLoad(std::function_rendering || !_renderer->allowNewFrame(_maxFps)) { return; } @@ -691,7 +686,6 @@ bool OffscreenQmlSurface::eventFilter(QObject* originalDestination, QEvent* even } #endif - switch (event->type()) { case QEvent::Resize: { QResizeEvent* resizeEvent = static_cast(event); @@ -761,8 +755,8 @@ void OffscreenQmlSurface::resume() { _paused = false; requestRender(); - getRootItem()->setProperty("eventBridge", QVariant::fromValue(_webEntityAPIHelper)); - getRootContext()->setContextProperty("webEntity", _webEntityAPIHelper); + getRootItem()->setProperty("eventBridge", QVariant::fromValue(this)); + getRootContext()->setContextProperty("webEntity", this); } bool OffscreenQmlSurface::isPaused() const { @@ -897,13 +891,7 @@ void OffscreenQmlSurface::setKeyboardRaised(bool raised) { } -void WebEntityAPIHelper::synthesizeKeyPress(QString key) { - if (_offscreenQmlSurface) { - _offscreenQmlSurface->synthesizeKeyPress(key); - } -} - -void WebEntityAPIHelper::emitScriptEvent(const QVariant& message) { +void OffscreenQmlSurface::emitScriptEvent(const QVariant& message) { if (QThread::currentThread() != thread()) { QMetaObject::invokeMethod(this, "emitScriptEvent", Qt::QueuedConnection, Q_ARG(QVariant, message)); } else { @@ -911,15 +899,15 @@ void WebEntityAPIHelper::emitScriptEvent(const QVariant& message) { } } -void WebEntityAPIHelper::emitWebEvent(const QVariant& message) { +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" && _offscreenQmlSurface) { - _offscreenQmlSurface->setKeyboardRaised(true); - } else if (message.type() == QVariant::String && message.toString() == "_LOWER_KEYBOARD" && _offscreenQmlSurface) { - _offscreenQmlSurface->setKeyboardRaised(false); + if (message.type() == QVariant::String && message.toString() == "_RAISE_KEYBOARD") { + setKeyboardRaised(true); + } else if (message.type() == QVariant::String && message.toString() == "_LOWER_KEYBOARD") { + setKeyboardRaised(false); } else { emit webEventReceived(message); } diff --git a/libraries/gl/src/gl/OffscreenQmlSurface.h b/libraries/gl/src/gl/OffscreenQmlSurface.h index 5c7444c947..ecdf3fbef5 100644 --- a/libraries/gl/src/gl/OffscreenQmlSurface.h +++ b/libraries/gl/src/gl/OffscreenQmlSurface.h @@ -25,31 +25,7 @@ class QQmlContext; class QQmlComponent; class QQuickWindow; class QQuickItem; - class OffscreenQmlRenderThread; -class OffscreenQmlSurface; - - -class WebEntityAPIHelper : public QObject { - Q_OBJECT -public: - void setOffscreenQmlSurface(OffscreenQmlSurface* renderableWebEntityItem) { - _offscreenQmlSurface = renderableWebEntityItem; - } - Q_INVOKABLE void synthesizeKeyPress(QString key); - - // event bridge -public slots: - void emitScriptEvent(const QVariant& scriptMessage); - void emitWebEvent(const QVariant& webMessage); -signals: - void scriptEventReceived(const QVariant& message); - void webEventReceived(const QVariant& message); - -protected: - OffscreenQmlSurface* _offscreenQmlSurface{ nullptr }; -}; - class OffscreenQmlSurface : public QObject { Q_OBJECT @@ -92,13 +68,10 @@ public: QPointF mapToVirtualScreen(const QPointF& originalPoint, QObject* originalWidget); bool eventFilter(QObject* originalDestination, QEvent* event) override; - void setKeyboardRaised(bool raised); - void synthesizeKeyPress(QString key); + Q_INVOKABLE void setKeyboardRaised(bool raised); + Q_INVOKABLE void synthesizeKeyPress(QString key); - // XXX make private - WebEntityAPIHelper* _webEntityAPIHelper; - signals: void textureUpdated(unsigned int texture); void focusObjectChanged(QObject* newFocus); @@ -109,6 +82,16 @@ public slots: void requestRender(); void onAboutToQuit(); + + // event bridge +public slots: + void emitScriptEvent(const QVariant& scriptMessage); + void emitWebEvent(const QVariant& webMessage); +signals: + void scriptEventReceived(const QVariant& message); + void webEventReceived(const QVariant& message); + + protected: bool filterEnabled(QObject* originalDestination, QEvent* event) const; void setFocusText(bool newFocusText); From c396196e0f068b6f9c0e5c34ed1faf50111d6cc1 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 9 Sep 2016 16:48:46 -0700 Subject: [PATCH 07/47] show and hide keyboard for qml windows --- interface/resources/qml/AddressBarDialog.qml | 5 ++- libraries/gl/src/gl/OffscreenQmlSurface.cpp | 34 +++++++++++++++++--- libraries/gl/src/gl/OffscreenQmlSurface.h | 6 ++-- 3 files changed, 37 insertions(+), 8 deletions(-) diff --git a/interface/resources/qml/AddressBarDialog.qml b/interface/resources/qml/AddressBarDialog.qml index 646c6bf2f0..e743031465 100644 --- a/interface/resources/qml/AddressBarDialog.qml +++ b/interface/resources/qml/AddressBarDialog.qml @@ -18,7 +18,7 @@ import "hifi/toolbars" import "controls-uit" as HifiControls Window { - property bool keyboardRaised: true + property bool keyboardRaised: false property bool punctuationMode: false id: root @@ -70,6 +70,7 @@ Window { AddressBarDialog { id: addressBarDialog + objectName: "AddressBarDialogDialog" implicitWidth: backgroundImage.width implicitHeight: backgroundImage.height + (keyboardRaised ? 200 : 0) // The buttons have their button state changed on hover, so we have to manually fix them up here @@ -126,6 +127,7 @@ Window { } Image { id: backgroundImage + objectName: "AddressBarDialogImage" source: "../images/address-bar.svg" width: 576 * root.scale height: 80 * root.scale @@ -175,6 +177,7 @@ Window { TextInput { id: addressLine focus: true + objectName: "AddressBarDialogTextInput" anchors { top: parent.top bottom: parent.bottom diff --git a/libraries/gl/src/gl/OffscreenQmlSurface.cpp b/libraries/gl/src/gl/OffscreenQmlSurface.cpp index fe25940198..4e7200c6c7 100644 --- a/libraries/gl/src/gl/OffscreenQmlSurface.cpp +++ b/libraries/gl/src/gl/OffscreenQmlSurface.cpp @@ -814,15 +814,29 @@ QVariant OffscreenQmlSurface::returnFromUiThread(std::function funct return function(); } +void OffscreenQmlSurface::focusDestroyed(QObject *obj) { + _currentFocusItem = nullptr; +} + void OffscreenQmlSurface::onFocusObjectChanged(QObject* object) { - if (!object) { + QQuickItem* item = dynamic_cast(object); + if (!item) { setFocusText(false); + _currentFocusItem = nullptr; return; } QInputMethodQueryEvent query(Qt::ImEnabled); qApp->sendEvent(object, &query); setFocusText(query.value(Qt::ImEnabled).toBool()); + + if (_currentFocusItem) { + disconnect(_currentFocusItem, &QObject::destroyed, this, 0); + setKeyboardRaised(_currentFocusItem, false); + } + setKeyboardRaised(item, item->hasActiveFocus()); + _currentFocusItem = item; + connect(_currentFocusItem, &QObject::destroyed, this, &OffscreenQmlSurface::focusDestroyed); } void OffscreenQmlSurface::setFocusText(bool newFocusText) { @@ -880,15 +894,25 @@ void OffscreenQmlSurface::synthesizeKeyPress(QString key) { QCoreApplication::postEvent(getEventHandler(), releaseEvent); } -void OffscreenQmlSurface::setKeyboardRaised(bool raised) { +void OffscreenQmlSurface::setKeyboardRaised(QObject* object, bool raised) { // raise the keyboard only while in HMD mode and it's being requested. // XXX // bool value = AbstractViewStateInterface::instance()->isHMDMode() && raised; // getRootItem()->setProperty("keyboardRaised", QVariant(value)); - getRootItem()->setProperty("keyboardRaised", QVariant(raised)); + if (!object) { + return; + } + QQuickItem* item = dynamic_cast(object); + while (item) { + if (item->property("keyboardRaised").isValid()) { + item->setProperty("keyboardRaised", QVariant(raised)); + return; + } + item = dynamic_cast(item->parentItem()); + } } void OffscreenQmlSurface::emitScriptEvent(const QVariant& message) { @@ -905,9 +929,9 @@ void OffscreenQmlSurface::emitWebEvent(const QVariant& message) { } else { // special case to handle raising and lowering the virtual keyboard if (message.type() == QVariant::String && message.toString() == "_RAISE_KEYBOARD") { - setKeyboardRaised(true); + setKeyboardRaised(getRootItem(), true); } else if (message.type() == QVariant::String && message.toString() == "_LOWER_KEYBOARD") { - setKeyboardRaised(false); + setKeyboardRaised(getRootItem(), false); } else { emit webEventReceived(message); } diff --git a/libraries/gl/src/gl/OffscreenQmlSurface.h b/libraries/gl/src/gl/OffscreenQmlSurface.h index ecdf3fbef5..bd83d4f41d 100644 --- a/libraries/gl/src/gl/OffscreenQmlSurface.h +++ b/libraries/gl/src/gl/OffscreenQmlSurface.h @@ -68,7 +68,7 @@ public: QPointF mapToVirtualScreen(const QPointF& originalPoint, QObject* originalWidget); bool eventFilter(QObject* originalDestination, QEvent* event) override; - Q_INVOKABLE void setKeyboardRaised(bool raised); + void setKeyboardRaised(QObject* object, bool raised); Q_INVOKABLE void synthesizeKeyPress(QString key); @@ -81,7 +81,7 @@ public slots: void requestUpdate(); void requestRender(); void onAboutToQuit(); - + void focusDestroyed(QObject *obj); // event bridge public slots: @@ -119,6 +119,8 @@ private: uint8_t _maxFps{ 60 }; MouseTranslator _mouseTranslator{ [](const QPointF& p) { return p.toPoint(); } }; QWindow* _proxyWindow { nullptr }; + + QQuickItem* _currentFocusItem { nullptr }; }; #endif From 44af3b43cc53437fe870bbbfff23f7e9b69f4f9a Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 9 Sep 2016 17:02:11 -0700 Subject: [PATCH 08/47] fix property access --- interface/resources/qml/AddressBarDialog.qml | 23 ++++++++++---------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/interface/resources/qml/AddressBarDialog.qml b/interface/resources/qml/AddressBarDialog.qml index e743031465..f257999dd9 100644 --- a/interface/resources/qml/AddressBarDialog.qml +++ b/interface/resources/qml/AddressBarDialog.qml @@ -18,9 +18,6 @@ import "hifi/toolbars" import "controls-uit" as HifiControls Window { - property bool keyboardRaised: false - property bool punctuationMode: false - id: root HifiConstants { id: hifi } @@ -71,6 +68,10 @@ Window { AddressBarDialog { id: addressBarDialog objectName: "AddressBarDialogDialog" + + property bool keyboardRaised: false + property bool punctuationMode: false + implicitWidth: backgroundImage.width implicitHeight: backgroundImage.height + (keyboardRaised ? 200 : 0) // The buttons have their button state changed on hover, so we have to manually fix them up here @@ -245,10 +246,10 @@ Window { // virtual keyboard, letters Keyboard { id: keyboard1 - y: keyboardRaised ? parent.height : 0 - height: keyboardRaised ? 200 : 0 - visible: keyboardRaised && !punctuationMode - enabled: keyboardRaised && !punctuationMode + y: parent.keyboardRaised ? parent.height : 0 + height: parent.keyboardRaised ? 200 : 0 + visible: parent.keyboardRaised && !parent.punctuationMode + enabled: parent.keyboardRaised && !parent.punctuationMode anchors.right: parent.right anchors.rightMargin: 0 anchors.left: parent.left @@ -259,10 +260,10 @@ Window { KeyboardPunctuation { id: keyboard2 - y: keyboardRaised ? parent.height : 0 - height: keyboardRaised ? 200 : 0 - visible: keyboardRaised && punctuationMode - enabled: keyboardRaised && punctuationMode + y: parent.keyboardRaised ? parent.height : 0 + height: parent.keyboardRaised ? 200 : 0 + visible: parent.keyboardRaised && parent.punctuationMode + enabled: parent.keyboardRaised && parent.punctuationMode anchors.right: parent.right anchors.rightMargin: 0 anchors.left: parent.left From 38a1556716bf46d36e2daa5cc63339c66ad0f940 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 12 Sep 2016 13:28:46 -0700 Subject: [PATCH 09/47] qml keyboard for running-scripts window --- .../qml/hifi/dialogs/RunningScripts.qml | 28 ++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/interface/resources/qml/hifi/dialogs/RunningScripts.qml b/interface/resources/qml/hifi/dialogs/RunningScripts.qml index 3f05a140ae..e1db3bc02f 100644 --- a/interface/resources/qml/hifi/dialogs/RunningScripts.qml +++ b/interface/resources/qml/hifi/dialogs/RunningScripts.qml @@ -16,6 +16,7 @@ import Qt.labs.settings 1.0 import "../../styles-uit" import "../../controls-uit" as HifiControls import "../../windows" +import "../../controls" ScrollingWindow { id: root @@ -92,6 +93,9 @@ ScrollingWindow { } Column { + property bool keyboardRaised: false + property bool punctuationMode: false + width: pane.contentWidth HifiControls.ContentSection { @@ -353,6 +357,28 @@ ScrollingWindow { visible: !isHMD } } + + // virtual keyboard, letters + Keyboard { + id: keyboard1 + height: parent.keyboardRaised ? 200 : 0 + visible: parent.keyboardRaised && !parent.punctuationMode + enabled: parent.keyboardRaised && !parent.punctuationMode + anchors.right: parent.right + anchors.rightMargin: 0 + anchors.left: parent.left + anchors.leftMargin: 0 + } + + KeyboardPunctuation { + id: keyboard2 + height: parent.keyboardRaised ? 200 : 0 + visible: parent.keyboardRaised && parent.punctuationMode + enabled: parent.keyboardRaised && parent.punctuationMode + anchors.right: parent.right + anchors.rightMargin: 0 + anchors.left: parent.left + anchors.leftMargin: 0 + } } } - From 4c370d0d32db74940935d09b28a1f5103d44bae3 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 12 Sep 2016 15:31:07 -0700 Subject: [PATCH 10/47] qml keyboard for query-dialog --- .../resources/qml/dialogs/QueryDialog.qml | 40 ++++++++++++++++++- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/interface/resources/qml/dialogs/QueryDialog.qml b/interface/resources/qml/dialogs/QueryDialog.qml index 05cb347169..865c2f1bd7 100644 --- a/interface/resources/qml/dialogs/QueryDialog.qml +++ b/interface/resources/qml/dialogs/QueryDialog.qml @@ -15,6 +15,7 @@ import QtQuick.Dialogs 1.2 as OriginalDialogs import "../controls-uit" import "../styles-uit" import "../windows" +import "../controls" as Controls ModalWindow { id: root @@ -53,11 +54,17 @@ ModalWindow { } Item { + id: modalWindowItem clip: true width: pane.width height: pane.height anchors.margins: 0 + property bool keyboardRaised: false + property bool punctuationMode: false + + onKeyboardRaisedChanged: d.resize(); + QtObject { id: d readonly property int minWidth: 480 @@ -69,14 +76,14 @@ ModalWindow { var targetWidth = Math.max(titleWidth, pane.width) var targetHeight = (items ? comboBox.controlHeight : textResult.controlHeight) + 5 * hifi.dimensions.contentSpacing.y + buttons.height root.width = (targetWidth < d.minWidth) ? d.minWidth : ((targetWidth > d.maxWdith) ? d.maxWidth : targetWidth) - root.height = (targetHeight < d.minHeight) ? d.minHeight: ((targetHeight > d.maxHeight) ? d.maxHeight : targetHeight) + root.height = ((targetHeight < d.minHeight) ? d.minHeight: ((targetHeight > d.maxHeight) ? d.maxHeight : targetHeight)) + (modalWindowItem.keyboardRaised ? (200 + 2 * hifi.dimensions.contentSpacing.y) : 0) } } Item { anchors { top: parent.top - bottom: buttons.top; + bottom: keyboard1.top; left: parent.left; right: parent.right; margins: 0 @@ -110,6 +117,35 @@ ModalWindow { } } + // virtual keyboard, letters + Controls.Keyboard { + id: keyboard1 + y: parent.keyboardRaised ? parent.height : 0 + height: parent.keyboardRaised ? 200 : 0 + visible: parent.keyboardRaised && !parent.punctuationMode + enabled: parent.keyboardRaised && !parent.punctuationMode + anchors.right: parent.right + anchors.rightMargin: 0 + anchors.left: parent.left + anchors.leftMargin: 0 + anchors.bottom: buttons.top + anchors.bottomMargin: 2 * hifi.dimensions.contentSpacing.y + } + + Controls.KeyboardPunctuation { + id: keyboard2 + y: parent.keyboardRaised ? parent.height : 0 + height: parent.keyboardRaised ? 200 : 0 + visible: parent.keyboardRaised && parent.punctuationMode + enabled: parent.keyboardRaised && parent.punctuationMode + anchors.right: parent.right + anchors.rightMargin: 0 + anchors.left: parent.left + anchors.leftMargin: 0 + anchors.bottom: buttons.top + anchors.bottomMargin: 2 * hifi.dimensions.contentSpacing.y + } + Flow { id: buttons focus: true From 3e86b2f0f284d42a7b8f22adb723a514d4fdd9b8 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 12 Sep 2016 15:34:29 -0700 Subject: [PATCH 11/47] remove some unneeded objectNames --- interface/resources/qml/AddressBarDialog.qml | 3 --- 1 file changed, 3 deletions(-) diff --git a/interface/resources/qml/AddressBarDialog.qml b/interface/resources/qml/AddressBarDialog.qml index f257999dd9..66e613ff4d 100644 --- a/interface/resources/qml/AddressBarDialog.qml +++ b/interface/resources/qml/AddressBarDialog.qml @@ -67,7 +67,6 @@ Window { AddressBarDialog { id: addressBarDialog - objectName: "AddressBarDialogDialog" property bool keyboardRaised: false property bool punctuationMode: false @@ -128,7 +127,6 @@ Window { } Image { id: backgroundImage - objectName: "AddressBarDialogImage" source: "../images/address-bar.svg" width: 576 * root.scale height: 80 * root.scale @@ -178,7 +176,6 @@ Window { TextInput { id: addressLine focus: true - objectName: "AddressBarDialogTextInput" anchors { top: parent.top bottom: parent.bottom From b841e3094d02f8260cbc59ec798ff153080b40c4 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 12 Sep 2016 16:23:05 -0700 Subject: [PATCH 12/47] qml keyboard for file dialog --- .../resources/qml/dialogs/FileDialog.qml | 40 ++++++++++++++++++- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/interface/resources/qml/dialogs/FileDialog.qml b/interface/resources/qml/dialogs/FileDialog.qml index ff8be580db..86804099e0 100644 --- a/interface/resources/qml/dialogs/FileDialog.qml +++ b/interface/resources/qml/dialogs/FileDialog.qml @@ -19,6 +19,7 @@ import ".." import "../controls-uit" import "../styles-uit" import "../windows" +import "../controls" as Controls import "fileDialog" @@ -27,7 +28,7 @@ ModalWindow { id: root resizable: true implicitWidth: 480 - implicitHeight: 360 + implicitHeight: 360 + (fileDialogItem.keyboardRaised ? 200 + (2 * hifi.dimensions.contentSpacing.y) : 0) minSize: Qt.vector2d(360, 240) draggable: true @@ -100,11 +101,16 @@ ModalWindow { } Item { + id: fileDialogItem clip: true width: pane.width height: pane.height anchors.margins: 0 + property bool keyboardRaised: false + property bool punctuationMode: false + + MouseArea { // Clear selection when click on internal unused area. anchors.fill: parent @@ -619,7 +625,7 @@ ModalWindow { left: parent.left right: selectionType.visible ? selectionType.left: parent.right rightMargin: selectionType.visible ? hifi.dimensions.contentSpacing.x : 0 - bottom: buttonRow.top + bottom: keyboard1.top bottomMargin: hifi.dimensions.contentSpacing.y } readOnly: !root.saveDialog @@ -640,6 +646,36 @@ ModalWindow { KeyNavigation.right: openButton } + + // virtual keyboard, letters + Controls.Keyboard { + id: keyboard1 + // y: parent.keyboardRaised ? parent.height : 0 + height: parent.keyboardRaised ? 200 : 0 + visible: parent.keyboardRaised && !parent.punctuationMode + enabled: parent.keyboardRaised && !parent.punctuationMode + anchors.right: parent.right + anchors.rightMargin: 0 + anchors.left: parent.left + anchors.leftMargin: 0 + anchors.bottom: buttonRow.top + anchors.bottomMargin: 2 * hifi.dimensions.contentSpacing.y + } + + Controls.KeyboardPunctuation { + id: keyboard2 + // y: parent.keyboardRaised ? parent.height : 0 + height: parent.keyboardRaised ? 200 : 0 + visible: parent.keyboardRaised && parent.punctuationMode + enabled: parent.keyboardRaised && parent.punctuationMode + anchors.right: parent.right + anchors.rightMargin: 0 + anchors.left: parent.left + anchors.leftMargin: 0 + anchors.bottom: buttonRow.top + anchors.bottomMargin: 2 * hifi.dimensions.contentSpacing.y + } + Row { id: buttonRow anchors { From 2c0676d9b1bf5446d33eb27a092d8a4993a2f2ba Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 12 Sep 2016 16:28:24 -0700 Subject: [PATCH 13/47] make qml keyboard work better in running-scripts dialog --- interface/resources/qml/hifi/dialogs/RunningScripts.qml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/interface/resources/qml/hifi/dialogs/RunningScripts.qml b/interface/resources/qml/hifi/dialogs/RunningScripts.qml index e1db3bc02f..043e454f46 100644 --- a/interface/resources/qml/hifi/dialogs/RunningScripts.qml +++ b/interface/resources/qml/hifi/dialogs/RunningScripts.qml @@ -24,8 +24,8 @@ ScrollingWindow { title: "Running Scripts" resizable: true destroyOnHidden: true - implicitWidth: 424 - implicitHeight: isHMD ? 695 : 728 + implicitWidth: 480 + implicitHeight: (isHMD ? 695 : 728) + (runningScriptsColumn.keyboardRaised ? 200 + (2 * hifi.dimensions.contentSpacing.y) : 0) minSize: Qt.vector2d(424, 300) HifiConstants { id: hifi } @@ -93,6 +93,8 @@ ScrollingWindow { } Column { + id: runningScriptsColumn + property bool keyboardRaised: false property bool punctuationMode: false From 753e4c4c7bc079ab463ff2ce2dacaae1b60388da Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 12 Sep 2016 16:49:10 -0700 Subject: [PATCH 14/47] keyboard for avatar attachment model url dialog --- .../hifi/dialogs/attachments/Attachment.qml | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/interface/resources/qml/hifi/dialogs/attachments/Attachment.qml b/interface/resources/qml/hifi/dialogs/attachments/Attachment.qml index 6d371741ea..730ab367fa 100644 --- a/interface/resources/qml/hifi/dialogs/attachments/Attachment.qml +++ b/interface/resources/qml/hifi/dialogs/attachments/Attachment.qml @@ -9,6 +9,7 @@ import ".." import "../../../styles-uit" import "../../../controls-uit" as HifiControls import "../../../windows" +import "../../../controls" as Controls Item { height: column.height + 2 * 8 @@ -34,6 +35,9 @@ Item { anchors { left: parent.left; right: parent.right; margins: 20 } spacing: 8 + property bool keyboardRaised: false + property bool punctuationMode: false + Item { height: modelChooserButton.height + urlLabel.height + 4 anchors { left: parent.left; right: parent.right;} @@ -71,6 +75,35 @@ Item { } } + // virtual keyboard, letters + Controls.Keyboard { + id: keyboard1 + // y: parent.keyboardRaised ? parent.height : 0 + height: parent.keyboardRaised ? 200 : 0 + visible: parent.keyboardRaised && !parent.punctuationMode + enabled: parent.keyboardRaised && !parent.punctuationMode + anchors.right: parent.right + anchors.rightMargin: 0 + anchors.left: parent.left + anchors.leftMargin: 0 + // anchors.bottom: buttonRow.top + // anchors.bottomMargin: 2 * hifi.dimensions.contentSpacing.y + } + + Controls.KeyboardPunctuation { + id: keyboard2 + // y: parent.keyboardRaised ? parent.height : 0 + height: parent.keyboardRaised ? 200 : 0 + visible: parent.keyboardRaised && parent.punctuationMode + enabled: parent.keyboardRaised && parent.punctuationMode + anchors.right: parent.right + anchors.rightMargin: 0 + anchors.left: parent.left + anchors.leftMargin: 0 + // anchors.bottom: buttonRow.top + // anchors.bottomMargin: 2 * hifi.dimensions.contentSpacing.y + } + Item { height: jointChooser.height + jointLabel.height + 4 anchors { left: parent.left; right: parent.right; } From 161424afaf7164abfd5501b21c60ead6e3a787e0 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 12 Sep 2016 21:39:52 -0700 Subject: [PATCH 15/47] qml keyboard for browsable preferences --- .../preferences/BrowsablePreference.qml | 40 ++++++++++++++++++- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/interface/resources/qml/dialogs/preferences/BrowsablePreference.qml b/interface/resources/qml/dialogs/preferences/BrowsablePreference.qml index 2cf50891c9..2e5ea7578c 100644 --- a/interface/resources/qml/dialogs/preferences/BrowsablePreference.qml +++ b/interface/resources/qml/dialogs/preferences/BrowsablePreference.qml @@ -12,12 +12,17 @@ import QtQuick 2.5 import "../../dialogs" import "../../controls-uit" +import "../../controls" as Controls + Preference { id: root property alias text: dataTextField.text property alias placeholderText: dataTextField.placeholderText - height: control.height + hifi.dimensions.controlInterlineHeight + height: control.height + hifi.dimensions.controlInterlineHeight + (keyboardRaised ? 200 : 0) + + property bool keyboardRaised: false + property bool punctuationMode: false Component.onCompleted: { dataTextField.text = preference.value; @@ -33,7 +38,7 @@ Preference { anchors { left: parent.left right: parent.right - bottom: parent.bottom + bottom: keyboard1.top } height: Math.max(dataTextField.controlHeight, button.height) @@ -76,4 +81,35 @@ Preference { } } } + + // virtual keyboard, letters + Controls.Keyboard { + id: keyboard1 + // y: parent.keyboardRaised ? parent.height : 0 + height: parent.keyboardRaised ? 200 : 0 + visible: parent.keyboardRaised && !parent.punctuationMode + enabled: parent.keyboardRaised && !parent.punctuationMode + anchors.right: parent.right + anchors.rightMargin: 0 + anchors.left: parent.left + anchors.leftMargin: 0 + anchors.bottom: parent.bottom + anchors.bottomMargin: 0 + // anchors.bottomMargin: 2 * hifi.dimensions.contentSpacing.y + } + + Controls.KeyboardPunctuation { + id: keyboard2 + // y: parent.keyboardRaised ? parent.height : 0 + height: parent.keyboardRaised ? 200 : 0 + visible: parent.keyboardRaised && parent.punctuationMode + enabled: parent.keyboardRaised && parent.punctuationMode + anchors.right: parent.right + anchors.rightMargin: 0 + anchors.left: parent.left + anchors.leftMargin: 0 + anchors.bottom: parent.bottom + anchors.bottomMargin: 0 + // anchors.bottomMargin: 2 * hifi.dimensions.contentSpacing.y + } } From dff567054dc0d2f4891fc5b60138b3c94d58628c Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 13 Sep 2016 11:17:00 -0700 Subject: [PATCH 16/47] qml keyboard for avatar preferences dialog --- .../dialogs/preferences/AvatarPreference.qml | 39 +++++++++- .../preferences/BrowsablePreference.qml | 73 ++++++++++--------- .../preferences/EditablePreference.qml | 58 +++++++++++++-- 3 files changed, 126 insertions(+), 44 deletions(-) diff --git a/interface/resources/qml/dialogs/preferences/AvatarPreference.qml b/interface/resources/qml/dialogs/preferences/AvatarPreference.qml index 8f05ca4ffe..16a96f791f 100644 --- a/interface/resources/qml/dialogs/preferences/AvatarPreference.qml +++ b/interface/resources/qml/dialogs/preferences/AvatarPreference.qml @@ -12,6 +12,7 @@ import QtQuick 2.5 import "../../dialogs" import "../../controls-uit" +import "../../controls" as Controls Preference { id: root @@ -53,12 +54,16 @@ Preference { Item { id: control + + property bool keyboardRaised: false + property bool punctuationMode: false + anchors { left: parent.left right: parent.right bottom: parent.bottom } - height: Math.max(dataTextField.controlHeight, button.height) + height: Math.max(dataTextField.controlHeight, button.height) + (keyboardRaised ? 200 : 0) TextField { id: dataTextField @@ -69,7 +74,7 @@ Preference { left: parent.left right: button.left rightMargin: hifi.dimensions.contentSpacing.x - bottom: parent.bottom + bottom: keyboard1.top } colorScheme: hifi.colorSchemes.dark } @@ -94,5 +99,35 @@ Preference { } } + // virtual keyboard, letters + Controls.Keyboard { + id: keyboard1 + // y: parent.keyboardRaised ? parent.height : 0 + height: parent.keyboardRaised ? 200 : 0 + visible: parent.keyboardRaised && !parent.punctuationMode + enabled: parent.keyboardRaised && !parent.punctuationMode + anchors.right: parent.right + anchors.rightMargin: 0 + anchors.left: parent.left + anchors.leftMargin: 0 + anchors.bottom: parent.bottom + anchors.bottomMargin: 0 + // anchors.bottomMargin: 2 * hifi.dimensions.contentSpacing.y + } + + Controls.KeyboardPunctuation { + id: keyboard2 + // y: parent.keyboardRaised ? parent.height : 0 + height: parent.keyboardRaised ? 200 : 0 + visible: parent.keyboardRaised && parent.punctuationMode + enabled: parent.keyboardRaised && parent.punctuationMode + anchors.right: parent.right + anchors.rightMargin: 0 + anchors.left: parent.left + anchors.leftMargin: 0 + anchors.bottom: parent.bottom + anchors.bottomMargin: 0 + // anchors.bottomMargin: 2 * hifi.dimensions.contentSpacing.y + } } } diff --git a/interface/resources/qml/dialogs/preferences/BrowsablePreference.qml b/interface/resources/qml/dialogs/preferences/BrowsablePreference.qml index 2e5ea7578c..4989c57694 100644 --- a/interface/resources/qml/dialogs/preferences/BrowsablePreference.qml +++ b/interface/resources/qml/dialogs/preferences/BrowsablePreference.qml @@ -19,10 +19,7 @@ Preference { id: root property alias text: dataTextField.text property alias placeholderText: dataTextField.placeholderText - height: control.height + hifi.dimensions.controlInterlineHeight + (keyboardRaised ? 200 : 0) - - property bool keyboardRaised: false - property bool punctuationMode: false + height: control.height + hifi.dimensions.controlInterlineHeight Component.onCompleted: { dataTextField.text = preference.value; @@ -35,12 +32,16 @@ Preference { Item { id: control + + property bool keyboardRaised: false + property bool punctuationMode: false + anchors { left: parent.left right: parent.right - bottom: keyboard1.top + bottom: parent.bottom } - height: Math.max(dataTextField.controlHeight, button.height) + height: Math.max(dataTextField.controlHeight, button.height) + (keyboardRaised ? 200 : 0) TextField { id: dataTextField @@ -49,7 +50,7 @@ Preference { left: parent.left right: button.left rightMargin: hifi.dimensions.contentSpacing.x - bottom: parent.bottom + bottom: keyboard1.top } label: root.label @@ -80,36 +81,36 @@ Preference { }); } } - } - // virtual keyboard, letters - Controls.Keyboard { - id: keyboard1 - // y: parent.keyboardRaised ? parent.height : 0 - height: parent.keyboardRaised ? 200 : 0 - visible: parent.keyboardRaised && !parent.punctuationMode - enabled: parent.keyboardRaised && !parent.punctuationMode - anchors.right: parent.right - anchors.rightMargin: 0 - anchors.left: parent.left - anchors.leftMargin: 0 - anchors.bottom: parent.bottom - anchors.bottomMargin: 0 - // anchors.bottomMargin: 2 * hifi.dimensions.contentSpacing.y - } + // virtual keyboard, letters + Controls.Keyboard { + id: keyboard1 + // y: parent.keyboardRaised ? parent.height : 0 + height: parent.keyboardRaised ? 200 : 0 + visible: parent.keyboardRaised && !parent.punctuationMode + enabled: parent.keyboardRaised && !parent.punctuationMode + anchors.right: parent.right + anchors.rightMargin: 0 + anchors.left: parent.left + anchors.leftMargin: 0 + anchors.bottom: parent.bottom + anchors.bottomMargin: 0 + // anchors.bottomMargin: 2 * hifi.dimensions.contentSpacing.y + } - Controls.KeyboardPunctuation { - id: keyboard2 - // y: parent.keyboardRaised ? parent.height : 0 - height: parent.keyboardRaised ? 200 : 0 - visible: parent.keyboardRaised && parent.punctuationMode - enabled: parent.keyboardRaised && parent.punctuationMode - anchors.right: parent.right - anchors.rightMargin: 0 - anchors.left: parent.left - anchors.leftMargin: 0 - anchors.bottom: parent.bottom - anchors.bottomMargin: 0 - // anchors.bottomMargin: 2 * hifi.dimensions.contentSpacing.y + Controls.KeyboardPunctuation { + id: keyboard2 + // y: parent.keyboardRaised ? parent.height : 0 + height: parent.keyboardRaised ? 200 : 0 + visible: parent.keyboardRaised && parent.punctuationMode + enabled: parent.keyboardRaised && parent.punctuationMode + anchors.right: parent.right + anchors.rightMargin: 0 + anchors.left: parent.left + anchors.leftMargin: 0 + anchors.bottom: parent.bottom + anchors.bottomMargin: 0 + // anchors.bottomMargin: 2 * hifi.dimensions.contentSpacing.y + } } } diff --git a/interface/resources/qml/dialogs/preferences/EditablePreference.qml b/interface/resources/qml/dialogs/preferences/EditablePreference.qml index 8acf8e1f76..40df94dd9f 100644 --- a/interface/resources/qml/dialogs/preferences/EditablePreference.qml +++ b/interface/resources/qml/dialogs/preferences/EditablePreference.qml @@ -12,10 +12,11 @@ import QtQuick 2.5 import "../../dialogs" import "../../controls-uit" +import "../../controls" as Controls Preference { id: root - height: dataTextField.controlHeight + hifi.dimensions.controlInterlineHeight + height: dataTextField.controlHeight + hifi.dimensions.controlInterlineHeight + (editablePreferenceColumn.keyboardRaised ? 200 : 0) Component.onCompleted: { dataTextField.text = preference.value; @@ -26,16 +27,61 @@ Preference { preference.save(); } - TextField { - id: dataTextField - placeholderText: preference.placeholderText - label: root.label - colorScheme: hifi.colorSchemes.dark + Column { + id: editablePreferenceColumn + height: dataTextField.height + (keyboardRaised ? 200 : 0) + + property bool keyboardRaised: false + property bool punctuationMode: false anchors { left: parent.left right: parent.right bottom: parent.bottom } + + TextField { + id: dataTextField + placeholderText: preference.placeholderText + label: root.label + colorScheme: hifi.colorSchemes.dark + + anchors { + left: parent.left + right: parent.right + // bottom: keyboard1.bottom + } + } + + // virtual keyboard, letters + Controls.Keyboard { + id: keyboard1 + // y: parent.keyboardRaised ? parent.height : 0 + height: parent.keyboardRaised ? 200 : 0 + visible: parent.keyboardRaised && !parent.punctuationMode + enabled: parent.keyboardRaised && !parent.punctuationMode + anchors.right: parent.right + anchors.rightMargin: 0 + anchors.left: parent.left + anchors.leftMargin: 0 + // anchors.bottom: parent.bottom + // anchors.bottomMargin: 0 + // anchors.bottomMargin: 2 * hifi.dimensions.contentSpacing.y + } + + Controls.KeyboardPunctuation { + id: keyboard2 + // y: parent.keyboardRaised ? parent.height : 0 + height: parent.keyboardRaised ? 200 : 0 + visible: parent.keyboardRaised && parent.punctuationMode + enabled: parent.keyboardRaised && parent.punctuationMode + anchors.right: parent.right + anchors.rightMargin: 0 + anchors.left: parent.left + anchors.leftMargin: 0 + // anchors.bottom: parent.bottom + // anchors.bottomMargin: 0 + // anchors.bottomMargin: 2 * hifi.dimensions.contentSpacing.y + } } } From 92bda6827b73ea74db8bc5bcca6c6adb34430044 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 13 Sep 2016 11:27:10 -0700 Subject: [PATCH 17/47] remove vive keyboard --- plugins/openvr/src/OpenVrHelpers.cpp | 82 ++-------------------------- 1 file changed, 6 insertions(+), 76 deletions(-) diff --git a/plugins/openvr/src/OpenVrHelpers.cpp b/plugins/openvr/src/OpenVrHelpers.cpp index 820476191a..f5e36492bd 100644 --- a/plugins/openvr/src/OpenVrHelpers.cpp +++ b/plugins/openvr/src/OpenVrHelpers.cpp @@ -44,7 +44,7 @@ static const uint32_t RELEASE_OPENVR_HMD_DELAY_MS = 5000; bool isOculusPresent() { bool result = false; -#if defined(Q_OS_WIN32) +#if defined(Q_OS_WIN32) HANDLE oculusServiceEvent = ::OpenEventW(SYNCHRONIZE, FALSE, L"OculusHMDConnected"); // The existence of the service indicates a running Oculus runtime if (oculusServiceEvent) { @@ -54,7 +54,7 @@ bool isOculusPresent() { } ::CloseHandle(oculusServiceEvent); } -#endif +#endif return result; } @@ -123,65 +123,12 @@ static bool _keyboardShown { false }; static bool _overlayRevealed { false }; static const uint32_t SHOW_KEYBOARD_DELAY_MS = 400; -void showOpenVrKeyboard(bool show = true) { - if (!_overlay) { - return; - } - - if (show) { - // To avoid flickering the keyboard when a text element is only briefly selected, - // show the keyboard asynchrnously after a very short delay, but only after we check - // that the current focus object is still one that is text enabled - QTimer::singleShot(SHOW_KEYBOARD_DELAY_MS, [] { - auto offscreenUi = DependencyManager::get(); - auto currentFocus = offscreenUi->getWindow()->focusObject(); - QInputMethodQueryEvent query(Qt::ImEnabled | Qt::ImQueryInput | Qt::ImHints); - qApp->sendEvent(currentFocus, &query); - // Current focus isn't text enabled, bail early. - if (!query.value(Qt::ImEnabled).toBool()) { - return; - } - // We're going to show the keyboard now... - _keyboardFocusObject = currentFocus; - _currentHints = Qt::InputMethodHints(query.value(Qt::ImHints).toUInt()); - vr::EGamepadTextInputMode inputMode = vr::k_EGamepadTextInputModeNormal; - if (_currentHints & Qt::ImhHiddenText) { - inputMode = vr::k_EGamepadTextInputModePassword; - } - vr::EGamepadTextInputLineMode lineMode = vr::k_EGamepadTextInputLineModeSingleLine; - if (_currentHints & Qt::ImhMultiLine) { - lineMode = vr::k_EGamepadTextInputLineModeMultipleLines; - } - _existingText = query.value(Qt::ImSurroundingText).toString(); - - auto showKeyboardResult = _overlay->ShowKeyboard(inputMode, lineMode, "Keyboard", 1024, - _existingText.toLocal8Bit().toStdString().c_str(), false, 0); - - if (vr::VROverlayError_None == showKeyboardResult) { - _keyboardShown = true; - // Try to position the keyboard slightly below where the user is looking. - mat4 headPose = cancelOutRollAndPitch(toGlm(_nextSimPoseData.vrPoses[0].mDeviceToAbsoluteTracking)); - mat4 keyboardTransform = glm::translate(headPose, vec3(0, -0.5, -1)); - keyboardTransform = keyboardTransform * glm::rotate(mat4(), 3.14159f / 4.0f, vec3(-1, 0, 0)); - auto keyboardTransformVr = toOpenVr(keyboardTransform); - _overlay->SetKeyboardTransformAbsolute(vr::ETrackingUniverseOrigin::TrackingUniverseStanding, &keyboardTransformVr); - } - }); - } else { - _keyboardFocusObject = nullptr; - if (_keyboardShown) { - _overlay->HideKeyboard(); - _keyboardShown = false; - } - } -} - void updateFromOpenVrKeyboardInput() { auto chars = _overlay->GetKeyboardText(textArray, 8192); auto newText = QString(QByteArray(textArray, chars)); _keyboardFocusObject->setProperty("text", newText); //// TODO modify the new text to match the possible input hints: - //// ImhDigitsOnly ImhFormattedNumbersOnly ImhUppercaseOnly ImhLowercaseOnly + //// ImhDigitsOnly ImhFormattedNumbersOnly ImhUppercaseOnly ImhLowercaseOnly //// ImhDialableCharactersOnly ImhEmailCharactersOnly ImhUrlCharactersOnly ImhLatinOnly //QInputMethodEvent event(_existingText, QList()); //event.setCommitString(newText, 0, _existingText.size()); @@ -208,11 +155,11 @@ void enableOpenVrKeyboard(PluginContainer* container) { auto offscreenUi = DependencyManager::get(); _overlay = vr::VROverlay(); - + auto menu = container->getPrimaryMenu(); auto action = menu->getActionForOption(MenuOption::Overlays); - // When the overlays are revealed, suppress the keyboard from appearing on text focus for a tenth of a second. + // When the overlays are revealed, suppress the keyboard from appearing on text focus for a tenth of a second. _overlayMenuConnection = QObject::connect(action, &QAction::triggered, [action] { if (action->isChecked()) { _overlayRevealed = true; @@ -220,23 +167,6 @@ void enableOpenVrKeyboard(PluginContainer* container) { QTimer::singleShot(KEYBOARD_DELAY_MS, [&] { _overlayRevealed = false; }); } }); - - _focusConnection = QObject::connect(offscreenUi->getWindow(), &QQuickWindow::focusObjectChanged, [](QObject* object) { - if (object != _keyboardFocusObject) { - showOpenVrKeyboard(false); - } - }); - - _focusTextConnection = QObject::connect(offscreenUi.data(), &OffscreenUi::focusTextChanged, [](bool focusText) { - if (_openVrDisplayActive) { - if (_overlayRevealed) { - // suppress at most one text focus event - _overlayRevealed = false; - return; - } - showOpenVrKeyboard(focusText); - } - }); } @@ -276,7 +206,7 @@ void handleOpenVrEvents() { updateFromOpenVrKeyboardInput(); break; - case vr::VREvent_KeyboardDone: + case vr::VREvent_KeyboardDone: finishOpenVrKeyboardInput(); // FALL THROUGH From 447de7cd5a41ce07b8ca1ab37e4c1d241d408f9e Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 13 Sep 2016 16:31:59 -0700 Subject: [PATCH 18/47] qml keyboard for edit.js window --- interface/resources/qml/ToolWindow.qml | 195 +++++++++++++++---------- 1 file changed, 120 insertions(+), 75 deletions(-) diff --git a/interface/resources/qml/ToolWindow.qml b/interface/resources/qml/ToolWindow.qml index f6a4600e06..59ef7520f5 100644 --- a/interface/resources/qml/ToolWindow.qml +++ b/interface/resources/qml/ToolWindow.qml @@ -18,6 +18,8 @@ import Qt.labs.settings 1.0 import "windows" import "controls-uit" import "styles-uit" +import "controls" as Controls + ScrollingWindow { id: toolWindow @@ -47,92 +49,135 @@ ScrollingWindow { property alias y: toolWindow.y } - TabView { - id: tabView; + Item { + id: toolWindowTabViewItem + height: pane.scrollHeight width: pane.contentWidth - height: pane.scrollHeight // Pane height so that don't use Window's scrollbars otherwise tabs may be scrolled out of view. - property int tabCount: 0 + anchors.left: parent.left + anchors.top: parent.top - Repeater { - model: 4 - Tab { - // Force loading of the content even if the tab is not visible - // (required for letting the C++ code access the webview) - active: true - enabled: false - property string originalUrl: ""; + property bool keyboardRaised: false + property bool punctuationMode: false - WebView { - id: webView; - anchors.fill: parent + TabView { + id: tabView; + width: pane.contentWidth + // Pane height so that don't use Window's scrollbars otherwise tabs may be scrolled out of view. + height: pane.scrollHeight - (toolWindowTabViewItem.keyboardRaised ? 200 : 0) + property int tabCount: 0 + + Repeater { + model: 4 + Tab { + // Force loading of the content even if the tab is not visible + // (required for letting the C++ code access the webview) + active: true enabled: false - property alias eventBridgeWrapper: eventBridgeWrapper - - QtObject { - id: eventBridgeWrapper - WebChannel.id: "eventBridgeWrapper" - property var eventBridge; + property string originalUrl: ""; + + WebView { + id: webView; + anchors.fill: parent + enabled: false + property alias eventBridgeWrapper: eventBridgeWrapper + + QtObject { + id: eventBridgeWrapper + WebChannel.id: "eventBridgeWrapper" + property var eventBridge; + } + + webChannel.registeredObjects: [eventBridgeWrapper] + onEnabledChanged: toolWindow.updateVisiblity(); + } + } + } + + style: TabViewStyle { + + frame: Rectangle { // Background shown before content loads. + anchors.fill: parent + color: hifi.colors.baseGray + } + + frameOverlap: 0 + + tab: Rectangle { + implicitWidth: text.width + implicitHeight: 3 * text.height + color: styleData.selected ? hifi.colors.black : hifi.colors.tabBackgroundDark + + RalewayRegular { + id: text + text: styleData.title + font.capitalization: Font.AllUppercase + size: hifi.fontSizes.tabName + width: tabView.tabCount > 1 ? styleData.availableWidth / tabView.tabCount : implicitWidth + 2 * hifi.dimensions.contentSpacing.x + elide: Text.ElideRight + color: styleData.selected ? hifi.colors.primaryHighlight : hifi.colors.lightGrayText + horizontalAlignment: Text.AlignHCenter + anchors.centerIn: parent } - webChannel.registeredObjects: [eventBridgeWrapper] - onEnabledChanged: toolWindow.updateVisiblity(); + Rectangle { // Separator. + width: 1 + height: parent.height + color: hifi.colors.black + anchors.left: parent.left + anchors.top: parent.top + visible: styleData.index > 0 + + Rectangle { + width: 1 + height: 1 + color: hifi.colors.baseGray + anchors.left: parent.left + anchors.bottom: parent.bottom + } + } + + Rectangle { // Active underline. + width: parent.width - (styleData.index > 0 ? 1 : 0) + height: 1 + anchors.right: parent.right + anchors.bottom: parent.bottom + color: styleData.selected ? hifi.colors.primaryHighlight : hifi.colors.baseGray + } } + + tabOverlap: 0 } } - style: TabViewStyle { + // virtual keyboard, letters + Controls.Keyboard { + id: keyboard1 + // y: parent.keyboardRaised ? parent.height : 0 + height: parent.keyboardRaised ? 200 : 0 + visible: parent.keyboardRaised && !parent.punctuationMode + enabled: parent.keyboardRaised && !parent.punctuationMode + anchors.right: parent.right + anchors.rightMargin: 0 + anchors.left: parent.left + anchors.leftMargin: 0 + anchors.bottom: parent.bottom + anchors.bottomMargin: 0 + // anchors.bottomMargin: 2 * hifi.dimensions.contentSpacing.y + } - frame: Rectangle { // Background shown before content loads. - anchors.fill: parent - color: hifi.colors.baseGray - } - - frameOverlap: 0 - - tab: Rectangle { - implicitWidth: text.width - implicitHeight: 3 * text.height - color: styleData.selected ? hifi.colors.black : hifi.colors.tabBackgroundDark - - RalewayRegular { - id: text - text: styleData.title - font.capitalization: Font.AllUppercase - size: hifi.fontSizes.tabName - width: tabView.tabCount > 1 ? styleData.availableWidth / tabView.tabCount : implicitWidth + 2 * hifi.dimensions.contentSpacing.x - elide: Text.ElideRight - color: styleData.selected ? hifi.colors.primaryHighlight : hifi.colors.lightGrayText - horizontalAlignment: Text.AlignHCenter - anchors.centerIn: parent - } - - Rectangle { // Separator. - width: 1 - height: parent.height - color: hifi.colors.black - anchors.left: parent.left - anchors.top: parent.top - visible: styleData.index > 0 - - Rectangle { - width: 1 - height: 1 - color: hifi.colors.baseGray - anchors.left: parent.left - anchors.bottom: parent.bottom - } - } - - Rectangle { // Active underline. - width: parent.width - (styleData.index > 0 ? 1 : 0) - height: 1 - anchors.right: parent.right - anchors.bottom: parent.bottom - color: styleData.selected ? hifi.colors.primaryHighlight : hifi.colors.baseGray - } - } - - tabOverlap: 0 + Controls.KeyboardPunctuation { + id: keyboard2 + // y: parent.keyboardRaised ? parent.height : 0 + height: parent.keyboardRaised ? 200 : 0 + visible: parent.keyboardRaised && parent.punctuationMode + enabled: parent.keyboardRaised && parent.punctuationMode + anchors.right: parent.right + anchors.rightMargin: 0 + anchors.left: parent.left + anchors.leftMargin: 0 + anchors.bottom: parent.bottom + anchors.bottomMargin: 0 + // anchors.bottomMargin: 2 * hifi.dimensions.contentSpacing.y } } From b48270c9a79b44cfd5455b1dd3b48685a33e041e Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 14 Sep 2016 10:25:30 -0700 Subject: [PATCH 19/47] don't accidently select entities through edit.js window --- scripts/system/libraries/entitySelectionTool.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/system/libraries/entitySelectionTool.js b/scripts/system/libraries/entitySelectionTool.js index 461204b7aa..6ae283573b 100644 --- a/scripts/system/libraries/entitySelectionTool.js +++ b/scripts/system/libraries/entitySelectionTool.js @@ -1029,7 +1029,9 @@ SelectionDisplay = (function() { var entityIntersection = Entities.findRayIntersection(pickRay, true); var overlayIntersection = Overlays.findRayIntersection(pickRay); if (entityIntersection.intersects && - (!overlayIntersection.intersects || (entityIntersection.distance < overlayIntersection.distance))) { + (!overlayIntersection.intersects || + (entityIntersection.distance < overlayIntersection.distance)) && + (!(Reticle.pointingAtSystemOverlay || Overlays.getOverlayAtPoint(Reticle.position)))) { selectionManager.setSelections([entityIntersection.entityID]); } } From 409ebe526b19e6a458e994b464a87dd48dc3d746 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 14 Sep 2016 10:38:08 -0700 Subject: [PATCH 20/47] qml keyboard for Browser window --- interface/resources/qml/Browser.qml | 37 ++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/interface/resources/qml/Browser.qml b/interface/resources/qml/Browser.qml index 631036580e..a221108bdc 100644 --- a/interface/resources/qml/Browser.qml +++ b/interface/resources/qml/Browser.qml @@ -6,6 +6,7 @@ import "controls-uit" import "styles" as HifiStyles import "styles-uit" import "windows" +import "controls" as Controls ScrollingWindow { id: root @@ -52,6 +53,9 @@ ScrollingWindow { width: pane.contentWidth implicitHeight: pane.scrollHeight + property bool keyboardRaised: false + property bool punctuationMode: false + Row { id: buttons spacing: 4 @@ -202,7 +206,7 @@ ScrollingWindow { url: "https://highfidelity.com" anchors.top: buttons.bottom anchors.topMargin: 8 - anchors.bottom: parent.bottom + anchors.bottom: keyboard1.top anchors.left: parent.left anchors.right: parent.right onFeaturePermissionRequested: { @@ -234,6 +238,37 @@ ScrollingWindow { profile: desktop.browserProfile } + // virtual keyboard, letters + Controls.Keyboard { + id: keyboard1 + // y: parent.keyboardRaised ? parent.height : 0 + height: parent.keyboardRaised ? 200 : 0 + visible: parent.keyboardRaised && !parent.punctuationMode + enabled: parent.keyboardRaised && !parent.punctuationMode + anchors.right: parent.right + anchors.rightMargin: 0 + anchors.left: parent.left + anchors.leftMargin: 0 + anchors.bottom: parent.bottom + anchors.bottomMargin: 0 + // anchors.bottomMargin: 2 * hifi.dimensions.contentSpacing.y + } + + Controls.KeyboardPunctuation { + id: keyboard2 + // y: parent.keyboardRaised ? parent.height : 0 + height: parent.keyboardRaised ? 200 : 0 + visible: parent.keyboardRaised && parent.punctuationMode + enabled: parent.keyboardRaised && parent.punctuationMode + anchors.right: parent.right + anchors.rightMargin: 0 + anchors.left: parent.left + anchors.leftMargin: 0 + anchors.bottom: parent.bottom + anchors.bottomMargin: 0 + // anchors.bottomMargin: 2 * hifi.dimensions.contentSpacing.y + } + } // item From 2e83f218449499f243091310c1d9989ced0b51bc Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 20 Sep 2016 13:32:05 -0700 Subject: [PATCH 21/47] merge from upstream --- scripts/system/libraries/entitySelectionTool.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/scripts/system/libraries/entitySelectionTool.js b/scripts/system/libraries/entitySelectionTool.js index 25bd0bd495..9d98a19305 100644 --- a/scripts/system/libraries/entitySelectionTool.js +++ b/scripts/system/libraries/entitySelectionTool.js @@ -1032,9 +1032,7 @@ SelectionDisplay = (function() { var entityIntersection = Entities.findRayIntersection(pickRay, true); var overlayIntersection = Overlays.findRayIntersection(pickRay); if (entityIntersection.intersects && - (!overlayIntersection.intersects || - (entityIntersection.distance < overlayIntersection.distance)) && - (!(Reticle.pointingAtSystemOverlay || Overlays.getOverlayAtPoint(Reticle.position)))) { + (!overlayIntersection.intersects || (entityIntersection.distance < overlayIntersection.distance))) { selectionManager.setSelections([entityIntersection.entityID]); } } From e1164edfde3a6199a31220931a130ce34e62c915 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 22 Sep 2016 15:28:49 +1200 Subject: [PATCH 22/47] Display keyboard only for editable fields --- libraries/gl/src/gl/OffscreenQmlSurface.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/gl/src/gl/OffscreenQmlSurface.cpp b/libraries/gl/src/gl/OffscreenQmlSurface.cpp index 29370194dd..e8b300f171 100644 --- a/libraries/gl/src/gl/OffscreenQmlSurface.cpp +++ b/libraries/gl/src/gl/OffscreenQmlSurface.cpp @@ -835,7 +835,8 @@ void OffscreenQmlSurface::onFocusObjectChanged(QObject* object) { disconnect(_currentFocusItem, &QObject::destroyed, this, 0); setKeyboardRaised(_currentFocusItem, false); } - setKeyboardRaised(item, item->hasActiveFocus()); + const char* READ_ONLY_PROPERTY = "readOnly"; + setKeyboardRaised(item, item->hasActiveFocus() && item->property(READ_ONLY_PROPERTY) == false); _currentFocusItem = item; connect(_currentFocusItem, &QObject::destroyed, this, &OffscreenQmlSurface::focusDestroyed); } From 52137cb3c1357b50cd327ade13746e3e1b3aa5d4 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sat, 24 Sep 2016 11:40:38 +1200 Subject: [PATCH 23/47] Put keyboard at bottom of scrolling dialogs rather than under controls --- interface/resources/qml/Browser.qml | 37 +----------- .../qml/dialogs/PreferencesDialog.qml | 4 +- .../dialogs/preferences/AvatarPreference.qml | 39 +------------ .../preferences/BrowsablePreference.qml | 41 +------------ .../preferences/EditablePreference.qml | 58 ++----------------- .../qml/hifi/dialogs/RunningScripts.qml | 34 +---------- .../resources/qml/windows/ScrollingWindow.qml | 55 ++++++++++++++++-- 7 files changed, 65 insertions(+), 203 deletions(-) diff --git a/interface/resources/qml/Browser.qml b/interface/resources/qml/Browser.qml index a221108bdc..631036580e 100644 --- a/interface/resources/qml/Browser.qml +++ b/interface/resources/qml/Browser.qml @@ -6,7 +6,6 @@ import "controls-uit" import "styles" as HifiStyles import "styles-uit" import "windows" -import "controls" as Controls ScrollingWindow { id: root @@ -53,9 +52,6 @@ ScrollingWindow { width: pane.contentWidth implicitHeight: pane.scrollHeight - property bool keyboardRaised: false - property bool punctuationMode: false - Row { id: buttons spacing: 4 @@ -206,7 +202,7 @@ ScrollingWindow { url: "https://highfidelity.com" anchors.top: buttons.bottom anchors.topMargin: 8 - anchors.bottom: keyboard1.top + anchors.bottom: parent.bottom anchors.left: parent.left anchors.right: parent.right onFeaturePermissionRequested: { @@ -238,37 +234,6 @@ ScrollingWindow { profile: desktop.browserProfile } - // virtual keyboard, letters - Controls.Keyboard { - id: keyboard1 - // y: parent.keyboardRaised ? parent.height : 0 - height: parent.keyboardRaised ? 200 : 0 - visible: parent.keyboardRaised && !parent.punctuationMode - enabled: parent.keyboardRaised && !parent.punctuationMode - anchors.right: parent.right - anchors.rightMargin: 0 - anchors.left: parent.left - anchors.leftMargin: 0 - anchors.bottom: parent.bottom - anchors.bottomMargin: 0 - // anchors.bottomMargin: 2 * hifi.dimensions.contentSpacing.y - } - - Controls.KeyboardPunctuation { - id: keyboard2 - // y: parent.keyboardRaised ? parent.height : 0 - height: parent.keyboardRaised ? 200 : 0 - visible: parent.keyboardRaised && parent.punctuationMode - enabled: parent.keyboardRaised && parent.punctuationMode - anchors.right: parent.right - anchors.rightMargin: 0 - anchors.left: parent.left - anchors.leftMargin: 0 - anchors.bottom: parent.bottom - anchors.bottomMargin: 0 - // anchors.bottomMargin: 2 * hifi.dimensions.contentSpacing.y - } - } // item diff --git a/interface/resources/qml/dialogs/PreferencesDialog.qml b/interface/resources/qml/dialogs/PreferencesDialog.qml index 5278118a22..ac9aad0e4a 100644 --- a/interface/resources/qml/dialogs/PreferencesDialog.qml +++ b/interface/resources/qml/dialogs/PreferencesDialog.qml @@ -97,9 +97,9 @@ ScrollingWindow { footer: Row { anchors { - right: parent.right; + top: parent.top + right: parent.right rightMargin: hifi.dimensions.contentMargin.x - verticalCenter: parent.verticalCenter } spacing: hifi.dimensions.contentSpacing.x diff --git a/interface/resources/qml/dialogs/preferences/AvatarPreference.qml b/interface/resources/qml/dialogs/preferences/AvatarPreference.qml index 16a96f791f..8f05ca4ffe 100644 --- a/interface/resources/qml/dialogs/preferences/AvatarPreference.qml +++ b/interface/resources/qml/dialogs/preferences/AvatarPreference.qml @@ -12,7 +12,6 @@ import QtQuick 2.5 import "../../dialogs" import "../../controls-uit" -import "../../controls" as Controls Preference { id: root @@ -54,16 +53,12 @@ Preference { Item { id: control - - property bool keyboardRaised: false - property bool punctuationMode: false - anchors { left: parent.left right: parent.right bottom: parent.bottom } - height: Math.max(dataTextField.controlHeight, button.height) + (keyboardRaised ? 200 : 0) + height: Math.max(dataTextField.controlHeight, button.height) TextField { id: dataTextField @@ -74,7 +69,7 @@ Preference { left: parent.left right: button.left rightMargin: hifi.dimensions.contentSpacing.x - bottom: keyboard1.top + bottom: parent.bottom } colorScheme: hifi.colorSchemes.dark } @@ -99,35 +94,5 @@ Preference { } } - // virtual keyboard, letters - Controls.Keyboard { - id: keyboard1 - // y: parent.keyboardRaised ? parent.height : 0 - height: parent.keyboardRaised ? 200 : 0 - visible: parent.keyboardRaised && !parent.punctuationMode - enabled: parent.keyboardRaised && !parent.punctuationMode - anchors.right: parent.right - anchors.rightMargin: 0 - anchors.left: parent.left - anchors.leftMargin: 0 - anchors.bottom: parent.bottom - anchors.bottomMargin: 0 - // anchors.bottomMargin: 2 * hifi.dimensions.contentSpacing.y - } - - Controls.KeyboardPunctuation { - id: keyboard2 - // y: parent.keyboardRaised ? parent.height : 0 - height: parent.keyboardRaised ? 200 : 0 - visible: parent.keyboardRaised && parent.punctuationMode - enabled: parent.keyboardRaised && parent.punctuationMode - anchors.right: parent.right - anchors.rightMargin: 0 - anchors.left: parent.left - anchors.leftMargin: 0 - anchors.bottom: parent.bottom - anchors.bottomMargin: 0 - // anchors.bottomMargin: 2 * hifi.dimensions.contentSpacing.y - } } } diff --git a/interface/resources/qml/dialogs/preferences/BrowsablePreference.qml b/interface/resources/qml/dialogs/preferences/BrowsablePreference.qml index 4989c57694..2cf50891c9 100644 --- a/interface/resources/qml/dialogs/preferences/BrowsablePreference.qml +++ b/interface/resources/qml/dialogs/preferences/BrowsablePreference.qml @@ -12,8 +12,6 @@ import QtQuick 2.5 import "../../dialogs" import "../../controls-uit" -import "../../controls" as Controls - Preference { id: root @@ -32,16 +30,12 @@ Preference { Item { id: control - - property bool keyboardRaised: false - property bool punctuationMode: false - anchors { left: parent.left right: parent.right bottom: parent.bottom } - height: Math.max(dataTextField.controlHeight, button.height) + (keyboardRaised ? 200 : 0) + height: Math.max(dataTextField.controlHeight, button.height) TextField { id: dataTextField @@ -50,7 +44,7 @@ Preference { left: parent.left right: button.left rightMargin: hifi.dimensions.contentSpacing.x - bottom: keyboard1.top + bottom: parent.bottom } label: root.label @@ -81,36 +75,5 @@ Preference { }); } } - - // virtual keyboard, letters - Controls.Keyboard { - id: keyboard1 - // y: parent.keyboardRaised ? parent.height : 0 - height: parent.keyboardRaised ? 200 : 0 - visible: parent.keyboardRaised && !parent.punctuationMode - enabled: parent.keyboardRaised && !parent.punctuationMode - anchors.right: parent.right - anchors.rightMargin: 0 - anchors.left: parent.left - anchors.leftMargin: 0 - anchors.bottom: parent.bottom - anchors.bottomMargin: 0 - // anchors.bottomMargin: 2 * hifi.dimensions.contentSpacing.y - } - - Controls.KeyboardPunctuation { - id: keyboard2 - // y: parent.keyboardRaised ? parent.height : 0 - height: parent.keyboardRaised ? 200 : 0 - visible: parent.keyboardRaised && parent.punctuationMode - enabled: parent.keyboardRaised && parent.punctuationMode - anchors.right: parent.right - anchors.rightMargin: 0 - anchors.left: parent.left - anchors.leftMargin: 0 - anchors.bottom: parent.bottom - anchors.bottomMargin: 0 - // anchors.bottomMargin: 2 * hifi.dimensions.contentSpacing.y - } } } diff --git a/interface/resources/qml/dialogs/preferences/EditablePreference.qml b/interface/resources/qml/dialogs/preferences/EditablePreference.qml index 40df94dd9f..8acf8e1f76 100644 --- a/interface/resources/qml/dialogs/preferences/EditablePreference.qml +++ b/interface/resources/qml/dialogs/preferences/EditablePreference.qml @@ -12,11 +12,10 @@ import QtQuick 2.5 import "../../dialogs" import "../../controls-uit" -import "../../controls" as Controls Preference { id: root - height: dataTextField.controlHeight + hifi.dimensions.controlInterlineHeight + (editablePreferenceColumn.keyboardRaised ? 200 : 0) + height: dataTextField.controlHeight + hifi.dimensions.controlInterlineHeight Component.onCompleted: { dataTextField.text = preference.value; @@ -27,61 +26,16 @@ Preference { preference.save(); } - Column { - id: editablePreferenceColumn - height: dataTextField.height + (keyboardRaised ? 200 : 0) - - property bool keyboardRaised: false - property bool punctuationMode: false + TextField { + id: dataTextField + placeholderText: preference.placeholderText + label: root.label + colorScheme: hifi.colorSchemes.dark anchors { left: parent.left right: parent.right bottom: parent.bottom } - - TextField { - id: dataTextField - placeholderText: preference.placeholderText - label: root.label - colorScheme: hifi.colorSchemes.dark - - anchors { - left: parent.left - right: parent.right - // bottom: keyboard1.bottom - } - } - - // virtual keyboard, letters - Controls.Keyboard { - id: keyboard1 - // y: parent.keyboardRaised ? parent.height : 0 - height: parent.keyboardRaised ? 200 : 0 - visible: parent.keyboardRaised && !parent.punctuationMode - enabled: parent.keyboardRaised && !parent.punctuationMode - anchors.right: parent.right - anchors.rightMargin: 0 - anchors.left: parent.left - anchors.leftMargin: 0 - // anchors.bottom: parent.bottom - // anchors.bottomMargin: 0 - // anchors.bottomMargin: 2 * hifi.dimensions.contentSpacing.y - } - - Controls.KeyboardPunctuation { - id: keyboard2 - // y: parent.keyboardRaised ? parent.height : 0 - height: parent.keyboardRaised ? 200 : 0 - visible: parent.keyboardRaised && parent.punctuationMode - enabled: parent.keyboardRaised && parent.punctuationMode - anchors.right: parent.right - anchors.rightMargin: 0 - anchors.left: parent.left - anchors.leftMargin: 0 - // anchors.bottom: parent.bottom - // anchors.bottomMargin: 0 - // anchors.bottomMargin: 2 * hifi.dimensions.contentSpacing.y - } } } diff --git a/interface/resources/qml/hifi/dialogs/RunningScripts.qml b/interface/resources/qml/hifi/dialogs/RunningScripts.qml index 043e454f46..3f05a140ae 100644 --- a/interface/resources/qml/hifi/dialogs/RunningScripts.qml +++ b/interface/resources/qml/hifi/dialogs/RunningScripts.qml @@ -16,7 +16,6 @@ import Qt.labs.settings 1.0 import "../../styles-uit" import "../../controls-uit" as HifiControls import "../../windows" -import "../../controls" ScrollingWindow { id: root @@ -24,8 +23,8 @@ ScrollingWindow { title: "Running Scripts" resizable: true destroyOnHidden: true - implicitWidth: 480 - implicitHeight: (isHMD ? 695 : 728) + (runningScriptsColumn.keyboardRaised ? 200 + (2 * hifi.dimensions.contentSpacing.y) : 0) + implicitWidth: 424 + implicitHeight: isHMD ? 695 : 728 minSize: Qt.vector2d(424, 300) HifiConstants { id: hifi } @@ -93,11 +92,6 @@ ScrollingWindow { } Column { - id: runningScriptsColumn - - property bool keyboardRaised: false - property bool punctuationMode: false - width: pane.contentWidth HifiControls.ContentSection { @@ -359,28 +353,6 @@ ScrollingWindow { visible: !isHMD } } - - // virtual keyboard, letters - Keyboard { - id: keyboard1 - height: parent.keyboardRaised ? 200 : 0 - visible: parent.keyboardRaised && !parent.punctuationMode - enabled: parent.keyboardRaised && !parent.punctuationMode - anchors.right: parent.right - anchors.rightMargin: 0 - anchors.left: parent.left - anchors.leftMargin: 0 - } - - KeyboardPunctuation { - id: keyboard2 - height: parent.keyboardRaised ? 200 : 0 - visible: parent.keyboardRaised && parent.punctuationMode - enabled: parent.keyboardRaised && parent.punctuationMode - anchors.right: parent.right - anchors.rightMargin: 0 - anchors.left: parent.left - anchors.leftMargin: 0 - } } } + diff --git a/interface/resources/qml/windows/ScrollingWindow.qml b/interface/resources/qml/windows/ScrollingWindow.qml index f1dc744344..2050f0fbf2 100644 --- a/interface/resources/qml/windows/ScrollingWindow.qml +++ b/interface/resources/qml/windows/ScrollingWindow.qml @@ -15,6 +15,7 @@ import QtGraphicalEffects 1.0 import "." import "../styles-uit" +import "../controls" as HiFiControls // FIXME how do I set the initial position of a window without // overriding places where the a individual client of the window @@ -23,6 +24,7 @@ import "../styles-uit" // FIXME how to I enable dragging without allowing the window to lay outside // of the desktop? How do I ensure when the desktop resizes all the windows // are still at least partially visible? + Window { id: window HifiConstants { id: hifi } @@ -30,6 +32,9 @@ Window { property var footer: Item { } // Optional static footer at the bottom of the dialog. + property bool keyboardRaised: false + property bool punctuationMode: false + // Scrollable window content. // FIXME this should not define any visual content in this type. The base window // type should only consist of logic sized areas, with nothing drawn (although the @@ -73,7 +78,7 @@ Window { verticalScrollBarPolicy: Qt.ScrollBarAsNeeded anchors.fill: parent anchors.rightMargin: parent.isScrolling ? 1 : 0 - anchors.bottomMargin: footer.height > 0 ? footerPane.height : 0 + anchors.bottomMargin: footerPane.height style: ScrollViewStyle { @@ -119,18 +124,28 @@ Window { Rectangle { // Optional non-scrolling footer. id: footerPane + + property alias keyboardRaised: window.keyboardRaised + property alias punctuationMode: window.punctuationMode + anchors { left: parent.left bottom: parent.bottom } width: parent.contentWidth - height: footer.height + 2 * hifi.dimensions.contentSpacing.y + 3 + height: (footer.height > 0 ? footer.height + 2 * hifi.dimensions.contentSpacing.y + 3 : 0) + (keyboardRaised ? 200 : 0) color: hifi.colors.baseGray - visible: footer.height > 0 + visible: footer.height > 0 || keyboardRaised Item { // Horizontal rule. - anchors.fill: parent + anchors { + top: parent.top + left: parent.left + right: parent.right + } + + visible: footer.height > 0 Rectangle { width: parent.width @@ -148,10 +163,38 @@ Window { } Item { - anchors.fill: parent - anchors.topMargin: 3 // Horizontal rule. + anchors { + left: parent.left + right: parent.right + top: parent.top + topMargin: hifi.dimensions.contentSpacing.y + 3 + } children: [ footer ] } + + HiFiControls.Keyboard { + id: keyboard1 + height: parent.keyboardRaised ? 200 : 0 + visible: parent.keyboardRaised && !parent.punctuationMode + enabled: parent.keyboardRaised && !parent.punctuationMode + anchors { + left: parent.left + right: parent.right + bottom: parent.bottom + } + } + + HiFiControls.KeyboardPunctuation { + id: keyboard2 + height: parent.keyboardRaised ? 200 : 0 + visible: parent.keyboardRaised && parent.punctuationMode + enabled: parent.keyboardRaised && parent.punctuationMode + anchors { + left: parent.left + right: parent.right + bottom: parent.bottom + } + } } } } From 8663455d01c23d3da02c00b80796abda01bcdc60 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sat, 24 Sep 2016 17:34:02 +1200 Subject: [PATCH 24/47] Unfocus field and hide keyboard when click in blank part of dialog --- interface/resources/qml/controls-uit/ContentSection.qml | 7 ++++++- interface/resources/qml/windows/Window.qml | 4 +++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/interface/resources/qml/controls-uit/ContentSection.qml b/interface/resources/qml/controls-uit/ContentSection.qml index 98350a9333..3a87e3058a 100644 --- a/interface/resources/qml/controls-uit/ContentSection.qml +++ b/interface/resources/qml/controls-uit/ContentSection.qml @@ -109,8 +109,13 @@ Column { } MouseArea { + // Events are propogated so that any active control is defocussed. anchors.fill: parent - onClicked: toggleCollapsed() + propagateComposedEvents: true + onClicked: { + toggleCollapsed(); + mouse.accepted = false; + } } } diff --git a/interface/resources/qml/windows/Window.qml b/interface/resources/qml/windows/Window.qml index 40ef74c59b..4e0231ba06 100644 --- a/interface/resources/qml/windows/Window.qml +++ b/interface/resources/qml/windows/Window.qml @@ -133,7 +133,9 @@ Fadable { hoverEnabled: true acceptedButtons: Qt.AllButtons enabled: window.visible - onClicked: {} + onClicked: { + frame.forceActiveFocus(); // Defocus any current field so that the keyboard gets hidden. + } onDoubleClicked: {} onPressAndHold: {} onReleased: {} From 0f672c3aa29c415d8a1fa27c5b0f2e76ff87d9f4 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sat, 24 Sep 2016 18:56:35 +1200 Subject: [PATCH 25/47] Scroll content if necessary when keyboard is displayed --- .../resources/qml/windows/ScrollingWindow.qml | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/interface/resources/qml/windows/ScrollingWindow.qml b/interface/resources/qml/windows/ScrollingWindow.qml index 2050f0fbf2..ca378b82f2 100644 --- a/interface/resources/qml/windows/ScrollingWindow.qml +++ b/interface/resources/qml/windows/ScrollingWindow.qml @@ -31,6 +31,7 @@ Window { children: [ swallower, frame, pane, activator ] property var footer: Item { } // Optional static footer at the bottom of the dialog. + readonly property var footerContentHeight: footer.height > 0 ? (footer.height + 2 * hifi.dimensions.contentSpacing.y + 3) : 0 property bool keyboardRaised: false property bool punctuationMode: false @@ -121,6 +122,10 @@ Window { } } + function scrollBy(delta) { + scrollView.flickableItem.contentY += delta; + } + Rectangle { // Optional non-scrolling footer. id: footerPane @@ -133,7 +138,7 @@ Window { bottom: parent.bottom } width: parent.contentWidth - height: (footer.height > 0 ? footer.height + 2 * hifi.dimensions.contentSpacing.y + 3 : 0) + (keyboardRaised ? 200 : 0) + height: footerContentHeight + (keyboardRaised ? 200 : 0) color: hifi.colors.baseGray visible: footer.height > 0 || keyboardRaised @@ -197,4 +202,19 @@ Window { } } } + + onKeyboardRaisedChanged: { + if (keyboardRaised) { + var delta = activator.mouseY + - (activator.height + activator.y - 200 - footerContentHeight - hifi.dimensions.controlLineHeight); + + if (delta > 0) { + pane.scrollBy(delta); + } else { + // HACK: Work around for case where are 100% scrolled; stops window from erroneously scrolling to 100% when show keyboard. + pane.scrollBy(-1); + pane.scrollBy(1); + } + } + } } From 5b6835fbdb3714a6968ec7decf890900c502ce0d Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sat, 24 Sep 2016 21:23:30 +1200 Subject: [PATCH 26/47] Fix defocusing --- .../qml/controls-uit/ContentSection.qml | 2 +- .../resources/qml/windows/ScrollingWindow.qml | 2 +- interface/resources/qml/windows/Window.qml | 21 +++++++++++++++---- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/interface/resources/qml/controls-uit/ContentSection.qml b/interface/resources/qml/controls-uit/ContentSection.qml index 3a87e3058a..5fc86fc565 100644 --- a/interface/resources/qml/controls-uit/ContentSection.qml +++ b/interface/resources/qml/controls-uit/ContentSection.qml @@ -112,7 +112,7 @@ Column { // Events are propogated so that any active control is defocussed. anchors.fill: parent propagateComposedEvents: true - onClicked: { + onPressed: { toggleCollapsed(); mouse.accepted = false; } diff --git a/interface/resources/qml/windows/ScrollingWindow.qml b/interface/resources/qml/windows/ScrollingWindow.qml index ca378b82f2..2b80b01d95 100644 --- a/interface/resources/qml/windows/ScrollingWindow.qml +++ b/interface/resources/qml/windows/ScrollingWindow.qml @@ -28,7 +28,7 @@ import "../controls" as HiFiControls Window { id: window HifiConstants { id: hifi } - children: [ swallower, frame, pane, activator ] + children: [ swallower, frame, defocuser, pane, activator ] property var footer: Item { } // Optional static footer at the bottom of the dialog. readonly property var footerContentHeight: footer.height > 0 ? (footer.height + 2 * hifi.dimensions.contentSpacing.y + 3) : 0 diff --git a/interface/resources/qml/windows/Window.qml b/interface/resources/qml/windows/Window.qml index 4e0231ba06..35e0fb961c 100644 --- a/interface/resources/qml/windows/Window.qml +++ b/interface/resources/qml/windows/Window.qml @@ -44,7 +44,7 @@ Fadable { implicitHeight: content ? content.height : 0 implicitWidth: content ? content.width : 0 x: desktop.invalid_position; y: desktop.invalid_position; - children: [ swallower, frame, content, activator ] + children: [ swallower, frame, defocuser, content, activator ] // // Custom properties @@ -122,6 +122,21 @@ Fadable { } } + // This mouse area defocuses the current control so that the HMD keyboard gets hidden. + property var defocuser: MouseArea { + width: frame.decoration ? frame.decoration.width : window.width + height: frame.decoration ? frame.decoration.height : window.height + x: frame.decoration ? frame.decoration.anchors.leftMargin : 0 + y: frame.decoration ? frame.decoration.anchors.topMargin : 0 + propagateComposedEvents: true + acceptedButtons: Qt.AllButtons + enabled: window.visible + onPressed: { + frame.forceActiveFocus(); + mouse.accepted = false; + } + } + // This mouse area serves to swallow mouse events while the mouse is over the window // to prevent things like mouse wheel events from reaching the application and changing // the camera if the user is scrolling through a list and gets to the end. @@ -133,9 +148,7 @@ Fadable { hoverEnabled: true acceptedButtons: Qt.AllButtons enabled: window.visible - onClicked: { - frame.forceActiveFocus(); // Defocus any current field so that the keyboard gets hidden. - } + onClicked: {} onDoubleClicked: {} onPressAndHold: {} onReleased: {} From 023efe05f0a132726150ac10f4ad75569ad072e3 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sun, 25 Sep 2016 09:54:48 +1300 Subject: [PATCH 27/47] Move keyboard QML files --- interface/resources/qml/AddressBarDialog.qml | 4 ++-- interface/resources/qml/ToolWindow.qml | 5 ++--- interface/resources/qml/{controls => controls-uit}/Key.qml | 0 .../resources/qml/{controls => controls-uit}/Keyboard.qml | 0 .../qml/{controls => controls-uit}/KeyboardPunctuation.qml | 0 interface/resources/qml/controls/WebView.qml | 5 +++-- interface/resources/qml/dialogs/FileDialog.qml | 5 ++--- interface/resources/qml/dialogs/QueryDialog.qml | 5 ++--- .../resources/qml/hifi/dialogs/attachments/Attachment.qml | 5 ++--- interface/resources/qml/windows/ScrollingWindow.qml | 2 +- 10 files changed, 14 insertions(+), 17 deletions(-) rename interface/resources/qml/{controls => controls-uit}/Key.qml (100%) rename interface/resources/qml/{controls => controls-uit}/Keyboard.qml (100%) rename interface/resources/qml/{controls => controls-uit}/KeyboardPunctuation.qml (100%) diff --git a/interface/resources/qml/AddressBarDialog.qml b/interface/resources/qml/AddressBarDialog.qml index b48adf2e68..ca2f5e6852 100644 --- a/interface/resources/qml/AddressBarDialog.qml +++ b/interface/resources/qml/AddressBarDialog.qml @@ -244,7 +244,7 @@ Window { } // virtual keyboard, letters - Keyboard { + HifiControls.Keyboard { id: keyboard1 y: parent.keyboardRaised ? parent.height : 0 height: parent.keyboardRaised ? 200 : 0 @@ -258,7 +258,7 @@ Window { anchors.bottomMargin: 0 } - KeyboardPunctuation { + HifiControls.KeyboardPunctuation { id: keyboard2 y: parent.keyboardRaised ? parent.height : 0 height: parent.keyboardRaised ? 200 : 0 diff --git a/interface/resources/qml/ToolWindow.qml b/interface/resources/qml/ToolWindow.qml index b3f46a79db..705e59bbc3 100644 --- a/interface/resources/qml/ToolWindow.qml +++ b/interface/resources/qml/ToolWindow.qml @@ -18,7 +18,6 @@ import Qt.labs.settings 1.0 import "windows" import "controls-uit" import "styles-uit" -import "controls" as Controls ScrollingWindow { @@ -150,7 +149,7 @@ ScrollingWindow { } // virtual keyboard, letters - Controls.Keyboard { + Keyboard { id: keyboard1 // y: parent.keyboardRaised ? parent.height : 0 height: parent.keyboardRaised ? 200 : 0 @@ -165,7 +164,7 @@ ScrollingWindow { // anchors.bottomMargin: 2 * hifi.dimensions.contentSpacing.y } - Controls.KeyboardPunctuation { + KeyboardPunctuation { id: keyboard2 // y: parent.keyboardRaised ? parent.height : 0 height: parent.keyboardRaised ? 200 : 0 diff --git a/interface/resources/qml/controls/Key.qml b/interface/resources/qml/controls-uit/Key.qml similarity index 100% rename from interface/resources/qml/controls/Key.qml rename to interface/resources/qml/controls-uit/Key.qml diff --git a/interface/resources/qml/controls/Keyboard.qml b/interface/resources/qml/controls-uit/Keyboard.qml similarity index 100% rename from interface/resources/qml/controls/Keyboard.qml rename to interface/resources/qml/controls-uit/Keyboard.qml diff --git a/interface/resources/qml/controls/KeyboardPunctuation.qml b/interface/resources/qml/controls-uit/KeyboardPunctuation.qml similarity index 100% rename from interface/resources/qml/controls/KeyboardPunctuation.qml rename to interface/resources/qml/controls-uit/KeyboardPunctuation.qml diff --git a/interface/resources/qml/controls/WebView.qml b/interface/resources/qml/controls/WebView.qml index 22c751fb24..c3381ab824 100644 --- a/interface/resources/qml/controls/WebView.qml +++ b/interface/resources/qml/controls/WebView.qml @@ -1,6 +1,7 @@ import QtQuick 2.5 import QtWebEngine 1.1 import QtWebChannel 1.0 +import "../controls-uit" as HiFiControls Item { property alias url: root.url @@ -105,7 +106,7 @@ Item { } // virtual keyboard, letters - Keyboard { + HiFiControls.Keyboard { id: keyboard1 y: keyboardRaised ? parent.height : 0 height: keyboardRaised ? 200 : 0 @@ -119,7 +120,7 @@ Item { anchors.bottomMargin: 0 } - KeyboardPunctuation { + HiFiControls.KeyboardPunctuation { id: keyboard2 y: keyboardRaised ? parent.height : 0 height: keyboardRaised ? 200 : 0 diff --git a/interface/resources/qml/dialogs/FileDialog.qml b/interface/resources/qml/dialogs/FileDialog.qml index 86804099e0..2d245958ad 100644 --- a/interface/resources/qml/dialogs/FileDialog.qml +++ b/interface/resources/qml/dialogs/FileDialog.qml @@ -19,7 +19,6 @@ import ".." import "../controls-uit" import "../styles-uit" import "../windows" -import "../controls" as Controls import "fileDialog" @@ -648,7 +647,7 @@ ModalWindow { // virtual keyboard, letters - Controls.Keyboard { + Keyboard { id: keyboard1 // y: parent.keyboardRaised ? parent.height : 0 height: parent.keyboardRaised ? 200 : 0 @@ -662,7 +661,7 @@ ModalWindow { anchors.bottomMargin: 2 * hifi.dimensions.contentSpacing.y } - Controls.KeyboardPunctuation { + KeyboardPunctuation { id: keyboard2 // y: parent.keyboardRaised ? parent.height : 0 height: parent.keyboardRaised ? 200 : 0 diff --git a/interface/resources/qml/dialogs/QueryDialog.qml b/interface/resources/qml/dialogs/QueryDialog.qml index 865c2f1bd7..eae2c037c4 100644 --- a/interface/resources/qml/dialogs/QueryDialog.qml +++ b/interface/resources/qml/dialogs/QueryDialog.qml @@ -15,7 +15,6 @@ import QtQuick.Dialogs 1.2 as OriginalDialogs import "../controls-uit" import "../styles-uit" import "../windows" -import "../controls" as Controls ModalWindow { id: root @@ -118,7 +117,7 @@ ModalWindow { } // virtual keyboard, letters - Controls.Keyboard { + Keyboard { id: keyboard1 y: parent.keyboardRaised ? parent.height : 0 height: parent.keyboardRaised ? 200 : 0 @@ -132,7 +131,7 @@ ModalWindow { anchors.bottomMargin: 2 * hifi.dimensions.contentSpacing.y } - Controls.KeyboardPunctuation { + KeyboardPunctuation { id: keyboard2 y: parent.keyboardRaised ? parent.height : 0 height: parent.keyboardRaised ? 200 : 0 diff --git a/interface/resources/qml/hifi/dialogs/attachments/Attachment.qml b/interface/resources/qml/hifi/dialogs/attachments/Attachment.qml index 730ab367fa..9dab51437a 100644 --- a/interface/resources/qml/hifi/dialogs/attachments/Attachment.qml +++ b/interface/resources/qml/hifi/dialogs/attachments/Attachment.qml @@ -9,7 +9,6 @@ import ".." import "../../../styles-uit" import "../../../controls-uit" as HifiControls import "../../../windows" -import "../../../controls" as Controls Item { height: column.height + 2 * 8 @@ -76,7 +75,7 @@ Item { } // virtual keyboard, letters - Controls.Keyboard { + HifiControls.Keyboard { id: keyboard1 // y: parent.keyboardRaised ? parent.height : 0 height: parent.keyboardRaised ? 200 : 0 @@ -90,7 +89,7 @@ Item { // anchors.bottomMargin: 2 * hifi.dimensions.contentSpacing.y } - Controls.KeyboardPunctuation { + HifiControls.KeyboardPunctuation { id: keyboard2 // y: parent.keyboardRaised ? parent.height : 0 height: parent.keyboardRaised ? 200 : 0 diff --git a/interface/resources/qml/windows/ScrollingWindow.qml b/interface/resources/qml/windows/ScrollingWindow.qml index 2b80b01d95..b49f8fe4bb 100644 --- a/interface/resources/qml/windows/ScrollingWindow.qml +++ b/interface/resources/qml/windows/ScrollingWindow.qml @@ -15,7 +15,7 @@ import QtGraphicalEffects 1.0 import "." import "../styles-uit" -import "../controls" as HiFiControls +import "../controls-uit" as HiFiControls // FIXME how do I set the initial position of a window without // overriding places where the a individual client of the window From 7d1d71084d0e970f0ab334cfd349a32ac31eb1f9 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Mon, 26 Sep 2016 14:32:29 +1300 Subject: [PATCH 28/47] Add keyboard to custom query dialog --- .../qml/dialogs/CustomQueryDialog.qml | 48 +++++++++++++++++-- .../resources/qml/windows/ScrollingWindow.qml | 20 ++++---- 2 files changed, 56 insertions(+), 12 deletions(-) diff --git a/interface/resources/qml/dialogs/CustomQueryDialog.qml b/interface/resources/qml/dialogs/CustomQueryDialog.qml index d1fb885e0b..563dfc3099 100644 --- a/interface/resources/qml/dialogs/CustomQueryDialog.qml +++ b/interface/resources/qml/dialogs/CustomQueryDialog.qml @@ -22,6 +22,7 @@ ModalWindow { implicitWidth: 640; implicitHeight: 320; visible: true; + keyboardEnabled: false // Disable ModalWindow's keyboard. signal selected(var result); signal canceled(); @@ -50,6 +51,10 @@ ModalWindow { } } + property bool keyboardRaised: false + property bool punctuationMode: false + onKeyboardRaisedChanged: d.resize(); + property var warning: ""; property var result; @@ -110,7 +115,9 @@ ModalWindow { var targetWidth = Math.max(titleWidth, pane.width); var targetHeight = (textField.visible ? textField.controlHeight + hifi.dimensions.contentSpacing.y : 0) + (extraInputs.visible ? extraInputs.height + hifi.dimensions.contentSpacing.y : 0) + - (buttons.height + 3 * hifi.dimensions.contentSpacing.y); + (buttons.height + 3 * hifi.dimensions.contentSpacing.y) + + (root.keyboardRaised ? (200 + hifi.dimensions.contentSpacing.y) : 0); + root.width = (targetWidth < d.minWidth) ? d.minWidth : ((targetWidth > d.maxWdith) ? d.maxWidth : targetWidth); root.height = (targetHeight < d.minHeight) ? d.minHeight : ((targetHeight > d.maxHeight) ? d.maxHeight : targetHeight); @@ -130,7 +137,6 @@ ModalWindow { left: parent.left; right: parent.right; margins: 0; - bottomMargin: hifi.dimensions.contentSpacing.y; } // FIXME make a text field type that can be bound to a history for autocompletion @@ -142,7 +148,43 @@ ModalWindow { anchors { left: parent.left; right: parent.right; - bottom: parent.bottom; + bottom: keyboard.top; + bottomMargin: hifi.dimensions.contentSpacing.y; + } + } + + Item { + id: keyboard + + height: keyboardRaised ? 200 : 0 + + anchors { + left: parent.left + right: parent.right + bottom: parent.bottom + bottomMargin: keyboardRaised ? hifi.dimensions.contentSpacing.y : 0 + } + + Keyboard { + id: keyboard1 + visible: keyboardRaised && !punctuationMode + enabled: keyboardRaised && !punctuationMode + anchors { + left: parent.left + right: parent.right + bottom: parent.bottom + } + } + + KeyboardPunctuation { + id: keyboard2 + visible: keyboardRaised && punctuationMode + enabled: keyboardRaised && punctuationMode + anchors { + left: parent.left + right: parent.right + bottom: parent.bottom + } } } } diff --git a/interface/resources/qml/windows/ScrollingWindow.qml b/interface/resources/qml/windows/ScrollingWindow.qml index b49f8fe4bb..7298c94a4f 100644 --- a/interface/resources/qml/windows/ScrollingWindow.qml +++ b/interface/resources/qml/windows/ScrollingWindow.qml @@ -33,6 +33,7 @@ Window { property var footer: Item { } // Optional static footer at the bottom of the dialog. readonly property var footerContentHeight: footer.height > 0 ? (footer.height + 2 * hifi.dimensions.contentSpacing.y + 3) : 0 + property bool keyboardEnabled: true // Set false if derived control implements its own keyboard. property bool keyboardRaised: false property bool punctuationMode: false @@ -130,6 +131,7 @@ Window { // Optional non-scrolling footer. id: footerPane + property alias keyboardEnabled: window.keyboardEnabled property alias keyboardRaised: window.keyboardRaised property alias punctuationMode: window.punctuationMode @@ -138,9 +140,9 @@ Window { bottom: parent.bottom } width: parent.contentWidth - height: footerContentHeight + (keyboardRaised ? 200 : 0) + height: footerContentHeight + (keyboardEnabled && keyboardRaised ? 200 : 0) color: hifi.colors.baseGray - visible: footer.height > 0 || keyboardRaised + visible: footer.height > 0 || keyboardEnabled && keyboardRaised Item { // Horizontal rule. @@ -179,9 +181,9 @@ Window { HiFiControls.Keyboard { id: keyboard1 - height: parent.keyboardRaised ? 200 : 0 - visible: parent.keyboardRaised && !parent.punctuationMode - enabled: parent.keyboardRaised && !parent.punctuationMode + height: parent.keyboardEnabled && parent.keyboardRaised ? 200 : 0 + visible: parent.keyboardEnabled && parent.keyboardRaised && !parent.punctuationMode + enabled: parent.keyboardEnabled && parent.keyboardRaised && !parent.punctuationMode anchors { left: parent.left right: parent.right @@ -191,9 +193,9 @@ Window { HiFiControls.KeyboardPunctuation { id: keyboard2 - height: parent.keyboardRaised ? 200 : 0 - visible: parent.keyboardRaised && parent.punctuationMode - enabled: parent.keyboardRaised && parent.punctuationMode + height: parent.keyboardEnabled && parent.keyboardRaised ? 200 : 0 + visible: parent.keyboardEnabled && parent.keyboardRaised && parent.punctuationMode + enabled: parent.keyboardEnabled && parent.keyboardRaised && parent.punctuationMode anchors { left: parent.left right: parent.right @@ -204,7 +206,7 @@ Window { } onKeyboardRaisedChanged: { - if (keyboardRaised) { + if (parent.KeyboardEnabled && keyboardRaised) { var delta = activator.mouseY - (activator.height + activator.y - 200 - footerContentHeight - hifi.dimensions.controlLineHeight); From 302c8ede602b0186398f4fec57637a9cc223eea6 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Mon, 26 Sep 2016 15:34:39 +1300 Subject: [PATCH 29/47] Miscellaneous fixes --- .../resources/qml/dialogs/FileDialog.qml | 24 +++++++------------ .../resources/qml/dialogs/QueryDialog.qml | 4 ++-- 2 files changed, 11 insertions(+), 17 deletions(-) diff --git a/interface/resources/qml/dialogs/FileDialog.qml b/interface/resources/qml/dialogs/FileDialog.qml index 2d245958ad..0942e728f9 100644 --- a/interface/resources/qml/dialogs/FileDialog.qml +++ b/interface/resources/qml/dialogs/FileDialog.qml @@ -27,7 +27,7 @@ ModalWindow { id: root resizable: true implicitWidth: 480 - implicitHeight: 360 + (fileDialogItem.keyboardRaised ? 200 + (2 * hifi.dimensions.contentSpacing.y) : 0) + implicitHeight: 360 + (fileDialogItem.keyboardRaised ? 200 + hifi.dimensions.contentSpacing.y : 0) minSize: Qt.vector2d(360, 240) draggable: true @@ -109,12 +109,14 @@ ModalWindow { property bool keyboardRaised: false property bool punctuationMode: false - MouseArea { // Clear selection when click on internal unused area. anchors.fill: parent drag.target: root - onClicked: d.clearSelection() + onClicked: { + d.clearSelection(); + frame.forceActiveFocus(); // Defocus text field so that the keyboard gets hidden. + } } Row { @@ -645,34 +647,26 @@ ModalWindow { KeyNavigation.right: openButton } - - // virtual keyboard, letters Keyboard { id: keyboard1 - // y: parent.keyboardRaised ? parent.height : 0 height: parent.keyboardRaised ? 200 : 0 visible: parent.keyboardRaised && !parent.punctuationMode - enabled: parent.keyboardRaised && !parent.punctuationMode + enabled: visible anchors.right: parent.right - anchors.rightMargin: 0 anchors.left: parent.left - anchors.leftMargin: 0 anchors.bottom: buttonRow.top - anchors.bottomMargin: 2 * hifi.dimensions.contentSpacing.y + anchors.bottomMargin: visible ? hifi.dimensions.contentSpacing.y : 0 } KeyboardPunctuation { id: keyboard2 - // y: parent.keyboardRaised ? parent.height : 0 height: parent.keyboardRaised ? 200 : 0 visible: parent.keyboardRaised && parent.punctuationMode - enabled: parent.keyboardRaised && parent.punctuationMode + enabled: visible anchors.right: parent.right - anchors.rightMargin: 0 anchors.left: parent.left - anchors.leftMargin: 0 anchors.bottom: buttonRow.top - anchors.bottomMargin: 2 * hifi.dimensions.contentSpacing.y + anchors.bottomMargin: visible ? hifi.dimensions.contentSpacing.y : 0 } Row { diff --git a/interface/resources/qml/dialogs/QueryDialog.qml b/interface/resources/qml/dialogs/QueryDialog.qml index eae2c037c4..cf1b1e370a 100644 --- a/interface/resources/qml/dialogs/QueryDialog.qml +++ b/interface/resources/qml/dialogs/QueryDialog.qml @@ -128,7 +128,7 @@ ModalWindow { anchors.left: parent.left anchors.leftMargin: 0 anchors.bottom: buttons.top - anchors.bottomMargin: 2 * hifi.dimensions.contentSpacing.y + anchors.bottomMargin: parent.keyboardRaised ? 2 * hifi.dimensions.contentSpacing.y : 0 } KeyboardPunctuation { @@ -142,7 +142,7 @@ ModalWindow { anchors.left: parent.left anchors.leftMargin: 0 anchors.bottom: buttons.top - anchors.bottomMargin: 2 * hifi.dimensions.contentSpacing.y + anchors.bottomMargin: parent.keyboardRaised ? 2 * hifi.dimensions.contentSpacing.y : 0 } Flow { From bc8c400448bd909d0266640d37e332bd6a965a7e Mon Sep 17 00:00:00 2001 From: David Rowe Date: Mon, 26 Sep 2016 16:39:34 +1300 Subject: [PATCH 30/47] Fix up keyboards in attachments dialogs --- .../qml/hifi/dialogs/AttachmentsDialog.qml | 23 ++++++++++++- .../qml/hifi/dialogs/ModelBrowserDialog.qml | 2 +- .../hifi/dialogs/attachments/Attachment.qml | 32 ------------------- 3 files changed, 23 insertions(+), 34 deletions(-) diff --git a/interface/resources/qml/hifi/dialogs/AttachmentsDialog.qml b/interface/resources/qml/hifi/dialogs/AttachmentsDialog.qml index 15467f8021..cc9a570d47 100644 --- a/interface/resources/qml/hifi/dialogs/AttachmentsDialog.qml +++ b/interface/resources/qml/hifi/dialogs/AttachmentsDialog.qml @@ -45,7 +45,7 @@ ScrollingWindow { Rectangle { width: parent.width - height: root.height + height: root.height - (keyboardRaised ? 200 : 0) radius: 4 color: hifi.colors.baseGray @@ -128,6 +128,10 @@ ScrollingWindow { } onCountChanged: MyAvatar.setAttachmentsVariant(attachments); } + + function scrollBy(delta) { + flickableItem.contentY += delta; + } } } @@ -204,5 +208,22 @@ ScrollingWindow { } } } + + onKeyboardRaisedChanged: { + if (keyboardRaised) { + // Scroll to item with focus if necessary. + var footerHeight = newAttachmentButton.height + buttonRow.height + 3 * hifi.dimensions.contentSpacing.y; + var delta = activator.mouseY + - (activator.height + activator.y - 200 - footerHeight - hifi.dimensions.controlLineHeight); + + if (delta > 0) { + scrollView.scrollBy(delta); + } else { + // HACK: Work around for case where are 100% scrolled; stops window from erroneously scrolling to 100% when show keyboard. + scrollView.scrollBy(-1); + scrollView.scrollBy(1); + } + } + } } diff --git a/interface/resources/qml/hifi/dialogs/ModelBrowserDialog.qml b/interface/resources/qml/hifi/dialogs/ModelBrowserDialog.qml index aeffb8e4bf..a5a254f605 100644 --- a/interface/resources/qml/hifi/dialogs/ModelBrowserDialog.qml +++ b/interface/resources/qml/hifi/dialogs/ModelBrowserDialog.qml @@ -30,7 +30,7 @@ ScrollingWindow { Rectangle { width: parent.width - height: root.height + height: root.height - (keyboardRaised ? 200 : 0) radius: 4 color: hifi.colors.baseGray diff --git a/interface/resources/qml/hifi/dialogs/attachments/Attachment.qml b/interface/resources/qml/hifi/dialogs/attachments/Attachment.qml index 9dab51437a..6d371741ea 100644 --- a/interface/resources/qml/hifi/dialogs/attachments/Attachment.qml +++ b/interface/resources/qml/hifi/dialogs/attachments/Attachment.qml @@ -34,9 +34,6 @@ Item { anchors { left: parent.left; right: parent.right; margins: 20 } spacing: 8 - property bool keyboardRaised: false - property bool punctuationMode: false - Item { height: modelChooserButton.height + urlLabel.height + 4 anchors { left: parent.left; right: parent.right;} @@ -74,35 +71,6 @@ Item { } } - // virtual keyboard, letters - HifiControls.Keyboard { - id: keyboard1 - // y: parent.keyboardRaised ? parent.height : 0 - height: parent.keyboardRaised ? 200 : 0 - visible: parent.keyboardRaised && !parent.punctuationMode - enabled: parent.keyboardRaised && !parent.punctuationMode - anchors.right: parent.right - anchors.rightMargin: 0 - anchors.left: parent.left - anchors.leftMargin: 0 - // anchors.bottom: buttonRow.top - // anchors.bottomMargin: 2 * hifi.dimensions.contentSpacing.y - } - - HifiControls.KeyboardPunctuation { - id: keyboard2 - // y: parent.keyboardRaised ? parent.height : 0 - height: parent.keyboardRaised ? 200 : 0 - visible: parent.keyboardRaised && parent.punctuationMode - enabled: parent.keyboardRaised && parent.punctuationMode - anchors.right: parent.right - anchors.rightMargin: 0 - anchors.left: parent.left - anchors.leftMargin: 0 - // anchors.bottom: buttonRow.top - // anchors.bottomMargin: 2 * hifi.dimensions.contentSpacing.y - } - Item { height: jointChooser.height + jointLabel.height + 4 anchors { left: parent.left; right: parent.right; } From ec001299884ccdbdec54d561d38b0f9b7f49cbfd Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 28 Sep 2016 12:51:00 +1300 Subject: [PATCH 31/47] Don't flood event bridge with raise/lower keyboard messages from HTML --- .../resources/html/raiseAndLowerKeyboard.js | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/interface/resources/html/raiseAndLowerKeyboard.js b/interface/resources/html/raiseAndLowerKeyboard.js index 723767790a..84a166ace3 100644 --- a/interface/resources/html/raiseAndLowerKeyboard.js +++ b/interface/resources/html/raiseAndLowerKeyboard.js @@ -11,6 +11,7 @@ var POLL_FREQUENCY = 500; // ms var MAX_WARNINGS = 3; var numWarnings = 0; + var isKeyboardRaised = false; function shouldRaiseKeyboard() { if (document.activeElement.nodeName == "INPUT" || document.activeElement.nodeName == "TEXTAREA") { @@ -28,13 +29,15 @@ }; setInterval(function () { - var event = shouldRaiseKeyboard() ? "_RAISE_KEYBOARD" : "_LOWER_KEYBOARD"; - if (typeof EventBridge != "undefined") { - EventBridge.emitWebEvent(event); - } else { - if (numWarnings < MAX_WARNINGS) { - console.log("WARNING: no global EventBridge object found"); - numWarnings++; + if (isKeyboardRaised !== shouldRaiseKeyboard()) { + isKeyboardRaised = !isKeyboardRaised; + if (typeof EventBridge != "undefined") { + EventBridge.emitWebEvent(isKeyboardRaised ? "_RAISE_KEYBOARD" : "_LOWER_KEYBOARD"); + } else { + if (numWarnings < MAX_WARNINGS) { + console.log("WARNING: no global EventBridge object found"); + numWarnings++; + } } } }, POLL_FREQUENCY); From 875566d9568e72bcaffd8bf393073b85062f2810 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 28 Sep 2016 16:40:38 +1300 Subject: [PATCH 32/47] Raise and lower keyboard for HTML fields in Browser window --- interface/resources/qml/Browser.qml | 46 +++++++++++++++---- .../qml/controls-uit/BaseWebView.qml | 2 +- libraries/gl/src/gl/OffscreenQmlSurface.cpp | 32 ++++++++----- 3 files changed, 60 insertions(+), 20 deletions(-) diff --git a/interface/resources/qml/Browser.qml b/interface/resources/qml/Browser.qml index 631036580e..8374fa5a98 100644 --- a/interface/resources/qml/Browser.qml +++ b/interface/resources/qml/Browser.qml @@ -1,5 +1,6 @@ import QtQuick 2.5 import QtQuick.Controls 1.2 +import QtWebChannel 1.0 import QtWebEngine 1.2 import "controls-uit" @@ -19,6 +20,9 @@ ScrollingWindow { property variant permissionsBar: {'securityOrigin':'none','feature':'none'} property alias url: webview.url property alias webView: webview + + property alias eventBridge: eventBridgeWrapper.eventBridge + x: 100 y: 100 @@ -197,32 +201,60 @@ ScrollingWindow { } } - WebEngineView { + WebView { id: webview url: "https://highfidelity.com" + + property alias eventBridgeWrapper: eventBridgeWrapper + + QtObject { + id: eventBridgeWrapper + WebChannel.id: "eventBridgeWrapper" + property var eventBridge; + } + + webChannel.registeredObjects: [eventBridgeWrapper] + + // Create a global EventBridge object for raiseAndLowerKeyboard. + WebEngineScript { + id: createGlobalEventBridge + sourceCode: eventBridgeJavaScriptToInject + injectionPoint: WebEngineScript.DocumentCreation + worldId: WebEngineScript.MainWorld + } + + // Detect when may want to raise and lower keyboard. + WebEngineScript { + id: raiseAndLowerKeyboard + injectionPoint: WebEngineScript.Deferred + sourceUrl: resourceDirectoryUrl + "/html/raiseAndLowerKeyboard.js" + worldId: WebEngineScript.MainWorld + } + + userScripts: [ createGlobalEventBridge, raiseAndLowerKeyboard ] + anchors.top: buttons.bottom anchors.topMargin: 8 anchors.bottom: parent.bottom anchors.left: parent.left anchors.right: parent.right + onFeaturePermissionRequested: { permissionsBar.securityOrigin = securityOrigin; permissionsBar.feature = feature; root.showPermissionsBar(); } + onLoadingChanged: { if (loadRequest.status === WebEngineView.LoadSucceededStatus) { addressBar.text = loadRequest.url } } + onIconChanged: { console.log("New icon: " + icon) } - onNewViewRequested: { - var component = Qt.createComponent("Browser.qml"); - var newWindow = component.createObject(desktop); - request.openIn(newWindow.webView) - } + onWindowCloseRequested: { root.destroy(); } @@ -230,8 +262,6 @@ ScrollingWindow { Component.onCompleted: { desktop.initWebviewProfileHandlers(webview.profile) } - - profile: desktop.browserProfile } } // item diff --git a/interface/resources/qml/controls-uit/BaseWebView.qml b/interface/resources/qml/controls-uit/BaseWebView.qml index cefaf653fc..ef4764b08f 100644 --- a/interface/resources/qml/controls-uit/BaseWebView.qml +++ b/interface/resources/qml/controls-uit/BaseWebView.qml @@ -9,7 +9,7 @@ // import QtQuick 2.5 -import QtWebEngine 1.1 +import QtWebEngine 1.2 WebEngineView { id: root diff --git a/libraries/gl/src/gl/OffscreenQmlSurface.cpp b/libraries/gl/src/gl/OffscreenQmlSurface.cpp index e8b300f171..d53c1289e4 100644 --- a/libraries/gl/src/gl/OffscreenQmlSurface.cpp +++ b/libraries/gl/src/gl/OffscreenQmlSurface.cpp @@ -565,6 +565,19 @@ QObject* OffscreenQmlSurface::finishQmlLoad(std::functionbeginCreate(newContext); if (_qmlComponent->isError()) { @@ -577,6 +590,9 @@ QObject* OffscreenQmlSurface::finishQmlLoad(std::functionsetProperty("eventBridge", QVariant::fromValue(this)); + newContext->setContextProperty("eventBridgeJavaScriptToInject", QVariant(javaScriptToInject)); + f(newContext, newObject); _qmlComponent->completeCreate(); @@ -835,6 +851,9 @@ void OffscreenQmlSurface::onFocusObjectChanged(QObject* object) { disconnect(_currentFocusItem, &QObject::destroyed, this, 0); setKeyboardRaised(_currentFocusItem, false); } + + // Handle QML text fields' focus and unfocus - testing READ_ONLY_PROPERTY prevents action for HTML files. + // HTML text fields are handled via emitWebEvent(). const char* READ_ONLY_PROPERTY = "readOnly"; setKeyboardRaised(item, item->hasActiveFocus() && item->property(READ_ONLY_PROPERTY) == false); _currentFocusItem = item; @@ -897,12 +916,6 @@ void OffscreenQmlSurface::synthesizeKeyPress(QString key) { } void OffscreenQmlSurface::setKeyboardRaised(QObject* object, bool raised) { - - // raise the keyboard only while in HMD mode and it's being requested. - // XXX - // bool value = AbstractViewStateInterface::instance()->isHMDMode() && raised; - // getRootItem()->setProperty("keyboardRaised", QVariant(value)); - if (!object) { return; } @@ -931,16 +944,13 @@ void OffscreenQmlSurface::emitWebEvent(const QVariant& message) { } else { // special case to handle raising and lowering the virtual keyboard if (message.type() == QVariant::String && message.toString() == "_RAISE_KEYBOARD") { - setKeyboardRaised(getRootItem(), true); + setKeyboardRaised(_currentFocusItem, true); } else if (message.type() == QVariant::String && message.toString() == "_LOWER_KEYBOARD") { - setKeyboardRaised(getRootItem(), false); + setKeyboardRaised(_currentFocusItem, false); } else { emit webEventReceived(message); } } } - - - #include "OffscreenQmlSurface.moc" From 2344d15dbcedf8e5ae09bd6e85c56cb709868b7f Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 28 Sep 2016 16:41:01 +1300 Subject: [PATCH 33/47] Raise and lower keyboard for HTML fields in Marketplace window --- interface/resources/qml/QmlWebWindow.qml | 18 ++++++++++++++++++ libraries/ui/src/QmlWebWindowClass.cpp | 24 +++++++++++++++++++++++- libraries/ui/src/QmlWebWindowClass.h | 3 +++ 3 files changed, 44 insertions(+), 1 deletion(-) diff --git a/interface/resources/qml/QmlWebWindow.qml b/interface/resources/qml/QmlWebWindow.qml index 153498e2f7..7ea45bff6b 100644 --- a/interface/resources/qml/QmlWebWindow.qml +++ b/interface/resources/qml/QmlWebWindow.qml @@ -66,6 +66,24 @@ Windows.ScrollingWindow { anchors.fill: parent focus: true webChannel.registeredObjects: [eventBridgeWrapper] + + // Create a global EventBridge object for raiseAndLowerKeyboard. + WebEngineScript { + id: createGlobalEventBridge + sourceCode: eventBridgeJavaScriptToInject + injectionPoint: WebEngineScript.DocumentCreation + worldId: WebEngineScript.MainWorld + } + + // Detect when may want to raise and lower keyboard. + WebEngineScript { + id: raiseAndLowerKeyboard + injectionPoint: WebEngineScript.Deferred + sourceUrl: resourceDirectoryUrl + "/html/raiseAndLowerKeyboard.js" + worldId: WebEngineScript.MainWorld + } + + userScripts: [ createGlobalEventBridge, raiseAndLowerKeyboard ] } } } diff --git a/libraries/ui/src/QmlWebWindowClass.cpp b/libraries/ui/src/QmlWebWindowClass.cpp index b964f305a4..5a357a83d4 100644 --- a/libraries/ui/src/QmlWebWindowClass.cpp +++ b/libraries/ui/src/QmlWebWindowClass.cpp @@ -43,7 +43,29 @@ void QmlWebWindowClass::emitWebEvent(const QVariant& webMessage) { if (QThread::currentThread() != thread()) { QMetaObject::invokeMethod(this, "emitWebEvent", Qt::QueuedConnection, Q_ARG(QVariant, webMessage)); } else { - emit webEventReceived(webMessage); + // 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") { + setKeyboardRaised(asQuickItem(), false); + } else { + emit webEventReceived(webMessage); + } + } +} + +void QmlWebWindowClass::setKeyboardRaised(QObject* object, bool raised) { + if (!object) { + return; + } + + QQuickItem* item = dynamic_cast(object); + while (item) { + if (item->property("keyboardRaised").isValid()) { + item->setProperty("keyboardRaised", QVariant(raised)); + return; + } + item = dynamic_cast(item->parentItem()); } } diff --git a/libraries/ui/src/QmlWebWindowClass.h b/libraries/ui/src/QmlWebWindowClass.h index 86d0e9b2c4..95851d2857 100644 --- a/libraries/ui/src/QmlWebWindowClass.h +++ b/libraries/ui/src/QmlWebWindowClass.h @@ -33,6 +33,9 @@ signals: protected: QString qmlSource() const override { return "QmlWebWindow.qml"; } + +private: + void setKeyboardRaised(QObject* object, bool raised); }; #endif From a94d77ee12b8e786d03f8c7e2ea20ca77138886f Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 28 Sep 2016 17:57:53 +1300 Subject: [PATCH 34/47] Raise and lower keyboard in entities editor --- scripts/system/html/entityList.html | 1 + scripts/system/html/entityProperties.html | 1 + scripts/system/html/gridControls.html | 1 + scripts/system/html/js/entityList.js | 2 ++ scripts/system/html/js/entityProperties.js | 2 ++ scripts/system/html/js/gridControls.js | 2 ++ scripts/system/html/js/keyboardControl.js | 41 ++++++++++++++++++++++ 7 files changed, 50 insertions(+) create mode 100644 scripts/system/html/js/keyboardControl.js diff --git a/scripts/system/html/entityList.html b/scripts/system/html/entityList.html index 58dca4567f..6ea281e467 100644 --- a/scripts/system/html/entityList.html +++ b/scripts/system/html/entityList.html @@ -14,6 +14,7 @@ + diff --git a/scripts/system/html/entityProperties.html b/scripts/system/html/entityProperties.html index 6de1eec7d0..5cc8b67b44 100644 --- a/scripts/system/html/entityProperties.html +++ b/scripts/system/html/entityProperties.html @@ -19,6 +19,7 @@ + diff --git a/scripts/system/html/gridControls.html b/scripts/system/html/gridControls.html index cd646fed51..c0bd87988d 100644 --- a/scripts/system/html/gridControls.html +++ b/scripts/system/html/gridControls.html @@ -16,6 +16,7 @@ + diff --git a/scripts/system/html/js/entityList.js b/scripts/system/html/js/entityList.js index e9075da3eb..185baefcab 100644 --- a/scripts/system/html/js/entityList.js +++ b/scripts/system/html/js/entityList.js @@ -412,6 +412,8 @@ function loaded() { augmentSpinButtons(); + setUpKeyboardControl(); + // Disable right-click context menu which is not visible in the HMD and makes it seem like the app has locked document.addEventListener("contextmenu", function (event) { event.preventDefault(); diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index 8ce3fbbe00..67aa8bdb13 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -1590,6 +1590,8 @@ function loaded() { augmentSpinButtons(); + setUpKeyboardControl(); + // Disable right-click context menu which is not visible in the HMD and makes it seem like the app has locked document.addEventListener("contextmenu", function(event) { event.preventDefault(); diff --git a/scripts/system/html/js/gridControls.js b/scripts/system/html/js/gridControls.js index cc268bcbff..a245ed4cda 100644 --- a/scripts/system/html/js/gridControls.js +++ b/scripts/system/html/js/gridControls.js @@ -127,6 +127,8 @@ function loaded() { augmentSpinButtons(); + setUpKeyboardControl(); + EventBridge.emitWebEvent(JSON.stringify({ type: 'init' })); }); diff --git a/scripts/system/html/js/keyboardControl.js b/scripts/system/html/js/keyboardControl.js new file mode 100644 index 0000000000..e33b0c8159 --- /dev/null +++ b/scripts/system/html/js/keyboardControl.js @@ -0,0 +1,41 @@ +// +// keyboardControl.js +// +// Created by David Rowe on 28 Sep 2016. +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +function setUpKeyboardControl() { + + var lowerTimer = null; + + function raiseKeyboard() { + if (lowerTimer !== null) { + clearTimeout(lowerTimer); + lowerTimer = null; + } + EventBridge.emitWebEvent("_RAISE_KEYBOARD"); + } + + function doLowerKeyboard() { + EventBridge.emitWebEvent("_LOWER_KEYBOARD"); + lowerTimer = null; + } + + function lowerKeyboard() { + // Delay lowering keyboard a little in case immediately raise it again. + if (lowerTimer === null) { + lowerTimer = setTimeout(doLowerKeyboard, 20); + } + } + + var inputs = document.querySelectorAll("input[type=text], input[type=number], textarea"); + for (var i = 0, length = inputs.length; i < length; i++) { + inputs[i].addEventListener("focus", raiseKeyboard); + inputs[i].addEventListener("blur", lowerKeyboard); + } +} + From b60f649e0a7ebc4a330e3da71411396f1ae41eaf Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 28 Sep 2016 19:27:16 +1300 Subject: [PATCH 35/47] Scroll HTML window if necessary when raise keyboard --- interface/resources/html/raiseAndLowerKeyboard.js | 10 ++++++++++ scripts/system/html/js/keyboardControl.js | 15 +++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/interface/resources/html/raiseAndLowerKeyboard.js b/interface/resources/html/raiseAndLowerKeyboard.js index 84a166ace3..a4138d1627 100644 --- a/interface/resources/html/raiseAndLowerKeyboard.js +++ b/interface/resources/html/raiseAndLowerKeyboard.js @@ -12,6 +12,7 @@ var MAX_WARNINGS = 3; var numWarnings = 0; var isKeyboardRaised = false; + var KEYBOARD_HEIGHT = 200; function shouldRaiseKeyboard() { if (document.activeElement.nodeName == "INPUT" || document.activeElement.nodeName == "TEXTAREA") { @@ -31,6 +32,15 @@ setInterval(function () { if (isKeyboardRaised !== shouldRaiseKeyboard()) { isKeyboardRaised = !isKeyboardRaised; + + if (isKeyboardRaised) { + var delta = document.activeElement.getBoundingClientRect().bottom + 10 + - (document.body.clientHeight - KEYBOARD_HEIGHT); + if (delta > 0) { + document.body.scrollTop += delta; + } + } + if (typeof EventBridge != "undefined") { EventBridge.emitWebEvent(isKeyboardRaised ? "_RAISE_KEYBOARD" : "_LOWER_KEYBOARD"); } else { diff --git a/scripts/system/html/js/keyboardControl.js b/scripts/system/html/js/keyboardControl.js index e33b0c8159..4041687c25 100644 --- a/scripts/system/html/js/keyboardControl.js +++ b/scripts/system/html/js/keyboardControl.js @@ -11,18 +11,33 @@ function setUpKeyboardControl() { var lowerTimer = null; + var isRaised = false; + var KEYBOARD_HEIGHT = 200; function raiseKeyboard() { if (lowerTimer !== null) { clearTimeout(lowerTimer); lowerTimer = null; } + + if (isRaised) { + return; + } + + var delta = this.getBoundingClientRect().bottom + 10 - (document.body.clientHeight - KEYBOARD_HEIGHT); + if (delta > 0) { + document.body.scrollTop += delta; + } + EventBridge.emitWebEvent("_RAISE_KEYBOARD"); + + isRaised = true; } function doLowerKeyboard() { EventBridge.emitWebEvent("_LOWER_KEYBOARD"); lowerTimer = null; + isRaised = false; } function lowerKeyboard() { From 52f2d360963891f89071bcedeb8a2b7ed4c6d6b8 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 29 Sep 2016 10:17:31 +1300 Subject: [PATCH 36/47] Move "," and "." to numeric keyboard for ready use with numeric fields --- .../resources/qml/controls-uit/Keyboard.qml | 4 ++-- .../qml/controls-uit/KeyboardPunctuation.qml | 16 ++++++++-------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/interface/resources/qml/controls-uit/Keyboard.qml b/interface/resources/qml/controls-uit/Keyboard.qml index eb34740402..1d957ce9cb 100644 --- a/interface/resources/qml/controls-uit/Keyboard.qml +++ b/interface/resources/qml/controls-uit/Keyboard.qml @@ -304,13 +304,13 @@ Item { Key { id: key31 width: 43 - glyph: "," + glyph: "_" } Key { id: key33 width: 43 - glyph: "." + glyph: "?" } Key { diff --git a/interface/resources/qml/controls-uit/KeyboardPunctuation.qml b/interface/resources/qml/controls-uit/KeyboardPunctuation.qml index 6fef366772..485468b46a 100644 --- a/interface/resources/qml/controls-uit/KeyboardPunctuation.qml +++ b/interface/resources/qml/controls-uit/KeyboardPunctuation.qml @@ -208,49 +208,49 @@ Item { Key { id: key22 width: 43 - glyph: "_" + glyph: "," } Key { id: key23 width: 43 - glyph: ";" + glyph: "." } Key { id: key24 width: 43 - glyph: ":" + glyph: ";" } Key { id: key25 width: 43 - glyph: "'" + glyph: ":" } Key { id: key26 width: 43 - glyph: "\"" + glyph: "'" } Key { id: key31 width: 43 - glyph: "<" + glyph: "\"" } Key { id: key33 width: 43 - glyph: ">" + glyph: "<" } Key { id: key36 width: 43 - glyph: "?" + glyph: ">" } } From 40bfbf40210de2551e1728c595d211226f136bea Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 29 Sep 2016 10:35:18 +1300 Subject: [PATCH 37/47] Prevent flicker of keyboard area when navigate to a new page in browser --- interface/resources/qml/Browser.qml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/interface/resources/qml/Browser.qml b/interface/resources/qml/Browser.qml index 8374fa5a98..b258dadae4 100644 --- a/interface/resources/qml/Browser.qml +++ b/interface/resources/qml/Browser.qml @@ -134,10 +134,11 @@ ScrollingWindow { case Qt.Key_Return: event.accepted = true if (text.indexOf("http") != 0) { - text = "http://" + text + text = "http://" + text; } root.hidePermissionsBar(); - webview.url = text + root.keyboardRaised = false; + webview.url = text; break; } } From 2933e37a0a59c370502922b273f028e47c66b065 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 29 Sep 2016 10:47:15 +1300 Subject: [PATCH 38/47] Fix field not scrolling into view when raise keyboard in settings --- interface/resources/qml/windows/ScrollingWindow.qml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/interface/resources/qml/windows/ScrollingWindow.qml b/interface/resources/qml/windows/ScrollingWindow.qml index 7298c94a4f..ce4bd45cff 100644 --- a/interface/resources/qml/windows/ScrollingWindow.qml +++ b/interface/resources/qml/windows/ScrollingWindow.qml @@ -1,3 +1,4 @@ + // // Window.qml // @@ -206,7 +207,7 @@ Window { } onKeyboardRaisedChanged: { - if (parent.KeyboardEnabled && keyboardRaised) { + if (keyboardEnabled && keyboardRaised) { var delta = activator.mouseY - (activator.height + activator.y - 200 - footerContentHeight - hifi.dimensions.controlLineHeight); From e9a398472a81e9a7f29c1014948d6b930f345a02 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 29 Sep 2016 12:09:04 +1300 Subject: [PATCH 39/47] Remove duplicate keyboard Fixes keyboard raising and lowering when select entity with editor open. --- interface/resources/qml/ToolWindow.qml | 37 +------------------------- 1 file changed, 1 insertion(+), 36 deletions(-) diff --git a/interface/resources/qml/ToolWindow.qml b/interface/resources/qml/ToolWindow.qml index 705e59bbc3..a3a04be13e 100644 --- a/interface/resources/qml/ToolWindow.qml +++ b/interface/resources/qml/ToolWindow.qml @@ -55,14 +55,11 @@ ScrollingWindow { anchors.left: parent.left anchors.top: parent.top - property bool keyboardRaised: false - property bool punctuationMode: false - TabView { id: tabView; width: pane.contentWidth // Pane height so that don't use Window's scrollbars otherwise tabs may be scrolled out of view. - height: pane.scrollHeight - (toolWindowTabViewItem.keyboardRaised ? 200 : 0) + height: pane.scrollHeight property int tabCount: 0 Repeater { @@ -147,37 +144,6 @@ ScrollingWindow { tabOverlap: 0 } } - - // virtual keyboard, letters - Keyboard { - id: keyboard1 - // y: parent.keyboardRaised ? parent.height : 0 - height: parent.keyboardRaised ? 200 : 0 - visible: parent.keyboardRaised && !parent.punctuationMode - enabled: parent.keyboardRaised && !parent.punctuationMode - anchors.right: parent.right - anchors.rightMargin: 0 - anchors.left: parent.left - anchors.leftMargin: 0 - anchors.bottom: parent.bottom - anchors.bottomMargin: 0 - // anchors.bottomMargin: 2 * hifi.dimensions.contentSpacing.y - } - - KeyboardPunctuation { - id: keyboard2 - // y: parent.keyboardRaised ? parent.height : 0 - height: parent.keyboardRaised ? 200 : 0 - visible: parent.keyboardRaised && parent.punctuationMode - enabled: parent.keyboardRaised && parent.punctuationMode - anchors.right: parent.right - anchors.rightMargin: 0 - anchors.left: parent.left - anchors.leftMargin: 0 - anchors.bottom: parent.bottom - anchors.bottomMargin: 0 - // anchors.bottomMargin: 2 * hifi.dimensions.contentSpacing.y - } } function updateVisiblity() { @@ -268,7 +234,6 @@ ScrollingWindow { return; } - if (properties.width) { tabView.width = Math.min(Math.max(tabView.width, properties.width), toolWindow.maxSize.x); } From 8e44096981f7dbfb008ed46ee0735ffee7a75cf9 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 29 Sep 2016 15:59:24 +1300 Subject: [PATCH 40/47] Fix last entities properties not scrolling when keyboard raised --- scripts/system/html/js/keyboardControl.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/scripts/system/html/js/keyboardControl.js b/scripts/system/html/js/keyboardControl.js index 4041687c25..b19b8953c0 100644 --- a/scripts/system/html/js/keyboardControl.js +++ b/scripts/system/html/js/keyboardControl.js @@ -25,12 +25,15 @@ function setUpKeyboardControl() { } var delta = this.getBoundingClientRect().bottom + 10 - (document.body.clientHeight - KEYBOARD_HEIGHT); - if (delta > 0) { - document.body.scrollTop += delta; - } EventBridge.emitWebEvent("_RAISE_KEYBOARD"); + if (delta > 0) { + setTimeout(function () { + document.body.scrollTop += delta; + }, 500); // Allow time for keyboard to be raised in QML. + } + isRaised = true; } From e3be34528fb7af7a809f38dd1b73244bf0080326 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 29 Sep 2016 16:53:20 +1300 Subject: [PATCH 41/47] Fix keyboard flickering when select entities Fix entities list footer count of selected entities in the process. --- scripts/system/html/js/entityList.js | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/scripts/system/html/js/entityList.js b/scripts/system/html/js/entityList.js index 185baefcab..60aa2ebe25 100644 --- a/scripts/system/html/js/entityList.js +++ b/scripts/system/html/js/entityList.js @@ -122,6 +122,8 @@ function loaded() { focus: false, entityIds: selection, })); + + refreshFooter(); } function onRowDoubleClicked() { @@ -184,6 +186,7 @@ function loaded() { function clearEntities() { entities = {}; entityList.clear(); + refreshFooter(); } var elSortOrder = { @@ -236,13 +239,16 @@ function loaded() { refreshFooter(); } - function updateSelectedEntities(selectedEntities) { + function updateSelectedEntities(selectedIDs) { var notFound = false; for (var id in entities) { entities[id].el.className = ''; } - for (var i = 0; i < selectedEntities.length; i++) { - var id = selectedEntities[i]; + + selectedEntities = []; + for (var i = 0; i < selectedIDs.length; i++) { + var id = selectedIDs[i]; + selectedEntities.push(id); if (id in entities) { var entity = entities[id]; entity.el.className = 'selected'; @@ -251,10 +257,7 @@ function loaded() { } } - // HACK: Fixes the footer and header text sometimes not displaying after adding or deleting entities. - // The problem appears to be a bug in the Qt HTML/CSS rendering (Qt 5.5). - document.getElementById("radius").focus(); - document.getElementById("radius").blur(); + refreshFooter(); return notFound; } From 5e842843c61c3103264939bfd4a7784ef5a6e9e7 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Fri, 30 Sep 2016 11:54:32 +1300 Subject: [PATCH 42/47] 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; From a0dd3d877175eaa32780c8cbb37c8bf8e147fede Mon Sep 17 00:00:00 2001 From: David Rowe Date: Fri, 30 Sep 2016 13:43:55 +1300 Subject: [PATCH 43/47] Debounce lowering keyboard and immediately raising it again --- libraries/gl/src/gl/OffscreenQmlSurface.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/libraries/gl/src/gl/OffscreenQmlSurface.cpp b/libraries/gl/src/gl/OffscreenQmlSurface.cpp index 2112288db1..74cdb78b46 100644 --- a/libraries/gl/src/gl/OffscreenQmlSurface.cpp +++ b/libraries/gl/src/gl/OffscreenQmlSurface.cpp @@ -853,13 +853,17 @@ void OffscreenQmlSurface::onFocusObjectChanged(QObject* object) { if (_currentFocusItem) { disconnect(_currentFocusItem, &QObject::destroyed, this, 0); - setKeyboardRaised(_currentFocusItem, false); } - // Handle QML text fields' focus and unfocus - testing READ_ONLY_PROPERTY prevents action for HTML files. - // HTML text fields are handled in emitWebEvent() methods. + // Raise and lower keyboard for QML text fields. + // HTML text fields are handled in emitWebEvent() methods - testing READ_ONLY_PROPERTY prevents action for HTML files. const char* READ_ONLY_PROPERTY = "readOnly"; - setKeyboardRaised(item, item->hasActiveFocus() && item->property(READ_ONLY_PROPERTY) == false); + bool raiseKeyboard = item->hasActiveFocus() && item->property(READ_ONLY_PROPERTY) == false; + if (_currentFocusItem && !raiseKeyboard) { + setKeyboardRaised(_currentFocusItem, false); + } + setKeyboardRaised(item, raiseKeyboard); // Always set focus so that alphabetic / numeric setting is updated. + _currentFocusItem = item; connect(_currentFocusItem, &QObject::destroyed, this, &OffscreenQmlSurface::focusDestroyed); } From ad5d525340756a624e6f67ffa6f9ccb59fc78a83 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Fri, 30 Sep 2016 14:13:35 +1300 Subject: [PATCH 44/47] Fix keyboard status when switching between entities editor tabs --- scripts/system/html/js/keyboardControl.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/scripts/system/html/js/keyboardControl.js b/scripts/system/html/js/keyboardControl.js index 291330e8de..964f5f5786 100644 --- a/scripts/system/html/js/keyboardControl.js +++ b/scripts/system/html/js/keyboardControl.js @@ -47,10 +47,21 @@ function setUpKeyboardControl() { } } + function documentBlur() { + // Action any pending Lower keyboard event immediately upon leaving document window so that they don't interfere with + // other Entities Editor tab. + if (lowerTimer !== null) { + clearTimeout(lowerTimer); + doLowerKeyboard(); + } + } + var inputs = document.querySelectorAll("input[type=text], input[type=number], textarea"); for (var i = 0, length = inputs.length; i < length; i++) { inputs[i].addEventListener("focus", raiseKeyboard); inputs[i].addEventListener("blur", lowerKeyboard); } + + window.addEventListener("blur", documentBlur); } From 3242a7884ca8584b797d9caf1818b80bd90f14f7 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 4 Oct 2016 11:02:14 +1300 Subject: [PATCH 45/47] Apply fix from merge conflict to moved code --- libraries/gl/src/gl/OffscreenQmlSurface.cpp | 49 +++++++++++---------- 1 file changed, 26 insertions(+), 23 deletions(-) diff --git a/libraries/gl/src/gl/OffscreenQmlSurface.cpp b/libraries/gl/src/gl/OffscreenQmlSurface.cpp index 164abbd671..1aa4419599 100644 --- a/libraries/gl/src/gl/OffscreenQmlSurface.cpp +++ b/libraries/gl/src/gl/OffscreenQmlSurface.cpp @@ -988,31 +988,34 @@ static bool equals(const QByteArray& byteArray, const uint8_t* ptr) { } void OffscreenQmlSurface::synthesizeKeyPress(QString key) { - auto utf8Key = key.toUtf8(); + auto eventHandler = getEventHandler(); + if (eventHandler) { + auto utf8Key = key.toUtf8(); - int scanCode = (int)utf8Key[0]; - QString keyString = key; - if (equals(utf8Key, UPWARDS_WHITE_ARROW_FROM_BAR) || equals(utf8Key, ASTERISIM) || - equals(utf8Key, (uint8_t*)PUNCTUATION_STRING) || equals(utf8Key, (uint8_t*)ALPHABET_STRING)) { - return; // ignore - } else if (equals(utf8Key, LEFT_ARROW)) { - scanCode = Qt::Key_Backspace; - keyString = "\x08"; - } else if (equals(utf8Key, RETURN_SYMBOL)) { - scanCode = Qt::Key_Return; - keyString = "\x0d"; - } else if (equals(utf8Key, LEFTWARD_WHITE_ARROW)) { - scanCode = Qt::Key_Left; - keyString = ""; - } else if (equals(utf8Key, RIGHTWARD_WHITE_ARROW)) { - scanCode = Qt::Key_Right; - keyString = ""; + int scanCode = (int)utf8Key[0]; + QString keyString = key; + if (equals(utf8Key, UPWARDS_WHITE_ARROW_FROM_BAR) || equals(utf8Key, ASTERISIM) || + equals(utf8Key, (uint8_t*)PUNCTUATION_STRING) || equals(utf8Key, (uint8_t*)ALPHABET_STRING)) { + return; // ignore + } else if (equals(utf8Key, LEFT_ARROW)) { + scanCode = Qt::Key_Backspace; + keyString = "\x08"; + } else if (equals(utf8Key, RETURN_SYMBOL)) { + scanCode = Qt::Key_Return; + keyString = "\x0d"; + } else if (equals(utf8Key, LEFTWARD_WHITE_ARROW)) { + scanCode = Qt::Key_Left; + keyString = ""; + } else if (equals(utf8Key, RIGHTWARD_WHITE_ARROW)) { + scanCode = Qt::Key_Right; + keyString = ""; + } + + QKeyEvent* pressEvent = new QKeyEvent(QEvent::KeyPress, scanCode, Qt::NoModifier, keyString); + QKeyEvent* releaseEvent = new QKeyEvent(QEvent::KeyRelease, scanCode, Qt::NoModifier, keyString); + QCoreApplication::postEvent(eventHandler, pressEvent); + QCoreApplication::postEvent(eventHandler, releaseEvent); } - - QKeyEvent* pressEvent = new QKeyEvent(QEvent::KeyPress, scanCode, Qt::NoModifier, keyString); - QKeyEvent* releaseEvent = new QKeyEvent(QEvent::KeyRelease, scanCode, Qt::NoModifier, keyString); - QCoreApplication::postEvent(getEventHandler(), pressEvent); - QCoreApplication::postEvent(getEventHandler(), releaseEvent); } void OffscreenQmlSurface::setKeyboardRaised(QObject* object, bool raised, bool numeric) { From 3d75188500d7d91a7800269a05e7a882cc91dda1 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 4 Oct 2016 11:03:41 +1300 Subject: [PATCH 46/47] Untabify --- libraries/gl/src/gl/OffscreenQmlSurface.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/libraries/gl/src/gl/OffscreenQmlSurface.cpp b/libraries/gl/src/gl/OffscreenQmlSurface.cpp index 1aa4419599..afdf9aa5a9 100644 --- a/libraries/gl/src/gl/OffscreenQmlSurface.cpp +++ b/libraries/gl/src/gl/OffscreenQmlSurface.cpp @@ -40,16 +40,16 @@ QString fixupHifiUrl(const QString& urlString) { - static const QString ACCESS_TOKEN_PARAMETER = "access_token"; - static const QString ALLOWED_HOST = "metaverse.highfidelity.com"; + static const QString ACCESS_TOKEN_PARAMETER = "access_token"; + static const QString ALLOWED_HOST = "metaverse.highfidelity.com"; QUrl url(urlString); - QUrlQuery query(url); - if (url.host() == ALLOWED_HOST && query.allQueryItemValues(ACCESS_TOKEN_PARAMETER).empty()) { - auto accountManager = DependencyManager::get(); - query.addQueryItem(ACCESS_TOKEN_PARAMETER, accountManager->getAccountInfo().getAccessToken().token); - url.setQuery(query.query()); - return url.toString(); - } + QUrlQuery query(url); + if (url.host() == ALLOWED_HOST && query.allQueryItemValues(ACCESS_TOKEN_PARAMETER).empty()) { + auto accountManager = DependencyManager::get(); + query.addQueryItem(ACCESS_TOKEN_PARAMETER, accountManager->getAccountInfo().getAccessToken().token); + url.setQuery(query.query()); + return url.toString(); + } return urlString; } From bdff71151dab4b3c7f74ab13c832f0b4062603ad Mon Sep 17 00:00:00 2001 From: David Rowe Date: Fri, 7 Oct 2016 13:35:44 +1300 Subject: [PATCH 47/47] Updates from code review --- interface/resources/qml/ToolWindow.qml | 10 +++++----- .../resources/qml/controls-uit/ContentSection.qml | 2 +- libraries/gl/src/gl/OffscreenQmlSurface.cpp | 1 - 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/interface/resources/qml/ToolWindow.qml b/interface/resources/qml/ToolWindow.qml index a3a04be13e..68c8099970 100644 --- a/interface/resources/qml/ToolWindow.qml +++ b/interface/resources/qml/ToolWindow.qml @@ -56,7 +56,7 @@ ScrollingWindow { anchors.top: parent.top TabView { - id: tabView; + id: tabView width: pane.contentWidth // Pane height so that don't use Window's scrollbars otherwise tabs may be scrolled out of view. height: pane.scrollHeight @@ -69,10 +69,10 @@ ScrollingWindow { // (required for letting the C++ code access the webview) active: true enabled: false - property string originalUrl: ""; + property string originalUrl: "" WebView { - id: webView; + id: webView anchors.fill: parent enabled: false property alias eventBridgeWrapper: eventBridgeWrapper @@ -80,11 +80,11 @@ ScrollingWindow { QtObject { id: eventBridgeWrapper WebChannel.id: "eventBridgeWrapper" - property var eventBridge; + property var eventBridge } webChannel.registeredObjects: [eventBridgeWrapper] - onEnabledChanged: toolWindow.updateVisiblity(); + onEnabledChanged: toolWindow.updateVisiblity() } } } diff --git a/interface/resources/qml/controls-uit/ContentSection.qml b/interface/resources/qml/controls-uit/ContentSection.qml index 5fc86fc565..47a13e9262 100644 --- a/interface/resources/qml/controls-uit/ContentSection.qml +++ b/interface/resources/qml/controls-uit/ContentSection.qml @@ -109,7 +109,7 @@ Column { } MouseArea { - // Events are propogated so that any active control is defocussed. + // Events are propogated so that any active control is defocused. anchors.fill: parent propagateComposedEvents: true onPressed: { diff --git a/libraries/gl/src/gl/OffscreenQmlSurface.cpp b/libraries/gl/src/gl/OffscreenQmlSurface.cpp index b299421a1b..5b267ab7d5 100644 --- a/libraries/gl/src/gl/OffscreenQmlSurface.cpp +++ b/libraries/gl/src/gl/OffscreenQmlSurface.cpp @@ -581,7 +581,6 @@ bool OffscreenQmlRenderThread::allowNewFrame(uint8_t fps) { } OffscreenQmlSurface::OffscreenQmlSurface() { - // moveToThread(qApp->thread()); } static const uint64_t MAX_SHUTDOWN_WAIT_SECS = 2;