110QQuickWindowContainer::QQuickWindowContainer(QQuickItem *parent, ContainerMode containerMode)
111 : QQuickImplicitSizeItem(*(
new QQuickWindowContainerPrivate), parent)
113 Q_D(QQuickWindowContainer);
115 qCDebug(lcWindowContainer).verbosity(1) <<
"Creating window container"
116 <<
this <<
"with parent" << parent <<
"and" << containerMode;
118 d->containerMode = containerMode;
120 setFlag(QQuickItem::ItemObservesViewport);
121 setFocusPolicy(Qt::TabFocus);
123 connect(
this, &QQuickItem::windowChanged,
124 this, &QQuickWindowContainer::parentWindowChanged);
126 if (lcWindowContainer().isDebugEnabled()) {
127 auto *debugRectangle =
new QQuickRectangle(
this);
128 debugRectangle->setColor(QColor(255, 0, 255, 20));
129 auto *border = debugRectangle->border();
130 border->setColor(Qt::magenta);
131 border->setWidth(1.0);
132 QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(debugRectangle);
133 rectPrivate->anchors()->setFill(
this);
137QQuickWindowContainer::~QQuickWindowContainer()
139 Q_D(
const QQuickWindowContainer);
140 qCDebug(lcWindowContainer) <<
"Destructing window container" <<
this;
144 auto ownership = QJSEngine::objectOwnership(d->window);
145 qCDebug(lcWindowContainer) <<
"Contained window" << d->window
146 <<
"has" << (ownership == QQmlEngine::JavaScriptOwnership ?
147 "JavaScript" :
"C++") <<
"ownership";
148 if (ownership == QQmlEngine::JavaScriptOwnership) {
151 d->window->destroy();
152 d->window->setParent(
nullptr);
190void QQuickWindowContainer::setContainedWindow(QWindow *window)
192 qCDebug(lcWindowContainer) <<
"Setting contained window for" <<
this <<
"to" << window;
194 Q_D(QQuickWindowContainer);
196 if (window == d->window)
199 if (
auto *previousWindow = d->window) {
200 qCDebug(lcWindowContainer) <<
"Decoupling container from" << d->window;
201 previousWindow->disconnect(
this);
202 previousWindow->removeEventFilter(
this);
203 previousWindow->setParent(
nullptr);
209 if (d->containerMode == ItemControlsWindow) {
210 if (
auto *quickWindow = qobject_cast<QQuickWindowQmlImpl*>(d->window)) {
212 quickWindow->setVisualParent(
this);
220 connect(d->window, &QWindow::xChanged,
this, &QQuickWindowContainer::windowUpdated);
221 connect(d->window, &QWindow::yChanged,
this, &QQuickWindowContainer::windowUpdated);
222 connect(d->window, &QWindow::widthChanged,
this, &QQuickWindowContainer::windowUpdated);
223 connect(d->window, &QWindow::heightChanged,
this, &QQuickWindowContainer::windowUpdated);
224 connect(d->window, &QWindow::visibleChanged,
this, &QQuickWindowContainer::windowUpdated);
226 connect(d->window, &QObject::destroyed,
this, &QQuickWindowContainer::windowDestroyed);
228 d->window->installEventFilter(
this);
230 if (d->componentComplete)
231 initializeContainedWindow();
237 emit containedWindowChanged(d->window);
301void QQuickWindowContainer::updatePolish()
303 Q_D(QQuickWindowContainer);
305 qCDebug(lcWindowContainer) <<
"Propagating" <<
this <<
"state"
306 <<
"to" << d->window;
308 auto *parentWindow = window();
316 if (!d->window || !parentWindow)
319 if (d->window->parent() != parentWindow) {
320 qCDebug(lcWindowContainer) <<
"Updating window parent to" << parentWindow;
321 d->window->setParent(parentWindow);
324 auto transform = sanitizeTransform(d->itemToWindowTransform());
330 const QRectF itemSceneRect = transform.mapRect(boundingRect());
333 QRect windowGeometry = itemSceneRect.toRect();
334 if (windowGeometry != d->window->geometry()) {
335 QRectF itemRect(position(), size());
336 qCDebug(lcWindowContainer) <<
"Updating window geometry to" << windowGeometry
337 <<
"based on item rect" << itemRect <<
"and scene rect" << itemSceneRect;
338 d->window->setGeometry(windowGeometry);
350 const auto clipMask = [&]{
351 if (clipRect() == boundingRect())
358 auto scaleTransform = QTransform::fromScale(transform.m11(), transform.m22());
359 auto rect = scaleTransform.mapRect(clipRect()).toRect();
367 return QRect(-1, -1, 1, 1);
372 if (clipMask != d->window->mask().boundingRect()) {
373 qCDebug(lcWindowContainer) <<
"Updating window clip mask to" << clipMask
374 <<
"based on clip rect" << clipRect();
375 d->window->setMask(clipMask);
388 if (d->window->isVisible() != isVisible()) {
389 qCDebug(lcWindowContainer) <<
"Updating window visibility"
390 <<
"based on item visible" << isVisible();
391 d->window->setVisible(isVisible());
406QRectF QQuickWindowContainer::clipRect()
const
408 QRectF rect = boundingRect();
410 for (
auto *viewport = viewportItem(); viewport; viewport = viewport->viewportItem()) {
411 if (viewport ==
this)
414 if (viewport->flags().testFlag(QQuickItem::ItemClipsChildrenToShape)) {
416 const auto mappedViewportRect = mapRectFromItem(viewport, viewport->boundingRect());
417 rect = mappedViewportRect.intersected(rect);
420 if (viewport->viewportItem() == viewport)
464bool QQuickWindowContainer::eventFilter(QObject *object, QEvent *event)
466 Q_D(
const QQuickWindowContainer);
467 Q_ASSERT(object == d->window);
469 if (event->type() == QEvent::PlatformSurface) {
470 auto type =
static_cast<QPlatformSurfaceEvent*>(event)->surfaceEventType();
471 if (type == QPlatformSurfaceEvent::SurfaceCreated) {
472 qCDebug(lcWindowContainer) <<
"Surface created for" << object;
479 if (
auto *quickWindow = qobject_cast<QQuickWindow*>(window()))
480 QQuickWindowPrivate::get(quickWindow)->updateChildWindowStackingOrder();
484 return QQuickImplicitSizeItem::eventFilter(object, event);
487void QQuickWindowContainer::focusInEvent(QFocusEvent *event)
489 Q_D(QQuickWindowContainer);
491 const auto reason = event->reason();
492 QWindowPrivate::FocusTarget target = QWindowPrivate::FocusTarget::Current;
493 if (reason == Qt::TabFocusReason)
494 target = QWindowPrivate::FocusTarget::First;
495 else if (reason == Qt::BacktabFocusReason)
496 target = QWindowPrivate::FocusTarget::Last;
497 QWindowPrivate::get(d->window)->setFocusToTarget(target, reason);
498 d->window->requestActivate();
536void QQuickWindowContainer::itemChange(QQuickItem::ItemChange change,
const QQuickItem::ItemChangeData &data)
539 case ItemVisibleHasChanged:
540 qCDebug(lcWindowContainer) <<
"Visible changed for" <<
this <<
"to" << isVisible();
547 QQuickImplicitSizeItem::itemChange(change, data);
585 Q_Q(QQuickWindowContainer);
587 if (
this->componentComplete &&
this->window) {
588 auto *transformedItemPrivate = QQuickItemPrivate::get(transformedItem);
589 qCDebug(lcWindowContainer) <<
"Transform changed for" << transformedItem
590 <<
"with dirty state" << transformedItemPrivate->dirtyToString();
592 if (transformedItemPrivate->dirtyAttributes
593 & QQuickItemPrivate::BasicTransform) {
604 return QQuickItemPrivate::transformChanged(transformedItem);