2023-08-02 13:34:36 +00:00
|
|
|
// Copyright (C) 2023 The Qt Company Ltd.
|
|
|
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
|
|
|
|
|
|
|
#include <QtGui>
|
|
|
|
|
Android: Add preliminary support for child windows
Update the manual test case for embedded windows to have
native window on Android.
There are still some sharp corners, for example:
* The windows are implemented with SurfaceViews, which makes
z-ordering with multiple of them a bit tricky. The Surfaces
they instantiate are basically z-ordered to either be below
everything, with a hole punched in the window, or on top of
everything, with the Surfaces created later on top of the
ones created earlier. Also, with the foreign views it looks
like the native view is on top of the Surface, because it
is created later. And since the child windows create their
Surfaces before the parent, they would be behind the parent
window, currently circumventing this with letting the
parent be z-ordered behind everything, and the children
on top of everything. A follow up commit addresses this by
changing the native view class to TextureView when multiple
windows are present.
* Parent window always gets the touch events - fixed in
a follow up commit
* If a child window has a text edit, it does not receive
focus when clicking on it
Task-number: QTBUG-116187
Change-Id: I32188ec5e3d3fce9fd8e3a931e317d1e081f691c
Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io>
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
2023-09-19 11:55:12 +00:00
|
|
|
#if defined(Q_OS_MACOS) || defined(Q_OS_IOS) || defined(Q_OS_WIN) || QT_CONFIG(xcb) || defined(ANDROID)
|
2023-08-02 13:34:36 +00:00
|
|
|
#include "../../shared/nativewindow.h"
|
2023-08-08 13:01:23 +00:00
|
|
|
#define HAVE_NATIVE_WINDOW
|
|
|
|
#endif
|
2023-08-02 13:34:36 +00:00
|
|
|
|
|
|
|
#include <QDebug>
|
|
|
|
|
|
|
|
class TestWindow : public QRasterWindow
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
using QRasterWindow::QRasterWindow;
|
|
|
|
TestWindow(const QBrush &brush) : m_brush(brush) {}
|
|
|
|
|
|
|
|
protected:
|
|
|
|
void mousePressEvent(QMouseEvent *) override
|
|
|
|
{
|
|
|
|
m_pressed = true;
|
|
|
|
update();
|
|
|
|
}
|
|
|
|
|
|
|
|
void mouseReleaseEvent(QMouseEvent *) override
|
|
|
|
{
|
|
|
|
m_pressed = false;
|
|
|
|
update();
|
|
|
|
}
|
|
|
|
|
2023-08-15 19:48:05 +00:00
|
|
|
void paintEvent(QPaintEvent *) override
|
2023-08-02 13:34:36 +00:00
|
|
|
{
|
|
|
|
QPainter painter(this);
|
|
|
|
painter.setCompositionMode(QPainter::CompositionMode_Source);
|
2023-08-15 19:49:03 +00:00
|
|
|
if (!mask().isNull())
|
|
|
|
painter.setClipRegion(mask());
|
2023-08-15 19:48:05 +00:00
|
|
|
painter.fillRect(QRect(0, 0, width(), height()),
|
|
|
|
m_pressed ? QGradient(QGradient::JuicyPeach) : m_brush);
|
2023-08-02 13:34:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
QBrush m_brush = QGradient(QGradient::DustyGrass);
|
|
|
|
bool m_pressed = false;
|
|
|
|
};
|
|
|
|
|
|
|
|
int main(int argc, char *argv[])
|
|
|
|
{
|
|
|
|
QGuiApplication app(argc, argv);
|
|
|
|
|
|
|
|
TestWindow window{QGradient(QGradient::WinterNeva)};
|
|
|
|
window.resize(500, 500);
|
|
|
|
|
|
|
|
TestWindow *opaqueChildWindow = new TestWindow;
|
|
|
|
opaqueChildWindow->setParent(&window);
|
|
|
|
opaqueChildWindow->setGeometry(50, 50, 100, 100);
|
|
|
|
opaqueChildWindow->showNormal();
|
|
|
|
|
|
|
|
TestWindow *maskedChildWindow = new TestWindow;
|
|
|
|
maskedChildWindow->setParent(&window);
|
|
|
|
maskedChildWindow->setGeometry(200, 50, 100, 100);
|
|
|
|
maskedChildWindow->setMask(QRegion(0, 0, 100, 100, QRegion::Ellipse));
|
|
|
|
maskedChildWindow->showNormal();
|
|
|
|
|
|
|
|
static const QColor transparentGreen = QColor(0, 255, 0, 20);
|
|
|
|
TestWindow *transparentChildWindow = new TestWindow(transparentGreen);
|
|
|
|
// The default surface format of a platform may not include
|
|
|
|
// an alpha, so set it explicitly.
|
|
|
|
QSurfaceFormat format = transparentChildWindow->format();
|
|
|
|
format.setAlphaBufferSize(8);
|
|
|
|
transparentChildWindow->setFormat(format);
|
|
|
|
// FIXME: Windows requires this, even for child windows
|
|
|
|
transparentChildWindow->setFlag(Qt::FramelessWindowHint);
|
|
|
|
transparentChildWindow->setParent(&window);
|
|
|
|
transparentChildWindow->setGeometry(350, 50, 100, 100);
|
|
|
|
transparentChildWindow->showNormal();
|
|
|
|
|
2023-08-08 13:01:23 +00:00
|
|
|
#if defined(HAVE_NATIVE_WINDOW)
|
2023-08-02 13:34:36 +00:00
|
|
|
NativeWindow nativeWindow;
|
|
|
|
if (QWindow *foreignWindow = QWindow::fromWinId(nativeWindow)) {
|
|
|
|
foreignWindow->setParent(&window);
|
|
|
|
foreignWindow->setGeometry(50, 200, 100, 100);
|
|
|
|
foreignWindow->showNormal();
|
|
|
|
}
|
|
|
|
|
|
|
|
NativeWindow maskedNativeWindow;
|
|
|
|
if (QWindow *foreignWindow = QWindow::fromWinId(maskedNativeWindow)) {
|
|
|
|
foreignWindow->setParent(&window);
|
|
|
|
foreignWindow->setGeometry(200, 200, 100, 100);
|
|
|
|
foreignWindow->setMask(QRegion(0, 0, 100, 100, QRegion::Ellipse));
|
|
|
|
foreignWindow->showNormal();
|
|
|
|
}
|
|
|
|
|
|
|
|
NativeWindow nativeParentWindow;
|
|
|
|
if (QWindow *foreignWindow = QWindow::fromWinId(nativeParentWindow)) {
|
|
|
|
foreignWindow->setParent(&window);
|
|
|
|
foreignWindow->setGeometry(50, 350, 100, 100);
|
|
|
|
foreignWindow->showNormal();
|
|
|
|
|
|
|
|
TestWindow *maskedChildWindowOfNativeWindow = new TestWindow;
|
|
|
|
maskedChildWindowOfNativeWindow->setParent(foreignWindow);
|
|
|
|
maskedChildWindowOfNativeWindow->setGeometry(25, 25, 50, 50);
|
|
|
|
maskedChildWindowOfNativeWindow->showNormal();
|
|
|
|
}
|
2023-08-08 13:01:23 +00:00
|
|
|
#endif
|
2023-08-02 13:34:36 +00:00
|
|
|
|
|
|
|
window.show();
|
|
|
|
|
|
|
|
return app.exec();
|
|
|
|
}
|