Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
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
4#include "qquickwindow.h"
5#include "qquickwindow_p.h"
6
7#include "qquickitem.h"
8#include "qquickitem_p.h"
9#include "qquickevents_p_p.h"
12
13#include <QtQuick/private/qsgrenderer_p.h>
14#include <QtQuick/private/qsgplaintexture_p.h>
15#include <QtQuick/private/qquickpointerhandler_p.h>
16#include <QtQuick/private/qquickpointerhandler_p_p.h>
17#include <private/qsgrenderloop_p.h>
18#include <private/qsgrhisupport_p.h>
19#include <private/qquickrendercontrol_p.h>
20#include <private/qquickanimatorcontroller_p.h>
21#include <private/qquickprofiler_p.h>
22#include <private/qquicktextinterface_p.h>
23
24#include <private/qguiapplication_p.h>
25
26#include <private/qabstractanimation_p.h>
27
28#include <QtGui/qpainter.h>
29#include <QtGui/qevent.h>
30#include <QtGui/qmatrix4x4.h>
31#include <QtGui/private/qevent_p.h>
32#include <QtGui/private/qpointingdevice_p.h>
33#include <QtCore/qvarlengtharray.h>
34#include <QtCore/qabstractanimation.h>
35#include <QtCore/QLibraryInfo>
36#include <QtCore/QRunnable>
37#include <QtQml/qqmlincubator.h>
38#include <QtQml/qqmlinfo.h>
39#include <QtQml/private/qqmlmetatype_p.h>
40
41#include <QtQuick/private/qquickpixmap_p.h>
42
43#include <private/qqmldebugserviceinterfaces_p.h>
44#include <private/qqmldebugconnector_p.h>
45#include <private/qsgdefaultrendercontext_p.h>
46#if QT_CONFIG(opengl)
47#include <private/qopengl_p.h>
48#include <QOpenGLContext>
49#endif
50#ifndef QT_NO_DEBUG_STREAM
51#include <private/qdebug_p.h>
52#endif
53#include <QtCore/qpointer.h>
54
55#include <rhi/qrhi.h>
56
57#include <utility>
58#include <mutex>
59
61
66Q_LOGGING_CATEGORY(lcDirty, "qt.quick.dirty")
67Q_LOGGING_CATEGORY(lcQuickWindow, "qt.quick.window")
68Q_LOGGING_CATEGORY(lcTransient, "qt.quick.window.transient")
69
70bool QQuickWindowPrivate::defaultAlphaBuffer = false;
71
72#if defined(QT_QUICK_DEFAULT_TEXT_RENDER_TYPE)
73QQuickWindow::TextRenderType QQuickWindowPrivate::textRenderType = QQuickWindow::QT_QUICK_DEFAULT_TEXT_RENDER_TYPE;
74#else
75QQuickWindow::TextRenderType QQuickWindowPrivate::textRenderType = QQuickWindow::QtTextRendering;
76#endif
77
79{
81
82public:
84 : m_renderLoop(loop), m_timer(0)
85 {
86 // Allow incubation for 1/3 of a frame.
87 m_incubation_time = qMax(1, int(1000 / QGuiApplication::primaryScreen()->refreshRate()) / 3);
88
89 QAnimationDriver *animationDriver = m_renderLoop->animationDriver();
90 if (animationDriver) {
93 }
94 }
95
96protected:
97 void timerEvent(QTimerEvent *) override
98 {
99 killTimer(m_timer);
100 m_timer = 0;
101 incubate();
102 }
103
105 if (m_timer == 0) {
106 // Wait for a while before processing the next batch. Using a
107 // timer to avoid starvation of system events.
108 m_timer = startTimer(m_incubation_time);
109 }
110 }
111
112public slots:
113 void incubate() {
114 if (m_renderLoop && incubatingObjectCount()) {
115 if (m_renderLoop->interleaveIncubation()) {
116 incubateFor(m_incubation_time);
117 } else {
118 incubateFor(m_incubation_time * 2);
121 }
122 }
123 }
124
126
127protected:
129 {
130 if (count && m_renderLoop && !m_renderLoop->interleaveIncubation())
132 }
133
134private:
135 QPointer<QSGRenderLoop> m_renderLoop;
136 int m_incubation_time;
137 int m_timer;
138};
139
140#if QT_CONFIG(accessibility)
145QAccessibleInterface *QQuickWindow::accessibleRoot() const
146{
147 return QAccessible::queryAccessibleInterface(const_cast<QQuickWindow*>(this));
148}
149#endif
150
151
152/*
153Focus behavior
154==============
155
156Prior to being added to a valid window items can set and clear focus with no
157effect. Only once items are added to a window (by way of having a parent set that
158already belongs to a window) do the focus rules apply. Focus goes back to
159having no effect if an item is removed from a window.
160
161When an item is moved into a new focus scope (either being added to a window
162for the first time, or having its parent changed), if the focus scope already has
163a scope focused item that takes precedence over the item being added. Otherwise,
164the focus of the added tree is used. In the case of a tree of items being
165added to a window for the first time, which may have a conflicted focus state (two
166or more items in one scope having focus set), the same rule is applied item by item -
167thus the first item that has focus will get it (assuming the scope doesn't already
168have a scope focused item), and the other items will have their focus cleared.
169*/
170
172{
173 // child items with ItemObservesViewport can treat the window's content item
174 // as the ultimate viewport: avoid populating SG nodes that fall outside
176}
177
180{
181 Q_D(QQuickWindow);
182 if (d->windowManager)
183 d->windowManager->exposureChanged(this);
184}
185
188{
189 Q_D(QQuickWindow);
190 if (d->contentItem)
191 d->contentItem->setSize(ev->size());
192 if (d->windowManager)
193 d->windowManager->resize(this);
194}
195
198{
199 Q_D(QQuickWindow);
200 if (d->windowManager)
201 d->windowManager->show(this);
202}
203
206{
207 Q_D(QQuickWindow);
208 if (auto da = d->deliveryAgentPrivate())
209 da->handleWindowHidden(this);
210 if (d->windowManager)
211 d->windowManager->hide(this);
212}
213
216{
218 qev.setAccepted(e->isAccepted());
219 emit closing(&qev);
220 e->setAccepted(qev.isAccepted());
221}
222
225{
226 Q_D(QQuickWindow);
227 if (d->contentItem)
228 d->contentItem->setFocus(false, ev->reason());
229}
230
233{
234 Q_D(QQuickWindow);
235 if (d->inDestructor)
236 return;
237 if (d->contentItem)
238 d->contentItem->setFocus(true, ev->reason());
239 if (auto da = d->deliveryAgentPrivate())
240 da->updateFocusItemTransform();
241}
242
243#if QT_CONFIG(im)
244static bool transformDirtyOnItemOrAncestor(const QQuickItem *item)
245{
246 while (item) {
247 if (QQuickItemPrivate::get(item)->dirtyAttributes & (
255 return true;
256 }
257 item = item->parentItem();
258 }
259 return false;
260}
261#endif
262
280{
281 PolishLoopDetector(const QVector<QQuickItem*> &itemsToPolish)
283 {
284 }
285
286 /*
287 * returns true when it detected a likely infinite loop
288 * (suggests it should abort the polish loop)
289 **/
290 bool check(QQuickItem *item, int itemsRemainingBeforeUpdatePolish)
291 {
292 if (itemsToPolish.size() > itemsRemainingBeforeUpdatePolish) {
293 // Detected potential polish loop.
295 if (numPolishLoopsInSequence >= 1000) {
296 // Start to warn about polish loop after 1000 consecutive polish loops
297 if (numPolishLoopsInSequence == 100000) {
298 // We have looped 100,000 times without actually reducing the list of items to
299 // polish, give up for now.
300 // This is not a fix, just a remedy so that the application can be somewhat
301 // responsive.
303 return true;
304 } else if (numPolishLoopsInSequence < 1005) {
305 // Show the 5 next items involved in the polish loop.
306 // (most likely they will be the same 5 items...)
307 QQuickItem *guiltyItem = itemsToPolish.last();
308 qmlWarning(item) << "possible QQuickItem::polish() loop";
309
310 auto typeAndObjectName = [](QQuickItem *item) {
312 QString objName = item->objectName();
313 if (!objName.isNull())
314 return QLatin1String("%1(%2)").arg(typeName, objName);
315 return typeName;
316 };
317
318 qmlWarning(guiltyItem) << typeAndObjectName(guiltyItem)
319 << " called polish() inside updatePolish() of " << typeAndObjectName(item);
320
321 if (numPolishLoopsInSequence == 1004)
322 // Enough warnings. Reset counter in order to speed things up and re-detect
323 // more loops
325 }
326 }
327 } else {
329 }
330 return false;
331 }
332 const QVector<QQuickItem*> &itemsToPolish; // Just a ref to the one in polishItems()
334};
335
337{
338 if (QQuickItemPrivate::get(item)->dirtyAttributes
340 return item;
341 }
342
343 const auto childItems = item->childItems();
344 for (const auto *childItem : childItems) {
345 if (auto *dirtyItem = firstItemWithDirtyChildrenStacking(childItem))
346 return dirtyItem;
347 }
348
349 return nullptr;
350}
351
353{
354 // An item can trigger polish on another item, or itself for that matter,
355 // during its updatePolish() call. Because of this, we cannot simply
356 // iterate through the set, we must continue pulling items out until it
357 // is empty.
358 // In the case where polish is called from updatePolish() either directly
359 // or indirectly, we use a PolishLoopDetector to determine if a warning should
360 // be printed to the user.
361
362 PolishLoopDetector polishLoopDetector(itemsToPolish);
363 while (!itemsToPolish.isEmpty()) {
364 QQuickItem *item = itemsToPolish.takeLast();
366 itemPrivate->polishScheduled = false;
367 const int itemsRemaining = itemsToPolish.size();
368 itemPrivate->updatePolish();
369 item->updatePolish();
370 if (polishLoopDetector.check(item, itemsRemaining) == true)
371 break;
372 }
373
374#if QT_CONFIG(im)
375 if (QQuickItem *focusItem = q_func()->activeFocusItem()) {
376 // If the current focus item, or any of its anchestors, has changed location
377 // inside the window, we need inform IM about it. This to ensure that overlays
378 // such as selection handles will be updated.
379 const bool isActiveFocusItem = (focusItem == QGuiApplication::focusObject());
380 const bool hasImEnabled = focusItem->inputMethodQuery(Qt::ImEnabled).toBool();
381 if (isActiveFocusItem && hasImEnabled && transformDirtyOnItemOrAncestor(focusItem))
383 }
384#endif
385
387 qCDebug(lcQuickWindow) << dirtyItem << "has dirty child stacking order";
389 }
390}
391
400{
401 Q_D(QQuickWindow);
402 if (d->windowManager)
403 d->windowManager->update(this);
404 else if (d->renderControl)
405 QQuickRenderControlPrivate::get(d->renderControl)->update();
406}
407
408static void updatePixelRatioHelper(QQuickItem *item, float pixelRatio)
409{
413 }
414
415 QList <QQuickItem *> items = item->childItems();
416 for (int i = 0; i < items.size(); ++i)
417 updatePixelRatioHelper(items.at(i), pixelRatio);
418}
419
420void QQuickWindow::physicalDpiChanged()
421{
422 Q_D(QQuickWindow);
423 const qreal newPixelRatio = effectiveDevicePixelRatio();
424 if (qFuzzyCompare(newPixelRatio, d->lastReportedItemDevicePixelRatio))
425 return;
426 d->lastReportedItemDevicePixelRatio = newPixelRatio;
427 if (d->contentItem)
428 updatePixelRatioHelper(d->contentItem, newPixelRatio);
429 d->forcePolish();
430}
431
432void QQuickWindow::handleFontDatabaseChanged()
433{
434 Q_D(QQuickWindow);
435 d->pendingFontUpdate = true;
436}
437
439{
441 item->polish();
442 }
443
444 QList <QQuickItem *> items = item->childItems();
445 for (int i=0; i<items.size(); ++i)
447}
448
449void QQuickWindow::handleScreenChanged(QScreen *screen)
450{
451 Q_D(QQuickWindow);
452 Q_UNUSED(screen);
453 d->forcePolish();
454}
455
460{
461 Q_Q(QQuickWindow);
462 if (!q->screen())
463 return;
465}
466
468{
470 item->update();
472
473 QList <QQuickItem *> items = item->childItems();
474 for (int i=0; i<items.size(); ++i)
476}
477
479{
480 if (rhi) {
481 if (rt.owns)
482 delete rt.renderTarget;
483
484 delete res.texture;
485 delete res.renderBuffer;
486 delete res.rpDesc;
487 }
488
489 rt = {};
490 res = {};
491
493 implicitBuffers.reset(rhi);
494
495 if (sw.owns)
496 delete sw.paintDevice;
497
498 sw = {};
499}
500
502{
503 if (rhi) {
504 delete depthStencil;
505 delete depthStencilTexture;
506 delete multisampleTexture;
507 }
508 *this = {};
509}
510
512{
513 QQuickTextInterface *textItem = qobject_cast<QQuickTextInterface *>(item);
514 if (textItem != nullptr)
515 textItem->invalidate();
516
517 QList<QQuickItem *> children = item->childItems();
518 for (QQuickItem *child : children)
519 invalidateFontData(child);
520}
521
523{
524 // resolve() can be expensive when importing an existing native texture, so
525 // it is important to only do it when the QQuickRenderTarget was really changed.
526 if (!redirect.renderTargetDirty)
527 return;
528
529 redirect.renderTargetDirty = false;
530
532
533 if (!QQuickRenderTargetPrivate::get(&customRenderTarget)->resolve(rhi, &redirect.rt)) {
534 qWarning("Failed to set up render target redirection for QQuickWindow");
535 redirect.rt.reset(rhi);
536 }
537}
538
540{
541 // ownership not transferred
542 redirect.commandBuffer = cb;
543}
544
546{
547 Q_Q(QQuickWindow);
548
549 ensureCustomRenderTarget();
550
551 QRhiCommandBuffer *cb = nullptr;
552 if (rhi) {
553 if (redirect.commandBuffer)
554 cb = redirect.commandBuffer;
555 else
556 cb = swapchain->currentFrameCommandBuffer();
557 }
558 context->prepareSync(q->effectiveDevicePixelRatio(), cb, graphicsConfig);
559
560 animationController->beforeNodeSync();
561
562 emit q->beforeSynchronizing();
563 runAndClearJobs(&beforeSynchronizingJobs);
564
565 if (pendingFontUpdate) {
567 invalidateFontData(contentItem);
568 }
569
570 if (!renderer) {
571 forceUpdate(contentItem);
572
573 QSGRootNode *rootNode = new QSGRootNode;
574 rootNode->appendChildNode(QQuickItemPrivate::get(contentItem)->itemNode());
575 const bool useDepth = graphicsConfig.isDepthBufferEnabledFor2D();
578 renderer = context->createRenderer(renderMode);
579 renderer->setRootNode(rootNode);
580 }
581
582 updateDirtyNodes();
583
584 animationController->afterNodeSync();
585
586 renderer->setClearColor(clearColor);
587
588 renderer->setVisualizationMode(visualizationMode);
589
590 if (pendingFontUpdate) {
591 context->invalidateGlyphCaches();
592 pendingFontUpdate = false;
593 }
594
595 emit q->afterSynchronizing();
596 runAndClearJobs(&afterSynchronizingJobs);
597}
598
600{
601 QQuickWindow *w = reinterpret_cast<QQuickWindow *>(ud);
602 emit w->beforeRenderPassRecording();
603}
604
606{
607 QQuickWindow *w = reinterpret_cast<QQuickWindow *>(ud);
608 emit w->afterRenderPassRecording();
609}
610
612{
613 if (rhi) {
614 ensureCustomRenderTarget();
615 if (redirect.rt.rt.renderTarget)
616 return redirect.rt.rt.multiViewCount;
617 }
618
619 // Note that on QRhi level 0 and 1 are often used interchangeably, as both mean
620 // no-multiview. Here in Qt Quick let's always use 1 as the default
621 // (no-multiview), so that higher layers (effects, materials) do not need to
622 // handle both 0 and 1, only 1.
623 return 1;
624}
625
627{
628 if (rhi) {
629 ensureCustomRenderTarget();
630 return redirect.rt.rt.renderTarget;
631 }
632 return nullptr;
633}
634
636{
637 Q_Q(QQuickWindow);
638 if (!renderer)
639 return;
640
641 ensureCustomRenderTarget();
642
643 QSGRenderTarget sgRenderTarget;
644 if (rhi) {
648 if (redirect.rt.rt.renderTarget) {
649 rt = redirect.rt.rt.renderTarget;
650 rp = rt->renderPassDescriptor();
651 if (!rp) {
652 qWarning("Custom render target is set but no renderpass descriptor has been provided.");
653 return;
654 }
655 cb = redirect.commandBuffer;
656 if (!cb) {
657 qWarning("Custom render target is set but no command buffer has been provided.");
658 return;
659 }
660 } else {
661 if (!swapchain) {
662 qWarning("QQuickWindow: No render target (neither swapchain nor custom target was provided)");
663 return;
664 }
665 rt = swapchain->currentFrameRenderTarget();
666 rp = rpDescForSwapchain;
667 cb = swapchain->currentFrameCommandBuffer();
668 }
669 sgRenderTarget = QSGRenderTarget(rt, rp, cb);
670 sgRenderTarget.multiViewCount = multiViewCount();
671 } else {
672 sgRenderTarget = QSGRenderTarget(redirect.rt.sw.paintDevice);
673 }
674
675 context->beginNextFrame(renderer,
676 sgRenderTarget,
677 emitBeforeRenderPassRecording,
678 emitAfterRenderPassRecording,
679 q);
680
681 animationController->advance();
682 emit q->beforeRendering();
683 runAndClearJobs(&beforeRenderingJobs);
684
685 const qreal devicePixelRatio = q->effectiveDevicePixelRatio();
686 QSize pixelSize;
687 if (redirect.rt.rt.renderTarget)
688 pixelSize = redirect.rt.rt.renderTarget->pixelSize();
689 else if (redirect.rt.sw.paintDevice)
690 pixelSize = QSize(redirect.rt.sw.paintDevice->width(), redirect.rt.sw.paintDevice->height());
691 else if (rhi)
692 pixelSize = swapchain->currentPixelSize();
693 else // software or other backend
694 pixelSize = q->size() * devicePixelRatio;
695
696 renderer->setDevicePixelRatio(devicePixelRatio);
697 renderer->setDeviceRect(QRect(QPoint(0, 0), pixelSize));
698 renderer->setViewportRect(QRect(QPoint(0, 0), pixelSize));
699
700 QSGAbstractRenderer::MatrixTransformFlags matrixFlags;
701 bool flipY = rhi ? !rhi->isYUpInNDC() : false;
702 if (!customRenderTarget.isNull() && customRenderTarget.mirrorVertically())
703 flipY = !flipY;
704 if (flipY)
706
707 const QRectF rect(QPointF(0, 0), pixelSize / devicePixelRatio);
708 renderer->setProjectionMatrixToRect(rect, matrixFlags, rhi && !rhi->isYUpInNDC());
709
710 context->renderNextFrame(renderer);
711
712 emit q->afterRendering();
713 runAndClearJobs(&afterRenderingJobs);
714
715 context->endNextFrame(renderer);
716
717 if (renderer && renderer->hasVisualizationModeWithContinuousUpdate()) {
718 // For the overdraw visualizer. This update is not urgent so avoid a
719 // direct update() call, this is only here to keep the overdraw
720 // visualization box rotating even when the scene is static.
721 QCoreApplication::postEvent(q, new QEvent(QEvent::Type(FullUpdateRequest)));
722 }
723}
724
726 : contentItem(nullptr)
727 , dirtyItemList(nullptr)
728 , lastReportedItemDevicePixelRatio(0)
731 , windowManager(nullptr)
732 , renderControl(nullptr)
733 , clearColor(Qt::white)
734 , persistentGraphics(true)
735 , persistentSceneGraph(true)
736 , inDestructor(false)
737 , incubationController(nullptr)
738 , hasActiveSwapchain(false)
739 , hasRenderableSwapchain(false)
740 , swapchainJustBecameRenderable(false)
741 , updatesEnabled(true)
742{
743}
744
746{
747 inDestructor = true;
748 redirect.rt.reset(rhi);
749 if (QQmlInspectorService *service = QQmlDebugConnector::service<QQmlInspectorService>())
750 service->removeWindow(q_func());
751 deliveryAgent = nullptr;
752}
753
766
771
773{
774 Q_Q(QQuickWindow);
775 if (auto root = q->contentItem()) {
776 for (auto &&child: root->childItems()) {
778 }
779 }
780}
781
783{
784 q_ptr = c;
785
786
787 Q_Q(QQuickWindow);
788
790 contentItem->setObjectName(q->objectName());
794 contentItemPrivate->window = q;
795 contentItemPrivate->windowRefCount = 1;
796 contentItemPrivate->flags |= QQuickItem::ItemIsFocusScope;
797 contentItem->setSize(q->size());
799
800 visualizationMode = qgetenv("QSG_VISUALIZE");
801 renderControl = control;
802 if (renderControl)
804
805 if (!renderControl)
807
809
812 q,
813 &QQuickWindow::handleFontDatabaseChanged);
814
815 if (q->screen()) {
816 lastReportedItemDevicePixelRatio = q->effectiveDevicePixelRatio();
817 }
818
819 QSGContext *sg;
820 if (renderControl) {
822 sg = renderControlPriv->sg;
823 context = renderControlPriv->rc;
824 } else {
828 }
829
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
838
841 QObject::connect(context, &QSGRenderContext::invalidated, q, &QQuickWindow::cleanupSceneGraph, Qt::DirectConnection);
842
843 QObject::connect(q, &QQuickWindow::focusObjectChanged, q, &QQuickWindow::activeFocusItemChanged);
844 QObject::connect(q, &QQuickWindow::screenChanged, q, &QQuickWindow::handleScreenChanged);
845 QObject::connect(qApp, &QGuiApplication::applicationStateChanged, q, &QQuickWindow::handleApplicationStateChanged);
846 QObject::connect(q, &QQuickWindow::frameSwapped, q, &QQuickWindow::runJobsAfterSwap, Qt::DirectConnection);
847
848 if (QQmlInspectorService *service = QQmlDebugConnector::service<QQmlInspectorService>())
849 service->addWindow(q);
850}
851
852void QQuickWindow::handleApplicationStateChanged(Qt::ApplicationState state)
853{
854 Q_D(QQuickWindow);
855 if (state != Qt::ApplicationActive && d->contentItem) {
856 auto da = d->deliveryAgentPrivate();
857 Q_ASSERT(da);
858 da->handleWindowDeactivate(this);
859 }
860}
861
877
879{
880 Q_Q(QQuickWindow);
881 q->maybeUpdate();
882}
883
888QQuickItem *QQuickWindow::mouseGrabberItem() const
889{
890 Q_D(const QQuickWindow);
891 auto da = const_cast<QQuickWindowPrivate *>(d)->deliveryAgentPrivate();
892 Q_ASSERT(da);
893 // The normal use case is to call this function while an event is being delivered;
894 // but if the caller knows about the event, it should call QPointerEvent::exclusiveGrabber() instead.
895 if (auto epd = da->mousePointData())
896 return qmlobject_cast<QQuickItem *>(epd->exclusiveGrabber);
897
898 if (Q_LIKELY(d->deliveryAgentPrivate()->eventsInDelivery.isEmpty()))
899 // mousePointData() checked that already: it's one reason epd can be null
900 qCDebug(lcMouse, "mouse grabber ambiguous: no event is currently being delivered");
901 // If no event is being delivered, we can return "the mouse" grabber,
902 // but in general there could be more than one mouse, could be only a touchscreen etc.
903 // That's why this function is obsolete.
905 firstPointExclusiveGrabber());
906}
907
909{
910 Q_Q(QQuickWindow);
911
914 q->maybeUpdate();
915}
916
1143QQuickWindow::QQuickWindow(QWindow *parent)
1144 : QQuickWindow(*new QQuickWindowPrivate, parent)
1145{
1146}
1147
1148
1149
1153QQuickWindow::QQuickWindow(QQuickWindowPrivate &dd, QWindow *parent)
1154 : QWindow(dd, parent)
1155{
1156 Q_D(QQuickWindow);
1157 d->init(this);
1158}
1159
1167QQuickWindow::QQuickWindow(QQuickRenderControl *control)
1169{
1170 Q_D(QQuickWindow);
1171 d->init(this, control);
1172}
1173
1177QQuickWindow::QQuickWindow(QQuickWindowPrivate &dd, QQuickRenderControl *control)
1178 : QWindow(dd, nullptr)
1179{
1180 Q_D(QQuickWindow);
1181 d->init(this, control);
1182}
1183
1188{
1189 Q_D(QQuickWindow);
1190 d->inDestructor = true;
1191 if (d->renderControl) {
1192 QQuickRenderControlPrivate::get(d->renderControl)->windowDestroyed();
1193 } else if (d->windowManager) {
1194 d->windowManager->removeWindow(this);
1195 d->windowManager->windowDestroyed(this);
1196 }
1197
1198 delete d->incubationController; d->incubationController = nullptr;
1199 QQuickRootItem *root = d->contentItem;
1200 d->contentItem = nullptr;
1201 root->setParent(nullptr); // avoid QChildEvent delivery during deletion
1202 delete root;
1203 d->deliveryAgent = nullptr; // avoid forwarding events there during destruction
1204
1205
1206 {
1207 const std::lock_guard locker(d->renderJobMutex);
1208 qDeleteAll(std::exchange(d->beforeSynchronizingJobs, {}));
1209 qDeleteAll(std::exchange(d->afterSynchronizingJobs, {}));
1210 qDeleteAll(std::exchange(d->beforeRenderingJobs, {}));
1211 qDeleteAll(std::exchange(d->afterRenderingJobs, {}));;
1212 qDeleteAll(std::exchange(d->afterSwapJobs, {}));
1213 }
1214
1215 // It is important that the pixmap cache is cleaned up during shutdown.
1216 // Besides playing nice, this also solves a practical problem that
1217 // QQuickTextureFactory implementations in other libraries need
1218 // have their destructors loaded while they the library is still
1219 // loaded into memory.
1221}
1222
1223#if QT_CONFIG(quick_shadereffect)
1225#endif
1226
1254{
1255 Q_D(QQuickWindow);
1256 if (d->windowManager)
1257 d->windowManager->releaseResources(this);
1259#if QT_CONFIG(quick_shadereffect)
1261#endif
1262}
1263
1264
1265
1294void QQuickWindow::setPersistentGraphics(bool persistent)
1295{
1296 Q_D(QQuickWindow);
1297 d->persistentGraphics = persistent;
1298}
1299
1300
1301
1311bool QQuickWindow::isPersistentGraphics() const
1312{
1313 Q_D(const QQuickWindow);
1314 return d->persistentGraphics;
1315}
1316
1317
1318
1341void QQuickWindow::setPersistentSceneGraph(bool persistent)
1342{
1343 Q_D(QQuickWindow);
1344 d->persistentSceneGraph = persistent;
1345}
1346
1347
1348
1357bool QQuickWindow::isPersistentSceneGraph() const
1358{
1359 Q_D(const QQuickWindow);
1360 return d->persistentSceneGraph;
1361}
1362
1381{
1382 Q_D(const QQuickWindow);
1383
1384 return d->contentItem;
1385}
1386
1396{
1397 Q_D(const QQuickWindow);
1398 auto da = d->deliveryAgentPrivate();
1399 Q_ASSERT(da);
1400 return da->activeFocusItem;
1401}
1402
1408{
1409 Q_D(const QQuickWindow);
1410 auto da = d->deliveryAgentPrivate();
1411 Q_ASSERT(da);
1412 if (!d->inDestructor && da->activeFocusItem)
1413 return da->activeFocusItem;
1414 return const_cast<QQuickWindow*>(this);
1415}
1416
1430{
1431 if (pointerEvent->isEndEvent()
1435 if (pointerEvent->isSinglePointEvent()) {
1436 if (static_cast<QSinglePointEvent *>(pointerEvent)->buttons() == Qt::NoButton) {
1437 auto &firstPt = pointerEvent->point(0);
1438 pointerEvent->setExclusiveGrabber(firstPt, nullptr);
1439 pointerEvent->clearPassiveGrabbers(firstPt);
1440 }
1441 } else {
1442 for (auto &point : pointerEvent->points()) {
1443 if (point.state() == QEventPoint::State::Released) {
1444 pointerEvent->setExclusiveGrabber(point, nullptr);
1445 pointerEvent->clearPassiveGrabbers(point);
1446 }
1447 }
1448 }
1449 }
1450}
1451
1454{
1455 Q_D(QQuickWindow);
1456
1457 // bypass QWindow::event dispatching of input events: deliveryAgent takes care of it
1458 QQuickDeliveryAgent *da = d->deliveryAgent;
1459 if (event->isPointerEvent()) {
1460 /*
1461 We can't bypass the virtual functions like mousePressEvent() tabletEvent() etc.,
1462 for the sake of code that subclasses QQuickWindow and overrides them, even though
1463 we no longer need them as entry points for Qt Quick event delivery.
1464 So dispatch to them now, ahead of normal delivery, and stop them from calling
1465 back into this function if they were called from here (avoid recursion).
1466 It could also be that user code expects them to work as entry points, too;
1467 in that case, windowEventDispatch _won't_ be set, so the event comes here and
1468 we'll dispatch it further below.
1469 */
1470 if (d->windowEventDispatch)
1471 return false;
1472 {
1473 const bool wasAccepted = event->isAccepted();
1474 QBoolBlocker windowEventDispatchGuard(d->windowEventDispatch, true);
1475 qCDebug(lcPtr) << "dispatching to window functions in case of override" << event;
1477 if (event->isAccepted() && !wasAccepted)
1478 return true;
1479 }
1480 /*
1481 QQuickWindow does not override touchEvent(). If the application has a subclass
1482 of QQuickWindow which allows the event to remain accepted, it means they want
1483 to stop propagation here, so return early (below). But otherwise we will call
1484 QWindow::touchEvent(), which will ignore(); in that case, we need to continue
1485 with the usual delivery below, so we need to undo the ignore().
1486 */
1487 auto pe = static_cast<QPointerEvent *>(event);
1489 event->accept();
1490 // end of dispatch to user-overridden virtual window functions
1491
1492 /*
1493 When delivering update and release events to existing grabbers,
1494 use the subscene delivery agent, if any. A possible scenario:
1495 1) Two touchpoints pressed on the main window: QQuickWindowPrivate::deliveryAgent delivers to QQuick3DViewport,
1496 which does picking and finds two subscenes ("root" Items mapped onto two different 3D objects) to deliver it to.
1497 2) The QTouchEvent is split up so that each subscene sees points relevant to it.
1498 3) During delivery to either subscene, an item in the subscene grabs.
1499 4) The user moves finger(s) generating a move event: the correct grabber item needs to get the update
1500 via the same subscene delivery agent from which it got the press, so that the coord transform will be done properly.
1501 5) Likewise with the touchpoint releases.
1502 With single-point events (mouse, or only one finger) it's simplified: there can only be one subscene of interest;
1503 for (pt : pe->points()) would only iterate once, so we might as well skip that logic.
1504 */
1505 if (pe->pointCount()) {
1506 const bool synthMouse = QQuickDeliveryAgentPrivate::isSynthMouse(pe);
1508 bool ret = false;
1509 // Split up the multi-point event according to the relevant QQuickDeliveryAgent that should deliver to each existing grabber
1510 // but send ungrabbed points to d->deliveryAgent()
1511 QFlatMap<QQuickDeliveryAgent*, QList<QEventPoint>> deliveryAgentsNeedingPoints;
1512 QEventPoint::States eventStates;
1513
1514 auto insert = [&](QQuickDeliveryAgent *ptda, const QEventPoint &pt) {
1515 if (pt.state() == QEventPoint::Pressed && !synthMouse)
1516 pe->clearPassiveGrabbers(pt);
1517 auto &ptList = deliveryAgentsNeedingPoints[ptda];
1518 auto idEquals = [](auto id) { return [id] (const auto &e) { return e.id() == id; }; };
1519 if (std::none_of(ptList.cbegin(), ptList.cend(), idEquals(pt.id())))
1520 ptList.append(pt);
1521 };
1522
1523 for (const auto &pt : pe->points()) {
1524 eventStates |= pt.state();
1525 auto epd = QPointingDevicePrivate::get(const_cast<QPointingDevice*>(pe->pointingDevice()))->queryPointById(pt.id());
1526 Q_ASSERT(epd);
1527 bool foundAgent = false;
1528 if (!epd->exclusiveGrabber.isNull() && !epd->exclusiveGrabberContext.isNull()) {
1529 if (auto ptda = qobject_cast<QQuickDeliveryAgent *>(epd->exclusiveGrabberContext.data())) {
1530 insert(ptda, pt);
1531 qCDebug(lcPtr) << pe->type() << "point" << pt.id() << pt.state()
1532 << "@" << pt.scenePosition() << "will be re-delivered via known grabbing agent" << ptda << "to" << epd->exclusiveGrabber.data();
1533 foundAgent = true;
1534 }
1535 }
1536 for (auto pgda : epd->passiveGrabbersContext) {
1537 if (auto ptda = qobject_cast<QQuickDeliveryAgent *>(pgda.data())) {
1538 insert(ptda, pt);
1539 qCDebug(lcPtr) << pe->type() << "point" << pt.id() << pt.state()
1540 << "@" << pt.scenePosition() << "will be re-delivered via known passive-grabbing agent" << ptda;
1541 foundAgent = true;
1542 }
1543 }
1544 // fallback: if we didn't find remembered/known grabber agent(s), expect the root DA to handle it
1545 if (!foundAgent)
1546 insert(da, pt);
1547 }
1548 for (auto daAndPoints : deliveryAgentsNeedingPoints) {
1549 if (pe->pointCount() > 1) {
1551 // if all points have the same state, set the event type accordingly
1552 QEvent::Type eventType = pe->type();
1553 switch (eventStates) {
1555 eventType = QEvent::TouchBegin;
1556 break;
1558 eventType = QEvent::TouchEnd;
1559 break;
1560 default:
1561 eventType = QEvent::TouchUpdate;
1562 break;
1563 }
1564 // Make a new touch event for the subscene, the same way QQuickItemPrivate::localizedTouchEvent() does it
1565 QMutableTouchEvent te(eventType, pe->pointingDevice(), pe->modifiers(), daAndPoints.second);
1566 te.setTimestamp(pe->timestamp());
1567 te.accept();
1568 qCDebug(lcTouch) << daAndPoints.first << "shall now receive" << &te;
1569 ret = daAndPoints.first->event(&te) || ret;
1570 } else {
1571 qCDebug(lcPtr) << daAndPoints.first << "shall now receive" << pe;
1572 ret = daAndPoints.first->event(pe) || ret;
1573 }
1574 }
1575
1576 if (ret)
1577 return true;
1578 } else if (!synthMouse) {
1579 // clear passive grabbers unless it's a system synth-mouse event
1580 // QTBUG-104890: Windows sends synth mouse events (which should be ignored) after touch events
1581 for (const auto &pt : pe->points()) {
1582 if (pt.state() == QEventPoint::Pressed)
1583 pe->clearPassiveGrabbers(pt);
1584 }
1585 }
1586 }
1587
1588 // If it has no points, it's probably a TouchCancel, and DeliveryAgent needs to handle it.
1589 // If we didn't handle it in the block above, handle it now.
1590 // TODO should we deliver to all DAs at once then, since we don't know which one should get it?
1591 // or fix QTBUG-90851 so that the event always has points?
1592 qCDebug(lcHoverTrace) << this << "some sort of event" << event;
1593 bool ret = (da && da->event(event));
1594
1595 d->clearGrabbers(pe);
1596
1597 if (ret)
1598 return true;
1599 } else if (event->isInputEvent()) {
1600 if (da && da->event(event))
1601 return true;
1602 }
1603
1604 switch (event->type()) {
1605 // a few more types that are not QInputEvents, but QQuickDeliveryAgent needs to handle them anyway
1607 case QEvent::Enter:
1608 case QEvent::Leave:
1611#if QT_CONFIG(quick_draganddrop)
1612 case QEvent::DragEnter:
1613 case QEvent::DragLeave:
1614 case QEvent::DragMove:
1615 case QEvent::Drop:
1616#endif
1617 if (d->inDestructor)
1618 return false;
1619 if (da && da->event(event))
1620 return true;
1621 break;
1624 if (d->contentItem)
1625 QCoreApplication::sendEvent(d->contentItem, event);
1626 break;
1628 if (d->windowManager)
1629 d->windowManager->handleUpdateRequest(this);
1630 break;
1632 if ((static_cast<QPlatformSurfaceEvent *>(event))->surfaceEventType() == QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed) {
1633 // Ensure that the rendering thread is notified before
1634 // the QPlatformWindow is destroyed.
1635 if (d->windowManager)
1636 d->windowManager->hide(this);
1637 }
1638 break;
1640 if (auto da = d->deliveryAgentPrivate())
1641 da->handleWindowDeactivate(this);
1642 Q_FALLTHROUGH();
1644 if (d->contentItem)
1645 QCoreApplication::sendEvent(d->contentItem, event);
1646 break;
1648 d->inheritPalette(QGuiApplication::palette());
1649 if (d->contentItem)
1650 QCoreApplication::sendEvent(d->contentItem, event);
1651 break;
1653 physicalDpiChanged();
1654 break;
1656 auto *childEvent = static_cast<QChildWindowEvent*>(event);
1657 auto *childWindow = childEvent->child();
1658 qCDebug(lcQuickWindow) << "Child window" << childWindow << "added to" << this;
1659 if (childWindow->handle()) {
1660 // The reparenting has already resulted in the native window
1661 // being added to its parent, on top of all other windows. We need
1662 // to do a synchronous re-stacking of the windows here, to avoid
1663 // leaving the window in the wrong position while waiting for the
1664 // asynchronous callback to QQuickWindow::polishItems().
1665 d->updateChildWindowStackingOrder();
1666 } else {
1667 qCDebug(lcQuickWindow) << "No platform window yet."
1668 << "Deferring child window stacking until surface creation";
1669 }
1670 break;
1671 }
1672 default:
1673 break;
1674 }
1675
1677 update();
1679 d->windowManager->handleContextCreationFailure(this);
1680
1681 if (event->isPointerEvent())
1682 return true;
1683 else
1684 return QWindow::event(event);
1685}
1686
1688{
1689 Q_Q(QQuickWindow);
1690
1691 if (!item) {
1692 qCDebug(lcQuickWindow) << "Updating child window stacking order for" << q;
1693 item = contentItem;
1694 }
1695 auto *itemPrivate = QQuickItemPrivate::get(item);
1696 const auto paintOrderChildItems = itemPrivate->paintOrderChildItems();
1697 for (auto *child : paintOrderChildItems) {
1698 if (auto *windowContainer = qobject_cast<QQuickWindowContainer*>(child)) {
1699 auto *window = windowContainer->containedWindow();
1700 if (!window) {
1701 qCDebug(lcQuickWindow) << windowContainer << "has no contained window yet";
1702 continue;
1703 }
1704 if (window->parent() != q) {
1705 qCDebug(lcQuickWindow) << window << "is not yet child of this window";
1706 continue;
1707 }
1708 qCDebug(lcQuickWindow) << "Raising" << window << "owned by" << windowContainer;
1709 window->raise();
1710 }
1711
1713 }
1714}
1715
1718{
1719 Q_D(QQuickWindow);
1720 if (d->windowEventDispatch)
1721 return;
1722 auto da = d->deliveryAgentPrivate();
1723 Q_ASSERT(da);
1724 da->deliverKeyEvent(e);
1725}
1726
1729{
1730 Q_D(QQuickWindow);
1731 if (d->windowEventDispatch)
1732 return;
1733 auto da = d->deliveryAgentPrivate();
1734 Q_ASSERT(da);
1735 da->deliverKeyEvent(e);
1736}
1737
1738#if QT_CONFIG(wheelevent)
1740void QQuickWindow::wheelEvent(QWheelEvent *event)
1741{
1742 Q_D(QQuickWindow);
1743 if (d->windowEventDispatch)
1744 return;
1745 auto da = d->deliveryAgentPrivate();
1746 Q_ASSERT(da);
1747 da->deliverSinglePointEventUntilAccepted(event);
1748}
1749#endif // wheelevent
1750
1751#if QT_CONFIG(tabletevent)
1753void QQuickWindow::tabletEvent(QTabletEvent *event)
1754{
1755 Q_D(QQuickWindow);
1756 if (d->windowEventDispatch)
1757 return;
1758 auto da = d->deliveryAgentPrivate();
1759 Q_ASSERT(da);
1760 da->deliverPointerEvent(event);
1761}
1762#endif // tabletevent
1763
1766{
1767 Q_D(QQuickWindow);
1768 if (d->windowEventDispatch)
1769 return;
1770 auto da = d->deliveryAgentPrivate();
1771 Q_ASSERT(da);
1772 da->handleMouseEvent(event);
1773}
1776{
1777 Q_D(QQuickWindow);
1778 if (d->windowEventDispatch)
1779 return;
1780 auto da = d->deliveryAgentPrivate();
1781 Q_ASSERT(da);
1782 da->handleMouseEvent(event);
1783}
1786{
1787 Q_D(QQuickWindow);
1788 if (d->windowEventDispatch)
1789 return;
1790 auto da = d->deliveryAgentPrivate();
1791 Q_ASSERT(da);
1792 da->handleMouseEvent(event);
1793}
1796{
1797 Q_D(QQuickWindow);
1798 if (d->windowEventDispatch)
1799 return;
1800 auto da = d->deliveryAgentPrivate();
1801 Q_ASSERT(da);
1802 da->handleMouseEvent(event);
1803}
1804
1805#if QT_CONFIG(cursor)
1806void QQuickWindowPrivate::updateCursor(const QPointF &scenePos, QQuickItem *rootItem)
1807{
1808 Q_Q(QQuickWindow);
1809 if (!rootItem)
1811 auto cursorItemAndHandler = findCursorItemAndHandler(rootItem, scenePos);
1812 if (cursorItem != cursorItemAndHandler.first || cursorHandler != cursorItemAndHandler.second ||
1813 (cursorItemAndHandler.second && QQuickPointerHandlerPrivate::get(cursorItemAndHandler.second)->cursorDirty)) {
1815 QWindow *window = renderWindow ? renderWindow : q;
1816 cursorItem = cursorItemAndHandler.first;
1817 cursorHandler = cursorItemAndHandler.second;
1818 if (cursorHandler)
1819 QQuickPointerHandlerPrivate::get(cursorItemAndHandler.second)->cursorDirty = false;
1820 if (cursorItem) {
1821 const auto cursor = QQuickItemPrivate::get(cursorItem)->effectiveCursor(cursorHandler);
1822 qCDebug(lcHoverTrace) << "setting cursor" << cursor << "from" << cursorHandler << "or" << cursorItem;
1823 window->setCursor(cursor);
1824 } else {
1825 qCDebug(lcHoverTrace) << "unsetting cursor";
1826 window->unsetCursor();
1827 }
1828 }
1829}
1830
1831QPair<QQuickItem*, QQuickPointerHandler*> QQuickWindowPrivate::findCursorItemAndHandler(QQuickItem *item, const QPointF &scenePos) const
1832{
1834 if (itemPrivate->flags & QQuickItem::ItemClipsChildrenToShape) {
1835 QPointF p = item->mapFromScene(scenePos);
1836 if (!item->contains(p))
1837 return {nullptr, nullptr};
1838 }
1839
1840 if (itemPrivate->subtreeCursorEnabled) {
1841 QList<QQuickItem *> children = itemPrivate->paintOrderChildItems();
1842 for (int ii = children.size() - 1; ii >= 0; --ii) {
1843 QQuickItem *child = children.at(ii);
1844 if (!child->isVisible() || !child->isEnabled() || QQuickItemPrivate::get(child)->culled)
1845 continue;
1846 auto ret = findCursorItemAndHandler(child, scenePos);
1847 if (ret.first)
1848 return ret;
1849 }
1850 if (itemPrivate->hasCursorHandler) {
1851 if (auto handler = itemPrivate->effectiveCursorHandler()) {
1852 if (handler->parentContains(scenePos))
1853 return {item, handler};
1854 }
1855 }
1856 if (itemPrivate->hasCursor) {
1857 QPointF p = item->mapFromScene(scenePos);
1858 if (item->contains(p))
1859 return {item, nullptr};
1860 }
1861 }
1862
1863 return {nullptr, nullptr};
1864}
1865#endif
1866
1868{
1869 if (auto da = deliveryAgentPrivate())
1870 da->clearFocusObject();
1871}
1872
1874{
1875 if (!contentItem)
1876 return;
1877
1878 QQuickItem *newFocusItem = nullptr;
1879 switch (target) {
1880 case FocusTarget::First:
1881 case FocusTarget::Last: {
1882 const bool forward = (target == FocusTarget::First);
1884 if (newFocusItem) {
1885 const auto *itemPriv = QQuickItemPrivate::get(newFocusItem);
1886 if (itemPriv->subFocusItem && itemPriv->flags & QQuickItem::ItemIsFocusScope)
1887 clearFocusInScope(newFocusItem, itemPriv->subFocusItem, reason);
1888 }
1889 break;
1890 }
1891 case FocusTarget::Next:
1892 case FocusTarget::Prev: {
1893 const auto da = deliveryAgentPrivate();
1894 Q_ASSERT(da);
1895 QQuickItem *focusItem = da->focusTargetItem() ? da->focusTargetItem() : contentItem;
1896 bool forward = (target == FocusTarget::Next);
1897 newFocusItem = QQuickItemPrivate::nextPrevItemInTabFocusChain(focusItem, forward);
1898 break;
1899 }
1900 default:
1901 break;
1902 }
1903
1904 if (newFocusItem)
1905 newFocusItem->forceActiveFocus(reason);
1906}
1907
1932void QQuickWindowPrivate::data_append(QQmlListProperty<QObject> *property, QObject *o)
1933{
1934 if (!o)
1935 return;
1936 QQuickWindow *that = static_cast<QQuickWindow *>(property->object);
1937 QQmlListProperty<QObject> itemProperty = QQuickItemPrivate::get(that->contentItem())->data();
1938 itemProperty.append(&itemProperty, o);
1939}
1940
1942{
1943 QQuickWindow *win = static_cast<QQuickWindow*>(property->object);
1944 if (!win || !win->contentItem() || !QQuickItemPrivate::get(win->contentItem())->data().count)
1945 return 0;
1946 QQmlListProperty<QObject> itemProperty = QQuickItemPrivate::get(win->contentItem())->data();
1947 return itemProperty.count(&itemProperty);
1948}
1949
1951{
1952 QQuickWindow *win = static_cast<QQuickWindow*>(property->object);
1953 QQmlListProperty<QObject> itemProperty = QQuickItemPrivate::get(win->contentItem())->data();
1954 return itemProperty.at(&itemProperty, i);
1955}
1956
1957void QQuickWindowPrivate::data_clear(QQmlListProperty<QObject> *property)
1958{
1959 QQuickWindow *win = static_cast<QQuickWindow*>(property->object);
1960 QQmlListProperty<QObject> itemProperty = QQuickItemPrivate::get(win->contentItem())->data();
1961 itemProperty.clear(&itemProperty);
1962}
1963
1965{
1966 QQuickWindow *win = static_cast<QQuickWindow*>(property->object);
1967 QQmlListProperty<QObject> itemProperty = QQuickItemPrivate::get(win->contentItem())->data();
1968 itemProperty.replace(&itemProperty, i, o);
1969}
1970
1971void QQuickWindowPrivate::data_removeLast(QQmlListProperty<QObject> *property)
1972{
1973 QQuickWindow *win = static_cast<QQuickWindow*>(property->object);
1974 QQmlListProperty<QObject> itemProperty = QQuickItemPrivate::get(win->contentItem())->data();
1975 itemProperty.removeLast(&itemProperty);
1976}
1977
1979{
1980 Q_Q(const QQuickWindow);
1981 return ((q->isExposed() && q->isVisible())) && q->geometry().isValid();
1982}
1983
1985 QString *translatedMessage,
1986 QString *untranslatedMessage)
1987{
1988 const char msg[] = QT_TRANSLATE_NOOP("QQuickWindow",
1989 "Failed to initialize graphics backend for %1.");
1990 *translatedMessage = QQuickWindow::tr(msg).arg(backendName);
1991 *untranslatedMessage = QString::fromLatin1(msg).arg(backendName);
1992}
1993
1995{
1996 qDeleteAll(std::exchange(cleanupNodeList, {}));
1997}
1998
2000{
2002 if (p->itemNodeInstance) {
2003 delete p->itemNodeInstance;
2004 p->itemNodeInstance = nullptr;
2005
2006 if (p->extra.isAllocated()) {
2007 p->extra->opacityNode = nullptr;
2008 p->extra->clipNode = nullptr;
2009 p->extra->rootNode = nullptr;
2010 }
2011
2012 p->paintNode = nullptr;
2013
2015 }
2016
2017 // Qt 7: Make invalidateSceneGraph a virtual member of QQuickItem
2018 if (p->flags & QQuickItem::ItemHasContents) {
2019 const QMetaObject *mo = item->metaObject();
2020 int index = mo->indexOfSlot("invalidateSceneGraph()");
2021 if (index >= 0) {
2022 const QMetaMethod &method = mo->method(index);
2023 // Skip functions named invalidateSceneGraph() in QML items.
2024 if (strstr(method.enclosingMetaObject()->className(), "_QML_") == nullptr)
2026 }
2027 }
2028
2029 for (int ii = 0; ii < p->childItems.size(); ++ii)
2030 cleanupNodesOnShutdown(p->childItems.at(ii));
2031}
2032
2033// This must be called from the render thread, with the main thread frozen
2044
2046{
2047 qCDebug(lcDirty) << "QQuickWindowPrivate::updateDirtyNodes():";
2048
2049 cleanupNodes();
2050
2051 QQuickItem *updateList = dirtyItemList;
2052 dirtyItemList = nullptr;
2053 if (updateList) QQuickItemPrivate::get(updateList)->prevDirtyItem = &updateList;
2054
2055 while (updateList) {
2056 QQuickItem *item = updateList;
2058 itemPriv->removeFromDirtyList();
2059
2060 qCDebug(lcDirty) << " QSGNode:" << item << qPrintable(itemPriv->dirtyToString());
2062 }
2063}
2064
2066{
2067 const QList<QQuickItem *> childItems = d->paintOrderChildItems();
2068 QQuickItem *before = nullptr;
2069 for (int i=0; i<childItems.size(); ++i) {
2070 QQuickItemPrivate *dd = QQuickItemPrivate::get(childItems.at(i));
2071 // Perform the same check as the in fetchNextNode below.
2072 if (dd->z() < 0 && (dd->explicitVisible || (dd->extra.isAllocated() && dd->extra->effectRefCount)))
2073 before = childItems.at(i);
2074 else
2075 break;
2076 }
2077 return Q_UNLIKELY(before) ? QQuickItemPrivate::get(before)->itemNode() : nullptr;
2078}
2079
2080static QSGNode *fetchNextNode(QQuickItemPrivate *itemPriv, int &ii, bool &returnedPaintNode)
2081{
2082 QList<QQuickItem *> orderedChildren = itemPriv->paintOrderChildItems();
2083
2084 for (; ii < orderedChildren.size() && orderedChildren.at(ii)->z() < 0; ++ii) {
2085 QQuickItemPrivate *childPrivate = QQuickItemPrivate::get(orderedChildren.at(ii));
2086 if (!childPrivate->explicitVisible &&
2087 (!childPrivate->extra.isAllocated() || !childPrivate->extra->effectRefCount))
2088 continue;
2089
2090 ii++;
2091 return childPrivate->itemNode();
2092 }
2093
2094 if (itemPriv->paintNode && !returnedPaintNode) {
2095 returnedPaintNode = true;
2096 return itemPriv->paintNode;
2097 }
2098
2099 for (; ii < orderedChildren.size(); ++ii) {
2100 QQuickItemPrivate *childPrivate = QQuickItemPrivate::get(orderedChildren.at(ii));
2101 if (!childPrivate->explicitVisible &&
2102 (!childPrivate->extra.isAllocated() || !childPrivate->extra->effectRefCount))
2103 continue;
2104
2105 ii++;
2106 return childPrivate->itemNode();
2107 }
2108
2109 return nullptr;
2110}
2111
2113{
2115 quint32 dirty = itemPriv->dirtyAttributes;
2116 itemPriv->dirtyAttributes = 0;
2117
2119 (dirty & QQuickItemPrivate::Size && itemPriv->origin() != QQuickItem::TopLeft &&
2120 (itemPriv->scale() != 1. || itemPriv->rotation() != 0.))) {
2121
2123
2124 if (itemPriv->x != 0. || itemPriv->y != 0.)
2125 matrix.translate(itemPriv->x, itemPriv->y);
2126
2127 for (int ii = itemPriv->transforms.size() - 1; ii >= 0; --ii)
2128 itemPriv->transforms.at(ii)->applyTo(&matrix);
2129
2130 if (itemPriv->scale() != 1. || itemPriv->rotation() != 0.) {
2131 QPointF origin = item->transformOriginPoint();
2132 matrix.translate(origin.x(), origin.y());
2133 if (itemPriv->scale() != 1.)
2134 matrix.scale(itemPriv->scale(), itemPriv->scale());
2135 if (itemPriv->rotation() != 0.)
2136 matrix.rotate(itemPriv->rotation(), 0, 0, 1);
2137 matrix.translate(-origin.x(), -origin.y());
2138 }
2139
2140 itemPriv->itemNode()->setMatrix(matrix);
2141 }
2142
2143 const bool clipEffectivelyChanged = dirty & (QQuickItemPrivate::Clip | QQuickItemPrivate::Window);
2144 if (clipEffectivelyChanged) {
2145 QSGNode *parent = itemPriv->opacityNode() ? (QSGNode *)itemPriv->opacityNode()
2146 : (QSGNode *)itemPriv->itemNode();
2147 QSGNode *child = itemPriv->rootNode();
2148
2149 if (bool initializeClipNode = item->clip() && itemPriv->clipNode() == nullptr;
2150 initializeClipNode) {
2151 QQuickDefaultClipNode *clip = new QQuickDefaultClipNode(item->clipRect());
2152 itemPriv->extra.value().clipNode = clip;
2153 clip->update();
2154
2155 if (!child) {
2156 parent->reparentChildNodesTo(clip);
2157 parent->appendChildNode(clip);
2158 } else {
2159 parent->removeChildNode(child);
2160 clip->appendChildNode(child);
2161 parent->appendChildNode(clip);
2162 }
2163
2164 } else if (bool updateClipNode = item->clip() && itemPriv->clipNode() != nullptr;
2165 updateClipNode) {
2166 QQuickDefaultClipNode *clip = itemPriv->clipNode();
2167 clip->setClipRect(item->clipRect());
2168 clip->update();
2169 } else if (bool removeClipNode = !item->clip() && itemPriv->clipNode() != nullptr;
2170 removeClipNode) {
2171 QQuickDefaultClipNode *clip = itemPriv->clipNode();
2172 parent->removeChildNode(clip);
2173 if (child) {
2174 clip->removeChildNode(child);
2175 parent->appendChildNode(child);
2176 } else {
2178 }
2179
2180 delete itemPriv->clipNode();
2181 itemPriv->extra->clipNode = nullptr;
2182 }
2183 }
2184
2185 const int effectRefCount = itemPriv->extra.isAllocated() ? itemPriv->extra->effectRefCount : 0;
2186 const bool effectRefEffectivelyChanged =
2188 && ((effectRefCount == 0) != (itemPriv->rootNode() == nullptr));
2189 if (effectRefEffectivelyChanged) {
2191 itemPriv->childContainerNode()->removeAllChildNodes();
2192
2193 QSGNode *parent = itemPriv->clipNode();
2194 if (!parent)
2195 parent = itemPriv->opacityNode();
2196 if (!parent)
2197 parent = itemPriv->itemNode();
2198
2199 if (itemPriv->extra.isAllocated() && itemPriv->extra->effectRefCount) {
2200 Q_ASSERT(itemPriv->rootNode() == nullptr);
2201 QSGRootNode *root = new QSGRootNode();
2202 itemPriv->extra->rootNode = root;
2203 parent->reparentChildNodesTo(root);
2204 parent->appendChildNode(root);
2205 } else {
2206 Q_ASSERT(itemPriv->rootNode() != nullptr);
2207 QSGRootNode *root = itemPriv->rootNode();
2208 parent->removeChildNode(root);
2210 delete itemPriv->rootNode();
2211 itemPriv->extra->rootNode = nullptr;
2212 }
2213 }
2214
2216 int ii = 0;
2217 bool fetchedPaintNode = false;
2218 QList<QQuickItem *> orderedChildren = itemPriv->paintOrderChildItems();
2219 int desiredNodesSize = orderedChildren.size() + (itemPriv->paintNode ? 1 : 0);
2220
2221 // now start making current state match the promised land of
2222 // desiredNodes. in the case of our current state matching desiredNodes
2223 // (though why would we get ChildrenUpdateMask with no changes?) then we
2224 // should make no changes at all.
2225
2226 // how many nodes did we process, when examining changes
2227 int desiredNodesProcessed = 0;
2228
2229 // currentNode is how far, in our present tree, we have processed. we
2230 // make use of this later on to trim the current child list if the
2231 // desired list is shorter.
2232 QSGNode *groupNode = itemPriv->childContainerNode();
2233 QSGNode *currentNode = groupNode->firstChild();
2234 QSGNode *desiredNode = nullptr;
2235
2236 while (currentNode && (desiredNode = fetchNextNode(itemPriv, ii, fetchedPaintNode))) {
2237 if (currentNode != desiredNode) {
2238 // uh oh... reality and our utopic paradise are diverging!
2239 // we need to reconcile this...
2240 if (currentNode->nextSibling() == desiredNode) {
2241 // nice and simple: a node was removed, and the next in line is correct.
2242 groupNode->removeChildNode(currentNode);
2243 } else {
2244 // a node needs to be added..
2245 // remove it from any pre-existing parent, and push it before currentNode,
2246 // so it's in the correct place...
2247 if (desiredNode->parent()) {
2248 desiredNode->parent()->removeChildNode(desiredNode);
2249 }
2250 groupNode->insertChildNodeBefore(desiredNode, currentNode);
2251 }
2252
2253 // continue iteration at the correct point, now desiredNode is in place...
2254 currentNode = desiredNode;
2255 }
2256
2257 currentNode = currentNode->nextSibling();
2258 desiredNodesProcessed++;
2259 }
2260
2261 // if we didn't process as many nodes as in the new list, then we have
2262 // more nodes at the end of desiredNodes to append to our list.
2263 // this will be the case when adding new nodes, for instance.
2264 if (desiredNodesProcessed < desiredNodesSize) {
2265 while ((desiredNode = fetchNextNode(itemPriv, ii, fetchedPaintNode))) {
2266 if (desiredNode->parent())
2267 desiredNode->parent()->removeChildNode(desiredNode);
2268 groupNode->appendChildNode(desiredNode);
2269 }
2270 } else if (currentNode) {
2271 // on the other hand, if we processed less than our current node
2272 // tree, then nodes have been _removed_ from the scene, and we need
2273 // to take care of that here.
2274 while (currentNode) {
2275 QSGNode *node = currentNode->nextSibling();
2276 groupNode->removeChildNode(currentNode);
2277 currentNode = node;
2278 }
2279 }
2280 }
2281
2282 if ((dirty & QQuickItemPrivate::Size) && itemPriv->clipNode()) {
2283 itemPriv->clipNode()->setRect(item->clipRect());
2284 itemPriv->clipNode()->update();
2285 }
2286
2289 {
2290 qreal opacity = itemPriv->explicitVisible && (!itemPriv->extra.isAllocated() || itemPriv->extra->hideRefCount == 0)
2291 ? itemPriv->opacity() : qreal(0);
2292
2293 if (opacity != 1 && !itemPriv->opacityNode()) {
2294 QSGOpacityNode *node = new QSGOpacityNode;
2295 itemPriv->extra.value().opacityNode = node;
2296
2297 QSGNode *parent = itemPriv->itemNode();
2298 QSGNode *child = itemPriv->clipNode();
2299 if (!child)
2300 child = itemPriv->rootNode();
2301
2302 if (child) {
2303 parent->removeChildNode(child);
2304 node->appendChildNode(child);
2305 parent->appendChildNode(node);
2306 } else {
2307 parent->reparentChildNodesTo(node);
2308 parent->appendChildNode(node);
2309 }
2310 }
2311 if (itemPriv->opacityNode())
2312 itemPriv->opacityNode()->setOpacity(opacity);
2313 }
2314
2316
2317 if (itemPriv->flags & QQuickItem::ItemHasContents) {
2318 updatePaintNodeData.transformNode = itemPriv->itemNode();
2319 itemPriv->paintNode = item->updatePaintNode(itemPriv->paintNode, &updatePaintNodeData);
2320
2321 Q_ASSERT(itemPriv->paintNode == nullptr ||
2322 itemPriv->paintNode->parent() == nullptr ||
2323 itemPriv->paintNode->parent() == itemPriv->childContainerNode());
2324
2325 if (itemPriv->paintNode && itemPriv->paintNode->parent() == nullptr) {
2326 QSGNode *before = qquickitem_before_paintNode(itemPriv);
2327 if (before && before->parent()) {
2328 Q_ASSERT(before->parent() == itemPriv->childContainerNode());
2329 itemPriv->childContainerNode()->insertChildNodeAfter(itemPriv->paintNode, before);
2330 } else {
2331 itemPriv->childContainerNode()->prependChildNode(itemPriv->paintNode);
2332 }
2333 }
2334 } else if (itemPriv->paintNode) {
2335 delete itemPriv->paintNode;
2336 itemPriv->paintNode = nullptr;
2337 }
2338 }
2339
2340#ifndef QT_NO_DEBUG
2341 // Check consistency.
2342
2343 QList<QSGNode *> nodes;
2344 nodes << itemPriv->itemNodeInstance
2345 << itemPriv->opacityNode()
2346 << itemPriv->clipNode()
2347 << itemPriv->rootNode()
2348 << itemPriv->paintNode;
2349 nodes.removeAll(nullptr);
2350
2351 Q_ASSERT(nodes.constFirst() == itemPriv->itemNodeInstance);
2352 for (int i=1; i<nodes.size(); ++i) {
2353 QSGNode *n = nodes.at(i);
2354 // Failing this means we messed up reparenting
2355 Q_ASSERT(n->parent() == nodes.at(i-1));
2356 // Only the paintNode and the one who is childContainer may have more than one child.
2357 Q_ASSERT(n == itemPriv->paintNode || n == itemPriv->childContainerNode() || n->childCount() == 1);
2358 }
2359#endif
2360
2361}
2362
2363bool QQuickWindowPrivate::emitError(QQuickWindow::SceneGraphError error, const QString &msg)
2364{
2365 Q_Q(QQuickWindow);
2366 static const QMetaMethod errorSignal = QMetaMethod::fromSignal(&QQuickWindow::sceneGraphError);
2367 if (q->isSignalConnected(errorSignal)) {
2368 emit q->sceneGraphError(error, msg);
2369 return true;
2370 }
2371 return false;
2372}
2373
2374void QQuickWindow::maybeUpdate()
2375{
2376 Q_D(QQuickWindow);
2377 if (d->renderControl)
2378 QQuickRenderControlPrivate::get(d->renderControl)->maybeUpdate();
2379 else if (d->windowManager)
2380 d->windowManager->maybeUpdate(this);
2381}
2382
2383void QQuickWindow::cleanupSceneGraph()
2384{
2385 Q_D(QQuickWindow);
2386 if (!d->renderer)
2387 return;
2388
2389 delete d->renderer->rootNode();
2390 delete d->renderer;
2391 d->renderer = nullptr;
2392
2393 d->runAndClearJobs(&d->beforeSynchronizingJobs);
2394 d->runAndClearJobs(&d->afterSynchronizingJobs);
2395 d->runAndClearJobs(&d->beforeRenderingJobs);
2396 d->runAndClearJobs(&d->afterRenderingJobs);
2397 d->runAndClearJobs(&d->afterSwapJobs);
2398}
2399
2401{
2402#if QT_CONFIG(opengl)
2403 if (context && context->isValid()) {
2405 if (rif) {
2406 Q_Q(QQuickWindow);
2407 return reinterpret_cast<QOpenGLContext *>(rif->getResource(q, QSGRendererInterface::OpenGLContextResource));
2408 }
2409 }
2410#endif
2411 return nullptr;
2412}
2413
2417bool QQuickWindow::isSceneGraphInitialized() const
2418{
2419 Q_D(const QQuickWindow);
2420 return d->context != nullptr && d->context->isValid();
2421}
2422
2622void QQuickWindow::setRenderTarget(const QQuickRenderTarget &target)
2623{
2624 Q_D(QQuickWindow);
2625 if (target != d->customRenderTarget) {
2626 d->customRenderTarget = target;
2627 d->redirect.renderTargetDirty = true;
2628 }
2629}
2630
2639QQuickRenderTarget QQuickWindow::renderTarget() const
2640{
2641 Q_D(const QQuickWindow);
2642 return d->customRenderTarget;
2643}
2644
2645#ifdef Q_OS_WEBOS
2646class GrabWindowForProtectedContent : public QRunnable
2647{
2648public:
2649 GrabWindowForProtectedContent(QQuickWindow *window, QImage *image, QWaitCondition *condition)
2650 : m_window(window)
2651 , m_image(image)
2652 , m_condition(condition)
2653 {
2654 }
2655
2656 bool checkGrabbable()
2657 {
2658 if (!m_window)
2659 return false;
2660 if (!m_image)
2661 return false;
2662 if (!QQuickWindowPrivate::get(m_window))
2663 return false;
2664
2665 return true;
2666 }
2667
2668 void run() override
2669 {
2670 if (!checkGrabbable())
2671 return;
2672
2673 *m_image = QSGRhiSupport::instance()->grabOffscreenForProtectedContent(m_window);
2674 if (m_condition)
2675 m_condition->wakeOne();
2676 return;
2677 }
2678
2679private:
2680 QQuickWindow *m_window;
2681 QImage *m_image;
2682 QWaitCondition *m_condition;
2683
2684};
2685#endif
2686
2707QImage QQuickWindow::grabWindow()
2708{
2709 Q_D(QQuickWindow);
2710
2711 if (!d->isRenderable() && !d->renderControl) {
2712 // backends like software can grab regardless of the window state
2713 if (d->windowManager && (d->windowManager->flags() & QSGRenderLoop::SupportsGrabWithoutExpose))
2714 return d->windowManager->grab(this);
2715
2716 if (!isSceneGraphInitialized()) {
2717 // We do not have rendering up and running. Forget the render loop,
2718 // do a frame completely offscreen and synchronously into a
2719 // texture. This can be *very* slow due to all the device/context
2720 // and resource initialization but the documentation warns for it,
2721 // and is still important for some use cases.
2722 Q_ASSERT(!d->rhi);
2723 return QSGRhiSupport::instance()->grabOffscreen(this);
2724 }
2725 }
2726
2727#ifdef Q_OS_WEBOS
2728 if (requestedFormat().testOption(QSurfaceFormat::ProtectedContent)) {
2729 QImage image;
2730 QMutex mutex;
2732 mutex.lock();
2733 GrabWindowForProtectedContent *job = new GrabWindowForProtectedContent(this, &image, &condition);
2734 if (!job) {
2735 qWarning("QQuickWindow::grabWindow: Failed to create a job for capturing protected content");
2736 mutex.unlock();
2737 return QImage();
2738 }
2739 scheduleRenderJob(job, QQuickWindow::NoStage);
2740 condition.wait(&mutex);
2741 mutex.unlock();
2742 return image;
2743 }
2744#endif
2745 // The common case: we have an exposed window with an initialized
2746 // scenegraph, meaning we can request grabbing via the render loop, or we
2747 // are not targeting the window, in which case the request is to be
2748 // forwarded to the rendercontrol.
2749 if (d->renderControl)
2750 return QQuickRenderControlPrivate::get(d->renderControl)->grab();
2751 else if (d->windowManager)
2752 return d->windowManager->grab(this);
2753
2754 return QImage();
2755}
2756
2765QQmlIncubationController *QQuickWindow::incubationController() const
2766{
2767 Q_D(const QQuickWindow);
2768
2769 if (!d->windowManager)
2770 return nullptr; // TODO: make sure that this is safe
2771
2772 if (!d->incubationController)
2773 d->incubationController = new QQuickWindowIncubationController(d->windowManager);
2774 return d->incubationController;
2775}
2776
2777
2778
3151QSGTexture *QQuickWindow::createTextureFromImage(const QImage &image) const
3152{
3153 return createTextureFromImage(image, {});
3154}
3155
3156
3202QSGTexture *QQuickWindow::createTextureFromImage(const QImage &image, CreateTextureOptions options) const
3203{
3204 Q_D(const QQuickWindow);
3205 if (!isSceneGraphInitialized()) // check both for d->context and d->context->isValid()
3206 return nullptr;
3207 uint flags = 0;
3208 if (options & TextureCanUseAtlas) flags |= QSGRenderContext::CreateTexture_Atlas;
3209 if (options & TextureHasMipmaps) flags |= QSGRenderContext::CreateTexture_Mipmap;
3210 if (!(options & TextureIsOpaque)) flags |= QSGRenderContext::CreateTexture_Alpha;
3211 return d->context->createTexture(image, flags);
3212}
3213
3247QSGTexture *QQuickWindow::createTextureFromRhiTexture(QRhiTexture *texture, CreateTextureOptions options) const
3248{
3249 Q_D(const QQuickWindow);
3250 if (!d->rhi)
3251 return nullptr;
3252
3254 t->setOwnsTexture(true);
3255 t->setTexture(texture);
3256 t->setHasAlphaChannel(options & QQuickWindow::TextureHasAlphaChannel);
3257 t->setTextureSize(texture->pixelSize());
3258 return t;
3259}
3260
3261// Legacy, private alternative to createTextureFromRhiTexture() that internally
3262// creates a QRhiTexture wrapping the existing native graphics resource.
3263// New code should prefer using the public API.
3265 int nativeLayoutOrState,
3266 uint nativeFormat,
3267 const QSize &size,
3268 QQuickWindow::CreateTextureOptions options,
3269 TextureFromNativeTextureFlags flags) const
3270{
3271 if (!rhi)
3272 return nullptr;
3273
3275 texture->setTextureFromNativeTexture(rhi, nativeObjectHandle, nativeLayoutOrState, nativeFormat,
3276 size, options, flags);
3277 texture->setHasAlphaChannel(options & QQuickWindow::TextureHasAlphaChannel);
3278 // note that the QRhiTexture does not (and cannot) own the native object
3279 texture->setOwnsTexture(true); // texture meaning the QRhiTexture here, not the native object
3280 texture->setTextureSize(size);
3281 return texture;
3282}
3283
3305void QQuickWindow::setColor(const QColor &color)
3306{
3307 Q_D(QQuickWindow);
3308 if (color == d->clearColor)
3309 return;
3310
3311 if (color.alpha() != d->clearColor.alpha()) {
3312 QSurfaceFormat fmt = requestedFormat();
3313 if (color.alpha() < 255)
3314 fmt.setAlphaBufferSize(8);
3315 else
3316 fmt.setAlphaBufferSize(-1);
3317 setFormat(fmt);
3318 }
3319 d->clearColor = color;
3321 update();
3322}
3323
3325{
3326 return d_func()->clearColor;
3327}
3328
3335bool QQuickWindow::hasDefaultAlphaBuffer()
3336{
3338}
3339
3349void QQuickWindow::setDefaultAlphaBuffer(bool useAlpha)
3350{
3352}
3353
3417const QQuickWindow::GraphicsStateInfo &QQuickWindow::graphicsStateInfo()
3418{
3419 Q_D(QQuickWindow);
3420 if (d->rhi) {
3421 d->rhiStateInfo.currentFrameSlot = d->rhi->currentFrameSlot();
3422 d->rhiStateInfo.framesInFlight = d->rhi->resourceLimit(QRhi::FramesInFlight);
3423 }
3424 return d->rhiStateInfo;
3425}
3426
3468void QQuickWindow::beginExternalCommands()
3469{
3470 Q_D(QQuickWindow);
3471 if (d->rhi && d->context && d->context->isValid()) {
3472 QSGDefaultRenderContext *rc = static_cast<QSGDefaultRenderContext *>(d->context);
3474 if (cb)
3475 cb->beginExternal();
3476 }
3477}
3478
3505void QQuickWindow::endExternalCommands()
3506{
3507 Q_D(QQuickWindow);
3508 if (d->rhi && d->context && d->context->isValid()) {
3509 QSGDefaultRenderContext *rc = static_cast<QSGDefaultRenderContext *>(d->context);
3511 if (cb)
3512 cb->endExternal();
3513 }
3514}
3515
3983void QQuickWindow::scheduleRenderJob(QRunnable *job, RenderStage stage)
3984{
3985 Q_D(QQuickWindow);
3986
3987 d->renderJobMutex.lock();
3988 if (stage == BeforeSynchronizingStage) {
3989 d->beforeSynchronizingJobs << job;
3990 } else if (stage == AfterSynchronizingStage) {
3991 d->afterSynchronizingJobs << job;
3992 } else if (stage == BeforeRenderingStage) {
3993 d->beforeRenderingJobs << job;
3994 } else if (stage == AfterRenderingStage) {
3995 d->afterRenderingJobs << job;
3996 } else if (stage == AfterSwapStage) {
3997 d->afterSwapJobs << job;
3998 } else if (stage == NoStage) {
3999 if (d->renderControl && d->rhi && d->rhi->thread() == QThread::currentThread()) {
4000 job->run();
4001 delete job;
4002 } else if (isExposed()) {
4003 d->windowManager->postJob(this, job);
4004 } else {
4005 delete job;
4006 }
4007 }
4008 d->renderJobMutex.unlock();
4009}
4010
4011void QQuickWindowPrivate::runAndClearJobs(QList<QRunnable *> *jobs)
4012{
4014 QList<QRunnable *> jobList = *jobs;
4015 jobs->clear();
4017
4018 for (QRunnable *r : std::as_const(jobList)) {
4019 r->run();
4020 delete r;
4021 }
4022}
4023
4024void QQuickWindow::runJobsAfterSwap()
4025{
4026 Q_D(QQuickWindow);
4027 d->runAndClearJobs(&d->afterSwapJobs);
4028}
4029
4045qreal QQuickWindow::effectiveDevicePixelRatio() const
4046{
4047 Q_D(const QQuickWindow);
4049 if (w)
4050 return w->devicePixelRatio();
4051
4052 if (!d->customRenderTarget.isNull())
4053 return d->customRenderTarget.devicePixelRatio();
4054
4055 return devicePixelRatio();
4056}
4057
4079QSGRendererInterface *QQuickWindow::rendererInterface() const
4080{
4081 Q_D(const QQuickWindow);
4082
4083 // no context validity check - it is essential to be able to return a
4084 // renderer interface instance before scenegraphInitialized() is emitted
4085 // (depending on the backend, that can happen way too late for some of the
4086 // rif use cases, like examining the graphics api or shading language in
4087 // use)
4088
4089 return d->context->sceneGraphContext()->rendererInterface(d->context);
4090}
4091
4112QRhi *QQuickWindow::rhi() const
4113{
4114 Q_D(const QQuickWindow);
4115 return d->rhi;
4116}
4117
4128QRhiSwapChain *QQuickWindow::swapChain() const
4129{
4130 Q_D(const QQuickWindow);
4131 return d->swapchain;
4132}
4133
4180void QQuickWindow::setGraphicsApi(QSGRendererInterface::GraphicsApi api)
4181{
4182 // Special cases: these are different scenegraph backends.
4183 switch (api) {
4185 setSceneGraphBackend(QStringLiteral("software"));
4186 break;
4188 setSceneGraphBackend(QStringLiteral("openvg"));
4189 break;
4190 default:
4191 break;
4192 }
4193
4194 // Standard case: tell the QRhi-based default adaptation what graphics api
4195 // (QRhi backend) to use.
4198}
4199
4229QSGRendererInterface::GraphicsApi QQuickWindow::graphicsApi()
4230{
4231 // Note that this applies the settings e.g. from the env vars
4232 // (QSG_RHI_BACKEND) if it was not done at least once already. Whereas if
4233 // setGraphicsApi() was called before, or the scene graph is already
4234 // initialized, then this is just a simple query.
4235 return QSGRhiSupport::instance()->graphicsApi();
4236}
4237
4258void QQuickWindow::setSceneGraphBackend(const QString &backend)
4259{
4260 QSGContext::setBackend(backend);
4261}
4262
4275QString QQuickWindow::sceneGraphBackend()
4276{
4277 return QSGContext::backend();
4278}
4279
4343void QQuickWindow::setGraphicsDevice(const QQuickGraphicsDevice &device)
4344{
4345 Q_D(QQuickWindow);
4346 d->customDeviceObjects = device;
4347}
4348
4357QQuickGraphicsDevice QQuickWindow::graphicsDevice() const
4358{
4359 Q_D(const QQuickWindow);
4360 return d->customDeviceObjects;
4361}
4362
4390void QQuickWindow::setGraphicsConfiguration(const QQuickGraphicsConfiguration &config)
4391{
4392 Q_D(QQuickWindow);
4393 d->graphicsConfig = config;
4394}
4395
4404QQuickGraphicsConfiguration QQuickWindow::graphicsConfiguration() const
4405{
4406 Q_D(const QQuickWindow);
4407 return d->graphicsConfig;
4408}
4409
4416QSGTextNode *QQuickWindow::createTextNode() const
4417{
4418 Q_D(const QQuickWindow);
4419 return isSceneGraphInitialized() ? d->context->sceneGraphContext()->createTextNode(d->context) : nullptr;
4420}
4421
4430QSGRectangleNode *QQuickWindow::createRectangleNode() const
4431{
4432 Q_D(const QQuickWindow);
4433 return isSceneGraphInitialized() ? d->context->sceneGraphContext()->createRectangleNode() : nullptr;
4434}
4435
4444QSGImageNode *QQuickWindow::createImageNode() const
4445{
4446 Q_D(const QQuickWindow);
4447 return isSceneGraphInitialized() ? d->context->sceneGraphContext()->createImageNode() : nullptr;
4448}
4449
4455QSGNinePatchNode *QQuickWindow::createNinePatchNode() const
4456{
4457 Q_D(const QQuickWindow);
4458 return isSceneGraphInitialized() ? d->context->sceneGraphContext()->createNinePatchNode() : nullptr;
4459}
4460
4469QQuickWindow::TextRenderType QQuickWindow::textRenderType()
4470{
4472}
4473
4484void QQuickWindow::setTextRenderType(QQuickWindow::TextRenderType renderType)
4485{
4487}
4488
4489
4507
4509#ifndef QT_NO_DEBUG_STREAM
4511{
4512 QDebugStateSaver saver(debug);
4513 debug.nospace();
4514 if (!win) {
4515 debug << "QQuickWindow(nullptr)";
4516 return debug;
4517 }
4518
4519 debug << win->metaObject()->className() << '(' << static_cast<const void *>(win);
4520 if (win->isActive())
4521 debug << " active";
4522 if (win->isExposed())
4523 debug << " exposed";
4524 debug << ", visibility=" << win->visibility() << ", flags=" << win->flags();
4525 if (!win->title().isEmpty())
4526 debug << ", title=" << win->title();
4527 if (!win->objectName().isEmpty())
4528 debug << ", name=" << win->objectName();
4529 if (win->parent())
4530 debug << ", parent=" << static_cast<const void *>(win->parent());
4531 if (win->transientParent())
4532 debug << ", transientParent=" << static_cast<const void *>(win->transientParent());
4533 debug << ", geometry=";
4535 debug << ')';
4536 return debug;
4537}
4538#endif
4539
4541
4542#include "qquickwindow.moc"
4543#include "moc_qquickwindow_p.cpp"
4544#include "moc_qquickwindow.cpp"
IOBluetoothDevice * device
\inmodule QtCore
void stopped()
This signal is emitted by the animation framework to notify the driver that continuous animation has ...
\inmodule QtGui
Definition qevent.h:1025
The QCloseEvent class contains parameters that describe a close event.
Definition qevent.h:562
The QColor class provides colors based on RGB, HSV or CMYK values.
Definition qcolor.h:31
static bool sendEvent(QObject *receiver, QEvent *event)
Sends event event directly to receiver receiver, using the notify() function.
static QCoreApplication * instance() noexcept
Returns a pointer to the application's QCoreApplication (or QGuiApplication/QApplication) instance.
static void postEvent(QObject *receiver, QEvent *event, int priority=Qt::NormalEventPriority)
\inmodule QtCore
\inmodule QtCore
The QEventPoint class provides information about a point in a QPointerEvent.
Definition qeventpoint.h:20
\inmodule QtCore
Definition qcoreevent.h:45
virtual void setAccepted(bool accepted)
Definition qcoreevent.h:307
bool isSinglePointEvent() const noexcept
Definition qcoreevent.h:315
Type
This enum type defines the valid event types in Qt.
Definition qcoreevent.h:51
@ ApplicationPaletteChange
Definition qcoreevent.h:93
@ DevicePixelRatioChange
Definition qcoreevent.h:287
@ FocusAboutToChange
Definition qcoreevent.h:68
@ InputMethod
Definition qcoreevent.h:120
@ DragEnter
Definition qcoreevent.h:101
@ LocaleChange
Definition qcoreevent.h:122
@ InputMethodQuery
Definition qcoreevent.h:261
@ TouchUpdate
Definition qcoreevent.h:242
@ TouchBegin
Definition qcoreevent.h:241
@ WindowActivate
Definition qcoreevent.h:83
@ LanguageChange
Definition qcoreevent.h:123
@ UpdateRequest
Definition qcoreevent.h:113
@ DragLeave
Definition qcoreevent.h:103
@ PlatformSurface
Definition qcoreevent.h:278
@ ChildWindowAdded
Definition qcoreevent.h:289
@ WindowDeactivate
Definition qcoreevent.h:84
bool isAccepted() const
Definition qcoreevent.h:308
void accept()
Sets the accept flag of the event object, the equivalent of calling setAccepted(true).
Definition qcoreevent.h:310
The QExposeEvent class contains event parameters for expose events. \inmodule QtGui.
Definition qevent.h:515
The QFocusEvent class contains event parameters for widget focus events.
Definition qevent.h:470
static void cleanup()
Definition qfont.cpp:2259
virtual bool contains(const QPointF &point) const
Returns true if this item contains point, which is in local coordinates; otherwise,...
void update(const QRectF &rect=QRectF())
Schedules a redraw of the area covered by rect in this item.
QList< QGraphicsItem * > childItems() const
QPointF transformOriginPoint() const
virtual QVariant inputMethodQuery(Qt::InputMethodQuery query) const
This method is only relevant for input items.
QGraphicsItem * parentItem() const
Returns a pointer to this item's parent item.
GraphicsItemFlags flags() const
Returns this item's flags.
QPointF mapFromScene(const QPointF &point) const
Maps the point point, which is in this item's scene's coordinate system, to this item's coordinate sy...
\macro qGuiApp
QScreen * primaryScreen
the primary (or default) screen of the application.
static QPalette palette()
Returns the current application palette.
static QObject * focusObject()
Returns the QObject in currently active window that will be final receiver of events tied to focus,...
void applicationStateChanged(Qt::ApplicationState state)
void fontDatabaseChanged()
This signal is emitted when the available fonts have changed.
The QHideEvent class provides an event which is sent after a widget is hidden.
Definition qevent.h:586
\inmodule QtGui
Definition qimage.h:37
static void setObjectOwnership(QObject *, ObjectOwnership)
Sets the ownership of object.
The QKeyEvent class describes a key event.
Definition qevent.h:424
QString arg(Args &&...args) const
qsizetype size() const noexcept
Definition qlist.h:397
const_reference at(qsizetype i) const noexcept
Definition qlist.h:446
void append(parameter_type t)
Definition qlist.h:458
The QMatrix4x4 class represents a 4x4 transformation matrix in 3D space.
Definition qmatrix4x4.h:25
void translate(const QVector3D &vector)
Multiplies this matrix by another that translates coordinates by the components of vector.
\inmodule QtCore
Definition qmetaobject.h:19
static QMetaMethod fromSignal(PointerToMemberFunction signal)
\inmodule QtGui
Definition qevent.h:196
\inmodule QtCore
Definition qmutex.h:281
void unlock() noexcept
Unlocks the mutex.
Definition qmutex.h:289
void lock() noexcept
Locks the mutex.
Definition qmutex.h:286
QObject * q_ptr
Definition qobject.h:72
QObjectList children
Definition qobject.h:74
QObject * parent
Definition qobject.h:73
static QMetaObject::Connection connect(const typename QtPrivate::FunctionPointer< Func1 >::Object *sender, Func1 signal, const typename QtPrivate::FunctionPointer< Func2 >::Object *receiverPrivate, Func2 slot, Qt::ConnectionType type=Qt::AutoConnection)
Definition qobject_p.h:299
\inmodule QtCore
Definition qobject.h:103
int startTimer(int interval, Qt::TimerType timerType=Qt::CoarseTimer)
This is an overloaded function that will start a timer of type timerType and a timeout of interval mi...
Definition qobject.cpp:1817
QObject * parent() const
Returns a pointer to the parent object.
Definition qobject.h:346
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2960
virtual void childEvent(QChildEvent *event)
This event handler can be reimplemented in a subclass to receive child events.
Definition qobject.cpp:1508
QString objectName
the name of this object
Definition qobject.h:107
void setParent(QObject *parent)
Makes the object a child of parent.
Definition qobject.cpp:2195
Q_WEAK_OVERLOAD void setObjectName(const QString &name)
Sets the object's name to name.
Definition qobject.h:127
void killTimer(int id)
Kills the timer with timer identifier, id.
Definition qobject.cpp:1912
\inmodule QtGui
The QPalette class contains color groups for each widget state.
Definition qpalette.h:19
The QPlatformSurfaceEvent class is used to notify about native platform surface events....
Definition qevent.h:531
\inmodule QtCore\reentrant
Definition qpoint.h:217
constexpr qreal x() const noexcept
Returns the x coordinate of this point.
Definition qpoint.h:343
constexpr qreal y() const noexcept
Returns the y coordinate of this point.
Definition qpoint.h:348
\inmodule QtCore\reentrant
Definition qpoint.h:25
A base class for pointer events.
Definition qevent.h:73
virtual bool isEndEvent() const
Definition qevent.h:92
void clearPassiveGrabbers(const QEventPoint &point)
Removes all passive grabbers from the given point.
Definition qevent.cpp:433
void setExclusiveGrabber(const QEventPoint &point, QObject *exclusiveGrabber)
Informs the delivery logic that the given exclusiveGrabber is to receive all future update events and...
Definition qevent.cpp:369
QEventPoint & point(qsizetype i)
Returns a QEventPoint reference for the point at index i.
Definition qevent.cpp:240
const QList< QEventPoint > & points() const
Returns a list of points in this pointer event.
Definition qevent.h:87
static QPointingDevicePrivate * get(QPointingDevice *q)
The QPointingDevice class describes a device from which mouse, touch or tablet events originate.
static const QPointingDevice * primaryPointingDevice(const QString &seatName=QString())
Returns the primary pointing device (the core pointer, traditionally assumed to be a mouse) on the gi...
QQmlIncubationController instances drive the progress of QQmlIncubators.
void incubateFor(int msecs)
Incubate objects for msecs, or until there are no more objects to incubate.
int incubatingObjectCount() const
Return the number of objects currently incubating.
static QString prettyTypeName(const QObject *object)
Returns the pretty QML type name (e.g.
\qmlsignal QtQuick::Window::sceneGraphError(SceneGraphError error, QString message)
void setAccepted(bool accepted)
static bool isTabletEvent(const QPointerEvent *ev)
static bool isSynthMouse(const QPointerEvent *ev)
static bool isTouchEvent(const QPointerEvent *ev)
QQuickGraphicsConfiguration controls lower level graphics settings for the QQuickWindow.
The QQuickGraphicsDevice class provides an opaque container for native graphics objects representing ...
QLazilyAllocated< ExtraData, ExtraDataTags > extra
virtual void updatePolish()
QList< QQuickItem * > paintOrderChildItems() const
quint32 subtreeCursorEnabled
static QQuickItem * nextPrevItemInTabFocusChain(QQuickItem *item, bool forward, bool wrap=true)
void itemChange(QQuickItem::ItemChange, const QQuickItem::ItemChangeData &)
qreal z() const
static QQuickItemPrivate * get(QQuickItem *item)
The QQuickItem class provides the most basic of all visual items in \l {Qt Quick}.
Definition qquickitem.h:63
void setSize(const QSizeF &size)
void setFlag(Flag flag, bool enabled=true)
Enables the specified flag for this item if enabled is true; if enabled is false, the flag is disable...
@ ItemDevicePixelRatioHasChanged
Definition qquickitem.h:154
@ ItemClipsChildrenToShape
Definition qquickitem.h:130
Contains color groups for each QML item state. \inmodule QtQuick.
static void purgeCache()
static QQuickPointerHandlerPrivate * get(QQuickPointerHandler *q)
static QQuickRenderControlPrivate * get(QQuickRenderControl *renderControl)
The QQuickRenderControl class provides a mechanism for rendering the Qt Quick scenegraph onto an offs...
static QWindow * renderWindowFor(QQuickWindow *win, QPoint *offset=nullptr)
Returns the real window that win is being rendered to, if any.
static QQuickRenderTargetPrivate * get(QQuickRenderTarget *rt)
The QQuickRenderTarget class provides an opaque container for native graphics resources specifying a ...
void incubatingObjectCountChanged(int count) override
Called when the number of incubating objects changes.
void timerEvent(QTimerEvent *) override
This event handler can be reimplemented in a subclass to receive timer events for the object.
QQuickWindowIncubationController(QSGRenderLoop *loop)
~QQuickWindowPrivate() override
void init(QQuickWindow *, QQuickRenderControl *control=nullptr)
QByteArray visualizationMode
bool emitError(QQuickWindow::SceneGraphError error, const QString &msg)
QQuickItem::UpdatePaintNodeData updatePaintNodeData
static void data_clear(QQmlListProperty< QObject > *)
static void data_replace(QQmlListProperty< QObject > *, qsizetype, QObject *)
QQuickRootItem * contentItem
void dirtyItem(QQuickItem *)
void clearFocusObject() override
static QQuickWindowPrivate * get(QQuickWindow *c)
static QQuickWindow::TextRenderType textRenderType
QSGRenderContext * context
QQuickRenderControl * renderControl
void runAndClearJobs(QList< QRunnable * > *jobs)
QVector< QQuickItem * > itemsToPolish
QQuickItem * dirtyItemList
void updateDirtyNode(QQuickItem *)
void clearGrabbers(QPointerEvent *event)
static void rhiCreationFailureMessage(const QString &backendName, QString *translatedMessage, QString *untranslatedMessage)
static void emitBeforeRenderPassRecording(void *ud)
static bool defaultAlphaBuffer
void setCustomCommandBuffer(QRhiCommandBuffer *cb)
QPointer< QQuickPalette > windowPaletteRef
static void data_append(QQmlListProperty< QObject > *, QObject *)
\qmlproperty list<QtObject> Window::data \qmldefault
void invalidateFontData(QQuickItem *item)
void setPalette(QQuickPalette *p) override
void cleanup(QSGNode *)
QQuickDeliveryAgentPrivate * deliveryAgentPrivate() const
QQmlListProperty< QObject > data()
QSet< QQuickItem * > parentlessItems
void updateChildrenPalettes(const QPalette &parentPalette) override
qreal lastReportedItemDevicePixelRatio
QScopedPointer< QQuickAnimatorController > animationController
QSGTexture * createTextureFromNativeTexture(quint64 nativeObjectHandle, int nativeLayoutOrState, uint nativeFormat, const QSize &size, QQuickWindow::CreateTextureOptions options, TextureFromNativeTextureFlags flags={}) const
void forcePolish()
Schedules polish events on all items in the scene.
static void data_removeLast(QQmlListProperty< QObject > *)
void setFocusToTarget(FocusTarget, Qt::FocusReason) override
struct QQuickWindowPrivate::Redirect redirect
static void emitAfterRenderPassRecording(void *ud)
void clearFocusInScope(QQuickItem *scope, QQuickItem *item, Qt::FocusReason reason)
QRhiRenderTarget * activeCustomRhiRenderTarget()
QSGRenderLoop * windowManager
bool isRenderable() const
void updateChildWindowStackingOrder(QQuickItem *item=nullptr)
QList< QSGNode * > cleanupNodeList
QOpenGLContext * openglContext()
QQuickDeliveryAgent * deliveryAgent
static QObject * data_at(QQmlListProperty< QObject > *, qsizetype)
static qsizetype data_count(QQmlListProperty< QObject > *)
\qmltype Window \instantiates QQuickWindow \inqmlmodule QtQuick
void focusOutEvent(QFocusEvent *) override
\reimp
void frameSwapped()
This signal is emitted when a frame has been queued for presenting.
void mousePressEvent(QMouseEvent *) override
\reimp
void resizeEvent(QResizeEvent *) override
\reimp
void update()
Schedules the window to render another frame.
void mouseReleaseEvent(QMouseEvent *) override
\reimp
void exposeEvent(QExposeEvent *) override
\reimp
QQuickItem * contentItem
\qmlattachedproperty Item Window::contentItem
void focusInEvent(QFocusEvent *) override
\reimp
void sceneGraphInitialized()
\qmlsignal QtQuick::Window::frameSwapped()
bool event(QEvent *) override
\reimp
QColor color
\qmlproperty color Window::color
void closeEvent(QCloseEvent *) override
\reimp
~QQuickWindow() override
Destroys the window.
void sceneGraphInvalidated()
\qmlsignal QtQuick::Window::sceneGraphInitialized()
void mouseMoveEvent(QMouseEvent *) override
\reimp
QQuickItem * activeFocusItem
The item which currently has active focus or null if there is no item with active focus.
QObject * focusObject() const override
void releaseResources()
This function tries to release redundant resources currently held by the QML scene.
void hideEvent(QHideEvent *) override
\reimp
void showEvent(QShowEvent *) override
\reimp
void keyReleaseEvent(QKeyEvent *) override
\reimp
void mouseDoubleClickEvent(QMouseEvent *) override
\reimp
void keyPressEvent(QKeyEvent *) override
\reimp
\inmodule QtCore\reentrant
Definition qrect.h:484
\inmodule QtCore\reentrant
Definition qrect.h:30
The QResizeEvent class contains event parameters for resize events.
Definition qevent.h:548
\inmodule QtGui
Definition qrhi.h:1651
\inmodule QtGui
Definition qrhi.h:1142
\inmodule QtGui
Definition qrhi.h:1158
\inmodule QtGui
Definition qrhi.h:1549
\inmodule QtGui
Definition qrhi.h:895
\inmodule QtGuiPrivate \inheaderfile rhi/qrhi.h
Definition qrhi.h:1804
@ FramesInFlight
Definition qrhi.h:1890
\inmodule QtCore
Definition qrunnable.h:18
virtual void run()=0
Implement this pure virtual function in your subclass.
void setClipRect(const QRectF &)
Sets the clip rect of this clip node to rect.
Definition qsgnode.cpp:1101
The QSGContext holds the scene graph entry points for one QML engine.
static QString backend()
virtual QSGRendererInterface * rendererInterface(QSGRenderContext *renderContext)
Returns a pointer to the (presumably) global renderer interface.
static void setBackend(const QString &backend)
virtual QSurfaceFormat defaultSurfaceFormat() const =0
QRhiCommandBuffer * currentFrameCommandBuffer() const
The QSGImageNode class is provided for convenience to easily draw textured content using the QML scen...
\inmodule QtQuick
\group qtquick-scenegraph-nodes \title Qt Quick Scene Graph Node classes
Definition qsgnode.h:37
void removeChildNode(QSGNode *node)
Removes node from this node's list of children.
Definition qsgnode.cpp:500
QSGNode * nextSibling() const
Returns the node after this in the parent's list of children.
Definition qsgnode.h:107
void reparentChildNodesTo(QSGNode *newParent)
Definition qsgnode.cpp:547
void appendChildNode(QSGNode *node)
Appends node to this node's list of children.
Definition qsgnode.cpp:398
QSGNode * parent() const
Returns the parent node of this node.
Definition qsgnode.h:93
QSGNode * firstChild() const
Returns the first child of this node.
Definition qsgnode.h:105
The QSGOpacityNode class is used to change opacity of nodes.
Definition qsgnode.h:276
void setTextureFromNativeTexture(QRhi *rhi, quint64 nativeObjectHandle, int nativeLayoutOrState, uint nativeFormat, const QSize &size, QQuickWindow::CreateTextureOptions options, QQuickWindowPrivate::TextureFromNativeTextureFlags flags)
void setOwnsTexture(bool owns)
The QSGRectangleNode class is a convenience class for drawing solid filled rectangles using scenegrap...
QSGContext * sceneGraphContext() const
virtual bool isValid() const
static QSGRenderLoop * instance()
void timeToIncubate()
void addWindow(QQuickWindow *win)
virtual QAnimationDriver * animationDriver() const =0
virtual QSurface::SurfaceType windowSurfaceType() const
virtual QSGRenderContext * createRenderContext(QSGContext *) const =0
virtual QSGContext * sceneGraphContext() const =0
virtual bool interleaveIncubation() const
An interface providing access to some of the graphics API specific internals of the scenegraph.
RenderMode
\value RenderMode2D Normal 2D rendering \value RenderMode2DNoDepthBuffer Normal 2D rendering with dep...
static bool isApiRhiBased(GraphicsApi api)
GraphicsApi
\value Unknown An unknown graphics API is in use \value Software The Qt Quick 2D Renderer is in use \...
static QSGRhiSupport * instance_internal()
static QSGRhiSupport * instance()
The QSGRootNode is the toplevel root of any scene graph.
Definition qsgnode.h:259
The QSGTextNode class is a class for drawing text layouts and text documents in the Qt Quick scene gr...
Definition qsgtextnode.h:14
\inmodule QtQuick
Definition qsgtexture.h:20
void reset(T *other=nullptr) noexcept(noexcept(Cleanup::cleanup(std::declval< T * >())))
Deletes the existing object it is pointing to (if any), and sets its pointer to other.
The QScreen class is used to query screen properties. \inmodule QtGui.
Definition qscreen.h:32
iterator begin()
Definition qset.h:136
iterator end()
Definition qset.h:140
The QShowEvent class provides an event that is sent when a widget is shown.
Definition qevent.h:578
A base class for pointer events containing a single point, such as mouse events.
Definition qevent.h:109
\inmodule QtCore
Definition qsize.h:25
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
static QString fromLatin1(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5871
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:192
The QSurfaceFormat class represents the format of a QSurface. \inmodule QtGui.
@ OpenGLSurface
Definition qsurface.h:32
static QThread * currentThread()
Definition qthread.cpp:1039
\inmodule QtCore
Definition qcoreevent.h:366
QRect geometry
the geometry of the widget relative to its parent and excluding the window frame
Definition qwidget.h:106
QCursor cursor
Definition qwindow_p.h:154
\inmodule QtGui
Definition qwindow.h:63
virtual QAccessibleInterface * accessibleRoot() const
Returns the accessibility interface for the object that the window represents.
Definition qwindow.cpp:2222
void focusObjectChanged(QObject *object)
This signal is emitted when the final receiver of events tied to focus is changed to object.
virtual bool event(QEvent *) override
Override this to handle any event (ev) sent to the window.
Definition qwindow.cpp:2511
void screenChanged(QScreen *screen)
This signal is emitted when a window's screen changes, either by being set explicitly with setScreen(...
widget setFormat(format)
void colorChanged()
qDeleteAll(list.begin(), list.end())
cache insert(employee->id(), employee)
QSet< QString >::iterator it
auto mo
[7]
rect
[4]
else opt state
[0]
Combined button and popup list for selecting options.
QTCONCURRENT_RUN_NODISCARD auto run(QThreadPool *pool, Function &&f, Args &&...args)
static void formatQRect(QDebug &debug, const Rect &rect)
Definition qdebug_p.h:45
Definition qcompare.h:63
@ ImEnabled
@ NoButton
Definition qnamespace.h:57
@ AA_SynthesizeMouseForUnhandledTabletEvents
Definition qnamespace.h:459
ApplicationState
Definition qnamespace.h:262
@ ApplicationActive
Definition qnamespace.h:266
@ DirectConnection
FocusReason
Definition image.cpp:4
static void * context
#define Q_FALLTHROUGH()
#define Q_UNLIKELY(x)
#define Q_LIKELY(x)
#define qApp
DBusConnection const char DBusError * error
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char * method
EGLConfig config
bool qFuzzyCompare(qfloat16 p1, qfloat16 p2) noexcept
Definition qfloat16.h:333
static QString backendName
#define qWarning
Definition qlogging.h:166
#define Q_LOGGING_CATEGORY(name,...)
#define qCDebug(category,...)
#define Q_DECLARE_LOGGING_CATEGORY(name)
return ret
const char * typeName
constexpr const T & qMax(const T &a, const T &b)
Definition qminmax.h:42
GLfloat GLfloat GLfloat w
[0]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLuint index
[2]
GLenum condition
GLboolean r
[2]
GLenum GLuint id
[7]
GLenum GLenum GLsizei count
GLuint color
[2]
GLenum target
GLbitfield flags
GLenum GLuint texture
GLfloat n
struct _cl_event * event
GLuint res
const GLubyte * c
GLuint GLenum matrix
GLdouble GLdouble t
Definition qopenglext.h:243
GLdouble GLdouble GLdouble GLdouble q
Definition qopenglext.h:259
GLfloat GLfloat p
[1]
void QQml_setParent_noEvent(QObject *object, QObject *parent)
Makes the object a child of parent.
QQuickItem * qmlobject_cast< QQuickItem * >(QObject *object)
Q_QML_EXPORT QQmlInfo qmlWarning(const QObject *me)
static const QQmlJSScope * resolve(const QQmlJSScope *current, const QStringList &names)
const QQuickItem * rootItem(const I &item)
void qtquick_shadereffect_purge_gui_thread_shader_cache()
static void updatePixelRatioHelper(QQuickItem *item, float pixelRatio)
static const QQuickItem * firstItemWithDirtyChildrenStacking(const QQuickItem *item)
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)
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
SSL_CTX int(* cb)(SSL *ssl, unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg)
#define qPrintable(string)
Definition qstring.h:1531
QLatin1StringView QLatin1String
Definition qstringfwd.h:31
#define QStringLiteral(str)
QScreen * screen
[1]
Definition main.cpp:29
Q_CORE_EXPORT QByteArray qgetenv(const char *varName)
#define Q_OBJECT
#define slots
#define emit
#define Q_UNUSED(x)
#define QT_TRANSLATE_NOOP(scope, x)
unsigned int quint32
Definition qtypes.h:50
unsigned long long quint64
Definition qtypes.h:61
ptrdiff_t qsizetype
Definition qtypes.h:165
unsigned int uint
Definition qtypes.h:34
double qreal
Definition qtypes.h:187
QVideoFrameFormat::PixelFormat fmt
const char property[13]
Definition qwizard.cpp:101
QWidget * win
Definition settings.cpp:6
QObject::connect nullptr
myObject disconnect()
[26]
QMutex mutex
[2]
QGraphicsItem * item
QList< QTreeWidgetItem * > items
QLayoutItem * child
[0]
aWidget window() -> setWindowTitle("New Window Title")
[2]
QNetworkRequestFactory api
[0]
QSvgRenderer * renderer
[0]
bool check(QQuickItem *item, int itemsRemainingBeforeUpdatePolish)
const QVector< QQuickItem * > & itemsToPolish
PolishLoopDetector(const QVector< QQuickItem * > &itemsToPolish)
bool contains(const AT &t) const noexcept
Definition qlist.h:45
\inmodule QtCore
QSGTransformNode * transformNode
Definition qquickitem.h:372
struct QQuickWindowRenderTarget::@696 rt
struct QQuickWindowRenderTarget::@698 sw
void reset(QRhi *rhi, ResetFlags flags={})
struct QQuickWindowRenderTarget::ImplicitBuffers implicitBuffers