diff options
Diffstat (limited to 'src/quickwidgets/qquickwidget.cpp')
-rw-r--r-- | src/quickwidgets/qquickwidget.cpp | 88 |
1 files changed, 72 insertions, 16 deletions
diff --git a/src/quickwidgets/qquickwidget.cpp b/src/quickwidgets/qquickwidget.cpp index 620d169eb4..cc7ece9c5b 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)) { @@ -338,8 +347,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 +549,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 +573,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; @@ -766,7 +782,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 +896,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 +1095,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 +1108,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 +1168,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) { @@ -1172,6 +1215,10 @@ bool QQuickWidget::event(QEvent *e) d->updatePosition(); break; + case QEvent::WindowStateChange: + d->offscreenWindow->setWindowState(resolveWindowState(windowState())); + break; + default: break; } @@ -1249,6 +1296,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 +1333,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() */ |