112QQuickWindowContainer::QQuickWindowContainer(QQuickItem *parent, ContainerMode containerMode)
113 : QQuickImplicitSizeItem(*(
new QQuickWindowContainerPrivate), parent)
115 Q_D(QQuickWindowContainer);
117 qCDebug(lcWindowContainer).verbosity(1) <<
"Creating window container"
118 <<
this <<
"with parent" << parent <<
"and" << containerMode;
120 d->containerMode = containerMode;
122 setFlag(QQuickItem::ItemObservesViewport);
123 setFocusPolicy(Qt::TabFocus);
125#if QT_CONFIG(accessibility)
132 connect(
this, &QQuickItem::windowChanged,
133 this, &QQuickWindowContainer::parentWindowChanged);
135 if (lcWindowContainer().isDebugEnabled()) {
136 auto *debugRectangle =
new QQuickRectangle(
this);
137 debugRectangle->setColor(QColor(255, 0, 255, 20));
138 auto *border = debugRectangle->border();
139 border->setColor(Qt::magenta);
140 border->setWidth(1.0);
141 QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(debugRectangle);
142 rectPrivate->anchors()->setFill(
this);
146QQuickWindowContainer::~QQuickWindowContainer()
148 Q_D(QQuickWindowContainer);
149 qCDebug(lcWindowContainer) <<
"Destructing window container" <<
this;
151 disconnect(
this, &QQuickItem::windowChanged,
152 this, &QQuickWindowContainer::parentWindowChanged);
155 d->window->disconnect(
this);
156 d->window->removeEventFilter(
this);
158 auto ownership = QJSEngine::objectOwnership(d->window);
159 qCDebug(lcWindowContainer) <<
"Contained window" << d->window
160 <<
"has" << (ownership == QQmlEngine::JavaScriptOwnership ?
161 "JavaScript" :
"C++") <<
"ownership";
162 if (ownership == QQmlEngine::JavaScriptOwnership) {
165 d->window->destroy();
166 d->window->setParent(
nullptr);
167#if QT_CONFIG(accessibility)
168 auto *windowPrivate = QWindowPrivate::get(d->window);
169 if (windowPrivate->accessibleParent ==
this)
170 windowPrivate->setAccessibleParent(
nullptr);
211void QQuickWindowContainer::setContainedWindow(QWindow *window)
213 qCDebug(lcWindowContainer) <<
"Setting contained window for" <<
this <<
"to" << window;
215 Q_D(QQuickWindowContainer);
217 if (window == d->window)
220 if (
auto *previousWindow = d->window) {
221 qCDebug(lcWindowContainer) <<
"Decoupling container from" << d->window;
222 previousWindow->disconnect(
this);
223 previousWindow->removeEventFilter(
this);
224 previousWindow->setParent(
nullptr);
225#if QT_CONFIG(accessibility)
226 auto *previousWindowPrivate = QWindowPrivate::get(previousWindow);
227 if (previousWindowPrivate->accessibleParent ==
this)
228 previousWindowPrivate->setAccessibleParent(
nullptr);
235 if (d->containerMode == ItemControlsWindow) {
236 if (
auto *quickWindow = qobject_cast<QQuickWindowQmlImpl*>(d->window)) {
238 quickWindow->setVisualParent(
this);
246 connect(d->window, &QWindow::xChanged,
this, &QQuickWindowContainer::windowUpdated);
247 connect(d->window, &QWindow::yChanged,
this, &QQuickWindowContainer::windowUpdated);
248 connect(d->window, &QWindow::widthChanged,
this, &QQuickWindowContainer::windowUpdated);
249 connect(d->window, &QWindow::heightChanged,
this, &QQuickWindowContainer::windowUpdated);
250 connect(d->window, &QWindow::visibleChanged,
this, &QQuickWindowContainer::windowUpdated);
252 connect(d->window, &QObject::destroyed,
this, &QQuickWindowContainer::windowDestroyed);
254 d->window->installEventFilter(
this);
256#if QT_CONFIG(accessibility)
257 QWindowPrivate::get(d->window)->setAccessibleParent(
this);
260 if (d->componentComplete)
261 initializeContainedWindow();
267 emit containedWindowChanged(d->window);
331void QQuickWindowContainer::updatePolish()
333 Q_D(QQuickWindowContainer);
335 qCDebug(lcWindowContainer) <<
"Propagating" <<
this <<
"state"
336 <<
"to" << d->window;
338 auto *parentWindow = window();
346 if (!d->window || !parentWindow)
349 if (d->window->parent() != parentWindow) {
350 qCDebug(lcWindowContainer) <<
"Updating window parent to" << parentWindow;
351 d->window->setParent(parentWindow);
354 auto transform = sanitizeTransform(d->itemToWindowTransform());
360 const QRectF itemSceneRect = transform.mapRect(boundingRect());
363 QRect windowGeometry = itemSceneRect.toRect();
364 if (windowGeometry != d->window->geometry()) {
365 QRectF itemRect(position(), size());
366 qCDebug(lcWindowContainer) <<
"Updating window geometry to" << windowGeometry
367 <<
"based on item rect" << itemRect <<
"and scene rect" << itemSceneRect;
368 d->window->setGeometry(windowGeometry);
380 const auto clipMask = [&]{
381 if (clipRect() == boundingRect())
388 auto scaleTransform = QTransform::fromScale(transform.m11(), transform.m22());
389 auto rect = scaleTransform.mapRect(clipRect()).toRect();
397 return QRect(-1, -1, 1, 1);
402 if (clipMask != d->window->mask().boundingRect()) {
403 qCDebug(lcWindowContainer) <<
"Updating window clip mask to" << clipMask
404 <<
"based on clip rect" << clipRect();
405 d->window->setMask(clipMask);
418 if (d->window->isVisible() != isVisible()) {
419 qCDebug(lcWindowContainer) <<
"Updating window visibility"
420 <<
"based on item visible" << isVisible();
421 d->window->setVisible(isVisible());
436QRectF QQuickWindowContainer::clipRect()
const
438 QRectF rect = boundingRect();
440 for (
auto *viewport = viewportItem(); viewport; viewport = viewport->viewportItem()) {
441 if (viewport ==
this)
444 if (viewport->flags().testFlag(QQuickItem::ItemClipsChildrenToShape)) {
446 const auto mappedViewportRect = mapRectFromItem(viewport, viewport->boundingRect());
447 rect = mappedViewportRect.intersected(rect);
450 if (viewport->viewportItem() == viewport)
494bool QQuickWindowContainer::eventFilter(QObject *object, QEvent *event)
496 Q_D(
const QQuickWindowContainer);
497 Q_ASSERT(object == d->window);
499 if (event->type() == QEvent::PlatformSurface) {
500 auto type =
static_cast<QPlatformSurfaceEvent*>(event)->surfaceEventType();
501 if (type == QPlatformSurfaceEvent::SurfaceCreated) {
502 qCDebug(lcWindowContainer) <<
"Surface created for" << object;
509 if (
auto *quickWindow = qobject_cast<QQuickWindow*>(window()))
510 QQuickWindowPrivate::get(quickWindow)->updateChildWindowStackingOrder();
514 return QQuickImplicitSizeItem::eventFilter(object, event);
517void QQuickWindowContainer::focusInEvent(QFocusEvent *event)
519 Q_D(QQuickWindowContainer);
521 const auto reason = event->reason();
522 QWindowPrivate::FocusTarget target = QWindowPrivate::FocusTarget::Current;
523 if (reason == Qt::TabFocusReason)
524 target = QWindowPrivate::FocusTarget::First;
525 else if (reason == Qt::BacktabFocusReason)
526 target = QWindowPrivate::FocusTarget::Last;
527 QWindowPrivate::get(d->window)->setFocusToTarget(target, reason);
528 d->window->requestActivate();
566void QQuickWindowContainer::itemChange(QQuickItem::ItemChange change,
const QQuickItem::ItemChangeData &data)
569 case ItemVisibleHasChanged:
570 qCDebug(lcWindowContainer) <<
"Visible changed for" <<
this <<
"to" << isVisible();
577 QQuickImplicitSizeItem::itemChange(change, data);
615 Q_Q(QQuickWindowContainer);
617 if (
this->componentComplete &&
this->window) {
618 auto *transformedItemPrivate = QQuickItemPrivate::get(transformedItem);
619 qCDebug(lcWindowContainer) <<
"Transform changed for" << transformedItem
620 <<
"with dirty state" << transformedItemPrivate->dirtyToString();
622 if (transformedItemPrivate->dirtyAttributes
623 & QQuickItemPrivate::BasicTransform) {
634 return QQuickItemPrivate::transformChanged(transformedItem);