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
qohosplatformintegration.cpp
Go to the documentation of this file.
1// Copyright (C) 2025 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 "private/qohosplatformtheme_p.h"
10#include "qohosjsmain.h"
23#include "qohosutils.h"
24
25#include <QtCore/qdebug.h>
26#include <QtCore/qthread.h>
27#include <QtCore/private/qnapi_p.h>
28#include <QtGui/private/qeglpbuffer_p.h>
29#include <QtGui/private/qrhibackingstore_p.h>
30#include <QtCore/private/qohoslogger_p.h>
31#include <QtGui/private/qguiapplication_p.h>
32#include <QtCore/qcoreapplication.h>
33#include <qohosdeviceinfo_p.h>
34#include <qohosplugincore.h>
35#include <qohossettings.h>
36
38
39#include <qpa/qwindowsysteminterface.h>
40#include <qpa/qplatforminputcontextfactory_p.h>
41#include <QtCore/qset.h>
42#include <algorithm>
43#include <string>
44#include <utility>
45#include <vector>
46
47#if QT_CONFIG(vulkan)
48#include "qohosplatformvulkaninstance.h"
49#endif
50
51QT_BEGIN_NAMESPACE
52
53namespace {
54
55bool isInputDeviceOfType(QtOhos::JsState &jsState, std::uint32_t deviceId, const std::string &type)
56{
57 auto devSources = QNapi::getArrayElements<std::vector<std::string>, QNapi::String>(
58 jsState.eval<QNapi::Array>(
59 "@ohos.multimodalInput.inputDevice.getDeviceInfoSync(*).sources",
60 {deviceId}));
61 return std::find(devSources.begin(), devSources.end(), type) != devSources.end();
62}
63
64bool isInputDeviceWithTouchscreen(QtOhos::JsState &jsState, std::uint32_t deviceId)
65{
66 return isInputDeviceOfType(jsState, deviceId, "touchscreen");
67}
68
69bool isInputDeviceWithTouchpad(QtOhos::JsState &jsState, std::uint32_t deviceId)
70{
71 return isInputDeviceOfType(jsState, deviceId, "touchpad");
72}
73
74bool isInputDeviceWithMouse(QtOhos::JsState &jsState, std::uint32_t deviceId)
75{
76 return isInputDeviceOfType(jsState, deviceId, "mouse");
77}
78
80 QtOhos::JsState &jsState, const std::vector<std::uint32_t> &deviceIds,
81 const std::function<bool(QtOhos::JsState &, std::uint32_t)> &isDeviceTypeFunc)
82{
83 return std::any_of(
84 deviceIds.begin(), deviceIds.end(),
85 [&](std::uint32_t deviceId) {
86 return isDeviceTypeFunc(jsState, deviceId);
87 });
88}
89
91{
92 return QtOhos::evalInJsThreadWithPromise<std::set<QInputDevice::DeviceType>>(
93 [](QtOhos::JsState &jsState, QOhosTaskPromise<std::set<QInputDevice::DeviceType>> evalPromise) {
94 auto thenCatchPromises = std::move(evalPromise).makeThenCatchBranches(Q_FUNC_INFO);
95 jsState.evalToPromiseOrRejectOnThrow("@ohos.multimodalInput.inputDevice.getDeviceList()")
96 .onThen(
97 [thenPromise = std::move(thenCatchPromises.first)](const QtOhos::CallbackInfo &cbInfo) {
98 auto deviceIdsJsArray = cbInfo.getFirstArg<QNapi::Array>(Q_FUNC_INFO);
99 auto deviceIds = QNapi::getArrayElements<std::vector<std::uint32_t>, QNapi::Number>(deviceIdsJsArray);
100 std::set<QInputDevice::DeviceType> deviceTypes;
101 if (isDeviceTypeInDeviceIds(cbInfo.jsState(), deviceIds, isInputDeviceWithTouchscreen))
102 deviceTypes.insert(QInputDevice::DeviceType::TouchScreen);
103 if (isDeviceTypeInDeviceIds(cbInfo.jsState(), deviceIds, isInputDeviceWithTouchpad))
104 deviceTypes.insert(QInputDevice::DeviceType::TouchPad);
105 if (isDeviceTypeInDeviceIds(cbInfo.jsState(), deviceIds, isInputDeviceWithMouse))
106 deviceTypes.insert(QInputDevice::DeviceType::Mouse);
107 thenPromise(deviceTypes);
108 })
109 .onCatch(
110 [catchPromise = std::move(thenCatchPromises.second)](const QtOhos::CallbackInfo &) {
111 qOhosPrintfError(
112 "Error while obtaining device list (@ohos.multimodalInput.inputDevice.getDeviceList()). "
113 "No pointing devices will be pre-registered; every device will instead be lazily "
114 "created and registered on first use.");
115 catchPromise({});
116 });
117 },
118 Q_FUNC_INFO);
119}
120
121}
122
123QScopedPointer<QOhosSystemLocale> QOhosPlatformIntegration::m_systemLocale;
126
128{
129 return static_cast<QOhosPlatformIntegration *>(QGuiApplicationPrivate::platformIntegration());
130}
131
133{
134 Q_UNUSED(paramList);
135 auto __dbg = make_QCScopedDebug("QOhosPlatformIntegration::QOhosPlatformIntegration");
136 m_settingsCacheHandle = QOhosSettings::instance().installSettingsCache();
137 m_ohosPlatformNativeInterface.reset(new QOhosPlatformNativeInterface());
138
140 auto rawDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
141 if (Q_UNLIKELY(rawDisplay == EGL_NO_DISPLAY))
142 qOhosReportFatalErrorAndAbort("Could not open egl display");
143
144 EGLint major;
145 EGLint minor;
146 if (Q_UNLIKELY(!eglInitialize(rawDisplay, &major, &minor)))
147 qOhosReportFatalErrorAndAbort("Could not initialize egl display");
148
149 m_eglDisplay = std::shared_ptr<EGLDisplay>(
150 new EGLDisplay(rawDisplay),
151 [](EGLDisplay *p) {
152 eglTerminate(*p);
153 delete p;
154 });
155
156 if (Q_UNLIKELY(!eglBindAPI(EGL_OPENGL_ES_API)))
157 qOhosReportFatalErrorAndAbort("Could not bind GL_ES API");
158 }
159
160 if (!QtOhos::isOhosNoUiChildMode())
161 m_screenManager = std::make_unique<QOhosScreenManager>();
162
163 m_mainThread = QThread::currentThread();
164
165 m_ohosFDB = std::make_unique<QOhosPlatformFontDatabase>();
166 m_ohosPlatformServices = std::make_unique<QOhosPlatformServices>();
167 if (!QtOhos::isOhosNoUiChildMode())
168 m_ohosInputMethodEventHandler = std::make_unique<QOhosInputMethodEventHandler>(getAvailableDeviceTypes());
169
170#ifndef QT_NO_CLIPBOARD
171 if (!QtOhos::isOhosNoUiChildMode())
172 m_platformClipboard = std::make_unique<QOhosPlatformClipboard>();
173#endif // QT_NO_CLIPBOARD
174
175#if QT_CONFIG(draganddrop)
176 if (!QtOhos::isOhosNoUiChildMode())
177 m_drag = makeQOhosPlatformDrag();
178#endif // QT_CONFIG(draganddrop)
179
180 QWindowSystemInterfacePrivate::TabletEvent::setPlatformSynthesizesMouse(false);
181
182 // QCoreApplication::postEvent takes ownership of the created event.
183 QCoreApplication::postEvent(m_ohosPlatformNativeInterface.data(), new QEvent(QEvent::User));
184}
185
187{
188 return m_ohosInputMethodEventHandler.get();
189}
190
195
197{
198 if (hint == ShowIsMaximized)
199 return false;
200 return QPlatformIntegration::styleHint(hint);
201}
202
204{
205 // Don't maximize dialogs on Android
206 if ((flags & Qt::Dialog & ~Qt::Window) != 0)
207 return Qt::WindowNoState;
208
209 return QPlatformIntegration::defaultWindowState(flags);
210}
211
213{
214 auto __dbg = make_QCScopedDebug("QOhosPlatformIntegration::createPlatformWindow");
215
216 static const QSet<QString> nativeDialogClass = {
217 QString::fromUtf8("QFileDialogClassWindow"),
218 };
219 // FIXME: - System that decides the window class should be reworked
220 // For now this behaviour avoids potential crashes related to the lack of surface
221 if (window != nullptr && !nativeDialogClass.contains(window->objectName()))
222 return new QOhosFloatingWindow(window);
223 return new QOhosPlatformWindow(window);
224}
225
227{
228 return new QOhosForeignWindow(window, windowId);
229}
230
232{
233 return m_ohosFDB.get();
234}
235
236#ifndef QT_NO_CLIPBOARD
238{
239 return m_platformClipboard.get();
240}
241#endif
242
243#if QT_CONFIG(draganddrop)
244QPlatformDrag *QOhosPlatformIntegration::drag() const
245{
246 return m_drag.get();
247}
248#endif // QT_CONFIG(draganddrop)
249
251{
252 std::unique_ptr<QPlatformBackingStore> result;
253 switch (window->surfaceType()) {
254 case QSurface::RasterSurface:
255 // NOTE - This is temporary change done so that tests can be performed
256 // on the new implementation - if there are no problems
257 // a switch to it as the default will be made
258 result = QtOhos::isGlBackingStoreDefaultEnabled()
259 ? makeGlOhosPlatformBackingStore(window)
260 : std::make_unique<QOhosPlatformBackingStore>(
261 window,
262 QOhosPlatformBackingStore::CreateInfo{
263 .debugDrawFlushedRegion = QtOhos::isDebugDrawQtRasterBackingStoreFlushedRegionEnabled(),
264 .enableVsync = QtOhos::isVsyncOnSoftwareBackingStoreEnabled(),
265 });
266 break;
267 case QSurface::OpenGLSurface:
268 case QSurface::VulkanSurface:
269 result = std::make_unique<QRhiBackingStore>(window);
270 break;
271 case QSurface::OpenVGSurface:
272 case QSurface::MetalSurface:
273 case QSurface::Direct3DSurface:
274 qOhosReportFatalErrorAndAbort("Unsupported window surface type for backing store: %d", window->surfaceType());
275 break;
276 }
277
278 return result.release();
279}
280#ifndef QT_NO_OPENGL
282{
283 QSurfaceFormat format = context->format();
284 format.setRedBufferSize(8);
285 format.setGreenBufferSize(8);
286 format.setBlueBufferSize(8);
287 format.setAlphaBufferSize(8);
288 auto *eglCtx = new QOhosEGLPlatformContext(format, context->shareHandle(), *m_eglDisplay);
289 return eglCtx;
290}
291
292QOpenGLContext *QOhosPlatformIntegration::createOpenGLContext(EGLContext context, EGLDisplay display, QOpenGLContext *shareContext) const
293{
294 return QEGLPlatformContext::createFrom<QOhosEGLPlatformContext>(context, display, *m_eglDisplay, shareContext);
295}
296#endif // QT_NO_OPENGL
297
298QPlatformOffscreenSurface *
300{
301 auto __dbg = make_QCScopedDebug("QOhosPlatformIntegration::createPlatformOffscreenSurface");
302 return new QEGLPbuffer(*m_eglDisplay, surface->requestedFormat(), surface);
303}
304
305bool QOhosPlatformIntegration::hasCapability(Capability cap) const
306{
307 qOhosDebug(QtForOhos) << "QOhosPlatformIntegration::hasCapability:" << cap;
308
309 switch (cap) {
310 case ApplicationState: return true;
311 case ThreadedPixmaps: return true;
312 case ForeignWindows: return !QtOhos::isOhosNoUiChildMode();
313 case NativeWidgets: return !QtOhos::isOhosNoUiChildMode();
314 case OpenGL: return !QtOhos::isOhosNoUiChildMode();
315 case ThreadedOpenGL: return !QtOhos::isOhosNoUiChildMode();
316 case OffscreenSurface: return true;
317 // TODO: Enable the capability of OpenGLRasterSurface to have emulator
318 // working for OHOS. It doesn't work with other rendering options
319 case OpenGLOnRasterSurface: {
320 return (QOhosDeviceInfo::getProperty(QOhosDeviceInfo::Type::productModel).toString() == QString::fromUtf8("emulator"));
321 }
322 case MultipleWindows: return true;
323 case WindowManagement:
324 case NonFullScreenWindows:
326 case TopStackedNativeChildWindows: return false;
327 default:
328 return QPlatformIntegration::hasCapability(cap);
329 }
330}
331
333{
334 return m_platformInputContext.data();
335}
336
338{
339 auto d = make_QCScopedDebug("QOhosPlatformIntegration::initialize");
340 const auto requestedInputContext = QPlatformInputContextFactory::requested();
341 if (requestedInputContext.isEmpty()) {
343 m_platformInputContext.reset(context);
344 } else {
345 m_platformInputContext.reset(QPlatformInputContextFactory::create(requestedInputContext));
346 }
347
348 if (QWindowSystemInterfacePrivate::eventHandler != nullptr)
349 qOhosReportFatalErrorAndAbort("QWindowSystemInterfacePrivate::eventHandler was already registered.");
350
351 auto tracker = makeApplicationStateTracker();
352 QWindowSystemInterfacePrivate::installWindowSystemEventHandler(tracker.get());
353 m_applicationStateTracker = QtOhos::makeDestroyNotifier(
354 [tracker = std::move(tracker)]() {
355 QWindowSystemInterfacePrivate::removeWindowSystemEventhandler(tracker.get());
356 });
357}
358
360{
361 if (QtOhos::isDebugUseBasicStyleAndThemeEnabled())
362 return std::make_unique<QPlatformTheme>().release();
363
364 if (name == QString::fromUtf8(ohosThemeName))
365 return new QOhosPlatformTheme();
366 return nullptr;
367}
368
370{
371 return {QString::fromUtf8(ohosThemeName)};
372}
373
374WId QOhosPlatformIntegration::windowHandle(ArkUI_NodeHandle content)
375{
376 return reinterpret_cast<WId>(new QtOhos::WindowIdStruct{.content = content});
377}
378
380{
381 return m_systemLocale.data();
382}
383
385{
386 m_systemLocale.reset(systemLocale);
387}
388
394
404
409
411{
412 return m_ohosPlatformServices.get();
413}
414
416{
417 return m_ohosPlatformNativeInterface.get();
418}
419
421{
422 return m_screenManager.get();
423}
424
425#if QT_CONFIG(vulkan)
426
427QPlatformVulkanInstance *QOhosPlatformIntegration::createPlatformVulkanInstance(
428 QVulkanInstance *instance) const
429{
430 return new QOhosPlatformVulkanInstance(instance);
431}
432
433#endif // QT_CONFIG(vulkan)
434
435QT_END_NAMESPACE
static void setMainWindowGeometryPersistencePolicy(WindowGeometryPersistencePolicy policy)
QOhosScreenManager * screenManager() const
QPlatformOpenGLContext * createPlatformOpenGLContext(QOpenGLContext *context) const override
Factory function for QPlatformOpenGLContext.
WId windowHandle(ArkUI_NodeHandle content) override
QOhosPlatformClipboard * clipboard() const override
Accessor for the platform integration's clipboard.
QPlatformOffscreenSurface * createPlatformOffscreenSurface(QOffscreenSurface *surface) const override
Factory function for QOffscreenSurface.
bool hasCapability(Capability cap) const override
QPlatformInputContext * inputContext() const override
Returns the platforms input context.
QPlatformFontDatabase * fontDatabase() const override
Accessor for the platform integration's fontdatabase.
QPlatformServices * services() const override
QPlatformNativeInterface * nativeInterface() const override
QOpenGLContext * createOpenGLContext(EGLContext context, EGLDisplay display, QOpenGLContext *shareContext) const override
QPlatformWindow * createPlatformWindow(QWindow *window) const override
Factory function for QPlatformWindow.
static QOhosPlatformIntegration * instance()
QPlatformTheme * createPlatformTheme(const QString &name) const override
QVariant styleHint(StyleHint hint) const override
QStringList themeNames() const override
static WindowGeometryPersistencePolicy getMainWindowGeometryPersistencePolicy()
Qt::WindowState defaultWindowState(Qt::WindowFlags flags) const override
QPlatformWindow * createForeignWindow(QWindow *, WId) const override
QOhosInputMethodEventHandler * inputMethodEventHandler() const
QPlatformBackingStore * createPlatformBackingStore(QWindow *window) const override
Factory function for QPlatformBackingStore.
QOhosPlatformIntegration(const QStringList &paramList)
QAbstractEventDispatcher * createEventDispatcher() const override
Factory function for the GUI event dispatcher.
void initialize() override
Performs initialization steps that depend on having an event dispatcher available.
static QOhosSystemLocale * systemLocale()
static void setSystemLocale(QOhosSystemLocale *systemLocale)
void setMainWindowGeometryPersistenceEnabled(std::optional< bool > enabled) override
bool isWindowPcModeEnabled() const
static QOhosSettings & instance()
bool isInputDeviceWithMouse(QtOhos::JsState &jsState, std::uint32_t deviceId)
std::set< QInputDevice::DeviceType > getAvailableDeviceTypes()
bool isDeviceTypeInDeviceIds(QtOhos::JsState &jsState, const std::vector< std::uint32_t > &deviceIds, const std::function< bool(QtOhos::JsState &, std::uint32_t)> &isDeviceTypeFunc)
bool isInputDeviceWithTouchscreen(QtOhos::JsState &jsState, std::uint32_t deviceId)
bool isInputDeviceOfType(QtOhos::JsState &jsState, std::uint32_t deviceId, const std::string &type)
bool isInputDeviceWithTouchpad(QtOhos::JsState &jsState, std::uint32_t deviceId)
bool isOhosNoUiChildMode()