Tablet can switch to a web url.

Help button has been updated to switch to the help.html.  It doesn't look good because
the content was authored expecting landscape window, not portrait.

The API is by no means final.  But it exposes two methods to JS.

* Tablet.gotoHomeScreen() - Used to forcefully go back to the home tablet "springboard", eventually this will
  hooked up to the tablet button.
* Tablet.gotoWebScreen(url) - Causes the tablet to switch from the home "springboard" and load a web url.

tabletTest.js and help.js have been updated to use this functionality.
This commit is contained in:
Anthony J. Thibault 2016-12-19 17:52:19 -08:00
parent 856791c11d
commit a791ddcc22
7 changed files with 144 additions and 28 deletions

View file

@ -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
}

View file

@ -0,0 +1,9 @@
import QtQuick 2.0
import QtWebEngine 1.2
WebEngineView {
id: webEngineView
height: parent.height
width: parent.width
}

View file

@ -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) {

View file

@ -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
//

View file

@ -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

View file

@ -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 () {

View file

@ -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);