Android: Improve the foreign-window implementation
Adds: - Improved geometry calculations (e.g, inside a parent) - Change visibility - proper stacking order. Native views now reserve the top of the stack to ensure that they stay visible. - React to application state changes. Change-Id: I35de0396937fff37ffcd272c9a7d8e9873a91dfb Reviewed-by: Paul Olav Tvete <paul.tvete@digia.com>
This commit is contained in:
parent
c30687f519
commit
8b0d9a16db
@ -1025,8 +1025,8 @@ public class QtActivityDelegate
|
|||||||
view.setLayoutParams(new QtLayout.LayoutParams(w, h, x, y));
|
view.setLayoutParams(new QtLayout.LayoutParams(w, h, x, y));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
view.setId(id);
|
||||||
m_layout.addView(view);
|
m_layout.addView(view);
|
||||||
m_layout.bringChildToFront(view);
|
|
||||||
m_nativeViews.put(id, view);
|
m_nativeViews.put(id, view);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1057,9 +1057,11 @@ public class QtActivityDelegate
|
|||||||
surface.setLayoutParams( new QtLayout.LayoutParams(w, h, x, y));
|
surface.setLayoutParams( new QtLayout.LayoutParams(w, h, x, y));
|
||||||
}
|
}
|
||||||
|
|
||||||
m_layout.addView(surface);
|
// Native views are always inserted in the end of the stack (i.e., on top).
|
||||||
if (onTop)
|
// All other views are stacked based on the order they are created.
|
||||||
m_layout.bringChildToFront(surface);
|
final int index = m_layout.getChildCount() - m_nativeViews.size() - 1;
|
||||||
|
m_layout.addView(surface, index < 0 ? 0 : index);
|
||||||
|
|
||||||
m_surfaces.put(id, surface);
|
m_surfaces.put(id, surface);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1070,7 +1072,6 @@ public class QtActivityDelegate
|
|||||||
} else if (m_nativeViews.containsKey(id)) {
|
} else if (m_nativeViews.containsKey(id)) {
|
||||||
View view = m_nativeViews.get(id);
|
View view = m_nativeViews.get(id);
|
||||||
view.setLayoutParams(new QtLayout.LayoutParams(w, h, x, y));
|
view.setLayoutParams(new QtLayout.LayoutParams(w, h, x, y));
|
||||||
m_layout.bringChildToFront(view);
|
|
||||||
} else {
|
} else {
|
||||||
Log.e(QtNative.QtTAG, "Surface " + id +" not found!");
|
Log.e(QtNative.QtTAG, "Surface " + id +" not found!");
|
||||||
return;
|
return;
|
||||||
|
@ -69,7 +69,6 @@ static AAssetManager *m_assetManager = Q_NULLPTR;
|
|||||||
static jobject m_resourcesObj = Q_NULLPTR;
|
static jobject m_resourcesObj = Q_NULLPTR;
|
||||||
static jobject m_activityObject = Q_NULLPTR;
|
static jobject m_activityObject = Q_NULLPTR;
|
||||||
static jmethodID m_createSurfaceMethodID = Q_NULLPTR;
|
static jmethodID m_createSurfaceMethodID = Q_NULLPTR;
|
||||||
static jmethodID m_insertNativeViewMethodID = Q_NULLPTR;
|
|
||||||
static jmethodID m_setSurfaceGeometryMethodID = Q_NULLPTR;
|
static jmethodID m_setSurfaceGeometryMethodID = Q_NULLPTR;
|
||||||
static jmethodID m_destroySurfaceMethodID = Q_NULLPTR;
|
static jmethodID m_destroySurfaceMethodID = Q_NULLPTR;
|
||||||
|
|
||||||
@ -345,27 +344,24 @@ namespace QtAndroid
|
|||||||
|
|
||||||
int insertNativeView(jobject view, const QRect &geometry)
|
int insertNativeView(jobject view, const QRect &geometry)
|
||||||
{
|
{
|
||||||
QJNIEnvironmentPrivate env;
|
|
||||||
if (!env)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
m_surfacesMutex.lock();
|
m_surfacesMutex.lock();
|
||||||
const int surfaceId = m_surfaceId++;
|
const int surfaceId = m_surfaceId++;
|
||||||
|
m_surfaces[surfaceId] = Q_NULLPTR; // dummy
|
||||||
m_surfacesMutex.unlock();
|
m_surfacesMutex.unlock();
|
||||||
|
|
||||||
jint x = 0, y = 0, w = -1, h = -1;
|
jint x = 0, y = 0, w = -1, h = -1;
|
||||||
if (!geometry.isNull()) {
|
if (!geometry.isNull())
|
||||||
x = geometry.x();
|
geometry.getRect(&x, &y, &w, &h);
|
||||||
y = geometry.y();
|
|
||||||
w = std::max(geometry.width(), 1);
|
|
||||||
h = std::max(geometry.height(), 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
env->CallStaticVoidMethod(m_applicationClass,
|
QJNIObjectPrivate::callStaticMethod<void>(m_applicationClass,
|
||||||
m_insertNativeViewMethodID,
|
"insertNativeView",
|
||||||
|
"(ILandroid/view/View;IIII)V",
|
||||||
surfaceId,
|
surfaceId,
|
||||||
view,
|
view,
|
||||||
x, y, w, h);
|
x,
|
||||||
|
y,
|
||||||
|
qMax(w, 1),
|
||||||
|
qMax(h, 1));
|
||||||
|
|
||||||
return surfaceId;
|
return surfaceId;
|
||||||
}
|
}
|
||||||
@ -539,6 +535,9 @@ static void setSurface(JNIEnv *env, jobject /*thiz*/, jint id, jobject jSurface,
|
|||||||
{
|
{
|
||||||
QMutexLocker lock(&m_surfacesMutex);
|
QMutexLocker lock(&m_surfacesMutex);
|
||||||
const auto &it = m_surfaces.find(id);
|
const auto &it = m_surfaces.find(id);
|
||||||
|
if (it.value() == Q_NULLPTR) // This should never happen...
|
||||||
|
return;
|
||||||
|
|
||||||
if (it == m_surfaces.end()) {
|
if (it == m_surfaces.end()) {
|
||||||
qWarning()<<"Can't find surface" << id;
|
qWarning()<<"Can't find surface" << id;
|
||||||
return;
|
return;
|
||||||
@ -718,7 +717,6 @@ static int registerNatives(JNIEnv *env)
|
|||||||
}
|
}
|
||||||
|
|
||||||
GET_AND_CHECK_STATIC_METHOD(m_createSurfaceMethodID, m_applicationClass, "createSurface", "(IZIIIII)V");
|
GET_AND_CHECK_STATIC_METHOD(m_createSurfaceMethodID, m_applicationClass, "createSurface", "(IZIIIII)V");
|
||||||
GET_AND_CHECK_STATIC_METHOD(m_insertNativeViewMethodID, m_applicationClass, "insertNativeView", "(ILandroid/view/View;IIII)V");
|
|
||||||
GET_AND_CHECK_STATIC_METHOD(m_setSurfaceGeometryMethodID, m_applicationClass, "setSurfaceGeometry", "(IIIII)V");
|
GET_AND_CHECK_STATIC_METHOD(m_setSurfaceGeometryMethodID, m_applicationClass, "setSurfaceGeometry", "(IIIII)V");
|
||||||
GET_AND_CHECK_STATIC_METHOD(m_destroySurfaceMethodID, m_applicationClass, "destroySurface", "(I)V");
|
GET_AND_CHECK_STATIC_METHOD(m_destroySurfaceMethodID, m_applicationClass, "destroySurface", "(I)V");
|
||||||
|
|
||||||
|
@ -34,16 +34,17 @@
|
|||||||
#include "qandroidplatformforeignwindow.h"
|
#include "qandroidplatformforeignwindow.h"
|
||||||
#include "androidjnimain.h"
|
#include "androidjnimain.h"
|
||||||
#include <QtCore/qvariant.h>
|
#include <QtCore/qvariant.h>
|
||||||
|
#include <qpa/qwindowsysteminterface.h>
|
||||||
|
#include <QtCore/private/qjnihelpers_p.h>
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
QAndroidPlatformForeignWindow::QAndroidPlatformForeignWindow(QWindow *window)
|
QAndroidPlatformForeignWindow::QAndroidPlatformForeignWindow(QWindow *window)
|
||||||
: QAndroidPlatformWindow(window)
|
: QAndroidPlatformWindow(window),
|
||||||
|
m_surfaceId(-1)
|
||||||
{
|
{
|
||||||
const WId wId = window->property("_q_foreignWinId").value<WId>();
|
const WId wId = window->property("_q_foreignWinId").value<WId>();
|
||||||
if (wId) {
|
|
||||||
m_view = reinterpret_cast<jobject>(wId);
|
m_view = reinterpret_cast<jobject>(wId);
|
||||||
Q_ASSERT(m_view.isValid());
|
|
||||||
m_surfaceId = QtAndroid::insertNativeView(m_view.object(), geometry());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QAndroidPlatformForeignWindow::~QAndroidPlatformForeignWindow()
|
QAndroidPlatformForeignWindow::~QAndroidPlatformForeignWindow()
|
||||||
@ -54,9 +55,64 @@ QAndroidPlatformForeignWindow::~QAndroidPlatformForeignWindow()
|
|||||||
|
|
||||||
void QAndroidPlatformForeignWindow::setGeometry(const QRect &rect)
|
void QAndroidPlatformForeignWindow::setGeometry(const QRect &rect)
|
||||||
{
|
{
|
||||||
if (rect == geometry())
|
QWindow *parent = window()->parent();
|
||||||
|
QRect newGeometry = rect;
|
||||||
|
|
||||||
|
if (parent != 0)
|
||||||
|
newGeometry.moveTo(parent->mapToGlobal(rect.topLeft()));
|
||||||
|
|
||||||
|
if (newGeometry == geometry())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
QAndroidPlatformWindow::setGeometry(rect);
|
QAndroidPlatformWindow::setGeometry(newGeometry);
|
||||||
QtAndroid::setSurfaceGeometry(m_surfaceId, rect);
|
|
||||||
|
if (m_surfaceId != -1)
|
||||||
|
QtAndroid::setSurfaceGeometry(m_surfaceId, newGeometry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QAndroidPlatformForeignWindow::setVisible(bool visible)
|
||||||
|
{
|
||||||
|
if (!m_view.isValid())
|
||||||
|
return;
|
||||||
|
|
||||||
|
QAndroidPlatformWindow::setVisible(visible);
|
||||||
|
|
||||||
|
if (!visible && m_surfaceId != -1) {
|
||||||
|
QtAndroid::destroySurface(m_surfaceId);
|
||||||
|
m_surfaceId = -1;
|
||||||
|
} else if (m_surfaceId == -1) {
|
||||||
|
m_surfaceId = QtAndroid::insertNativeView(m_view.object(), geometry());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QAndroidPlatformForeignWindow::applicationStateChanged(Qt::ApplicationState state)
|
||||||
|
{
|
||||||
|
if (state <= Qt::ApplicationHidden
|
||||||
|
&& QtAndroid::blockEventLoopsWhenSuspended()
|
||||||
|
&& m_surfaceId != -1) {
|
||||||
|
QtAndroid::destroySurface(m_surfaceId);
|
||||||
|
m_surfaceId = -1;
|
||||||
|
} else if (m_view.isValid() && m_surfaceId == -1){
|
||||||
|
m_surfaceId = QtAndroid::insertNativeView(m_view.object(), geometry());
|
||||||
|
}
|
||||||
|
|
||||||
|
QAndroidPlatformWindow::applicationStateChanged(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QAndroidPlatformForeignWindow::setParent(const QPlatformWindow *window)
|
||||||
|
{
|
||||||
|
QRect newGeometry = geometry();
|
||||||
|
|
||||||
|
if (window != 0)
|
||||||
|
newGeometry.moveTo(window->mapToGlobal(geometry().topLeft()));
|
||||||
|
|
||||||
|
if (newGeometry != geometry())
|
||||||
|
QAndroidPlatformWindow::setGeometry(newGeometry);
|
||||||
|
|
||||||
|
if (m_surfaceId == -1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
QtAndroid::setSurfaceGeometry(m_surfaceId, newGeometry);
|
||||||
|
}
|
||||||
|
|
||||||
|
QT_END_NAMESPACE
|
||||||
|
@ -38,16 +38,23 @@
|
|||||||
#include "qandroidplatformwindow.h"
|
#include "qandroidplatformwindow.h"
|
||||||
#include <QtCore/private/qjni_p.h>
|
#include <QtCore/private/qjni_p.h>
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
class QAndroidPlatformForeignWindow : public QAndroidPlatformWindow
|
class QAndroidPlatformForeignWindow : public QAndroidPlatformWindow
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit QAndroidPlatformForeignWindow(QWindow *window);
|
explicit QAndroidPlatformForeignWindow(QWindow *window);
|
||||||
~QAndroidPlatformForeignWindow();
|
~QAndroidPlatformForeignWindow();
|
||||||
void setGeometry(const QRect &rect);
|
void setGeometry(const QRect &rect) Q_DECL_OVERRIDE;
|
||||||
|
void setVisible(bool visible) Q_DECL_OVERRIDE;
|
||||||
|
void applicationStateChanged(Qt::ApplicationState state) Q_DECL_OVERRIDE;
|
||||||
|
void setParent(const QPlatformWindow *window) Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
int m_surfaceId;
|
||||||
QJNIObjectPrivate m_view;
|
QJNIObjectPrivate m_view;
|
||||||
int m_surfaceId = -1;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
#endif // QANDROIDPLATFORMFOREIGNWINDOW_H
|
#endif // QANDROIDPLATFORMFOREIGNWINDOW_H
|
||||||
|
@ -65,6 +65,9 @@ public:
|
|||||||
void requestActivateWindow();
|
void requestActivateWindow();
|
||||||
void updateStatusBarVisibility();
|
void updateStatusBarVisibility();
|
||||||
inline bool isRaster() const {
|
inline bool isRaster() const {
|
||||||
|
if ((window()->flags() & Qt::ForeignWindow) == Qt::ForeignWindow)
|
||||||
|
return false;
|
||||||
|
|
||||||
return window()->surfaceType() == QSurface::RasterSurface
|
return window()->surfaceType() == QSurface::RasterSurface
|
||||||
|| window()->surfaceType() == QSurface::RasterGLSurface;
|
|| window()->surfaceType() == QSurface::RasterGLSurface;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user