summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/android
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/platforms/android')
-rw-r--r--src/plugins/platforms/android/androidjnimain.cpp14
-rw-r--r--src/plugins/platforms/android/qandroideventdispatcher.cpp11
-rw-r--r--src/plugins/platforms/android/qandroidplatformdialoghelpers.cpp25
-rw-r--r--src/plugins/platforms/android/qandroidplatformdialoghelpers.h3
-rw-r--r--src/plugins/platforms/android/qandroidplatformfontdatabase.cpp8
5 files changed, 47 insertions, 14 deletions
diff --git a/src/plugins/platforms/android/androidjnimain.cpp b/src/plugins/platforms/android/androidjnimain.cpp
index e887a4ebdc..cf81f92e47 100644
--- a/src/plugins/platforms/android/androidjnimain.cpp
+++ b/src/plugins/platforms/android/androidjnimain.cpp
@@ -42,6 +42,7 @@
#include "androidjniinput.h"
#include "androidjniclipboard.h"
#include "androidjnimenu.h"
+#include "androiddeadlockprotector.h"
#include "qandroidplatformdialoghelpers.h"
#include "qandroidplatformintegration.h"
#include "qandroidassetsfileenginehandler.h"
@@ -595,11 +596,22 @@ static void updateApplicationState(JNIEnv */*env*/, jobject /*thiz*/, jint state
}
if (state <= Qt::ApplicationInactive) {
+ // NOTE: sometimes we will receive two consecutive suspended notifications,
+ // In the second suspended notification, QWindowSystemInterface::flushWindowSystemEvents()
+ // will deadlock since the dispatcher has been stopped in the first suspended notification.
+ // To avoid the deadlock we simply return if we found the event dispatcher has been stopped.
+ if (QAndroidEventDispatcherStopper::instance()->stopped())
+ return;
+
// 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();
+ {
+ AndroidDeadlockProtector protector;
+ if (protector.acquire())
+ QWindowSystemInterface::flushWindowSystemEvents();
+ }
if (state == Qt::ApplicationSuspended)
QAndroidEventDispatcherStopper::instance()->stopAll();
} else {
diff --git a/src/plugins/platforms/android/qandroideventdispatcher.cpp b/src/plugins/platforms/android/qandroideventdispatcher.cpp
index b83d148ce8..aecea0d4e1 100644
--- a/src/plugins/platforms/android/qandroideventdispatcher.cpp
+++ b/src/plugins/platforms/android/qandroideventdispatcher.cpp
@@ -33,6 +33,7 @@
#include "qandroideventdispatcher.h"
#include "androidjnimain.h"
+#include "androiddeadlockprotector.h"
QAndroidEventDispatcher::QAndroidEventDispatcher(QObject *parent) :
QUnixEventDispatcherQPA(parent)
@@ -78,11 +79,13 @@ void QAndroidEventDispatcher::goingToStop(bool stop)
int QAndroidEventDispatcher::select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, timespec *timeout)
{
- if (m_stopRequest.testAndSetAcquire(StopRequest, Stopping)) {
- m_semaphore.acquire();
- wakeUp();
+ {
+ AndroidDeadlockProtector protector;
+ if (protector.acquire() && m_stopRequest.testAndSetAcquire(StopRequest, Stopping)) {
+ m_semaphore.acquire();
+ wakeUp();
+ }
}
-
return QUnixEventDispatcherQPA::select(nfds, readfds, writefds, exceptfds, timeout);
}
diff --git a/src/plugins/platforms/android/qandroidplatformdialoghelpers.cpp b/src/plugins/platforms/android/qandroidplatformdialoghelpers.cpp
index b43c714482..cc2a394d6e 100644
--- a/src/plugins/platforms/android/qandroidplatformdialoghelpers.cpp
+++ b/src/plugins/platforms/android/qandroidplatformdialoghelpers.cpp
@@ -97,11 +97,15 @@ bool QAndroidPlatformMessageDialogHelper::show(Qt::WindowFlags windowFlags
if (!str.isEmpty())
m_javaMessageDialog.callMethod<void>("setDetailedText", "(Ljava/lang/String;)V", QJNIObjectPrivate::fromString(str).object());
- for (int i = QPlatformDialogHelper::FirstButton; i < QPlatformDialogHelper::LastButton; i<<=1) {
- if ( opt->standardButtons() & i ) {
- const QString text = QGuiApplicationPrivate::platformTheme()->standardButtonText(i);
- m_javaMessageDialog.callMethod<void>("addButton", "(ILjava/lang/String;)V", i, QJNIObjectPrivate::fromString(text).object());
- }
+ // http://developer.android.com/design/building-blocks/dialogs.html
+ // dismissive action on the left, affirmative on the right
+ // There don't seem to be more fine-grained rules, but the OS X layout
+ // at least conforms to this one rule and makes the rest deterministic.
+ const int * currentLayout = buttonLayout(Qt::Horizontal, MacLayout);
+ while (*currentLayout != QPlatformDialogHelper::EOL) {
+ int role = (*currentLayout & ~QPlatformDialogHelper::Reverse);
+ addButtons(opt, static_cast<ButtonRole>(role));
+ ++currentLayout;
}
m_javaMessageDialog.callMethod<void>("show", "(J)V", jlong(static_cast<QObject*>(this)));
@@ -109,6 +113,17 @@ bool QAndroidPlatformMessageDialogHelper::show(Qt::WindowFlags windowFlags
return true;
}
+void QAndroidPlatformMessageDialogHelper::addButtons(QSharedPointer<QMessageDialogOptions> opt, ButtonRole role)
+{
+ for (int i = QPlatformDialogHelper::FirstButton; i < QPlatformDialogHelper::LastButton; i<<=1) {
+ StandardButton b = static_cast<StandardButton>(i);
+ if (buttonRole(b) == role && (opt->standardButtons() & i)) {
+ const QString text = QGuiApplicationPrivate::platformTheme()->standardButtonText(b);
+ m_javaMessageDialog.callMethod<void>("addButton", "(ILjava/lang/String;)V", i, QJNIObjectPrivate::fromString(text).object());
+ }
+ }
+}
+
void QAndroidPlatformMessageDialogHelper::hide()
{
m_javaMessageDialog.callMethod<void>("hide", "()V");
diff --git a/src/plugins/platforms/android/qandroidplatformdialoghelpers.h b/src/plugins/platforms/android/qandroidplatformdialoghelpers.h
index a70468000f..94f01a1835 100644
--- a/src/plugins/platforms/android/qandroidplatformdialoghelpers.h
+++ b/src/plugins/platforms/android/qandroidplatformdialoghelpers.h
@@ -57,6 +57,9 @@ public slots:
void dialogResult(int buttonID);
private:
+ void addButtons(QSharedPointer<QMessageDialogOptions> opt, ButtonRole role);
+
+private:
int m_buttonId;
QEventLoop m_loop;
QJNIObjectPrivate m_javaMessageDialog;
diff --git a/src/plugins/platforms/android/qandroidplatformfontdatabase.cpp b/src/plugins/platforms/android/qandroidplatformfontdatabase.cpp
index c951e6f938..9b60ab291c 100644
--- a/src/plugins/platforms/android/qandroidplatformfontdatabase.cpp
+++ b/src/plugins/platforms/android/qandroidplatformfontdatabase.cpp
@@ -51,10 +51,10 @@ void QAndroidPlatformFontDatabase::populateFontDatabase()
qPrintable(fontpath));
}
- QDir dir(fontpath, QLatin1String("*.ttf"));
- for (int i = 0; i < int(dir.count()); ++i) {
- const QByteArray file = QFile::encodeName(dir.absoluteFilePath(dir[i]));
-
+ QDir dir(fontpath);
+ QList<QFileInfo> entries = dir.entryInfoList(QStringList() << QStringLiteral("*.ttf") << QStringLiteral("*.otf"), QDir::Files);
+ for (int i = 0; i < int(entries.count()); ++i) {
+ const QByteArray file = QFile::encodeName(entries.at(i).absoluteFilePath());
QSupportedWritingSystems supportedWritingSystems;
QStringList families = addTTFile(QByteArray(), file, &supportedWritingSystems);