diff options
Diffstat (limited to 'src/plugins/platforms/android/qandroidplatformintegration.cpp')
-rw-r--r-- | src/plugins/platforms/android/qandroidplatformintegration.cpp | 170 |
1 files changed, 136 insertions, 34 deletions
diff --git a/src/plugins/platforms/android/qandroidplatformintegration.cpp b/src/plugins/platforms/android/qandroidplatformintegration.cpp index 19a7326115..4d9e6fa704 100644 --- a/src/plugins/platforms/android/qandroidplatformintegration.cpp +++ b/src/plugins/platforms/android/qandroidplatformintegration.cpp @@ -9,7 +9,6 @@ #include "qabstracteventdispatcher.h" #include "qandroideventdispatcher.h" #include "qandroidplatformaccessibility.h" -#include "qandroidplatformbackingstore.h" #include "qandroidplatformclipboard.h" #include "qandroidplatformfontdatabase.h" #include "qandroidplatformforeignwindow.h" @@ -29,6 +28,7 @@ #include <QtGui/private/qeglpbuffer_p.h> #include <QtGui/private/qguiapplication_p.h> #include <QtGui/private/qoffscreensurface_p.h> +#include <QtGui/private/qrhibackingstore_p.h> #include <qpa/qplatformoffscreensurface.h> #include <qpa/qplatformwindow.h> #include <qpa/qwindowsysteminterface.h> @@ -46,24 +46,46 @@ QT_BEGIN_NAMESPACE using namespace Qt::StringLiterals; -QSize QAndroidPlatformIntegration::m_defaultScreenSize = QSize(320, 455); -QRect QAndroidPlatformIntegration::m_defaultAvailableGeometry = QRect(0, 0, 320, 455); -QSize QAndroidPlatformIntegration::m_defaultPhysicalSize = QSize(50, 71); +Q_CONSTINIT QSize QAndroidPlatformIntegration::m_defaultScreenSize = QSize(320, 455); +Q_CONSTINIT QRect QAndroidPlatformIntegration::m_defaultAvailableGeometry = QRect(0, 0, 320, 455); +Q_CONSTINIT QSize QAndroidPlatformIntegration::m_defaultPhysicalSize = QSize(50, 71); Qt::ScreenOrientation QAndroidPlatformIntegration::m_orientation = Qt::PrimaryOrientation; Qt::ScreenOrientation QAndroidPlatformIntegration::m_nativeOrientation = Qt::PrimaryOrientation; bool QAndroidPlatformIntegration::m_showPasswordEnabled = false; -static bool m_running = false; + +Q_DECLARE_JNI_CLASS(QtNative, "org/qtproject/qt/android/QtNative") +Q_DECLARE_JNI_CLASS(QtDisplayManager, "org/qtproject/qt/android/QtDisplayManager") +Q_DECLARE_JNI_CLASS(Display, "android/view/Display") + +Q_DECLARE_JNI_CLASS(List, "java/util/List") + +namespace { + +QAndroidPlatformScreen* createScreenForDisplayId(int displayId) +{ + const QJniObject display = QtJniTypes::QtDisplayManager::callStaticMethod<QtJniTypes::Display>( + "getDisplay", QtAndroidPrivate::context(), displayId); + if (!display.isValid()) + return nullptr; + return new QAndroidPlatformScreen(display); +} + +} // anonymous namespace void *QAndroidPlatformNativeInterface::nativeResourceForIntegration(const QByteArray &resource) { if (resource=="JavaVM") return QtAndroid::javaVM(); - if (resource == "QtActivity") - return QtAndroid::activity(); - if (resource == "QtService") - return QtAndroid::service(); + if (resource == "QtActivity") { + extern Q_CORE_EXPORT jobject qt_androidActivity(); + return qt_androidActivity(); + } + if (resource == "QtService") { + extern Q_CORE_EXPORT jobject qt_androidService(); + return qt_androidService(); + } if (resource == "AndroidStyleData") { if (m_androidStyle) { if (m_androidStyle->m_styleData.isEmpty()) @@ -136,10 +158,6 @@ void QAndroidPlatformNativeInterface::customEvent(QEvent *event) api->accessibility()->setActive(QtAndroidAccessibility::isActive()); #endif // QT_CONFIG(accessibility) - if (!m_running) { - m_running = true; - QtAndroid::notifyQtAndroidPluginRunning(m_running); - } api->flushPendingUpdates(); } @@ -163,10 +181,32 @@ QAndroidPlatformIntegration::QAndroidPlatformIntegration(const QStringList ¶ if (Q_UNLIKELY(!eglBindAPI(EGL_OPENGL_ES_API))) qFatal("Could not bind GL_ES API"); - m_primaryScreen = new QAndroidPlatformScreen(); - QWindowSystemInterface::handleScreenAdded(m_primaryScreen); - m_primaryScreen->setSizeParameters(m_defaultPhysicalSize, m_defaultScreenSize, - m_defaultAvailableGeometry); + using namespace QtJniTypes; + m_primaryDisplayId = Display::getStaticField<jint>("DEFAULT_DISPLAY"); + const QJniObject nativeDisplaysList = QtDisplayManager::callStaticMethod<List>( + "getAvailableDisplays", QtAndroidPrivate::context()); + + const int numberOfAvailableDisplays = nativeDisplaysList.callMethod<jint>("size"); + for (int i = 0; i < numberOfAvailableDisplays; ++i) { + const QJniObject display = + nativeDisplaysList.callObjectMethod<jobject, jint>("get", jint(i)); + const int displayId = display.callMethod<jint>("getDisplayId"); + const bool isPrimary = (m_primaryDisplayId == displayId); + auto screen = new QAndroidPlatformScreen(display); + + if (isPrimary) + m_primaryScreen = screen; + + QWindowSystemInterface::handleScreenAdded(screen, isPrimary); + m_screens[displayId] = screen; + } + + if (numberOfAvailableDisplays == 0) { + // If no displays are found, add a dummy display + auto defaultScreen = new QAndroidPlatformScreen(QJniObject {}); + m_primaryScreen = defaultScreen; + QWindowSystemInterface::handleScreenAdded(defaultScreen, true); + } m_mainThread = QThread::currentThread(); @@ -183,9 +223,9 @@ QAndroidPlatformIntegration::QAndroidPlatformIntegration(const QStringList ¶ m_accessibility = new QAndroidPlatformAccessibility(); #endif // QT_CONFIG(accessibility) - QJniObject javaActivity(QtAndroid::activity()); + QJniObject javaActivity = QtAndroidPrivate::activity(); if (!javaActivity.isValid()) - javaActivity = QtAndroid::service(); + javaActivity = QtAndroidPrivate::service(); if (javaActivity.isValid()) { QJniObject resources = javaActivity.callObjectMethod("getResources", "()Landroid/content/res/Resources;"); @@ -225,6 +265,10 @@ QAndroidPlatformIntegration::QAndroidPlatformIntegration(const QStringList ¶ maxTouchPoints, 0); QWindowSystemInterface::registerInputDevice(m_touchDevice); + + QWindowSystemInterface::registerInputDevice( + new QInputDevice("Virtual keyboard"_L1, 0, QInputDevice::DeviceType::Keyboard, + {}, qApp)); } auto contentResolver = javaActivity.callObjectMethod("getContentResolver", "()Landroid/content/ContentResolver;"); @@ -260,11 +304,11 @@ static bool needsBasicRenderloopWorkaround() void QAndroidPlatformIntegration::initialize() { - const QString icStr = QPlatformInputContextFactory::requested(); - if (icStr.isNull()) + const auto icStrs = QPlatformInputContextFactory::requested(); + if (icStrs.isEmpty()) m_inputContext.reset(new QAndroidInputContext); else - m_inputContext.reset(QPlatformInputContextFactory::create(icStr)); + m_inputContext.reset(QPlatformInputContextFactory::create(icStrs)); } bool QAndroidPlatformIntegration::hasCapability(Capability cap) const @@ -272,13 +316,16 @@ bool QAndroidPlatformIntegration::hasCapability(Capability cap) const switch (cap) { case ApplicationState: return true; case ThreadedPixmaps: return true; - case NativeWidgets: return QtAndroid::activity(); - case OpenGL: return QtAndroid::activity(); - case ForeignWindows: return QtAndroid::activity(); - case ThreadedOpenGL: return !needsBasicRenderloopWorkaround() && QtAndroid::activity(); - case RasterGLSurface: return QtAndroid::activity(); + case NativeWidgets: return QtAndroidPrivate::activity().isValid(); + case OpenGL: return QtAndroidPrivate::activity().isValid(); + case ForeignWindows: return QtAndroidPrivate::activity().isValid(); + case ThreadedOpenGL: return !needsBasicRenderloopWorkaround() && QtAndroidPrivate::activity().isValid(); + case RasterGLSurface: return QtAndroidPrivate::activity().isValid(); case TopStackedNativeChildWindows: return false; case MaximizeUsingFullscreenGeometry: return true; + // FIXME QTBUG-118849 - we do not implement grabWindow() anymore, calling it will return + // a null QPixmap also for raster windows - for OpenGL windows this was always true + case ScreenWindowGrabbing: return false; default: return QPlatformIntegration::hasCapability(cap); } @@ -286,15 +333,15 @@ bool QAndroidPlatformIntegration::hasCapability(Capability cap) const QPlatformBackingStore *QAndroidPlatformIntegration::createPlatformBackingStore(QWindow *window) const { - if (!QtAndroid::activity()) + if (!QtAndroidPrivate::activity().isValid()) return nullptr; - return new QAndroidPlatformBackingStore(window); + return new QRhiBackingStore(window); } QPlatformOpenGLContext *QAndroidPlatformIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const { - if (!QtAndroid::activity()) + if (!QtAndroidPrivate::activity().isValid()) return nullptr; QSurfaceFormat format(context->format()); format.setAlphaBufferSize(8); @@ -312,7 +359,7 @@ QOpenGLContext *QAndroidPlatformIntegration::createOpenGLContext(EGLContext cont QPlatformOffscreenSurface *QAndroidPlatformIntegration::createPlatformOffscreenSurface(QOffscreenSurface *surface) const { - if (!QtAndroid::activity()) + if (!QtAndroidPrivate::activity().isValid()) return nullptr; QSurfaceFormat format(surface->requestedFormat()); @@ -326,7 +373,7 @@ QPlatformOffscreenSurface *QAndroidPlatformIntegration::createPlatformOffscreenS QOffscreenSurface *QAndroidPlatformIntegration::createOffscreenSurface(ANativeWindow *nativeSurface) const { - if (!QtAndroid::activity() || !nativeSurface) + if (!QtAndroidPrivate::activity().isValid() || !nativeSurface) return nullptr; auto *surface = new QOffscreenSurface; @@ -337,7 +384,7 @@ QOffscreenSurface *QAndroidPlatformIntegration::createOffscreenSurface(ANativeWi QPlatformWindow *QAndroidPlatformIntegration::createPlatformWindow(QWindow *window) const { - if (!QtAndroid::activity()) + if (!QtAndroidPrivate::activity().isValid()) return nullptr; #if QT_CONFIG(vulkan) @@ -432,7 +479,7 @@ QStringList QAndroidPlatformIntegration::themeNames() const QPlatformTheme *QAndroidPlatformIntegration::createPlatformTheme(const QString &name) const { if (androidThemeName == name) - return new QAndroidPlatformTheme(m_androidPlatformNativeInterface); + return QAndroidPlatformTheme::instance(m_androidPlatformNativeInterface); return 0; } @@ -488,6 +535,18 @@ void QAndroidPlatformIntegration::setScreenSize(int width, int height) QMetaObject::invokeMethod(m_primaryScreen, "setSize", Qt::AutoConnection, Q_ARG(QSize, QSize(width, height))); } +Qt::ColorScheme QAndroidPlatformIntegration::m_colorScheme = Qt::ColorScheme::Light; + +void QAndroidPlatformIntegration::updateColorScheme(Qt::ColorScheme colorScheme) +{ + if (m_colorScheme == colorScheme) + return; + m_colorScheme = colorScheme; + + QMetaObject::invokeMethod(qGuiApp, + [] () { QAndroidPlatformTheme::instance()->updateColorScheme();}); +} + void QAndroidPlatformIntegration::setScreenSizeParameters(const QSize &physicalSize, const QSize &screenSize, const QRect &availableGeometry) @@ -505,6 +564,49 @@ void QAndroidPlatformIntegration::setRefreshRate(qreal refreshRate) QMetaObject::invokeMethod(m_primaryScreen, "setRefreshRate", Qt::AutoConnection, Q_ARG(qreal, refreshRate)); } + +void QAndroidPlatformIntegration::handleScreenAdded(int displayId) +{ + auto result = m_screens.insert(displayId, nullptr); + if (result.first->second == nullptr) { + auto it = result.first; + it->second = createScreenForDisplayId(displayId); + if (it->second == nullptr) + return; + const bool isPrimary = (m_primaryDisplayId == displayId); + if (isPrimary) + m_primaryScreen = it->second; + QWindowSystemInterface::handleScreenAdded(it->second, isPrimary); + } else { + qWarning() << "Display with id" << displayId << "already exists."; + } +} + +void QAndroidPlatformIntegration::handleScreenChanged(int displayId) +{ + auto it = m_screens.find(displayId); + if (it == m_screens.end() || it->second == nullptr) { + handleScreenAdded(displayId); + } + // We do not do anything more here as handling of change of + // rotation and refresh rate is done in QtActivityDelegate java class + // which calls QAndroidPlatformIntegration::setOrientation, and + // QAndroidPlatformIntegration::setRefreshRate accordingly. +} + +void QAndroidPlatformIntegration::handleScreenRemoved(int displayId) +{ + auto it = m_screens.find(displayId); + + if (it == m_screens.end()) + return; + + if (it->second != nullptr) + QWindowSystemInterface::handleScreenRemoved(it->second); + + m_screens.erase(it); +} + #if QT_CONFIG(vulkan) QPlatformVulkanInstance *QAndroidPlatformIntegration::createPlatformVulkanInstance(QVulkanInstance *instance) const |