diff options
Diffstat (limited to 'src/quickwidgets')
-rw-r--r-- | src/quickwidgets/qquickwidget.cpp | 109 | ||||
-rw-r--r-- | src/quickwidgets/qquickwidget.h | 3 | ||||
-rw-r--r-- | src/quickwidgets/qquickwidget_p.h | 13 |
3 files changed, 103 insertions, 22 deletions
diff --git a/src/quickwidgets/qquickwidget.cpp b/src/quickwidgets/qquickwidget.cpp index 620d169eb4..2120be768c 100644 --- a/src/quickwidgets/qquickwidget.cpp +++ b/src/quickwidgets/qquickwidget.cpp @@ -39,8 +39,9 @@ #include "private/qquickitemchangelistener_p.h" #include "private/qquickrendercontrol_p.h" +#include <private/qqmldebugconnector_p.h> #include <private/qquickprofiler_p.h> -#include <private/qqmlinspectorservice_p.h> +#include <private/qqmldebugserviceinterfaces_p.h> #include <private/qqmlmemoryprofiler_p.h> #include <QtQml/qqmlengine.h> @@ -95,8 +96,9 @@ void QQuickWidgetPrivate::init(QQmlEngine* e) if (!engine.data()->incubationController()) engine.data()->setIncubationController(offscreenWindow->incubationController()); - if (QQmlDebugService::isDebuggingEnabled()) - QQmlInspectorService::instance()->addView(q); + QQmlInspectorService *service = QQmlDebugConnector::service<QQmlInspectorService>(); + if (service) + service->addView(q); #ifndef QT_NO_DRAGANDDROP q->setAcceptDrops(true); @@ -142,13 +144,15 @@ QQuickWidgetPrivate::QQuickWidgetPrivate() , eventPending(false) , updatePending(false) , fakeHidden(false) + , requestedSamples(0) { } QQuickWidgetPrivate::~QQuickWidgetPrivate() { - if (QQmlDebugService::isDebuggingEnabled()) - QQmlInspectorService::instance()->removeView(q_func()); + QQmlInspectorService *service = QQmlDebugConnector::service<QQmlInspectorService>(); + if (service) + service->removeView(q_func()); invalidateRenderControl(); @@ -202,6 +206,11 @@ void QQuickWidgetPrivate::itemGeometryChanged(QQuickItem *resizeItem, const QRec void QQuickWidgetPrivate::render(bool needsSync) { + // createFramebufferObject() bails out when the size is empty. In this case + // we cannot render either. + if (!fbo) + return; + Q_ASSERT(context); if (!context->makeCurrent(offscreenSurface)) { @@ -243,8 +252,15 @@ void QQuickWidgetPrivate::renderSceneGraph() } Q_ASSERT(offscreenSurface); + render(true); - q->update(); // schedule composition + +#ifndef QT_NO_GRAPHICSVIEW + if (q->window()->graphicsProxyWidget()) + QWidgetPrivate::nearestGraphicsProxyWidget(q)->update(); + else +#endif + q->update(); // schedule composition } QImage QQuickWidgetPrivate::grabFramebuffer() @@ -338,8 +354,8 @@ QObject *QQuickWidgetPrivate::focusObject() This limitation only applies when there are other widgets underneath the QQuickWidget inside the same window. Making the window semi-transparent, with other applications and the desktop visible in the background, is done in the traditional way: Set - Qt::WA_TranslucentBackground and change the Qt Quick Scenegraph's clear color to - Qt::transparent via setClearColor(). + Qt::WA_TranslucentBackground on the top-level window, request an alpha channel, and + change the Qt Quick Scenegraph's clear color to Qt::transparent via setClearColor(). \sa {Exposing Attributes of C++ Types to QML}, {Qt Quick Widgets Example}, QQuickView */ @@ -540,6 +556,9 @@ QQuickWidget::Status QQuickWidget::status() const if (!d->component) return QQuickWidget::Null; + if (d->component->status() == QQmlComponent::Ready && !d->root) + return QQuickWidget::Error; + return QQuickWidget::Status(d->component->status()); } @@ -561,6 +580,10 @@ QList<QQmlError> QQuickWidget::errors() const QQmlError error; error.setDescription(QLatin1String("QQuickWidget: invalid qml engine.")); errs << error; + } else if (d->component && d->component->status() == QQmlComponent::Ready && !d->root) { + QQmlError error; + error.setDescription(QLatin1String("QQuickWidget: invalid root object.")); + errs << error; } return errs; @@ -689,6 +712,7 @@ void QQuickWidgetPrivate::handleContextCreationFailure(const QSurfaceFormat &for void QQuickWidgetPrivate::createContext() { + Q_Q(QQuickWidget); // On hide-show we invalidate() but our context is kept. // We nonetheless need to initialize() again. const bool reinit = context && !offscreenWindow->openglContext(); @@ -700,11 +724,13 @@ void QQuickWidgetPrivate::createContext() context = new QOpenGLContext; context->setFormat(offscreenWindow->requestedFormat()); - if (qt_gl_global_share_context()) { - context->setShareContext(qt_gl_global_share_context()); - context->setScreen(context->shareContext()->screen()); + QOpenGLContext *shareContext = qt_gl_global_share_context(); + if (!shareContext) + shareContext = QWidgetPrivate::get(q->window())->shareContext(); + if (shareContext) { + context->setShareContext(shareContext); + context->setScreen(shareContext->screen()); } - if (!context->create()) { const bool isEs = context->isOpenGLES(); delete context; @@ -766,7 +792,7 @@ void QQuickWidget::createFramebufferObject() context->makeCurrent(d->offscreenSurface); - int samples = d->offscreenWindow->requestedFormat().samples(); + int samples = d->requestedSamples; if (!QOpenGLExtensions(context).hasOpenGLExtension(QOpenGLExtensions::FramebufferMultisample)) samples = 0; @@ -880,14 +906,15 @@ void QQuickWidgetPrivate::setRootObject(QObject *obj) if (QQuickItem *sgItem = qobject_cast<QQuickItem *>(obj)) { root = sgItem; sgItem->setParentItem(offscreenWindow->contentItem()); + } else if (qobject_cast<QWindow *>(obj)) { + qWarning() << "QQuickWidget does not support using windows as a root item." << endl + << endl + << "If you wish to create your root window from QML, consider using QQmlApplicationEngine instead." << endl; } else { qWarning() << "QQuickWidget only supports loading of root objects that derive from QQuickItem." << endl << endl - << "If your example is using QML 2, (such as qmlscene) and the .qml file you" << endl - << "loaded has 'import QtQuick 1.0' or 'import Qt 4.7', this error will occur." << endl - << endl - << "To load files with 'import QtQuick 1.0' or 'import Qt 4.7', use the" << endl - << "QDeclarativeView class in the Qt Quick 1 module." << endl; + << "Ensure your QML code is written for QtQuick 2, and uses a root that is or" << endl + << "inherits from QtQuick's Item (not a Timer, QtObject, etc)." << endl; delete obj; root = 0; } @@ -1078,6 +1105,12 @@ void QQuickWidget::showEvent(QShowEvent *) d->render(true); else triggerUpdate(); + QWindowPrivate *offscreenPrivate = QWindowPrivate::get(d->offscreenWindow); + if (!offscreenPrivate->visible) { + offscreenPrivate->visible = true; + emit d->offscreenWindow->visibleChanged(true); + offscreenPrivate->updateVisibility(); + } } /*! \reimp */ @@ -1085,6 +1118,12 @@ void QQuickWidget::hideEvent(QHideEvent *) { Q_D(QQuickWidget); d->invalidateRenderControl(); + QWindowPrivate *offscreenPrivate = QWindowPrivate::get(d->offscreenWindow); + if (offscreenPrivate->visible) { + offscreenPrivate->visible = false; + emit d->offscreenWindow->visibleChanged(false); + offscreenPrivate->updateVisibility(); + } } /*! \reimp */ @@ -1139,6 +1178,20 @@ void QQuickWidget::focusOutEvent(QFocusEvent * event) d->offscreenWindow->focusOutEvent(event); } +static Qt::WindowState resolveWindowState(Qt::WindowStates states) +{ + // No more than one of these 3 can be set + if (states & Qt::WindowMinimized) + return Qt::WindowMinimized; + if (states & Qt::WindowMaximized) + return Qt::WindowMaximized; + if (states & Qt::WindowFullScreen) + return Qt::WindowFullScreen; + + // No state means "windowed" - we ignore Qt::WindowActive + return Qt::WindowNoState; +} + /*! \reimp */ bool QQuickWidget::event(QEvent *e) { @@ -1168,10 +1221,15 @@ bool QQuickWidget::event(QEvent *e) } break; + case QEvent::Show: case QEvent::Move: d->updatePosition(); break; + case QEvent::WindowStateChange: + d->offscreenWindow->setWindowState(resolveWindowState(windowState())); + break; + default: break; } @@ -1249,6 +1307,14 @@ void QQuickWidget::setFormat(const QSurfaceFormat &format) newFormat.setDepthBufferSize(qMax(newFormat.depthBufferSize(), currentFormat.depthBufferSize())); newFormat.setStencilBufferSize(qMax(newFormat.stencilBufferSize(), currentFormat.stencilBufferSize())); newFormat.setAlphaBufferSize(qMax(newFormat.alphaBufferSize(), currentFormat.alphaBufferSize())); + + // Do not include the sample count. Requesting a multisampled context is not necessary + // since we render into an FBO, never to an actual surface. What's more, attempting to + // create a pbuffer with a multisampled config crashes certain implementations. Just + // avoid the entire hassle, the result is the same. + d->requestedSamples = newFormat.samples(); + newFormat.setSamples(0); + d->offscreenWindow->setFormat(newFormat); } @@ -1278,9 +1344,10 @@ QImage QQuickWidget::grabFramebuffer() const /*! Sets the clear \a color. By default this is an opaque color. - To get a semi- or fully transparent QQuickWidget, call this function with \a - color set to Qt::transparent and set the Qt::WA_TranslucentBackground widget - attribute. + To get a semi-transparent QQuickWidget, call this function with + \a color set to Qt::transparent, set the Qt::WA_TranslucentBackground + widget attribute on the top-level window, and request an alpha + channel via setFormat(). \sa QQuickWindow::setColor() */ diff --git a/src/quickwidgets/qquickwidget.h b/src/quickwidgets/qquickwidget.h index a8bf03edfb..5bb6b49a49 100644 --- a/src/quickwidgets/qquickwidget.h +++ b/src/quickwidgets/qquickwidget.h @@ -56,7 +56,6 @@ class Q_QUICKWIDGETS_EXPORT QQuickWidget : public QWidget Q_PROPERTY(ResizeMode resizeMode READ resizeMode WRITE setResizeMode) Q_PROPERTY(Status status READ status NOTIFY statusChanged) Q_PROPERTY(QUrl source READ source WRITE setSource DESIGNABLE true) - Q_ENUMS(ResizeMode Status) public: explicit QQuickWidget(QWidget *parent = 0); @@ -72,10 +71,12 @@ public: QQuickItem *rootObject() const; enum ResizeMode { SizeViewToRootObject, SizeRootObjectToView }; + Q_ENUM(ResizeMode) ResizeMode resizeMode() const; void setResizeMode(ResizeMode); enum Status { Null, Ready, Loading, Error }; + Q_ENUM(Status) Status status() const; QList<QQmlError> errors() const; diff --git a/src/quickwidgets/qquickwidget_p.h b/src/quickwidgets/qquickwidget_p.h index e8d1f714f3..46f6ac5d8a 100644 --- a/src/quickwidgets/qquickwidget_p.h +++ b/src/quickwidgets/qquickwidget_p.h @@ -34,6 +34,17 @@ #ifndef QQUICKWIDGET_P_H #define QQUICKWIDGET_P_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include "qquickwidget.h" #include <private/qwidget_p.h> @@ -115,6 +126,8 @@ public: bool eventPending; bool updatePending; bool fakeHidden; + + int requestedSamples; }; QT_END_NAMESPACE |