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.setId(id);
|
||||
m_layout.addView(view);
|
||||
m_layout.bringChildToFront(view);
|
||||
m_nativeViews.put(id, view);
|
||||
}
|
||||
|
||||
@ -1057,9 +1057,11 @@ public class QtActivityDelegate
|
||||
surface.setLayoutParams( new QtLayout.LayoutParams(w, h, x, y));
|
||||
}
|
||||
|
||||
m_layout.addView(surface);
|
||||
if (onTop)
|
||||
m_layout.bringChildToFront(surface);
|
||||
// Native views are always inserted in the end of the stack (i.e., on top).
|
||||
// All other views are stacked based on the order they are created.
|
||||
final int index = m_layout.getChildCount() - m_nativeViews.size() - 1;
|
||||
m_layout.addView(surface, index < 0 ? 0 : index);
|
||||
|
||||
m_surfaces.put(id, surface);
|
||||
}
|
||||
|
||||
@ -1070,7 +1072,6 @@ public class QtActivityDelegate
|
||||
} else if (m_nativeViews.containsKey(id)) {
|
||||
View view = m_nativeViews.get(id);
|
||||
view.setLayoutParams(new QtLayout.LayoutParams(w, h, x, y));
|
||||
m_layout.bringChildToFront(view);
|
||||
} else {
|
||||
Log.e(QtNative.QtTAG, "Surface " + id +" not found!");
|
||||
return;
|
||||
|
@ -69,7 +69,6 @@ static AAssetManager *m_assetManager = Q_NULLPTR;
|
||||
static jobject m_resourcesObj = Q_NULLPTR;
|
||||
static jobject m_activityObject = Q_NULLPTR;
|
||||
static jmethodID m_createSurfaceMethodID = Q_NULLPTR;
|
||||
static jmethodID m_insertNativeViewMethodID = Q_NULLPTR;
|
||||
static jmethodID m_setSurfaceGeometryMethodID = Q_NULLPTR;
|
||||
static jmethodID m_destroySurfaceMethodID = Q_NULLPTR;
|
||||
|
||||
@ -345,27 +344,24 @@ namespace QtAndroid
|
||||
|
||||
int insertNativeView(jobject view, const QRect &geometry)
|
||||
{
|
||||
QJNIEnvironmentPrivate env;
|
||||
if (!env)
|
||||
return 0;
|
||||
|
||||
m_surfacesMutex.lock();
|
||||
const int surfaceId = m_surfaceId++;
|
||||
m_surfaces[surfaceId] = Q_NULLPTR; // dummy
|
||||
m_surfacesMutex.unlock();
|
||||
|
||||
jint x = 0, y = 0, w = -1, h = -1;
|
||||
if (!geometry.isNull()) {
|
||||
x = geometry.x();
|
||||
y = geometry.y();
|
||||
w = std::max(geometry.width(), 1);
|
||||
h = std::max(geometry.height(), 1);
|
||||
}
|
||||
if (!geometry.isNull())
|
||||
geometry.getRect(&x, &y, &w, &h);
|
||||
|
||||
env->CallStaticVoidMethod(m_applicationClass,
|
||||
m_insertNativeViewMethodID,
|
||||
surfaceId,
|
||||
view,
|
||||
x, y, w, h);
|
||||
QJNIObjectPrivate::callStaticMethod<void>(m_applicationClass,
|
||||
"insertNativeView",
|
||||
"(ILandroid/view/View;IIII)V",
|
||||
surfaceId,
|
||||
view,
|
||||
x,
|
||||
y,
|
||||
qMax(w, 1),
|
||||
qMax(h, 1));
|
||||
|
||||
return surfaceId;
|
||||
}
|
||||
@ -539,6 +535,9 @@ static void setSurface(JNIEnv *env, jobject /*thiz*/, jint id, jobject jSurface,
|
||||
{
|
||||
QMutexLocker lock(&m_surfacesMutex);
|
||||
const auto &it = m_surfaces.find(id);
|
||||
if (it.value() == Q_NULLPTR) // This should never happen...
|
||||
return;
|
||||
|
||||
if (it == m_surfaces.end()) {
|
||||
qWarning()<<"Can't find surface" << id;
|
||||
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_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_destroySurfaceMethodID, m_applicationClass, "destroySurface", "(I)V");
|
||||
|
||||
|
@ -34,16 +34,17 @@
|
||||
#include "qandroidplatformforeignwindow.h"
|
||||
#include "androidjnimain.h"
|
||||
#include <QtCore/qvariant.h>
|
||||
#include <qpa/qwindowsysteminterface.h>
|
||||
#include <QtCore/private/qjnihelpers_p.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
QAndroidPlatformForeignWindow::QAndroidPlatformForeignWindow(QWindow *window)
|
||||
: QAndroidPlatformWindow(window)
|
||||
: QAndroidPlatformWindow(window),
|
||||
m_surfaceId(-1)
|
||||
{
|
||||
const WId wId = window->property("_q_foreignWinId").value<WId>();
|
||||
if (wId) {
|
||||
m_view = reinterpret_cast<jobject>(wId);
|
||||
Q_ASSERT(m_view.isValid());
|
||||
m_surfaceId = QtAndroid::insertNativeView(m_view.object(), geometry());
|
||||
}
|
||||
m_view = reinterpret_cast<jobject>(wId);
|
||||
}
|
||||
|
||||
QAndroidPlatformForeignWindow::~QAndroidPlatformForeignWindow()
|
||||
@ -54,9 +55,64 @@ QAndroidPlatformForeignWindow::~QAndroidPlatformForeignWindow()
|
||||
|
||||
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;
|
||||
|
||||
QAndroidPlatformWindow::setGeometry(rect);
|
||||
QtAndroid::setSurfaceGeometry(m_surfaceId, rect);
|
||||
QAndroidPlatformWindow::setGeometry(newGeometry);
|
||||
|
||||
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 <QtCore/private/qjni_p.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QAndroidPlatformForeignWindow : public QAndroidPlatformWindow
|
||||
{
|
||||
public:
|
||||
explicit QAndroidPlatformForeignWindow(QWindow *window);
|
||||
~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:
|
||||
int m_surfaceId;
|
||||
QJNIObjectPrivate m_view;
|
||||
int m_surfaceId = -1;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QANDROIDPLATFORMFOREIGNWINDOW_H
|
||||
|
@ -65,6 +65,9 @@ public:
|
||||
void requestActivateWindow();
|
||||
void updateStatusBarVisibility();
|
||||
inline bool isRaster() const {
|
||||
if ((window()->flags() & Qt::ForeignWindow) == Qt::ForeignWindow)
|
||||
return false;
|
||||
|
||||
return window()->surfaceType() == QSurface::RasterSurface
|
||||
|| window()->surfaceType() == QSurface::RasterGLSurface;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user