1 | // Copyright (C) 2016 The Qt Company Ltd. |
---|---|
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
3 | |
4 | #include "qwaylandintegration_p.h" |
5 | |
6 | #include "qwaylanddisplay_p.h" |
7 | #include "qwaylandshmwindow_p.h" |
8 | #include "qwaylandinputdevice_p.h" |
9 | #include "qwaylandinputcontext_p.h" |
10 | #include "qwaylandinputmethodcontext_p.h" |
11 | #include "qwaylandshmbackingstore_p.h" |
12 | #include "qwaylandnativeinterface_p.h" |
13 | #if QT_CONFIG(clipboard) |
14 | #include "qwaylandclipboard_p.h" |
15 | #endif |
16 | #include "qwaylanddnd_p.h" |
17 | #include "qwaylandwindowmanagerintegration_p.h" |
18 | #include "qwaylandplatformservices_p.h" |
19 | #include "qwaylandscreen_p.h" |
20 | #include "qwaylandcursor_p.h" |
21 | |
22 | #if defined(Q_OS_MACOS) |
23 | # include <QtGui/private/qcoretextfontdatabase_p.h> |
24 | # include <QtGui/private/qfontengine_coretext_p.h> |
25 | #else |
26 | # include <QtGui/private/qgenericunixfontdatabase_p.h> |
27 | #endif |
28 | #include <QtGui/private/qgenericunixeventdispatcher_p.h> |
29 | #include <QtGui/private/qgenericunixthemes_p.h> |
30 | |
31 | #include <QtGui/private/qguiapplication_p.h> |
32 | |
33 | #include <qpa/qwindowsysteminterface.h> |
34 | #include <qpa/qplatformcursor.h> |
35 | #include <QtGui/QSurfaceFormat> |
36 | #if QT_CONFIG(opengl) |
37 | #include <QtGui/QOpenGLContext> |
38 | #endif // QT_CONFIG(opengl) |
39 | #include <QSocketNotifier> |
40 | |
41 | #include <qpa/qplatforminputcontextfactory_p.h> |
42 | #include <qpa/qplatformaccessibility.h> |
43 | #include <qpa/qplatforminputcontext.h> |
44 | |
45 | #include "qwaylandhardwareintegration_p.h" |
46 | #include "qwaylandclientbufferintegration_p.h" |
47 | #include "qwaylandclientbufferintegrationfactory_p.h" |
48 | |
49 | #include "qwaylandserverbufferintegration_p.h" |
50 | #include "qwaylandserverbufferintegrationfactory_p.h" |
51 | #include "qwaylandshellsurface_p.h" |
52 | |
53 | #include "qwaylandshellintegration_p.h" |
54 | #include "qwaylandshellintegrationfactory_p.h" |
55 | |
56 | #include "qwaylandinputdeviceintegration_p.h" |
57 | #include "qwaylandinputdeviceintegrationfactory_p.h" |
58 | #include "qwaylandwindow_p.h" |
59 | |
60 | #if QT_CONFIG(accessibility_atspi_bridge) |
61 | #include <QtGui/private/qspiaccessiblebridge_p.h> |
62 | #endif |
63 | |
64 | #if QT_CONFIG(xkbcommon) |
65 | #include <QtGui/private/qxkbcommon_p.h> |
66 | #endif |
67 | |
68 | #if QT_CONFIG(vulkan) |
69 | #include "qwaylandvulkaninstance_p.h" |
70 | #include "qwaylandvulkanwindow_p.h" |
71 | #endif |
72 | |
73 | QT_BEGIN_NAMESPACE |
74 | |
75 | namespace QtWaylandClient { |
76 | |
77 | QWaylandIntegration *QWaylandIntegration::sInstance = nullptr; |
78 | |
79 | QWaylandIntegration::QWaylandIntegration() |
80 | #if defined(Q_OS_MACOS) |
81 | : mFontDb(new QCoreTextFontDatabaseEngineFactory<QCoreTextFontEngine>) |
82 | #else |
83 | : mFontDb(new QGenericUnixFontDatabase()) |
84 | #endif |
85 | { |
86 | mDisplay.reset(other: new QWaylandDisplay(this)); |
87 | mPlatformServices.reset(other: new QWaylandPlatformServices(mDisplay.data())); |
88 | |
89 | QWaylandWindow::fixedToplevelPositions = |
90 | !qEnvironmentVariableIsSet(varName: "QT_WAYLAND_DISABLE_FIXED_POSITIONS"); |
91 | |
92 | sInstance = this; |
93 | } |
94 | |
95 | QWaylandIntegration::~QWaylandIntegration() |
96 | { |
97 | sInstance = nullptr; |
98 | } |
99 | |
100 | bool QWaylandIntegration::init() |
101 | { |
102 | return mDisplay->initialize(); |
103 | } |
104 | |
105 | QPlatformNativeInterface * QWaylandIntegration::nativeInterface() const |
106 | { |
107 | return mNativeInterface.data(); |
108 | } |
109 | |
110 | bool QWaylandIntegration::hasCapability(QPlatformIntegration::Capability cap) const |
111 | { |
112 | switch (cap) { |
113 | case ThreadedPixmaps: return true; |
114 | case OpenGL: |
115 | return mDisplay->clientBufferIntegration(); |
116 | case ThreadedOpenGL: |
117 | return mDisplay->clientBufferIntegration() && mDisplay->clientBufferIntegration()->supportsThreadedOpenGL(); |
118 | case BufferQueueingOpenGL: |
119 | return true; |
120 | case MultipleWindows: |
121 | case NonFullScreenWindows: |
122 | return true; |
123 | case RasterGLSurface: |
124 | return true; |
125 | case WindowActivation: |
126 | return false; |
127 | case ScreenWindowGrabbing: // whether QScreen::grabWindow() is supported |
128 | return false; |
129 | default: return QPlatformIntegration::hasCapability(cap); |
130 | } |
131 | } |
132 | |
133 | QPlatformWindow *QWaylandIntegration::createPlatformWindow(QWindow *window) const |
134 | { |
135 | if ((window->surfaceType() == QWindow::OpenGLSurface || window->surfaceType() == QWindow::RasterGLSurface) |
136 | && mDisplay->clientBufferIntegration()) |
137 | return mDisplay->clientBufferIntegration()->createEglWindow(window); |
138 | |
139 | #if QT_CONFIG(vulkan) |
140 | if (window->surfaceType() == QSurface::VulkanSurface) |
141 | return new QWaylandVulkanWindow(window, mDisplay.data()); |
142 | #endif // QT_CONFIG(vulkan) |
143 | |
144 | return new QWaylandShmWindow(window, mDisplay.data()); |
145 | } |
146 | |
147 | #if QT_CONFIG(opengl) |
148 | QPlatformOpenGLContext *QWaylandIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const |
149 | { |
150 | if (mDisplay->clientBufferIntegration()) |
151 | return mDisplay->clientBufferIntegration()->createPlatformOpenGLContext(glFormat: context->format(), share: context->shareHandle()); |
152 | return nullptr; |
153 | } |
154 | #endif // opengl |
155 | |
156 | QPlatformBackingStore *QWaylandIntegration::createPlatformBackingStore(QWindow *window) const |
157 | { |
158 | return new QWaylandShmBackingStore(window, mDisplay.data()); |
159 | } |
160 | |
161 | QAbstractEventDispatcher *QWaylandIntegration::createEventDispatcher() const |
162 | { |
163 | return createUnixEventDispatcher(); |
164 | } |
165 | |
166 | QPlatformNativeInterface *QWaylandIntegration::createPlatformNativeInterface() |
167 | { |
168 | return new QWaylandNativeInterface(this); |
169 | } |
170 | |
171 | // Support platform specific initialization |
172 | void QWaylandIntegration::initializePlatform() |
173 | { |
174 | mDisplay->initEventThread(); |
175 | |
176 | mNativeInterface.reset(other: createPlatformNativeInterface()); |
177 | initializeInputDeviceIntegration(); |
178 | #if QT_CONFIG(clipboard) |
179 | mClipboard.reset(other: new QWaylandClipboard(mDisplay.data())); |
180 | #endif |
181 | #if QT_CONFIG(draganddrop) |
182 | mDrag.reset(other: new QWaylandDrag(mDisplay.data())); |
183 | #endif |
184 | |
185 | reconfigureInputContext(); |
186 | } |
187 | |
188 | void QWaylandIntegration::initialize() |
189 | { |
190 | initializePlatform(); |
191 | |
192 | // Call this after initializing event thread for QWaylandDisplay::flushRequests() |
193 | QAbstractEventDispatcher *dispatcher = QGuiApplicationPrivate::eventDispatcher; |
194 | QObject::connect(dispatcher, SIGNAL(aboutToBlock()), mDisplay.data(), SLOT(flushRequests())); |
195 | QObject::connect(dispatcher, SIGNAL(awake()), mDisplay.data(), SLOT(flushRequests())); |
196 | |
197 | // Qt does not support running with no screens |
198 | mDisplay->ensureScreen(); |
199 | } |
200 | |
201 | QPlatformFontDatabase *QWaylandIntegration::fontDatabase() const |
202 | { |
203 | return mFontDb.data(); |
204 | } |
205 | |
206 | #if QT_CONFIG(clipboard) |
207 | QPlatformClipboard *QWaylandIntegration::clipboard() const |
208 | { |
209 | return mClipboard.data(); |
210 | } |
211 | #endif |
212 | |
213 | #if QT_CONFIG(draganddrop) |
214 | QPlatformDrag *QWaylandIntegration::drag() const |
215 | { |
216 | return mDrag.data(); |
217 | } |
218 | #endif // draganddrop |
219 | |
220 | QPlatformInputContext *QWaylandIntegration::inputContext() const |
221 | { |
222 | return mInputContext.data(); |
223 | } |
224 | |
225 | QVariant QWaylandIntegration::styleHint(StyleHint hint) const |
226 | { |
227 | if (hint == ShowIsFullScreen && mDisplay->windowManagerIntegration()) |
228 | return mDisplay->windowManagerIntegration()->showIsFullScreen(); |
229 | |
230 | return QPlatformIntegration::styleHint(hint); |
231 | } |
232 | |
233 | #if QT_CONFIG(accessibility) |
234 | QPlatformAccessibility *QWaylandIntegration::accessibility() const |
235 | { |
236 | if (!mAccessibility) { |
237 | #if QT_CONFIG(accessibility_atspi_bridge) |
238 | Q_ASSERT_X(QCoreApplication::eventDispatcher(), "QWaylandIntegration", |
239 | "Initializing accessibility without event-dispatcher!"); |
240 | mAccessibility.reset(other: new QSpiAccessibleBridge()); |
241 | #else |
242 | mAccessibility.reset(new QPlatformAccessibility()); |
243 | #endif |
244 | } |
245 | return mAccessibility.data(); |
246 | } |
247 | #endif |
248 | |
249 | QPlatformServices *QWaylandIntegration::services() const |
250 | { |
251 | return mPlatformServices.data(); |
252 | } |
253 | |
254 | QWaylandDisplay *QWaylandIntegration::display() const |
255 | { |
256 | return mDisplay.data(); |
257 | } |
258 | |
259 | Qt::KeyboardModifiers QWaylandIntegration::queryKeyboardModifiers() const |
260 | { |
261 | if (auto *seat = mDisplay->currentInputDevice(); seat && seat->keyboardFocus()) { |
262 | return seat->modifiers(); |
263 | } |
264 | return Qt::NoModifier; |
265 | } |
266 | |
267 | QList<int> QWaylandIntegration::possibleKeys(const QKeyEvent *event) const |
268 | { |
269 | if (auto *seat = mDisplay->currentInputDevice()) |
270 | return seat->possibleKeys(event); |
271 | return {}; |
272 | } |
273 | |
274 | QStringList QWaylandIntegration::themeNames() const |
275 | { |
276 | return QGenericUnixTheme::themeNames(); |
277 | } |
278 | |
279 | QPlatformTheme *QWaylandIntegration::createPlatformTheme(const QString &name) const |
280 | { |
281 | return QGenericUnixTheme::createUnixTheme(name); |
282 | } |
283 | |
284 | QWaylandScreen *QWaylandIntegration::createPlatformScreen(QWaylandDisplay *waylandDisplay, int version, uint32_t id) const |
285 | { |
286 | return new QWaylandScreen(waylandDisplay, version, id); |
287 | } |
288 | |
289 | QWaylandCursor *QWaylandIntegration::createPlatformCursor(QWaylandDisplay *display) const |
290 | { |
291 | return new QWaylandCursor(display); |
292 | } |
293 | |
294 | #if QT_CONFIG(vulkan) |
295 | QPlatformVulkanInstance *QWaylandIntegration::createPlatformVulkanInstance(QVulkanInstance *instance) const |
296 | { |
297 | return new QWaylandVulkanInstance(instance); |
298 | } |
299 | #endif // QT_CONFIG(vulkan) |
300 | |
301 | // May be called from non-GUI threads |
302 | QWaylandClientBufferIntegration *QWaylandIntegration::clientBufferIntegration() const |
303 | { |
304 | // Do an inexpensive check first to avoid locking whenever possible |
305 | if (Q_UNLIKELY(!mClientBufferIntegrationInitialized)) |
306 | const_cast<QWaylandIntegration *>(this)->initializeClientBufferIntegration(); |
307 | |
308 | Q_ASSERT(mClientBufferIntegrationInitialized); |
309 | return mClientBufferIntegration && mClientBufferIntegration->isValid() ? mClientBufferIntegration.data() : nullptr; |
310 | } |
311 | |
312 | QWaylandServerBufferIntegration *QWaylandIntegration::serverBufferIntegration() const |
313 | { |
314 | if (!mServerBufferIntegrationInitialized) |
315 | const_cast<QWaylandIntegration *>(this)->initializeServerBufferIntegration(); |
316 | |
317 | return mServerBufferIntegration.data(); |
318 | } |
319 | |
320 | QWaylandShellIntegration *QWaylandIntegration::shellIntegration() const |
321 | { |
322 | if (!mShellIntegrationInitialized) |
323 | const_cast<QWaylandIntegration *>(this)->initializeShellIntegration(); |
324 | |
325 | return mShellIntegration.data(); |
326 | } |
327 | |
328 | // May be called from non-GUI threads |
329 | void QWaylandIntegration::initializeClientBufferIntegration() |
330 | { |
331 | QMutexLocker lock(&mClientBufferInitLock); |
332 | if (mClientBufferIntegrationInitialized) |
333 | return; |
334 | |
335 | QString targetKey = QString::fromLocal8Bit(ba: qgetenv(varName: "QT_WAYLAND_CLIENT_BUFFER_INTEGRATION")); |
336 | |
337 | if (targetKey.isEmpty()) { |
338 | if (mDisplay->hardwareIntegration() |
339 | && mDisplay->hardwareIntegration()->clientBufferIntegration() != QLatin1String("wayland-eglstream-controller") |
340 | && mDisplay->hardwareIntegration()->clientBufferIntegration() != QLatin1String("linux-dmabuf-unstable-v1")) { |
341 | targetKey = mDisplay->hardwareIntegration()->clientBufferIntegration(); |
342 | } else { |
343 | targetKey = QLatin1String("wayland-egl"); |
344 | } |
345 | } |
346 | |
347 | if (targetKey.isEmpty()) { |
348 | qWarning(msg: "Failed to determine what client buffer integration to use"); |
349 | } else { |
350 | QStringList keys = QWaylandClientBufferIntegrationFactory::keys(); |
351 | qCDebug(lcQpaWayland) << "Available client buffer integrations:"<< keys; |
352 | |
353 | if (keys.contains(str: targetKey)) |
354 | mClientBufferIntegration.reset(other: QWaylandClientBufferIntegrationFactory::create(name: targetKey, args: QStringList())); |
355 | |
356 | if (mClientBufferIntegration) { |
357 | qCDebug(lcQpaWayland) << "Initializing client buffer integration"<< targetKey; |
358 | mClientBufferIntegration->initialize(display: mDisplay.data()); |
359 | } else { |
360 | qCWarning(lcQpaWayland) << "Failed to load client buffer integration:"<< targetKey; |
361 | qCWarning(lcQpaWayland) << "Available client buffer integrations:"<< keys; |
362 | } |
363 | } |
364 | |
365 | // This must be set last to make sure other threads don't use the |
366 | // integration before initialization is complete. |
367 | mClientBufferIntegrationInitialized = true; |
368 | } |
369 | |
370 | void QWaylandIntegration::initializeServerBufferIntegration() |
371 | { |
372 | mServerBufferIntegrationInitialized = true; |
373 | |
374 | QString targetKey = QString::fromLocal8Bit(ba: qgetenv(varName: "QT_WAYLAND_SERVER_BUFFER_INTEGRATION")); |
375 | |
376 | if (targetKey.isEmpty() && mDisplay->hardwareIntegration()) |
377 | targetKey = mDisplay->hardwareIntegration()->serverBufferIntegration(); |
378 | |
379 | if (targetKey.isEmpty()) { |
380 | qWarning(msg: "Failed to determine what server buffer integration to use"); |
381 | return; |
382 | } |
383 | |
384 | QStringList keys = QWaylandServerBufferIntegrationFactory::keys(); |
385 | qCDebug(lcQpaWayland) << "Available server buffer integrations:"<< keys; |
386 | |
387 | if (keys.contains(str: targetKey)) |
388 | mServerBufferIntegration.reset(other: QWaylandServerBufferIntegrationFactory::create(name: targetKey, args: QStringList())); |
389 | |
390 | if (mServerBufferIntegration) { |
391 | qCDebug(lcQpaWayland) << "Initializing server buffer integration"<< targetKey; |
392 | mServerBufferIntegration->initialize(display: mDisplay.data()); |
393 | } else { |
394 | qCWarning(lcQpaWayland) << "Failed to load server buffer integration: "<< targetKey; |
395 | qCWarning(lcQpaWayland) << "Available server buffer integrations:"<< keys; |
396 | } |
397 | } |
398 | |
399 | void QWaylandIntegration::initializeShellIntegration() |
400 | { |
401 | mShellIntegrationInitialized = true; |
402 | |
403 | QByteArray integrationNames = qgetenv(varName: "QT_WAYLAND_SHELL_INTEGRATION"); |
404 | QString targetKeys = QString::fromLocal8Bit(ba: integrationNames); |
405 | |
406 | QStringList preferredShells; |
407 | if (!targetKeys.isEmpty()) { |
408 | preferredShells = targetKeys.split(sep: QLatin1Char(';')); |
409 | } else { |
410 | preferredShells << QLatin1String("xdg-shell"); |
411 | preferredShells << QLatin1String("wl-shell") << QLatin1String( "ivi-shell"); |
412 | preferredShells << QLatin1String("qt-shell"); |
413 | } |
414 | |
415 | for (const QString &preferredShell : std::as_const(t&: preferredShells)) { |
416 | mShellIntegration.reset(other: createShellIntegration(interfaceName: preferredShell)); |
417 | if (mShellIntegration) { |
418 | qCDebug(lcQpaWayland, "Using the '%s' shell integration", qPrintable(preferredShell)); |
419 | break; |
420 | } |
421 | } |
422 | |
423 | if (!mShellIntegration) { |
424 | qCWarning(lcQpaWayland) << "Loading shell integration failed."; |
425 | qCWarning(lcQpaWayland) << "Attempted to load the following shells"<< preferredShells; |
426 | } |
427 | |
428 | QWindowSystemInterfacePrivate::TabletEvent::setPlatformSynthesizesMouse(false); |
429 | } |
430 | |
431 | QWaylandInputDevice *QWaylandIntegration::createInputDevice(QWaylandDisplay *display, int version, uint32_t id) const |
432 | { |
433 | if (mInputDeviceIntegration) { |
434 | return mInputDeviceIntegration->createInputDevice(d: display, version, id); |
435 | } |
436 | return new QWaylandInputDevice(display, version, id); |
437 | } |
438 | |
439 | void QWaylandIntegration::initializeInputDeviceIntegration() |
440 | { |
441 | QByteArray integrationName = qgetenv(varName: "QT_WAYLAND_INPUTDEVICE_INTEGRATION"); |
442 | QString targetKey = QString::fromLocal8Bit(ba: integrationName); |
443 | |
444 | if (targetKey.isEmpty()) { |
445 | return; |
446 | } |
447 | |
448 | QStringList keys = QWaylandInputDeviceIntegrationFactory::keys(); |
449 | if (keys.contains(str: targetKey)) { |
450 | mInputDeviceIntegration.reset(other: QWaylandInputDeviceIntegrationFactory::create(name: targetKey, args: QStringList())); |
451 | qDebug(msg: "Using the '%s' input device integration", qPrintable(targetKey)); |
452 | } else { |
453 | qWarning(msg: "Wayland inputdevice integration '%s' not found, using default", qPrintable(targetKey)); |
454 | } |
455 | } |
456 | |
457 | void QWaylandIntegration::reconfigureInputContext() |
458 | { |
459 | if (!mDisplay) { |
460 | // This function can be called from QWaylandDisplay::registry_global() when we |
461 | // are in process of constructing QWaylandDisplay. Configuring input context |
462 | // in that case is done by calling reconfigureInputContext() from QWaylandIntegration |
463 | // constructor, after QWaylandDisplay has been constructed. |
464 | return; |
465 | } |
466 | |
467 | auto requested = QPlatformInputContextFactory::requested(); |
468 | if (requested.contains(str: QLatin1String("qtvirtualkeyboard"))) |
469 | qCWarning(lcQpaWayland) << "qtvirtualkeyboard currently is not supported at client-side," |
470 | " use QT_IM_MODULES=qtvirtualkeyboard at compositor-side."; |
471 | |
472 | if (mDisplay->isWaylandInputContextRequested() |
473 | && !requested.contains(str: QLatin1String(WAYLAND_IM_KEY))) |
474 | requested.append(t: QLatin1String(WAYLAND_IM_KEY)); |
475 | |
476 | const QString defaultInputContext(QStringLiteral("compose")); |
477 | if (!requested.contains(str: defaultInputContext)) |
478 | requested.append(t: defaultInputContext); |
479 | |
480 | for (const QString &imKey : requested) { |
481 | if (imKey == QLatin1String(WAYLAND_IM_KEY)) { |
482 | Q_ASSERT(mDisplay->isWaylandInputContextRequested()); |
483 | if (mDisplay->textInputMethodManager() != nullptr) |
484 | mInputContext.reset(other: new QWaylandInputMethodContext(mDisplay.data())); |
485 | else if (mDisplay->textInputManagerv1() != nullptr |
486 | || mDisplay->textInputManagerv2() != nullptr |
487 | || mDisplay->textInputManagerv3() != nullptr) |
488 | mInputContext.reset(other: new QWaylandInputContext(mDisplay.data())); |
489 | } else { |
490 | mInputContext.reset(other: QPlatformInputContextFactory::create(key: imKey)); |
491 | } |
492 | |
493 | if (mInputContext && mInputContext->isValid()) |
494 | break; |
495 | } |
496 | |
497 | #if QT_CONFIG(xkbcommon) |
498 | QXkbCommon::setXkbContext(inputContext: mInputContext.data(), context: mDisplay->xkbContext()); |
499 | if (QWaylandInputContext* waylandInput = qobject_cast<QWaylandInputContext*>(object: mInputContext.get())) { |
500 | waylandInput->setXkbContext(mDisplay->xkbContext()); |
501 | } |
502 | #endif |
503 | |
504 | qCDebug(lcQpaWayland) << "using input method:"<< (inputContext() ? inputContext()->metaObject()->className() : "<none>"); |
505 | } |
506 | |
507 | QWaylandShellIntegration *QWaylandIntegration::createShellIntegration(const QString &integrationName) |
508 | { |
509 | if (QWaylandShellIntegrationFactory::keys().contains(str: integrationName)) { |
510 | return QWaylandShellIntegrationFactory::create(name: integrationName, display: mDisplay.data()); |
511 | } else { |
512 | qCWarning(lcQpaWayland) << "No shell integration named"<< integrationName << "found"; |
513 | return nullptr; |
514 | } |
515 | } |
516 | |
517 | void QWaylandIntegration::reset() |
518 | { |
519 | mServerBufferIntegration.reset(); |
520 | mServerBufferIntegrationInitialized = false; |
521 | |
522 | mInputDeviceIntegration.reset(); |
523 | |
524 | mClientBufferIntegration.reset(); |
525 | mClientBufferIntegrationInitialized = false; |
526 | } |
527 | |
528 | void QWaylandIntegration::setApplicationBadge(qint64 number) |
529 | { |
530 | mPlatformServices->setApplicationBadge(number); |
531 | } |
532 | } |
533 | |
534 | QT_END_NAMESPACE |
535 |
Definitions
- sInstance
- QWaylandIntegration
- ~QWaylandIntegration
- init
- nativeInterface
- hasCapability
- createPlatformWindow
- createPlatformOpenGLContext
- createPlatformBackingStore
- createEventDispatcher
- createPlatformNativeInterface
- initializePlatform
- initialize
- fontDatabase
- clipboard
- drag
- inputContext
- styleHint
- accessibility
- services
- display
- queryKeyboardModifiers
- possibleKeys
- themeNames
- createPlatformTheme
- createPlatformScreen
- createPlatformCursor
- createPlatformVulkanInstance
- clientBufferIntegration
- serverBufferIntegration
- shellIntegration
- initializeClientBufferIntegration
- initializeServerBufferIntegration
- initializeShellIntegration
- createInputDevice
- initializeInputDeviceIntegration
- reconfigureInputContext
- createShellIntegration
- reset
Start learning QML with our Intro Training
Find out more