Add Window attached property on Item
An Item sometimes needs to know a few things about the window
in which it is being displayed; this attached property can expose
them without needing to go up the heirarchy to find the window.
Instead of adding the QQuickWindow pointer as a property on Item
as in 8f49f50a16
, having an attached
property means that it will not be found by introspection; and
it solves the problem that Window is in the QtQuick.Window module:
you must import the module to use the attached property, instead
of having access to a pointer whose type might not be defined
if you didn't import it. The Window attached property is created
on-demand (so the memory cost adds up if you use it in too many
places); the tradeoff is that it can exist even when the item
is not yet being shown in a window, so bindings at startup work.
The API is purposely incomplete compared to that in QQuickWindow
so that we can introduce what is needed in a controlled fasion
over time. For now we know of use cases for visibility, active
and activeFocusItem.
[ChangeLog][QtQuick][Window] Added Item.Window attached property
Change-Id: I649404cbd1383326678aa2144f790b2f2542dbbc
Reviewed-by: J-P Nurmi <jpnurmi@digia.com>
This commit is contained in:
parent
b4b27168ac
commit
60ed6a433a
|
@ -73,6 +73,7 @@ HEADERS += \
|
|||
$$PWD/qquickitemview_p_p.h \
|
||||
$$PWD/qquickitemviewtransition_p.h \
|
||||
$$PWD/qquickscreen_p.h \
|
||||
$$PWD/qquickwindowattached_p.h \
|
||||
$$PWD/qquickwindowmodule_p.h \
|
||||
$$PWD/qquickframebufferobject.h \
|
||||
$$PWD/qquickitemgrabresult.h \
|
||||
|
@ -129,6 +130,7 @@ SOURCES += \
|
|||
$$PWD/qquickitemviewtransition.cpp \
|
||||
$$PWD/qquickwindowmodule.cpp \
|
||||
$$PWD/qquickscreen.cpp \
|
||||
$$PWD/qquickwindowattached.cpp \
|
||||
$$PWD/qquickframebufferobject.cpp \
|
||||
$$PWD/qquickitemgrabresult.cpp \
|
||||
$$PWD/qquickrendercontrol.cpp
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
|
||||
#include "qquickwindow.h"
|
||||
#include "qquickwindow_p.h"
|
||||
#include "qquickwindowattached_p.h"
|
||||
|
||||
#include "qquickitem.h"
|
||||
#include "qquickitem_p.h"
|
||||
|
@ -3849,6 +3850,18 @@ bool QQuickWindow::glslIsCoreProfile() const
|
|||
\since 5.1
|
||||
*/
|
||||
|
||||
/*!
|
||||
\qmlattachedproperty QWindow::Visibility Window::visibility
|
||||
\since 5.4
|
||||
|
||||
This attached property holds whether whether the window is currently shown
|
||||
in the windowing system as normal, minimized, maximized, fullscreen or
|
||||
hidden. The Window attached property can be attached to any Item. If the
|
||||
item is not shown in any window, the value will be \l {QWindow::}{Hidden}.
|
||||
|
||||
\sa visible, visibility
|
||||
*/
|
||||
|
||||
/*!
|
||||
\qmlproperty Qt::ScreenOrientation Window::contentOrientation
|
||||
|
||||
|
@ -3895,6 +3908,15 @@ bool QQuickWindow::glslIsCoreProfile() const
|
|||
no item with active focus.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\qmlattachedproperty Item Window::activeFocusItem
|
||||
\since 5.4
|
||||
|
||||
This attached property holds the item which currently has active focus or
|
||||
\c null if there is no item with active focus. The Window attached property
|
||||
can be attached to any Item.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\qmlproperty Window::active
|
||||
\since 5.1
|
||||
|
@ -3904,6 +3926,26 @@ bool QQuickWindow::glslIsCoreProfile() const
|
|||
\sa requestActivate()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\qmlattachedproperty bool Window::active
|
||||
\since 5.4
|
||||
|
||||
This attached property tells whether the window is active. The Window
|
||||
attached property can be attached to any Item.
|
||||
|
||||
Here is an example which changes a label to show the active state of the
|
||||
window in which it is shown:
|
||||
|
||||
\qml
|
||||
import QtQuick 2.4
|
||||
import QtQuick.Window 2.2
|
||||
|
||||
Text {
|
||||
text: Window.active ? "active" : "inactive"
|
||||
}
|
||||
\endqml
|
||||
*/
|
||||
|
||||
/*!
|
||||
\qmlmethod QtQuick::Window::requestActivate()
|
||||
\since 5.1
|
||||
|
@ -3983,6 +4025,11 @@ void QQuickWindow::scheduleRenderJob(QRunnable *job, RenderStage stage)
|
|||
d->renderJobMutex.unlock();
|
||||
}
|
||||
|
||||
QQuickWindowAttached *QQuickWindow::qmlAttachedProperties(QObject *object)
|
||||
{
|
||||
return new QQuickWindowAttached(object);
|
||||
}
|
||||
|
||||
void QQuickWindowPrivate::runAndClearJobs(QList<QRunnable *> *jobs)
|
||||
{
|
||||
renderJobMutex.lock();
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
#include <QtGui/qopengl.h>
|
||||
#include <QtGui/qwindow.h>
|
||||
#include <QtGui/qevent.h>
|
||||
#include <qqml.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
|
@ -55,6 +56,7 @@ class QQuickItem;
|
|||
class QSGTexture;
|
||||
class QInputMethodEvent;
|
||||
class QQuickWindowPrivate;
|
||||
class QQuickWindowAttached;
|
||||
class QOpenGLFramebufferObject;
|
||||
class QQmlIncubationController;
|
||||
class QInputMethodEvent;
|
||||
|
@ -156,6 +158,8 @@ public:
|
|||
|
||||
void scheduleRenderJob(QRunnable *job, RenderStage schedule);
|
||||
|
||||
static QQuickWindowAttached *qmlAttachedProperties(QObject *object);
|
||||
|
||||
Q_SIGNALS:
|
||||
void frameSwapped();
|
||||
Q_REVISION(2) void openglContextCreated(QOpenGLContext *context);
|
||||
|
@ -220,6 +224,7 @@ private:
|
|||
QT_END_NAMESPACE
|
||||
|
||||
Q_DECLARE_METATYPE(QQuickWindow *)
|
||||
QML_DECLARE_TYPEINFO(QQuickWindow, QML_HAS_ATTACHED_PROPERTIES)
|
||||
|
||||
#endif // QQUICKWINDOW_H
|
||||
|
||||
|
|
|
@ -0,0 +1,110 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** This file is part of the QtQuick module of the Qt Toolkit.
|
||||
**
|
||||
** $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 Digia. For licensing terms and
|
||||
** conditions see http://qt.digia.com/licensing. For further information
|
||||
** use the contact form at http://qt.digia.com/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 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, Digia gives you certain additional
|
||||
** rights. These rights are described in the Digia Qt 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 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU General Public License version 3.0 requirements will be
|
||||
** met: http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "qquickwindow.h"
|
||||
#include "qquickitem.h"
|
||||
#include "qquickwindowattached_p.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
// QDoc comments must go in qquickwindow.cpp to avoid overwriting the Window docs
|
||||
|
||||
QQuickWindowAttached::QQuickWindowAttached(QObject* attachee)
|
||||
: QObject(attachee)
|
||||
, m_window(NULL)
|
||||
{
|
||||
m_attachee = qobject_cast<QQuickItem*>(attachee);
|
||||
if (m_attachee && m_attachee->window()) // It might not be in a window yet
|
||||
windowChanged(m_attachee->window());
|
||||
if (m_attachee)
|
||||
connect(m_attachee, &QQuickItem::windowChanged, this, &QQuickWindowAttached::windowChanged);
|
||||
}
|
||||
|
||||
QWindow::Visibility QQuickWindowAttached::visibility() const
|
||||
{
|
||||
return (m_window ? m_window->visibility() : QWindow::Hidden);
|
||||
}
|
||||
|
||||
bool QQuickWindowAttached::isActive() const
|
||||
{
|
||||
return (m_window ? m_window->isActive() : false);
|
||||
}
|
||||
|
||||
QQuickItem *QQuickWindowAttached::activeFocusItem() const
|
||||
{
|
||||
return (m_window ? m_window->activeFocusItem() : Q_NULLPTR);
|
||||
}
|
||||
|
||||
void QQuickWindowAttached::windowChanged(QQuickWindow *window)
|
||||
{
|
||||
if (window != m_window) {
|
||||
QQuickWindow* oldWindow = m_window;
|
||||
m_window = window;
|
||||
|
||||
if (oldWindow)
|
||||
oldWindow->disconnect(this);
|
||||
|
||||
if (!window)
|
||||
return; // No values to get, therefore nothing to emit
|
||||
|
||||
if (!oldWindow || window->visibility() != oldWindow->visibility())
|
||||
emit visibilityChanged();
|
||||
if (!oldWindow || window->isActive() != oldWindow->isActive())
|
||||
emit activeChanged();
|
||||
if (!oldWindow || window->activeFocusItem() != oldWindow->activeFocusItem())
|
||||
emit activeFocusItemChanged();
|
||||
|
||||
// QQuickWindowQmlImpl::visibilityChanged also exists, and window might even
|
||||
// be QQuickWindowQmlImpl, but that's not what we are connecting to.
|
||||
// So this is actual window state rather than a buffered or as-requested one.
|
||||
// If we used the metaobject connect syntax there would be a warning:
|
||||
// QMetaObjectPrivate::indexOfSignalRelative - QMetaObject::indexOfSignal:
|
||||
// signal visibilityChanged(QWindow::Visibility) from QQuickWindow redefined in QQuickWindowQmlImpl
|
||||
connect(window, &QQuickWindow::visibilityChanged,
|
||||
this, &QQuickWindowAttached::visibilityChanged);
|
||||
connect(window, &QQuickWindow::activeChanged,
|
||||
this, &QQuickWindowAttached::activeChanged);
|
||||
connect(window, &QQuickWindow::activeFocusItemChanged,
|
||||
this, &QQuickWindowAttached::activeFocusItemChanged);
|
||||
}
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
|
@ -0,0 +1,84 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** This file is part of the QtQuick module of the Qt Toolkit.
|
||||
**
|
||||
** $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 Digia. For licensing terms and
|
||||
** conditions see http://qt.digia.com/licensing. For further information
|
||||
** use the contact form at http://qt.digia.com/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 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, Digia gives you certain additional
|
||||
** rights. These rights are described in the Digia Qt 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 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU General Public License version 3.0 requirements will be
|
||||
** met: http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef QQUICKWINDOW_ATTACHED_P_H
|
||||
#define QQUICKWINDOW_ATTACHED_P_H
|
||||
|
||||
#include <qqml.h>
|
||||
#include <QWindow>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QQuickItem;
|
||||
class QQuickWindow;
|
||||
|
||||
class Q_AUTOTEST_EXPORT QQuickWindowAttached : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(QWindow::Visibility visibility READ visibility NOTIFY visibilityChanged)
|
||||
Q_PROPERTY(bool active READ isActive NOTIFY activeChanged)
|
||||
Q_PROPERTY(QQuickItem* activeFocusItem READ activeFocusItem NOTIFY activeFocusItemChanged)
|
||||
|
||||
public:
|
||||
QQuickWindowAttached(QObject* attachee);
|
||||
|
||||
QWindow::Visibility visibility() const;
|
||||
bool isActive() const;
|
||||
QQuickItem* activeFocusItem() const;
|
||||
|
||||
Q_SIGNALS:
|
||||
|
||||
void visibilityChanged();
|
||||
void activeChanged();
|
||||
void activeFocusItemChanged();
|
||||
|
||||
protected Q_SLOTS:
|
||||
void windowChanged(QQuickWindow*);
|
||||
|
||||
private:
|
||||
QQuickWindow* m_window;
|
||||
QQuickItem* m_attachee;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif
|
|
@ -40,6 +40,7 @@
|
|||
****************************************************************************/
|
||||
|
||||
#include "qquickwindowmodule_p.h"
|
||||
#include "qquickwindowattached_p.h"
|
||||
#include "qquickscreen_p.h"
|
||||
#include "qquickview_p.h"
|
||||
#include <QtQuick/QQuickWindow>
|
||||
|
@ -173,6 +174,10 @@ void QQuickWindowModule::defineModule()
|
|||
{
|
||||
const char uri[] = "QtQuick.Window";
|
||||
|
||||
// Since Window is both an attached property and a createable type,
|
||||
// the attached property declaration must come first so that it can
|
||||
// be overridden below.
|
||||
qmlRegisterUncreatableType<QQuickWindow>(uri, 2, 2, "Window", QQuickWindow::tr("Window is available via attached properties"));
|
||||
qmlRegisterType<QQuickWindow>(uri, 2, 0, "Window");
|
||||
qmlRegisterRevision<QWindow,1>(uri, 2, 1);
|
||||
qmlRegisterRevision<QWindow,2>(uri, 2, 2);
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
import QtQuick 2.4
|
||||
import QtQuick.Window 2.2
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
width: 100
|
||||
height: 100
|
||||
property bool windowActive: root.Window.active
|
||||
Text {
|
||||
objectName: "rectangleWindowText"
|
||||
anchors.centerIn: parent
|
||||
text: (windowActive ? "active" : "inactive") + "\nvisibility: " + root.Window.visibility
|
||||
}
|
||||
|
||||
property Window extraWindow: Window {
|
||||
objectName: "extraWindow"
|
||||
title: "extra window"
|
||||
visible: true
|
||||
Text {
|
||||
objectName: "extraWindowText"
|
||||
anchors.centerIn: parent
|
||||
text: (extraWindow.active ? "active" : "inactive") + "\nvisibility: " + Window.visibility
|
||||
}
|
||||
}
|
||||
}
|
|
@ -43,6 +43,7 @@
|
|||
#include <QDebug>
|
||||
#include <QTouchEvent>
|
||||
#include <QtQuick/QQuickItem>
|
||||
#include <QtQuick/QQuickView>
|
||||
#include <QtQuick/QQuickWindow>
|
||||
#include <QtQml/QQmlEngine>
|
||||
#include <QtQml/QQmlComponent>
|
||||
|
@ -368,6 +369,8 @@ private slots:
|
|||
void defaultSurfaceFormat();
|
||||
void glslVersion();
|
||||
|
||||
void attachedProperty();
|
||||
|
||||
void testRenderJob();
|
||||
|
||||
private:
|
||||
|
@ -1974,6 +1977,24 @@ void tst_qquickwindow::glslVersion()
|
|||
}
|
||||
}
|
||||
|
||||
void tst_qquickwindow::attachedProperty()
|
||||
{
|
||||
QQuickView view(testFileUrl("windowattached.qml"));
|
||||
view.show();
|
||||
view.requestActivate();
|
||||
QVERIFY(QTest::qWaitForWindowActive(&view));
|
||||
QVERIFY(view.rootObject()->property("windowActive").toBool());
|
||||
|
||||
QQuickWindow *innerWindow = view.rootObject()->findChild<QQuickWindow*>("extraWindow");
|
||||
QVERIFY(innerWindow);
|
||||
innerWindow->requestActivate();
|
||||
QVERIFY(QTest::qWaitForWindowActive(innerWindow));
|
||||
|
||||
QQuickText *text = view.rootObject()->findChild<QQuickText*>("extraWindowText");
|
||||
QVERIFY(text);
|
||||
QCOMPARE(text->text(), QLatin1String("active\nvisibility: 2"));
|
||||
}
|
||||
|
||||
class RenderJob : public QRunnable
|
||||
{
|
||||
public:
|
||||
|
|
Loading…
Reference in New Issue