From 7c024b4e8aa3e49fa1d78c6152fdc2dfb57764e6 Mon Sep 17 00:00:00 2001 From: dante ruiz <dante@highfidelity.io> Date: Thu, 13 Jun 2019 11:37:42 -0700 Subject: [PATCH 1/4] fix interactive window crash --- .../scripting/DesktopScriptingInterface.cpp | 19 ++- .../src/scripting/DesktopScriptingInterface.h | 2 + interface/src/ui/InteractiveWindow.cpp | 114 ++++-------------- 3 files changed, 45 insertions(+), 90 deletions(-) diff --git a/interface/src/scripting/DesktopScriptingInterface.cpp b/interface/src/scripting/DesktopScriptingInterface.cpp index ef5bd7abb9..678e698033 100644 --- a/interface/src/scripting/DesktopScriptingInterface.cpp +++ b/interface/src/scripting/DesktopScriptingInterface.cpp @@ -111,10 +111,11 @@ void DesktopScriptingInterface::show(const QString& path, const QString& title) InteractiveWindowPointer DesktopScriptingInterface::createWindow(const QString& sourceUrl, const QVariantMap& properties) { if (QThread::currentThread() != thread()) { InteractiveWindowPointer interactiveWindow = nullptr; - BLOCKING_INVOKE_METHOD(this, "createWindow", + BLOCKING_INVOKE_METHOD(this, "createWindowOnThread", Q_RETURN_ARG(InteractiveWindowPointer, interactiveWindow), Q_ARG(QString, sourceUrl), - Q_ARG(QVariantMap, properties)); + Q_ARG(QVariantMap, properties), + Q_ARG(QThread*, QThread::currentThread())); return interactiveWindow; } @@ -129,3 +130,17 @@ InteractiveWindowPointer DesktopScriptingInterface::createWindow(const QString& return new InteractiveWindow(sourceUrl, properties); } + +InteractiveWindowPointer DesktopScriptingInterface::createWindowOnThread(const QString& sourceUrl, const QVariantMap& properties, QThread* targetThread) { + + // The offscreen surface already validates against non-local QML sources, but we also need to ensure that + // if we create top level QML, like dock widgets or other types of QQuickView containing desktop windows + // that the source URL is permitted + const auto& urlValidator = OffscreenQmlSurface::getUrlValidator(); + if (!urlValidator(sourceUrl)) { + return nullptr; + } + InteractiveWindowPointer window = new InteractiveWindow(sourceUrl, properties); + window->moveToThread(targetThread); + return window; +} diff --git a/interface/src/scripting/DesktopScriptingInterface.h b/interface/src/scripting/DesktopScriptingInterface.h index b4ff159176..525fd7c803 100644 --- a/interface/src/scripting/DesktopScriptingInterface.h +++ b/interface/src/scripting/DesktopScriptingInterface.h @@ -101,6 +101,8 @@ private: static int flagAlwaysOnTop() { return AlwaysOnTop; } static int flagCloseButtonHides() { return CloseButtonHides; } + Q_INVOKABLE InteractiveWindowPointer createWindowOnThread(const QString& sourceUrl, const QVariantMap& properties, QThread* targetThread); + static QVariantMap getDockArea(); Q_INVOKABLE static QVariantMap getPresentationMode(); diff --git a/interface/src/ui/InteractiveWindow.cpp b/interface/src/ui/InteractiveWindow.cpp index dfef16b536..c85d7bc301 100644 --- a/interface/src/ui/InteractiveWindow.cpp +++ b/interface/src/ui/InteractiveWindow.cpp @@ -85,13 +85,13 @@ void InteractiveWindow::forwardKeyReleaseEvent(int key, int modifiers) { * @property {string} [title="InteractiveWindow] - The title of the window. * @property {Vec2} [position] - The initial position of the window, in pixels. * @property {Vec2} [size] - The initial size of the window, in pixels - * @property {boolean} [visible=true] - <code>true</code> to make the window visible when created, <code>false</code> to make + * @property {boolean} [visible=true] - <code>true</code> to make the window visible when created, <code>false</code> to make * it invisible. - * @property {InteractiveWindow.PresentationMode} [presentationMode=Desktop.PresentationMode.VIRTUAL] - - * <code>Desktop.PresentationMode.VIRTUAL</code> to display the window inside Interface, <code>.NATIVE</code> to display it + * @property {InteractiveWindow.PresentationMode} [presentationMode=Desktop.PresentationMode.VIRTUAL] - + * <code>Desktop.PresentationMode.VIRTUAL</code> to display the window inside Interface, <code>.NATIVE</code> to display it * as its own separate window. - * @property {InteractiveWindow.PresentationWindowInfo} [presentationWindowInfo] - Controls how a <code>NATIVE</code> window is - * displayed. If used, the window is docked to the specified edge of the Interface window, otherwise the window is + * @property {InteractiveWindow.PresentationWindowInfo} [presentationWindowInfo] - Controls how a <code>NATIVE</code> window is + * displayed. If used, the window is docked to the specified edge of the Interface window, otherwise the window is * displayed as its own separate window. * @property {InteractiveWindow.AdditionalFlags} [additionalFlags=0] - Window behavior flags in addition to "native window flags" (minimize/maximize/close), * set at window creation. Possible flag values are provided as {@link Desktop|Desktop.ALWAYS_ON_TOP} and {@link Desktop|Desktop.CLOSE_BUTTON_HIDES}. @@ -124,7 +124,7 @@ InteractiveWindow::InteractiveWindow(const QString& sourceUrl, const QVariantMap auto mainWindow = qApp->getWindow(); _dockWidget = std::shared_ptr<DockWidget>(new DockWidget(title, mainWindow), dockWidgetDeleter); auto quickView = _dockWidget->getQuickView(); - + Application::setupQmlSurface(quickView->rootContext() , true); //add any whitelisted callbacks @@ -176,7 +176,6 @@ InteractiveWindow::InteractiveWindow(const QString& sourceUrl, const QVariantMap }); _dockWidget->setSource(QUrl(sourceUrl)); - mainWindow->addDockWidget(dockArea, _dockWidget.get()); } else { auto offscreenUi = DependencyManager::get<OffscreenUi>(); @@ -254,55 +253,35 @@ void InteractiveWindow::sendToQml(const 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); - } + 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); - } + emit webEventReceived(webMessage); } void InteractiveWindow::close() { - if (QThread::currentThread() != thread()) { - QMetaObject::invokeMethod(this, "close"); - return; - } - if (_qmlWindow) { _qmlWindow->deleteLater(); } - qApp->getWindow()->removeDockWidget(_dockWidget.get()); + if (_dockWidget) { + auto window = qApp->getWindow(); + BLOCKING_INVOKE_METHOD(window, "removeDockWidget", Q_ARG(QDockWidget*, _dockWidget.get())); + } _dockWidget = nullptr; _qmlWindow = nullptr; } void InteractiveWindow::show() { - if (QThread::currentThread() != thread()) { - QMetaObject::invokeMethod(this, "show"); - return; - } - if (_qmlWindow) { - QMetaObject::invokeMethod(_qmlWindow, "show", Qt::DirectConnection); + QMetaObject::invokeMethod(_qmlWindow, "show"); } } void InteractiveWindow::raise() { - if (QThread::currentThread() != thread()) { - QMetaObject::invokeMethod(this, "raise"); - return; - } - if (_qmlWindow) { - QMetaObject::invokeMethod(_qmlWindow, "raiseWindow", Qt::DirectConnection); + QMetaObject::invokeMethod(_qmlWindow, "raiseWindow"); } } @@ -323,17 +302,12 @@ void InteractiveWindow::setVisible(bool visible) { } if (!_qmlWindow.isNull()) { - _qmlWindow->setProperty(INTERACTIVE_WINDOW_VISIBLE_PROPERTY, visible); + QMetaObject::invokeMethod(_qmlWindow, "setProperty", Q_ARG(const char*, INTERACTIVE_WINDOW_VISIBLE_PROPERTY), + Q_ARG(bool, 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; - } - if (_qmlWindow.isNull()) { return false; } @@ -342,12 +316,6 @@ bool InteractiveWindow::isVisible() const { } glm::vec2 InteractiveWindow::getPosition() const { - if (QThread::currentThread() != thread()) { - glm::vec2 result; - BLOCKING_INVOKE_METHOD(const_cast<InteractiveWindow*>(this), "getPosition", Q_RETURN_ARG(glm::vec2, result)); - return result; - } - if (_qmlWindow.isNull()) { return {}; } @@ -362,18 +330,13 @@ void InteractiveWindow::setPosition(const glm::vec2& position) { } if (!_qmlWindow.isNull()) { - _qmlWindow->setProperty(INTERACTIVE_WINDOW_POSITION_PROPERTY, QPointF(position.x, position.y)); - QMetaObject::invokeMethod(_qmlWindow, "updateInteractiveWindowPositionForMode", Qt::DirectConnection); + QMetaObject::invokeMethod(_qmlWindow, "setProperty", Q_ARG(const char*, INTERACTIVE_WINDOW_POSITION_PROPERTY), + Q_ARG(QPointF, QPointF(position.x, position.y))); + QMetaObject::invokeMethod(_qmlWindow, "updateInteractiveWindowPositionForMode"); } } glm::vec2 InteractiveWindow::getSize() const { - if (QThread::currentThread() != thread()) { - glm::vec2 result; - BLOCKING_INVOKE_METHOD(const_cast<InteractiveWindow*>(this), "getSize", Q_RETURN_ARG(glm::vec2, result)); - return result; - } - if (_qmlWindow.isNull()) { return {}; } @@ -381,24 +344,14 @@ glm::vec2 InteractiveWindow::getSize() const { } 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)); - QMetaObject::invokeMethod(_qmlWindow, "updateInteractiveWindowSizeForMode", Qt::DirectConnection); + QMetaObject::invokeMethod(_qmlWindow, "setProperty", Q_ARG(const char*, INTERACTIVE_WINDOW_SIZE_PROPERTY), + Q_ARG(QSize, QSize(size.x, size.y))); + QMetaObject::invokeMethod(_qmlWindow, "updateInteractiveWindowSizeForMode"); } } QString InteractiveWindow::getTitle() const { - if (QThread::currentThread() != thread()) { - QString result; - BLOCKING_INVOKE_METHOD(const_cast<InteractiveWindow*>(this), "getTitle", Q_RETURN_ARG(QString, result)); - return result; - } - if (_qmlWindow.isNull()) { return QString(); } @@ -406,24 +359,13 @@ QString InteractiveWindow::getTitle() const { } void InteractiveWindow::setTitle(const QString& title) { - if (QThread::currentThread() != thread()) { - QMetaObject::invokeMethod(this, "setTitle", Q_ARG(const QString&, title)); - return; - } - if (!_qmlWindow.isNull()) { - _qmlWindow->setProperty(TITLE_PROPERTY, title); + QMetaObject::invokeMethod(_qmlWindow, "setProperty", Q_ARG(const char*, TITLE_PROPERTY), + Q_ARG(QString, title)); } } int InteractiveWindow::getPresentationMode() const { - if (QThread::currentThread() != thread()) { - int result; - BLOCKING_INVOKE_METHOD(const_cast<InteractiveWindow*>(this), "getPresentationMode", - Q_RETURN_ARG(int, result)); - return result; - } - if (_qmlWindow.isNull()) { return Virtual; } @@ -449,12 +391,8 @@ void InteractiveWindow::parentNativeWindowToMainWindow() { } void InteractiveWindow::setPresentationMode(int presentationMode) { - if (QThread::currentThread() != thread()) { - QMetaObject::invokeMethod(this, "setPresentationMode", Q_ARG(int, presentationMode)); - return; - } - if (!_qmlWindow.isNull()) { - _qmlWindow->setProperty(PRESENTATION_MODE_PROPERTY, presentationMode); + QMetaObject::invokeMethod(_qmlWindow, "setProperty", Q_ARG(const char*, PRESENTATION_MODE_PROPERTY), + Q_ARG(int, presentationMode)); } } From c4a0b39068f7c0666be1c1ed6859e0c64c8afb2c Mon Sep 17 00:00:00 2001 From: dante ruiz <dante@highfidelity.io> Date: Wed, 10 Jul 2019 17:56:54 -0700 Subject: [PATCH 2/4] requested changes --- interface/src/ui/InteractiveWindow.cpp | 30 +++++++++++++++++--------- interface/src/ui/InteractiveWindow.h | 23 ++++++++++++++++++++ 2 files changed, 43 insertions(+), 10 deletions(-) diff --git a/interface/src/ui/InteractiveWindow.cpp b/interface/src/ui/InteractiveWindow.cpp index c85d7bc301..84094a2500 100644 --- a/interface/src/ui/InteractiveWindow.cpp +++ b/interface/src/ui/InteractiveWindow.cpp @@ -51,6 +51,26 @@ static const QStringList KNOWN_SCHEMES = QStringList() << "http" << "https" << " static const int DEFAULT_HEIGHT = 60; +QmlWindowProxy::QmlWindowProxy(QObject* qmlObject, QObject* parent) : QmlWrapper(qmlObject, parent) { + _qmlWindow = qmlObject; +} + +void QmlWindowProxy::updateInteractiveWindowPositionForMode() { +} + +void QmlWindowProxy::setPosition(const glm::vec2& position) { +} + +glm::vec2 QmlWindowProxy::getPosition() const { +} + +void QmlWindowProxy::setSize(const glm::vec2& size) { +} + +glm::vec2 QmlWindowProxy::getSize() const { +} + +void QmlWindowProxy::setTitle(const QString& title static void dockWidgetDeleter(DockWidget* dockWidget) { dockWidget->deleteLater(); } @@ -296,11 +316,6 @@ void InteractiveWindow::qmlToScript(const QVariant& message) { } void InteractiveWindow::setVisible(bool visible) { - if (QThread::currentThread() != thread()) { - QMetaObject::invokeMethod(this, "setVisible", Q_ARG(bool, visible)); - return; - } - if (!_qmlWindow.isNull()) { QMetaObject::invokeMethod(_qmlWindow, "setProperty", Q_ARG(const char*, INTERACTIVE_WINDOW_VISIBLE_PROPERTY), Q_ARG(bool, visible)); @@ -324,11 +339,6 @@ glm::vec2 InteractiveWindow::getPosition() const { } 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()) { QMetaObject::invokeMethod(_qmlWindow, "setProperty", Q_ARG(const char*, INTERACTIVE_WINDOW_POSITION_PROPERTY), Q_ARG(QPointF, QPointF(position.x, position.y))); diff --git a/interface/src/ui/InteractiveWindow.h b/interface/src/ui/InteractiveWindow.h index c7b3631dde..d9886bd138 100644 --- a/interface/src/ui/InteractiveWindow.h +++ b/interface/src/ui/InteractiveWindow.h @@ -18,10 +18,33 @@ #include <QtCore/QPointer> #include <QtScript/QScriptValue> #include <QQmlEngine> +#include <ui/QmlWrapper.h> #include <glm/glm.hpp> #include <GLMHelpers.h> +class QmlWindowProxy : QmlWrapper { + Q_OBJECT + +public: + QmlWindowProxy(QObject* qmlObject, QObject* parent = nullptr); + + Q_INVOKABLE void updateInteractiveWindowPositionForMode(); + + Q_INVOKABLE void setPosition(const glm::vec2& position); + glm::vec2 getPositiion() const; + + Q_INVOKABLE void setSize(const glm::vec2& size); + glm::vec2 getSize() const; + + Q_INVOKABLE void setTitle(const QString& title); + QString getTitle() const; +private: + QObject* _qmlWindow; + +}; + + namespace InteractiveWindowEnums { Q_NAMESPACE From 2f74f8253fc232a82ac903192933b75b0bcf7d5f Mon Sep 17 00:00:00 2001 From: Dante Ruiz <danteruiz102@gmail.com> Date: Thu, 11 Jul 2019 15:32:44 -0700 Subject: [PATCH 3/4] finishing requested changes --- interface/src/ui/InteractiveWindow.cpp | 167 +++++++++++++++++-------- interface/src/ui/InteractiveWindow.h | 18 ++- 2 files changed, 126 insertions(+), 59 deletions(-) diff --git a/interface/src/ui/InteractiveWindow.cpp b/interface/src/ui/InteractiveWindow.cpp index 84094a2500..2c580deb47 100644 --- a/interface/src/ui/InteractiveWindow.cpp +++ b/interface/src/ui/InteractiveWindow.cpp @@ -55,22 +55,96 @@ QmlWindowProxy::QmlWindowProxy(QObject* qmlObject, QObject* parent) : QmlWrapper _qmlWindow = qmlObject; } -void QmlWindowProxy::updateInteractiveWindowPositionForMode() { -} - void QmlWindowProxy::setPosition(const glm::vec2& position) { + if (_qmlWindow) { + _qmlWindow->setProperty(INTERACTIVE_WINDOW_POSITION_PROPERTY, QPointF(position.x, position.y)); + QMetaObject::invokeMethod(_qmlWindow, "updateInteractiveWindowPositionForMode"); + } } glm::vec2 QmlWindowProxy::getPosition() const { + if (!_qmlWindow) { + return {}; + } + + return toGlm(_qmlWindow->property(INTERACTIVE_WINDOW_POSITION_PROPERTY).toPointF()); } void QmlWindowProxy::setSize(const glm::vec2& size) { + if (_qmlWindow) { + _qmlWindow->setProperty(INTERACTIVE_WINDOW_SIZE_PROPERTY, QSize(size.x, size.y)); + QMetaObject::invokeMethod(_qmlWindow, "updateInteractiveWindowSizeForMode"); + } } glm::vec2 QmlWindowProxy::getSize() const { + if (!_qmlWindow) { + return {}; + } + + return toGlm(_qmlWindow->property(INTERACTIVE_WINDOW_SIZE_PROPERTY).toSize()); +} + +void QmlWindowProxy::setTitle(const QString& title) { + if (_qmlWindow) { + _qmlWindow->setProperty(TITLE_PROPERTY, title); + } +} + +QString QmlWindowProxy::getTitle() const { + if (!_qmlWindow) { + return QString(); + } + + return _qmlWindow->property(TITLE_PROPERTY).toString(); +} + +void QmlWindowProxy::setVisible(bool visible) { + if (_qmlWindow) { + _qmlWindow->setProperty(INTERACTIVE_WINDOW_VISIBLE_PROPERTY, visible); + } +} + +bool QmlWindowProxy::isVisible() const { + if (!_qmlWindow) { + return false; + } + + return _qmlWindow->property(INTERACTIVE_WINDOW_VISIBLE_PROPERTY).toBool(); +} + +void QmlWindowProxy::setPresentationMode(int presentationMode) { + if (_qmlWindow) { + _qmlWindow->setProperty(PRESENTATION_MODE_PROPERTY, presentationMode); + } +} + +int QmlWindowProxy::getPresentationMode() const { + if (!_qmlWindow) { + return Virtual; + } + + return _qmlWindow->property(PRESENTATION_MODE_PROPERTY).toInt(); +} + +void QmlWindowProxy::parentNativeWindowToMainWindow() { +#ifdef Q_OS_WIN + if (!_qmlWindow) { + return; + } + const auto nativeWindowProperty = _qmlWindow->property("nativeWindow"); + if (nativeWindowProperty.isNull() || !nativeWindowProperty.isValid()) { + return; + } + const auto nativeWindow = qvariant_cast<QQuickWindow*>(nativeWindowProperty); + SetWindowLongPtr((HWND)nativeWindow->winId(), GWLP_HWNDPARENT, (LONG)MainWindow::findMainWindow()->winId()); +#endif +} + +static void qmlWindowProxyDeleter(QmlWindowProxy* qmlWindowProxy) { + qmlWindowProxy->deleteLater(); } -void QmlWindowProxy::setTitle(const QString& title static void dockWidgetDeleter(DockWidget* dockWidget) { dockWidget->deleteLater(); } @@ -201,7 +275,7 @@ InteractiveWindow::InteractiveWindow(const QString& sourceUrl, const QVariantMap 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; + _qmlWindowProxy = std::shared_ptr<QmlWindowProxy>(new QmlWindowProxy(object, nullptr), qmlWindowProxyDeleter); context->setContextProperty(EVENT_BRIDGE_PROPERTY, this); if (properties.contains(ADDITIONAL_FLAGS_PROPERTY)) { object->setProperty(ADDITIONAL_FLAGS_PROPERTY, properties[ADDITIONAL_FLAGS_PROPERTY].toUInt()); @@ -268,7 +342,7 @@ void InteractiveWindow::sendToQml(const QVariant& message) { QMetaObject::invokeMethod(rootItem, "fromScript", Qt::QueuedConnection, Q_ARG(QVariant, message)); } } else { - QMetaObject::invokeMethod(_qmlWindow, "fromScript", Qt::QueuedConnection, Q_ARG(QVariant, message)); + QMetaObject::invokeMethod(_qmlWindowProxy->getQmlWindow(), "fromScript", Qt::QueuedConnection, Q_ARG(QVariant, message)); } } @@ -281,8 +355,12 @@ void InteractiveWindow::emitWebEvent(const QVariant& webMessage) { } void InteractiveWindow::close() { - if (_qmlWindow) { - _qmlWindow->deleteLater(); + if (_qmlWindowProxy) { + QObject* qmlWindow = _qmlWindowProxy->getQmlWindow(); + if (qmlWindow) { + qmlWindow->deleteLater(); + } + _qmlWindowProxy->deleteLater(); } if (_dockWidget) { @@ -290,18 +368,18 @@ void InteractiveWindow::close() { BLOCKING_INVOKE_METHOD(window, "removeDockWidget", Q_ARG(QDockWidget*, _dockWidget.get())); } _dockWidget = nullptr; - _qmlWindow = nullptr; + _qmlWindowProxy = nullptr; } void InteractiveWindow::show() { - if (_qmlWindow) { - QMetaObject::invokeMethod(_qmlWindow, "show"); + if (_qmlWindowProxy) { + QMetaObject::invokeMethod(_qmlWindowProxy->getQmlWindow(), "show"); } } void InteractiveWindow::raise() { - if (_qmlWindow) { - QMetaObject::invokeMethod(_qmlWindow, "raiseWindow"); + if (_qmlWindowProxy) { + QMetaObject::invokeMethod(_qmlWindowProxy->getQmlWindow(), "raiseWindow"); } } @@ -316,93 +394,74 @@ void InteractiveWindow::qmlToScript(const QVariant& message) { } void InteractiveWindow::setVisible(bool visible) { - if (!_qmlWindow.isNull()) { - QMetaObject::invokeMethod(_qmlWindow, "setProperty", Q_ARG(const char*, INTERACTIVE_WINDOW_VISIBLE_PROPERTY), - Q_ARG(bool, visible)); + if (_qmlWindowProxy) { + QMetaObject::invokeMethod(_qmlWindowProxy.get(), "setVisible", Q_ARG(bool, visible)); } } bool InteractiveWindow::isVisible() const { - if (_qmlWindow.isNull()) { + if (!_qmlWindowProxy) { return false; } - return _qmlWindow->property(INTERACTIVE_WINDOW_VISIBLE_PROPERTY).toBool(); + return _qmlWindowProxy->isVisible(); } glm::vec2 InteractiveWindow::getPosition() const { - if (_qmlWindow.isNull()) { + if (!_qmlWindowProxy) { return {}; } - return toGlm(_qmlWindow->property(INTERACTIVE_WINDOW_POSITION_PROPERTY).toPointF()); + return _qmlWindowProxy->getPosition(); } void InteractiveWindow::setPosition(const glm::vec2& position) { - if (!_qmlWindow.isNull()) { - QMetaObject::invokeMethod(_qmlWindow, "setProperty", Q_ARG(const char*, INTERACTIVE_WINDOW_POSITION_PROPERTY), - Q_ARG(QPointF, QPointF(position.x, position.y))); - QMetaObject::invokeMethod(_qmlWindow, "updateInteractiveWindowPositionForMode"); + if (_qmlWindowProxy) { + QMetaObject::invokeMethod(_qmlWindowProxy.get(), "setPosition", Q_ARG(const glm::vec2&, position)); } } glm::vec2 InteractiveWindow::getSize() const { - if (_qmlWindow.isNull()) { + if (!_qmlWindowProxy) { return {}; } - return toGlm(_qmlWindow->property(INTERACTIVE_WINDOW_SIZE_PROPERTY).toSize()); + return _qmlWindowProxy->getSize(); } void InteractiveWindow::setSize(const glm::vec2& size) { - if (!_qmlWindow.isNull()) { - QMetaObject::invokeMethod(_qmlWindow, "setProperty", Q_ARG(const char*, INTERACTIVE_WINDOW_SIZE_PROPERTY), - Q_ARG(QSize, QSize(size.x, size.y))); - QMetaObject::invokeMethod(_qmlWindow, "updateInteractiveWindowSizeForMode"); + if (_qmlWindowProxy) { + QMetaObject::invokeMethod(_qmlWindowProxy.get(), "setSize", Q_ARG(const glm::vec2&, size)); } } QString InteractiveWindow::getTitle() const { - if (_qmlWindow.isNull()) { + if (!_qmlWindowProxy) { return QString(); } - return _qmlWindow->property(TITLE_PROPERTY).toString(); + return _qmlWindowProxy->getTitle(); } void InteractiveWindow::setTitle(const QString& title) { - if (!_qmlWindow.isNull()) { - QMetaObject::invokeMethod(_qmlWindow, "setProperty", Q_ARG(const char*, TITLE_PROPERTY), - Q_ARG(QString, title)); + if (_qmlWindowProxy) { + QMetaObject::invokeMethod(_qmlWindowProxy.get(), "setTitle", Q_ARG(const QString&, title)); } } int InteractiveWindow::getPresentationMode() const { - if (_qmlWindow.isNull()) { + if (!_qmlWindowProxy) { return Virtual; } - return _qmlWindow->property(PRESENTATION_MODE_PROPERTY).toInt(); + return _qmlWindowProxy->getPresentationMode(); } void InteractiveWindow::parentNativeWindowToMainWindow() { -#ifdef Q_OS_WIN - if (QThread::currentThread() != thread()) { - QMetaObject::invokeMethod(this, "parentNativeWindowToMainWindow"); - return; + if (_qmlWindowProxy) { + QMetaObject::invokeMethod(_qmlWindowProxy.get(), "parentNativeWindowToMainWindow"); } - if (_qmlWindow.isNull()) { - return; - } - const auto nativeWindowProperty = _qmlWindow->property("nativeWindow"); - if (nativeWindowProperty.isNull() || !nativeWindowProperty.isValid()) { - return; - } - const auto nativeWindow = qvariant_cast<QQuickWindow*>(nativeWindowProperty); - SetWindowLongPtr((HWND)nativeWindow->winId(), GWLP_HWNDPARENT, (LONG)MainWindow::findMainWindow()->winId()); -#endif } void InteractiveWindow::setPresentationMode(int presentationMode) { - if (!_qmlWindow.isNull()) { - QMetaObject::invokeMethod(_qmlWindow, "setProperty", Q_ARG(const char*, PRESENTATION_MODE_PROPERTY), - Q_ARG(int, presentationMode)); + if (_qmlWindowProxy) { + QMetaObject::invokeMethod(_qmlWindowProxy.get(), "setPresentationMode", Q_ARG(int, presentationMode)); } } diff --git a/interface/src/ui/InteractiveWindow.h b/interface/src/ui/InteractiveWindow.h index d9886bd138..7abdc5210a 100644 --- a/interface/src/ui/InteractiveWindow.h +++ b/interface/src/ui/InteractiveWindow.h @@ -23,22 +23,30 @@ #include <glm/glm.hpp> #include <GLMHelpers.h> -class QmlWindowProxy : QmlWrapper { +class QmlWindowProxy : public QmlWrapper { Q_OBJECT public: QmlWindowProxy(QObject* qmlObject, QObject* parent = nullptr); - Q_INVOKABLE void updateInteractiveWindowPositionForMode(); - Q_INVOKABLE void setPosition(const glm::vec2& position); - glm::vec2 getPositiion() const; + glm::vec2 getPosition() const; Q_INVOKABLE void setSize(const glm::vec2& size); glm::vec2 getSize() const; Q_INVOKABLE void setTitle(const QString& title); QString getTitle() const; + + Q_INVOKABLE void setVisible(bool visible); + bool isVisible() const; + + Q_INVOKABLE void setPresentationMode(int presentationMode); + int getPresentationMode() const; + + Q_INVOKABLE void parentNativeWindowToMainWindow(); + + QObject* getQmlWindow() const { return _qmlWindow; } private: QObject* _qmlWindow; @@ -314,7 +322,7 @@ protected slots: void forwardKeyReleaseEvent(int key, int modifiers); private: - QPointer<QObject> _qmlWindow; + std::shared_ptr<QmlWindowProxy> _qmlWindowProxy; std::shared_ptr<DockWidget> _dockWidget { nullptr }; }; From d78661a47f6c191a88a4e133b49a3e2dbb9b31bf Mon Sep 17 00:00:00 2001 From: dante ruiz <dante@highfidelity.io> Date: Fri, 12 Jul 2019 13:34:08 -0700 Subject: [PATCH 4/4] redo requested work --- interface/src/ui/InteractiveWindow.cpp | 118 ++++++++----------------- interface/src/ui/InteractiveWindow.h | 15 ---- 2 files changed, 35 insertions(+), 98 deletions(-) diff --git a/interface/src/ui/InteractiveWindow.cpp b/interface/src/ui/InteractiveWindow.cpp index 2c580deb47..dff1f4dcb5 100644 --- a/interface/src/ui/InteractiveWindow.cpp +++ b/interface/src/ui/InteractiveWindow.cpp @@ -55,78 +55,6 @@ QmlWindowProxy::QmlWindowProxy(QObject* qmlObject, QObject* parent) : QmlWrapper _qmlWindow = qmlObject; } -void QmlWindowProxy::setPosition(const glm::vec2& position) { - if (_qmlWindow) { - _qmlWindow->setProperty(INTERACTIVE_WINDOW_POSITION_PROPERTY, QPointF(position.x, position.y)); - QMetaObject::invokeMethod(_qmlWindow, "updateInteractiveWindowPositionForMode"); - } -} - -glm::vec2 QmlWindowProxy::getPosition() const { - if (!_qmlWindow) { - return {}; - } - - return toGlm(_qmlWindow->property(INTERACTIVE_WINDOW_POSITION_PROPERTY).toPointF()); -} - -void QmlWindowProxy::setSize(const glm::vec2& size) { - if (_qmlWindow) { - _qmlWindow->setProperty(INTERACTIVE_WINDOW_SIZE_PROPERTY, QSize(size.x, size.y)); - QMetaObject::invokeMethod(_qmlWindow, "updateInteractiveWindowSizeForMode"); - } -} - -glm::vec2 QmlWindowProxy::getSize() const { - if (!_qmlWindow) { - return {}; - } - - return toGlm(_qmlWindow->property(INTERACTIVE_WINDOW_SIZE_PROPERTY).toSize()); -} - -void QmlWindowProxy::setTitle(const QString& title) { - if (_qmlWindow) { - _qmlWindow->setProperty(TITLE_PROPERTY, title); - } -} - -QString QmlWindowProxy::getTitle() const { - if (!_qmlWindow) { - return QString(); - } - - return _qmlWindow->property(TITLE_PROPERTY).toString(); -} - -void QmlWindowProxy::setVisible(bool visible) { - if (_qmlWindow) { - _qmlWindow->setProperty(INTERACTIVE_WINDOW_VISIBLE_PROPERTY, visible); - } -} - -bool QmlWindowProxy::isVisible() const { - if (!_qmlWindow) { - return false; - } - - return _qmlWindow->property(INTERACTIVE_WINDOW_VISIBLE_PROPERTY).toBool(); -} - -void QmlWindowProxy::setPresentationMode(int presentationMode) { - if (_qmlWindow) { - _qmlWindow->setProperty(PRESENTATION_MODE_PROPERTY, presentationMode); - } -} - -int QmlWindowProxy::getPresentationMode() const { - if (!_qmlWindow) { - return Virtual; - } - - return _qmlWindow->property(PRESENTATION_MODE_PROPERTY).toInt(); -} - void QmlWindowProxy::parentNativeWindowToMainWindow() { #ifdef Q_OS_WIN if (!_qmlWindow) { @@ -395,7 +323,8 @@ void InteractiveWindow::qmlToScript(const QVariant& message) { void InteractiveWindow::setVisible(bool visible) { if (_qmlWindowProxy) { - QMetaObject::invokeMethod(_qmlWindowProxy.get(), "setVisible", Q_ARG(bool, visible)); + QMetaObject::invokeMethod(_qmlWindowProxy.get(), "writeProperty", Q_ARG(QString, INTERACTIVE_WINDOW_VISIBLE_PROPERTY), + Q_ARG(QVariant, visible)); } } @@ -403,8 +332,10 @@ bool InteractiveWindow::isVisible() const { if (!_qmlWindowProxy) { return false; } - - return _qmlWindowProxy->isVisible(); + QVariant result; + BLOCKING_INVOKE_METHOD(_qmlWindowProxy.get(), "readProperty", Q_RETURN_ARG(QVariant, result), + Q_ARG(QString, INTERACTIVE_WINDOW_VISIBLE_PROPERTY)); + return result.toBool(); } glm::vec2 InteractiveWindow::getPosition() const { @@ -412,12 +343,18 @@ glm::vec2 InteractiveWindow::getPosition() const { return {}; } - return _qmlWindowProxy->getPosition(); + QVariant result; + BLOCKING_INVOKE_METHOD(_qmlWindowProxy.get(), "readProperty", Q_RETURN_ARG(QVariant, result), + Q_ARG(QString, INTERACTIVE_WINDOW_POSITION_PROPERTY)); + + return toGlm(result.toPointF()); } void InteractiveWindow::setPosition(const glm::vec2& position) { if (_qmlWindowProxy) { - QMetaObject::invokeMethod(_qmlWindowProxy.get(), "setPosition", Q_ARG(const glm::vec2&, position)); + QMetaObject::invokeMethod(_qmlWindowProxy.get(), "writeProperty", Q_ARG(QString, INTERACTIVE_WINDOW_POSITION_PROPERTY), + Q_ARG(QVariant, QPointF(position.x, position.y))); + QMetaObject::invokeMethod(_qmlWindowProxy->getQmlWindow(), "updateInteractiveWindowPositionForMode"); } } @@ -425,12 +362,18 @@ glm::vec2 InteractiveWindow::getSize() const { if (!_qmlWindowProxy) { return {}; } - return _qmlWindowProxy->getSize(); + + QVariant result; + BLOCKING_INVOKE_METHOD(_qmlWindowProxy.get(), "readProperty", Q_RETURN_ARG(QVariant, result), + Q_ARG(QString, INTERACTIVE_WINDOW_SIZE_PROPERTY)); + return toGlm(result.toSize()); } void InteractiveWindow::setSize(const glm::vec2& size) { if (_qmlWindowProxy) { - QMetaObject::invokeMethod(_qmlWindowProxy.get(), "setSize", Q_ARG(const glm::vec2&, size)); + QMetaObject::invokeMethod(_qmlWindowProxy.get(), "writeProperty", Q_ARG(QString, INTERACTIVE_WINDOW_SIZE_PROPERTY), + Q_ARG(QVariant, QSize(size.x, size.y))); + QMetaObject::invokeMethod(_qmlWindowProxy->getQmlWindow(), "updateInteractiveWindowSizeForMode"); } } @@ -438,12 +381,17 @@ QString InteractiveWindow::getTitle() const { if (!_qmlWindowProxy) { return QString(); } - return _qmlWindowProxy->getTitle(); + + QVariant result; + BLOCKING_INVOKE_METHOD(_qmlWindowProxy.get(), "readProperty", Q_RETURN_ARG(QVariant, result), + Q_ARG(QString, TITLE_PROPERTY)); + return result.toString(); } void InteractiveWindow::setTitle(const QString& title) { if (_qmlWindowProxy) { - QMetaObject::invokeMethod(_qmlWindowProxy.get(), "setTitle", Q_ARG(const QString&, title)); + QMetaObject::invokeMethod(_qmlWindowProxy.get(), "writeProperty", Q_ARG(QString, TITLE_PROPERTY), + Q_ARG(QVariant, title)); } } @@ -451,7 +399,10 @@ int InteractiveWindow::getPresentationMode() const { if (!_qmlWindowProxy) { return Virtual; } - return _qmlWindowProxy->getPresentationMode(); + QVariant result; + BLOCKING_INVOKE_METHOD(_qmlWindowProxy.get(), "readProperty", Q_RETURN_ARG(QVariant, result), + Q_ARG(QString, PRESENTATION_MODE_PROPERTY)); + return result.toInt(); } void InteractiveWindow::parentNativeWindowToMainWindow() { @@ -462,6 +413,7 @@ void InteractiveWindow::parentNativeWindowToMainWindow() { void InteractiveWindow::setPresentationMode(int presentationMode) { if (_qmlWindowProxy) { - QMetaObject::invokeMethod(_qmlWindowProxy.get(), "setPresentationMode", Q_ARG(int, presentationMode)); + QMetaObject::invokeMethod(_qmlWindowProxy.get(), "writeProperty", Q_ARG(QString, PRESENTATION_MODE_PROPERTY), + Q_ARG(QVariant, presentationMode)); } } diff --git a/interface/src/ui/InteractiveWindow.h b/interface/src/ui/InteractiveWindow.h index 7abdc5210a..0098658c16 100644 --- a/interface/src/ui/InteractiveWindow.h +++ b/interface/src/ui/InteractiveWindow.h @@ -29,21 +29,6 @@ class QmlWindowProxy : public QmlWrapper { public: QmlWindowProxy(QObject* qmlObject, QObject* parent = nullptr); - Q_INVOKABLE void setPosition(const glm::vec2& position); - glm::vec2 getPosition() const; - - Q_INVOKABLE void setSize(const glm::vec2& size); - glm::vec2 getSize() const; - - Q_INVOKABLE void setTitle(const QString& title); - QString getTitle() const; - - Q_INVOKABLE void setVisible(bool visible); - bool isVisible() const; - - Q_INVOKABLE void setPresentationMode(int presentationMode); - int getPresentationMode() const; - Q_INVOKABLE void parentNativeWindowToMainWindow(); QObject* getQmlWindow() const { return _qmlWindow; }