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 <vector>
45
46#if QT_CONFIG(vulkan)
47#include "qohosplatformvulkaninstance.h"
48#endif
49
50QT_BEGIN_NAMESPACE
51
52namespace {
53
54bool isInputDeviceOfType(QtOhos::JsState &jsState, std::uint32_t deviceId, const std::string &type)
55{
56 auto devSources = QNapi::getArrayElements<std::vector<std::string>, QNapi::String>(
57 jsState.eval<QNapi::Array>(
58 "@ohos.multimodalInput.inputDevice.getDeviceInfoSync(*).sources",
59 {deviceId}));
60 return std::find(devSources.begin(), devSources.end(), type) != devSources.end();
61}
62
63bool isInputDeviceWithTouchscreen(QtOhos::JsState &jsState, std::uint32_t deviceId)
64{
65 return isInputDeviceOfType(jsState, deviceId, "touchscreen");
66}
67
68bool isInputDeviceWithTouchpad(QtOhos::JsState &jsState, std::uint32_t deviceId)
69{
70 return isInputDeviceOfType(jsState, deviceId, "touchpad");
71}
72
73bool isInputDeviceWithMouse(QtOhos::JsState &jsState, std::uint32_t deviceId)
74{
75 return isInputDeviceOfType(jsState, deviceId, "mouse");
76}
77
79 QtOhos::JsState &jsState, const std::vector<std::uint32_t> &deviceIds,
80 const std::function<bool(QtOhos::JsState &, std::uint32_t)> &isDeviceTypeFunc)
81{
82 return std::any_of(
83 deviceIds.begin(), deviceIds.end(),
84 [&](std::uint32_t deviceId) {
85 return isDeviceTypeFunc(jsState, deviceId);
86 });
87}
88
90{
91 return QtOhos::evalInJsThreadWithPromise<std::set<QInputDevice::DeviceType>>(
92 [](QtOhos::JsState &jsState, QOhosTaskPromise<std::set<QInputDevice::DeviceType>> evalPromise) {
93 auto thenCatchPromises = std::move(evalPromise).makeThenCatchBranches(Q_FUNC_INFO);
94 jsState.evalToPromiseOrRejectOnThrow("@ohos.multimodalInput.inputDevice.getDeviceList()")
95 .onThen(
96 [thenPromise = std::move(thenCatchPromises.first)](const QtOhos::CallbackInfo &cbInfo) {
97 auto deviceIdsJsArray = cbInfo.getFirstArg<QNapi::Array>(Q_FUNC_INFO);
98 auto deviceIds = QNapi::getArrayElements<std::vector<std::uint32_t>, QNapi::Number>(deviceIdsJsArray);
99 std::set<QInputDevice::DeviceType> deviceTypes;
100 if (isDeviceTypeInDeviceIds(cbInfo.jsState(), deviceIds, isInputDeviceWithTouchscreen))
101 deviceTypes.insert(QInputDevice::DeviceType::TouchScreen);
102 if (isDeviceTypeInDeviceIds(cbInfo.jsState(), deviceIds, isInputDeviceWithTouchpad))
103 deviceTypes.insert(QInputDevice::DeviceType::TouchPad);
104 if (isDeviceTypeInDeviceIds(cbInfo.jsState(), deviceIds, isInputDeviceWithMouse))
105 deviceTypes.insert(QInputDevice::DeviceType::Mouse);
106 thenPromise(deviceTypes);
107 })
108 .onCatch(
109 [catchPromise = std::move(thenCatchPromises.second)](const QtOhos::CallbackInfo &) {
110 qOhosPrintfError(
111 "Error while obtaining device list (@ohos.multimodalInput.inputDevice.getDeviceList()). "
112 "No pointing devices will be pre-registered; every device will instead be lazily "
113 "created and registered on first use.");
114 catchPromise({});
115 });
116 },
117 Q_FUNC_INFO);
118}
119
120}
121
122QScopedPointer<QOhosSystemLocale> QOhosPlatformIntegration::m_systemLocale;
125
127{
128 return static_cast<QOhosPlatformIntegration *>(QGuiApplicationPrivate::platformIntegration());
129}
130
132{
133 Q_UNUSED(paramList);
134 auto __dbg = make_QCScopedDebug("QOhosPlatformIntegration::QOhosPlatformIntegration");
135 m_settingsCacheHandle = QOhosSettings::instance().installSettingsCache();
136 m_ohosPlatformNativeInterface.reset(new QOhosPlatformNativeInterface());
137
139 auto rawDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
140 if (Q_UNLIKELY(rawDisplay == EGL_NO_DISPLAY))
141 qOhosReportFatalErrorAndAbort("Could not open egl display");
142
143 EGLint major;
144 EGLint minor;
145 if (Q_UNLIKELY(!eglInitialize(rawDisplay, &major, &minor)))
146 qOhosReportFatalErrorAndAbort("Could not initialize egl display");
147
148 m_eglDisplay = std::shared_ptr<EGLDisplay>(
149 new EGLDisplay(rawDisplay),
150 [](EGLDisplay *p) {
151 eglTerminate(*p);
152 delete p;
153 });
154
155 if (Q_UNLIKELY(!eglBindAPI(EGL_OPENGL_ES_API)))
156 qOhosReportFatalErrorAndAbort("Could not bind GL_ES API");
157 }
158
159 if (!QtOhos::isOhosNoUiChildMode())
160 m_screenManager = std::make_unique<QOhosScreenManager>();
161
162 m_mainThread = QThread::currentThread();
163
164 m_ohosFDB = std::make_unique<QOhosPlatformFontDatabase>();
165 m_ohosPlatformServices = std::make_unique<QOhosPlatformServices>();
166 if (!QtOhos::isOhosNoUiChildMode())
167 m_ohosInputMethodEventHandler = std::make_unique<QOhosInputMethodEventHandler>(getAvailableDeviceTypes());
168
169#ifndef QT_NO_CLIPBOARD
170 if (!QtOhos::isOhosNoUiChildMode())
171 m_platformClipboard = std::make_unique<QOhosPlatformClipboard>();
172#endif // QT_NO_CLIPBOARD
173
174#if QT_CONFIG(draganddrop)
175 if (!QtOhos::isOhosNoUiChildMode())
176 m_drag = makeQOhosPlatformDrag();
177#endif // QT_CONFIG(draganddrop)
178
179 QWindowSystemInterfacePrivate::TabletEvent::setPlatformSynthesizesMouse(false);
180
181 // QCoreApplication::postEvent takes ownership of the created event.
182 QCoreApplication::postEvent(m_ohosPlatformNativeInterface.data(), new QEvent(QEvent::User));
183}
184
186{
187 return m_ohosInputMethodEventHandler.get();
188}
189
194
196{
197 if (hint == ShowIsMaximized)
198 return false;
199 return QPlatformIntegration::styleHint(hint);
200}
201
203{
204 // Don't maximize dialogs on Android
205 if ((flags & Qt::Dialog & ~Qt::Window) != 0)
206 return Qt::WindowNoState;
207
208 return QPlatformIntegration::defaultWindowState(flags);
209}
210
212{
213 auto __dbg = make_QCScopedDebug("QOhosPlatformIntegration::createPlatformWindow");
214
215 static const QSet<QString> nativeDialogClass = {
216 QString::fromUtf8("QFileDialogClassWindow"),
217 };
218 // FIXME: - System that decides the window class should be reworked
219 // For now this behaviour avoids potential crashes related to the lack of surface
220 if (window != nullptr && !nativeDialogClass.contains(window->objectName()))
221 return new QOhosFloatingWindow(window);
222 return new QOhosPlatformWindow(window);
223}
224
226{
227 return new QOhosForeignWindow(window, windowId);
228}
229
231{
232 return m_ohosFDB.get();
233}
234
235#ifndef QT_NO_CLIPBOARD
237{
238 return m_platformClipboard.get();
239}
240#endif
241
242#if QT_CONFIG(draganddrop)
243QPlatformDrag *QOhosPlatformIntegration::drag() const
244{
245 return m_drag.get();
246}
247#endif // QT_CONFIG(draganddrop)
248
250{
251 std::unique_ptr<QPlatformBackingStore> result;
252 switch (window->surfaceType()) {
253#if QT_DEPRECATED_SINCE(6, 11)
254QT_IGNORE_DEPRECATIONS(
255 case QSurface::RasterGLSurface:
256 break;
257)
258#endif
259 case QSurface::RasterSurface:
260 // NOTE - This is temporary change done so that tests can be performed
261 // on the new implementation - if there are no problems
262 // a switch to it as the default will be made
263 result = QtOhos::isGlBackingStoreDefaultEnabled()
264 ? makeGlOhosPlatformBackingStore(window)
265 : std::make_unique<QOhosPlatformBackingStore>(
266 window,
267 QOhosPlatformBackingStore::CreateInfo{
268 .debugDrawFlushedRegion = QtOhos::isDebugDrawQtRasterBackingStoreFlushedRegionEnabled(),
269 .enableVsync = QtOhos::isVsyncOnSoftwareBackingStoreEnabled(),
270 });
271 break;
272 case QSurface::OpenGLSurface:
273 case QSurface::VulkanSurface:
274 result = std::make_unique<QRhiBackingStore>(window);
275 break;
276 case QSurface::OpenVGSurface:
277 case QSurface::MetalSurface:
278 case QSurface::Direct3DSurface:
279 qOhosReportFatalErrorAndAbort("Unsupported window surface type for backing store: %d", window->surfaceType());
280 break;
281 }
282
283 return result.release();
284}
285#ifndef QT_NO_OPENGL
287{
288 QSurfaceFormat format = context->format();
289 format.setRedBufferSize(8);
290 format.setGreenBufferSize(8);
291 format.setBlueBufferSize(8);
292 format.setAlphaBufferSize(8);
293 auto *eglCtx = new QOhosEGLPlatformContext(format, context->shareHandle(), *m_eglDisplay);
294 return eglCtx;
295}
296
297QOpenGLContext *QOhosPlatformIntegration::createOpenGLContext(EGLContext context, EGLDisplay display, QOpenGLContext *shareContext) const
298{
299 return QEGLPlatformContext::createFrom<QOhosEGLPlatformContext>(context, display, *m_eglDisplay, shareContext);
300}
301#endif // QT_NO_OPENGL
302
303QPlatformOffscreenSurface *
305{
306 auto __dbg = make_QCScopedDebug("QOhosPlatformIntegration::createPlatformOffscreenSurface");
307 return new QEGLPbuffer(*m_eglDisplay, surface->requestedFormat(), surface);
308}
309
310bool QOhosPlatformIntegration::hasCapability(Capability cap) const
311{
312 qOhosDebug(QtForOhos) << "QOhosPlatformIntegration::hasCapability:" << cap;
313
314 switch (cap) {
315 case ApplicationState: return true;
316 case ThreadedPixmaps: return true;
317 case ForeignWindows: return !QtOhos::isOhosNoUiChildMode();
318 case NativeWidgets: return !QtOhos::isOhosNoUiChildMode();
319 case OpenGL: return !QtOhos::isOhosNoUiChildMode();
320 case ThreadedOpenGL: return !QtOhos::isOhosNoUiChildMode();
321 case OffscreenSurface: return true;
322 // TODO: Enable the capability of OpenGLRasterSurface to have emulator
323 // working for OHOS. It doesn't work with other rendering options
324 case OpenGLOnRasterSurface: {
325 return (QOhosDeviceInfo::getProperty(QOhosDeviceInfo::Type::productModel).toString() == QString::fromUtf8("emulator"));
326 }
327 case MultipleWindows:
328 case WindowManagement:
329 case NonFullScreenWindows:
331 case TopStackedNativeChildWindows: return false;
332 default:
333 return QPlatformIntegration::hasCapability(cap);
334 }
335}
336
338{
339 return m_platformInputContext.data();
340}
341
343{
344 auto d = make_QCScopedDebug("QOhosPlatformIntegration::initialize");
345 const auto requestedInputContext = QPlatformInputContextFactory::requested();
346 if (requestedInputContext.isEmpty()) {
348 m_platformInputContext.reset(context);
349 } else {
350 m_platformInputContext.reset(QPlatformInputContextFactory::create(requestedInputContext));
351 }
352
353 if (QWindowSystemInterfacePrivate::eventHandler != nullptr)
354 qOhosReportFatalErrorAndAbort("QWindowSystemInterfacePrivate::eventHandler was already registered.");
355
356 auto tracker = makeApplicationStateTracker();
357 QWindowSystemInterfacePrivate::installWindowSystemEventHandler(tracker.get());
358 m_applicationStateTracker = QtOhos::makeDestroyNotifier(
359 [tracker = std::move(tracker)]() {
360 QWindowSystemInterfacePrivate::removeWindowSystemEventhandler(tracker.get());
361 });
362}
363
365{
366 if (QtOhos::isDebugUseBasicStyleAndThemeEnabled())
367 return std::make_unique<QPlatformTheme>().release();
368
369 if (name == QString::fromUtf8(ohosThemeName))
370 return new QOhosPlatformTheme();
371 return nullptr;
372}
373
375{
376 return {QString::fromUtf8(ohosThemeName)};
377}
378
379WId QOhosPlatformIntegration::windowHandle(ArkUI_NodeHandle content)
380{
381 auto *windowIdStruct = new QtOhos::WindowIdStruct{};
382 windowIdStruct->content = content;
383 return reinterpret_cast<WId>(windowIdStruct);
384}
385
387{
388 return m_systemLocale.data();
389}
390
392{
393 m_systemLocale.reset(systemLocale);
394}
395
401
411
416
418{
419 return m_ohosPlatformServices.get();
420}
421
423{
424 return m_ohosPlatformNativeInterface.get();
425}
426
428{
429 return m_screenManager.get();
430}
431
432#if QT_CONFIG(vulkan)
433
434QPlatformVulkanInstance *QOhosPlatformIntegration::createPlatformVulkanInstance(
435 QVulkanInstance *instance) const
436{
437 return new QOhosPlatformVulkanInstance(instance);
438}
439
440#endif // QT_CONFIG(vulkan)
441
442QT_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()