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
qohosplugincore.h
Go to the documentation of this file.
1// Copyright (C) 2026 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#ifndef QOHOSPLUGINCORE_H
5#define QOHOSPLUGINCORE_H
6
7#include <QtCore/private/qcore_ohos_p.h>
8#include <QtCore/private/qnapi_p.h>
9#include <QtCore/private/qohoscommon_p.h>
10#include <QtCore/qobject.h>
11#include <atomic>
12#include <chrono>
13#include <cstdlib>
14#include <functional>
15#include <map>
16#include <memory>
17#include <optional>
18#include <qohosenums.h>
19#include <string>
20#include <type_traits>
21#include <typeinfo>
22#include <vector>
23
24QT_BEGIN_NAMESPACE
25
27
28template<typename A, typename B, typename = void>
30
31template<typename A, typename B>
32struct HasEqualityComparatorT<A, B, decltype(void(std::declval<A>() == std::declval<B>()))>
33 : std::true_type {};
34
35template<typename A, typename B>
37
38template<typename>
40
41template<typename T>
42struct IsStdOptional<std::optional<T>> : std::true_type {};
43
44template<typename T>
46
47}
48
49template<typename T, typename Func>
50std::enable_if_t<
51 qohosplugincore_h_detail::isStdOptional<QOhosInvokeResult<Func, T>>,
52 QOhosInvokeResult<Func, T>>
53qAndThen(const std::optional<T> &opt, Func &&func);
54
55template<typename T, typename Func>
56std::optional<std::remove_cv_t<QOhosInvokeResult<Func, T>>> qTransform(const std::optional<T> &opt, Func &&func);
57
58namespace QtOhos {
59
61{
62public:
63 static void tagWindowAsClosing(QNapi::Object jsWindow, const char *logContext);
64 static bool isWindowClosing(QNapi::Object jsWindow);
65
66 JsWindowsTracker() = delete;
67};
68
70{
71public:
72 virtual ~QAbilityPeer();
73
74 virtual std::string instanceId() = 0;
75 virtual QNapi::Object uiContext() = 0;
76 virtual QNapi::Object qAbility() = 0;
77 virtual QNapi::Object launchWant() = 0;
80 virtual void forceResolveQWindowDestroyPromiseIfPresent(Napi::Env env) = 0;
81 virtual std::shared_ptr<std::atomic_bool> destroyAllowedFlag() = 0;
82 virtual bool isTerminating() = 0;
83
84 virtual void setQWindow(Napi::Env env, QObjectThreadSafeRef qwindow) = 0;
85
86 virtual void *tryCastWithTypeIdObject(const void *matchTypeIdObject) = 0;
87
88protected:
90};
91
93{
94 std::string name;
95 std::string bundleName;
96 std::string moduleName;
97};
98
100{
101public:
102 virtual ~QAbilityEngine();
103
104 virtual QAbilityInfo readAbilityInfo(const QNapi::Object &ability) const = 0;
105
106protected:
108};
109
110class JsState;
111
113{
114public:
115 virtual ~AppFunctions();
116
118 QNapi::Object baseQAbility, QObjectThreadSafeRef qwindow,
119 QNapi::Object optStartOptions,
120 std::function<void(JsState &, std::shared_ptr<QAbilityPeer>)> startupNotifyFunc) = 0;
121
122 virtual void startAppProcess(
123 QNapi::Object baseQAbility, const std::string &processId, QNapi::Object want,
124 QNapi::Object optStartOptions, std::function<void(JsState &)> continueFunc) = 0;
125
126 virtual void startNoUiChildProcess(JsState &jsState, const std::string &libraryName, const std::vector<std::string> &args) = 0;
127
128 virtual void tagWidgetOrWindowAsFloatWindow(QObject *widgetOrWindow, bool floatWindowEnabled) = 0;
129};
130
136
137class JsState : public QOhosJsState
138{
139public:
140 JsState(const JsState &) = delete;
141 JsState &operator=(const JsState &) = delete;
142
144
146
147 virtual std::shared_ptr<QAbilityPeer> defaultQAbilityPeer() = 0;
148 virtual std::shared_ptr<QAbilityPeer> tryGetQAbilityPeerByInstanceId(const std::string &instanceId) = 0;
149 virtual std::shared_ptr<QAbilityPeer> tryGetQAbilityPeerByInstance(QNapi::Object qAbility) = 0;
150 virtual std::shared_ptr<QAbilityPeer> tryGetQAbilityPeerByQWindow(QObjectThreadSafeRef qwindow) = 0;
151
152 virtual void visitEachQAbilityPeer(const std::function<void(std::shared_ptr<QAbilityPeer>)> &visitor) = 0;
153
155 QNapi::Object baseQAbility, QObjectThreadSafeRef qwindow,
156 QNapi::Object optStartOptions,
157 std::function<void(JsState &, std::shared_ptr<QAbilityPeer>)> startupNotifyFunc) = 0;
158
159 virtual QtRunMode qtRunMode() = 0;
160
161 template<typename T>
163
164 template<typename T>
166
167protected:
169
170private:
172 const std::type_info &objectTypeInfo, QOhosSupplier<std::shared_ptr<void>> objectFactory) = 0;
173
174 virtual QNapi::Symbol getJsSymbolForType(const std::type_info &typeInfo) = 0;
175};
176
178
180{
181public:
182 static std::shared_ptr<QUiAbilityPeer> tryCastFromQAbilityPeerOrNull(std::shared_ptr<QAbilityPeer> qAbilityPeer);
183
184 ~QUiAbilityPeer() override;
185
186 virtual QNapi::Object launchParam() = 0;
187
188 virtual QNapi::Object windowStage() = 0;
189 virtual QNapi::Object window() = 0;
190
192 std::function<void(JsState &, QNapi::Object, QOhosConsumer<JsState &, QOhosAbilityOnContinueResult>)> requestsHandler) = 0;
193
194protected:
196
197private:
198 static const nullptr_t typeIdObject;
199
200 void *tryCastWithTypeIdObject(const void *matchTypeIdObject) final;
201};
202
204{
205public:
207
208 JsState &jsState() const;
209};
210
211// this function should be called once from JS thread at some point during startup
215
216// this function should be called from JS thread for each UIAbility when it's ready
217void addJsQAbilityPeer(std::shared_ptr<QAbilityPeer> qAbilityPeer);
218
219// this function should be called from JS thread when WindowStage of UIAbility is destroyed
220void removeMatchingJsQAbilityPeer(QNapi::Object qAbility);
221
222// this function should be called from JS thread when new Want object is received
223void dispatchNewWant(QNapi::Object want, QNapi::Object launchParam);
224
225// invokes the task inside the JS thread, can be called from Qt thread at any time
226void invokeInJsThread(std::function<void(JsState &)> task);
227
228// Invokes the task inside the JS thread and blocks the caller's thread until
229// the "continue" function (std::function<void()>, passed as second argument to
230// the task) is called on the JS side.
231// It can be called from the Qt thread at any time, calling it from the JS
232// thread is illegal.
234 std::function<void(JsState &, QOhosTaskPromise<>)> &&task,
235 std::string callerContextName = {});
236
237// Runs the task inside the JS thread and waits until its execution ends.
238// When called from the JS thread, it calls the task directly. For other threads
239// it behaves like a wrapper around the invokeInJsThreadAndWaitForContinue().
241 const std::function<void(JsState &)> &task,
242 std::string callerContextName = {});
243
244template<typename Func>
245auto evalInJsThread(Func &&func, std::string callerContextName = {}) -> decltype(func(std::declval<JsState &>()));
246
247template<typename T>
248T evalInJsThreadWithConsumer(std::function<void(QtOhos::JsState &, std::function<void(T)>)> evalFunc);
249
250template<typename T>
252 std::function<void(QtOhos::JsState &, QOhosTaskPromise<T>)> evalFunc,
253 std::string callerContextName = {});
254
255// Invokes the task inside the Qt thread and blocks the caller's thread until either:
256// - the "continue" function (std::function<void()>, passed as second argument to
257// the task) is called on the Qt side and returns,
258// - timeout occurs (we don't receive response from the finished task within the
259// specified time limit),
260// - deadlock is detected (both Qt and JS thread use synchronous calls at the same
261// time).
262// It can be called from the JS thread. Calling it from the Qt thread is illegal.
263//
264// Returns true iff the caller receives confirmation about finishing the task within
265// the time limit.
266//
267// Note:
268// If the function returns false then:
269// - either the task wasn't started at all (timeout or deadlock)
270// - or the task was still running (and may be still running!) in the Qt thread
271// after reaching the timeout.
273 std::function<void(std::function<void()>)> &&task,
274 std::chrono::nanoseconds timeout);
275
276template<typename T>
278{
279 auto *objectPtr = reinterpret_cast<T *>(
280 getAttachedObjectWithLazyCreate(typeid(T), &std::make_shared<T>));
281 return *objectPtr;
282}
283
284template<typename T>
286{
287 return getJsSymbolForType(typeid(T));
288}
289
290template<typename Func>
291auto evalInJsThread(Func &&func, std::string callerContextName) -> decltype(func(std::declval<JsState &>()))
292{
293 Q_UNUSED(callerContextName);
294 return QOhosJsThreadGateway::eval(
295 [&func](QOhosJsState &jsState) {
296 return func(static_cast<JsState &>(jsState));
297 });
298}
299
300template<typename T>
301T evalInJsThreadWithConsumer(std::function<void(QtOhos::JsState &, std::function<void(T)>)> evalFunc)
302{
303 return QOhosJsThreadGateway::evalWithConsumer<T>(
304 [evalFunc = std::move(evalFunc)](QOhosJsState &jsState, std::function<void(T)> consumer) {
305 evalFunc(static_cast<JsState &>(jsState), std::move(consumer));
306 });
307}
308
309template<typename T>
311 std::function<void(QtOhos::JsState &, QOhosTaskPromise<T>)> evalFunc,
312 std::string callerContextName)
313{
314 return evalInJsThreadWithConsumer<T>(
315 [evalFunc = std::move(evalFunc), callerContextName](QtOhos::JsState &jsState, std::function<void(T)> consumer) {
316 evalFunc(jsState, QOhosTaskPromise<T>(std::move(consumer), {}, callerContextName));
317 });
318}
319
320}
321
322template<typename T, typename Func>
323std::enable_if_t<
324 qohosplugincore_h_detail::isStdOptional<QOhosInvokeResult<Func, T>>,
325 QOhosInvokeResult<Func, T>>
326qAndThen(const std::optional<T> &opt, Func &&func)
327{
328 return opt.has_value() ? func(*opt) : QOhosInvokeResult<Func, T>();
329}
330
331template<typename T, typename Func>
332std::optional<std::remove_cv_t<QOhosInvokeResult<Func, T>>> qTransform(const std::optional<T> &opt, Func &&func)
333{
334 using TransformedT = std::remove_cv_t<QOhosInvokeResult<Func, T>>;
335 return opt.has_value()
336 ? std::optional<TransformedT>(func(*opt))
337 : std::optional<TransformedT>();
338}
339
340QT_END_NAMESPACE
341
342#endif
QNapi::Object jsObject()
Definition window.cpp:90
JsWindowRef(JsWindowRef &&)=delete
JsWindowRef(std::string owningQAbilityInstanceId, JsWindowId windowId, QNapi::Object jsWindow, QtOhos::QObjectThreadSafeRef owningQWindowRef)
Definition window.cpp:45
bool isFocused() const
Definition window.cpp:68
JsWindowRef(const JsWindowRef &)=delete
QtOhos::QObjectThreadSafeRef owningQWindowRef() const
Definition window.cpp:85
JsWindowRef & operator=(JsWindowRef &&)=delete
Result eval(const std::string &expr, const std::vector< QNapi::ValueWrapper > &exprArgs={}) const
Definition window.h:69
bool isWindowShown() const
Definition window.cpp:55
JsWindowId id() const
Definition window.cpp:80
JsWindowRef & operator=(const JsWindowRef &)=delete
const std::string & owningQAbilityInstanceId() const
Definition window.cpp:75
QNapi::Promise evalToPromiseOrRejectOnThrow(const std::string &expr, const std::vector< QNapi::ValueWrapper > &exprArgs={}) const
Definition window.h:74
virtual void startQAbilityInstance(QNapi::Object baseQAbility, QObjectThreadSafeRef qwindow, QNapi::Object optStartOptions, std::function< void(JsState &, std::shared_ptr< QAbilityPeer >)> startupNotifyFunc)=0
virtual void tagWidgetOrWindowAsFloatWindow(QObject *widgetOrWindow, bool floatWindowEnabled)=0
virtual void startAppProcess(QNapi::Object baseQAbility, const std::string &processId, QNapi::Object want, QNapi::Object optStartOptions, std::function< void(JsState &)> continueFunc)=0
virtual void startNoUiChildProcess(JsState &jsState, const std::string &libraryName, const std::vector< std::string > &args)=0
JsState & jsState() const
JsState & operator=(const JsState &)=delete
virtual QtRunMode qtRunMode()=0
JsState(const JsState &)=delete
virtual std::shared_ptr< QAbilityPeer > tryGetQAbilityPeerByInstanceId(const std::string &instanceId)=0
virtual void * getAttachedObjectWithLazyCreate(const std::type_info &objectTypeInfo, QOhosSupplier< std::shared_ptr< void > > objectFactory)=0
~JsState() override
virtual std::shared_ptr< QAbilityPeer > tryGetQAbilityPeerByQWindow(QObjectThreadSafeRef qwindow)=0
virtual void visitEachQAbilityPeer(const std::function< void(std::shared_ptr< QAbilityPeer >)> &visitor)=0
QNapi::Symbol getJsSymbolForType()
virtual std::shared_ptr< QAbilityPeer > defaultQAbilityPeer()=0
virtual std::shared_ptr< QAbilityPeer > tryGetQAbilityPeerByInstance(QNapi::Object qAbility)=0
virtual void startNewQAbilityInstance(QNapi::Object baseQAbility, QObjectThreadSafeRef qwindow, QNapi::Object optStartOptions, std::function< void(JsState &, std::shared_ptr< QAbilityPeer >)> startupNotifyFunc)=0
std::enable_if_t< std::is_default_constructible< T >::value, T > & getAttachedObjectWithLazyCreate()
virtual QNapi::Symbol getJsSymbolForType(const std::type_info &typeInfo)=0
static void tagWindowAsClosing(QNapi::Object jsWindow, const char *logContext)
static bool isWindowClosing(QNapi::Object jsWindow)
virtual QAbilityInfo readAbilityInfo(const QNapi::Object &ability) const =0
virtual std::string instanceId()=0
virtual QObjectThreadSafeRef qWindowRef()=0
virtual QNapi::Object launchWant()=0
virtual bool isTerminating()=0
virtual void setQWindow(Napi::Env env, QObjectThreadSafeRef qwindow)=0
virtual void * tryCastWithTypeIdObject(const void *matchTypeIdObject)=0
virtual std::shared_ptr< std::atomic_bool > destroyAllowedFlag()=0
virtual std::optional< QNapi::Promise > qWindowDestroyPromise()=0
virtual QNapi::Object qAbility()=0
virtual QNapi::Object uiContext()=0
virtual void forceResolveQWindowDestroyPromiseIfPresent(Napi::Env env)=0
virtual void setOnContinueRequestsHandler(std::function< void(JsState &, QNapi::Object, QOhosConsumer< JsState &, QOhosAbilityOnContinueResult >)> requestsHandler)=0
virtual QNapi::Object launchParam()=0
virtual QNapi::Object windowStage()=0
void * tryCastWithTypeIdObject(const void *matchTypeIdObject) final
static std::shared_ptr< QUiAbilityPeer > tryCastFromQAbilityPeerOrNull(std::shared_ptr< QAbilityPeer > qAbilityPeer)
~QUiAbilityPeer() override
virtual QNapi::Object window()=0
std::optional< WindowProperties > tryGetWindowProperties(JsWindowId jsWindowId)
Definition window.cpp:27
Combined button and popup list for selecting options.
void invokeInJsThread(std::function< void(JsState &)> task)
void dispatchNewWant(QNapi::Object want, QNapi::Object launchParam)
void removeMatchingJsQAbilityPeer(QNapi::Object qAbility)
T evalInJsThreadWithPromise(std::function< void(QtOhos::JsState &, QOhosTaskPromise< T >)> evalFunc, std::string callerContextName={})
T evalInJsThreadWithConsumer(std::function< void(QtOhos::JsState &, std::function< void(T)>)> evalFunc)
void runInJsThreadAndWait(const std::function< void(JsState &)> &task, std::string callerContextName={})
void initJsThreadState(napi_env env, std::map< std::string, QNapi::Reference< QNapi::Function > > &&jsModulesFactories, std::shared_ptr< AppFunctions > appFunctions, QtRunMode qtRunMode)
Q_REQUIRED_RESULT bool tryInvokeInQtThreadAndTryWaitForContinue(std::function< void(std::function< void()>)> &&task, std::chrono::nanoseconds timeout)
void invokeInJsThreadAndWaitForContinue(std::function< void(JsState &, QOhosTaskPromise<>)> &&task, std::string callerContextName={})
auto evalInJsThread(Func &&func, std::string callerContextName={}) -> decltype(func(std::declval< JsState & >()))
void addJsQAbilityPeer(std::shared_ptr< QAbilityPeer > qAbilityPeer)
constexpr bool hasEqualityComparator
std::optional< std::remove_cv_t< QOhosInvokeResult< Func, T > > > qTransform(const std::optional< T > &opt, Func &&func)
QT_END_NAMESPACE Q_DECLARE_METATYPE(QT_PREPEND_NAMESPACE(QtOhos::QOhosQpaFunctions::AudioStreamUsage))
std::optional< QOhosDisplayInfo::JsDisplayId > displayId
Definition window.h:29
bool isDisplayMainOrExtended() const
std::optional< DisplaySourceMode > sourceMode
QSizeF physicalSize() const
QRect displayGeometryPixels() const
std::optional< QPoint > topLeftOffsetPixels
static QOhosDisplayInfo makeFromOhosDisplayObject(QtOhos::JsState &jsState, QNapi::Object displayObject)
std::optional< JsDisplayOrientation > orientation
static std::optional< QNapi::Object > tryGetDisplayById(QtOhos::JsState &jsState, QOhosDisplayInfo::JsDisplayId displayId)
bool shouldIgnoreDisplay() const