InteractiveWindow scripting API

This commit is contained in:
Thijs Wenker 2018-06-28 19:04:08 +02:00
parent 736c56f5f4
commit 5029767493
8 changed files with 755 additions and 4 deletions

View file

@ -0,0 +1,283 @@
//
// InteractiveWindow.qml
//
// Created by Thijs Wenker on 2018-06-25
// Copyright 2018 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
//
import QtQuick 2.3
import InteractiveWindowFlags 1.0
import "windows" as Windows
import "controls"
import "controls-uit" as Controls
import "styles"
import "styles-uit"
Windows.Window {
id: root;
HifiConstants { id: hifi }
title: "InteractiveWindow";
resizable: true;
// Virtual window visibility
shown: false;
focus: true;
property var channel;
// Don't destroy on close... otherwise the JS/C++ will have a dangling pointer
destroyOnCloseButton: false;
property var flags: 0;
property var source;
property var dynamicContent;
property var nativeWindow;
// custom visibility flag for interactiveWindow to proxy virtualWindow.shown / nativeWindow.visible
property var interactiveWindowVisible: true;
property point interactiveWindowPosition;
property size interactiveWindowSize;
// Keyboard control properties in case needed by QML content.
property bool keyboardEnabled: false;
property bool keyboardRaised: false;
property bool punctuationMode: false;
readonly property int modeNotSet: 0;
readonly property int modeNative: 1;
readonly property int modeVirtual: 2;
property int windowMode: modeNotSet;
property bool forceNative: false;
property bool forceVirtual: false;
property string windowModeText: getModeString();
function getModeString() {
switch (windowMode) {
case modeNotSet:
return "none";
case modeNative:
return "native";
case modeVirtual:
return "virtual";
}
return "unknown";
}
onWindowModeChanged: {
windowModeText = getModeString();
}
onSourceChanged: {
if (dynamicContent) {
dynamicContent.destroy();
dynamicContent = null;
}
QmlSurface.load(source, contentHolder, function(newObject) {
dynamicContent = newObject;
if (dynamicContent && dynamicContent.anchors) {
dynamicContent.anchors.fill = contentHolder;
}
});
}
function updateInteractiveWindowPositionForMode() {
if (windowMode === modeVirtual) {
x = interactiveWindowPosition.x;
y = interactiveWindowPosition.y;
} else if (windowMode === modeVirtual && nativeWindow) {
nativeWindow.x = interactiveWindowPosition.x;
nativeWindow.y = interactiveWindowPosition.y;
}
}
function updateInteractiveWindowSizeForMode() {
if (windowMode === modeVirtual) {
width = interactiveWindowSize.width;
height = interactiveWindowSize.height;
} else if (windowMode === modeVirtual && nativeWindow) {
nativeWindow.width = interactiveWindowSize.width;
nativeWindow.height = interactiveWindowSize.heigth;
}
}
function trySwitchWindowMode() {
if (windowMode !== modeVirtual && (HMD.active || (forceVirtual && !forceNative))) {
windowMode = modeVirtual;
if (nativeWindow) {
nativeWindow.setVisible(false);
}
contentHolder.parent = root;
updateInteractiveWindowPositionForMode();
shown = interactiveWindowVisible;
} else if (windowMode !== modeNative && (!HMD.active || (forceNative && !forceVirtual))) {
windowMode = modeNative;
shown = false;
if (nativeWindow) {
contentHolder.parent = nativeWindow.contentItem;
nativeWindow.setVisible(interactiveWindowVisible);
updateInteractiveWindowPositionForMode();
}
} else if (windowMode === modeNotSet) {
console.error("windowMode should be set.");
}
}
function displayModeChanged(isHMD) {
trySwitchWindowMode();
}
Component.onCompleted: {
HMD.displayModeChanged.connect(displayModeChanged);
forceVirtual = (flags & InteractiveWindowFlags.ForceVirtual) === InteractiveWindowFlags.ForceVirtual;
forceNative = (flags & InteractiveWindowFlags.ForceNative) === InteractiveWindowFlags.ForceNative;
x = interactiveWindowPosition.x;
y = interactiveWindowPosition.y;
width = interactiveWindowSize.width;
height = interactiveWindowSize.height;
if (!forceVirtual || (forceVirtual && forceNative)) {
nativeWindow = Qt.createQmlObject('
import QtQuick 2.3;
import QtQuick.Window 2.3;
Window {
id: root;
Rectangle {
color: hifi.colors.baseGray
anchors.fill: parent
}
}', root, 'InteractiveWindow.qml->nativeWindow');
nativeWindow.title = root.title;
var nativeWindowFlags = Qt.Window |
Qt.WindowTitleHint |
Qt.WindowSystemMenuHint |
Qt.WindowCloseButtonHint |
Qt.WindowMaximizeButtonHint |
Qt.WindowMinimizeButtonHint;
if ((flags & InteractiveWindowFlags.AlwaysOnTop) === InteractiveWindowFlags.AlwaysOnTop) {
nativeWindowFlags |= Qt.WindowStaysOnTopHint;
}
nativeWindow.flags = nativeWindowFlags;
nativeWindow.x = interactiveWindowPosition.x;
nativeWindow.y = interactiveWindowPosition.y;
nativeWindow.width = interactiveWindowSize.width;
nativeWindow.height = interactiveWindowSize.height;
nativeWindow.xChanged.connect(function() {
if (windowMode === modeNative && nativeWindow.visible) {
interactiveWindowPosition = Qt.point(nativeWindow.x, interactiveWindowPosition.y);
}
});
nativeWindow.yChanged.connect(function() {
if (windowMode === modeNative && nativeWindow.visible) {
interactiveWindowPosition = Qt.point(interactiveWindowPosition.x, nativeWindow.y);
}
});
nativeWindow.widthChanged.connect(function() {
if (windowMode === modeNative && nativeWindow.visible) {
interactiveWindowSize = Qt.size(nativeWindow.width, interactiveWindowSize.height);
}
});
nativeWindow.heightChanged.connect(function() {
if (windowMode === modeNative && nativeWindow.visible) {
interactiveWindowSize = Qt.size(interactiveWindowSize.width, nativeWindow.height);
}
});
}
// finally set the initial window mode:
trySwitchWindowMode();
}
// Handle message traffic from the script that launched us to the loaded QML
function fromScript(message) {
if (root.dynamicContent && root.dynamicContent.fromScript) {
root.dynamicContent.fromScript(message);
}
}
function show() {
interactiveWindowVisible = true;
raiseWindow();
}
function raiseWindow() {
if (windowMode === modeVirtual) {
raise();
} else if (windowMode === modeNative && nativeWindow) {
nativeWindow.raise();
}
}
// Handle message traffic from our loaded QML to the script that launched us
signal sendToScript(var message);
onDynamicContentChanged: {
if (dynamicContent && dynamicContent.sendToScript) {
dynamicContent.sendToScript.connect(sendToScript);
}
}
onInteractiveWindowVisibleChanged: {
if (windowMode === modeVirtual) {
shown = interactiveWindowVisible;
} else if (windowMode === modeNative && nativeWindow) {
nativeWindow.setVisible(interactiveWindowVisible);
}
}
onTitleChanged: {
if (nativeWindow) {
nativeWindow.title = title;
}
}
onXChanged: {
if (windowMode === modeVirtual) {
interactiveWindowPosition = Qt.point(x, interactiveWindowPosition.y);
}
}
onYChanged: {
if (windowMode === modeVirtual) {
interactiveWindowPosition = Qt.point(interactiveWindowPosition.x, y);
}
}
onWidthChanged: {
if (windowMode === modeVirtual) {
interactiveWindowSize = Qt.size(width, interactiveWindowSize.height);
}
}
onHeightChanged: {
if (windowMode === modeVirtual) {
interactiveWindowSize = Qt.size(interactiveWindowSize.width, height);
}
}
onInteractiveWindowPositionChanged: {
updateInteractiveWindowPositionForMode();
}
onInteractiveWindowSizeChanged: {
updateInteractiveWindowSizeForMode();
}
Item {
id: contentHolder
anchors.fill: parent
}
}

View file

@ -12,7 +12,7 @@ Rectangle {
}
Label {
text: OverlayWindowTestString
text: "OverlayWindowTestString"
anchors.centerIn: parent
}
}

