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