summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/android/java/AndroidManifest.xml8
-rw-r--r--src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java7
-rw-r--r--src/corelib/kernel/qeventdispatcher_unix_p.h2
-rw-r--r--src/plugins/platforms/android/android.pro6
-rw-r--r--src/plugins/platforms/android/androidjnimain.cpp23
-rw-r--r--src/plugins/platforms/android/androidjnimain.h1
-rw-r--r--src/plugins/platforms/android/qandroideventdispatcher.cpp149
-rw-r--r--src/plugins/platforms/android/qandroideventdispatcher.h89
-rw-r--r--src/plugins/platforms/android/qandroidplatformintegration.cpp5
9 files changed, 282 insertions, 8 deletions
diff --git a/src/android/java/AndroidManifest.xml b/src/android/java/AndroidManifest.xml
index 8e551ba7ac..e5060f0de9 100644
--- a/src/android/java/AndroidManifest.xml
+++ b/src/android/java/AndroidManifest.xml
@@ -36,6 +36,14 @@
<meta-data android:name="android.app.splash_screen_drawable" android:resource="@drawable/logo"/>
-->
<!-- Splash screen -->
+
+ <!-- Background running -->
+ <!-- Warning: changing this value to true may cause unexpected crashes if the
+ application still try to draw after
+ "applicationStateChanged(Qt::ApplicationSuspended)"
+ signal is sent! -->
+ <meta-data android:name="android.app.background_running" android:value="false"/>
+ <!-- Background running -->
</activity>
</application>
<uses-sdk android:minSdkVersion="9" android:targetSdkVersion="14"/>
diff --git a/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java b/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java
index 13d6359d36..c70f1d1aaf 100644
--- a/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java
+++ b/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java
@@ -892,6 +892,13 @@ public class QtActivity extends Activity
getWindow().setBackgroundDrawableResource(m_activityInfo.metaData.getInt("android.app.splash_screen_drawable"));
else
getWindow().setBackgroundDrawable(new ColorDrawable(0xff000000));
+
+ if (m_activityInfo.metaData.containsKey("android.app.background_running")
+ && m_activityInfo.metaData.getBoolean("android.app.background_running")) {
+ ENVIRONMENT_VARIABLES += "QT_BLOCK_EVENT_LOOPS_WHEN_SUSPENDED=0\t";
+ } else {
+ ENVIRONMENT_VARIABLES += "QT_BLOCK_EVENT_LOOPS_WHEN_SUSPENDED=1\t";
+ }
startApp(true);
}
}
diff --git a/src/corelib/kernel/qeventdispatcher_unix_p.h b/src/corelib/kernel/qeventdispatcher_unix_p.h
index 242aa9e695..6060f34b47 100644
--- a/src/corelib/kernel/qeventdispatcher_unix_p.h
+++ b/src/corelib/kernel/qeventdispatcher_unix_p.h
@@ -136,7 +136,7 @@ protected:
virtual int select(int nfds,
fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
- timespec *timeout) Q_DECL_FINAL;
+ timespec *timeout);
};
class Q_CORE_EXPORT QEventDispatcherUNIXPrivate : public QAbstractEventDispatcherPrivate
diff --git a/src/plugins/platforms/android/android.pro b/src/plugins/platforms/android/android.pro
index 32c37ab17a..0209379afb 100644
--- a/src/plugins/platforms/android/android.pro
+++ b/src/plugins/platforms/android/android.pro
@@ -51,7 +51,8 @@ SOURCES += $$PWD/androidplatformplugin.cpp \
$$PWD/qandroidplatformbackingstore.cpp \
$$PWD/qandroidplatformopenglcontext.cpp \
$$PWD/qandroidplatformforeignwindow.cpp \
- $$PWD/extract.cpp
+ $$PWD/extract.cpp \
+ $$PWD/qandroideventdispatcher.cpp
HEADERS += $$PWD/qandroidplatformintegration.h \
$$PWD/androidjnimain.h \
@@ -78,7 +79,8 @@ HEADERS += $$PWD/qandroidplatformintegration.h \
$$PWD/qandroidplatformrasterwindow.h \
$$PWD/qandroidplatformbackingstore.h \
$$PWD/qandroidplatformopenglcontext.h \
- $$PWD/qandroidplatformforeignwindow.h
+ $$PWD/qandroidplatformforeignwindow.h \
+ $$PWD/qandroideventdispatcher.h
#Non-standard install directory, QTBUG-29859
DESTDIR = $$DESTDIR/android
diff --git a/src/plugins/platforms/android/androidjnimain.cpp b/src/plugins/platforms/android/androidjnimain.cpp
index 3e3e169df9..4ee32d79c2 100644
--- a/src/plugins/platforms/android/androidjnimain.cpp
+++ b/src/plugins/platforms/android/androidjnimain.cpp
@@ -69,6 +69,7 @@
#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>
@@ -426,6 +427,12 @@ namespace QtAndroid
surfaceId);
}
+ bool blockEventLoopsWhenSuspended()
+ {
+ static bool block = qgetenv("QT_BLOCK_EVENT_LOOPS_WHEN_SUSPENDED").toInt();
+ return block;
+ }
+
} // namespace QtAndroid
@@ -596,10 +603,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)
diff --git a/src/plugins/platforms/android/androidjnimain.h b/src/plugins/platforms/android/androidjnimain.h
index 29896529ca..4fc2bf1992 100644
--- a/src/plugins/platforms/android/androidjnimain.h
+++ b/src/plugins/platforms/android/androidjnimain.h
@@ -120,6 +120,7 @@ namespace QtAndroid
const char *qtTagText();
QString deviceName();
+ bool blockEventLoopsWhenSuspended();
}
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/android/qandroideventdispatcher.cpp b/src/plugins/platforms/android/qandroideventdispatcher.cpp
new file mode 100644
index 0000000000..074ba71f80
--- /dev/null
+++ b/src/plugins/platforms/android/qandroideventdispatcher.cpp
@@ -0,0 +1,149 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 BogDan Vatra <bogdan@kde.org>
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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
+** 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.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** 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 "qandroideventdispatcher.h"
+#include "androidjnimain.h"
+
+QAndroidEventDispatcher::QAndroidEventDispatcher(QObject *parent) :
+ QUnixEventDispatcherQPA(parent)
+{
+ if (QtAndroid::blockEventLoopsWhenSuspended())
+ QAndroidEventDispatcherStopper::instance()->addEventDispatcher(this);
+}
+
+QAndroidEventDispatcher::~QAndroidEventDispatcher()
+{
+ if (QtAndroid::blockEventLoopsWhenSuspended())
+ QAndroidEventDispatcherStopper::instance()->removeEventDispatcher(this);
+}
+
+void QAndroidEventDispatcher::start()
+{
+ if (m_stopRequest.testAndSetAcquire(1, 0)) {
+ m_dispatcherSemaphore.release();
+ wakeUp();
+ }
+}
+
+void QAndroidEventDispatcher::stop()
+{
+ if (m_stopRequest.testAndSetAcquire(0, 1)) {
+ wakeUp();
+ m_stopperSemaphore.acquire();
+ }
+}
+
+void QAndroidEventDispatcher::goingToStop(bool stop)
+{
+ m_goingToStop.store(stop ? 1 : 0);
+ if (!stop)
+ wakeUp();
+}
+
+int QAndroidEventDispatcher::select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, timespec *timeout)
+{
+ if (m_stopRequest.load() == 1) {
+ m_stopperSemaphore.release();
+ m_dispatcherSemaphore.acquire();
+ wakeUp();
+ }
+
+ return QUnixEventDispatcherQPA::select(nfds, readfds, writefds, exceptfds, timeout);
+}
+
+bool QAndroidEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags)
+{
+ if (m_goingToStop.load()) {
+ return QUnixEventDispatcherQPA::processEvents(flags /*| QEventLoop::ExcludeUserInputEvents*/
+ | QEventLoop::ExcludeSocketNotifiers
+ | QEventLoop::X11ExcludeTimers);
+ } else {
+ return QUnixEventDispatcherQPA::processEvents(flags);
+ }
+}
+
+
+QAndroidEventDispatcherStopper *QAndroidEventDispatcherStopper::instance()
+{
+ static QAndroidEventDispatcherStopper androidEventDispatcherStopper;
+ return &androidEventDispatcherStopper;
+}
+
+void QAndroidEventDispatcherStopper::startAll()
+{
+ QMutexLocker lock(&m_mutex);
+ if (started)
+ return;
+
+ started = true;
+ foreach (QAndroidEventDispatcher *d, m_dispatchers)
+ d->start();
+}
+
+void QAndroidEventDispatcherStopper::stopAll()
+{
+ QMutexLocker lock(&m_mutex);
+ if (!started)
+ return;
+
+ started = false;
+ foreach (QAndroidEventDispatcher *d, m_dispatchers)
+ d->stop();
+}
+
+void QAndroidEventDispatcherStopper::addEventDispatcher(QAndroidEventDispatcher *dispatcher)
+{
+ QMutexLocker lock(&m_mutex);
+ m_dispatchers.push_back(dispatcher);
+}
+
+void QAndroidEventDispatcherStopper::removeEventDispatcher(QAndroidEventDispatcher *dispatcher)
+{
+ QMutexLocker lock(&m_mutex);
+ m_dispatchers.erase(std::find(m_dispatchers.begin(), m_dispatchers.end(), dispatcher));
+}
+
+void QAndroidEventDispatcherStopper::goingToStop(bool stop)
+{
+ QMutexLocker lock(&m_mutex);
+ foreach (QAndroidEventDispatcher *d, m_dispatchers)
+ d->goingToStop(stop);
+}
diff --git a/src/plugins/platforms/android/qandroideventdispatcher.h b/src/plugins/platforms/android/qandroideventdispatcher.h
new file mode 100644
index 0000000000..8d1bcf2122
--- /dev/null
+++ b/src/plugins/platforms/android/qandroideventdispatcher.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 BogDan Vatra <bogdan@kde.org>
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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
+** 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.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** 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$
+**
+****************************************************************************/
+
+#ifndef QANDROIDEVENTDISPATCHER_H
+#define QANDROIDEVENTDISPATCHER_H
+
+#include <QtCore/QMutex>
+#include <QtCore/QSemaphore>
+#include <QtPlatformSupport/private/qunixeventdispatcher_qpa_p.h>
+
+class QAndroidEventDispatcher : public QUnixEventDispatcherQPA
+{
+ Q_OBJECT
+public:
+ explicit QAndroidEventDispatcher(QObject *parent = 0);
+ ~QAndroidEventDispatcher();
+ void start();
+ void stop();
+
+ void goingToStop(bool stop);
+
+protected:
+ int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
+ timespec *timeout);
+
+ bool processEvents(QEventLoop::ProcessEventsFlags flags);
+
+private:
+ QAtomicInt m_stopRequest;
+ QAtomicInt m_goingToStop;
+ QSemaphore m_dispatcherSemaphore, m_stopperSemaphore;
+};
+
+class QAndroidEventDispatcherStopper
+{
+public:
+ static QAndroidEventDispatcherStopper *instance();
+ void startAll();
+ void stopAll();
+ void addEventDispatcher(QAndroidEventDispatcher *dispatcher);
+ void removeEventDispatcher(QAndroidEventDispatcher *dispatcher);
+ void goingToStop(bool stop);
+
+private:
+ QMutex m_mutex;
+ bool started = true;
+ QVector<QAndroidEventDispatcher *> m_dispatchers;
+};
+
+
+#endif // QANDROIDEVENTDISPATCHER_H
diff --git a/src/plugins/platforms/android/qandroidplatformintegration.cpp b/src/plugins/platforms/android/qandroidplatformintegration.cpp
index d6d7d3b173..829227f81c 100644
--- a/src/plugins/platforms/android/qandroidplatformintegration.cpp
+++ b/src/plugins/platforms/android/qandroidplatformintegration.cpp
@@ -47,15 +47,14 @@
#include <QThread>
#include <QOffscreenSurface>
-#include <QtPlatformSupport/private/qgenericunixeventdispatcher_p.h>
#include <QtPlatformSupport/private/qeglpbuffer_p.h>
-
#include <qpa/qwindowsysteminterface.h>
#include <qpa/qplatformwindow.h>
#include <qpa/qplatformoffscreensurface.h>
#include "androidjnimain.h"
#include "qabstracteventdispatcher.h"
+#include "qandroideventdispatcher.h"
#include "qandroidplatformbackingstore.h"
#include "qandroidplatformaccessibility.h"
#include "qandroidplatformclipboard.h"
@@ -236,7 +235,7 @@ QPlatformWindow *QAndroidPlatformIntegration::createPlatformWindow(QWindow *wind
QAbstractEventDispatcher *QAndroidPlatformIntegration::createEventDispatcher() const
{
- return createUnixEventDispatcher();
+ return new QAndroidEventDispatcher;
}
QAndroidPlatformIntegration::~QAndroidPlatformIntegration()