aboutsummaryrefslogtreecommitdiffstats
path: root/src/quickwidgets/qquickwidget.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/quickwidgets/qquickwidget.cpp')
-rw-r--r--src/quickwidgets/qquickwidget.cpp113
1 files changed, 69 insertions, 44 deletions
diff --git a/src/quickwidgets/qquickwidget.cpp b/src/quickwidgets/qquickwidget.cpp
index 39f7b6c3d3..b0838e5dc4 100644
--- a/src/quickwidgets/qquickwidget.cpp
+++ b/src/quickwidgets/qquickwidget.cpp
@@ -1,31 +1,37 @@
/****************************************************************************
**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtQuick module of the Qt Toolkit.
**
-** $QT_BEGIN_LICENSE:LGPL21$
+** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
@@ -90,16 +96,9 @@ void QQuickWidgetPrivate::init(QQmlEngine* e)
engine = e;
- if (engine.isNull())
- engine = new QQmlEngine(q);
-
- if (!engine.data()->incubationController())
+ if (!engine.isNull() && !engine.data()->incubationController())
engine.data()->setIncubationController(offscreenWindow->incubationController());
- QQmlInspectorService *service = QQmlDebugConnector::service<QQmlInspectorService>();
- if (service)
- service->addView(q);
-
#ifndef QT_NO_DRAGANDDROP
q->setAcceptDrops(true);
#endif
@@ -110,6 +109,16 @@ void QQuickWidgetPrivate::init(QQmlEngine* e)
QObject::connect(renderControl, SIGNAL(sceneChanged()), q, SLOT(triggerUpdate()));
}
+void QQuickWidgetPrivate::ensureEngine() const
+{
+ Q_Q(const QQuickWidget);
+ if (!engine.isNull())
+ return;
+
+ engine = new QQmlEngine(const_cast<QQuickWidget*>(q));
+ engine.data()->setIncubationController(offscreenWindow->incubationController());
+}
+
void QQuickWidgetPrivate::invalidateRenderControl()
{
if (!context) // this is not an error, could be called before creating the context, or multiple times
@@ -150,10 +159,6 @@ QQuickWidgetPrivate::QQuickWidgetPrivate()
QQuickWidgetPrivate::~QQuickWidgetPrivate()
{
- QQmlInspectorService *service = QQmlDebugConnector::service<QQmlInspectorService>();
- if (service)
- service->removeView(q_func());
-
invalidateRenderControl();
// context and offscreenSurface are current at this stage, if the context was created.
@@ -169,10 +174,7 @@ QQuickWidgetPrivate::~QQuickWidgetPrivate()
void QQuickWidgetPrivate::execute()
{
Q_Q(QQuickWidget);
- if (!engine) {
- qWarning() << "QQuickWidget: invalid qml engine.";
- return;
- }
+ ensureEngine();
if (root) {
delete root;
@@ -406,7 +408,6 @@ QQuickWidget::QQuickWidget(QQmlEngine* engine, QWidget *parent)
{
setMouseTracking(true);
setFocusPolicy(Qt::StrongFocus);
- Q_ASSERT(engine);
d_func()->init(engine);
}
@@ -492,7 +493,8 @@ QUrl QQuickWidget::source() const
QQmlEngine* QQuickWidget::engine() const
{
Q_D(const QQuickWidget);
- return d->engine ? const_cast<QQmlEngine *>(d->engine.data()) : 0;
+ d->ensureEngine();
+ return const_cast<QQmlEngine *>(d->engine.data());
}
/*!
@@ -505,7 +507,8 @@ QQmlEngine* QQuickWidget::engine() const
QQmlContext* QQuickWidget::rootContext() const
{
Q_D(const QQuickWidget);
- return d->engine ? d->engine.data()->rootContext() : 0;
+ d->ensureEngine();
+ return d->engine.data()->rootContext();
}
/*!
@@ -550,7 +553,7 @@ QQmlContext* QQuickWidget::rootContext() const
QQuickWidget::Status QQuickWidget::status() const
{
Q_D(const QQuickWidget);
- if (!d->engine)
+ if (!d->engine && !d->source.isEmpty())
return QQuickWidget::Error;
if (!d->component)
@@ -576,11 +579,12 @@ QList<QQmlError> QQuickWidget::errors() const
if (d->component)
errs = d->component->errors();
- if (!d->engine) {
+ if (!d->engine && !d->source.isEmpty()) {
QQmlError error;
error.setDescription(QLatin1String("QQuickWidget: invalid qml engine."));
errs << error;
- } else if (d->component && d->component->status() == QQmlComponent::Ready && !d->root) {
+ }
+ if (d->component && d->component->status() == QQmlComponent::Ready && !d->root) {
QQmlError error;
error.setDescription(QLatin1String("QQuickWidget: invalid root object."));
errs << error;
@@ -989,7 +993,9 @@ QSize QQuickWidget::initialSize() const
}
/*!
- Returns the view's root \l {QQuickItem} {item}.
+ Returns the view's root \l {QQuickItem} {item}. Can be null
+ when setContents/setSource has not been called, if they were called with
+ broken QtQuick code or while the QtQuick contents are being created.
*/
QQuickItem *QQuickWidget::rootObject() const
{
@@ -1050,7 +1056,8 @@ void QQuickWidget::resizeEvent(QResizeEvent *e)
void QQuickWidget::keyPressEvent(QKeyEvent *e)
{
Q_D(QQuickWidget);
- Q_QUICK_INPUT_PROFILE(addEvent<QQuickProfiler::Key>());
+ Q_QUICK_INPUT_PROFILE(QQuickProfiler::Key, QQuickProfiler::InputKeyPress, e->key(),
+ e->modifiers());
QCoreApplication::sendEvent(d->offscreenWindow, e);
}
@@ -1059,7 +1066,8 @@ void QQuickWidget::keyPressEvent(QKeyEvent *e)
void QQuickWidget::keyReleaseEvent(QKeyEvent *e)
{
Q_D(QQuickWidget);
- Q_QUICK_INPUT_PROFILE(addEvent<QQuickProfiler::Key>());
+ Q_QUICK_INPUT_PROFILE(QQuickProfiler::Key, QQuickProfiler::InputKeyRelease, e->key(),
+ e->modifiers());
QCoreApplication::sendEvent(d->offscreenWindow, e);
}
@@ -1068,7 +1076,8 @@ void QQuickWidget::keyReleaseEvent(QKeyEvent *e)
void QQuickWidget::mouseMoveEvent(QMouseEvent *e)
{
Q_D(QQuickWidget);
- Q_QUICK_INPUT_PROFILE(addEvent<QQuickProfiler::Mouse>());
+ Q_QUICK_INPUT_PROFILE(QQuickProfiler::Mouse, QQuickProfiler::InputMouseMove, e->localPos().x(),
+ e->localPos().y());
// Use the constructor taking localPos and screenPos. That puts localPos into the
// event's localPos and windowPos, and screenPos into the event's screenPos. This way
@@ -1083,7 +1092,8 @@ void QQuickWidget::mouseMoveEvent(QMouseEvent *e)
void QQuickWidget::mouseDoubleClickEvent(QMouseEvent *e)
{
Q_D(QQuickWidget);
- Q_QUICK_INPUT_PROFILE(addEvent<QQuickProfiler::Mouse>());
+ Q_QUICK_INPUT_PROFILE(QQuickProfiler::Mouse, QQuickProfiler::InputMouseDoubleClick,
+ e->button(), e->buttons());
// As the second mouse press is suppressed in widget windows we emulate it here for QML.
// See QTBUG-25831
@@ -1123,6 +1133,8 @@ void QQuickWidget::showEvent(QShowEvent *)
emit d->offscreenWindow->visibleChanged(true);
offscreenPrivate->updateVisibility();
}
+ if (QQmlInspectorService *service = QQmlDebugConnector::service<QQmlInspectorService>())
+ service->setParentWindow(d->offscreenWindow, window()->windowHandle());
}
/*! \reimp */
@@ -1136,13 +1148,16 @@ void QQuickWidget::hideEvent(QHideEvent *)
emit d->offscreenWindow->visibleChanged(false);
offscreenPrivate->updateVisibility();
}
+ if (QQmlInspectorService *service = QQmlDebugConnector::service<QQmlInspectorService>())
+ service->setParentWindow(d->offscreenWindow, d->offscreenWindow);
}
/*! \reimp */
void QQuickWidget::mousePressEvent(QMouseEvent *e)
{
Q_D(QQuickWidget);
- Q_QUICK_INPUT_PROFILE(addEvent<QQuickProfiler::Mouse>());
+ Q_QUICK_INPUT_PROFILE(QQuickProfiler::Mouse, QQuickProfiler::InputMousePress, e->button(),
+ e->buttons());
QMouseEvent mappedEvent(e->type(), e->localPos(), e->screenPos(), e->button(), e->buttons(), e->modifiers());
QCoreApplication::sendEvent(d->offscreenWindow, &mappedEvent);
@@ -1153,7 +1168,8 @@ void QQuickWidget::mousePressEvent(QMouseEvent *e)
void QQuickWidget::mouseReleaseEvent(QMouseEvent *e)
{
Q_D(QQuickWidget);
- Q_QUICK_INPUT_PROFILE(addEvent<QQuickProfiler::Mouse>());
+ Q_QUICK_INPUT_PROFILE(QQuickProfiler::Mouse, QQuickProfiler::InputMouseRelease, e->button(),
+ e->buttons());
QMouseEvent mappedEvent(e->type(), e->localPos(), e->screenPos(), e->button(), e->buttons(), e->modifiers());
QCoreApplication::sendEvent(d->offscreenWindow, &mappedEvent);
@@ -1165,7 +1181,8 @@ void QQuickWidget::mouseReleaseEvent(QMouseEvent *e)
void QQuickWidget::wheelEvent(QWheelEvent *e)
{
Q_D(QQuickWidget);
- Q_QUICK_INPUT_PROFILE(addEvent<QQuickProfiler::Mouse>());
+ Q_QUICK_INPUT_PROFILE(QQuickProfiler::Mouse, QQuickProfiler::InputMouseWheel,
+ e->angleDelta().x(), e->angleDelta().y());
// Wheel events only have local and global positions, no need to map.
QCoreApplication::sendEvent(d->offscreenWindow, e);
@@ -1305,6 +1322,14 @@ void QQuickWidget::triggerUpdate()
Q_D(QQuickWidget);
d->updatePending = true;
if (!d->eventPending) {
+ // There's no sense in immediately kicking a render off now, as
+ // there may be a number of triggerUpdate calls to come from a multitude
+ // of different sources (network, touch/mouse/keyboard, timers,
+ // animations, ...), and we want to batch them all into single frames as
+ // much as possible for the sake of interactivity and responsiveness.
+ //
+ // To achieve this, we set a timer and only perform the rendering when
+ // this is complete.
const int exhaustDelay = 5;
d->updateTimer.start(exhaustDelay, Qt::PreciseTimer, this);
d->eventPending = true;