diff options
author | Tor Arne Vestbø <tor.arne.vestbo@qt.io> | 2023-11-27 17:57:00 +0100 |
---|---|---|
committer | Tor Arne Vestbø <tor.arne.vestbo@qt.io> | 2023-12-08 13:22:34 +0100 |
commit | 27071a0a32917d2dcf9fbf56f4386ad3d2b91e9b (patch) | |
tree | 93764a7e2389cd00bbd21ba8858d2c9e8832bf77 /src/quick/items/qquickwindow.cpp | |
parent | dd18c4614ac5006d7df76024f361a96abc8027d0 (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.cpp | 73 |
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 */ /*! |