12#include <QtQuick/QQuickWindow>
13#include <QtCore/QCoreApplication>
14#include <QtQml/QQmlEngine>
16#include <private/qguiapplication_p.h>
17#include <private/qqmlengine_p.h>
18#include <private/qv4qobjectwrapper_p.h>
19#include <private/qqmlglobal_p.h>
20#include <qpa/qplatformintegration.h>
24using namespace Qt::StringLiterals;
28QQuickWindowQmlImplPrivate::QQuickWindowQmlImplPrivate() =
default;
30QQuickWindowQmlImpl::QQuickWindowQmlImpl(QWindow *parent)
31 : QQuickWindowQmlImpl(*(
new QQuickWindowQmlImplPrivate), parent)
35QQuickWindowQmlImpl::QQuickWindowQmlImpl(QQuickWindowQmlImplPrivate &dd, QWindow *parent)
36 : QQuickWindow(dd, parent)
38 connect(
this, &QWindow::visibleChanged,
this, [&] {
39 Q_D(QQuickWindowQmlImpl);
40 d->visible = QWindow::isVisible();
41 emit QQuickWindowQmlImpl::visibleChanged(d->visible);
43 connect(
this, &QWindow::visibilityChanged,
this, [&]{
44 Q_D(QQuickWindowQmlImpl);
48 d->visibility = QWindow::visibility();
49 d->visibilityExplicitlySet =
false;
50 emit QQuickWindowQmlImpl::visibilityChanged(d->visibility);
53 connect(
this, &QWindow::screenChanged,
this, [
this]() {
54 Q_D(QQuickWindowQmlImpl);
56 d->screenInfo =
nullptr;
58 emit QQuickWindowQmlImpl::screenChanged();
65 QObject::connect(
this, &QWindow::xChanged,
this, [
this] { emit xChanged(x()); });
66 QObject::connect(
this, &QWindow::yChanged,
this, [
this] { emit yChanged(y()); });
69QQuickWindowQmlImpl::~QQuickWindowQmlImpl()
76void QQuickWindowQmlImpl::classBegin()
78 Q_D(QQuickWindowQmlImpl);
79 qCDebug(lcQuickWindow) <<
"Class begin for" <<
this;
80 d->componentComplete =
false;
82 QQmlEngine* e = qmlEngine(
this);
84 QQmlEngine::setContextForObject(contentItem(), e->rootContext());
87 if (QCoreApplication::instance()->property(
"__qml_using_qqmlapplicationengine") == QVariant(
true)) {
88 if (e && !e->incubationController())
89 e->setIncubationController(incubationController());
94 QV4::ExecutionEngine *v4 = e->handle();
95 QV4::QObjectWrapper::ensureWrapper(v4, d->contentItem);
99void QQuickWindowQmlImpl::componentComplete()
101 Q_D(QQuickWindowQmlImpl);
102 qCDebug(lcQuickWindow) <<
"Component completed for" <<
this;
103 d->componentComplete =
true;
109 updateTransientParent();
110 d->receiveParentEvents =
true;
112 applyWindowVisibility();
116 connect(
this, &QWindow::transientParentChanged,
117 this, &QQuickWindowQmlImpl::applyWindowVisibility);
120void QQuickWindowQmlImpl::setVisible(
bool visible)
122 Q_D(QQuickWindowQmlImpl);
123 d->visible = visible;
124 d->visibleExplicitlySet =
true;
125 if (d->componentComplete)
126 applyWindowVisibility();
129void QQuickWindowQmlImpl::setVisibility(Visibility visibility)
131 Q_D(QQuickWindowQmlImpl);
132 d->visibility = visibility;
133 d->visibilityExplicitlySet =
true;
134 if (d->componentComplete)
135 applyWindowVisibility();
138bool QQuickWindowQmlImpl::event(QEvent *event)
140 Q_D(QQuickWindowQmlImpl);
142 if (event->type() == QEvent::ParentWindowChange) {
143 qCDebug(lcQuickWindow) <<
"Parent of" <<
this <<
"changed to" << parent();
144 if (d->visualParent) {
147 applyWindowVisibility();
149 QObject::disconnect(d->itemParentWindowChangeListener);
150 updateTransientParent();
153 return QQuickWindow::event(event);
157
158
159
160
161void QQuickWindowQmlImpl::updateTransientParent()
163 Q_D(QQuickWindowQmlImpl);
168 if (!d->componentComplete)
173 if (d->transientParentPropertySet)
180 auto *objectParent = QObject::parent();
181 qCDebug(lcTransient) <<
"Applying transient parent magic to"
182 <<
this <<
"based on object parent" << objectParent <<
"🪄";
184 QWindow *transientParent =
nullptr;
185 if (
auto *windowParent = qmlobject_cast<QWindow *>(objectParent)) {
186 transientParent = windowParent;
187 }
else if (
auto *itemParent = qmlobject_cast<QQuickItem *>(objectParent)) {
188 if (!d->itemParentWindowChangeListener) {
189 d->itemParentWindowChangeListener = connect(
190 itemParent, &QQuickItem::windowChanged,
191 this, &QQuickWindowQmlImpl::updateTransientParent);
193 transientParent = itemParent->window();
196 if (!transientParent) {
197 qCDebug(lcTransient) <<
"No transient parent resolved from object parent";
201 qCDebug(lcTransient) <<
"Setting" << transientParent <<
"as transient parent of" <<
this;
202 setTransientParent(transientParent);
205 d->transientParentPropertySet =
false;
208void QQuickWindowQmlImpl::applyWindowVisibility()
210 Q_D(QQuickWindowQmlImpl);
212 Q_ASSERT(d->componentComplete);
214 const bool visible = d->visibilityExplicitlySet
215 ? d->visibility != Hidden : d->visible;
217 qCDebug(lcQuickWindow) <<
"Applying visible" << visible <<
"for" <<
this;
220 if (d->visualParent) {
225 if (!QWindow::parent()) {
226 qCDebug(lcQuickWindow) <<
"Waiting for visual parent to reparent us into a window";
232 auto *itemParent = qmlobject_cast<QQuickItem *>(QObject::parent());
233 if (!d->transientParentPropertySet && itemParent && !itemParent->window()) {
234 qCDebug(lcTransient) <<
"Waiting for parent" << itemParent <<
"to resolve"
235 <<
"its window. Deferring visibility";
239 const QWindow *transientParent = QWindow::transientParent();
240 if (transientParent && !transientParentVisible()) {
243 qCDebug(lcTransient) <<
"Transient parent" << transientParent
244 <<
"not visible yet. Deferring visibility";
250 connect(transientParent, &QQuickWindow::visibleChanged,
this,
251 &QQuickWindowQmlImpl::applyWindowVisibility,
252 Qt::ConnectionType(Qt::QueuedConnection | Qt::SingleShotConnection));
258 if (d->visibleExplicitlySet && d->visibilityExplicitlySet &&
259 ((d->visibility == Hidden && d->visible) ||
260 (d->visibility > AutomaticVisibility && !d->visible))) {
262 qmlWarning(
this) <<
"Conflicting properties 'visible' and 'visibility'";
265 if (d->visibility == AutomaticVisibility) {
270 if (QWindow::parent() || visualParent())
271 setWindowState(Qt::WindowNoState);
273 setWindowState(QGuiApplicationPrivate::platformIntegration()->defaultWindowState(flags()));
274 QQuickWindow::setVisible(d->visible);
275 }
else if (d->visibilityExplicitlySet) {
278 QQuickWindow::setVisibility(d->visibility);
281 QQuickWindow::setVisible(d->visible);
285bool QQuickWindowQmlImpl::transientParentVisible()
287 Q_ASSERT(transientParent());
288 if (!transientParent()->isVisible()) {
290 QWindow *rw = QQuickRenderControl::renderWindowFor(qobject_cast<QQuickWindow*>(transientParent()));
291 return rw && rw->isVisible();
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
324void QQuickWindowQmlImpl::setVisualParent(QObject *visualParent)
326 Q_D(QQuickWindowQmlImpl);
327 if (visualParent == d->visualParent)
330 qCDebug(lcQuickWindow) <<
"Setting visual parent of" <<
this <<
"to" << visualParent;
332 if (d->visualParent) {
334 d->visualParent->disconnect(
this);
337 d->visualParent = visualParent;
339 if (d->componentComplete)
342 emit visualParentChanged(d->visualParent);
345void QQuickWindowQmlImpl::applyVisualParent()
347 Q_D(QQuickWindowQmlImpl);
348 Q_ASSERT(d->componentComplete);
350 qCDebug(lcQuickWindow) <<
"Applying" <<
this <<
"visual parent" << d->visualParent;
352 if (!d->visualParent) {
353 if (d->windowContainer) {
354 d->windowContainer->setContainedWindow(
nullptr);
355 delete std::exchange(d->windowContainer,
nullptr);
357 QQuickWindow::setParent(
nullptr);
361 QQuickItem *parentItem =
nullptr;
362 if ((parentItem = qobject_cast<QQuickItem*>(d->visualParent)))
364 else if (
auto *parentWindow = qobject_cast<QWindow*>(d->visualParent)) {
365 if (
auto *parentQuickWindow = qobject_cast<QQuickWindow*>(parentWindow)) {
366 parentItem = parentQuickWindow->contentItem();
368 qmlWarning(
this) <<
"Parenting into non-Quick window. "
369 <<
"Stacking, position, and destruction must be handled manually";
370 QQuickWindow::setParent(parentWindow);
376 qmlWarning(
this) <<
"Unsupported visual parent type"
377 << d->visualParent->metaObject()->className();
381 if (!parentItem->window()) {
382 qCDebug(lcQuickWindow) <<
"No window yet. Deferring.";
383 connect(parentItem, &QQuickItem::windowChanged,
this, [
this]{
384 qCDebug(lcQuickWindow) <<
"Got window. Applying deferred visual parent item.";
386 }, Qt::SingleShotConnection);
390 if (qobject_cast<QQuickWindowContainer*>(d->visualParent)) {
391 qCDebug(lcQuickWindow) <<
"Visual parent is window container, everything is in order";
395 if (!d->windowContainer) {
396 d->windowContainer =
new QQuickWindowContainer(parentItem,
397 QQuickWindowContainer::WindowControlsItem);
398 d->windowContainer->setObjectName(objectName() +
"Container"_L1);
400 auto *objectParent =
this->QObject::parent();
401 if (objectParent == parentItem) {
410 auto &objectChildren = QObjectPrivate::get(objectParent)->children;
411 auto windowIndex = objectChildren.indexOf(
this);
412 auto containerIndex = objectChildren.indexOf(d->windowContainer);
413 objectChildren.move(containerIndex, windowIndex);
414 containerIndex = windowIndex;
420 for (
int i = containerIndex + 1; i < objectChildren.size(); ++i) {
421 if (
auto *childItem = qobject_cast<QQuickItem*>(objectChildren.at(i))) {
422 qCDebug(lcQuickWindow) <<
"Stacking" << d->windowContainer
423 <<
"below" << childItem;
424 d->windowContainer->stackBefore(childItem);
431 qCDebug(lcQuickWindow) <<
"Visual parent is not object parent."
432 <<
"Can not reflect document order as stacking order.";
435 QQmlEngine::setContextForObject(d->windowContainer, qmlContext(
this));
437 d->windowContainer->classBegin();
438 d->windowContainer->setContainedWindow(
this);
443 d->windowContainer->setPosition(position());
444 d->windowContainer->setZ(d->z);
445 d->windowContainer->componentComplete();
447 QObject::connect(d->windowContainer, &QQuickItem::zChanged,
448 this, &QQuickWindowQmlImpl::zChanged);
450 d->windowContainer->setParentItem(parentItem);
454QObject *QQuickWindowQmlImpl::visualParent()
const
456 Q_D(
const QQuickWindowQmlImpl);
457 return d->visualParent;
469void QQuickWindowQmlImpl::setX(
int x)
471 Q_D(QQuickWindowQmlImpl);
472 if (Q_UNLIKELY(d->windowContainer && d->windowContainer->window()))
473 d->windowContainer->setX(x);
475 QQuickWindow::setX(x);
478int QQuickWindowQmlImpl::x()
const
480 Q_D(
const QQuickWindowQmlImpl);
481 if (Q_UNLIKELY(d->windowContainer && d->windowContainer->window()))
482 return d->windowContainer->x();
484 return QQuickWindow::x();
487void QQuickWindowQmlImpl::setY(
int y)
489 Q_D(QQuickWindowQmlImpl);
490 if (Q_UNLIKELY(d->windowContainer && d->windowContainer->window()))
491 d->windowContainer->setY(y);
493 QQuickWindow::setY(y);
496int QQuickWindowQmlImpl::y()
const
498 Q_D(
const QQuickWindowQmlImpl);
499 if (Q_UNLIKELY(d->windowContainer && d->windowContainer->window()))
500 return d->windowContainer->y();
502 return QQuickWindow::y();
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
522void QQuickWindowQmlImpl::setZ(qreal z)
524 Q_D(QQuickWindowQmlImpl);
525 if (Q_UNLIKELY(d->windowContainer && d->windowContainer->window()))
526 d->windowContainer->setZ(z);
531qreal QQuickWindowQmlImpl::z()
const
533 Q_D(
const QQuickWindowQmlImpl);
534 if (Q_UNLIKELY(d->windowContainer && d->windowContainer->window()))
535 return d->windowContainer->z();
542QObject *QQuickWindowQmlImpl::screen()
const
544 Q_D(
const QQuickWindowQmlImpl);
546 d->screenInfo =
new QQuickScreenInfo(
const_cast<QQuickWindowQmlImpl *>(
this), QWindow::screen());
547 return d->screenInfo;
550void QQuickWindowQmlImpl::setScreen(QObject *screen)
552 QQuickScreenInfo *screenWrapper = qobject_cast<QQuickScreenInfo *>(screen);
553 QWindow::setScreen(screenWrapper ? screenWrapper->wrappedScreen() :
nullptr);
556QQuickWindowAttached *QQuickWindowQmlImpl::qmlAttachedProperties(QObject *object)
558 return new QQuickWindowAttached(object);
563#include "moc_qquickwindowmodule_p.cpp"
Q_STATIC_LOGGING_CATEGORY(lcAccessibilityCore, "qt.accessibility.core")