Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qandroidplatformintegration.cpp
Go to the documentation of this file.
1// Copyright (C) 2012 BogDan Vatra <bogdan@kde.org>
2// Copyright (C) 2021 The Qt Company Ltd.
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4// Qt-Security score:significant reason:default
5
8
9#if QT_CONFIG(accessibility)
10#include "androidjniaccessibility.h"
11#endif
12#include "androidjnimain.h"
15#if QT_CONFIG(accessibility)
16#include "qandroidplatformaccessibility.h"
17#endif
19#if QT_CONFIG(draganddrop)
20#include "qandroidplatformdrag.h"
21#endif
25#if QT_CONFIG(egl)
26#include "qandroidplatformopenglcontext.h"
27#endif
32
33#include <QGuiApplication>
34#include <QOffscreenSurface>
35#include <QOpenGLContext>
36#include <QThread>
37#include <QtCore/QJniObject>
38#if QT_CONFIG(egl)
39#include <QtGui/private/qeglpbuffer_p.h>
40#endif
41#include <QtGui/private/qguiapplication_p.h>
42#include <QtGui/private/qoffscreensurface_p.h>
43#include <QtGui/private/qrhibackingstore_p.h>
44#include <qpa/qplatformoffscreensurface.h>
45#include <qpa/qplatformwindow.h>
46#include <qpa/qwindowsysteminterface.h>
47
48#include <jni.h>
49
50#if QT_CONFIG(vulkan)
51#include "qandroidplatformvulkanwindow.h"
52#include "qandroidplatformvulkaninstance.h"
53#endif
54
55#include <QtGui/qpa/qplatforminputcontextfactory_p.h>
56
58
59using namespace Qt::StringLiterals;
60
61Qt::ScreenOrientation QAndroidPlatformIntegration::m_orientation = Qt::PrimaryOrientation;
62Qt::ScreenOrientation QAndroidPlatformIntegration::m_nativeOrientation = Qt::PrimaryOrientation;
63
64bool QAndroidPlatformIntegration::m_showPasswordEnabled = false;
65
66Q_DECLARE_JNI_CLASS(QtDisplayManager, "org/qtproject/qt/android/QtDisplayManager")
67Q_DECLARE_JNI_CLASS(Display, "android/view/Display")
68
69Q_DECLARE_JNI_CLASS(List, "java/util/List")
70
71namespace {
72
73QAndroidPlatformScreen* createScreenForDisplayId(int displayId)
74{
75 const QJniObject display = QtJniTypes::QtDisplayManager::callStaticMethod<QtJniTypes::Display>(
76 "getDisplay", QtAndroidPrivate::context(), displayId);
77 if (!display.isValid())
78 return nullptr;
79 return new QAndroidPlatformScreen(display);
80}
81
82static bool isValidAndroidContextForRendering()
83{
84 return QtAndroid::isQtApplication() ? QtAndroidPrivate::activity().isValid()
85 : QtAndroidPrivate::context().isValid();
86}
87
88} // anonymous namespace
89
91{
92 if (resource=="JavaVM")
93 return QtAndroidPrivate::javaVM();
94 if (resource == "QtActivity") {
95 extern Q_CORE_EXPORT jobject qt_androidActivity();
96 return qt_androidActivity();
97 }
98 if (resource == "QtService") {
99 extern Q_CORE_EXPORT jobject qt_androidService();
100 return qt_androidService();
101 }
102 if (resource == "AndroidStyleData") {
103 if (m_androidStyle) {
104 if (m_androidStyle->m_styleData.isEmpty())
105 m_androidStyle->m_styleData = AndroidStyle::loadStyleData();
106 return &m_androidStyle->m_styleData;
107 }
108 else
109 return nullptr;
110 }
111 if (resource == "AndroidStandardPalette") {
112 if (m_androidStyle)
113 return &m_androidStyle->m_standardPalette;
114
115 return nullptr;
116 }
117 if (resource == "AndroidQWidgetFonts") {
118 if (m_androidStyle)
119 return &m_androidStyle->m_QWidgetsFonts;
120
121 return nullptr;
122 }
123 if (resource == "AndroidDeviceName") {
124 static QString deviceName = QtAndroid::deviceName();
125 return &deviceName;
126 }
127 return 0;
128}
129
130void *QAndroidPlatformNativeInterface::nativeResourceForWindow(const QByteArray &resource, QWindow *window)
131{
132#if QT_CONFIG(vulkan)
133 if (resource == "vkSurface") {
134 if (window->surfaceType() == QSurface::VulkanSurface) {
135 QAndroidPlatformVulkanWindow *w = static_cast<QAndroidPlatformVulkanWindow *>(window->handle());
136 // return a pointer to the VkSurfaceKHR, not the value
137 return w ? w->vkSurface() : nullptr;
138 }
139 }
140#else
141 Q_UNUSED(resource);
142 Q_UNUSED(window);
143#endif
144 return nullptr;
145}
146
147void *QAndroidPlatformNativeInterface::nativeResourceForContext(const QByteArray &resource, QOpenGLContext *context)
148{
149#if QT_CONFIG(egl)
150 if (QEGLPlatformContext *platformContext = static_cast<QEGLPlatformContext *>(context->handle())) {
151 if (resource == "eglcontext")
152 return platformContext->eglContext();
153 else if (resource == "eglconfig")
154 return platformContext->eglConfig();
155 else if (resource == "egldisplay")
156 return platformContext->eglDisplay();
157 }
158#else
159 Q_UNUSED(resource)
160 Q_UNUSED(context)
161#endif
162 return nullptr;
163}
164
165void QAndroidPlatformNativeInterface::customEvent(QEvent *event)
166{
167 if (event->type() != QEvent::User)
168 return;
169
170 QMutexLocker lock(QtAndroid::platformInterfaceMutex());
171 QAndroidPlatformIntegration *api = static_cast<QAndroidPlatformIntegration *>(QGuiApplicationPrivate::platformIntegration());
173
174#if QT_CONFIG(accessibility)
175 // Android accessibility activation event might have been already received
176 api->accessibility()->setActive(QtAndroidAccessibility::isActive());
177#endif // QT_CONFIG(accessibility)
178
180}
181
183 : m_touchDevice(nullptr)
184#if QT_CONFIG(accessibility)
185 , m_accessibility(nullptr)
186#endif
187{
188 Q_UNUSED(paramList);
189 m_androidPlatformNativeInterface = new QAndroidPlatformNativeInterface();
190
191#if QT_CONFIG(egl)
192 m_eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
193 if (Q_UNLIKELY(m_eglDisplay == EGL_NO_DISPLAY))
194 qFatal("Could not open egl display");
195
196 EGLint major, minor;
197 if (Q_UNLIKELY(!eglInitialize(m_eglDisplay, &major, &minor)))
198 qFatal("Could not initialize egl display");
199
200 if (Q_UNLIKELY(!eglBindAPI(EGL_OPENGL_ES_API)))
201 qFatal("Could not bind GL_ES API");
202#endif
203
204 using namespace QtJniTypes;
205 m_primaryDisplayId = Display::getStaticField<jint>("DEFAULT_DISPLAY");
206 const QJniObject nativeDisplaysList = QtDisplayManager::callStaticMethod<List>(
207 "getAvailableDisplays", QtAndroidPrivate::context());
208
209 const int numberOfAvailableDisplays = nativeDisplaysList.callMethod<jint>("size");
210 for (int i = 0; i < numberOfAvailableDisplays; ++i) {
211 const QJniObject display =
212 nativeDisplaysList.callObjectMethod<jobject, jint>("get", jint(i));
213 const int displayId = display.callMethod<jint>("getDisplayId");
214 const bool isPrimary = (m_primaryDisplayId == displayId);
215 auto screen = new QAndroidPlatformScreen(display);
216
217 if (isPrimary)
218 m_primaryScreen = screen;
219
220 QWindowSystemInterface::handleScreenAdded(screen, isPrimary);
221 m_screens[displayId] = screen;
222 }
223
224 if (numberOfAvailableDisplays == 0) {
225 // If no displays are found, add a dummy display
226 auto defaultScreen = new QAndroidPlatformScreen(QJniObject {});
227 m_primaryScreen = defaultScreen;
228 QWindowSystemInterface::handleScreenAdded(defaultScreen, true);
229 }
230
231 m_mainThread = QThread::currentThread();
232
233 m_androidFDB = new QAndroidPlatformFontDatabase();
234 m_androidPlatformServices.reset(new QAndroidPlatformServices);
235
236#ifndef QT_NO_CLIPBOARD
237 m_androidPlatformClipboard = new QAndroidPlatformClipboard();
238#endif
239
240#if QT_CONFIG(draganddrop)
241 m_androidPlatformDrag = new QAndroidPlatformDrag();
242#endif
243
244#if QT_CONFIG(accessibility)
245 m_accessibility = new QAndroidPlatformAccessibility();
246#endif // QT_CONFIG(accessibility)
247
248 QJniObject javaActivity = QtAndroidPrivate::activity();
249 if (!javaActivity.isValid())
250 javaActivity = QtAndroidPrivate::service();
251
252 if (javaActivity.isValid()) {
253 QJniObject resources = javaActivity.callObjectMethod("getResources", "()Landroid/content/res/Resources;");
254 QJniObject configuration = resources.callObjectMethod("getConfiguration", "()Landroid/content/res/Configuration;");
255
256 int touchScreen = configuration.getField<jint>("touchscreen");
257 if (touchScreen == QJniObject::getStaticField<jint>("android/content/res/Configuration", "TOUCHSCREEN_FINGER")
258 || touchScreen == QJniObject::getStaticField<jint>("android/content/res/Configuration", "TOUCHSCREEN_STYLUS"))
259 {
260 QJniObject pm = javaActivity.callObjectMethod("getPackageManager", "()Landroid/content/pm/PackageManager;");
261 Q_ASSERT(pm.isValid());
262 int maxTouchPoints = 1;
263 if (pm.callMethod<jboolean>("hasSystemFeature","(Ljava/lang/String;)Z",
264 QJniObject::getStaticObjectField("android/content/pm/PackageManager",
265 "FEATURE_TOUCHSCREEN_MULTITOUCH_JAZZHAND",
266 "Ljava/lang/String;").object())) {
267 maxTouchPoints = 10;
268 } else if (pm.callMethod<jboolean>("hasSystemFeature","(Ljava/lang/String;)Z",
269 QJniObject::getStaticObjectField("android/content/pm/PackageManager",
270 "FEATURE_TOUCHSCREEN_MULTITOUCH_DISTINCT",
271 "Ljava/lang/String;").object())) {
272 maxTouchPoints = 4;
273 } else if (pm.callMethod<jboolean>("hasSystemFeature","(Ljava/lang/String;)Z",
274 QJniObject::getStaticObjectField("android/content/pm/PackageManager",
275 "FEATURE_TOUCHSCREEN_MULTITOUCH",
276 "Ljava/lang/String;").object())) {
277 maxTouchPoints = 2;
278 }
279
280 m_touchDevice = new QPointingDevice("Android touchscreen", 1,
281 QInputDevice::DeviceType::TouchScreen,
282 QPointingDevice::PointerType::Finger,
283 QPointingDevice::Capability::Position
284 | QPointingDevice::Capability::Area
285 | QPointingDevice::Capability::Pressure,
286 maxTouchPoints,
287 0);
288 QWindowSystemInterface::registerInputDevice(m_touchDevice);
289
290 QWindowSystemInterface::registerInputDevice(
291 new QInputDevice("Virtual keyboard"_L1, 0, QInputDevice::DeviceType::Keyboard,
292 {}, qApp));
293 }
294
295 auto contentResolver = javaActivity.callObjectMethod("getContentResolver", "()Landroid/content/ContentResolver;");
296 Q_ASSERT(contentResolver.isValid());
297 QJniObject txtShowPassValue = QJniObject::callStaticObjectMethod(
298 "android/provider/Settings$System",
299 "getString",
300 "(Landroid/content/ContentResolver;Ljava/lang/String;)Ljava/lang/String;",
301 contentResolver.object(),
302 QJniObject::getStaticObjectField("android/provider/Settings$System",
303 "TEXT_SHOW_PASSWORD",
304 "Ljava/lang/String;").object());
305 if (txtShowPassValue.isValid()) {
306 bool ok = false;
307 const int txtShowPass = txtShowPassValue.toString().toInt(&ok);
308 m_showPasswordEnabled = ok ? (txtShowPass == 1) : false;
309 }
310 }
311
312 // We can't safely notify the jni bridge that we're up and running just yet, so let's postpone
313 // it for now.
314 QCoreApplication::postEvent(m_androidPlatformNativeInterface, new QEvent(QEvent::User));
315}
316
318{
319 static bool needsWorkaround =
320 QtAndroid::deviceName().compare("samsung SM-T211"_L1, Qt::CaseInsensitive) == 0
321 || QtAndroid::deviceName().compare("samsung SM-T210"_L1, Qt::CaseInsensitive) == 0
322 || QtAndroid::deviceName().compare("samsung SM-T215"_L1, Qt::CaseInsensitive) == 0;
323 return needsWorkaround;
324}
325
327{
328 const auto icStrs = QPlatformInputContextFactory::requested();
329 if (icStrs.isEmpty())
330 m_inputContext.reset(new QAndroidInputContext);
331 else
332 m_inputContext.reset(QPlatformInputContextFactory::create(icStrs));
333}
334
336{
337 switch (cap) {
338 case ApplicationState: return true;
339 case ThreadedPixmaps: return true;
340 case NativeWidgets: return QtAndroidPrivate::activity().isValid();
341 case OpenGL:
342 return isValidAndroidContextForRendering();
343 case ForeignWindows:
344 return isValidAndroidContextForRendering();
345 case ThreadedOpenGL:
346 return !needsBasicRenderloopWorkaround() && isValidAndroidContextForRendering();
347 case TopStackedNativeChildWindows: return false;
348 case ChildWindows: return true;
349 case MaximizeUsingFullscreenGeometry: return true;
350 // FIXME QTBUG-118849 - we do not implement grabWindow() anymore, calling it will return
351 // a null QPixmap also for raster windows - for OpenGL windows this was always true
352 case ScreenWindowGrabbing: return false;
353 case OffscreenSurface: return QtAndroidPrivate::activity().isValid();
354 default:
355 return QPlatformIntegration::hasCapability(cap);
356 }
357}
358
360{
361 if (!QtAndroidPrivate::activity().isValid())
362 return nullptr;
363
364 return new QRhiBackingStore(window);
365}
366
367#if QT_CONFIG(egl)
368static void fillUnsetColorBufferSizes(QSurfaceFormat &format)
369{
370 if (format.redBufferSize() < 0) format.setRedBufferSize(8);
371 if (format.greenBufferSize() < 0) format.setGreenBufferSize(8);
372 if (format.blueBufferSize() < 0) format.setBlueBufferSize(8);
373 if (format.alphaBufferSize() < 0) format.setAlphaBufferSize(8);
374}
375
376QPlatformOpenGLContext *QAndroidPlatformIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const
377{
378 if (!isValidAndroidContextForRendering())
379 return nullptr;
380 QSurfaceFormat format(context->format());
381 fillUnsetColorBufferSizes(format);
382 auto ctx = new QAndroidPlatformOpenGLContext(format, context->shareHandle(), m_eglDisplay);
383 return ctx;
384}
385
386QOpenGLContext *QAndroidPlatformIntegration::createOpenGLContext(EGLContext context, EGLDisplay display, QOpenGLContext *shareContext) const
387{
388 return QEGLPlatformContext::createFrom<QAndroidPlatformOpenGLContext>(context, display, m_eglDisplay, shareContext);
389}
390
391QPlatformOffscreenSurface *QAndroidPlatformIntegration::createPlatformOffscreenSurface(QOffscreenSurface *surface) const
392{
393 if (!QtAndroidPrivate::activity().isValid())
394 return nullptr;
395
396 QSurfaceFormat format(surface->requestedFormat());
397 fillUnsetColorBufferSizes(format);
398
399 return new QEGLPbuffer(m_eglDisplay, format, surface);
400}
401
402QOffscreenSurface *QAndroidPlatformIntegration::createOffscreenSurface(ANativeWindow *nativeSurface) const
403{
404 if (!QtAndroidPrivate::activity().isValid() || !nativeSurface)
405 return nullptr;
406
407 auto *surface = new QOffscreenSurface;
408 auto *surfacePrivate = QOffscreenSurfacePrivate::get(surface);
409 surfacePrivate->platformOffscreenSurface = new QAndroidPlatformOffscreenSurface(nativeSurface, m_eglDisplay, surface);
410 return surface;
411}
412#endif
413
415{
416 if (!isValidAndroidContextForRendering())
417 return nullptr;
418
419#if QT_CONFIG(vulkan)
420 if (window->surfaceType() == QSurface::VulkanSurface)
421 return new QAndroidPlatformVulkanWindow(window);
422#endif
423
424#if QT_CONFIG(egl)
425 return new QAndroidPlatformOpenGLWindow(window, m_eglDisplay);
426#endif
427
428 return nullptr;
429}
430
431QPlatformWindow *QAndroidPlatformIntegration::createForeignWindow(QWindow *window, WId nativeHandle) const
432{
433 return new QAndroidPlatformForeignWindow(window, nativeHandle);
434}
435
440
442{
443#if QT_CONFIG(egl)
444 if (m_eglDisplay != EGL_NO_DISPLAY)
445 eglTerminate(m_eglDisplay);
446#endif
447
448 delete m_androidPlatformNativeInterface;
449 delete m_androidFDB;
450
451#ifndef QT_NO_CLIPBOARD
452 delete m_androidPlatformClipboard;
453#endif
454
455#if QT_CONFIG(draganddrop)
456 delete m_androidPlatformDrag;
457#endif
458
460}
461
463{
464 return m_androidFDB;
465}
466
467#ifndef QT_NO_CLIPBOARD
469{
470 return m_androidPlatformClipboard;
471}
472#endif
473
474#if QT_CONFIG(draganddrop)
475QPlatformDrag *QAndroidPlatformIntegration::drag() const
476{
477 return m_androidPlatformDrag;
478}
479#endif
480
482{
483 return m_inputContext.data();
484}
485
487{
488 return m_androidPlatformNativeInterface;
489}
490
492{
493 return m_androidPlatformServices.data();
494}
495
496QVariant QAndroidPlatformIntegration::styleHint(StyleHint hint) const
497{
498 switch (hint) {
499 case PasswordMaskDelay:
500 // this number is from a hard-coded value in Android code (cf. PasswordTransformationMethod)
501 return m_showPasswordEnabled ? 1500 : 0;
502 case ShowIsMaximized:
503 return true;
504 default:
505 return QPlatformIntegration::styleHint(hint);
506 }
507}
508
510{
511 // Don't maximize dialogs on Android
512 if (flags & Qt::Dialog & ~Qt::Window)
513 return Qt::WindowNoState;
514
515 return QPlatformIntegration::defaultWindowState(flags);
516}
517
518static const auto androidThemeName = "android"_L1;
520{
521 return QStringList(QString(androidThemeName));
522}
523
525{
526 if (androidThemeName == name)
527 return QAndroidPlatformTheme::instance(m_androidPlatformNativeInterface);
528
529 return 0;
530}
531
532void QAndroidPlatformIntegration::setScreenOrientation(Qt::ScreenOrientation currentOrientation,
533 Qt::ScreenOrientation nativeOrientation)
534{
535 m_orientation = currentOrientation;
536 m_nativeOrientation = nativeOrientation;
537}
538
540{
541 if (!m_primaryScreen)
542 return;
543
544 // Apply the latest layout size, it may have changed since the screen
545 // snapshotted it at construction, e.g. an app enabling edge-to-edge.
546 const QRect availableDefault = QAndroidPlatformScreen::defaultAvailableGeometry();
547 m_primaryScreen->setAvailableGeometry(availableDefault.isNull() ?
548 m_primaryScreen->availableGeometry() : availableDefault);
549}
550
551#if QT_CONFIG(accessibility)
552QPlatformAccessibility *QAndroidPlatformIntegration::accessibility() const
553{
554 return m_accessibility;
555}
556#endif
557
558extern "C" JNIEXPORT bool JNICALL
559Java_org_qtproject_qt_android_QtNativeAccessibility_accessibilitySupported(JNIEnv *, jobject)
560{
561 #if QT_CONFIG(accessibility)
562 return true;
563 #endif // QT_CONFIG(accessibility)
564
565 return false;
566}
567
568void QAndroidPlatformIntegration::setAvailableGeometry(const QRect &availableGeometry)
569{
570 if (m_primaryScreen)
571 QMetaObject::invokeMethod(m_primaryScreen, "setAvailableGeometry", Qt::AutoConnection, Q_ARG(QRect, availableGeometry));
572}
573
575{
576 if (m_primaryScreen)
577 QMetaObject::invokeMethod(m_primaryScreen, "setPhysicalSize", Qt::AutoConnection, Q_ARG(QSize, QSize(width, height)));
578}
579
580void QAndroidPlatformIntegration::setScreenSize(int width, int height)
581{
582 if (m_primaryScreen)
583 QMetaObject::invokeMethod(m_primaryScreen, "setSize", Qt::AutoConnection, Q_ARG(QSize, QSize(width, height)));
584}
585
586Qt::ColorScheme QAndroidPlatformIntegration::m_colorScheme = Qt::ColorScheme::Light;
587
588void QAndroidPlatformIntegration::updateColorScheme(Qt::ColorScheme colorScheme)
589{
590 if (m_colorScheme == colorScheme)
591 return;
592 m_colorScheme = colorScheme;
593
594 QMetaObject::invokeMethod(qGuiApp,
595 [] () { QAndroidPlatformTheme::instance()->updateColorScheme();});
596}
597
599{
600 if (m_primaryScreen)
601 QMetaObject::invokeMethod(m_primaryScreen, "setRefreshRate", Qt::AutoConnection,
602 Q_ARG(qreal, refreshRate));
603}
604
606{
607 auto result = m_screens.insert(displayId, nullptr);
608 if (result.first->second == nullptr) {
609 auto it = result.first;
610 it->second = createScreenForDisplayId(displayId);
611 if (it->second == nullptr)
612 return;
613 const bool isPrimary = (m_primaryDisplayId == displayId);
614 if (isPrimary)
615 m_primaryScreen = it->second;
616 QWindowSystemInterface::handleScreenAdded(it->second, isPrimary);
617 } else {
618 qWarning() << "Display with id" << displayId << "already exists.";
619 }
620}
621
623{
624 auto it = m_screens.find(displayId);
625 if (it == m_screens.end() || it->second == nullptr) {
626 handleScreenAdded(displayId);
627 }
628
629 if (QAndroidPlatformScreen *screen = it->second) {
630 QSize size = QAndroidPlatformScreen::sizeForDisplayId(displayId);
631 if (screen->geometry().size() != size) {
632 screen->setSize(size);
633 }
634 }
635
636 // We do not do handle changes in rotation, refresh rate and density
637 // as they are done under QtDisplayManager.
638}
639
641{
642 auto it = m_screens.find(displayId);
643
644 if (it == m_screens.end())
645 return;
646
647 if (it->second != nullptr)
648 QWindowSystemInterface::handleScreenRemoved(it->second);
649
650 m_screens.erase(it);
651}
652
653#if QT_CONFIG(vulkan)
654
655QPlatformVulkanInstance *QAndroidPlatformIntegration::createPlatformVulkanInstance(QVulkanInstance *instance) const
656{
657 return new QAndroidPlatformVulkanInstance(instance);
658}
659
660#endif // QT_CONFIG(vulkan)
661
662QT_END_NAMESPACE
QPlatformFontDatabase * fontDatabase() const override
Accessor for the platform integration's fontdatabase.
QPlatformWindow * createForeignWindow(QWindow *window, WId nativeHandle) const override
void initialize() override
Performs initialization steps that depend on having an event dispatcher available.
QPlatformInputContext * inputContext() const override
Returns the platforms input context.
QStringList themeNames() const override
QPlatformNativeInterface * nativeInterface() const override
QPlatformTheme * createPlatformTheme(const QString &name) const override
QPlatformBackingStore * createPlatformBackingStore(QWindow *window) const override
Factory function for QPlatformBackingStore.
void setAvailableGeometry(const QRect &availableGeometry)
void setScreenSize(int width, int height)
void setPhysicalSize(int width, int height)
bool hasCapability(QPlatformIntegration::Capability cap) const override
QPlatformWindow * createPlatformWindow(QWindow *window) const override
Factory function for QPlatformWindow.
QPlatformClipboard * clipboard() const override
Accessor for the platform integration's clipboard.
Qt::WindowState defaultWindowState(Qt::WindowFlags flags) const override
QAndroidPlatformIntegration(const QStringList &paramList)
QAbstractEventDispatcher * createEventDispatcher() const override
Factory function for the GUI event dispatcher.
QVariant styleHint(StyleHint hint) const override
QPlatformServices * services() const override
void * nativeResourceForContext(const QByteArray &resource, QOpenGLContext *context) override
void * nativeResourceForWindow(const QByteArray &resource, QWindow *window) override
void * nativeResourceForIntegration(const QByteArray &resource) override
static QAndroidPlatformTheme * instance(QAndroidPlatformNativeInterface *androidPlatformNativeInterface=nullptr)
Combined button and popup list for selecting options.
void setAndroidPlatformIntegration(QAndroidPlatformIntegration *androidPlatformIntegration)
QBasicMutex * platformInterfaceMutex()
QString deviceName()
static const auto androidThemeName
static bool needsBasicRenderloopWorkaround()
Q_DECLARE_JNI_CLASS(MotionEvent, "android/view/MotionEvent")