summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/android/src/qandroidinputcontext.cpp
diff options
context:
space:
mode:
authorPaul Olav Tvete <paul.tvete@digia.com>2013-03-04 10:16:42 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-03-05 08:31:23 +0100
commit97fcf3bc987a18f32233fea550eb4a5a22e2b822 (patch)
tree31d75557fdc4a525af8f5053db514066c63bd1bd /src/plugins/platforms/android/src/qandroidinputcontext.cpp
parent1b582d64eb6d13e60a02ebc40956302a4864eb6c (diff)
Introducing the Qt Android port
Based on the Necessitas project by Bogdan Vatra. Contributors to the Qt5 project: BogDan Vatra <bogdan@kde.org> Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@digia.com> hjk <hjk121@nokiamail.com> Oswald Buddenhagen <oswald.buddenhagen@digia.com> Paul Olav Tvete <paul.tvete@digia.com> Robin Burchell <robin+qt@viroteck.net> Samuel Rødal <samuel.rodal@digia.com> Yoann Lopes <yoann.lopes@digia.com> The full history of the Qt5 port can be found in refs/old-heads/android, SHA-1 249ca9ca2c7d876b91b31df9434dde47f9065d0d Change-Id: Iff1a7b2dbb707c986f2639e65e39ed8f22430120 Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@digia.com> Reviewed-by: Lars Knoll <lars.knoll@digia.com>
Diffstat (limited to 'src/plugins/platforms/android/src/qandroidinputcontext.cpp')
-rw-r--r--src/plugins/platforms/android/src/qandroidinputcontext.cpp644
1 files changed, 644 insertions, 0 deletions
diff --git a/src/plugins/platforms/android/src/qandroidinputcontext.cpp b/src/plugins/platforms/android/src/qandroidinputcontext.cpp
new file mode 100644
index 0000000000..37fb605ea8
--- /dev/null
+++ b/src/plugins/platforms/android/src/qandroidinputcontext.cpp
@@ -0,0 +1,644 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 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 <android/log.h>
+
+#include "qandroidinputcontext.h"
+#include "androidjnimain.h"
+#include "androidjniinput.h"
+#include <QDebug>
+#include <qevent.h>
+#include <qguiapplication.h>
+#include <qsharedpointer.h>
+#include <qthread.h>
+#include <qinputmethod.h>
+#include <qwindow.h>
+
+#include <QTextCharFormat>
+
+QT_BEGIN_NAMESPACE
+
+static QAndroidInputContext *m_androidInputContext = 0;
+static char const *const QtNativeInputConnectionClassName = "org/qtproject/qt5/android/QtNativeInputConnection";
+static char const *const QtExtractedTextClassName = "org/qtproject/qt5/android/QtExtractedText";
+static jclass m_extractedTextClass = 0;
+static jmethodID m_classConstructorMethodID = 0;
+static jfieldID m_partialEndOffsetFieldID = 0;
+static jfieldID m_partialStartOffsetFieldID = 0;
+static jfieldID m_selectionEndFieldID = 0;
+static jfieldID m_selectionStartFieldID = 0;
+static jfieldID m_startOffsetFieldID = 0;
+static jfieldID m_textFieldID = 0;
+
+static jboolean commitText(JNIEnv *env, jobject /*thiz*/, jstring text, jint newCursorPosition)
+{
+ if (!m_androidInputContext)
+ return JNI_FALSE;
+
+ jboolean isCopy;
+ const jchar *jstr = env->GetStringChars(text, &isCopy);
+ QString str(reinterpret_cast<const QChar *>(jstr), env->GetStringLength(text));
+ env->ReleaseStringChars(text, jstr);
+
+ return m_androidInputContext->commitText(str, newCursorPosition);
+}
+
+static jboolean deleteSurroundingText(JNIEnv */*env*/, jobject /*thiz*/, jint leftLength, jint rightLength)
+{
+ if (!m_androidInputContext)
+ return JNI_FALSE;
+
+ return m_androidInputContext->deleteSurroundingText(leftLength, rightLength);
+}
+
+static jboolean finishComposingText(JNIEnv */*env*/, jobject /*thiz*/)
+{
+ if (!m_androidInputContext)
+ return JNI_FALSE;
+
+ return m_androidInputContext->finishComposingText();
+}
+
+static jint getCursorCapsMode(JNIEnv */*env*/, jobject /*thiz*/, jint reqModes)
+{
+ if (!m_androidInputContext)
+ return 0;
+
+ return m_androidInputContext->getCursorCapsMode(reqModes);
+}
+
+static jobject getExtractedText(JNIEnv *env, jobject /*thiz*/, int hintMaxChars, int hintMaxLines, jint flags)
+{
+ if (!m_androidInputContext)
+ return 0;
+
+ const QAndroidInputContext::ExtractedText &extractedText =
+ m_androidInputContext->getExtractedText(hintMaxChars, hintMaxLines, flags);
+
+ jobject object = env->NewObject(m_extractedTextClass, m_classConstructorMethodID);
+ env->SetIntField(object, m_partialStartOffsetFieldID, extractedText.partialStartOffset);
+ env->SetIntField(object, m_partialEndOffsetFieldID, extractedText.partialEndOffset);
+ env->SetIntField(object, m_selectionStartFieldID, extractedText.selectionStart);
+ env->SetIntField(object, m_selectionEndFieldID, extractedText.selectionEnd);
+ env->SetIntField(object, m_startOffsetFieldID, extractedText.startOffset);
+ env->SetObjectField(object,
+ m_textFieldID,
+ env->NewString(reinterpret_cast<const jchar *>(extractedText.text.constData()),
+ jsize(extractedText.text.length())));
+
+ return object;
+}
+
+static jstring getSelectedText(JNIEnv *env, jobject /*thiz*/, jint flags)
+{
+ if (!m_androidInputContext)
+ return 0;
+
+ const QString &text = m_androidInputContext->getSelectedText(flags);
+ return env->NewString(reinterpret_cast<const jchar *>(text.constData()), jsize(text.length()));
+}
+
+static jstring getTextAfterCursor(JNIEnv *env, jobject /*thiz*/, jint length, jint flags)
+{
+ if (!m_androidInputContext)
+ return 0;
+
+ const QString &text = m_androidInputContext->getTextAfterCursor(length, flags);
+ return env->NewString(reinterpret_cast<const jchar *>(text.constData()), jsize(text.length()));
+}
+
+static jstring getTextBeforeCursor(JNIEnv *env, jobject /*thiz*/, jint length, jint flags)
+{
+ if (!m_androidInputContext)
+ return 0;
+
+ const QString &text = m_androidInputContext->getTextBeforeCursor(length, flags);
+ return env->NewString(reinterpret_cast<const jchar *>(text.constData()), jsize(text.length()));
+}
+
+static jboolean setComposingText(JNIEnv *env, jobject /*thiz*/, jstring text, jint newCursorPosition)
+{
+ if (!m_androidInputContext)
+ return JNI_FALSE;
+
+ jboolean isCopy;
+ const jchar *jstr = env->GetStringChars(text, &isCopy);
+ QString str(reinterpret_cast<const QChar *>(jstr), env->GetStringLength(text));
+ env->ReleaseStringChars(text, jstr);
+
+ return m_androidInputContext->setComposingText(str, newCursorPosition);
+}
+
+static jboolean setSelection(JNIEnv */*env*/, jobject /*thiz*/, jint start, jint end)
+{
+ if (!m_androidInputContext)
+ return JNI_FALSE;
+
+ return m_androidInputContext->setSelection(start, end);
+}
+
+static jboolean selectAll(JNIEnv */*env*/, jobject /*thiz*/)
+{
+ if (!m_androidInputContext)
+ return JNI_FALSE;
+
+ return m_androidInputContext->selectAll();
+}
+
+static jboolean cut(JNIEnv */*env*/, jobject /*thiz*/)
+{
+ if (!m_androidInputContext)
+ return JNI_FALSE;
+
+ return m_androidInputContext->cut();
+}
+
+static jboolean copy(JNIEnv */*env*/, jobject /*thiz*/)
+{
+ if (!m_androidInputContext)
+ return JNI_FALSE;
+
+ return m_androidInputContext->copy();
+}
+
+static jboolean copyURL(JNIEnv */*env*/, jobject /*thiz*/)
+{
+ if (!m_androidInputContext)
+ return JNI_FALSE;
+
+ return m_androidInputContext->copyURL();
+}
+
+static jboolean paste(JNIEnv */*env*/, jobject /*thiz*/)
+{
+ if (!m_androidInputContext)
+ return JNI_FALSE;
+
+ return m_androidInputContext->paste();
+}
+
+
+static JNINativeMethod methods[] = {
+ {"commitText", "(Ljava/lang/String;I)Z", (void *)commitText},
+ {"deleteSurroundingText", "(II)Z", (void *)deleteSurroundingText},
+ {"finishComposingText", "()Z", (void *)finishComposingText},
+ {"getCursorCapsMode", "(I)I", (void *)getCursorCapsMode},
+ {"getExtractedText", "(III)Lorg/qtproject/qt5/android/QtExtractedText;", (void *)getExtractedText},
+ {"getSelectedText", "(I)Ljava/lang/String;", (void *)getSelectedText},
+ {"getTextAfterCursor", "(II)Ljava/lang/String;", (void *)getTextAfterCursor},
+ {"getTextBeforeCursor", "(II)Ljava/lang/String;", (void *)getTextBeforeCursor},
+ {"setComposingText", "(Ljava/lang/String;I)Z", (void *)setComposingText},
+ {"setSelection", "(II)Z", (void *)setSelection},
+ {"selectAll", "()Z", (void *)selectAll},
+ {"cut", "()Z", (void *)cut},
+ {"copy", "()Z", (void *)copy},
+ {"copyURL", "()Z", (void *)copyURL},
+ {"paste", "()Z", (void *)paste}
+};
+
+
+QAndroidInputContext::QAndroidInputContext():QPlatformInputContext()
+{
+ JNIEnv *env = 0;
+ if (QtAndroid::javaVM()->AttachCurrentThread(&env, NULL) < 0) {
+ qCritical() << "AttachCurrentThread failed";
+ return;
+ }
+
+ jclass clazz = QtAndroid::findClass(QtNativeInputConnectionClassName, env);
+ if (clazz == NULL) {
+ qCritical() << "Native registration unable to find class '"
+ << QtNativeInputConnectionClassName
+ << "'";
+ return;
+ }
+
+ if (env->RegisterNatives(clazz, methods, sizeof(methods) / sizeof(methods[0])) < 0) {
+ qCritical() << "RegisterNatives failed for '"
+ << QtNativeInputConnectionClassName
+ << "'";
+ return;
+ }
+
+ clazz = QtAndroid::findClass(QtExtractedTextClassName, env);
+ if (clazz == NULL) {
+ qCritical() << "Native registration unable to find class '"
+ << QtExtractedTextClassName
+ << "'";
+ return;
+ }
+
+ m_extractedTextClass = static_cast<jclass>(env->NewGlobalRef(clazz));
+ m_classConstructorMethodID = env->GetMethodID(m_extractedTextClass, "<init>", "()V");
+ if (m_classConstructorMethodID == NULL) {
+ qCritical() << "GetMethodID failed";
+ return;
+ }
+
+ m_partialEndOffsetFieldID = env->GetFieldID(m_extractedTextClass, "partialEndOffset", "I");
+ if (m_partialEndOffsetFieldID == NULL) {
+ qCritical() << "Can't find field partialEndOffset";
+ return;
+ }
+
+ m_partialStartOffsetFieldID = env->GetFieldID(m_extractedTextClass, "partialStartOffset", "I");
+ if (m_partialStartOffsetFieldID == NULL) {
+ qCritical() << "Can't find field partialStartOffset";
+ return;
+ }
+
+ m_selectionEndFieldID = env->GetFieldID(m_extractedTextClass, "selectionEnd", "I");
+ if (m_selectionEndFieldID == NULL) {
+ qCritical() << "Can't find field selectionEnd";
+ return;
+ }
+
+ m_selectionStartFieldID = env->GetFieldID(m_extractedTextClass, "selectionStart", "I");
+ if (m_selectionStartFieldID == NULL) {
+ qCritical() << "Can't find field selectionStart";
+ return;
+ }
+
+ m_startOffsetFieldID = env->GetFieldID(m_extractedTextClass, "startOffset", "I");
+ if (m_startOffsetFieldID == NULL) {
+ qCritical() << "Can't find field startOffset";
+ return;
+ }
+
+ m_textFieldID = env->GetFieldID(m_extractedTextClass, "text", "Ljava/lang/String;");
+ if (m_textFieldID == NULL) {
+ qCritical() << "Can't find field text";
+ return;
+ }
+ qRegisterMetaType<QInputMethodEvent *>("QInputMethodEvent*");
+ qRegisterMetaType<QInputMethodQueryEvent *>("QInputMethodQueryEvent*");
+ m_androidInputContext = this;
+}
+
+QAndroidInputContext::~QAndroidInputContext()
+{
+ m_androidInputContext = 0;
+ m_extractedTextClass = 0;
+ m_partialEndOffsetFieldID = 0;
+ m_partialStartOffsetFieldID = 0;
+ m_selectionEndFieldID = 0;
+ m_selectionStartFieldID = 0;
+ m_startOffsetFieldID = 0;
+ m_textFieldID = 0;
+}
+
+void QAndroidInputContext::reset()
+{
+ clear();
+ if (qGuiApp->focusObject())
+ QtAndroidInput::resetSoftwareKeyboard();
+ else
+ QtAndroidInput::hideSoftwareKeyboard();
+}
+
+void QAndroidInputContext::commit()
+{
+ finishComposingText();
+
+ QSharedPointer<QInputMethodQueryEvent> query = focusObjectInputMethodQuery();
+ if (!query.isNull()) {
+ const int cursorPos = query->value(Qt::ImCursorPosition).toInt();
+ QtAndroidInput::updateSelection(cursorPos, cursorPos, -1, -1); //selection empty and no pre-edit text
+ }
+}
+
+void QAndroidInputContext::update(Qt::InputMethodQueries queries)
+{
+ QSharedPointer<QInputMethodQueryEvent> query = focusObjectInputMethodQuery(queries);
+ if (query.isNull())
+ return;
+#warning TODO extract the needed data from query
+}
+
+void QAndroidInputContext::invokeAction(QInputMethod::Action action, int cursorPosition)
+{
+#warning TODO Handle at least QInputMethod::ContextMenu action
+ Q_UNUSED(action)
+ Q_UNUSED(cursorPosition)
+
+ if (action == QInputMethod::Click)
+ commit();
+}
+
+QRectF QAndroidInputContext::keyboardRect() const
+{
+ return QPlatformInputContext::keyboardRect();
+}
+
+bool QAndroidInputContext::isAnimating() const
+{
+ return false;
+}
+
+void QAndroidInputContext::showInputPanel()
+{
+ QSharedPointer<QInputMethodQueryEvent> query = focusObjectInputMethodQuery();
+ if (query.isNull())
+ return;
+ QRectF itemRect = qGuiApp->inputMethod()->inputItemRectangle();
+ QRect rect = qGuiApp->inputMethod()->inputItemTransform().mapRect(itemRect).toRect();
+ QWindow *window = qGuiApp->focusWindow();
+ if (window)
+ rect = QRect(window->mapToGlobal(rect.topLeft()), rect.size());
+
+ QtAndroidInput::showSoftwareKeyboard(rect.left(),
+ rect.top(),
+ rect.width(),
+ rect.height(),
+ query->value(Qt::ImHints).toUInt());
+}
+
+void QAndroidInputContext::hideInputPanel()
+{
+ QtAndroidInput::hideSoftwareKeyboard();
+}
+
+bool QAndroidInputContext::isInputPanelVisible() const
+{
+ return QtAndroidInput::isSoftwareKeyboardVisible();
+}
+
+bool QAndroidInputContext::isComposing() const
+{
+ return m_composingText.length();
+}
+
+void QAndroidInputContext::clear()
+{
+ m_composingText.clear();
+ m_extractedText.clear();
+}
+
+void QAndroidInputContext::sendEvent(QObject *receiver, QInputMethodEvent *event)
+{
+ QCoreApplication::sendEvent(receiver, event);
+}
+
+void QAndroidInputContext::sendEvent(QObject *receiver, QInputMethodQueryEvent *event)
+{
+ QCoreApplication::sendEvent(receiver, event);
+}
+
+jboolean QAndroidInputContext::commitText(const QString &text, jint /*newCursorPosition*/)
+{
+ m_composingText = text;
+ return finishComposingText();
+}
+
+jboolean QAndroidInputContext::deleteSurroundingText(jint leftLength, jint rightLength)
+{
+ QSharedPointer<QInputMethodQueryEvent> query = focusObjectInputMethodQuery();
+ if (query.isNull())
+ return JNI_TRUE;
+
+ m_composingText.clear();
+
+ QInputMethodEvent event;
+ event.setCommitString(QString(), -leftLength, leftLength+rightLength);
+ sendInputMethodEvent(&event);
+ clear();
+
+ return JNI_TRUE;
+}
+
+jboolean QAndroidInputContext::finishComposingText()
+{
+ QInputMethodEvent event;
+ event.setCommitString(m_composingText);
+ sendInputMethodEvent(&event);
+ clear();
+
+ return JNI_TRUE;
+}
+
+jint QAndroidInputContext::getCursorCapsMode(jint /*reqModes*/)
+{
+ jint res = 0;
+ QSharedPointer<QInputMethodQueryEvent> query = focusObjectInputMethodQuery();
+ if (query.isNull())
+ return res;
+
+ const uint qtInputMethodHints = query->value(Qt::ImHints).toUInt();
+
+ if (qtInputMethodHints & Qt::ImhPreferUppercase)
+ res = CAP_MODE_SENTENCES;
+
+ if (qtInputMethodHints & Qt::ImhUppercaseOnly)
+ res = CAP_MODE_CHARACTERS;
+
+ return res;
+}
+
+const QAndroidInputContext::ExtractedText &QAndroidInputContext::getExtractedText(jint hintMaxChars, jint /*hintMaxLines*/, jint /*flags*/)
+{
+ QSharedPointer<QInputMethodQueryEvent> query = focusObjectInputMethodQuery();
+ if (query.isNull())
+ return m_extractedText;
+
+ if (hintMaxChars)
+ m_extractedText.text = query->value(Qt::ImSurroundingText).toString().right(hintMaxChars);
+
+ m_extractedText.startOffset = query->value(Qt::ImCursorPosition).toInt();
+ const QString &selection = query->value(Qt::ImCurrentSelection).toString();
+ const int selLen = selection.length();
+ if (selLen) {
+ m_extractedText.selectionStart = query->value(Qt::ImAnchorPosition).toInt();
+ m_extractedText.selectionEnd = m_extractedText.startOffset;
+ }
+
+ return m_extractedText;
+}
+
+QString QAndroidInputContext::getSelectedText(jint /*flags*/)
+{
+ QSharedPointer<QInputMethodQueryEvent> query = focusObjectInputMethodQuery();
+ if (query.isNull())
+ return QString();
+
+ return query->value(Qt::ImCurrentSelection).toString();
+}
+
+QString QAndroidInputContext::getTextAfterCursor(jint length, jint /*flags*/)
+{
+ QSharedPointer<QInputMethodQueryEvent> query = focusObjectInputMethodQuery();
+ if (query.isNull())
+ return QString();
+
+ QString text = query->value(Qt::ImSurroundingText).toString();
+ if (!text.length())
+ return text;
+
+ int cursorPos = query->value(Qt::ImCursorPosition).toInt();
+ return text.mid(cursorPos, length);
+}
+
+QString QAndroidInputContext::getTextBeforeCursor(jint length, jint /*flags*/)
+{
+ QSharedPointer<QInputMethodQueryEvent> query = focusObjectInputMethodQuery();
+ if (query.isNull())
+ return QString();
+
+ QString text = query->value(Qt::ImSurroundingText).toString();
+ if (!text.length())
+ return text;
+
+ int cursorPos = query->value(Qt::ImCursorPosition).toInt();
+ const int wordLeftPos = cursorPos - length;
+ return text.mid(wordLeftPos > 0 ? wordLeftPos : 0, cursorPos);
+}
+
+jboolean QAndroidInputContext::setComposingText(const QString &text, jint newCursorPosition)
+{
+ if (newCursorPosition > 0)
+ newCursorPosition += text.length() - 1;
+ m_composingText = text;
+ QList<QInputMethodEvent::Attribute> attributes;
+ attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::Cursor,
+ newCursorPosition,
+ 1,
+ QVariant()));
+ // Show compose text underlined
+ QTextCharFormat underlined;
+ underlined.setFontUnderline(true);
+ attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat,0, text.length(),
+ QVariant(underlined)));
+
+ QInputMethodEvent event(m_composingText, attributes);
+ sendInputMethodEvent(&event);
+
+ QSharedPointer<QInputMethodQueryEvent> query = focusObjectInputMethodQuery();
+ if (!query.isNull()) {
+ int cursorPos = query->value(Qt::ImCursorPosition).toInt();
+ int preeditLength = text.length();
+ QtAndroidInput::updateSelection(cursorPos+preeditLength, cursorPos+preeditLength, cursorPos, cursorPos+preeditLength);
+ }
+
+ return JNI_TRUE;
+}
+
+jboolean QAndroidInputContext::setSelection(jint start, jint end)
+{
+ QList<QInputMethodEvent::Attribute> attributes;
+ attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::Selection,
+ start,
+ end - start,
+ QVariant()));
+
+ QInputMethodEvent event(QString(), attributes);
+ sendInputMethodEvent(&event);
+ return JNI_TRUE;
+}
+
+jboolean QAndroidInputContext::selectAll()
+{
+#warning TODO
+ return JNI_FALSE;
+}
+
+jboolean QAndroidInputContext::cut()
+{
+#warning TODO
+ return JNI_FALSE;
+}
+
+jboolean QAndroidInputContext::copy()
+{
+#warning TODO
+ return JNI_FALSE;
+}
+
+jboolean QAndroidInputContext::copyURL()
+{
+#warning TODO
+ return JNI_FALSE;
+}
+
+jboolean QAndroidInputContext::paste()
+{
+#warning TODO
+ return JNI_FALSE;
+}
+
+QSharedPointer<QInputMethodQueryEvent> QAndroidInputContext::focusObjectInputMethodQuery(Qt::InputMethodQueries queries)
+{
+#warning TODO make qGuiApp->focusObject() thread safe !!!
+ QObject *focusObject = qGuiApp->focusObject();
+ if (!focusObject)
+ return QSharedPointer<QInputMethodQueryEvent>();
+
+ QSharedPointer<QInputMethodQueryEvent> ret = QSharedPointer<QInputMethodQueryEvent>(new QInputMethodQueryEvent(queries));
+ if (qGuiApp->thread()==QThread::currentThread()) {
+ QCoreApplication::sendEvent(focusObject, ret.data());
+ } else {
+ QMetaObject::invokeMethod(this,
+ "sendEvent",
+ Qt::BlockingQueuedConnection,
+ Q_ARG(QObject*, focusObject),
+ Q_ARG(QInputMethodQueryEvent*, ret.data()));
+ }
+
+ return ret;
+}
+
+void QAndroidInputContext::sendInputMethodEvent(QInputMethodEvent *event)
+{
+#warning TODO make qGuiApp->focusObject() thread safe !!!
+ QObject *focusObject = qGuiApp->focusObject();
+ if (!focusObject)
+ return;
+
+ if (qGuiApp->thread() == QThread::currentThread()) {
+ QCoreApplication::sendEvent(focusObject, event);
+ } else {
+ QMetaObject::invokeMethod(this,
+ "sendEvent",
+ Qt::BlockingQueuedConnection,
+ Q_ARG(QObject*, focusObject),
+ Q_ARG(QInputMethodEvent*, event));
+ }
+}
+
+QT_END_NAMESPACE