1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qquickwindowmodule_p.h"
5#include "qquickwindowattached_p.h"
6#include "qquickrendercontrol.h"
7#include "qquickscreen_p.h"
8#include "qquickview_p.h"
9#include "qquickwindowmodule_p_p.h"
10#include "qquickitem_p.h"
11#include <QtQuick/QQuickWindow>
12#include <QtCore/QCoreApplication>
13#include <QtQml/QQmlEngine>
14
15#include <private/qguiapplication_p.h>
16#include <private/qqmlengine_p.h>
17#include <private/qv4qobjectwrapper_p.h>
18#include <private/qqmlglobal_p.h>
19#include <qpa/qplatformintegration.h>
20
21QT_BEGIN_NAMESPACE
22
23Q_DECLARE_LOGGING_CATEGORY(lcTransient)
24
25QQuickWindowQmlImplPrivate::QQuickWindowQmlImplPrivate() = default;
26
27QQuickWindowQmlImpl::QQuickWindowQmlImpl(QWindow *parent)
28 : QQuickWindowQmlImpl(*(new QQuickWindowQmlImplPrivate), parent)
29{
30}
31
32void QQuickWindowQmlImpl::setVisible(bool visible)
33{
34 Q_D(QQuickWindowQmlImpl);
35 d->visible = visible;
36 d->visibleExplicitlySet = true;
37 if (d->componentComplete && (!transientParent() || transientParentVisible()))
38 QQuickWindow::setVisible(visible);
39}
40
41void QQuickWindowQmlImpl::setVisibility(Visibility visibility)
42{
43 Q_D(QQuickWindowQmlImpl);
44 d->visibility = visibility;
45 if (d->componentComplete)
46 QQuickWindow::setVisibility(visibility);
47}
48
49QQuickWindowAttached *QQuickWindowQmlImpl::qmlAttachedProperties(QObject *object)
50{
51 return new QQuickWindowAttached(object);
52}
53
54void QQuickWindowQmlImpl::classBegin()
55{
56 Q_D(QQuickWindowQmlImpl);
57 d->componentComplete = false;
58 QQmlEngine* e = qmlEngine(this);
59
60 QQmlEngine::setContextForObject(contentItem(), e->rootContext());
61
62 //Give QQuickView behavior when created from QML with QQmlApplicationEngine
63 if (QCoreApplication::instance()->property(name: "__qml_using_qqmlapplicationengine") == QVariant(true)) {
64 if (e && !e->incubationController())
65 e->setIncubationController(incubationController());
66 }
67 {
68 // The content item has CppOwnership policy (set in QQuickWindow). Ensure the presence of a JS
69 // wrapper so that the garbage collector can see the policy.
70 QV4::ExecutionEngine *v4 = e->handle();
71 QV4::QObjectWrapper::wrap(engine: v4, object: d->contentItem);
72 }
73}
74
75void QQuickWindowQmlImpl::componentComplete()
76{
77 Q_D(QQuickWindowQmlImpl);
78 d->componentComplete = true;
79
80 QQuickItem *itemParent = qmlobject_cast<QQuickItem *>(object: QObject::parent());
81 const bool transientParentAlreadySet = QQuickWindowPrivate::get(c: this)->transientParentPropertySet;
82 if (!transientParentAlreadySet && itemParent && !itemParent->window()) {
83 qCDebug(lcTransient) << "window" << title() << "has invisible Item parent" << itemParent << "transientParent"
84 << transientParent() << "declared visibility" << d->visibility << "; delaying show";
85 connect(sender: itemParent, signal: &QQuickItem::windowChanged, context: this,
86 slot: &QQuickWindowQmlImpl::setWindowVisibility, type: Qt::QueuedConnection);
87 } else if (transientParent() && !transientParent()->isVisible()) {
88 connect(sender: transientParent(), signal: &QQuickWindow::visibleChanged, context: this,
89 slot: &QQuickWindowQmlImpl::setWindowVisibility, type: Qt::QueuedConnection);
90 } else {
91 setWindowVisibility();
92 }
93}
94
95QQuickWindowQmlImpl::QQuickWindowQmlImpl(QQuickWindowQmlImplPrivate &dd, QWindow *parent)
96 : QQuickWindow(dd, parent)
97{
98 // These two signals are called during QWindow's dtor, thus they have to be queued connections
99 // or else our slots will be called instantly when our destructor has already run but our
100 // connections haven't been removed yet.
101 connect(sender: this, signal: &QWindow::visibleChanged, context: this, slot: &QQuickWindowQmlImpl::visibleChanged,
102 type: Qt::QueuedConnection);
103 connect(sender: this, signal: &QWindow::visibilityChanged, context: this, slot: &QQuickWindowQmlImpl::visibilityChanged,
104 type: Qt::QueuedConnection);
105
106 connect(sender: this, signal: &QWindow::screenChanged, context: this, slot: &QQuickWindowQmlImpl::screenChanged);
107}
108
109void QQuickWindowQmlImpl::setWindowVisibility()
110{
111 Q_D(QQuickWindowQmlImpl);
112 if (transientParent() && !transientParentVisible())
113 return;
114
115 if (QQuickItem *senderItem = qmlobject_cast<QQuickItem *>(object: sender())) {
116 disconnect(sender: senderItem, signal: &QQuickItem::windowChanged, receiver: this, slot: &QQuickWindowQmlImpl::setWindowVisibility);
117 } else if (sender()) {
118 disconnect(sender: transientParent(), signal: &QWindow::visibleChanged, receiver: this, slot: &QQuickWindowQmlImpl::setWindowVisibility);
119 }
120
121 // We have deferred window creation until we have the full picture of what
122 // the user wanted in terms of window state, geometry, visibility, etc.
123
124 if (d->visibleExplicitlySet && ((d->visibility == Hidden && d->visible) ||
125 (d->visibility > AutomaticVisibility && !d->visible))) {
126 QQmlData *data = QQmlData::get(object: this);
127 Q_ASSERT(data && data->context);
128
129 QQmlError error;
130 error.setObject(this);
131
132 QQmlRefPointer<QQmlContextData> urlContext = data->context;
133 while (urlContext && urlContext->url().isEmpty())
134 urlContext = urlContext->parent();
135 error.setUrl(urlContext ? urlContext->url() : QUrl());
136
137 QString objectId = data->context->findObjectId(obj: this);
138 if (!objectId.isEmpty())
139 error.setDescription(QCoreApplication::translate(context: "QQuickWindowQmlImpl",
140 key: "Conflicting properties 'visible' and 'visibility' for Window '%1'").arg(a: objectId));
141 else
142 error.setDescription(QCoreApplication::translate(context: "QQuickWindowQmlImpl",
143 key: "Conflicting properties 'visible' and 'visibility'"));
144
145 QQmlEnginePrivate::get(e: data->context->engine())->warning(error);
146 }
147
148 if (d->visibility == AutomaticVisibility) {
149 setWindowState(QGuiApplicationPrivate::platformIntegration()->defaultWindowState(flags()));
150 setVisible(d->visible);
151 } else {
152 setVisibility(d->visibility);
153 }
154}
155
156QObject *QQuickWindowQmlImpl::screen() const
157{
158 return new QQuickScreenInfo(const_cast<QQuickWindowQmlImpl *>(this), QWindow::screen());
159}
160
161void QQuickWindowQmlImpl::setScreen(QObject *screen)
162{
163 QQuickScreenInfo *screenWrapper = qobject_cast<QQuickScreenInfo *>(object: screen);
164 QWindow::setScreen(screenWrapper ? screenWrapper->wrappedScreen() : nullptr);
165}
166
167bool QQuickWindowQmlImpl::transientParentVisible()
168{
169 Q_ASSERT(transientParent());
170 if (!transientParent()->isVisible()) {
171 // handle case where transient parent is offscreen window
172 QWindow *rw = QQuickRenderControl::renderWindowFor(win: qobject_cast<QQuickWindow*>(object: transientParent()));
173 return rw && rw->isVisible();
174 }
175 return true;
176}
177
178QT_END_NAMESPACE
179
180#include "moc_qquickwindowmodule_p.cpp"
181

source code of qtdeclarative/src/quick/items/qquickwindowmodule.cpp