Android: Add support for foreign window acting as embedding container

In the case when our foreign window is created to act as a parent for
embedding Qt content into a native Android app, we need a more "hands
off"
approach. If the foreign window represents an Android view which the
user
has created outside of Qt, we should not try to reparent it since it
already has a parent in the view hierarchy. Neither should we try to
remove it from the hierarchy, or set its visibility.

Change-Id: Iea496578a40f45ebdd73947a1bb0e46a7131108c
Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io>
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
(cherry picked from commit 5ba91c9decb4d13d7f7176bc7ce29b40007a19c5)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Tinja Paavoseppä 2023-10-31 14:52:30 +02:00 committed by Qt Cherry-pick Bot
parent 2112dfe313
commit 030a60d681
4 changed files with 45 additions and 6 deletions

View File

@ -14,12 +14,20 @@ QAndroidPlatformForeignWindow::QAndroidPlatformForeignWindow(QWindow *window, WI
: QAndroidPlatformWindow(window), m_view(nullptr), m_nativeViewInserted(false)
{
m_view = reinterpret_cast<jobject>(nativeHandle);
if (isEmbeddingContainer()) {
m_nativeViewId = m_view.callMethod<jint>("getId");
return;
}
if (m_view.isValid())
QtAndroid::setViewVisibility(m_view.object(), false);
}
QAndroidPlatformForeignWindow::~QAndroidPlatformForeignWindow()
{
if (isEmbeddingContainer())
return;
if (m_view.isValid())
QtAndroid::setViewVisibility(m_view.object(), false);
@ -31,13 +39,16 @@ void QAndroidPlatformForeignWindow::setGeometry(const QRect &rect)
{
QAndroidPlatformWindow::setGeometry(rect);
if (isEmbeddingContainer())
return;
if (m_nativeViewInserted)
setNativeGeometry(rect);
}
void QAndroidPlatformForeignWindow::setVisible(bool visible)
{
if (!m_view.isValid())
if (!m_view.isValid() || isEmbeddingContainer())
return;
QtAndroid::setViewVisibility(m_view.object(), visible);
@ -53,18 +64,33 @@ void QAndroidPlatformForeignWindow::setVisible(bool visible)
void QAndroidPlatformForeignWindow::applicationStateChanged(Qt::ApplicationState state)
{
if (state <= Qt::ApplicationHidden && m_nativeViewInserted) {
m_nativeQtWindow.callMethod<void>("removeNativeView");
m_nativeViewInserted = false;
} else if (m_view.isValid() && !m_nativeViewInserted){
addViewToWindow();
if (!isEmbeddingContainer()) {
if (state <= Qt::ApplicationHidden
&& m_nativeViewInserted) {
m_nativeQtWindow.callMethod<void>("removeNativeView");
m_nativeViewInserted = false;
} else if (m_view.isValid() && !m_nativeViewInserted){
addViewToWindow();
}
}
QAndroidPlatformWindow::applicationStateChanged(state);
}
WId QAndroidPlatformForeignWindow::winId() const
{
if (isEmbeddingContainer() && m_view.isValid())
return reinterpret_cast<WId>(m_view.object());
if (m_nativeQtWindow.isValid())
return reinterpret_cast<WId>(m_nativeQtWindow.object());
return 0L;
}
void QAndroidPlatformForeignWindow::addViewToWindow()
{
if (isEmbeddingContainer())
return;
jint x = 0, y = 0, w = -1, h = -1;
if (!geometry().isNull())
geometry().getRect(&x, &y, &w, &h);

View File

@ -22,6 +22,8 @@ public:
void applicationStateChanged(Qt::ApplicationState state) override;
bool isForeignWindow() const override { return true; }
WId winId() const override;
private:
void addViewToWindow();

View File

@ -45,6 +45,9 @@ QAndroidPlatformWindow::QAndroidPlatformWindow(QWindow *window)
setGeometry(finalNativeGeometry);
}
if (isEmbeddingContainer())
return;
if (parent())
m_nativeParentQtWindow = static_cast<QAndroidPlatformWindow*>(parent())->nativeWindow();
@ -296,6 +299,13 @@ bool QAndroidPlatformWindow::blockedByModal() const
return modalWindow && modalWindow != window();
}
bool QAndroidPlatformWindow::isEmbeddingContainer() const
{
// Returns true if the window is a wrapper for a foreign window solely to allow embedding Qt
// into a native Android app, in which case we should not try to control it more than we "need" to
return !QtAndroid::isQtApplication() && window()->isTopLevel();
}
void QAndroidPlatformWindow::setSurface(JNIEnv *env, jobject object, jint windowId,
QtJniTypes::Surface surface)
{

View File

@ -69,6 +69,7 @@ protected:
void setNativeGeometry(const QRect &geometry);
void sendExpose() const;
bool blockedByModal() const;
bool isEmbeddingContainer() const;
Qt::WindowFlags m_windowFlags;
Qt::WindowStates m_windowState;