diff options
author | Tinja Paavoseppä <tinja.paavoseppa@qt.io> | 2023-09-05 09:01:46 +0300 |
---|---|---|
committer | Tinja Paavoseppä <tinja.paavoseppa@qt.io> | 2023-12-08 15:53:36 +0200 |
commit | 0a92d881bb91d3ff14187e7838af1cad9ad1070c (patch) | |
tree | 0ff35b64f6213d749d1da9fa10746632b06a5dfd /src/plugins/platforms/android/qandroidplatformwindow.cpp | |
parent | 0bfec6cd1183f4985733e355f01f6e12df2fb2be (diff) |
Android: Make QtLayout per window instead of per screen
Each QAndroidPlatformWindow has its own QtLayout,
instead of one for the whole app/screen. This paves the
way for addition of child windows.
Task-number: QTBUG-116187
Change-Id: I36c68cea1a5f27ded3696bcfc2fbc04d9a8ce79e
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io>
Diffstat (limited to 'src/plugins/platforms/android/qandroidplatformwindow.cpp')
-rw-r--r-- | src/plugins/platforms/android/qandroidplatformwindow.cpp | 132 |
1 files changed, 105 insertions, 27 deletions
diff --git a/src/plugins/platforms/android/qandroidplatformwindow.cpp b/src/plugins/platforms/android/qandroidplatformwindow.cpp index 23b83834d4..1e30799ae4 100644 --- a/src/plugins/platforms/android/qandroidplatformwindow.cpp +++ b/src/plugins/platforms/android/qandroidplatformwindow.cpp @@ -14,11 +14,15 @@ QT_BEGIN_NAMESPACE +Q_LOGGING_CATEGORY(lcQpaWindow, "qt.qpa.window") + Q_CONSTINIT static QBasicAtomicInt winIdGenerator = Q_BASIC_ATOMIC_INITIALIZER(0); QAndroidPlatformWindow::QAndroidPlatformWindow(QWindow *window) - : QPlatformWindow(window), m_androidSurfaceObject(nullptr) + : QPlatformWindow(window), m_nativeQtWindow(QNativeInterface::QAndroidApplication::context()), + 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 @@ -44,8 +48,15 @@ QAndroidPlatformWindow::QAndroidPlatformWindow(QWindow *window) if (requestedNativeGeometry != finalNativeGeometry) setGeometry(finalNativeGeometry); } + platformScreen()->addWindow(this); +} + +QAndroidPlatformWindow::~QAndroidPlatformWindow() +{ + platformScreen()->removeWindow(this); } + void QAndroidPlatformWindow::lower() { platformScreen()->lower(this); @@ -76,23 +87,19 @@ void QAndroidPlatformWindow::setGeometry(const QRect &rect) void QAndroidPlatformWindow::setVisible(bool visible) { - if (visible) - updateSystemUiVisibility(); - 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()); } + requestActivateWindow(); + } else if (window() == qGuiApp->focusWindow()) { + platformScreen()->topVisibleWindowChanged(); } - if (visible) - platformScreen()->addWindow(this); - else - platformScreen()->removeWindow(this); - QRect availableGeometry = screen()->availableGeometry(); if (geometry().width() > 0 && geometry().height() > 0 && availableGeometry.width() > 0 && availableGeometry.height() > 0) QPlatformWindow::setVisible(visible); @@ -125,7 +132,14 @@ Qt::WindowFlags QAndroidPlatformWindow::windowFlags() const void QAndroidPlatformWindow::setParent(const QPlatformWindow *window) { - Q_UNUSED(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 + if (window) { + platformScreen()->removeWindow(this); + } else { + platformScreen()->addWindow(this); + } } QAndroidPlatformScreen *QAndroidPlatformWindow::platformScreen() const @@ -140,7 +154,8 @@ void QAndroidPlatformWindow::propagateSizeHints() void QAndroidPlatformWindow::requestActivateWindow() { - platformScreen()->topWindowChanged(window()); + if (!blockedByModal()) + raise(); } void QAndroidPlatformWindow::updateSystemUiVisibility() @@ -176,25 +191,62 @@ void QAndroidPlatformWindow::applicationStateChanged(Qt::ApplicationState) void QAndroidPlatformWindow::createSurface() { + const QRect rect = geometry(); + jint x = 0, y = 0, w = -1, h = -1; + if (!rect.isNull()) { + x = rect.x(); + y = rect.y(); + w = std::max(rect.width(), 1); + h = std::max(rect.height(), 1); + } + const bool windowStaysOnTop = bool(window()->flags() & Qt::WindowStaysOnTopHint); - m_nativeSurfaceId = QtAndroid::createSurface(this, geometry(), windowStaysOnTop, 32); + + m_nativeQtWindow.callMethod<void>("createSurface", windowStaysOnTop, x, y, w, h, 32); + m_surfaceCreated = true; } void QAndroidPlatformWindow::destroySurface() { - if (m_nativeSurfaceId != -1) { - QtAndroid::destroySurface(m_nativeSurfaceId); - m_nativeSurfaceId = -1; + if (m_surfaceCreated) { + m_nativeQtWindow.callMethod<void>("destroySurface"); + m_surfaceCreated = false; } } -void QAndroidPlatformWindow::setSurfaceGeometry(const QRect &rect) +void QAndroidPlatformWindow::setSurfaceGeometry(const QRect &geometry) { - if (m_nativeSurfaceId != -1) - QtAndroid::setSurfaceGeometry(m_nativeSurfaceId, rect); + if (!m_surfaceCreated) + return; + + jint x = 0; + jint y = 0; + jint w = -1; + jint h = -1; + if (!geometry.isNull()) { + x = geometry.x(); + y = geometry.y(); + w = geometry.width(); + h = geometry.height(); + } + m_nativeQtWindow.callMethod<void>("setSurfaceGeometry", x, y, w, h); } -void QAndroidPlatformWindow::sendExpose() +void QAndroidPlatformWindow::onSurfaceChanged(QtJniTypes::Surface surface) +{ + lockSurface(); + m_androidSurfaceObject = surface; + if (m_androidSurfaceObject.isValid()) // wait until we have a valid surface to draw into + m_surfaceWaitCondition.wakeOne(); + unlockSurface(); + + if (m_androidSurfaceObject.isValid()) { + // repaint the window, when we have a valid surface + sendExpose(); + } +} + +void QAndroidPlatformWindow::sendExpose() const { QRect availableGeometry = screen()->availableGeometry(); if (!geometry().isNull() && !availableGeometry.isNull()) { @@ -203,15 +255,41 @@ void QAndroidPlatformWindow::sendExpose() } } -void QAndroidPlatformWindow::onSurfaceChanged(QtJniTypes::Surface surface) +bool QAndroidPlatformWindow::blockedByModal() const { - lockSurface(); - m_androidSurfaceObject = surface; - if (m_androidSurfaceObject.isValid()) - m_surfaceWaitCondition.wakeOne(); - unlockSurface(); - if (m_androidSurfaceObject.isValid()) - sendExpose(); + QWindow *modalWindow = QGuiApplication::modalWindow(); + return modalWindow && modalWindow != window(); +} + +void QAndroidPlatformWindow::setSurface(JNIEnv *env, jobject object, jint windowId, + QtJniTypes::Surface surface) +{ + Q_UNUSED(env) + Q_UNUSED(object) + + if (!qGuiApp) + return; + + const QList<QWindow*> windows = qGuiApp->allWindows(); + for (QWindow * window : windows) { + if (!window->handle()) + continue; + QAndroidPlatformWindow *platformWindow = + static_cast<QAndroidPlatformWindow *>(window->handle()); + if (platformWindow->nativeViewId() == windowId) + platformWindow->onSurfaceChanged(surface); + } +} + +bool QAndroidPlatformWindow::registerNatives(QJniEnvironment &env) +{ + if (!env.registerNativeMethods(QtJniTypes::Traits<QtJniTypes::QtWindow>::className(), + {Q_JNI_NATIVE_SCOPED_METHOD(setSurface, QAndroidPlatformWindow)})) { + qCCritical(lcQpaWindow) << "RegisterNatives failed for" + << QtJniTypes::Traits<QtJniTypes::QtWindow>::className(); + return false; + } + return true; } QT_END_NAMESPACE |