summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/android/qandroidplatformwindow.cpp
diff options
context:
space:
mode:
authorTinja Paavoseppä <tinja.paavoseppa@qt.io>2023-09-19 14:55:12 +0300
committerTinja Paavoseppä <tinja.paavoseppa@qt.io>2023-12-08 15:53:37 +0200
commit6ff88f97a6d24d1098583421161f8f903f9dafde (patch)
tree47572de37222e50f4017243cdc1da851438b7f0d /src/plugins/platforms/android/qandroidplatformwindow.cpp
parent0a92d881bb91d3ff14187e7838af1cad9ad1070c (diff)
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>
Diffstat (limited to 'src/plugins/platforms/android/qandroidplatformwindow.cpp')
-rw-r--r--src/plugins/platforms/android/qandroidplatformwindow.cpp71
1 files changed, 53 insertions, 18 deletions
diff --git a/src/plugins/platforms/android/qandroidplatformwindow.cpp b/src/plugins/platforms/android/qandroidplatformwindow.cpp
index 1e30799ae4..9a633e97af 100644
--- a/src/plugins/platforms/android/qandroidplatformwindow.cpp
+++ b/src/plugins/platforms/android/qandroidplatformwindow.cpp
@@ -19,10 +19,9 @@ Q_LOGGING_CATEGORY(lcQpaWindow, "qt.qpa.window")
Q_CONSTINIT static QBasicAtomicInt winIdGenerator = Q_BASIC_ATOMIC_INITIALIZER(0);
QAndroidPlatformWindow::QAndroidPlatformWindow(QWindow *window)
- : QPlatformWindow(window), m_nativeQtWindow(QNativeInterface::QAndroidApplication::context()),
+ : QPlatformWindow(window), m_nativeQtWindow(nullptr), m_nativeParentQtWindow(nullptr),
m_androidSurfaceObject(nullptr)
{
- m_nativeViewId = m_nativeQtWindow.callMethod<jint>("getId");
m_windowFlags = Qt::Widget;
m_windowState = Qt::WindowNoState;
// the surfaceType is overwritten in QAndroidPlatformOpenGLWindow ctor so let's save
@@ -48,22 +47,44 @@ QAndroidPlatformWindow::QAndroidPlatformWindow(QWindow *window)
if (requestedNativeGeometry != finalNativeGeometry)
setGeometry(finalNativeGeometry);
}
- platformScreen()->addWindow(this);
+
+ if (parent())
+ m_nativeParentQtWindow = static_cast<QAndroidPlatformWindow*>(parent())->nativeWindow();
+
+ QNativeInterface::QAndroidApplication::runOnAndroidMainThread([this]() {
+ m_nativeQtWindow = QJniObject::construct<QtJniTypes::QtWindow>(
+ QNativeInterface::QAndroidApplication::context(),
+ m_nativeParentQtWindow);
+ m_nativeViewId = m_nativeQtWindow.callMethod<jint>("getId");
+ }).waitForFinished();
+
+ if (window->isTopLevel())
+ platformScreen()->addWindow(this);
}
QAndroidPlatformWindow::~QAndroidPlatformWindow()
{
- platformScreen()->removeWindow(this);
+ if (window()->isTopLevel())
+ platformScreen()->removeWindow(this);
}
void QAndroidPlatformWindow::lower()
{
+ if (m_nativeParentQtWindow.isValid()) {
+ m_nativeParentQtWindow.callMethod<void>("bringChildToBack", nativeViewId());
+ return;
+ }
platformScreen()->lower(this);
}
void QAndroidPlatformWindow::raise()
{
+ if (m_nativeParentQtWindow.isValid()) {
+ m_nativeParentQtWindow.callMethod<void>("bringChildToFront", nativeViewId());
+ QWindowSystemInterface::handleFocusWindowChanged(window(), Qt::ActiveWindowFocusReason);
+ return;
+ }
updateSystemUiVisibility();
platformScreen()->raise(this);
}
@@ -87,16 +108,20 @@ void QAndroidPlatformWindow::setGeometry(const QRect &rect)
void QAndroidPlatformWindow::setVisible(bool visible)
{
+ m_nativeQtWindow.callMethod<void>("setVisible", visible);
+
if (visible) {
- updateSystemUiVisibility();
- if ((m_windowState & Qt::WindowFullScreen)
- || ((m_windowState & Qt::WindowMaximized) && (window()->flags() & Qt::MaximizeUsingFullscreenGeometryHint))) {
- setGeometry(platformScreen()->geometry());
- } else if (m_windowState & Qt::WindowMaximized) {
- setGeometry(platformScreen()->availableGeometry());
+ if (window()->isTopLevel()) {
+ updateSystemUiVisibility();
+ if ((m_windowState & Qt::WindowFullScreen)
+ || ((m_windowState & Qt::WindowMaximized) && (window()->flags() & Qt::MaximizeUsingFullscreenGeometryHint))) {
+ setGeometry(platformScreen()->geometry());
+ } else if (m_windowState & Qt::WindowMaximized) {
+ setGeometry(platformScreen()->availableGeometry());
+ }
+ requestActivateWindow();
}
- requestActivateWindow();
- } else if (window() == qGuiApp->focusWindow()) {
+ } else if (window()->isTopLevel() && window() == qGuiApp->focusWindow()) {
platformScreen()->topVisibleWindowChanged();
}
@@ -132,13 +157,22 @@ Qt::WindowFlags QAndroidPlatformWindow::windowFlags() const
void QAndroidPlatformWindow::setParent(const QPlatformWindow *window)
{
- // even though we do not yet support child windows properly, any windows getting a parent
- // should be removed from screen's window stack which is only for top level windows,
- // and respectively any window becoming top level should go in there
+ using namespace QtJniTypes;
if (window) {
- platformScreen()->removeWindow(this);
+ // If we were a top level window, remove from screen
+ if (!m_nativeParentQtWindow.isValid())
+ platformScreen()->removeWindow(this);
+
+ const QAndroidPlatformWindow *androidWindow =
+ static_cast<const QAndroidPlatformWindow*>(window);
+ const QtWindow parentWindow = androidWindow->nativeWindow();
+ // If this was a child window of another window, the java method takes care of that
+ m_nativeQtWindow.callMethod<void, QtWindow>("setParent", parentWindow.object());
+ m_nativeParentQtWindow = parentWindow;
} else {
+ m_nativeQtWindow.callMethod<void, QtWindow>("setParent", nullptr);
platformScreen()->addWindow(this);
+ m_nativeParentQtWindow = QJniObject();
}
}
@@ -154,6 +188,7 @@ void QAndroidPlatformWindow::propagateSizeHints()
void QAndroidPlatformWindow::requestActivateWindow()
{
+ // raise() will handle differences between top level and child windows, and requesting focus
if (!blockedByModal())
raise();
}
@@ -214,7 +249,7 @@ void QAndroidPlatformWindow::destroySurface()
}
}
-void QAndroidPlatformWindow::setSurfaceGeometry(const QRect &geometry)
+void QAndroidPlatformWindow::setNativeGeometry(const QRect &geometry)
{
if (!m_surfaceCreated)
return;
@@ -229,7 +264,7 @@ void QAndroidPlatformWindow::setSurfaceGeometry(const QRect &geometry)
w = geometry.width();
h = geometry.height();
}
- m_nativeQtWindow.callMethod<void>("setSurfaceGeometry", x, y, w, h);
+ m_nativeQtWindow.callMethod<void>("setGeometry", x, y, w, h);
}
void QAndroidPlatformWindow::onSurfaceChanged(QtJniTypes::Surface surface)