diff --git a/examples/html/eventBridgeLoader.js b/examples/html/eventBridgeLoader.js
index ebfb6dc740..de6553ee1c 100644
--- a/examples/html/eventBridgeLoader.js
+++ b/examples/html/eventBridgeLoader.js
@@ -10,50 +10,11 @@
var EventBridge;
-EventBridgeConnectionProxy = function(parent) {
- this.parent = parent;
- this.realSignal = this.parent.realBridge.scriptEventReceived
- this.webWindowId = this.parent.webWindow.windowId;
-}
-
-EventBridgeConnectionProxy.prototype.connect = function(callback) {
- var that = this;
- this.realSignal.connect(function(id, message) {
- if (id === that.webWindowId) { callback(message); }
+openEventBridge = function(callback) {
+ new QWebChannel(qt.webChannelTransport, function(channel) {
+ console.log("uid " + EventBridgeUid);
+ EventBridge = channel.objects[EventBridgeUid];
+ callback(EventBridge);
});
}
-EventBridgeProxy = function(webWindow) {
- this.webWindow = webWindow;
- this.realBridge = this.webWindow.eventBridge;
- this.scriptEventReceived = new EventBridgeConnectionProxy(this);
-}
-
-EventBridgeProxy.prototype.emitWebEvent = function(data) {
- this.realBridge.emitWebEvent(data);
-}
-
-openEventBridge = function(callback) {
- EVENT_BRIDGE_URI = "ws://localhost:51016";
- socket = new WebSocket(this.EVENT_BRIDGE_URI);
-
- socket.onclose = function() {
- console.error("web channel closed");
- };
-
- socket.onerror = function(error) {
- console.error("web channel error: " + error);
- };
-
- socket.onopen = function() {
- channel = new QWebChannel(socket, function(channel) {
- console.log("Document url is " + document.URL);
- var webWindow = channel.objects[document.URL.toLowerCase()];
- console.log("WebWindow is " + webWindow)
- eventBridgeProxy = new EventBridgeProxy(webWindow);
- EventBridge = eventBridgeProxy;
- if (callback) { callback(eventBridgeProxy); }
- });
- }
-}
-
diff --git a/examples/html/qmlWebTest.html b/examples/html/qmlWebTest.html
index e59535701d..553ce83417 100644
--- a/examples/html/qmlWebTest.html
+++ b/examples/html/qmlWebTest.html
@@ -4,21 +4,17 @@
-
diff --git a/examples/tests/qmlWebTest.js b/examples/tests/qmlWebTest.js
index 5faa68668d..d29f2ba002 100644
--- a/examples/tests/qmlWebTest.js
+++ b/examples/tests/qmlWebTest.js
@@ -8,26 +8,14 @@ webWindow.eventBridge.webEventReceived.connect(function(data) {
print("JS Side event received: " + data);
});
-var titles = ["A", "B", "C"];
-var titleIndex = 0;
-
Script.setInterval(function() {
- webWindow.eventBridge.emitScriptEvent("JS Event sent");
- var size = webWindow.size;
- var position = webWindow.position;
- print("Window url: " + webWindow.url)
- print("Window visible: " + webWindow.visible)
- print("Window size: " + size.x + "x" + size.y)
- print("Window pos: " + position.x + "x" + position.y)
- webWindow.setVisible(!webWindow.visible);
- webWindow.setTitle(titles[titleIndex]);
- webWindow.setSize(320 + Math.random() * 100, 240 + Math.random() * 100);
- titleIndex += 1;
- titleIndex %= titles.length;
-}, 2 * 1000);
+ var message = [ Math.random(), Math.random() ];
+ print("JS Side sending: " + message);
+ webWindow.emitScriptEvent(message);
+}, 5 * 1000);
-Script.setTimeout(function() {
- print("Closing script");
+Script.scriptEnding.connect(function(){
webWindow.close();
- Script.stop();
-}, 15 * 1000)
+ webWindow.deleteLater();
+});
+
diff --git a/interface/resources/qml/QmlWebWindow.qml b/interface/resources/qml/QmlWebWindow.qml
index fd4e629568..0058770462 100644
--- a/interface/resources/qml/QmlWebWindow.qml
+++ b/interface/resources/qml/QmlWebWindow.qml
@@ -1,6 +1,7 @@
import QtQuick 2.3
import QtQuick.Controls 1.2
import QtWebEngine 1.1
+import QtWebChannel 1.0
import "windows" as Windows
import "controls" as Controls
@@ -15,11 +16,22 @@ Windows.Window {
// Don't destroy on close... otherwise the JS/C++ will have a dangling pointer
destroyOnCloseButton: false
property alias source: webview.url
+ property alias webChannel: webview.webChannel
+ // A unique identifier to let the HTML JS find the event bridge
+ // object (our C++ wrapper)
+ property string uid;
+
+ // This is for JS/QML communication, which is unused in a WebWindow,
+ // but not having this here results in spurious warnings about a
+ // missing signal
+ signal sendToScript(var message);
Controls.WebView {
id: webview
url: "about:blank"
anchors.fill: parent
focus: true
+ onUrlChanged: webview.runJavaScript("EventBridgeUid = \"" + uid + "\";");
+ Component.onCompleted: webview.runJavaScript("EventBridgeUid = \"" + uid + "\";");
}
} // dialog
diff --git a/interface/resources/qml/ToolWindow.qml b/interface/resources/qml/ToolWindow.qml
index 75aa50aa34..5313ca23e9 100644
--- a/interface/resources/qml/ToolWindow.qml
+++ b/interface/resources/qml/ToolWindow.qml
@@ -37,14 +37,33 @@ Windows.Window {
Repeater {
model: 4
Tab {
+ // Force loading of the content even if the tab is not visible
+ // (required for letting the C++ code access the webview)
active: true
- enabled: false;
- // we need to store the original url here for future identification
+ enabled: false
property string originalUrl: "";
- onEnabledChanged: toolWindow.updateVisiblity();
+
Controls.WebView {
id: webView;
+ // we need to store the original url here for future identification
+ // A unique identifier to let the HTML JS find the event bridge
+ // object (our C++ wrapper)
+ property string uid;
anchors.fill: parent
+ enabled: false
+
+ // This is for JS/QML communication, which is unused in a WebWindow,
+ // but not having this here results in spurious warnings about a
+ // missing signal
+ signal sendToScript(var message);
+
+ onUrlChanged: webView.runJavaScript("EventBridgeUid = \"" + uid + "\";");
+ onEnabledChanged: toolWindow.updateVisiblity();
+ onLoadingChanged: {
+ if (loadRequest.status == WebEngineView.LoadSucceededStatus) {
+ webView.runJavaScript("EventBridgeUid = \"" + uid + "\";");
+ }
+ }
}
}
}
@@ -113,20 +132,23 @@ Windows.Window {
var tab = tabView.getTab(index);
tab.title = "";
- tab.originalUrl = "";
tab.enabled = false;
+ tab.originalUrl = "";
+ tab.item.url = "about:blank";
+ tab.item.enabled = false;
}
function addWebTab(properties) {
if (!properties.source) {
- console.warn("Attempted to open Web Tool Pane without URL")
+ console.warn("Attempted to open Web Tool Pane without URL");
return;
}
var existingTabIndex = findIndexForUrl(properties.source);
if (existingTabIndex >= 0) {
- console.log("Existing tab " + existingTabIndex + " found with URL " + properties.source)
- return tabView.getTab(existingTabIndex);
+ console.log("Existing tab " + existingTabIndex + " found with URL " + properties.source);
+ var tab = tabView.getTab(existingTabIndex);
+ return tab.item;
}
var freeTabIndex = findFreeTab();
@@ -135,25 +157,22 @@ Windows.Window {
return;
}
- var newTab = tabView.getTab(freeTabIndex);
- newTab.title = properties.title || "Unknown";
- newTab.originalUrl = properties.source;
- newTab.item.url = properties.source;
- newTab.active = true;
-
if (properties.width) {
- tabView.width = Math.min(Math.max(tabView.width, properties.width),
- toolWindow.maxSize.x);
+ tabView.width = Math.min(Math.max(tabView.width, properties.width), toolWindow.maxSize.x);
}
if (properties.height) {
- tabView.height = Math.min(Math.max(tabView.height, properties.height),
- toolWindow.maxSize.y);
+ tabView.height = Math.min(Math.max(tabView.height, properties.height), toolWindow.maxSize.y);
}
- console.log("Updating visibility based on child tab added");
- newTab.enabledChanged.connect(updateVisiblity)
- updateVisiblity();
- return newTab
+ var tab = tabView.getTab(freeTabIndex);
+ tab.title = properties.title || "Unknown";
+ tab.enabled = true;
+ tab.originalUrl = properties.source;
+
+ var result = tab.item;
+ result.enabled = true;
+ result.url = properties.source;
+ return result;
}
}
diff --git a/interface/resources/qml/controls/WebView.qml b/interface/resources/qml/controls/WebView.qml
index 18080cd448..1361e6e322 100644
--- a/interface/resources/qml/controls/WebView.qml
+++ b/interface/resources/qml/controls/WebView.qml
@@ -59,6 +59,7 @@ WebEngineView {
request.openIn(newWindow.webView)
}
-
- profile: desktop.browserProfile
+ // This breaks the webchannel used for passing messages. Fixed in Qt 5.6
+ // See https://bugreports.qt.io/browse/QTBUG-49521
+ //profile: desktop.browserProfile
}
diff --git a/libraries/ui/src/QmlWebWindowClass.cpp b/libraries/ui/src/QmlWebWindowClass.cpp
index f12fb51b19..43fd5a64df 100644
--- a/libraries/ui/src/QmlWebWindowClass.cpp
+++ b/libraries/ui/src/QmlWebWindowClass.cpp
@@ -14,6 +14,8 @@
#include
+#include
+
#include
#include
@@ -31,19 +33,39 @@ static const char* const URL_PROPERTY = "source";
// Method called by Qt scripts to create a new web window in the overlay
QScriptValue QmlWebWindowClass::constructor(QScriptContext* context, QScriptEngine* engine) {
return QmlWindowClass::internalConstructor("QmlWebWindow.qml", context, engine,
- [&](QObject* object) { return new QmlWebWindowClass(object); });
+ [&](QObject* object) { return new QmlWebWindowClass(object); });
}
QmlWebWindowClass::QmlWebWindowClass(QObject* qmlWindow) : QmlWindowClass(qmlWindow) {
+ _uid = QUuid::createUuid().toString();
+ asQuickItem()->setProperty("uid", _uid);
+ auto webchannelVar = qmlWindow->property("webChannel");
+ _webchannel = qvariant_cast(webchannelVar);
+ Q_ASSERT(_webchannel);
+ _webchannel->registerObject(_uid, this);
}
+void QmlWebWindowClass::emitScriptEvent(const QVariant& scriptMessage) {
+ if (QThread::currentThread() != thread()) {
+ QMetaObject::invokeMethod(this, "emitScriptEvent", Qt::QueuedConnection, Q_ARG(QVariant, scriptMessage));
+ } else {
+ emit scriptEventReceived(scriptMessage);
+ }
+}
-// FIXME remove.
-void QmlWebWindowClass::handleNavigation(const QString& url) {
+void QmlWebWindowClass::emitWebEvent(const QVariant& webMessage) {
+ if (QThread::currentThread() != thread()) {
+ QMetaObject::invokeMethod(this, "emitWebEvent", Qt::QueuedConnection, Q_ARG(QVariant, webMessage));
+ } else {
+ emit webEventReceived(webMessage);
+ }
}
QString QmlWebWindowClass::getURL() const {
QVariant result = DependencyManager::get()->returnFromUiThread([&]()->QVariant {
+ if (_qmlWindow.isNull()) {
+ return QVariant();
+ }
return _qmlWindow->property(URL_PROPERTY);
});
return result.toString();
@@ -54,6 +76,8 @@ extern QString fixupHifiUrl(const QString& urlString);
void QmlWebWindowClass::setURL(const QString& urlString) {
DependencyManager::get()->executeOnUiThread([=] {
- _qmlWindow->setProperty(URL_PROPERTY, fixupHifiUrl(urlString));
+ if (!_qmlWindow.isNull()) {
+ _qmlWindow->setProperty(URL_PROPERTY, fixupHifiUrl(urlString));
+ }
});
}
diff --git a/libraries/ui/src/QmlWebWindowClass.h b/libraries/ui/src/QmlWebWindowClass.h
index 14e533c7b4..35322ef0ea 100644
--- a/libraries/ui/src/QmlWebWindowClass.h
+++ b/libraries/ui/src/QmlWebWindowClass.h
@@ -11,10 +11,13 @@
#include "QmlWindowClass.h"
+class QWebChannel;
+
// FIXME refactor this class to be a QQuickItem derived type and eliminate the needless wrapping
class QmlWebWindowClass : public QmlWindowClass {
Q_OBJECT
Q_PROPERTY(QString url READ getURL CONSTANT)
+ Q_PROPERTY(QString uid READ getUid CONSTANT)
public:
static QScriptValue constructor(QScriptContext* context, QScriptEngine* engine);
@@ -23,12 +26,18 @@ public:
public slots:
QString getURL() const;
void setURL(const QString& url);
+ const QString& getUid() const { return _uid; }
+ void emitScriptEvent(const QVariant& scriptMessage);
+ void emitWebEvent(const QVariant& webMessage);
signals:
void urlChanged();
+ void scriptEventReceived(const QVariant& message);
+ void webEventReceived(const QVariant& message);
-private slots:
- void handleNavigation(const QString& url);
+private:
+ QString _uid;
+ QWebChannel* _webchannel { nullptr };
};
#endif
diff --git a/libraries/ui/src/QmlWindowClass.cpp b/libraries/ui/src/QmlWindowClass.cpp
index 679e86f4ae..37d461acd0 100644
--- a/libraries/ui/src/QmlWindowClass.cpp
+++ b/libraries/ui/src/QmlWindowClass.cpp
@@ -26,10 +26,6 @@
#include "OffscreenUi.h"
-QWebSocketServer* QmlWindowClass::_webChannelServer { nullptr };
-static QWebChannel webChannel;
-static const uint16_t WEB_CHANNEL_PORT = 51016;
-static std::atomic nextWindowId;
static const char* const SOURCE_PROPERTY = "source";
static const char* const TITLE_PROPERTY = "title";
static const char* const WIDTH_PROPERTY = "width";
@@ -37,54 +33,6 @@ static const char* const HEIGHT_PROPERTY = "height";
static const char* const VISIBILE_PROPERTY = "visible";
static const char* const TOOLWINDOW_PROPERTY = "toolWindow";
-void QmlScriptEventBridge::emitWebEvent(const QString& data) {
- QMetaObject::invokeMethod(this, "webEventReceived", Qt::QueuedConnection, Q_ARG(QString, data));
-}
-
-void QmlScriptEventBridge::emitScriptEvent(const QString& data) {
- QMetaObject::invokeMethod(this, "scriptEventReceived", Qt::QueuedConnection,
- Q_ARG(int, _webWindow->getWindowId()), Q_ARG(QString, data));
-}
-
-class QmlWebTransport : public QWebChannelAbstractTransport {
- Q_OBJECT
-public:
- QmlWebTransport(QWebSocket* webSocket) : _webSocket(webSocket) {
- // Translate from the websocket layer to the webchannel layer
- connect(webSocket, &QWebSocket::textMessageReceived, [this](const QString& message) {
- QJsonParseError error;
- QJsonDocument document = QJsonDocument::fromJson(message.toUtf8(), &error);
- if (error.error || !document.isObject()) {
- qWarning() << "Unable to parse incoming JSON message" << message;
- return;
- }
- emit messageReceived(document.object(), this);
- });
- }
-
- virtual void sendMessage(const QJsonObject &message) override {
- // Translate from the webchannel layer to the websocket layer
- _webSocket->sendTextMessage(QJsonDocument(message).toJson(QJsonDocument::Compact));
- }
-
-private:
- QWebSocket* const _webSocket;
-};
-
-
-void QmlWindowClass::setupServer() {
- if (!_webChannelServer) {
- _webChannelServer = new QWebSocketServer("EventBridge Server", QWebSocketServer::NonSecureMode);
- if (!_webChannelServer->listen(QHostAddress::LocalHost, WEB_CHANNEL_PORT)) {
- qFatal("Failed to open web socket server.");
- }
-
- QObject::connect(_webChannelServer, &QWebSocketServer::newConnection, [] {
- webChannel.connectTo(new QmlWebTransport(_webChannelServer->nextPendingConnection()));
- });
- }
-}
-
QScriptValue QmlWindowClass::internalConstructor(const QString& qmlSource,
QScriptContext* context, QScriptEngine* engine,
std::function builder)
@@ -168,10 +116,8 @@ QScriptValue QmlWindowClass::internalConstructor(const QString& qmlSource,
}
offscreenUi->returnFromUiThread([&] {
- setupServer();
retVal = builder(newTab);
retVal->_toolWindow = true;
- registerObject(url.toLower(), retVal);
return QVariant();
});
} else {
@@ -179,10 +125,8 @@ QScriptValue QmlWindowClass::internalConstructor(const QString& qmlSource,
QMetaObject::invokeMethod(offscreenUi.data(), "load", Qt::BlockingQueuedConnection,
Q_ARG(const QString&, qmlSource),
Q_ARG(std::function, [&](QQmlContext* context, QObject* object) {
- setupServer();
retVal = builder(object);
context->engine()->setObjectOwnership(retVal->_qmlWindow, QQmlEngine::CppOwnership);
- registerObject(url.toLower(), retVal);
if (!title.isEmpty()) {
retVal->setTitle(title);
}
@@ -209,12 +153,9 @@ QScriptValue QmlWindowClass::constructor(QScriptContext* context, QScriptEngine*
});
}
-QmlWindowClass::QmlWindowClass(QObject* qmlWindow)
- : _windowId(++nextWindowId), _qmlWindow(qmlWindow)
-{
- qDebug() << "Created window with ID " << _windowId;
+QmlWindowClass::QmlWindowClass(QObject* qmlWindow) : _qmlWindow(qmlWindow) {
Q_ASSERT(_qmlWindow);
- Q_ASSERT(dynamic_cast(_qmlWindow));
+ Q_ASSERT(dynamic_cast(_qmlWindow.data()));
// Forward messages received from QML on to the script
connect(_qmlWindow, SIGNAL(sendToScript(QVariant)), this, SIGNAL(fromQml(const QVariant&)), Qt::QueuedConnection);
}
@@ -228,19 +169,11 @@ QmlWindowClass::~QmlWindowClass() {
close();
}
-void QmlWindowClass::registerObject(const QString& name, QObject* object) {
- webChannel.registerObject(name, object);
-}
-
-void QmlWindowClass::deregisterObject(QObject* object) {
- webChannel.deregisterObject(object);
-}
-
QQuickItem* QmlWindowClass::asQuickItem() const {
if (_toolWindow) {
return DependencyManager::get()->getToolWindow();
}
- return dynamic_cast(_qmlWindow);
+ return _qmlWindow.isNull() ? nullptr : dynamic_cast(_qmlWindow.data());
}
void QmlWindowClass::setVisible(bool visible) {
@@ -260,32 +193,34 @@ void QmlWindowClass::setVisible(bool visible) {
bool QmlWindowClass::isVisible() const {
// The tool window itself has special logic based on whether any tabs are enabled
- if (_toolWindow) {
- auto targetTab = dynamic_cast(_qmlWindow);
- return DependencyManager::get()->returnFromUiThread([&] {
- return QVariant::fromValue(targetTab->isEnabled());
- }).toBool();
- } else {
- QQuickItem* targetWindow = asQuickItem();
- return DependencyManager::get()->returnFromUiThread([&] {
- return QVariant::fromValue(targetWindow->isVisible());
- }).toBool();
- }
+ return DependencyManager::get()->returnFromUiThread([&] {
+ if (_qmlWindow.isNull()) {
+ return QVariant::fromValue(false);
+ }
+ if (_toolWindow) {
+ return QVariant::fromValue(dynamic_cast(_qmlWindow.data())->isEnabled());
+ } else {
+ return QVariant::fromValue(asQuickItem()->isVisible());
+ }
+ }).toBool();
}
glm::vec2 QmlWindowClass::getPosition() const {
- QQuickItem* targetWindow = asQuickItem();
QVariant result = DependencyManager::get()->returnFromUiThread([&]()->QVariant {
- return targetWindow->position();
+ if (_qmlWindow.isNull()) {
+ return QVariant(QPointF(0, 0));
+ }
+ return asQuickItem()->position();
});
return toGlm(result.toPointF());
}
void QmlWindowClass::setPosition(const glm::vec2& position) {
- QQuickItem* targetWindow = asQuickItem();
DependencyManager::get()->executeOnUiThread([=] {
- targetWindow->setPosition(QPointF(position.x, position.y));
+ if (!_qmlWindow.isNull()) {
+ asQuickItem()->setPosition(QPointF(position.x, position.y));
+ }
});
}
@@ -299,17 +234,21 @@ glm::vec2 toGlm(const QSizeF& size) {
}
glm::vec2 QmlWindowClass::getSize() const {
- QQuickItem* targetWindow = asQuickItem();
QVariant result = DependencyManager::get()->returnFromUiThread([&]()->QVariant {
+ if (_qmlWindow.isNull()) {
+ return QVariant(QSizeF(0, 0));
+ }
+ QQuickItem* targetWindow = asQuickItem();
return QSizeF(targetWindow->width(), targetWindow->height());
});
return toGlm(result.toSizeF());
}
void QmlWindowClass::setSize(const glm::vec2& size) {
- QQuickItem* targetWindow = asQuickItem();
DependencyManager::get()->executeOnUiThread([=] {
- targetWindow->setSize(QSizeF(size.x, size.y));
+ if (!_qmlWindow.isNull()) {
+ asQuickItem()->setSize(QSizeF(size.x, size.y));
+ }
});
}
@@ -318,9 +257,10 @@ void QmlWindowClass::setSize(int width, int height) {
}
void QmlWindowClass::setTitle(const QString& title) {
- QQuickItem* targetWindow = asQuickItem();
DependencyManager::get()->executeOnUiThread([=] {
- targetWindow->setProperty(TITLE_PROPERTY, title);
+ if (!_qmlWindow.isNull()) {
+ asQuickItem()->setProperty(TITLE_PROPERTY, title);
+ }
});
}
@@ -345,7 +285,12 @@ void QmlWindowClass::hasClosed() {
}
void QmlWindowClass::raise() {
- QMetaObject::invokeMethod(asQuickItem(), "raise", Qt::QueuedConnection);
+ auto offscreenUi = DependencyManager::get();
+ offscreenUi->executeOnUiThread([=] {
+ if (!_qmlWindow.isNull()) {
+ QMetaObject::invokeMethod(asQuickItem(), "raise", Qt::DirectConnection);
+ }
+ });
}
#include "QmlWindowClass.moc"
diff --git a/libraries/ui/src/QmlWindowClass.h b/libraries/ui/src/QmlWindowClass.h
index 26152b1f24..eda6ce674c 100644
--- a/libraries/ui/src/QmlWindowClass.h
+++ b/libraries/ui/src/QmlWindowClass.h
@@ -10,42 +10,21 @@
#define hifi_ui_QmlWindowClass_h
#include
-#include
+#include
#include
#include
-#include
+
+#include
class QScriptEngine;
class QScriptContext;
-class QmlWindowClass;
-class QWebSocketServer;
-class QWebSocket;
-
-class QmlScriptEventBridge : public QObject {
- Q_OBJECT
-public:
- QmlScriptEventBridge(const QmlWindowClass* webWindow) : _webWindow(webWindow) {}
-
-public slots :
- void emitWebEvent(const QString& data);
- void emitScriptEvent(const QString& data);
-
-signals:
- void webEventReceived(const QString& data);
- void scriptEventReceived(int windowId, const QString& data);
-
-private:
- const QmlWindowClass* _webWindow { nullptr };
- QWebSocket *_socket { nullptr };
-};
// FIXME refactor this class to be a QQuickItem derived type and eliminate the needless wrapping
class QmlWindowClass : public QObject {
Q_OBJECT
Q_PROPERTY(QObject* eventBridge READ getEventBridge CONSTANT)
- Q_PROPERTY(int windowId READ getWindowId CONSTANT)
- Q_PROPERTY(glm::vec2 position READ getPosition WRITE setPosition)
- Q_PROPERTY(glm::vec2 size READ getSize WRITE setSize)
+ Q_PROPERTY(glm::vec2 position READ getPosition WRITE setPosition NOTIFY positionChanged)
+ Q_PROPERTY(glm::vec2 size READ getSize WRITE setSize NOTIFY sizeChanged)
Q_PROPERTY(bool visible READ isVisible WRITE setVisible NOTIFY visibilityChanged)
public:
@@ -64,21 +43,19 @@ public slots:
glm::vec2 getSize() const;
void setSize(const glm::vec2& size);
void setSize(int width, int height);
-
void setTitle(const QString& title);
-
- // Ugh.... do not want to do
Q_INVOKABLE void raise();
Q_INVOKABLE void close();
- Q_INVOKABLE int getWindowId() const { return _windowId; };
- Q_INVOKABLE QmlScriptEventBridge* getEventBridge() const { return _eventBridge; };
+ Q_INVOKABLE QObject* getEventBridge() { return this; };
// Scripts can use this to send a message to the QML object
void sendToQml(const QVariant& message);
signals:
void visibilityChanged(bool visible); // Tool window
+ void positionChanged();
+ void sizeChanged();
void moved(glm::vec2 position);
void resized(QSizeF size);
void closed();
@@ -92,19 +69,13 @@ protected:
static QScriptValue internalConstructor(const QString& qmlSource,
QScriptContext* context, QScriptEngine* engine,
std::function function);
- static void setupServer();
- static void registerObject(const QString& name, QObject* object);
- static void deregisterObject(QObject* object);
- static QWebSocketServer* _webChannelServer;
QQuickItem* asQuickItem() const;
- QmlScriptEventBridge* const _eventBridge { new QmlScriptEventBridge(this) };
// FIXME needs to be initialized in the ctor once we have support
// for tool window panes in QML
bool _toolWindow { false };
- const int _windowId;
- QObject* _qmlWindow;
+ QPointer _qmlWindow;
QString _source;
};