4#include <qarkui/qqtembeddedwindownode.h>
6#include <arkui/native_node.h>
7#include <arkui/native_type.h>
8#include <qarkui/qarkuiutils.h>
9#include <qohosjsmain.h>
10#include <qohosutils.h>
17class XComponentCallbackDispatcher
20 static XComponentCallbackDispatcher &instance();
22 XComponentCallbackDispatcher(
const XComponentCallbackDispatcher &) =
delete;
23 XComponentCallbackDispatcher(XComponentCallbackDispatcher &&) =
delete;
24 XComponentCallbackDispatcher &operator=(
const XComponentCallbackDispatcher &) =
delete;
25 XComponentCallbackDispatcher &operator=(XComponentCallbackDispatcher &&) =
delete;
27 std::shared_ptr<
void> registerCallbackReceiver(
28 ::OH_NativeXComponent *xComponent,
32 XComponentCallbackDispatcher() =
default;
34 static void handleSurfaceCreated(::OH_NativeXComponent *xComponent,
void *window);
35 static void handleSurfaceChanged(::OH_NativeXComponent *xComponent,
void *window);
36 static void handleSurfaceDestroyed(::OH_NativeXComponent *xComponent,
void *window);
37 static void handleSurfaceTouchEvent(::OH_NativeXComponent *xComponent,
void *window);
38 static void handleMouseEvent(::OH_NativeXComponent *xComponent,
void *window);
39 static void handleHoverEvent(::OH_NativeXComponent *xComponent,
bool hover);
40 static void handleKeyEvent(::OH_NativeXComponent *xComponent,
void *window);
43 std::map<::OH_NativeXComponent *, QXComponentCallbackReceiver *> m_receivers;
46XComponentCallbackDispatcher &XComponentCallbackDispatcher::instance()
48 static XComponentCallbackDispatcher dispatcher;
52std::shared_ptr<
void> XComponentCallbackDispatcher::registerCallbackReceiver(
55 qOhosPrintfDebug(
"Registering callbacks for xcomponent %p", xComponent);
57 if (m_receivers.find(xComponent) != m_receivers.end()) {
58 qOhosPrintfError(
"XComponent %p callbacks were already registered", xComponent);
59 throw std::runtime_error(
"Duplicate xcomponent");
62 m_receivers[xComponent] = receiver;
64 static ::OH_NativeXComponent_Callback callbacks = {
65 .OnSurfaceCreated = &XComponentCallbackDispatcher::handleSurfaceCreated,
66 .OnSurfaceChanged = &XComponentCallbackDispatcher::handleSurfaceChanged,
67 .OnSurfaceDestroyed = &XComponentCallbackDispatcher::handleSurfaceDestroyed,
68 .DispatchTouchEvent = &XComponentCallbackDispatcher::handleSurfaceTouchEvent,
71 static ::OH_NativeXComponent_MouseEvent_Callback mouseEventCallbacks = {
72 .DispatchMouseEvent = &XComponentCallbackDispatcher::handleMouseEvent,
73 .DispatchHoverEvent = &XComponentCallbackDispatcher::handleHoverEvent,
76 auto lifecycleAndTouchCallbackRegisterStatus = ::OH_NativeXComponent_RegisterCallback(
77 xComponent, &callbacks);
78 if (lifecycleAndTouchCallbackRegisterStatus != ::OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
79 qOhosReportFatalErrorAndAbort(
80 "OH_NativeXComponent_RegisterCallback failed with error: %d",
81 lifecycleAndTouchCallbackRegisterStatus);
85 auto mouseRegisterStatus = ::OH_NativeXComponent_RegisterMouseEventCallback(
87 &mouseEventCallbacks);
88 if (mouseRegisterStatus != ::OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
89 qOhosReportFatalErrorAndAbort(
90 "OH_NativeXComponent_RegisterMouseEventCallback failed with error: %d",
96 auto keyRegisterStatus = ::OH_NativeXComponent_RegisterKeyEventCallback(
97 xComponent, &XComponentCallbackDispatcher::handleKeyEvent);
98 if (keyRegisterStatus != ::OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
99 qOhosReportFatalErrorAndAbort(
100 "OH_NativeXComponent_RegisterKeyEventCallback failed with error: %d",
105 return QtOhos::makeDestroyNotifier([
this, xComponent](){
106 qOhosPrintfDebug(
"Unregistering callbacks for xcomponent %p", xComponent);
107 m_receivers.erase(xComponent);
108 ::OH_NativeXComponent_RegisterCallback(xComponent,
nullptr);
109 ::OH_NativeXComponent_RegisterMouseEventCallback(xComponent,
nullptr);
110 ::OH_NativeXComponent_RegisterKeyEventCallback(xComponent,
nullptr);
116 auto &dispatcher = XComponentCallbackDispatcher::instance();
117 auto it = dispatcher.m_receivers.find(xComponent);
118 if (it == dispatcher.m_receivers.end()) {
119 qOhosPrintfDebug(
"Error: xComponent %p does not have any assigned receiver", xComponent);
125void XComponentCallbackDispatcher::handleSurfaceTouchEvent(::OH_NativeXComponent *xComponent,
void *window)
127 auto *receiver = findCallbackReceiverOrNull(xComponent);
128 if (receiver !=
nullptr) {
129 receiver->onInputEvent(
131 reinterpret_cast<::OHNativeWindow *>(window));
135void XComponentCallbackDispatcher::handleHoverEvent(::OH_NativeXComponent *xComponent,
bool isHover)
137 auto *receiver = findCallbackReceiverOrNull(xComponent);
138 if (receiver !=
nullptr)
139 receiver->onHoverEvent(isHover);
143void XComponentCallbackDispatcher::handleKeyEvent(::OH_NativeXComponent *xComponent,
void *window)
145 auto *receiver = findCallbackReceiverOrNull(xComponent);
146 if (receiver !=
nullptr) {
147 receiver->onInputEvent(
149 reinterpret_cast<::OHNativeWindow *>(window));
153void XComponentCallbackDispatcher::handleMouseEvent(::OH_NativeXComponent *xComponent,
void *window)
155 auto *receiver = findCallbackReceiverOrNull(xComponent);
156 if (receiver !=
nullptr) {
157 receiver->onInputEvent(
159 reinterpret_cast<::OHNativeWindow *>(window));
163void XComponentCallbackDispatcher::handleSurfaceCreated(::OH_NativeXComponent *xComponent,
void *window)
165 qOhosPrintfDebug(
"%s: xc: %p window: %p", Q_FUNC_INFO, xComponent, window);
166 auto *receiver = findCallbackReceiverOrNull(xComponent);
167 if (receiver !=
nullptr) {
168 receiver->onSurfaceEvent(
170 reinterpret_cast<::OHNativeWindow*>(window));
174void XComponentCallbackDispatcher::handleSurfaceChanged(::OH_NativeXComponent *xComponent,
void *window)
176 qOhosPrintfDebug(
"%s: xc: %p window: %p", Q_FUNC_INFO, xComponent, window);
177 auto *receiver = findCallbackReceiverOrNull(xComponent);
178 if (receiver !=
nullptr) {
179 receiver->onSurfaceEvent(
181 reinterpret_cast<::OHNativeWindow*>(window));
185void XComponentCallbackDispatcher::handleSurfaceDestroyed(::OH_NativeXComponent *xComponent,
void *window)
187 qOhosPrintfDebug(
"%s: xc: %p window: %p", Q_FUNC_INFO, xComponent, window);
188 auto *receiver = findCallbackReceiverOrNull(xComponent);
189 if (receiver !=
nullptr) {
190 receiver->onSurfaceEvent(
192 reinterpret_cast<::OHNativeWindow*>(window));
202 constexpr std::uint32_t transparentArgb8888 = 0;
204 auto stackNode = Node::createOrFail(::ARKUI_NODE_STACK);
205 stackNode->setAttributeOrFail(::NODE_STACK_ALIGN_CONTENT, ::ARKUI_ALIGNMENT_TOP_START);
206 stackNode->setAttributeOrFail(::NODE_Z_INDEX, createInfo
.zIndex);
207 stackNode->setAttributeOrFail(::NODE_BACKGROUND_COLOR, transparentArgb8888);
208 stackNode->setAttributeOrFail(
210 std::make_tuple(::ARKUI_BLEND_MODE_SRC_OVER, ::BLEND_APPLY_TYPE_FAST));
211 stackNode->setLengthMetricUnitOrFail(::ARKUI_LENGTH_METRIC_UNIT_PX);
213 ::ArkUI_NodeAttributeType widthAttribute;
214 ::ArkUI_NodeAttributeType heightAttribute;
217 case SizePolicy::Points:
218 widthAttribute = ::NODE_WIDTH;
219 heightAttribute = ::NODE_HEIGHT;
221 case SizePolicy::PercentNormalized:
222 widthAttribute = ::NODE_WIDTH_PERCENT;
223 heightAttribute = ::NODE_HEIGHT_PERCENT;
227 stackNode->setAttributeOrFail(
229 static_cast<
float>(createInfo.size.width()));
230 stackNode->setAttributeOrFail(
232 static_cast<
float>(createInfo.size.height()));
233 stackNode->setAttributeOrFail(
235 toFloatArray(createInfo.offset));
237 auto xComponentNode = Node::createOrFail(::ARKUI_NODE_XCOMPONENT);
238 xComponentNode->setAttributeOrFail(::NODE_XCOMPONENT_TYPE, createInfo.xComponentType);
239 xComponentNode->setAttributeOrFail(::NODE_FOCUS_ON_TOUCH, createInfo
.focusOnTouch);
240 xComponentNode->setAttributeOrFail(
241 ::NODE_BACKGROUND_COLOR,
242 createInfo.backgroundColor.has_value()
243 ? createInfo.backgroundColor.value().rgba()
244 : transparentArgb8888);
245 xComponentNode->setAttributeOrFail(
246 ::NODE_XCOMPONENT_ID,
247 createInfo.xComponentId.stringId());
248 xComponentNode->setAttributeOrFail(
250 std::make_tuple(::ARKUI_BLEND_MODE_SRC_OVER, ::BLEND_APPLY_TYPE_FAST));
251 xComponentNode->setAttributeOrFail(::NODE_FOCUSABLE, createInfo
.focusable);
252 xComponentNode->setAttributeOrFail(::NODE_RENDER_FIT, createInfo.renderFit);
253 xComponentNode->setAttributeOrFail(::NODE_Z_INDEX, createInfo
.zIndex);
254 xComponentNode->setLengthMetricUnitOrFail(::ARKUI_LENGTH_METRIC_UNIT_PX);
256 stackNode->addChildOrFail(*xComponentNode);
259 .nodeType = ::ArkUI_NodeType::ARKUI_NODE_XCOMPONENT,
260 .content = xComponentNode->handle(),
261 .stack = stackNode->handle(),
263 .nodePrivate =
nullptr,
266 auto node =
std::shared_ptr<QQtEmbeddedWindowNode>(
267 new QQtEmbeddedWindowNode(
std::move(stackNode),
std::move(xComponentNode),
std::move(windowId)));
268 if (createInfo.optParent.has_value())
269 node->setParentOrReparent(createInfo.optParent.value());
271 node->setNodeVisibility(
false);
278 auto *xComponent = ::OH_NativeXComponent_GetNativeXComponent(contentNode().handle());
279 if (xComponent ==
nullptr)
280 qOhosReportFatalErrorAndAbort(
"::OH_NativeXComponent_GetNativeXComponent failed");
285 std::unique_ptr<QXComponentCallbackReceiver> callbackReceiver)
287 m_callbackReceiver = std::move(callbackReceiver);
292 ::OHNativeWindow *nativeWindow)
294 qOhosPrintfDebug(
"%s: node: %p eventType: %d surface: %p", Q_FUNC_INFO,
this, eventType, nativeWindow);
296 case SurfaceEventType::SurfaceCreated:
297 case SurfaceEventType::SurfaceChanged:
298 m_nativeWindow = nativeWindow;
300 case SurfaceEventType::SurfaceDestroyed:
301 m_nativeWindow =
nullptr;
305 if (m_callbackReceiver)
306 m_callbackReceiver->onSurfaceEvent(eventType, nativeWindow);
311 ::OHNativeWindow *nativeWindow)
313 if (m_callbackReceiver)
314 m_callbackReceiver->onInputEvent(inputEventType, nativeWindow);
319 if (m_callbackReceiver)
320 m_callbackReceiver->onHoverEvent(isHover);
323QQtEmbeddedWindowNode::QQtEmbeddedWindowNode(
324 std::unique_ptr<Node> stackNode,
325 std::unique_ptr<Node> xComponentNode,
326 std::unique_ptr<QtOhos::WindowIdStruct> windowId)
328 , m_xComponentCallbackDispatcherToken(
329 XComponentCallbackDispatcher::instance().registerCallbackReceiver(
330 renderXComponent().handle(),
this))
338 m_optAreaChangedReceiver = std::move(areaChangeReceiver);
340 stackNode().setEventHandler(
341 ::ArkUI_NodeEventType::NODE_EVENT_ON_AREA_CHANGE,
342 [
this](::ArkUI_NodeEvent *) {
343 m_optAreaChangedReceiver(nodeAreaInfo());
349 m_optFocusedChangedReceiver = std::move(focusChangedReceiver);
351 stackNode().setEventHandler(
352 ::ArkUI_NodeEventType::NODE_ON_FOCUS,
353 [
this](::ArkUI_NodeEvent *) {
354 m_optFocusedChangedReceiver(
true);
357 stackNode().setEventHandler(
358 ::ArkUI_NodeEventType::NODE_ON_BLUR,
359 [
this](::ArkUI_NodeEvent *) {
360 m_optFocusedChangedReceiver(
false);
366 m_optVisibilityChangedReceiver = std::move(visibilityChangedReceiver);
368 stackNode().setEventHandler(
369 ::ArkUI_NodeEventType::NODE_EVENT_ON_APPEAR,
370 [
this](::ArkUI_NodeEvent *) {
371 m_optVisibilityChangedReceiver(
true);
374 stackNode().setEventHandler(
375 ::ArkUI_NodeEventType::NODE_EVENT_ON_DISAPPEAR,
376 [
this](::ArkUI_NodeEvent *) {
377 m_optVisibilityChangedReceiver(
false);
382 QOhosConsumer<
const ::ArkUI_UIInputEvent *> touchInterceptReceiver)
384 m_optTouchInterceptReceiver = std::move(touchInterceptReceiver);
385 stackNode().setEventHandler(
386 ::ArkUI_NodeEventType::NODE_ON_TOUCH_INTERCEPT,
387 [
this](::ArkUI_NodeEvent *nodeEvent) {
388 auto *uiInputEvent = ::OH_ArkUI_NodeEvent_GetInputEvent(nodeEvent);
389 if (uiInputEvent ==
nullptr)
391 m_optTouchInterceptReceiver(uiInputEvent);
397 ::ArkUI_IntOffset screenPositionPx;
398 callArkUiOrFailOnErrorResult(
399 Q_OHOS_NAMED_FUNC(::OH_ArkUI_NodeUtils_GetLayoutPositionInScreen),
400 stackNode().handle(), &screenPositionPx);
402 ::ArkUI_IntSize screenSizePx;
403 callArkUiOrFailOnErrorResult(
404 Q_OHOS_NAMED_FUNC(::OH_ArkUI_NodeUtils_GetLayoutSize),
405 stackNode().handle(), &screenSizePx);
408 QPoint(screenPositionPx.x, screenPositionPx.y),
409 QSize(screenSizePx.width, screenSizePx.height));
414 return QArkUi::Node::tryfindChild(
415 stackNode().handle(),
416 [&](::ArkUI_NodeHandle nodeHandle) {
417 return !QArkUi::Node::isQtManagedNode(nodeHandle);
423 return NodeAreaInfo {
424 .screenGeometryPixels = nodeScreenGeometryPixels(),
425 .windowRelativeOffsetPixels = windowRelativeOffsetPixels(),
426 .parentRelativeOffsetPixels = parentRelativeOffsetPixels(),
427 .globalRelativeOffsetPixels = globalRelativeOffsetPixels(),
433 ::ArkUI_IntOffset windowPositionPx;
434 callArkUiOrFailOnErrorResult(
435 Q_OHOS_NAMED_FUNC(::OH_ArkUI_NodeUtils_GetLayoutPositionInWindow),
436 stackNode().handle(), &windowPositionPx);
437 return QPoint(windowPositionPx.x, windowPositionPx.y);
442 ::ArkUI_IntOffset parentPositionPx;
443 callArkUiOrFailOnErrorResult(
444 Q_OHOS_NAMED_FUNC(::OH_ArkUI_NodeUtils_GetLayoutPosition),
445 stackNode().handle(), &parentPositionPx);
446 return QPoint(parentPositionPx.x, parentPositionPx.y);
451 return QArkUi::Node::nodeGlobalPosition(stackNode().handle());
void setTouchInterceptReceiver(QOhosConsumer< const ::ArkUI_UIInputEvent * > touchInterceptReceiver)
void onHoverEvent(bool isHover) override
QPoint parentRelativeOffsetPixels() const
QPoint globalRelativeOffsetPixels() const
void setFocusedChangeReceiver(QOhosConsumer< bool > focus)
bool hasNonQtManagedChildren() const
~QQtEmbeddedWindowNode() override
void onSurfaceEvent(SurfaceEventType surfaceEventType, ::OHNativeWindow *nativeWindow) override
NodeAreaInfo nodeAreaInfo() const
static std::shared_ptr< QQtEmbeddedWindowNode > createOrFail(const CreateInfo &createInfo)
QRect nodeScreenGeometryPixels() const
void onInputEvent(InputEventType inputEventType, ::OHNativeWindow *nativeWindow) override
QPoint windowRelativeOffsetPixels() const
void setCallbackReceiver(std::unique_ptr< QXComponentCallbackReceiver > callbackReceiver)
QXComponentRender renderXComponent() const
void setAreaChangeReceiver(QOhosConsumer< NodeAreaInfo > areaChangeReceiver)
void setVisibilityChangeReceiver(QOhosConsumer< bool > visibilityChangedReceiver)
virtual ~QXComponentCallbackReceiver()
Combined button and popup list for selecting options.
bool isNativeNodeApiMouseEventsEnabled()
bool isNativeNodeApiKeyEventsEnabled()
QXComponent< QXComponentType::Render > QXComponentRender