summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/android/androidjnimain.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/platforms/android/androidjnimain.cpp')
-rw-r--r--src/plugins/platforms/android/androidjnimain.cpp221
1 files changed, 121 insertions, 100 deletions
diff --git a/src/plugins/platforms/android/androidjnimain.cpp b/src/plugins/platforms/android/androidjnimain.cpp
index c571e16062..11f0bc5ffe 100644
--- a/src/plugins/platforms/android/androidjnimain.cpp
+++ b/src/plugins/platforms/android/androidjnimain.cpp
@@ -1,60 +1,41 @@
/****************************************************************************
**
** Copyright (C) 2014 BogDan Vatra <bogdan@kde.org>
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
**
-** $QT_BEGIN_LICENSE:LGPL$
+** $QT_BEGIN_LICENSE:LGPL21$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
+** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-**
** $QT_END_LICENSE$
**
****************************************************************************/
-#include <QtGui/private/qguiapplication_p.h>
-
#include <dlfcn.h>
#include <pthread.h>
-#include <qcoreapplication.h>
-#include <qimage.h>
-#include <qpoint.h>
#include <qplugin.h>
-#include <qsemaphore.h>
-#include <qmutex.h>
#include <qdebug.h>
-#include <qglobal.h>
-#include <qobjectdefs.h>
-#include <QtCore/private/qjni_p.h>
-#include <stdlib.h>
#include "androidjnimain.h"
#include "androidjniaccessibility.h"
@@ -63,14 +44,16 @@
#include "androidjnimenu.h"
#include "qandroidplatformdialoghelpers.h"
#include "qandroidplatformintegration.h"
-
-#include <qabstracteventdispatcher.h>
+#include "qandroidassetsfileenginehandler.h"
#include <android/bitmap.h>
#include <android/asset_manager_jni.h>
-#include "qandroidassetsfileenginehandler.h"
+#include "qandroideventdispatcher.h"
#include <android/api-level.h>
+
#include <QtCore/private/qjnihelpers_p.h>
+#include <QtCore/private/qjni_p.h>
+#include <QtGui/private/qguiapplication_p.h>
#include <qpa/qwindowsysteminterface.h>
@@ -78,42 +61,41 @@ Q_IMPORT_PLUGIN(QAndroidPlatformIntegrationPlugin)
QT_BEGIN_NAMESPACE
-static JavaVM *m_javaVM = NULL;
-static jclass m_applicationClass = NULL;
-static jobject m_classLoaderObject = NULL;
-static jmethodID m_loadClassMethodID = NULL;
-static AAssetManager *m_assetManager = NULL;
-static jobject m_resourcesObj;
-static jobject m_activityObject = NULL;
-static jmethodID m_createSurfaceMethodID = 0;
-static jmethodID m_insertNativeViewMethodID = 0;
-static jmethodID m_setSurfaceGeometryMethodID = 0;
-static jmethodID m_destroySurfaceMethodID = 0;
+static JavaVM *m_javaVM = Q_NULLPTR;
+static jclass m_applicationClass = Q_NULLPTR;
+static jobject m_classLoaderObject = Q_NULLPTR;
+static jmethodID m_loadClassMethodID = Q_NULLPTR;
+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_setSurfaceGeometryMethodID = Q_NULLPTR;
+static jmethodID m_destroySurfaceMethodID = Q_NULLPTR;
static bool m_activityActive = true; // defaults to true because when the platform plugin is
// initialized, QtActivity::onResume() has already been called
-static jclass m_bitmapClass = 0;
-static jmethodID m_createBitmapMethodID = 0;
-static jobject m_ARGB_8888_BitmapConfigValue = 0;
-static jobject m_RGB_565_BitmapConfigValue = 0;
+static jclass m_bitmapClass = Q_NULLPTR;
+static jmethodID m_createBitmapMethodID = Q_NULLPTR;
+static jobject m_ARGB_8888_BitmapConfigValue = Q_NULLPTR;
+static jobject m_RGB_565_BitmapConfigValue = Q_NULLPTR;
-jmethodID m_setFullScreenMethodID = 0;
+jmethodID m_setFullScreenMethodID = Q_NULLPTR;
static bool m_statusBarShowing = true;
-static jclass m_bitmapDrawableClass = 0;
-static jmethodID m_bitmapDrawableConstructorMethodID = 0;
+static jclass m_bitmapDrawableClass = Q_NULLPTR;
+static jmethodID m_bitmapDrawableConstructorMethodID = Q_NULLPTR;
extern "C" typedef int (*Main)(int, char **); //use the standard main method to start the application
-static Main m_main = NULL;
-static void *m_mainLibraryHnd = NULL;
+static Main m_main = Q_NULLPTR;
+static void *m_mainLibraryHnd = Q_NULLPTR;
static QList<QByteArray> m_applicationParams;
struct SurfaceData
{
~SurfaceData() { delete surface; }
- QJNIObjectPrivate *surface = 0;
- AndroidSurfaceClient *client = 0;
+ QJNIObjectPrivate *surface = Q_NULLPTR;
+ AndroidSurfaceClient *client = Q_NULLPTR;
};
QHash<int, AndroidSurfaceClient *> m_surfaces;
@@ -121,11 +103,8 @@ QHash<int, AndroidSurfaceClient *> m_surfaces;
static QMutex m_surfacesMutex;
static int m_surfaceId = 1;
-static QSemaphore m_quitAppSemaphore;
-static QSemaphore m_pauseApplicationSemaphore;
-static QMutex m_pauseApplicationMutex;
-static QAndroidPlatformIntegration *m_androidPlatformIntegration = 0;
+static QAndroidPlatformIntegration *m_androidPlatformIntegration = Q_NULLPTR;
static int m_desktopWidthPixels = 0;
static int m_desktopHeightPixels = 0;
@@ -133,7 +112,7 @@ static double m_scaledDensity = 0;
static volatile bool m_pauseApplication;
-static AndroidAssetsFileEngineHandler *m_androidAssetsFileEngineHandler = 0;
+static AndroidAssetsFileEngineHandler *m_androidAssetsFileEngineHandler = Q_NULLPTR;
@@ -183,14 +162,6 @@ namespace QtAndroid
return m_javaVM;
}
- jclass findClass(const QString &className, JNIEnv *env)
- {
- return static_cast<jclass>(env->CallObjectMethod(m_classLoaderObject,
- m_loadClassMethodID,
- env->NewString(reinterpret_cast<const jchar *>(className.constData()),
- jsize(className.length()))));
- }
-
AAssetManager *assetManager()
{
return m_assetManager;
@@ -212,7 +183,7 @@ namespace QtAndroid
return;
QtAndroid::AttachedJNIEnv env;
- if (env.jniEnv == 0) {
+ if (!env.jniEnv) {
qWarning("Failed to get JNI Environment.");
return;
}
@@ -227,7 +198,7 @@ namespace QtAndroid
return;
QtAndroid::AttachedJNIEnv env;
- if (env.jniEnv == 0) {
+ if (!env.jniEnv) {
qWarning("Failed to get JNI Environment.");
return;
}
@@ -365,33 +336,33 @@ 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;
}
void setSurfaceGeometry(int surfaceId, const QRect &geometry)
{
+ if (surfaceId == -1)
+ return;
+
QJNIEnvironmentPrivate env;
if (!env)
return;
@@ -411,10 +382,15 @@ namespace QtAndroid
void destroySurface(int surfaceId)
{
+ if (surfaceId == -1)
+ return;
+
QMutexLocker lock(&m_surfacesMutex);
const auto &it = m_surfaces.find(surfaceId);
if (it != m_surfaces.end())
m_surfaces.remove(surfaceId);
+ if (m_surfaces.isEmpty())
+ m_surfaceId = 1;
QJNIEnvironmentPrivate env;
if (!env)
@@ -425,12 +401,40 @@ namespace QtAndroid
surfaceId);
}
+ void bringChildToFront(int surfaceId)
+ {
+ if (surfaceId == -1)
+ return;
+
+ QJNIObjectPrivate::callStaticMethod<void>(m_applicationClass,
+ "bringChildToFront",
+ "(I)V",
+ surfaceId);
+ }
+
+ void bringChildToBack(int surfaceId)
+ {
+ if (surfaceId == -1)
+ return;
+
+ QJNIObjectPrivate::callStaticMethod<void>(m_applicationClass,
+ "bringChildToBack",
+ "(I)V",
+ surfaceId);
+ }
+
+ bool blockEventLoopsWhenSuspended()
+ {
+ static bool block = qgetenv("QT_BLOCK_EVENT_LOOPS_WHEN_SUSPENDED").toInt();
+ return block;
+ }
+
} // namespace QtAndroid
static jboolean startQtAndroidPlugin(JNIEnv* /*env*/, jobject /*object*//*, jobject applicationAssetManager*/)
{
- m_androidPlatformIntegration = 0;
+ m_androidPlatformIntegration = Q_NULLPTR;
m_androidAssetsFileEngineHandler = new AndroidAssetsFileEngineHandler();
return true;
}
@@ -449,7 +453,8 @@ static void *startMainMethod(void */*data*/)
if (res < 0)
qWarning() << "dlclose failed:" << dlerror();
}
-
+ m_mainLibraryHnd = Q_NULLPTR;
+ m_main = Q_NULLPTR;
QtAndroid::AttachedJNIEnv env;
if (!env.jniEnv)
return 0;
@@ -464,7 +469,7 @@ static void *startMainMethod(void */*data*/)
static jboolean startQtApplication(JNIEnv *env, jobject /*object*/, jstring paramsString, jstring environmentString)
{
- m_mainLibraryHnd = NULL;
+ m_mainLibraryHnd = Q_NULLPTR;
{ // Set env. vars
const char *nativeString = env->GetStringUTFChars(environmentString, 0);
const QList<QByteArray> envVars = QByteArray(nativeString).split('\t');
@@ -490,7 +495,7 @@ static jboolean startQtApplication(JNIEnv *env, jobject /*object*/, jstring para
// Obtain a handle to the main library (the library that contains the main() function).
// This library should already be loaded, and calling dlopen() will just return a reference to it.
m_mainLibraryHnd = dlopen(m_applicationParams.first().data(), 0);
- if (m_mainLibraryHnd == NULL) {
+ if (m_mainLibraryHnd == Q_NULLPTR) {
qCritical() << "dlopen failed:" << dlerror();
return false;
}
@@ -507,15 +512,16 @@ static jboolean startQtApplication(JNIEnv *env, jobject /*object*/, jstring para
}
pthread_t appThread;
- return pthread_create(&appThread, NULL, startMainMethod, NULL) == 0;
+ return pthread_create(&appThread, Q_NULLPTR, startMainMethod, Q_NULLPTR) == 0;
}
static void quitQtAndroidPlugin(JNIEnv *env, jclass /*clazz*/)
{
Q_UNUSED(env);
- m_androidPlatformIntegration = 0;
+ m_androidPlatformIntegration = Q_NULLPTR;
delete m_androidAssetsFileEngineHandler;
+ m_androidAssetsFileEngineHandler = Q_NULLPTR;
}
static void terminateQt(JNIEnv *env, jclass /*clazz*/)
@@ -534,14 +540,18 @@ static void terminateQt(JNIEnv *env, jclass /*clazz*/)
env->DeleteGlobalRef(m_RGB_565_BitmapConfigValue);
if (m_bitmapDrawableClass)
env->DeleteGlobalRef(m_bitmapDrawableClass);
- m_androidPlatformIntegration = 0;
+ m_androidPlatformIntegration = Q_NULLPTR;
delete m_androidAssetsFileEngineHandler;
+ m_androidAssetsFileEngineHandler = Q_NULLPTR;
}
static void setSurface(JNIEnv *env, jobject /*thiz*/, jint id, jobject jSurface, jint w, jint h)
{
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;
@@ -584,11 +594,11 @@ static void updateWindow(JNIEnv */*env*/, jobject /*thiz*/)
if (!m_androidPlatformIntegration)
return;
- if (QGuiApplication::instance() != 0) {
+ if (QGuiApplication::instance() != Q_NULLPTR) {
foreach (QWindow *w, QGuiApplication::topLevelWindows()) {
QRect availableGeometry = w->screen()->availableGeometry();
if (w->geometry().width() > 0 && w->geometry().height() > 0 && availableGeometry.width() > 0 && availableGeometry.height() > 0)
- QWindowSystemInterface::handleExposeEvent(w, QRegion(w->geometry()));
+ QWindowSystemInterface::handleExposeEvent(w, QRegion(QRect(QPoint(), w->geometry().size())));
}
}
@@ -601,10 +611,22 @@ static void updateApplicationState(JNIEnv */*env*/, jobject /*thiz*/, jint state
{
m_activityActive = (state == Qt::ApplicationActive);
- if (!m_androidPlatformIntegration || !QGuiApplicationPrivate::platformIntegration())
+ if (!m_main || !m_androidPlatformIntegration || !QGuiApplicationPrivate::platformIntegration())
return;
- QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationState(state));
+ if (state <= Qt::ApplicationInactive) {
+ // Don't send timers and sockets events anymore if we are going to hide all windows
+ QAndroidEventDispatcherStopper::instance()->goingToStop(true);
+ QCoreApplication::processEvents();
+ QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationState(state));
+ QWindowSystemInterface::flushWindowSystemEvents();
+ if (state == Qt::ApplicationSuspended)
+ QAndroidEventDispatcherStopper::instance()->stopAll();
+ } else {
+ QAndroidEventDispatcherStopper::instance()->startAll();
+ QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationState(state));
+ QAndroidEventDispatcherStopper::instance()->goingToStop(false);
+ }
}
static void handleOrientationChanged(JNIEnv */*env*/, jobject /*thiz*/, jint newRotation, jint nativeOrientation)
@@ -709,7 +731,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");
@@ -767,8 +788,8 @@ Q_DECL_EXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void */*reserved*/)
__android_log_print(ANDROID_LOG_INFO, "Qt", "qt start");
UnionJNIEnvToVoid uenv;
- uenv.venv = NULL;
- m_javaVM = 0;
+ uenv.venv = Q_NULLPTR;
+ m_javaVM = Q_NULLPTR;
if (vm->GetEnv(&uenv.venv, JNI_VERSION_1_4) != JNI_OK) {
__android_log_print(ANDROID_LOG_FATAL, "Qt", "GetEnv failed");