summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorChristian Strømme <christian.stromme@digia.com>2014-08-28 12:18:14 +0200
committerChristian Stromme <christian.stromme@digia.com>2014-09-26 23:44:42 +0200
commit8b0d9a16db7bcfb5d6439b8863aded5c583f9ed5 (patch)
tree5fca60950d6e7dba1f12f9ceda0e564965d35116 /src
parentc30687f519de47279a70c3eca95eec2191eddbb1 (diff)
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>
Diffstat (limited to 'src')
-rw-r--r--src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java11
-rw-r--r--src/plugins/platforms/android/androidjnimain.cpp34
-rw-r--r--src/plugins/platforms/android/qandroidplatformforeignwindow.cpp74
-rw-r--r--src/plugins/platforms/android/qandroidplatformforeignwindow.h11
-rw-r--r--src/plugins/platforms/android/qandroidplatformwindow.h3
5 files changed, 99 insertions, 34 deletions
diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java b/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java
index db970b6656..9507d7eb3b 100644
--- a/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java
+++ b/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java
@@ -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;
diff --git a/src/plugins/platforms/android/androidjnimain.cpp b/src/plugins/platforms/android/androidjnimain.cpp
index be1fd49c0c..17a587b333 100644
--- a/src/plugins/platforms/android/androidjnimain.cpp
+++ b/src/plugins/platforms/android/androidjnimain.cpp
@@ -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);
- }
-
- env->CallStaticVoidMethod(m_applicationClass,
- m_insertNativeViewMethodID,
- surfaceId,
- view,
- x, y, w, h);
+ if (!geometry.isNull())
+ geometry.getRect(&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");
diff --git a/src/plugins/platforms/android/qandroidplatformforeignwindow.cpp b/src/plugins/platforms/android/qandroidplatformforeignwindow.cpp
index e8f7b3d145..af409d13a0 100644
--- a/src/plugins/platforms/android/qandroidplatformforeignwindow.cpp
+++ b/src/plugins/platforms/android/qandroidplatformforeignwindow.cpp
@@ -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(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;
- QAndroidPlatformWindow::setGeometry(rect);
- QtAndroid::setSurfaceGeometry(m_surfaceId, rect);
+ QtAndroid::setSurfaceGeometry(m_surfaceId, newGeometry);
}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/android/qandroidplatformforeignwindow.h b/src/plugins/platforms/android/qandroidplatformforeignwindow.h
index cb04142696..974ffbc376 100644
--- a/src/plugins/platforms/android/qandroidplatformforeignwindow.h
+++ b/src/plugins/platforms/android/qandroidplatformforeignwindow.h
@@ -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
diff --git a/src/plugins/platforms/android/qandroidplatformwindow.h b/src/plugins/platforms/android/qandroidplatformwindow.h
index f01f36ee27..edf062bcb4 100644
--- a/src/plugins/platforms/android/qandroidplatformwindow.h
+++ b/src/plugins/platforms/android/qandroidplatformwindow.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;
}