aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick/items/qquickwindow.cpp
diff options
context:
space:
mode:
authorTor Arne Vestbø <tor.arne.vestbo@qt.io>2023-11-27 17:57:00 +0100
committerTor Arne Vestbø <tor.arne.vestbo@qt.io>2023-12-08 13:22:34 +0100
commit27071a0a32917d2dcf9fbf56f4386ad3d2b91e9b (patch)
tree93764a7e2389cd00bbd21ba8858d2c9e8832bf77 /src/quick/items/qquickwindow.cpp
parentdd18c4614ac5006d7df76024f361a96abc8027d0 (diff)
Add preliminary support for embedding QWindows into Qt Quick
The new WindowContainer item allows embedding arbitrary windows into the Qt Quick scene, including foreign windows such as native map or web views. A new parent property is also added to Window, allowing these to be embedded inside other Items without the need for an explicit window container, along with a new z property, allowing modifications to the child Window's stacking order. Splitting the Quick document up into child windows allows interesting use-cases, such as setting a different surface format on the child window, for example for enabling HDR without affecting the rest of the UI. The embedded windows are managed as a child windows of the root QQuickWindow, with positioning, sizing, and stacking order reflecting the implicit or explicit window container item. Clipping is also supported, by setting a mask on the embedded window. The advantage of managing all embedded windows as as children of the root window is that we always have a QQuickWindow to handle the stacking order, we're not limited by the platform surface clip, and don't risk being interleaved behind native parts of the window we embed into that we don’t control. [ChangeLog[Quick] Preliminary support for embedding QWindows into the Qt Quick scene has been added, along with a parent property on Window, to allow setting a visual parent of the Window. Task-number: QTBUG-102835 Change-Id: I78b973e2685fb0ebbc850a110712f3e747bfe09a Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
Diffstat (limited to 'src/quick/items/qquickwindow.cpp')
-rw-r--r--src/quick/items/qquickwindow.cpp73
1 files changed, 73 insertions, 0 deletions
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp
index 5c19a9bb81..4954a49a1c 100644
--- a/src/quick/items/qquickwindow.cpp
+++ b/src/quick/items/qquickwindow.cpp
@@ -8,6 +8,7 @@
#include "qquickitem_p.h"
#include "qquickevents_p_p.h"
#include "qquickgraphicsdevice_p.h"
+#include "qquickwindowcontainer_p.h"
#include <QtQuick/private/qsgrenderer_p.h>
#include <QtQuick/private/qsgplaintexture_p.h>
@@ -332,6 +333,22 @@ struct PolishLoopDetector
int numPolishLoopsInSequence = 0;
};
+static const QQuickItem *firstItemWithDirtyChildrenStacking(const QQuickItem *item)
+{
+ if (QQuickItemPrivate::get(item)->dirtyAttributes
+ & QQuickItemPrivate::ChildrenStackingChanged) {
+ return item;
+ }
+
+ const auto childItems = item->childItems();
+ for (const auto *childItem : childItems) {
+ if (auto *dirtyItem = firstItemWithDirtyChildrenStacking(childItem))
+ return dirtyItem;
+ }
+
+ return nullptr;
+}
+
void QQuickWindowPrivate::polishItems()
{
// An item can trigger polish on another item, or itself for that matter,
@@ -365,6 +382,11 @@ void QQuickWindowPrivate::polishItems()
deliveryAgentPrivate()->updateFocusItemTransform();
}
#endif
+
+ if (auto *dirtyItem = firstItemWithDirtyChildrenStacking(contentItem)) {
+ qCDebug(lcQuickWindow) << dirtyItem << "has dirty child stacking order";
+ updateChildWindowStackingOrder();
+ }
}
/*!
@@ -1567,6 +1589,23 @@ bool QQuickWindow::event(QEvent *event)
case QEvent::DevicePixelRatioChange:
physicalDpiChanged();
break;
+ case QEvent::ChildWindowAdded: {
+ auto *childEvent = static_cast<QChildWindowEvent*>(event);
+ auto *childWindow = childEvent->child();
+ qCDebug(lcQuickWindow) << "Child window" << childWindow << "added to" << this;
+ if (childWindow->handle()) {
+ // The reparenting has already resulted in the native window
+ // being added to its parent, on top of all other windows. We need
+ // to do a synchronous re-stacking of the windows here, to avoid
+ // leaving the window in the wrong position while waiting for the
+ // asynchronous callback to QQuickWindow::polishItems().
+ d->updateChildWindowStackingOrder();
+ } else {
+ qCDebug(lcQuickWindow) << "No platform window yet."
+ << "Deferring child window stacking until surface creation";
+ }
+ break;
+ }
default:
break;
}
@@ -1582,6 +1621,35 @@ bool QQuickWindow::event(QEvent *event)
return QWindow::event(event);
}
+void QQuickWindowPrivate::updateChildWindowStackingOrder(QQuickItem *item)
+{
+ Q_Q(QQuickWindow);
+
+ if (!item) {
+ qCDebug(lcQuickWindow) << "Updating child window stacking order for" << q;
+ item = contentItem;
+ }
+ auto *itemPrivate = QQuickItemPrivate::get(item);
+ const auto paintOrderChildItems = itemPrivate->paintOrderChildItems();
+ for (auto *child : paintOrderChildItems) {
+ if (auto *windowContainer = qobject_cast<QQuickWindowContainer*>(child)) {
+ auto *window = windowContainer->containedWindow();
+ if (!window) {
+ qCDebug(lcQuickWindow) << windowContainer << "has no contained window yet";
+ continue;
+ }
+ if (window->parent() != q) {
+ qCDebug(lcQuickWindow) << window << "is not yet child of this window";
+ continue;
+ }
+ qCDebug(lcQuickWindow) << "Raising" << window << "owned by" << windowContainer;
+ window->raise();
+ }
+
+ updateChildWindowStackingOrder(child);
+ }
+}
+
/*! \reimp */
void QQuickWindow::keyPressEvent(QKeyEvent *e)
{
@@ -3590,6 +3658,11 @@ void QQuickWindow::endExternalCommands()
default, depending on the window manager, it may also be necessary to set
the \l Window::flags property with a suitable \l Qt::WindowType (such as
\c Qt::Dialog).
+
+ If a \l{QtQuick::Window::parent}{visual parent} is set on the Window
+ the visual parent will take precedence over the transientParent.
+
+ \sa QtQuick::Window::parent
*/
/*!