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()),
101 setNodeAttributeOrFail(node, attribute, {item});
104std::shared_ptr<
void> registerNodeEvent(
105 ::ArkUI_NodeHandle node, ::ArkUI_NodeEventType eventType,
void *userData)
107 auto registerEventRes = nativeNodeApi().registerNodeEvent(
108 node, eventType,
static_cast<std::int32_t>(eventType), userData);
109 if (registerEventRes != ::ARKUI_ERROR_CODE_NO_ERROR) {
110 qOhosReportFatalErrorAndAbort(
111 "QArkUi: registerNodeEvent(%p, %d) failed with error: %d",
112 node, eventType, registerEventRes);
115 return QtOhos::makeDestroyNotifier(
116 [node, eventType]() {
117 nativeNodeApi().unregisterNodeEvent(node, eventType);
121std::shared_ptr<
void> addNodeEventReceiver(
122 ::ArkUI_NodeHandle node,
void (*eventReceiver)(::ArkUI_NodeEvent *event))
124 auto addEventReceiverRes = nativeNodeApi().addNodeEventReceiver(node, eventReceiver);
125 if (addEventReceiverRes != ::ARKUI_ERROR_CODE_NO_ERROR) {
126 qOhosReportFatalErrorAndAbort(
127 "QArkUi: addNodeEventReceiver(%p, ...) failed with error: %d",
128 node, addEventReceiverRes);
131 return QtOhos::makeDestroyNotifier(
132 [node, eventReceiver]() {
133 nativeNodeApi().removeNodeEventReceiver(node, eventReceiver);
139std::set<::ArkUI_NodeHandle>
Node::qtManagedNodes;
142 ::ArkUI_NodeAttributeType attributeType,
float value)
144 setNodeAttributeOrFail(handle(), attributeType, {toArkUiNumberValue(value)});
148 ::ArkUI_NodeAttributeType attributeType,
std::int32_t value)
150 setNodeAttributeOrFail(handle(), attributeType, {toArkUiNumberValue(value)});
154 ::ArkUI_NodeAttributeType attributeType,
std::uint32_t value)
156 setNodeAttributeOrFail(handle(), attributeType, {toArkUiNumberValue(value)});
160 ::ArkUI_NodeAttributeType attributeType,
bool value)
162 std::int32_t intValue = value ? 1 : 0;
163 setNodeAttributeOrFail(handle(), attributeType, {toArkUiNumberValue(intValue)});
167 ::ArkUI_NodeAttributeType attributeType,
const std::string &value)
169 ::ArkUI_AttributeItem item = {
170 .string = value.data(),
172 setNodeAttributeOrFail(handle(), attributeType, {item});
177 auto errorCode = nativeNodeApi().addChild(handle(), child.handle());
178 if (errorCode != ::ARKUI_ERROR_CODE_NO_ERROR) {
179 qOhosReportFatalErrorAndAbort(
180 "addChild failed for parent: %p, child: %p with error: %d",
201Node::Node(::ArkUI_NodeHandle handle)
205 auto *parentNode = nativeNodeApi().getParent(handle);
206 if (parentNode !=
nullptr)
207 nativeNodeApi().removeChild(parentNode, handle);
208 nativeNodeApi().disposeNode(handle);
209 std::ignore = qtManagedNodes.erase(handle);
213 std::tie(
std::ignore, added) = qtManagedNodes.insert(handle);
215 qOhosReportFatalErrorAndAbort(
"Attempted to take ownership of ::ArkUI_NodeHandle for a second time.");
220 auto errorCode = nativeNodeApi().removeChild(handle(), child.handle());
221 if (errorCode != ::ARKUI_ERROR_CODE_NO_ERROR)
222 qOhosReportFatalErrorAndAbort(
"removeChild failed with error: %d", errorCode);
226 ::ArkUI_NodeEventType eventType,
227 std::function<
void(::ArkUI_NodeEvent *)> eventHandler)
229 if (!m_eventReceiverHandle) {
230 m_eventReceiverHandle = addNodeEventReceiver(
232 [](ArkUI_NodeEvent *event) {
233 void *userData = ::OH_ArkUI_NodeEvent_GetUserData(event);
234 if (userData ==
nullptr) {
235 qOhosPrintfWarning(
"QArkUi: got node event with null userData, ignoring");
239 auto *self =
reinterpret_cast<Node *>(userData);
241 auto eventType = ::OH_ArkUI_NodeEvent_GetEventType(event);
243 auto eventHandlerIter = self->m_eventHandlers.find(eventType);
244 if (eventHandlerIter != self->m_eventHandlers.end())
245 eventHandlerIter->second(event);
247 qOhosPrintfWarning(
"QArkUi: got node event type %d with no handler set, ignoring", eventType);
251 m_eventHandlers.erase(eventType);
253 auto eventRegistrationHandle = registerNodeEvent(handle(), eventType,
this);
255 m_eventHandlers.emplace(
257 [eventRegistrationHandle, eventHandler = std::move(eventHandler)](ArkUI_NodeEvent *event) {
262void Node::setAttributeOrFail(
263 ::ArkUI_NodeAttributeType attributeType,
264 std::size_t numberCount,
const ::ArkUI_NumberValue *numbers)
266 ::ArkUI_AttributeItem item = {
268 .size =
static_cast<
std::int32_t>(numberCount),
271 setNodeAttributeOrFail(handle(), attributeType, {item});
274std::unique_ptr<Node>
Node::takeOwnershipOfExternalNode(::ArkUI_NodeHandle nodeHandle)
276 if (nodeHandle ==
nullptr)
277 qOhosReportFatalErrorAndAbort(
"nodeHandle must not be null");
279 return std::unique_ptr<Node>(
new Node(nodeHandle));
282bool Node::isQtManagedNode(::ArkUI_NodeHandle nodeHandle)
284 return qtManagedNodes.find(nodeHandle) != qtManagedNodes.end();
287::ArkUI_NumberValue
Node::getNumberValueAttributeOrFail(::ArkUI_NodeAttributeType attributeType)
const
289 const auto *item = nativeNodeApi().getAttribute(handle(), attributeType);
290 if (item ==
nullptr) {
291 qOhosReportFatalErrorAndAbort(
292 "QArkUi: Failed to retrieve node: %p attribute: %d", handle(), attributeType);
305 auto errorCode = nativeNodeApi().setLengthMetricUnit(handle(), unit);
306 if (errorCode != ::ARKUI_ERROR_CODE_NO_ERROR) {
307 qOhosReportFatalErrorAndAbort(
308 "setLengthMetricUnit failed for node: %p with error: %d", handle(), errorCode);
314 return nativeNodeApi().getParent(handle()) !=
nullptr;
319 auto *parentHandle = nativeNodeApi().getParent(handle());
320 return parentHandle !=
nullptr
321 ? nativeNodeApi().getTotalChildCount(parentHandle) - 1
328 Q_OHOS_NAMED_FUNC(::OH_ArkUI_NodeUtils_MoveTo),
329 handle(), nativeNodeApi().getParent(handle()), index);
332QOhosOptional<::ArkUI_NodeHandle>
Node::tryfindChild(
333 ::ArkUI_NodeHandle nodeHandle,
const std::function<
bool(::ArkUI_NodeHandle)> predicate)
335 const auto childCount = nativeNodeApi().getTotalChildCount(nodeHandle);
336 for (
std::uint32_t i = 0; i < childCount; ++i) {
337 auto *childNodeHandle = nativeNodeApi().getChildAt(nodeHandle, i);
338 if (predicate(childNodeHandle))
339 return makeQOhosOptional(childNodeHandle);
344QPoint
Node::nodeGlobalPosition(::ArkUI_NodeHandle nodeHandle)
346 ::ArkUI_IntOffset globalPositionPx;
347 callArkUiOrFailOnErrorResult(
348 Q_OHOS_NAMED_FUNC(::OH_ArkUI_NodeUtils_GetLayoutPositionInGlobalDisplay),
349 nodeHandle, &globalPositionPx);
350 return QPoint(globalPositionPx.x, globalPositionPx.y);
353QPoint
Node::nodeDisplayPosition(::ArkUI_NodeHandle nodeHandle)
355 ::ArkUI_IntOffset displayPosition;
356 callArkUiOrFailOnErrorResult(
357 Q_OHOS_NAMED_FUNC(::OH_ArkUI_NodeUtils_GetLayoutPositionInScreen),
358 nodeHandle, &displayPosition);
359 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.
std::nullopt_t makeEmptyQOhosOptional()