diff --git a/interface/resources/qml/hifi/tablet/TabletGeneralPreferences.qml b/interface/resources/qml/hifi/tablet/TabletGeneralPreferences.qml index 254e4203ce..1d15fe8b23 100644 --- a/interface/resources/qml/hifi/tablet/TabletGeneralPreferences.qml +++ b/interface/resources/qml/hifi/tablet/TabletGeneralPreferences.qml @@ -19,6 +19,7 @@ StackView { objectName: "stack" property string title: "General Settings" property alias gotoPreviousApp: root.gotoPreviousApp; + property alias gotoPreviousAppFromScript: root.gotoPreviousAppFromScript; signal sendToScript(var message); function pushSource(path) { @@ -30,6 +31,10 @@ StackView { profileRoot.pop(); } + function emitSendToScript(message) { + profileRoot.sendToScript(message); + } + TabletPreferencesDialog { id: root objectName: "TabletGeneralPreferences" diff --git a/interface/resources/qml/hifi/tablet/TabletRoot.qml b/interface/resources/qml/hifi/tablet/TabletRoot.qml index 5559c36fd1..6001497743 100644 --- a/interface/resources/qml/hifi/tablet/TabletRoot.qml +++ b/interface/resources/qml/hifi/tablet/TabletRoot.qml @@ -104,6 +104,10 @@ Rectangle { if (loader.item.hasOwnProperty("gotoPreviousApp")) { loader.item.gotoPreviousApp = true; } + + if (loader.item.hasOwnProperty("gotoPreviousAppFromScript")) { + loader.item.gotoPreviousAppFromScript = true; + } }); } } @@ -276,7 +280,7 @@ Rectangle { } else { console.log("newSource is of unknown type!"); } - + screenChanged(type, newSource); }); } diff --git a/interface/resources/qml/hifi/tablet/tabletWindows/TabletPreferencesDialog.qml b/interface/resources/qml/hifi/tablet/tabletWindows/TabletPreferencesDialog.qml index c6b4fce14e..8e8a262107 100644 --- a/interface/resources/qml/hifi/tablet/tabletWindows/TabletPreferencesDialog.qml +++ b/interface/resources/qml/hifi/tablet/tabletWindows/TabletPreferencesDialog.qml @@ -30,6 +30,7 @@ Item { property bool keyboardRaised: false property bool punctuationMode: false property bool gotoPreviousApp: false + property bool gotoPreviousAppFromScript: false property var tablet; @@ -72,7 +73,9 @@ Item { function closeDialog() { var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); - if (gotoPreviousApp) { + if (gotoPreviousAppFromScript) { + dialog.parent.sendToScript("returnToPreviousApp"); + } else if (gotoPreviousApp) { tablet.returnToPreviousApp(); } else { tablet.gotoHomeScreen(); diff --git a/libraries/ui/src/ui/TabletScriptingInterface.cpp b/libraries/ui/src/ui/TabletScriptingInterface.cpp index 3465138e00..75b08ba44f 100644 --- a/libraries/ui/src/ui/TabletScriptingInterface.cpp +++ b/libraries/ui/src/ui/TabletScriptingInterface.cpp @@ -592,12 +592,51 @@ void TabletProxy::gotoMenuScreen(const QString& submenu) { } } -void TabletProxy::loadQMLOnTop(const QVariant& path) { - if (QThread::currentThread() != thread()) { - QMetaObject::invokeMethod(this, "loadQMLOnTop", Q_ARG(QVariant, path)); +void TabletProxy::loadQMLOnTopImpl(const QVariant& path, bool localSafeContext) { + if (QThread::currentThread() != thread()) { + qCWarning(uiLogging) << __FUNCTION__ << "may not be called directly by scripts"; return; } + QObject* root = nullptr; + if (!_toolbarMode && _qmlTabletRoot) { + root = _qmlTabletRoot; + } else if (_toolbarMode && _desktopWindow) { + root = _desktopWindow->asQuickItem(); + } + + if (root) { + if (localSafeContext) { + hifi::scripting::setLocalAccessSafeThread(true); + } + QMetaObject::invokeMethod(root, "loadQMLOnTop", Q_ARG(const QVariant&, path)); + QMetaObject::invokeMethod(root, "setShown", Q_ARG(const QVariant&, QVariant(true))); + if (_toolbarMode && _desktopWindow) { + QMetaObject::invokeMethod(root, "setResizable", Q_ARG(const QVariant&, QVariant(false))); + } + hifi::scripting::setLocalAccessSafeThread(false); + } else { + qCDebug(uiLogging) << "tablet cannot load QML because _qmlTabletRoot is null"; + } +} + +void TabletProxy::loadQMLOnTop(const QVariant& path) { + bool localSafeContext = hifi::scripting::isLocalAccessSafeThread(); + if (QThread::currentThread() != thread()) { + QMetaObject::invokeMethod(this, "loadQMLOnTopImpl", Q_ARG(QVariant, path), Q_ARG(bool, localSafeContext)); + return; + } + + loadQMLOnTopImpl(path, localSafeContext); +} + +void TabletProxy::returnToPreviousAppImpl(bool localSafeContext) { + if (QThread::currentThread() != thread()) { + qCWarning(uiLogging) << __FUNCTION__ << "may not be called directly by scripts"; + return; + + } + QObject* root = nullptr; if (!_toolbarMode && _qmlTabletRoot) { root = _qmlTabletRoot; @@ -606,35 +645,26 @@ void TabletProxy::loadQMLOnTop(const QVariant& path) { } if (root) { - QMetaObject::invokeMethod(root, "loadQMLOnTop", Q_ARG(const QVariant&, path)); - QMetaObject::invokeMethod(root, "setShown", Q_ARG(const QVariant&, QVariant(true))); - if (_toolbarMode && _desktopWindow) { - QMetaObject::invokeMethod(root, "setResizable", Q_ARG(const QVariant&, QVariant(false))); + if (localSafeContext) { + hifi::scripting::setLocalAccessSafeThread(true); } + QMetaObject::invokeMethod(root, "returnToPreviousApp"); + QMetaObject::invokeMethod(root, "setShown", Q_ARG(const QVariant&, QVariant(true))); + hifi::scripting::setLocalAccessSafeThread(false); } else { qCDebug(uiLogging) << "tablet cannot load QML because _qmlTabletRoot is null"; } } void TabletProxy::returnToPreviousApp() { + bool localSafeContext = hifi::scripting::isLocalAccessSafeThread(); + qDebug() << "TabletProxy::returnToPreviousApp -> localSafeContext: " << localSafeContext; if (QThread::currentThread() != thread()) { - QMetaObject::invokeMethod(this, "returnToPreviousApp"); + QMetaObject::invokeMethod(this, "returnToPreviousAppImpl", Q_ARG(bool, localSafeContext)); return; } - QObject* root = nullptr; - if (!_toolbarMode && _qmlTabletRoot) { - root = _qmlTabletRoot; - } else if (_toolbarMode && _desktopWindow) { - root = _desktopWindow->asQuickItem(); - } - - if (root) { - QMetaObject::invokeMethod(root, "returnToPreviousApp"); - QMetaObject::invokeMethod(root, "setShown", Q_ARG(const QVariant&, QVariant(true))); - } else { - qCDebug(uiLogging) << "tablet cannot load QML because _qmlTabletRoot is null"; - } + returnToPreviousAppImpl(localSafeContext); } void TabletProxy::loadQMLSource(const QVariant& path, bool resizable) { @@ -940,8 +970,6 @@ void TabletProxy::sendToQml(const QVariant& msg) { } } - - OffscreenQmlSurface* TabletProxy::getTabletSurface() { if (QThread::currentThread() != thread()) { OffscreenQmlSurface* result = nullptr; diff --git a/libraries/ui/src/ui/TabletScriptingInterface.h b/libraries/ui/src/ui/TabletScriptingInterface.h index 9a5ff9efac..bae5eda29e 100644 --- a/libraries/ui/src/ui/TabletScriptingInterface.h +++ b/libraries/ui/src/ui/TabletScriptingInterface.h @@ -298,10 +298,26 @@ public: */ Q_INVOKABLE void loadQMLSourceImpl(const QVariant& path, bool resizable, bool localSafeContext); + /**jsdoc + * Internal function, do not call from scripts + * @function TabletProxy#loadHTMLSourceImpl + */ Q_INVOKABLE void loadHTMLSourceImpl(const QVariant& url, const QString& injectJavaScriptUrl, bool localSafeContext); + /**jsdoc + * Internal function, do not call from scripts + * @function TabletProxy#loadHTMLSourceImpl + */ Q_INVOKABLE void loadHTMLSourceImpl(const QString& url, const QString& injectedJavaScriptUrl, bool loadOtherBase, bool localSafeContext); + /**jsdoc + * Internal function, do not call from scripts + * @function TabletProxy#returnToPreviousAppImpl + */ + Q_INVOKABLE void returnToPreviousAppImpl(bool localSafeContext); + + Q_INVOKABLE void loadQMLOnTopImpl(const QVariant& path, bool localSafeContext); + // FIXME: This currently relies on a script initializing the tablet (hence the bool denoting success); // it should be initialized internally so it cannot fail diff --git a/scripts/system/snapshot.js b/scripts/system/snapshot.js index 946de6df0f..a37fb13bd9 100644 --- a/scripts/system/snapshot.js +++ b/scripts/system/snapshot.js @@ -65,6 +65,7 @@ function onMessage(message) { // 2. Although we currently use a single image, we would like to take snapshot, a selfie, a 360 etc. all at the // same time, show the user all of them, and have the user deselect any that they do not want to share. // So we'll ultimately be receiving a set of objects, perhaps with different post processing for each. + if (message.type !== "snapshot") { return; } @@ -85,7 +86,7 @@ function onMessage(message) { image_data: imageData, canShare: canShare }); - }); + }); } else { ui.sendMessage({ type: "snapshot", @@ -274,6 +275,14 @@ var POLAROID_MODEL_URL = 'http://hifi-content.s3.amazonaws.com/alan/dev/Test/sna var POLAROID_RATE_LIMIT_MS = 1000; var polaroidPrintingIsRateLimited = false; +// force call the gotoPreviousApp on script thead to load snapshot html page. +var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); +tablet.fromQml.connect(function(message) { + if (message === 'returnToPreviousApp') { + tablet.returnToPreviousApp(); + } +}); + function printToPolaroid(image_url) { // Rate-limit printing if (polaroidPrintingIsRateLimited) {