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 case QSurface::RasterSurface:
254 // NOTE - This is temporary change done so that tests can be performed
255 // on the new implementation - if there are no problems
256 // a switch to it as the default will be made
257 result = QtOhos::isGlBackingStoreDefaultEnabled()
258 ? makeGlOhosPlatformBackingStore(window)
259 : std::make_unique<QOhosPlatformBackingStore>(
260 window,
261 QOhosPlatformBackingStore::CreateInfo{
262 .debugDrawFlushedRegion = QtOhos::isDebugDrawQtRasterBackingStoreFlushedRegionEnabled(),
263 .enableVsync = QtOhos::isVsyncOnSoftwareBackingStoreEnabled(),
264 });
265 break;
266 case QSurface::OpenGLSurface:
267 case QSurface::VulkanSurface:
268 result = std::make_unique<QRhiBackingStore>(window);
269 break;
270 case QSurface::OpenVGSurface:
271 case QSurface::MetalSurface:
272 case QSurface::Direct3DSurface:
273 qOhosReportFatalErrorAndAbort("Unsupported window surface type for backing store: %d", window->surfaceType());
274 break;
275 }
276
277 return result.release();
278}
279#ifndef QT_NO_OPENGL
281{
282 QSurfaceFormat format = context->format();
283 format.setRedBufferSize(8);
284 format.setGreenBufferSize(8);
285 format.setBlueBufferSize(8);
286 format.setAlphaBufferSize(8);
287 auto *eglCtx = new QOhosEGLPlatformContext(format, context->shareHandle(), *m_eglDisplay);
288 return eglCtx;
289}
290
291QOpenGLContext *QOhosPlatformIntegration::createOpenGLContext(EGLContext context, EGLDisplay display, QOpenGLContext *shareContext) const
292{
293 return QEGLPlatformContext::createFrom<QOhosEGLPlatformContext>(context, display, *m_eglDisplay, shareContext);
294}
295#endif // QT_NO_OPENGL
296
297QPlatformOffscreenSurface *
299{
300 auto __dbg = make_QCScopedDebug("QOhosPlatformIntegration::createPlatformOffscreenSurface");
301 return new QEGLPbuffer(*m_eglDisplay, surface->requestedFormat(), surface);
302}
303
304bool QOhosPlatformIntegration::hasCapability(Capability cap) const
305{
306 qOhosDebug(QtForOhos) << "QOhosPlatformIntegration::hasCapability:" << cap;
307
308 switch (cap) {
309 case ApplicationState: return true;
310 case ThreadedPixmaps: return true;
311 case ForeignWindows: return !QtOhos::isOhosNoUiChildMode();
312 case NativeWidgets: return !QtOhos::isOhosNoUiChildMode();
313 case OpenGL: return !QtOhos::isOhosNoUiChildMode();
314 case ThreadedOpenGL: return !QtOhos::isOhosNoUiChildMode();
315 case OffscreenSurface: return true;
316 // TODO: Enable the capability of OpenGLRasterSurface to have emulator
317 // working for OHOS. It doesn't work with other rendering options
318 case OpenGLOnRasterSurface: {
319 return (QOhosDeviceInfo::getProperty(QOhosDeviceInfo::Type::productModel).toString() == QString::fromUtf8("emulator"));
320 }
321 case MultipleWindows: return true;
322 case WindowManagement:
323 case NonFullScreenWindows:
325 case TopStackedNativeChildWindows: return false;
326 default:
327 return QPlatformIntegration::hasCapability(cap);
328 }
329}
330
332{
333 return m_platformInputContext.data();
334}
335
337{
338 auto d = make_QCScopedDebug("QOhosPlatformIntegration::initialize");
339 const auto requestedInputContext = QPlatformInputContextFactory::requested();
340 if (requestedInputContext.isEmpty()) {
342 m_platformInputContext.reset(context);
343 } else {
344 m_platformInputContext.reset(QPlatformInputContextFactory::create(requestedInputContext));
345 }
346
347 if (QWindowSystemInterfacePrivate::eventHandler != nullptr)
348 qOhosReportFatalErrorAndAbort("QWindowSystemInterfacePrivate::eventHandler was already registered.");
349
350 auto tracker = makeApplicationStateTracker();
351 QWindowSystemInterfacePrivate::installWindowSystemEventHandler(tracker.get());
352 m_applicationStateTracker = QtOhos::makeDestroyNotifier(
353 [tracker = std::move(tracker)]() {
354 QWindowSystemInterfacePrivate::removeWindowSystemEventhandler(tracker.get());
355 });
356}
357
359{
360 if (QtOhos::isDebugUseBasicStyleAndThemeEnabled())
361 return std::make_unique<QPlatformTheme>().release();
362
363 if (name == QString::fromUtf8(ohosThemeName))
364 return new QOhosPlatformTheme();
365 return nullptr;
366}
367
369{
370 return {QString::fromUtf8(ohosThemeName)};
371}
372
373WId QOhosPlatformIntegration::windowHandle(ArkUI_NodeHandle content)
374{
375 return reinterpret_cast<WId>(new QtOhos::WindowIdStruct{.content = content});
376}
377
379{
380 return m_systemLocale.data();
381}
382
384{
385 m_systemLocale.reset(systemLocale);
386}
387
393
403
408
410{
411 return m_ohosPlatformServices.get();
412}
413
415{
416 return m_ohosPlatformNativeInterface.get();
417}
418
420{
421 return m_screenManager.get();
422}
423
424#if QT_CONFIG(vulkan)
425
426QPlatformVulkanInstance *QOhosPlatformIntegration::createPlatformVulkanInstance(
427 QVulkanInstance *instance) const
428{
429 return new QOhosPlatformVulkanInstance(instance);
430}
431
432#endif // QT_CONFIG(vulkan)
433
434QT_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()