From ed11edad56a760c811db401cc54325a2b35d61c0 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Wed, 15 Feb 2017 13:59:04 -0800 Subject: [PATCH] EventBridge support --- .../resources/qml/hifi/tablet/TabletRoot.qml | 1 + .../resources/qml/hifi/tablet/WindowRoot.qml | 1 + .../src/TabletScriptingInterface.cpp | 83 +++++++++++++------ .../src/TabletScriptingInterface.h | 3 +- libraries/ui/src/QmlWindowClass.h | 6 +- 5 files changed, 65 insertions(+), 29 deletions(-) diff --git a/interface/resources/qml/hifi/tablet/TabletRoot.qml b/interface/resources/qml/hifi/tablet/TabletRoot.qml index 792c8d5082..edc2666c27 100644 --- a/interface/resources/qml/hifi/tablet/TabletRoot.qml +++ b/interface/resources/qml/hifi/tablet/TabletRoot.qml @@ -15,6 +15,7 @@ Item { } function loadSource(url) { + loader.source = ""; // HACK: make sure we load the qml fresh each time. loader.source = url; } diff --git a/interface/resources/qml/hifi/tablet/WindowRoot.qml b/interface/resources/qml/hifi/tablet/WindowRoot.qml index 14e969b3a6..6fb41512c2 100644 --- a/interface/resources/qml/hifi/tablet/WindowRoot.qml +++ b/interface/resources/qml/hifi/tablet/WindowRoot.qml @@ -25,6 +25,7 @@ Windows.ScrollingWindow { signal showDesktop(); function loadSource(url) { + loader.source = ""; // HACK: make sure we load the qml fresh each time. loader.source = url; } diff --git a/libraries/script-engine/src/TabletScriptingInterface.cpp b/libraries/script-engine/src/TabletScriptingInterface.cpp index dc6b1d6aa3..3142e27d15 100644 --- a/libraries/script-engine/src/TabletScriptingInterface.cpp +++ b/libraries/script-engine/src/TabletScriptingInterface.cpp @@ -11,10 +11,11 @@ #include #include +#include "DependencyManager.h" #include +#include #include #include "ScriptEngineLogging.h" -#include "DependencyManager.h" #include #include #include "SoundEffect.h" @@ -159,6 +160,10 @@ static const char* WEB_VIEW_SOURCE_URL = "TabletWebView.qml"; static const char* VRMENU_SOURCE_URL = "TabletMenu.qml"; static int s_windowNameCounter = 1; +class TabletRootWindow : public QmlWindowClass { + virtual QString qmlSource() const { return "hifi/tablet/WindowRoot.qml"; } +}; + TabletProxy::TabletProxy(QString name) : _name(name) { } @@ -177,13 +182,16 @@ void TabletProxy::setToolbarMode(bool toolbarMode) { // create new desktop window auto offscreenUi = DependencyManager::get(); offscreenUi->executeOnUiThread([=, this] { - InfoView::registerType(); - QString name = _name + QString("%1").arg(s_windowNameCounter++); - offscreenUi->show(QUrl("hifi/tablet/WindowRoot.qml"), name, [&](QQmlContext* context, QObject* newObject) { - QQuickItem* item = dynamic_cast(newObject); - _desktopWindow = item; - QObject::connect(_desktopWindow, SIGNAL(windowClosed), this, SLOT(desktopWindowClosed())); - }); + auto tabletRootWindow = new TabletRootWindow(); + tabletRootWindow->initQml(QVariantMap()); + auto quickItem = tabletRootWindow->asQuickItem(); + _desktopWindow = tabletRootWindow; + QMetaObject::invokeMethod(quickItem, "setShown", Q_ARG(const QVariant&, QVariant(false))); + + QObject::connect(tabletRootWindow, SIGNAL(webEventReceived(QVariant)), this, SIGNAL(webEventReceived(QVariant))); + + // forward qml surface events to interface js + connect(tabletRootWindow, &QmlWindowClass::fromQml, this, &TabletProxy::fromQml); }); } else { removeButtonsFromToolbar(); @@ -271,7 +279,7 @@ void TabletProxy::gotoMenuScreen(const QString& submenu) { if (!_toolbarMode && _qmlTabletRoot) { root = _qmlTabletRoot; } else if (_toolbarMode && _desktopWindow) { - root = _desktopWindow; + root = _desktopWindow->asQuickItem(); } if (root) { @@ -294,7 +302,7 @@ void TabletProxy::loadQMLSource(const QVariant& path) { if (!_toolbarMode && _qmlTabletRoot) { root = _qmlTabletRoot; } else if (_toolbarMode && _desktopWindow) { - root = _desktopWindow; + root = _desktopWindow->asQuickItem(); } if (root) { @@ -317,8 +325,8 @@ void TabletProxy::gotoHomeScreen() { QMetaObject::invokeMethod(_qmlTabletRoot, "playButtonClickSound"); } else if (_toolbarMode && _desktopWindow) { // close desktop window - if (_desktopWindow) { - QMetaObject::invokeMethod(_desktopWindow, "setShown", Q_ARG(const QVariant&, QVariant(false))); + if (_desktopWindow->asQuickItem()) { + QMetaObject::invokeMethod(_desktopWindow->asQuickItem(), "setShown", Q_ARG(const QVariant&, QVariant(false))); } } _state = State::Home; @@ -336,33 +344,47 @@ void TabletProxy::gotoWebScreen(const QString& url, const QString& injectedJavaS if (!_toolbarMode && _qmlTabletRoot) { root = _qmlTabletRoot; } else if (_toolbarMode && _desktopWindow) { - root = _desktopWindow; + root = _desktopWindow->asQuickItem(); } - if (_state != State::Web) { - if (root) { - QMetaObject::invokeMethod(root, "loadSource", Q_ARG(const QVariant&, QVariant(WEB_VIEW_SOURCE_URL))); - } - _state = State::Web; - emit screenChanged(QVariant("Web"), QVariant(url)); - } if (root) { + QMetaObject::invokeMethod(root, "loadSource", Q_ARG(const QVariant&, QVariant(WEB_VIEW_SOURCE_URL))); QMetaObject::invokeMethod(root, "setShown", Q_ARG(const QVariant&, QVariant(true))); QMetaObject::invokeMethod(root, "loadWebUrl", Q_ARG(const QVariant&, QVariant(url)), Q_ARG(const QVariant&, QVariant(injectedJavaScriptUrl))); } + _state = State::Web; + emit screenChanged(QVariant("Web"), QVariant(url)); } QObject* TabletProxy::addButton(const QVariant& properties) { auto tabletButtonProxy = QSharedPointer(new TabletButtonProxy(properties.toMap())); std::lock_guard guard(_mutex); _tabletButtonProxies.push_back(tabletButtonProxy); - if (_qmlTabletRoot) { + if (!_toolbarMode && _qmlTabletRoot) { auto tablet = getQmlTablet(); if (tablet) { addButtonProxyToQmlTablet(tablet, tabletButtonProxy.data()); } else { qCCritical(scriptengine) << "Could not find tablet in TabletRoot.qml"; } + } else if (_toolbarMode) { + + auto tabletScriptingInterface = DependencyManager::get(); + QObject* toolbarProxy = tabletScriptingInterface->getSystemToolbarProxy(); + + Qt::ConnectionType connectionType = Qt::AutoConnection; + if (QThread::currentThread() != toolbarProxy->thread()) { + connectionType = Qt::BlockingQueuedConnection; + } + + // copy properties from tablet button proxy to toolbar button proxy. + QObject* toolbarButtonProxy = nullptr; + bool hasResult = QMetaObject::invokeMethod(toolbarProxy, "addButton", connectionType, Q_RETURN_ARG(QObject*, toolbarButtonProxy), Q_ARG(QVariant, tabletButtonProxy->getProperties())); + if (hasResult) { + tabletButtonProxy->setToolbarButtonProxy(toolbarButtonProxy); + } else { + qCWarning(scriptengine) << "ToolbarProxy addButton has no result"; + } } return tabletButtonProxy.data(); } @@ -381,11 +403,18 @@ void TabletProxy::removeButton(QObject* tabletButtonProxy) { auto iter = std::find(_tabletButtonProxies.begin(), _tabletButtonProxies.end(), tabletButtonProxy); if (iter != _tabletButtonProxies.end()) { - if (_qmlTabletRoot) { + if (!_toolbarMode && _qmlTabletRoot) { (*iter)->setQmlButton(nullptr); if (tablet) { QMetaObject::invokeMethod(tablet, "removeButtonProxy", Qt::AutoConnection, Q_ARG(QVariant, (*iter)->getProperties())); } + } else if (_toolbarMode) { + auto tabletScriptingInterface = DependencyManager::get(); + QObject* toolbarProxy = tabletScriptingInterface->getSystemToolbarProxy(); + + // remove button from toolbarProxy + QMetaObject::invokeMethod(toolbarProxy, "removeButton", Qt::AutoConnection, Q_ARG(QVariant, (*iter)->getUuid().toString())); + (*iter)->setToolbarButtonProxy(nullptr); } _tabletButtonProxies.erase(iter); } else { @@ -412,14 +441,18 @@ void TabletProxy::updateAudioBar(const double micLevel) { } void TabletProxy::emitScriptEvent(QVariant msg) { - if (_qmlOffscreenSurface) { + if (!_toolbarMode && _qmlOffscreenSurface) { QMetaObject::invokeMethod(_qmlOffscreenSurface, "emitScriptEvent", Qt::AutoConnection, Q_ARG(QVariant, msg)); + } else if (_toolbarMode && _desktopWindow) { + QMetaObject::invokeMethod(_desktopWindow, "emitScriptEvent", Qt::AutoConnection, Q_ARG(QVariant, msg)); } } void TabletProxy::sendToQml(QVariant msg) { - if (_qmlOffscreenSurface) { + if (!_toolbarMode && _qmlOffscreenSurface) { QMetaObject::invokeMethod(_qmlOffscreenSurface, "sendToQml", Qt::AutoConnection, Q_ARG(QVariant, msg)); + } else if (_toolbarMode && _desktopWindow) { + QMetaObject::invokeMethod(_desktopWindow, "sendToQml", Qt::AutoConnection, Q_ARG(QVariant, msg)); } } @@ -446,7 +479,7 @@ void TabletProxy::addButtonsToMenuScreen() { if (!_toolbarMode && _qmlTabletRoot) { root = _qmlTabletRoot; } else if (_toolbarMode && _desktopWindow) { - root = _desktopWindow; + root = _desktopWindow->asQuickItem(); } if (!root) { diff --git a/libraries/script-engine/src/TabletScriptingInterface.h b/libraries/script-engine/src/TabletScriptingInterface.h index c9aee518fc..88e1cca60b 100644 --- a/libraries/script-engine/src/TabletScriptingInterface.h +++ b/libraries/script-engine/src/TabletScriptingInterface.h @@ -26,6 +26,7 @@ class TabletProxy; class TabletButtonProxy; +class QmlWindowClass; /**jsdoc * @namespace Tablet @@ -193,7 +194,7 @@ protected: std::vector> _tabletButtonProxies; QQuickItem* _qmlTabletRoot { nullptr }; QObject* _qmlOffscreenSurface { nullptr }; - QQuickItem* _desktopWindow { nullptr }; + QmlWindowClass* _desktopWindow { nullptr }; bool _toolbarMode { false }; enum class State { Uninitialized, Home, Web, Menu, QML }; diff --git a/libraries/ui/src/QmlWindowClass.h b/libraries/ui/src/QmlWindowClass.h index a6f59104fd..95777718bf 100644 --- a/libraries/ui/src/QmlWindowClass.h +++ b/libraries/ui/src/QmlWindowClass.h @@ -31,6 +31,9 @@ public: QmlWindowClass(); ~QmlWindowClass(); + virtual void initQml(QVariantMap properties); + QQuickItem* asQuickItem() const; + public slots: bool isVisible() const; void setVisible(bool visible); @@ -81,9 +84,6 @@ protected: virtual QString qmlSource() const { return "QmlWindow.qml"; } - virtual void initQml(QVariantMap properties); - QQuickItem* asQuickItem() const; - // FIXME needs to be initialized in the ctor once we have support // for tool window panes in QML bool _toolWindow { false };