4#include <render/qohoswindowproxydatafactory.h>
6#include <QtCore/qscopeguard.h>
8#include <qarkui/qxcomponentregistry.h>
10#include <render/qohoswindowproxy.h>
11#include <render/qxcomponent.h>
19 static std::uint64_t uniqueIdSuffixCounter = 0;
20 auto result = QStringLiteral(
"QtWindow_%1_%2")
21 .arg(internalWindowId.toString())
22 .arg(QString::number(uniqueIdSuffixCounter));
23 ++uniqueIdSuffixCounter;
24 return result.toStdString();
65 qOhosReportFatalErrorAndAbort(
66 "Failed to find QAbilityPeer for qAbilityInstanceId: %s", qAbilityInstanceId.c_str());
75 if (!nativeNodeXComponentOpt.hasValue()) {
76 qOhosReportFatalErrorAndAbort(
77 "Failed to fetch native node xcomponent with id: %s",
80 return nativeNodeXComponentOpt.value();
85 return jsState.eval<QNapi::Object>(
"LocalStorage.makeNewLocalStorage()");
89 QNapi::Object windowStageOrWindowObject,
92 auto subWindowOptionsObject =
94 windowStageOrWindowObject.Env(),
96 {
"title", subWindowOptions.windowTitle},
97 {
"decorEnabled", subWindowOptions.decorEnabled},
98 {
"isModal", subWindowOptions.isModal},
101 return windowStageOrWindowObject.call<QNapi::Promise>(
102 "createSubWindowWithOptions",
103 {windowName, subWindowOptionsObject});
109 auto sharedContext = QtOhos::moveToSharedPtr(std::move(subWindowOnAppearCbCtx));
114 auto xComponent = takeNodeXComponentFromRegistryOrFail(sharedContext->xComponentId);
116 sharedContext->resultConsumer(
118 QOhosWindowProxyData {
119 .qAbilityPeer = sharedContext->qAbilityPeer,
120 .jsWindow = std::move(sharedContext->windowObject),
121 .windowProxyType = sharedContext->windowProxyType,
122 .nodeXComponent = std::make_shared<QXComponentNode>(xComponent),
123 .jsKeepAliveData = QtOhos::moveToSharedPtr(std::move(sharedContext->localStorageObj)),
126 sharedContext.reset();
132 return window.call<QNapi::Promise>(
"loadContent", {contentPagePath, localStorage});
138 auto *env = jsState.env();
140 auto localStorage = makeLocalStorage(jsState);
141 auto subWindowNativeNodeCreateInfo = QNapi::makeObject(
144 {
"xComponentId", createInfo.xComponentId.toNapiValue(env)},
147 [xComponentId = createInfo.xComponentId.stringId()]() {
149 "WindowNativeNodeCreateInfo.onDisAppear() called from JS for xComponentId='%s'",
150 xComponentId.c_str());
155 makeSubWindowOnAppearCallbackHandler(SubWindowOnAppearContext {
156 .xComponentId = createInfo.xComponentId,
157 .localStorageObj = Napi::Persistent(localStorage),
158 .windowObject = Napi::Persistent(createInfo.windowObject),
159 .resultConsumer = std::move(createInfo.resultConsumer),
160 .qAbilityPeer = std::move(createInfo.qAbilityPeer),
161 .windowProxyType = createInfo.windowProxyType,
166 localStorage.call(
"setOrCreate", {
"createInfo", subWindowNativeNodeCreateInfo});
174 struct LoadWindowContentsArgs
176 QNapi::Reference<QNapi::Object> window;
177 QNapi::Reference<QNapi::Object> localStorage;
178 std::string contentPagePath;
181 return !context.disableWindowFocusableBeforeLoadContentHack
182 ? loadWindowContents(windowObject, context.localStorage, context.contentPagePath)
183 : windowObject.call<QNapi::Promise>(
"setWindowFocusable", {
false})
184 .withContext(LoadWindowContentsArgs {
185 .window = Napi::Persistent(windowObject),
186 .localStorage = Napi::Persistent(context.localStorage),
187 .contentPagePath = context.contentPagePath,
189 .onThenWithContext([](LoadWindowContentsArgs &windowLocalStoragePair) {
190 return loadWindowContents(
191 windowLocalStoragePair.window.Value(),
192 windowLocalStoragePair.localStorage.Value(),
193 windowLocalStoragePair.contentPagePath);
202 QOhosConsumer<QtOhos::JsState &, QOhosWindowProxyData> resultConsumer)
204 auto abilityStartupOptions =
208 {
"windowLeft", createInfo.frameGeometry.x()},
209 {
"windowTop", createInfo.frameGeometry.y()},
210 {
"windowWidth", createInfo.frameGeometry.width()},
211 {
"windowHeight", createInfo.frameGeometry.height()},
215 auto fullscreenWindowMode = jsState.eval<QNapi::Number>(
216 "@ohos.app.ability.AbilityConstant.WindowMode.WINDOW_MODE_FULLSCREEN");
217 abilityStartupOptions.set(
"windowMode", fullscreenWindowMode);
220 if (createInfo.displayId.hasValue())
221 abilityStartupOptions.set(
"displayId", createInfo.displayId.value().value());
223 jsState.startNewQAbilityInstance(
225 abilityStartupOptions,
226 [qWindowRef = createInfo.qWindowRef,
227 windowId = createInfo.windowId,
229 auto createInfo = QOhosWindowProxyExistingMainWindowCreateInfo {
230 .qWindowRef = qWindowRef,
231 .qAbilityInstanceId = qAbilityPeer->instanceId(),
232 .windowId = windowId,
235 makeWindowProxyDataForExistingMainWindowInJsThread(
236 jsState, createInfo,
std::move(resultConsumer));
243 QOhosConsumer<QtOhos::JsState &, QOhosWindowProxyData> resultConsumer)
246 getQAbilityPeerByInstanceIdOrFail(jsState, createInfo.qAbilityInstanceId));
247 if (!optQUiAbilityPeer) {
248 qOhosReportFatalErrorAndAbort(
249 "%s Attempting to make window proxy for main window for ability without windowStage. This is most likely a programming error. Aborting...",
252 optQUiAbilityPeer->setQWindow(jsState.env(), createInfo.qWindowRef);
254 auto window = optQUiAbilityPeer->windowStage().call<QNapi::Object>(
"getMainWindowSync");
256 auto nodeXComponent = takeNodeXComponentFromRegistryOrFail(nativeNodeXComponentId);
260 QOhosWindowProxyData {
261 .qAbilityPeer = optQUiAbilityPeer,
262 .jsWindow = Napi::Persistent(window),
263 .windowProxyType = WindowProxyType::MainWindow,
264 .nodeXComponent = std::make_shared<QXComponentNode>(nodeXComponent),
265 .jsKeepAliveData =
nullptr,
272 QOhosConsumer<QtOhos::JsState &, QOhosWindowProxyData> resultConsumer)
274 auto qAbilityPeer = getQAbilityPeerByInstanceIdOrFail(jsState, createInfo.qAbilityInstanceId);
276 if (!optQUiAbilityPeer) {
277 qOhosReportFatalErrorAndAbort(
278 "%s Attempting to make window proxy for sub window for ability without windowStage. This is most likely a programming error. Aborting...",
281 makeWindowProxyDataForSubWindowInJsThread(
282 jsState, optQUiAbilityPeer->windowStage(), createInfo,
std::move(resultConsumer));
287 QNapi::Object windowStageOrWindowObject,
289 QOhosConsumer<QtOhos::JsState &, QOhosWindowProxyData> resultConsumer)
291 auto xComponentId = QXComponentId::createForNativeNodeSubWindow(createInfo.windowId);
294 bool disableWindowFocusableBeforeLoadContentHack;
299 auto qAbilityPeer = getQAbilityPeerByInstanceIdOrFail(jsState, createInfo.qAbilityInstanceId);
301 createSubWindowWithOptions(
302 windowStageOrWindowObject,
309 .withContext(Context {
311 .xComponentId = xComponentId,
312 .qAbilityPeer = qAbilityPeer,
314 .onThenWithContext([resultConsumer = std::move(resultConsumer)](
const QtOhos::
CallbackInfo &cbInfo, Context &context)
mutable {
315 auto windowObject = cbInfo.getFirstArg<QNapi::Object>(Q_FUNC_INFO);
317 auto localStorage = makeLocalStorageForWindow(
319 LocalStorageForWindowCreateInfo {
320 .xComponentId = context.xComponentId,
321 .windowObject = windowObject,
322 .resultConsumer = std::move(resultConsumer),
323 .qAbilityPeer = context.qAbilityPeer,
324 .windowProxyType = WindowProxyType::SubWindow,
327 return onWindowCreatedLoadWindowContents(
328 cbInfo.jsState(), windowObject,
329 OnWindowCreatedLoadWindowContentsContext {
330 .disableWindowFocusableBeforeLoadContentHack = context.disableWindowFocusableBeforeLoadContentHack,
331 .contentPagePath =
"pages/SubWindowNativeNode",
332 .localStorage = localStorage,
336 QtOhos::logJsCallbackError(cbInfo,
"createSubWindowWithOptions() failed");
337 qOhosReportFatalErrorAndAbort(
338 "Failed to create subwindow for windowId='%s'",
339 windowId.toStdString().c_str());
345 QOhosConsumer<QtOhos::JsState &, QOhosWindowProxyData> resultConsumer)
347 auto xComponentId = QXComponentId::createForNativeNodeFloatWindow(createInfo.internalWindowId);
350 auto configurationObject = QNapi::makeObject(
354 {
"name", makeOhosUniqueSystemWindowName(createInfo.internalWindowId)},
355 {
"windowType", jsState.eval<QNapi::Number>(
"@ohos.window.WindowType.TYPE_FLOAT")},
356 {
"ctx", qAbilityPeer->qAbility().get<QNapi::Object>(
"context")},
359 if (createInfo.displayId.hasValue())
360 configurationObject.set(
"displayId", createInfo.displayId.value().value());
369 .eval<QNapi::Promise>(
"@ohos.window.createWindow(*)", {configurationObject})
370 .withContext(Context {
371 .xComponentId = xComponentId,
372 .qAbilityPeer = qAbilityPeer,
374 .onThenWithContext([resultConsumer = std::move(resultConsumer)](
const QtOhos::CallbackInfo &cbInfo, Context &context)
mutable {
375 auto windowObject = cbInfo.getFirstArg<QNapi::Object>(Q_FUNC_INFO);
377 auto localStorage = makeLocalStorageForWindow(
379 LocalStorageForWindowCreateInfo {
380 .xComponentId = context.xComponentId,
381 .windowObject = windowObject,
382 .resultConsumer = std::move(resultConsumer),
383 .qAbilityPeer = context.qAbilityPeer,
384 .windowProxyType = WindowProxyType::FloatWindow,
387 return onWindowCreatedLoadWindowContents(
388 cbInfo.jsState(), windowObject,
389 OnWindowCreatedLoadWindowContentsContext {
390 .disableWindowFocusableBeforeLoadContentHack =
false,
391 .contentPagePath =
"pages/FloatWindowNativeNode",
392 .localStorage = localStorage,
395 .onCatch([internalWindowId = createInfo.internalWindowId](
const QtOhos::CallbackInfo &cbInfo) {
396 QtOhos::logJsCallbackError(cbInfo,
"Failed to create TYPE_FLOAT window");
397 qOhosReportFatalErrorAndAbort(
398 "Failed to create TYPE_FLOAT window for windowId='%s'",
399 internalWindowId.toStdString().c_str());
static QXComponentRegistry & instance()
QOhosOptional< QXComponentNode > tryTakeNodeByXComponentId(const QXComponentId &id)
static QXComponentId createForNativeNodeMainWindow(const std::string &qAbilityInstanceId)
std::string stringId() const
JsState & jsState() const
virtual std::shared_ptr< QAbilityPeer > tryGetQAbilityPeerByInstanceId(const std::string &instanceId)=0
virtual std::shared_ptr< QAbilityPeer > defaultQAbilityPeer()=0
static std::shared_ptr< QUiAbilityPeer > tryCastFromQAbilityPeerOrNull(std::shared_ptr< QAbilityPeer > qAbilityPeer)
std::shared_ptr< QtOhos::QAbilityPeer > getQAbilityPeerByInstanceIdOrFail(QtOhos::JsState &jsState, const std::string &qAbilityInstanceId)
QNapi::Promise createSubWindowWithOptions(QNapi::Object windowStageOrWindowObject, const std::string &windowName, const SubWindowOptions &subWindowOptions)
QXComponentNode takeNodeXComponentFromRegistryOrFail(const QXComponentId &xComponentId)
std::function< void(const QtOhos::CallbackInfo &)> makeSubWindowOnAppearCallbackHandler(SubWindowOnAppearContext subWindowOnAppearCbCtx)
QNapi::Object makeLocalStorage(QtOhos::JsState &jsState)
QNapi::Promise onWindowCreatedLoadWindowContents(QtOhos::JsState &, const QNapi::Object &windowObject, OnWindowCreatedLoadWindowContentsContext context)
QNapi::Promise loadWindowContents(QNapi::Object window, QNapi::Object localStorage, const std::string &contentPagePath)
std::string makeOhosUniqueSystemWindowName(QtOhos::InternalWindowId internalWindowId)
QNapi::Object makeLocalStorageForWindow(QtOhos::JsState &jsState, LocalStorageForWindowCreateInfo &&createInfo)
void makeWindowProxyDataForFloatWindowInJsThread(QtOhos::JsState &jsState, const QOhosWindowProxyFloatWindowCreateInfo &createInfo, QOhosConsumer< QtOhos::JsState &, QOhosWindowProxyData > resultConsumer)
void makeWindowProxyDataForSubWindowInJsThread(QtOhos::JsState &jsState, QNapi::Object windowStageOrWindowObject, const QOhosWindowProxySubWindowCreateInfo &createInfo, QOhosConsumer< QtOhos::JsState &, QOhosWindowProxyData > resultConsumer)
void makeWindowProxyDataForSubWindowInJsThread(QtOhos::JsState &jsState, const QOhosWindowProxySubWindowCreateInfo &createInfo, QOhosConsumer< QtOhos::JsState &, QOhosWindowProxyData > resultConsumer)
void makeWindowProxyDataForExistingMainWindowInJsThread(QtOhos::JsState &jsState, const QOhosWindowProxyExistingMainWindowCreateInfo &createInfo, QOhosConsumer< QtOhos::JsState &, QOhosWindowProxyData > resultConsumer)
void makeWindowProxyDataForMainWindowInJsThread(QtOhos::JsState &jsState, const QOhosWindowProxyMainWindowCreateInfo &createInfo, QOhosConsumer< QtOhos::JsState &, QOhosWindowProxyData > resultConsumer)
QXComponent< QXComponentType::Node > QXComponentNode
bool disableWindowFocusableBeforeLoadContentHack
std::shared_ptr< QtOhos::QAbilityPeer > qAbilityPeer
QOhosConsumer< QtOhos::JsState &, QOhosWindowProxyData > resultConsumer
QNapi::Object windowObject
QXComponentId xComponentId
WindowProxyType windowProxyType
bool disableWindowFocusableBeforeLoadContentHack
std::string contentPagePath
QNapi::Object localStorage
QNapi::Reference< QNapi::Object > windowObject
QOhosConsumer< QtOhos::JsState &, QOhosWindowProxyData > resultConsumer
std::shared_ptr< QtOhos::QAbilityPeer > qAbilityPeer
WindowProxyType windowProxyType
QXComponentId xComponentId
QNapi::Reference< QNapi::Object > localStorageObj