aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick/items/qquickwindow.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/quick/items/qquickwindow.cpp')
-rw-r--r--src/quick/items/qquickwindow.cpp320
1 files changed, 261 insertions, 59 deletions
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp
index 4789314e01..619c72afb8 100644
--- a/src/quick/items/qquickwindow.cpp
+++ b/src/quick/items/qquickwindow.cpp
@@ -72,6 +72,10 @@
QT_BEGIN_NAMESPACE
+extern Q_GUI_EXPORT QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format, bool include_alpha);
+
+bool QQuickWindowPrivate::defaultAlphaBuffer(0);
+
void QQuickWindowPrivate::updateFocusItemTransform()
{
Q_Q(QQuickWindow);
@@ -85,44 +89,49 @@ void QQuickWindowPrivate::updateFocusItemTransform()
#endif
}
-
class QQuickWindowIncubationController : public QObject, public QQmlIncubationController
{
Q_OBJECT
public:
- QQuickWindowIncubationController(const QQuickWindow *window)
- : m_window(QQuickWindowPrivate::get(const_cast<QQuickWindow *>(window)))
+ QQuickWindowIncubationController(QSGRenderLoop *loop)
+ : m_renderLoop(loop), m_timer(0)
{
// Allow incubation for 1/3 of a frame.
m_incubation_time = qMax(1, int(1000 / QGuiApplication::primaryScreen()->refreshRate()) / 3);
- m_animation_driver = m_window->windowManager->animationDriver();
+ m_animation_driver = m_renderLoop->animationDriver();
if (m_animation_driver) {
connect(m_animation_driver, SIGNAL(stopped()), this, SLOT(animationStopped()));
- connect(window, SIGNAL(frameSwapped()), this, SLOT(incubate()));
+ connect(m_renderLoop, SIGNAL(timeToIncubate()), this, SLOT(incubate()));
}
}
protected:
- virtual bool event(QEvent *e)
+ void timerEvent(QTimerEvent *)
{
- if (e->type() == QEvent::User) {
- incubate();
- return true;
+ killTimer(m_timer);
+ m_timer = 0;
+ incubate();
+ }
+
+ void incubateAgain() {
+ if (m_timer == 0) {
+ // Wait for a while before processing the next batch. Using a
+ // timer to avoid starvation of system events.
+ m_timer = startTimer(m_incubation_time);
}
- return QObject::event(e);
}
public slots:
void incubate() {
if (incubatingObjectCount()) {
- if (m_animation_driver && m_animation_driver->isRunning()) {
+ if (m_renderLoop->interleaveIncubation()) {
incubateFor(m_incubation_time);
} else {
incubateFor(m_incubation_time * 2);
if (incubatingObjectCount())
- QCoreApplication::postEvent(this, new QEvent(QEvent::User));
+ incubateAgain();
}
}
}
@@ -132,14 +141,15 @@ public slots:
protected:
virtual void incubatingObjectCountChanged(int count)
{
- if (count && (!m_animation_driver || !m_animation_driver->isRunning()))
- QCoreApplication::postEvent(this, new QEvent(QEvent::User));
+ if (count && !m_renderLoop->interleaveIncubation())
+ incubateAgain();
}
private:
- QQuickWindowPrivate *m_window;
+ QSGRenderLoop *m_renderLoop;
int m_incubation_time;
QAnimationDriver *m_animation_driver;
+ int m_timer;
};
#include "qquickwindow.moc"
@@ -149,8 +159,6 @@ private:
/*!
Returns an accessibility interface for this window, or 0 if such an
interface cannot be created.
-
- \warning The caller is responsible for deleting the returned interface.
*/
QAccessibleInterface *QQuickWindow::accessibleRoot() const
{
@@ -258,29 +266,6 @@ void QQuickWindowPrivate::polishItems()
updateFocusItemTransform();
}
-/**
- * This parameter enables that this window can be rendered without
- * being shown on screen. This feature is very limited in what it supports.
- *
- * For this feature to be useful one needs to hook into beforeRender()
- * and set the render target.
- *
- */
-void QQuickWindowPrivate::setRenderWithoutShowing(bool render)
-{
- if (render == renderWithoutShowing)
- return;
-
- Q_Q(QQuickWindow);
- renderWithoutShowing = render;
-
- if (render)
- windowManager->show(q);
- else
- windowManager->hide(q);
-}
-
-
/*!
* Schedules the window to render another frame.
*
@@ -361,7 +346,6 @@ QQuickWindowPrivate::QQuickWindowPrivate()
#endif
, touchMouseId(-1)
, touchMousePressTimestamp(0)
- , renderWithoutShowing(false)
, dirtyItemList(0)
, context(0)
, renderer(0)
@@ -371,6 +355,7 @@ QQuickWindowPrivate::QQuickWindowPrivate()
, persistentGLContext(true)
, persistentSceneGraph(true)
, lastWheelEventAccepted(false)
+ , componentCompleted(true)
, renderTarget(0)
, renderTargetId(0)
, incubationController(0)
@@ -414,7 +399,10 @@ void QQuickWindowPrivate::init(QQuickWindow *c)
QQmlListProperty<QObject> QQuickWindowPrivate::data()
{
initContentItem();
- return QQuickItemPrivate::get(contentItem)->data();
+ return QQmlListProperty<QObject>(q_func(), 0, QQuickWindowPrivate::data_append,
+ QQuickWindowPrivate::data_count,
+ QQuickWindowPrivate::data_at,
+ QQuickWindowPrivate::data_clear);
}
void QQuickWindowPrivate::initContentItem()
@@ -432,7 +420,7 @@ static QMouseEvent *touchToMouseEvent(QEvent::Type type, const QTouchEvent::Touc
{
// The touch point local position and velocity are not yet transformed.
QMouseEvent *me = new QMouseEvent(type, transformNeeded ? item->mapFromScene(p.scenePos()) : p.pos(), p.scenePos(), p.screenPos(),
- Qt::LeftButton, Qt::LeftButton, event->modifiers());
+ Qt::LeftButton, (type == QEvent::MouseButtonRelease ? Qt::NoButton : Qt::LeftButton), event->modifiers());
me->setAccepted(true);
me->setTimestamp(event->timestamp());
QVector2D transformedVelocity = p.velocity();
@@ -838,15 +826,34 @@ void QQuickWindowPrivate::cleanup(QSGNode *n)
\ingroup qtquick-visual
\brief Creates a new top-level window
- The Window object creates a new top-level window for a QtQuick scene. It automatically sets up the
- window for use with QtQuick 2.x graphical types.
+ The Window object creates a new top-level window for a Qt Quick scene. It automatically sets up the
+ window for use with \c {QtQuick 2.x} graphical types.
To use this type, you will need to import the module with the following line:
\code
import QtQuick.Window 2.1
\endcode
- Restricting this import will allow you to have a QML environment without access to window system features.
+ Omitting this import will allow you to have a QML environment without
+ access to window system features.
+
+ A Window can be declared inside an Item or inside another Window; in that
+ case the inner Window will automatically become "transient for" the outer
+ Window: that is, most platforms will show it centered upon the outer window
+ by default, and there may be other platform-dependent behaviors, depending
+ also on the \l flags. If the nested window is intended to be a dialog in
+ your application, you should also set \l flags to Qt.Dialog, because some
+ window managers will not provide the centering behavior without that flag.
+ You can also declare multiple windows inside a top-level \l QtObject, in which
+ case the windows will have no transient relationship.
+
+ Alternatively you can set or bind \l x and \l y to position the Window
+ explicitly on the screen.
+
+ When the user attempts to close a window, the \a closing signal will be
+ emitted. You can force the window to stay open (for example to prompt the
+ user to save changes) by writing an onClosing handler and setting
+ close.accepted = false.
*/
/*!
\class QQuickWindow
@@ -1094,7 +1101,10 @@ QQuickItem *QQuickWindow::contentItem() const
}
/*!
- Returns the item which currently has active focus.
+ \property QQuickWindow::activeFocusItem
+
+ \brief The item which currently has active focus or \c null if there is
+ no item with active focus.
*/
QQuickItem *QQuickWindow::activeFocusItem() const
{
@@ -1178,6 +1188,14 @@ bool QQuickWindow::event(QEvent *e)
case QEvent::WindowDeactivate:
contentItem()->windowDeactivateEvent();
break;
+ case QEvent::Close: {
+ // TOOD Qt 6 (binary incompatible)
+ // closeEvent(static_cast<QCloseEvent *>(e));
+ QQuickCloseEvent qev;
+ qev.setAccepted(e->isAccepted());
+ emit closing(&qev);
+ e->setAccepted(qev.isAccepted());
+ } break;
case QEvent::FocusAboutToChange:
#ifndef QT_NO_IM
if (d->activeFocusItem)
@@ -2037,16 +2055,68 @@ bool QQuickWindowPrivate::dragOverThreshold(qreal d, Qt::Axis axis, QMouseEvent
return overThreshold;
}
+/*!
+ \qmlproperty list<Object> QtQuick.Window2::Window::data
+ \default
+
+ The data property allows you to freely mix visual children, resources
+ and other Windows in a Window.
+
+ If you assign another Window to the data list, the nested window will
+ become "transient for" the outer Window.
+
+ If you assign an \l Item to the data list, it becomes a child of the
+ Window's \l contentItem, so that it appears inside the window. The item's
+ parent will be the window's contentItem, which is the root of the Item
+ ownership tree within that Window.
+
+ If you assign any other object type, it is added as a resource.
+
+ It should not generally be necessary to refer to the \c data property,
+ as it is the default property for Window and thus all child items are
+ automatically assigned to this property.
+
+ \sa QWindow::transientParent()
+ */
+
+void QQuickWindowPrivate::data_append(QQmlListProperty<QObject> *property, QObject *o)
+{
+ if (!o)
+ return;
+ QQuickWindow *that = static_cast<QQuickWindow *>(property->object);
+ if (QQuickWindow *window = qmlobject_cast<QQuickWindow *>(o))
+ window->setTransientParent(that);
+ QQmlListProperty<QObject> itemProperty = QQuickItemPrivate::get(that->contentItem())->data();
+ itemProperty.append(&itemProperty, o);
+}
+
+int QQuickWindowPrivate::data_count(QQmlListProperty<QObject> *property)
+{
+ QQuickWindow *win = static_cast<QQuickWindow*>(property->object);
+ if (!win || !win->contentItem() || !QQuickItemPrivate::get(win->contentItem())->data().count)
+ return 0;
+ QQmlListProperty<QObject> itemProperty = QQuickItemPrivate::get(win->contentItem())->data();
+ return itemProperty.count(&itemProperty);
+}
+
+QObject *QQuickWindowPrivate::data_at(QQmlListProperty<QObject> *property, int i)
+{
+ QQuickWindow *win = static_cast<QQuickWindow*>(property->object);
+ QQmlListProperty<QObject> itemProperty = QQuickItemPrivate::get(win->contentItem())->data();
+ return itemProperty.at(&itemProperty, i);
+}
+
+void QQuickWindowPrivate::data_clear(QQmlListProperty<QObject> *property)
+{
+ QQuickWindow *win = static_cast<QQuickWindow*>(property->object);
+ QQmlListProperty<QObject> itemProperty = QQuickItemPrivate::get(win->contentItem())->data();
+ itemProperty.clear(&itemProperty);
+}
+
bool QQuickWindowPrivate::isRenderable() const
{
- const QQuickWindow *q = q_func();
- QRect geom = q->geometry();
- if (geom.width() <= 0 || geom.height() <= 0)
- return false;
- // Change to be applied after the visibility property is integrated in qtbase:
-// return visibility != QWindow::Hidden || (renderWithoutShowing && platformWindow);
- // Temporary version which is implementation-agnostic but slightly less efficient:
- return q->isVisible() || (renderWithoutShowing && platformWindow);
+ Q_Q(const QQuickWindow);
+ return q->isExposed() && q->isVisible() && q->geometry().isValid();
}
/*!
@@ -2456,6 +2526,13 @@ void QQuickWindow::cleanupSceneGraph()
d->renderer = 0;
}
+void QQuickWindow::setTransientParent_helper(QQuickWindow *window)
+{
+ setTransientParent(window);
+ disconnect(sender(), SIGNAL(windowChanged(QQuickWindow*)),
+ this, SLOT(setTransientParent_helper(QQuickWindow*)));
+}
+
/*!
Returns the opengl context used for rendering.
@@ -2503,6 +2580,57 @@ QOpenGLContext *QQuickWindow::openglContext() const
This signal will be emitted from the scene graph rendering thread.
*/
+/*!
+ \class QQuickCloseEvent
+ \internal
+ \since QtQuick 2.1
+
+ \inmodule QtQuick.Window
+
+ \brief Notification that a \l QQuickWindow is about to be closed
+*/
+/*!
+ \qmltype CloseEvent
+ \instantiates QQuickCloseEvent
+ \inqmlmodule QtQuick.Window 2
+ \ingroup qtquick-visual
+ \brief Notification that a \l Window is about to be closed
+ \since Qt 5.1
+
+ Notification that a window is about to be closed by the windowing system
+ (e.g. the user clicked the titlebar close button). The CloseEvent contains
+ an accepted property which can be set to false to abort closing the window.
+
+ \sa Window.closing()
+*/
+
+/*!
+ \qmlproperty bool QtQuick.Window2::CloseEvent::accepted
+
+ This property indicates whether the application will allow the user to
+ close the window. It is true by default.
+*/
+
+/*!
+ \fn void QQuickWindow::closing()
+ \since QtQuick 2.1
+
+ This signal is emitted when the window receives a QCloseEvent from the
+ windowing system.
+*/
+
+/*!
+ \qmlsignal QtQuick.Window2::closing(CloseEvent close)
+ \since Qt 5.1
+
+ This signal is emitted when the user tries to close the window.
+
+ This signal includes a closeEvent parameter. The \a close \l accepted
+ property is true by default so that the window is allowed to close; but you
+ can implement an onClosing() handler and set close.accepted = false if
+ you need to do something else before the window can be closed.
+ */
+
/*!
Sets the render target for this window to be \a fbo.
@@ -2600,7 +2728,10 @@ QOpenGLFramebufferObject *QQuickWindow::renderTarget() const
/*!
Grabs the contents of the window and returns it as an image.
- This function might not work if the window is not visible.
+ It is possible to call the grabWindow() function when the window is not
+ visible. This requires that the window is \l{QWindow::create} {created}
+ and has a valid size and that no other QQuickWindow instances are rendering
+ in the same process.
\warning Calling this function will cause performance problems.
@@ -2609,6 +2740,36 @@ QOpenGLFramebufferObject *QQuickWindow::renderTarget() const
QImage QQuickWindow::grabWindow()
{
Q_D(QQuickWindow);
+ if (!isVisible()) {
+
+ if (d->context->isReady()) {
+ qWarning("QQuickWindow::grabWindow: scene graph already in use");
+ return QImage();
+ }
+
+ if (!handle() || !size().isValid()) {
+ qWarning("QQuickWindow::grabWindow: window must be created and have a valid size");
+ return QImage();
+ }
+
+ QOpenGLContext context;
+ context.setFormat(requestedFormat());
+ context.create();
+ context.makeCurrent(this);
+ d->context->initialize(&context);
+
+ d->polishItems();
+ d->syncSceneGraph();
+ d->renderSceneGraph(size());
+
+ QImage image = qt_gl_read_framebuffer(size(), false, false);
+ d->cleanupNodesOnShutdown();
+ d->context->invalidate();
+ context.doneCurrent();
+
+ return image;
+ }
+
return d->windowManager->grab(this);
}
@@ -2625,7 +2786,7 @@ QQmlIncubationController *QQuickWindow::incubationController() const
Q_D(const QQuickWindow);
if (!d->incubationController)
- d->incubationController = new QQuickWindowIncubationController(this);
+ d->incubationController = new QQuickWindowIncubationController(d->windowManager);
return d->incubationController;
}
@@ -2817,7 +2978,7 @@ QSGTexture *QQuickWindow::createTextureFromId(uint id, const QSize &size, Create
Setting the clear color has no effect when clearing is disabled.
By default, the clear color is white.
- \sa setClearBeforeRendering()
+ \sa setClearBeforeRendering(), setDefaultAlphaBuffer()
*/
void QQuickWindow::setColor(const QColor &color)
@@ -2827,7 +2988,7 @@ void QQuickWindow::setColor(const QColor &color)
return;
if (color.alpha() != d->clearColor.alpha()) {
- QSurfaceFormat fmt = format();
+ QSurfaceFormat fmt = requestedFormat();
if (color.alpha() < 255)
fmt.setAlphaBufferSize(8);
else
@@ -2845,6 +3006,31 @@ QColor QQuickWindow::color() const
}
/*!
+ \brief Returns whether to use alpha transparency on newly created windows.
+
+ \since Qt 5.1
+ \sa setDefaultAlphaBuffer()
+ */
+bool QQuickWindow::hasDefaultAlphaBuffer()
+{
+ return QQuickWindowPrivate::defaultAlphaBuffer;
+}
+
+/*!
+ \brief \a useAlpha specifies whether to use alpha transparency on newly created windows.
+ \since Qt 5.1
+
+ In any application which expects to create translucent windows, it's
+ necessary to set this to true before creating the first QQuickWindow,
+ because all windows will share the same \l QOpenGLContext. The default
+ value is false.
+ */
+void QQuickWindow::setDefaultAlphaBuffer(bool useAlpha)
+{
+ QQuickWindowPrivate::defaultAlphaBuffer = useAlpha;
+}
+
+/*!
\qmlproperty string QtQuick.Window2::Window::title
The window's title in the windowing system.
@@ -2994,6 +3180,22 @@ QColor QQuickWindow::color() const
no item with active focus.
*/
+/*!
+ \qmlproperty QtQuick.Window2::Window::active
+ \since Qt 5.1
+
+ The active status of the window.
+
+ \sa requestActivate()
+ */
+
+/*!
+ \qmlmethod QtQuick2::Window::requestActivate()
+ \since QtQuick 2.1
+
+ Requests the window to be activated, i.e. receive keyboard focus.
+ */
+
#include "moc_qquickwindow.cpp"
QT_END_NAMESPACE