Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qquickwindow.cpp
Go to the documentation of this file.
1// Copyright (C) 2020 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// Qt-Security score:significant reason:default
4
5#include "qquickwindow.h"
7
8#include "qquickitem.h"
9#include "qquickitem_p.h"
14
15#include <QtQuick/private/qsgrenderer_p.h>
16#include <QtQuick/private/qsgplaintexture_p.h>
17#include <QtQuick/private/qquickpointerhandler_p.h>
18#include <QtQuick/private/qquickpointerhandler_p_p.h>
19#include <QtQuick/private/qquicktaphandler_p.h>
20#include <private/qsgrenderloop_p.h>
21#include <private/qsgrhisupport_p.h>
22#include <private/qquickrendercontrol_p.h>
23#include <private/qquickanimatorcontroller_p.h>
24#include <private/qquickprofiler_p.h>
25#include <private/qquicktextinterface_p.h>
26
27#include <private/qguiapplication_p.h>
28
29#include <private/qabstractanimation_p.h>
30
31#include <QtGui/qpainter.h>
32#include <QtGui/qevent.h>
33#include <QtGui/qmatrix4x4.h>
34#include <QtGui/private/qevent_p.h>
35#include <QtGui/private/qpointingdevice_p.h>
36#include <QtCore/qvarlengtharray.h>
37#include <QtCore/qabstractanimation.h>
38#include <QtCore/QLibraryInfo>
39#include <QtCore/QRunnable>
40#include <QtQml/qqmlincubator.h>
41#include <QtQml/qqmlinfo.h>
42#include <QtQml/private/qqmlmetatype_p.h>
43
44#include <QtQuick/private/qquickpixmap_p.h>
45
46#include <private/qqmldebugserviceinterfaces_p.h>
47#include <private/qqmldebugconnector_p.h>
48#include <private/qsgdefaultrendercontext_p.h>
49#include <private/qsgsoftwarerenderer_p.h>
50#if QT_CONFIG(opengl)
51#include <private/qopengl_p.h>
52#include <QOpenGLContext>
53#endif
54#ifndef QT_NO_DEBUG_STREAM
55#include <private/qdebug_p.h>
56#endif
57#include <QtCore/qpointer.h>
58
59#include <rhi/qrhi.h>
60
61#include <utility>
62#include <mutex>
63
65
66Q_STATIC_LOGGING_CATEGORY(lcDirty, "qt.quick.dirty")
67Q_LOGGING_CATEGORY(lcQuickWindow, "qt.quick.window")
68
69bool QQuickWindowPrivate::defaultAlphaBuffer = false;
70
71#if defined(QT_QUICK_DEFAULT_TEXT_RENDER_TYPE)
72QQuickWindow::TextRenderType QQuickWindowPrivate::textRenderType = QQuickWindow::QT_QUICK_DEFAULT_TEXT_RENDER_TYPE;
73#else
74QQuickWindow::TextRenderType QQuickWindowPrivate::textRenderType = QQuickWindow::QtTextRendering;
75#endif
76
78{
80
81public:
94
95protected:
97 {
99 m_timer = 0;
100 incubate();
101 }
102
104 if (m_timer == 0) {
105 // Wait for a while before processing the next batch. Using a
106 // timer to avoid starvation of system events.
108 }
109 }
110
111public slots:
112 void incubate() {
116 } else {
120 }
121 }
122 }
123
125
126protected:
132
133private:
135 int m_incubation_time;
136 int m_timer;
137};
138
139#if QT_CONFIG(accessibility)
140/*!
141 Returns an accessibility interface for this window, or 0 if such an
142 interface cannot be created.
143*/
144QAccessibleInterface *QQuickWindow::accessibleRoot() const
145{
146 return QAccessible::queryAccessibleInterface(const_cast<QQuickWindow*>(this));
147}
148#endif
149
150
151/*
152Focus behavior
153==============
154
155Prior to being added to a valid window items can set and clear focus with no
156effect. Only once items are added to a window (by way of having a parent set that
157already belongs to a window) do the focus rules apply. Focus goes back to
158having no effect if an item is removed from a window.
159
160When an item is moved into a new focus scope (either being added to a window
161for the first time, or having its parent changed), if the focus scope already has
162a scope focused item that takes precedence over the item being added. Otherwise,
163the focus of the added tree is used. In the case of a tree of items being
164added to a window for the first time, which may have a conflicted focus state (two
165or more items in one scope having focus set), the same rule is applied item by item -
166thus the first item that has focus will get it (assuming the scope doesn't already
167have a scope focused item), and the other items will have their focus cleared.
168*/
169
170QQuickRootItem::QQuickRootItem()
171{
172 // child items with ItemObservesViewport can treat the window's content item
173 // as the ultimate viewport: avoid populating SG nodes that fall outside
174 setFlag(ItemIsViewport);
175}
176
177/*! \reimp */
178void QQuickWindow::exposeEvent(QExposeEvent *)
179{
180 Q_D(QQuickWindow);
181 if (d->windowManager)
182 d->windowManager->exposureChanged(this);
183}
184
185/*! \reimp */
186void QQuickWindow::resizeEvent(QResizeEvent *ev)
187{
188 Q_D(QQuickWindow);
189 if (d->contentItem)
190 d->contentItem->setSize(ev->size());
191 if (d->windowManager)
192 d->windowManager->resize(this);
193}
194
195/*! \reimp */
196void QQuickWindow::showEvent(QShowEvent *)
197{
198 Q_D(QQuickWindow);
199 if (d->windowManager)
200 d->windowManager->show(this);
201}
202
203/*! \reimp */
204void QQuickWindow::hideEvent(QHideEvent *)
205{
206 Q_D(QQuickWindow);
207 if (auto da = d->deliveryAgentPrivate())
208 da->handleWindowHidden(this);
209 if (d->windowManager)
210 d->windowManager->hide(this);
211}
212
213/*! \reimp */
214void QQuickWindow::closeEvent(QCloseEvent *e)
215{
216 QQuickCloseEvent qev;
217 qev.setAccepted(e->isAccepted());
218 emit closing(&qev);
219 e->setAccepted(qev.isAccepted());
220}
221
222/*! \reimp */
223void QQuickWindow::focusOutEvent(QFocusEvent *ev)
224{
225 Q_D(QQuickWindow);
226 if (d->contentItem)
227 d->contentItem->setFocus(false, ev->reason());
228}
229
230/*! \reimp */
231void QQuickWindow::focusInEvent(QFocusEvent *ev)
232{
233 Q_D(QQuickWindow);
234 if (d->inDestructor)
235 return;
236 if (d->contentItem)
237 d->contentItem->setFocus(true, ev->reason());
238 if (auto da = d->deliveryAgentPrivate())
239 da->updateFocusItemTransform();
240}
241
242#if QT_CONFIG(im)
243static bool transformDirtyOnItemOrAncestor(const QQuickItem *item)
244{
245 while (item) {
246 if (QQuickItemPrivate::get(item)->dirtyAttributes & (
247 QQuickItemPrivate::TransformOrigin |
248 QQuickItemPrivate::Transform |
249 QQuickItemPrivate::BasicTransform |
250 QQuickItemPrivate::Position |
251 QQuickItemPrivate::Size |
252 QQuickItemPrivate::ParentChanged |
253 QQuickItemPrivate::Clip)) {
254 return true;
255 }
256 item = item->parentItem();
257 }
258 return false;
259}
260#endif
261
262/*!
263 * \internal
264
265 A "polish loop" can occur inside QQuickWindowPrivate::polishItems(). It is when an item calls
266 polish() on an(other?) item from updatePolish(). If this anomaly happens repeatedly and without
267 interruption (of a well-behaved updatePolish() that doesn't call polish()), it is a strong
268 indication that we are heading towards an infinite polish loop. A polish loop is not a bug in
269 Qt Quick - it is a bug caused by ill-behaved items put in the scene.
270
271 We can detect this sequence of polish loops easily, since the
272 QQuickWindowPrivate::itemsToPolish is basically a stack: polish() will push to it, and
273 polishItems() will pop from it.
274 Therefore if updatePolish() calls polish(), the immediate next item polishItems() processes is
275 the item that was polished by the previous call to updatePolish().
276 We therefore just need to count the number of polish loops we detected in _sequence_.
277*/
279{
280 PolishLoopDetector(const QList<QQuickItem*> &itemsToPolish)
282 {
283 }
284
285 /*
286 * returns true when it detected a likely infinite loop
287 * (suggests it should abort the polish loop)
288 **/
289 bool check(QQuickItem *item, int itemsRemainingBeforeUpdatePolish)
290 {
291 if (itemsToPolish.size() > itemsRemainingBeforeUpdatePolish) {
292 // Detected potential polish loop.
294 if (numPolishLoopsInSequence == 10000) {
295 // We have looped 10,000 times without actually reducing the list of items to
296 // polish, give up for now.
297 // This is not a fix, just a remedy so that the application can be somewhat
298 // responsive.
300 return true;
301 }
303 // Start to warn about polish loop after 1000 consecutive polish loops
304 // Show the 5 next items involved in the polish loop.
305 // (most likely they will be the same 5 items...)
306 QQuickItem *guiltyItem = itemsToPolish.last();
307 qmlWarning(item) << "possible QQuickItem::polish() loop";
308
309 auto typeAndObjectName = [](QQuickItem *item) {
310 QString typeName = QQmlMetaType::prettyTypeName(item);
311 QString objName = item->objectName();
312 if (!objName.isNull())
313 return QLatin1String("%1(%2)").arg(typeName, objName);
314 return typeName;
315 };
316
317 qmlWarning(guiltyItem) << typeAndObjectName(guiltyItem)
318 << " called polish() inside updatePolish() of " << typeAndObjectName(item);
319 }
320 } else {
322 }
323 return false;
324 }
325 const QList<QQuickItem*> &itemsToPolish; // Just a ref to the one in polishItems()
327};
328
329void QQuickWindowPrivate::polishItems()
330{
331 // An item can trigger polish on another item, or itself for that matter,
332 // during its updatePolish() call. Because of this, we cannot simply
333 // iterate through the set, we must continue pulling items out until it
334 // is empty.
335 // In the case where polish is called from updatePolish() either directly
336 // or indirectly, we use a PolishLoopDetector to determine if a warning should
337 // be printed to the user.
338
339 PolishLoopDetector polishLoopDetector(itemsToPolish);
340 while (!itemsToPolish.isEmpty()) {
341 QQuickItem *item = itemsToPolish.takeLast();
342 QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
343 itemPrivate->polishScheduled = false;
344 const int itemsRemaining = itemsToPolish.size();
345 itemPrivate->updatePolish();
346 item->updatePolish();
347 if (polishLoopDetector.check(item, itemsRemaining) == true)
348 break;
349 }
350
351#if QT_CONFIG(im)
352 if (QQuickItem *focusItem = q_func()->activeFocusItem()) {
353 // If the current focus item, or any of its anchestors, has changed location
354 // inside the window, we need inform IM about it. This to ensure that overlays
355 // such as selection handles will be updated.
356 const bool isActiveFocusItem = (focusItem == QGuiApplication::focusObject());
357 const bool hasImEnabled = focusItem->inputMethodQuery(Qt::ImEnabled).toBool();
358 if (isActiveFocusItem && hasImEnabled && transformDirtyOnItemOrAncestor(focusItem))
359 deliveryAgentPrivate()->updateFocusItemTransform();
360 }
361#endif
362
363 if (needsChildWindowStackingOrderUpdate) {
364 updateChildWindowStackingOrder();
365 needsChildWindowStackingOrderUpdate = false;
366 }
367}
368
369/*!
370 * Schedules the window to render another frame.
371 *
372 * Calling QQuickWindow::update() differs from QQuickItem::update() in that
373 * it always triggers a repaint, regardless of changes in the underlying
374 * scene graph or not.
375 */
376void QQuickWindow::update()
377{
378 Q_D(QQuickWindow);
379 if (d->windowManager)
380 d->windowManager->update(this);
381 else if (d->renderControl)
382 QQuickRenderControlPrivate::get(d->renderControl)->update();
383}
384
385static void updatePixelRatioHelper(QQuickItem *item, float pixelRatio)
386{
387 if (item->flags() & QQuickItem::ItemHasContents) {
388 QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
389 itemPrivate->itemChange(QQuickItem::ItemDevicePixelRatioHasChanged, pixelRatio);
390 }
391
392 QList <QQuickItem *> items = item->childItems();
393 for (int i = 0; i < items.size(); ++i)
394 updatePixelRatioHelper(items.at(i), pixelRatio);
395}
396
397void QQuickWindow::physicalDpiChanged()
398{
399 Q_D(QQuickWindow);
400 const qreal newPixelRatio = effectiveDevicePixelRatio();
401 if (qFuzzyCompare(newPixelRatio, d->lastReportedItemDevicePixelRatio))
402 return;
403 d->lastReportedItemDevicePixelRatio = newPixelRatio;
404 if (d->contentItem)
405 updatePixelRatioHelper(d->contentItem, newPixelRatio);
406 d->forcePolish();
407 emit devicePixelRatioChanged();
408}
409
410void QQuickWindow::handleFontDatabaseChanged()
411{
412 Q_D(QQuickWindow);
413 d->pendingFontUpdate = true;
414}
415
416void forcePolishHelper(QQuickItem *item)
417{
418 if (item->flags() & QQuickItem::ItemHasContents) {
419 item->polish();
420 }
421
422 QList <QQuickItem *> items = item->childItems();
423 for (int i=0; i<items.size(); ++i)
424 forcePolishHelper(items.at(i));
425}
426
427void QQuickWindow::handleScreenChanged(QScreen *screen)
428{
429 Q_D(QQuickWindow);
430 Q_UNUSED(screen);
431 d->forcePolish();
432}
433
434/*!
435 Schedules polish events on all items in the scene.
436*/
437void QQuickWindowPrivate::forcePolish()
438{
439 Q_Q(QQuickWindow);
440 if (!q->screen())
441 return;
442 forcePolishHelper(contentItem);
443}
444
445void forceUpdate(QQuickItem *item)
446{
447 if (item->flags() & QQuickItem::ItemHasContents)
448 item->update();
449 QQuickItemPrivate::get(item)->dirty(QQuickItemPrivate::ChildrenUpdateMask);
450
451 QList <QQuickItem *> items = item->childItems();
452 for (int i=0; i<items.size(); ++i)
453 forceUpdate(items.at(i));
454}
455
456void QQuickWindowRenderTarget::reset(QRhi *rhi, ResetFlags flags)
457{
458 if (rhi) {
459 if (rt.owns)
460 delete rt.renderTarget;
461
462 delete res.texture;
463 delete res.renderBuffer;
464 delete res.rpDesc;
465 }
466
467 rt = {};
468 res = {};
469
470 if (!flags.testFlag(ResetFlag::KeepImplicitBuffers))
471 implicitBuffers.reset(rhi);
472
473 if (sw.owns)
474 delete sw.paintDevice;
475
476 sw = {};
477}
478
480{
481 if (rhi) {
482 delete depthStencil;
483 delete depthStencilTexture;
484 delete multisampleTexture;
485 }
486 *this = {};
487}
488
489void QQuickWindowPrivate::invalidateFontData(QQuickItem *item)
490{
491 QQuickTextInterface *textItem = qobject_cast<QQuickTextInterface *>(item);
492 if (textItem != nullptr)
493 textItem->invalidate();
494
495 QList<QQuickItem *> children = item->childItems();
496 for (QQuickItem *child : children)
497 invalidateFontData(child);
498}
499
500void QQuickWindowPrivate::ensureCustomRenderTarget()
501{
502 // resolve() can be expensive when importing an existing native texture, so
503 // it is important to only do it when the QQuickRenderTarget was really changed.
504 if (!redirect.renderTargetDirty)
505 return;
506
507 redirect.renderTargetDirty = false;
508
509 redirect.rt.reset(rhi, QQuickWindowRenderTarget::ResetFlag::KeepImplicitBuffers);
510
511 if (!QQuickRenderTargetPrivate::get(&customRenderTarget)->resolve(rhi, &redirect.rt)) {
512 qWarning("Failed to set up render target redirection for QQuickWindow");
513 redirect.rt.reset(rhi);
514 }
515}
516
517void QQuickWindowPrivate::setCustomCommandBuffer(QRhiCommandBuffer *cb)
518{
519 // ownership not transferred
520 redirect.commandBuffer = cb;
521}
522
523void QQuickWindowPrivate::syncSceneGraph()
524{
525 Q_Q(QQuickWindow);
526
527 const bool wasRtDirty = redirect.renderTargetDirty;
528 ensureCustomRenderTarget();
529
530 QRhiCommandBuffer *cb = nullptr;
531 if (rhi) {
532 if (redirect.commandBuffer)
533 cb = redirect.commandBuffer;
534 else
535 cb = swapchain->currentFrameCommandBuffer();
536 }
537 context->prepareSync(q->effectiveDevicePixelRatio(), cb, graphicsConfig);
538
539 animationController->beforeNodeSync();
540
541 emit q->beforeSynchronizing();
542 runAndClearJobs(&beforeSynchronizingJobs);
543
544 if (pendingFontUpdate) {
545 QFont::cleanup();
546 invalidateFontData(contentItem);
547 context->invalidateGlyphCaches();
548 }
549
550 if (Q_UNLIKELY(!renderer)) {
551 forceUpdate(contentItem);
552
553 QSGRootNode *rootNode = new QSGRootNode;
554 rootNode->appendChildNode(QQuickItemPrivate::get(contentItem)->itemNode());
555 const bool useDepth = graphicsConfig.isDepthBufferEnabledFor2D();
556 const QSGRendererInterface::RenderMode renderMode = useDepth ? QSGRendererInterface::RenderMode2D
557 : QSGRendererInterface::RenderMode2DNoDepthBuffer;
558 renderer = context->createRenderer(renderMode);
559 renderer->setRootNode(rootNode);
560 } else if (Q_UNLIKELY(wasRtDirty)
561 && q->rendererInterface()->graphicsApi() == QSGRendererInterface::Software) {
562 auto softwareRenderer = static_cast<QSGSoftwareRenderer *>(renderer);
563 softwareRenderer->markDirty();
564 }
565
566 updateDirtyNodes();
567
568 animationController->afterNodeSync();
569
570 renderer->setClearColor(clearColor);
571
572 renderer->setVisualizationMode(visualizationMode);
573
574 if (pendingFontUpdate) {
575 context->flushGlyphCaches();
576 pendingFontUpdate = false;
577 }
578
579 emit q->afterSynchronizing();
580 runAndClearJobs(&afterSynchronizingJobs);
581}
582
583void QQuickWindowPrivate::emitBeforeRenderPassRecording(void *ud)
584{
585 QQuickWindow *w = reinterpret_cast<QQuickWindow *>(ud);
586 emit w->beforeRenderPassRecording();
587}
588
589void QQuickWindowPrivate::emitAfterRenderPassRecording(void *ud)
590{
591 QQuickWindow *w = reinterpret_cast<QQuickWindow *>(ud);
592 emit w->afterRenderPassRecording();
593}
594
595int QQuickWindowPrivate::multiViewCount()
596{
597 if (rhi) {
598 ensureCustomRenderTarget();
599 if (redirect.rt.rt.renderTarget)
600 return redirect.rt.rt.multiViewCount;
601 }
602
603 // Note that on QRhi level 0 and 1 are often used interchangeably, as both mean
604 // no-multiview. Here in Qt Quick let's always use 1 as the default
605 // (no-multiview), so that higher layers (effects, materials) do not need to
606 // handle both 0 and 1, only 1.
607 return 1;
608}
609
610QRhiRenderTarget *QQuickWindowPrivate::activeCustomRhiRenderTarget()
611{
612 if (rhi) {
613 ensureCustomRenderTarget();
614 return redirect.rt.rt.renderTarget;
615 }
616 return nullptr;
617}
618
619void QQuickWindowPrivate::renderSceneGraph()
620{
621 Q_Q(QQuickWindow);
622 if (!renderer)
623 return;
624
625 ensureCustomRenderTarget();
626
627 QSGRenderTarget sgRenderTarget;
628 if (rhi) {
629 QRhiRenderTarget *rt;
630 QRhiRenderPassDescriptor *rp;
631 QRhiCommandBuffer *cb;
632 if (redirect.rt.rt.renderTarget) {
633 rt = redirect.rt.rt.renderTarget;
634 rp = rt->renderPassDescriptor();
635 if (!rp) {
636 qWarning("Custom render target is set but no renderpass descriptor has been provided.");
637 return;
638 }
639 cb = redirect.commandBuffer;
640 if (!cb) {
641 qWarning("Custom render target is set but no command buffer has been provided.");
642 return;
643 }
644 } else {
645 if (!swapchain) {
646 qWarning("QQuickWindow: No render target (neither swapchain nor custom target was provided)");
647 return;
648 }
649 rt = swapchain->currentFrameRenderTarget();
650 rp = rpDescForSwapchain;
651 cb = swapchain->currentFrameCommandBuffer();
652 }
653 sgRenderTarget = QSGRenderTarget(rt, rp, cb);
654 sgRenderTarget.multiViewCount = multiViewCount();
655 } else {
656 sgRenderTarget = QSGRenderTarget(redirect.rt.sw.paintDevice);
657 }
658
659 context->beginNextFrame(renderer,
660 sgRenderTarget,
661 emitBeforeRenderPassRecording,
662 emitAfterRenderPassRecording,
663 q);
664
665 animationController->advance();
666 emit q->beforeRendering();
667 runAndClearJobs(&beforeRenderingJobs);
668
669 const qreal devicePixelRatio = q->effectiveDevicePixelRatio();
670 QSize pixelSize;
671 if (redirect.rt.rt.renderTarget)
672 pixelSize = redirect.rt.rt.renderTarget->pixelSize();
673 else if (redirect.rt.sw.paintDevice)
674 pixelSize = QSize(redirect.rt.sw.paintDevice->width(), redirect.rt.sw.paintDevice->height());
675 else if (rhi)
676 pixelSize = swapchain->currentPixelSize();
677 else // software or other backend
678 pixelSize = q->size() * devicePixelRatio;
679
680 renderer->setDevicePixelRatio(devicePixelRatio);
681 renderer->setDeviceRect(QRect(QPoint(0, 0), pixelSize));
682 renderer->setViewportRect(QRect(QPoint(0, 0), pixelSize));
683
684 QSGAbstractRenderer::MatrixTransformFlags matrixFlags;
685 bool flipY = rhi ? !rhi->isYUpInNDC() : false;
686 if (!customRenderTarget.isNull() && customRenderTarget.mirrorVertically())
687 flipY = !flipY;
688 if (flipY)
689 matrixFlags |= QSGAbstractRenderer::MatrixTransformFlipY;
690
691 const QRectF rect(QPointF(0, 0), pixelSize / devicePixelRatio);
692 renderer->setProjectionMatrixToRect(rect, matrixFlags, rhi && !rhi->isYUpInNDC());
693
694 context->renderNextFrame(renderer);
695
696 emit q->afterRendering();
697 runAndClearJobs(&afterRenderingJobs);
698
699 context->endNextFrame(renderer);
700
701 if (renderer && renderer->hasVisualizationModeWithContinuousUpdate()) {
702 // For the overdraw visualizer. This update is not urgent so avoid a
703 // direct update() call, this is only here to keep the overdraw
704 // visualization box rotating even when the scene is static.
705 QCoreApplication::postEvent(q, new QEvent(QEvent::Type(FullUpdateRequest)));
706 }
707}
708
709QQuickWindowPrivate::QQuickWindowPrivate()
710 : contentItem(nullptr)
711 , dirtyItemList(nullptr)
712 , lastReportedItemDevicePixelRatio(0)
713 , context(nullptr)
714 , renderer(nullptr)
715 , windowManager(nullptr)
716 , renderControl(nullptr)
717 , clearColor(Qt::white)
718 , persistentGraphics(true)
719 , persistentSceneGraph(true)
720 , inDestructor(false)
721 , incubationController(nullptr)
722 , hasActiveSwapchain(false)
723 , hasRenderableSwapchain(false)
724 , swapchainJustBecameRenderable(false)
725 , updatesEnabled(true)
726{
727}
728
729QQuickWindowPrivate::~QQuickWindowPrivate()
730{
731#ifdef QT_BUILD_INTERNAL
732 qCDebug(lcQuickWindow, "lifetime total, in all windows: constructed %d QQuickItems, %d ExtraData (%d%%)",
733 QQuickItemPrivate::item_counter, QQuickItemPrivate::itemExtra_counter,
734 QQuickItemPrivate::itemExtra_counter * 100 / QQuickItemPrivate::item_counter);
735 qCDebug(lcQuickWindow, "event-handling items fully within parent bounds: %d (%d%%)",
736 QQuickItemPrivate::eventHandlingChildrenWithinBounds_counter,
737 QQuickItemPrivate::eventHandlingChildrenWithinBounds_counter * 100 / QQuickItemPrivate::item_counter);
738 qCDebug(lcQuickWindow, "transform accessor calls: itemToParent %lld itemToWindow %lld windowToItem %lld; skipped due to effectiveClipping: %lld",
739 QQuickItemPrivate::itemToParentTransform_counter,
740 QQuickItemPrivate::itemToWindowTransform_counter,
741 QQuickItemPrivate::windowToItemTransform_counter,
742 QQuickItemPrivate::effectiveClippingSkips_counter);
743#endif
744 inDestructor = true;
745 redirect.rt.reset(rhi);
746 if (QQmlInspectorService *service = QQmlDebugConnector::service<QQmlInspectorService>())
747 service->removeWindow(q_func());
748 deliveryAgent = nullptr;
749}
750
751void QQuickWindowPrivate::setPalette(QQuickPalette* palette)
752{
753 if (windowPaletteRef == palette)
754 return;
755
756 if (windowPaletteRef)
757 disconnect(windowPaletteRef, &QQuickPalette::changed, this, &QQuickWindowPrivate::updateWindowPalette);
758 windowPaletteRef = palette;
759 updateWindowPalette();
760 if (windowPaletteRef)
761 connect(windowPaletteRef, &QQuickPalette::changed, this, &QQuickWindowPrivate::updateWindowPalette);
762}
763
764void QQuickWindowPrivate::updateWindowPalette()
765{
766 QQuickPaletteProviderPrivateBase::setPalette(windowPaletteRef);
767}
768
769void QQuickWindowPrivate::updateChildrenPalettes(const QPalette &parentPalette)
770{
771 Q_Q(QQuickWindow);
772 if (auto root = q->contentItem()) {
773 for (auto &&child: root->childItems()) {
774 QQuickItemPrivate::get(child)->inheritPalette(parentPalette);
775 }
776 }
777}
778
779void QQuickWindowPrivate::init(QQuickWindow *c, QQuickRenderControl *control)
780{
781 q_ptr = c;
782
783
784 Q_Q(QQuickWindow);
785
786 contentItem = new QQuickRootItem;
787 contentItem->setObjectName(q->objectName());
788 QQml_setParent_noEvent(contentItem, c);
789 QQmlEngine::setObjectOwnership(contentItem, QQmlEngine::CppOwnership);
790 QQuickItemPrivate *contentItemPrivate = QQuickItemPrivate::get(contentItem);
791 contentItemPrivate->window = q;
792 contentItemPrivate->windowRefCount = 1;
793 contentItemPrivate->flags |= QQuickItem::ItemIsFocusScope;
794 contentItem->setSize(q->size());
795 deliveryAgent = new QQuickDeliveryAgent(contentItem);
796
797 visualizationMode = qgetenv("QSG_VISUALIZE");
798 renderControl = control;
799 if (renderControl)
800 QQuickRenderControlPrivate::get(renderControl)->window = q;
801
802 if (!renderControl)
803 windowManager = QSGRenderLoop::instance();
804
805 Q_ASSERT(windowManager || renderControl);
806
807 QObject::connect(static_cast<QGuiApplication *>(QGuiApplication::instance()),
808 &QGuiApplication::fontDatabaseChanged,
809 q,
810 &QQuickWindow::handleFontDatabaseChanged);
811
812 if (q->screen()) {
813 lastReportedItemDevicePixelRatio = q->effectiveDevicePixelRatio();
814 }
815
816 QSGContext *sg;
817 if (renderControl) {
818 QQuickRenderControlPrivate *renderControlPriv = QQuickRenderControlPrivate::get(renderControl);
819 sg = renderControlPriv->sg;
820 context = renderControlPriv->rc;
821 } else {
822 windowManager->addWindow(q);
823 sg = windowManager->sceneGraphContext();
824 context = windowManager->createRenderContext(sg);
825 }
826
827 q->setSurfaceType(windowManager ? windowManager->windowSurfaceType() : QSurface::OpenGLSurface);
828 q->setFormat(sg->defaultSurfaceFormat());
829 // When using Vulkan, associating a scenegraph-managed QVulkanInstance with
830 // the window (but only when not using renderControl) is deferred to
831 // QSGRhiSupport::createRhi(). This allows applications to set up their own
832 // QVulkanInstance and set that on the window, if they wish to.
833
834 animationController.reset(new QQuickAnimatorController(q));
835
836 connections = {
837 QObject::connect(context, &QSGRenderContext::initialized, q, &QQuickWindow::sceneGraphInitialized, Qt::DirectConnection),
838 QObject::connect(context, &QSGRenderContext::invalidated, q, &QQuickWindow::sceneGraphInvalidated, Qt::DirectConnection),
839 QObject::connect(context, &QSGRenderContext::invalidated, q, &QQuickWindow::cleanupSceneGraph, Qt::DirectConnection),
840
841 QObject::connect(q, &QQuickWindow::focusObjectChanged, q, &QQuickWindow::activeFocusItemChanged),
842 QObject::connect(q, &QQuickWindow::screenChanged, q, &QQuickWindow::handleScreenChanged),
843 QObject::connect(qApp, &QGuiApplication::applicationStateChanged, q, &QQuickWindow::handleApplicationStateChanged),
844 QObject::connect(q, &QQuickWindow::frameSwapped, q, &QQuickWindow::runJobsAfterSwap, Qt::DirectConnection),
845 };
846
847 if (QQmlInspectorService *service = QQmlDebugConnector::service<QQmlInspectorService>())
848 service->addWindow(q);
849}
850
851void QQuickWindow::handleApplicationStateChanged(Qt::ApplicationState state)
852{
853 Q_D(QQuickWindow);
854 if (state != Qt::ApplicationActive && d->contentItem) {
855 auto da = d->deliveryAgentPrivate();
856 Q_ASSERT(da);
857 da->handleWindowDeactivate(this);
858 }
859}
860
861/*!
862 \property QQuickWindow::data
863 \internal
864*/
865
866QQmlListProperty<QObject> QQuickWindowPrivate::data()
867{
868 QQmlListProperty<QObject> ret;
869
870 ret.object = q_func();
871 ret.append = QQuickWindowPrivate::data_append;
872 ret.count = QQuickWindowPrivate::data_count;
873 ret.at = QQuickWindowPrivate::data_at;
874 ret.clear = QQuickWindowPrivate::data_clear;
875 // replace is not supported by QQuickItem. Don't synthesize it.
876 ret.removeLast = QQuickWindowPrivate::data_removeLast;
877
878 return ret;
879}
880
881void QQuickWindowPrivate::dirtyItem(QQuickItem *item)
882{
883 Q_Q(QQuickWindow);
884
885 QQuickItemPrivate *itemPriv = QQuickItemPrivate::get(item);
886 if (itemPriv->dirtyAttributes & QQuickItemPrivate::ChildrenStackingChanged)
887 needsChildWindowStackingOrderUpdate = true;
888
889 q->maybeUpdate();
890}
891
892/*!
893 \deprecated Use QPointerEvent::exclusiveGrabber().
894 Returns the item which currently has the mouse grab.
895*/
896QQuickItem *QQuickWindow::mouseGrabberItem() const
897{
898 Q_D(const QQuickWindow);
899 auto da = const_cast<QQuickWindowPrivate *>(d)->deliveryAgentPrivate();
900 Q_ASSERT(da);
901 // The normal use case is to call this function while an event is being delivered;
902 // but if the caller knows about the event, it should call QPointerEvent::exclusiveGrabber() instead.
903 if (auto epd = da->mousePointData())
904 return qmlobject_cast<QQuickItem *>(epd->exclusiveGrabber);
905
906 if (Q_LIKELY(d->deliveryAgentPrivate()->eventsInDelivery.isEmpty()))
907 // mousePointData() checked that already: it's one reason epd can be null
908 qCDebug(lcMouse, "mouse grabber ambiguous: no event is currently being delivered");
909 // If no event is being delivered, we can return "the mouse" grabber,
910 // but in general there could be more than one mouse, could be only a touchscreen etc.
911 // That's why this function is obsolete.
912 return qmlobject_cast<QQuickItem *>(QPointingDevicePrivate::get(QPointingDevice::primaryPointingDevice())->
913 firstPointExclusiveGrabber());
914}
915
916void QQuickWindowPrivate::cleanup(QSGNode *n)
917{
918 Q_Q(QQuickWindow);
919
920 Q_ASSERT(!cleanupNodeList.contains(n));
921 cleanupNodeList.append(n);
922 q->maybeUpdate();
923}
924
925/*!
926 \qmltype Window
927 \nativetype QQuickWindow
928 \inqmlmodule QtQuick
929 \ingroup qtquick-visual
930 \brief Creates a new top-level window.
931
932 The Window object creates a new top-level window for a Qt Quick scene. It automatically sets up the
933 window for use with \c {QtQuick} graphical types.
934
935 A Window can be declared inside an Item or inside another Window, in which
936 case the inner Window will automatically become "transient for" the outer
937 Window, with the outer Window as its \l transientParent. Most platforms will
938 show the Window centered upon the outer window in this case, and there may be
939 other platform-dependent behaviors, depending also on the \l flags. If the nested
940 window is intended to be a dialog in your application, you should also set \l flags
941 to \c Qt.Dialog, because some window managers will not provide the centering behavior
942 without that flag.
943
944 You can also declare multiple windows inside a top-level \l QtObject, in which
945 case the windows will have no transient relationship.
946
947 Alternatively you can set or bind \l x and \l y to position the Window
948 explicitly on the screen.
949
950 When the user attempts to close a window, the \l closing signal will be
951 emitted. You can force the window to stay open (for example to prompt the
952 user to save changes) by writing an \c onClosing handler that sets
953 \c {close.accepted = false} unless it's safe to close the window (for example,
954 because there are no more unsaved changes).
955
956 \code
957 onClosing: (close) => {
958 if (document.changed) {
959 close.accepted = false
960 confirmExitPopup.open()
961 }
962 }
963
964 // The confirmExitPopup allows user to save or discard the document,
965 // or to cancel the closing.
966 \endcode
967
968 \section1 Styling
969
970 As with all visual types in Qt Quick, Window supports
971 \l {palette}{palettes}. However, as with types like \l Text, Window does
972 not use palettes by default. For example, to change the background color
973 of the window when the operating system's theme changes, the \l color must
974 be set:
975
976 \snippet qml/windowPalette.qml declaration-and-color
977 \codeline
978 \snippet qml/windowPalette.qml text-item
979 \snippet qml/windowPalette.qml closing-brace
980
981 Use \l {ApplicationWindow} (and \l {Label}) from \l {Qt Quick Controls}
982 instead of Window to get automatic styling.
983*/
984
985/*!
986 \class QQuickWindow
987 \since 5.0
988
989 \inmodule QtQuick
990
991 \brief The QQuickWindow class provides the window for displaying a graphical QML scene.
992
993 QQuickWindow provides the graphical scene management needed to interact with and display
994 a scene of QQuickItems.
995
996 A QQuickWindow always has a single invisible root item. To add items to this window,
997 reparent the items to the root item or to an existing item in the scene.
998
999 For easily displaying a scene from a QML file, see \l{QQuickView}.
1000
1001 \section1 Rendering
1002
1003 QQuickWindow uses a scene graph to represent what needs to be rendered.
1004 This scene graph is disconnected from the QML scene and potentially lives in
1005 another thread, depending on the platform implementation. Since the
1006 rendering scene graph lives independently from the QML scene, it can also be
1007 completely released without affecting the state of the QML scene.
1008
1009 The sceneGraphInitialized() signal is emitted on the rendering thread before
1010 the QML scene is rendered to the screen for the first time. If the rendering
1011 scene graph has been released, the signal will be emitted again before the
1012 next frame is rendered. A visible, on-screen QQuickWindow is driven
1013 internally by a \c{render loop}, of which there are multiple implementations
1014 provided in the scene graph. For details on the scene graph rendering
1015 process, see \l{Qt Quick Scene Graph}.
1016
1017 By default, a QQuickWindow renders using an accelerated 3D graphics API,
1018 such as OpenGL or Vulkan. See \l{Scene Graph Adaptations} for a detailed
1019 overview of scene graph backends and the supported graphics APIs.
1020
1021 \warning It is crucial that graphics operations and interaction with the
1022 scene graph happens exclusively on the rendering thread, primarily during
1023 the updatePaintNode() phase.
1024
1025 \warning As many of the signals related to rendering are emitted from the
1026 rendering thread, connections should be made using Qt::DirectConnection.
1027
1028 \section2 Integration with Accelerated 3D Graphics APIs
1029
1030 It is possible to integrate OpenGL, Vulkan, Metal, or Direct3D 11 calls
1031 directly into the QQuickWindow, as long as the QQuickWindow and the
1032 underlying scene graph is rendering using the same API. To access native
1033 graphics objects, such as device or context object handles, use
1034 QSGRendererInterface. An instance of QSGRendererInterface is queriable from
1035 QQuickWindow by calling rendererInterface(). The enablers for this
1036 integration are the beforeRendering(), beforeRenderPassRecording(),
1037 afterRenderPassRecording(), and related signals. These allow rendering
1038 underlays or overlays. Alternatively, QNativeInterface::QSGOpenGLTexture,
1039 QNativeInterface::QSGVulkanTexture, and other similar classes allow
1040 wrapping an existing native texture or image object in a QSGTexture that
1041 can then be used with the scene graph.
1042
1043 \section2 Rendering without Acceleration
1044
1045 A limited, pure software based rendering path is available as well. With the
1046 \c software backend, a number of Qt Quick features are not available, QML
1047 items relying on these will not be rendered at all. At the same time, this
1048 allows QQuickWindow to be functional even on systems where there is no 3D
1049 graphics API available at all. See \l{Qt Quick Software Adaptation} for more
1050 details.
1051
1052 \section2 Redirected Rendering
1053
1054 A QQuickWindow is not necessarily backed by a native window on screen. The
1055 rendering can be redirected to target a custom render target, such as a
1056 given native texture. This is achieved in combination with the
1057 QQuickRenderControl class, and functions such as setRenderTarget(),
1058 setGraphicsDevice(), and setGraphicsConfiguration().
1059
1060 In this case, the QQuickWindow represents the scene, and provides the
1061 intrastructure for rendering a frame. It will not be backed by a render
1062 loop and a native window. Instead, in this case the application drives
1063 rendering, effectively substituting for the render loops. This allows
1064 generating image sequences, rendering into textures for use in external 3D
1065 engines, or rendering Qt Quick content within a VR environment.
1066
1067 \section2 Resource Management
1068
1069 QML will try to cache images and scene graph nodes to improve performance,
1070 but in some low-memory scenarios it might be required to aggressively
1071 release these resources. The releaseResources() function can be used to
1072 force the clean up of certain resources, especially resource that are cached
1073 and can be recreated later when needed again.
1074
1075 Additionally, calling releaseResources() may result in releasing the entire
1076 scene graph and the associated graphics resources. The
1077 sceneGraphInvalidated() signal will be emitted when this happens. This
1078 behavior is controlled by the setPersistentGraphics() and
1079 setPersistentSceneGraph() functions.
1080
1081 \note All classes with QSG prefix should be used solely on the scene graph's
1082 rendering thread. See \l {Scene Graph and Rendering} for more information.
1083
1084 \section2 Exposure and Visibility
1085
1086 When a QQuickWindow instance is deliberately hidden with hide() or
1087 setVisible(false), it will stop rendering and its scene graph and graphics
1088 context might be released as well. This depends on the settings configured
1089 by setPersistentGraphics() and setPersistentSceneGraph(). The behavior in
1090 this respect is identical to explicitly calling the releaseResources()
1091 function. A window can become not exposed, in other words non-renderable, by
1092 other means as well. This depends on the platform and windowing system. For
1093 example, on Windows minimizing a window makes it stop rendering. On \macos
1094 fully obscuring a window by other windows on top triggers the same. On
1095 Linux/X11, the behavior is dependent on the window manager.
1096
1097 \section2 OpenGL Context and Surface Formats
1098
1099 While it is possible to specify a QSurfaceFormat for every QQuickWindow by
1100 calling the member function setFormat(), windows may also be created from
1101 QML by using the Window and ApplicationWindow elements. In this case there
1102 is no C++ code involved in the creation of the window instance, yet
1103 applications may still wish to set certain surface format values, for
1104 example to request a given OpenGL version or profile. Such applications can
1105 call the static function QSurfaceFormat::setDefaultFormat() at startup. The
1106 specified format will be used for all Quick windows created afterwards.
1107
1108 \section2 Vulkan Instance
1109
1110 When using Vulkan, a QQuickWindow is automatically associated with a
1111 QVulkanInstance that is created and managed internally by the scene graph.
1112 This way most applications do not need to worry about having a \c
1113 VkInstance available since it all happens automatically. In advanced cases
1114 an application may wish to create its own QVulkanInstance, in order to
1115 configure it in a specific way. That is possible as well. Calling
1116 \l{QWindow::setVulkanInstance()}{setVulkanInstance()} on the QQuickWindow
1117 right after construction, before making it visible, leads to using the
1118 application-supplied QVulkanInstance (and the underlying \c VkInstance).
1119 When redirecting via QQuickRenderControl, there is no QVulkanInstance
1120 provided automatically, but rather the application is expected to provide
1121 its own and associate it with the QQuickWindow.
1122
1123 \section2 Graphics Contexts and Devices
1124
1125 When the scene graph is initialized, which typically happens when the
1126 window becomes exposed or, in case of redirected rendering, initialization
1127 is performed \l{QQuickRenderControl::initialize()}{via
1128 QQuickRenderControl}, the context or device objects necessary for rendering
1129 are created automatically. This includes OpenGL contexts, Direct3D devices
1130 and device contexts, Vulkan and Metal devices. These are also queriable by
1131 application code afterwards via
1132 \l{QSGRendererInterface::getResource()}{QSGRendererInterface}. When using
1133 the \c basic render loop, which performs all rendering on the GUI thread,
1134 the same context or device is used with all visible QQuickWindows. The \c
1135 threaded render loop uses a dedicated context or device object for each
1136 rendering thread, and so for each QQuickWindow. With some graphics APIs,
1137 there is a degree of customizability provided via
1138 setGraphicsConfiguration(). This makes it possible, for example, to specify
1139 the list of Vulkan extensions to enable on the \c VkDevice. Alternatively,
1140 it is also possible to provide a set of existing context or device objects
1141 for use by the QQuickWindow, instead of letting it construct its own. This
1142 is achieved through setGraphicsDevice().
1143
1144 \sa QQuickView, QQuickRenderControl, QQuickRenderTarget,
1145 QQuickGraphicsDevice, QQuickGraphicsConfiguration, QSGRendererInterface
1146*/
1147
1148/*!
1149 \qmlmethod void Window::startSystemMove()
1150 \since 6.8
1151
1152 \brief Starts a system-specific move operation.
1153
1154 Starts an interactive move operation on the window using platform support.
1155 The window follows the mouse cursor until the mouse button is released.
1156
1157 Use this method instead of \c setPosition, because it allows the window manager
1158 to handle snapping, tiling, and related animations. On Wayland, \c setPosition
1159 is not supported, so this is the only way the application can influence the
1160 window’s position.
1161*/
1162
1163/*!
1164 \qmlmethod void Window::startSystemResize(Qt::Edges edges)
1165 \since 6.8
1166
1167 \brief Starts a system-specific resize operation.
1168
1169 Starts an interactive resize operation on the window using platform support.
1170 The specified edge follows the mouse cursor while dragging.
1171
1172 Use this method instead of \c setGeometry, because it allows the window manager
1173 to handle snapping and resize animations when resizing to screen edges.
1174
1175 \a edges must be a single edge or a combination of two adjacent edges (a corner).
1176 Other values are not allowed.
1177*/
1178
1179/*!
1180 Constructs a window for displaying a QML scene with parent window \a parent.
1181*/
1182QQuickWindow::QQuickWindow(QWindow *parent)
1183 : QQuickWindow(*new QQuickWindowPrivate, parent)
1184{
1185}
1186
1187
1188
1189/*!
1190 \internal
1191*/
1192QQuickWindow::QQuickWindow(QQuickWindowPrivate &dd, QWindow *parent)
1193 : QWindow(dd, parent)
1194{
1195 Q_D(QQuickWindow);
1196 d->init(this);
1197}
1198
1199/*!
1200 Constructs a window for displaying a QML scene, whose rendering will
1201 be controlled by the \a control object.
1202 Please refer to QQuickRenderControl's documentation for more information.
1203
1204 \since 5.4
1205*/
1206QQuickWindow::QQuickWindow(QQuickRenderControl *control)
1207 : QWindow(*(new QQuickWindowPrivate), nullptr)
1208{
1209 Q_D(QQuickWindow);
1210 d->init(this, control);
1211}
1212
1213/*!
1214 \internal
1215*/
1216QQuickWindow::QQuickWindow(QQuickWindowPrivate &dd, QQuickRenderControl *control)
1217 : QWindow(dd, nullptr)
1218{
1219 Q_D(QQuickWindow);
1220 d->init(this, control);
1221}
1222
1223/*!
1224 Destroys the window.
1225*/
1226QQuickWindow::~QQuickWindow()
1227{
1228 Q_D(QQuickWindow);
1229 d->inDestructor = true;
1230 if (d->renderControl) {
1231 QQuickRenderControlPrivate::get(d->renderControl)->windowDestroyed();
1232 } else if (d->windowManager) {
1233 d->windowManager->removeWindow(this);
1234 d->windowManager->windowDestroyed(this);
1235 }
1236
1237 disconnect(this, &QQuickWindow::focusObjectChanged, this, &QQuickWindow::activeFocusItemChanged);
1238 disconnect(this, &QQuickWindow::screenChanged, this, &QQuickWindow::handleScreenChanged);
1239 disconnect(qApp, &QGuiApplication::applicationStateChanged, this, &QQuickWindow::handleApplicationStateChanged);
1240 disconnect(this, &QQuickWindow::frameSwapped, this, &QQuickWindow::runJobsAfterSwap);
1241
1242 delete d->incubationController; d->incubationController = nullptr;
1243 QQuickRootItem *root = d->contentItem;
1244 d->contentItem = nullptr;
1245 root->setParent(nullptr); // avoid QChildEvent delivery during deletion
1246 delete root;
1247 d->deliveryAgent = nullptr; // avoid forwarding events there during destruction
1248
1249
1250 {
1251 const std::lock_guard locker(d->renderJobMutex);
1252 qDeleteAll(std::exchange(d->beforeSynchronizingJobs, {}));
1253 qDeleteAll(std::exchange(d->afterSynchronizingJobs, {}));
1254 qDeleteAll(std::exchange(d->beforeRenderingJobs, {}));
1255 qDeleteAll(std::exchange(d->afterRenderingJobs, {}));;
1256 qDeleteAll(std::exchange(d->afterSwapJobs, {}));
1257 }
1258
1259 // It is important that the pixmap cache is cleaned up during shutdown.
1260 // Besides playing nice, this also solves a practical problem that
1261 // QQuickTextureFactory implementations in other libraries need
1262 // have their destructors loaded while they the library is still
1263 // loaded into memory.
1264 QQuickPixmap::purgeCache();
1265
1266 for (QMetaObject::Connection &connection : d->connections)
1267 disconnect(connection);
1268}
1269
1270#if QT_CONFIG(quick_shadereffect)
1271void qtquick_shadereffect_purge_gui_thread_shader_cache();
1272#endif
1273
1274/*!
1275 This function tries to release redundant resources currently held by the QML scene.
1276
1277 Calling this function requests the scene graph to release cached graphics
1278 resources, such as graphics pipeline objects, shader programs, or image
1279 data.
1280
1281 Additionally, depending on the render loop in use, this function may also
1282 result in the scene graph and all window-related rendering resources to be
1283 released. If this happens, the sceneGraphInvalidated() signal will be
1284 emitted, allowing users to clean up their own graphics resources. The
1285 setPersistentGraphics() and setPersistentSceneGraph() functions can be used
1286 to prevent this from happening, if handling the cleanup is not feasible in
1287 the application, at the cost of higher memory usage.
1288
1289 \note The releasing of cached graphics resources, such as graphics
1290 pipelines or shader programs is not dependent on the persistency hints. The
1291 releasing of those will happen regardless of the values of the persistent
1292 graphics and scenegraph hints.
1293
1294 \note This function is not related to the QQuickItem::releaseResources()
1295 virtual function.
1296
1297 \sa sceneGraphInvalidated(), setPersistentGraphics(), setPersistentSceneGraph()
1298 */
1299
1300void QQuickWindow::releaseResources()
1301{
1302 Q_D(QQuickWindow);
1303 if (d->windowManager)
1304 d->windowManager->releaseResources(this);
1305 QQuickPixmap::purgeCache();
1306#if QT_CONFIG(quick_shadereffect)
1307 qtquick_shadereffect_purge_gui_thread_shader_cache();
1308#endif
1309}
1310
1311
1312
1313/*!
1314 Sets whether the graphics resources (graphics device or context,
1315 swapchain, buffers, textures) should be preserved, and cannot be
1316 released until the last window is deleted, to \a persistent. The
1317 default value is true.
1318
1319 When calling releaseResources(), or when the window gets hidden (more
1320 specifically, not renderable), some render loops have the possibility
1321 to release all, not just the cached, graphics resources. This can free
1322 up memory temporarily, but it also means the rendering engine will have
1323 to do a full, potentially costly reinitialization of the resources when
1324 the window needs to render again.
1325
1326 \note The rules for when a window is not renderable are platform and
1327 window manager specific.
1328
1329 \note All graphics resources are released when the last QQuickWindow is
1330 deleted, regardless of this setting.
1331
1332 \note This is a hint, and is not guaranteed that it is taken into account.
1333
1334 \note This hint does not apply to cached resources, that are relatively
1335 cheap to drop and then recreate later. Therefore, calling releaseResources()
1336 will typically lead to releasing those regardless of the value of this hint.
1337
1338 \sa setPersistentSceneGraph(), sceneGraphInitialized(), sceneGraphInvalidated(), releaseResources()
1339 */
1340
1341void QQuickWindow::setPersistentGraphics(bool persistent)
1342{
1343 Q_D(QQuickWindow);
1344 d->persistentGraphics = persistent;
1345}
1346
1347
1348
1349/*!
1350 Returns whether essential graphics resources can be released during the
1351 lifetime of the QQuickWindow.
1352
1353 \note This is a hint, and is not guaranteed that it is taken into account.
1354
1355 \sa setPersistentGraphics()
1356 */
1357
1358bool QQuickWindow::isPersistentGraphics() const
1359{
1360 Q_D(const QQuickWindow);
1361 return d->persistentGraphics;
1362}
1363
1364
1365
1366/*!
1367 Sets whether the scene graph nodes and resources are \a persistent.
1368 Persistent means the nodes and resources cannot be released.
1369 The default value is \c true.
1370
1371 When calling releaseResources(), when the window gets hidden (more
1372 specifically, not renderable), some render loops have the possibility
1373 to release the scene graph nodes and related graphics resources. This
1374 frees up memory temporarily, but will also mean the scene graph has to
1375 be rebuilt when the window renders next time.
1376
1377 \note The rules for when a window is not renderable are platform and
1378 window manager specific.
1379
1380 \note The scene graph nodes and resources are always released when the
1381 last QQuickWindow is deleted, regardless of this setting.
1382
1383 \note This is a hint, and is not guaranteed that it is taken into account.
1384
1385 \sa setPersistentGraphics(), sceneGraphInvalidated(), sceneGraphInitialized(), releaseResources()
1386 */
1387
1388void QQuickWindow::setPersistentSceneGraph(bool persistent)
1389{
1390 Q_D(QQuickWindow);
1391 d->persistentSceneGraph = persistent;
1392}
1393
1394
1395
1396/*!
1397 Returns whether the scene graph nodes and resources can be
1398 released during the lifetime of this QQuickWindow.
1399
1400 \note This is a hint. When and how this happens is implementation
1401 specific.
1402 */
1403
1404bool QQuickWindow::isPersistentSceneGraph() const
1405{
1406 Q_D(const QQuickWindow);
1407 return d->persistentSceneGraph;
1408}
1409
1410/*!
1411 \qmlattachedproperty Item Window::contentItem
1412 \since 5.4
1413
1414 This attached property holds the invisible root item of the scene or
1415 \c null if the item is not in a window. The Window attached property
1416 can be attached to any Item.
1417*/
1418
1419/*!
1420 \property QQuickWindow::contentItem
1421 \brief The invisible root item of the scene.
1422
1423 A QQuickWindow always has a single invisible root item containing all of its content.
1424 To add items to this window, reparent the items to the contentItem or to an existing
1425 item in the scene.
1426*/
1427QQuickItem *QQuickWindow::contentItem() const
1428{
1429 Q_D(const QQuickWindow);
1430
1431 return d->contentItem;
1432}
1433
1434/*!
1435 \property QQuickWindow::activeFocusItem
1436
1437 \brief The item which currently has active focus or \c null if there is
1438 no item with active focus.
1439
1440 \sa QQuickItem::forceActiveFocus(), {Keyboard Focus in Qt Quick}
1441*/
1442QQuickItem *QQuickWindow::activeFocusItem() const
1443{
1444 Q_D(const QQuickWindow);
1445 auto da = d->deliveryAgentPrivate();
1446 Q_ASSERT(da);
1447 return da->activeFocusItem;
1448}
1449
1450/*!
1451 \internal
1452 \reimp
1453*/
1454QObject *QQuickWindow::focusObject() const
1455{
1456 Q_D(const QQuickWindow);
1457 auto da = d->deliveryAgentPrivate();
1458 Q_ASSERT(da);
1459 if (!d->inDestructor && da->activeFocusItem)
1460 return da->activeFocusItem;
1461 return const_cast<QQuickWindow*>(this);
1462}
1463
1464/*! \reimp */
1465bool QQuickWindow::event(QEvent *event)
1466{
1467 Q_D(QQuickWindow);
1468
1469 // bypass QWindow::event dispatching of input events: deliveryAgent takes care of it
1470 QQuickDeliveryAgent *da = d->deliveryAgent;
1471 if (event->isPointerEvent()) {
1472 /*
1473 We can't bypass the virtual functions like mousePressEvent() tabletEvent() etc.,
1474 for the sake of code that subclasses QQuickWindow and overrides them, even though
1475 we no longer need them as entry points for Qt Quick event delivery.
1476 So dispatch to them now, ahead of normal delivery, and stop them from calling
1477 back into this function if they were called from here (avoid recursion).
1478 It could also be that user code expects them to work as entry points, too;
1479 in that case, windowEventDispatch _won't_ be set, so the event comes here and
1480 we'll dispatch it further below.
1481 */
1482 if (d->windowEventDispatch)
1483 return false;
1484 {
1485 const bool wasAccepted = event->isAccepted();
1486 QScopedValueRollback windowEventDispatchGuard(d->windowEventDispatch, true);
1487 qCDebug(lcPtr) << "dispatching to window functions in case of override" << event;
1488 QWindow::event(event);
1489 if (event->isAccepted() && !wasAccepted)
1490 return true;
1491 }
1492 /*
1493 QQuickWindow does not override touchEvent(). If the application has a subclass
1494 of QQuickWindow which allows the event to remain accepted, it means they want
1495 to stop propagation here, so return early (below). But otherwise we will call
1496 QWindow::touchEvent(), which will ignore(); in that case, we need to continue
1497 with the usual delivery below, so we need to undo the ignore().
1498 */
1499 auto pe = static_cast<QPointerEvent *>(event);
1500 if (QQuickDeliveryAgentPrivate::isTouchEvent(pe))
1501 event->accept();
1502 // end of dispatch to user-overridden virtual window functions
1503
1504 /*
1505 When delivering update and release events to existing grabbers,
1506 use the subscene delivery agent, if any. A possible scenario:
1507 1) Two touchpoints pressed on the main window: QQuickWindowPrivate::deliveryAgent delivers to QQuick3DViewport,
1508 which does picking and finds two subscenes ("root" Items mapped onto two different 3D objects) to deliver it to.
1509 2) The QTouchEvent is split up so that each subscene sees points relevant to it.
1510 3) During delivery to either subscene, an item in the subscene grabs.
1511 4) The user moves finger(s) generating a move event: the correct grabber item needs to get the update
1512 via the same subscene delivery agent from which it got the press, so that the coord transform will be done properly.
1513 5) Likewise with the touchpoint releases.
1514 With single-point events (mouse, or only one finger) it's simplified: there can only be one subscene of interest;
1515 for (pt : pe->points()) would only iterate once, so we might as well skip that logic.
1516 */
1517 if (pe->pointCount()) {
1518 const bool synthMouse = QQuickDeliveryAgentPrivate::isSynthMouse(pe);
1519 if (QQuickDeliveryAgentPrivate::subsceneAgentsExist) {
1520 bool ret = false;
1521 // Split up the multi-point event according to the relevant QQuickDeliveryAgent that should deliver to each existing grabber
1522 // but send ungrabbed points to d->deliveryAgent()
1523 QFlatMap<QQuickDeliveryAgent*, QList<QEventPoint>> deliveryAgentsNeedingPoints;
1524 QEventPoint::States eventStates;
1525
1526 auto insert = [&](QQuickDeliveryAgent *ptda, const QEventPoint &pt) {
1527 if (pt.state() == QEventPoint::Pressed && !synthMouse)
1528 pe->clearPassiveGrabbers(pt);
1529 auto &ptList = deliveryAgentsNeedingPoints[ptda];
1530 auto idEquals = [](auto id) { return [id] (const auto &e) { return e.id() == id; }; };
1531 if (std::none_of(ptList.cbegin(), ptList.cend(), idEquals(pt.id())))
1532 ptList.append(pt);
1533 };
1534
1535 for (const auto &pt : pe->points()) {
1536 eventStates |= pt.state();
1537 auto epd = QPointingDevicePrivate::get(const_cast<QPointingDevice*>(pe->pointingDevice()))->queryPointById(pt.id());
1538 Q_ASSERT(epd);
1539 bool foundAgent = false;
1540 if (!epd->exclusiveGrabber.isNull() && !epd->exclusiveGrabberContext.isNull()) {
1541 if (auto ptda = qobject_cast<QQuickDeliveryAgent *>(epd->exclusiveGrabberContext.data())) {
1542 insert(ptda, pt);
1543 qCDebug(lcPtr) << pe->type() << "point" << pt.id() << pt.state()
1544 << "@" << pt.scenePosition() << "will be re-delivered via known grabbing agent" << ptda << "to" << epd->exclusiveGrabber.data();
1545 foundAgent = true;
1546 }
1547 }
1548 for (auto pgda : epd->passiveGrabbersContext) {
1549 if (auto ptda = qobject_cast<QQuickDeliveryAgent *>(pgda.data())) {
1550 insert(ptda, pt);
1551 qCDebug(lcPtr) << pe->type() << "point" << pt.id() << pt.state()
1552 << "@" << pt.scenePosition() << "will be re-delivered via known passive-grabbing agent" << ptda;
1553 foundAgent = true;
1554 }
1555 }
1556 // fallback: if we didn't find remembered/known grabber agent(s), expect the root DA to handle it
1557 if (!foundAgent)
1558 insert(da, pt);
1559 }
1560 for (auto daAndPoints : deliveryAgentsNeedingPoints) {
1561 if (pe->pointCount() > 1) {
1562 Q_ASSERT(QQuickDeliveryAgentPrivate::isTouchEvent(pe));
1563 // if all points have the same state, set the event type accordingly
1564 QEvent::Type eventType = pe->type();
1565 switch (eventStates) {
1566 case QEventPoint::State::Pressed:
1567 eventType = QEvent::TouchBegin;
1568 break;
1569 case QEventPoint::State::Released:
1570 eventType = QEvent::TouchEnd;
1571 break;
1572 default:
1573 eventType = QEvent::TouchUpdate;
1574 break;
1575 }
1576 // Make a new touch event for the subscene, the same way QQuickItemPrivate::localizedTouchEvent() does it
1577 QMutableTouchEvent te(eventType, pe->pointingDevice(), pe->modifiers(), daAndPoints.second);
1578 te.setTimestamp(pe->timestamp());
1579 te.accept();
1580 qCDebug(lcTouch) << daAndPoints.first << "shall now receive" << &te;
1581 ret = daAndPoints.first->event(&te) || ret;
1582 } else {
1583 qCDebug(lcPtr) << daAndPoints.first << "shall now receive" << pe;
1584 ret = daAndPoints.first->event(pe) || ret;
1585 }
1586 }
1587
1588 if (ret) {
1589 d->deliveryAgentPrivate()->clearGrabbers(pe);
1590 return true;
1591 }
1592 } else if (!synthMouse) {
1593 // clear passive grabbers unless it's a system synth-mouse event
1594 // QTBUG-104890: Windows sends synth mouse events (which should be ignored) after touch events
1595 for (const auto &pt : pe->points()) {
1596 if (pt.state() == QEventPoint::Pressed)
1597 pe->clearPassiveGrabbers(pt);
1598 }
1599 }
1600 }
1601
1602 // If it has no points, it's probably a TouchCancel, and DeliveryAgent needs to handle it.
1603 // If we didn't handle it in the block above, handle it now.
1604 // TODO should we deliver to all DAs at once then, since we don't know which one should get it?
1605 // or fix QTBUG-90851 so that the event always has points?
1606 qCDebug(lcHoverTrace) << this << "some sort of event" << event;
1607 bool ret = (da && da->event(event));
1608
1609 d->deliveryAgentPrivate()->clearGrabbers(pe);
1610
1611 if (pe->type() == QEvent::MouseButtonPress || pe->type() == QEvent::MouseButtonRelease) {
1612 // Ensure that we synthesize a context menu event as QWindow::event does, if necessary.
1613 // We only send the context menu event if the pointer event wasn't accepted (ret == false).
1614 d->maybeSynthesizeContextMenuEvent(static_cast<QMouseEvent *>(pe));
1615 }
1616
1617#if QT_CONFIG(tabletevent)
1618 // QGuiApplication::processTabletEvent() uses forwardToPopup() to send
1619 // tablet events to popup windows so they can handle them or block
1620 // further delivery. Prevent fall-through to any window behind a popup
1621 // by accepting any tablet event that landed outside the popup's bounds.
1622 // QTabletEvent.accepted is false by default (unlike mouse events), so
1623 // we need to stop delivery by accepting explicitly.
1624 if (type() == Qt::Popup && QQuickDeliveryAgentPrivate::isTabletEvent(pe) &&
1625 !QRect(QPoint(), size()).contains(pe->points().first().scenePosition().toPoint())) {
1626 pe->accept();
1627 return true;
1628 }
1629#endif
1630
1631 if (ret)
1632 return true;
1633 } else if (event->isInputEvent()) {
1634 if (da && da->event(event))
1635 return true;
1636 }
1637
1638 switch (event->type()) {
1639 // a few more types that are not QInputEvents, but QQuickDeliveryAgent needs to handle them anyway
1640 case QEvent::FocusAboutToChange:
1641 case QEvent::Enter:
1642 case QEvent::Leave:
1643 case QEvent::InputMethod:
1644 case QEvent::InputMethodQuery:
1645#if QT_CONFIG(quick_draganddrop)
1646 case QEvent::DragEnter:
1647 case QEvent::DragLeave:
1648 case QEvent::DragMove:
1649 case QEvent::Drop:
1650#endif
1651 if (d->inDestructor)
1652 return false;
1653 if (da && da->event(event))
1654 return true;
1655 break;
1656 case QEvent::LanguageChange:
1657 case QEvent::LocaleChange:
1658 if (d->contentItem)
1659 QCoreApplication::sendEvent(d->contentItem, event);
1660 break;
1661 case QEvent::UpdateRequest:
1662 if (d->windowManager)
1663 d->windowManager->handleUpdateRequest(this);
1664 break;
1665 case QEvent::PlatformSurface:
1666 if ((static_cast<QPlatformSurfaceEvent *>(event))->surfaceEventType() == QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed) {
1667 // Ensure that the rendering thread is notified before
1668 // the QPlatformWindow is destroyed.
1669 if (d->windowManager)
1670 d->windowManager->hide(this);
1671 }
1672 break;
1673 case QEvent::WindowDeactivate:
1674 if (auto da = d->deliveryAgentPrivate())
1675 da->handleWindowDeactivate(this);
1676 Q_FALLTHROUGH();
1677 case QEvent::WindowActivate:
1678 if (d->contentItem)
1679 QCoreApplication::sendEvent(d->contentItem, event);
1680 break;
1681 case QEvent::ApplicationPaletteChange:
1682 d->inheritPalette(QGuiApplication::palette());
1683 if (d->contentItem)
1684 QCoreApplication::sendEvent(d->contentItem, event);
1685 break;
1686 case QEvent::DevicePixelRatioChange:
1687 physicalDpiChanged();
1688 break;
1689 case QEvent::SafeAreaMarginsChange:
1690 QQuickSafeArea::updateSafeAreasRecursively(d->contentItem);
1691 break;
1692 case QEvent::ChildWindowAdded: {
1693 auto *childEvent = static_cast<QChildWindowEvent*>(event);
1694 auto *childWindow = childEvent->child();
1695 qCDebug(lcQuickWindow) << "Child window" << childWindow << "added to" << this;
1696 if (childWindow->handle()) {
1697 // The reparenting has already resulted in the native window
1698 // being added to its parent, on top of all other windows. We need
1699 // to do a synchronous re-stacking of the windows here, to avoid
1700 // leaving the window in the wrong position while waiting for the
1701 // asynchronous callback to QQuickWindow::polishItems().
1702 d->updateChildWindowStackingOrder();
1703 } else {
1704 qCDebug(lcQuickWindow) << "No platform window yet."
1705 << "Deferring child window stacking until surface creation";
1706 }
1707 break;
1708 }
1709 default:
1710 break;
1711 }
1712
1713 if (event->type() == QEvent::Type(QQuickWindowPrivate::FullUpdateRequest))
1714 update();
1715 else if (event->type() == QEvent::Type(QQuickWindowPrivate::TriggerContextCreationFailure))
1716 d->windowManager->handleContextCreationFailure(this);
1717
1718 if (event->isPointerEvent())
1719 return true;
1720 else
1721 return QWindow::event(event);
1722}
1723
1724void QQuickWindowPrivate::maybeSynthesizeContextMenuEvent(QMouseEvent *event)
1725{
1726 // See comment in QQuickWindow::event; we need to follow that pattern here,
1727 // otherwise the context menu event will be sent before the press (since
1728 // QQuickWindow::mousePressEvent returns early if windowEventDispatch is true).
1729 // If we don't do this, the incorrect order will cause the menu to
1730 // immediately close when the press is delivered.
1731 // Also, don't send QContextMenuEvent if a menu has already been opened while
1732 // handling a QMouseEvent in which the right button was pressed or released.
1733 if (windowEventDispatch || !rmbContextMenuEventEnabled)
1734 return;
1735
1736#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
1737 /*
1738 If this is a press event and the EventPoint already has a grab, it may be
1739 that a TapHandler.onTapped() or MouseArea.onClicked() function
1740 intends to show a context menu. Menus were often added that way; so if
1741 we can detect that it's likely, then don't synthesize a QContextMenuEvent,
1742 in case it could be redundant, even though we can't tell in advance
1743 whether the TapHandler or MouseArea will open a menu or do something else.
1744 However, we are only checking for MouseArea and TapHandler; it's also
1745 possible (but hopefully much less likely) that a user adds a custom
1746 QQuickItem subclass to handle mouse events to open a context menu.
1747 If a bug gets written about that, we can ask them to try out the
1748 ContextMenu attached property instead, or handle the QContextMenuEvent
1749 in their subclass. Anyway, let's expect applications to be adjusted for
1750 Qt 7 or before, so that we can get rid of this second-guessing hack.
1751 */
1752 const auto &firstPoint = event->points().first();
1753 auto hasRightButtonTapHandler = [](const auto &passiveGrabbers) {
1754 return std::find_if(passiveGrabbers.constBegin(), passiveGrabbers.constEnd(),
1755 [](const auto grabber) {
1756 auto *tapHandler = qmlobject_cast<QQuickTapHandler *>(grabber);
1757 return tapHandler && tapHandler->acceptedButtons().testFlag(Qt::RightButton); })
1758 != passiveGrabbers.constEnd();
1759 };
1760 if (event->type() == QEvent::MouseButtonPress && event->button() == Qt::RightButton &&
1761 (qmlobject_cast<QQuickMouseArea *>(event->exclusiveGrabber(firstPoint))
1762 || hasRightButtonTapHandler(event->passiveGrabbers(firstPoint)))) {
1763 qCDebug(lcPtr) << "skipping QContextMenuEvent synthesis due to grabber(s)" << event;
1764 return;
1765 }
1766#endif
1767
1768 QWindowPrivate::maybeSynthesizeContextMenuEvent(event);
1769}
1770
1771void QQuickWindowPrivate::updateChildWindowStackingOrder(QQuickItem *item)
1772{
1773 Q_Q(QQuickWindow);
1774
1775 if (!item) {
1776 qCDebug(lcQuickWindow) << "Updating child window stacking order for" << q;
1777 item = contentItem;
1778 }
1779 auto *itemPrivate = QQuickItemPrivate::get(item);
1780 const auto paintOrderChildItems = itemPrivate->paintOrderChildItems();
1781 for (auto *child : paintOrderChildItems) {
1782 if (auto *windowContainer = qobject_cast<QQuickWindowContainer*>(child)) {
1783 auto *window = windowContainer->containedWindow();
1784 if (!window) {
1785 qCDebug(lcQuickWindow) << windowContainer << "has no contained window yet";
1786 continue;
1787 }
1788 if (window->parent() != q) {
1789 qCDebug(lcQuickWindow) << window << "is not yet child of this window";
1790 continue;
1791 }
1792 qCDebug(lcQuickWindow) << "Raising" << window << "owned by" << windowContainer;
1793 window->raise();
1794 }
1795
1796 updateChildWindowStackingOrder(child);
1797 }
1798}
1799
1800/*! \reimp */
1801void QQuickWindow::keyPressEvent(QKeyEvent *e)
1802{
1803 Q_D(QQuickWindow);
1804 if (d->windowEventDispatch)
1805 return;
1806 auto da = d->deliveryAgentPrivate();
1807 Q_ASSERT(da);
1808 da->deliverKeyEvent(e);
1809}
1810
1811/*! \reimp */
1812void QQuickWindow::keyReleaseEvent(QKeyEvent *e)
1813{
1814 Q_D(QQuickWindow);
1815 if (d->windowEventDispatch)
1816 return;
1817 auto da = d->deliveryAgentPrivate();
1818 Q_ASSERT(da);
1819 da->deliverKeyEvent(e);
1820}
1821
1822#if QT_CONFIG(wheelevent)
1823/*! \reimp */
1824void QQuickWindow::wheelEvent(QWheelEvent *event)
1825{
1826 Q_D(QQuickWindow);
1827 if (d->windowEventDispatch)
1828 return;
1829 auto da = d->deliveryAgentPrivate();
1830 Q_ASSERT(da);
1831 da->deliverSinglePointEventUntilAccepted(event);
1832}
1833#endif // wheelevent
1834
1835#if QT_CONFIG(tabletevent)
1836/*! \reimp */
1837void QQuickWindow::tabletEvent(QTabletEvent *event)
1838{
1839 Q_D(QQuickWindow);
1840 if (d->windowEventDispatch)
1841 return;
1842 auto da = d->deliveryAgentPrivate();
1843 Q_ASSERT(da);
1844 da->deliverPointerEvent(event);
1845}
1846#endif // tabletevent
1847
1848/*! \reimp */
1849void QQuickWindow::mousePressEvent(QMouseEvent *event)
1850{
1851 Q_D(QQuickWindow);
1852 if (d->windowEventDispatch)
1853 return;
1854 auto da = d->deliveryAgentPrivate();
1855 Q_ASSERT(da);
1856 da->handleMouseEvent(event);
1857}
1858/*! \reimp */
1859void QQuickWindow::mouseMoveEvent(QMouseEvent *event)
1860{
1861 Q_D(QQuickWindow);
1862 if (d->windowEventDispatch)
1863 return;
1864 auto da = d->deliveryAgentPrivate();
1865 Q_ASSERT(da);
1866 da->handleMouseEvent(event);
1867}
1868/*! \reimp */
1869void QQuickWindow::mouseDoubleClickEvent(QMouseEvent *event)
1870{
1871 Q_D(QQuickWindow);
1872 if (d->windowEventDispatch)
1873 return;
1874 auto da = d->deliveryAgentPrivate();
1875 Q_ASSERT(da);
1876 da->handleMouseEvent(event);
1877}
1878/*! \reimp */
1879void QQuickWindow::mouseReleaseEvent(QMouseEvent *event)
1880{
1881 Q_D(QQuickWindow);
1882 if (d->windowEventDispatch)
1883 return;
1884 auto da = d->deliveryAgentPrivate();
1885 Q_ASSERT(da);
1886 da->handleMouseEvent(event);
1887}
1888
1889#if QT_CONFIG(cursor)
1890void QQuickWindowPrivate::updateCursor(const QPointF &scenePos, QQuickItem *rootItem)
1891{
1892 Q_Q(QQuickWindow);
1893 if (!rootItem)
1894 rootItem = contentItem;
1895 auto cursorItemAndHandler = findCursorItemAndHandler(rootItem, scenePos, scenePos);
1896 if (cursorItem != cursorItemAndHandler.first || cursorHandler != cursorItemAndHandler.second ||
1897 (cursorItemAndHandler.second && QQuickPointerHandlerPrivate::get(cursorItemAndHandler.second)->cursorDirty)) {
1898 QWindow *renderWindow = QQuickRenderControl::renderWindowFor(q);
1899 QWindow *window = renderWindow ? renderWindow : q;
1900 cursorItem = cursorItemAndHandler.first;
1901 cursorHandler = cursorItemAndHandler.second;
1902 if (cursorHandler)
1903 QQuickPointerHandlerPrivate::get(cursorItemAndHandler.second)->cursorDirty = false;
1904 if (cursorItem) {
1905 const auto cursor = QQuickItemPrivate::get(cursorItem)->effectiveCursor(cursorHandler);
1906 qCDebug(lcHoverCursor) << "setting cursor" << cursor << "from" << cursorHandler << "or" << cursorItem;
1907 window->setCursor(cursor);
1908 } else {
1909 qCDebug(lcHoverCursor) << "unsetting cursor";
1910 window->unsetCursor();
1911 }
1912 }
1913}
1914
1915std::pair<QQuickItem*, QQuickPointerHandler*> QQuickWindowPrivate::findCursorItemAndHandler(QQuickItem *item,
1916 const QPointF &localPos, const QPointF &scenePos) const
1917{
1918 QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
1919 if (itemPrivate->effectivelyClipsEventHandlingChildren() &&
1920 !itemPrivate->eventHandlingBounds().contains(localPos)) {
1921#ifdef QT_BUILD_INTERNAL
1922 ++QQuickItemPrivate::effectiveClippingSkips_counter;
1923#endif
1924 return {nullptr, nullptr};
1925 }
1926
1927 if (itemPrivate->subtreeCursorEnabled) {
1928 QList<QQuickItem *> children = itemPrivate->paintOrderChildItems();
1929 for (int ii = children.size() - 1; ii >= 0; --ii) {
1930 QQuickItem *child = children.at(ii);
1931 if (!child->isVisible() || !child->isEnabled() || QQuickItemPrivate::get(child)->culled)
1932 continue;
1933
1934 const QQuickItemPrivate *childPrivate = QQuickItemPrivate::get(child);
1935 QTransform childToParent;
1936 childPrivate->itemToParentTransform(&childToParent);
1937 const QPointF childLocalPos = childToParent.inverted().map(localPos);
1938 auto ret = findCursorItemAndHandler(child, childLocalPos, scenePos);
1939 if (ret.first)
1940 return ret;
1941 }
1942 if (itemPrivate->hasCursorHandler) {
1943 if (auto handler = itemPrivate->effectiveCursorHandler()) {
1944 if (handler->parentContains(localPos, scenePos))
1945 return {item, handler};
1946 }
1947 }
1948 if (itemPrivate->hasCursor) {
1949 if (item->contains(localPos))
1950 return {item, nullptr};
1951 }
1952 }
1953
1954 return {nullptr, nullptr};
1955}
1956#endif
1957
1958void QQuickWindowPrivate::clearFocusObject()
1959{
1960 if (auto da = deliveryAgentPrivate())
1961 da->clearFocusObject();
1962}
1963
1964void QQuickWindowPrivate::setFocusToTarget(FocusTarget target, Qt::FocusReason reason)
1965{
1966 if (!contentItem)
1967 return;
1968
1969 QQuickItem *newFocusItem = nullptr;
1970 switch (target) {
1971 case FocusTarget::First:
1972 case FocusTarget::Last: {
1973 const bool forward = (target == FocusTarget::First);
1974 newFocusItem = QQuickItemPrivate::nextPrevItemInTabFocusChain(contentItem, forward);
1975 if (newFocusItem) {
1976 const auto *itemPriv = QQuickItemPrivate::get(newFocusItem);
1977 if (itemPriv->subFocusItem && itemPriv->flags & QQuickItem::ItemIsFocusScope)
1978 deliveryAgentPrivate()->clearFocusInScope(newFocusItem, itemPriv->subFocusItem, reason);
1979 }
1980 break;
1981 }
1982 case FocusTarget::Next:
1983 case FocusTarget::Prev: {
1984 const auto da = deliveryAgentPrivate();
1985 Q_ASSERT(da);
1986 QQuickItem *focusItem = da->focusTargetItem() ? da->focusTargetItem() : contentItem;
1987 bool forward = (target == FocusTarget::Next);
1988 newFocusItem = QQuickItemPrivate::nextPrevItemInTabFocusChain(focusItem, forward);
1989 break;
1990 }
1991 default:
1992 break;
1993 }
1994
1995 if (newFocusItem)
1996 newFocusItem->forceActiveFocus(reason);
1997}
1998
1999/*!
2000 \qmlproperty list<QtObject> Window::data
2001 \qmldefault
2002
2003 The data property allows you to freely mix visual children, resources
2004 and other Windows in a Window.
2005
2006 If you assign another Window to the data list, the nested window will
2007 become "transient for" the outer Window.
2008
2009 If you assign an \l Item to the data list, it becomes a child of the
2010 Window's \l contentItem, so that it appears inside the window. The item's
2011 parent will be the window's contentItem, which is the root of the Item
2012 ownership tree within that Window.
2013
2014 If you assign any other object type, it is added as a resource.
2015
2016 It should not generally be necessary to refer to the \c data property,
2017 as it is the default property for Window and thus all child items are
2018 automatically assigned to this property.
2019
2020 \sa QWindow::transientParent()
2021 */
2022
2023void QQuickWindowPrivate::data_append(QQmlListProperty<QObject> *property, QObject *o)
2024{
2025 if (!o)
2026 return;
2027 QQuickWindow *that = static_cast<QQuickWindow *>(property->object);
2028 QQmlListProperty<QObject> itemProperty = QQuickItemPrivate::get(that->contentItem())->data();
2029 itemProperty.append(&itemProperty, o);
2030}
2031
2032qsizetype QQuickWindowPrivate::data_count(QQmlListProperty<QObject> *property)
2033{
2034 QQuickWindow *win = static_cast<QQuickWindow*>(property->object);
2035 if (!win || !win->contentItem() || !QQuickItemPrivate::get(win->contentItem())->data().count)
2036 return 0;
2037 QQmlListProperty<QObject> itemProperty = QQuickItemPrivate::get(win->contentItem())->data();
2038 return itemProperty.count(&itemProperty);
2039}
2040
2041QObject *QQuickWindowPrivate::data_at(QQmlListProperty<QObject> *property, qsizetype i)
2042{
2043 QQuickWindow *win = static_cast<QQuickWindow*>(property->object);
2044 QQmlListProperty<QObject> itemProperty = QQuickItemPrivate::get(win->contentItem())->data();
2045 return itemProperty.at(&itemProperty, i);
2046}
2047
2048void QQuickWindowPrivate::data_clear(QQmlListProperty<QObject> *property)
2049{
2050 QQuickWindow *win = static_cast<QQuickWindow*>(property->object);
2051 QQmlListProperty<QObject> itemProperty = QQuickItemPrivate::get(win->contentItem())->data();
2052 itemProperty.clear(&itemProperty);
2053}
2054
2055void QQuickWindowPrivate::data_removeLast(QQmlListProperty<QObject> *property)
2056{
2057 QQuickWindow *win = static_cast<QQuickWindow*>(property->object);
2058 QQmlListProperty<QObject> itemProperty = QQuickItemPrivate::get(win->contentItem())->data();
2059 itemProperty.removeLast(&itemProperty);
2060}
2061
2062bool QQuickWindowPrivate::isRenderable() const
2063{
2064 Q_Q(const QQuickWindow);
2065 return ((q->isExposed() && q->isVisible())) && q->geometry().isValid();
2066}
2067
2068void QQuickWindowPrivate::rhiCreationFailureMessage(const QString &backendName,
2069 QString *translatedMessage,
2070 QString *untranslatedMessage)
2071{
2072 const char msg[] = QT_TRANSLATE_NOOP("QQuickWindow",
2073 "Failed to initialize graphics backend for %1.");
2074 *translatedMessage = QQuickWindow::tr(msg).arg(backendName);
2075 *untranslatedMessage = QString::fromLatin1(msg).arg(backendName);
2076}
2077
2078void QQuickWindowPrivate::cleanupNodes()
2079{
2080 qDeleteAll(cleanupNodeList);
2081 cleanupNodeList.clear();
2082}
2083
2084void QQuickWindowPrivate::cleanupNodesOnShutdown(QQuickItem *item)
2085{
2086 QQuickItemPrivate *p = QQuickItemPrivate::get(item);
2087 if (p->itemNodeInstance) {
2088 delete p->itemNodeInstance;
2089 p->itemNodeInstance = nullptr;
2090
2091 if (p->extra.isAllocated()) {
2092 p->extra->opacityNode = nullptr;
2093 p->extra->clipNode = nullptr;
2094 p->extra->rootNode = nullptr;
2095 }
2096
2097 p->paintNode = nullptr;
2098
2099 p->dirty(QQuickItemPrivate::Window);
2100 }
2101
2102 // Qt 7: Make invalidateSceneGraph a virtual member of QQuickItem
2103 if (p->flags & QQuickItem::ItemHasContents) {
2104 const QMetaObject *mo = item->metaObject();
2105 int index = mo->indexOfSlot("invalidateSceneGraph()");
2106 if (index >= 0) {
2107 const QMetaMethod &method = mo->method(index);
2108 // Skip functions named invalidateSceneGraph() in QML items.
2109 if (strstr(method.enclosingMetaObject()->className(), "_QML_") == nullptr)
2110 method.invoke(item, Qt::DirectConnection);
2111 }
2112 }
2113
2114 for (int ii = 0; ii < p->childItems.size(); ++ii)
2115 cleanupNodesOnShutdown(p->childItems.at(ii));
2116}
2117
2118// This must be called from the render thread, with the main thread frozen
2119void QQuickWindowPrivate::cleanupNodesOnShutdown()
2120{
2121 Q_Q(QQuickWindow);
2122 cleanupNodes();
2123 cleanupNodesOnShutdown(contentItem);
2124 for (QSet<QQuickItem *>::const_iterator it = parentlessItems.begin(), cend = parentlessItems.end(); it != cend; ++it)
2125 cleanupNodesOnShutdown(*it);
2126 animationController->windowNodesDestroyed();
2127 q->cleanupSceneGraph();
2128}
2129
2130void QQuickWindowPrivate::updateDirtyNodes()
2131{
2132 qCDebug(lcDirty) << "QQuickWindowPrivate::updateDirtyNodes():";
2133
2134 cleanupNodes();
2135
2136 QQuickItem *updateList = dirtyItemList;
2137 dirtyItemList = nullptr;
2138 if (updateList) QQuickItemPrivate::get(updateList)->prevDirtyItem = &updateList;
2139
2140 while (updateList) {
2141 QQuickItem *item = updateList;
2142 QQuickItemPrivate *itemPriv = QQuickItemPrivate::get(item);
2143 itemPriv->removeFromDirtyList();
2144
2145 qCDebug(lcDirty) << " QSGNode:" << item << qPrintable(itemPriv->dirtyToString());
2146 updateDirtyNode(item);
2147 }
2148}
2149
2150static inline QSGNode *qquickitem_before_paintNode(QQuickItemPrivate *d)
2151{
2152 const QList<QQuickItem *> childItems = d->paintOrderChildItems();
2153 QQuickItem *before = nullptr;
2154 for (int i=0; i<childItems.size(); ++i) {
2155 QQuickItemPrivate *dd = QQuickItemPrivate::get(childItems.at(i));
2156 // Perform the same check as the in fetchNextNode below.
2157 if (dd->z() < 0 && (dd->explicitVisible || (dd->extra.isAllocated() && dd->extra->effectRefCount)))
2158 before = childItems.at(i);
2159 else
2160 break;
2161 }
2162 return Q_UNLIKELY(before) ? QQuickItemPrivate::get(before)->itemNode() : nullptr;
2163}
2164
2165static QSGNode *fetchNextNode(QQuickItemPrivate *itemPriv, int &ii, bool &returnedPaintNode)
2166{
2167 QList<QQuickItem *> orderedChildren = itemPriv->paintOrderChildItems();
2168
2169 for (; ii < orderedChildren.size() && orderedChildren.at(ii)->z() < 0; ++ii) {
2170 QQuickItemPrivate *childPrivate = QQuickItemPrivate::get(orderedChildren.at(ii));
2171 if (!childPrivate->explicitVisible &&
2172 (!childPrivate->extra.isAllocated() || !childPrivate->extra->effectRefCount))
2173 continue;
2174
2175 ii++;
2176 return childPrivate->itemNode();
2177 }
2178
2179 if (itemPriv->paintNode && !returnedPaintNode) {
2180 returnedPaintNode = true;
2181 return itemPriv->paintNode;
2182 }
2183
2184 for (; ii < orderedChildren.size(); ++ii) {
2185 QQuickItemPrivate *childPrivate = QQuickItemPrivate::get(orderedChildren.at(ii));
2186 if (!childPrivate->explicitVisible &&
2187 (!childPrivate->extra.isAllocated() || !childPrivate->extra->effectRefCount))
2188 continue;
2189
2190 ii++;
2191 return childPrivate->itemNode();
2192 }
2193
2194 return nullptr;
2195}
2196
2197void QQuickWindowPrivate::updateDirtyNode(QQuickItem *item)
2198{
2199 QQuickItemPrivate *itemPriv = QQuickItemPrivate::get(item);
2200 quint32 dirty = itemPriv->dirtyAttributes;
2201 itemPriv->dirtyAttributes = 0;
2202
2203 if ((dirty & QQuickItemPrivate::TransformUpdateMask) ||
2204 (dirty & QQuickItemPrivate::Size && itemPriv->origin() != QQuickItem::TopLeft &&
2205 (itemPriv->scale() != 1. || itemPriv->rotation() != 0.))) {
2206
2207 QMatrix4x4 matrix;
2208
2209 if (itemPriv->x != 0. || itemPriv->y != 0.)
2210 matrix.translate(itemPriv->x, itemPriv->y);
2211
2212 for (int ii = itemPriv->transforms.size() - 1; ii >= 0; --ii)
2213 itemPriv->transforms.at(ii)->applyTo(&matrix);
2214
2215 if (itemPriv->scale() != 1. || itemPriv->rotation() != 0.) {
2216 QPointF origin = item->transformOriginPoint();
2217 matrix.translate(origin.x(), origin.y());
2218 if (itemPriv->scale() != 1.)
2219 matrix.scale(itemPriv->scale(), itemPriv->scale());
2220 if (itemPriv->rotation() != 0.)
2221 matrix.rotate(itemPriv->rotation(), 0, 0, 1);
2222 matrix.translate(-origin.x(), -origin.y());
2223 }
2224
2225 itemPriv->itemNode()->setMatrix(matrix);
2226 }
2227
2228 const bool clipEffectivelyChanged = dirty & (QQuickItemPrivate::Clip | QQuickItemPrivate::Window);
2229 if (clipEffectivelyChanged) {
2230 QSGNode *parent = itemPriv->opacityNode() ? (QSGNode *)itemPriv->opacityNode()
2231 : (QSGNode *)itemPriv->itemNode();
2232 QSGNode *child = itemPriv->rootNode();
2233
2234 if (bool initializeClipNode = item->clip() && itemPriv->clipNode() == nullptr;
2235 initializeClipNode) {
2236 QQuickDefaultClipNode *clip = new QQuickDefaultClipNode(item->clipRect());
2237 itemPriv->extra.value().clipNode = clip;
2238 clip->update();
2239
2240 if (!child) {
2241 parent->reparentChildNodesTo(clip);
2242 parent->appendChildNode(clip);
2243 } else {
2244 parent->removeChildNode(child);
2245 clip->appendChildNode(child);
2246 parent->appendChildNode(clip);
2247 }
2248
2249 } else if (bool updateClipNode = item->clip() && itemPriv->clipNode() != nullptr;
2250 updateClipNode) {
2251 QQuickDefaultClipNode *clip = itemPriv->clipNode();
2252 clip->setClipRect(item->clipRect());
2253 clip->update();
2254 } else if (bool removeClipNode = !item->clip() && itemPriv->clipNode() != nullptr;
2255 removeClipNode) {
2256 QQuickDefaultClipNode *clip = itemPriv->clipNode();
2257 parent->removeChildNode(clip);
2258 if (child) {
2259 clip->removeChildNode(child);
2260 parent->appendChildNode(child);
2261 } else {
2262 clip->reparentChildNodesTo(parent);
2263 }
2264
2265 delete itemPriv->clipNode();
2266 itemPriv->extra->clipNode = nullptr;
2267 }
2268 }
2269
2270 const int effectRefCount = itemPriv->extra.isAllocated() ? itemPriv->extra->effectRefCount : 0;
2271 const bool effectRefEffectivelyChanged =
2272 (dirty & (QQuickItemPrivate::EffectReference | QQuickItemPrivate::Window))
2273 && ((effectRefCount == 0) != (itemPriv->rootNode() == nullptr));
2274 if (effectRefEffectivelyChanged) {
2275 if (dirty & QQuickItemPrivate::ChildrenUpdateMask)
2276 itemPriv->childContainerNode()->removeAllChildNodes();
2277
2278 QSGNode *parent = itemPriv->clipNode();
2279 if (!parent)
2280 parent = itemPriv->opacityNode();
2281 if (!parent)
2282 parent = itemPriv->itemNode();
2283
2284 if (itemPriv->extra.isAllocated() && itemPriv->extra->effectRefCount) {
2285 Q_ASSERT(itemPriv->rootNode() == nullptr);
2286 QSGRootNode *root = new QSGRootNode();
2287 itemPriv->extra->rootNode = root;
2288 parent->reparentChildNodesTo(root);
2289 parent->appendChildNode(root);
2290 } else {
2291 Q_ASSERT(itemPriv->rootNode() != nullptr);
2292 QSGRootNode *root = itemPriv->rootNode();
2293 parent->removeChildNode(root);
2294 root->reparentChildNodesTo(parent);
2295 delete itemPriv->rootNode();
2296 itemPriv->extra->rootNode = nullptr;
2297 }
2298 }
2299
2300 if (dirty & QQuickItemPrivate::ChildrenUpdateMask) {
2301 int ii = 0;
2302 bool fetchedPaintNode = false;
2303 QList<QQuickItem *> orderedChildren = itemPriv->paintOrderChildItems();
2304 int desiredNodesSize = orderedChildren.size() + (itemPriv->paintNode ? 1 : 0);
2305
2306 // now start making current state match the promised land of
2307 // desiredNodes. in the case of our current state matching desiredNodes
2308 // (though why would we get ChildrenUpdateMask with no changes?) then we
2309 // should make no changes at all.
2310
2311 // how many nodes did we process, when examining changes
2312 int desiredNodesProcessed = 0;
2313
2314 // currentNode is how far, in our present tree, we have processed. we
2315 // make use of this later on to trim the current child list if the
2316 // desired list is shorter.
2317 QSGNode *groupNode = itemPriv->childContainerNode();
2318 QSGNode *currentNode = groupNode->firstChild();
2319 QSGNode *desiredNode = nullptr;
2320
2321 while (currentNode && (desiredNode = fetchNextNode(itemPriv, ii, fetchedPaintNode))) {
2322 if (currentNode != desiredNode) {
2323 // uh oh... reality and our utopic paradise are diverging!
2324 // we need to reconcile this...
2325 if (currentNode->nextSibling() == desiredNode) {
2326 // nice and simple: a node was removed, and the next in line is correct.
2327 groupNode->removeChildNode(currentNode);
2328 } else {
2329 // a node needs to be added..
2330 // remove it from any pre-existing parent, and push it before currentNode,
2331 // so it's in the correct place...
2332 if (desiredNode->parent()) {
2333 desiredNode->parent()->removeChildNode(desiredNode);
2334 }
2335 groupNode->insertChildNodeBefore(desiredNode, currentNode);
2336 }
2337
2338 // continue iteration at the correct point, now desiredNode is in place...
2339 currentNode = desiredNode;
2340 }
2341
2342 currentNode = currentNode->nextSibling();
2343 desiredNodesProcessed++;
2344 }
2345
2346 // if we didn't process as many nodes as in the new list, then we have
2347 // more nodes at the end of desiredNodes to append to our list.
2348 // this will be the case when adding new nodes, for instance.
2349 if (desiredNodesProcessed < desiredNodesSize) {
2350 while ((desiredNode = fetchNextNode(itemPriv, ii, fetchedPaintNode))) {
2351 if (desiredNode->parent())
2352 desiredNode->parent()->removeChildNode(desiredNode);
2353 groupNode->appendChildNode(desiredNode);
2354 }
2355 } else if (currentNode) {
2356 // on the other hand, if we processed less than our current node
2357 // tree, then nodes have been _removed_ from the scene, and we need
2358 // to take care of that here.
2359 while (currentNode) {
2360 QSGNode *node = currentNode->nextSibling();
2361 groupNode->removeChildNode(currentNode);
2362 currentNode = node;
2363 }
2364 }
2365 }
2366
2367 if ((dirty & QQuickItemPrivate::Size) && itemPriv->clipNode()) {
2368 itemPriv->clipNode()->setRect(item->clipRect());
2369 itemPriv->clipNode()->update();
2370 }
2371
2372 if (dirty & (QQuickItemPrivate::OpacityValue | QQuickItemPrivate::Visible
2373 | QQuickItemPrivate::HideReference | QQuickItemPrivate::Window))
2374 {
2375 qreal opacity = itemPriv->explicitVisible && (!itemPriv->extra.isAllocated() || itemPriv->extra->hideRefCount == 0)
2376 ? itemPriv->opacity() : qreal(0);
2377
2378 if (opacity != 1 && !itemPriv->opacityNode()) {
2379 QSGOpacityNode *node = new QSGOpacityNode;
2380 itemPriv->extra.value().opacityNode = node;
2381
2382 QSGNode *parent = itemPriv->itemNode();
2383 QSGNode *child = itemPriv->clipNode();
2384 if (!child)
2385 child = itemPriv->rootNode();
2386
2387 if (child) {
2388 parent->removeChildNode(child);
2389 node->appendChildNode(child);
2390 parent->appendChildNode(node);
2391 } else {
2392 parent->reparentChildNodesTo(node);
2393 parent->appendChildNode(node);
2394 }
2395 }
2396 if (itemPriv->opacityNode())
2397 itemPriv->opacityNode()->setOpacity(opacity);
2398 }
2399
2400 if (dirty & QQuickItemPrivate::ContentUpdateMask) {
2401
2402 if (itemPriv->flags & QQuickItem::ItemHasContents) {
2403 updatePaintNodeData.transformNode = itemPriv->itemNode();
2404 itemPriv->paintNode = item->updatePaintNode(itemPriv->paintNode, &updatePaintNodeData);
2405
2406 Q_ASSERT(itemPriv->paintNode == nullptr ||
2407 itemPriv->paintNode->parent() == nullptr ||
2408 itemPriv->paintNode->parent() == itemPriv->childContainerNode());
2409
2410 if (itemPriv->paintNode && itemPriv->paintNode->parent() == nullptr) {
2411 QSGNode *before = qquickitem_before_paintNode(itemPriv);
2412 if (before && before->parent()) {
2413 Q_ASSERT(before->parent() == itemPriv->childContainerNode());
2414 itemPriv->childContainerNode()->insertChildNodeAfter(itemPriv->paintNode, before);
2415 } else {
2416 itemPriv->childContainerNode()->prependChildNode(itemPriv->paintNode);
2417 }
2418 }
2419 } else if (itemPriv->paintNode) {
2420 delete itemPriv->paintNode;
2421 itemPriv->paintNode = nullptr;
2422 }
2423 }
2424
2425#ifndef QT_NO_DEBUG
2426 // Check consistency.
2427
2428 QList<QSGNode *> nodes;
2429 nodes << itemPriv->itemNodeInstance
2430 << itemPriv->opacityNode()
2431 << itemPriv->clipNode()
2432 << itemPriv->rootNode()
2433 << itemPriv->paintNode;
2434 nodes.removeAll(nullptr);
2435
2436 Q_ASSERT(nodes.constFirst() == itemPriv->itemNodeInstance);
2437 for (int i=1; i<nodes.size(); ++i) {
2438 QSGNode *n = nodes.at(i);
2439 // Failing this means we messed up reparenting
2440 Q_ASSERT(n->parent() == nodes.at(i-1));
2441 // Only the paintNode and the one who is childContainer may have more than one child.
2442 Q_ASSERT(n == itemPriv->paintNode || n == itemPriv->childContainerNode() || n->childCount() == 1);
2443 }
2444#endif
2445
2446}
2447
2448bool QQuickWindowPrivate::emitError(QQuickWindow::SceneGraphError error, const QString &msg)
2449{
2450 Q_Q(QQuickWindow);
2451 static const QMetaMethod errorSignal = QMetaMethod::fromSignal(&QQuickWindow::sceneGraphError);
2452 if (q->isSignalConnected(errorSignal)) {
2453 emit q->sceneGraphError(error, msg);
2454 return true;
2455 }
2456 return false;
2457}
2458
2459void QQuickWindow::maybeUpdate()
2460{
2461 Q_D(QQuickWindow);
2462 if (d->renderControl)
2463 QQuickRenderControlPrivate::get(d->renderControl)->maybeUpdate();
2464 else if (d->windowManager)
2465 d->windowManager->maybeUpdate(this);
2466}
2467
2468void QQuickWindow::cleanupSceneGraph()
2469{
2470 Q_D(QQuickWindow);
2471 if (!d->renderer)
2472 return;
2473
2474 delete d->renderer->rootNode();
2475 delete d->renderer;
2476 d->renderer = nullptr;
2477
2478 d->runAndClearJobs(&d->beforeSynchronizingJobs);
2479 d->runAndClearJobs(&d->afterSynchronizingJobs);
2480 d->runAndClearJobs(&d->beforeRenderingJobs);
2481 d->runAndClearJobs(&d->afterRenderingJobs);
2482 d->runAndClearJobs(&d->afterSwapJobs);
2483}
2484
2485QOpenGLContext *QQuickWindowPrivate::openglContext()
2486{
2487#if QT_CONFIG(opengl)
2488 if (context && context->isValid()) {
2489 QSGRendererInterface *rif = context->sceneGraphContext()->rendererInterface(context);
2490 if (rif) {
2491 Q_Q(QQuickWindow);
2492 return reinterpret_cast<QOpenGLContext *>(rif->getResource(q, QSGRendererInterface::OpenGLContextResource));
2493 }
2494 }
2495#endif
2496 return nullptr;
2497}
2498
2499/*!
2500 Returns true if the scene graph has been initialized; otherwise returns false.
2501 */
2502bool QQuickWindow::isSceneGraphInitialized() const
2503{
2504 Q_D(const QQuickWindow);
2505 return d->context != nullptr && d->context->isValid();
2506}
2507
2508/*!
2509 \fn void QQuickWindow::frameSwapped()
2510
2511 This signal is emitted when a frame has been queued for presenting. With
2512 vertical synchronization enabled the signal is emitted at most once per
2513 vsync interval in a continuously animating scene.
2514
2515 This signal will be emitted from the scene graph rendering thread.
2516*/
2517
2518/*!
2519 \qmlsignal QtQuick::Window::frameSwapped()
2520
2521 This signal is emitted when a frame has been queued for presenting. With
2522 vertical synchronization enabled the signal is emitted at most once per
2523 vsync interval in a continuously animating scene.
2524 */
2525
2526/*!
2527 \fn void QQuickWindow::sceneGraphInitialized()
2528
2529 This signal is emitted when the scene graph has been initialized.
2530
2531 This signal will be emitted from the scene graph rendering thread.
2532 */
2533
2534/*!
2535 \qmlsignal QtQuick::Window::sceneGraphInitialized()
2536 \internal
2537 */
2538
2539/*!
2540 \fn void QQuickWindow::sceneGraphInvalidated()
2541
2542 This signal is emitted when the scene graph has been invalidated.
2543
2544 This signal implies that the graphics rendering context used
2545 has been invalidated and all user resources tied to that context
2546 should be released.
2547
2548 When rendering with OpenGL, the QOpenGLContext of this window will
2549 be bound when this function is called. The only exception is if
2550 the native OpenGL has been destroyed outside Qt's control, for
2551 instance through EGL_CONTEXT_LOST.
2552
2553 This signal will be emitted from the scene graph rendering thread.
2554 */
2555
2556/*!
2557 \qmlsignal QtQuick::Window::sceneGraphInvalidated()
2558 \internal
2559 */
2560
2561/*!
2562 \fn void QQuickWindow::sceneGraphError(SceneGraphError error, const QString &message)
2563
2564 This signal is emitted when an \a error occurred during scene graph initialization.
2565
2566 Applications should connect to this signal if they wish to handle errors,
2567 like graphics context creation failures, in a custom way. When no slot is
2568 connected to the signal, the behavior will be different: Quick will print
2569 the \a message, or show a message box, and terminate the application.
2570
2571 This signal will be emitted from the GUI thread.
2572
2573 \since 5.3
2574 */
2575
2576/*!
2577 \qmlsignal QtQuick::Window::sceneGraphError(SceneGraphError error, QString message)
2578
2579 This signal is emitted when an \a error occurred during scene graph initialization.
2580
2581 You can implement onSceneGraphError(error, message) to handle errors,
2582 such as graphics context creation failures, in a custom way.
2583 If no handler is connected to this signal, Quick will print the \a message,
2584 or show a message box, and terminate the application.
2585
2586 \since 5.3
2587 */
2588
2589/*!
2590 \class QQuickCloseEvent
2591 \internal
2592 \since 5.1
2593
2594 \inmodule QtQuick
2595
2596 \brief Notification that a \l QQuickWindow is about to be closed
2597*/
2598/*!
2599 \qmltype CloseEvent
2600 \nativetype QQuickCloseEvent
2601 \inqmlmodule QtQuick
2602 \ingroup qtquick-visual
2603 \brief Notification that a \l Window is about to be closed.
2604 \since 5.1
2605
2606 Notification that a window is about to be closed by the windowing system
2607 (e.g. the user clicked the title bar close button). The CloseEvent contains
2608 an accepted property which can be set to false to abort closing the window.
2609*/
2610
2611/*!
2612 \qmlproperty bool CloseEvent::accepted
2613
2614 This property indicates whether the application will allow the user to
2615 close the window. It is true by default.
2616*/
2617
2618/*!
2619 \internal
2620 \fn void QQuickWindow::closing(QQuickCloseEvent *close)
2621 \since 5.1
2622
2623 This signal is emitted when the window receives the event \a close from
2624 the windowing system.
2625
2626 On \macOs, Qt will create a menu item \c Quit if there is no menu item
2627 whose text is "quit" or "exit". This menu item calls the \c QCoreApplication::quit
2628 signal, not the \c QQuickWindow::closing() signal.
2629
2630 \sa {QMenuBar as a Global Menu Bar}
2631*/
2632
2633/*!
2634 \qmlsignal QtQuick::Window::closing(CloseEvent close)
2635 \since 5.1
2636
2637 This signal is emitted when the user tries to close the window.
2638
2639 This signal includes a \a close parameter. The \c {close.accepted}
2640 property is true by default so that the window is allowed to close; but you
2641 can implement an \c onClosing handler and set \c {close.accepted = false} if
2642 you need to do something else before the window can be closed.
2643 */
2644
2645/*!
2646 Sets the render target for this window to be \a target.
2647
2648 A QQuickRenderTarget serves as an opaque handle for a renderable native
2649 object, most commonly a 2D texture, and associated metadata, such as the
2650 size in pixels.
2651
2652 A default constructed QQuickRenderTarget means no redirection. A valid
2653 \a target, created via one of the static QQuickRenderTarget factory functions,
2654 on the other hand, enables redirection of the rendering of the Qt Quick
2655 scene: it will no longer target the color buffers for the surface
2656 associated with the window, but rather the textures or other graphics
2657 objects specified in \a target.
2658
2659 For example, assuming the scenegraph is using Vulkan to render, one can
2660 redirect its output into a \c VkImage. For graphics APIs like Vulkan, the
2661 image layout must be provided as well. QQuickRenderTarget instances are
2662 implicitly shared and are copyable and can be passed by value. They do not
2663 own the associated native objects (such as, the VkImage in the example),
2664 however.
2665
2666 \badcode
2667 QQuickRenderTarget rt = QQuickRenderTarget::fromVulkanImage(vulkanImage, VK_IMAGE_LAYOUT_PREINITIALIZED, pixelSize);
2668 quickWindow->setRenderTarget(rt);
2669 \endcode
2670
2671 This function is very often used in combination with QQuickRenderControl
2672 and an invisible QQuickWindow, in order to render Qt Quick content into a
2673 texture, without creating an on-screen native window for this QQuickWindow.
2674
2675 When the desired target, or associated data, such as the size, changes,
2676 call this function with a new QQuickRenderTarget. Constructing
2677 QQuickRenderTarget instances and calling this function is cheap, but be
2678 aware that setting a new \a target with a different native object or other
2679 data may lead to potentially expensive initialization steps when the
2680 scenegraph is about to render the next frame. Therefore change the target
2681 only when necessary.
2682
2683 \note The window does not take ownership of any native objects referenced
2684 in \a target.
2685
2686 \note It is the caller's responsibility to ensure the native objects
2687 referred to in \a target are valid for the scenegraph renderer too. For
2688 instance, with Vulkan, Metal, and Direct3D this implies that the texture or
2689 image is created on the same graphics device that is used by the scenegraph
2690 internally. Therefore, when texture objects created on an already existing
2691 device or context are involved, this function is often used in combination
2692 with setGraphicsDevice().
2693
2694 \note With graphics APIs where relevant, the application must pay attention
2695 to image layout transitions performed by the scenegraph. For example, once
2696 a VkImage is associated with the scenegraph by calling this function, its
2697 layout will transition to \c VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL when
2698 rendering a frame.
2699
2700 \warning This function can only be called from the thread doing the
2701 rendering.
2702
2703 \since 6.0
2704
2705 \sa QQuickRenderControl, setGraphicsDevice(), setGraphicsApi()
2706 */
2707void QQuickWindow::setRenderTarget(const QQuickRenderTarget &target)
2708{
2709 Q_D(QQuickWindow);
2710 if (target != d->customRenderTarget) {
2711 d->customRenderTarget = target;
2712 d->redirect.renderTargetDirty = true;
2713 }
2714}
2715
2716/*!
2717 \return the QQuickRenderTarget passed to setRenderTarget(), or a default
2718 constructed one otherwise
2719
2720 \since 6.0
2721
2722 \sa setRenderTarget()
2723 */
2724QQuickRenderTarget QQuickWindow::renderTarget() const
2725{
2726 Q_D(const QQuickWindow);
2727 return d->customRenderTarget;
2728}
2729
2730#ifdef Q_OS_WEBOS
2731class GrabWindowForProtectedContent : public QRunnable
2732{
2733public:
2734 GrabWindowForProtectedContent(QQuickWindow *window, QImage *image, QWaitCondition *condition)
2735 : m_window(window)
2736 , m_image(image)
2737 , m_condition(condition)
2738 {
2739 }
2740
2741 bool checkGrabbable()
2742 {
2743 if (!m_window)
2744 return false;
2745 if (!m_image)
2746 return false;
2747 if (!QQuickWindowPrivate::get(m_window))
2748 return false;
2749
2750 return true;
2751 }
2752
2753 void run() override
2754 {
2755 if (!checkGrabbable())
2756 return;
2757
2758 *m_image = QSGRhiSupport::instance()->grabOffscreenForProtectedContent(m_window);
2759 if (m_condition)
2760 m_condition->wakeOne();
2761 return;
2762 }
2763
2764private:
2765 QQuickWindow *m_window;
2766 QImage *m_image;
2767 QWaitCondition *m_condition;
2768
2769};
2770#endif
2771
2772/*!
2773 Grabs the contents of the window and returns it as an image.
2774
2775 It is possible to call the grabWindow() function when the window is not
2776 visible. This requires that the window is \l{QWindow::create()} {created}
2777 and has a valid size and that no other QQuickWindow instances are rendering
2778 in the same process.
2779
2780 \note When using this window in combination with QQuickRenderControl, the
2781 result of this function is an empty image, unless the \c software backend
2782 is in use. This is because when redirecting the output to an
2783 application-managed graphics resource (such as, a texture) by using
2784 QQuickRenderControl and setRenderTarget(), the application is better suited
2785 for managing and executing an eventual read back operation, since it is in
2786 full control of the resource to begin with.
2787
2788 \warning Calling this function will cause performance problems.
2789
2790 \warning This function can only be called from the GUI thread.
2791 */
2792QImage QQuickWindow::grabWindow()
2793{
2794 Q_D(QQuickWindow);
2795
2796 if (!d->isRenderable() && !d->renderControl) {
2797 // backends like software can grab regardless of the window state
2798 if (d->windowManager && (d->windowManager->flags() & QSGRenderLoop::SupportsGrabWithoutExpose))
2799 return d->windowManager->grab(this);
2800
2801 if (!isSceneGraphInitialized()) {
2802 // We do not have rendering up and running. Forget the render loop,
2803 // do a frame completely offscreen and synchronously into a
2804 // texture. This can be *very* slow due to all the device/context
2805 // and resource initialization but the documentation warns for it,
2806 // and is still important for some use cases.
2807 Q_ASSERT(!d->rhi);
2808 return QSGRhiSupport::instance()->grabOffscreen(this);
2809 }
2810 }
2811
2812#ifdef Q_OS_WEBOS
2813 if (requestedFormat().testOption(QSurfaceFormat::ProtectedContent)) {
2814 QImage image;
2815 QMutex mutex;
2816 QWaitCondition condition;
2817 mutex.lock();
2818 GrabWindowForProtectedContent *job = new GrabWindowForProtectedContent(this, &image, &condition);
2819 if (!job) {
2820 qWarning("QQuickWindow::grabWindow: Failed to create a job for capturing protected content");
2821 mutex.unlock();
2822 return QImage();
2823 }
2824 scheduleRenderJob(job, QQuickWindow::NoStage);
2825 condition.wait(&mutex);
2826 mutex.unlock();
2827 return image;
2828 }
2829#endif
2830 // The common case: we have an exposed window with an initialized
2831 // scenegraph, meaning we can request grabbing via the render loop, or we
2832 // are not targeting the window, in which case the request is to be
2833 // forwarded to the rendercontrol.
2834 if (d->renderControl)
2835 return QQuickRenderControlPrivate::get(d->renderControl)->grab();
2836 else if (d->windowManager)
2837 return d->windowManager->grab(this);
2838
2839 return QImage();
2840}
2841
2842/*!
2843 Returns an incubation controller that splices incubation between frames
2844 for this window. QQuickView automatically installs this controller for you,
2845 otherwise you will need to install it yourself using \l{QQmlEngine::setIncubationController()}.
2846
2847 The controller is owned by the window and will be destroyed when the window
2848 is deleted.
2849*/
2850QQmlIncubationController *QQuickWindow::incubationController() const
2851{
2852 Q_D(const QQuickWindow);
2853
2854 if (!d->windowManager)
2855 return nullptr; // TODO: make sure that this is safe
2856
2857 if (!d->incubationController)
2858 d->incubationController = new QQuickWindowIncubationController(d->windowManager);
2859 return d->incubationController;
2860}
2861
2862
2863
2864/*!
2865 \enum QQuickWindow::CreateTextureOption
2866
2867 The CreateTextureOption enums are used to customize a texture is wrapped.
2868
2869 \value TextureHasAlphaChannel The texture has an alpha channel and should
2870 be drawn using blending.
2871
2872 \value TextureHasMipmaps The texture has mipmaps and can be drawn with
2873 mipmapping enabled.
2874
2875 \value TextureOwnsGLTexture As of Qt 6.0, this flag is not used in practice
2876 and is ignored. Native graphics resource ownership is not transferable to
2877 the wrapping QSGTexture, because Qt Quick may not have the necessary details
2878 on how such an object and the associated memory should be freed.
2879
2880 \value TextureCanUseAtlas The image can be uploaded into a texture atlas.
2881
2882 \value TextureIsOpaque The texture will return false for
2883 QSGTexture::hasAlphaChannel() and will not be blended. This flag was added
2884 in Qt 5.6.
2885
2886 */
2887
2888/*!
2889 \enum QQuickWindow::SceneGraphError
2890
2891 This enum describes the error in a sceneGraphError() signal.
2892
2893 \value ContextNotAvailable graphics context creation failed. This typically means that
2894 no suitable OpenGL implementation was found, for example because no graphics drivers
2895 are installed and so no OpenGL 2 support is present. On mobile and embedded boards
2896 that use OpenGL ES such an error is likely to indicate issues in the windowing system
2897 integration and possibly an incorrect configuration of Qt.
2898
2899 \since 5.3
2900 */
2901
2902/*!
2903 \enum QQuickWindow::TextRenderType
2904 \since 5.10
2905
2906 This enum describes the default render type of text-like elements in Qt
2907 Quick (\l Text, \l TextInput, etc.).
2908
2909 Select NativeTextRendering if you prefer text to look native on the target
2910 platform and do not require advanced features such as transformation of the
2911 text. Using such features in combination with the NativeTextRendering
2912 render type will lend poor and sometimes pixelated results.
2913
2914 Both \c QtTextRendering and \c CurveTextRendering are hardware-accelerated techniques.
2915 \c QtTextRendering is the faster of the two, but uses more memory and will exhibit rendering
2916 artifacts at large sizes. \c CurveTextRendering should be considered as an alternative in cases
2917 where \c QtTextRendering does not give good visual results or where reducing graphics memory
2918 consumption is a priority.
2919
2920 \value QtTextRendering Use Qt's own rasterization algorithm.
2921 \value NativeTextRendering Use the operating system's native rasterizer for text.
2922 \value CurveTextRendering Text is rendered using a curve rasterizer running directly on
2923 the graphics hardware. (Introduced in Qt 6.7.0.)
2924*/
2925
2926/*!
2927 \fn void QQuickWindow::beforeSynchronizing()
2928
2929 This signal is emitted before the scene graph is synchronized with the QML state.
2930
2931 Even though the signal is emitted from the scene graph rendering thread,
2932 the GUI thread is guaranteed to be blocked, like it is in
2933 QQuickItem::updatePaintNode(). Therefore, it is safe to access GUI thread
2934 thread data in a slot or lambda that is connected with
2935 Qt::DirectConnection.
2936
2937 This signal can be used to do any preparation required before calls to
2938 QQuickItem::updatePaintNode().
2939
2940 When using OpenGL, the QOpenGLContext used for rendering by the scene graph
2941 will be bound at this point.
2942
2943 \warning This signal is emitted from the scene graph rendering thread. If your
2944 slot function needs to finish before execution continues, you must make sure that
2945 the connection is direct (see Qt::ConnectionType).
2946
2947 \warning When using OpenGL, be aware that setting OpenGL 3.x or 4.x specific
2948 states and leaving these enabled or set to non-default values when returning
2949 from the connected slot can interfere with the scene graph's rendering.
2950*/
2951
2952/*!
2953 \qmlsignal QtQuick::Window::beforeSynchronizing()
2954 \internal
2955*/
2956
2957/*!
2958 \fn void QQuickWindow::afterSynchronizing()
2959
2960 This signal is emitted after the scene graph is synchronized with the QML state.
2961
2962 This signal can be used to do preparation required after calls to
2963 QQuickItem::updatePaintNode(), while the GUI thread is still locked.
2964
2965 When using OpenGL, the QOpenGLContext used for rendering by the scene graph
2966 will be bound at this point.
2967
2968 \warning This signal is emitted from the scene graph rendering thread. If your
2969 slot function needs to finish before execution continues, you must make sure that
2970 the connection is direct (see Qt::ConnectionType).
2971
2972 \warning When using OpenGL, be aware that setting OpenGL 3.x or 4.x specific
2973 states and leaving these enabled or set to non-default values when returning
2974 from the connected slot can interfere with the scene graph's rendering.
2975
2976 \since 5.3
2977 */
2978
2979/*!
2980 \qmlsignal QtQuick::Window::afterSynchronizing()
2981 \internal
2982 \since 5.3
2983 */
2984
2985/*!
2986 \fn void QQuickWindow::beforeRendering()
2987
2988 This signal is emitted after the preparations for the frame have been done,
2989 meaning there is a command buffer in recording mode, where applicable. If
2990 desired, the slot function connected to this signal can query native
2991 resources like the command before via QSGRendererInterface. Note however
2992 that the recording of the main render pass is not yet started at this point
2993 and it is not possible to add commands within that pass. Starting a pass
2994 means clearing the color, depth, and stencil buffers so it is not possible
2995 to achieve an underlay type of rendering by just connecting to this
2996 signal. Rather, connect to beforeRenderPassRecording(). However, connecting
2997 to this signal is still important if the recording of copy type of commands
2998 is desired since those cannot be enqueued within a render pass.
2999
3000 \warning This signal is emitted from the scene graph rendering thread. If your
3001 slot function needs to finish before execution continues, you must make sure that
3002 the connection is direct (see Qt::ConnectionType).
3003
3004 \note When using OpenGL, be aware that setting OpenGL 3.x or 4.x specific
3005 states and leaving these enabled or set to non-default values when
3006 returning from the connected slot can interfere with the scene graph's
3007 rendering. The QOpenGLContext used for rendering by the scene graph will be
3008 bound when the signal is emitted.
3009
3010 \sa rendererInterface(), {Scene Graph - RHI Under QML}, {Scene Graph -
3011 OpenGL Under QML}, {Scene Graph - Metal Under QML}, {Scene Graph - Vulkan
3012 Under QML}, {Scene Graph - Direct3D 11 Under QML}
3013*/
3014
3015/*!
3016 \qmlsignal QtQuick::Window::beforeRendering()
3017 \internal
3018*/
3019
3020/*!
3021 \fn void QQuickWindow::afterRendering()
3022
3023 The signal is emitted after scene graph has added its commands to the
3024 command buffer, which is not yet submitted to the graphics queue. If
3025 desired, the slot function connected to this signal can query native
3026 resources, like the command buffer, before via QSGRendererInterface. Note
3027 however that the render pass (or passes) are already recorded at this point
3028 and it is not possible to add more commands within the scenegraph's
3029 pass. Instead, use afterRenderPassRecording() for that. This signal has
3030 therefore limited use in Qt 6, unlike in Qt 5. Rather, it is the combination
3031 of beforeRendering() and beforeRenderPassRecording(), or beforeRendering()
3032 and afterRenderPassRecording(), that is typically used to achieve under- or
3033 overlaying of the custom rendering.
3034
3035 \warning This signal is emitted from the scene graph rendering thread. If your
3036 slot function needs to finish before execution continues, you must make sure that
3037 the connection is direct (see Qt::ConnectionType).
3038
3039 \note When using OpenGL, be aware that setting OpenGL 3.x or 4.x specific
3040 states and leaving these enabled or set to non-default values when
3041 returning from the connected slot can interfere with the scene graph's
3042 rendering. The QOpenGLContext used for rendering by the scene graph will be
3043 bound when the signal is emitted.
3044
3045 \sa rendererInterface(), {Scene Graph - RHI Under QML}, {Scene Graph -
3046 OpenGL Under QML}, {Scene Graph - Metal Under QML}, {Scene Graph - Vulkan
3047 Under QML}, {Scene Graph - Direct3D 11 Under QML}
3048 */
3049
3050/*!
3051 \qmlsignal QtQuick::Window::afterRendering()
3052 \internal
3053 */
3054
3055/*!
3056 \fn void QQuickWindow::beforeRenderPassRecording()
3057
3058 This signal is emitted before the scenegraph starts recording commands for
3059 the main render pass. (Layers have their own passes and are fully recorded
3060 by the time this signal is emitted.) The render pass is already active on
3061 the command buffer when the signal is emitted.
3062
3063 This signal is emitted later than beforeRendering() and it guarantees that
3064 not just the frame, but also the recording of the scenegraph's main render
3065 pass is active. This allows inserting commands without having to generate an
3066 entire, separate render pass (which would typically clear the attached
3067 images). The native graphics objects can be queried via
3068 QSGRendererInterface.
3069
3070 \note Resource updates (uploads, copies) typically cannot be enqueued from
3071 within a render pass. Therefore, more complex user rendering will need to
3072 connect to both beforeRendering() and this signal.
3073
3074 \warning This signal is emitted from the scene graph rendering thread. If your
3075 slot function needs to finish before execution continues, you must make sure that
3076 the connection is direct (see Qt::ConnectionType).
3077
3078 \sa rendererInterface()
3079
3080 \since 5.14
3081
3082 \sa {Scene Graph - RHI Under QML}
3083*/
3084
3085/*!
3086 \qmlsignal QtQuick::Window::beforeRenderPassRecording()
3087 \internal
3088 \since 5.14
3089*/
3090
3091/*!
3092 \fn void QQuickWindow::afterRenderPassRecording()
3093
3094 This signal is emitted after the scenegraph has recorded the commands for
3095 its main render pass, but the pass is not yet finalized on the command
3096 buffer.
3097
3098 This signal is emitted earlier than afterRendering(), and it guarantees that
3099 not just the frame but also the recording of the scenegraph's main render
3100 pass is still active. This allows inserting commands without having to
3101 generate an entire, separate render pass (which would typically clear the
3102 attached images). The native graphics objects can be queried via
3103 QSGRendererInterface.
3104
3105 \note Resource updates (uploads, copies) typically cannot be enqueued from
3106 within a render pass. Therefore, more complex user rendering will need to
3107 connect to both beforeRendering() and this signal.
3108
3109 \warning This signal is emitted from the scene graph rendering thread. If your
3110 slot function needs to finish before execution continues, you must make sure that
3111 the connection is direct (see Qt::ConnectionType).
3112
3113 \sa rendererInterface()
3114
3115 \since 5.14
3116
3117 \sa {Scene Graph - RHI Under QML}
3118*/
3119
3120/*!
3121 \fn void QQuickWindow::beforeFrameBegin()
3122
3123 This signal is emitted before the scene graph starts preparing the frame.
3124 This precedes signals like beforeSynchronizing() or beforeRendering(). It is
3125 the earliest signal that is emitted by the scene graph rendering thread
3126 when starting to prepare a new frame.
3127
3128 This signal is relevant for lower level graphics frameworks that need to
3129 execute certain operations, such as resource cleanup, at a stage where Qt
3130 Quick has not initiated the recording of a new frame via the underlying
3131 rendering hardware interface APIs.
3132
3133 \warning This signal is emitted from the scene graph rendering thread. If your
3134 slot function needs to finish before execution continues, you must make sure that
3135 the connection is direct (see Qt::ConnectionType).
3136
3137 \since 6.0
3138
3139 \sa afterFrameEnd(), rendererInterface()
3140*/
3141
3142/*!
3143 \qmlsignal QtQuick::Window::beforeFrameBegin()
3144 \internal
3145*/
3146
3147/*!
3148 \fn void QQuickWindow::afterFrameEnd()
3149
3150 This signal is emitted when the scene graph has submitted a frame. This is
3151 emitted after all other related signals, such as afterRendering(). It is
3152 the last signal that is emitted by the scene graph rendering thread when
3153 rendering a frame.
3154
3155 \note Unlike frameSwapped(), this signal is guaranteed to be emitted also
3156 when the Qt Quick output is redirected via QQuickRenderControl.
3157
3158 \warning This signal is emitted from the scene graph rendering thread. If your
3159 slot function needs to finish before execution continues, you must make sure that
3160 the connection is direct (see Qt::ConnectionType).
3161
3162 \since 6.0
3163
3164 \sa beforeFrameBegin(), rendererInterface()
3165*/
3166
3167/*!
3168 \qmlsignal QtQuick::Window::afterFrameEnd()
3169 \internal
3170*/
3171
3172/*!
3173 \qmlsignal QtQuick::Window::afterRenderPassRecording()
3174 \internal
3175 \since 5.14
3176*/
3177
3178/*!
3179 \fn void QQuickWindow::afterAnimating()
3180
3181 This signal is emitted on the GUI thread before requesting the render thread to
3182 perform the synchronization of the scene graph.
3183
3184 Unlike the other similar signals, this one is emitted on the GUI thread
3185 instead of the render thread. It can be used to synchronize external
3186 animation systems with the QML content. At the same time this means that
3187 this signal is not suitable for triggering graphics operations.
3188
3189 \since 5.3
3190 */
3191
3192/*!
3193 \qmlsignal QtQuick::Window::afterAnimating()
3194
3195 This signal is emitted on the GUI thread before requesting the render thread to
3196 perform the synchronization of the scene graph.
3197
3198 You can implement onAfterAnimating to do additional processing after each animation step.
3199
3200 \since 5.3
3201 */
3202
3203/*!
3204 \fn void QQuickWindow::sceneGraphAboutToStop()
3205
3206 This signal is emitted on the render thread when the scene graph is
3207 about to stop rendering. This happens usually because the window
3208 has been hidden.
3209
3210 Applications may use this signal to release resources, but should be
3211 prepared to reinstantiated them again fast. The scene graph and the
3212 graphics context are not released at this time.
3213
3214 \warning This signal is emitted from the scene graph rendering thread. If your
3215 slot function needs to finish before execution continues, you must make sure that
3216 the connection is direct (see Qt::ConnectionType).
3217
3218 \warning Make very sure that a signal handler for sceneGraphAboutToStop() leaves the
3219 graphics context in the same state as it was when the signal handler was entered.
3220 Failing to do so can result in the scene not rendering properly.
3221
3222 \sa sceneGraphInvalidated()
3223 \since 5.3
3224 */
3225
3226/*!
3227 \qmlsignal QtQuick::Window::sceneGraphAboutToStop()
3228 \internal
3229 \since 5.3
3230 */
3231
3232/*!
3233 \overload
3234 */
3235
3236QSGTexture *QQuickWindow::createTextureFromImage(const QImage &image) const
3237{
3238 return createTextureFromImage(image, {});
3239}
3240
3241
3242/*!
3243 Creates a new QSGTexture from the supplied \a image. If the image has an
3244 alpha channel, the corresponding texture will have an alpha channel.
3245
3246 The caller of the function is responsible for deleting the returned texture.
3247 The underlying native texture object is then destroyed together with the
3248 QSGTexture.
3249
3250 When \a options contains TextureCanUseAtlas, the engine may put the image
3251 into a texture atlas. Textures in an atlas need to rely on
3252 QSGTexture::normalizedTextureSubRect() for their geometry and will not
3253 support QSGTexture::Repeat. Other values from CreateTextureOption are
3254 ignored.
3255
3256 When \a options contains TextureIsOpaque, the engine will create an RGB
3257 texture which returns false for QSGTexture::hasAlphaChannel(). Opaque
3258 textures will in most cases be faster to render. When this flag is not set,
3259 the texture will have an alpha channel based on the image's format.
3260
3261 When \a options contains TextureHasMipmaps, the engine will create a texture
3262 which can use mipmap filtering. Mipmapped textures can not be in an atlas.
3263
3264 Setting TextureHasAlphaChannel in \a options serves no purpose for this
3265 function since assuming an alpha channel and blending is the default. To opt
3266 out, set TextureIsOpaque.
3267
3268 When the scene graph uses OpenGL, the returned texture will be using \c
3269 GL_TEXTURE_2D as texture target and \c GL_RGBA as internal format. With
3270 other graphics APIs, the texture format is typically \c RGBA8. Reimplement
3271 QSGTexture to create textures with different parameters.
3272
3273 \warning This function will return 0 if the scene graph has not yet been
3274 initialized.
3275
3276 \warning The returned texture is not memory managed by the scene graph and
3277 must be explicitly deleted by the caller on the rendering thread. This is
3278 achieved by deleting the texture from a QSGNode destructor or by using
3279 deleteLater() in the case where the texture already has affinity to the
3280 rendering thread.
3281
3282 This function can be called from both the main and the render thread.
3283
3284 \sa sceneGraphInitialized(), QSGTexture
3285 */
3286
3287QSGTexture *QQuickWindow::createTextureFromImage(const QImage &image, CreateTextureOptions options) const
3288{
3289 Q_D(const QQuickWindow);
3290 if (!isSceneGraphInitialized()) // check both for d->context and d->context->isValid()
3291 return nullptr;
3292 uint flags = 0;
3293 if (options & TextureCanUseAtlas) flags |= QSGRenderContext::CreateTexture_Atlas;
3294 if (options & TextureHasMipmaps) flags |= QSGRenderContext::CreateTexture_Mipmap;
3295 if (!(options & TextureIsOpaque)) flags |= QSGRenderContext::CreateTexture_Alpha;
3296 return d->context->createTexture(image, flags);
3297}
3298
3299/*!
3300 Creates a new QSGTexture from the supplied \a texture.
3301
3302 Use \a options to customize the texture attributes. Only the
3303 TextureHasAlphaChannel flag is taken into account by this function. When
3304 set, the resulting QSGTexture is always treated by the scene graph renderer
3305 as needing blending. For textures that are fully opaque, not setting the
3306 flag can save the cost of performing alpha blending during rendering. The
3307 flag has no direct correspondence to the \l{QRhiTexture::format()}{format}
3308 of the QRhiTexture, i.e. not setting the flag while having a texture format
3309 such as the commonly used \l QRhiTexture::RGBA8 is perfectly normal.
3310
3311 Mipmapping is not controlled by \a options since \a texture is already
3312 created and has the presence or lack of mipmaps baked in.
3313
3314 The returned QSGTexture owns the QRhiTexture, meaning \a texture is
3315 destroyed together with the returned QSGTexture.
3316
3317 If \a texture owns its underlying native graphics resources (OpenGL texture
3318 object, Vulkan image, etc.), that depends on how the QRhiTexture was created
3319 (\l{QRhiTexture::create()} or \l{QRhiTexture::createFrom()}), and that is
3320 not controlled or changed by this function.
3321
3322 \note This is only functional when the scene graph has already initialized
3323 and is using the default, \l{QRhi}-based \l{Scene Graph
3324 Adaptations}{adaptation}. The return value is \nullptr otherwise.
3325
3326 \note This function can only be called on the scene graph render thread.
3327
3328 \since 6.6
3329
3330 \sa createTextureFromImage(), sceneGraphInitialized(), QSGTexture
3331 */
3332QSGTexture *QQuickWindow::createTextureFromRhiTexture(QRhiTexture *texture, CreateTextureOptions options) const
3333{
3334 Q_D(const QQuickWindow);
3335 if (!d->rhi)
3336 return nullptr;
3337
3338 QSGPlainTexture *t = new QSGPlainTexture;
3339 t->setOwnsTexture(true);
3340 t->setTexture(texture);
3341 t->setHasAlphaChannel(options & QQuickWindow::TextureHasAlphaChannel);
3342 t->setTextureSize(texture->pixelSize());
3343 return t;
3344}
3345
3346// Legacy, private alternative to createTextureFromRhiTexture() that internally
3347// creates a QRhiTexture wrapping the existing native graphics resource.
3348// New code should prefer using the public API.
3349QSGTexture *QQuickWindowPrivate::createTextureFromNativeTexture(quint64 nativeObjectHandle,
3350 int nativeLayoutOrState,
3351 uint nativeFormat,
3352 const QSize &size,
3353 QQuickWindow::CreateTextureOptions options,
3354 TextureFromNativeTextureFlags flags) const
3355{
3356 if (!rhi)
3357 return nullptr;
3358
3359 QSGPlainTexture *texture = new QSGPlainTexture;
3360 texture->setTextureFromNativeTexture(rhi, nativeObjectHandle, nativeLayoutOrState, nativeFormat,
3361 size, options, flags);
3362 texture->setHasAlphaChannel(options & QQuickWindow::TextureHasAlphaChannel);
3363 // note that the QRhiTexture does not (and cannot) own the native object
3364 texture->setOwnsTexture(true); // texture meaning the QRhiTexture here, not the native object
3365 texture->setTextureSize(size);
3366 return texture;
3367}
3368
3369/*!
3370 \qmlproperty color Window::color
3371
3372 The background color for the window.
3373
3374 Setting this property is more efficient than using a separate Rectangle.
3375
3376 \note If you set the color to \c "transparent" or to a color with alpha translucency,
3377 you should also set suitable \l flags such as \c {flags: Qt.FramelessWindowHint}.
3378 Otherwise, window translucency may not be enabled consistently on all platforms.
3379*/
3380
3381/*!
3382 \property QQuickWindow::color
3383 \brief The color used to clear the color buffer at the beginning of each frame.
3384
3385 By default, the clear color is white.
3386
3387 \sa setDefaultAlphaBuffer()
3388 */
3389
3390void QQuickWindow::setColor(const QColor &color)
3391{
3392 Q_D(QQuickWindow);
3393 if (color == d->clearColor)
3394 return;
3395
3396 if (color.alpha() != d->clearColor.alpha()) {
3397 QSurfaceFormat fmt = requestedFormat();
3398 if (color.alpha() < 255)
3399 fmt.setAlphaBufferSize(8);
3400 else
3401 fmt.setAlphaBufferSize(-1);
3402 setFormat(fmt);
3403 }
3404 d->clearColor = color;
3405 emit colorChanged(color);
3406 update();
3407}
3408
3409QColor QQuickWindow::color() const
3410{
3411 return d_func()->clearColor;
3412}
3413
3414/*!
3415 \brief Returns whether to use alpha transparency on newly created windows.
3416
3417 \since 5.1
3418 \sa setDefaultAlphaBuffer()
3419 */
3420bool QQuickWindow::hasDefaultAlphaBuffer()
3421{
3422 return QQuickWindowPrivate::defaultAlphaBuffer;
3423}
3424
3425/*!
3426 \brief \a useAlpha specifies whether to use alpha transparency on newly created windows.
3427 \since 5.1
3428
3429 In any application which expects to create translucent windows, it's necessary to set
3430 this to true before creating the first QQuickWindow. The default value is false.
3431
3432 \sa hasDefaultAlphaBuffer()
3433 */
3434void QQuickWindow::setDefaultAlphaBuffer(bool useAlpha)
3435{
3436 QQuickWindowPrivate::defaultAlphaBuffer = useAlpha;
3437}
3438
3439/*!
3440 \struct QQuickWindow::GraphicsStateInfo
3441 \inmodule QtQuick
3442 \since 5.14
3443
3444 \brief Describes some of the RHI's graphics state at the point of a
3445 \l{QQuickWindow::beginExternalCommands()}{beginExternalCommands()} call.
3446 */
3447
3448/*!
3449 \variable QQuickWindow::GraphicsStateInfo::currentFrameSlot
3450 \since 5.14
3451 \brief the current frame slot index while recording a frame.
3452
3453 When the scenegraph renders with lower level 3D APIs such as Vulkan or
3454 Metal, it is the Qt's responsibility to ensure blocking whenever starting a
3455 new frame and finding the CPU is already a certain number of frames ahead
3456 of the GPU (because the command buffer submitted in frame no. \c{current} -
3457 \c{FramesInFlight} has not yet completed). With other graphics APIs, such
3458 as OpenGL or Direct 3D 11 this level of control is not exposed to the API
3459 client but rather handled by the implementation of the graphics API.
3460
3461 By extension, this also means that the appropriate double (or triple)
3462 buffering of resources, such as buffers, is up to the graphics API client
3463 to manage. Most commonly, a uniform buffer where the data changes between
3464 frames cannot simply change its contents when submitting a frame, given
3465 that the frame may still be active ("in flight") when starting to record
3466 the next frame. To avoid stalling the pipeline, one way is to have multiple
3467 buffers (and memory allocations) under the hood, thus realizing at least a
3468 double buffered scheme for such resources.
3469
3470 Applications that integrate rendering done directly with a graphics API
3471 such as Vulkan may want to perform a similar double or triple buffering of
3472 their own graphics resources, in a way that is compatible with the Qt
3473 rendering engine's frame submission process. That then involves knowing the
3474 values for the maximum number of in-flight frames (which is typically 2 or
3475 3) and the current frame slot index, which is a number running 0, 1, ..,
3476 FramesInFlight-1, and then wrapping around. The former is exposed in the
3477 \l{QQuickWindow::GraphicsStateInfo::framesInFlight}{framesInFlight}
3478 variable. The latter, current index, is this value.
3479
3480 For an example of using these values in practice, refer to the {Scene Graph
3481 - Vulkan Under QML} and {Scene Graph - Vulkan Texture Import} examples.
3482 */
3483
3484/*!
3485 \variable QQuickWindow::GraphicsStateInfo::framesInFlight
3486 \since 5.14
3487 \brief the maximum number of frames kept in flight.
3488
3489 See \l{QQuickWindow::GraphicsStateInfo::currentFrameSlot}{currentFrameSlot}
3490 for a detailed description.
3491 */
3492
3493/*!
3494 \return a reference to a GraphicsStateInfo struct describing some of the
3495 RHI's internal state, in particular, the double or tripple buffering status
3496 of the backend (such as, the Vulkan or Metal integrations). This is
3497 relevant when the underlying graphics APIs is Vulkan or Metal, and the
3498 external rendering code wishes to perform double or tripple buffering of
3499 its own often-changing resources, such as, uniform buffers, in order to
3500 avoid stalling the pipeline.
3501 */
3502const QQuickWindow::GraphicsStateInfo &QQuickWindow::graphicsStateInfo()
3503{
3504 Q_D(QQuickWindow);
3505 if (d->rhi) {
3506 d->rhiStateInfo.currentFrameSlot = d->rhi->currentFrameSlot();
3507 d->rhiStateInfo.framesInFlight = d->rhi->resourceLimit(QRhi::FramesInFlight);
3508 }
3509 return d->rhiStateInfo;
3510}
3511
3512/*!
3513 When mixing raw graphics (OpenGL, Vulkan, Metal, etc.) commands with scene
3514 graph rendering, it is necessary to call this function before recording
3515 commands to the command buffer used by the scene graph to render its main
3516 render pass. This is to avoid clobbering state.
3517
3518 In practice this function is often called from a slot connected to the
3519 beforeRenderPassRecording() or afterRenderPassRecording() signals.
3520
3521 The function does not need to be called when recording commands to the
3522 application's own command buffer (such as, a VkCommandBuffer or
3523 MTLCommandBuffer + MTLRenderCommandEncoder created and managed by the
3524 application, not retrieved from the scene graph). With graphics APIs where
3525 no native command buffer concept is exposed (OpenGL, Direct 3D 11),
3526 beginExternalCommands() and endExternalCommands() together provide a
3527 replacement for the Qt 5 resetOpenGLState() function.
3528
3529 Calling this function and endExternalCommands() is not necessary within the
3530 \l{QSGRenderNode::render()}{render()} implementation of a QSGRenderNode
3531 because the scene graph performs the necessary steps implicitly for render
3532 nodes.
3533
3534 Native graphics objects (such as, graphics device, command buffer or
3535 encoder) are accessible via QSGRendererInterface::getResource().
3536
3537 \warning Watch out for the fact that
3538 QSGRendererInterface::CommandListResource may return a different object
3539 between beginExternalCommands() - endExternalCommands(). This can happen
3540 when the underlying implementation provides a dedicated secondary command
3541 buffer for recording external graphics commands within a render pass.
3542 Therefore, always query CommandListResource after calling this function. Do
3543 not attempt to reuse an object from an earlier query.
3544
3545 \note When the scenegraph is using OpenGL, pay attention to the fact that
3546 the OpenGL state in the context can have arbitrary settings, and this
3547 function does not perform any resetting of the state back to defaults.
3548
3549 \sa endExternalCommands(), QQuickOpenGLUtils::resetOpenGLState()
3550
3551 \since 5.14
3552 */
3553void QQuickWindow::beginExternalCommands()
3554{
3555 Q_D(QQuickWindow);
3556 if (d->rhi && d->context && d->context->isValid()) {
3557 QSGDefaultRenderContext *rc = static_cast<QSGDefaultRenderContext *>(d->context);
3558 QRhiCommandBuffer *cb = rc->currentFrameCommandBuffer();
3559 if (cb)
3560 cb->beginExternal();
3561 }
3562}
3563
3564/*!
3565 When mixing raw graphics (OpenGL, Vulkan, Metal, etc.) commands with scene
3566 graph rendering, it is necessary to call this function after recording
3567 commands to the command buffer used by the scene graph to render its main
3568 render pass. This is to avoid clobbering state.
3569
3570 In practice this function is often called from a slot connected to the
3571 beforeRenderPassRecording() or afterRenderPassRecording() signals.
3572
3573 The function does not need to be called when recording commands to the
3574 application's own command buffer (such as, a VkCommandBuffer or
3575 MTLCommandBuffer + MTLRenderCommandEncoder created and managed by the
3576 application, not retrieved from the scene graph). With graphics APIs where
3577 no native command buffer concept is exposed (OpenGL, Direct 3D 11),
3578 beginExternalCommands() and endExternalCommands() together provide a
3579 replacement for the Qt 5 resetOpenGLState() function.
3580
3581 Calling this function and beginExternalCommands() is not necessary within the
3582 \l{QSGRenderNode::render()}{render()} implementation of a QSGRenderNode
3583 because the scene graph performs the necessary steps implicitly for render
3584 nodes.
3585
3586 \sa beginExternalCommands(), QQuickOpenGLUtils::resetOpenGLState()
3587
3588 \since 5.14
3589 */
3590void QQuickWindow::endExternalCommands()
3591{
3592 Q_D(QQuickWindow);
3593 if (d->rhi && d->context && d->context->isValid()) {
3594 QSGDefaultRenderContext *rc = static_cast<QSGDefaultRenderContext *>(d->context);
3595 QRhiCommandBuffer *cb = rc->currentFrameCommandBuffer();
3596 if (cb)
3597 cb->endExternal();
3598 }
3599}
3600
3601/*!
3602 \qmlproperty string Window::title
3603
3604 The window's title in the windowing system.
3605
3606 The window title might appear in the title area of the window decorations,
3607 depending on the windowing system and the window flags. It might also
3608 be used by the windowing system to identify the window in other contexts,
3609 such as in the task switcher.
3610 */
3611
3612/*!
3613 \qmlproperty Qt::WindowModality Window::modality
3614
3615 The modality of the window.
3616
3617 A modal window prevents other windows from receiving input events.
3618 Possible values are Qt.NonModal (the default), Qt.WindowModal,
3619 and Qt.ApplicationModal.
3620 */
3621
3622/*!
3623 \qmlproperty Qt::WindowFlags Window::flags
3624
3625 The window flags of the window.
3626
3627 The window flags control the window's appearance in the windowing system,
3628 whether it's a dialog, popup, or a regular window, and whether it should
3629 have a title bar, etc.
3630
3631 The flags that you read from this property might differ from the ones
3632 that you set if the requested flags could not be fulfilled.
3633
3634 \snippet qml/splashWindow.qml entire
3635
3636 \sa Qt::WindowFlags, {Qt Quick Examples - Window and Screen}
3637 */
3638
3639/*!
3640 \qmlattachedproperty Window Window::window
3641 \since 5.7
3642
3643 This attached property holds the item's window.
3644 The Window attached property can be attached to any Item.
3645*/
3646
3647/*!
3648 \qmlattachedproperty int Window::width
3649 \qmlattachedproperty int Window::height
3650 \since 5.5
3651
3652 These attached properties hold the size of the item's window.
3653 The Window attached property can be attached to any Item.
3654*/
3655
3656/*!
3657 \qmlproperty int Window::x
3658 \qmlproperty int Window::y
3659 \qmlproperty int Window::width
3660 \qmlproperty int Window::height
3661
3662 Defines the window's position and size.
3663
3664 The (x,y) position is relative to the \l Screen if there is only one,
3665 or to the virtual desktop (arrangement of multiple screens).
3666
3667 \note Not all windowing systems support setting or querying top level
3668 window positions. On such a system, programmatically moving windows
3669 may not have any effect, and artificial values may be returned for
3670 the current positions, such as \c QPoint(0, 0).
3671
3672 \qml
3673 Window { x: 100; y: 100; width: 100; height: 100 }
3674 \endqml
3675
3676 \image screen-and-window-dimensions.jpg
3677 */
3678
3679/*!
3680 \qmlproperty int Window::minimumWidth
3681 \qmlproperty int Window::minimumHeight
3682 \since 5.1
3683
3684 Defines the window's minimum size.
3685
3686 This is a hint to the window manager to prevent resizing below the specified
3687 width and height.
3688 */
3689
3690/*!
3691 \qmlproperty int Window::maximumWidth
3692 \qmlproperty int Window::maximumHeight
3693 \since 5.1
3694
3695 Defines the window's maximum size.
3696
3697 This is a hint to the window manager to prevent resizing above the specified
3698 width and height.
3699 */
3700
3701/*!
3702 \qmlproperty bool Window::visible
3703
3704 Whether the window is visible on the screen.
3705
3706 Setting visible to false is the same as setting \l visibility to \l {QWindow::}{Hidden}.
3707
3708 The default value is \c false, unless overridden by setting \l visibility.
3709
3710 \sa visibility
3711 */
3712
3713/*!
3714 \keyword qml-window-visibility-prop
3715 \qmlproperty QWindow::Visibility Window::visibility
3716
3717 The screen-occupation state of the window.
3718
3719 Visibility is whether the window should appear in the windowing system as
3720 normal, minimized, maximized, fullscreen or hidden.
3721
3722 To set the visibility to \l {QWindow::}{AutomaticVisibility} means to give the
3723 window a default visible state, which might be \l {QWindow::}{FullScreen} or
3724 \l {QWindow::}{Windowed} depending on the platform. However when reading the
3725 visibility property you will always get the actual state, never
3726 \c AutomaticVisibility.
3727
3728 When a window is not \l visible, its visibility is \c Hidden.
3729 Setting visibility to \l {QWindow::}{Hidden} is the same as setting \l visible to \c false.
3730
3731 The default value is \l {QWindow::}{Hidden}
3732
3733 \snippet qml/windowVisibility.qml entire
3734
3735 \sa visible, {Qt Quick Examples - Window and Screen}
3736 \since 5.1
3737 */
3738
3739/*!
3740 \qmlattachedproperty QWindow::Visibility Window::visibility
3741 \readonly
3742 \since 5.4
3743
3744 This attached property holds whether the window is currently shown
3745 in the windowing system as normal, minimized, maximized, fullscreen or
3746 hidden. The \c Window attached property can be attached to any Item. If the
3747 item is not shown in any window, the value will be \l {QWindow::}{Hidden}.
3748
3749 \sa visible, {qml-window-visibility-prop}{visibility}
3750*/
3751
3752/*!
3753 \qmlproperty Item Window::contentItem
3754 \readonly
3755 \brief The invisible root item of the scene.
3756*/
3757
3758/*!
3759 \qmlproperty Qt::ScreenOrientation Window::contentOrientation
3760
3761 This is a hint to the window manager in case it needs to display
3762 additional content like popups, dialogs, status bars, or similar
3763 in relation to the window.
3764
3765 The recommended orientation is \l {Screen::orientation}{Screen.orientation}, but
3766 an application doesn't have to support all possible orientations,
3767 and thus can opt to ignore the current screen orientation.
3768
3769 The difference between the window and the content orientation
3770 determines how much to rotate the content by.
3771
3772 The default value is Qt::PrimaryOrientation.
3773
3774 \sa Screen
3775
3776 \since 5.1
3777 */
3778
3779/*!
3780 \qmlproperty real Window::opacity
3781
3782 The opacity of the window.
3783
3784 If the windowing system supports window opacity, this can be used to fade the
3785 window in and out, or to make it semitransparent.
3786
3787 A value of 1.0 or above is treated as fully opaque, whereas a value of 0.0 or below
3788 is treated as fully transparent. Values inbetween represent varying levels of
3789 translucency between the two extremes.
3790
3791 The default value is 1.0.
3792
3793 \since 5.1
3794 */
3795
3796/*!
3797 \qmlproperty Screen Window::screen
3798
3799 The screen with which the window is associated.
3800
3801 If specified before showing a window, will result in the window being shown
3802 on that screen, unless an explicit window position has been set. The value
3803 must be an element from the \l{Application::screens}{Application.screens}
3804 array.
3805
3806 \note To ensure that the window is associated with the desired screen when
3807 the underlying native window is created, make sure this property is set as
3808 early as possible and that the setting of its value is not deferred. This
3809 can be particularly important on embedded platforms without a windowing system,
3810 where only one window per screen is allowed at a time. Setting the screen after
3811 a window has been created does not move the window if the new screen is part of
3812 the same virtual desktop as the old screen.
3813
3814 \since 5.9
3815
3816 \sa QWindow::setScreen(), QWindow::screen(), QScreen, {QtQuick::Application}{Application}
3817 */
3818
3819/*!
3820 \qmlproperty QWindow Window::transientParent
3821 \since 5.13
3822
3823 The window for which this window is a transient pop-up.
3824
3825 This is a hint to the window manager that this window is a dialog or pop-up
3826 on behalf of the transient parent. It usually means that the transient
3827 window will be centered over its transient parent when it is initially
3828 shown, that minimizing the parent window will also minimize the transient
3829 window, and so on; however results vary somewhat from platform to platform.
3830
3831 Declaring a Window inside an Item or another Window, either via the
3832 \l{Window::data}{default property} or a dedicated property, will automatically
3833 set up a transient parent relationship to the containing window,
3834 unless the \l transientParent property is explicitly set. This applies
3835 when creating Window items via \l [QML] {QtQml::Qt::createComponent()}
3836 {Qt.createComponent} or \l [QML] {QtQml::Qt::createQmlObject()}
3837 {Qt.createQmlObject} as well, as long as an Item or Window is passed
3838 as the \c parent argument.
3839
3840 A Window with a transient parent will not be shown until its transient
3841 parent is shown, even if the \l visible property is \c true. This also
3842 applies for the automatic transient parent relationship described above.
3843 In particular, if the Window's containing element is an Item, the window
3844 will not be shown until the containing item is added to a scene, via its
3845 \l{Concepts - Visual Parent in Qt Quick}{visual parent hierarchy}. Setting
3846 the \l transientParent to \c null will override this behavior:
3847
3848 \snippet qml/nestedWindowTransientParent.qml 0
3849 \snippet qml/nestedWindowTransientParent.qml 1
3850
3851 In order to cause the window to be centered above its transient parent by
3852 default, depending on the window manager, it may also be necessary to set
3853 the \l Window::flags property with a suitable \l Qt::WindowType (such as
3854 \c Qt::Dialog).
3855
3856 \sa {QQuickWindow::}{parent()}
3857*/
3858
3859/*!
3860 \property QQuickWindow::transientParent
3861 \brief The window for which this window is a transient pop-up.
3862 \since 5.13
3863
3864 This is a hint to the window manager that this window is a dialog or pop-up
3865 on behalf of the transient parent, which may be any kind of \l QWindow.
3866
3867 In order to cause the window to be centered above its transient parent by
3868 default, depending on the window manager, it may also be necessary to set
3869 the \l flags property with a suitable \l Qt::WindowType (such as \c Qt::Dialog).
3870
3871 \sa parent()
3872 */
3873
3874/*!
3875 \qmlproperty Item Window::activeFocusItem
3876 \since 5.1
3877
3878 The item which currently has active focus or \c null if there is
3879 no item with active focus.
3880 */
3881
3882/*!
3883 \qmlattachedproperty Item Window::activeFocusItem
3884 \since 5.4
3885
3886 This attached property holds the item which currently has active focus or
3887 \c null if there is no item with active focus. The Window attached property
3888 can be attached to any Item.
3889*/
3890
3891/*!
3892 \qmlproperty bool Window::active
3893 \since 5.1
3894
3895 The active status of the window.
3896
3897 \snippet qml/windowPalette.qml declaration-and-color
3898 \snippet qml/windowPalette.qml closing-brace
3899
3900 \sa requestActivate()
3901 */
3902
3903/*!
3904 \qmlattachedproperty bool Window::active
3905 \since 5.4
3906
3907 This attached property tells whether the window is active. The Window
3908 attached property can be attached to any Item.
3909
3910 Here is an example which changes a label to show the active state of the
3911 window in which it is shown:
3912
3913 \snippet qml/windowActiveAttached.qml entire
3914*/
3915
3916/*!
3917 \qmlmethod void QtQuick::Window::requestActivate()
3918 \since 5.1
3919
3920 Requests the window to be activated, i.e. receive keyboard focus.
3921 */
3922
3923/*!
3924 \qmlmethod void QtQuick::Window::alert(int msec)
3925 \since 5.1
3926
3927 Causes an alert to be shown for \a msec milliseconds. If \a msec is \c 0
3928 (the default), then the alert is shown indefinitely until the window
3929 becomes active again.
3930
3931 In alert state, the window indicates that it demands attention, for example
3932 by flashing or bouncing the taskbar entry.
3933*/
3934
3935/*!
3936 \qmlmethod void QtQuick::Window::close()
3937
3938 Closes the window.
3939
3940 When this method is called, or when the user tries to close the window by
3941 its title bar button, the \l closing signal will be emitted. If there is no
3942 handler, or the handler does not revoke permission to close, the window
3943 will subsequently close. If the QGuiApplication::quitOnLastWindowClosed
3944 property is \c true, and there are no other windows open, the application
3945 will quit.
3946*/
3947
3948/*!
3949 \qmlmethod void QtQuick::Window::raise()
3950
3951 Raises the window in the windowing system.
3952
3953 Requests that the window be raised to appear above other windows.
3954*/
3955
3956/*!
3957 \qmlmethod void QtQuick::Window::lower()
3958
3959 Lowers the window in the windowing system.
3960
3961 Requests that the window be lowered to appear below other windows.
3962*/
3963
3964/*!
3965 \qmlmethod void QtQuick::Window::show()
3966
3967 Shows the window.
3968
3969 This is equivalent to calling showFullScreen(), showMaximized(), or showNormal(),
3970 depending on the platform's default behavior for the window type and flags.
3971
3972 \sa showFullScreen(), showMaximized(), showNormal(), hide(), QQuickItem::flags()
3973*/
3974
3975/*!
3976 \qmlmethod void QtQuick::Window::hide()
3977
3978 Hides the window.
3979
3980 Equivalent to setting \l visible to \c false or \l visibility to \l {QWindow::}{Hidden}.
3981
3982 \sa show()
3983*/
3984
3985/*!
3986 \qmlmethod void QtQuick::Window::showMinimized()
3987
3988 Shows the window as minimized.
3989
3990 Equivalent to setting \l visibility to \l {QWindow::}{Minimized}.
3991*/
3992
3993/*!
3994 \qmlmethod void QtQuick::Window::showMaximized()
3995
3996 Shows the window as maximized.
3997
3998 Equivalent to setting \l visibility to \l {QWindow::}{Maximized}.
3999*/
4000
4001/*!
4002 \qmlmethod void QtQuick::Window::showFullScreen()
4003
4004 Shows the window as fullscreen.
4005
4006 Equivalent to setting \l visibility to \l {QWindow::}{FullScreen}.
4007*/
4008
4009/*!
4010 \qmlmethod void QtQuick::Window::showNormal()
4011
4012 Shows the window as normal, i.e. neither maximized, minimized, nor fullscreen.
4013
4014 Equivalent to setting \l visibility to \l {QWindow::}{Windowed}.
4015*/
4016
4017/*!
4018 \enum QQuickWindow::RenderStage
4019 \since 5.4
4020
4021 \value BeforeSynchronizingStage Before synchronization.
4022 \value AfterSynchronizingStage After synchronization.
4023 \value BeforeRenderingStage Before rendering.
4024 \value AfterRenderingStage After rendering.
4025 \value AfterSwapStage After the frame is swapped.
4026 \value NoStage As soon as possible. This value was added in Qt 5.6.
4027
4028 \sa {Scene Graph and Rendering}
4029 */
4030
4031/*!
4032 \since 5.4
4033
4034 Schedules \a job to run when the rendering of this window reaches
4035 the given \a stage.
4036
4037 This is a convenience to the equivalent signals in QQuickWindow for
4038 "one shot" tasks.
4039
4040 The window takes ownership over \a job and will delete it when the
4041 job is completed.
4042
4043 If rendering is shut down before \a job has a chance to run, the
4044 job will be run and then deleted as part of the scene graph cleanup.
4045 If the window is never shown and no rendering happens before the QQuickWindow
4046 is destroyed, all pending jobs will be destroyed without their run()
4047 method being called.
4048
4049 If the rendering is happening on a different thread, then the job
4050 will happen on the rendering thread.
4051
4052 If \a stage is \l NoStage, \a job will be run at the earliest opportunity
4053 whenever the render thread is not busy rendering a frame. If the window is
4054 not exposed, and is not renderable, at the time the job is either posted or
4055 handled, the job is deleted without executing the run() method. If a
4056 non-threaded renderer is in use, the run() method of the job is executed
4057 synchronously. When rendering with OpenGL, the OpenGL context is changed to
4058 the renderer's context before executing any job, including \l NoStage jobs.
4059
4060 \note This function does not trigger rendering; the jobs targeting any other
4061 stage than NoStage will be stored run until rendering is triggered elsewhere.
4062 To force the job to run earlier, call QQuickWindow::update();
4063
4064 \sa beforeRendering(), afterRendering(), beforeSynchronizing(),
4065 afterSynchronizing(), frameSwapped(), sceneGraphInvalidated()
4066 */
4067
4068void QQuickWindow::scheduleRenderJob(QRunnable *job, RenderStage stage)
4069{
4070 Q_D(QQuickWindow);
4071
4072 d->renderJobMutex.lock();
4073 if (stage == BeforeSynchronizingStage) {
4074 d->beforeSynchronizingJobs << job;
4075 } else if (stage == AfterSynchronizingStage) {
4076 d->afterSynchronizingJobs << job;
4077 } else if (stage == BeforeRenderingStage) {
4078 d->beforeRenderingJobs << job;
4079 } else if (stage == AfterRenderingStage) {
4080 d->afterRenderingJobs << job;
4081 } else if (stage == AfterSwapStage) {
4082 d->afterSwapJobs << job;
4083 } else if (stage == NoStage) {
4084 if (d->renderControl && d->rhi && d->rhi->thread() == QThread::currentThread()) {
4085 job->run();
4086 delete job;
4087 } else if (isExposed()) {
4088 d->windowManager->postJob(this, job);
4089 } else {
4090 delete job;
4091 }
4092 }
4093 d->renderJobMutex.unlock();
4094}
4095
4096void QQuickWindowPrivate::runAndClearJobs(QList<QRunnable *> *jobs)
4097{
4098 renderJobMutex.lock();
4099 QList<QRunnable *> jobList = *jobs;
4100 jobs->clear();
4101 renderJobMutex.unlock();
4102
4103 for (QRunnable *r : std::as_const(jobList)) {
4104 r->run();
4105 delete r;
4106 }
4107}
4108
4109void QQuickWindow::runJobsAfterSwap()
4110{
4111 Q_D(QQuickWindow);
4112 d->runAndClearJobs(&d->afterSwapJobs);
4113}
4114
4115/*!
4116 \fn void QQuickWindow::devicePixelRatioChanged()
4117 \since 6.11
4118 This signal is emitted when the effective device pixel ratio has
4119 been changed.
4120 \sa effectiveDevicePixelRatio()
4121 */
4122
4123/*!
4124 \qmlsignal QtQuick::Window::devicePixelRatioChanged()
4125 */
4126
4127/*!
4128 \property QQuickWindow::devicePixelRatio
4129 \since 6.11
4130
4131 Returns the ratio between physical pixels and device-independent pixels for the window. This value is dependent on the screen the window is on, and may change when the window is moved.
4132 */
4133
4134/*!
4135 Returns the device pixel ratio for this window.
4136
4137 This is different from QWindow::devicePixelRatio() in that it supports
4138 redirected rendering via QQuickRenderControl and QQuickRenderTarget. When
4139 using a QQuickRenderControl, the QQuickWindow is often not fully created,
4140 meaning it is never shown and there is no underlying native window created
4141 in the windowing system. As a result, querying properties like the device
4142 pixel ratio cannot give correct results. This function takes into account
4143 both QQuickRenderControl::renderWindowFor() and
4144 QQuickRenderTarget::devicePixelRatio(). When no redirection is in effect,
4145 the result is same as QWindow::devicePixelRatio().
4146
4147 \sa QQuickRenderControl, QQuickRenderTarget, setRenderTarget(), QWindow::devicePixelRatio()
4148 */
4149qreal QQuickWindow::effectiveDevicePixelRatio() const
4150{
4151 Q_D(const QQuickWindow);
4152 QWindow *w = QQuickRenderControl::renderWindowFor(const_cast<QQuickWindow *>(this));
4153 if (w)
4154 return w->devicePixelRatio();
4155
4156 if (!d->customRenderTarget.isNull())
4157 return d->customRenderTarget.devicePixelRatio();
4158
4159 return devicePixelRatio();
4160}
4161
4162/*!
4163 \return the current renderer interface. The value is always valid and is never null.
4164
4165 \note This function can be called at any time after constructing the
4166 QQuickWindow, even while isSceneGraphInitialized() is still false. However,
4167 some renderer interface functions, in particular
4168 QSGRendererInterface::getResource() will not be functional until the
4169 scenegraph is up and running. Backend queries, like
4170 QSGRendererInterface::graphicsApi() or QSGRendererInterface::shaderType(),
4171 will always be functional on the other hand.
4172
4173 \note The ownership of the returned pointer stays with Qt. The returned
4174 instance may or may not be shared between different QQuickWindow instances,
4175 depending on the scenegraph backend in use. Therefore applications are
4176 expected to query the interface object for each QQuickWindow instead of
4177 reusing the already queried pointer.
4178
4179 \sa QSGRenderNode, QSGRendererInterface
4180
4181 \since 5.8
4182 */
4183QSGRendererInterface *QQuickWindow::rendererInterface() const
4184{
4185 Q_D(const QQuickWindow);
4186
4187 // no context validity check - it is essential to be able to return a
4188 // renderer interface instance before scenegraphInitialized() is emitted
4189 // (depending on the backend, that can happen way too late for some of the
4190 // rif use cases, like examining the graphics api or shading language in
4191 // use)
4192
4193 return d->context->sceneGraphContext()->rendererInterface(d->context);
4194}
4195
4196/*!
4197 \return the QRhi object used by this window for rendering.
4198
4199 Available only when the window is using Qt's 3D API and shading language
4200 abstractions, meaning the result is always null when using the \c software
4201 adaptation.
4202
4203 The result is valid only when rendering has been initialized, which is
4204 indicated by the emission of the sceneGraphInitialized() signal. Before
4205 that point, the returned value is null. With a regular, on-screen
4206 QQuickWindow scenegraph initialization typically happens when the native
4207 window gets exposed (shown) the first time. When using QQuickRenderControl,
4208 initialization is done in the explicit
4209 \l{QQuickRenderControl::initialize()}{initialize()} call.
4210
4211 In practice this function is a shortcut to querying the QRhi via the
4212 QSGRendererInterface.
4213
4214 \since 6.6
4215 */
4216QRhi *QQuickWindow::rhi() const
4217{
4218 Q_D(const QQuickWindow);
4219 return d->rhi;
4220}
4221
4222/*!
4223 \return the QRhiSwapChain used by this window, if there is one.
4224
4225 \note Only on-screen windows backed by one of the standard render loops
4226 (such as, \c basic or \c threaded) will have a swapchain. Otherwise the
4227 returned value is null. For example, the result is always null when the
4228 window is used with QQuickRenderControl.
4229
4230 \since 6.6
4231 */
4232QRhiSwapChain *QQuickWindow::swapChain() const
4233{
4234 Q_D(const QQuickWindow);
4235 return d->swapchain;
4236}
4237
4238/*!
4239 Requests the specified graphics \a api.
4240
4241 When the built-in, default graphics adaptation is used, \a api specifies
4242 which graphics API (OpenGL, Vulkan, Metal, or Direct3D) the scene graph
4243 should use to render. In addition, the \c software backend is built-in as
4244 well, and can be requested by setting \a api to
4245 QSGRendererInterface::Software.
4246
4247 Unlike setSceneGraphBackend(), which can only be used to request a given
4248 backend (shipped either built-in or installed as dynamically loaded
4249 plugins), this function works with the higher level concept of graphics
4250 APIs. It covers the backends that ship with Qt Quick, and thus have
4251 corresponding values in the QSGRendererInterface::GraphicsApi enum.
4252
4253 When this function is not called at all, and the equivalent environment
4254 variable \c{QSG_RHI_BACKEND} is not set either, the scene graph will choose
4255 the graphics API to use based on the platform.
4256
4257 This function becomes important in applications that are only prepared for
4258 rendering with a given API. For example, if there is native OpenGL or
4259 Vulkan rendering done by the application, it will want to ensure Qt Quick
4260 is rendering using OpenGL or Vulkan too. Such applications are expected to
4261 call this function early in their main() function.
4262
4263 \note The call to the function must happen before constructing the first
4264 QQuickWindow in the application. The graphics API cannot be changed
4265 afterwards.
4266
4267 \note When used in combination with QQuickRenderControl, this rule is
4268 relaxed: it is possible to change the graphics API, but only when all
4269 existing QQuickRenderControl and QQuickWindow instances have been
4270 destroyed.
4271
4272 To query what graphics API the scene graph is using to render,
4273 QSGRendererInterface::graphicsApi() after the scene graph
4274 \l{QQuickWindow::isSceneGraphInitialized()}{has initialized}, which
4275 typically happens either when the window becomes visible for the first time, or
4276 when QQuickRenderControl::initialize() is called.
4277
4278 To switch back to the default behavior, where the scene graph chooses a
4279 graphics API based on the platform and other conditions, set \a api to
4280 QSGRendererInterface::Unknown.
4281
4282 \since 6.0
4283 */
4284void QQuickWindow::setGraphicsApi(QSGRendererInterface::GraphicsApi api)
4285{
4286 // Special cases: these are different scenegraph backends.
4287 switch (api) {
4288 case QSGRendererInterface::Software:
4289 setSceneGraphBackend(QStringLiteral("software"));
4290 break;
4291 case QSGRendererInterface::OpenVG:
4292 setSceneGraphBackend(QStringLiteral("openvg"));
4293 break;
4294 default:
4295 break;
4296 }
4297
4298 // Standard case: tell the QRhi-based default adaptation what graphics api
4299 // (QRhi backend) to use.
4300 if (QSGRendererInterface::isApiRhiBased(api) || api == QSGRendererInterface::Unknown)
4301 QSGRhiSupport::instance_internal()->configure(api);
4302}
4303
4304/*!
4305 \return the graphics API that would be used by the scene graph if it was
4306 initialized at this point in time.
4307
4308 The standard way to query the API used by the scene graph is to use
4309 QSGRendererInterface::graphicsApi() once the scene graph has initialized,
4310 for example when or after the sceneGraphInitialized() signal is emitted. In
4311 that case one gets the true, real result, because then it is known that
4312 everything was initialized correctly using that graphics API.
4313
4314 This is not always convenient. If the application needs to set up external
4315 frameworks, or needs to work with setGraphicsDevice() in a manner that
4316 depends on the scene graph's built in API selection logic, it is not always
4317 feasiable to defer such operations until after the QQuickWindow has been
4318 made visible or QQuickRenderControl::initialize() has been called.
4319
4320 Therefore, this static function is provided as a counterpart to
4321 setGraphicsApi(): it can be called at any time, and the result reflects
4322 what API the scene graph would choose if it was initialized at the point of
4323 the call.
4324
4325 \note This static function is intended to be called on the main (GUI)
4326 thread only. For querying the API when rendering, use QSGRendererInterface
4327 since that object lives on the render thread.
4328
4329 \note This function does not take scene graph backends into account.
4330
4331 \since 6.0
4332 */
4333QSGRendererInterface::GraphicsApi QQuickWindow::graphicsApi()
4334{
4335 // Note that this applies the settings e.g. from the env vars
4336 // (QSG_RHI_BACKEND) if it was not done at least once already. Whereas if
4337 // setGraphicsApi() was called before, or the scene graph is already
4338 // initialized, then this is just a simple query.
4339 return QSGRhiSupport::instance()->graphicsApi();
4340}
4341
4342/*!
4343 Requests a Qt Quick scenegraph \a backend. Backends can either be built-in
4344 or be installed in form of dynamically loaded plugins.
4345
4346 \overload
4347
4348 \note The call to the function must happen before constructing the first
4349 QQuickWindow in the application. It cannot be changed afterwards.
4350
4351 See \l{Switch Between Adaptations in Your Application} for more information
4352 about the list of backends. If \a backend is invalid or an error occurs, the
4353 request is ignored.
4354
4355 \note Calling this function is equivalent to setting the
4356 \c QT_QUICK_BACKEND or \c QMLSCENE_DEVICE environment variables. However, this
4357 API is safer to use in applications that spawn other processes as there is
4358 no need to worry about environment inheritance.
4359
4360 \since 5.8
4361 */
4362void QQuickWindow::setSceneGraphBackend(const QString &backend)
4363{
4364 QSGContext::setBackend(backend);
4365}
4366
4367/*!
4368 Returns the requested Qt Quick scenegraph backend.
4369
4370 \note The return value of this function may still be outdated by
4371 subsequent calls to setSceneGraphBackend() until the first QQuickWindow in the
4372 application has been constructed.
4373
4374 \note The value only reflects the request in the \c{QT_QUICK_BACKEND}
4375 environment variable after a QQuickWindow has been constructed.
4376
4377 \since 5.9
4378 */
4379QString QQuickWindow::sceneGraphBackend()
4380{
4381 return QSGContext::backend();
4382}
4383
4384/*!
4385 Sets the graphics device objects for this window. The scenegraph will use
4386 existing device, physical device, and other objects specified by \a device
4387 instead of creating new ones.
4388
4389 This function is very often used in combination with QQuickRenderControl
4390 and setRenderTarget(), in order to redirect Qt Quick rendering into a
4391 texture.
4392
4393 A default constructed QQuickGraphicsDevice does not change the default
4394 behavior in any way. Once a \a device created via one of the
4395 QQuickGraphicsDevice factory functions, such as,
4396 QQuickGraphicsDevice::fromDeviceObjects(), is passed in, and the scenegraph
4397 uses a matching graphics API (with the example of fromDeviceObjects(), that
4398 would be Vulkan), the scenegraph will use the existing device objects (such
4399 as, the \c VkPhysicalDevice, \c VkDevice, and graphics queue family index,
4400 in case of Vulkan) encapsulated by the QQuickGraphicsDevice. This allows
4401 using the same device, and so sharing resources, such as buffers and
4402 textures, between Qt Quick and native rendering engines.
4403
4404 \warning This function can only be called before initializing the
4405 scenegraph and will have no effect if called afterwards. In practice this
4406 typically means calling it right before QQuickRenderControl::initialize().
4407
4408 As an example, this time with Direct3D, the typical usage is expected to be
4409 the following:
4410
4411 \badcode
4412 // native graphics resources set up by a custom D3D rendering engine
4413 ID3D11Device *device;
4414 ID3D11DeviceContext *context;
4415 ID3D11Texture2D *texture;
4416 ...
4417 // now to redirect Qt Quick content into 'texture' we could do the following:
4418 QQuickRenderControl *renderControl = new QQuickRenderControl;
4419 QQuickWindow *window = new QQuickWindow(renderControl); // this window will never be shown on-screen
4420 ...
4421 window->setGraphicsDevice(QQuickGraphicsDevice::fromDeviceAndContext(device, context));
4422 renderControl->initialize();
4423 window->setRenderTarget(QQuickRenderTarget::fromD3D11Texture(texture, textureSize);
4424 ...
4425 \endcode
4426
4427 The key aspect of using this function is to ensure that resources or
4428 handles to resources, such as \c texture in the above example, are visible
4429 to and usable by both the external rendering engine and the scenegraph
4430 renderer. This requires using the same graphics device (or with OpenGL,
4431 OpenGL context).
4432
4433 QQuickGraphicsDevice instances are implicitly shared, copyable, and
4434 can be passed by value. They do not own the associated native objects (such
4435 as, the ID3D11Device in the example).
4436
4437 \note Using QQuickRenderControl does not always imply having to call this
4438 function. When adopting an existing device or context is not needed, this
4439 function should not be called, and the scene graph will then initialize its
4440 own devices and contexts normally, just as it would with an on-screen
4441 QQuickWindow.
4442
4443 \since 6.0
4444
4445 \sa QQuickRenderControl, setRenderTarget(), setGraphicsApi()
4446 */
4447void QQuickWindow::setGraphicsDevice(const QQuickGraphicsDevice &device)
4448{
4449 Q_D(QQuickWindow);
4450 d->customDeviceObjects = device;
4451}
4452
4453/*!
4454 \return the QQuickGraphicsDevice passed to setGraphicsDevice(), or a
4455 default constructed one otherwise
4456
4457 \since 6.0
4458
4459 \sa setGraphicsDevice()
4460 */
4461QQuickGraphicsDevice QQuickWindow::graphicsDevice() const
4462{
4463 Q_D(const QQuickWindow);
4464 return d->customDeviceObjects;
4465}
4466
4467/*!
4468 Sets the graphics configuration for this window. \a config contains various
4469 settings that may be taken into account by the scene graph when
4470 initializing the underlying graphics devices and contexts.
4471
4472 Such additional configuration, specifying for example what device
4473 extensions to enable for Vulkan, becomes relevant and essential when
4474 integrating native graphics rendering code that relies on certain
4475 extensions. The same is true when integrating with an external 3D or VR
4476 engines, such as OpenXR.
4477
4478 \note The configuration is ignored when adopting existing graphics devices
4479 via setGraphicsDevice() since the scene graph is then not in control of the
4480 actual construction of those objects.
4481
4482 QQuickGraphicsConfiguration instances are implicitly shared, copyable, and
4483 can be passed by value.
4484
4485 \warning Setting a QQuickGraphicsConfiguration on a QQuickWindow must
4486 happen early enough, before the scene graph is initialized for the first
4487 time for that window. With on-screen windows this means the call must be
4488 done before invoking show() on the QQuickWindow or QQuickView. With
4489 QQuickRenderControl the configuration must be finalized before calling
4490 \l{QQuickRenderControl::initialize()}{initialize()}.
4491
4492 \since 6.0
4493 */
4494void QQuickWindow::setGraphicsConfiguration(const QQuickGraphicsConfiguration &config)
4495{
4496 Q_D(QQuickWindow);
4497 d->graphicsConfig = config;
4498}
4499
4500/*!
4501 \return the QQuickGraphicsConfiguration passed to
4502 setGraphicsConfiguration(), or a default constructed one otherwise.
4503
4504 \since 6.0
4505
4506 \sa setGraphicsConfiguration()
4507 */
4508QQuickGraphicsConfiguration QQuickWindow::graphicsConfiguration() const
4509{
4510 Q_D(const QQuickWindow);
4511 return d->graphicsConfig;
4512}
4513
4514/*!
4515 Creates a text node. When the scenegraph is not initialized, the return value is null.
4516
4517 \since 6.7
4518 \sa QSGTextNode
4519 */
4520QSGTextNode *QQuickWindow::createTextNode() const
4521{
4522 Q_D(const QQuickWindow);
4523 return isSceneGraphInitialized() ? d->context->sceneGraphContext()->createTextNode(d->context) : nullptr;
4524}
4525
4526/*!
4527 Creates a simple rectangle node. When the scenegraph is not initialized, the return value is null.
4528
4529 This is cross-backend alternative to constructing a QSGSimpleRectNode directly.
4530
4531 \since 5.8
4532 \sa QSGRectangleNode
4533 */
4534QSGRectangleNode *QQuickWindow::createRectangleNode() const
4535{
4536 Q_D(const QQuickWindow);
4537 return isSceneGraphInitialized() ? d->context->sceneGraphContext()->createRectangleNode() : nullptr;
4538}
4539
4540/*!
4541 Creates a simple image node. When the scenegraph is not initialized, the return value is null.
4542
4543 This is cross-backend alternative to constructing a QSGSimpleTextureNode directly.
4544
4545 \since 5.8
4546 \sa QSGImageNode
4547 */
4548QSGImageNode *QQuickWindow::createImageNode() const
4549{
4550 Q_D(const QQuickWindow);
4551 return isSceneGraphInitialized() ? d->context->sceneGraphContext()->createImageNode() : nullptr;
4552}
4553
4554/*!
4555 Creates a nine patch node. When the scenegraph is not initialized, the return value is null.
4556
4557 \since 5.8
4558 */
4559QSGNinePatchNode *QQuickWindow::createNinePatchNode() const
4560{
4561 Q_D(const QQuickWindow);
4562 return isSceneGraphInitialized() ? d->context->sceneGraphContext()->createNinePatchNode() : nullptr;
4563}
4564
4565/*!
4566 \since 5.10
4567
4568 Returns the render type of text-like elements in Qt Quick.
4569 The default is QQuickWindow::QtTextRendering.
4570
4571 \sa setTextRenderType()
4572*/
4573QQuickWindow::TextRenderType QQuickWindow::textRenderType()
4574{
4575 return QQuickWindowPrivate::textRenderType;
4576}
4577
4578/*!
4579 \since 5.10
4580
4581 Sets the default render type of text-like elements in Qt Quick to \a renderType.
4582
4583 \note setting the render type will only affect elements created afterwards;
4584 the render type of existing elements will not be modified.
4585
4586 \sa textRenderType()
4587*/
4588void QQuickWindow::setTextRenderType(QQuickWindow::TextRenderType renderType)
4589{
4590 QQuickWindowPrivate::textRenderType = renderType;
4591}
4592
4593
4594/*!
4595 \since 6.0
4596 \qmlproperty Palette Window::palette
4597
4598 This property holds the palette currently set for the window.
4599
4600 The default palette depends on the system environment. QGuiApplication maintains a system/theme
4601 palette which serves as a default for all application windows. You can also set the default palette
4602 for windows by passing a custom palette to QGuiApplication::setPalette(), before loading any QML.
4603
4604 Window propagates explicit palette properties to child items and controls,
4605 overriding any system defaults for that property.
4606
4607 \snippet qml/windowPalette.qml entire
4608
4609 \sa Item::palette, Popup::palette, ColorGroup, SystemPalette
4610 //! internal \sa QQuickAbstractPaletteProvider, QQuickPalette
4611*/
4612
4613#ifndef QT_NO_DEBUG_STREAM
4614QDebug operator<<(QDebug debug, const QQuickWindow *win)
4615{
4616 QDebugStateSaver saver(debug);
4617 debug.nospace();
4618 if (!win) {
4619 debug << "QQuickWindow(nullptr)";
4620 return debug;
4621 }
4622
4623 debug << win->metaObject()->className() << '(' << static_cast<const void *>(win);
4624 if (win->isActive())
4625 debug << " active";
4626 if (win->isExposed())
4627 debug << " exposed";
4628 debug << ", visibility=" << win->visibility() << ", flags=" << win->flags();
4629 if (!win->title().isEmpty())
4630 debug << ", title=" << win->title();
4631 if (!win->objectName().isEmpty())
4632 debug << ", name=" << win->objectName();
4633 if (win->parent())
4634 debug << ", parent=" << static_cast<const void *>(win->parent());
4635 if (win->transientParent())
4636 debug << ", transientParent=" << static_cast<const void *>(win->transientParent());
4637 debug << ", geometry=";
4638 QtDebugUtils::formatQRect(debug, win->geometry());
4639 debug << ')';
4640 return debug;
4641}
4642#endif
4643
4644QT_END_NAMESPACE
4645
4646#include "qquickwindow.moc"
4647#include "moc_qquickwindow_p.cpp"
4648#include "moc_qquickwindow.cpp"
QT_BEGIN_NAMESPACE Q_STATIC_LOGGING_CATEGORY(lcSynthesizedIterableAccess, "qt.iterable.synthesized", QtWarningMsg)
static void updatePixelRatioHelper(QQuickItem *item, float pixelRatio)
void forcePolishHelper(QQuickItem *item)
void forceUpdate(QQuickItem *item)
QDebug operator<<(QDebug debug, const QQuickWindow *win)
static QSGNode * qquickitem_before_paintNode(QQuickItemPrivate *d)
static QSGNode * fetchNextNode(QQuickItemPrivate *itemPriv, int &ii, bool &returnedPaintNode)
const QList< QQuickItem * > & itemsToPolish
bool check(QQuickItem *item, int itemsRemainingBeforeUpdatePolish)
PolishLoopDetector(const QList< QQuickItem * > &itemsToPolish)
QRhiRenderPassDescriptor * rpDesc
QRhiRenderBuffer * renderBuffer