Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qohoswindowproxy.cpp
Go to the documentation of this file.
1// Copyright (C) 2025 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include <render/qohoswindowproxy.h>
5
6#include <QtCore/qcoreapplication.h>
7#include <QtCore/qharmonyjscontext.h>
8#include <QtCore/qset.h>
9#include <QtCore/private/qnapi_p.h>
10#include <QtCore/qscopeguard.h>
11#include <QtGui/private/qohosimageconversions_p.h>
12#include <QtGui/qguiapplication.h>
13#include <QtGui/qimage.h>
14#include <algorithm>
15#include <functional>
16#include <memory>
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 <qohosjsutils.h>
26#include <qohospixelmapconversions.h>
27#include <qohosplugincore.h>
28#include <qohosqpaenums.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>
35#include <type_traits>
36
38
39namespace
40{
41
43
44QRect ohosWindowRectToQRect(const QNapi::Object &ohosWindowRect)
45{
46 return QRect {
47 ohosWindowRect.get<QNapi::Number>("left"),
48 ohosWindowRect.get<QNapi::Number>("top"),
49 ohosWindowRect.get<QNapi::Number>("width"),
50 ohosWindowRect.get<QNapi::Number>("height"),
51 };
52}
53
54QOhosWindowProxy::AvoidArea mapAvoidAreaFromJs(const QNapi::Object &avoidAreaObject)
55{
56 return {
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")),
62 };
63}
64
66{
67 switch (shape) {
68 case Qt::ArrowCursor:
70 case Qt::UpArrowCursor:
72 case Qt::CrossCursor:
74 case Qt::WaitCursor:
76 case Qt::IBeamCursor:
78 case Qt::SizeVerCursor:
80 case Qt::SizeHorCursor:
82 case Qt::SizeBDiagCursor:
84 case Qt::SizeFDiagCursor:
86 case Qt::SizeAllCursor:
88 case Qt::BlankCursor:
89 // TODO: there is no dedicated Ohos 'Qt::BlankCursor'. Return default.
91 case Qt::SplitVCursor:
93 case Qt::SplitHCursor:
95 case Qt::PointingHandCursor:
97 case Qt::ForbiddenCursor:
99 case Qt::WhatsThisCursor:
101 case Qt::BusyCursor:
103 case Qt::OpenHandCursor:
105 case Qt::ClosedHandCursor:
107 case Qt::DragCopyCursor:
109 case Qt::DragMoveCursor:
111 case Qt::DragLinkCursor:
112 // TODO: there is no dedicated Ohos 'Qt::DragLinkCursor'. Return default.
114 case Qt::BitmapCursor:
115 // TODO: there is no dedicated Ohos 'Qt::BitmapCursor'. Return default.
117 case Qt::CustomCursor:
118 // TODO: there is no dedicated Ohos 'Qt::CustomCursor'. Return default.
120 }
121
123}
124
125std::optional<double> getOptionalNumberPropAsOptionalDouble(const QNapi::Object &object, const std::string &propertyName)
126{
127 auto propOrEmpty = QNapi::getOptionalPropOrEmpty<QNapi::Number>(object, propertyName);
128 return !propOrEmpty.IsEmpty()
129 ? std::optional<double>(propOrEmpty)
130 : std::nullopt;
131}
132
134{
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()})
143 : std::nullopt,
144 };
145}
146
147QNapi::Object toNapiObject(napi_env env, const QOhosWindowProxy::MoveConfiguration &moveConfiguration)
148{
149 auto moveConfigurationObject = QNapi::makeObject(env);
150 if (moveConfiguration.displayId.has_value()) {
151 moveConfigurationObject.set(
152 "displayId", moveConfiguration.displayId.value().value());
153 }
154 return moveConfigurationObject;
155}
156
157template<typename ...Args>
159 std::function<void(Args...)> QOhosWindowProxy::WindowCallbacks::*memberPtr,
160 std::shared_ptr<QOhosWindowProxy::WindowCallbacks> qtWindowCallbacks)
161{
162 auto weakQtWindowCallbacks = QtOhos::makeWeakPtr(qtWindowCallbacks);
163
164 return [memberPtr, weakQtWindowCallbacks](Args ...args) {
165 QtOhos::invokeInQtThread([memberPtr, weakQtWindowCallbacks, args...]() {
166 auto qtWindowCallbacks = weakQtWindowCallbacks.lock();
167 if (qtWindowCallbacks)
168 (*qtWindowCallbacks.*memberPtr)(args...);
169 });
170 };
171}
172
173template<typename T>
175 std::function<void(T)> QOhosWindowProxy::WindowCallbacks::*memberPtr,
176 std::shared_ptr<QOhosWindowProxy::WindowCallbacks> qtWindowCallbacks)
177{
178 auto weakQtWindowCallbacks = QtOhos::makeWeakPtr(qtWindowCallbacks);
179
180 return QtOhos::makeCompressingAsyncConsumer<T>(
181 [memberPtr, weakQtWindowCallbacks](T value) {
182 auto qtWindowCallbacks = weakQtWindowCallbacks.lock();
183 if (qtWindowCallbacks)
184 (*qtWindowCallbacks.*memberPtr)(value);
185 },
186 QtOhos::invokeInQtThread);
187}
188
189bool isPointInNonClientArea(const QPoint &point, const QArkUi::WindowProperties &windowProperties)
190{
191 constexpr bool containsPolicyExcludeEdgeValue = true;
192
193 auto drawableRectInScreenSpace =
194 windowProperties.drawableRect.translated(windowProperties.windowRect.topLeft());
195 return !drawableRectInScreenSpace.contains(point, containsPolicyExcludeEdgeValue);
196}
197
199{
200 switch (action) {
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:
211 break;
212 }
213 return std::nullopt;
214}
215
216std::optional<Qt::MouseButton> tryMapMouseEventButtonToQt(::Input_MouseEventButton button)
217{
218 switch (button) {
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:
230 break;
231 }
232 return std::nullopt;
233}
234
236{
237 switch (action) {
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:
245 break;
246 }
247 return std::nullopt;
248}
249
250template<typename EnumsContainer>
251std::string mapEnumsToLogString(const EnumsContainer &enums)
252{
253 std::string output;
254 for (auto enumValue : enums) {
255 if (!output.empty())
256 output += ",";
257 output += std::to_string(static_cast<std::underlying_type_t<decltype(enumValue)>>(enumValue));
258 }
259 return output;
260}
261
262bool isAbilityTerminating(QNapi::Object ability)
263{
264 return ability.eval<QNapi::Boolean>("context.isTerminating()");
265}
266
268{
269 try {
270 return jsWindowRef.eval<QNapi::Boolean>("isInFreeWindowMode()");
271 } catch (const Napi::Error &error) {
272 qOhosPrintfWarning("isInFreeWindowMode() failed (%s), assuming it is not", error.what());
273 return false;
274 }
275}
276
278 QNapi::Object jsWindow, WindowProxyType windowType, std::shared_ptr<QtOhos::QAbilityPeer> abilityPeer)
279{
280 const bool boundToAbility = windowType != WindowProxyType::FloatWindow;
281 return QtOhos::JsWindowsTracker::isWindowClosing(jsWindow) || (boundToAbility && isAbilityTerminating(abilityPeer->qAbility()));
282}
283
284}
285
286const QOhosWindowProxy::EventHandlerDescriptor QOhosWindowProxy::eventHandlerDescriptors[] = {
287 {
288 .eventName = "avoidAreaChange",
289 .eventHandler = &QOhosWindowProxy::JsScopeData::handleAvoidAreaChangeCallback,
290 .eventHandlerFlags = {},
291 },
292 {
293 .eventName = "touchOutside",
294 .eventHandler = &QOhosWindowProxy::JsScopeData::handleWindowTouchOutsideCallback,
295 .eventHandlerFlags = {},
296 },
297 {
298 .eventName = "windowEvent",
299 .eventHandler = &QOhosWindowProxy::JsScopeData::handleWindowEventCallback,
300 .eventHandlerFlags = EventHandlerFlagBits::allowCallWhenAbilityIsTerminating,
301 },
302 {
303 .eventName = "windowRectChange",
304 .eventHandler = &QOhosWindowProxy::JsScopeData::handleWindowRectChangeCallback,
305 .eventHandlerFlags = {},
306 },
307 {
308 .eventName = "rectChangeInGlobalDisplay",
309 .eventHandler = &QOhosWindowProxy::JsScopeData::handleWindowRectChangeInGlobalDisplayCallback,
310 .eventHandlerFlags = {},
311 },
312 {
313 .eventName = "windowStatusChange",
314 .eventHandler = &QOhosWindowProxy::JsScopeData::handleWindowStatusCallback,
315 .eventHandlerFlags = {},
316 },
317 {
318 .eventName = "windowVisibilityChange",
319 .eventHandler = &QOhosWindowProxy::JsScopeData::handleWindowVisibilityCallback,
320 .eventHandlerFlags = {},
321 },
322 {
323 .eventName = "displayIdChange",
324 .eventHandler = &QOhosWindowProxy::JsScopeData::handleWindowDisplayIdChangeCallback,
325 .eventHandlerFlags = EventHandlerFlagBits::allowEventHandlerRegistrationFailure,
326 },
327};
328
329QOhosWindowProxy::QOhosWindowProxy(
330 const std::function<void(QtOhos::JsState &, QOhosConsumer<QtOhos::JsState &, QOhosWindowProxyData>)> &makeWindowProxyDataInJsThread)
331{
332 auto jsThreadInitResult = QOhosJsThreadGateway::evalWithPromise<JsThreadInitResult>(
333 [&](QOhosJsState &jsState, QOhosTaskPromise<JsThreadInitResult> evalPromise) {
334 auto sharedEvalPromise = QtOhos::moveToSharedPtr(std::move(evalPromise).makeChained(Q_FUNC_INFO));
335 makeWindowProxyDataInJsThread(
336 QtOhos::JsState::castFrom(jsState),
337 [sharedEvalPromise, this](QtOhos::JsState &jsState, QOhosWindowProxyData windowProxyData) {
338 (*sharedEvalPromise)(initInJsThread(jsState, std::move(windowProxyData)));
339 });
340 },
341 Q_FUNC_INFO);
342 m_windowProxyType = jsThreadInitResult.windowProxyType;
343 m_subWindowMaximizeSupported = jsThreadInitResult.subWindowMaximizeSupported;
344 m_nodeXComponent = std::move(jsThreadInitResult.nodeXComponent);
345 m_qAbilityInstanceId = std::move(jsThreadInitResult.qAbilityInstanceId);
346 m_abilityObjectRef = std::move(jsThreadInitResult.abilityObjectRef);
347 m_jsWindowObjectRef = std::move(jsThreadInitResult.jsWindowObjectRef);
348 m_jsWindowRegistrationHandle = std::move(jsThreadInitResult.jsWindowRegistrationHandle);
349}
350
351QOhosWindowProxy::JsThreadInitResult QOhosWindowProxy::initInJsThread(
352 QtOhos::JsState &jsState, QOhosWindowProxyData windowProxyData)
353{
354 *m_jsScopeData = JsScopeData(
355 windowProxyData.windowProxyType,
356 std::move(windowProxyData.jsWindow),
357 std::move(windowProxyData.jsKeepAliveData),
358 std::move(windowProxyData.qAbilityPeer),
359 windowProxyData.owningQWindowRef);
360
361 std::vector<std::shared_ptr<void>> eventListenersHandles;
362 for (const auto &eventHandlerDescriptor : eventHandlerDescriptors) {
363 eventListenersHandles.push_back(
364 m_jsScopeData->registerEventListener(
365 eventHandlerDescriptor.eventName, eventHandlerDescriptor.eventHandler,
366 eventHandlerDescriptor.eventHandlerFlags));
367 }
368 m_jsScopeData->m_eventListenersHandle = QtOhos::moveToSharedPtr(std::move(eventListenersHandles));
369
370 auto &jsContext = QHarmonyJsContext::fromEnv(jsState.env());
371 return JsThreadInitResult {
372 .windowProxyType = windowProxyData.windowProxyType,
373 .subWindowMaximizeSupported = windowProxyData.subWindowMaximizeSupported,
374 .nodeXComponent = std::move(windowProxyData.nodeXComponent),
375 .qAbilityInstanceId = m_jsScopeData->jsWindowRef->owningQAbilityInstanceId(),
376 .abilityObjectRef = QHarmonyJsObjectRef::fromValue(jsContext, m_jsScopeData->qAbilityPeer->qAbility()),
377 .jsWindowObjectRef = QHarmonyJsObjectRef::fromValue(jsContext, m_jsScopeData->jsWindowRef->jsObject()),
378 .jsWindowRegistrationHandle = QOhosJsWindowRegistry::instance(jsState).registerJsWindow(m_jsScopeData->jsWindowRef),
379 };
380}
381
382QOhosWindowProxy::~QOhosWindowProxy()
383{
384 // NOTE
385 // we need to unregister from JS Window events now, while the Window is
386 // still in consistent state. While destroying the m_jsScopeData we
387 // call Window::destroyWindow(), which makes the JS object unusable
388 // (trying to unregister something on it will throw).
389 // The registry entry goes first so lookups never return a window being torn down.
390 m_jsWindowRegistrationHandle.reset();
391 m_subWindowCloseRegistrationHandle.reset();
392}
393
394void QOhosWindowProxy::removeStartingWindow()
395{
396 QOhosJsThreadGateway::invokeAndWaitForContinue(
397 [&](QOhosJsState &, QOhosTaskPromise<> taskPromise) {
398 if (m_jsScopeData->isWindowClosing()) {
399 taskPromise();
400 return;
401 }
402 auto optQUiAbilityPeer
403 = QtOhos::QUiAbilityPeer::tryCastFromQAbilityPeerOrNull(m_jsScopeData->qAbilityPeer);
404 if (!optQUiAbilityPeer) {
405 taskPromise();
406 return;
407 }
408 auto promise = optQUiAbilityPeer->windowStage().evalToPromiseOrRejectOnThrow(
409 "removeStartingWindow()");
410 promise
411 .onCatch(QtOhos::makeErrorLoggingJsCallback(Q_FUNC_INFO))
412 .onFinally(std::move(taskPromise).makeChained(Q_FUNC_INFO));
413 },
414 Q_FUNC_INFO);
415}
416
418 const QPoint &point, std::optional<QOhosDisplayInfo::JsDisplayId> optMoveToTargetDisplay)
419{
420 auto displayIdValue = optMoveToTargetDisplay.value_or(QOhosDisplayInfo::JsDisplayId(-1)).value();
421 qOhosPrintfDebug("%s: %d,%d,%f", Q_FUNC_INFO, point.x(), point.y(), displayIdValue);
422
423 QOhosJsThreadGateway::invokeAndWaitForContinue(
424 [&](QOhosJsState &jsState, QOhosTaskPromise<> taskPromise) {
425 if (m_jsScopeData->isWindowClosing()) {
426 taskPromise();
427 return;
428 }
429
430 const auto primaryJsDisplayId = QOhosDisplayInfo::JsDisplayId(0);
431
432 auto targetDisplayId = optMoveToTargetDisplay.has_value()
433 ? optMoveToTargetDisplay.value()
434 : getWindowProperties().displayId.value_or(primaryJsDisplayId);
435
436 auto optDisplayInfo = qTransform(
437 QOhosDisplayInfo::tryGetDisplayById(jsState, targetDisplayId),
438 [&](auto displayObject) {
439 return QOhosDisplayInfo::makeFromOhosDisplayObject(jsState, displayObject);
440 });
441
442 auto optIsDisplayMainOrExtended = qTransform(
443 optDisplayInfo,
444 [](const QOhosDisplayInfo &displayInfo) {
445 return displayInfo.isDisplayMainOrExtended();
446 });
447
448 bool isDisplayMainOrExtended;
449 if (optIsDisplayMainOrExtended.has_value()) {
450 isDisplayMainOrExtended = optIsDisplayMainOrExtended.value();
451 } else {
452 qOhosPrintfWarning(
453 "%s: no display source mode detected. Assumming main/extended screen", Q_FUNC_INFO);
454 isDisplayMainOrExtended = true;
455 }
456
457 QNapi::Promise promise;
458 if (!isDisplayMainOrExtended) {
459 auto optDisplayOffset = qAndThen(
460 optDisplayInfo,
461 [](const QOhosDisplayInfo &displayInfo) {
462 return displayInfo.topLeftOffsetPixels;
463 });
464
465 const QPoint defaultDisplayOffset(0, 0);
466 auto targetCoordinates = point - optDisplayOffset.value_or(defaultDisplayOffset);
467
468 if (!optMoveToTargetDisplay.has_value())
469 qOhosPrintfWarning("%s: trying to move window to not valid target display", Q_FUNC_INFO);
470
471 auto moveConfigurationObject = toNapiObject(
472 jsState.env(),
473 MoveConfiguration {
474 .displayId = optMoveToTargetDisplay,
475 });
476
477 promise = m_jsScopeData->jsWindowRef->evalToPromiseOrRejectOnThrow(
478 "moveWindowToGlobal(*)", {targetCoordinates.x(), targetCoordinates.y(), moveConfigurationObject});
479 } else {
480 promise = m_jsScopeData->jsWindowRef->evalToPromiseOrRejectOnThrow(
481 "moveWindowToGlobalDisplay(*)", {point.x(), point.y()});
482 }
483
484 promise
485 .onCatch(QtOhos::makeErrorLoggingJsCallback(Q_FUNC_INFO))
486 .onFinally(std::move(taskPromise));
487 });
488}
489
490void QOhosWindowProxy::setSize(const QSize &size)
491{
492 qOhosPrintfDebug("%s: %d,%d", Q_FUNC_INFO, size.width(), size.height());
493
494 QOhosJsThreadGateway::invokeAndWaitForContinue(
495 [&](QOhosJsState &, QOhosTaskPromise<> taskPromise) {
496 if (m_jsScopeData->isWindowClosing()) {
497 taskPromise();
498 return;
499 }
500
501 const auto currentSize = getWindowPropertiesFromJsWindow(
502 m_jsScopeData->jsWindowRef->jsObject()).windowRect.size();
503 if (currentSize == size) {
504 taskPromise();
505 return;
506 }
507
508 auto promise = m_jsScopeData->jsWindowRef->evalToPromiseOrRejectOnThrow(
509 "resizeAsync(*)", {size.width(), size.height()});
510 promise
511 .onCatch(QtOhos::makeErrorLoggingJsCallback(Q_FUNC_INFO))
512 .onFinally(std::move(taskPromise).makeChained(Q_FUNC_INFO));
513 },
514 Q_FUNC_INFO);
515}
516
517void QOhosWindowProxy::setWindowBackgroundColor(const QColor &color)
518{
519 qCDebug(QtForOhos) << Q_FUNC_INFO << color;
520
521 QOhosJsThreadGateway::runAndWait([&](QOhosJsState &) {
522 if (m_jsScopeData->isWindowClosing())
523 return;
524 m_jsScopeData->jsWindowRef->eval("setWindowBackgroundColor(*)", {color.name(QColor::HexArgb).toStdString()});
525 },
526 Q_FUNC_INFO);
527}
528
529void QOhosWindowProxy::setCustomCursor(const QImage &customCursorImage, const QPoint &hotSpot)
530{
531 const auto maxOhosCustomCursorSize = QSize(256, 256);
532 const auto customCursorSize = customCursorImage.size();
533 if (customCursorSize.width() > maxOhosCustomCursorSize.width()
534 || customCursorSize.height() > maxOhosCustomCursorSize.height()) {
535 qOhosPrintfError(
536 "%s: can't set %dx%d custom cursor, OHOS max custom cursor size is %dx%d",
537 Q_FUNC_INFO, customCursorSize.width(), customCursorSize.height(),
538 maxOhosCustomCursorSize.width(), maxOhosCustomCursorSize.height());
539 return;
540 }
541
542 auto convertedImage = customCursorImage.convertToFormat(QImage::Format_RGBA8888);
543 QOhosJsThreadGateway::invokeAndWaitForContinue([&](QOhosJsState &jsState, QOhosTaskPromise<> taskPromise) {
544 if (m_jsScopeData->isWindowClosing()) {
545 taskPromise();
546 return;
547 }
548 auto windowId = m_jsScopeData->jsWindowRef->jsObject().get<QNapi::Number>("getWindowProperties().id");
549
550 auto jsCursor = QNapi::makeObject(
551 jsState.env(),
552 {
553 {"pixelMap", makeOhosNapiPixelMapFromQImage(jsState, convertedImage)},
554 {"focusX", hotSpot.x()},
555 {"focusY", hotSpot.y()},
556 });
557
558 auto jsCursorConfig = QNapi::makeObject(
559 jsState.env(),
560 {
561 {"followSystem", false},
562 });
563
564 jsState.evalToPromiseOrRejectOnThrow(
565 "@ohos.multimodalInput.pointer.setCustomCursor(*)", {windowId, jsCursor, jsCursorConfig})
566 .onCatch(QtOhos::makeErrorLoggingJsCallback("setCustomCursor()"))
567 .onFinally(std::move(taskPromise).makeChained(Q_FUNC_INFO));
568 },
569 Q_FUNC_INFO);
570}
571
572void QOhosWindowProxy::setPointerStyleSync(const QCursor &cursor)
573{
574 QOhosJsThreadGateway::runAndWait([&](QOhosJsState &jsState) {
575 if (m_jsScopeData->isWindowClosing())
576 return;
577 auto windowId = m_jsScopeData->jsWindowRef->jsObject().get<QNapi::Number>("getWindowProperties().id");
578
579 jsState.eval(
580 "@ohos.multimodalInput.pointer.setPointerStyleSync(*)",
581 {windowId, jsState.mapOhosEnumToJs(convertToOhosCursor(cursor.shape()))});
582 },
583 Q_FUNC_INFO);
584}
585
587{
588 return QOhosJsThreadGateway::eval(
589 [&](QOhosJsState &) {
590 if (m_jsScopeData->isWindowClosing())
591 return QArkUi::WindowProperties {};
592 return getWindowPropertiesFromJsWindow(m_jsScopeData->jsWindowRef->jsObject());
593 },
594 Q_FUNC_INFO);
595}
596
597void QOhosWindowProxy::setWindowCallbackReceiver(std::unique_ptr<WindowCallbacks> callbackReceiver)
598{
599 auto sharedWindowCallbackReceiver = std::shared_ptr<WindowCallbacks>(std::move(callbackReceiver));
600
601 QOhosJsThreadGateway::runAndWait([&](QOhosJsState &) {
602 m_jsScopeData->windowCallbackReceiver = QtOhos::moveToSharedPtr(WindowCallbacks {
603 .onWindowEvent = makeQtThreadWindowCallbackDelegate(&WindowCallbacks::onWindowEvent, sharedWindowCallbackReceiver),
604 .onWindowStatusChange = makeQtThreadWindowCallbackDelegate(&WindowCallbacks::onWindowStatusChange, sharedWindowCallbackReceiver),
605 .onWindowVisibilityChange = makeQtThreadWindowCallbackDelegate(&WindowCallbacks::onWindowVisibilityChange, sharedWindowCallbackReceiver),
606 .onTouchOutside = makeQtThreadWindowCallbackDelegate(&WindowCallbacks::onTouchOutside, sharedWindowCallbackReceiver),
607 .onAvoidAreaChange = makeQtThreadWindowCallbackDelegate(&WindowCallbacks::onAvoidAreaChange, sharedWindowCallbackReceiver),
608 .onWindowRectChange = makeCompressingQtThreadWindowCallbackDelegate(&WindowCallbacks::onWindowRectChange, sharedWindowCallbackReceiver),
609 .onWindowRectChangeInGlobalDisplay = makeCompressingQtThreadWindowCallbackDelegate(&WindowCallbacks::onWindowRectChangeInGlobalDisplay, sharedWindowCallbackReceiver),
610 .onWindowDisplayIdChange = makeQtThreadWindowCallbackDelegate(&WindowCallbacks::onWindowDisplayIdChange, sharedWindowCallbackReceiver),
611 });
612 },
613 Q_FUNC_INFO);
614
615 m_qtWindowCallbacksReceiverHandle = sharedWindowCallbackReceiver;
616}
617
619 QObject *contextObject, QOhosConsumer<std::vector<NonClientAreaMouseEvent>> mouseEventBatchConsumer)
620{
621 auto qtConsumer = QtOhos::moveToSharedPtr(std::move(mouseEventBatchConsumer));
622 auto weakQtConsumer = QtOhos::makeWeakPtr(qtConsumer);
623
624 auto jsConsumer = makeQtOhosSimpleBatchingQtRequestsHandler<NonClientAreaMouseEvent>(
625 QtOhos::QObjectThreadSafeRef(contextObject),
626 [weakQtConsumer](std::vector<NonClientAreaMouseEvent> &&batch) {
627 auto qtConsumer = weakQtConsumer.lock();
628 if (qtConsumer)
629 (*qtConsumer)(std::move(batch));
630 });
631
632 QOhosJsThreadGateway::runAndWait([&](QOhosJsState &) {
633 m_jsScopeData->nonClientAreaEventsDispatcher->mouseEventsConsumer = std::move(jsConsumer);
634 },
635 Q_FUNC_INFO);
636
637 m_qtNonClientAreaMouseWindowCallbackReceiverHandle = qtConsumer;
638}
639
641 QObject *contextObject, QOhosConsumer<std::vector<NonClientAreaTouchEvent>> touchEventBatchConsumer)
642{
643 auto qtConsumer = QtOhos::moveToSharedPtr(std::move(touchEventBatchConsumer));
644 auto weakQtConsumer = QtOhos::makeWeakPtr(qtConsumer);
645
646 auto jsConsumer = makeQtOhosSimpleBatchingQtRequestsHandler<NonClientAreaTouchEvent>(
647 QtOhos::QObjectThreadSafeRef(contextObject),
648 [weakQtConsumer](std::vector<NonClientAreaTouchEvent> &&batch) {
649 auto qtConsumer = weakQtConsumer.lock();
650 if (qtConsumer)
651 (*qtConsumer)(std::move(batch));
652 });
653
654 QOhosJsThreadGateway::runAndWait([&](QOhosJsState &) {
655 m_jsScopeData->nonClientAreaEventsDispatcher->touchEventsConsumer = std::move(jsConsumer);
656 },
657 Q_FUNC_INFO);
658
659 m_qtNonClientAreaTouchWindowCallbackReceiverHandle = qtConsumer;
660}
661
662bool QOhosWindowProxy::qtIsMainWindow() const
663{
664 return m_windowProxyType == WindowProxyType::MainWindow;
665}
666
667bool QOhosWindowProxy::isSubWindowMaximizeSupported() const
668{
669 return m_subWindowMaximizeSupported;
670}
671
672void QOhosWindowProxy::raiseToAppTop()
673{
674 qCDebug(QtForOhos, "%s", Q_FUNC_INFO);
675 QOhosJsThreadGateway::invokeAndWaitForContinue([&](QOhosJsState &, QOhosTaskPromise<> taskPromise) {
676 if (m_jsScopeData->isWindowClosing()) {
677 taskPromise();
678 return;
679 }
680 auto promise = m_jsScopeData->jsWindowRef->evalToPromiseOrRejectOnThrow("raiseToAppTop()");
681 promise
682 .onCatch(QtOhos::makeErrorLoggingJsCallback(Q_FUNC_INFO))
683 .onFinally(std::move(taskPromise).makeChained(Q_FUNC_INFO));
684 },
685 Q_FUNC_INFO);
686}
687
688void QOhosWindowProxy::showWindow(const ShowWindowOptions &options)
689{
690 qCDebug(QtForOhos, "%s", Q_FUNC_INFO);
691 QOhosJsThreadGateway::invokeAndWaitForContinue([&](QOhosJsState &jsState, QOhosTaskPromise<> taskPromise) {
692 if (m_jsScopeData->isWindowClosing()) {
693 taskPromise();
694 return;
695 }
696
697 std::vector<std::pair<std::string, QNapi::ValueWrapper>> jsOptionsProps;
698
699 if (options.focusOnShow.has_value())
700 jsOptionsProps.emplace_back("focusOnShow", options.focusOnShow.value());
701
702 std::vector<QNapi::ValueWrapper> showWindowArgs;
703 constexpr bool brokenHandlingOfEmptyOptionsParamInOhos = true;
704 if (!(jsOptionsProps.empty() && brokenHandlingOfEmptyOptionsParamInOhos))
705 showWindowArgs.push_back(QNapi::makeObject(jsState.env(), jsOptionsProps));
706
707 auto promise = m_jsScopeData->jsWindowRef->evalToPromiseOrRejectOnThrow("showWindow(*)", showWindowArgs);
708 promise
709 .onCatch(QtOhos::makeErrorLoggingJsCallback(Q_FUNC_INFO))
710 .onFinally(std::move(taskPromise).makeChained(Q_FUNC_INFO));
711 },
712 Q_FUNC_INFO);
713}
714
715void QOhosWindowProxy::recover()
716{
717 qCDebug(QtForOhos, "%s", Q_FUNC_INFO);
718 QOhosJsThreadGateway::invokeAndWaitForContinue([&](QOhosJsState &, QOhosTaskPromise<> taskPromise) {
719 if (m_jsScopeData->isWindowClosing()) {
720 taskPromise();
721 return;
722 }
723
724 m_jsScopeData->jsWindowRef->evalToPromiseOrRejectOnThrow("recover()")
725 .onCatch(QtOhos::makeErrorLoggingJsCallback("recover()"))
726 .onFinally(std::move(taskPromise).makeChained(Q_FUNC_INFO));
727 },
728 Q_FUNC_INFO);
729}
730
731void QOhosWindowProxy::restore()
732{
733 qCDebug(QtForOhos, "%s", Q_FUNC_INFO);
734 QOhosJsThreadGateway::invokeAndWaitForContinue([&](QOhosJsState &, QOhosTaskPromise<> taskPromise) {
735 if (m_jsScopeData->isWindowClosing()) {
736 taskPromise();
737 return;
738 }
739 m_jsScopeData->jsWindowRef->evalToPromiseOrRejectOnThrow("restore()")
740 .onCatch(QtOhos::makeErrorLoggingJsCallback(Q_FUNC_INFO))
741 .onFinally(std::move(taskPromise).makeChained(Q_FUNC_INFO));
742 },
743 Q_FUNC_INFO);
744}
745
746void QOhosWindowProxy::minimize()
747{
748 qCDebug(QtForOhos, "%s", Q_FUNC_INFO);
749 QOhosJsThreadGateway::invokeAndWaitForContinue([&](QOhosJsState &, QOhosTaskPromise<> taskPromise) {
750 if (m_jsScopeData->isWindowClosing()) {
751 taskPromise();
752 return;
753 }
754 m_jsScopeData->jsWindowRef->evalToPromiseOrRejectOnThrow("minimize()")
755 .onCatch(QtOhos::makeErrorLoggingJsCallback(Q_FUNC_INFO))
756 .onFinally(std::move(taskPromise).makeChained(Q_FUNC_INFO));
757 },
758 Q_FUNC_INFO);
759}
760
761bool QOhosWindowProxy::tryMaximize(MaximizePresentation maximizePresentation)
762{
763 qCDebug(QtForOhos, "%s", Q_FUNC_INFO);
764
765 if (m_windowProxyType != WindowProxyType::MainWindow && m_windowProxyType != WindowProxyType::SubWindow) {
766 qCWarning(QtForOhos(), "%s: Maximize is currently supported only on main and sub windows", Q_FUNC_INFO);
767 return false;
768 }
769
770 return QOhosJsThreadGateway::evalWithPromise<bool>(
771 [&](QOhosJsState &jsState, QOhosTaskPromise<bool> evalPromise) {
772 if (m_jsScopeData->isWindowClosing()) {
773 evalPromise(false);
774 return;
775 }
776
777 if (m_windowProxyType == WindowProxyType::SubWindow
778 && !isJsWindowInFreeWindowMode(*m_jsScopeData->jsWindowRef)) {
779 qOhosPrintfWarning(
780 "%s: maximize request ignored: the sub window is not in free window mode",
781 Q_FUNC_INFO);
782 evalPromise(false);
783 return;
784 }
785
786 auto thenCatchPromises = std::move(evalPromise).makeThenCatchBranches(Q_FUNC_INFO);
787 m_jsScopeData->jsWindowRef->evalToPromiseOrRejectOnThrow(
788 "maximize(*)", {jsState.mapOhosEnumToJs(maximizePresentation)})
789 .onThen(
790 [thenPromise = std::move(thenCatchPromises.first)](const QtOhos::CallbackInfo &) {
791 thenPromise(true);
792 })
793 .onCatch(
794 [catchPromise = std::move(thenCatchPromises.second)](const QtOhos::CallbackInfo &cbInfo) {
795 QtOhos::logJsCallbackError(cbInfo, "Got error from maximize()");
796 catchPromise(false);
797 });
798 },
799 Q_FUNC_INFO);
800}
801
802void QOhosWindowProxy::setWindowLayoutFullScreen(bool isLayoutFullScreen)
803{
804 qCDebug(QtForOhos, "%s: %s", Q_FUNC_INFO, isLayoutFullScreen ? "true" : "false");
805 QOhosJsThreadGateway::invokeAndWaitForContinue(
806 [&](QOhosJsState &, QOhosTaskPromise<> taskPromise) {
807 if (m_jsScopeData->isWindowClosing()) {
808 taskPromise();
809 return;
810 }
811 m_jsScopeData->jsWindowRef->evalToPromiseOrRejectOnThrow(
812 "setWindowLayoutFullScreen(*)", {isLayoutFullScreen})
813 .onCatch(QtOhos::makeErrorLoggingJsCallback("setWindowLayoutFullScreen()"))
814 .onFinally(std::move(taskPromise).makeChained(Q_FUNC_INFO));
815 },
816 Q_FUNC_INFO);
817}
818
819void QOhosWindowProxy::setWindowSystemBarEnable(const QStringList &names)
820{
821 qCDebug(QtForOhos) << Q_FUNC_INFO << names;
822 QOhosJsThreadGateway::invokeAndWaitForContinue(
823 [&](QOhosJsState &jsState, QOhosTaskPromise<> taskPromise) {
824 if (m_jsScopeData->isWindowClosing()) {
825 taskPromise();
826 return;
827 }
828 m_jsScopeData->jsWindowRef->evalToPromiseOrRejectOnThrow(
829 "setWindowSystemBarEnable(*)",
830 {QNapi::makeArray(jsState.env(), names, std::mem_fn(&QString::toStdString))})
831 .onCatch(QtOhos::makeErrorLoggingJsCallback("setWindowSystemBarEnable()"))
832 .onFinally(std::move(taskPromise).makeChained(Q_FUNC_INFO));
833 },
834 Q_FUNC_INFO);
835}
836
837void QOhosWindowProxy::showAbility()
838{
839 qCDebug(QtForOhos, "%s", Q_FUNC_INFO);
840
841 QOhosJsThreadGateway::invokeAndWaitForContinue([&](QOhosJsState &, QOhosTaskPromise<> taskPromise) {
842 if (m_jsScopeData->isWindowClosing()) {
843 taskPromise();
844 return;
845 }
846
847 m_jsScopeData->qAbilityPeer->qAbility().evalToPromiseOrRejectOnThrow("context.showAbility()")
848 .onCatch(QtOhos::makeErrorLoggingJsCallback("showAbility()"))
849 .onFinally(std::move(taskPromise).makeChained(Q_FUNC_INFO));
850 },
851 Q_FUNC_INFO);
852}
853
854bool QOhosWindowProxy::tryHideAbility()
855{
856 qCDebug(QtForOhos, "%s", Q_FUNC_INFO);
857
858 return QOhosJsThreadGateway::evalWithPromise<bool>([&](QOhosJsState &, QOhosTaskPromise<bool> evalPromise) {
859 if (m_jsScopeData->isWindowClosing()) {
860 evalPromise(false);
861 return;
862 }
863
864 auto thenCatchPromises = std::move(evalPromise).makeThenCatchBranches(Q_FUNC_INFO);
865 m_jsScopeData->qAbilityPeer->qAbility().evalToPromiseOrRejectOnThrow("context.hideAbility()")
866 .onThen(
867 [thenPromise = std::move(thenCatchPromises.first)](const QtOhos::CallbackInfo &) {
868 thenPromise(true);
869 })
870 .onCatch(
871 [catchPromise = std::move(thenCatchPromises.second)](const QtOhos::CallbackInfo &cbInfo) {
872 QtOhos::logJsCallbackError(cbInfo, "got error from hideAbility()");
873 catchPromise(false);
874 });
875 },
876 Q_FUNC_INFO);
877}
878
879bool QOhosWindowProxy::getImmersiveModeEnabledState()
880{
881 return QOhosJsThreadGateway::eval(
882 [&](QOhosJsState &) {
883 if (m_jsScopeData->isWindowClosing())
884 return false;
885 return m_jsScopeData->jsWindowRef->eval<QNapi::Boolean>("getImmersiveModeEnabledState()").Value();
886 },
887 Q_FUNC_INFO);
888}
889
890void QOhosWindowProxy::setWindowPrivacyMode(bool privacyMode)
891{
892 qCDebug(QtForOhos, "%s: %s", Q_FUNC_INFO, privacyMode ? "true" : "false");
893
894 QOhosJsThreadGateway::invokeAndWaitForContinue([&](QOhosJsState &, QOhosTaskPromise<> taskPromise) {
895 if (m_jsScopeData->isWindowClosing()) {
896 taskPromise();
897 return;
898 }
899
900 m_jsScopeData->jsWindowRef->evalToPromiseOrRejectOnThrow("setWindowPrivacyMode(*)", {privacyMode})
901 .onCatch(QtOhos::makeErrorLoggingJsCallback("setPrivacyMode()"))
902 .onFinally(std::move(taskPromise).makeChained(Q_FUNC_INFO));
903 },
904 Q_FUNC_INFO);
905}
906
907void QOhosWindowProxy::setWindowFocusable(bool focusable)
908{
909 qCDebug(QtForOhos, "%s: %s", Q_FUNC_INFO, focusable ? "true" : "false");
910 QOhosJsThreadGateway::invokeAndWaitForContinue([&](QOhosJsState &, QOhosTaskPromise<> taskPromise) {
911 if (m_jsScopeData->isWindowClosing()) {
912 taskPromise();
913 return;
914 }
915
916 m_jsScopeData->jsWindowRef->evalToPromiseOrRejectOnThrow("setWindowFocusable(*)", {focusable})
917 .onCatch(QtOhos::makeErrorLoggingJsCallback("setWindowFocusable()"))
918 .onFinally(std::move(taskPromise).makeChained(Q_FUNC_INFO));
919 },
920 Q_FUNC_INFO);
921}
922
923void QOhosWindowProxy::setWindowTouchable(bool touchable)
924{
925 qCDebug(QtForOhos, "%s: %s", Q_FUNC_INFO, touchable ? "true" : "false");
926 QOhosJsThreadGateway::invokeAndWaitForContinue([&](QOhosJsState &, QOhosTaskPromise<> taskPromise) {
927 if (m_jsScopeData->isWindowClosing()) {
928 taskPromise();
929 return;
930 }
931
932 m_jsScopeData->jsWindowRef->evalToPromiseOrRejectOnThrow("setWindowTouchable(*)", {touchable})
933 .onCatch(QtOhos::makeErrorLoggingJsCallback("setWindowTouchable()"))
934 .onFinally(std::move(taskPromise).makeChained(Q_FUNC_INFO));
935 },
936 Q_FUNC_INFO);
937}
938
939void QOhosWindowProxy::setWindowLimits(const QSize &minSize, const QSize &maxSize)
940{
941 qCDebug(
942 QtForOhos, "%s: (%d x %d)-(%d x %d)", Q_FUNC_INFO, minSize.width(), minSize.height(),
943 maxSize.width(), maxSize.height());
944 QOhosJsThreadGateway::invokeAndWaitForContinue(
945 [&](QOhosJsState &jsState, QOhosTaskPromise<> taskPromise) {
946 if (m_jsScopeData->isWindowClosing()) {
947 taskPromise();
948 return;
949 }
950 auto windowLimits = QNapi::makeObject(
951 jsState.env(),
952 {
953 {"minWidth", minSize.width()},
954 {"minHeight", minSize.height()},
955 {"maxWidth", maxSize.width()},
956 {"maxHeight", maxSize.height()},
957 });
958
959 std::vector<QNapi::ValueWrapper> setWindowLimitsArgs = {windowLimits};
960 if (QOhosDeviceInfo::is2in1()) {
961 constexpr bool isForcible = true;
962 setWindowLimitsArgs.push_back(isForcible);
963 }
964 m_jsScopeData->jsWindowRef->evalToPromiseOrRejectOnThrow(
965 "setWindowLimits(*)", setWindowLimitsArgs)
966 .onCatch(QtOhos::makeErrorLoggingJsCallback("setWindowLimits()"))
967 .onFinally(std::move(taskPromise).makeChained(Q_FUNC_INFO));
968 },
969 Q_FUNC_INFO);
970}
971
972QOhosWindowProxy::WindowLimits QOhosWindowProxy::getWindowLimits() const
973{
974 qCDebug(QtForOhos, "%s", Q_FUNC_INFO);
975 return QOhosJsThreadGateway::eval(
976 [&](QOhosJsState &) {
977 if (m_jsScopeData->isWindowClosing())
978 return WindowLimits {};
979 auto windowLimitsObject = m_jsScopeData->jsWindowRef->eval<QNapi::Object>("getWindowLimits()");
980 return WindowLimits {
981 .minWidth = getOptionalNumberPropAsOptionalDouble(windowLimitsObject, "minWidth"),
982 .minHeight = getOptionalNumberPropAsOptionalDouble(windowLimitsObject, "minHeight"),
983 .maxWidth = getOptionalNumberPropAsOptionalDouble(windowLimitsObject, "maxWidth"),
984 .maxHeight = getOptionalNumberPropAsOptionalDouble(windowLimitsObject, "maxHeight"),
985 };
986 },
987 Q_FUNC_INFO);
988}
989
990QOhosWindowProxy::AvoidArea QOhosWindowProxy::getWindowAvoidArea(AvoidAreaType avoidAreaType) const
991{
992 qCDebug(QtForOhos, "%s: %d", Q_FUNC_INFO, avoidAreaType);
993 return QOhosJsThreadGateway::eval(
994 [&](QOhosJsState &jsState) {
995 if (m_jsScopeData->isWindowClosing())
996 return AvoidArea {};
997 auto avoidAreaObject = m_jsScopeData->jsWindowRef->eval<QNapi::Object>(
998 "getWindowAvoidArea(*)", {jsState.mapOhosEnumToJs(avoidAreaType)});
999 return mapAvoidAreaFromJs(avoidAreaObject);
1000 },
1001 Q_FUNC_INFO);
1002}
1003
1004void QOhosWindowProxy::setWindowMask(
1005 const WindowMask &windowMask, const std::optional<QSize> &ohosMaskSizeOverride)
1006{
1007 if (qtIsMainWindow())
1008 return;
1009
1010 auto ohosMaskSize = ohosMaskSizeOverride.has_value()
1011 ? ohosMaskSizeOverride.value()
1012 : getWindowProperties().windowRect.size();
1013
1014 if (ohosMaskSize.isEmpty()) {
1015 const auto *maskSrcSizeMsg = ohosMaskSizeOverride.has_value()
1016 ? "overridden mask source"
1017 : "window";
1018 if (ohosMaskSizeOverride.has_value()) {
1019 qOhosPrintfError(
1020 "%s failed - %s size is 0x0", maskSrcSizeMsg,
1021 "QOhosWindowProxy::setWindowMask");
1022 }
1023 return;
1024 }
1025
1026 QOhosJsThreadGateway::invokeAndWaitForContinue([&](QOhosJsState &jsState, QOhosTaskPromise<> taskPromise) {
1027 if (m_jsScopeData->isWindowClosing()) {
1028 taskPromise();
1029 return;
1030 }
1031 auto *env = jsState.env();
1032
1033 QNapi::Array maskRowsArray = QNapi::Array::New(env, ohosMaskSize.height());
1034 const int defaultValue = windowMask.windowMaskRegion.isEmpty() ? 1 : 0;
1035
1036 for (int rowIndex = 0; rowIndex < ohosMaskSize.height(); ++rowIndex) {
1037 auto arr = QNapi::Array::New(env, ohosMaskSize.width());
1038 arr.fill(defaultValue);
1039 maskRowsArray[rowIndex] = arr;
1040 }
1041
1042 auto valueToSet = QNapi::Number::New(env, 1);
1043 for (const auto &rect: windowMask.windowMaskRegion) {
1044 auto top = qBound(0, rect.top(), ohosMaskSize.height() - 1);
1045 auto bottom = qBound(0, rect.bottom(), ohosMaskSize.height() - 1);
1046 auto left = qBound(0, rect.left(), ohosMaskSize.width() - 1);
1047 auto right = qBound(0, rect.right(), ohosMaskSize.width() - 1);
1048
1049 for (auto rowIndex = top; rowIndex <= bottom; ++rowIndex) {
1050 auto row = maskRowsArray.Get(rowIndex).As<QNapi::Array>();
1051 for (auto columnIndex = left; columnIndex <= right; ++columnIndex)
1052 row[columnIndex] = valueToSet;
1053 }
1054 }
1055
1056 m_jsScopeData->jsWindowRef->evalToPromiseOrRejectOnThrow("setWindowMask(*)", {maskRowsArray})
1057 .onCatch(QtOhos::makeErrorLoggingJsCallback("setWindowMask()"))
1058 .onFinally(std::move(taskPromise).makeChained(Q_FUNC_INFO));
1059 },
1060 Q_FUNC_INFO);
1061}
1062
1063void QOhosWindowProxy::setSubWindowModalDisabled()
1064{
1065 if (qtIsMainWindow())
1066 return;
1067
1068 QOhosJsThreadGateway::invokeAndWaitForContinue(
1069 [&](QOhosJsState &, QOhosTaskPromise<> taskPromise) {
1070 if (m_jsScopeData->isWindowClosing()) {
1071 taskPromise();
1072 return;
1073 }
1074 m_jsScopeData->jsWindowRef->evalToPromiseOrRejectOnThrow("setSubWindowModal(*)", {false})
1075 .onCatch(QtOhos::makeErrorLoggingJsCallback("setSubWindowModal()"))
1076 .onFinally(std::move(taskPromise).makeChained(Q_FUNC_INFO));
1077 },
1078 Q_FUNC_INFO);
1079}
1080
1081void QOhosWindowProxy::setSubWindowModalEnabled(ModalityType modalityType)
1082{
1083 if (qtIsMainWindow())
1084 return;
1085
1087 qOhosPrintfWarning(
1088 "%s: APPLICATION_MODALITY option can be used only on devices in the freeform window state - skipping",
1089 Q_FUNC_INFO);
1090 return;
1091 }
1092
1093 QOhosJsThreadGateway::invokeAndWaitForContinue(
1094 [&](QOhosJsState &jsState, QOhosTaskPromise<> taskPromise) {
1095 if (m_jsScopeData->isWindowClosing()) {
1096 taskPromise();
1097 return;
1098 }
1099 m_jsScopeData->jsWindowRef->evalToPromiseOrRejectOnThrow(
1100 "setSubWindowModal(*)", {true, jsState.mapOhosEnumToJs(modalityType)})
1101 .onCatch(QtOhos::makeErrorLoggingJsCallback("setSubWindowModal()"))
1102 .onFinally(std::move(taskPromise).makeChained(Q_FUNC_INFO));
1103 },
1104 Q_FUNC_INFO);
1105}
1106
1107void QOhosWindowProxy::setTitle(const QString &title)
1108{
1109 QOhosJsThreadGateway::invokeAndWaitForContinue(
1110 [&](QOhosJsState &, QOhosTaskPromise<> taskPromise) {
1111 if (m_jsScopeData->isWindowClosing()) {
1112 taskPromise();
1113 return;
1114 }
1115
1116 m_jsScopeData->jsWindowRef->evalToPromiseOrRejectOnThrow("setWindowTitle(*)", {title.toStdString()})
1117 .onCatch(QtOhos::makeErrorLoggingJsCallback(Q_FUNC_INFO))
1118 .onFinally(std::move(taskPromise).makeChained(Q_FUNC_INFO));
1119 },
1120 Q_FUNC_INFO);
1121}
1122
1123void QOhosWindowProxy::setWindowTitleButtonVisible(bool maximizeVisible, bool minimizeVisible, bool closeVisible)
1124{
1125 qOhosPrintfDebug(
1126 "%s: isMaximizeVisible:%s, isMinimizeVisible:%s, isCloseVisible:%s",
1127 Q_FUNC_INFO, maximizeVisible ? "true" : "false", minimizeVisible ? "true": "false",
1128 closeVisible ? "true" : "false");
1129
1130 if (!qtIsMainWindow())
1131 return;
1132
1133 QOhosJsThreadGateway::runAndWait(
1134 [&](QOhosJsState &jsState) {
1135 if (m_jsScopeData->isWindowClosing())
1136 return;
1137
1138 constexpr auto capabilityNotSupportedErrorCode = 801;
1139 QtOhos::runIgnoringJsBusinessError(
1140 jsState, capabilityNotSupportedErrorCode, "setWindowTitleButtonVisible()",
1141 [&]() {
1142 m_jsScopeData->jsWindowRef->eval(
1143 "setWindowTitleButtonVisible(*)",
1144 {maximizeVisible, minimizeVisible, closeVisible});
1145 });
1146 },
1147 Q_FUNC_INFO);
1148}
1149
1150void QOhosWindowProxy::setWindowTopmost(bool topmost)
1151{
1152 if (!qtIsMainWindow())
1153 return;
1154
1156 qOhosPrintfWarning("%s: can be used only on 2-in-1 devices or tablets in PC mode - skipping", Q_FUNC_INFO);
1157 return;
1158 }
1159
1160 qOhosPrintfDebug("%s: topMost: %s", Q_FUNC_INFO, topmost ? "true" : "false");
1161
1162 QOhosJsThreadGateway::invokeAndWaitForContinue(
1163 [&](QOhosJsState &, QOhosTaskPromise<> taskPromise) {
1164 if (m_jsScopeData->isWindowClosing()) {
1165 taskPromise();
1166 return;
1167 }
1168
1169 m_jsScopeData->jsWindowRef->evalToPromiseOrRejectOnThrow("setWindowTopmost(*)", {topmost})
1170 .onCatch(QtOhos::makeErrorLoggingJsCallback(Q_FUNC_INFO))
1171 .onFinally(std::move(taskPromise).makeChained(Q_FUNC_INFO));
1172 },
1173 Q_FUNC_INFO);
1174}
1175
1176void QOhosWindowProxy::setWindowDecorVisible(bool visible)
1177{
1178 QOhosJsThreadGateway::runAndWait([&](QOhosJsState &) {
1179 if (m_jsScopeData->isWindowClosing())
1180 return;
1181
1182 m_jsScopeData->jsWindowRef->eval("setWindowDecorVisible(*)", {visible});
1183 },
1184 Q_FUNC_INFO);
1185}
1186
1187void QOhosWindowProxy::setWindowTitleMoveEnabled(bool enabled)
1188{
1190 qOhosPrintfWarning("%s: can be used only on 2-in-1 devices or tablets in PC mode - skipping", Q_FUNC_INFO);
1191 return;
1192 }
1193
1194 QOhosJsThreadGateway::runAndWait([&](QOhosJsState &) {
1195 if (m_jsScopeData->isWindowClosing())
1196 return;
1197
1198 m_jsScopeData->jsWindowRef->eval("setWindowTitleMoveEnabled(*)", {enabled});
1199 },
1200 Q_FUNC_INFO);
1201}
1202
1203void QOhosWindowProxy::setWindowShadowRadius(double radius)
1204{
1206 qOhosPrintfWarning("%s: can be used only on 2-in-1 devices or tablets - skipping", Q_FUNC_INFO);
1207 return;
1208 }
1209
1210 if (qtIsMainWindow())
1211 return;
1212
1213 QOhosJsThreadGateway::runAndWait([&](QOhosJsState &) {
1214 m_jsScopeData->jsWindowRef->eval("setWindowShadowRadius(*)", {radius});
1215 },
1216 Q_FUNC_INFO);
1217}
1218
1219void QOhosWindowProxy::setWindowCornerRadius(double radius)
1220{
1221 if (qtIsMainWindow())
1222 return;
1223
1224 QOhosJsThreadGateway::invokeAndWaitForContinue(
1225 [&](QOhosJsState &, QOhosTaskPromise<> taskPromise) {
1226 m_jsScopeData->jsWindowRef->evalToPromiseOrRejectOnThrow("setWindowCornerRadius(*)", {radius})
1227 .onCatch(QtOhos::makeErrorLoggingJsCallback(Q_FUNC_INFO))
1228 .onFinally(std::move(taskPromise).makeChained(Q_FUNC_INFO));
1229 },
1230 Q_FUNC_INFO);
1231}
1232
1233bool QOhosWindowProxy::isWindowRectAutoSave() const
1234{
1235 return QOhosJsThreadGateway::evalWithPromise<bool>(
1236 [&](QOhosJsState &, QOhosTaskPromise<bool> evalPromise) {
1237 if (m_jsScopeData->isWindowClosing()) {
1238 evalPromise(false);
1239 return;
1240 }
1241 auto optQUiAbilityPeer = QtOhos::QUiAbilityPeer::tryCastFromQAbilityPeerOrNull(m_jsScopeData->qAbilityPeer);
1242 if (!optQUiAbilityPeer) {
1243 evalPromise(false);
1244 return;
1245 }
1246
1247 auto thenCatchPromises = std::move(evalPromise).makeThenCatchBranches(Q_FUNC_INFO);
1248 optQUiAbilityPeer->windowStage()
1249 .evalToPromiseOrRejectOnThrow("isWindowRectAutoSave()")
1250 .onThen(
1251 [thenPromise = std::move(thenCatchPromises.first)](const QtOhos::CallbackInfo &cbInfo) {
1252 bool windowRectAutoSaveEnabled = cbInfo.getFirstArg<QNapi::Boolean>(Q_FUNC_INFO);
1253 thenPromise(windowRectAutoSaveEnabled);
1254 })
1255 .onCatch(
1256 [catchPromise = std::move(thenCatchPromises.second)](const QtOhos::CallbackInfo &cbInfo) {
1257 QtOhos::logJsCallbackError(cbInfo, "isWindowRectAutoSave()");
1258 catchPromise(false);
1259 });
1260 },
1261 Q_FUNC_INFO);
1262}
1263
1264void QOhosWindowProxy::setFollowParentMultiScreenPolicy(bool enabled)
1265{
1266 if (qtIsMainWindow())
1267 return;
1268
1269 QOhosJsThreadGateway::invokeAndWaitForContinue(
1270 [&](QOhosJsState &, QOhosTaskPromise<> taskPromise) {
1271 if (m_jsScopeData->isWindowClosing()) {
1272 taskPromise();
1273 return;
1274 }
1275 m_jsScopeData->jsWindowRef->evalToPromiseOrRejectOnThrow("setFollowParentMultiScreenPolicy(*)", {enabled})
1276 .onCatch(QtOhos::makeErrorLoggingJsCallback("setFollowParentMultiScreenPolicy()"))
1277 .onFinally(std::move(taskPromise).makeChained(Q_FUNC_INFO));
1278 },
1279 Q_FUNC_INFO);
1280}
1281
1282void QOhosWindowProxy::setWindowKeepScreenOn(bool keepScreenOn)
1283{
1284 qCDebug(QtForOhos, "%s: %s", Q_FUNC_INFO, QtOhos::mapBoolToTrueFalseStr(keepScreenOn));
1285
1286 QOhosJsThreadGateway::invokeAndWaitForContinue(
1287 [&](QOhosJsState &, QOhosTaskPromise<> taskPromise) {
1288 if (m_jsScopeData->isWindowClosing()) {
1289 taskPromise();
1290 return;
1291 }
1292
1293 m_jsScopeData->jsWindowRef->evalToPromiseOrRejectOnThrow("setWindowKeepScreenOn(*)", {keepScreenOn})
1294 .onCatch(QtOhos::makeErrorLoggingJsCallback("setWindowKeepScreenOn()"))
1295 .onFinally(std::move(taskPromise).makeChained(Q_FUNC_INFO));
1296 },
1297 Q_FUNC_INFO);
1298}
1299
1300void QOhosWindowProxy::setSupportedWindowModes(const std::set<SupportWindowMode> &supportedWindowModes)
1301{
1302 qCDebug(QtForOhos, "%s: %s", Q_FUNC_INFO, mapEnumsToLogString(supportedWindowModes).c_str());
1303
1304 QOhosJsThreadGateway::invokeAndWaitForContinue(
1305 [&](QOhosJsState &jsState, QOhosTaskPromise<> taskPromise) {
1306 if (m_jsScopeData->isWindowClosing()) {
1307 taskPromise();
1308 return;
1309 }
1310
1311 auto jsSupportedWindowModes = QNapi::makeArray(
1312 jsState.env(), supportedWindowModes,
1313 [&](auto mode) {
1314 return jsState.mapOhosEnumToJs(mode);
1315 });
1316
1317 QNapi::Promise evalPromise;
1318 if (m_windowProxyType != WindowProxyType::MainWindow) {
1319 evalPromise = m_jsScopeData->jsWindowRef->evalToPromiseOrRejectOnThrow(
1320 "setSupportedWindowModes(*)", {jsSupportedWindowModes});
1321 } else if (auto qUiAbilityPeer = QtOhos::QUiAbilityPeer::tryCastFromQAbilityPeerOrNull(
1322 m_jsScopeData->qAbilityPeer)) {
1323 evalPromise = qUiAbilityPeer->windowStage().evalToPromiseOrRejectOnThrow(
1324 "setSupportedWindowModes(*)", {jsSupportedWindowModes});
1325 } else {
1326 qOhosPrintfWarning(
1327 "%s: ability has no window stage, supported window modes not applied",
1328 Q_FUNC_INFO);
1329 evalPromise = QtOhos::makeResolvedPromise(Napi::Env(jsState.env()).Undefined());
1330 }
1331
1332 evalPromise
1333 .onCatch(QtOhos::makeErrorLoggingJsCallback("setSupportedWindowModes()"))
1334 .onFinally(std::move(taskPromise).makeChained(Q_FUNC_INFO));
1335 },
1336 Q_FUNC_INFO);
1337}
1338
1339void QOhosWindowProxy::setWindowRectAutoSave(bool enabled)
1340{
1341 constexpr bool isSaveBySpecifiedFlag = true;
1342
1343 QOhosJsThreadGateway::invokeAndWaitForContinue(
1344 [&](QOhosJsState &, QOhosTaskPromise<> taskPromise) {
1345 if (m_jsScopeData->isWindowClosing()) {
1346 taskPromise();
1347 return;
1348 }
1349 auto optQUiAbilityPeer = QtOhos::QUiAbilityPeer::tryCastFromQAbilityPeerOrNull(m_jsScopeData->qAbilityPeer);
1350 if (!optQUiAbilityPeer) {
1351 taskPromise();
1352 return;
1353 }
1354
1355 optQUiAbilityPeer->windowStage()
1356 .evalToPromiseOrRejectOnThrow("setWindowRectAutoSave(*)", {enabled, isSaveBySpecifiedFlag})
1357 .onCatch(QtOhos::makeErrorLoggingJsCallback("setWindowRectAutoSave()"))
1358 .onFinally(std::move(taskPromise).makeChained(Q_FUNC_INFO));
1359 },
1360 Q_FUNC_INFO);
1361}
1362
1363void QOhosWindowProxy::setSubWindowCloseHandler(
1364 std::function<void()> handler, bool handlerReturnValue)
1365{
1366 m_subWindowCloseRegistrationHandle =
1367 registerSubWindowCloseHandler(std::move(handler), handlerReturnValue);
1368}
1369
1370void QOhosWindowProxy::resetSubWindowCloseHandler()
1371{
1372 m_subWindowCloseRegistrationHandle.reset();
1373}
1374
1375std::shared_ptr<void> QOhosWindowProxy::registerSubWindowCloseHandler(
1376 std::function<void()> handler, bool handlerReturnValue)
1377{
1378 auto sharedHandler = QtOhos::moveToSharedPtr(std::move(handler));
1379 auto jsWindowRegistrationHandle = QOhosJsThreadGateway::eval(
1380 [&](QOhosJsState &jsState) {
1381 return QtOhos::makeProxyWithJsThreadDeleter(
1382 m_jsScopeData->registerSubWindowCloseHandler(
1383 jsState,
1384 [weakHandler = QtOhos::makeWeakPtr(sharedHandler), handlerReturnValue]() {
1385 QtOhos::invokeInQtThread(
1386 [weakHandler]() {
1387 auto sharedHandler = weakHandler.lock();
1388 if (sharedHandler)
1389 (*sharedHandler)();
1390 });
1391 return handlerReturnValue;
1392 }));
1393 },
1394 Q_FUNC_INFO);
1395
1396 return QtOhos::moveToSharedPtr(
1397 std::make_tuple(sharedHandler, jsWindowRegistrationHandle));
1398}
1399
1400std::shared_ptr<QOhosWindowProxy>
1402{
1403 return std::shared_ptr<QOhosWindowProxy>(
1404 new QOhosWindowProxy(
1405 [&](QtOhos::JsState &jsState, QOhosConsumer<QtOhos::JsState &, QOhosWindowProxyData> windowProxyDataConsumer) {
1406 makeWindowProxyDataForExistingMainWindowInJsThread(jsState, createInfo, std::move(windowProxyDataConsumer));
1407 }));
1408}
1409
1410std::shared_ptr<QOhosWindowProxy>
1411QOhosWindowProxy::createFloatWindow(const FloatWindowCreateInfo &createInfo)
1412{
1413 return std::shared_ptr<QOhosWindowProxy>(
1414 new QOhosWindowProxy(
1415 [&](QtOhos::JsState &jsState, QOhosConsumer<QtOhos::JsState &, QOhosWindowProxyData> windowProxyDataConsumer) {
1416 makeWindowProxyDataForFloatWindowInJsThread(jsState, createInfo, std::move(windowProxyDataConsumer));
1417 }));
1418}
1419
1420std::shared_ptr<QOhosWindowProxy>
1421QOhosWindowProxy::createMainWindow(const MainWindowCreateInfo &createInfo)
1422{
1423 return std::shared_ptr<QOhosWindowProxy>(
1424 new QOhosWindowProxy(
1425 [&](QtOhos::JsState &jsState, QOhosConsumer<QtOhos::JsState &, QOhosWindowProxyData> windowProxyDataConsumer) {
1426 makeWindowProxyDataForMainWindowInJsThread(jsState, createInfo, std::move(windowProxyDataConsumer));
1427 }));
1428}
1429
1430std::shared_ptr<QXComponentNode> QOhosWindowProxy::nodeXComponent() const
1431{
1432 return m_nodeXComponent;
1433}
1434
1435std::string QOhosWindowProxy::qAbilityInstanceId() const
1436{
1437 return m_qAbilityInstanceId;
1438}
1439
1440QHarmonyJsObjectRef QOhosWindowProxy::abilityObjectRef() const
1441{
1442 return m_abilityObjectRef;
1443}
1444
1446{
1447 return m_jsWindowObjectRef;
1448}
1449
1450std::shared_ptr<QOhosWindowProxy>
1451QOhosWindowProxy::createSubWindow(const SubWindowCreateInfo &createInfo)
1452{
1453 return std::shared_ptr<QOhosWindowProxy>(
1454 new QOhosWindowProxy(
1455 [&](QtOhos::JsState &jsState, QOhosConsumer<QtOhos::JsState &, QOhosWindowProxyData> windowProxyDataConsumer) {
1456 // HACK - outside free window mode, the platform shows a maximize button that does
1457 // not work, although maximizeSupported is documented to have no effect there
1458 auto subWindowCreateInfo = createInfo;
1459 subWindowCreateInfo.maximizeSupported = createInfo.maximizeSupported
1460 && !m_jsScopeData->isWindowClosing()
1461 && isJsWindowInFreeWindowMode(*m_jsScopeData->jsWindowRef);
1462
1463 // HACK - calling createSubWindow from window may throw while the context is termination
1464 // This is only a problem because we currenlty do not properly handle main window closing
1465 // Remove this hacky branch after QTFOROH-1080 issues are resolved.
1466 if (m_jsScopeData->isWindowClosing()) {
1467 makeWindowProxyDataForSubWindowInJsThread(
1468 jsState, subWindowCreateInfo, std::move(windowProxyDataConsumer));
1469 } else {
1470 makeWindowProxyDataForSubWindowInJsThread(
1471 jsState, m_jsScopeData->jsWindowRef->jsObject(), subWindowCreateInfo,
1472 std::move(windowProxyDataConsumer));
1473 }
1474 }));
1475}
1476
1477QOhosWindowProxy::JsScopeData::JsScopeData() = default;
1478
1479QOhosWindowProxy::JsScopeData::JsScopeData(
1480 WindowProxyType windowProxyType, QNapi::Reference<QNapi::Object> jsWindow,
1481 std::shared_ptr<void> optKeepAliveData,
1482 std::shared_ptr<QtOhos::QAbilityPeer> qAbilityPeer,
1483 QtOhos::QObjectThreadSafeRef owningQWindowRef)
1484 : windowProxyType(windowProxyType)
1485 , windowCallbackReceiver(nullptr)
1486 , windowDestroyedFromSystem(false)
1487 , optKeepAliveData(optKeepAliveData)
1488 , qAbilityPeer(qAbilityPeer)
1489 , nonClientAreaEventsDispatcher(std::make_shared<NonClientAreaEventsDispatcher>())
1490 , m_windowFrameMouseFilterHandle(
1491 QArkUi::registerMouseEventsConsumer(
1492 getWindowPropertiesFromJsWindow(jsWindow.Value()).id,
1493 [dispatcher = nonClientAreaEventsDispatcher](const QArkUi::MouseEvent &event) {
1494 dispatcher->onMouseEventFromArkUi(event);
1495 }))
1496 , m_windowFrameTouchFilterHandle(
1497 QArkUi::registerTouchEventsConsumer(
1498 getWindowPropertiesFromJsWindow(jsWindow.Value()).id,
1499 [dispatcher = nonClientAreaEventsDispatcher](const QArkUi::TouchEvent &event) {
1500 dispatcher->onTouchEventFromArkUi(event);
1501 }))
1502 , jsWindowRef(
1503 std::make_shared<QArkUi::JsWindowRef>(
1504 qAbilityPeer->instanceId(),
1505 getWindowPropertiesFromJsWindow(jsWindow.Value()).id,
1506 jsWindow.Value(),
1507 owningQWindowRef))
1508{
1509}
1510
1511QOhosWindowProxy::JsScopeData::~JsScopeData()
1512{
1513 if (jsWindowRef) {
1514 if (isWindowClosingFromSystem(jsWindowRef->jsObject(), windowProxyType, qAbilityPeer)) {
1515 windowDestroyedFromSystem = true;
1516 return;
1517 }
1518
1519 QtOhos::JsWindowsTracker::tagWindowAsClosing(jsWindowRef->jsObject(), "QOhosWindowProxy::JsScopeData destructor");
1520
1521 if (windowProxyType == WindowProxyType::MainWindow) {
1522 // NOTE - Set the windowDestroyedFromSystem flag here early
1523 // to avoid callbacks being invoked directly as a result of
1524 // calling terminate
1525 windowDestroyedFromSystem = true;
1526 qOhosPrintfWarning(
1527 "Attempting to terminate qAbility with instance id: %s",
1528 jsWindowRef->owningQAbilityInstanceId().c_str());
1529 qAbilityPeer->qAbility().eval("context.terminateSelf()");
1530 } else if (!windowDestroyedFromSystem) {
1531 // FIXME - destroyWindow usually does and returns nothing
1532 // once the actual implementation is provided wait for the proomise that this function should return
1533 jsWindowRef->eval("destroyWindow()");
1534 }
1535 }
1536}
1537
1538std::shared_ptr<void> QOhosWindowProxy::JsScopeData::registerEventListener(
1539 const std::string &eventName,
1540 void (QOhosWindowProxy::JsScopeData::*handleFunction)(const QtOhos::CallbackInfo &),
1541 QFlags<EventHandlerFlagBits> eventHandlerFlags)
1542{
1543
1544 std::weak_ptr<JsScopeData> weakSelf = shared_from_this();
1545 bool ignoreWhenAbilityIsTerminating = !eventHandlerFlags.testFlag(EventHandlerFlagBits::allowCallWhenAbilityIsTerminating);
1546
1547 return registerQOhosOnOffMethodsBasedEventHandler(
1548 jsWindowRef->jsObject(), eventName,
1549 [weakSelf, handleFunction, eventName, ignoreWhenAbilityIsTerminating](const QtOhos::CallbackInfo &cbInfo) {
1550 auto self = weakSelf.lock();
1551 if (Q_UNLIKELY(!self)) {
1552 qOhosPrintfWarning(
1553 "callback '%s' called for destroyed QOhosWindowProxy::JsScopeData, ignoring",
1554 eventName.c_str());
1555 return;
1556 }
1557
1558 if (self->isWindowClosing() && ignoreWhenAbilityIsTerminating) {
1559 qOhosPrintfError(
1560 "QOhosWindowProxy: Received callback for event '%s' during termination of the related QAbility.",
1561 eventName.c_str());
1562 return;
1563 }
1564
1565 if (Q_UNLIKELY(self->windowDestroyedFromSystem)) {
1566 qOhosPrintfError(
1567 "QOhosWindowProxy: Received callback for event '%s' after WINDOW_DESTROYED",
1568 eventName.c_str());
1569 return;
1570 }
1571
1572 ((*self).*handleFunction)(cbInfo);
1573 },
1574 {
1575 .optEventSourceAliveCheckFunc = {},
1576 .extraOnArg = {},
1577 .extraOffArg = {},
1578 .optOnCallExceptionHandler = [&](const Napi::Error &error) {
1579 constexpr std::uint32_t capabilityNotSupportedErrorCode = 801;
1580 constexpr std::uint32_t windowStateIsAbnormalErrorCode = 1300002;
1581
1582 const QSet<std::uint32_t> ignorableErrorCodes = {
1583 capabilityNotSupportedErrorCode,
1584 windowStateIsAbnormalErrorCode,
1585 };
1586
1587 auto errorCode = QtOhos::tryGetCodeFromJsBusinessError(error);
1588
1589 auto ignorableError =
1590 eventHandlerFlags.testFlag(EventHandlerFlagBits::allowEventHandlerRegistrationFailure)
1591 && errorCode.has_value()
1592 && ignorableErrorCodes.contains(errorCode.value());
1593
1594 if (!ignorableError)
1595 throw;
1596
1597 qOhosPrintfWarning(
1598 "%s: Ignored error %u while registering for window event '%s'",
1599 Q_FUNC_INFO, errorCode.value(), eventName.c_str());
1600 },
1601 });
1602}
1603
1604std::shared_ptr<void> QOhosWindowProxy::JsScopeData::registerSubWindowCloseHandler(
1605 QOhosJsState &, std::function<bool()> handler)
1606{
1607 auto weakSelf = QtOhos::makeWeakPtr(shared_from_this());
1608 return registerQOhosOnOffMethodsBasedEventHandler(
1609 jsWindowRef->jsObject(), "subWindowClose",
1610 [weakSelf, handler = std::move(handler)](const QtOhos::CallbackInfo &cbInfo) {
1611 bool deferClose = handler();
1612 auto self = weakSelf.lock();
1613 if (self && !deferClose)
1614 QtOhos::JsWindowsTracker::tagWindowAsClosing(self->jsWindowRef->jsObject(), "subWindowClose => false");
1615 return QNapi::Boolean::New(cbInfo.Env(), deferClose);
1616 });
1617}
1618
1619void QOhosWindowProxy::JsScopeData::handleWindowEventCallback(const QtOhos::CallbackInfo &cbInfo)
1620{
1621 auto eventType = cbInfo.getFirstArg<QNapi::Number>(Q_FUNC_INFO);
1622 // NOTE - All windowEvents should be handled by qt but currently
1623 // some are not exposed as a part of public api.
1624 WindowEvent event;
1625 try {
1626 event.type = cbInfo.jsState().mapOhosEnumFromJs<WindowEventType>(eventType);
1627 } catch (const Napi::Error &err) {
1628 qOhosPrintfError(
1629 "Error converting WindowEventType to known value: %s. Event will be ignored.", err.what());
1630 return;
1631 }
1632
1633 if (isWindowClosing() && event.type != WindowEventType::WINDOW_DESTROYED) {
1634 qOhosPrintfError(
1635 "Received WindowEvent for window when it's closing. WindowEventType: %d",
1636 event.type);
1637 return;
1638 }
1639
1640 onWindowEvent(cbInfo.jsState(), event);
1641}
1642
1643void QOhosWindowProxy::JsScopeData::handleWindowStatusCallback(const QtOhos::CallbackInfo &cbInfo)
1644{
1645 auto windowStatusType = cbInfo.getFirstArg<QNapi::Number>(Q_FUNC_INFO);
1646 if (windowCallbackReceiver != nullptr) {
1647 windowCallbackReceiver->onWindowStatusChange(
1648 WindowStatus {
1649 .type = cbInfo.jsState().mapOhosEnumFromJs<WindowStatusType>(windowStatusType),
1650 });
1651 }
1652}
1653
1654void QOhosWindowProxy::JsScopeData::handleWindowVisibilityCallback(const QtOhos::CallbackInfo &cbInfo)
1655{
1656 auto windowVisibility = cbInfo.getFirstArg<QNapi::Boolean>(Q_FUNC_INFO);
1657 if (windowCallbackReceiver != nullptr)
1658 windowCallbackReceiver->onWindowVisibilityChange(windowVisibility);
1659}
1660
1661void QOhosWindowProxy::JsScopeData::handleWindowTouchOutsideCallback(const QtOhos::CallbackInfo &)
1662{
1663 if (windowCallbackReceiver != nullptr)
1664 windowCallbackReceiver->onTouchOutside();
1665}
1666
1667void QOhosWindowProxy::JsScopeData::handleAvoidAreaChangeCallback(const QtOhos::CallbackInfo &cbInfo)
1668{
1669 if (windowCallbackReceiver != nullptr) {
1670 auto callbackArg = cbInfo.getFirstArg<QNapi::Object>(Q_FUNC_INFO);
1671 windowCallbackReceiver->onAvoidAreaChange(
1672 cbInfo.jsState().mapOhosEnumFromJs<AvoidAreaType>(callbackArg.get<QNapi::Number>("type")),
1673 mapAvoidAreaFromJs(callbackArg.get<QNapi::Object>("area")));
1674 }
1675}
1676
1677void QOhosWindowProxy::JsScopeData::handleWindowRectChangeCallback(const QtOhos::CallbackInfo &cbInfo)
1678{
1679 auto rectChangeOptionsObjectArg = cbInfo.getFirstArg<QNapi::Object>(Q_FUNC_INFO);
1680 auto rectChangeOptions = RectChangeOptions {
1681 .rect = ohosWindowRectToQRect(rectChangeOptionsObjectArg.get<QNapi::Object>("rect")),
1682 .reason = cbInfo.jsState().mapOhosEnumFromJs<RectChangeReason>(rectChangeOptionsObjectArg.get<QNapi::Number>("reason")),
1683 };
1684
1685 if (windowCallbackReceiver != nullptr)
1686 windowCallbackReceiver->onWindowRectChange(rectChangeOptions);
1687}
1688
1689void QOhosWindowProxy::JsScopeData::handleWindowRectChangeInGlobalDisplayCallback(const QtOhos::CallbackInfo &cbInfo)
1690{
1691 auto rectChangeOptionsObjectArg = cbInfo.getFirstArg<QNapi::Object>(Q_FUNC_INFO);
1692 auto rectChangeOptions = RectChangeOptions {
1693 .rect = ohosWindowRectToQRect(rectChangeOptionsObjectArg.get<QNapi::Object>("rect")),
1694 .reason = cbInfo.jsState().mapOhosEnumFromJs<RectChangeReason>(rectChangeOptionsObjectArg.get<QNapi::Number>("reason")),
1695 };
1696
1697 if (windowCallbackReceiver != nullptr)
1698 windowCallbackReceiver->onWindowRectChangeInGlobalDisplay(rectChangeOptions);
1699}
1700
1701void QOhosWindowProxy::JsScopeData::handleWindowDisplayIdChangeCallback(const QtOhos::CallbackInfo &cbInfo)
1702{
1703 auto displayIdNumber = cbInfo.getFirstArg<QNapi::Number>(Q_FUNC_INFO);
1704 auto displayId = QOhosDisplayInfo::JsDisplayId(displayIdNumber);
1705
1706 if (windowCallbackReceiver != nullptr)
1707 windowCallbackReceiver->onWindowDisplayIdChange(displayId);
1708}
1709
1710void QOhosWindowProxy::JsScopeData::onWindowEvent(QtOhos::JsState &, const WindowEvent &windowEvent)
1711{
1712 if (windowEvent.type == WindowEventType::WINDOW_DESTROYED) {
1713 QtOhos::JsWindowsTracker::tagWindowAsClosing(jsWindowRef->jsObject(), "WINDOW_DESTROYED");
1714 windowDestroyedFromSystem = true;
1715 }
1716
1717 if (windowCallbackReceiver != nullptr)
1718 windowCallbackReceiver->onWindowEvent(windowEvent);
1719}
1720
1721bool QOhosWindowProxy::JsScopeData::isWindowClosing() const
1722{
1723 return isWindowClosingFromSystem(jsWindowRef->jsObject(), windowProxyType, qAbilityPeer);
1724}
1725
1726void QOhosWindowProxy::JsScopeData::NonClientAreaEventsDispatcher::onMouseEventFromArkUi(const QArkUi::MouseEvent &event) const
1727{
1728 if (mouseEventsConsumer == nullptr)
1729 return;
1730
1731 auto optAction = tryMapMouseEventActionToNonClientAreaEventType(event.action);
1732 if (!optAction.has_value())
1733 return;
1734
1735 auto optWindowProperties = QArkUi::tryGetWindowProperties(event.jsWindowId);
1736 if (!optWindowProperties.has_value()) {
1737 qOhosPrintfError(
1738 "%s: Failed to retrieve window properties for js window: %f. Ignoring event.",
1739 Q_FUNC_INFO, event.jsWindowId.value());
1740 return;
1741 }
1742
1743 const auto &windowProperties = optWindowProperties.value();
1744 if (!isPointInNonClientArea(event.displayPosition, windowProperties))
1745 return;
1746
1747 auto windowOrigin = windowProperties.windowRect.topLeft() + windowProperties.drawableRect.topLeft();
1748 NonClientAreaMouseEvent nonClientAreaMouseEvent = {
1749 .timestamp = std::chrono::duration_cast<std::chrono::milliseconds>(event.actionTime),
1750 .action = optAction.value(),
1751 .button = tryMapMouseEventButtonToQt(event.button).value_or(Qt::NoButton),
1752 .displayPosition = event.displayPosition,
1753 .localPosition = event.displayPosition - windowOrigin,
1754 .globalPosition = event.globalPosition,
1755 };
1756
1757 mouseEventsConsumer(nonClientAreaMouseEvent);
1758}
1759
1760void QOhosWindowProxy::JsScopeData::NonClientAreaEventsDispatcher::onTouchEventFromArkUi(const QArkUi::TouchEvent &event) const
1761{
1762 if (touchEventsConsumer == nullptr)
1763 return;
1764
1765 auto optAction = tryMapTouchEventActionToNonClientAreaEventType(event.action);
1766 if (!optAction.has_value())
1767 return;
1768
1769 auto optWindowProperties = QArkUi::tryGetWindowProperties(event.jsWindowId);
1770 if (!optWindowProperties.has_value()) {
1771 qOhosPrintfError(
1772 "%s: Failed to retrieve window properties for js window: %f. Ignoring event.",
1773 Q_FUNC_INFO, event.jsWindowId.value());
1774 return;
1775 }
1776
1777 const auto &windowProperties = optWindowProperties.value();
1778 if (!isPointInNonClientArea(event.displayPosition, windowProperties))
1779 return;
1780
1781 auto windowOrigin = windowProperties.windowRect.topLeft() + windowProperties.drawableRect.topLeft();
1782 NonClientAreaTouchEvent nonClientAreaTouchEvent = {
1783 .id = event.fingerId,
1784 .timestamp = std::chrono::duration_cast<std::chrono::milliseconds>(event.actionTime),
1785 .action = optAction.value(),
1786 .displayPosition = event.displayPosition,
1787 .localPosition = event.displayPosition - windowOrigin,
1788 .globalPosition = event.globalPosition,
1789 };
1790
1791 touchEventsConsumer(nonClientAreaTouchEvent);
1792}
1793
1794QPixmap QOhosWindowProxy::snapshot() const
1795{
1796 return QOhosJsThreadGateway::evalWithPromise<QPixmap>(
1797 [&](QOhosJsState &, QOhosTaskPromise<QPixmap> evalPromise) {
1798 auto thenCatchPromises = std::move(evalPromise).makeThenCatchBranches(Q_FUNC_INFO);
1799 m_jsScopeData->jsWindowRef->evalToPromiseOrRejectOnThrow("snapshot()")
1800 .onThen(
1801 [thenPromise = std::move(thenCatchPromises.first)](const QtOhos::CallbackInfo &cbInfo) {
1802 auto napiPixmap = cbInfo.getFirstArg<QNapi::Object>(Q_FUNC_INFO);
1803
1804 ::OH_PixelmapNative *pixelMapNativePtr;
1805 QArkUi::callArkUiOrFailOnErrorResult(
1806 Q_OHOS_NAMED_FUNC(::OH_PixelmapNative_ConvertPixelmapNativeFromNapi),
1807 cbInfo.Env(), napiPixmap, &pixelMapNativePtr);
1808 auto pixelMap = wrapOhosNativePixelMapPtr(pixelMapNativePtr);
1809
1810 thenPromise(
1811 QPixmap::fromImage(createQImageFromNativePixelMap(pixelMap.get())));
1812 })
1813 .onCatch(
1814 [catchPromise = std::move(thenCatchPromises.second)](const QtOhos::CallbackInfo &cbInfo) {
1815 QtOhos::logJsCallbackError(cbInfo, "Got error from snapshot()");
1816 catchPromise(QPixmap());
1817 });
1818 },
1819 Q_FUNC_INFO);
1820}
1821
1822QList<QRect> QOhosWindowProxy::getDisplayCutoutRects() const
1823{
1824 // The display cutout (e.g. camera hole) is not in getWindowAvoidArea(); read
1825 // it from the display. Returns the bounding rects in display coordinates.
1826 return QOhosJsThreadGateway::evalWithPromise<QList<QRect>>(
1827 [&](QOhosJsState &jsState, QOhosTaskPromise<QList<QRect>> evalPromise) {
1828 if (m_jsScopeData->isWindowClosing()) {
1829 evalPromise(QList<QRect>());
1830 return;
1831 }
1832
1833 auto optWindowDisplay = qAndThen(
1834 getWindowPropertiesFromJsWindow(
1835 m_jsScopeData->jsWindowRef->jsObject()).displayId,
1836 [&](QOhosDisplayInfo::JsDisplayId id) {
1837 return QOhosDisplayInfo::tryGetDisplayById(jsState, id);
1838 });
1839 auto display = optWindowDisplay.has_value()
1840 ? optWindowDisplay.value()
1841 : jsState.eval<QNapi::Object>("@ohos.display.getDefaultDisplaySync()");
1842
1843 auto branches = std::move(evalPromise).makeThenCatchBranches(Q_FUNC_INFO);
1844 display
1845 .evalToPromiseOrRejectOnThrow("getCutoutInfo()")
1846 .onThen(
1847 [thenPromise = std::move(branches.first)](const QtOhos::CallbackInfo &cbInfo) {
1848 auto cutoutInfo = cbInfo.getFirstArg<QNapi::Object>(Q_FUNC_INFO);
1849 auto cutoutRects = QNapi::getArrayElements<QList<QRect>, QNapi::Object>(
1850 cutoutInfo.get<QNapi::Array>("boundingRects"), [](QNapi::Object r) {
1851 return QRect(r.get<QNapi::Number>("left"),
1852 r.get<QNapi::Number>("top"),
1853 r.get<QNapi::Number>("width"),
1854 r.get<QNapi::Number>("height"));
1855 });
1856 thenPromise(cutoutRects);
1857 })
1858 .onCatch(
1859 [catchPromise = std::move(branches.second)](const QtOhos::CallbackInfo &cbInfo) {
1860 QtOhos::logJsCallbackError(cbInfo, "getCutoutInfo() failed");
1861 catchPromise(QList<QRect>());
1862 });
1863 },
1864 Q_FUNC_INFO);
1865}
1866
1867bool QOhosWindowProxy::startMoving()
1868{
1869 QOhosJsThreadGateway::invokeAndWaitForContinue(
1870 [&](QOhosJsState &, QOhosTaskPromise<> taskPromise) {
1871 if (m_jsScopeData->isWindowClosing()) {
1872 taskPromise();
1873 return;
1874 }
1875
1876 m_jsScopeData->jsWindowRef->evalToPromiseOrRejectOnThrow("startMoving()")
1877 .onCatch(QtOhos::makeErrorLoggingJsCallback("startMoving()"))
1878 .onFinally(std::move(taskPromise).makeChained(Q_FUNC_INFO));
1879 },
1880 Q_FUNC_INFO);
1881
1882 return true;
1883}
1884
1885void QOhosWindowProxy::enableDrag(bool enable)
1886{
1887 qCDebug(QtForOhos, "%s: %s", Q_FUNC_INFO, QtOhos::mapBoolToTrueFalseStr(enable));
1888
1889 if (qtIsMainWindow()) {
1890 qCWarning(QtForOhos(), "%s: enableDrag is not supported on main windows", Q_FUNC_INFO);
1891 return;
1892 }
1893
1894 QOhosJsThreadGateway::invokeAndWaitForContinue(
1895 [&](QOhosJsState &, QOhosTaskPromise<> taskPromise) {
1896 if (m_jsScopeData->isWindowClosing()) {
1897 taskPromise();
1898 return;
1899 }
1900 m_jsScopeData->jsWindowRef->evalToPromiseOrRejectOnThrow("enableDrag(*)", {enable})
1901 .onCatch(QtOhos::makeErrorLoggingJsCallback("enableDrag()"))
1902 .onFinally(std::move(taskPromise).makeChained(Q_FUNC_INFO));
1903 },
1904 Q_FUNC_INFO);
1905}
1906
1907std::optional<bool> QOhosWindowProxy::isFocused() const
1908{
1909 return QOhosJsThreadGateway::eval(
1910 [&](QOhosJsState &) -> std::optional<bool> {
1911 if (m_jsScopeData->isWindowClosing())
1912 return std::nullopt;
1913
1914 return m_jsScopeData->jsWindowRef->eval<QNapi::Boolean>("isFocused()");
1915 },
1916 Q_FUNC_INFO);
1917}
1918
1919std::vector<QArkUi::JsWindowId> QOhosWindowProxy::queryWindowIdsByCoordinate(
1920 QOhosDisplayInfo::JsDisplayId displayId, const QPoint &queryLocation, std::uint32_t queryLimit)
1921{
1922 return QOhosJsThreadGateway::evalWithPromise<std::vector<QArkUi::JsWindowId>>(
1923 [&](QOhosJsState &jsState, auto evalPromise) {
1924 auto thenCatchPromises = std::move(evalPromise).makeThenCatchBranches(Q_FUNC_INFO);
1925 jsState.evalToPromiseOrRejectOnThrow("@ohos.window.getWindowsByCoordinate(*)", {
1926 displayId.value(),
1927 queryLimit,
1928 queryLocation.x(),
1929 queryLocation.y()
1930 })
1931 .onThen([thenPromise = std::move(thenCatchPromises.first)](const QtOhos::CallbackInfo &cbInfo) {
1932 auto windowsArray = cbInfo.getFirstArg<QNapi::Array>(Q_FUNC_INFO);
1933 thenPromise(
1934 QNapi::getArrayElements<std::vector<QArkUi::JsWindowId>, QNapi::Object>(
1935 windowsArray,
1936 [&](QNapi::Object jsWindow) {
1937 return getWindowPropertiesFromJsWindow(jsWindow).id;
1938 }));
1939 })
1940 .onCatch([catchPromise = std::move(thenCatchPromises.second)](const QtOhos::CallbackInfo &cbInfo) {
1941 QtOhos::logJsCallbackError(
1942 cbInfo, "got error from @ohos.window.getWindowsByCoordinate()");
1943 catchPromise({});
1944 });
1945 },
1946 Q_FUNC_INFO);
1947}
1948
1949std::vector<QArkUi::JsWindowId> QOhosWindowProxy::queryQtManagedWindowIdsByPredicate(
1950 const std::function<bool(QOhosJsState &, const QArkUi::JsWindowRef &)> &predicate)
1951{
1952 return QOhosJsThreadGateway::eval([&](QOhosJsState &jsState) {
1953 return QOhosJsWindowRegistry::instance(jsState).queryByPredicate(jsState, predicate);
1954 },
1955 Q_FUNC_INFO);
1956}
1957
1958void QOhosWindowProxy::moveWindowToGlobal(
1959 const QPoint &position, const MoveConfiguration &moveConfiguration)
1960{
1961 QOhosJsThreadGateway::invokeAndWaitForContinue(
1962 [&](QOhosJsState &jsState, QOhosTaskPromise<> taskPromise) {
1963 if (m_jsScopeData->isWindowClosing()) {
1964 taskPromise();
1965 return;
1966 }
1967
1968 auto moveConfigurationObject = toNapiObject(jsState.env(), moveConfiguration);
1969 auto moveConfigurationObjectStr = QNapi::toJsonString(moveConfigurationObject);
1970 qOhosPrintfDebug(
1971 "%s: %d,%d,%s",
1972 Q_FUNC_INFO, position.x(), position.y(),
1973 moveConfigurationObjectStr.c_str());
1974
1975 m_jsScopeData->jsWindowRef->evalToPromiseOrRejectOnThrow(
1976 "moveWindowToGlobal(*)", {position.x(), position.y(), moveConfigurationObject})
1977 .onCatch(QtOhos::makeErrorLoggingJsCallback(Q_FUNC_INFO))
1978 .onFinally(std::move(taskPromise).makeChained(Q_FUNC_INFO));
1979 },
1980 Q_FUNC_INFO);
1981}
1982
1983std::optional<QOhosDisplayInfo::JsDisplayId> QOhosWindowProxy::tryGetMainWindowJsDisplayId() const
1984{
1985 return qtIsMainWindow()
1986 ? getWindowProperties().displayId
1987 : QOhosJsThreadGateway::eval(
1988 [&](QOhosJsState &) {
1989 auto qUiAbilityPeer
1990 = QtOhos::QUiAbilityPeer::tryCastFromQAbilityPeerOrNull(m_jsScopeData->qAbilityPeer);
1991 return qUiAbilityPeer
1992 ? getWindowPropertiesFromJsWindow(qUiAbilityPeer->window()).displayId
1993 : std::nullopt;
1994 },
1995 Q_FUNC_INFO);
1996}
1997
1998void QOhosWindowProxy::shiftAppWindowFocus(QOhosWindowProxy &targetProxy)
1999{
2000 QOhosJsThreadGateway::invokeAndWaitForContinue(
2001 [&](QOhosJsState &jsState, QOhosTaskPromise<> taskPromise) {
2002 if (m_jsScopeData->isWindowClosing() || targetProxy.m_jsScopeData->isWindowClosing()) {
2003 taskPromise();
2004 return;
2005 }
2006
2007 auto srcWindowId = getWindowPropertiesFromJsWindow(m_jsScopeData->jsWindowRef->jsObject()).id;
2008 auto targetWindowId = getWindowPropertiesFromJsWindow(targetProxy.m_jsScopeData->jsWindowRef->jsObject()).id;
2009 jsState.evalToPromiseOrRejectOnThrow(
2010 "@ohos.window.shiftAppWindowFocus(*)", {srcWindowId.value(), targetWindowId.value()})
2011 .onCatch(QtOhos::makeErrorLoggingJsCallback("@ohos.window.shiftAppWindowFocus()"))
2012 .onFinally(std::move(taskPromise).makeChained(Q_FUNC_INFO));
2013 },
2014 Q_FUNC_INFO);
2015}
2016
2017QT_END_NAMESPACE
bool isWindowPcModeEnabled() const
static QOhosSettings & instance()
void setWindowRectAutoSave(bool enabed)
QHarmonyJsObjectRef jsWindowObjectRef() const
void setSubWindowModalEnabled(ModalityType ModalityType)
QtOhosQpa::enums::ohos::window::MaximizePresentation MaximizePresentation
bool isSubWindowMaximizeSupported() const
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 setWindowPrivacyMode(bool privacyMode)
QtOhosQpa::enums::ohos::window::WindowEventType WindowEventType
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)
bool tryMaximize(MaximizePresentation maximizePresentation)
void setWindowSystemBarEnable(const QStringList &names)
std::shared_ptr< QOhosWindowProxy > createSubWindow(const SubWindowCreateInfo &createInfo)
QPixmap snapshot() const
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
QtOhosQpa::enums::ohos::window::ModalityType ModalityType
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)
QtOhosQpa::enums::ohos::window::AvoidAreaType AvoidAreaType
void setCustomCursor(const QImage &customCursorImage, const QPoint &hotSpot)
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)
void setPointerStyleSync(const QCursor &cursor)
QList< QRect > getDisplayCutoutRects() const
WindowLimits getWindowLimits() const
std::string qAbilityInstanceId() const
QHarmonyJsObjectRef abilityObjectRef() const
void setNonClientAreaTouchWindowCallbackReceiver(QObject *contextObject, QOhosConsumer< std::vector< NonClientAreaTouchEvent > > touchEventBatchConsumer)
static std::shared_ptr< QOhosWindowProxy > createMainWindow(const MainWindowCreateInfo &createInfo)
JsState & jsState() const
std::optional< WindowProperties > tryGetWindowProperties(JsWindowId jsWindowId)
Definition window.cpp:28
Combined button and popup list for selecting options.
QRect ohosWindowRectToQRect(const QNapi::Object &ohosWindowRect)
bool isPointInNonClientArea(const QPoint &point, const QArkUi::WindowProperties &windowProperties)
bool isJsWindowInFreeWindowMode(const QArkUi::JsWindowRef &jsWindowRef)
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)
bool isAbilityTerminating(QNapi::Object ability)
QtOhosQpa::enums::ohos::multimodalInput::pointer::PointerStyle QOhosPointerStyle
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)
QXComponent< QXComponentType::Node > QXComponentNode
Definition qxcomponent.h:44
std::int32_t fingerId
Definition input.h:54
void onTouchEventFromArkUi(const QArkUi::TouchEvent &event) const
void onMouseEventFromArkUi(const QArkUi::MouseEvent &event) const