4#include <render/qohoswindowproxy.h>
6#include <QtCore/QCoreApplication>
8#include <QtCore/private/qnapi_p.h>
9#include <qohosjsenv_p.h>
10#include <QtCore/qscopeguard.h>
11#include <QtGui/private/qohosimageconversions_p.h>
12#include <QtGui/qguiapplication.h>
13#include <QtGui/qimage.h>
17#include <multimedia/image_framework/image/pixelmap_native.h>
18#include <qarkui/input.h>
19#include <qarkui/qarkuiutils.h>
20#include <qarkui/qxcomponentregistry.h>
21#include <qarkui/window.h>
22#include <qarkui/window_manager.h>
23#include <qohosdeviceinfo_p.h>
24#include <qohosdisplayinfo.h>
25#include <qohosenums.h>
26#include <qohosjsutils.h>
27#include <qohospixelmapconversions.h>
28#include <qohosplugincore.h>
29#include <qohossettings.h>
30#include <qohosutils.h>
31#include <render/qohosbatchingrequestshandler.h>
32#include <render/qohosjswindowregistry.h>
33#include <render/qohoswindowproxydatafactory.h>
34#include <render/qxcomponent.h>
48 ohosWindowRect.get<QNapi::Number>(
"left"),
49 ohosWindowRect.get<QNapi::Number>(
"top"),
50 ohosWindowRect.get<QNapi::Number>(
"width"),
51 ohosWindowRect.get<QNapi::Number>(
"height"),
58 .visible = avoidAreaObject.get<QNapi::Boolean>(
"visible"),
59 .leftRect = ohosWindowRectToQRect(avoidAreaObject.get<QNapi::Object>(
"leftRect")),
60 .topRect = ohosWindowRectToQRect(avoidAreaObject.get<QNapi::Object>(
"topRect")),
61 .rightRect = ohosWindowRectToQRect(avoidAreaObject.get<QNapi::Object>(
"rightRect")),
62 .bottomRect = ohosWindowRectToQRect(avoidAreaObject.get<QNapi::Object>(
"bottomRect")),
71 case Qt::UpArrowCursor:
79 case Qt::SizeVerCursor:
81 case Qt::SizeHorCursor:
83 case Qt::SizeBDiagCursor:
85 case Qt::SizeFDiagCursor:
87 case Qt::SizeAllCursor:
92 case Qt::SplitVCursor:
94 case Qt::SplitHCursor:
96 case Qt::PointingHandCursor:
98 case Qt::ForbiddenCursor:
100 case Qt::WhatsThisCursor:
104 case Qt::OpenHandCursor:
106 case Qt::ClosedHandCursor:
108 case Qt::DragCopyCursor:
110 case Qt::DragMoveCursor:
112 case Qt::DragLinkCursor:
115 case Qt::BitmapCursor:
118 case Qt::CustomCursor:
128 auto propOrEmpty = QNapi::getOptionalPropOrEmpty<QNapi::Number>(object, propertyName);
129 return !propOrEmpty.IsEmpty()
130 ?
std::optional<
double>(propOrEmpty)
136 auto windowPropsObj = jsWindow.eval<QNapi::Object>(
"getWindowProperties()");
137 auto displayIdOrEmpty = QNapi::getOptionalPropOrEmpty<QNapi::Number>(windowPropsObj,
"displayId");
138 return QArkUi::WindowProperties {
139 .windowRect = ohosWindowRectToQRect(windowPropsObj.get<QNapi::Object>(
"windowRect")),
140 .drawableRect = ohosWindowRectToQRect(windowPropsObj.get<QNapi::Object>(
"drawableRect")),
141 .id = QArkUi::JsWindowId(windowPropsObj.get<QNapi::Number>(
"id")),
142 .displayId = !displayIdOrEmpty.IsEmpty()
143 ? std::optional(QOhosDisplayInfo::JsDisplayId{displayIdOrEmpty.DoubleValue()})
150 auto moveConfigurationObject = QNapi::makeObject(env);
151 if (moveConfiguration.displayId.has_value()) {
152 moveConfigurationObject.set(
153 "displayId", moveConfiguration.displayId.value().value());
155 return moveConfigurationObject;
158template<
typename ...Args>
160 std::function<
void(Args...)> QOhosWindowProxy::WindowCallbacks::*memberPtr,
163 auto weakQtWindowCallbacks = QtOhos::makeWeakPtr(qtWindowCallbacks);
165 return [memberPtr, weakQtWindowCallbacks](Args ...args) {
166 QtOhos::invokeInQtThread([memberPtr, weakQtWindowCallbacks, args...]() {
167 auto qtWindowCallbacks = weakQtWindowCallbacks.lock();
168 if (qtWindowCallbacks)
169 (*qtWindowCallbacks.*memberPtr)(args...);
176 std::function<
void(T)> QOhosWindowProxy::WindowCallbacks::*memberPtr,
179 auto weakQtWindowCallbacks = QtOhos::makeWeakPtr(qtWindowCallbacks);
181 return QtOhos::makeCompressingAsyncConsumer<T>(
182 [memberPtr, weakQtWindowCallbacks](T value) {
183 auto qtWindowCallbacks = weakQtWindowCallbacks.lock();
184 if (qtWindowCallbacks)
185 (*qtWindowCallbacks.*memberPtr)(value);
187 QtOhos::invokeInQtThread);
192 constexpr bool containsPolicyExcludeEdgeValue =
true;
194 auto drawableRectInScreenSpace =
195 windowProperties.drawableRect.translated(windowProperties.windowRect.topLeft());
196 return !drawableRectInScreenSpace.contains(point, containsPolicyExcludeEdgeValue);
202 case ::MOUSE_ACTION_MOVE:
203 return QEvent::NonClientAreaMouseMove;
204 case ::MOUSE_ACTION_BUTTON_DOWN:
205 return QEvent::NonClientAreaMouseButtonPress;
206 case ::MOUSE_ACTION_BUTTON_UP:
207 return QEvent::NonClientAreaMouseButtonRelease;
208 case ::MOUSE_ACTION_CANCEL:
209 case ::MOUSE_ACTION_AXIS_BEGIN:
210 case ::MOUSE_ACTION_AXIS_UPDATE:
211 case ::MOUSE_ACTION_AXIS_END:
220 case ::MOUSE_BUTTON_LEFT:
221 return Qt::LeftButton;
222 case ::MOUSE_BUTTON_MIDDLE:
223 return Qt::MiddleButton;
224 case ::MOUSE_BUTTON_RIGHT:
225 return Qt::RightButton;
226 case ::MOUSE_BUTTON_FORWARD:
227 return Qt::ForwardButton;
228 case ::MOUSE_BUTTON_BACK:
229 return Qt::BackButton;
230 case ::MOUSE_BUTTON_NONE:
239 case ::TOUCH_ACTION_MOVE:
240 return QEventPoint::State::Updated;
241 case ::TOUCH_ACTION_DOWN:
242 return QEventPoint::State::Pressed;
243 case ::TOUCH_ACTION_UP:
244 return QEventPoint::State::Released;
245 case ::TOUCH_ACTION_CANCEL:
251template<
typename EnumsContainer>
255 for (
auto enumValue : enums) {
258 output +=
std::to_string(
static_cast<std::underlying_type_t<
decltype(enumValue)>>(enumValue));
267 return QtOhos::JsWindowsTracker::isWindowClosing(jsWindow) || (boundToAbility && abilityPeer->isTerminating());
272const QOhosWindowProxy::EventHandlerDescriptor QOhosWindowProxy::eventHandlerDescriptors[] = {
274 .eventName =
"avoidAreaChange",
275 .eventHandler = &QOhosWindowProxy::JsScopeData::handleAvoidAreaChangeCallback,
276 .eventHandlerFlags = {},
279 .eventName =
"touchOutside",
280 .eventHandler = &QOhosWindowProxy::JsScopeData::handleWindowTouchOutsideCallback,
281 .eventHandlerFlags = {},
284 .eventName =
"windowEvent",
285 .eventHandler = &QOhosWindowProxy::JsScopeData::handleWindowEventCallback,
286 .eventHandlerFlags = EventHandlerFlagBits::allowCallWhenAbilityIsTerminating,
289 .eventName =
"windowRectChange",
290 .eventHandler = &QOhosWindowProxy::JsScopeData::handleWindowRectChangeCallback,
291 .eventHandlerFlags = {},
294 .eventName =
"rectChangeInGlobalDisplay",
295 .eventHandler = &QOhosWindowProxy::JsScopeData::handleWindowRectChangeInGlobalDisplayCallback,
296 .eventHandlerFlags = {},
299 .eventName =
"windowStatusChange",
300 .eventHandler = &QOhosWindowProxy::JsScopeData::handleWindowStatusCallback,
301 .eventHandlerFlags = {},
304 .eventName =
"windowVisibilityChange",
305 .eventHandler = &QOhosWindowProxy::JsScopeData::handleWindowVisibilityCallback,
306 .eventHandlerFlags = {},
309 .eventName =
"displayIdChange",
310 .eventHandler = &QOhosWindowProxy::JsScopeData::handleWindowDisplayIdChangeCallback,
311 .eventHandlerFlags = EventHandlerFlagBits::allowEventHandlerRegistrationFailure,
315QOhosWindowProxy::QOhosWindowProxy(
318 QtOhos::makeProxyWithJsThreadDeleter(
319 std::make_shared<JsScopeData>(
320 windowProxyData.windowProxyType,
321 std::move(windowProxyData.jsWindow),
322 std::move(windowProxyData.jsKeepAliveData),
323 std::move(windowProxyData.qAbilityPeer),
324 windowProxyData.owningQWindowRef)))
326 , m_nodeXComponent(windowProxyData.nodeXComponent)
327 , m_qAbilityInstanceId(m_jsScopeData->qAbilityPeer->instanceId())
329 std::vector<std::shared_ptr<
void>> eventListenersHandles;
330 for (
const auto &eventHandlerDescriptor : eventHandlerDescriptors) {
331 eventListenersHandles.push_back(
332 m_jsScopeData->registerEventListener(
333 eventHandlerDescriptor.eventName, eventHandlerDescriptor.eventHandler,
334 eventHandlerDescriptor.eventHandlerFlags));
336 m_jsScopeData->m_eventListenersHandle = QtOhos::moveToSharedPtr(std::move(eventListenersHandles));
346 m_subWindowCloseRegistrationHandle.reset();
347 m_jsScopeData.reset();
354 if (m_jsScopeData->isWindowClosing()) {
358 auto optQUiAbilityPeer
360 if (!optQUiAbilityPeer) {
364 auto promise = optQUiAbilityPeer->windowStage().evalToPromiseOrRejectOnThrow(
365 "removeStartingWindow()");
366 promise.onFinally(
std::move(taskPromise).makeChained(Q_FUNC_INFO));
374 auto displayIdValue = optMoveToTargetDisplay.value_or(QOhosDisplayInfo::JsDisplayId(-1)).value();
375 qOhosPrintfDebug(
"%s: %d,%d,%f", Q_FUNC_INFO, point.x(), point.y(), displayIdValue);
378 [&](
QtOhos::
JsState &jsState, QOhosTaskPromise<> taskPromise) {
379 if (m_jsScopeData->isWindowClosing()) {
384 const auto primaryJsDisplayId = QOhosDisplayInfo::JsDisplayId(0);
386 auto targetDisplayId = optMoveToTargetDisplay.has_value()
387 ? optMoveToTargetDisplay.value()
390 auto optDisplayInfo = qTransform(
391 QOhosDisplayInfo::tryGetDisplayById(jsState, targetDisplayId),
392 [&](
auto displayObject) {
393 return QOhosDisplayInfo::makeFromOhosDisplayObject(jsState, displayObject);
396 auto optIsDisplayMainOrExtended = qTransform(
402 bool isDisplayMainOrExtended;
403 if (optIsDisplayMainOrExtended.has_value()) {
404 isDisplayMainOrExtended = optIsDisplayMainOrExtended.value();
407 "%s: no display source mode detected. Assumming main/extended screen", Q_FUNC_INFO);
408 isDisplayMainOrExtended =
true;
411 QNapi::Promise promise;
412 if (!isDisplayMainOrExtended) {
413 auto optDisplayOffset = qAndThen(
416 return displayInfo.topLeftOffsetPixels;
419 const QPoint defaultDisplayOffset(0, 0);
420 auto targetCoordinates = point - optDisplayOffset.value_or(defaultDisplayOffset);
422 if (!optMoveToTargetDisplay.has_value())
423 qOhosPrintfWarning(
"%s: trying to move window to not valid target display", Q_FUNC_INFO);
425 auto moveConfigurationObject = toNapiObject(
428 .displayId = optMoveToTargetDisplay,
431 promise = m_jsScopeData->jsWindowRef->evalToPromiseOrRejectOnThrow(
432 "moveWindowToGlobal(*)", {targetCoordinates.x(), targetCoordinates.y(), moveConfigurationObject});
434 promise = m_jsScopeData->jsWindowRef->evalToPromiseOrRejectOnThrow(
435 "moveWindowToGlobalDisplay(*)", {point.x(), point.y()});
438 promise.onFinally(
std::move(taskPromise));
442void QOhosWindowProxy::
setSize(
const QSize &size)
444 qOhosPrintfDebug(
"%s: %d,%d", Q_FUNC_INFO, size.width(), size.height());
448 if (m_jsScopeData->isWindowClosing()) {
452 auto promise = m_jsScopeData->jsWindowRef->evalToPromiseOrRejectOnThrow(
453 "resizeAsync(*)", {size.width(), size.height()});
454 promise.onFinally(
std::move(taskPromise).makeChained(Q_FUNC_INFO));
461 qCDebug(QtForOhos) << Q_FUNC_INFO << color;
464 if (m_jsScopeData->isWindowClosing())
466 m_jsScopeData->jsWindowRef->eval(
"setWindowBackgroundColor(*)", {color.name(QColor::HexArgb).toStdString()});
471void QOhosWindowProxy::
setCustomCursor(
const QImage &customCursorImage,
const QPoint &hotSpot)
473 const auto maxOhosCustomCursorSize = QSize(256, 256);
474 const auto customCursorSize = customCursorImage.size();
475 if (customCursorSize.width() > maxOhosCustomCursorSize.width()
476 || customCursorSize.height() > maxOhosCustomCursorSize.height()) {
478 "%s: can't set %dx%d custom cursor, OHOS max custom cursor size is %dx%d",
479 Q_FUNC_INFO, customCursorSize.width(), customCursorSize.height(),
480 maxOhosCustomCursorSize.width(), maxOhosCustomCursorSize.height());
484 auto convertedImage = customCursorImage.convertToFormat(QImage::Format_RGBA8888);
486 if (m_jsScopeData->isWindowClosing()) {
490 auto windowId = m_jsScopeData->jsWindowRef->jsObject().get<QNapi::Number>(
"getWindowProperties().id");
492 auto jsCursor = QNapi::makeObject(
495 {
"pixelMap", makeOhosNapiPixelMapFromQImage(jsState, convertedImage)},
496 {
"focusX", hotSpot.x()},
497 {
"focusY", hotSpot.y()},
500 auto jsCursorConfig = QNapi::makeObject(
503 {
"followSystem",
false},
506 jsState.evalToPromiseOrRejectOnThrow(
507 "@ohos.multimodalInput.pointer.setCustomCursor(*)", {windowId, jsCursor, jsCursorConfig})
508 .onCatch(QtOhos::makeErrorLoggingJsCallback(
"setCustomCursor()"))
509 .onFinally(
std::move(taskPromise).makeChained(Q_FUNC_INFO));
517 if (m_jsScopeData->isWindowClosing())
519 auto windowId = m_jsScopeData->jsWindowRef->jsObject().get<QNapi::Number>(
"getWindowProperties().id");
522 "@ohos.multimodalInput.pointer.setPointerStyleSync(*)",
523 {windowId, jsState.mapOhosEnumToJs(convertToOhosCursor(cursor.shape()))});
530 return QtOhos::evalInJsThread(
532 if (m_jsScopeData->isWindowClosing())
533 return QArkUi::WindowProperties {};
534 return getWindowPropertiesFromJsWindow(m_jsScopeData->jsWindowRef->jsObject());
544 m_jsScopeData->windowCallbackReceiver = QtOhos::moveToSharedPtr(WindowCallbacks {
545 .onWindowEvent = makeQtThreadWindowCallbackDelegate(&WindowCallbacks::onWindowEvent, sharedWindowCallbackReceiver),
546 .onWindowStatusChange = makeQtThreadWindowCallbackDelegate(&WindowCallbacks::onWindowStatusChange, sharedWindowCallbackReceiver),
547 .onWindowVisibilityChange = makeQtThreadWindowCallbackDelegate(&WindowCallbacks::onWindowVisibilityChange, sharedWindowCallbackReceiver),
548 .onTouchOutside = makeQtThreadWindowCallbackDelegate(&WindowCallbacks::onTouchOutside, sharedWindowCallbackReceiver),
549 .onAvoidAreaChange = makeQtThreadWindowCallbackDelegate(&WindowCallbacks::onAvoidAreaChange, sharedWindowCallbackReceiver),
550 .onWindowRectChange = makeCompressingQtThreadWindowCallbackDelegate(&WindowCallbacks::onWindowRectChange, sharedWindowCallbackReceiver),
551 .onWindowRectChangeInGlobalDisplay = makeCompressingQtThreadWindowCallbackDelegate(&WindowCallbacks::onWindowRectChangeInGlobalDisplay, sharedWindowCallbackReceiver),
552 .onWindowDisplayIdChange = makeQtThreadWindowCallbackDelegate(&WindowCallbacks::onWindowDisplayIdChange, sharedWindowCallbackReceiver),
557 m_qtWindowCallbacksReceiverHandle = sharedWindowCallbackReceiver;
561 QObject *contextObject, QOhosConsumer<std::vector<NonClientAreaMouseEvent>> mouseEventBatchConsumer)
563 auto qtConsumer = QtOhos::moveToSharedPtr(std::move(mouseEventBatchConsumer));
564 auto weakQtConsumer = QtOhos::makeWeakPtr(qtConsumer);
567 QtOhos::QObjectThreadSafeRef(contextObject),
568 [weakQtConsumer](std::vector<NonClientAreaMouseEvent> &&batch) {
569 auto qtConsumer = weakQtConsumer.lock();
571 (*qtConsumer)(
std::move(batch));
575 m_jsScopeData->nonClientAreaMouseEventConsumer = std::move(jsConsumer);
579 m_qtNonClientAreaMouseWindowCallbackReceiverHandle = qtConsumer;
583 QObject *contextObject, QOhosConsumer<std::vector<NonClientAreaTouchEvent>> touchEventBatchConsumer)
585 auto qtConsumer = QtOhos::moveToSharedPtr(std::move(touchEventBatchConsumer));
586 auto weakQtConsumer = QtOhos::makeWeakPtr(qtConsumer);
589 QtOhos::QObjectThreadSafeRef(contextObject),
590 [weakQtConsumer](std::vector<NonClientAreaTouchEvent> &&batch) {
591 auto qtConsumer = weakQtConsumer.lock();
593 (*qtConsumer)(
std::move(batch));
597 m_jsScopeData->nonClientAreaTouchEventConsumer = std::move(jsConsumer);
601 m_qtNonClientAreaTouchWindowCallbackReceiverHandle = qtConsumer;
611 return m_windowProxyType;
616 qCDebug(QtForOhos,
"%s", Q_FUNC_INFO);
618 if (m_jsScopeData->isWindowClosing()) {
622 auto promise = m_jsScopeData->jsWindowRef->evalToPromiseOrRejectOnThrow(
"raiseToAppTop()");
623 promise.onFinally(
std::move(taskPromise).makeChained(Q_FUNC_INFO));
630 qCDebug(QtForOhos,
"%s", Q_FUNC_INFO);
632 if (m_jsScopeData->isWindowClosing()) {
637 std::vector<std::pair<std::string, QNapi::ValueWrapper>> jsOptionsProps;
639 if (options.focusOnShow.has_value())
640 jsOptionsProps.emplace_back(
"focusOnShow", options.focusOnShow.value());
642 std::vector<QNapi::ValueWrapper> showWindowArgs;
643 constexpr bool brokenHandlingOfEmptyOptionsParamInOhos =
true;
644 if (!(jsOptionsProps.empty() && brokenHandlingOfEmptyOptionsParamInOhos))
645 showWindowArgs.push_back(QNapi::makeObject(jsState.env(), jsOptionsProps));
647 auto promise = m_jsScopeData->jsWindowRef->evalToPromiseOrRejectOnThrow(
"showWindow(*)", showWindowArgs);
648 promise.onFinally(
std::move(taskPromise).makeChained(Q_FUNC_INFO));
655 qCDebug(QtForOhos,
"%s", Q_FUNC_INFO);
657 if (m_jsScopeData->isWindowClosing())
659 m_jsScopeData->jsWindowRef->eval(
"recover()");
666 qCDebug(QtForOhos,
"%s", Q_FUNC_INFO);
668 if (m_jsScopeData->isWindowClosing()) {
672 m_jsScopeData->jsWindowRef->evalToPromiseOrRejectOnThrow(
"restore()").onFinally(std::move(taskPromise).makeChained(Q_FUNC_INFO));
679 qCDebug(QtForOhos,
"%s", Q_FUNC_INFO);
681 if (m_jsScopeData->isWindowClosing()) {
685 m_jsScopeData->jsWindowRef->evalToPromiseOrRejectOnThrow(
"minimize()").onFinally(std::move(taskPromise).makeChained(Q_FUNC_INFO));
692 qCDebug(QtForOhos,
"%s", Q_FUNC_INFO);
695 qCWarning(QtForOhos(),
"%s: Maximize is currently supported only on main windows", Q_FUNC_INFO);
700 if (m_jsScopeData->isWindowClosing())
702 m_jsScopeData->jsWindowRef->eval(
"maximize(*)", {jsState.mapOhosEnumToJs(maximizePresentation)});
709 qCDebug(QtForOhos,
"%s: %s", Q_FUNC_INFO, isLayoutFullScreen ?
"true" :
"false");
712 if (m_jsScopeData->isWindowClosing()) {
716 m_jsScopeData->jsWindowRef->evalToPromiseOrRejectOnThrow(
717 "setWindowLayoutFullScreen(*)", {isLayoutFullScreen})
718 .onCatch(QtOhos::makeErrorLoggingJsCallback(
"setWindowLayoutFullScreen()"))
719 .onFinally(std::move(taskPromise).makeChained(Q_FUNC_INFO));
726 qCDebug(QtForOhos) << Q_FUNC_INFO << names;
728 [&](
QtOhos::
JsState &jsState, QOhosTaskPromise<> taskPromise) {
729 if (m_jsScopeData->isWindowClosing()) {
733 m_jsScopeData->jsWindowRef->evalToPromiseOrRejectOnThrow(
734 "setWindowSystemBarEnable(*)",
735 {QNapi::makeArray(jsState.env(), names, std::mem_fn(&QString::toStdString))})
736 .onCatch(QtOhos::makeErrorLoggingJsCallback(
"setWindowSystemBarEnable()"))
737 .onFinally(std::move(taskPromise).makeChained(Q_FUNC_INFO));
744 qCDebug(QtForOhos,
"%s", Q_FUNC_INFO);
747 if (m_jsScopeData->isWindowClosing()) {
752 m_jsScopeData->qAbilityPeer->qAbility().evalToPromiseOrRejectOnThrow(
"context.showAbility()")
753 .onCatch(QtOhos::makeErrorLoggingJsCallback(
"showAbility()"))
754 .onFinally(std::move(taskPromise).makeChained(Q_FUNC_INFO));
761 qCDebug(QtForOhos,
"%s", Q_FUNC_INFO);
763 return QtOhos::evalInJsThreadWithPromise<
bool>([&](
QtOhos::
JsState &, QOhosTaskPromise<
bool> evalPromise) {
764 if (m_jsScopeData->isWindowClosing()) {
769 auto thenCatchPromises =
std::move(evalPromise).makeThenCatchBranches(Q_FUNC_INFO);
770 m_jsScopeData->qAbilityPeer->qAbility().evalToPromiseOrRejectOnThrow(
"context.hideAbility()")
772 [thenPromise = std::move(thenCatchPromises.first)](
const QtOhos::CallbackInfo &) {
776 [catchPromise = std::move(thenCatchPromises.second)](
const QtOhos::CallbackInfo &cbInfo) {
777 QtOhos::logJsCallbackError(cbInfo,
"got error from hideAbility()");
786 return QtOhos::evalInJsThread(
788 if (m_jsScopeData->isWindowClosing())
790 return m_jsScopeData->jsWindowRef->eval<QNapi::Boolean>(
"getImmersiveModeEnabledState()").Value();
797 qCDebug(QtForOhos,
"%s: %s", Q_FUNC_INFO, privacyMode ?
"true" :
"false");
800 if (m_jsScopeData->isWindowClosing()) {
805 m_jsScopeData->jsWindowRef->evalToPromiseOrRejectOnThrow(
"setWindowPrivacyMode(*)", {privacyMode})
806 .onCatch(QtOhos::makeErrorLoggingJsCallback(
"setPrivacyMode()"))
807 .onFinally(std::move(taskPromise).makeChained(Q_FUNC_INFO));
814 qCDebug(QtForOhos,
"%s: %s", Q_FUNC_INFO, focusable ?
"true" :
"false");
816 if (m_jsScopeData->isWindowClosing())
818 m_jsScopeData->jsWindowRef->eval(
"setWindowFocusable(*)", {focusable});
825 qCDebug(QtForOhos,
"%s: %s", Q_FUNC_INFO, touchable ?
"true" :
"false");
827 if (m_jsScopeData->isWindowClosing())
829 m_jsScopeData->jsWindowRef->eval(
"setWindowTouchable(*)", {touchable});
837 QtForOhos,
"%s: (%d x %d)-(%d x %d)", Q_FUNC_INFO, minSize.width(), minSize.height(),
838 maxSize.width(), maxSize.height());
840 [&](
QtOhos::
JsState &jsState, QOhosTaskPromise<> taskPromise) {
841 if (m_jsScopeData->isWindowClosing()) {
845 auto windowLimits = QNapi::makeObject(
848 {
"minWidth", minSize.width()},
849 {
"minHeight", minSize.height()},
850 {
"maxWidth", maxSize.width()},
851 {
"maxHeight", maxSize.height()},
854 std::vector<QNapi::ValueWrapper> setWindowLimitsArgs = {windowLimits};
856 constexpr bool isForcible =
true;
857 setWindowLimitsArgs.push_back(isForcible);
859 m_jsScopeData->jsWindowRef->evalToPromiseOrRejectOnThrow(
860 "setWindowLimits(*)", setWindowLimitsArgs)
861 .onCatch(QtOhos::makeErrorLoggingJsCallback(
"setWindowLimits()"))
862 .onFinally(std::move(taskPromise).makeChained(Q_FUNC_INFO));
869 qCDebug(QtForOhos,
"%s", Q_FUNC_INFO);
870 return QtOhos::evalInJsThread(
872 if (m_jsScopeData->isWindowClosing())
873 return WindowLimits {};
874 auto windowLimitsObject = m_jsScopeData->jsWindowRef->eval<QNapi::Object>(
"getWindowLimits()");
875 return WindowLimits {
876 .minWidth = getOptionalNumberPropAsOptionalDouble(windowLimitsObject,
"minWidth"),
877 .minHeight = getOptionalNumberPropAsOptionalDouble(windowLimitsObject,
"minHeight"),
878 .maxWidth = getOptionalNumberPropAsOptionalDouble(windowLimitsObject,
"maxWidth"),
879 .maxHeight = getOptionalNumberPropAsOptionalDouble(windowLimitsObject,
"maxHeight"),
887 qCDebug(QtForOhos,
"%s: %d", Q_FUNC_INFO, avoidAreaType);
888 return QtOhos::evalInJsThread(
890 if (m_jsScopeData->isWindowClosing())
892 auto avoidAreaObject = m_jsScopeData->jsWindowRef->eval<QNapi::Object>(
893 "getWindowAvoidArea(*)", {jsState.mapOhosEnumToJs(avoidAreaType)});
894 return mapAvoidAreaFromJs(avoidAreaObject);
900 const WindowMask &windowMask,
const std::optional<QSize> &ohosMaskSizeOverride)
905 auto ohosMaskSize = ohosMaskSizeOverride.has_value()
906 ? ohosMaskSizeOverride.value()
909 if (ohosMaskSize.isEmpty()) {
910 const auto *maskSrcSizeMsg = ohosMaskSizeOverride.has_value()
911 ?
"overridden mask source"
913 if (ohosMaskSizeOverride.has_value()) {
915 "%s failed - %s size is 0x0", maskSrcSizeMsg,
916 "QOhosWindowProxy::setWindowMask");
922 if (m_jsScopeData->isWindowClosing()) {
926 auto *env = jsState.env();
928 QNapi::Array maskRowsArray = QNapi::Array::New(env, ohosMaskSize.height());
929 const int defaultValue = windowMask.windowMaskRegion.isEmpty() ? 1 : 0;
931 for (
int rowIndex = 0; rowIndex < ohosMaskSize.height(); ++rowIndex) {
932 auto arr = QNapi::Array::New(env, ohosMaskSize.width());
933 arr.fill(defaultValue);
934 maskRowsArray[rowIndex] = arr;
937 auto valueToSet = QNapi::Number::New(env, 1);
938 for (
const auto &rect: windowMask.windowMaskRegion) {
939 auto top = qBound(0, rect.top(), ohosMaskSize.height() - 1);
940 auto bottom = qBound(0, rect.bottom(), ohosMaskSize.height() - 1);
941 auto left = qBound(0, rect.left(), ohosMaskSize.width() - 1);
942 auto right = qBound(0, rect.right(), ohosMaskSize.width() - 1);
944 for (
auto rowIndex = top; rowIndex <= bottom; ++rowIndex) {
945 auto row = maskRowsArray.Get(rowIndex).As<QNapi::Array>();
946 for (
auto columnIndex = left; columnIndex <= right; ++columnIndex)
947 row[columnIndex] = valueToSet;
951 m_jsScopeData->jsWindowRef->evalToPromiseOrRejectOnThrow(
"setWindowMask(*)", {maskRowsArray})
952 .onCatch(QtOhos::makeErrorLoggingJsCallback(
"setWindowMask()"))
953 .onFinally(std::move(taskPromise).makeChained(Q_FUNC_INFO));
965 if (m_jsScopeData->isWindowClosing()) {
969 m_jsScopeData->jsWindowRef->evalToPromiseOrRejectOnThrow(
"setSubWindowModal(*)", {
false})
970 .onCatch(QtOhos::makeErrorLoggingJsCallback(
"setSubWindowModal()"))
971 .onFinally(std::move(taskPromise).makeChained(Q_FUNC_INFO));
983 "%s: APPLICATION_MODALITY option can be used only on devices in the freeform window state - skipping",
989 [&](
QtOhos::
JsState &jsState, QOhosTaskPromise<> taskPromise) {
990 if (m_jsScopeData->isWindowClosing()) {
994 m_jsScopeData->jsWindowRef->evalToPromiseOrRejectOnThrow(
995 "setSubWindowModal(*)", {
true, jsState.mapOhosEnumToJs(modalityType)})
996 .onCatch(QtOhos::makeErrorLoggingJsCallback(
"setSubWindowModal()"))
997 .onFinally(std::move(taskPromise).makeChained(Q_FUNC_INFO));
1006 if (m_jsScopeData->isWindowClosing()) {
1011 m_jsScopeData->jsWindowRef->evalToPromiseOrRejectOnThrow(
"setWindowTitle(*)", {title.toStdString()})
1012 .onFinally(std::move(taskPromise).makeChained(Q_FUNC_INFO));
1020 "%s: isMaximizeVisible:%s, isMinimizeVisible:%s, isCloseVisible:%s",
1021 Q_FUNC_INFO, maximizeVisible ?
"true" :
"false", minimizeVisible ?
"true":
"false",
1022 closeVisible ?
"true" :
"false");
1029 if (m_jsScopeData->isWindowClosing())
1032 constexpr auto capabilityNotSupportedErrorCode = 801;
1033 QtOhos::runIgnoringJsBusinessError(
1034 jsState, capabilityNotSupportedErrorCode,
"setWindowTitleButtonVisible()",
1036 m_jsScopeData->jsWindowRef->eval(
1037 "setWindowTitleButtonVisible(*)",
1038 {maximizeVisible, minimizeVisible, closeVisible});
1050 qOhosPrintfWarning(
"%s: can be used only on 2-in-1 devices or tablets in PC mode - skipping", Q_FUNC_INFO);
1054 qOhosPrintfDebug(
"%s: topMost: %s", Q_FUNC_INFO, topmost ?
"true" :
"false");
1058 if (m_jsScopeData->isWindowClosing()) {
1063 m_jsScopeData->jsWindowRef->evalToPromiseOrRejectOnThrow(
"setWindowTopmost(*)", {topmost})
1064 .onFinally(std::move(taskPromise).makeChained(Q_FUNC_INFO));
1072 if (m_jsScopeData->isWindowClosing())
1075 m_jsScopeData->jsWindowRef->eval(
"setWindowDecorVisible(*)", {visible});
1083 qOhosPrintfWarning(
"%s: can be used only on 2-in-1 devices or tablets in PC mode - skipping", Q_FUNC_INFO);
1088 if (m_jsScopeData->isWindowClosing())
1091 m_jsScopeData->jsWindowRef->eval(
"setWindowTitleMoveEnabled(*)", {enabled});
1099 qOhosPrintfWarning(
"%s: can be used only on 2-in-1 devices or tablets - skipping", Q_FUNC_INFO);
1107 m_jsScopeData->jsWindowRef->eval(
"setWindowShadowRadius(*)", {radius});
1119 m_jsScopeData->jsWindowRef->evalToPromiseOrRejectOnThrow(
"setWindowCornerRadius(*)", {radius})
1120 .onFinally(std::move(taskPromise).makeChained(Q_FUNC_INFO));
1127 return QtOhos::evalInJsThreadWithPromise<
bool>(
1128 [&](
QtOhos::
JsState &, QOhosTaskPromise<
bool> evalPromise) {
1129 if (m_jsScopeData->isWindowClosing()) {
1134 if (!optQUiAbilityPeer) {
1139 auto thenCatchPromises =
std::move(evalPromise).makeThenCatchBranches(Q_FUNC_INFO);
1140 optQUiAbilityPeer->windowStage()
1141 .evalToPromiseOrRejectOnThrow(
"isWindowRectAutoSave()")
1143 [thenPromise = std::move(thenCatchPromises.first)](
const QtOhos::
CallbackInfo &cbInfo) {
1144 bool windowRectAutoSaveEnabled = cbInfo.getFirstArg<QNapi::Boolean>(Q_FUNC_INFO);
1145 thenPromise(windowRectAutoSaveEnabled);
1148 [catchPromise = std::move(thenCatchPromises.second)](
const QtOhos::
CallbackInfo &cbInfo) {
1149 QtOhos::logJsCallbackError(cbInfo,
"isWindowRectAutoSave()");
1150 catchPromise(
false);
1163 if (m_jsScopeData->isWindowClosing()) {
1167 m_jsScopeData->jsWindowRef->evalToPromiseOrRejectOnThrow(
"setFollowParentMultiScreenPolicy(*)", {enabled})
1168 .onCatch(QtOhos::makeErrorLoggingJsCallback(
"setFollowParentMultiScreenPolicy()"))
1169 .onFinally(std::move(taskPromise).makeChained(Q_FUNC_INFO));
1180 if (m_jsScopeData->isWindowClosing()) {
1185 m_jsScopeData->jsWindowRef->evalToPromiseOrRejectOnThrow(
"setWindowKeepScreenOn(*)", {keepScreenOn})
1186 .onCatch(QtOhos::makeErrorLoggingJsCallback(
"setWindowKeepScreenOn()"))
1187 .onFinally(std::move(taskPromise).makeChained(Q_FUNC_INFO));
1194 qCDebug(QtForOhos,
"%s: %s", Q_FUNC_INFO, mapEnumsToLogString(supportedWindowModes).c_str());
1197 [&](
QtOhos::
JsState &jsState, QOhosTaskPromise<> taskPromise) {
1198 if (m_jsScopeData->isWindowClosing()) {
1203 if (!qUiAbilityPeer) {
1208 auto jsSupportedWindowModes = QNapi::makeArray(
1209 jsState.env(), supportedWindowModes,
1211 return jsState.mapOhosEnumToJs(mode);
1214 qUiAbilityPeer->windowStage().evalToPromiseOrRejectOnThrow(
"setSupportedWindowModes(*)", {jsSupportedWindowModes})
1215 .onCatch(QtOhos::makeErrorLoggingJsCallback(
"setSupportedWindowModes()"))
1216 .onFinally(
std::move(taskPromise).makeChained(Q_FUNC_INFO));
1223 constexpr bool isSaveBySpecifiedFlag =
true;
1227 if (m_jsScopeData->isWindowClosing()) {
1232 if (!optQUiAbilityPeer) {
1237 optQUiAbilityPeer->windowStage()
1238 .evalToPromiseOrRejectOnThrow(
"setWindowRectAutoSave(*)", {enabled, isSaveBySpecifiedFlag})
1239 .onCatch(QtOhos::makeErrorLoggingJsCallback(
"setWindowRectAutoSave()"))
1240 .onFinally(
std::move(taskPromise).makeChained(Q_FUNC_INFO));
1246 std::function<
void()> handler,
bool handlerReturnValue)
1248 m_subWindowCloseRegistrationHandle =
1249 registerSubWindowCloseHandler(std::move(handler), handlerReturnValue);
1254 m_subWindowCloseRegistrationHandle.reset();
1257std::shared_ptr<
void> QOhosWindowProxy::registerSubWindowCloseHandler(
1258 std::function<
void()> handler,
bool handlerReturnValue)
1260 auto sharedHandler = QtOhos::moveToSharedPtr(std::move(handler));
1261 auto jsWindowRegistrationHandle =
QtOhos::evalInJsThread(
1263 return QtOhos::makeProxyWithJsThreadDeleter(
1264 m_jsScopeData->registerSubWindowCloseHandler(
1266 [weakHandler = QtOhos::makeWeakPtr(sharedHandler), handlerReturnValue]() {
1267 QtOhos::invokeInQtThread(
1269 auto sharedHandler = weakHandler.lock();
1273 return handlerReturnValue;
1278 return QtOhos::moveToSharedPtr(
1279 std::make_tuple(sharedHandler, jsWindowRegistrationHandle));
1282std::shared_ptr<QOhosWindowProxy>
1285 return QtOhos::evalInJsThreadWithPromise<
std::shared_ptr<QOhosWindowProxy>>(
1286 [&](
QtOhos::
JsState &jsState, QOhosTaskPromise<std::shared_ptr<QOhosWindowProxy>> evalPromise) {
1287 auto sharedEvalPromise = QtOhos::moveToSharedPtr(std::move(evalPromise).makeChained(Q_FUNC_INFO));
1288 makeWindowProxyDataForExistingMainWindowInJsThread(
1292 (*sharedEvalPromise)(QOhosWindowProxy::create(jsState,
std::move(windowProxyData)));
1298std::shared_ptr<QOhosWindowProxy>
1301 return QtOhos::evalInJsThreadWithPromise<
std::shared_ptr<QOhosWindowProxy>>(
1302 [&](
QtOhos::
JsState &jsState, QOhosTaskPromise<std::shared_ptr<QOhosWindowProxy>> evalPromise) {
1303 auto sharedEvalPromise = QtOhos::moveToSharedPtr(std::move(evalPromise).makeChained(Q_FUNC_INFO));
1304 makeWindowProxyDataForFloatWindowInJsThread(
1305 jsState, createInfo,
1307 (*sharedEvalPromise)(QOhosWindowProxy::create(jsState,
std::move(windowProxyData)));
1313std::shared_ptr<QOhosWindowProxy>
1316 return QtOhos::evalInJsThreadWithPromise<
std::shared_ptr<QOhosWindowProxy>>(
1317 [&](
QtOhos::
JsState &jsState, QOhosTaskPromise<std::shared_ptr<QOhosWindowProxy>> evalPromise) {
1318 auto sharedEvalPromise = QtOhos::moveToSharedPtr(std::move(evalPromise).makeChained(Q_FUNC_INFO));
1319 makeWindowProxyDataForMainWindowInJsThread(
1323 (*sharedEvalPromise)(QOhosWindowProxy::create(jsState,
std::move(windowProxyData)));
1331 return m_nodeXComponent;
1336 return m_qAbilityInstanceId;
1339std::shared_ptr<QOhosWindowProxy>
1342 return QtOhos::evalInJsThreadWithPromise<
std::shared_ptr<QOhosWindowProxy>>(
1343 [&](
QtOhos::
JsState &jsState, QOhosTaskPromise<std::shared_ptr<QOhosWindowProxy>> evalPromise) {
1344 auto sharedEvalPromise = QtOhos::moveToSharedPtr(std::move(evalPromise).makeChained(Q_FUNC_INFO));
1345 auto proxyDataConsumer =
1347 (*sharedEvalPromise)(QOhosWindowProxy::create(jsState,
std::move(windowProxyData)));
1352 if (m_jsScopeData->isWindowClosing()) {
1353 makeWindowProxyDataForSubWindowInJsThread(
1354 jsState, createInfo,
std::move(proxyDataConsumer));
1356 makeWindowProxyDataForSubWindowInJsThread(
1357 jsState, m_jsScopeData->jsWindowRef->jsObject(), createInfo,
1358 std::move(proxyDataConsumer));
1364QOhosWindowProxy::JsScopeData::JsScopeData(
1365 WindowProxyType windowProxyType, QNapi::Reference<QNapi::Object> jsWindow,
1366 std::shared_ptr<
void> optKeepAliveData,
1368 QtOhos::QObjectThreadSafeRef owningQWindowRef)
1369 : windowProxyType(windowProxyType)
1370 , windowCallbackReceiver(
nullptr)
1371 , windowDestroyedFromSystem(
false)
1372 , optKeepAliveData(optKeepAliveData)
1373 , qAbilityPeer(qAbilityPeer)
1374 , m_windowFrameMouseFilterHandle(
1375 QArkUi::registerMouseEventsConsumer(
1376 getWindowPropertiesFromJsWindow(jsWindow.Value()).id,
1377 [
this](
const QArkUi::MouseEvent &event) {
1378 onMouseEventFromArkUi(event);
1380 , m_windowFrameTouchFilterHandle(
1381 QArkUi::registerTouchEventsConsumer(
1382 getWindowPropertiesFromJsWindow(jsWindow.Value()).id,
1383 [
this](
const QArkUi::TouchEvent &event) {
1384 onTouchEventFromArkUi(event);
1387 std::make_shared<QArkUi::JsWindowRef>(
1388 qAbilityPeer->instanceId(),
1389 getWindowPropertiesFromJsWindow(jsWindow.Value()).id,
1395QOhosWindowProxy::JsScopeData::~JsScopeData()
1397 if (isWindowClosingFromSystem(jsWindowRef->jsObject(), windowProxyType, qAbilityPeer)) {
1398 windowDestroyedFromSystem =
true;
1402 QtOhos::JsWindowsTracker::tagWindowAsClosing(jsWindowRef->jsObject(),
"QOhosWindowProxy::JsScopeData destructor");
1408 windowDestroyedFromSystem =
true;
1410 "Attempting to terminate qAbility with instance id: %s",
1411 qAbilityPeer->instanceId().c_str());
1412 qAbilityPeer->qAbility().eval(
"context.terminateSelf()");
1413 }
else if (!windowDestroyedFromSystem) {
1416 jsWindowRef->eval(
"destroyWindow()");
1420std::shared_ptr<
void> QOhosWindowProxy::JsScopeData::registerEventListener(
1421 const std::string &eventName,
1423 QFlags<EventHandlerFlagBits> eventHandlerFlags)
1426 std::weak_ptr<JsScopeData> weakSelf = shared_from_this();
1427 bool ignoreWhenAbilityIsTerminating = !eventHandlerFlags.testFlag(EventHandlerFlagBits::allowCallWhenAbilityIsTerminating);
1429 return registerQOhosOnOffMethodsBasedEventHandler(
1430 jsWindowRef->jsObject(), eventName,
1431 [weakSelf, handleFunction, eventName, ignoreWhenAbilityIsTerminating](
const QtOhos::
CallbackInfo &cbInfo) {
1432 auto self = weakSelf.lock();
1433 if (Q_UNLIKELY(!self)) {
1435 "callback '%s' called for destroyed QOhosWindowProxy::JsScopeData, ignoring",
1440 if (self->isWindowClosing() && ignoreWhenAbilityIsTerminating) {
1442 "QOhosWindowProxy: Received callback for event '%s' during termination of the related QAbility.",
1447 if (Q_UNLIKELY(self->windowDestroyedFromSystem)) {
1449 "QOhosWindowProxy: Received callback for event '%s' after WINDOW_DESTROYED",
1454 ((*self).*handleFunction)(cbInfo);
1457 .optOnCallExceptionHandler = [&](
const Napi::Error &error) {
1458 constexpr std::uint32_t capabilityNotSupportedErrorCode = 801;
1459 constexpr std::uint32_t windowStateIsAbnormalErrorCode = 1300002;
1461 const QSet<std::uint32_t> ignorableErrorCodes = {
1462 capabilityNotSupportedErrorCode,
1463 windowStateIsAbnormalErrorCode,
1466 auto errorCode = QtOhos::tryGetCodeFromJsBusinessError(error);
1468 auto ignorableError =
1469 eventHandlerFlags.testFlag(EventHandlerFlagBits::allowEventHandlerRegistrationFailure)
1470 && errorCode.has_value()
1471 && ignorableErrorCodes.contains(errorCode.value());
1473 if (!ignorableError)
1477 "%s: Ignored error %u while registering for window event '%s'",
1478 Q_FUNC_INFO, errorCode.value(), eventName.c_str());
1483std::shared_ptr<
void> QOhosWindowProxy::JsScopeData::registerSubWindowCloseHandler(
1486 auto weakSelf = QtOhos::makeWeakPtr(shared_from_this());
1487 return registerQOhosOnOffMethodsBasedEventHandler(
1488 jsWindowRef->jsObject(),
"subWindowClose",
1490 bool deferClose = handler();
1491 auto self = weakSelf.lock();
1492 if (self && !deferClose)
1493 QtOhos::JsWindowsTracker::tagWindowAsClosing(self->jsWindowRef->jsObject(),
"subWindowClose => false");
1494 return QNapi::Boolean::New(cbInfo.Env(), deferClose);
1498void QOhosWindowProxy::JsScopeData::handleWindowEventCallback(
const QtOhos::
CallbackInfo &cbInfo)
1500 auto eventType = cbInfo.getFirstArg<QNapi::Number>(Q_FUNC_INFO);
1505 event
.type = cbInfo
.jsState().mapOhosEnumFromJs<WindowEventType>(eventType);
1506 }
catch (
const Napi::Error &err) {
1508 "Error converting WindowEventType to known value: %s. Event will be ignored.", err.what());
1514 "Received WindowEvent for window when it's closing. WindowEventType: %d",
1522void QOhosWindowProxy::JsScopeData::handleWindowStatusCallback(
const QtOhos::
CallbackInfo &cbInfo)
1524 auto windowStatusType = cbInfo.getFirstArg<QNapi::Number>(Q_FUNC_INFO);
1525 if (windowCallbackReceiver !=
nullptr) {
1526 windowCallbackReceiver->onWindowStatusChange(
1528 .type = cbInfo.jsState().mapOhosEnumFromJs<WindowStatusType>(windowStatusType),
1533void QOhosWindowProxy::JsScopeData::handleWindowVisibilityCallback(
const QtOhos::
CallbackInfo &cbInfo)
1535 auto windowVisibility = cbInfo.getFirstArg<QNapi::Boolean>(Q_FUNC_INFO);
1536 if (windowCallbackReceiver !=
nullptr)
1537 windowCallbackReceiver->onWindowVisibilityChange(windowVisibility);
1540void QOhosWindowProxy::JsScopeData::handleWindowTouchOutsideCallback(
const QtOhos::
CallbackInfo &)
1542 if (windowCallbackReceiver !=
nullptr)
1543 windowCallbackReceiver->onTouchOutside();
1546void QOhosWindowProxy::JsScopeData::handleAvoidAreaChangeCallback(
const QtOhos::
CallbackInfo &cbInfo)
1548 if (windowCallbackReceiver !=
nullptr) {
1549 auto callbackArg = cbInfo.getFirstArg<QNapi::Object>(Q_FUNC_INFO);
1550 windowCallbackReceiver->onAvoidAreaChange(
1551 cbInfo.jsState().mapOhosEnumFromJs<AvoidAreaType>(callbackArg.get<QNapi::Number>(
"type")),
1552 mapAvoidAreaFromJs(callbackArg.get<QNapi::Object>(
"area")));
1556void QOhosWindowProxy::JsScopeData::handleWindowRectChangeCallback(
const QtOhos::
CallbackInfo &cbInfo)
1558 auto rectChangeOptionsObjectArg = cbInfo.getFirstArg<QNapi::Object>(Q_FUNC_INFO);
1559 auto rectChangeOptions = RectChangeOptions {
1560 .rect = ohosWindowRectToQRect(rectChangeOptionsObjectArg.get<QNapi::Object>(
"rect")),
1561 .reason = cbInfo.jsState().mapOhosEnumFromJs<RectChangeReason>(rectChangeOptionsObjectArg.get<QNapi::Number>(
"reason")),
1564 if (windowCallbackReceiver !=
nullptr)
1565 windowCallbackReceiver->onWindowRectChange(rectChangeOptions);
1568void QOhosWindowProxy::JsScopeData::handleWindowRectChangeInGlobalDisplayCallback(
const QtOhos::
CallbackInfo &cbInfo)
1570 auto rectChangeOptionsObjectArg = cbInfo.getFirstArg<QNapi::Object>(Q_FUNC_INFO);
1571 auto rectChangeOptions = RectChangeOptions {
1572 .rect = ohosWindowRectToQRect(rectChangeOptionsObjectArg.get<QNapi::Object>(
"rect")),
1573 .reason = cbInfo.jsState().mapOhosEnumFromJs<RectChangeReason>(rectChangeOptionsObjectArg.get<QNapi::Number>(
"reason")),
1576 if (windowCallbackReceiver !=
nullptr)
1577 windowCallbackReceiver->onWindowRectChangeInGlobalDisplay(rectChangeOptions);
1580void QOhosWindowProxy::JsScopeData::handleWindowDisplayIdChangeCallback(
const QtOhos::
CallbackInfo &cbInfo)
1582 auto displayIdNumber = cbInfo.getFirstArg<QNapi::Number>(Q_FUNC_INFO);
1585 if (windowCallbackReceiver !=
nullptr)
1586 windowCallbackReceiver->onWindowDisplayIdChange(displayId);
1592 QtOhos::JsWindowsTracker::tagWindowAsClosing(jsWindowRef->jsObject(),
"WINDOW_DESTROYED");
1593 windowDestroyedFromSystem =
true;
1596 if (windowCallbackReceiver !=
nullptr)
1597 windowCallbackReceiver->onWindowEvent(windowEvent);
1600bool QOhosWindowProxy::JsScopeData::isWindowClosing()
const
1602 return isWindowClosingFromSystem(jsWindowRef->jsObject(), windowProxyType, qAbilityPeer);
1605void QOhosWindowProxy::JsScopeData::onMouseEventFromArkUi(
const QArkUi::
MouseEvent &event)
1607 if (nonClientAreaMouseEventConsumer ==
nullptr)
1610 auto optAction = tryMapMouseEventActionToNonClientAreaEventType(event.action);
1611 if (!optAction.has_value())
1615 if (!optWindowProperties.has_value()) {
1617 "%s: Failed to retrieve window properties for js window: %f. Ignoring event.",
1618 Q_FUNC_INFO, event.jsWindowId.value());
1622 const auto &windowProperties = optWindowProperties.value();
1623 if (!isPointInNonClientArea(event.displayPosition, windowProperties))
1626 auto windowOrigin = windowProperties.windowRect.topLeft() + windowProperties.drawableRect.topLeft();
1628 .timestamp = std::chrono::duration_cast<std::chrono::milliseconds>(event.actionTime),
1629 .action = optAction.value(),
1630 .button = tryMapMouseEventButtonToQt(event.button).value_or(Qt::NoButton),
1631 .displayPosition = event.displayPosition,
1632 .localPosition = event.displayPosition - windowOrigin,
1633 .globalPosition = event.globalPosition,
1636 nonClientAreaMouseEventConsumer(nonClientAreaMouseEvent);
1639void QOhosWindowProxy::JsScopeData::onTouchEventFromArkUi(
const QArkUi::
TouchEvent &event)
1641 if (nonClientAreaTouchEventConsumer ==
nullptr)
1644 auto optState = tryMapTouchEventActionToNonClientAreaEventState(event.action);
1645 if (!optState.has_value())
1649 if (!optWindowProperties.has_value()) {
1651 "%s: Failed to retrieve window properties for js window: %f. Ignoring event.",
1652 Q_FUNC_INFO, event.jsWindowId.value());
1656 if (!isPointInNonClientArea(event.displayPosition, optWindowProperties.value()))
1661 .timestamp =
std::chrono::duration_cast<
std::chrono::milliseconds>(event.actionTime),
1662 .state = optState.value(),
1663 .displayPosition = event.displayPosition,
1664 .globalPosition = event.globalPosition,
1667 nonClientAreaTouchEventConsumer(nonClientAreaTouchEvent);
1672 return QtOhos::evalInJsThreadWithPromise<QPixmap>(
1673 [&](QtOhos::JsState &, QOhosTaskPromise<QPixmap> evalPromise) {
1674 auto thenCatchPromises = std::move(evalPromise).makeThenCatchBranches(Q_FUNC_INFO);
1675 m_jsScopeData->jsWindowRef->evalToPromiseOrRejectOnThrow(
"snapshot()")
1677 [thenPromise = std::move(thenCatchPromises.first)](
const QtOhos::CallbackInfo &cbInfo) {
1678 auto napiPixmap = cbInfo.getFirstArg<QNapi::Object>(Q_FUNC_INFO);
1680 ::OH_PixelmapNative *pixelMapNativePtr;
1681 QArkUi::callArkUiOrFailOnErrorResult(
1682 Q_OHOS_NAMED_FUNC(::OH_PixelmapNative_ConvertPixelmapNativeFromNapi),
1683 cbInfo.Env(), napiPixmap, &pixelMapNativePtr);
1684 auto pixelMap = wrapOhosNativePixelMapPtr(pixelMapNativePtr);
1687 QPixmap::fromImage(createQImageFromNativePixelMap(pixelMap.get())));
1690 [catchPromise = std::move(thenCatchPromises.second)](
const QtOhos::CallbackInfo &cbInfo) {
1691 QtOhos::logJsCallbackError(cbInfo,
"Got error from snapshot()");
1692 catchPromise(QPixmap());
1702 if (m_jsScopeData->isWindowClosing()) {
1707 m_jsScopeData->jsWindowRef->evalToPromiseOrRejectOnThrow(
"startMoving()")
1708 .onCatch(QtOhos::makeErrorLoggingJsCallback(
"startMoving()"))
1709 .onFinally(std::move(taskPromise).makeChained(Q_FUNC_INFO));
1721 qCWarning(QtForOhos(),
"%s: enableDrag is not supported on main windows", Q_FUNC_INFO);
1727 if (m_jsScopeData->isWindowClosing()) {
1731 m_jsScopeData->jsWindowRef->evalToPromiseOrRejectOnThrow(
"enableDrag(*)", {enable})
1732 .onCatch(QtOhos::makeErrorLoggingJsCallback(
"enableDrag()"))
1733 .onFinally(std::move(taskPromise).makeChained(Q_FUNC_INFO));
1740 return QtOhos::evalInJsThread(
1742 if (m_jsScopeData->isWindowClosing())
1745 return m_jsScopeData->jsWindowRef->eval<QNapi::Boolean>(
"isFocused()");
1750std::vector<QArkUi::JsWindowId> QOhosWindowProxy::queryWindowIdsByCoordinate(
1751 QOhosDisplayInfo::JsDisplayId displayId,
const QPoint &queryLocation,
std::uint32_t queryLimit)
1753 return QtOhos::evalInJsThreadWithPromise<std::vector<QArkUi::JsWindowId>>(
1754 [&](QtOhos::JsState &jsState,
auto evalPromise) {
1755 auto thenCatchPromises = std::move(evalPromise).makeThenCatchBranches(Q_FUNC_INFO);
1756 jsState.evalToPromiseOrRejectOnThrow(
"@ohos.window.getWindowsByCoordinate(*)", {
1762 .onThen([thenPromise = std::move(thenCatchPromises.first)](
const QtOhos::CallbackInfo &cbInfo) {
1763 auto windowsArray = cbInfo.getFirstArg<QNapi::Array>(Q_FUNC_INFO);
1765 QNapi::getArrayElements<std::vector<QArkUi::JsWindowId>, QNapi::Object>(
1767 [&](QNapi::Object jsWindow) {
1768 return getWindowPropertiesFromJsWindow(jsWindow).id;
1771 .onCatch([catchPromise = std::move(thenCatchPromises.second)](
const QtOhos::CallbackInfo &cbInfo) {
1772 QtOhos::logJsCallbackError(
1773 cbInfo,
"got error from @ohos.window.getWindowsByCoordinate()");
1780std::vector<QArkUi::JsWindowId> QOhosWindowProxy::queryQtManagedWindowIdsByPredicate(
1785 return jsWindowRegistry.queryByPredicate(jsState, predicate);
1794 [&](
QtOhos::
JsState &jsState, QOhosTaskPromise<> taskPromise) {
1795 if (m_jsScopeData->isWindowClosing()) {
1800 auto moveConfigurationObject = toNapiObject(jsState.env(), moveConfiguration);
1801 auto moveConfigurationObjectStr = QNapi::toJsonString(moveConfigurationObject);
1804 Q_FUNC_INFO, position.x(), position.y(),
1805 moveConfigurationObjectStr.c_str());
1807 m_jsScopeData->jsWindowRef->evalToPromiseOrRejectOnThrow(
1808 "moveWindowToGlobal(*)", {position.x(), position.y(), moveConfigurationObject})
1809 .onFinally(std::move(taskPromise).makeChained(Q_FUNC_INFO));
1818 :
QtOhos::evalInJsThread(
1822 return qUiAbilityPeer
1823 ? getWindowPropertiesFromJsWindow(qUiAbilityPeer->window()).displayId
1832 [&](
QtOhos::
JsState &jsState, QOhosTaskPromise<> taskPromise) {
1833 if (m_jsScopeData->isWindowClosing() || targetProxy.m_jsScopeData->isWindowClosing()) {
1838 auto srcWindowId = getWindowPropertiesFromJsWindow(m_jsScopeData->jsWindowRef->jsObject()).id;
1839 auto targetWindowId = getWindowPropertiesFromJsWindow(targetProxy.m_jsScopeData->jsWindowRef->jsObject()).id;
1840 jsState.evalToPromiseOrRejectOnThrow(
1841 "@ohos.window.shiftAppWindowFocus(*)", {srcWindowId.value(), targetWindowId.value()})
1842 .onCatch(QtOhos::makeErrorLoggingJsCallback(
"@ohos.window.shiftAppWindowFocus()"))
1843 .onFinally(
std::move(taskPromise).makeChained(Q_FUNC_INFO));
1850 auto window =
std::shared_ptr<QOhosWindowProxy>(
new QOhosWindowProxy(
std::move(data)));
1852 return QtOhos::makeSharedPtrWithAttachedExtraData(
1854 jsWindowRegistry.registerJsWindow(window->m_jsScopeData->jsWindowRef));
bool isWindowPcModeEnabled() const
static QOhosSettings & instance()
void setWindowRectAutoSave(bool enabed)
void setSubWindowModalEnabled(ModalityType ModalityType)
void setWindowKeepScreenOn(bool keepScreenOn)
void moveWindowToGlobal(const QPoint &position, const MoveConfiguration &moveConfiguration)
static std::shared_ptr< QOhosWindowProxy > createFloatWindow(const FloatWindowCreateInfo &createInfo)
void setWindowMask(const WindowMask &windowMask, const std::optional< QSize > &ohosMaskSizeOverride={})
QArkUi::WindowProperties getWindowProperties() const
void moveWindowToGlobalOrGlobalDisplay(const QPoint &position, std::optional< QOhosDisplayInfo::JsDisplayId > optDisplayId)
void setSubWindowModalDisabled()
void setWindowPrivacyMode(bool privacyMode)
void resetSubWindowCloseHandler()
AvoidArea getWindowAvoidArea(AvoidAreaType type) const
QtOhos::enums::ohos::window::ModalityType ModalityType
void setWindowLayoutFullScreen(bool isLayoutFullScreen)
std::optional< QOhosDisplayInfo::JsDisplayId > tryGetMainWindowJsDisplayId() const
QtOhos::enums::ohos::window::AvoidAreaType AvoidAreaType
void enableDrag(bool enable)
void setWindowCornerRadius(double radius)
QOhosWindowProxyExistingMainWindowCreateInfo ExistingMainWindowCreateInfo
void setSupportedWindowModes(const std::set< SupportWindowMode > &supportedWindowModes)
void removeStartingWindow()
void setWindowSystemBarEnable(const QStringList &names)
std::shared_ptr< QOhosWindowProxy > createSubWindow(const SubWindowCreateInfo &createInfo)
static std::shared_ptr< QOhosWindowProxy > createForExistingMainWindow(const ExistingMainWindowCreateInfo &createInfo)
QtOhos::enums::ohos::window::MaximizePresentation MaximizePresentation
void setWindowTouchable(bool touchable)
WindowProxyType windowProxyType() const
void setTitle(const QString &title)
void setFollowParentMultiScreenPolicy(bool enabled)
void setWindowTopmost(bool topmost)
std::shared_ptr< QXComponentNode > nodeXComponent() const
void setWindowCallbackReceiver(std::unique_ptr< WindowCallbacks > receiver)
void setSubWindowCloseHandler(std::function< void()> handler, bool handlerReturnValue)
std::optional< bool > isFocused() const
void setWindowLimits(const QSize &minSize, const QSize &maxSize)
bool isWindowRectAutoSave() const
void setWindowDecorVisible(bool visible)
void showWindow(const ShowWindowOptions &options=ShowWindowOptions())
void shiftAppWindowFocus(QOhosWindowProxy &targetProxy)
QOhosWindowProxySubWindowCreateInfo SubWindowCreateInfo
void setNonClientAreaMouseWindowCallbackReceiver(QObject *contextObject, QOhosConsumer< std::vector< NonClientAreaMouseEvent > > mouseEventBatchConsumer)
void setCustomCursor(const QImage &customCursorImage, const QPoint &hotSpot)
QtOhos::enums::ohos::window::WindowEventType WindowEventType
void setWindowTitleMoveEnabled(bool enabled)
void setWindowFocusable(bool focusable)
void setWindowBackgroundColor(const QColor &color)
void setSize(const QSize &size)
QOhosWindowProxyMainWindowCreateInfo MainWindowCreateInfo
void setWindowShadowRadius(double radius)
bool qtIsMainWindow() const
QOhosWindowProxyFloatWindowCreateInfo FloatWindowCreateInfo
void setWindowTitleButtonVisible(bool maximizeVisible, bool minimizeVisible, bool closeVisible)
bool getImmersiveModeEnabledState()
void setPointerStyleSync(const QCursor &cursor)
WindowLimits getWindowLimits() const
std::string qAbilityInstanceId() const
void maximize(MaximizePresentation maximizePresentation)
void setNonClientAreaTouchWindowCallbackReceiver(QObject *contextObject, QOhosConsumer< std::vector< NonClientAreaTouchEvent > > touchEventBatchConsumer)
static std::shared_ptr< QOhosWindowProxy > createMainWindow(const MainWindowCreateInfo &createInfo)
JsState & jsState() const
static std::shared_ptr< QUiAbilityPeer > tryCastFromQAbilityPeerOrNull(std::shared_ptr< QAbilityPeer > qAbilityPeer)
std::optional< WindowProperties > tryGetWindowProperties(JsWindowId jsWindowId)
Combined button and popup list for selecting options.
std::optional< QEventPoint::State > tryMapTouchEventActionToNonClientAreaEventState(::Input_TouchEventAction action)
QRect ohosWindowRectToQRect(const QNapi::Object &ohosWindowRect)
bool isPointInNonClientArea(const QPoint &point, const QArkUi::WindowProperties &windowProperties)
std::optional< QEvent::Type > tryMapMouseEventActionToNonClientAreaEventType(::Input_MouseEventAction action)
QtOhos::enums::ohos::multimodalInput::pointer::PointerStyle QOhosPointerStyle
std::optional< double > getOptionalNumberPropAsOptionalDouble(const QNapi::Object &object, const std::string &propertyName)
QOhosPointerStyle convertToOhosCursor(Qt::CursorShape shape)
QOhosWindowProxy::AvoidArea mapAvoidAreaFromJs(const QNapi::Object &avoidAreaObject)
std::string mapEnumsToLogString(const EnumsContainer &enums)
std::optional< Qt::MouseButton > tryMapMouseEventButtonToQt(::Input_MouseEventButton button)
bool isWindowClosingFromSystem(QNapi::Object jsWindow, WindowProxyType windowType, std::shared_ptr< QtOhos::QAbilityPeer > abilityPeer)
QArkUi::WindowProperties getWindowPropertiesFromJsWindow(QNapi::Object jsWindow)
std::function< void(Args...)> makeQtThreadWindowCallbackDelegate(std::function< void(Args...)> QOhosWindowProxy::WindowCallbacks::*memberPtr, std::shared_ptr< QOhosWindowProxy::WindowCallbacks > qtWindowCallbacks)
std::function< void(T)> makeCompressingQtThreadWindowCallbackDelegate(std::function< void(T)> QOhosWindowProxy::WindowCallbacks::*memberPtr, std::shared_ptr< QOhosWindowProxy::WindowCallbacks > qtWindowCallbacks)
QNapi::Object toNapiObject(napi_env env, const QOhosWindowProxy::MoveConfiguration &moveConfiguration)
std::string const char * mapBoolToTrueFalseStr(bool value)
void runInJsThreadAndWait(const std::function< void(JsState &)> &task, std::string callerContextName={})
void invokeInJsThreadAndWaitForContinue(std::function< void(JsState &, QOhosTaskPromise<>)> &&task, std::string callerContextName={})
QXComponent< QXComponentType::Node > QXComponentNode
bool isDisplayMainOrExtended() const
WindowProxyType windowProxyType