diff options
Diffstat (limited to 'src/plugins/platforms/android/androidjnimain.cpp')
-rw-r--r-- | src/plugins/platforms/android/androidjnimain.cpp | 118 |
1 files changed, 81 insertions, 37 deletions
diff --git a/src/plugins/platforms/android/androidjnimain.cpp b/src/plugins/platforms/android/androidjnimain.cpp index 9e4007b37a..577a7905b9 100644 --- a/src/plugins/platforms/android/androidjnimain.cpp +++ b/src/plugins/platforms/android/androidjnimain.cpp @@ -1,7 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2014 BogDan Vatra <bogdan@kde.org> -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2022 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the plugins of the Qt Toolkit. @@ -60,10 +60,11 @@ #include "qandroideventdispatcher.h" #include <android/api-level.h> -#include <QtCore/qresource.h> -#include <QtCore/qthread.h> #include <QtCore/private/qjnihelpers_p.h> #include <QtCore/private/qjni_p.h> +#include <QtCore/qbasicatomic.h> +#include <QtCore/qresource.h> +#include <QtCore/qthread.h> #include <QtGui/private/qguiapplication_p.h> #include <QtGui/private/qhighdpiscaling_p.h> @@ -106,7 +107,6 @@ static sem_t m_exitSemaphore, m_terminateSemaphore; QHash<int, AndroidSurfaceClient *> m_surfaces; static QBasicMutex m_surfacesMutex; -static int m_surfaceId = 1; static QAndroidPlatformIntegration *m_androidPlatformIntegration = nullptr; @@ -125,6 +125,8 @@ static const char m_qtTag[] = "Qt"; static const char m_classErrorMsg[] = "Can't find class \"%s\""; static const char m_methodErrorMsg[] = "Can't find method \"%s%s\""; +static QBasicAtomicInt startQtAndroidPluginCalled = Q_BASIC_ATOMIC_INITIALIZER(0); + namespace QtAndroid { QBasicMutex *platformInterfaceMutex() @@ -223,14 +225,17 @@ namespace QtAndroid m_statusBarShowing = false; } - void notifyAccessibilityLocationChange() + void notifyAccessibilityLocationChange(uint accessibilityObjectId) { - QJNIObjectPrivate::callStaticMethod<void>(m_applicationClass, "notifyAccessibilityLocationChange"); + QJNIObjectPrivate::callStaticMethod<void>(m_applicationClass, + "notifyAccessibilityLocationChange", + "(I)V", accessibilityObjectId); } - void notifyObjectHide(uint accessibilityObjectId) + void notifyObjectHide(uint accessibilityObjectId, uint parentObjectId) { - QJNIObjectPrivate::callStaticMethod<void>(m_applicationClass, "notifyObjectHide","(I)V", accessibilityObjectId); + QJNIObjectPrivate::callStaticMethod<void>(m_applicationClass, "notifyObjectHide", "(II)V", + accessibilityObjectId, parentObjectId); } void notifyObjectFocus(uint accessibilityObjectId) @@ -238,6 +243,24 @@ namespace QtAndroid QJNIObjectPrivate::callStaticMethod<void>(m_applicationClass, "notifyObjectFocus","(I)V", accessibilityObjectId); } + void notifyValueChanged(uint accessibilityObjectId, jstring value) + { + QJNIObjectPrivate::callStaticMethod<void>(m_applicationClass, "notifyValueChanged", + "(ILjava/lang/String;)V", accessibilityObjectId, + value); + } + + void notifyScrolledEvent(uint accessibilityObjectId) + { + QJNIObjectPrivate::callStaticMethod<void>(m_applicationClass, "notifyScrolledEvent", "(I)V", + accessibilityObjectId); + } + + void notifyQtAndroidPluginRunning(bool running) + { + QJNIObjectPrivate::callStaticMethod<void>(m_applicationClass, "notifyQtAndroidPluginRunning","(Z)V", running); + } + jobject createBitmap(QImage img, JNIEnv *env) { if (!m_bitmapClass) @@ -332,6 +355,12 @@ namespace QtAndroid return manufacturer + QLatin1Char(' ') + model; } + jint generateViewId() + { + return QJNIObjectPrivate::callStaticMethod<jint>("android/view/View","generateViewId", + "()I"); + } + int createSurface(AndroidSurfaceClient *client, const QRect &geometry, bool onTop, int imageDepth) { QJNIEnvironmentPrivate env; @@ -339,7 +368,7 @@ namespace QtAndroid return -1; m_surfacesMutex.lock(); - int surfaceId = m_surfaceId++; + jint surfaceId = generateViewId(); m_surfaces[surfaceId] = client; m_surfacesMutex.unlock(); @@ -362,7 +391,7 @@ namespace QtAndroid int insertNativeView(jobject view, const QRect &geometry) { m_surfacesMutex.lock(); - const int surfaceId = m_surfaceId++; + jint surfaceId = generateViewId(); m_surfaces[surfaceId] = nullptr; // dummy m_surfacesMutex.unlock(); @@ -546,15 +575,21 @@ static void startQtApplication(JNIEnv */*env*/, jclass /*clazz*/) vm->AttachCurrentThread(&env, &args); } + // Register type for invokeMethod() calls. + qRegisterMetaType<Qt::ScreenOrientation>("Qt::ScreenOrientation"); + // Register resources if they are available if (QFile{QStringLiteral("assets:/android_rcc_bundle.rcc")}.exists()) QResource::registerResource(QStringLiteral("assets:/android_rcc_bundle.rcc")); - QVarLengthArray<const char *> params(m_applicationParams.size()); - for (int i = 0; i < m_applicationParams.size(); i++) - params[i] = static_cast<const char *>(m_applicationParams[i].constData()); + const int argc = m_applicationParams.size(); + QVarLengthArray<char *> argv(argc + 1); + for (int i = 0; i < argc; i++) + argv[i] = m_applicationParams[i].data(); + argv[argc] = nullptr; - int ret = m_main(m_applicationParams.length(), const_cast<char **>(params.data())); + startQtAndroidPluginCalled.fetchAndAddRelease(1); + int ret = m_main(argc, argv.data()); if (m_mainLibraryHnd) { int res = dlclose(m_mainLibraryHnd); @@ -601,7 +636,9 @@ static void terminateQt(JNIEnv *env, jclass /*clazz*/) QAndroidEventDispatcherStopper::instance()->goingToStop(false); } - sem_wait(&m_terminateSemaphore); + if (startQtAndroidPluginCalled.loadAcquire()) + sem_wait(&m_terminateSemaphore); + sem_destroy(&m_terminateSemaphore); env->DeleteGlobalRef(m_applicationClass); @@ -644,32 +681,28 @@ static void setDisplayMetrics(JNIEnv */*env*/, jclass /*clazz*/, jint widthPixels, jint heightPixels, jint desktopWidthPixels, jint desktopHeightPixels, jdouble xdpi, jdouble ydpi, - jdouble scaledDensity, jdouble density) + jdouble scaledDensity, jdouble density, jfloat refreshRate) { - // Android does not give us the correct screen size for immersive mode, but - // the surface does have the right size - - widthPixels = qMax(widthPixels, desktopWidthPixels); - heightPixels = qMax(heightPixels, desktopHeightPixels); - m_desktopWidthPixels = desktopWidthPixels; m_desktopHeightPixels = desktopHeightPixels; m_scaledDensity = scaledDensity; m_density = density; + const QSize screenSize(widthPixels, heightPixels); + // available geometry always starts from top left + const QRect availableGeometry(0, 0, desktopWidthPixels, desktopHeightPixels); + const QSize physicalSize(qRound(double(widthPixels) / xdpi * 25.4), + qRound(double(heightPixels) / ydpi * 25.4)); + QMutexLocker lock(&m_platformMutex); if (!m_androidPlatformIntegration) { - QAndroidPlatformIntegration::setDefaultDisplayMetrics(desktopWidthPixels, - desktopHeightPixels, - qRound(double(widthPixels) / xdpi * 25.4), - qRound(double(heightPixels) / ydpi * 25.4), - widthPixels, - heightPixels); + QAndroidPlatformIntegration::setDefaultDisplayMetrics( + availableGeometry.width(), availableGeometry.height(), physicalSize.width(), + physicalSize.height(), screenSize.width(), screenSize.height()); } else { - m_androidPlatformIntegration->setDisplayMetrics(qRound(double(widthPixels) / xdpi * 25.4), - qRound(double(heightPixels) / ydpi * 25.4)); - m_androidPlatformIntegration->setScreenSize(widthPixels, heightPixels); - m_androidPlatformIntegration->setDesktopSize(desktopWidthPixels, desktopHeightPixels); + m_androidPlatformIntegration->setScreenSizeParameters(physicalSize, screenSize, + availableGeometry); + m_androidPlatformIntegration->setRefreshRate(refreshRate); } } @@ -764,12 +797,22 @@ static void handleOrientationChanged(JNIEnv */*env*/, jobject /*thiz*/, jint new QAndroidPlatformIntegration::setScreenOrientation(screenOrientation, native); QMutexLocker lock(&m_platformMutex); if (m_androidPlatformIntegration) { - QPlatformScreen *screen = m_androidPlatformIntegration->screen(); - QWindowSystemInterface::handleScreenOrientationChange(screen->screen(), - screenOrientation); + QAndroidPlatformScreen *screen = m_androidPlatformIntegration->screen(); + // Use invokeMethod to keep the certain order of the "geometry change" + // and "orientation change" event handling. + if (screen) { + QMetaObject::invokeMethod(screen, "setOrientation", Qt::AutoConnection, + Q_ARG(Qt::ScreenOrientation, screenOrientation)); + } } } +static void handleRefreshRateChanged(JNIEnv */*env*/, jclass /*cls*/, jfloat refreshRate) +{ + if (m_androidPlatformIntegration) + m_androidPlatformIntegration->setRefreshRate(refreshRate); +} + static void onActivityResult(JNIEnv */*env*/, jclass /*cls*/, jint requestCode, jint resultCode, @@ -795,14 +838,15 @@ static JNINativeMethod methods[] = { {"quitQtCoreApplication", "()V", (void *)quitQtCoreApplication}, {"terminateQt", "()V", (void *)terminateQt}, {"waitForServiceSetup", "()V", (void *)waitForServiceSetup}, - {"setDisplayMetrics", "(IIIIDDDD)V", (void *)setDisplayMetrics}, + {"setDisplayMetrics", "(IIIIDDDDF)V", (void *)setDisplayMetrics}, {"setSurface", "(ILjava/lang/Object;II)V", (void *)setSurface}, {"updateWindow", "()V", (void *)updateWindow}, {"updateApplicationState", "(I)V", (void *)updateApplicationState}, {"handleOrientationChanged", "(II)V", (void *)handleOrientationChanged}, {"onActivityResult", "(IILandroid/content/Intent;)V", (void *)onActivityResult}, {"onNewIntent", "(Landroid/content/Intent;)V", (void *)onNewIntent}, - {"onBind", "(Landroid/content/Intent;)Landroid/os/IBinder;", (void *)onBind} + {"onBind", "(Landroid/content/Intent;)Landroid/os/IBinder;", (void *)onBind}, + {"handleRefreshRateChanged", "(F)V", (void *)handleRefreshRateChanged} }; #define FIND_AND_CHECK_CLASS(CLASS_NAME) \ |