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(QQuickWindowContainer);
140 qCDebug(lcWindowContainer) <<
"Destructing window container" <<
this;
142 disconnect(
this, &QQuickItem::windowChanged,
143 this, &QQuickWindowContainer::parentWindowChanged);
146 d->window->disconnect(
this);
147 d->window->removeEventFilter(
this);
149 auto ownership = QJSEngine::objectOwnership(d->window);
150 qCDebug(lcWindowContainer) <<
"Contained window" << d->window
151 <<
"has" << (ownership == QQmlEngine::JavaScriptOwnership ?
152 "JavaScript" :
"C++") <<
"ownership";
153 if (ownership == QQmlEngine::JavaScriptOwnership) {
156 d->window->destroy();
157 d->window->setParent(
nullptr);
197void QQuickWindowContainer::setContainedWindow(QWindow *window)
199 qCDebug(lcWindowContainer) <<
"Setting contained window for" <<
this <<
"to" << window;
201 Q_D(QQuickWindowContainer);
203 if (window == d->window)
206 if (
auto *previousWindow = d->window) {
207 qCDebug(lcWindowContainer) <<
"Decoupling container from" << d->window;
208 previousWindow->disconnect(
this);
209 previousWindow->removeEventFilter(
this);
210 previousWindow->setParent(
nullptr);
216 if (d->containerMode == ItemControlsWindow) {
217 if (
auto *quickWindow = qobject_cast<QQuickWindowQmlImpl*>(d->window)) {
219 quickWindow->setVisualParent(
this);
227 connect(d->window, &QWindow::xChanged,
this, &QQuickWindowContainer::windowUpdated);
228 connect(d->window, &QWindow::yChanged,
this, &QQuickWindowContainer::windowUpdated);
229 connect(d->window, &QWindow::widthChanged,
this, &QQuickWindowContainer::windowUpdated);
230 connect(d->window, &QWindow::heightChanged,
this, &QQuickWindowContainer::windowUpdated);
231 connect(d->window, &QWindow::visibleChanged,
this, &QQuickWindowContainer::windowUpdated);
233 connect(d->window, &QObject::destroyed,
this, &QQuickWindowContainer::windowDestroyed);
235 d->window->installEventFilter(
this);
237 if (d->componentComplete)
238 initializeContainedWindow();
244 emit containedWindowChanged(d->window);
308void QQuickWindowContainer::updatePolish()
310 Q_D(QQuickWindowContainer);
312 qCDebug(lcWindowContainer) <<
"Propagating" <<
this <<
"state"
313 <<
"to" << d->window;
315 auto *parentWindow = window();
323 if (!d->window || !parentWindow)
326 if (d->window->parent() != parentWindow) {
327 qCDebug(lcWindowContainer) <<
"Updating window parent to" << parentWindow;
328 d->window->setParent(parentWindow);
331 auto transform = sanitizeTransform(d->itemToWindowTransform());
337 const QRectF itemSceneRect = transform.mapRect(boundingRect());
340 QRect windowGeometry = itemSceneRect.toRect();
341 if (windowGeometry != d->window->geometry()) {
342 QRectF itemRect(position(), size());
343 qCDebug(lcWindowContainer) <<
"Updating window geometry to" << windowGeometry
344 <<
"based on item rect" << itemRect <<
"and scene rect" << itemSceneRect;
345 d->window->setGeometry(windowGeometry);
357 const auto clipMask = [&]{
358 if (clipRect() == boundingRect())
365 auto scaleTransform = QTransform::fromScale(transform.m11(), transform.m22());
366 auto rect = scaleTransform.mapRect(clipRect()).toRect();
374 return QRect(-1, -1, 1, 1);
379 if (clipMask != d->window->mask().boundingRect()) {
380 qCDebug(lcWindowContainer) <<
"Updating window clip mask to" << clipMask
381 <<
"based on clip rect" << clipRect();
382 d->window->setMask(clipMask);
395 if (d->window->isVisible() != isVisible()) {
396 qCDebug(lcWindowContainer) <<
"Updating window visibility"
397 <<
"based on item visible" << isVisible();
398 d->window->setVisible(isVisible());
413QRectF QQuickWindowContainer::clipRect()
const
415 QRectF rect = boundingRect();
417 for (
auto *viewport = viewportItem(); viewport; viewport = viewport->viewportItem()) {
418 if (viewport ==
this)
421 if (viewport->flags().testFlag(QQuickItem::ItemClipsChildrenToShape)) {
423 const auto mappedViewportRect = mapRectFromItem(viewport, viewport->boundingRect());
424 rect = mappedViewportRect.intersected(rect);
427 if (viewport->viewportItem() == viewport)
471bool QQuickWindowContainer::eventFilter(QObject *object, QEvent *event)
473 Q_D(
const QQuickWindowContainer);
474 Q_ASSERT(object == d->window);
476 if (event->type() == QEvent::PlatformSurface) {
477 auto type =
static_cast<QPlatformSurfaceEvent*>(event)->surfaceEventType();
478 if (type == QPlatformSurfaceEvent::SurfaceCreated) {
479 qCDebug(lcWindowContainer) <<
"Surface created for" << object;
486 if (
auto *quickWindow = qobject_cast<QQuickWindow*>(window()))
487 QQuickWindowPrivate::get(quickWindow)->updateChildWindowStackingOrder();
491 return QQuickImplicitSizeItem::eventFilter(object, event);
494void QQuickWindowContainer::focusInEvent(QFocusEvent *event)
496 Q_D(QQuickWindowContainer);
498 const auto reason = event->reason();
499 QWindowPrivate::FocusTarget target = QWindowPrivate::FocusTarget::Current;
500 if (reason == Qt::TabFocusReason)
501 target = QWindowPrivate::FocusTarget::First;
502 else if (reason == Qt::BacktabFocusReason)
503 target = QWindowPrivate::FocusTarget::Last;
504 QWindowPrivate::get(d->window)->setFocusToTarget(target, reason);
505 d->window->requestActivate();
543void QQuickWindowContainer::itemChange(QQuickItem::ItemChange change,
const QQuickItem::ItemChangeData &data)
546 case ItemVisibleHasChanged:
547 qCDebug(lcWindowContainer) <<
"Visible changed for" <<
this <<
"to" << isVisible();
554 QQuickImplicitSizeItem::itemChange(change, data);
592 Q_Q(QQuickWindowContainer);
594 if (
this->componentComplete &&
this->window) {
595 auto *transformedItemPrivate = QQuickItemPrivate::get(transformedItem);
596 qCDebug(lcWindowContainer) <<
"Transform changed for" << transformedItem
597 <<
"with dirty state" << transformedItemPrivate->dirtyToString();
599 if (transformedItemPrivate->dirtyAttributes
600 & QQuickItemPrivate::BasicTransform) {
611 return QQuickItemPrivate::transformChanged(transformedItem);