View file

@ -129,6 +129,7 @@
#include <SoundCache.h>
#include <ui/TabletScriptingInterface.h>
#include <ui/ToolbarScriptingInterface.h>
#include <InteractiveWindow.h>
#include <Tooltip.h>
#include <udt/PacketHeaders.h>
#include <UserActivityLogger.h>
@ -2827,6 +2828,8 @@ void Application::initializeUi() {
qmlRegisterType<Preference>("Hifi", 1, 0, "Preference");
qmlRegisterType<WebBrowserSuggestionsEngine>("HifiWeb", 1, 0, "WebBrowserSuggestionsEngine");
InteractiveWindowEnums::declareQML();
{
auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>();
tabletScriptingInterface->getTablet(SYSTEM_TABLET);
@ -6632,6 +6635,8 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEnginePointe
qScriptRegisterMetaType(scriptEngine.data(), OverlayIDtoScriptValue, OverlayIDfromScriptValue);
registerInteractiveWindowMetaType(scriptEngine.data());
DependencyManager::get<PickScriptingInterface>()->registerMetaTypes(scriptEngine.data());
// connect this script engines printedMessage signal to the global ScriptEngines these various messages

View file

@ -14,6 +14,8 @@
#include <QWindow>
#include <QScreen>
#include <shared/QtHelpers.h>
#include "Application.h"
#include "MainWindow.h"
#include <display-plugins/CompositorHelper.h>
@ -41,3 +43,14 @@ void DesktopScriptingInterface::show(const QString& path, const QString& title)
DependencyManager::get<OffscreenUi>()->show(path, title);
}
InteractiveWindowPointer DesktopScriptingInterface::createWindow(const QString& sourceUrl, const QVariantMap& properties) {
if (QThread::currentThread() != thread()) {
InteractiveWindowPointer interactiveWindow = nullptr;
BLOCKING_INVOKE_METHOD(this, "createWindow",
Q_RETURN_ARG(InteractiveWindowPointer, interactiveWindow),
Q_ARG(QString, sourceUrl),
Q_ARG(QVariantMap, properties));
return interactiveWindow;
}
return new InteractiveWindow(sourceUrl, properties);;
}

View file

@ -13,20 +13,38 @@
#define hifi_DesktopScriptingInterface_h
#include <QObject>
#include <QtScript/QScriptValue>
#include <DependencyManager.h>
#include "InteractiveWindow.h"
class DesktopScriptingInterface : public QObject, public Dependency {
Q_OBJECT
Q_PROPERTY(int width READ getWidth) // Physical width of screen(s) including task bars and system menus
Q_PROPERTY(int height READ getHeight) // Physical height of screen(s) including task bars and system menus
Q_PROPERTY(int ForceNative READ flagForceNative)
Q_PROPERTY(int ForceVirtual READ flagForceVirtual)
Q_PROPERTY(int AlwaysOnTop READ flagAlwaysOnTop)
Q_PROPERTY(int CloseButtonHides READ flagCloseButtonHides)
public:
Q_INVOKABLE void setHUDAlpha(float alpha);
Q_INVOKABLE void show(const QString& path, const QString& title);
Q_INVOKABLE InteractiveWindowPointer createWindow(const QString& sourceUrl, const QVariantMap& properties = QVariantMap());
int getWidth();
int getHeight();
private:
int flagForceNative() { return ForceNative; }
int flagForceVirtual() { return ForceVirtual; }
int flagAlwaysOnTop() { return AlwaysOnTop; }
int flagCloseButtonHides() { return CloseButtonHides; }
};
#endif // hifi_DesktopScriptingInterface_h

View file

@ -393,9 +393,6 @@ void OffscreenSurface::finishQmlLoad(QQmlComponent* qmlComponent,
_sharedObject->setRootItem(newItem);
}
qmlComponent->completeCreate();
qmlComponent->deleteLater();
onItemCreated(qmlContext, newItem);
if (!rootCreated) {
@ -405,6 +402,8 @@ void OffscreenSurface::finishQmlLoad(QQmlComponent* qmlComponent,
// Call this callback after rootitem is set, otherwise VrMenu wont work
callback(qmlContext, newItem);
}
qmlComponent->completeCreate();
qmlComponent->deleteLater();
}
QQmlContext* OffscreenSurface::contextForUrl(const QUrl& qmlSource, QQuickItem* parent, bool forceNewContext) {

View file

@ -0,0 +1,252 @@
//
// InteractiveWindow.cpp
// libraries/ui/src
//
// Created by Thijs Wenker on 2018-06-25
// Copyright 2018 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
//
#include "InteractiveWindow.h"
#include <QtQml/QQmlContext>
#include <QtCore/QThread>
#include <DependencyManager.h>
#include <RegisteredMetaTypes.h>
#include "OffscreenUi.h"
#include "shared/QtHelpers.h"
static auto CONTENT_WINDOW_QML = QUrl("InteractiveWindow.qml");
static const char* const FLAGS_PROPERTY = "flags";
static const char* const SOURCE_PROPERTY = "source";
static const char* const TITLE_PROPERTY = "title";
static const char* const POSITION_PROPERTY = "position";
static const char* const INTERACTIVE_WINDOW_POSITION_PROPERTY = "interactiveWindowPosition";
static const char* const SIZE_PROPERTY = "size";
static const char* const INTERACTIVE_WINDOW_SIZE_PROPERTY = "interactiveWindowSize";
static const char* const VISIBLE_PROPERTY = "visible";
static const char* const INTERACTIVE_WINDOW_VISIBLE_PROPERTY = "interactiveWindowVisible";
static const char* const EVENT_BRIDGE_PROPERTY = "eventBridge";
static const char* const WINDOW_MODE_TEXT_PROPERTY = "windowModeText";
static const uvec2 MAX_QML_WINDOW_SIZE{ 1280, 720 };
static const uvec2 MIN_QML_WINDOW_SIZE{ 120, 80 };
static const QStringList KNOWN_SCHEMES = QStringList() << "http" << "https" << "file" << "about" << "atp" << "qrc";
void registerInteractiveWindowMetaType(QScriptEngine* engine) {
qScriptRegisterMetaType(engine, interactiveWindowPointerToScriptValue, interactiveWindowPointerFromScriptValue);
}
QScriptValue interactiveWindowPointerToScriptValue(QScriptEngine* engine, const InteractiveWindowPointer& in) {
return engine->newQObject(in, QScriptEngine::ScriptOwnership);
}
void interactiveWindowPointerFromScriptValue(const QScriptValue& object, InteractiveWindowPointer& out) {
if (const auto interactiveWindow = qobject_cast<InteractiveWindowPointer>(object.toQObject())) {
out = interactiveWindow;
}
}
InteractiveWindow::InteractiveWindow(const QString& sourceUrl, const QVariantMap& properties) {
auto offscreenUi = DependencyManager::get<OffscreenUi>();
// Build the event bridge and wrapper on the main thread
offscreenUi->loadInNewContext(CONTENT_WINDOW_QML, [&](QQmlContext* context, QObject* object) {
_qmlWindow = object;
context->setContextProperty(EVENT_BRIDGE_PROPERTY, this);
if (properties.contains(FLAGS_PROPERTY)) {
object->setProperty(FLAGS_PROPERTY, properties[FLAGS_PROPERTY].toUInt());
}
if (properties.contains(TITLE_PROPERTY)) {
object->setProperty(TITLE_PROPERTY, properties[TITLE_PROPERTY].toString());
}
if (properties.contains(SIZE_PROPERTY)) {
const auto size = vec2FromVariant(properties[SIZE_PROPERTY]);
object->setProperty(INTERACTIVE_WINDOW_SIZE_PROPERTY, QSize(size.x, size.y));
}
if (properties.contains(POSITION_PROPERTY)) {
const auto position = vec2FromVariant(properties[POSITION_PROPERTY]);
object->setProperty(INTERACTIVE_WINDOW_POSITION_PROPERTY, QPointF(position.x, position.y));
}
if (properties.contains(VISIBLE_PROPERTY)) {
object->setProperty(VISIBLE_PROPERTY, properties[INTERACTIVE_WINDOW_VISIBLE_PROPERTY].toBool());
}
connect(object, SIGNAL(sendToScript(QVariant)), this, SLOT(qmlToScript(const QVariant&)), Qt::QueuedConnection);
connect(object, SIGNAL(interactiveWindowPositionChanged()), this, SIGNAL(positionChanged()), Qt::QueuedConnection);
connect(object, SIGNAL(interactiveWindowSizeChanged()), this, SIGNAL(sizeChanged()), Qt::QueuedConnection);
connect(object, SIGNAL(interactiveWindowVisibleChanged()), this, SIGNAL(visibleChanged()), Qt::QueuedConnection);
connect(object, SIGNAL(windowModeChanged()), this, SIGNAL(modeChanged()), Qt::QueuedConnection);
connect(object, SIGNAL(titleChanged()), this, SIGNAL(titleChanged()), Qt::QueuedConnection);
QUrl sourceURL{ sourceUrl };
// If the passed URL doesn't correspond to a known scheme, assume it's a local file path
if (!KNOWN_SCHEMES.contains(sourceURL.scheme(), Qt::CaseInsensitive)) {
sourceURL = QUrl::fromLocalFile(sourceURL.toString()).toString();
}
object->setProperty(SOURCE_PROPERTY, sourceURL);
});
}
InteractiveWindow::~InteractiveWindow() {
close();
}
void InteractiveWindow::sendToQml(const QVariant& message) {
// Forward messages received from the script on to QML
QMetaObject::invokeMethod(_qmlWindow, "fromScript", Qt::QueuedConnection, Q_ARG(QVariant, message));
}
void InteractiveWindow::emitScriptEvent(const QVariant& scriptMessage) {
if (QThread::currentThread() != thread()) {
QMetaObject::invokeMethod(this, "emitScriptEvent", Qt::QueuedConnection, Q_ARG(QVariant, scriptMessage));
} else {
emit scriptEventReceived(scriptMessage);
}
}
void InteractiveWindow::emitWebEvent(const QVariant& webMessage) {
if (QThread::currentThread() != thread()) {
QMetaObject::invokeMethod(this, "emitWebEvent", Qt::QueuedConnection, Q_ARG(QVariant, webMessage));
} else {
emit webEventReceived(webMessage);
}
}
void InteractiveWindow::close() {
if (QThread::currentThread() != thread()) {
QMetaObject::invokeMethod(this, "close");
return;
}
if (_qmlWindow) {
_qmlWindow->deleteLater();
}
_qmlWindow = nullptr;
}
void InteractiveWindow::show() {
if (QThread::currentThread() != thread()) {
QMetaObject::invokeMethod(this, "show");
return;
}
if (_qmlWindow) {
QMetaObject::invokeMethod(_qmlWindow, "show", Qt::DirectConnection);
}
}
void InteractiveWindow::raise() {
if (QThread::currentThread() != thread()) {
QMetaObject::invokeMethod(this, "raise");
return;
}
if (_qmlWindow) {
QMetaObject::invokeMethod(_qmlWindow, "raiseWindow", Qt::DirectConnection);
}
}
void InteractiveWindow::qmlToScript(const QVariant& message) {
if (message.canConvert<QJSValue>()) {
emit fromQml(qvariant_cast<QJSValue>(message).toVariant());
} else if (message.canConvert<QString>()) {
emit fromQml(message.toString());
} else {
qWarning() << "Unsupported message type " << message;
}
}
void InteractiveWindow::setVisible(bool visible) {
if (QThread::currentThread() != thread()) {
QMetaObject::invokeMethod(this, "setVisible", Q_ARG(bool, visible));
return;
}
if (!_qmlWindow.isNull()) {
_qmlWindow->setProperty(INTERACTIVE_WINDOW_VISIBLE_PROPERTY, visible);
}
}
bool InteractiveWindow::isVisible() const {
if (QThread::currentThread() != thread()) {
bool result = false;
BLOCKING_INVOKE_METHOD(const_cast<InteractiveWindow*>(this), "isVisible", Q_RETURN_ARG(bool, result));
return result;
}
// The tool window itself has special logic based on whether any tabs are enabled
if (_qmlWindow.isNull()) {
return false;
}
return _qmlWindow->property(INTERACTIVE_WINDOW_VISIBLE_PROPERTY).toBool();
}
glm::vec2 InteractiveWindow::getPosition() const {
if (QThread::currentThread() != thread()) {
vec2 result;
BLOCKING_INVOKE_METHOD(const_cast<InteractiveWindow*>(this), "getPosition", Q_RETURN_ARG(glm::vec2, result));
return result;
}
if (_qmlWindow.isNull()) {
return {};
}
return toGlm(_qmlWindow->property(INTERACTIVE_WINDOW_POSITION_PROPERTY).toPointF());
}
void InteractiveWindow::setPosition(const glm::vec2& position) {
if (QThread::currentThread() != thread()) {
QMetaObject::invokeMethod(this, "setPosition", Q_ARG(const glm::vec2&, position));
return;
}
if (!_qmlWindow.isNull()) {
_qmlWindow->setProperty(INTERACTIVE_WINDOW_POSITION_PROPERTY, QPointF(position.x, position.y));
}
}
glm::vec2 InteractiveWindow::getSize() const {
if (QThread::currentThread() != thread()) {
vec2 result;
BLOCKING_INVOKE_METHOD(const_cast<InteractiveWindow*>(this), "getSize", Q_RETURN_ARG(glm::vec2, result));
return result;
}
if (_qmlWindow.isNull()) {
return {};
}
return toGlm(_qmlWindow->property(INTERACTIVE_WINDOW_SIZE_PROPERTY).toSize());
}
void InteractiveWindow::setSize(const glm::vec2& size) {
if (QThread::currentThread() != thread()) {
QMetaObject::invokeMethod(this, "setSize", Q_ARG(const glm::vec2&, size));
return;
}
if (!_qmlWindow.isNull()) {
_qmlWindow->setProperty(INTERACTIVE_WINDOW_SIZE_PROPERTY, QSize(size.x, size.y));
}
}
QString InteractiveWindow::getMode() const {
if (QThread::currentThread() != thread()) {
QString result;
BLOCKING_INVOKE_METHOD(const_cast<InteractiveWindow*>(this), "getMode", Q_RETURN_ARG(QString, result));
return result;
}
if (_qmlWindow.isNull()) {
return QString();
}
return _qmlWindow->property(WINDOW_MODE_TEXT_PROPERTY).toString();
}

View file

@ -0,0 +1,181 @@
//
// InteractiveWindow.h
// libraries/ui/src
//
// Created by Thijs Wenker on 2018-06-25
// Copyright 2018 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
//
#pragma once
#ifndef hifi_InteractiveWindow_h
#define hifi_InteractiveWindow_h
#include <QtCore/QObject>
#include <QtCore/QPointer>
#include <QtScript/QScriptValue>
#include <QQmlEngine>
#include <GLMHelpers.h>
namespace InteractiveWindowEnums {
Q_NAMESPACE
enum InteractiveWindowFlags : uint8_t {
ForceNative = 1 << 0,
ForceVirtual = 1 << 1,
AlwaysOnTop = 1 << 2,
CloseButtonHides = 1 << 3
};
Q_ENUM_NS(InteractiveWindowFlags);
inline void declareQML() {
qmlRegisterUncreatableMetaObject(staticMetaObject, "InteractiveWindowFlags", 1, 0,
"InteractiveWindowFlags", "Error: enums only");
}
}
using namespace InteractiveWindowEnums;
class InteractiveWindow : public QObject {
Q_OBJECT
Q_PROPERTY(glm::vec2 position READ getPosition WRITE setPosition)
Q_PROPERTY(glm::vec2 size READ getSize WRITE setSize)
Q_PROPERTY(bool visible READ isVisible WRITE setVisible)
Q_PROPERTY(QString mode READ getMode)
public:
InteractiveWindow(const QString& sourceUrl, const QVariantMap& properties);
~InteractiveWindow();
private:
// define property getters and setters as private to not expose them to the JS API
Q_INVOKABLE glm::vec2 getPosition() const;
Q_INVOKABLE void setPosition(const glm::vec2& position);
Q_INVOKABLE glm::vec2 getSize() const;
Q_INVOKABLE void setSize(const glm::vec2& size);
Q_INVOKABLE void setVisible(bool visible);
Q_INVOKABLE bool isVisible() const;
Q_INVOKABLE QString getMode() const;
public slots:
/**jsdoc
* @function InteractiveWindow.sendToQml
* @param {object} message
*/
// Scripts can use this to send a message to the QML object
void sendToQml(const QVariant& message);
/**jsdoc
* @function InteractiveWindow.emitScriptEvent
* @param {object} message
*/
// QmlWindow content may include WebView requiring EventBridge.
void emitScriptEvent(const QVariant& scriptMessage);
/**jsdoc
* @function InteractiveWindow.emitWebEvent
* @param {object} message
*/
void emitWebEvent(const QVariant& webMessage);
/**jsdoc
* @function InteractiveWindow.close
*/
Q_INVOKABLE void close();
/**jsdoc
* @function InteractiveWindow.show
*/
Q_INVOKABLE void show();
/**jsdoc
* @function InteractiveWindow.raise
*/
Q_INVOKABLE void raise();
signals:
/**jsdoc
* @function InteractiveWindow.visibleChanged
* @returns {Signal}
*/
void visibleChanged();
/**jsdoc
* @function InteractiveWindow.positionChanged
* @returns {Signal}
*/
void positionChanged();
/**jsdoc
* @function InteractiveWindow.sizeChanged
* @returns {Signal}
*/
void sizeChanged();
/**jsdoc
* @function InteractiveWindow.modeChanged
* @returns {Signal}
*/
void modeChanged();
/**jsdoc
* @function InteractiveWindow.titleChanged
* @returns {Signal}
*/
void titleChanged();
/**jsdoc
* @function InteractiveWindow.fromQml
* @param {object} message
* @returns {Signal}
*/
// Scripts can connect to this signal to receive messages from the QML object
void fromQml(const QVariant& message);
/**jsdoc
* @function InteractiveWindow.scriptEventReceived
* @param {object} message
* @returns {Signal}
*/
// InteractiveWindow content may include WebView requiring EventBridge.
void scriptEventReceived(const QVariant& message);
/**jsdoc
* @function InteractiveWindow.webEventReceived
* @param {object} message
* @returns {Signal}
*/
void webEventReceived(const QVariant& message);
protected slots:
/**jsdoc
* @function InteractiveWindow.qmlToScript
* @param {object} message
* @returns {Signal}
*/
void qmlToScript(const QVariant& message);
private:
QPointer<QObject> _qmlWindow;
};
typedef InteractiveWindow* InteractiveWindowPointer;
QScriptValue interactiveWindowPointerToScriptValue(QScriptEngine* engine, const InteractiveWindowPointer& in);
void interactiveWindowPointerFromScriptValue(const QScriptValue& object, InteractiveWindowPointer& out);
void registerInteractiveWindowMetaType(QScriptEngine* engine);
Q_DECLARE_METATYPE(InteractiveWindowPointer)
#endif // hifi_InteractiveWindow_h