diff options
author | Liang Qi <liang.qi@theqtcompany.com> | 2015-03-31 10:03:31 +0200 |
---|---|---|
committer | Liang Qi <liang.qi@theqtcompany.com> | 2015-03-31 10:03:31 +0200 |
commit | ce9519593a0b3deb99d1dd2529770f7e9fffef92 (patch) | |
tree | c9bca05230dd68f49494240ae930bad1fe0c5956 /src/plugins/platforms/android | |
parent | 509f77cca28aa3edea5523c5869bae4412ed2ccc (diff) | |
parent | 7baaec17edb06634f1d6235a55c7adbd112cba3e (diff) |
Merge remote-tracking branch 'origin/5.4' into 5.5
Conflicts:
mkspecs/android-g++/qmake.conf
qmake/generators/unix/unixmake2.cpp
src/gui/image/qimage_conversions.cpp
Change-Id: Ib76264b8c2d29a0228438ec02bd97d4b97545be0
Diffstat (limited to 'src/plugins/platforms/android')
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); |