diff options
Diffstat (limited to 'src/plugins/platforms/android')
11 files changed, 133 insertions, 32 deletions
diff --git a/src/plugins/platforms/android/androidjniaccessibility.cpp b/src/plugins/platforms/android/androidjniaccessibility.cpp index fa7e259460..d9f5cec27a 100644 --- a/src/plugins/platforms/android/androidjniaccessibility.cpp +++ b/src/plugins/platforms/android/androidjniaccessibility.cpp @@ -56,6 +56,18 @@ static const char m_methodErrorMsg[] = "Can't find method \"%s%s\""; namespace QtAndroidAccessibility { + static jmethodID m_addActionMethodID = 0; + static jmethodID m_setCheckableMethodID = 0; + static jmethodID m_setCheckedMethodID = 0; + static jmethodID m_setClickableMethodID = 0; + static jmethodID m_setContentDescriptionMethodID = 0; + static jmethodID m_setEnabledMethodID = 0; + static jmethodID m_setFocusableMethodID = 0; + static jmethodID m_setFocusedMethodID = 0; + static jmethodID m_setTextSelectionMethodID = 0; + static jmethodID m_setVisibleToUserMethodID = 0; + + static void setActive(JNIEnv */*env*/, jobject /*thiz*/, jboolean active) { QAndroidPlatformIntegration *platformIntegration = QtAndroid::androidPlatformIntegration(); @@ -164,17 +176,6 @@ if (!clazz) { \ //__android_log_print(ANDROID_LOG_FATAL, m_qtTag, m_methodErrorMsg, METHOD_NAME, METHOD_SIGNATURE); -#define CALL_METHOD(OBJECT, METHOD_NAME, METHOD_SIGNATURE, ...) \ -{ \ - jclass clazz = env->GetObjectClass(OBJECT); \ - jmethodID method = env->GetMethodID(clazz, METHOD_NAME, METHOD_SIGNATURE); \ - if (!method) { \ - __android_log_print(ANDROID_LOG_WARN, m_qtTag, m_methodErrorMsg, METHOD_NAME, METHOD_SIGNATURE); \ - return false; \ - } \ - env->CallVoidMethod(OBJECT, method, __VA_ARGS__); \ -} - static jstring descriptionForAccessibleObject(JNIEnv *env, jobject /*thiz*/, jint objectId) { @@ -210,30 +211,30 @@ if (!clazz) { \ int startSelection; int endSelection; textIface->selection(0, &startSelection, &endSelection); - CALL_METHOD(node, "setTextSelection", "(II)V", startSelection, endSelection) + env->CallVoidMethod(node, m_setTextSelectionMethodID, startSelection, endSelection); } } - CALL_METHOD(node, "setEnabled", "(Z)V", !state.disabled) - CALL_METHOD(node, "setFocusable", "(Z)V", (bool)state.focusable) - CALL_METHOD(node, "setFocused", "(Z)V", (bool)state.focused) - CALL_METHOD(node, "setCheckable", "(Z)V", (bool)state.checkable) - CALL_METHOD(node, "setChecked", "(Z)V", (bool)state.checked) - CALL_METHOD(node, "setVisibleToUser", "(Z)V", !state.invisible) + env->CallVoidMethod(node, m_setEnabledMethodID, !state.disabled); + env->CallVoidMethod(node, m_setCheckedMethodID, (bool)state.checked); + env->CallVoidMethod(node, m_setFocusableMethodID, (bool)state.focusable); + env->CallVoidMethod(node, m_setFocusedMethodID, (bool)state.focused); + env->CallVoidMethod(node, m_setCheckableMethodID, (bool)state.checkable); + env->CallVoidMethod(node, m_setVisibleToUserMethodID, !state.invisible); if (iface->actionInterface()) { QStringList actions = iface->actionInterface()->actionNames(); bool clickable = actions.contains(QAccessibleActionInterface::pressAction()); bool toggle = actions.contains(QAccessibleActionInterface::toggleAction()); if (clickable || toggle) { - CALL_METHOD(node, "setClickable", "(Z)V", (bool)clickable) - CALL_METHOD(node, "addAction", "(I)V", 16) // ACTION_CLICK defined in AccessibilityNodeInfo + env->CallVoidMethod(node, m_setClickableMethodID, (bool)clickable); + env->CallVoidMethod(node, m_addActionMethodID, (int)16); // ACTION_CLICK defined in AccessibilityNodeInfo } } jstring jdesc = env->NewString((jchar*) desc.constData(), (jsize) desc.size()); //CALL_METHOD(node, "setText", "(Ljava/lang/CharSequence;)V", jdesc) - CALL_METHOD(node, "setContentDescription", "(Ljava/lang/CharSequence;)V", jdesc) + env->CallVoidMethod(node, m_setContentDescriptionMethodID, jdesc); return true; } @@ -249,6 +250,13 @@ if (!clazz) { \ {"clickAction", "(I)Z", (void*)clickAction}, }; +#define GET_AND_CHECK_STATIC_METHOD(VAR, CLASS, METHOD_NAME, METHOD_SIGNATURE) \ + VAR = env->GetMethodID(CLASS, METHOD_NAME, METHOD_SIGNATURE); \ + if (!VAR) { \ + __android_log_print(ANDROID_LOG_FATAL, QtAndroid::qtTagText(), QtAndroid::methodErrorMsgFmt(), METHOD_NAME, METHOD_SIGNATURE); \ + return false; \ + } + bool registerNatives(JNIEnv *env) { jclass clazz; @@ -260,6 +268,18 @@ if (!clazz) { \ return false; } + jclass nodeInfoClass = env->FindClass("android/view/accessibility/AccessibilityNodeInfo"); + GET_AND_CHECK_STATIC_METHOD(m_addActionMethodID, nodeInfoClass, "addAction", "(I)V"); + GET_AND_CHECK_STATIC_METHOD(m_setCheckableMethodID, nodeInfoClass, "setCheckable", "(Z)V"); + GET_AND_CHECK_STATIC_METHOD(m_setCheckedMethodID, nodeInfoClass, "setChecked", "(Z)V"); + GET_AND_CHECK_STATIC_METHOD(m_setClickableMethodID, nodeInfoClass, "setClickable", "(Z)V"); + GET_AND_CHECK_STATIC_METHOD(m_setContentDescriptionMethodID, nodeInfoClass, "setContentDescription", "(Ljava/lang/CharSequence;)V"); + GET_AND_CHECK_STATIC_METHOD(m_setEnabledMethodID, nodeInfoClass, "setEnabled", "(Z)V"); + GET_AND_CHECK_STATIC_METHOD(m_setFocusableMethodID, nodeInfoClass, "setFocusable", "(Z)V"); + GET_AND_CHECK_STATIC_METHOD(m_setFocusedMethodID, nodeInfoClass, "setFocused", "(Z)V"); + GET_AND_CHECK_STATIC_METHOD(m_setTextSelectionMethodID, nodeInfoClass, "setTextSelection", "(II)V"); + GET_AND_CHECK_STATIC_METHOD(m_setVisibleToUserMethodID, nodeInfoClass, "setVisibleToUser", "(Z)V"); + return true; } } diff --git a/src/plugins/platforms/android/androidjnimain.cpp b/src/plugins/platforms/android/androidjnimain.cpp index 7ca4db710b..d484a2faff 100644 --- a/src/plugins/platforms/android/androidjnimain.cpp +++ b/src/plugins/platforms/android/androidjnimain.cpp @@ -573,8 +573,11 @@ static void updateWindow(JNIEnv */*env*/, jobject /*thiz*/) return; if (QGuiApplication::instance() != 0) { - foreach (QWindow *w, QGuiApplication::topLevelWindows()) - QWindowSystemInterface::handleExposeEvent(w, QRegion(w->geometry())); + foreach (QWindow *w, QGuiApplication::topLevelWindows()) { + QRect availableGeometry = w->screen()->availableGeometry(); + if (w->geometry().width() > 0 && w->geometry().height() > 0 && availableGeometry.width() > 0 && availableGeometry.height() > 0) + QWindowSystemInterface::handleExposeEvent(w, QRegion(w->geometry())); + } } QAndroidPlatformScreen *screen = static_cast<QAndroidPlatformScreen *>(m_androidPlatformIntegration->screen()); diff --git a/src/plugins/platforms/android/qandroidinputcontext.cpp b/src/plugins/platforms/android/qandroidinputcontext.cpp index c2e5f83639..5d47d2fda4 100644 --- a/src/plugins/platforms/android/qandroidinputcontext.cpp +++ b/src/plugins/platforms/android/qandroidinputcontext.cpp @@ -472,12 +472,24 @@ void QAndroidInputContext::updateCursorPosition() if (m_composingText.isEmpty() != (m_composingTextStart == -1)) qWarning() << "Input method out of sync" << m_composingText << m_composingTextStart; - - // Qt's idea of the cursor position is the start of the preedit area, so we have to maintain our own preedit cursor pos int realCursorPosition = cursorPos; + int realAnchorPosition = cursorPos; + + int cpos = query->value(Qt::ImCursorPosition).toInt(); + int anchor = query->value(Qt::ImAnchorPosition).toInt(); + if (cpos != anchor) { + if (!m_composingText.isEmpty()) { + qWarning("Selecting text while preediting may give unpredictable results."); + finishComposingText(); + } + int blockPos = getBlockPosition(query); + realCursorPosition = blockPos + cpos; + realAnchorPosition = blockPos + anchor; + } + // Qt's idea of the cursor position is the start of the preedit area, so we maintain our own preedit cursor pos if (!m_composingText.isEmpty()) - realCursorPosition = m_composingCursor; - QtAndroidInput::updateSelection(realCursorPosition, realCursorPosition, //empty selection + realCursorPosition = realAnchorPosition = m_composingCursor; + QtAndroidInput::updateSelection(realCursorPosition, realAnchorPosition, m_composingTextStart, m_composingTextStart + composeLength); // pre-edit text } } diff --git a/src/plugins/platforms/android/qandroidplatformintegration.cpp b/src/plugins/platforms/android/qandroidplatformintegration.cpp index 7f0f40be0f..213b1bb7e6 100644 --- a/src/plugins/platforms/android/qandroidplatformintegration.cpp +++ b/src/plugins/platforms/android/qandroidplatformintegration.cpp @@ -45,11 +45,14 @@ #include <QGuiApplication> #include <QOpenGLContext> #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" @@ -207,6 +210,17 @@ QPlatformOpenGLContext *QAndroidPlatformIntegration::createPlatformOpenGLContext return new QAndroidPlatformOpenGLContext(format, context->shareHandle(), m_eglDisplay); } +QPlatformOffscreenSurface *QAndroidPlatformIntegration::createPlatformOffscreenSurface(QOffscreenSurface *surface) const +{ + QSurfaceFormat format(surface->requestedFormat()); + format.setAlphaBufferSize(8); + format.setRedBufferSize(8); + format.setGreenBufferSize(8); + format.setBlueBufferSize(8); + + return new QEGLPbuffer(m_eglDisplay, format, surface); +} + QPlatformWindow *QAndroidPlatformIntegration::createPlatformWindow(QWindow *window) const { if (window->type() == Qt::ForeignWindow) diff --git a/src/plugins/platforms/android/qandroidplatformintegration.h b/src/plugins/platforms/android/qandroidplatformintegration.h index 4a3fe6c766..f8fa1a91dd 100644 --- a/src/plugins/platforms/android/qandroidplatformintegration.h +++ b/src/plugins/platforms/android/qandroidplatformintegration.h @@ -82,6 +82,7 @@ public: QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const; QAbstractEventDispatcher *createEventDispatcher() const; QAndroidPlatformScreen *screen() { return m_primaryScreen; } + QPlatformOffscreenSurface *createPlatformOffscreenSurface(QOffscreenSurface *surface) const; virtual void setDesktopSize(int width, int height); virtual void setDisplayMetrics(int width, int height); diff --git a/src/plugins/platforms/android/qandroidplatformopenglcontext.cpp b/src/plugins/platforms/android/qandroidplatformopenglcontext.cpp index 152a06c99d..53047585cf 100644 --- a/src/plugins/platforms/android/qandroidplatformopenglcontext.cpp +++ b/src/plugins/platforms/android/qandroidplatformopenglcontext.cpp @@ -44,6 +44,8 @@ #include "qandroidplatformopenglwindow.h" #include "qandroidplatformintegration.h" +#include <QtPlatformSupport/private/qeglpbuffer_p.h> + #include <QSurface> #include <QtGui/private/qopenglcontext_p.h> @@ -98,7 +100,8 @@ EGLSurface QAndroidPlatformOpenGLContext::eglSurfaceForPlatformSurface(QPlatform { if (surface->surface()->surfaceClass() == QSurface::Window) return static_cast<QAndroidPlatformOpenGLWindow *>(surface)->eglSurface(eglConfig()); - return EGL_NO_SURFACE; + else + return static_cast<QEGLPbuffer *>(surface)->pbuffer(); } QT_END_NAMESPACE diff --git a/src/plugins/platforms/android/qandroidplatformopenglwindow.cpp b/src/plugins/platforms/android/qandroidplatformopenglwindow.cpp index 34db729289..f0c4a1de2a 100644 --- a/src/plugins/platforms/android/qandroidplatformopenglwindow.cpp +++ b/src/plugins/platforms/android/qandroidplatformopenglwindow.cpp @@ -47,7 +47,8 @@ #include <QSurfaceFormat> #include <qpa/qwindowsysteminterface.h> - +#include <qpa/qplatformscreen.h> +#include <QtPlatformSupport/private/qeglconvenience_p.h> #include <android/native_window.h> #include <android/native_window_jni.h> @@ -77,8 +78,20 @@ void QAndroidPlatformOpenGLWindow::setGeometry(const QRect &rect) if (rect == geometry()) return; + QRect oldGeometry = geometry(); + QAndroidPlatformWindow::setGeometry(rect); QtAndroid::setSurfaceGeometry(m_nativeSurfaceId, rect); + + QRect availableGeometry = screen()->availableGeometry(); + if (oldGeometry.width() == 0 + && oldGeometry.height() == 0 + && rect.width() > 0 + && rect.height() > 0 + && availableGeometry.width() > 0 + && availableGeometry.height() > 0) { + QWindowSystemInterface::handleExposeEvent(window(), QRegion(rect)); + } } EGLSurface QAndroidPlatformOpenGLWindow::eglSurface(EGLConfig config) @@ -100,8 +113,11 @@ void QAndroidPlatformOpenGLWindow::checkNativeSurface(EGLConfig config) createEgl(config); + // we've create another surface, the window should be repainted - QWindowSystemInterface::handleExposeEvent(window(), QRegion(geometry())); + QRect availableGeometry = screen()->availableGeometry(); + if (geometry().width() > 0 && geometry().height() > 0 && availableGeometry.width() > 0 && availableGeometry.height() > 0) + QWindowSystemInterface::handleExposeEvent(window(), QRegion(geometry())); } void QAndroidPlatformOpenGLWindow::createEgl(EGLConfig config) @@ -111,6 +127,7 @@ void QAndroidPlatformOpenGLWindow::createEgl(EGLConfig config) m_nativeWindow = ANativeWindow_fromSurface(env, m_androidSurfaceObject.object()); m_androidSurfaceObject = QJNIObjectPrivate(); m_eglSurface = eglCreateWindowSurface(m_eglDisplay, config, m_nativeWindow, NULL); + m_format = q_glFormatFromConfig(m_eglDisplay, config, window()->requestedFormat()); if (m_eglSurface == EGL_NO_SURFACE) { EGLint error = eglGetError(); eglTerminate(m_eglDisplay); @@ -118,6 +135,14 @@ void QAndroidPlatformOpenGLWindow::createEgl(EGLConfig config) } } +QSurfaceFormat QAndroidPlatformOpenGLWindow::format() const +{ + if (m_nativeWindow == 0) + return window()->requestedFormat(); + else + return m_format; +} + void QAndroidPlatformOpenGLWindow::clearEgl() { eglMakeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); @@ -143,7 +168,9 @@ void QAndroidPlatformOpenGLWindow::surfaceChanged(JNIEnv *jniEnv, jobject surfac unlockSurface(); // repaint the window - QWindowSystemInterface::handleExposeEvent(window(), QRegion(geometry())); + QRect availableGeometry = screen()->availableGeometry(); + if (geometry().width() > 0 && geometry().height() > 0 && availableGeometry.width() > 0 && availableGeometry.height() > 0) + QWindowSystemInterface::handleExposeEvent(window(), QRegion(geometry())); } QT_END_NAMESPACE diff --git a/src/plugins/platforms/android/qandroidplatformopenglwindow.h b/src/plugins/platforms/android/qandroidplatformopenglwindow.h index 7af8b722aa..83df15a524 100644 --- a/src/plugins/platforms/android/qandroidplatformopenglwindow.h +++ b/src/plugins/platforms/android/qandroidplatformopenglwindow.h @@ -60,6 +60,7 @@ public: void setGeometry(const QRect &rect); EGLSurface eglSurface(EGLConfig config); + QSurfaceFormat format() const; void checkNativeSurface(EGLConfig config); @@ -76,6 +77,7 @@ private: int m_nativeSurfaceId = -1; QJNIObjectPrivate m_androidSurfaceObject; QWaitCondition m_surfaceWaitCondition; + QSurfaceFormat m_format; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/android/qandroidplatformrasterwindow.cpp b/src/plugins/platforms/android/qandroidplatformrasterwindow.cpp index eb5a73c4a3..3fb236793b 100644 --- a/src/plugins/platforms/android/qandroidplatformrasterwindow.cpp +++ b/src/plugins/platforms/android/qandroidplatformrasterwindow.cpp @@ -76,6 +76,8 @@ void QAndroidPlatformRasterWindow::setGeometry(const QRect &rect) { m_oldGeometry = geometry(); QAndroidPlatformWindow::setGeometry(rect); + if (rect.topLeft() != m_oldGeometry.topLeft()) + repaint(QRegion(rect)); } QT_END_NAMESPACE diff --git a/src/plugins/platforms/android/qandroidplatformscreen.cpp b/src/plugins/platforms/android/qandroidplatformscreen.cpp index 678f4e6b5a..11472ce1da 100644 --- a/src/plugins/platforms/android/qandroidplatformscreen.cpp +++ b/src/plugins/platforms/android/qandroidplatformscreen.cpp @@ -55,6 +55,9 @@ #include <android/bitmap.h> #include <android/native_window_jni.h> +#include <QtGui/QGuiApplication> +#include <QtGui/QWindow> + QT_BEGIN_NAMESPACE #ifdef QANDROIDPLATFORMSCREEN_DEBUG @@ -217,11 +220,23 @@ void QAndroidPlatformScreen::setGeometry(const QRect &rect) if (m_geometry == rect) return; + QRect oldGeometry = m_geometry; + m_geometry = rect; QWindowSystemInterface::handleScreenGeometryChange(QPlatformScreen::screen(), geometry()); QWindowSystemInterface::handleScreenAvailableGeometryChange(QPlatformScreen::screen(), availableGeometry()); resizeMaximizedWindows(); + if (oldGeometry.width() == 0 && oldGeometry.height() == 0 && rect.width() > 0 && rect.height() > 0) { + QList<QWindow *> windows = QGuiApplication::allWindows(); + for (int i = 0; i < windows.size(); ++i) { + QWindow *w = windows.at(i); + QRect geometry = w->handle()->geometry(); + if (geometry.width() > 0 && geometry.height() > 0) + QWindowSystemInterface::handleExposeEvent(w, QRegion(geometry)); + } + } + if (m_id != -1) { if (m_nativeSurface) { ANativeWindow_release(m_nativeSurface); diff --git a/src/plugins/platforms/android/qandroidplatformwindow.cpp b/src/plugins/platforms/android/qandroidplatformwindow.cpp index b4231f0283..558525b78c 100644 --- a/src/plugins/platforms/android/qandroidplatformwindow.cpp +++ b/src/plugins/platforms/android/qandroidplatformwindow.cpp @@ -88,7 +88,9 @@ void QAndroidPlatformWindow::setVisible(bool visible) setGeometry(platformScreen()->availableGeometry()); } - QPlatformWindow::setVisible(visible); + QRect availableGeometry = screen()->availableGeometry(); + if (geometry().width() > 0 && geometry().height() > 0 && availableGeometry.width() > 0 && availableGeometry.height() > 0) + QPlatformWindow::setVisible(visible); if (visible) platformScreen()->addWindow(this); |