Revision control

++ // Copyright (C) 2024 The Qt Company Ltd.
++ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
++
++ /*!
++ \title Window Hosting Example
++ \ingroup examples-widgets
++ \example demos/windowhosting
++ \examplecategory {User Interface Components}
++ \meta {tag} {demo,gui,quick,widgets}
++ \brief A demonstration of how to host non-Qt UI elements in Qt applications.
++
++ Qt offers a wide range of UI controls for both Qt Widget and Qt Quick-based
++ applications, but sometimes it may be desirable to use controls from other
++ UI toolkits, such as the platform's native UI toolkit.
++
++ To integrate these controls, we build upon the QWindow abstraction in Qt, by creating a
++ QWindow representation of the native UI control, that can then be hosted within the Qt UI.
++ A window created in this manner is known in Qt as a \e{foreign window}, as it represents a
++ control created by a foreign (to Qt) UI toolkit.
++
++ \section1 Creating a foreign window
++
++ To create the QWindow representation we use QWindow::fromWinId(), passing a reference to a
++ native window handle, represented by the opaque WId type.
++
++ Each platform defines what native type the WId opaque type maps to.
++
++ \include platformintegration.qdocinc winid-types
++
++ The result is a QWindow that represents the native window handle.
++
++ \include platformintegration.qdocinc winid-ownership-note
++
++ Now, before we can create a QWindow using QWindow::fromWinId() we need a native window handle.
++ In this example, we will host a month calendar control, as most platforms have it in their
++ native UI toolkits, or otherwise readily available. The specifics of how to create the
++ calendar on each platform are shown in the code snippets below.
++
++ To ensure that the native handle stays alive, but is also cleaned up properly on
++ application exit, we maintain a list of cleanup functions that we execute before
++ returning from \c main().
++
++ In addition to creating the native window handle and turning that into a QWindow,
++ we also set a minimum size on the resulting QWindow, based on what the native toolkit
++ reports as the preferred minimum size of the calendar control. This allows
++
++ Qt to lay out the hosted foreign window properly.
++
++ \if defined(onlinedocs)
++ \tab {from-win-id}{macos}{macOS}{checked}
++ \tab {from-win-id}{windows}{Windows}{}
++ \tab {from-win-id}{x11}{X11}{}
++ \tab {from-win-id}{ios}{iOS}{}
++ \tab {from-win-id}{android}{Android}{}
++ \tab {from-win-id}{webassembly}{WebAssembly}{}
++ \endif
++
++ \if defined(onlinedocs)
++ \tabcontent {macos}
++ \else
++ \section2 macOS
++ \endif
++ \inlineimage macos.webp {Qt GUI, Qt Widgets, and Qt Quick windows hosting a macOS calendar}
++ \snippet demos/windowhosting/main.cpp macos
++ \if defined(onlinedocs)
++ \endtabcontent
++ \endif
++
++ \if defined(onlinedocs)
++ \tabcontent {windows}
++ \else
++ \section2 Windows
++ \endif
++ \inlineimage windows.webp
++ {Qt GUI, Qt Widgets, and Qt Quick windows hosting a Windows calendar}
++ \snippet demos/windowhosting/main.cpp windows
++ \if defined(onlinedocs)
++ \endtabcontent
++ \endif
++
++ \if defined(onlinedocs)
++ \tabcontent {x11}
++ \else
++ \section2 X11
++ \endif
++ \inlineimage x11.webp {Qt GUI, Qt Widgets, and Qt Quick windows hosting a GTK calendar}
++ \snippet demos/windowhosting/main.cpp x11
++ \if defined(onlinedocs)
++ \endtabcontent
++ \endif
++
++ \if defined(onlinedocs)
++ \tabcontent {ios}
++ \else
++ \section2 iOS
++ \endif
++ \inlineimage ios.webp {Qt GUI, Qt Widgets, and Qt Quick containers hosting an iOS calendar}
++
++ \snippet demos/windowhosting/main.cpp ios
++ \if defined(onlinedocs)
++ \endtabcontent
++ \endif
++
++ \if defined(onlinedocs)
++ \tabcontent {android}
++ \else
++ \section2 Android
++ \endif
++ \inlineimage android.webp {Qt GUI, Qt Widgets, and Qt Quick containers hosting an Android calendar}
++
++ \snippet demos/windowhosting/main.cpp android
++ \if defined(onlinedocs)
++ \endtabcontent
++ \endif
++
++ \if defined(onlinedocs)
++ \tabcontent {webassembly}
++ \else
++ \section2 WebAssembly
++ \endif
++ \inlineimage webassembly.webp {Qt GUI, Qt Widgets, and Qt Quick windows hosting a calendar on a WebAssembly calendar}
++ \snippet demos/windowhosting/main.cpp webassembly
++ \if defined(onlinedocs)
++ \endtabcontent
++ \endif
++
++ \section1 Hosting a foreign window
++
++ Now that we have a foreign QWindow, we can host it in a Qt UI.
++ We have several options here, as described below.
++
++ \section2 Hosting in Qt GUI
++
++ At the lowest level, we can host the foreign window by reparenting it into
++ another QWindow, via QWindow::setParent(). This approach leaves it up to
++ the application developer to handle positioning, resizing, and other aspects
++ of managing the hosted child window, so we generally advise against
++
++ integrating on this level, if at all possible.
++
++ In this example we first create a minimal container window implementation.
++
++ \snippet demos/windowhosting/main.cpp qt-gui-container-window
++
++ Which we can then reparent our foreign window into.
++
++ \snippet demos/windowhosting/main.cpp qt-gui
++
++ \section2 Hosting in Qt Widgets
++
++ For applications built on the Qt Widgets UI stack we follow the same approach
++ as for QWindow::fromWinId(), by creating a QWidget representation of the
++ QWindow, via QWidget::createWindowContainer().
++
++ We could then reparent the widget into another widget, via QWidget::setParent(),
++ with the same caveats as the Qt GUI example above of having to manage positioning,
++ resizing, etc. manually. In this example we prefer to add the window container
++ widget to a QVBoxLayout, which allows us to automatically center the foreign
++ window inside the top level widget.
++
++ \snippet demos/windowhosting/main.cpp qt-widgets
++
++ \section2 Hosting in Qt Quick
++
++ Finally, for applications built on the Qt Quick UI stack, we use the WindowContainer
++ item to manage the foreign window.
++
++ \snippet demos/windowhosting/Main.qml qt-quick
++
++ In this example the foreign window is exposed to the QML engine as an initial property,
++ but this could be solved in different ways depending on the needs of the application.
++
++ \snippet demos/windowhosting/main.cpp qt-quick
++ */