summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/android
diff options
context:
space:
mode:
authorFrederik Gladhorn <frederik.gladhorn@theqtcompany.com>2014-10-20 19:12:23 +0200
committerFrederik Gladhorn <frederik.gladhorn@theqtcompany.com>2014-10-20 19:12:25 +0200
commit3361fcbc28be96262d22fd2b024c85fbcbc61462 (patch)
tree48976f337b3885971dc1976b9a27cec5e7dfa2ec /src/plugins/platforms/android
parentdc612acdc6577594c8f61345cea2de549d7aae34 (diff)
parent5e342f6f041208d142d97202f61179d7163eb773 (diff)
Merge remote-tracking branch 'origin/5.4' into dev
Diffstat (limited to 'src/plugins/platforms/android')
-rw-r--r--src/plugins/platforms/android/android.pro2
-rw-r--r--src/plugins/platforms/android/androiddeadlockprotector.cpp37
-rw-r--r--src/plugins/platforms/android/androiddeadlockprotector.h67
-rw-r--r--src/plugins/platforms/android/androidjniaccessibility.cpp28
-rw-r--r--src/plugins/platforms/android/qandroidinputcontext.cpp29
-rw-r--r--src/plugins/platforms/android/qandroidinputcontext.h3
-rw-r--r--src/plugins/platforms/android/qandroidplatformclipboard.cpp16
-rw-r--r--src/plugins/platforms/android/qandroidplatformopenglwindow.cpp5
-rw-r--r--src/plugins/platforms/android/qandroidplatformscreen.cpp4
9 files changed, 169 insertions, 22 deletions
diff --git a/src/plugins/platforms/android/android.pro b/src/plugins/platforms/android/android.pro
index f55bc40a55..3c3a4b4b2e 100644
--- a/src/plugins/platforms/android/android.pro
+++ b/src/plugins/platforms/android/android.pro
@@ -26,6 +26,7 @@ INCLUDEPATH += \
$$QT_SOURCE_TREE/src/3rdparty/android
SOURCES += $$PWD/androidplatformplugin.cpp \
+ $$PWD/androiddeadlockprotector.cpp \
$$PWD/androidjnimain.cpp \
$$PWD/androidjniaccessibility.cpp \
$$PWD/androidjniinput.cpp \
@@ -53,6 +54,7 @@ SOURCES += $$PWD/androidplatformplugin.cpp \
$$PWD/qandroideventdispatcher.cpp
HEADERS += $$PWD/qandroidplatformintegration.h \
+ $$PWD/androidandroiddeadlockprotector.h \
$$PWD/androidjnimain.h \
$$PWD/androidjniaccessibility.h \
$$PWD/androidjniinput.h \
diff --git a/src/plugins/platforms/android/androiddeadlockprotector.cpp b/src/plugins/platforms/android/androiddeadlockprotector.cpp
new file mode 100644
index 0000000000..e53e0c2447
--- /dev/null
+++ b/src/plugins/platforms/android/androiddeadlockprotector.cpp
@@ -0,0 +1,37 @@
+/****************************************************************************
+**
+** 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: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
+** 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 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
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "androiddeadlockprotector.h"
+
+QAtomicInt AndroidDeadlockProtector::s_blocked(0);
+
diff --git a/src/plugins/platforms/android/androiddeadlockprotector.h b/src/plugins/platforms/android/androiddeadlockprotector.h
new file mode 100644
index 0000000000..a0a82aa9d1
--- /dev/null
+++ b/src/plugins/platforms/android/androiddeadlockprotector.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** 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: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
+** 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 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
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef ANDROID_DEADLOCKPROTECTOR_H
+#define ANDROID_DEADLOCKPROTECTOR_H
+
+#include <QAtomicInt>
+
+QT_BEGIN_NAMESPACE
+
+class AndroidDeadlockProtector
+{
+public:
+ AndroidDeadlockProtector()
+ : m_acquired(0)
+ {
+ }
+
+ ~AndroidDeadlockProtector() {
+ if (m_acquired)
+ s_blocked.storeRelease(0);
+ }
+
+ bool acquire() {
+ m_acquired = s_blocked.testAndSetAcquire(0, 1);
+ return m_acquired;
+ }
+
+private:
+ static QAtomicInt s_blocked;
+ int m_acquired;
+};
+
+QT_END_NAMESPACE
+
+#endif // ANDROID_DEADLOCKPROTECTOR_H
+
diff --git a/src/plugins/platforms/android/androidjniaccessibility.cpp b/src/plugins/platforms/android/androidjniaccessibility.cpp
index 7229fd7af5..5c927da9c5 100644
--- a/src/plugins/platforms/android/androidjniaccessibility.cpp
+++ b/src/plugins/platforms/android/androidjniaccessibility.cpp
@@ -187,18 +187,30 @@ if (!clazz) { \
//__android_log_print(ANDROID_LOG_FATAL, m_qtTag, m_methodErrorMsg, METHOD_NAME, METHOD_SIGNATURE);
- static jstring descriptionForAccessibleObject(JNIEnv *env, jobject /*thiz*/, jint objectId)
+
+ static jstring descriptionForAccessibleObject_helper(JNIEnv *env, QAccessibleInterface *iface)
{
QString desc;
- QAccessibleInterface *iface = interfaceFromId(objectId);
if (iface && iface->isValid()) {
desc = iface->text(QAccessible::Name);
if (desc.isEmpty())
desc = iface->text(QAccessible::Description);
+ if (desc.isEmpty()) {
+ desc = iface->text(QAccessible::Value);
+ if (desc.isEmpty()) {
+ if (QAccessibleValueInterface *valueIface = iface->valueInterface()) {
+ desc= valueIface->currentValue().toString();
+ }
+ }
+ }
}
+ return env->NewString((jchar*) desc.constData(), (jsize) desc.size());
+ }
- jstring jdesc = env->NewString((jchar*) desc.constData(), (jsize) desc.size());
- return jdesc;
+ static jstring descriptionForAccessibleObject(JNIEnv *env, jobject /*thiz*/, jint objectId)
+ {
+ QAccessibleInterface *iface = interfaceFromId(objectId);
+ return descriptionForAccessibleObject_helper(env, iface);
}
static bool populateNode(JNIEnv *env, jobject /*thiz*/, jint objectId, jobject node)
@@ -216,11 +228,8 @@ if (!clazz) { \
const bool hasDecreaseAction = actions.contains(QAccessibleActionInterface::decreaseAction());
// try to fill in the text property, this is what the screen reader reads
- QString desc = iface->text(QAccessible::Value);
- if (desc.isEmpty())
- desc = iface->text(QAccessible::Name);
- if (desc.isEmpty())
- desc = iface->text(QAccessible::Description);
+ jstring jdesc = descriptionForAccessibleObject_helper(env, iface);
+
if (QAccessibleTextInterface *textIface = iface->textInterface()) {
if (m_setTextSelectionMethodID && textIface->selectionCount() > 0) {
int startSelection;
@@ -252,7 +261,6 @@ if (!clazz) { \
env->CallVoidMethod(node, m_addActionMethodID, (int)8192); // ACTION_SCROLL_BACKWARD defined in AccessibilityNodeInfo
- jstring jdesc = env->NewString((jchar*) desc.constData(), (jsize) desc.size());
//CALL_METHOD(node, "setText", "(Ljava/lang/CharSequence;)V", jdesc)
env->CallVoidMethod(node, m_setContentDescriptionMethodID, jdesc);
diff --git a/src/plugins/platforms/android/qandroidinputcontext.cpp b/src/plugins/platforms/android/qandroidinputcontext.cpp
index a23d05520c..a3848c9c2b 100644
--- a/src/plugins/platforms/android/qandroidinputcontext.cpp
+++ b/src/plugins/platforms/android/qandroidinputcontext.cpp
@@ -38,6 +38,7 @@
#include "androidjnimain.h"
#include "androidjniinput.h"
#include "qandroideventdispatcher.h"
+#include "androiddeadlockprotector.h"
#include <QDebug>
#include <qevent.h>
#include <qguiapplication.h>
@@ -519,6 +520,10 @@ bool QAndroidInputContext::isAnimating() const
void QAndroidInputContext::showInputPanel()
{
+ if (QGuiApplication::applicationState() != Qt::ApplicationActive) {
+ connect(qGuiApp, SIGNAL(applicationStateChanged(Qt::ApplicationState)), this, SLOT(showInputPanelLater(Qt::ApplicationState)));
+ return;
+ }
QSharedPointer<QInputMethodQueryEvent> query = focusObjectInputMethodQueryThreadSafe();
if (query.isNull())
return;
@@ -541,6 +546,14 @@ void QAndroidInputContext::showInputPanel()
query->value(Qt::ImHints).toUInt());
}
+void QAndroidInputContext::showInputPanelLater(Qt::ApplicationState state)
+{
+ if (state != Qt::ApplicationActive)
+ return;
+ disconnect(qGuiApp, SIGNAL(applicationStateChanged(Qt::ApplicationState)), this, SLOT(showInputPanelLater(Qt::ApplicationState)));
+ showInputPanel();
+}
+
void QAndroidInputContext::hideInputPanel()
{
QtAndroidInput::hideSoftwareKeyboard();
@@ -642,13 +655,13 @@ jboolean QAndroidInputContext::deleteSurroundingText(jint leftLength, jint right
// Android docs say the cursor must not move
jboolean QAndroidInputContext::finishComposingText()
{
+ if (m_composingText.isEmpty())
+ return JNI_TRUE; // not composing
+
QSharedPointer<QInputMethodQueryEvent> query = focusObjectInputMethodQueryThreadSafe();
if (query.isNull())
return JNI_FALSE;
- if (m_composingText.isEmpty())
- return JNI_TRUE; // not composing
-
const int blockPos = getBlockPosition(query);
const int localCursorPos = m_composingCursor - blockPos;
@@ -986,6 +999,9 @@ QVariant QAndroidInputContext::queryFocusObjectThreadSafe(Qt::InputMethodQuery q
const bool inMainThread = qGuiApp->thread() == QThread::currentThread();
if (QAndroidEventDispatcherStopper::stopped() && !inMainThread)
return retval;
+ AndroidDeadlockProtector protector;
+ if (!inMainThread && !protector.acquire())
+ return retval;
QMetaObject::invokeMethod(this, "queryFocusObjectUnsafe",
inMainThread ? Qt::DirectConnection : Qt::BlockingQueuedConnection,
@@ -1003,6 +1019,9 @@ QSharedPointer<QInputMethodQueryEvent> QAndroidInputContext::focusObjectInputMet
const bool inMainThread = qGuiApp->thread() == QThread::currentThread();
if (QAndroidEventDispatcherStopper::stopped() && !inMainThread)
return QSharedPointer<QInputMethodQueryEvent>();
+ AndroidDeadlockProtector protector;
+ if (!inMainThread && !protector.acquire())
+ return QSharedPointer<QInputMethodQueryEvent>();
QInputMethodQueryEvent *queryEvent = 0;
QMetaObject::invokeMethod(this, "focusObjectInputMethodQueryUnsafe",
@@ -1040,7 +1059,9 @@ void QAndroidInputContext::sendInputMethodEventThreadSafe(QInputMethodEvent *eve
const bool inMainThread = qGuiApp->thread() == QThread::currentThread();
if (QAndroidEventDispatcherStopper::stopped() && !inMainThread)
return;
-
+ AndroidDeadlockProtector protector;
+ if (!inMainThread && !protector.acquire())
+ return;
QMetaObject::invokeMethod(this, "sendInputMethodEventUnsafe",
inMainThread ? Qt::DirectConnection : Qt::BlockingQueuedConnection,
Q_ARG(QInputMethodEvent*, event));
diff --git a/src/plugins/platforms/android/qandroidinputcontext.h b/src/plugins/platforms/android/qandroidinputcontext.h
index 670a051139..2ebb155d2a 100644
--- a/src/plugins/platforms/android/qandroidinputcontext.h
+++ b/src/plugins/platforms/android/qandroidinputcontext.h
@@ -112,6 +112,9 @@ public:
public slots:
void updateCursorPosition();
+private slots:
+ void showInputPanelLater(Qt::ApplicationState);
+
private:
void sendInputMethodEventThreadSafe(QInputMethodEvent *event);
Q_INVOKABLE void sendInputMethodEventUnsafe(QInputMethodEvent *event);
diff --git a/src/plugins/platforms/android/qandroidplatformclipboard.cpp b/src/plugins/platforms/android/qandroidplatformclipboard.cpp
index 86fd152bff..fb73db8455 100644
--- a/src/plugins/platforms/android/qandroidplatformclipboard.cpp
+++ b/src/plugins/platforms/android/qandroidplatformclipboard.cpp
@@ -44,19 +44,19 @@ QAndroidPlatformClipboard::QAndroidPlatformClipboard()
QMimeData *QAndroidPlatformClipboard::mimeData(QClipboard::Mode mode)
{
- if (QClipboard::Clipboard != mode || !QtAndroidClipboard::hasClipboardText())
- return 0;
-
- m_mimeData.setText(QtAndroidClipboard::clipboardText());
+ Q_ASSERT(supportsMode(mode));
+ m_mimeData.setText(QtAndroidClipboard::hasClipboardText()
+ ? QtAndroidClipboard::clipboardText()
+ : QString());
return &m_mimeData;
}
void QAndroidPlatformClipboard::setMimeData(QMimeData *data, QClipboard::Mode mode)
{
- if (!data || !data->hasText() || QClipboard::Clipboard != mode)
- return;
-
- QtAndroidClipboard::setClipboardText(data->text());
+ Q_ASSERT(supportsMode(mode));
+ QtAndroidClipboard::setClipboardText(data != 0 && data->hasText() ? data->text() : QString());
+ if (data != 0)
+ data->deleteLater();
}
bool QAndroidPlatformClipboard::supportsMode(QClipboard::Mode mode) const
diff --git a/src/plugins/platforms/android/qandroidplatformopenglwindow.cpp b/src/plugins/platforms/android/qandroidplatformopenglwindow.cpp
index 8afc35c57a..8dc8e84f0a 100644
--- a/src/plugins/platforms/android/qandroidplatformopenglwindow.cpp
+++ b/src/plugins/platforms/android/qandroidplatformopenglwindow.cpp
@@ -37,6 +37,7 @@
#include "qandroidplatformscreen.h"
#include "androidjnimain.h"
#include "qandroideventdispatcher.h"
+#include "androiddeadlockprotector.h"
#include <QSurfaceFormat>
#include <QtGui/private/qwindow_p.h>
@@ -120,6 +121,10 @@ EGLSurface QAndroidPlatformOpenGLWindow::eglSurface(EGLConfig config)
QMutexLocker lock(&m_surfaceMutex);
if (m_nativeSurfaceId == -1) {
+ AndroidDeadlockProtector protector;
+ if (!protector.acquire())
+ return m_eglSurface;
+
const bool windowStaysOnTop = bool(window()->flags() & Qt::WindowStaysOnTopHint);
m_nativeSurfaceId = QtAndroid::createSurface(this, geometry(), windowStaysOnTop, 32);
m_surfaceWaitCondition.wait(&m_surfaceMutex);
diff --git a/src/plugins/platforms/android/qandroidplatformscreen.cpp b/src/plugins/platforms/android/qandroidplatformscreen.cpp
index 09e5d7e346..8a07735e5f 100644
--- a/src/plugins/platforms/android/qandroidplatformscreen.cpp
+++ b/src/plugins/platforms/android/qandroidplatformscreen.cpp
@@ -43,6 +43,7 @@
#include "qandroidplatformwindow.h"
#include "androidjnimain.h"
#include "androidjnimenu.h"
+#include "androiddeadlockprotector.h"
#include <android/bitmap.h>
#include <android/native_window_jni.h>
@@ -299,6 +300,9 @@ void QAndroidPlatformScreen::doRedraw()
QMutexLocker lock(&m_surfaceMutex);
if (m_id == -1 && m_rasterSurfaces) {
m_id = QtAndroid::createSurface(this, m_availableGeometry, true, m_depth);
+ AndroidDeadlockProtector protector;
+ if (!protector.acquire())
+ return;
m_surfaceWaitCondition.wait(&m_surfaceMutex);
}