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.hasValue()
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);
255 stackNode->addChildOrFail(*xComponentNode);
258 .nodeType = ::ArkUI_NodeType::ARKUI_NODE_XCOMPONENT,
259 .content = xComponentNode->handle(),
260 .stack = stackNode->handle(),
262 .nodePrivate =
nullptr,
265 auto node =
std::shared_ptr<QQtEmbeddedWindowNode>(
266 new QQtEmbeddedWindowNode(
std::move(stackNode),
std::move(xComponentNode),
std::move(windowId)));
267 if (createInfo.optParent.hasValue())
268 node->setParentOrReparent(createInfo.optParent.value());
270 node->setNodeVisibility(
false);
277 auto *xComponent = ::OH_NativeXComponent_GetNativeXComponent(contentNode().handle());
278 if (xComponent ==
nullptr)
279 qOhosReportFatalErrorAndAbort(
"::OH_NativeXComponent_GetNativeXComponent failed");
284 std::unique_ptr<QXComponentCallbackReceiver> callbackReceiver)
286 m_callbackReceiver = std::move(callbackReceiver);
291 ::OHNativeWindow *nativeWindow)
293 qOhosPrintfDebug(
"%s: node: %p eventType: %d surface: %p", Q_FUNC_INFO,
this, eventType, nativeWindow);
295 case SurfaceEventType::SurfaceCreated:
296 case SurfaceEventType::SurfaceChanged:
297 m_nativeWindow = nativeWindow;
299 case SurfaceEventType::SurfaceDestroyed:
300 m_nativeWindow =
nullptr;
304 if (m_callbackReceiver)
305 m_callbackReceiver->onSurfaceEvent(eventType, nativeWindow);
310 ::OHNativeWindow *nativeWindow)
312 if (m_callbackReceiver)
313 m_callbackReceiver->onInputEvent(inputEventType, nativeWindow);
318 if (m_callbackReceiver)
319 m_callbackReceiver->onHoverEvent(isHover);
324 contentNode().setAttributeOrFail(
325 ::NODE_XCOMPONENT_SURFACE_SIZE,
326 std::array<std::uint32_t, 2>{width, height});
329QQtEmbeddedWindowNode::QQtEmbeddedWindowNode(
330 std::unique_ptr<Node> stackNode,
331 std::unique_ptr<Node> xComponentNode,
332 std::unique_ptr<QtOhos::WindowIdStruct> windowId)
334 , m_xComponentCallbackDispatcherToken(
335 XComponentCallbackDispatcher::instance().registerCallbackReceiver(
336 renderXComponent().handle(),
this))
344 m_optAreaChangedReceiver = std::move(areaChangeReceiver);
346 stackNode().setEventHandler(
347 ::ArkUI_NodeEventType::NODE_EVENT_ON_AREA_CHANGE,
348 [
this](::ArkUI_NodeEvent *) {
349 m_optAreaChangedReceiver(
351 .screenGeometryPixels = nodeScreenGeometryPixels(),
352 .windowRelativeOffsetPixels = windowRelativeOffsetPixels(),
353 .parentRelativeOffsetPixels = parentRelativeOffsetPixels(),
360 m_optFocusedChangedReceiver = std::move(focusChangedReceiver);
362 stackNode().setEventHandler(
363 ::ArkUI_NodeEventType::NODE_ON_FOCUS,
364 [
this](::ArkUI_NodeEvent *) {
365 m_optFocusedChangedReceiver(
true);
368 stackNode().setEventHandler(
369 ::ArkUI_NodeEventType::NODE_ON_BLUR,
370 [
this](::ArkUI_NodeEvent *) {
371 m_optFocusedChangedReceiver(
false);
377 m_optVisibilityChangedReceiver = std::move(visibilityChangedReceiver);
379 stackNode().setEventHandler(
380 ::ArkUI_NodeEventType::NODE_EVENT_ON_APPEAR,
381 [
this](::ArkUI_NodeEvent *) {
382 m_optVisibilityChangedReceiver(
true);
385 stackNode().setEventHandler(
386 ::ArkUI_NodeEventType::NODE_EVENT_ON_DISAPPEAR,
387 [
this](::ArkUI_NodeEvent *) {
388 m_optVisibilityChangedReceiver(
false);
393 QOhosConsumer<
const ::ArkUI_UIInputEvent *> touchInterceptReceiver)
395 m_optTouchInterceptReceiver = std::move(touchInterceptReceiver);
396 stackNode().setEventHandler(
397 ::ArkUI_NodeEventType::NODE_ON_TOUCH_INTERCEPT,
398 [
this](::ArkUI_NodeEvent *nodeEvent) {
399 auto *uiInputEvent = ::OH_ArkUI_NodeEvent_GetInputEvent(nodeEvent);
400 if (uiInputEvent ==
nullptr)
402 m_optTouchInterceptReceiver(uiInputEvent);
408 ::ArkUI_IntOffset screenPositionPx;
409 callArkUiOrFailOnErrorResult(
410 Q_OHOS_NAMED_FUNC(::OH_ArkUI_NodeUtils_GetLayoutPositionInScreen),
411 stackNode().handle(), &screenPositionPx);
413 ::ArkUI_IntSize screenSizePx;
414 callArkUiOrFailOnErrorResult(
415 Q_OHOS_NAMED_FUNC(::OH_ArkUI_NodeUtils_GetLayoutSize),
416 stackNode().handle(), &screenSizePx);
419 QPoint(screenPositionPx.x, screenPositionPx.y),
420 QSize(screenSizePx.width, screenSizePx.height));
425 return QArkUi::Node::tryfindChild(
426 stackNode().handle(),
427 [&](::ArkUI_NodeHandle nodeHandle) {
428 return !QArkUi::Node::isQtManagedNode(nodeHandle);
434 ::ArkUI_IntOffset windowPositionPx;
435 callArkUiOrFailOnErrorResult(
436 Q_OHOS_NAMED_FUNC(::OH_ArkUI_NodeUtils_GetLayoutPositionInWindow),
437 stackNode().handle(), &windowPositionPx);
438 return QPoint(windowPositionPx.x, windowPositionPx.y);
443 ::ArkUI_IntOffset parentPositionPx;
444 callArkUiOrFailOnErrorResult(
445 Q_OHOS_NAMED_FUNC(::OH_ArkUI_NodeUtils_GetLayoutPosition),
446 stackNode().handle(), &parentPositionPx);
447 return QPoint(parentPositionPx.x, parentPositionPx.y);
void setTouchInterceptReceiver(QOhosConsumer< const ::ArkUI_UIInputEvent * > touchInterceptReceiver)
void onHoverEvent(bool isHover) override
QPoint parentRelativeOffsetPixels() const
void setFocusedChangeReceiver(QOhosConsumer< bool > focus)
void setSurfaceResolution(std::uint32_t width, std::uint32_t height)
bool hasNonQtManagedChildren() const
~QQtEmbeddedWindowNode() override
void onSurfaceEvent(SurfaceEventType surfaceEventType, ::OHNativeWindow *nativeWindow) override
static std::shared_ptr< QQtEmbeddedWindowNode > createOrFail(const CreateInfo &createInfo)
QRect nodeScreenGeometryPixels() const
void setAreaChangeReceiver(QOhosConsumer< AreaChangeEvent > areaChangeReceiver)
void onInputEvent(InputEventType inputEventType, ::OHNativeWindow *nativeWindow) override
QPoint windowRelativeOffsetPixels() const
void setCallbackReceiver(std::unique_ptr< QXComponentCallbackReceiver > callbackReceiver)
QXComponentRender renderXComponent() const
void setVisibilityChangeReceiver(QOhosConsumer< bool > visibilityChangedReceiver)
virtual ~QXComponentCallbackReceiver()
Combined button and popup list for selecting options.
bool isNativeNodeApiMouseEventsEnabled()
bool isNativeNodeApiKeyEventsEnabled()
QXComponent< QXComponentType::Render > QXComponentRender