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
qohosqpafunctionsimpl.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 <QtCore/private/qnapi_p.h>
5#include <QtCore/private/qohoscommon_p.h>
6#include <qohosjsenv_p.h>
7#include <QtCore/qobject.h>
8#include <QtCore/qscopeguard.h>
9#include <QtGui/private/qguiapplication_p.h>
10#include <QtGui/qcolor.h>
11#include <QtGui/qimage.h>
12#include <QtGui/qscreen.h>
13#include <QtGui/qwindow.h>
14#include <algorithm>
15#include <chrono>
16#include <filemanagement/file_uri/oh_file_uri.h>
17#include <filemanagement/fileshare/oh_file_share.h>
18#include <functional>
19#include <info/application_target_sdk_version.h>
20#include <memory>
21#include <qohosapppermissions_p.h>
22#include <qohosdeviceinfo_p.h>
23#include <qohosenums.h>
24#include <qohosjsmain.h>
25#include <qohosjsutils.h>
26#include <qohospixelmapconversions.h>
27#include <qohosplatformclipboard.h>
28#include <qohosplatformintegration.h>
29#include <qohosplatformservices.h>
30#include <qohosplatformwindow.h>
31#include <qohosplugincore.h>
32#include <qohosqpafunctions_p.h>
33#include <qohossettings.h>
34#include <qohossharekit.h>
35#include <qohosudmfconversions.h>
36#include <qohosutils.h>
37#include <qohoswindowmanager.h>
38#include <render/qwindowproxyregistry.h>
39#include <signal.h>
40#include <thread>
41#include <unistd.h>
42#include <vector>
43
44using namespace std::chrono_literals;
45
46QT_BEGIN_NAMESPACE
47
48namespace QtOhos {
49
50namespace {
51
52QOhosOptional<QOhosQpaFunctions::WantInfo::LaunchReason> tryMapOhosLaunchReasonToWantInfoEnum(
53 enums::ohos::app::ability::AbilityConstant::LaunchReason ohosLaunchReason)
54{
55 using OhosLaunchReason = enums::ohos::app::ability::AbilityConstant::LaunchReason;
56 using WantInfo = QOhosQpaFunctions::WantInfo;
57
58 switch (ohosLaunchReason) {
59 case OhosLaunchReason::START_ABILITY:
60 return makeQOhosOptional(WantInfo::LaunchReason::START_ABILITY);
61 case OhosLaunchReason::CONTINUATION:
62 return makeQOhosOptional(WantInfo::LaunchReason::CONTINUATION);
63 case OhosLaunchReason::PREPARE_CONTINUATION:
64 return makeQOhosOptional(WantInfo::LaunchReason::PREPARE_CONTINUATION);
65 case OhosLaunchReason::PRELOAD:
66 return makeQOhosOptional(WantInfo::LaunchReason::PRELOAD);
67 case OhosLaunchReason::UNKNOWN:
68 case OhosLaunchReason::CALL:
69 case OhosLaunchReason::APP_RECOVERY:
70 case OhosLaunchReason::SHARE:
71 case OhosLaunchReason::AUTO_STARTUP:
72 case OhosLaunchReason::INSIGHT_INTENT:
73 return makeQOhosOptional(WantInfo::LaunchReason::UNKNOWN);
74 }
75
76 return {};
77}
78
79QOhosQpaFunctions::WantInfo::LaunchReason mapJsLaunchReasonToWantInfoEnumWithFallback(
80 QtOhos::JsState &jsState, QNapi::Number jsLaunchReason)
81{
82 auto optLaunchReasonJsEnum =
83 jsState.tryMapOhosEnumFromJs<enums::ohos::app::ability::AbilityConstant::LaunchReason>(jsLaunchReason);
84 auto optLaunchReason =
85 optLaunchReasonJsEnum.has_value()
86 ? tryMapOhosLaunchReasonToWantInfoEnum(optLaunchReasonJsEnum.value())
87 : makeEmptyQOhosOptional();
88 return optLaunchReason.valueOr(QOhosQpaFunctions::WantInfo::LaunchReason::UNKNOWN);
89}
90
91Q_NORETURN void killCurrentProcess()
92{
93 ::kill(getpid(), SIGKILL);
94 std::abort();
95}
96
97QOhosOptional<QOhosAbilityOnContinueResult> tryMapAbilityOnContinueResponseStatusToOhos(
99{
100 using AbilityOnContinueResponseStatus = QOhosQpaFunctions::AbilityOnContinueResponseStatus;
101
102 switch (status) {
103 case AbilityOnContinueResponseStatus::Agree:
104 return makeQOhosOptional(QOhosAbilityOnContinueResult::AGREE);
105 case AbilityOnContinueResponseStatus::Reject:
106 return makeQOhosOptional(QOhosAbilityOnContinueResult::REJECT);
107 case AbilityOnContinueResponseStatus::Mismatch:
108 return makeQOhosOptional(QOhosAbilityOnContinueResult::MISMATCH);
109 }
110 return {};
111}
112
113QOhosOptional<enums::ohos::app::ability::AbilityConstant::WindowMode> tryMapWindowModeToOhosOrLogWarning(
115{
116 namespace AbilityConstant = enums::ohos::app::ability::AbilityConstant;
117 using StartOptions = QOhosQpaFunctions::StartOptions;
118
119 switch (windowMode) {
121 return makeQOhosOptional(AbilityConstant::WindowMode::WINDOW_MODE_SPLIT_PRIMARY);
123 return makeQOhosOptional(AbilityConstant::WindowMode::WINDOW_MODE_SPLIT_SECONDARY);
125 return makeQOhosOptional(AbilityConstant::WindowMode::WINDOW_MODE_FULLSCREEN);
126 }
127
128 qCWarning(QtForOhos, "%s: got illegal WindowMode: %d", Q_FUNC_INFO, static_cast<int>(windowMode));
129
130 return {};
131}
132
133QOhosOptional<enums::ohos::app::ability::contextConstant::ProcessMode> tryMapProcessModeToOhosOrLogWarning(
135{
136 namespace contextConstant = enums::ohos::app::ability::contextConstant;
137 using StartOptions = QOhosQpaFunctions::StartOptions;
138
139 switch (processMode) {
141 return makeQOhosOptional(contextConstant::ProcessMode::NEW_PROCESS_ATTACH_TO_PARENT);
143 return makeQOhosOptional(contextConstant::ProcessMode::NEW_PROCESS_ATTACH_TO_STATUS_BAR_ITEM);
144 }
145
146 qCWarning(QtForOhos, "%s: got illegal ProcessMode: %d", Q_FUNC_INFO, static_cast<int>(processMode));
147
148 return {};
149}
150
151QOhosOptional<enums::ohos::app::ability::contextConstant::StartupVisibility> tryMapStartupVisibilityToOhosOrLogWarning(
153{
154 namespace contextConstant = enums::ohos::app::ability::contextConstant;
155 using StartOptions = QOhosQpaFunctions::StartOptions;
156
157 switch (startupVisibility) {
158 case StartOptions::StartupVisibility::STARTUP_HIDE:
159 return makeQOhosOptional(contextConstant::StartupVisibility::STARTUP_HIDE);
160 case StartOptions::StartupVisibility::STARTUP_SHOW:
161 return makeQOhosOptional(contextConstant::StartupVisibility::STARTUP_SHOW);
162 }
163
164 qCWarning(QtForOhos, "%s: got illegal StartupVisibility: %d", Q_FUNC_INFO, static_cast<int>(startupVisibility));
165
166 return {};
167}
168
169QOhosOptional<enums::ohos::bundle::bundleManager::SupportWindowMode> tryMapSupportWindowModeToOhosOrLogWarning(
171{
172 namespace bundleManager = enums::ohos::bundle::bundleManager;
173 using StartOptions = QOhosQpaFunctions::StartOptions;
174
175 switch (supportWindowMode) {
176 case StartOptions::SupportWindowMode::FULL_SCREEN:
177 return makeQOhosOptional(bundleManager::SupportWindowMode::FULL_SCREEN);
178 case StartOptions::SupportWindowMode::SPLIT:
179 return makeQOhosOptional(bundleManager::SupportWindowMode::SPLIT);
180 case StartOptions::SupportWindowMode::FLOATING:
181 return makeQOhosOptional(bundleManager::SupportWindowMode::FLOATING);
182 }
183
184 qCWarning(QtForOhos, "%s: got illegal SupportWindowMode: %d", Q_FUNC_INFO, static_cast<int>(supportWindowMode));
185
186 return {};
187}
188
189QNapi::Array mapSupportWindowModesToJsEnumsArray(
190 QtOhos::JsState &jsState, const QList<QOhosQpaFunctions::StartOptions::SupportWindowMode> &supportWindowModes)
191{
192 std::vector<QNapi::ValueWrapper> jsSupportWindowModes;
193 for (auto supportWindowMode : supportWindowModes) {
194 auto optOhosSupportWindowMode = tryMapSupportWindowModeToOhosOrLogWarning(supportWindowMode);
195 if (optOhosSupportWindowMode.hasValue())
196 jsSupportWindowModes.push_back(jsState.mapOhosEnumToJs(optOhosSupportWindowMode.value()));
197 }
198
199 return QNapi::makeArray(jsState.env(), jsSupportWindowModes);
200}
201
202QNapi::Object makeJsCompletionHandler(
203 QtOhos::JsState &jsState, std::shared_ptr<QOhosConsumer<bool, QJsonObject, QString>> qtThreadCompletionHandler)
204{
205 auto makeCompletionCallback = [qtThreadCompletionHandler](bool requestSuccess) {
206 return [qtThreadCompletionHandler, requestSuccess](const QNapi::CallbackInfo &cbInfo) {
207 QNapi::Object elementNameObj;
208 QNapi::String messageValue;
209 cbInfo.getLeadingArgs(Q_FUNC_INFO, elementNameObj, messageValue);
210
211 const QJsonObject elementName = QOhosJsEnv::fromNapiValue<QJsonObject>(elementNameObj);
212 const QString message = QString::fromStdString(messageValue);
213
214 QtOhos::invokeInQtThread(
215 [qtThreadCompletionHandler, requestSuccess, elementName, message]() {
216 (*qtThreadCompletionHandler)(requestSuccess, elementName, message);
217 });
218 };
219 };
220
221 return QNapi::makeObject(
222 jsState.env(),
223 {
224 {"onRequestSuccess", makeCompletionCallback(true)},
225 {"onRequestFailure", makeCompletionCallback(false)},
226 });
227}
228
229using OhosConfigurationColorMode = QtOhos::enums::ohos::app::ability::ConfigurationConstant::ColorMode;
230
231QNapi::Object convertStartOptionsToNapiObject(
232 QtOhos::JsState &jsState, const QOhosQpaFunctions::StartOptions &opts)
233{
234 auto *env = jsState.env();
235 auto napiOptions = QNapi::Object::New(env);
236
237 auto optOhosWindowMode = opts.windowMode.andThen(&tryMapWindowModeToOhosOrLogWarning);
238 if (optOhosWindowMode.hasValue())
239 napiOptions.set("windowMode", jsState.mapOhosEnumToJs(optOhosWindowMode.value()));
240 if (opts.displayId.hasValue())
241 napiOptions.set("displayId", opts.displayId.value());
242 if (opts.withAnimation.hasValue())
243 napiOptions.set("withAnimation", opts.withAnimation.value());
244 if (opts.windowLeft.hasValue())
245 napiOptions.set("windowLeft", opts.windowLeft.value());
246 if (opts.windowTop.hasValue())
247 napiOptions.set("windowTop", opts.windowTop.value());
248 if (opts.windowWidth.hasValue())
249 napiOptions.set("windowWidth", opts.windowWidth.value());
250 if (opts.windowHeight.hasValue())
251 napiOptions.set("windowHeight", opts.windowHeight.value());
252 auto optOhosProcessMode = opts.processMode.andThen(&tryMapProcessModeToOhosOrLogWarning);
253 if (optOhosProcessMode.hasValue())
254 napiOptions.set("processMode", jsState.mapOhosEnumToJs(optOhosProcessMode.value()));
255 auto optOhosStartupVisibility = opts.startupVisibility.andThen(&tryMapStartupVisibilityToOhosOrLogWarning);
256 if (optOhosStartupVisibility.hasValue())
257 napiOptions.set("startupVisibility", jsState.mapOhosEnumToJs(optOhosStartupVisibility.value()));
258 if (opts.windowFocused.hasValue())
259 napiOptions.set("windowFocused", opts.windowFocused.value());
260 if (opts.windowIcon.hasValue()) {
261 auto windowIcon = opts.windowIcon.value().value<QImage>();
262 if (!windowIcon.isNull())
263 napiOptions.set("startWindowIcon", createNapiPixelMapFromQImage(jsState, windowIcon));
264 }
265 if (opts.windowBackgroundColorHex.hasValue())
266 napiOptions.set("startWindowBackgroundColor", opts.windowBackgroundColorHex.value().toStdString());
267 if (opts.supportWindowModes.hasValue()) {
268 auto jsSupportWindowModes = mapSupportWindowModesToJsEnumsArray(jsState, opts.supportWindowModes.value());
269 if (jsSupportWindowModes.Length() != 0)
270 napiOptions.set("supportWindowModes", jsSupportWindowModes);
271 else
272 qCWarning(QtForOhos, "%s: OHOS doesn't support empty supportWindowModes, skipping", Q_FUNC_INFO);
273 }
274 if (opts.minWindowWidth.hasValue())
275 napiOptions.set("minWindowWidth", opts.minWindowWidth.value());
276 if (opts.minWindowHeight.hasValue())
277 napiOptions.set("minWindowHeight", opts.minWindowHeight.value());
278 if (opts.maxWindowWidth.hasValue())
279 napiOptions.set("maxWindowWidth", opts.maxWindowWidth.value());
280 if (opts.maxWindowHeight.hasValue())
281 napiOptions.set("maxWindowHeight", opts.maxWindowHeight.value());
282 if (opts.optCompletionHandler) {
283 constexpr auto minSupportedSdkVersion = 20;
284 const auto ohosSdkVersion = QOhosDeviceInfo::sdkApiVersion();
285 if (ohosSdkVersion >= minSupportedSdkVersion) {
286 napiOptions.set("completionHandler", makeJsCompletionHandler(jsState, opts.optCompletionHandler));
287 } else {
288 qCWarning(
289 QtForOhos,
290 "%s: completionHandler ignored because sdkApi %d < required %d",
291 Q_FUNC_INFO, ohosSdkVersion, minSupportedSdkVersion);
292 }
293 }
294 if (opts.hideStartWindow.hasValue()) {
295 constexpr auto minSupportedSdkVersion = 20;
296 const auto ohosSdkVersion = QOhosDeviceInfo::sdkApiVersion();
297 if (ohosSdkVersion >= minSupportedSdkVersion) {
298 napiOptions.set("hideStartWindow", opts.hideStartWindow.value());
299 } else {
300 qCWarning(
301 QtForOhos,
302 "%s: hideStartWindow ignored because sdkApi %d < required %d",
303 Q_FUNC_INFO, ohosSdkVersion, minSupportedSdkVersion);
304 }
305 }
306 if (opts.windowCreateParams.hasValue()) {
307 constexpr auto minSupportedSdkVersion = 20;
308 const auto ohosSdkVersion = QOhosDeviceInfo::sdkApiVersion();
309 if (ohosSdkVersion >= minSupportedSdkVersion) {
310 const auto &windowCreateParams = opts.windowCreateParams.value();
311 std::vector<std::pair<std::string, QNapi::ValueWrapper>> windowCreateParamsProps;
312 if (windowCreateParams.setWindowFadeInOutAnimation) {
313 windowCreateParamsProps.emplace_back(
314 "animationParams",
315 QNapi::makeObject(
316 env,
317 {
318 {
319 "type",
320 jsState.mapOhosEnumToJs(
321 enums::ohos::window::WindowCreateParams::AnimationType::FADE_IN_OUT),
322 }
323 }));
324 }
325 napiOptions.set("windowCreateParams", QNapi::makeObject(env, windowCreateParamsProps));
326 } else {
327 qCWarning(
328 QtForOhos,
329 "%s: windowCreateParams ignored because sdkApi %d < required %d",
330 Q_FUNC_INFO, ohosSdkVersion, minSupportedSdkVersion);
331 }
332 }
333
334 return napiOptions;
335}
336
337std::shared_ptr<void> registerAppContextEnvironmentCallback(
338 QtOhos::JsState &jsState, QNapi::Object environmentCallback)
339{
340 auto appContextRefPtr = QtOhos::moveToSharedPtr(
341 QNapi::Reference<>::makePersistentFrom(
342 jsState.defaultQAbilityPeer()->qAbility().eval<QNapi::Object>(
343 "context.getApplicationContext()")));
344
345 double environmentCallbackId = appContextRefPtr->call<QNapi::Number>(
346 "on",
347 {"environment", environmentCallback});
348
349 return std::shared_ptr<void>(
350 nullptr,
351 [environmentCallbackId, appContextRefPtr](auto) {
353 [&](QtOhos::JsState &) {
354 auto appContextRef = std::move(*appContextRefPtr);
355 appContextRef.call(
356 "off",
357 {"environment", environmentCallbackId});
358 });
359 });
360}
361
362std::shared_ptr<void> registerAppConfigurationUpdateListener(
363 QtOhos::JsState &jsState, std::function<void(QtOhos::JsState &, QNapi::Object)> updateListener)
364{
365 return registerAppContextEnvironmentCallback(
366 jsState,
367 QNapi::makeObject(
368 jsState.env(),
369 {
370 {
371 "onConfigurationUpdated",
372 [updateListener = std::move(updateListener)](const QtOhos::CallbackInfo &cbInfo) {
373 auto config = cbInfo.getFirstArg<QNapi::Object>(Q_FUNC_INFO);
374 updateListener(cbInfo.jsState(), config);
375 }
376 },
377 }));
378}
379
380OhosConfigurationColorMode mapOhosConfigurationColorModeFromJs(QtOhos::JsState &jsState, QNapi::Number colorModeJsEnum)
381{
382 constexpr auto fallbackColorMode = OhosConfigurationColorMode::COLOR_MODE_NOT_SET;
383 auto optColorMode = jsState.tryMapOhosEnumFromJs<OhosConfigurationColorMode>(colorModeJsEnum);
384 return optColorMode.value_or(fallbackColorMode);
385};
386
387void setOhosConfigColorMode(OhosConfigurationColorMode colorMode)
388{
390 qCWarning(QtForOhos, "%s: cannot set a color mode in 'no UI child mode'", Q_FUNC_INFO);
391 return;
392 }
393
395 [&](QtOhos::JsState &jsState) {
396 auto qAbility = jsState.defaultQAbilityPeer()->qAbility();
397 const auto jsColorMode = jsState.mapOhosEnumToJs(colorMode);
398 qAbility.call("context.getApplicationContext().setColorMode", {jsColorMode});
399 });
400}
401
402template<typename ConfigValue>
403QOhosSupplier<ConfigValue> makeOhosConfigValueDataSource(
404 std::function<ConfigValue(QtOhos::JsState &)> initValueSupplier,
405 std::function<ConfigValue(QtOhos::JsState &, const QNapi::Object &)> valueFetcher,
406 QOhosConsumer<ConfigValue> valueChangedHandler)
407{
408 struct Context {
409 QOhosConsumer<ConfigValue> valueChangedHandler;
410 ConfigValue receivedValue;
411 std::shared_ptr<void> updateListenerHandle;
412 };
413
414 auto context = QtOhos::evalInJsThread(
415 [&](QtOhos::JsState &jsState) {
416 auto context = std::make_shared<Context>();
417 context->valueChangedHandler = std::move(valueChangedHandler);
418 context->receivedValue = initValueSupplier(jsState);
419 context->updateListenerHandle = registerAppConfigurationUpdateListener(
420 jsState,
421 [weakContext = QtOhos::makeWeakPtr(context), valueFetcher = std::move(valueFetcher)](QtOhos::JsState &jsState, QNapi::Object config) {
422 auto configValue = valueFetcher(jsState, config);
423 QtOhos::invokeInQtThread(
424 [weakContext, configValue]() {
425 auto context = weakContext.lock();
426 if (context && configValue != context->receivedValue) {
427 context->receivedValue = configValue;
428 context->valueChangedHandler(context->receivedValue);
429 }
430 });
431 });
432 return context;
433 });
434
435 return [context]() {
436 return context->receivedValue;
437 };
438}
439
440QOhosSupplier<OhosConfigurationColorMode> makeOhosConfigColorModeDataSource(
441 QOhosConsumer<OhosConfigurationColorMode> valueChangedHandler)
442{
443 return makeOhosConfigValueDataSource<OhosConfigurationColorMode>(
444 [](QtOhos::JsState &jsState) {
445 return mapOhosConfigurationColorModeFromJs(
446 jsState, jsState.defaultQAbilityPeer()->qAbility().eval<QNapi::Number>("context.config.colorMode"));
447 },
448 [](QtOhos::JsState &jsState, const QNapi::Object &config) {
449 return mapOhosConfigurationColorModeFromJs(jsState, config.get<QNapi::Number>("colorMode"));
450 },
451 std::move(valueChangedHandler));
452}
453
454QOhosOptional<bool> mapOhosConfigurationColorModeToDarkModeFlag(OhosConfigurationColorMode colorMode)
455{
456 switch (colorMode) {
457 case OhosConfigurationColorMode::COLOR_MODE_NOT_SET:
459 case OhosConfigurationColorMode::COLOR_MODE_LIGHT:
460 return makeQOhosOptional(false);
461 case OhosConfigurationColorMode::COLOR_MODE_DARK:
462 return makeQOhosOptional(true);
463 }
464
466}
467
468std::shared_ptr<char> makeSharedNullTerminatedString(std::string str)
469{
470 auto sharedStrData = QtOhos::moveToSharedPtr(std::move(str) + '\0');
471 return std::shared_ptr<char>(sharedStrData, &sharedStrData->front());
472}
473
474std::shared_ptr<char> makeSharedNullTerminatedString(const char *str)
475{
476 return makeSharedNullTerminatedString(std::string(str != nullptr ? str : ""));
477}
478
479template<typename ConvFunc>
480std::string callOhFileUriConversionFunc(
481 ConvFunc convFunc, const std::string &input)
482{
483 char *outputPtr = nullptr;
484 auto outputPtrGuard = qScopeGuard(std::bind(::free, outputPtr));
485 auto convFuncRetVal = convFunc(input.c_str(), input.size(), &outputPtr);
486
487 std::string outputString;
488 if (convFuncRetVal == ::FileManagement_ErrCode::ERR_OK && outputPtr != nullptr) {
489 outputString = outputPtr;
490 } else {
491 qOhosPrintfWarning(
492 "OH FileUri conversion function '%s' failed for input '%s', retval: %d",
493 convFunc.name(), input.c_str(), static_cast<int>(convFuncRetVal));
494 }
495
496 return outputString;
497}
498
499std::string mapPathToOhosUriInJsThread(const std::string &path)
500{
501 return callOhFileUriConversionFunc(Q_OHOS_NAMED_FUNC(::OH_FileUri_GetUriFromPath), path);
502}
503
504std::string mapOhosFileUriToPathInJsThread(const std::string &ohosFileUri)
505{
506 return callOhFileUriConversionFunc(Q_OHOS_NAMED_FUNC(::OH_FileUri_GetPathFromUri), ohosFileUri);
507}
508
509std::shared_ptr<::FileShare_PolicyInfo> makeFileSharePolicyInfo(
510 std::string uri, unsigned operationMode)
511{
512 auto sharedUri = makeSharedNullTerminatedString(std::move(uri));
513
514 auto policyInfo = QtOhos::moveToSharedPtr(
515 ::FileShare_PolicyInfo{
516 .uri = sharedUri.get(),
517 .length = static_cast<unsigned>(std::strlen(sharedUri.get())),
518 .operationMode = operationMode,
519 });
520
521 return QtOhos::makeSharedPtrWithAttachedExtraData(
522 policyInfo, sharedUri);
523}
524
525std::vector<std::shared_ptr<::FileShare_PolicyInfo>> convertToFileSharePolicyInfos(
526 const QList<QOhosQpaFunctions::FileShare::PolicyInfo> &policyInfos)
527{
528 std::vector<std::shared_ptr<::FileShare_PolicyInfo>> fileSharePolicies;
529
530 for (const auto &policyInfo : policyInfos) {
531 unsigned ohosOperationModes = 0;
532 for (auto operationMode : policyInfo.operationModes)
533 ohosOperationModes |= static_cast<unsigned>(operationMode);
534 fileSharePolicies.push_back(
535 makeFileSharePolicyInfo(
536 mapPathToOhosUriInJsThread(policyInfo.path.toStdString()),
537 ohosOperationModes));
538 }
539
540 return fileSharePolicies;
541}
542
543std::shared_ptr<::FileShare_PolicyErrorResult> makeFileSharePolicyErrorResultFromRawStruct(
544 const ::FileShare_PolicyErrorResult &inputStruct)
545{
546 auto sharedUri = makeSharedNullTerminatedString(inputStruct.uri);
547 auto sharedMessage = makeSharedNullTerminatedString(inputStruct.message);
548
549 auto policyErrorResult = QtOhos::moveToSharedPtr(
550 ::FileShare_PolicyErrorResult{
551 .uri = sharedUri.get(),
552 .code = inputStruct.code,
553 .message = sharedMessage.get(),
554 });
555
556 return QtOhos::makeSharedPtrWithAttachedExtraData(
557 policyErrorResult,
558 QtOhos::moveToSharedPtr(std::make_tuple(sharedUri, sharedMessage)));
559};
560
561std::vector<::FileShare_PolicyInfo> makePoliciesRawVectorView(
562 const std::vector<std::shared_ptr<::FileShare_PolicyInfo>> &policies)
563{
564 std::vector<::FileShare_PolicyInfo> rawVectorView;
565 for (const auto &policyPtr : policies)
566 rawVectorView.push_back(*policyPtr);
567
568 return rawVectorView;
569}
570
571template<typename PermissionActionFunc>
572::FileManagement_ErrCode callFileSharePermissionActionFunc(
573 PermissionActionFunc permissionActionFunc,
574 const std::vector<std::shared_ptr<::FileShare_PolicyInfo>> &policies,
575 std::vector<std::shared_ptr<::FileShare_PolicyErrorResult>> &outResult)
576{
577 auto policiesRawVectorView = makePoliciesRawVectorView(policies);
578 ::FileShare_PolicyErrorResult *resultParam = nullptr;
579 unsigned resultNumParam = 0;
580 auto resultParamReleaseGuard = qScopeGuard(
581 [&]() {
582 if (resultParam != nullptr && resultNumParam != 0)
583 ::OH_FileShare_ReleasePolicyErrorResult(resultParam, resultNumParam);
584 });
585
586 auto errCode = permissionActionFunc(
587 policiesRawVectorView.data(), policiesRawVectorView.size(),
588 &resultParam, &resultNumParam);
589
590 outResult.clear();
591 if (resultParam != nullptr) {
592 for (unsigned i = 0; i < resultNumParam; ++i) {
593 outResult.push_back(
594 makeFileSharePolicyErrorResultFromRawStruct(resultParam[i]));
595 }
596 }
597
598 return errCode;
599}
600
601::FileManagement_ErrCode fileShareCheckPersistentPermission(
602 const std::vector<std::shared_ptr<::FileShare_PolicyInfo>> &policies,
603 std::vector<bool> &outResult)
604{
605 auto policiesRawVectorView = makePoliciesRawVectorView(policies);
606 bool *resultParam = nullptr;
607 auto resultParamReleaseGuard = qScopeGuard(
608 [&]() {
609 ::free(resultParam);
610 });
611 unsigned resultNumParam = 0;
612
613 auto errCode = ::OH_FileShare_CheckPersistentPermission(
614 policiesRawVectorView.data(), policiesRawVectorView.size(),
615 &resultParam, &resultNumParam);
616
617 outResult.clear();
618 if (resultParam != nullptr) {
619 for (unsigned i = 0; i < resultNumParam; ++i)
620 outResult.push_back(resultParam[i]);
621 }
622
623 return errCode;
624}
625
626::FileManagement_ErrCode fileSharePersistPermission(
627 const std::vector<std::shared_ptr<::FileShare_PolicyInfo>> &policies,
628 std::vector<std::shared_ptr<::FileShare_PolicyErrorResult>> &outResult)
629{
630 return callFileSharePermissionActionFunc(
631 Q_OHOS_NAMED_FUNC(::OH_FileShare_PersistPermission),
632 policies, outResult);
633}
634
635::FileManagement_ErrCode fileShareRevokePermission(
636 const std::vector<std::shared_ptr<::FileShare_PolicyInfo>> &policies,
637 std::vector<std::shared_ptr<::FileShare_PolicyErrorResult>> &outResult)
638{
639 return callFileSharePermissionActionFunc(
640 Q_OHOS_NAMED_FUNC(::OH_FileShare_RevokePermission),
641 policies, outResult);
642}
643
644::FileManagement_ErrCode fileShareActivatePermission(
645 const std::vector<std::shared_ptr<::FileShare_PolicyInfo>> &policies,
646 std::vector<std::shared_ptr<::FileShare_PolicyErrorResult>> &outResult)
647{
648 return callFileSharePermissionActionFunc(
649 Q_OHOS_NAMED_FUNC(::OH_FileShare_ActivatePermission),
650 policies, outResult);
651}
652
653::FileManagement_ErrCode fileShareDeactivatePermission(
654 const std::vector<std::shared_ptr<::FileShare_PolicyInfo>> &policies,
655 std::vector<std::shared_ptr<::FileShare_PolicyErrorResult>> &outResult)
656{
657 return callFileSharePermissionActionFunc(
658 Q_OHOS_NAMED_FUNC(::OH_FileShare_DeactivatePermission),
659 policies, outResult);
660}
661
662QOhosOptional<QOhosQpaFunctions::FileShare::PolicyErrorCode> tryMapFileSharePolicyErrorCode(
663 ::FileShare_PolicyErrorCode errorCode)
664{
665 using PolicyErrorCode = QOhosQpaFunctions::FileShare::PolicyErrorCode;
666 switch (errorCode) {
667 case ::FileShare_PolicyErrorCode::PERSISTENCE_FORBIDDEN:
668 return makeQOhosOptional(PolicyErrorCode::PERSISTENCE_FORBIDDEN);
669 case ::FileShare_PolicyErrorCode::INVALID_MODE:
670 return makeQOhosOptional(PolicyErrorCode::INVALID_MODE);
671 case ::FileShare_PolicyErrorCode::INVALID_PATH:
672 return makeQOhosOptional(PolicyErrorCode::INVALID_PATH);
673 case ::FileShare_PolicyErrorCode::PERMISSION_NOT_PERSISTED:
674 return makeQOhosOptional(PolicyErrorCode::PERMISSION_NOT_PERSISTED);
675 }
677}
678
679QList<QOhosQpaFunctions::FileShare::PolicyErrorResult> convertToPolicyErrorResults(
680 const std::vector<std::shared_ptr<::FileShare_PolicyErrorResult>> &policyErrorResults)
681{
682 QList<QOhosQpaFunctions::FileShare::PolicyErrorResult> result;
683 for (const auto &policyErrorResult : policyErrorResults) {
684 result.push_back({
685 .path = policyErrorResult->uri != nullptr
686 ? QString::fromStdString(mapOhosFileUriToPathInJsThread(policyErrorResult->uri))
687 : QString(),
688 .error =
689 tryMapFileSharePolicyErrorCode(policyErrorResult->code),
690 .errorMessage = QLatin1String(
691 policyErrorResult->message != nullptr ? policyErrorResult->message : ""),
692 });
693 }
694
695 return result;
696}
697
698bool isSuccessErrorCode(::FileManagement_ErrCode errorCode)
699{
700 return errorCode == ::FileManagement_ErrCode::ERR_OK;
701}
702
703QOhosOptional<QOhosQpaFunctions::ShareKit::SharedRecord> tryConvertNapiObjectToSharedRecord(QNapi::Object record)
704{
705 auto tryGetOptionalStringProp = [](const QNapi::Object &object, const std::string &propName) {
706 return getOptionalProperty<QNapi::String>(object, propName).transform(&QString::fromStdString);
707 };
708
709 auto tryGetOptionalByteArrayProp = [](const QNapi::Object &object, const std::string &propName) {
710 return getOptionalProperty<QNapi::TypedArrayOf<std::uint8_t>>(object, propName).transform(
711 [](const auto &napiArray) {
712 return QByteArray(
713 reinterpret_cast<const char *>(napiArray.Data()),
714 napiArray.ByteLength());
715 });
716 };
717
718 auto tryGetOptionalJsonObjectProp = [](const QNapi::Object &object, const std::string &propName) {
719 return getOptionalProperty<QNapi::Object>(object, propName).transform(
720 [](const auto &napiObject) {
721 return QOhosJsEnv::fromNapiValue<QJsonObject>(napiObject);
722 });
723 };
724
725 std::string utd = record.get<QNapi::String>("utd");
726 auto optMimeType = utd != QOhosUdsMeta<::OH_UdsHyperlink>::udmfMetaId
727 ? tryMapUtdTypeIdToMimeType(utd)
728 : QOhosOptional<std::string>(QOhosShareKit::mimeTextUriList);
729 if (!optMimeType.hasValue()) {
730 qOhosPrintfWarning(
731 "%s: can't map utd '%s' to mimetype, not mapping the record",
732 Q_FUNC_INFO, utd.c_str());
734 }
735
736 auto content = tryGetOptionalStringProp(record, "content");
737 auto uri = tryGetOptionalStringProp(record, "uri");
738 if (!content.hasValue() && !uri.hasValue()) {
739 qOhosPrintfWarning(
740 "%s: cannot create Shared Record, content and uri properties are empty", Q_FUNC_INFO);
742 }
743
744 return makeQOhosOptional(
745 QOhosQpaFunctions::ShareKit::SharedRecord{
746 .mimeType = QString::fromStdString(optMimeType.value()),
747 .content = content,
748 .filePath = uri,
749 .title = tryGetOptionalStringProp(record, "title"),
750 .label = tryGetOptionalStringProp(record, "label"),
751 .description = tryGetOptionalStringProp(record, "description"),
752 .thumbnail = tryGetOptionalByteArrayProp(record, "thumbnail"),
753 .thumbnailFilePath = tryGetOptionalStringProp(record, "thumbnailUri"),
754 .extraData = tryGetOptionalJsonObjectProp(record, "extraData").transform(std::mem_fn(&QJsonObject::toVariantMap)),
755 });
756}
757
758QOhosShareKit::ShareAbilityType mapShareAbilityTypeFromQpaFunctionsEnum(
760{
761 switch (abilityType) {
772 }
773
774 qOhosReportFatalErrorAndAbort(
775 "%s: unsupported ShareAbilityType value: %d",
776 Q_FUNC_INFO, static_cast<int>(abilityType));
777}
778
779class WantInfoImpl : public QOhosQpaFunctions::WantInfo
780{
781public:
782 WantInfoImpl(QNapi::Object want, LaunchReason launchReason);
783
784 QJsonObject jsonObject() const override;
785
786 QOhosOptional<QList<QOhosQpaFunctions::ShareKit::SharedRecord>> tryGetSharedDataRecords() const override;
787
788 QOhosOptional<ContactInfo> tryGetContactInfo() const override;
789
790 LaunchReason launchReason() const override;
791
792private:
793 struct JsScopeData
794 {
795 QNapi::Reference<QNapi::Object> want;
796 };
797
798 std::shared_ptr<JsScopeData> m_jsScopeData;
799 QJsonObject m_jsonObject;
800 LaunchReason m_launchReason;
801};
802
803WantInfoImpl::WantInfoImpl(QNapi::Object want, LaunchReason launchReason)
804 : WantInfo()
805 , m_jsScopeData(
806 QtOhos::makeProxyWithJsThreadDeleter(
807 QtOhos::moveToSharedPtr(
808 JsScopeData {
809 .want = QNapi::Reference<>::makePersistentFrom(want),
810 })))
811 , m_jsonObject(QOhosJsEnv::fromNapiValue<QJsonObject>(want))
812 , m_launchReason(launchReason)
813{
814}
815
816QJsonObject WantInfoImpl::jsonObject() const
817{
818 return m_jsonObject;
819}
820
821QOhosOptional<QList<QOhosQpaFunctions::ShareKit::SharedRecord>> WantInfoImpl::tryGetSharedDataRecords() const
822{
823 using SharedRecord = QOhosQpaFunctions::ShareKit::SharedRecord;
824
825 return QtOhos::evalInJsThreadWithConsumer<QOhosOptional<QList<SharedRecord>>>(
826 [&](QtOhos::JsState &jsState, QOhosConsumer<QOhosOptional<QList<SharedRecord>>> resultConsumer) {
827 jsState.eval<QNapi::Promise>(
828 "@kit.ShareKit.systemShare.getSharedData(*)", {m_jsScopeData->want.Value()})
829 .withContext(std::move(resultConsumer))
830 .onThenWithContext(
831 [](const QtOhos::CallbackInfo &cbInfo, auto &resultConsumer) {
832 QNapi::Object sharedData = cbInfo.getFirstArg<QNapi::Object>(Q_FUNC_INFO);
833
834 auto optRecords = QNapi::getArrayElements<QList<QOhosOptional<SharedRecord>>, QNapi::Object>(
835 sharedData.call<QNapi::Array>("getRecords"), &tryConvertNapiObjectToSharedRecord);
836
837 QList<SharedRecord> records;
838 for (const auto &optRecord : optRecords) {
839 if (optRecord.hasValue())
840 records.append(optRecord.value());
841 }
842
843 if (records.size() != optRecords.size()) {
844 qOhosPrintfWarning(
845 "%s: can't convert %lld Shared Records, ignoring them",
846 Q_FUNC_INFO, records.size() - optRecords.size());
847 }
848
849 resultConsumer(makeQOhosOptional(records));
850 })
851 .onCatchWithContext(
852 [](const QtOhos::CallbackInfo &cbInfo, auto &resultConsumer) {
853 QtOhos::logJsCallbackError(cbInfo, "@kit.ShareKit.systemShare.getSharedData() failed");
854 resultConsumer(makeEmptyQOhosOptional());
855 });
856 });
857}
858
859QOhosOptional<QOhosQpaFunctions::WantInfo::ContactInfo> WantInfoImpl::tryGetContactInfo() const
860{
861 using ContactInfo = QOhosQpaFunctions::WantInfo::ContactInfo;
862
863 return QtOhos::evalInJsThreadWithConsumer<QOhosOptional<ContactInfo>>(
864 [&](QtOhos::JsState &jsState, QOhosConsumer<QOhosOptional<ContactInfo>> resultConsumer) {
865 jsState.eval<QNapi::Promise>(
866 "@kit.ShareKit.systemShare.getContactInfo(*)", {m_jsScopeData->want.Value()})
867 .withContext(std::move(resultConsumer))
868 .onThenWithContext(
869 [](const QtOhos::CallbackInfo &cbInfo, QOhosConsumer<QOhosOptional<ContactInfo>> &resultConsumer) {
870 auto contactInfoObj = cbInfo.getFirstArg<QNapi::Object>(Q_FUNC_INFO);
871 ContactInfo contactInfo = {
872 .contactType = QString::fromStdString(
873 contactInfoObj.get<QNapi::String>("contactType")),
874 .contactId = QString::fromStdString(
875 contactInfoObj.get<QNapi::String>("contactId")),
876 };
877 resultConsumer(makeQOhosOptional(contactInfo));
878 })
879 .onCatchWithContext(
880 [](const QtOhos::CallbackInfo &cbInfo, auto &resultConsumer) {
881 QtOhos::logJsCallbackError(cbInfo, "@kit.ShareKit.systemShare.getContactInfo() failed");
882 resultConsumer(makeEmptyQOhosOptional());
883 });
884 });
885}
886
887QOhosQpaFunctions::WantInfo::LaunchReason WantInfoImpl::launchReason() const
888{
889 return m_launchReason;
890}
891
892class QOhosQpaFunctionsImpl : public QOhosQpaFunctions
893{
894public:
895 std::shared_ptr<void> startPickingColorFromScreenWithConsumer(
896 QOhosConsumer<QOhosOptional<quint32>> colorConsumer) override;
897
898 void setWindowPrivacyMode(QObject *window, bool privacyModeEnabled) override;
899 double getFontSizeScale() override;
900 void setWindowCornerRadius(QObject *window, double radius) override;
901 void tagWindowOrWidgetAsFloatWindow(QObject *windowOrWidget, bool floatWindow) override;
902
903 void setInAppOnlyPasteboardShareOption(bool shareInAppOnly) override;
904 QVariant getImageDataFromPasteboard() const override;
905 QString getTextDataFromPasteboard() const override;
906
907 ScreenChangeResult tryChangePlatformWindowScreenInternal(QObject *windowObject, QObject *screenObject) override;
908
909 void setWindowOrWidgetNativeNodeRenderFitPolicyHint(QObject *windowOrWidget, NativeNodeRenderFitPolicy renderFitPolicy) override;
910
911 void setSurfaceBackgroundColor(QObject *windowOrWidget, const QColor &color) override;
912
913 void setMainWindowGeometryPersistencePolicy(WindowGeometryPersistencePolicy policy) override;
914
915 void setWindowKeepScreenOn(QObject *windowOrWidget, bool keepScreenOn) override;
916
917 QOhosOptional<double> tryGetNativeWindowId(QObject *window) override;
918 QOhosOptional<double> tryGetScreenDisplayId(QObject *screenObject) override;
919
920 void setOnContinueRequestsHandlerForAbilityInstanceWindow(
921 QObject *windowObject, std::function<void(AbilityOnContinueRequest, QOhosConsumer<AbilityOnContinueResponse>)> requestsHandler) override;
922
923 void setAbilityContinuationActive(
924 QObject *optInstanceMainWindow, bool continuationActive) override;
925
926 Q_NORETURN void restartApp(QOhosOptional<QJsonObject> want) override;
927
928 QJsonObject getAppLaunchWant() override;
929 QSharedPointer<WantInfo> getAppLaunchWantInfo() const override;
930
931 void addNewWantConsumer(QObject *context, QOhosConsumer<QJsonObject> wantConsumer) override;
932 void addNewWantConsumer(
933 QObject *context, QOhosConsumer<QSharedPointer<WantInfo>> wantConsumer) override;
934
935 void startAppProcess(
936 const QString &processId, const QJsonObject &requestWant,
937 const QOhosOptional<StartOptions> &optStartOptions) override;
938
939 bool startAbility(const QJsonObject &want, const QOhosOptional<StartOptions> &options) override;
940
941 bool startAbilityByType(const QString &appType, const QJsonObject &wantParameters) override;
942
943 void startAbilityForResult(
944 const QJsonObject &want, const QOhosOptional<StartOptions> &options,
945 QObject *optInstanceMainWindow, QObject *resultConsumerQtContext,
946 QOhosConsumer<QOhosOptional<AbilityResult>> resultConsumer) override;
947
948 void setDestroyAllowedFlagForAbilityInstances(
949 std::vector<QObject *> instancesMainWindows, bool destroyEnabled) override;
950
951 void setOhosConfigDarkModeFlag(QOhosOptional<bool> darkModeFlag) override;
952
953 QOhosSupplier<QOhosOptional<bool>> makeOhosConfigDarkModeFlagDataSource(
954 QOhosConsumer<QOhosOptional<bool>> darkModeFlagChangedHandler) override;
955
956 QOhosSupplier<double> makeOhosConfigFontSizeScaleDataSource(
957 QOhosConsumer<double> valueChangedHandler) override;
958
959 int getCurrentApplicationVersionCode() override;
960
961 bool readOhosNoUiChildMode() override;
962
963 void startNoUiChildProcess(QString libraryName, QStringList args) override;
964
965 std::pair<bool, QList<FileShare::PolicyErrorResult>> persistPermission(
966 const QList<FileShare::PolicyInfo> &policyInfos) override;
967
968 std::pair<bool, QList<FileShare::PolicyErrorResult>> revokePermission(
969 const QList<FileShare::PolicyInfo> &policyInfos) override;
970
971 std::pair<bool, QList<FileShare::PolicyErrorResult>> activatePermission(
972 const QList<FileShare::PolicyInfo> &policyInfos) override;
973
974 std::pair<bool, QList<FileShare::PolicyErrorResult>> deactivatePermission(
975 const QList<FileShare::PolicyInfo> &policyInfos) override;
976
977 std::pair<bool, std::vector<bool>> checkPersistent(const QList<FileShare::PolicyInfo> &policyInfos) override;
978
979 bool showFileDialogToAuthorizeFilePath(QObject *parentWindow, const QString &filePath) override;
980
981 void setWindowBrightness(QObject *window, int brightness) override;
982 void setWindowContrast(QObject *window, int contrast) override;
983 void setWindowSaturation(QObject *window, int saturation) override;
984
985 bool shareDataUsingShareKit(
986 QObject *windowObject, const QList<ShareKit::SharedRecord> &recordsToShare,
987 const ShareKit::ShareControllerOptions &controllerOptions) override;
988
989 std::shared_ptr<void> shareDataUsingShareKit(
990 QObject *optWindowObject, const QList<ShareKit::SharedRecord> &recordsToShare,
991 const ShareKit::ShareControllerOptions &controllerOptions,
992 std::function<void()> panelClosedCallback) override;
993
994 bool tryOpenLink(QObject *optInstanceMainWindow, const QString &link, QOhosOptional<bool> appLinkingOnly) override;
995
996 QObject *getActiveWindowOrNull() const override;
997};
998
999std::shared_ptr<void> QOhosQpaFunctionsImpl::startPickingColorFromScreenWithConsumer(
1000 QOhosConsumer<QOhosOptional<quint32>> colorConsumer)
1001{
1002 struct Context
1003 {
1004 std::unique_ptr<QObject> colorConsumerQtContext;
1005 QOhosConsumer<QOhosOptional<quint32>> colorConsumer;
1006 };
1007
1008 auto sharedContext = QtOhos::moveToSharedPtr(
1009 Context{
1010 .colorConsumerQtContext = std::make_unique<QObject>(),
1011 .colorConsumer = std::move(colorConsumer),
1012 });
1013
1014 auto colorConsumerProxy = QtOhos::moveToSharedPtr(
1015 [weakContext = QtOhos::makeWeakPtr(sharedContext)](QOhosOptional<quint32> rgbaColor) {
1016 auto sharedContext = weakContext.lock();
1017 if (sharedContext) {
1018 QMetaObject::invokeMethod(
1019 sharedContext->colorConsumerQtContext.get(),
1020 [weakContext, rgbaColor]() {
1021 auto sharedContext = weakContext.lock();
1022 if (sharedContext)
1023 sharedContext->colorConsumer(rgbaColor);
1024 },
1025 Qt::QueuedConnection);
1026 }
1027 });
1028
1030 [colorConsumerProxy](QtOhos::JsState &jsState) {
1031 jsState.eval<QNapi::Promise>("@kit.Penkit.imageFeaturePicker.pickForResult()")
1032 .onThen(
1033 [colorConsumerProxy](const QtOhos::CallbackInfo &cbInfo) {
1034 auto pickedColorInfo = cbInfo.getFirstArg<QNapi::Object>(Q_FUNC_INFO);
1035 auto color = pickedColorInfo.get<QNapi::Object>("color");
1036 QColor qColor(
1037 color.get<QNapi::Number>("red"),
1038 color.get<QNapi::Number>("green"),
1039 color.get<QNapi::Number>("blue"),
1040 color.get<QNapi::Number>("alpha"));
1041 (*colorConsumerProxy)(makeQOhosOptional(qColor.rgba()));
1042 })
1043 .onCatch(
1044 [colorConsumerProxy](const QtOhos::CallbackInfo &cbInfo) {
1045 QtOhos::logJsCallbackError(cbInfo, "@kit.Penkit.imageFeaturePicker.pickForResult() failed");
1046 (*colorConsumerProxy)(makeEmptyQOhosOptional());
1047 });
1048 });
1049
1050 return sharedContext;
1051}
1052
1053void QOhosQpaFunctionsImpl::setWindowPrivacyMode(QObject *window, bool privacyModeEnabled)
1054{
1055 QOhosPlatformWindow::setWindowPrivacyMode(window, privacyModeEnabled);
1056}
1057
1058double QOhosQpaFunctionsImpl::getFontSizeScale()
1059{
1061}
1062
1063void QOhosQpaFunctionsImpl::setInAppOnlyPasteboardShareOption(bool shareInAppOnly)
1064{
1066}
1067
1068QVariant QOhosQpaFunctionsImpl::getImageDataFromPasteboard() const
1069{
1070 return QOhosPlatformIntegration::instance()->clipboard()->getPasteboardDataWithLazyFetchOrLocalIfOwner()->imageData();
1071}
1072
1073QString QOhosQpaFunctionsImpl::getTextDataFromPasteboard() const
1074{
1075 return QOhosPlatformIntegration::instance()->clipboard()->getPasteboardDataWithLazyFetchOrLocalIfOwner()->text();
1076}
1077
1078void QOhosQpaFunctionsImpl::setWindowCornerRadius(QObject *windowOrWidget, double radius)
1079{
1080 QOhosPlatformWindow::setWindowCornerRadius(windowOrWidget, radius);
1081}
1082
1083void QOhosQpaFunctionsImpl::tagWindowOrWidgetAsFloatWindow(
1084 QObject *windowOrWidget, bool floatWindow)
1085{
1086 QOhosPlatformWindow::tagWindowOrWidgetAsFloatWindow(windowOrWidget, floatWindow);
1087}
1088
1089QOhosQpaFunctions::ScreenChangeResult QOhosQpaFunctionsImpl::tryChangePlatformWindowScreenInternal(QObject *windowObject, QObject *screenObject)
1090{
1091 auto *qWindow = qobject_cast<QWindow *>(windowObject);
1092 auto *qScreen = qobject_cast<QScreen *>(screenObject);
1093
1094 if (qWindow == nullptr)
1095 qOhosReportFatalErrorAndAbort("%s: windowObject argument is null or not a QWindow", Q_FUNC_INFO);
1096
1097 if (screenObject != nullptr && qScreen == nullptr)
1098 qOhosReportFatalErrorAndAbort("%s: screenObject argument is not a QScreen", Q_FUNC_INFO);
1099
1100 auto *ohosPlatformWindow = QOhosPlatformWindow::fromQWindowOrNull(qWindow);
1101 auto *platformScreen = qScreen != nullptr ? qScreen->handle() : nullptr;
1102
1103 if (ohosPlatformWindow == nullptr)
1104 qOhosReportFatalErrorAndAbort("%s: platformWindow argument is null", Q_FUNC_INFO);
1105
1106 auto tryChangeScreenResult = ohosPlatformWindow->tryChangeScreen(static_cast<QOhosPlatformScreen *>(platformScreen));
1108 switch (tryChangeScreenResult) {
1111 break;
1114 break;
1115 }
1116 return result;
1117}
1118
1119void QOhosQpaFunctionsImpl::setWindowOrWidgetNativeNodeRenderFitPolicyHint(
1120 QObject *windowOrWidget, QOhosQpaFunctionsImpl::NativeNodeRenderFitPolicy renderFitPolicyHint)
1121{
1123 switch (renderFitPolicyHint) {
1126 break;
1129 break;
1130 }
1131
1132 if (policy.hasValue()) {
1133 QOhosPlatformWindow::setWindowOrWidgetNativeNodeRenderFitPolicyHint(windowOrWidget, policy.value());
1134 } else {
1135 qOhosReportFatalErrorAndAbort(
1136 "%s: Failed to convert render fit policy hint to QOhosPlatformWindow enum",
1137 Q_FUNC_INFO);
1138 }
1139}
1140
1141void QOhosQpaFunctionsImpl::setSurfaceBackgroundColor(QObject *windowOrWidget, const QColor &color)
1142{
1143 QOhosPlatformWindow::setSurfaceBackgroundColor(windowOrWidget, color);
1144}
1145
1146void QOhosQpaFunctionsImpl::setMainWindowGeometryPersistencePolicy(
1147 WindowGeometryPersistencePolicy geometryPolicyHint)
1148{
1150 switch (geometryPolicyHint) {
1153 break;
1156 break;
1159 break;
1160 }
1161
1162 if (policy.hasValue()) {
1164 } else {
1165 qOhosReportFatalErrorAndAbort(
1166 "%s: Failed to convert persistence geometry policy hint to QOhosPlatformIntegration enum",
1167 Q_FUNC_INFO);
1168 }
1169}
1170
1171void QOhosQpaFunctionsImpl::setWindowKeepScreenOn(QObject *windowOrWidget, bool keepScreenOn)
1172{
1173 QOhosPlatformWindow::setWindowKeepScreenOn(windowOrWidget, keepScreenOn);
1174}
1175
1176QOhosOptional<double> QOhosQpaFunctionsImpl::tryGetNativeWindowId(QObject *window)
1177{
1178 auto *qWindow = qobject_cast<QWindow *>(window);
1179 if (qWindow == nullptr)
1181
1182 auto *platformWindow = QOhosPlatformWindow::fromQWindowOrNull(qWindow);
1183 if (platformWindow == nullptr)
1185
1186 auto internalId = platformWindow->internalWindowId();
1187 auto jsWinId = QWindowProxyRegistry::instance().tryMapInternalWindowIdToJsWindowId(internalId);
1188 if (!jsWinId.hasValue())
1190
1191 qOhosPrintfInfo(
1192 "PlatformWindow WIID: %s is returning JsWindowId: %f to the user",
1193 qPrintable(internalId.toString()), jsWinId.value().value());
1194
1195 return makeQOhosOptional(jsWinId.value().value());
1196}
1197
1198QOhosOptional<double> QOhosQpaFunctionsImpl::tryGetScreenDisplayId(QObject *screenObject)
1199{
1200 auto *qScreen = qobject_cast<QScreen *>(screenObject);
1201 if (qScreen == nullptr) {
1202 qOhosPrintfWarning("%s: screenObject argument is not a QScreen", Q_FUNC_INFO);
1204 }
1205 auto *ohosPlatformScreen = static_cast<QOhosPlatformScreen *>(qScreen->handle());
1206
1207 return ohosPlatformScreen != nullptr
1208 ? makeQOhosOptional(ohosPlatformScreen->displayInfo().id.value())
1210}
1211
1212void QOhosQpaFunctionsImpl::setOnContinueRequestsHandlerForAbilityInstanceWindow(
1213 QObject *windowObject, std::function<void(AbilityOnContinueRequest, QOhosConsumer<AbilityOnContinueResponse>)> requestsHandler)
1214{
1215 auto *qWindow = qobject_cast<QWindow *>(windowObject);
1216 if (qWindow == nullptr)
1217 qOhosReportFatalErrorAndAbort("%s: windowObject argument is null or not a QWindow", Q_FUNC_INFO);
1218
1219 auto qWindowRef = QObjectThreadSafeRef(qWindow);
1220 auto sharedRequestsHandler = moveToSharedPtr(std::move(requestsHandler));
1221
1222 struct JsResultContext
1223 {
1224 QNapi::Reference<QNapi::Object> wantParamsReference;
1225 QOhosConsumer<JsState &, QOhosAbilityOnContinueResult> resultConsumer;
1226 };
1227
1229 [&](JsState &jsState) {
1231 jsState.tryGetQAbilityPeerByQWindow(qWindowRef));
1232 if (!uiAbilityPeer) {
1233 qOhosPrintfError(
1234 "%s: no QUiAbilityPeer for window %s, handler not set",
1235 Q_FUNC_INFO, qWindowRef.refName().c_str());
1236 return;
1237 }
1238
1239 uiAbilityPeer->setOnContinueRequestsHandler(
1240 [sharedRequestsHandler](JsState &, QNapi::Object wantParamsObj, auto resultConsumer) {
1241 int sourceVersionCode = wantParamsObj.get<QNapi::Number>("version");
1242 auto jsResultContext = makeProxyWithJsThreadDeleter(std::make_shared<JsResultContext>());
1243 jsResultContext->wantParamsReference = QNapi::Reference<>::makePersistentFrom(wantParamsObj);
1244 jsResultContext->resultConsumer = std::move(resultConsumer);
1245 QtOhos::invokeInQtThread(
1246 [sharedRequestsHandler, sourceVersionCode, jsResultContext]() {
1247 (*sharedRequestsHandler)(
1248 AbilityOnContinueRequest{
1249 .sourceApplicationVersionCode = sourceVersionCode,
1250 },
1251 [jsResultContext](AbilityOnContinueResponse qtResponse) {
1252 QtOhos::invokeInJsThread(
1253 [jsResultContext, qtResponse](JsState &jsState) {
1254 if (qtResponse.status == AbilityOnContinueResponseStatus::Agree) {
1255 auto wantParamsObj = jsResultContext->wantParamsReference.Value();
1256 auto newWantParamsIter = qtResponse.wantObjectParams.constKeyValueBegin();
1257 while (newWantParamsIter != qtResponse.wantObjectParams.constKeyValueEnd()) {
1258 wantParamsObj.set(
1259 newWantParamsIter->first.toStdString(),
1260 newWantParamsIter->second.toStdString());
1261 ++newWantParamsIter;
1262 }
1263 if (qtResponse.exitAppOnSourceDeviceAfterMigration.hasValue()) {
1264 wantParamsObj.set(
1265 jsState.eval<QNapi::String>(
1266 "@ohos.app.ability.wantConstant.Params.SUPPORT_CONTINUE_SOURCE_EXIT_KEY"),
1267 qtResponse.exitAppOnSourceDeviceAfterMigration.value());
1268 }
1269 }
1270 auto ohosResult = tryMapAbilityOnContinueResponseStatusToOhos(qtResponse.status);
1271 if (!ohosResult.hasValue()) {
1272 qOhosPrintfWarning(
1273 "%s: got illegal status (%d) from request handler, rejecting",
1274 Q_FUNC_INFO, static_cast<int>(qtResponse.status));
1275 }
1276 jsResultContext->resultConsumer(
1277 jsState, ohosResult.valueOr(QOhosAbilityOnContinueResult::REJECT));
1278 });
1279 });
1280 });
1281 });
1282 });
1283}
1284
1285void QOhosQpaFunctionsImpl::setAbilityContinuationActive(
1286 QObject *optInstanceMainWindow, bool continuationActive)
1287{
1288 using ContinueState = enums::ohos::app::ability::AbilityConstant::ContinueState;
1289
1290 auto optInstanceMainWindowRef =
1291 optInstanceMainWindow != nullptr
1292 ? makeQOhosOptional(QtOhos::QObjectThreadSafeRef(optInstanceMainWindow))
1294
1296 [&](JsState &jsState, std::function<void()> continueFunc) {
1297 auto optAbilityPeer = tryMapOptMainWindowToAbilityPeer(jsState, optInstanceMainWindowRef);
1298 if (!optAbilityPeer) {
1299 continueFunc();
1300 return;
1301 }
1302
1303 auto continueState = continuationActive ? ContinueState::ACTIVE : ContinueState::INACTIVE;
1304 optAbilityPeer->qAbility().call<QNapi::Promise>(
1305 "context.setMissionContinueState", {jsState.mapOhosEnumToJs(continueState)})
1306 .onCatch(QtOhos::makeErrorLoggingJsCallback("setMissionContinueState()"))
1307 .onFinally(std::move(continueFunc));
1308 });
1309}
1310
1311Q_NORETURN void QOhosQpaFunctionsImpl::restartApp(QOhosOptional<QJsonObject> want)
1312{
1314 [&](JsState &jsState) {
1315 auto napiWant = want.hasValue()
1316 ? QNapi::checkedCast<QNapi::Object>(QOhosJsEnv::toNapiValue(jsState.env(), want.value()))
1317 : jsState.appLaunchWant();
1318
1319 constexpr auto sleepTimeBeforeRetry = 3s;
1320
1321 unsigned remainingTries = 3;
1322
1323 while (true) {
1324 --remainingTries;
1325
1326 qOhosPrintfInfo(
1327 "%s: calling restartApp() using Want: %s",
1328 Q_FUNC_INFO, QNapi::toJsonString(napiWant).c_str());
1329
1330 try {
1331 jsState.defaultQAbilityPeer()->qAbility().call(
1332 "context.getApplicationContext().restartApp", {napiWant});
1333
1334 qOhosPrintfWarning("%s: restartApp() call unexpectedly returned, killing self", Q_FUNC_INFO);
1335 killCurrentProcess();
1336 } catch (const Napi::Error &error) {
1337 constexpr std::uint32_t restartTooFrequentlyErrorCode = 16000064;
1338
1339 auto errorCode = QtOhos::tryGetCodeFromJsBusinessError(error);
1340
1341 if (errorCode == restartTooFrequentlyErrorCode && remainingTries != 0) {
1342 qOhosPrintfWarning(
1343 "%s: restartApp() returned with error %u, sleeping before retry",
1344 Q_FUNC_INFO, restartTooFrequentlyErrorCode);
1345
1346 std::this_thread::sleep_for(sleepTimeBeforeRetry);
1347 } else {
1348 auto errorCodeStr = errorCode.hasValue()
1349 ? std::to_string(errorCode.value())
1350 : "?";
1351 qOhosPrintfWarning(
1352 "%s: restartApp() returned with error %s, killing self",
1353 Q_FUNC_INFO, errorCodeStr.c_str());
1354
1355 killCurrentProcess();
1356 }
1357 }
1358 }
1359 });
1360
1361 qOhosReportFatalErrorAndAbort("%s: unexpected return from the JS thread call", Q_FUNC_INFO);
1362}
1363
1364QJsonObject QOhosQpaFunctionsImpl::getAppLaunchWant()
1365{
1366 return getAppLaunchWantInfo()->jsonObject();
1367}
1368
1369QSharedPointer<QOhosQpaFunctions::WantInfo> QOhosQpaFunctionsImpl::getAppLaunchWantInfo() const
1370{
1371 return QtOhos::evalInJsThread(
1372 [](auto &jsState) {
1373 auto optAppLaunchReason = jsState.optAppLaunchParam().transform(
1374 [&](QNapi::Object appLaunchParam) {
1375 return mapJsLaunchReasonToWantInfoEnumWithFallback(
1376 jsState, appLaunchParam.get<QNapi::Number>("launchReason"));
1377 });
1378 auto appLaunchReason = optAppLaunchReason.valueOr(QOhosQpaFunctions::WantInfo::LaunchReason::UNKNOWN);
1379 return QSharedPointer<WantInfoImpl>::create(jsState.appLaunchWant(), appLaunchReason);
1380 });
1381}
1382
1383void QOhosQpaFunctionsImpl::addNewWantConsumer(QObject *context, QOhosConsumer<QJsonObject> wantConsumer)
1384{
1385 auto sharedWantConsumer = QtOhos::moveToSharedPtr(std::move(wantConsumer));
1386 addNewWantConsumer(
1387 context,
1388 [sharedWantConsumer](QSharedPointer<WantInfo> wantInfo) {
1389 (*sharedWantConsumer)(wantInfo->jsonObject());
1390 });
1391}
1392
1393void QOhosQpaFunctionsImpl::addNewWantConsumer(
1394 QObject *context, QOhosConsumer<QSharedPointer<WantInfo>> wantConsumer)
1395{
1396 auto contextRef = QtOhos::makeQThreadSafeRef(context);
1397 auto sharedWantConsumer = QtOhos::moveToSharedPtr(std::move(wantConsumer));
1399 [&](auto &jsState) {
1400 jsState.addNewWantConsumer(
1401 [contextRef, sharedWantConsumer](QtOhos::JsState &jsState, QNapi::Object napiWant, QNapi::Object launchParam) {
1402 auto launchReason = mapJsLaunchReasonToWantInfoEnumWithFallback(
1403 jsState, launchParam.get<QNapi::Number>("launchReason"));
1404 auto wantInfo = QSharedPointer<WantInfoImpl>::create(napiWant, launchReason);
1405 contextRef.visitInQtThreadIfAlive(
1406 [sharedWantConsumer, wantInfo](auto &) {
1407 (*sharedWantConsumer)(wantInfo);
1408 });
1409 });
1410 });
1411}
1412
1413void QOhosQpaFunctionsImpl::startAppProcess(
1414 const QString &processId, const QJsonObject &requestWant,
1415 const QOhosOptional<StartOptions> &optStartOptions)
1416{
1418 [&](auto &jsState, std::function<void()> continueFunc) {
1419 auto startOptions = optStartOptions.hasValue()
1420 ? convertStartOptionsToNapiObject(jsState, optStartOptions.value())
1421 : QNapi::Object();
1422
1423 jsState.startAppProcess(
1424 processId.toStdString(),
1425 QNapi::checkedCast<QNapi::Object>(
1426 QOhosJsEnv::toNapiValue(jsState.env(), requestWant)),
1427 startOptions,
1428 [continueFunc = std::move(continueFunc)](QtOhos::JsState &) {
1429 continueFunc();
1430 });
1431 });
1432}
1433
1434bool QOhosQpaFunctionsImpl::startAbility(const QJsonObject &want, const QOhosOptional<QOhosQpaFunctions::StartOptions> &options)
1435{
1436 return QtOhos::evalInJsThread(
1437 [&](auto &jsState) {
1438 auto mainUiAbility = jsState.defaultQAbilityPeer()->qAbility();
1439 if (mainUiAbility.IsEmpty())
1440 return false;
1441
1442 auto arguments = std::vector<QNapi::ValueWrapper>{QOhosJsEnv::toNapiValue(jsState.env(), want)};
1443 if (options.hasValue())
1444 arguments.push_back(convertStartOptionsToNapiObject(jsState, options.value()));
1445
1446 mainUiAbility.call("context.startAbility", arguments);
1447
1448 // FIXME:
1449 // * there should be error code taken from a call to JS `startAbility` function
1450 // * error code should be checked and provided to the returned `operationStatus`
1451 return true;
1452 });
1453}
1454
1455bool QOhosQpaFunctionsImpl::startAbilityByType(const QString &appType, const QJsonObject &wantParameters)
1456{
1457 // The call result of "context.startAbilityByType" will be synced and returned.
1458 // However, the started ability result won't be synced here.
1459 return QtOhos::evalInJsThreadWithConsumer<bool>(
1460 [&](QtOhos::JsState &jsState, QOhosConsumer<bool> resultConsumer) {
1461 auto qAbility = jsState.defaultQAbilityPeer()->qAbility();
1462 if (qAbility.IsEmpty()) {
1463 resultConsumer(false);
1464 return;
1465 }
1466
1467 qAbility.call<QNapi::Promise>(
1468 "context.startAbilityByType",
1469 {
1470 appType.toStdString(),
1471 QOhosJsEnv::toNapiValue(jsState.env(), wantParameters),
1472 QNapi::makeObject(
1473 jsState.env(),
1474 {
1475 {
1476 "onResult",
1477 [](const QtOhos::CallbackInfo&) {
1478 qOhosPrintfDebug("startAbilityByType: onResult called");
1479 }
1480 },
1481 {
1482 "onError",
1483 [](const QtOhos::CallbackInfo &cbInfo) {
1484 QtOhos::logJsCallbackError(cbInfo, "startAbilityByType: onError called");
1485 }
1486 }
1487 })
1488 })
1489 .withContext(std::move(resultConsumer))
1490 .onThenWithContext(
1491 [](QOhosConsumer<bool> &resultConsumer) {
1492 resultConsumer(true);
1493 })
1494 .onCatchWithContext(
1495 [](const QtOhos::CallbackInfo &cbInfo, QOhosConsumer<bool> &resultConsumer) {
1496 QtOhos::logJsCallbackError(cbInfo, "startAbilityByType: failed");
1497 resultConsumer(false);
1498 });
1499 });
1500}
1501
1502void QOhosQpaFunctionsImpl::startAbilityForResult(
1503 const QJsonObject &want, const QOhosOptional<StartOptions> &options,
1504 QObject *optInstanceMainWindow, QObject *resultConsumerQtContext,
1505 QOhosConsumer<QOhosOptional<AbilityResult>> resultConsumer)
1506{
1507 struct Context
1508 {
1509 QtOhos::QObjectThreadSafeRef resultConsumerQtContextRef;
1510 QOhosConsumer<QOhosOptional<AbilityResult>> resultConsumer;
1511 };
1512
1513 auto context = QtOhos::moveToSharedPtr(
1514 Context{
1515 .resultConsumerQtContextRef = QtOhos::QObjectThreadSafeRef(resultConsumerQtContext),
1516 .resultConsumer = std::move(resultConsumer),
1517 });
1518
1519 auto optInstanceMainWindowRef =
1520 optInstanceMainWindow != nullptr
1521 ? makeQOhosOptional(QtOhos::QObjectThreadSafeRef(optInstanceMainWindow))
1523
1525 [context, want, options, optInstanceMainWindowRef](QtOhos::JsState &jsState) {
1526 auto optAbilityPeer = tryMapOptMainWindowToAbilityPeer(jsState, optInstanceMainWindowRef);
1527 if (!optAbilityPeer) {
1528 context->resultConsumerQtContextRef.visitInQtThreadIfAlive(
1529 [context](auto &) {
1530 context->resultConsumer({});
1531 });
1532 return;
1533 }
1534
1535 auto arguments = std::vector<QNapi::ValueWrapper>{QOhosJsEnv::toNapiValue(jsState.env(), want)};
1536 if (options.hasValue())
1537 arguments.push_back(convertStartOptionsToNapiObject(jsState, options.value()));
1538
1539 optAbilityPeer->qAbility().call<QNapi::Promise>("context.startAbilityForResult", arguments)
1540 .onThen(
1541 [context](const QtOhos::CallbackInfo &cbInfo) {
1542 QNapi::Object abilityResult = cbInfo.getFirstArg<QNapi::Object>(Q_FUNC_INFO);
1543 int resultCode = abilityResult.get<QNapi::Number>("resultCode");
1544
1545 auto wantOrEmpty = QNapi::getOptionalPropOrEmpty<QNapi::Object>(abilityResult, "want");
1546 auto jsonWant = !wantOrEmpty.IsEmpty()
1547 ? QOhosOptional<QJsonObject>(QOhosJsEnv::fromNapiValue<QJsonObject>(wantOrEmpty))
1548 : makeEmptyQOhosOptional();
1549
1550 context->resultConsumerQtContextRef.visitInQtThreadIfAlive(
1551 [context, resultCode, jsonWant](auto &) {
1552 constexpr int startedAbilityErrorResultCode = -1;
1553 context->resultConsumer(
1554 resultCode != startedAbilityErrorResultCode
1555 ? QOhosOptional<AbilityResult>({resultCode, jsonWant})
1556 : makeEmptyQOhosOptional());
1557 });
1558 })
1559 .onCatch(
1560 [context](const QtOhos::CallbackInfo &cbInfo) {
1561 QtOhos::logJsCallbackError(cbInfo, "Got error from startAbilityForResult()");
1562 context->resultConsumerQtContextRef.visitInQtThreadIfAlive(
1563 [context](auto &) {
1564 context->resultConsumer({});
1565 });
1566 });
1567 });
1568}
1569
1570void QOhosQpaFunctionsImpl::setDestroyAllowedFlagForAbilityInstances(
1571 std::vector<QObject *> instancesMainWindows, bool destroyEnabled)
1572{
1573 std::vector<QtOhos::QObjectThreadSafeRef> instancesMainWindowsRefs;
1574 for (auto *instanceMainWindow : instancesMainWindows)
1575 instancesMainWindowsRefs.emplace_back(instanceMainWindow);
1576
1578 [&](auto &jsState) {
1579 for (const auto &instanceMainWindowRef : instancesMainWindowsRefs) {
1580 auto abilityPeer = jsState.tryGetQAbilityPeerByQWindow(instanceMainWindowRef);
1581 if (abilityPeer)
1582 abilityPeer->destroyAllowedFlag()->store(destroyEnabled);
1583 }
1584 });
1585}
1586
1587void QOhosQpaFunctionsImpl::setOhosConfigDarkModeFlag(QOhosOptional<bool> darkModeFlag)
1588{
1589 setOhosConfigColorMode(
1590 darkModeFlag.hasValue()
1591 ? darkModeFlag.value()
1592 ? OhosConfigurationColorMode::COLOR_MODE_DARK
1593 : OhosConfigurationColorMode::COLOR_MODE_LIGHT
1594 : OhosConfigurationColorMode::COLOR_MODE_NOT_SET);
1595}
1596
1597QOhosSupplier<QOhosOptional<bool>> QOhosQpaFunctionsImpl::makeOhosConfigDarkModeFlagDataSource(
1598 QOhosConsumer<QOhosOptional<bool>> darkModeFlagChangedHandler)
1599{
1600 auto colorModeDataSource = makeOhosConfigColorModeDataSource(
1601 [darkModeFlagChangedHandler = std::move(darkModeFlagChangedHandler)](OhosConfigurationColorMode newColorMode) {
1602 darkModeFlagChangedHandler(
1603 mapOhosConfigurationColorModeToDarkModeFlag(newColorMode));
1604 });
1605 return [colorModeDataSource = std::move(colorModeDataSource)]() {
1606 return mapOhosConfigurationColorModeToDarkModeFlag(colorModeDataSource());
1607 };
1608}
1609
1610QOhosSupplier<double> QOhosQpaFunctionsImpl::makeOhosConfigFontSizeScaleDataSource(
1611 QOhosConsumer<double> valueChangedHandler)
1612{
1614 return makeOhosConfigValueDataSource<double>(
1615 [initFontSizeScale](QtOhos::JsState &) {
1616 return initFontSizeScale;
1617 },
1618 [](QtOhos::JsState &, const QNapi::Object &config) {
1619 return config.get<QNapi::Number>("fontSizeScale").DoubleValue();
1620 },
1621 std::move(valueChangedHandler));
1622}
1623
1624int QOhosQpaFunctionsImpl::getCurrentApplicationVersionCode()
1625{
1626 return QtOhos::evalInJsThread(
1627 [](QtOhos::JsState &jsState) {
1628 auto applicationInfoFlag = jsState.eval<QNapi::Number>(
1629 "@ohos.bundle.bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION");
1630 auto bundleInfo = jsState.eval<QNapi::Object>(
1631 "@ohos.bundle.bundleManager.getBundleInfoForSelfSync(*)", {applicationInfoFlag});
1632 int versionCode = bundleInfo.get<QNapi::Number>("versionCode");
1633
1634 return versionCode;
1635 });
1636}
1637
1638bool QOhosQpaFunctionsImpl::readOhosNoUiChildMode()
1639{
1640 return QtOhos::evalInJsThread(
1641 [&](auto &jsState) {
1642 return jsState.defaultQAbilityPeer()->instanceId().empty();
1643 });
1644}
1645
1646void QOhosQpaFunctionsImpl::startNoUiChildProcess(QString libraryName, QStringList args)
1647{
1649 [&](auto &jsState) {
1650 std::vector<std::string> argsVector;
1651 std::transform(
1652 args.begin(), args.end(), std::back_inserter(argsVector),
1653 std::mem_fn(&QString::toStdString));
1654 jsState.startNoUiChildProcess(libraryName.toStdString(), argsVector);
1655 });
1656}
1657
1658std::pair<bool, QList<QOhosQpaFunctions::FileShare::PolicyErrorResult>> QOhosQpaFunctionsImpl::persistPermission(
1659 const QList<FileShare::PolicyInfo> &policyInfos)
1660{
1661 return QtOhos::evalInJsThread(
1662 [&](QtOhos::JsState &) {
1663 std::vector<std::shared_ptr<::FileShare_PolicyErrorResult>> outResults;
1664 auto retCode = fileSharePersistPermission(
1665 convertToFileSharePolicyInfos(policyInfos), outResults);
1666
1667 return std::make_pair(isSuccessErrorCode(retCode), convertToPolicyErrorResults(outResults));
1668 });
1669}
1670
1671std::pair<bool, QList<QOhosQpaFunctions::FileShare::PolicyErrorResult>> QOhosQpaFunctionsImpl::revokePermission(
1672 const QList<FileShare::PolicyInfo> &policyInfos)
1673{
1674 return QtOhos::evalInJsThread(
1675 [&](QtOhos::JsState &) {
1676 std::vector<std::shared_ptr<::FileShare_PolicyErrorResult>> outResults;
1677 auto retCode = fileShareRevokePermission(
1678 convertToFileSharePolicyInfos(policyInfos), outResults);
1679
1680 return std::make_pair(isSuccessErrorCode(retCode), convertToPolicyErrorResults(outResults));
1681 });
1682}
1683
1684std::pair<bool, QList<QOhosQpaFunctions::FileShare::PolicyErrorResult>> QOhosQpaFunctionsImpl::activatePermission(
1685 const QList<FileShare::PolicyInfo> &policyInfos)
1686{
1687 return QtOhos::evalInJsThread(
1688 [&](QtOhos::JsState &) {
1689 std::vector<std::shared_ptr<::FileShare_PolicyErrorResult>> outResults;
1690 auto retCode = fileShareActivatePermission(
1691 convertToFileSharePolicyInfos(policyInfos), outResults);
1692
1693 return std::make_pair(isSuccessErrorCode(retCode), convertToPolicyErrorResults(outResults));
1694 });
1695}
1696
1697std::pair<bool, QList<QOhosQpaFunctions::FileShare::PolicyErrorResult>> QOhosQpaFunctionsImpl::deactivatePermission(
1698 const QList<FileShare::PolicyInfo> &policyInfos)
1699{
1700 return QtOhos::evalInJsThread(
1701 [&](QtOhos::JsState &) {
1702 std::vector<std::shared_ptr<::FileShare_PolicyErrorResult>> outResults;
1703 auto retCode = fileShareDeactivatePermission(
1704 convertToFileSharePolicyInfos(policyInfos), outResults);
1705
1706 return std::make_pair(isSuccessErrorCode(retCode), convertToPolicyErrorResults(outResults));
1707 });
1708}
1709
1710std::pair<bool, std::vector<bool>> QOhosQpaFunctionsImpl::checkPersistent(
1711 const QList<FileShare::PolicyInfo> &policyInfos)
1712{
1713 return QtOhos::evalInJsThread(
1714 [&](QtOhos::JsState &) {
1715 std::vector<bool> outResults;
1716 auto retCode = fileShareCheckPersistentPermission(
1717 convertToFileSharePolicyInfos(policyInfos), outResults);
1718
1719 return std::make_pair(isSuccessErrorCode(retCode), outResults);
1720 });
1721}
1722
1723bool QOhosQpaFunctionsImpl::showFileDialogToAuthorizeFilePath(QObject *parentWindow, const QString &filePath)
1724{
1725 auto *qWindow = qobject_cast<QWindow *>(parentWindow);
1726 if (qWindow == nullptr)
1727 qOhosReportFatalErrorAndAbort("%s: window argument is null or not a QWindow", Q_FUNC_INFO);
1728
1729 auto *platformWindow = QOhosPlatformWindow::fromQWindowOrNull(qWindow);
1730 if (platformWindow == nullptr)
1731 qOhosReportFatalErrorAndAbort("%s: failed to get platform window", Q_FUNC_INFO);
1732
1733 auto eventLoop = std::make_shared<QEventLoop>();
1734 auto filePathAuthorized = std::make_shared<bool>(false);
1735
1737 platformWindow->internalWindowId(), filePath,
1738 [filePathAuthorized, eventLoop](bool result) {
1739 *filePathAuthorized = result;
1740 eventLoop->quit();
1741 });
1742
1743 eventLoop->exec();
1744
1745 return *filePathAuthorized;
1746}
1747
1748void QOhosQpaFunctionsImpl::setWindowBrightness(QObject *window, int brightness)
1749{
1750 auto *qWindow = qobject_cast<QWindow *>(window);
1751 if (qWindow == nullptr)
1752 qOhosReportFatalErrorAndAbort("%s: window argument is null or not a QWindow", Q_FUNC_INFO);
1753
1754 QOhosPlatformWindow::setBrightness(qWindow, brightness);
1755}
1756
1757void QOhosQpaFunctionsImpl::setWindowContrast(QObject *window, int contrast)
1758{
1759 auto *qWindow = qobject_cast<QWindow *>(window);
1760 if (qWindow == nullptr)
1761 qOhosReportFatalErrorAndAbort("%s: window argument is null or not a QWindow", Q_FUNC_INFO);
1762
1763 QOhosPlatformWindow::setContrast(qWindow, contrast);
1764}
1765
1766void QOhosQpaFunctionsImpl::setWindowSaturation(QObject *window, int saturation)
1767{
1768 auto *qWindow = qobject_cast<QWindow *>(window);
1769 if (qWindow == nullptr)
1770 qOhosReportFatalErrorAndAbort("%s: window argument is null or not a QWindow", Q_FUNC_INFO);
1771
1772 QOhosPlatformWindow::setSaturation(qWindow, saturation);
1773}
1774
1775bool QOhosQpaFunctionsImpl::shareDataUsingShareKit(
1776 QObject *optWindowObject, const QList<ShareKit::SharedRecord> &recordsToShare,
1777 const ShareKit::ShareControllerOptions &controllerOptions)
1778{
1779 return !!shareDataUsingShareKit(
1780 optWindowObject, recordsToShare, controllerOptions, makeQOhosNoOpConsumer());
1781}
1782
1783std::shared_ptr<void> QOhosQpaFunctionsImpl::shareDataUsingShareKit(
1784 QObject *optWindowObject, const QList<ShareKit::SharedRecord> &recordsToShare,
1785 const ShareKit::ShareControllerOptions &controllerOptions,
1786 std::function<void()> panelClosedCallback)
1787{
1788 auto *optQWindow = qobject_cast<QWindow *>(optWindowObject);
1789 if (optWindowObject != nullptr && optQWindow == nullptr)
1790 qOhosReportFatalErrorAndAbort("%s: window argument is not a QWindow", Q_FUNC_INFO);
1791
1792 std::vector<QOhosShareKit::SharedRecord> shareKitRecords;
1793 for (const auto &record : recordsToShare) {
1794 shareKitRecords.push_back(
1795 QOhosShareKit::SharedRecord{
1796 .mimeType = record.mimeType.toStdString(),
1797 .content = record.content.transform(std::mem_fn(&QString::toStdString)),
1798 .filePath = record.filePath.transform(std::mem_fn(&QString::toStdString)),
1799 .title = record.title.transform(std::mem_fn(&QString::toStdString)),
1800 .label = record.label.transform(std::mem_fn(&QString::toStdString)),
1801 .description = record.description.transform(std::mem_fn(&QString::toStdString)),
1802 .thumbnail = record.thumbnail,
1803 .thumbnailFilePath = record.thumbnailFilePath.transform(std::mem_fn(&QString::toStdString)),
1804 .extraData = record.extraData,
1805 });
1806 }
1807
1808 auto shareKitControllerOptions = QOhosShareKit::ControllerOptions{
1809 .anchor = controllerOptions.anchorOffset.transform(
1810 [&](auto anchorOffset) {
1812 .windowOffset = anchorOffset,
1813 .size = controllerOptions.anchorSize,
1814 };
1815 }),
1816 .selectionMode = controllerOptions.useSingleSelectionMode.transform(
1817 [](auto singleSelectionMode) {
1818 return singleSelectionMode
1821 }),
1822 .previewMode = controllerOptions.useDefaultPreviewMode.transform(
1823 [](auto defaultPreviewMode) {
1824 return defaultPreviewMode
1827 }),
1828 .excludedAbilities = controllerOptions.excludedAbilities.transform(
1829 [](const auto &excludedAbilities) {
1830 std::vector<QOhosShareKit::ShareAbilityType> outExcludedAbilities;
1831 for (auto excludedAbilityType : excludedAbilities) {
1832 outExcludedAbilities.push_back(
1833 mapShareAbilityTypeFromQpaFunctionsEnum(excludedAbilityType));
1834 }
1835 return outExcludedAbilities;
1836 }),
1837 };
1838
1839 return QOhosShareKit::shareData(
1840 optQWindow, shareKitRecords, shareKitControllerOptions, std::move(panelClosedCallback));
1841}
1842
1843bool QOhosQpaFunctionsImpl::tryOpenLink(QObject *optInstanceMainWindow, const QString &link, QOhosOptional<bool> appLinkingOnly)
1844{
1845 if (optInstanceMainWindow != nullptr && qobject_cast<QWindow *>(optInstanceMainWindow) == nullptr)
1846 qOhosReportFatalErrorAndAbort("%s: the main window argument is not a QWindow", Q_FUNC_INFO);
1847
1848 auto optInstanceMainWindowRef = optInstanceMainWindow != nullptr
1849 ? makeQOhosOptional(QtOhos::QObjectThreadSafeRef(optInstanceMainWindow))
1851
1852 return QtOhos::evalInJsThreadWithConsumer<bool>(
1853 [&](QtOhos::JsState &jsState, QOhosConsumer<bool> resultConsumer) {
1854 auto optAbilityPeer = tryMapOptMainWindowToAbilityPeer(jsState, optInstanceMainWindowRef);
1855 if (!optAbilityPeer) {
1856 resultConsumer(false);
1857 return;
1858 }
1859
1860 std::vector<std::pair<std::string, QNapi::ValueWrapper>> openLinkOptions;
1861 if (appLinkingOnly.hasValue())
1862 openLinkOptions.emplace_back("appLinkingOnly", appLinkingOnly.value());
1863
1864 optAbilityPeer->qAbility().call<QNapi::Promise>(
1865 "context.openLink",
1866 {
1867 link.toStdString(),
1868 QNapi::makeObject(jsState.env(), openLinkOptions),
1869 })
1870 .withContext(std::move(resultConsumer))
1871 .onThenWithContext(
1872 [](QOhosConsumer<bool> &resultConsumer) {
1873 resultConsumer(true);
1874 })
1875 .onCatchWithContext(
1876 [](const QtOhos::CallbackInfo &cbInfo, QOhosConsumer<bool> &resultConsumer) {
1877 QtOhos::logJsCallbackError(cbInfo, "Got error from openLink()");
1878 resultConsumer(false);
1879 });
1880 });
1881}
1882
1883QObject *QOhosQpaFunctionsImpl::getActiveWindowOrNull() const
1884{
1885 const auto focusedWindows = QWindowProxyRegistry::instance().queryWindowsWithSystemWindowAndFocus();
1886 return !focusedWindows.empty() ? focusedWindows.front() : nullptr;
1887}
1888
1889}
1890
1892
1894
1895QOhosQpaFunctions::WantInfo::WantInfo() = default;
1896
1897QOhosQpaFunctions::WantInfo::~WantInfo() = default;
1898
1900{
1901 static QOhosQpaFunctionsImpl qpaFunctions;
1902 return qpaFunctions;
1903}
1904
1905}
1906
1907QT_END_NAMESPACE
std::enable_if_t< qohosplugincore_h_detail::isQOhosOptional< QOhosInvokeResult< Func, T > >, QOhosInvokeResult< Func, T > > andThen(Func &&func) const
static void setInAppOnlyPasteboardShareOption(bool shareInAppOnly)
static void setMainWindowGeometryPersistencePolicy(WindowGeometryPersistencePolicy policy)
static QWindowProxyRegistry & instance()
virtual double getFontSizeScale()=0
static std::shared_ptr< QUiAbilityPeer > tryCastFromQAbilityPeerOrNull(std::shared_ptr< QAbilityPeer > qAbilityPeer)
double fontSizeScale()
void showFileDialogAuthorization(QtOhos::InternalWindowId contextWinId, QString filePath, QOhosConsumer< bool > resultCallback)
void invokeInJsThread(std::function< void(JsState &)> task)
QOhosQpaFunctions & getQOhosQpaFunctions()
bool isOhosNoUiChildMode()
QOhosAbilityOnContinueResult
void runInJsThreadAndWait(const std::function< void(JsState &)> &task)
void invokeInJsThreadAndWaitForContinue(std::function< void(JsState &, std::function< void()>)> &&task)
QOhosOptional< void > makeEmptyQOhosOptional()