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>
7#include <QtCore/QSet>
8#include <QtCore/private/qnapi_p.h>
9#include <qohosjsenv_p.h>
10#include <QtCore/qscopeguard.h>
11#include <QtGui/qguiapplication.h>
12#include <QtGui/qimage.h>
13#include <algorithm>
14#include <functional>
15#include <memory>
16#include <multimedia/image_framework/image/pixelmap_native.h>
17#include <qarkui/input.h>
18#include <qarkui/qarkuiutils.h>
19#include <qarkui/qxcomponentregistry.h>
20#include <qarkui/window.h>
21#include <qarkui/window_manager.h>
22#include <qohosdeviceinfo_p.h>
23#include <qohosimageformat.h>
24#include <qohosjsutils.h>
25#include <qohospixelmapconversions.h>
26#include <qohosplugincore.h>
27#include <qohospointerstyle.h>
28#include <qohossettings.h>
29#include <qohosutils.h>
30#include <render/qohosbatchingrequestshandler.h>
31#include <render/qohosjswindowregistry.h>
32#include <render/qohoswindowproxydatafactory.h>
33#include <render/qxcomponent.h>
34#include <type_traits>
35#include <utility>
36
38
39namespace
40{
41
42QRect ohosWindowRectToQRect(const QNapi::Object &ohosWindowRect)
43{
44 return QRect {
45 ohosWindowRect.get<QNapi::Number>("left"),
46 ohosWindowRect.get<QNapi::Number>("top"),
47 ohosWindowRect.get<QNapi::Number>("width"),
48 ohosWindowRect.get<QNapi::Number>("height"),
49 };
50}
51
52QOhosWindowProxy::AvoidArea mapAvoidAreaFromJs(const QNapi::Object &avoidAreaObject)
53{
54 return {
55 .visible = avoidAreaObject.get<QNapi::Boolean>("visible"),
56 .leftRect = ohosWindowRectToQRect(avoidAreaObject.get<QNapi::Object>("leftRect")),
57 .topRect = ohosWindowRectToQRect(avoidAreaObject.get<QNapi::Object>("topRect")),
58 .rightRect = ohosWindowRectToQRect(avoidAreaObject.get<QNapi::Object>("rightRect")),
59 .bottomRect = ohosWindowRectToQRect(avoidAreaObject.get<QNapi::Object>("bottomRect")),
60 };
61}
62
64{
65 switch (shape) {
66 case Qt::ArrowCursor:
68 case Qt::UpArrowCursor:
70 case Qt::CrossCursor:
72 case Qt::WaitCursor:
74 case Qt::IBeamCursor:
76 case Qt::SizeVerCursor:
78 case Qt::SizeHorCursor:
80 case Qt::SizeBDiagCursor:
82 case Qt::SizeFDiagCursor:
84 case Qt::SizeAllCursor:
86 case Qt::BlankCursor:
87 // TODO: there is no dedicated Ohos 'Qt::BlankCursor'. Return default.
89 case Qt::SplitVCursor:
91 case Qt::SplitHCursor:
93 case Qt::PointingHandCursor:
95 case Qt::ForbiddenCursor:
97 case Qt::WhatsThisCursor:
99 case Qt::BusyCursor:
101 case Qt::OpenHandCursor:
103 case Qt::ClosedHandCursor:
105 case Qt::DragCopyCursor:
107 case Qt::DragMoveCursor:
109 case Qt::DragLinkCursor:
110 // TODO: there is no dedicated Ohos 'Qt::DragLinkCursor'. Return default.
112 case Qt::BitmapCursor:
113 // TODO: there is no dedicated Ohos 'Qt::BitmapCursor'. Return default.
115 case Qt::CustomCursor:
116 // TODO: there is no dedicated Ohos 'Qt::CustomCursor'. Return default.
118 }
119
121}
122
123QOhosOptional<double> getOptionalNumberPropAsOptionalDouble(const QNapi::Object &object, const std::string &propertyName)
124{
125 auto propOrEmpty = QNapi::getOptionalPropOrEmpty<QNapi::Number>(object, propertyName);
126 return !propOrEmpty.IsEmpty()
127 ? QOhosOptional<double>(propOrEmpty)
129}
130
132{
133 auto windowPropsObj = jsWindow.call<QNapi::Object>("getWindowProperties", {});
134 auto displayIdOrEmpty = QNapi::getOptionalPropOrEmpty<QNapi::Number>(windowPropsObj, "displayId");
135 return QArkUi::WindowProperties {
136 .windowRect = ohosWindowRectToQRect(windowPropsObj.get<QNapi::Object>("windowRect")),
137 .drawableRect = ohosWindowRectToQRect(windowPropsObj.get<QNapi::Object>("drawableRect")),
138 .id = QArkUi::JsWindowId(windowPropsObj.get<QNapi::Number>("id")),
139 .displayId = !displayIdOrEmpty.IsEmpty()
140 ? makeQOhosOptional(QOhosDisplayInfo::JsDisplayId{displayIdOrEmpty.DoubleValue()})
141 : makeEmptyQOhosOptional(),
142 };
143}
144
145QNapi::Object toNapiObject(napi_env env, const QOhosWindowProxy::MoveConfiguration &moveConfiguration)
146{
147 auto moveConfigurationObject = QNapi::makeObject(env);
148 if (moveConfiguration.displayId.hasValue()) {
149 moveConfigurationObject.set(
150 "displayId", moveConfiguration.displayId.value().value());
151 }
152 return moveConfigurationObject;
153}
154
155template<typename ...Args>
157 std::function<void(Args...)> QOhosWindowProxy::WindowCallbacks::*memberPtr,
158 std::shared_ptr<QOhosWindowProxy::WindowCallbacks> qtWindowCallbacks)
159{
160 auto weakQtWindowCallbacks = QtOhos::makeWeakPtr(qtWindowCallbacks);
161
162 return [memberPtr, weakQtWindowCallbacks](Args ...args) {
163 QtOhos::invokeInQtThread([memberPtr, weakQtWindowCallbacks, args...]() {
164 auto qtWindowCallbacks = weakQtWindowCallbacks.lock();
165 if (qtWindowCallbacks)
166 (*qtWindowCallbacks.*memberPtr)(args...);
167 });
168 };
169}
170
171template<typename T>
173 std::function<void(T)> QOhosWindowProxy::WindowCallbacks::*memberPtr,
174 std::shared_ptr<QOhosWindowProxy::WindowCallbacks> qtWindowCallbacks)
175{
176 auto weakQtWindowCallbacks = QtOhos::makeWeakPtr(qtWindowCallbacks);
177
178 return QtOhos::makeCompressingAsyncConsumer<T>(
179 [memberPtr, weakQtWindowCallbacks](T value) {
180 auto qtWindowCallbacks = weakQtWindowCallbacks.lock();
181 if (qtWindowCallbacks)
182 (*qtWindowCallbacks.*memberPtr)(value);
183 },
184 QtOhos::invokeInQtThread);
185}
186
187bool isPointInNonClientArea(const QPoint &point, const QArkUi::WindowProperties &windowProperties)
188{
189 constexpr bool containsPolicyExcludeEdgeValue = true;
190
191 auto drawableRectInScreenSpace =
192 windowProperties.drawableRect.translated(windowProperties.windowRect.topLeft());
193 return !drawableRectInScreenSpace.contains(point, containsPolicyExcludeEdgeValue);
194}
195
197{
198 QOhosOptional<QEvent::Type> eventType;
199 switch (action) {
200 case ::MOUSE_ACTION_MOVE:
201 return makeQOhosOptional(QEvent::NonClientAreaMouseMove);
202 case ::MOUSE_ACTION_BUTTON_DOWN:
203 return makeQOhosOptional(QEvent::NonClientAreaMouseButtonPress);
204 case ::MOUSE_ACTION_BUTTON_UP:
205 return makeQOhosOptional(QEvent::NonClientAreaMouseButtonRelease);
206 case ::MOUSE_ACTION_CANCEL:
207 case ::MOUSE_ACTION_AXIS_BEGIN:
208 case ::MOUSE_ACTION_AXIS_UPDATE:
209 case ::MOUSE_ACTION_AXIS_END:
210 break;
211 }
213}
214
215QOhosOptional<Qt::MouseButton> tryMapMouseEventButtonToQt(::Input_MouseEventButton button)
216{
217 switch (button) {
218 case ::MOUSE_BUTTON_LEFT:
219 return makeQOhosOptional(Qt::LeftButton);
220 case ::MOUSE_BUTTON_MIDDLE:
221 return makeQOhosOptional(Qt::MiddleButton);
222 case ::MOUSE_BUTTON_RIGHT:
223 return makeQOhosOptional(Qt::RightButton);
224 case ::MOUSE_BUTTON_FORWARD:
225 return makeQOhosOptional(Qt::ForwardButton);
226 case ::MOUSE_BUTTON_BACK:
227 return makeQOhosOptional(Qt::BackButton);
228 case ::MOUSE_BUTTON_NONE:
229 break;
230 }
232}
233
235{
236 switch (action) {
237 case ::TOUCH_ACTION_MOVE:
238 return makeQOhosOptional(QEventPoint::State::Updated);
239 case ::TOUCH_ACTION_DOWN:
240 return makeQOhosOptional(QEventPoint::State::Pressed);
241 case ::TOUCH_ACTION_UP:
242 return makeQOhosOptional(QEventPoint::State::Released);
243 case ::TOUCH_ACTION_CANCEL:
244 break;
245 }
247}
248
249template<typename EnumsContainer>
250std::string mapEnumsToLogString(const EnumsContainer &enums)
251{
252 std::string output;
253 for (auto enumValue : enums) {
254 if (!output.empty())
255 output += ",";
256 output += std::to_string(static_cast<std::underlying_type_t<decltype(enumValue)>>(enumValue));
257 }
258 return output;
259}
260
261}
262
263const QOhosWindowProxy::EventHandlerDescriptor QOhosWindowProxy::eventHandlerDescriptors[] = {
264 {
265 .eventName = "avoidAreaChange",
266 .eventHandler = &QOhosWindowProxy::JsScopeData::handleAvoidAreaChangeCallback,
267 .eventHandlerFlags = {},
268 },
269 {
270 .eventName = "touchOutside",
271 .eventHandler = &QOhosWindowProxy::JsScopeData::handleWindowTouchOutsideCallback,
272 .eventHandlerFlags = {},
273 },
274 {
275 .eventName = "windowEvent",
276 .eventHandler = &QOhosWindowProxy::JsScopeData::handleWindowEventCallback,
277 .eventHandlerFlags = EventHandlerFlagBits::allowCallWhenAbilityIsTerminating,
278 },
279 {
280 .eventName = "windowRectChange",
281 .eventHandler = &QOhosWindowProxy::JsScopeData::handleWindowRectChangeCallback,
282 .eventHandlerFlags = {},
283 },
284 {
285 .eventName = "windowStatusChange",
286 .eventHandler = &QOhosWindowProxy::JsScopeData::handleWindowStatusCallback,
287 .eventHandlerFlags = {},
288 },
289 {
290 .eventName = "windowVisibilityChange",
291 .eventHandler = &QOhosWindowProxy::JsScopeData::handleWindowVisibilityCallback,
292 .eventHandlerFlags = {},
293 },
294 {
295 .eventName = "displayIdChange",
296 .eventHandler = &QOhosWindowProxy::JsScopeData::handleWindowDisplayIdChangeCallback,
297 .eventHandlerFlags = EventHandlerFlagBits::allowEventHandlerRegistrationFailure,
298 },
299};
300
301QOhosWindowProxy::QOhosWindowProxy(
302 QOhosWindowProxyData windowProxyData)
303 : m_jsScopeData(
304 QtOhos::makeProxyWithJsThreadDeleter(
305 std::make_shared<JsScopeData>(
306 windowProxyData.windowProxyType == WindowProxyType::MainWindow,
307 std::move(windowProxyData.jsWindow),
308 std::move(windowProxyData.jsKeepAliveData),
309 std::move(windowProxyData.qAbilityPeer))))
310 , m_windowProxyType(windowProxyData.windowProxyType)
311 , m_nodeXComponent(windowProxyData.nodeXComponent)
312 , m_qAbilityInstanceId(m_jsScopeData->qAbilityPeer->instanceId())
313{
314 for (const auto &eventHandlerDescriptor : eventHandlerDescriptors) {
315 m_jsScopeData->registerCallbackListener(
316 eventHandlerDescriptor.eventName, eventHandlerDescriptor.eventHandler,
317 eventHandlerDescriptor.eventHandlerFlags);
318 }
319}
320
321QOhosWindowProxy::~QOhosWindowProxy()
322{
323 // NOTE
324 // we need to unregister from JS Window events now, while the Window is
325 // still in consistent state. While destroying the m_jsScopeData we
326 // call Window::destroyWindow(), which makes the JS object unusable
327 // (trying to unregister something on it will throw).
328 m_subWindowCloseRegistrationHandle.reset();
329 m_jsScopeData.reset();
330}
331
332void QOhosWindowProxy::removeStartingWindow()
333{
335 [&](QtOhos::JsState &, std::function<void()> continueFunc) {
336 if (m_jsScopeData->isWindowClosing()) {
337 continueFunc();
338 return;
339 }
340 auto optQUiAbilityPeer
341 = QtOhos::QUiAbilityPeer::tryCastFromQAbilityPeerOrNull(m_jsScopeData->qAbilityPeer);
342 if (!optQUiAbilityPeer) {
343 continueFunc();
344 return;
345 }
346 auto promise = optQUiAbilityPeer->windowStage().call<QNapi::Promise>(
347 "removeStartingWindow");
348 promise.onFinally(std::move(continueFunc));
349 });
350}
351
352void QOhosWindowProxy::setSize(const QSize &size)
353{
354 qOhosPrintfDebug("%s: %d,%d", Q_FUNC_INFO, size.width(), size.height());
355
357 [&](QtOhos::JsState &, std::function<void()> continueFunc) {
358 if (m_jsScopeData->isWindowClosing()) {
359 continueFunc();
360 return;
361 }
362 auto promise = m_jsScopeData->jsWindowRef->call<QNapi::Promise>(
363 "resizeAsync", {size.width(), size.height()});
364 promise.onFinally(std::move(continueFunc));
365 });
366}
367
368void QOhosWindowProxy::setWindowBackgroundColor(const QColor &color)
369{
370 qCDebug(QtForOhos) << Q_FUNC_INFO << color;
371
373 if (m_jsScopeData->isWindowClosing())
374 return;
375 m_jsScopeData->jsWindowRef->call("setWindowBackgroundColor", {color.name(QColor::HexArgb).toStdString()});
376 });
377}
378
379void QOhosWindowProxy::setCustomCursor(const QImage &customCursorImage, const QPoint &hotSpot)
380{
381 const auto maxOhosCustomCursorSize = QSize(256, 256);
382 const auto customCursorSize = customCursorImage.size();
383 if (customCursorSize.width() > maxOhosCustomCursorSize.width()
384 || customCursorSize.height() > maxOhosCustomCursorSize.height()) {
385 qOhosPrintfError(
386 "%s: can't set %dx%d custom cursor, OHOS max custom cursor size is %dx%d",
387 Q_FUNC_INFO, customCursorSize.width(), customCursorSize.height(),
388 maxOhosCustomCursorSize.width(), maxOhosCustomCursorSize.height());
389 return;
390 }
391
392 auto convertedImage = customCursorImage.convertToFormat(QImage::Format_RGBA8888);
393 QtOhos::invokeInJsThreadAndWaitForContinue([&](QtOhos::JsState &jsState, std::function<void()> continueFunc) {
394 if (m_jsScopeData->isWindowClosing()) {
395 continueFunc();
396 return;
397 }
398 auto windowId = m_jsScopeData->jsWindowRef->jsObject().get<QNapi::Number>("getWindowProperties().id");
399
400 auto jsCursor = QNapi::makeObject(
401 jsState.env(),
402 {
403 {"pixelMap", createNapiPixelMapFromQImage(jsState, convertedImage)},
404 {"focusX", hotSpot.x()},
405 {"focusY", hotSpot.y()},
406 });
407
408 auto jsCursorConfig = QNapi::makeObject(
409 jsState.env(),
410 {
411 {"followSystem", false},
412 });
413
414 jsState.eval<QNapi::Promise>(
415 "@ohos.multimodalInput.pointer.setCustomCursor(*)", {windowId, jsCursor, jsCursorConfig})
416 .onCatch(QtOhos::makeErrorLoggingJsCallback("setCustomCursor()"))
417 .onFinally(std::move(continueFunc));
418 });
419}
420
421void QOhosWindowProxy::setPointerStyleSync(const QCursor &cursor)
422{
424 if (m_jsScopeData->isWindowClosing())
425 return;
426 auto windowId = m_jsScopeData->jsWindowRef->jsObject().get<QNapi::Number>("getWindowProperties().id");
427
428 jsState.eval(
429 "@ohos.multimodalInput.pointer.setPointerStyleSync(*)",
430 {windowId, jsState.mapOhosEnumToJs(convertToOhosCursor(cursor.shape()))});
431 });
432}
433
435{
436 return QtOhos::evalInJsThread(
437 [&](QtOhos::JsState &) {
438 if (m_jsScopeData->isWindowClosing())
439 return QArkUi::WindowProperties {};
440 return getWindowPropertiesFromJsWindow(m_jsScopeData->jsWindowRef->jsObject());
441 });
442}
443
444void QOhosWindowProxy::setWindowCallbackReceiver(std::unique_ptr<WindowCallbacks> callbackReceiver)
445{
446 auto sharedWindowCallbackReceiver = std::shared_ptr<WindowCallbacks>(std::move(callbackReceiver));
447
449 m_jsScopeData->windowCallbackReceiver = QtOhos::moveToSharedPtr(WindowCallbacks {
450 .onWindowEvent = makeQtThreadWindowCallbackDelegate(&WindowCallbacks::onWindowEvent, sharedWindowCallbackReceiver),
451 .onWindowStatusChange = makeQtThreadWindowCallbackDelegate(&WindowCallbacks::onWindowStatusChange, sharedWindowCallbackReceiver),
452 .onWindowVisibilityChange = makeQtThreadWindowCallbackDelegate(&WindowCallbacks::onWindowVisibilityChange, sharedWindowCallbackReceiver),
453 .onTouchOutside = makeQtThreadWindowCallbackDelegate(&WindowCallbacks::onTouchOutside, sharedWindowCallbackReceiver),
454 .onAvoidAreaChange = makeQtThreadWindowCallbackDelegate(&WindowCallbacks::onAvoidAreaChange, sharedWindowCallbackReceiver),
455 .onWindowRectChange = makeCompressingQtThreadWindowCallbackDelegate(&WindowCallbacks::onWindowRectChange, sharedWindowCallbackReceiver),
456 .onWindowDisplayIdChange = makeQtThreadWindowCallbackDelegate(&WindowCallbacks::onWindowDisplayIdChange, sharedWindowCallbackReceiver),
457 });
458 });
459
460 m_qtWindowCallbacksReceiverHandle = sharedWindowCallbackReceiver;
461}
462
464 QObject *contextObject, QOhosConsumer<std::vector<NonClientAreaMouseEvent>> mouseEventBatchConsumer)
465{
466 auto qtConsumer = QtOhos::moveToSharedPtr(std::move(mouseEventBatchConsumer));
467 auto weakQtConsumer = QtOhos::makeWeakPtr(qtConsumer);
468
469 auto jsConsumer = makeQtOhosSimpleBatchingQtRequestsHandler<NonClientAreaMouseEvent>(
470 QtOhos::QObjectThreadSafeRef(contextObject),
471 [weakQtConsumer](std::vector<NonClientAreaMouseEvent> &&batch) {
472 auto qtConsumer = weakQtConsumer.lock();
473 if (qtConsumer)
474 (*qtConsumer)(std::move(batch));
475 });
476
478 m_jsScopeData->nonClientAreaMouseEventConsumer = std::move(jsConsumer);
479 });
480
481 m_qtNonClientAreaMouseWindowCallbackReceiverHandle = qtConsumer;
482}
483
485 QObject *contextObject, QOhosConsumer<std::vector<NonClientAreaTouchEvent>> touchEventBatchConsumer)
486{
487 auto qtConsumer = QtOhos::moveToSharedPtr(std::move(touchEventBatchConsumer));
488 auto weakQtConsumer = QtOhos::makeWeakPtr(qtConsumer);
489
490 auto jsConsumer = makeQtOhosSimpleBatchingQtRequestsHandler<NonClientAreaTouchEvent>(
491 QtOhos::QObjectThreadSafeRef(contextObject),
492 [weakQtConsumer](std::vector<NonClientAreaTouchEvent> &&batch) {
493 auto qtConsumer = weakQtConsumer.lock();
494 if (qtConsumer)
495 (*qtConsumer)(std::move(batch));
496 });
497
499 m_jsScopeData->nonClientAreaTouchEventConsumer = std::move(jsConsumer);
500 });
501
502 m_qtNonClientAreaTouchWindowCallbackReceiverHandle = qtConsumer;
503}
504
505bool QOhosWindowProxy::qtIsMainWindow() const
506{
507 return m_windowProxyType == WindowProxyType::MainWindow;
508}
509
510WindowProxyType QOhosWindowProxy::windowProxyType() const
511{
512 return m_windowProxyType;
513}
514
515void QOhosWindowProxy::raiseToAppTop()
516{
517 qCDebug(QtForOhos, "%s", Q_FUNC_INFO);
518 QtOhos::invokeInJsThreadAndWaitForContinue([&](QtOhos::JsState &, std::function<void()> continueFunc) {
519 if (m_jsScopeData->isWindowClosing()) {
520 continueFunc();
521 return;
522 }
523 auto promise = m_jsScopeData->jsWindowRef->call<QNapi::Promise>("raiseToAppTop");
524 promise.onFinally(std::move(continueFunc));
525 });
526}
527
528void QOhosWindowProxy::showWindow(const ShowWindowOptions &options)
529{
530 qCDebug(QtForOhos, "%s", Q_FUNC_INFO);
531 QtOhos::invokeInJsThreadAndWaitForContinue([&](QtOhos::JsState &jsState, std::function<void()> continueFunc) {
532 if (m_jsScopeData->isWindowClosing()) {
533 continueFunc();
534 return;
535 }
536
537 std::vector<std::pair<std::string, QNapi::ValueWrapper>> jsOptionsProps;
538
539 if (options.focusOnShow.hasValue())
540 jsOptionsProps.emplace_back("focusOnShow", options.focusOnShow.value());
541
542 std::vector<QNapi::ValueWrapper> showWindowArgs;
543 constexpr auto minSupportedSdkVersionForOptions = 20;
544 if (QOhosDeviceInfo::sdkApiVersion() >= minSupportedSdkVersionForOptions) {
545 constexpr bool brokenHandlingOfEmptyOptionsParamInOhos = true;
546 if (!(jsOptionsProps.empty() && brokenHandlingOfEmptyOptionsParamInOhos)) {
547 showWindowArgs.push_back(QNapi::makeObject(jsState.env(), jsOptionsProps));
548 }
549 } else if (!jsOptionsProps.empty()) {
550 qOhosPrintfWarning(
551 "%s: showWindow() doesn't accept options in SDK version < %d, ignored %zu options",
552 Q_FUNC_INFO, minSupportedSdkVersionForOptions, jsOptionsProps.size());
553 }
554
555 auto promise = m_jsScopeData->jsWindowRef->call<QNapi::Promise>("showWindow", showWindowArgs);
556 promise.onFinally(std::move(continueFunc));
557 });
558}
559
560void QOhosWindowProxy::recover()
561{
562 qCDebug(QtForOhos, "%s", Q_FUNC_INFO);
564 if (m_jsScopeData->isWindowClosing())
565 return;
566 m_jsScopeData->jsWindowRef->call("recover");
567 });
568}
569
570void QOhosWindowProxy::restore()
571{
572 qCDebug(QtForOhos, "%s", Q_FUNC_INFO);
573 QtOhos::invokeInJsThreadAndWaitForContinue([&](QtOhos::JsState &, std::function<void()> continueFunc) {
574 if (m_jsScopeData->isWindowClosing()) {
575 continueFunc();
576 return;
577 }
578 m_jsScopeData->jsWindowRef->call<QNapi::Promise>("restore").onFinally(std::move(continueFunc));
579 });
580}
581
582void QOhosWindowProxy::minimize()
583{
584 qCDebug(QtForOhos, "%s", Q_FUNC_INFO);
585 QtOhos::invokeInJsThreadAndWaitForContinue([&](QtOhos::JsState &, std::function<void()> continueFunc) {
586 if (m_jsScopeData->isWindowClosing()) {
587 continueFunc();
588 return;
589 }
590 auto promise = m_jsScopeData->jsWindowRef->call<QNapi::Promise>("minimize");
591 promise.onFinally(std::move(continueFunc));
592 });
593}
594
595void QOhosWindowProxy::maximize(MaximizePresentation maximizePresentation)
596{
597 qCDebug(QtForOhos, "%s", Q_FUNC_INFO);
598
599 if (!qtIsMainWindow()) {
600 qCWarning(QtForOhos(), "%s: Maximize is currently supported only on main windows", Q_FUNC_INFO);
601 return;
602 }
603
605 if (m_jsScopeData->isWindowClosing())
606 return;
607 m_jsScopeData->jsWindowRef->call("maximize", {jsState.mapOhosEnumToJs(maximizePresentation)});
608 });
609}
610
611void QOhosWindowProxy::showAbility()
612{
613 qCDebug(QtForOhos, "%s", Q_FUNC_INFO);
614
615 QtOhos::invokeInJsThreadAndWaitForContinue([&](QtOhos::JsState &, std::function<void()> continueFunc) {
616 if (m_jsScopeData->isWindowClosing()) {
617 continueFunc();
618 return;
619 }
620
621 QNapi::Promise showAbilityPromise;
622 try {
623 showAbilityPromise = m_jsScopeData->qAbilityPeer->qAbility().call<QNapi::Promise>("context.showAbility");
624 } catch (const Napi::Error &error) {
625 qOhosPrintfError("showAbility failed with error: %s", error.what());
626 continueFunc();
627 return;
628 }
629
630 showAbilityPromise
631 .onCatch(QtOhos::makeErrorLoggingJsCallback("showAbility()"))
632 .onFinally(std::move(continueFunc));
633 });
634}
635
636bool QOhosWindowProxy::tryHideAbility()
637{
638 qCDebug(QtForOhos, "%s", Q_FUNC_INFO);
639
640 return QtOhos::evalInJsThreadWithConsumer<bool>([&](QtOhos::JsState &, QOhosConsumer<bool> resultConsumer) {
641 if (m_jsScopeData->isWindowClosing()) {
642 resultConsumer(false);
643 return;
644 }
645
646 QNapi::Promise hidePromise;
647 try {
648 hidePromise = m_jsScopeData->qAbilityPeer->qAbility().call<QNapi::Promise>("context.hideAbility");
649 } catch (const Napi::Error &error) {
650 qOhosPrintfError("hideAbility failed with error: %s", error.what());
651 resultConsumer(false);
652 return;
653 }
654
655 hidePromise
656 .withContext(std::move(resultConsumer))
657 .onThenWithContext(
658 [](const QtOhos::CallbackInfo &, auto &resultConsumer) {
659 resultConsumer(true);
660 })
661 .onCatchWithContext(
662 [](const QtOhos::CallbackInfo &cbInfo, auto &resultConsumer) {
663 QtOhos::logJsCallbackError(cbInfo, "got error from hideAbility()");
664 resultConsumer(false);
665 });
666 });
667}
668
669bool QOhosWindowProxy::getImmersiveModeEnabledState()
670{
671 return QtOhos::evalInJsThread(
672 [&](QtOhos::JsState &) {
673 if (m_jsScopeData->isWindowClosing())
674 return false;
675 return m_jsScopeData->jsWindowRef->call<QNapi::Boolean>("getImmersiveModeEnabledState").Value();
676 });
677}
678
679void QOhosWindowProxy::setWindowPrivacyMode(bool privacyMode)
680{
681 qCDebug(QtForOhos, "%s: %s", Q_FUNC_INFO, privacyMode ? "true" : "false");
682
683 QtOhos::invokeInJsThreadAndWaitForContinue([&](QtOhos::JsState &, std::function<void()> continueFunc) {
684 if (m_jsScopeData->isWindowClosing()) {
685 continueFunc();
686 return;
687 }
688
689 QNapi::Promise setPrivacyModePromise;
690 try {
691 setPrivacyModePromise = m_jsScopeData->jsWindowRef->call<QNapi::Promise>(
692 "setWindowPrivacyMode", {privacyMode});
693 } catch (const Napi::Error &error) {
694 qOhosPrintfError("setPrivacyMode failed with error: %s", error.what());
695 continueFunc();
696 return;
697 }
698
699 setPrivacyModePromise
700 .onCatch(QtOhos::makeErrorLoggingJsCallback("setPrivacyMode()"))
701 .onFinally(std::move(continueFunc));
702 });
703}
704
705void QOhosWindowProxy::setWindowFocusable(bool focusable)
706{
707 qCDebug(QtForOhos, "%s: %s", Q_FUNC_INFO, focusable ? "true" : "false");
709 if (m_jsScopeData->isWindowClosing())
710 return;
711 m_jsScopeData->jsWindowRef->call("setWindowFocusable", {focusable});
712 });
713}
714
715void QOhosWindowProxy::setWindowTouchable(bool touchable)
716{
717 qCDebug(QtForOhos, "%s: %s", Q_FUNC_INFO, touchable ? "true" : "false");
719 if (m_jsScopeData->isWindowClosing())
720 return;
721 m_jsScopeData->jsWindowRef->call("setWindowTouchable", {touchable});
722 });
723}
724
725void QOhosWindowProxy::setWindowLimits(const QSize &minSize, const QSize &maxSize)
726{
727 qCDebug(
728 QtForOhos, "%s: (%d x %d)-(%d x %d)", Q_FUNC_INFO, minSize.width(), minSize.height(),
729 maxSize.width(), maxSize.height());
731 [&](QtOhos::JsState &jsState, std::function<void()> continueFunc) {
732 if (m_jsScopeData->isWindowClosing()) {
733 continueFunc();
734 return;
735 }
736 auto windowLimits = QNapi::makeObject(
737 jsState.env(),
738 {
739 {"minWidth", minSize.width()},
740 {"minHeight", minSize.height()},
741 {"maxWidth", maxSize.width()},
742 {"maxHeight", maxSize.height()},
743 });
744
745 std::vector<QNapi::ValueWrapper> setWindowLimitsArgs = {windowLimits};
747 constexpr bool isForcible = true;
748 setWindowLimitsArgs.push_back(isForcible);
749 }
750 auto setWindowLimitsPromiseOrValue = m_jsScopeData->jsWindowRef->call(
751 "setWindowLimits", setWindowLimitsArgs);
752
753 if (setWindowLimitsPromiseOrValue.IsPromise()) {
754 QNapi::checkedCast<QNapi::Promise>(setWindowLimitsPromiseOrValue).onFinally(std::move(continueFunc));
755 } else {
756 qOhosPrintfWarning("setWindowLimits() didn't return a Promise, ignoring result");
757 continueFunc();
758 }
759 });
760}
761
762QOhosWindowProxy::WindowLimits QOhosWindowProxy::getWindowLimits() const
763{
764 qCDebug(QtForOhos, "%s", Q_FUNC_INFO);
765 return QtOhos::evalInJsThread(
766 [&](QtOhos::JsState &) {
767 if (m_jsScopeData->isWindowClosing())
768 return WindowLimits {};
769 auto windowLimitsObject = m_jsScopeData->jsWindowRef->call<QNapi::Object>("getWindowLimits");
770 return WindowLimits {
771 .minWidth = getOptionalNumberPropAsOptionalDouble(windowLimitsObject, "minWidth"),
772 .minHeight = getOptionalNumberPropAsOptionalDouble(windowLimitsObject, "minHeight"),
773 .maxWidth = getOptionalNumberPropAsOptionalDouble(windowLimitsObject, "maxWidth"),
774 .maxHeight = getOptionalNumberPropAsOptionalDouble(windowLimitsObject, "maxHeight"),
775 };
776 });
777}
778
779QOhosWindowProxy::AvoidArea QOhosWindowProxy::getWindowAvoidArea(AvoidAreaType avoidAreaType) const
780{
781 qCDebug(QtForOhos, "%s: %d", Q_FUNC_INFO, avoidAreaType);
782 return QtOhos::evalInJsThread(
783 [&](QtOhos::JsState &jsState) {
784 if (m_jsScopeData->isWindowClosing())
785 return AvoidArea {};
786 auto avoidAreaObject = m_jsScopeData->jsWindowRef->call<QNapi::Object>(
787 "getWindowAvoidArea", {jsState.mapOhosEnumToJs(avoidAreaType)});
788 return mapAvoidAreaFromJs(avoidAreaObject);
789 });
790}
791
792void QOhosWindowProxy::setWindowMask(
793 const WindowMask &windowMask, const QOhosOptional<QSize> &ohosMaskSizeOverride)
794{
796 return;
797
798 auto ohosMaskSize = ohosMaskSizeOverride.hasValue()
799 ? ohosMaskSizeOverride.value()
800 : getWindowProperties().windowRect.size();
801
802 if (ohosMaskSize.isEmpty()) {
803 const auto *maskSrcSizeMsg = ohosMaskSizeOverride.hasValue()
804 ? "overridden mask source"
805 : "window";
806 if (ohosMaskSizeOverride.hasValue()) {
807 qOhosPrintfError(
808 "%s failed - %s size is 0x0", maskSrcSizeMsg,
809 "QOhosWindowProxy::setWindowMask");
810 }
811 return;
812 }
813
814 QtOhos::invokeInJsThreadAndWaitForContinue([&](QtOhos::JsState &jsState, std::function<void()> continueFunc) {
815 if (m_jsScopeData->isWindowClosing()) {
816 continueFunc();
817 return;
818 }
819 auto *env = jsState.env();
820
821 QNapi::Array maskRowsArray = QNapi::Array::New(env, ohosMaskSize.height());
822 const int defaultValue = windowMask.windowMaskRegion.isEmpty() ? 1 : 0;
823
824 for (int rowIndex = 0; rowIndex < ohosMaskSize.height(); ++rowIndex) {
825 auto arr = QNapi::Array::New(env, ohosMaskSize.width());
826 arr.fill(defaultValue);
827 maskRowsArray[rowIndex] = arr;
828 }
829
830 auto valueToSet = QNapi::Number::New(env, 1);
831 for (const auto &rect: windowMask.windowMaskRegion) {
832 auto top = qBound(0, rect.top(), ohosMaskSize.height() - 1);
833 auto bottom = qBound(0, rect.bottom(), ohosMaskSize.height() - 1);
834 auto left = qBound(0, rect.left(), ohosMaskSize.width() - 1);
835 auto right = qBound(0, rect.right(), ohosMaskSize.width() - 1);
836
837 for (auto rowIndex = top; rowIndex <= bottom; ++rowIndex) {
838 auto row = maskRowsArray.Get(rowIndex).As<QNapi::Array>();
839 for (auto columnIndex = left; columnIndex <= right; ++columnIndex)
840 row[columnIndex] = valueToSet;
841 }
842 }
843
844 // HACK - The setWindowMask has inconsistent definition and the function implementation itself may throw
845 // without returning any promise.
846 QNapi::Promise setWindowMaskPromise;
847 try {
848 setWindowMaskPromise = m_jsScopeData->jsWindowRef->call<QNapi::Promise>(
849 "setWindowMask", {maskRowsArray});
850 } catch (const Napi::Error &error) {
851 qOhosPrintfError("setWindowMask failed with error: %s", error.what());
852 continueFunc();
853 return;
854 }
855
856 setWindowMaskPromise
857 .onCatch(QtOhos::makeErrorLoggingJsCallback("setWindowMask()"))
858 .onFinally(std::move(continueFunc));
859 });
860}
861
862void QOhosWindowProxy::setSubWindowModalDisabled()
863{
865 return;
866
868 [&](QtOhos::JsState &, std::function<void()> continueFunc) {
869 if (m_jsScopeData->isWindowClosing()) {
870 continueFunc();
871 return;
872 }
873 m_jsScopeData->jsWindowRef->call<QNapi::Promise>("setSubWindowModal", {false})
874 .onCatch(QtOhos::makeErrorLoggingJsCallback("setSubWindowModal()"))
875 .onFinally(std::move(continueFunc));
876 });
877}
878
879void QOhosWindowProxy::setSubWindowModalEnabled(ModalityType modalityType)
880{
882 return;
883
885 qOhosPrintfWarning(
886 "%s: APPLICATION_MODALITY option can be used only on 2-in-1 devices - skipping",
887 Q_FUNC_INFO);
888 return;
889 }
890
892 [&](QtOhos::JsState &jsState, std::function<void()> continueFunc) {
893 if (m_jsScopeData->isWindowClosing()) {
894 continueFunc();
895 return;
896 }
897 m_jsScopeData->jsWindowRef->call<QNapi::Promise>(
898 "setSubWindowModal", {true, jsState.mapOhosEnumToJs(modalityType)})
899 .onCatch(QtOhos::makeErrorLoggingJsCallback("setSubWindowModal()"))
900 .onFinally(std::move(continueFunc));
901 });
902}
903
904void QOhosWindowProxy::setTitle(const QString &title)
905{
907 [&](QtOhos::JsState &, std::function<void()> continueFunc) {
908 if (m_jsScopeData->isWindowClosing()) {
909 continueFunc();
910 return;
911 }
912
913 m_jsScopeData->jsWindowRef->call<QNapi::Promise>("setWindowTitle", {title.toStdString()})
914 .onFinally(std::move(continueFunc));
915 });
916}
917
918void QOhosWindowProxy::setWindowTitleButtonVisible(bool maximizeVisible, bool minimizeVisible, bool closeVisible)
919{
920 qOhosPrintfDebug(
921 "%s: isMaximizeVisible:%s, isMinimizeVisible:%s, isCloseVisible:%s",
922 Q_FUNC_INFO, maximizeVisible ? "true" : "false", minimizeVisible ? "true": "false",
923 closeVisible ? "true" : "false");
924
925 if (!qtIsMainWindow())
926 return;
927
929 qOhosPrintfWarning("%s: can be used only on 2-in-1 devices or tablets in PC mode - skipping", Q_FUNC_INFO);
930 return;
931 }
932
934 [&](QtOhos::JsState &) {
935 if (m_jsScopeData->isWindowClosing())
936 return;
937
938 m_jsScopeData->jsWindowRef->call(
939 "setWindowTitleButtonVisible", {maximizeVisible, minimizeVisible, closeVisible});
940 });
941}
942
943void QOhosWindowProxy::setWindowTopmost(bool topmost)
944{
945 if (!qtIsMainWindow())
946 return;
947
949 qOhosPrintfWarning("%s: can be used only on 2-in-1 devices or tablets in PC mode - skipping", Q_FUNC_INFO);
950 return;
951 }
952
953 qOhosPrintfDebug("%s: topMost: %s", Q_FUNC_INFO, topmost ? "true" : "false");
954
956 [&](QtOhos::JsState &, std::function<void()> continueFunc) {
957 if (m_jsScopeData->isWindowClosing()) {
958 continueFunc();
959 return;
960 }
961
962 m_jsScopeData->jsWindowRef->call<QNapi::Promise>("setWindowTopmost", {topmost})
963 .onFinally(std::move(continueFunc));
964 });
965}
966
967void QOhosWindowProxy::setWindowDecorVisible(bool visible)
968{
970 if (m_jsScopeData->isWindowClosing())
971 return;
972
973 m_jsScopeData->jsWindowRef->call("setWindowDecorVisible", {visible});
974 });
975}
976
977void QOhosWindowProxy::setWindowTitleMoveEnabled(bool enabled)
978{
980 qOhosPrintfWarning("%s: can be used only on 2-in-1 devices or tablets in PC mode - skipping", Q_FUNC_INFO);
981 return;
982 }
983
985 if (m_jsScopeData->isWindowClosing())
986 return;
987
988 m_jsScopeData->jsWindowRef->call("setWindowTitleMoveEnabled", {enabled});
989 });
990}
991
992void QOhosWindowProxy::setWindowShadowRadius(double radius)
993{
995 qOhosPrintfWarning("%s: can be used only on 2-in-1 devices or tablets - skipping", Q_FUNC_INFO);
996 return;
997 }
998
1000 return;
1001
1003 m_jsScopeData->jsWindowRef->call("setWindowShadowRadius", {radius});
1004 });
1005}
1006
1007void QOhosWindowProxy::setWindowCornerRadius(double radius)
1008{
1009 if (qtIsMainWindow())
1010 return;
1011
1013 [&](QtOhos::JsState &, std::function<void()> continueFunc) {
1014 m_jsScopeData->jsWindowRef->call<QNapi::Promise>("setWindowCornerRadius", {radius})
1015 .onFinally(std::move(continueFunc));
1016 });
1017}
1018
1019bool QOhosWindowProxy::isWindowRectAutoSave() const
1020{
1022 qCWarning(
1023 QtForOhos,
1024 "%s: geometry persistence feature is only supported on 2-in-1 devices. Returning default",
1025 Q_FUNC_INFO);
1026 return false;
1027 }
1028
1029 return QtOhos::evalInJsThreadWithConsumer<bool>(
1030 [&](QtOhos::JsState &, QOhosConsumer<bool> windowRectAutoSaveEnabledConsumer) {
1031 if (m_jsScopeData->isWindowClosing()) {
1032 windowRectAutoSaveEnabledConsumer(false);
1033 return;
1034 }
1035 auto optQUiAbilityPeer = QtOhos::QUiAbilityPeer::tryCastFromQAbilityPeerOrNull(m_jsScopeData->qAbilityPeer);
1036 if (!optQUiAbilityPeer) {
1037 windowRectAutoSaveEnabledConsumer(false);
1038 return;
1039 }
1040
1041 optQUiAbilityPeer->windowStage()
1042 .call<QNapi::Promise>("isWindowRectAutoSave")
1043 .withContext(std::move(windowRectAutoSaveEnabledConsumer))
1044 .onThenWithContext(
1045 [](const QtOhos::CallbackInfo &cbInfo, auto &windowRectAutoSaveEnabledConsumer) {
1046 bool windowRectAutoSaveEnabled = cbInfo.getFirstArg<QNapi::Boolean>(Q_FUNC_INFO);
1047 windowRectAutoSaveEnabledConsumer(windowRectAutoSaveEnabled);
1048 })
1049 .onCatchWithContext(
1050 [](const QtOhos::CallbackInfo &cbInfo, auto &windowRectAutoSaveEnabledConsumer) {
1051 QtOhos::logJsCallbackError(cbInfo, "isWindowRectAutoSave()");
1052 windowRectAutoSaveEnabledConsumer(false);
1053 });
1054 });
1055}
1056
1057void QOhosWindowProxy::setFollowParentMultiScreenPolicy(bool enabled)
1058{
1059 if (qtIsMainWindow())
1060 return;
1061
1063 qOhosPrintfDebug("%s: can be used only on 2-in-1 devices or tablets in PC mode - skipping", Q_FUNC_INFO);
1064 return;
1065 }
1066
1068 [&](QtOhos::JsState &, std::function<void()> continueFunc) {
1069 if (m_jsScopeData->isWindowClosing()) {
1070 continueFunc();
1071 return;
1072 }
1073 m_jsScopeData->jsWindowRef->call<QNapi::Promise>("setFollowParentMultiScreenPolicy", {enabled})
1074 .onCatch(QtOhos::makeErrorLoggingJsCallback("setFollowParentMultiScreenPolicy()"))
1075 .onFinally(std::move(continueFunc));
1076 });
1077}
1078
1079void QOhosWindowProxy::setWindowKeepScreenOn(bool keepScreenOn)
1080{
1081 qCDebug(QtForOhos, "%s: %s", Q_FUNC_INFO, QtOhos::mapBoolToTrueFalseStr(keepScreenOn));
1082
1084 [&](QtOhos::JsState &, std::function<void()> continueFunc) {
1085 if (m_jsScopeData->isWindowClosing()) {
1086 continueFunc();
1087 return;
1088 }
1089
1090 m_jsScopeData->jsWindowRef->call<QNapi::Promise>("setWindowKeepScreenOn", {keepScreenOn})
1091 .onCatch(QtOhos::makeErrorLoggingJsCallback("setWindowKeepScreenOn()"))
1092 .onFinally(std::move(continueFunc));
1093 });
1094}
1095
1096void QOhosWindowProxy::setSupportedWindowModes(const std::set<SupportWindowMode> &supportedWindowModes)
1097{
1098 qCDebug(QtForOhos, "%s: %s", Q_FUNC_INFO, mapEnumsToLogString(supportedWindowModes).c_str());
1099
1101 [&](QtOhos::JsState &jsState, std::function<void()> continueFunc) {
1102 if (m_jsScopeData->isWindowClosing()) {
1103 continueFunc();
1104 return;
1105 }
1106 auto qUiAbilityPeer = QtOhos::QUiAbilityPeer::tryCastFromQAbilityPeerOrNull(m_jsScopeData->qAbilityPeer);
1107 if (!qUiAbilityPeer) {
1108 continueFunc();
1109 return;
1110 }
1111
1112 std::vector<QNapi::ValueWrapper> jsSupportedWindowModes;
1113 for (const auto mode : supportedWindowModes)
1114 jsSupportedWindowModes.push_back(jsState.mapOhosEnumToJs(mode));
1115
1116 qUiAbilityPeer->windowStage().call<QNapi::Promise>("setSupportedWindowModes", {QNapi::makeArray(jsState.env(), jsSupportedWindowModes)})
1117 .onCatch(QtOhos::makeErrorLoggingJsCallback("setSupportedWindowModes()"))
1118 .onFinally(std::move(continueFunc));
1119 });
1120}
1121
1122void QOhosWindowProxy::setWindowRectAutoSave(bool enabled)
1123{
1124 constexpr bool isSaveBySpecifiedFlag = true;
1125
1127 qCWarning(
1128 QtForOhos,
1129 "%s: geometry persistence feature is only supported on 2-in-1 devices. Ignoring",
1130 Q_FUNC_INFO);
1131 return;
1132 }
1133
1135 [&](QtOhos::JsState &, std::function<void()> continueFunc) {
1136 if (m_jsScopeData->isWindowClosing()) {
1137 continueFunc();
1138 return;
1139 }
1140 auto optQUiAbilityPeer = QtOhos::QUiAbilityPeer::tryCastFromQAbilityPeerOrNull(m_jsScopeData->qAbilityPeer);
1141 if (!optQUiAbilityPeer) {
1142 continueFunc();
1143 return;
1144 }
1145
1146 optQUiAbilityPeer->windowStage()
1147 .call<QNapi::Promise>("setWindowRectAutoSave", {enabled, isSaveBySpecifiedFlag})
1148 .onCatch(QtOhos::makeErrorLoggingJsCallback("setWindowRectAutoSave()"))
1149 .onFinally(std::move(continueFunc));
1150 });
1151}
1152
1153void QOhosWindowProxy::setSubWindowCloseHandler(
1154 std::function<void()> handler, bool handlerReturnValue)
1155{
1156 m_subWindowCloseRegistrationHandle =
1157 registerSubWindowCloseHandler(std::move(handler), handlerReturnValue);
1158}
1159
1160void QOhosWindowProxy::resetSubWindowCloseHandler()
1161{
1162 m_subWindowCloseRegistrationHandle.reset();
1163}
1164
1165std::shared_ptr<void> QOhosWindowProxy::registerSubWindowCloseHandler(
1166 std::function<void()> handler, bool handlerReturnValue)
1167{
1168 auto sharedHandler = QtOhos::moveToSharedPtr(std::move(handler));
1169 auto jsWindowRegistrationHandle = QtOhos::evalInJsThread(
1170 [&](QtOhos::JsState &jsState) {
1171 return QtOhos::makeProxyWithJsThreadDeleter(
1172 m_jsScopeData->registerSubWindowCloseHandler(
1173 jsState,
1174 [weakHandler = QtOhos::makeWeakPtr(sharedHandler), handlerReturnValue]() {
1175 QtOhos::invokeInQtThread(
1176 [weakHandler]() {
1177 auto sharedHandler = weakHandler.lock();
1178 if (sharedHandler)
1179 (*sharedHandler)();
1180 });
1181 return handlerReturnValue;
1182 }));
1183 });
1184
1185 return QtOhos::moveToSharedPtr(
1186 std::make_tuple(sharedHandler, jsWindowRegistrationHandle));
1187}
1188
1189std::shared_ptr<QOhosWindowProxy>
1191{
1192 return QtOhos::evalInJsThreadWithConsumer<std::shared_ptr<QOhosWindowProxy>>(
1193 [&](QtOhos::JsState &jsState, QOhosConsumer<std::shared_ptr<QOhosWindowProxy>> resultConsumer) {
1194 makeWindowProxyDataForExistingMainWindowInJsThread(
1195 jsState,
1196 createInfo,
1197 [resultConsumer = std::move(resultConsumer)](QtOhos::JsState &jsState, QOhosWindowProxyData windowProxyData) {
1198 resultConsumer(QOhosWindowProxy::create(jsState, std::move(windowProxyData)));
1199 });
1200 });
1201}
1202
1203std::shared_ptr<QOhosWindowProxy>
1204QOhosWindowProxy::createFloatWindow(const FloatWindowCreateInfo &createInfo)
1205{
1206 return QtOhos::evalInJsThreadWithConsumer<std::shared_ptr<QOhosWindowProxy>>(
1207 [&](QtOhos::JsState &jsState, QOhosConsumer<std::shared_ptr<QOhosWindowProxy>> resultConsumer) {
1208 makeWindowProxyDataForFloatWindowInJsThread(
1209 jsState, createInfo,
1210 [resultConsumer = std::move(resultConsumer)](QtOhos::JsState &jsState, QOhosWindowProxyData windowProxyData) {
1211 resultConsumer(QOhosWindowProxy::create(jsState, std::move(windowProxyData)));
1212 });
1213 });
1214}
1215
1216std::shared_ptr<QOhosWindowProxy>
1217QOhosWindowProxy::createMainWindow(const MainWindowCreateInfo &createInfo)
1218{
1219 return QtOhos::evalInJsThreadWithConsumer<std::shared_ptr<QOhosWindowProxy>>(
1220 [&](QtOhos::JsState &jsState, QOhosConsumer<std::shared_ptr<QOhosWindowProxy>> resultConsumer) {
1221 makeWindowProxyDataForMainWindowInJsThread(
1222 jsState,
1223 createInfo,
1224 [resultConsumer = std::move(resultConsumer)](QtOhos::JsState &jsState, QOhosWindowProxyData windowProxyData) {
1225 resultConsumer(QOhosWindowProxy::create(jsState, std::move(windowProxyData)));
1226 });
1227 });
1228}
1229
1230std::shared_ptr<QXComponentNode> QOhosWindowProxy::nodeXComponent() const
1231{
1232 return m_nodeXComponent;
1233}
1234
1235std::string QOhosWindowProxy::qAbilityInstanceId() const
1236{
1237 return m_qAbilityInstanceId;
1238}
1239
1240std::shared_ptr<QOhosWindowProxy>
1241QOhosWindowProxy::createSubWindow(const SubWindowCreateInfo &createInfo)
1242{
1243 return QtOhos::evalInJsThreadWithConsumer<std::shared_ptr<QOhosWindowProxy>>(
1244 [&](QtOhos::JsState &jsState, QOhosConsumer<std::shared_ptr<QOhosWindowProxy>> resultConsumer) {
1245 auto proxyDataConsumer =
1246 [resultConsumer = std::move(resultConsumer)](QtOhos::JsState &jsState, QOhosWindowProxyData windowProxyData) {
1247 resultConsumer(QOhosWindowProxy::create(jsState, std::move(windowProxyData)));
1248 };
1249 // HACK - calling createSubWindow from window may throw while the context is termination
1250 // This is only a problem because we currenlty do not properly handle main window closing
1251 // Remove this hacky branch after QTFOROH-1080 issues are resolved.
1252 if (m_jsScopeData->isWindowClosing()) {
1253 makeWindowProxyDataForSubWindowInJsThread(
1254 jsState, createInfo, std::move(proxyDataConsumer));
1255 } else {
1256 makeWindowProxyDataForSubWindowInJsThread(
1257 jsState, m_jsScopeData->jsWindowRef->jsObject(), createInfo,
1258 std::move(proxyDataConsumer));
1259 }
1260 });
1261}
1262
1263QOhosWindowProxy::JsScopeData::JsScopeData(
1264 bool mainWindow, QNapi::Reference<QNapi::Object> jsWindow,
1265 std::shared_ptr<void> optKeepAliveData,
1266 std::shared_ptr<QtOhos::QAbilityPeer> qAbilityPeer)
1267 : mainWindow(mainWindow)
1268 , windowCallbackReceiver(nullptr)
1269 , windowDestroyedFromSystem(false)
1270 , optKeepAliveData(optKeepAliveData)
1271 , qAbilityPeer(qAbilityPeer)
1272 , m_windowFrameMouseFilterHandle(
1273 QArkUi::registerMouseEventsConsumer(
1274 getWindowPropertiesFromJsWindow(jsWindow.Value()).id,
1275 [this](const QArkUi::MouseEvent &event) {
1276 onMouseEventFromArkUi(event);
1277 }))
1278 , m_windowFrameTouchFilterHandle(
1279 QArkUi::registerTouchEventsConsumer(
1280 getWindowPropertiesFromJsWindow(jsWindow.Value()).id,
1281 [this](const QArkUi::TouchEvent &event) {
1282 onTouchEventFromArkUi(event);
1283 }))
1284 , jsWindowRef(
1285 std::make_shared<QArkUi::JsWindowRef>(
1286 getWindowPropertiesFromJsWindow(jsWindow.Value()).id,
1287 jsWindow.Value()))
1288{
1289}
1290
1291QOhosWindowProxy::JsScopeData::~JsScopeData()
1292{
1293 if (QtOhos::JsWindowsTracker::isWindowClosing(jsWindowRef->jsObject()) || qAbilityPeer->isTerminating()) {
1294 windowDestroyedFromSystem = true;
1295 return;
1296 }
1297
1298 if (!windowDestroyedFromSystem) {
1299 for (const auto &eventHandlerDescriptor : eventHandlerDescriptors)
1300 jsWindowRef->call("off", {eventHandlerDescriptor.eventName});
1301 }
1302
1303 QtOhos::JsWindowsTracker::tagWindowAsClosing(jsWindowRef->jsObject(), "QOhosWindowProxy::JsScopeData destructor");
1304
1305 if (mainWindow) {
1306 // NOTE - Set the windowDestroyedFromSystem flag here early
1307 // to avoid callbacks being invoked directly as a result of
1308 // calling terminate
1309 windowDestroyedFromSystem = true;
1310 qOhosPrintfWarning(
1311 "Attempting to terminate qAbility with instance id: %s",
1312 qAbilityPeer->instanceId().c_str());
1313 qAbilityPeer->qAbility().call("context.terminateSelf");
1314 } else if (!windowDestroyedFromSystem) {
1315 // FIXME - destroyWindow usually does and returns nothing
1316 // once the actual implementation is provided wait for the proomise that this function should return
1317 jsWindowRef->call("destroyWindow");
1318 }
1319}
1320
1321void QOhosWindowProxy::JsScopeData::registerCallbackListener(
1322 const std::string &eventName,
1323 void (QOhosWindowProxy::JsScopeData::*handleFunction)(const QtOhos::CallbackInfo &),
1324 QFlags<EventHandlerFlagBits> eventHandlerFlags)
1325{
1326
1327 std::weak_ptr<JsScopeData> weakSelf = shared_from_this();
1328 bool ignoreWhenAbilityIsTerminating = !eventHandlerFlags.testFlag(EventHandlerFlagBits::allowCallWhenAbilityIsTerminating);
1329 try {
1330 jsWindowRef->call(
1331 "on",
1332 {
1333 eventName,
1334 [weakSelf, handleFunction, eventName, ignoreWhenAbilityIsTerminating](const QtOhos::CallbackInfo &cbInfo) {
1335 auto self = weakSelf.lock();
1336 if (Q_UNLIKELY(!self)) {
1337 qOhosPrintfWarning(
1338 "callback '%s' called for destroyed QOhosWindowProxy::JsScopeData, ignoring",
1339 eventName.c_str());
1340 return;
1341 }
1342
1343 if (self->isWindowClosing() && ignoreWhenAbilityIsTerminating) {
1344 qOhosPrintfError(
1345 "QOhosWindowProxy: Received callback for event '%s' during termination of the related QAbility.",
1346 eventName.c_str());
1347 return;
1348 }
1349
1350 if (Q_UNLIKELY(self->windowDestroyedFromSystem)) {
1351 qOhosPrintfError(
1352 "QOhosWindowProxy: Received callback for event '%s' after WINDOW_DESTROYED",
1353 eventName.c_str());
1354 return;
1355 }
1356
1357 ((*self).*handleFunction)(cbInfo);
1358 }
1359 });
1360 } catch (const Napi::Error &error) {
1361 constexpr std::uint32_t capabilityNotSupportedErrorCode = 801;
1362 constexpr std::uint32_t windowStateIsAbnormalErrorCode = 1300002;
1363
1364 const QSet<std::uint32_t> ignorableErrorCodes = {
1365 capabilityNotSupportedErrorCode,
1366 windowStateIsAbnormalErrorCode,
1367 };
1368
1369 auto errorCode = QtOhos::tryGetCodeFromJsBusinessError(error);
1370
1371 auto ignorableError =
1372 eventHandlerFlags.testFlag(EventHandlerFlagBits::allowEventHandlerRegistrationFailure)
1373 && errorCode.hasValue()
1374 && ignorableErrorCodes.contains(errorCode.value());
1375
1376 if (!ignorableError)
1377 throw;
1378
1379 qOhosPrintfWarning(
1380 "%s: Ignored error %u while registering for window event '%s'",
1381 Q_FUNC_INFO, errorCode.value(), eventName.c_str());
1382 }
1383}
1384
1385std::shared_ptr<void> QOhosWindowProxy::JsScopeData::registerSubWindowCloseHandler(
1386 QtOhos::JsState &, std::function<bool()> handler)
1387{
1388 auto weakSelf = QtOhos::makeWeakPtr(shared_from_this());
1389 return QtOhos::registerOnOffMethodsBasedEventHandler(
1390 jsWindowRef->jsObject(), "subWindowClose",
1391 [weakSelf, handler = std::move(handler)](const QtOhos::CallbackInfo &cbInfo) {
1392 bool deferClose = handler();
1393 auto self = weakSelf.lock();
1394 if (self && !deferClose)
1395 QtOhos::JsWindowsTracker::tagWindowAsClosing(self->jsWindowRef->jsObject(), "subWindowClose => false");
1396 return QNapi::Boolean::New(cbInfo.Env(), deferClose);
1397 });
1398}
1399
1400void QOhosWindowProxy::JsScopeData::handleWindowEventCallback(const QtOhos::CallbackInfo &cbInfo)
1401{
1402 auto eventType = cbInfo.getFirstArg<QNapi::Number>(Q_FUNC_INFO);
1403 // NOTE - All windowEvents should be handled by qt but currently
1404 // some are not exposed as a part of public api.
1405 WindowEvent event;
1406 try {
1407 event.type = cbInfo.jsState().mapOhosEnumFromJs<WindowEventType>(eventType);
1408 } catch (const Napi::Error &err) {
1409 qOhosPrintfError(
1410 "Error converting WindowEventType to known value: %s. Event will be ignored.", err.what());
1411 return;
1412 }
1413
1414 if (isWindowClosing() && event.type != WindowEventType::WINDOW_DESTROYED) {
1415 qOhosPrintfError(
1416 "Received WindowEvent for window when it's closing. WindowEventType: %d",
1417 event.type);
1418 return;
1419 }
1420
1421 onWindowEvent(cbInfo.jsState(), event);
1422}
1423
1424void QOhosWindowProxy::JsScopeData::handleWindowStatusCallback(const QtOhos::CallbackInfo &cbInfo)
1425{
1426 auto windowStatusType = cbInfo.getFirstArg<QNapi::Number>(Q_FUNC_INFO);
1427 if (windowCallbackReceiver != nullptr) {
1428 windowCallbackReceiver->onWindowStatusChange(
1429 WindowStatus {
1430 .type = cbInfo.jsState().mapOhosEnumFromJs<WindowStatusType>(windowStatusType),
1431 });
1432 }
1433}
1434
1435void QOhosWindowProxy::JsScopeData::handleWindowVisibilityCallback(const QtOhos::CallbackInfo &cbInfo)
1436{
1437 auto windowVisibility = cbInfo.getFirstArg<QNapi::Boolean>(Q_FUNC_INFO);
1438 if (windowCallbackReceiver != nullptr)
1439 windowCallbackReceiver->onWindowVisibilityChange(windowVisibility);
1440}
1441
1442void QOhosWindowProxy::JsScopeData::handleWindowTouchOutsideCallback(const QtOhos::CallbackInfo &)
1443{
1444 if (windowCallbackReceiver != nullptr)
1445 windowCallbackReceiver->onTouchOutside();
1446}
1447
1448void QOhosWindowProxy::JsScopeData::handleAvoidAreaChangeCallback(const QtOhos::CallbackInfo &cbInfo)
1449{
1450 if (windowCallbackReceiver != nullptr) {
1451 auto callbackArg = cbInfo.getFirstArg<QNapi::Object>(Q_FUNC_INFO);
1452 windowCallbackReceiver->onAvoidAreaChange(
1453 cbInfo.jsState().mapOhosEnumFromJs<AvoidAreaType>(callbackArg.get<QNapi::Number>("type")),
1454 mapAvoidAreaFromJs(callbackArg.get<QNapi::Object>("area")));
1455 }
1456}
1457
1458void QOhosWindowProxy::JsScopeData::handleWindowRectChangeCallback(const QtOhos::CallbackInfo &cbInfo)
1459{
1460 auto rectChangeOptionsObjectArg = cbInfo.getFirstArg<QNapi::Object>(Q_FUNC_INFO);
1461 auto rectChangeOptions = RectChangeOptions {
1462 .rect = ohosWindowRectToQRect(rectChangeOptionsObjectArg.get<QNapi::Object>("rect")),
1463 .reason = cbInfo.jsState().mapOhosEnumFromJs<RectChangeReason>(rectChangeOptionsObjectArg.get<QNapi::Number>("reason")),
1464 };
1465
1466 if (windowCallbackReceiver != nullptr)
1467 windowCallbackReceiver->onWindowRectChange(rectChangeOptions);
1468}
1469
1470void QOhosWindowProxy::JsScopeData::handleWindowDisplayIdChangeCallback(const QtOhos::CallbackInfo &cbInfo)
1471{
1472 auto displayIdNumber = cbInfo.getFirstArg<QNapi::Number>(Q_FUNC_INFO);
1473 auto displayId = QOhosDisplayInfo::JsDisplayId(displayIdNumber);
1474
1475 if (windowCallbackReceiver != nullptr)
1476 windowCallbackReceiver->onWindowDisplayIdChange(displayId);
1477}
1478
1479void QOhosWindowProxy::JsScopeData::onWindowEvent(QtOhos::JsState &, const WindowEvent &windowEvent)
1480{
1481 if (windowEvent.type == WindowEventType::WINDOW_DESTROYED) {
1482 QtOhos::JsWindowsTracker::tagWindowAsClosing(jsWindowRef->jsObject(), "WINDOW_DESTROYED");
1483 windowDestroyedFromSystem = true;
1484 }
1485
1486 if (windowCallbackReceiver != nullptr)
1487 windowCallbackReceiver->onWindowEvent(windowEvent);
1488}
1489
1490bool QOhosWindowProxy::JsScopeData::isWindowClosing() const
1491{
1492 return QtOhos::JsWindowsTracker::isWindowClosing(jsWindowRef->jsObject()) || qAbilityPeer->isTerminating();
1493}
1494
1495void QOhosWindowProxy::JsScopeData::onMouseEventFromArkUi(const QArkUi::MouseEvent &event)
1496{
1497 if (nonClientAreaMouseEventConsumer == nullptr)
1498 return;
1499
1500 auto optAction = tryMapMouseEventActionToNonClientAreaEventType(event.action);
1501 if (!optAction.hasValue())
1502 return;
1503
1504 auto optWindowProperties = QArkUi::tryGetWindowProperties(event.jsWindowId);
1505 if (!optWindowProperties.hasValue()) {
1506 qOhosPrintfError(
1507 "%s: Failed to retrieve window properties for js window: %f. Ignoring event.",
1508 Q_FUNC_INFO, event.jsWindowId.value());
1509 return;
1510 }
1511
1512 const auto &windowProperties = optWindowProperties.value();
1513 if (!isPointInNonClientArea(event.displayPosition, windowProperties))
1514 return;
1515
1516 auto windowOrigin = windowProperties.windowRect.topLeft() + windowProperties.drawableRect.topLeft();
1517 NonClientAreaMouseEvent nonClientAreaMouseEvent = {
1518 .timestamp = std::chrono::duration_cast<std::chrono::milliseconds>(event.actionTime),
1519 .action = optAction.value(),
1520 .button = tryMapMouseEventButtonToQt(event.button).valueOr(Qt::NoButton),
1521 .displayPosition = event.displayPosition,
1522 .localPosition = event.displayPosition - windowOrigin,
1523 };
1524
1525 nonClientAreaMouseEventConsumer(nonClientAreaMouseEvent);
1526}
1527
1528void QOhosWindowProxy::JsScopeData::onTouchEventFromArkUi(const QArkUi::TouchEvent &event)
1529{
1530 if (nonClientAreaTouchEventConsumer == nullptr)
1531 return;
1532
1533 auto optState = tryMapTouchEventActionToNonClientAreaEventState(event.action);
1534 if (!optState.hasValue())
1535 return;
1536
1537 auto optWindowProperties = QArkUi::tryGetWindowProperties(event.jsWindowId);
1538 if (!optWindowProperties.hasValue()) {
1539 qOhosPrintfError(
1540 "%s: Failed to retrieve window properties for js window: %f. Ignoring event.",
1541 Q_FUNC_INFO, event.jsWindowId.value());
1542 return;
1543 }
1544
1545 if (!isPointInNonClientArea(event.displayPosition, optWindowProperties.value()))
1546 return;
1547
1548 NonClientAreaTouchEvent nonClientAreaTouchEvent = {
1549 .id = event.fingerId,
1550 .timestamp = std::chrono::duration_cast<std::chrono::milliseconds>(event.actionTime),
1551 .state = optState.value(),
1552 .displayPosition = event.displayPosition,
1553 };
1554
1555 nonClientAreaTouchEventConsumer(nonClientAreaTouchEvent);
1556}
1557
1558QPixmap QOhosWindowProxy::snapshot() const
1559{
1560 return QtOhos::evalInJsThreadWithConsumer<QPixmap>(
1561 [&](QtOhos::JsState &, QOhosConsumer<QPixmap> resultConsumer) {
1562 m_jsScopeData->jsWindowRef->call<QNapi::Promise>("snapshot")
1563 .withContext(std::move(resultConsumer))
1564 .onThenWithContext(
1565 [](const QtOhos::CallbackInfo &cbInfo, auto &resultConsumer) {
1566 auto napiPixmap = cbInfo.getFirstArg<QNapi::Object>(Q_FUNC_INFO);
1567
1568 ::OH_PixelmapNative *pixelMapNativePtr;
1569 QArkUi::callArkUiOrFailOnErrorResult(
1570 Q_OHOS_NAMED_FUNC(::OH_PixelmapNative_ConvertPixelmapNativeFromNapi),
1571 cbInfo.Env(), napiPixmap, &pixelMapNativePtr);
1572 auto pixelMap = wrapNativePixelMapPtr(pixelMapNativePtr);
1573
1574 resultConsumer(
1575 QPixmap::fromImage(createQImageFromNativePixelMap(pixelMap.get())));
1576 })
1577 .onCatchWithContext(
1578 [](const QtOhos::CallbackInfo &cbInfo, auto &resultConsumer) {
1579 QtOhos::logJsCallbackError(cbInfo, "Got error from snapshot()");
1580 resultConsumer(QPixmap());
1581 });
1582 });
1583}
1584
1585bool QOhosWindowProxy::startMoving()
1586{
1588 [&](QtOhos::JsState &, std::function<void()> continueFunc) {
1589 if (m_jsScopeData->isWindowClosing()) {
1590 continueFunc();
1591 return;
1592 }
1593
1594 m_jsScopeData->jsWindowRef->call<QNapi::Promise>("startMoving")
1595 .onCatch(QtOhos::makeErrorLoggingJsCallback("startMoving()"))
1596 .onFinally(std::move(continueFunc));
1597 });
1598
1599 return true;
1600}
1601
1602QOhosOptional<bool> QOhosWindowProxy::isFocused() const
1603{
1604 return QtOhos::evalInJsThread(
1605 [&](QtOhos::JsState &) {
1606 if (m_jsScopeData->isWindowClosing())
1607 return QOhosOptional<bool>();
1608
1609 bool focused = m_jsScopeData->jsWindowRef->call<QNapi::Boolean>("isFocused");
1610 return makeQOhosOptional(focused);
1611 });
1612}
1613
1614std::vector<QArkUi::JsWindowId> QOhosWindowProxy::queryWindowIdsByCoordinate(
1615 QOhosDisplayInfo::JsDisplayId displayId, const QPoint &queryLocation, std::uint32_t queryLimit)
1616{
1617 return QtOhos::evalInJsThreadWithConsumer<std::vector<QArkUi::JsWindowId>>(
1618 [&](QtOhos::JsState &jsState, auto resultConsumer) {
1619 jsState.eval<QNapi::Promise>("@ohos.window.getWindowsByCoordinate(*)", {
1620 displayId.value(),
1621 queryLimit,
1622 queryLocation.x(),
1623 queryLocation.y()
1624 })
1625 .withContext(std::move(resultConsumer))
1626 .onThenWithContext([](const QtOhos::CallbackInfo &cbInfo, auto &resultConsumer) {
1627 auto windowsArray = cbInfo.getFirstArg<QNapi::Array>(Q_FUNC_INFO);
1628 resultConsumer(
1629 QNapi::getArrayElements<std::vector<QArkUi::JsWindowId>, QNapi::Object>(
1630 windowsArray,
1631 [&](QNapi::Object jsWindow) {
1632 return getWindowPropertiesFromJsWindow(jsWindow).id;
1633 }));
1634 })
1635 .onCatchWithContext([](const QtOhos::CallbackInfo &cbInfo, auto &resultConsumer) {
1636 QtOhos::logJsCallbackError(
1637 cbInfo, "got error from @ohos.window.getWindowsByCoordinate()");
1638 resultConsumer({});
1639 });
1640 });
1641}
1642
1643std::vector<QArkUi::JsWindowId> QOhosWindowProxy::queryQtManagedWindowIdsByPredicate(
1644 const std::function<bool(QtOhos::JsState &, const QArkUi::JsWindowRef &)> &predicate)
1645{
1646 return QtOhos::evalInJsThread([&](QtOhos::JsState &jsState) {
1647 auto &jsWindowRegistry = jsState.getAttachedObjectWithLazyCreate<QOhosJsWindowRegistry>();
1648 return jsWindowRegistry.queryByPredicate(jsState, predicate);
1649 });
1650}
1651
1652void QOhosWindowProxy::moveWindowToGlobal(
1653 const QPoint &position, const MoveConfiguration &moveConfiguration)
1654{
1656 [&](QtOhos::JsState &jsState, std::function<void()> continueFunc) {
1657 if (m_jsScopeData->isWindowClosing()) {
1658 continueFunc();
1659 return;
1660 }
1661
1662 auto moveConfigurationObject = toNapiObject(jsState.env(), moveConfiguration);
1663 auto moveConfigurationObjectStr = QNapi::toJsonString(moveConfigurationObject);
1664 qOhosPrintfDebug(
1665 "%s: %d,%d,%s",
1666 Q_FUNC_INFO, position.x(), position.y(),
1667 moveConfigurationObjectStr.c_str());
1668
1669 m_jsScopeData->jsWindowRef->call<QNapi::Promise>(
1670 "moveWindowToGlobal", {position.x(), position.y(), moveConfigurationObject})
1671 .onFinally(std::move(continueFunc));
1672 });
1673}
1674
1675QOhosOptional<QOhosDisplayInfo::JsDisplayId> QOhosWindowProxy::tryGetMainWindowJsDisplayId() const
1676{
1677 return qtIsMainWindow()
1678 ? getWindowProperties().displayId
1679 : QtOhos::evalInJsThread(
1680 [&](QtOhos::JsState &) {
1681 auto qUiAbilityPeer
1682 = QtOhos::QUiAbilityPeer::tryCastFromQAbilityPeerOrNull(m_jsScopeData->qAbilityPeer);
1683 return qUiAbilityPeer
1684 ? getWindowPropertiesFromJsWindow(qUiAbilityPeer->window()).displayId
1685 : makeEmptyQOhosOptional();
1686 });
1687}
1688
1689void QOhosWindowProxy::shiftAppWindowFocus(QOhosWindowProxy &targetProxy)
1690{
1692 [&](QtOhos::JsState &jsState, std::function<void()> continueFunc) {
1693 if (m_jsScopeData->isWindowClosing() || targetProxy.m_jsScopeData->isWindowClosing()) {
1694 continueFunc();
1695 return;
1696 }
1697
1698 auto srcWindowId = getWindowPropertiesFromJsWindow(m_jsScopeData->jsWindowRef->jsObject()).id;
1699 auto targetWindowId = getWindowPropertiesFromJsWindow(targetProxy.m_jsScopeData->jsWindowRef->jsObject()).id;
1700 jsState.eval<QNapi::Promise> (
1701 "@ohos.window.shiftAppWindowFocus(*)", {srcWindowId.value(), targetWindowId.value()})
1702 .onCatch(QtOhos::makeErrorLoggingJsCallback("@ohos.window.shiftAppWindowFocus()"))
1703 .onFinally(std::move(continueFunc));
1704 });
1705}
1706
1707std::shared_ptr<QOhosWindowProxy> QOhosWindowProxy::create(QtOhos::JsState &jsState, QOhosWindowProxyData data)
1708{
1709 auto window = std::shared_ptr<QOhosWindowProxy>(new QOhosWindowProxy(std::move(data)));
1710 auto &jsWindowRegistry = jsState.getAttachedObjectWithLazyCreate<QOhosJsWindowRegistry>();
1711 return QtOhos::makeSharedPtrWithAttachedExtraData(
1712 window,
1713 jsWindowRegistry.registerJsWindow(window->m_jsScopeData->jsWindowRef));
1714}
1715
1716QT_END_NAMESPACE
std::enable_if_t< qohosplugincore_h_detail::isQOhosOptional< QOhosInvokeResult< Func, T > >, QOhosInvokeResult< Func, T > > andThen(Func &&func) const
void setWindowRectAutoSave(bool enabed)
void setWindowMask(const WindowMask &windowMask, const QOhosOptional< QSize > &ohosMaskSizeOverride={})
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)
QArkUi::WindowProperties getWindowProperties() const
void setWindowPrivacyMode(bool privacyMode)
AvoidArea getWindowAvoidArea(AvoidAreaType type) const
void setWindowCornerRadius(double radius)
QOhosWindowProxyExistingMainWindowCreateInfo ExistingMainWindowCreateInfo
void setSupportedWindowModes(const std::set< SupportWindowMode > &supportedWindowModes)
std::shared_ptr< QOhosWindowProxy > createSubWindow(const SubWindowCreateInfo &createInfo)
QPixmap snapshot() const
static std::shared_ptr< QOhosWindowProxy > createForExistingMainWindow(const ExistingMainWindowCreateInfo &createInfo)
void setWindowTouchable(bool touchable)
WindowProxyType windowProxyType() const
void setTitle(const QString &title)
void setFollowParentMultiScreenPolicy(bool enabled)
void setWindowTopmost(bool topmost)
std::shared_ptr< QXComponentNode > nodeXComponent() const
void setWindowCallbackReceiver(std::unique_ptr< WindowCallbacks > receiver)
void setSubWindowCloseHandler(std::function< void()> handler, bool handlerReturnValue)
QOhosOptional< 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)
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)
WindowLimits getWindowLimits() const
std::string qAbilityInstanceId() const
void maximize(MaximizePresentation maximizePresentation)
void setNonClientAreaTouchWindowCallbackReceiver(QObject *contextObject, QOhosConsumer< std::vector< NonClientAreaTouchEvent > > touchEventBatchConsumer)
QOhosOptional< QOhosDisplayInfo::JsDisplayId > tryGetMainWindowJsDisplayId() const
static std::shared_ptr< QOhosWindowProxy > createMainWindow(const MainWindowCreateInfo &createInfo)
JsState & jsState() const
static std::shared_ptr< QUiAbilityPeer > tryCastFromQAbilityPeerOrNull(std::shared_ptr< QAbilityPeer > qAbilityPeer)
QOhosOptional< WindowProperties > tryGetWindowProperties(JsWindowId jsWindowId)
Definition window.cpp:27
bool isWindowPcModeEnabled()
Combined button and popup list for selecting options.
QOhosOptional< double > getOptionalNumberPropAsOptionalDouble(const QNapi::Object &object, const std::string &propertyName)
QRect ohosWindowRectToQRect(const QNapi::Object &ohosWindowRect)
bool isPointInNonClientArea(const QPoint &point, const QArkUi::WindowProperties &windowProperties)
QOhosPointerStyle convertToOhosCursor(Qt::CursorShape shape)
QOhosOptional< QEvent::Type > tryMapMouseEventActionToNonClientAreaEventType(::Input_MouseEventAction action)
QOhosWindowProxy::AvoidArea mapAvoidAreaFromJs(const QNapi::Object &avoidAreaObject)
std::string mapEnumsToLogString(const EnumsContainer &enums)
QOhosOptional< QEventPoint::State > tryMapTouchEventActionToNonClientAreaEventState(::Input_TouchEventAction action)
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)
QOhosOptional< Qt::MouseButton > tryMapMouseEventButtonToQt(::Input_MouseEventButton button)
std::string const char * mapBoolToTrueFalseStr(bool value)
void runInJsThreadAndWait(const std::function< void(JsState &)> &task)
void invokeInJsThreadAndWaitForContinue(std::function< void(JsState &, std::function< void()>)> &&task)
QOhosOptional< void > makeEmptyQOhosOptional()
QOhosPointerStyle
QXComponent< QXComponentType::Node > QXComponentNode
Definition qxcomponent.h:44
std::int32_t fingerId
Definition input.h:48