4#include <render/qohoswindowproxy.h>
6#include <QtCore/qcoreapplication.h>
7#include <QtCore/qset.h>
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>
42using QOhosPointerStyle = QtOhos::enums::ohos::multimodalInput::pointer::PointerStyle;
47 ohosWindowRect.get<QNapi::Number>(
"left"),
48 ohosWindowRect.get<QNapi::Number>(
"top"),
49 ohosWindowRect.get<QNapi::Number>(
"width"),
50 ohosWindowRect.get<QNapi::Number>(
"height"),
57 .visible = avoidAreaObject.get<QNapi::Boolean>(
"visible"),
58 .leftRect = ohosWindowRectToQRect(avoidAreaObject.get<QNapi::Object>(
"leftRect")),
59 .topRect = ohosWindowRectToQRect(avoidAreaObject.get<QNapi::Object>(
"topRect")),
60 .rightRect = ohosWindowRectToQRect(avoidAreaObject.get<QNapi::Object>(
"rightRect")),
61 .bottomRect = ohosWindowRectToQRect(avoidAreaObject.get<QNapi::Object>(
"bottomRect")),
69 return QOhosPointerStyle::DEFAULT;
70 case Qt::UpArrowCursor:
71 return QOhosPointerStyle::NORTH;
73 return QOhosPointerStyle::CROSS;
75 return QOhosPointerStyle::LOADING;
77 return QOhosPointerStyle::TEXT_CURSOR;
78 case Qt::SizeVerCursor:
79 return QOhosPointerStyle::NORTH_SOUTH;
80 case Qt::SizeHorCursor:
81 return QOhosPointerStyle::WEST_EAST;
82 case Qt::SizeBDiagCursor:
83 return QOhosPointerStyle::NORTH_EAST_SOUTH_WEST;
84 case Qt::SizeFDiagCursor:
85 return QOhosPointerStyle::NORTH_WEST_SOUTH_EAST;
86 case Qt::SizeAllCursor:
87 return QOhosPointerStyle::MOVE;
90 return QOhosPointerStyle::DEFAULT;
91 case Qt::SplitVCursor:
92 return QOhosPointerStyle::RESIZE_UP_DOWN;
93 case Qt::SplitHCursor:
94 return QOhosPointerStyle::RESIZE_LEFT_RIGHT;
95 case Qt::PointingHandCursor:
96 return QOhosPointerStyle::HAND_POINTING;
97 case Qt::ForbiddenCursor:
98 return QOhosPointerStyle::CURSOR_FORBID;
99 case Qt::WhatsThisCursor:
100 return QOhosPointerStyle::HELP;
102 return QOhosPointerStyle::RUNNING;
103 case Qt::OpenHandCursor:
104 return QOhosPointerStyle::HAND_OPEN;
105 case Qt::ClosedHandCursor:
106 return QOhosPointerStyle::HAND_GRABBING;
107 case Qt::DragCopyCursor:
108 return QOhosPointerStyle::CURSOR_COPY;
109 case Qt::DragMoveCursor:
110 return QOhosPointerStyle::CROSS;
111 case Qt::DragLinkCursor:
113 return QOhosPointerStyle::DEFAULT;
114 case Qt::BitmapCursor:
116 return QOhosPointerStyle::DEFAULT;
117 case Qt::CustomCursor:
119 return QOhosPointerStyle::DEFAULT;
122 return QOhosPointerStyle::DEFAULT;
127 auto propOrEmpty = QNapi::getOptionalPropOrEmpty<QNapi::Number>(object, propertyName);
128 return !propOrEmpty.IsEmpty()
129 ?
std::optional<
double>(propOrEmpty)
135 auto windowPropsObj = jsWindow.eval<QNapi::Object>(
"getWindowProperties()");
136 auto displayIdOrEmpty = QNapi::getOptionalPropOrEmpty<QNapi::Number>(windowPropsObj,
"displayId");
137 return QArkUi::WindowProperties {
138 .windowRect = ohosWindowRectToQRect(windowPropsObj.get<QNapi::Object>(
"windowRect")),
139 .drawableRect = ohosWindowRectToQRect(windowPropsObj.get<QNapi::Object>(
"drawableRect")),
140 .id = QArkUi::JsWindowId(windowPropsObj.get<QNapi::Number>(
"id")),
141 .displayId = !displayIdOrEmpty.IsEmpty()
142 ? std::optional(QOhosDisplayInfo::JsDisplayId{displayIdOrEmpty.DoubleValue()})
149 auto moveConfigurationObject = QNapi::makeObject(env);
150 if (moveConfiguration.displayId.has_value()) {
151 moveConfigurationObject.set(
152 "displayId", moveConfiguration.displayId.value().value());
154 return moveConfigurationObject;
157template<
typename ...Args>
159 std::function<
void(Args...)> QOhosWindowProxy::WindowCallbacks::*memberPtr,
162 auto weakQtWindowCallbacks = QtOhos::makeWeakPtr(qtWindowCallbacks);
164 return [memberPtr, weakQtWindowCallbacks](Args ...args) {
165 QtOhos::invokeInQtThread([memberPtr, weakQtWindowCallbacks, args...]() {
166 auto qtWindowCallbacks = weakQtWindowCallbacks.lock();
167 if (qtWindowCallbacks)
168 (*qtWindowCallbacks.*memberPtr)(args...);
175 std::function<
void(T)> QOhosWindowProxy::WindowCallbacks::*memberPtr,
178 auto weakQtWindowCallbacks = QtOhos::makeWeakPtr(qtWindowCallbacks);
180 return QtOhos::makeCompressingAsyncConsumer<T>(
181 [memberPtr, weakQtWindowCallbacks](T value) {
182 auto qtWindowCallbacks = weakQtWindowCallbacks.lock();
183 if (qtWindowCallbacks)
184 (*qtWindowCallbacks.*memberPtr)(value);
186 QtOhos::invokeInQtThread);
191 constexpr bool containsPolicyExcludeEdgeValue =
true;
193 auto drawableRectInScreenSpace =
194 windowProperties.drawableRect.translated(windowProperties.windowRect.topLeft());
195 return !drawableRectInScreenSpace.contains(point, containsPolicyExcludeEdgeValue);
201 case ::MOUSE_ACTION_MOVE:
202 return QEvent::NonClientAreaMouseMove;
203 case ::MOUSE_ACTION_BUTTON_DOWN:
204 return QEvent::NonClientAreaMouseButtonPress;
205 case ::MOUSE_ACTION_BUTTON_UP:
206 return QEvent::NonClientAreaMouseButtonRelease;
207 case ::MOUSE_ACTION_CANCEL:
208 case ::MOUSE_ACTION_AXIS_BEGIN:
209 case ::MOUSE_ACTION_AXIS_UPDATE:
210 case ::MOUSE_ACTION_AXIS_END:
219 case ::MOUSE_BUTTON_LEFT:
220 return Qt::LeftButton;
221 case ::MOUSE_BUTTON_MIDDLE:
222 return Qt::MiddleButton;
223 case ::MOUSE_BUTTON_RIGHT:
224 return Qt::RightButton;
225 case ::MOUSE_BUTTON_FORWARD:
226 return Qt::ForwardButton;
227 case ::MOUSE_BUTTON_BACK:
228 return Qt::BackButton;
229 case ::MOUSE_BUTTON_NONE:
238 case ::TOUCH_ACTION_MOVE:
239 return QEvent::NonClientAreaMouseMove;
240 case ::TOUCH_ACTION_DOWN:
241 return QEvent::NonClientAreaMouseButtonPress;
242 case ::TOUCH_ACTION_UP:
243 return QEvent::NonClientAreaMouseButtonRelease;
244 case ::TOUCH_ACTION_CANCEL:
250template<
typename EnumsContainer>
254 for (
auto enumValue : enums) {
257 output +=
std::to_string(
static_cast<std::underlying_type_t<
decltype(enumValue)>>(enumValue));
266 return QtOhos::JsWindowsTracker::isWindowClosing(jsWindow) || (boundToAbility && abilityPeer->isTerminating());
273 .eventName =
"avoidAreaChange",
274 .eventHandler = &
QOhosWindowProxy::JsScopeData::handleAvoidAreaChangeCallback,
275 .eventHandlerFlags = {},
278 .eventName =
"touchOutside",
279 .eventHandler = &
QOhosWindowProxy::JsScopeData::handleWindowTouchOutsideCallback,
280 .eventHandlerFlags = {},
283 .eventName =
"windowEvent",
285 .eventHandlerFlags = EventHandlerFlagBits::allowCallWhenAbilityIsTerminating,
288 .eventName =
"windowRectChange",
289 .eventHandler = &
QOhosWindowProxy::JsScopeData::handleWindowRectChangeCallback,
290 .eventHandlerFlags = {},
293 .eventName =
"rectChangeInGlobalDisplay",
294 .eventHandler = &
QOhosWindowProxy::JsScopeData::handleWindowRectChangeInGlobalDisplayCallback,
295 .eventHandlerFlags = {},
298 .eventName =
"windowStatusChange",
300 .eventHandlerFlags = {},
303 .eventName =
"windowVisibilityChange",
304 .eventHandler = &
QOhosWindowProxy::JsScopeData::handleWindowVisibilityCallback,
305 .eventHandlerFlags = {},
308 .eventName =
"displayIdChange",
309 .eventHandler = &
QOhosWindowProxy::JsScopeData::handleWindowDisplayIdChangeCallback,
310 .eventHandlerFlags = EventHandlerFlagBits::allowEventHandlerRegistrationFailure,
317 QtOhos::makeProxyWithJsThreadDeleter(
318 std::make_shared<JsScopeData>(
319 windowProxyData.windowProxyType,
320 std::move(windowProxyData.jsWindow),
321 std::move(windowProxyData.jsKeepAliveData),
322 std::move(windowProxyData.qAbilityPeer),
323 windowProxyData.owningQWindowRef)))
325 , m_nodeXComponent(windowProxyData.nodeXComponent)
326 , m_qAbilityInstanceId(m_jsScopeData->qAbilityPeer->instanceId())
328 std::vector<std::shared_ptr<
void>> eventListenersHandles;
329 for (
const auto &eventHandlerDescriptor : eventHandlerDescriptors) {
330 eventListenersHandles.push_back(
331 m_jsScopeData->registerEventListener(
332 eventHandlerDescriptor.eventName, eventHandlerDescriptor.eventHandler,
333 eventHandlerDescriptor.eventHandlerFlags));
335 m_jsScopeData->m_eventListenersHandle = QtOhos::moveToSharedPtr(std::move(eventListenersHandles));
345 m_subWindowCloseRegistrationHandle.reset();
346 m_jsScopeData.reset();
353 if (m_jsScopeData->isWindowClosing()) {
357 auto optQUiAbilityPeer
359 if (!optQUiAbilityPeer) {
363 auto promise = optQUiAbilityPeer->windowStage().evalToPromiseOrRejectOnThrow(
364 "removeStartingWindow()");
365 promise.onFinally(
std::move(taskPromise).makeChained(Q_FUNC_INFO));
373 auto displayIdValue = optMoveToTargetDisplay.value_or(QOhosDisplayInfo::JsDisplayId(-1)).value();
374 qOhosPrintfDebug(
"%s: %d,%d,%f", Q_FUNC_INFO, point.x(), point.y(), displayIdValue);
377 [&](
QtOhos::
JsState &jsState, QOhosTaskPromise<> taskPromise) {
378 if (m_jsScopeData->isWindowClosing()) {
383 const auto primaryJsDisplayId = QOhosDisplayInfo::JsDisplayId(0);
385 auto targetDisplayId = optMoveToTargetDisplay.has_value()
386 ? optMoveToTargetDisplay.value()
389 auto optDisplayInfo = qTransform(
390 QOhosDisplayInfo::tryGetDisplayById(jsState, targetDisplayId),
391 [&](
auto displayObject) {
392 return QOhosDisplayInfo::makeFromOhosDisplayObject(jsState, displayObject);
395 auto optIsDisplayMainOrExtended = qTransform(
401 bool isDisplayMainOrExtended;
402 if (optIsDisplayMainOrExtended.has_value()) {
403 isDisplayMainOrExtended = optIsDisplayMainOrExtended.value();
406 "%s: no display source mode detected. Assumming main/extended screen", Q_FUNC_INFO);
407 isDisplayMainOrExtended =
true;
410 QNapi::Promise promise;
411 if (!isDisplayMainOrExtended) {
412 auto optDisplayOffset = qAndThen(
415 return displayInfo.topLeftOffsetPixels;
418 const QPoint defaultDisplayOffset(0, 0);
419 auto targetCoordinates = point - optDisplayOffset.value_or(defaultDisplayOffset);
421 if (!optMoveToTargetDisplay.has_value())
422 qOhosPrintfWarning(
"%s: trying to move window to not valid target display", Q_FUNC_INFO);
424 auto moveConfigurationObject = toNapiObject(
427 .displayId = optMoveToTargetDisplay,
430 promise = m_jsScopeData->jsWindowRef->evalToPromiseOrRejectOnThrow(
431 "moveWindowToGlobal(*)", {targetCoordinates.x(), targetCoordinates.y(), moveConfigurationObject});
433 promise = m_jsScopeData->jsWindowRef->evalToPromiseOrRejectOnThrow(
434 "moveWindowToGlobalDisplay(*)", {point.x(), point.y()});
437 promise.onFinally(
std::move(taskPromise));
443 qOhosPrintfDebug(
"%s: %d,%d", Q_FUNC_INFO, size.width(), size.height());
447 if (m_jsScopeData->isWindowClosing()) {
452 const auto currentSize = getWindowPropertiesFromJsWindow(
453 m_jsScopeData->jsWindowRef->jsObject()).windowRect.size();
454 if (currentSize == size) {
459 auto promise = m_jsScopeData->jsWindowRef->evalToPromiseOrRejectOnThrow(
460 "resizeAsync(*)", {size.width(), size.height()});
461 promise.onFinally(
std::move(taskPromise).makeChained(Q_FUNC_INFO));
468 qCDebug(QtForOhos) << Q_FUNC_INFO << color;
471 if (m_jsScopeData->isWindowClosing())
473 m_jsScopeData->jsWindowRef->eval(
"setWindowBackgroundColor(*)", {color.name(QColor::HexArgb).toStdString()});
480 const auto maxOhosCustomCursorSize = QSize(256, 256);
481 const auto customCursorSize = customCursorImage.size();
482 if (customCursorSize.width() > maxOhosCustomCursorSize.width()
483 || customCursorSize.height() > maxOhosCustomCursorSize.height()) {
485 "%s: can't set %dx%d custom cursor, OHOS max custom cursor size is %dx%d",
486 Q_FUNC_INFO, customCursorSize.width(), customCursorSize.height(),
487 maxOhosCustomCursorSize.width(), maxOhosCustomCursorSize.height());
491 auto convertedImage = customCursorImage.convertToFormat(QImage::Format_RGBA8888);
493 if (m_jsScopeData->isWindowClosing()) {
497 auto windowId = m_jsScopeData->jsWindowRef->jsObject().get<QNapi::Number>(
"getWindowProperties().id");
499 auto jsCursor = QNapi::makeObject(
502 {
"pixelMap", makeOhosNapiPixelMapFromQImage(jsState, convertedImage)},
503 {
"focusX", hotSpot.x()},
504 {
"focusY", hotSpot.y()},
507 auto jsCursorConfig = QNapi::makeObject(
510 {
"followSystem",
false},
513 jsState.evalToPromiseOrRejectOnThrow(
514 "@ohos.multimodalInput.pointer.setCustomCursor(*)", {windowId, jsCursor, jsCursorConfig})
515 .onCatch(QtOhos::makeErrorLoggingJsCallback(
"setCustomCursor()"))
516 .onFinally(
std::move(taskPromise).makeChained(Q_FUNC_INFO));
524 if (m_jsScopeData->isWindowClosing())
526 auto windowId = m_jsScopeData->jsWindowRef->jsObject().get<QNapi::Number>(
"getWindowProperties().id");
529 "@ohos.multimodalInput.pointer.setPointerStyleSync(*)",
530 {windowId, jsState.mapOhosEnumToJs(convertToOhosCursor(cursor.shape()))});
537 return QtOhos::evalInJsThread(
539 if (m_jsScopeData->isWindowClosing())
540 return QArkUi::WindowProperties {};
541 return getWindowPropertiesFromJsWindow(m_jsScopeData->jsWindowRef->jsObject());
551 m_jsScopeData->windowCallbackReceiver = QtOhos::moveToSharedPtr(WindowCallbacks {
552 .onWindowEvent = makeQtThreadWindowCallbackDelegate(&WindowCallbacks::onWindowEvent, sharedWindowCallbackReceiver),
553 .onWindowStatusChange = makeQtThreadWindowCallbackDelegate(&WindowCallbacks::onWindowStatusChange, sharedWindowCallbackReceiver),
554 .onWindowVisibilityChange = makeQtThreadWindowCallbackDelegate(&WindowCallbacks::onWindowVisibilityChange, sharedWindowCallbackReceiver),
555 .onTouchOutside = makeQtThreadWindowCallbackDelegate(&WindowCallbacks::onTouchOutside, sharedWindowCallbackReceiver),
556 .onAvoidAreaChange = makeQtThreadWindowCallbackDelegate(&WindowCallbacks::onAvoidAreaChange, sharedWindowCallbackReceiver),
557 .onWindowRectChange = makeCompressingQtThreadWindowCallbackDelegate(&WindowCallbacks::onWindowRectChange, sharedWindowCallbackReceiver),
558 .onWindowRectChangeInGlobalDisplay = makeCompressingQtThreadWindowCallbackDelegate(&WindowCallbacks::onWindowRectChangeInGlobalDisplay, sharedWindowCallbackReceiver),
559 .onWindowDisplayIdChange = makeQtThreadWindowCallbackDelegate(&WindowCallbacks::onWindowDisplayIdChange, sharedWindowCallbackReceiver),
564 m_qtWindowCallbacksReceiverHandle = sharedWindowCallbackReceiver;
568 QObject *contextObject, QOhosConsumer<std::vector<NonClientAreaMouseEvent>> mouseEventBatchConsumer)
570 auto qtConsumer = QtOhos::moveToSharedPtr(std::move(mouseEventBatchConsumer));
571 auto weakQtConsumer = QtOhos::makeWeakPtr(qtConsumer);
574 QtOhos::QObjectThreadSafeRef(contextObject),
575 [weakQtConsumer](std::vector<NonClientAreaMouseEvent> &&batch) {
576 auto qtConsumer = weakQtConsumer.lock();
578 (*qtConsumer)(
std::move(batch));
582 m_jsScopeData->nonClientAreaMouseEventConsumer = std::move(jsConsumer);
586 m_qtNonClientAreaMouseWindowCallbackReceiverHandle = qtConsumer;
590 QObject *contextObject, QOhosConsumer<std::vector<NonClientAreaTouchEvent>> touchEventBatchConsumer)
592 auto qtConsumer = QtOhos::moveToSharedPtr(std::move(touchEventBatchConsumer));
593 auto weakQtConsumer = QtOhos::makeWeakPtr(qtConsumer);
596 QtOhos::QObjectThreadSafeRef(contextObject),
597 [weakQtConsumer](std::vector<NonClientAreaTouchEvent> &&batch) {
598 auto qtConsumer = weakQtConsumer.lock();
600 (*qtConsumer)(
std::move(batch));
604 m_jsScopeData->nonClientAreaTouchEventConsumer = std::move(jsConsumer);
608 m_qtNonClientAreaTouchWindowCallbackReceiverHandle = qtConsumer;
618 qCDebug(QtForOhos,
"%s", Q_FUNC_INFO);
620 if (m_jsScopeData->isWindowClosing()) {
624 auto promise = m_jsScopeData->jsWindowRef->evalToPromiseOrRejectOnThrow(
"raiseToAppTop()");
625 promise.onFinally(
std::move(taskPromise).makeChained(Q_FUNC_INFO));
632 qCDebug(QtForOhos,
"%s", Q_FUNC_INFO);
634 if (m_jsScopeData->isWindowClosing()) {
639 std::vector<std::pair<std::string, QNapi::ValueWrapper>> jsOptionsProps;
641 if (options.focusOnShow.has_value())
642 jsOptionsProps.emplace_back(
"focusOnShow", options.focusOnShow.value());
644 std::vector<QNapi::ValueWrapper> showWindowArgs;
645 constexpr bool brokenHandlingOfEmptyOptionsParamInOhos =
true;
646 if (!(jsOptionsProps.empty() && brokenHandlingOfEmptyOptionsParamInOhos))
647 showWindowArgs.push_back(QNapi::makeObject(jsState.env(), jsOptionsProps));
649 auto promise = m_jsScopeData->jsWindowRef->evalToPromiseOrRejectOnThrow(
"showWindow(*)", showWindowArgs);
650 promise.onFinally(
std::move(taskPromise).makeChained(Q_FUNC_INFO));
657 qCDebug(QtForOhos,
"%s", Q_FUNC_INFO);
659 if (m_jsScopeData->isWindowClosing())
661 m_jsScopeData->jsWindowRef->eval(
"recover()");
668 qCDebug(QtForOhos,
"%s", Q_FUNC_INFO);
670 if (m_jsScopeData->isWindowClosing()) {
674 m_jsScopeData->jsWindowRef->evalToPromiseOrRejectOnThrow(
"restore()").onFinally(std::move(taskPromise).makeChained(Q_FUNC_INFO));
681 qCDebug(QtForOhos,
"%s", Q_FUNC_INFO);
683 if (m_jsScopeData->isWindowClosing()) {
687 m_jsScopeData->jsWindowRef->evalToPromiseOrRejectOnThrow(
"minimize()").onFinally(std::move(taskPromise).makeChained(Q_FUNC_INFO));
694 qCDebug(QtForOhos,
"%s", Q_FUNC_INFO);
697 qCWarning(QtForOhos(),
"%s: Maximize is currently supported only on main windows", Q_FUNC_INFO);
702 if (m_jsScopeData->isWindowClosing())
704 m_jsScopeData->jsWindowRef->eval(
"maximize(*)", {jsState.mapOhosEnumToJs(maximizePresentation)});
711 qCDebug(QtForOhos,
"%s: %s", Q_FUNC_INFO, isLayoutFullScreen ?
"true" :
"false");
714 if (m_jsScopeData->isWindowClosing()) {
718 m_jsScopeData->jsWindowRef->evalToPromiseOrRejectOnThrow(
719 "setWindowLayoutFullScreen(*)", {isLayoutFullScreen})
720 .onCatch(QtOhos::makeErrorLoggingJsCallback(
"setWindowLayoutFullScreen()"))
721 .onFinally(std::move(taskPromise).makeChained(Q_FUNC_INFO));
728 qCDebug(QtForOhos) << Q_FUNC_INFO << names;
730 [&](
QtOhos::
JsState &jsState, QOhosTaskPromise<> taskPromise) {
731 if (m_jsScopeData->isWindowClosing()) {
735 m_jsScopeData->jsWindowRef->evalToPromiseOrRejectOnThrow(
736 "setWindowSystemBarEnable(*)",
737 {QNapi::makeArray(jsState.env(), names, std::mem_fn(&QString::toStdString))})
738 .onCatch(QtOhos::makeErrorLoggingJsCallback(
"setWindowSystemBarEnable()"))
739 .onFinally(std::move(taskPromise).makeChained(Q_FUNC_INFO));
746 qCDebug(QtForOhos,
"%s", Q_FUNC_INFO);
749 if (m_jsScopeData->isWindowClosing()) {
754 m_jsScopeData->qAbilityPeer->qAbility().evalToPromiseOrRejectOnThrow(
"context.showAbility()")
755 .onCatch(QtOhos::makeErrorLoggingJsCallback(
"showAbility()"))
756 .onFinally(std::move(taskPromise).makeChained(Q_FUNC_INFO));
763 qCDebug(QtForOhos,
"%s", Q_FUNC_INFO);
765 return QtOhos::evalInJsThreadWithPromise<
bool>([&](
QtOhos::
JsState &, QOhosTaskPromise<
bool> evalPromise) {
766 if (m_jsScopeData->isWindowClosing()) {
771 auto thenCatchPromises =
std::move(evalPromise).makeThenCatchBranches(Q_FUNC_INFO);
772 m_jsScopeData->qAbilityPeer->qAbility().evalToPromiseOrRejectOnThrow(
"context.hideAbility()")
774 [thenPromise = std::move(thenCatchPromises.first)](
const QtOhos::CallbackInfo &) {
778 [catchPromise = std::move(thenCatchPromises.second)](
const QtOhos::CallbackInfo &cbInfo) {
779 QtOhos::logJsCallbackError(cbInfo,
"got error from hideAbility()");
788 return QtOhos::evalInJsThread(
790 if (m_jsScopeData->isWindowClosing())
792 return m_jsScopeData->jsWindowRef->eval<QNapi::Boolean>(
"getImmersiveModeEnabledState()").Value();
799 qCDebug(QtForOhos,
"%s: %s", Q_FUNC_INFO, privacyMode ?
"true" :
"false");
802 if (m_jsScopeData->isWindowClosing()) {
807 m_jsScopeData->jsWindowRef->evalToPromiseOrRejectOnThrow(
"setWindowPrivacyMode(*)", {privacyMode})
808 .onCatch(QtOhos::makeErrorLoggingJsCallback(
"setPrivacyMode()"))
809 .onFinally(std::move(taskPromise).makeChained(Q_FUNC_INFO));
816 qCDebug(QtForOhos,
"%s: %s", Q_FUNC_INFO, focusable ?
"true" :
"false");
818 if (m_jsScopeData->isWindowClosing())
820 m_jsScopeData->jsWindowRef->eval(
"setWindowFocusable(*)", {focusable});
827 qCDebug(QtForOhos,
"%s: %s", Q_FUNC_INFO, touchable ?
"true" :
"false");
829 if (m_jsScopeData->isWindowClosing())
831 m_jsScopeData->jsWindowRef->eval(
"setWindowTouchable(*)", {touchable});
839 QtForOhos,
"%s: (%d x %d)-(%d x %d)", Q_FUNC_INFO, minSize.width(), minSize.height(),
840 maxSize.width(), maxSize.height());
842 [&](
QtOhos::
JsState &jsState, QOhosTaskPromise<> taskPromise) {
843 if (m_jsScopeData->isWindowClosing()) {
847 auto windowLimits = QNapi::makeObject(
850 {
"minWidth", minSize.width()},
851 {
"minHeight", minSize.height()},
852 {
"maxWidth", maxSize.width()},
853 {
"maxHeight", maxSize.height()},
856 std::vector<QNapi::ValueWrapper> setWindowLimitsArgs = {windowLimits};
858 constexpr bool isForcible =
true;
859 setWindowLimitsArgs.push_back(isForcible);
861 m_jsScopeData->jsWindowRef->evalToPromiseOrRejectOnThrow(
862 "setWindowLimits(*)", setWindowLimitsArgs)
863 .onCatch(QtOhos::makeErrorLoggingJsCallback(
"setWindowLimits()"))
864 .onFinally(std::move(taskPromise).makeChained(Q_FUNC_INFO));
871 qCDebug(QtForOhos,
"%s", Q_FUNC_INFO);
872 return QtOhos::evalInJsThread(
874 if (m_jsScopeData->isWindowClosing())
875 return WindowLimits {};
876 auto windowLimitsObject = m_jsScopeData->jsWindowRef->eval<QNapi::Object>(
"getWindowLimits()");
877 return WindowLimits {
878 .minWidth = getOptionalNumberPropAsOptionalDouble(windowLimitsObject,
"minWidth"),
879 .minHeight = getOptionalNumberPropAsOptionalDouble(windowLimitsObject,
"minHeight"),
880 .maxWidth = getOptionalNumberPropAsOptionalDouble(windowLimitsObject,
"maxWidth"),
881 .maxHeight = getOptionalNumberPropAsOptionalDouble(windowLimitsObject,
"maxHeight"),
889 qCDebug(QtForOhos,
"%s: %d", Q_FUNC_INFO, avoidAreaType);
890 return QtOhos::evalInJsThread(
892 if (m_jsScopeData->isWindowClosing())
894 auto avoidAreaObject = m_jsScopeData->jsWindowRef->eval<QNapi::Object>(
895 "getWindowAvoidArea(*)", {jsState.mapOhosEnumToJs(avoidAreaType)});
896 return mapAvoidAreaFromJs(avoidAreaObject);
902 const WindowMask &windowMask,
const std::optional<QSize> &ohosMaskSizeOverride)
907 auto ohosMaskSize = ohosMaskSizeOverride.has_value()
908 ? ohosMaskSizeOverride.value()
911 if (ohosMaskSize.isEmpty()) {
912 const auto *maskSrcSizeMsg = ohosMaskSizeOverride.has_value()
913 ?
"overridden mask source"
915 if (ohosMaskSizeOverride.has_value()) {
917 "%s failed - %s size is 0x0", maskSrcSizeMsg,
918 "QOhosWindowProxy::setWindowMask");
924 if (m_jsScopeData->isWindowClosing()) {
928 auto *env = jsState.env();
930 QNapi::Array maskRowsArray = QNapi::Array::New(env, ohosMaskSize.height());
931 const int defaultValue = windowMask.windowMaskRegion.isEmpty() ? 1 : 0;
933 for (
int rowIndex = 0; rowIndex < ohosMaskSize.height(); ++rowIndex) {
934 auto arr = QNapi::Array::New(env, ohosMaskSize.width());
935 arr.fill(defaultValue);
936 maskRowsArray[rowIndex] = arr;
939 auto valueToSet = QNapi::Number::New(env, 1);
940 for (
const auto &rect: windowMask.windowMaskRegion) {
941 auto top = qBound(0, rect.top(), ohosMaskSize.height() - 1);
942 auto bottom = qBound(0, rect.bottom(), ohosMaskSize.height() - 1);
943 auto left = qBound(0, rect.left(), ohosMaskSize.width() - 1);
944 auto right = qBound(0, rect.right(), ohosMaskSize.width() - 1);
946 for (
auto rowIndex = top; rowIndex <= bottom; ++rowIndex) {
947 auto row = maskRowsArray.Get(rowIndex).As<QNapi::Array>();
948 for (
auto columnIndex = left; columnIndex <= right; ++columnIndex)
949 row[columnIndex] = valueToSet;
953 m_jsScopeData->jsWindowRef->evalToPromiseOrRejectOnThrow(
"setWindowMask(*)", {maskRowsArray})
954 .onCatch(QtOhos::makeErrorLoggingJsCallback(
"setWindowMask()"))
955 .onFinally(std::move(taskPromise).makeChained(Q_FUNC_INFO));
967 if (m_jsScopeData->isWindowClosing()) {
971 m_jsScopeData->jsWindowRef->evalToPromiseOrRejectOnThrow(
"setSubWindowModal(*)", {
false})
972 .onCatch(QtOhos::makeErrorLoggingJsCallback(
"setSubWindowModal()"))
973 .onFinally(std::move(taskPromise).makeChained(Q_FUNC_INFO));
983 if (modalityType == ModalityType::APPLICATION_MODALITY && !QOhosSettings::instance().isWindowPcModeEnabled()) {
985 "%s: APPLICATION_MODALITY option can be used only on devices in the freeform window state - skipping",
991 [&](
QtOhos::
JsState &jsState, QOhosTaskPromise<> taskPromise) {
992 if (m_jsScopeData->isWindowClosing()) {
996 m_jsScopeData->jsWindowRef->evalToPromiseOrRejectOnThrow(
997 "setSubWindowModal(*)", {
true, jsState.mapOhosEnumToJs(modalityType)})
998 .onCatch(QtOhos::makeErrorLoggingJsCallback(
"setSubWindowModal()"))
999 .onFinally(std::move(taskPromise).makeChained(Q_FUNC_INFO));
1008 if (m_jsScopeData->isWindowClosing()) {
1013 m_jsScopeData->jsWindowRef->evalToPromiseOrRejectOnThrow(
"setWindowTitle(*)", {title.toStdString()})
1014 .onFinally(std::move(taskPromise).makeChained(Q_FUNC_INFO));
1022 "%s: isMaximizeVisible:%s, isMinimizeVisible:%s, isCloseVisible:%s",
1023 Q_FUNC_INFO, maximizeVisible ?
"true" :
"false", minimizeVisible ?
"true":
"false",
1024 closeVisible ?
"true" :
"false");
1031 if (m_jsScopeData->isWindowClosing())
1034 constexpr auto capabilityNotSupportedErrorCode = 801;
1036 jsState, capabilityNotSupportedErrorCode,
"setWindowTitleButtonVisible()",
1038 m_jsScopeData->jsWindowRef->eval(
1039 "setWindowTitleButtonVisible(*)",
1040 {maximizeVisible, minimizeVisible, closeVisible});
1052 qOhosPrintfWarning(
"%s: can be used only on 2-in-1 devices or tablets in PC mode - skipping", Q_FUNC_INFO);
1056 qOhosPrintfDebug(
"%s: topMost: %s", Q_FUNC_INFO, topmost ?
"true" :
"false");
1060 if (m_jsScopeData->isWindowClosing()) {
1065 m_jsScopeData->jsWindowRef->evalToPromiseOrRejectOnThrow(
"setWindowTopmost(*)", {topmost})
1066 .onFinally(std::move(taskPromise).makeChained(Q_FUNC_INFO));
1074 if (m_jsScopeData->isWindowClosing())
1077 m_jsScopeData->jsWindowRef->eval(
"setWindowDecorVisible(*)", {visible});
1085 qOhosPrintfWarning(
"%s: can be used only on 2-in-1 devices or tablets in PC mode - skipping", Q_FUNC_INFO);
1090 if (m_jsScopeData->isWindowClosing())
1093 m_jsScopeData->jsWindowRef->eval(
"setWindowTitleMoveEnabled(*)", {enabled});
1101 qOhosPrintfWarning(
"%s: can be used only on 2-in-1 devices or tablets - skipping", Q_FUNC_INFO);
1109 m_jsScopeData->jsWindowRef->eval(
"setWindowShadowRadius(*)", {radius});
1121 m_jsScopeData->jsWindowRef->evalToPromiseOrRejectOnThrow(
"setWindowCornerRadius(*)", {radius})
1122 .onFinally(std::move(taskPromise).makeChained(Q_FUNC_INFO));
1129 return QtOhos::evalInJsThreadWithPromise<
bool>(
1130 [&](
QtOhos::
JsState &, QOhosTaskPromise<
bool> evalPromise) {
1131 if (m_jsScopeData->isWindowClosing()) {
1136 if (!optQUiAbilityPeer) {
1141 auto thenCatchPromises =
std::move(evalPromise).makeThenCatchBranches(Q_FUNC_INFO);
1142 optQUiAbilityPeer->windowStage()
1143 .evalToPromiseOrRejectOnThrow(
"isWindowRectAutoSave()")
1145 [thenPromise = std::move(thenCatchPromises.first)](
const QtOhos::
CallbackInfo &cbInfo) {
1146 bool windowRectAutoSaveEnabled = cbInfo.getFirstArg<QNapi::Boolean>(Q_FUNC_INFO);
1147 thenPromise(windowRectAutoSaveEnabled);
1150 [catchPromise = std::move(thenCatchPromises.second)](
const QtOhos::
CallbackInfo &cbInfo) {
1151 QtOhos::logJsCallbackError(cbInfo,
"isWindowRectAutoSave()");
1152 catchPromise(
false);
1165 if (m_jsScopeData->isWindowClosing()) {
1169 m_jsScopeData->jsWindowRef->evalToPromiseOrRejectOnThrow(
"setFollowParentMultiScreenPolicy(*)", {enabled})
1170 .onCatch(QtOhos::makeErrorLoggingJsCallback(
"setFollowParentMultiScreenPolicy()"))
1171 .onFinally(std::move(taskPromise).makeChained(Q_FUNC_INFO));
1182 if (m_jsScopeData->isWindowClosing()) {
1187 m_jsScopeData->jsWindowRef->evalToPromiseOrRejectOnThrow(
"setWindowKeepScreenOn(*)", {keepScreenOn})
1188 .onCatch(QtOhos::makeErrorLoggingJsCallback(
"setWindowKeepScreenOn()"))
1189 .onFinally(std::move(taskPromise).makeChained(Q_FUNC_INFO));
1196 qCDebug(QtForOhos,
"%s: %s", Q_FUNC_INFO, mapEnumsToLogString(supportedWindowModes).c_str());
1199 [&](
QtOhos::
JsState &jsState, QOhosTaskPromise<> taskPromise) {
1200 if (m_jsScopeData->isWindowClosing()) {
1205 if (!qUiAbilityPeer) {
1210 auto jsSupportedWindowModes = QNapi::makeArray(
1211 jsState.env(), supportedWindowModes,
1213 return jsState.mapOhosEnumToJs(mode);
1216 qUiAbilityPeer->windowStage().evalToPromiseOrRejectOnThrow(
"setSupportedWindowModes(*)", {jsSupportedWindowModes})
1217 .onCatch(QtOhos::makeErrorLoggingJsCallback(
"setSupportedWindowModes()"))
1218 .onFinally(
std::move(taskPromise).makeChained(Q_FUNC_INFO));
1225 constexpr bool isSaveBySpecifiedFlag =
true;
1229 if (m_jsScopeData->isWindowClosing()) {
1234 if (!optQUiAbilityPeer) {
1239 optQUiAbilityPeer->windowStage()
1240 .evalToPromiseOrRejectOnThrow(
"setWindowRectAutoSave(*)", {enabled, isSaveBySpecifiedFlag})
1241 .onCatch(QtOhos::makeErrorLoggingJsCallback(
"setWindowRectAutoSave()"))
1242 .onFinally(
std::move(taskPromise).makeChained(Q_FUNC_INFO));
1248 std::function<
void()> handler,
bool handlerReturnValue)
1250 m_subWindowCloseRegistrationHandle =
1251 registerSubWindowCloseHandler(std::move(handler), handlerReturnValue);
1256 m_subWindowCloseRegistrationHandle.reset();
1260 std::function<
void()> handler,
bool handlerReturnValue)
1262 auto sharedHandler = QtOhos::moveToSharedPtr(std::move(handler));
1263 auto jsWindowRegistrationHandle =
QtOhos::evalInJsThread(
1265 return QtOhos::makeProxyWithJsThreadDeleter(
1266 m_jsScopeData->registerSubWindowCloseHandler(
1268 [weakHandler = QtOhos::makeWeakPtr(sharedHandler), handlerReturnValue]() {
1269 QtOhos::invokeInQtThread(
1271 auto sharedHandler = weakHandler.lock();
1275 return handlerReturnValue;
1280 return QtOhos::moveToSharedPtr(
1281 std::make_tuple(sharedHandler, jsWindowRegistrationHandle));
1288 [&](
QtOhos::
JsState &jsState, QOhosTaskPromise<std::shared_ptr<QOhosWindowProxy>> evalPromise) {
1289 auto sharedEvalPromise = QtOhos::moveToSharedPtr(std::move(evalPromise).makeChained(Q_FUNC_INFO));
1290 makeWindowProxyDataForExistingMainWindowInJsThread(
1304 [&](
QtOhos::
JsState &jsState, QOhosTaskPromise<std::shared_ptr<QOhosWindowProxy>> evalPromise) {
1305 auto sharedEvalPromise = QtOhos::moveToSharedPtr(std::move(evalPromise).makeChained(Q_FUNC_INFO));
1306 makeWindowProxyDataForFloatWindowInJsThread(
1307 jsState, createInfo,
1319 [&](
QtOhos::
JsState &jsState, QOhosTaskPromise<std::shared_ptr<QOhosWindowProxy>> evalPromise) {
1320 auto sharedEvalPromise = QtOhos::moveToSharedPtr(std::move(evalPromise).makeChained(Q_FUNC_INFO));
1321 makeWindowProxyDataForMainWindowInJsThread(
1333 return m_nodeXComponent;
1338 return m_qAbilityInstanceId;
1345 [&](
QtOhos::
JsState &jsState, QOhosTaskPromise<std::shared_ptr<QOhosWindowProxy>> evalPromise) {
1346 auto sharedEvalPromise = QtOhos::moveToSharedPtr(std::move(evalPromise).makeChained(Q_FUNC_INFO));
1347 auto proxyDataConsumer =
1354 if (m_jsScopeData->isWindowClosing()) {
1355 makeWindowProxyDataForSubWindowInJsThread(
1356 jsState, createInfo,
std::move(proxyDataConsumer));
1358 makeWindowProxyDataForSubWindowInJsThread(
1359 jsState, m_jsScopeData->jsWindowRef->jsObject(), createInfo,
1360 std::move(proxyDataConsumer));
1367 WindowProxyType windowProxyType, QNapi::Reference<QNapi::Object> jsWindow,
1368 std::shared_ptr<
void> optKeepAliveData,
1370 QtOhos::QObjectThreadSafeRef owningQWindowRef)
1371 : windowProxyType(windowProxyType)
1372 , windowCallbackReceiver(
nullptr)
1373 , windowDestroyedFromSystem(
false)
1374 , optKeepAliveData(optKeepAliveData)
1375 , qAbilityPeer(qAbilityPeer)
1376 , m_windowFrameMouseFilterHandle(
1377 QArkUi::registerMouseEventsConsumer(
1378 getWindowPropertiesFromJsWindow(jsWindow.Value()).id,
1379 [
this](
const QArkUi::MouseEvent &event) {
1380 onMouseEventFromArkUi(event);
1382 , m_windowFrameTouchFilterHandle(
1383 QArkUi::registerTouchEventsConsumer(
1384 getWindowPropertiesFromJsWindow(jsWindow.Value()).id,
1385 [
this](
const QArkUi::TouchEvent &event) {
1386 onTouchEventFromArkUi(event);
1389 std::make_shared<QArkUi::JsWindowRef>(
1390 qAbilityPeer->instanceId(),
1391 getWindowPropertiesFromJsWindow(jsWindow.Value()).id,
1399 if (isWindowClosingFromSystem(jsWindowRef->jsObject(), windowProxyType, qAbilityPeer)) {
1400 windowDestroyedFromSystem =
true;
1404 QtOhos::JsWindowsTracker::tagWindowAsClosing(jsWindowRef->jsObject(),
"QOhosWindowProxy::JsScopeData destructor");
1410 windowDestroyedFromSystem =
true;
1412 "Attempting to terminate qAbility with instance id: %s",
1413 qAbilityPeer->instanceId().c_str());
1414 qAbilityPeer->qAbility().eval(
"context.terminateSelf()");
1415 }
else if (!windowDestroyedFromSystem) {
1418 jsWindowRef->eval(
"destroyWindow()");
1423 const std::string &eventName,
1425 QFlags<EventHandlerFlagBits> eventHandlerFlags)
1428 std::weak_ptr<JsScopeData> weakSelf = shared_from_this();
1429 bool ignoreWhenAbilityIsTerminating = !eventHandlerFlags.testFlag(EventHandlerFlagBits::allowCallWhenAbilityIsTerminating);
1431 return registerQOhosOnOffMethodsBasedEventHandler(
1432 jsWindowRef->jsObject(), eventName,
1433 [weakSelf, handleFunction, eventName, ignoreWhenAbilityIsTerminating](
const QtOhos::
CallbackInfo &cbInfo) {
1434 auto self = weakSelf.lock();
1435 if (Q_UNLIKELY(!self)) {
1437 "callback '%s' called for destroyed QOhosWindowProxy::JsScopeData, ignoring",
1442 if (self->isWindowClosing() && ignoreWhenAbilityIsTerminating) {
1444 "QOhosWindowProxy: Received callback for event '%s' during termination of the related QAbility.",
1449 if (Q_UNLIKELY(self->windowDestroyedFromSystem)) {
1451 "QOhosWindowProxy: Received callback for event '%s' after WINDOW_DESTROYED",
1456 ((*self).*handleFunction)(cbInfo);
1459 .optEventSourceAliveCheckFunc = {},
1462 .optOnCallExceptionHandler = [&](
const Napi::Error &error) {
1463 constexpr std::uint32_t capabilityNotSupportedErrorCode = 801;
1464 constexpr std::uint32_t windowStateIsAbnormalErrorCode = 1300002;
1466 const QSet<std::uint32_t> ignorableErrorCodes = {
1467 capabilityNotSupportedErrorCode,
1468 windowStateIsAbnormalErrorCode,
1471 auto errorCode = QtOhos::tryGetCodeFromJsBusinessError(error);
1473 auto ignorableError =
1474 eventHandlerFlags.testFlag(EventHandlerFlagBits::allowEventHandlerRegistrationFailure)
1475 && errorCode.has_value()
1476 && ignorableErrorCodes.contains(errorCode.value());
1478 if (!ignorableError)
1482 "%s: Ignored error %u while registering for window event '%s'",
1483 Q_FUNC_INFO, errorCode.value(), eventName.c_str());
1491 auto weakSelf = QtOhos::makeWeakPtr(shared_from_this());
1492 return registerQOhosOnOffMethodsBasedEventHandler(
1493 jsWindowRef->jsObject(),
"subWindowClose",
1495 bool deferClose = handler();
1496 auto self = weakSelf.lock();
1497 if (self && !deferClose)
1498 QtOhos::JsWindowsTracker::tagWindowAsClosing(self->jsWindowRef->jsObject(),
"subWindowClose => false");
1499 return QNapi::Boolean::New(cbInfo.Env(), deferClose);
1505 auto eventType = cbInfo.getFirstArg<QNapi::Number>(Q_FUNC_INFO);
1510 event.type = cbInfo.jsState().mapOhosEnumFromJs<WindowEventType>(eventType);
1511 }
catch (
const Napi::Error &err) {
1513 "Error converting WindowEventType to known value: %s. Event will be ignored.", err.what());
1517 if (isWindowClosing() && event.type != WindowEventType::WINDOW_DESTROYED) {
1519 "Received WindowEvent for window when it's closing. WindowEventType: %d",
1529 auto windowStatusType = cbInfo.getFirstArg<QNapi::Number>(Q_FUNC_INFO);
1530 if (windowCallbackReceiver !=
nullptr) {
1531 windowCallbackReceiver->onWindowStatusChange(
1533 .type = cbInfo.jsState().mapOhosEnumFromJs<WindowStatusType>(windowStatusType),
1540 auto windowVisibility = cbInfo.getFirstArg<QNapi::Boolean>(Q_FUNC_INFO);
1541 if (windowCallbackReceiver !=
nullptr)
1542 windowCallbackReceiver->onWindowVisibilityChange(windowVisibility);
1547 if (windowCallbackReceiver !=
nullptr)
1548 windowCallbackReceiver->onTouchOutside();
1553 if (windowCallbackReceiver !=
nullptr) {
1554 auto callbackArg = cbInfo.getFirstArg<QNapi::Object>(Q_FUNC_INFO);
1555 windowCallbackReceiver->onAvoidAreaChange(
1556 cbInfo.jsState().mapOhosEnumFromJs<AvoidAreaType>(callbackArg.get<QNapi::Number>(
"type")),
1557 mapAvoidAreaFromJs(callbackArg.get<QNapi::Object>(
"area")));
1563 auto rectChangeOptionsObjectArg = cbInfo.getFirstArg<QNapi::Object>(Q_FUNC_INFO);
1564 auto rectChangeOptions = RectChangeOptions {
1565 .rect = ohosWindowRectToQRect(rectChangeOptionsObjectArg.get<QNapi::Object>(
"rect")),
1566 .reason = cbInfo.jsState().mapOhosEnumFromJs<RectChangeReason>(rectChangeOptionsObjectArg.get<QNapi::Number>(
"reason")),
1569 if (windowCallbackReceiver !=
nullptr)
1570 windowCallbackReceiver->onWindowRectChange(rectChangeOptions);
1575 auto rectChangeOptionsObjectArg = cbInfo.getFirstArg<QNapi::Object>(Q_FUNC_INFO);
1576 auto rectChangeOptions = RectChangeOptions {
1577 .rect = ohosWindowRectToQRect(rectChangeOptionsObjectArg.get<QNapi::Object>(
"rect")),
1578 .reason = cbInfo.jsState().mapOhosEnumFromJs<RectChangeReason>(rectChangeOptionsObjectArg.get<QNapi::Number>(
"reason")),
1581 if (windowCallbackReceiver !=
nullptr)
1582 windowCallbackReceiver->onWindowRectChangeInGlobalDisplay(rectChangeOptions);
1587 auto displayIdNumber = cbInfo.getFirstArg<QNapi::Number>(Q_FUNC_INFO);
1590 if (windowCallbackReceiver !=
nullptr)
1591 windowCallbackReceiver->onWindowDisplayIdChange(displayId);
1596 if (windowEvent.type == WindowEventType::WINDOW_DESTROYED) {
1597 QtOhos::JsWindowsTracker::tagWindowAsClosing(jsWindowRef->jsObject(),
"WINDOW_DESTROYED");
1598 windowDestroyedFromSystem =
true;
1601 if (windowCallbackReceiver !=
nullptr)
1602 windowCallbackReceiver->onWindowEvent(windowEvent);
1607 return isWindowClosingFromSystem(jsWindowRef->jsObject(), windowProxyType, qAbilityPeer);
1612 if (nonClientAreaMouseEventConsumer ==
nullptr)
1615 auto optAction = tryMapMouseEventActionToNonClientAreaEventType(event.action);
1616 if (!optAction.has_value())
1620 if (!optWindowProperties.has_value()) {
1622 "%s: Failed to retrieve window properties for js window: %f. Ignoring event.",
1623 Q_FUNC_INFO, event.jsWindowId.value());
1627 const auto &windowProperties = optWindowProperties.value();
1628 if (!isPointInNonClientArea(event.displayPosition, windowProperties))
1631 auto windowOrigin = windowProperties.windowRect.topLeft() + windowProperties.drawableRect.topLeft();
1633 .timestamp = std::chrono::duration_cast<std::chrono::milliseconds>(event.actionTime),
1634 .action = optAction.value(),
1635 .button = tryMapMouseEventButtonToQt(event.button).value_or(Qt::NoButton),
1636 .displayPosition = event.displayPosition,
1637 .localPosition = event.displayPosition - windowOrigin,
1638 .globalPosition = event.globalPosition,
1641 nonClientAreaMouseEventConsumer(nonClientAreaMouseEvent);
1646 if (nonClientAreaTouchEventConsumer ==
nullptr)
1649 auto optAction = tryMapTouchEventActionToNonClientAreaEventType(event.action);
1650 if (!optAction.has_value())
1654 if (!optWindowProperties.has_value()) {
1656 "%s: Failed to retrieve window properties for js window: %f. Ignoring event.",
1657 Q_FUNC_INFO, event.jsWindowId.value());
1661 const auto &windowProperties = optWindowProperties.value();
1662 if (!isPointInNonClientArea(event.displayPosition, windowProperties))
1665 auto windowOrigin = windowProperties.windowRect.topLeft() + windowProperties.drawableRect.topLeft();
1668 .timestamp =
std::chrono::duration_cast<
std::chrono::milliseconds>(event.actionTime),
1669 .action = optAction.value(),
1670 .displayPosition = event.displayPosition,
1671 .localPosition = event.displayPosition - windowOrigin,
1672 .globalPosition = event.globalPosition,
1675 nonClientAreaTouchEventConsumer(nonClientAreaTouchEvent);
1680 return QtOhos::evalInJsThreadWithPromise<QPixmap>(
1681 [&](QtOhos::JsState &, QOhosTaskPromise<QPixmap> evalPromise) {
1682 auto thenCatchPromises = std::move(evalPromise).makeThenCatchBranches(Q_FUNC_INFO);
1683 m_jsScopeData->jsWindowRef->evalToPromiseOrRejectOnThrow(
"snapshot()")
1685 [thenPromise = std::move(thenCatchPromises.first)](
const QtOhos::CallbackInfo &cbInfo) {
1686 auto napiPixmap = cbInfo.getFirstArg<QNapi::Object>(Q_FUNC_INFO);
1688 ::OH_PixelmapNative *pixelMapNativePtr;
1689 QArkUi::callArkUiOrFailOnErrorResult(
1690 Q_OHOS_NAMED_FUNC(::OH_PixelmapNative_ConvertPixelmapNativeFromNapi),
1691 cbInfo.Env(), napiPixmap, &pixelMapNativePtr);
1692 auto pixelMap = wrapOhosNativePixelMapPtr(pixelMapNativePtr);
1695 QPixmap::fromImage(createQImageFromNativePixelMap(pixelMap.get())));
1698 [catchPromise = std::move(thenCatchPromises.second)](
const QtOhos::CallbackInfo &cbInfo) {
1699 QtOhos::logJsCallbackError(cbInfo,
"Got error from snapshot()");
1700 catchPromise(QPixmap());
1710 return QtOhos::evalInJsThreadWithPromise<QList<QRect>>(
1711 [&](QtOhos::JsState &jsState, QOhosTaskPromise<QList<QRect>> evalPromise) {
1712 if (m_jsScopeData->isWindowClosing()) {
1713 evalPromise(QList<QRect>());
1717 auto optWindowDisplay = qAndThen(
1718 getWindowPropertiesFromJsWindow(
1719 m_jsScopeData->jsWindowRef->jsObject()).displayId,
1720 [&](QOhosDisplayInfo::JsDisplayId id) {
1721 return QOhosDisplayInfo::tryGetDisplayById(jsState, id);
1723 auto display = optWindowDisplay.has_value()
1724 ? optWindowDisplay.value()
1725 : jsState.eval<QNapi::Object>(
"@ohos.display.getDefaultDisplaySync()");
1727 auto branches = std::move(evalPromise).makeThenCatchBranches(Q_FUNC_INFO);
1729 .evalToPromiseOrRejectOnThrow(
"getCutoutInfo()")
1731 [thenPromise = std::move(branches.first)](
const QtOhos::CallbackInfo &cbInfo) {
1732 auto cutoutInfo = cbInfo.getFirstArg<QNapi::Object>(Q_FUNC_INFO);
1733 auto cutoutRects = QNapi::getArrayElements<QList<QRect>, QNapi::Object>(
1734 cutoutInfo.get<QNapi::Array>(
"boundingRects"), [](QNapi::Object r) {
1735 return QRect(r.get<QNapi::Number>(
"left"),
1736 r.get<QNapi::Number>(
"top"),
1737 r.get<QNapi::Number>(
"width"),
1738 r.get<QNapi::Number>(
"height"));
1740 thenPromise(cutoutRects);
1743 [catchPromise = std::move(branches.second)](
const QtOhos::CallbackInfo &cbInfo) {
1744 QtOhos::logJsCallbackError(cbInfo,
"getCutoutInfo() failed");
1745 catchPromise(QList<QRect>());
1755 if (m_jsScopeData->isWindowClosing()) {
1760 m_jsScopeData->jsWindowRef->evalToPromiseOrRejectOnThrow(
"startMoving()")
1761 .onCatch(QtOhos::makeErrorLoggingJsCallback(
"startMoving()"))
1762 .onFinally(std::move(taskPromise).makeChained(Q_FUNC_INFO));
1774 qCWarning(QtForOhos(),
"%s: enableDrag is not supported on main windows", Q_FUNC_INFO);
1780 if (m_jsScopeData->isWindowClosing()) {
1784 m_jsScopeData->jsWindowRef->evalToPromiseOrRejectOnThrow(
"enableDrag(*)", {enable})
1785 .onCatch(QtOhos::makeErrorLoggingJsCallback(
"enableDrag()"))
1786 .onFinally(std::move(taskPromise).makeChained(Q_FUNC_INFO));
1793 return QtOhos::evalInJsThread(
1795 if (m_jsScopeData->isWindowClosing())
1798 return m_jsScopeData->jsWindowRef->eval<QNapi::Boolean>(
"isFocused()");
1804 QOhosDisplayInfo::JsDisplayId displayId,
const QPoint &queryLocation,
std::uint32_t queryLimit)
1806 return QtOhos::evalInJsThreadWithPromise<std::vector<QArkUi::JsWindowId>>(
1807 [&](QtOhos::JsState &jsState,
auto evalPromise) {
1808 auto thenCatchPromises = std::move(evalPromise).makeThenCatchBranches(Q_FUNC_INFO);
1809 jsState.evalToPromiseOrRejectOnThrow(
"@ohos.window.getWindowsByCoordinate(*)", {
1815 .onThen([thenPromise = std::move(thenCatchPromises.first)](
const QtOhos::CallbackInfo &cbInfo) {
1816 auto windowsArray = cbInfo.getFirstArg<QNapi::Array>(Q_FUNC_INFO);
1818 QNapi::getArrayElements<std::vector<QArkUi::JsWindowId>, QNapi::Object>(
1820 [&](QNapi::Object jsWindow) {
1821 return getWindowPropertiesFromJsWindow(jsWindow).id;
1824 .onCatch([catchPromise = std::move(thenCatchPromises.second)](
const QtOhos::CallbackInfo &cbInfo) {
1825 QtOhos::logJsCallbackError(
1826 cbInfo,
"got error from @ohos.window.getWindowsByCoordinate()");
1838 return jsWindowRegistry.queryByPredicate(jsState, predicate);
1847 [&](
QtOhos::
JsState &jsState, QOhosTaskPromise<> taskPromise) {
1848 if (m_jsScopeData->isWindowClosing()) {
1853 auto moveConfigurationObject = toNapiObject(jsState.env(), moveConfiguration);
1854 auto moveConfigurationObjectStr = QNapi::toJsonString(moveConfigurationObject);
1857 Q_FUNC_INFO, position.x(), position.y(),
1858 moveConfigurationObjectStr.c_str());
1860 m_jsScopeData->jsWindowRef->evalToPromiseOrRejectOnThrow(
1861 "moveWindowToGlobal(*)", {position.x(), position.y(), moveConfigurationObject})
1862 .onFinally(std::move(taskPromise).makeChained(Q_FUNC_INFO));
1871 :
QtOhos::evalInJsThread(
1875 return qUiAbilityPeer
1876 ? getWindowPropertiesFromJsWindow(qUiAbilityPeer->window()).displayId
1885 [&](
QtOhos::
JsState &jsState, QOhosTaskPromise<> taskPromise) {
1886 if (m_jsScopeData->isWindowClosing() || targetProxy.m_jsScopeData->isWindowClosing()) {
1891 auto srcWindowId = getWindowPropertiesFromJsWindow(m_jsScopeData->jsWindowRef->jsObject()).id;
1892 auto targetWindowId = getWindowPropertiesFromJsWindow(targetProxy.m_jsScopeData->jsWindowRef->jsObject()).id;
1893 jsState.evalToPromiseOrRejectOnThrow(
1894 "@ohos.window.shiftAppWindowFocus(*)", {srcWindowId.value(), targetWindowId.value()})
1895 .onCatch(QtOhos::makeErrorLoggingJsCallback(
"@ohos.window.shiftAppWindowFocus()"))
1896 .onFinally(
std::move(taskPromise).makeChained(Q_FUNC_INFO));
1905 return QtOhos::makeSharedPtrWithAttachedExtraData(
1907 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
void setWindowLayoutFullScreen(bool isLayoutFullScreen)
std::optional< QOhosDisplayInfo::JsDisplayId > tryGetMainWindowJsDisplayId() const
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)
void setWindowTouchable(bool touchable)
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)
QList< QRect > getDisplayCutoutRects() const
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.
QRect ohosWindowRectToQRect(const QNapi::Object &ohosWindowRect)
bool isPointInNonClientArea(const QPoint &point, const QArkUi::WindowProperties &windowProperties)
std::optional< QEvent::Type > tryMapMouseEventActionToNonClientAreaEventType(::Input_MouseEventAction action)
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::optional< QEvent::Type > tryMapTouchEventActionToNonClientAreaEventType(::Input_TouchEventAction action)
std::string const char * mapBoolToTrueFalseStr(bool value)
void runInJsThreadAndWait(const std::function< void(JsState &)> &task, std::string callerContextName={})
bool runIgnoringJsBusinessError(JsState &, std::uint32_t suppressedErrorCode, const char *callerContextName, const std::function< void()> &action)
void invokeInJsThreadAndWaitForContinue(std::function< void(JsState &, QOhosTaskPromise<>)> &&task, std::string callerContextName={})
QXComponent< QXComponentType::Node > QXComponentNode
bool isDisplayMainOrExtended() const
WindowProxyType windowProxyType