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
75 QtOhos::JsState &jsState, const std::vector<std::uint32_t> &deviceIds,
76 const std::function<bool(QtOhos::JsState &, std::uint32_t)> &isDeviceTypeFunc)
77{
78 return std::any_of(
79 deviceIds.begin(), deviceIds.end(),
80 [&](std::uint32_t deviceId) {
81 return isDeviceTypeFunc(jsState, deviceId);
82 });
83}
84
86{
87 return QtOhos::evalInJsThreadWithPromise<std::set<QInputDevice::DeviceType>>(
88 [](QtOhos::JsState &jsState, QOhosTaskPromise<std::set<QInputDevice::DeviceType>> evalPromise) {
89 auto thenCatchPromises = std::move(evalPromise).makeThenCatchBranches(Q_FUNC_INFO);
90 jsState.evalToPromiseOrRejectOnThrow("@ohos.multimodalInput.inputDevice.getDeviceList()")
91 .onThen(
92 [thenPromise = std::move(thenCatchPromises.first)](const QtOhos::CallbackInfo &cbInfo) {
93 auto deviceIdsJsArray = cbInfo.getFirstArg<QNapi::Array>(Q_FUNC_INFO);
94 auto deviceIds = QNapi::getArrayElements<std::vector<std::uint32_t>, QNapi::Number>(deviceIdsJsArray);
95 std::set<QInputDevice::DeviceType> deviceTypes;
96 if (isDeviceTypeInDeviceIds(cbInfo.jsState(), deviceIds, isInputDeviceWithTouchscreen))
97 deviceTypes.insert(QInputDevice::DeviceType::TouchScreen);
98 if (isDeviceTypeInDeviceIds(cbInfo.jsState(), deviceIds, isInputDeviceWithTouchpad))
99 deviceTypes.insert(QInputDevice::DeviceType::TouchPad);
100 thenPromise(deviceTypes);
101 })
102 .onCatch(
103 [catchPromise = std::move(thenCatchPromises.second)](const QtOhos::CallbackInfo &) {
104 qOhosPrintfError("Error while obtaining device list (@ohos.multimodalInput.inputDevice.getDeviceList())");
105 catchPromise({});
106 });
107 },
108 Q_FUNC_INFO);
109}
110
111}
112
113QScopedPointer<QOhosSystemLocale> QOhosPlatformIntegration::m_systemLocale;
116
118{
119 return static_cast<QOhosPlatformIntegration *>(QGuiApplicationPrivate::platformIntegration());
120}
121
123{
124 Q_UNUSED(paramList);
125 auto __dbg = make_QCScopedDebug("QOhosPlatformIntegration::QOhosPlatformIntegration");
126 m_ohosPlatformNativeInterface.reset(new QOhosPlatformNativeInterface());
127
129 auto rawDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
130 if (Q_UNLIKELY(rawDisplay == EGL_NO_DISPLAY))
131 qOhosReportFatalErrorAndAbort("Could not open egl display");
132
133 EGLint major;
134 EGLint minor;
135 if (Q_UNLIKELY(!eglInitialize(rawDisplay, &major, &minor)))
136 qOhosReportFatalErrorAndAbort("Could not initialize egl display");
137
138 m_eglDisplay = std::shared_ptr<EGLDisplay>(
139 new EGLDisplay(rawDisplay),
140 [](EGLDisplay *p) {
141 eglTerminate(*p);
142 delete p;
143 });
144
145 if (Q_UNLIKELY(!eglBindAPI(EGL_OPENGL_ES_API)))
146 qOhosReportFatalErrorAndAbort("Could not bind GL_ES API");
147 }
148
149 if (!QtOhos::isOhosNoUiChildMode())
150 m_screenManager = std::make_unique<QOhosScreenManager>();
151
152 m_mainThread = QThread::currentThread();
153
154 m_ohosFDB = std::make_unique<QOhosPlatformFontDatabase>();
155 m_ohosPlatformServices = std::make_unique<QOhosPlatformServices>();
156 if (!QtOhos::isOhosNoUiChildMode())
157 m_ohosInputMethodEventHandler = std::make_unique<QOhosInputMethodEventHandler>(getAvailableDeviceTypes());
158
159#ifndef QT_NO_CLIPBOARD
160 if (!QtOhos::isOhosNoUiChildMode())
161 m_platformClipboard = std::make_unique<QOhosPlatformClipboard>();
162#endif // QT_NO_CLIPBOARD
163
164#if QT_CONFIG(draganddrop)
165 if (!QtOhos::isOhosNoUiChildMode())
166 m_drag = makeQOhosPlatformDrag();
167#endif // QT_CONFIG(draganddrop)
168
169 QWindowSystemInterfacePrivate::TabletEvent::setPlatformSynthesizesMouse(false);
170
171 // QCoreApplication::postEvent takes ownership of the created event.
172 QCoreApplication::postEvent(m_ohosPlatformNativeInterface.data(), new QEvent(QEvent::User));
173}
174
176{
177 return m_ohosInputMethodEventHandler.get();
178}
179
184
186{
187 if (hint == ShowIsMaximized)
188 return false;
189 return QPlatformIntegration::styleHint(hint);
190}
191
193{
194 // Don't maximize dialogs on Android
195 if ((flags & Qt::Dialog & ~Qt::Window) != 0)
196 return Qt::WindowNoState;
197
198 return QPlatformIntegration::defaultWindowState(flags);
199}
200
202{
203 auto __dbg = make_QCScopedDebug("QOhosPlatformIntegration::createPlatformWindow");
204
205 static const QSet<QString> nativeDialogClass = {
206 QString::fromUtf8("QFileDialogClassWindow"),
207 };
208 // FIXME: - System that decides the window class should be reworked
209 // For now this behaviour avoids potential crashes related to the lack of surface
210 if (window != nullptr && !nativeDialogClass.contains(window->objectName()))
211 return new QOhosFloatingWindow(window);
212 return new QOhosPlatformWindow(window);
213}
214
216{
217 return new QOhosForeignWindow(window, windowId);
218}
219
221{
222 return m_ohosFDB.get();
223}
224
225#ifndef QT_NO_CLIPBOARD
227{
228 return m_platformClipboard.get();
229}
230#endif
231
232#if QT_CONFIG(draganddrop)
233QPlatformDrag *QOhosPlatformIntegration::drag() const
234{
235 return m_drag.get();
236}
237#endif // QT_CONFIG(draganddrop)
238
240{
241 std::unique_ptr<QPlatformBackingStore> result;
242 switch (window->surfaceType()) {
243 case QSurface::RasterSurface:
244 // NOTE - This is temporary change done so that tests can be performed
245 // on the new implementation - if there are no problems
246 // a switch to it as the default will be made
247 result = QtOhos::isGlBackingStoreDefaultEnabled()
248 ? makeGlOhosPlatformBackingStore(window)
249 : std::make_unique<QOhosPlatformBackingStore>(
250 window,
251 QOhosPlatformBackingStore::CreateInfo{
252 .debugDrawFlushedRegion = QtOhos::isDebugDrawQtRasterBackingStoreFlushedRegionEnabled(),
253 .enableVsync = QtOhos::isVsyncOnSoftwareBackingStoreEnabled(),
254 });
255 break;
256 case QSurface::OpenGLSurface:
257 case QSurface::VulkanSurface:
258 result = std::make_unique<QRhiBackingStore>(window);
259 break;
260 case QSurface::OpenVGSurface:
261 case QSurface::MetalSurface:
262 case QSurface::Direct3DSurface:
263 qOhosReportFatalErrorAndAbort("Unsupported window surface type for backing store: %d", window->surfaceType());
264 break;
265 }
266
267 return result.release();
268}
269#ifndef QT_NO_OPENGL
271{
272 QSurfaceFormat format = context->format();
273 format.setRedBufferSize(8);
274 format.setGreenBufferSize(8);
275 format.setBlueBufferSize(8);
276 format.setAlphaBufferSize(8);
277 auto *eglCtx = new QOhosEGLPlatformContext(format, context->shareHandle(), *m_eglDisplay);
278 return eglCtx;
279}
280
281QOpenGLContext *QOhosPlatformIntegration::createOpenGLContext(EGLContext context, EGLDisplay display, QOpenGLContext *shareContext) const
282{
283 return QEGLPlatformContext::createFrom<QOhosEGLPlatformContext>(context, display, *m_eglDisplay, shareContext);
284}
285#endif // QT_NO_OPENGL
286
287QPlatformOffscreenSurface *
289{
290 auto __dbg = make_QCScopedDebug("QOhosPlatformIntegration::createPlatformOffscreenSurface");
291 return new QEGLPbuffer(*m_eglDisplay, surface->requestedFormat(), surface);
292}
293
294bool QOhosPlatformIntegration::hasCapability(Capability cap) const
295{
296 qOhosDebug(QtForOhos) << "QOhosPlatformIntegration::hasCapability:" << cap;
297
298 switch (cap) {
299 case ApplicationState: return true;
300 case ThreadedPixmaps: return true;
301 case ForeignWindows: return !QtOhos::isOhosNoUiChildMode();
302 case NativeWidgets: return !QtOhos::isOhosNoUiChildMode();
303 case OpenGL: return !QtOhos::isOhosNoUiChildMode();
304 case ThreadedOpenGL: return !QtOhos::isOhosNoUiChildMode();
305 case OffscreenSurface: return true;
306 // TODO: Enable the capability of OpenGLRasterSurface to have emulator
307 // working for OHOS. It doesn't work with other rendering options
308 case OpenGLOnRasterSurface: {
309 return (QOhosDeviceInfo::getProperty(QOhosDeviceInfo::Type::productModel).toString() == QString::fromUtf8("emulator"));
310 }
311 case MultipleWindows: return true;
312 case WindowManagement:
313 case NonFullScreenWindows:
315 case TopStackedNativeChildWindows: return false;
316 default:
317 return QPlatformIntegration::hasCapability(cap);
318 }
319}
320
322{
323 return m_platformInputContext.data();
324}
325
327{
328 auto d = make_QCScopedDebug("QOhosPlatformIntegration::initialize");
329 const auto requestedInputContext = QPlatformInputContextFactory::requested();
330 if (requestedInputContext.isEmpty()) {
332 m_platformInputContext.reset(context);
333 } else {
334 m_platformInputContext.reset(QPlatformInputContextFactory::create(requestedInputContext));
335 }
336
337 if (QWindowSystemInterfacePrivate::eventHandler != nullptr)
338 qOhosReportFatalErrorAndAbort("QWindowSystemInterfacePrivate::eventHandler was already registered.");
339
340 auto tracker = makeApplicationStateTracker();
341 QWindowSystemInterfacePrivate::installWindowSystemEventHandler(tracker.get());
342 m_applicationStateTracker = QtOhos::makeDestroyNotifier(
343 [tracker = std::move(tracker)]() {
344 QWindowSystemInterfacePrivate::removeWindowSystemEventhandler(tracker.get());
345 });
346
347 m_settings = std::make_unique<QOhosSettings>();
348}
349
351{
352 return m_settings.get();
353}
354
356{
357 if (QtOhos::isDebugUseBasicStyleAndThemeEnabled())
358 return std::make_unique<QPlatformTheme>().release();
359
360 if (name == QString::fromUtf8(ohosThemeName))
361 return new QOhosPlatformTheme();
362 return nullptr;
363}
364
366{
367 return {QString::fromUtf8(ohosThemeName)};
368}
369
370WId QOhosPlatformIntegration::windowHandle(ArkUI_NodeHandle content)
371{
372 return reinterpret_cast<WId>(new QtOhos::WindowIdStruct{.content = content});
373}
374
376{
377 return m_systemLocale.data();
378}
379
381{
382 m_systemLocale.reset(systemLocale);
383}
384
390
395
397{
398 return m_ohosPlatformServices.get();
399}
400
402{
403 return m_ohosPlatformNativeInterface.get();
404}
405
407{
408 return m_screenManager.get();
409}
410
411#if QT_CONFIG(vulkan)
412
413QPlatformVulkanInstance *QOhosPlatformIntegration::createPlatformVulkanInstance(
414 QVulkanInstance *instance) const
415{
416 return new QOhosPlatformVulkanInstance(instance);
417}
418
419#endif // QT_CONFIG(vulkan)
420
421QT_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)
bool isWindowPcModeEnabled() const
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()