4#include <qarkui/qnativenodeapi.h>
6#include <QtCore/private/qohoslogger_p.h>
7#include <arkui/native_interface.h>
8#include <arkui/native_node.h>
9#include <arkui/native_type.h>
10#include <qarkui/qarkuiutils.h>
11#include <qohosutils.h>
18const ::ArkUI_NativeNodeAPI_1 &nativeNodeApi()
20 static const ::ArkUI_NativeNodeAPI_1 api = []() {
24 auto *nativeNodeApi =
reinterpret_cast<::ArkUI_NativeNodeAPI_1 *>(
25 ::OH_ArkUI_QueryModuleInterfaceByName(::ARKUI_NATIVE_NODE,
"ArkUI_NativeNodeAPI_1"));
27 if (nativeNodeApi ==
nullptr)
28 qOhosReportFatalErrorAndAbort(
"::OH_ArkUI_QueryModuleInterface failed");
30 static constexpr auto requiredNonNullFunctionPointersMembers =
std::make_tuple(
31 &::ArkUI_NativeNodeAPI_1::addChild,
32 &::ArkUI_NativeNodeAPI_1::addNodeEventReceiver,
33 &::ArkUI_NativeNodeAPI_1::createNode,
34 &::ArkUI_NativeNodeAPI_1::disposeNode,
35 &::ArkUI_NativeNodeAPI_1::getAttribute,
36 &::ArkUI_NativeNodeAPI_1::getChildAt,
37 &::ArkUI_NativeNodeAPI_1::getParent,
38 &::ArkUI_NativeNodeAPI_1::getTotalChildCount,
39 &::ArkUI_NativeNodeAPI_1::registerNodeEvent,
40 &::ArkUI_NativeNodeAPI_1::removeChild,
41 &::ArkUI_NativeNodeAPI_1::removeNodeEventReceiver,
42 &::ArkUI_NativeNodeAPI_1::setAttribute,
43 &::ArkUI_NativeNodeAPI_1::unregisterNodeEvent);
45 QtOhos::tupleForEach(requiredNonNullFunctionPointersMembers, [&](
auto functionMemberPointer) {
46 if ((nativeNodeApi->*functionMemberPointer) ==
nullptr)
47 qOhosReportFatalErrorAndAbort(
"Required function is null");
50 return *nativeNodeApi;
56::ArkUI_NumberValue toArkUiNumberValue(
std::int32_t value)
58 return ::ArkUI_NumberValue {
63::ArkUI_NumberValue toArkUiNumberValue(
std::uint32_t value)
65 return ::ArkUI_NumberValue {
70::ArkUI_NumberValue toArkUiNumberValue(
float value)
72 return ::ArkUI_NumberValue {
77void setNodeAttributeOrFail(
78 ::ArkUI_NodeHandle node,
79 ::ArkUI_NodeAttributeType attribute,
80 std::initializer_list<::ArkUI_AttributeItem> values)
82 auto errorCode = nativeNodeApi().setAttribute(node, attribute, values.begin());
83 if (errorCode != ::ARKUI_ERROR_CODE_NO_ERROR) {
84 qOhosReportFatalErrorAndAbort(
85 "Failed to set attribute: %d on node: %p with error: %d",
92void setNodeAttributeOrFail(
93 ::ArkUI_NodeHandle node,
94 ::ArkUI_NodeAttributeType attribute,
95 std::initializer_list<::ArkUI_NumberValue> values)
97 ::ArkUI_AttributeItem item = {
98 .value = values.begin(),
99 .size =
static_cast<
std::int32_t>(values.size()),
103 setNodeAttributeOrFail(node, attribute, {item});
106std::shared_ptr<
void> registerNodeEvent(
107 ::ArkUI_NodeHandle node, ::ArkUI_NodeEventType eventType,
void *userData)
109 auto registerEventRes = nativeNodeApi().registerNodeEvent(
110 node, eventType,
static_cast<std::int32_t>(eventType), userData);
111 if (registerEventRes != ::ARKUI_ERROR_CODE_NO_ERROR) {
112 qOhosReportFatalErrorAndAbort(
113 "QArkUi: registerNodeEvent(%p, %d) failed with error: %d",
114 node, eventType, registerEventRes);
117 return QtOhos::makeDestroyNotifier(
118 [node, eventType]() {
119 nativeNodeApi().unregisterNodeEvent(node, eventType);
123std::shared_ptr<
void> addNodeEventReceiver(
124 ::ArkUI_NodeHandle node,
void (*eventReceiver)(::ArkUI_NodeEvent *event))
126 auto addEventReceiverRes = nativeNodeApi().addNodeEventReceiver(node, eventReceiver);
127 if (addEventReceiverRes != ::ARKUI_ERROR_CODE_NO_ERROR) {
128 qOhosReportFatalErrorAndAbort(
129 "QArkUi: addNodeEventReceiver(%p, ...) failed with error: %d",
130 node, addEventReceiverRes);
133 return QtOhos::makeDestroyNotifier(
134 [node, eventReceiver]() {
135 nativeNodeApi().removeNodeEventReceiver(node, eventReceiver);
141std::set<::ArkUI_NodeHandle>
Node::qtManagedNodes;
144 ::ArkUI_NodeAttributeType attributeType,
float value)
146 setNodeAttributeOrFail(handle(), attributeType, {toArkUiNumberValue(value)});
150 ::ArkUI_NodeAttributeType attributeType,
std::int32_t value)
152 setNodeAttributeOrFail(handle(), attributeType, {toArkUiNumberValue(value)});
156 ::ArkUI_NodeAttributeType attributeType,
std::uint32_t value)
158 setNodeAttributeOrFail(handle(), attributeType, {toArkUiNumberValue(value)});
162 ::ArkUI_NodeAttributeType attributeType,
bool value)
164 std::int32_t intValue = value ? 1 : 0;
165 setNodeAttributeOrFail(handle(), attributeType, {toArkUiNumberValue(intValue)});
169 ::ArkUI_NodeAttributeType attributeType,
const std::string &value)
171 ::ArkUI_AttributeItem item = {
174 .string = value.data(),
177 setNodeAttributeOrFail(handle(), attributeType, {item});
182 auto errorCode = nativeNodeApi().addChild(handle(), child.handle());
183 if (errorCode != ::ARKUI_ERROR_CODE_NO_ERROR) {
184 qOhosReportFatalErrorAndAbort(
185 "addChild failed for parent: %p, child: %p with error: %d",
206Node::Node(::ArkUI_NodeHandle handle)
210 auto *parentNode = nativeNodeApi().getParent(handle);
211 if (parentNode !=
nullptr)
212 nativeNodeApi().removeChild(parentNode, handle);
213 nativeNodeApi().disposeNode(handle);
214 std::ignore = qtManagedNodes.erase(handle);
218 std::tie(
std::ignore, added) = qtManagedNodes.insert(handle);
220 qOhosReportFatalErrorAndAbort(
"Attempted to take ownership of ::ArkUI_NodeHandle for a second time.");
225 auto errorCode = nativeNodeApi().removeChild(handle(), child.handle());
226 if (errorCode != ::ARKUI_ERROR_CODE_NO_ERROR)
227 qOhosReportFatalErrorAndAbort(
"removeChild failed with error: %d", errorCode);
231 ::ArkUI_NodeEventType eventType,
232 std::function<
void(::ArkUI_NodeEvent *)> eventHandler)
234 if (!m_eventReceiverHandle) {
235 m_eventReceiverHandle = addNodeEventReceiver(
237 [](ArkUI_NodeEvent *event) {
238 void *userData = ::OH_ArkUI_NodeEvent_GetUserData(event);
239 if (userData ==
nullptr) {
240 qOhosPrintfWarning(
"QArkUi: got node event with null userData, ignoring");
244 auto *self =
reinterpret_cast<Node *>(userData);
246 auto eventType = ::OH_ArkUI_NodeEvent_GetEventType(event);
248 auto eventHandlerIter = self->m_eventHandlers.find(eventType);
249 if (eventHandlerIter != self->m_eventHandlers.end())
250 eventHandlerIter->second(event);
252 qOhosPrintfWarning(
"QArkUi: got node event type %d with no handler set, ignoring", eventType);
256 m_eventHandlers.erase(eventType);
258 auto eventRegistrationHandle = registerNodeEvent(handle(), eventType,
this);
260 m_eventHandlers.emplace(
262 [eventRegistrationHandle, eventHandler = std::move(eventHandler)](ArkUI_NodeEvent *event) {
267void Node::setAttributeOrFail(
268 ::ArkUI_NodeAttributeType attributeType,
269 std::size_t numberCount,
const ::ArkUI_NumberValue *numbers)
271 ::ArkUI_AttributeItem item = {
273 .size =
static_cast<
std::int32_t>(numberCount),
278 setNodeAttributeOrFail(handle(), attributeType, {item});
281std::unique_ptr<Node>
Node::takeOwnershipOfExternalNode(::ArkUI_NodeHandle nodeHandle)
283 if (nodeHandle ==
nullptr)
284 qOhosReportFatalErrorAndAbort(
"nodeHandle must not be null");
286 return std::unique_ptr<Node>(
new Node(nodeHandle));
289bool Node::isQtManagedNode(::ArkUI_NodeHandle nodeHandle)
291 return qtManagedNodes.find(nodeHandle) != qtManagedNodes.end();
294::ArkUI_NumberValue
Node::getNumberValueAttributeOrFail(::ArkUI_NodeAttributeType attributeType)
const
296 const auto *item = nativeNodeApi().getAttribute(handle(), attributeType);
297 if (item ==
nullptr) {
298 qOhosReportFatalErrorAndAbort(
299 "QArkUi: Failed to retrieve node: %p attribute: %d", handle(), attributeType);
312 auto errorCode = nativeNodeApi().setLengthMetricUnit(handle(), unit);
313 if (errorCode != ::ARKUI_ERROR_CODE_NO_ERROR) {
314 qOhosReportFatalErrorAndAbort(
315 "setLengthMetricUnit failed for node: %p with error: %d", handle(), errorCode);
321 return nativeNodeApi().getParent(handle()) !=
nullptr;
326 auto *parentHandle = nativeNodeApi().getParent(handle());
327 return parentHandle !=
nullptr
328 ? nativeNodeApi().getTotalChildCount(parentHandle) - 1
335 Q_OHOS_NAMED_FUNC(::OH_ArkUI_NodeUtils_MoveTo),
336 handle(), nativeNodeApi().getParent(handle()), index);
339std::optional<::ArkUI_NodeHandle>
Node::tryfindChild(
340 ::ArkUI_NodeHandle nodeHandle,
const std::function<
bool(::ArkUI_NodeHandle)> predicate)
342 const auto childCount = nativeNodeApi().getTotalChildCount(nodeHandle);
343 for (
std::uint32_t i = 0; i < childCount; ++i) {
344 auto *childNodeHandle = nativeNodeApi().getChildAt(nodeHandle, i);
345 if (predicate(childNodeHandle))
346 return childNodeHandle;
351QPoint
Node::nodeGlobalPosition(::ArkUI_NodeHandle nodeHandle)
353 ::ArkUI_IntOffset globalPositionPx;
354 callArkUiOrFailOnErrorResult(
355 Q_OHOS_NAMED_FUNC(::OH_ArkUI_NodeUtils_GetLayoutPositionInGlobalDisplay),
356 nodeHandle, &globalPositionPx);
357 return QPoint(globalPositionPx.x, globalPositionPx.y);
360QPoint
Node::nodeDisplayPosition(::ArkUI_NodeHandle nodeHandle)
362 ::ArkUI_IntOffset displayPosition;
363 callArkUiOrFailOnErrorResult(
364 Q_OHOS_NAMED_FUNC(::OH_ArkUI_NodeUtils_GetLayoutPositionInScreen),
365 nodeHandle, &displayPosition);
366 return QPoint(displayPosition.x, displayPosition.y);
std::uint32_t siblingsCount() const
void setAttributeOrFail(::ArkUI_NodeAttributeType attributeType, bool value)
void setAttributeOrFail(::ArkUI_NodeAttributeType attributeType, std::uint32_t value)
void setAttributeOrFail(::ArkUI_NodeAttributeType attributeType, std::int32_t value)
void moveTo(std::uint32_t index)
void setAttributeOrFail(::ArkUI_NodeAttributeType attributeType, const std::string &value)
void setEventHandler(::ArkUI_NodeEventType eventType, std::function< void(::ArkUI_NodeEvent *)> eventHandler)
::ArkUI_NodeHandle handle() const
void removeChildOrFail(Node &child)
void setLengthMetricUnitOrFail(::ArkUI_LengthMetricUnit unit)
void setAttributeOrFail(::ArkUI_NodeAttributeType attributeType, float value)
void addChildOrFail(Node &child)
std::int32_t Node::getAttributeOrFail< std::int32_t >(::ArkUI_NodeAttributeType attributeType) const
Combined button and popup list for selecting options.