diff --git a/interface/resources/qml/hifi/tablet/TabletRoot.qml b/interface/resources/qml/hifi/tablet/TabletRoot.qml new file mode 100644 index 0000000000..9186c4b086 --- /dev/null +++ b/interface/resources/qml/hifi/tablet/TabletRoot.qml @@ -0,0 +1,26 @@ +import QtQuick 2.0 + +Item { + id: tabletRoot + objectName: "tabletRoot" + + function loadSource(url) { + loader.source = url; + } + + function loadWebUrl(url) { + loader.item.url = url; + } + + Loader { + id: loader + objectName: "loader" + asynchronous: false + + width: parent.width + height: parent.height + } + + width: 480 + height: 720 +} diff --git a/interface/resources/qml/hifi/tablet/TabletWebView.qml b/interface/resources/qml/hifi/tablet/TabletWebView.qml new file mode 100644 index 0000000000..1bdba0ad22 --- /dev/null +++ b/interface/resources/qml/hifi/tablet/TabletWebView.qml @@ -0,0 +1,9 @@ +import QtQuick 2.0 +import QtWebEngine 1.2 + +WebEngineView { + id: webEngineView + height: parent.height + width: parent.width +} + diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp index 8e95a22560..7bd32aa99e 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp @@ -260,12 +260,8 @@ void RenderableWebEntityItem::loadSourceURL() { // TABLET_UI_HACK: move this to overlays as well! if (_webSurface->getRootItem() && _webSurface->getRootItem()->objectName() == "tabletRoot") { - auto loader = _webSurface->getRootItem()->findChild<QQuickItem*>("loader"); - if (loader) { - auto tablet = loader->findChild<QQuickItem*>("tablet"); - auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>(); - tabletScriptingInterface->setQmlTablet("com.highfidelity.interface.tablet.system", tablet); - } + auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>(); + tabletScriptingInterface->setQmlTabletRoot("com.highfidelity.interface.tablet.system", _webSurface->getRootItem()); } } } @@ -369,7 +365,7 @@ void RenderableWebEntityItem::destroyWebSurface() { // TABLET_UI_HACK: move this to overlays as well! if (rootItem && rootItem->objectName() == "tabletRoot") { auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>(); - tabletScriptingInterface->setQmlTablet("com.highfidelity.interface.tablet.system", nullptr); + tabletScriptingInterface->setQmlTabletRoot("com.highfidelity.interface.tablet.system", nullptr); } if (rootItem) { diff --git a/libraries/script-engine/src/TabletScriptingInterface.cpp b/libraries/script-engine/src/TabletScriptingInterface.cpp index d77c60e9e7..86ee706e0f 100644 --- a/libraries/script-engine/src/TabletScriptingInterface.cpp +++ b/libraries/script-engine/src/TabletScriptingInterface.cpp @@ -27,10 +27,10 @@ QObject* TabletScriptingInterface::getTablet(const QString& tabletId) { } } -void TabletScriptingInterface::setQmlTablet(QString tabletId, QQuickItem* qmlTablet) { +void TabletScriptingInterface::setQmlTabletRoot(QString tabletId, QQuickItem* qmlTabletRoot) { TabletProxy* tablet = qobject_cast<TabletProxy*>(getTablet(tabletId)); if (tablet) { - tablet->setQmlTablet(qmlTablet); + tablet->setQmlTabletRoot(qmlTabletRoot); } else { qWarning() << "TabletScriptingInterface::setupTablet() bad tablet object"; } @@ -40,6 +40,10 @@ void TabletScriptingInterface::setQmlTablet(QString tabletId, QQuickItem* qmlTab // TabletProxy // +static const char* TABLET_SOURCE_URL = "Tablet.qml"; +static const char* WEB_VIEW_SOURCE_URL = "TabletWebView.qml"; +static const char* LOADER_SOURCE_PROPERTY_NAME = "loaderSource"; + TabletProxy::TabletProxy(QString name) : _name(name) { ; } @@ -66,18 +70,35 @@ static void addButtonProxyToQmlTablet(QQuickItem* qmlTablet, TabletButtonProxy* buttonProxy->setQmlButton(qobject_cast<QQuickItem*>(qmlButton)); } -void TabletProxy::setQmlTablet(QQuickItem* qmlTablet) { +void TabletProxy::setQmlTabletRoot(QQuickItem* qmlTabletRoot) { std::lock_guard<std::mutex> guard(_mutex); - if (qmlTablet) { - _qmlTablet = qmlTablet; - for (auto& buttonProxy : _tabletButtonProxies) { - addButtonProxyToQmlTablet(_qmlTablet, buttonProxy.data()); - } + _qmlTabletRoot = qmlTabletRoot; + if (_qmlTabletRoot) { + gotoHomeScreen(); } else { - for (auto& buttonProxy : _tabletButtonProxies) { - buttonProxy->setQmlButton(nullptr); + removeButtonsFromHomeScreen(); + } +} + +void TabletProxy::gotoHomeScreen() { + if (_qmlTabletRoot) { + QString tabletSource = _qmlTabletRoot->property(LOADER_SOURCE_PROPERTY_NAME).toString(); + if (tabletSource != TABLET_SOURCE_URL) { + QMetaObject::invokeMethod(_qmlTabletRoot, "loadSource", Q_ARG(const QVariant&, QVariant(TABLET_SOURCE_URL))); + addButtonsToHomeScreen(); } - _qmlTablet = nullptr; + } +} + +void TabletProxy::gotoWebScreen(const QString& url) { + if (_qmlTabletRoot) { + removeButtonsFromHomeScreen(); + QString tabletSource = _qmlTabletRoot->property(LOADER_SOURCE_PROPERTY_NAME).toString(); + if (tabletSource != WEB_VIEW_SOURCE_URL) { + QMetaObject::invokeMethod(_qmlTabletRoot, "loadSource", Q_ARG(const QVariant&, QVariant(WEB_VIEW_SOURCE_URL))); + // TABLET_UI_HACK: TODO: addEventBridge to tablet.... + } + QMetaObject::invokeMethod(_qmlTabletRoot, "loadWebUrl", Q_ARG(const QVariant&, QVariant(url))); } } @@ -85,8 +106,8 @@ QObject* TabletProxy::addButton(const QVariant& properties) { auto tabletButtonProxy = QSharedPointer<TabletButtonProxy>(new TabletButtonProxy(properties.toMap())); std::lock_guard<std::mutex> guard(_mutex); _tabletButtonProxies.push_back(tabletButtonProxy); - if (_qmlTablet) { - addButtonProxyToQmlTablet(_qmlTablet, tabletButtonProxy.data()); + if (_qmlTabletRoot) { + addButtonProxyToQmlTablet(_qmlTabletRoot, tabletButtonProxy.data()); } return tabletButtonProxy.data(); } @@ -95,9 +116,9 @@ void TabletProxy::removeButton(QObject* tabletButtonProxy) { std::lock_guard<std::mutex> guard(_mutex); auto iter = std::find(_tabletButtonProxies.begin(), _tabletButtonProxies.end(), tabletButtonProxy); if (iter != _tabletButtonProxies.end()) { - if (_qmlTablet) { + if (_qmlTabletRoot) { (*iter)->setQmlButton(nullptr); - QMetaObject::invokeMethod(_qmlTablet, "removeButtonProxy", Qt::AutoConnection, Q_ARG(QVariant, (*iter)->getProperties())); + QMetaObject::invokeMethod(_qmlTabletRoot, "removeButtonProxy", Qt::AutoConnection, Q_ARG(QVariant, (*iter)->getProperties())); } _tabletButtonProxies.erase(iter); } else { @@ -105,6 +126,34 @@ void TabletProxy::removeButton(QObject* tabletButtonProxy) { } } +void TabletProxy::addButtonsToHomeScreen() { + if (!_qmlTabletRoot) { + return; + } + + auto loader = _qmlTabletRoot->findChild<QQuickItem*>("loader"); + if (!loader) { + return; + } + + auto tablet = loader->findChild<QQuickItem*>("tablet"); + if (!tablet) { + return; + } + + auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>(); + for (auto& buttonProxy : _tabletButtonProxies) { + addButtonProxyToQmlTablet(tablet, buttonProxy.data()); + } +} + +void TabletProxy::removeButtonsFromHomeScreen() { + auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>(); + for (auto& buttonProxy : _tabletButtonProxies) { + buttonProxy->setQmlButton(nullptr); + } +} + // // TabletButtonProxy // diff --git a/libraries/script-engine/src/TabletScriptingInterface.h b/libraries/script-engine/src/TabletScriptingInterface.h index da796be174..b9482ca8a4 100644 --- a/libraries/script-engine/src/TabletScriptingInterface.h +++ b/libraries/script-engine/src/TabletScriptingInterface.h @@ -37,7 +37,7 @@ public: */ Q_INVOKABLE QObject* getTablet(const QString& tabletId); - void setQmlTablet(QString tabletId, QQuickItem* qmlTablet); + void setQmlTabletRoot(QString tabletId, QQuickItem* qmlTabletRoot); protected: std::mutex _mutex; @@ -54,7 +54,20 @@ class TabletProxy : public QObject { public: TabletProxy(QString name); - void setQmlTablet(QQuickItem* qmlTablet); + void setQmlTabletRoot(QQuickItem* qmlTabletRoot); + + /**jsdoc + * @function TabletProxy#gotoHomeScreen + * transition to the home screen + */ + Q_INVOKABLE void gotoHomeScreen(); + + /**jsdoc + * @function TabletProxy#gotoWebScreen + * show the specified web url on the tablet. + * @param url {string} + */ + Q_INVOKABLE void gotoWebScreen(const QString& url); /**jsdoc * @function TabletProxy#addButton @@ -73,10 +86,14 @@ public: QString getName() const { return _name; } protected: + + void addButtonsToHomeScreen(); + void removeButtonsFromHomeScreen(); + QString _name; std::mutex _mutex; std::vector<QSharedPointer<TabletButtonProxy>> _tabletButtonProxies; - QQuickItem* _qmlTablet { nullptr }; + QQuickItem* _qmlTabletRoot { nullptr }; }; /**jsdoc diff --git a/scripts/developer/tests/tabletTest.js b/scripts/developer/tests/tabletTest.js index 9920ff30b8..9eba7e53d7 100644 --- a/scripts/developer/tests/tabletTest.js +++ b/scripts/developer/tests/tabletTest.js @@ -28,6 +28,8 @@ Script.setInterval(function () { button.clicked.connect(function () { print("AJT: BAM!!! CLICK from JS!"); + var url = "https://news.ycombinator.com/"; + tablet.gotoWebScreen(url); }); Script.scriptEnding.connect(function () { diff --git a/scripts/system/help.js b/scripts/system/help.js index c8e14a80a6..b95ccbb529 100644 --- a/scripts/system/help.js +++ b/scripts/system/help.js @@ -10,6 +10,7 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +/* globals Tablet */ (function() { // BEGIN LOCAL_SCOPE @@ -18,9 +19,25 @@ text: "HELP" }); - // TODO: make button state reflect whether the window is opened or closed (independently from us). - function onClicked(){ - Menu.triggerOption('Help...') + function onClicked() { + var HELP_URL = Script.resourcesPath() + "html/help.html"; + + // Similar logic to Application::showHelp() + var defaultTab = "kbm"; + var handControllerName = "vive"; + if (HMD.active) { + if ("Vive" in Controller.Hardware) { + defaultTab = "handControllers"; + handControllerName = "vive"; + } else if ("OculusTouch" in Controller.Hardware) { + defaultTab = "handControllers"; + handControllerName = "oculus"; + } + } else if ("SDL2" in Controller.Hardware) { + defaultTab = "gamepad"; + } + var queryParameters = "handControllerName=" + handControllerName + "&defaultTab=" + defaultTab; + tablet.gotoWebScreen(HELP_URL + "?" + queryParameters); } button.clicked.connect(onClicked);