1 /*
2 * Copyright (c) 2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include <cstdint>
17 #include <string>
18
19 #include <js_native_api.h>
20 #include <js_native_api_types.h>
21 #include <hilog/log.h>
22
23 #include "container.h"
24
25 namespace NativeXComponentSample {
26 namespace {
27
28 static int32_t g_zero = 0;
29 static int32_t g_one = 0;
30 static int32_t g_two = 0;
31 static int32_t g_three = 0;
32 static int32_t g_nine = 0;
33 static int32_t g_ten = 0;
34 static int32_t g_fifty = 50;
35 static int32_t g_textWidth = 100;
36 static int32_t g_textHeight = 30;
37 static int32_t g_positionY = 180;
38 static float g_percentNinety = 0.9f;
39
OnSurfaceCreatedCB(OH_NativeXComponent * component,void * window)40 void OnSurfaceCreatedCB(OH_NativeXComponent *component, void *window)
41 {
42 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Callback", "OnSurfaceCreatedCB");
43 if ((component == nullptr) || (window == nullptr)) {
44 return;
45 }
46
47 OH_NativeNode *nodeAPI;
48 OH_NativeXComponent_GetNativeNode(component, &nodeAPI);
49 if (nodeAPI != nullptr) {
50 if (nodeAPI->CreateNode != nullptr && nodeAPI->AddChild != nullptr && nodeAPI->GetCommonModifier) {
51 const OH_CommonModifier *modifier = nodeAPI->GetCommonModifier();
52
53 OH_NativeNodeHandle text1 = nodeAPI->CreateNode("Text", g_textWidth, g_zero);
54 modifier->SetWidth(text1, g_textWidth, g_zero, nullptr); // 100px
55 modifier->SetHeight(text1, g_textHeight, g_zero, nullptr); // px
56 modifier->SetBackgroundColor(text1, 0xfffff0f0);
57 modifier->SetPosition(text1, g_ten, g_zero, g_ten, g_zero); // 10px, 10px
58
59 OH_NativeNodeHandle text2 = nodeAPI->CreateNode("Text", g_textWidth, g_one);
60 modifier->SetWidth(text2, g_one, g_three, nullptr); // 100 percent
61 modifier->SetHeight(text2, g_textHeight, 0, nullptr); // px
62 modifier->SetBackgroundColor(text2, 0xffff0000);
63 modifier->SetPosition(text2, g_ten, 0, g_fifty, 0); // 10px, 10px
64
65 OH_NativeNodeHandle text3 = nodeAPI->CreateNode("Text", g_textWidth, 2);
66 modifier->SetWidth(text3, g_percentNinety, g_three, nullptr); // 90 percent
67 modifier->SetHeight(text3, g_textHeight, 0, nullptr); // px
68 modifier->SetBackgroundColor(text3, 0xff0000ff);
69 modifier->SetPosition(text3, g_ten, 0, g_positionY, 0); // 10px, 10px
70
71 OH_NativeNodeHandle stack = nodeAPI->CreateNode("Stack", g_textWidth, 2);
72
73 modifier->SetWidth(stack, 1, g_three, nullptr); // 200px
74 modifier->SetHeight(stack, g_textWidth, 0, nullptr); // 200px
75 modifier->SetBackgroundColor(stack, 0xffffff00);
76
77 OH_NativeNodeHandle scroll = nodeAPI->CreateNode("Scroll", g_textWidth, 2);
78
79 modifier->SetWidth(scroll, 1, g_three, nullptr); // 200px
80 modifier->SetHeight(scroll, g_textWidth, 0, nullptr); // 200px
81 modifier->SetBackgroundColor(scroll, 0xff00f000);
82
83 nodeAPI->AddChild(stack, text1);
84 nodeAPI->AddChild(stack, text2);
85 nodeAPI->AddChild(stack, text3);
86 nodeAPI->AddChild(scroll, stack);
87
88 OH_NativeXComponent_AttachNativeRootNode(component, scroll);
89 OH_NativeXComponent_MarkDirtyContainer(component, g_one << g_nine);
90 }
91 }
92
93 char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {'\0'};
94 uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
95 if (OH_NativeXComponent_GetXComponentId(component, idStr, &idSize) != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
96 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Callback",
97 "OnSurfaceCreatedCB: Unable to get XComponent id");
98 return;
99 }
100 }
101
OnSurfaceChangedCB(OH_NativeXComponent * component,void * window)102 void OnSurfaceChangedCB(OH_NativeXComponent *component, void *window)
103 {
104 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Callback", "OnSurfaceChangedCB");
105 if ((component == nullptr) || (window == nullptr)) {
106 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Callback",
107 "OnSurfaceChangedCB: component or window is null");
108 return;
109 }
110
111 char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {'\0'};
112 uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
113 if (OH_NativeXComponent_GetXComponentId(component, idStr, &idSize) != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
114 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Callback",
115 "OnSurfaceChangedCB: Unable to get XComponent id");
116 return;
117 }
118
119 std::string id(idStr);
120 auto container = Container::GetInstance(id);
121 if (container != nullptr) {
122 container->OnSurfaceChanged(component, window);
123 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Callback", "surface changed");
124 }
125 }
126
OnSurfaceDestroyedCB(OH_NativeXComponent * component,void * window)127 void OnSurfaceDestroyedCB(OH_NativeXComponent *component, void *window)
128 {
129 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Callback", "OnSurfaceDestroyedCB");
130 if ((component == nullptr) || (window == nullptr)) {
131 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Callback",
132 "OnSurfaceDestroyedCB: component or window is null");
133 return;
134 }
135
136 char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {'\0'};
137 uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
138 if (OH_NativeXComponent_GetXComponentId(component, idStr, &idSize) != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
139 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Callback",
140 "OnSurfaceDestroyedCB: Unable to get XComponent id");
141 return;
142 }
143
144 std::string id(idStr);
145 Container::Release(id);
146 }
147
DispatchTouchEventCB(OH_NativeXComponent * component,void * window)148 void DispatchTouchEventCB(OH_NativeXComponent *component, void *window)
149 {
150 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Callback", "DispatchTouchEventCB");
151 if ((component == nullptr) || (window == nullptr)) {
152 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Callback",
153 "DispatchTouchEventCB: component or window is null");
154 return;
155 }
156
157 char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {'\0'};
158 uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
159 if (OH_NativeXComponent_GetXComponentId(component, idStr, &idSize) != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
160 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Callback",
161 "DispatchTouchEventCB: Unable to get XComponent id");
162 return;
163 }
164
165 std::string id(idStr);
166 Container *render = Container::GetInstance(id);
167 if (render != nullptr) {
168 render->OnTouchEvent(component, window);
169 }
170 }
171
DispatchMouseEventCB(OH_NativeXComponent * component,void * window)172 void DispatchMouseEventCB(OH_NativeXComponent *component, void *window)
173 {
174 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Callback", "DispatchMouseEventCB");
175 int32_t ret;
176 char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {};
177 uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
178 ret = OH_NativeXComponent_GetXComponentId(component, idStr, &idSize);
179 if (ret != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
180 return;
181 }
182
183 std::string id(idStr);
184 auto render = Container::GetInstance(id);
185 if (render != nullptr) {
186 render->OnMouseEvent(component, window);
187 }
188 }
189
190
DispatchHoverEventCB(OH_NativeXComponent * component,bool isHover)191 void DispatchHoverEventCB(OH_NativeXComponent *component, bool isHover)
192 {
193 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Callback", "DispatchHoverEventCB");
194 int32_t ret;
195 char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {};
196 uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
197 ret = OH_NativeXComponent_GetXComponentId(component, idStr, &idSize);
198 if (ret != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
199 return;
200 }
201
202 std::string id(idStr);
203 auto container = Container::GetInstance(id);
204 if (container != nullptr) {
205 container->OnHoverEvent(component, isHover);
206 }
207 }
208 } // namespace
209
210
211 std::unordered_map<std::string, Container *> Container::instance_;
212
Container(const std::string & id)213 Container::Container(const std::string &id)
214 {
215 this->id_ = id;
216 }
217
GetInstance(const std::string & id)218 Container *Container::GetInstance(const std::string &id)
219 {
220 if (instance_.find(id) == instance_.end()) {
221 Container *instance = new Container(id);
222 instance_[id] = instance;
223 return instance;
224 } else {
225 return instance_[id];
226 }
227 }
228
Release(const std::string & id)229 void Container::Release(const std::string &id)
230 {
231 Container *render = Container::GetInstance(id);
232 if (render != nullptr) {
233 }
234 }
235
OnSurfaceChanged(OH_NativeXComponent * component,void * window)236 void Container::OnSurfaceChanged(OH_NativeXComponent *component, void *window)
237 {
238 char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {'\0'};
239 uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
240 if (OH_NativeXComponent_GetXComponentId(component, idStr, &idSize) != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
241 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Callback", "OnSurfaceChanged: Unable to get XComponent id");
242 return;
243 }
244
245 std::string id(idStr);
246 Container *container = Container::GetInstance(id);
247 double offsetX;
248 double offsetY;
249 OH_NativeXComponent_GetXComponentOffset(component, window, &offsetX, &offsetY);
250 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "OH_NativeXComponent_GetXComponentOffset",
251 "offsetX = %{public}lf, offsetY = %{public}lf", offsetX, offsetY);
252 uint64_t width;
253 uint64_t height;
254 OH_NativeXComponent_GetXComponentSize(component, window, &width, &height);
255 }
256
OnTouchEvent(OH_NativeXComponent * component,void * window)257 void Container::OnTouchEvent(OH_NativeXComponent *component, void *window)
258 {
259 char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {'\0'};
260 uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
261 if (OH_NativeXComponent_GetXComponentId(component, idStr, &idSize) != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
262 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Callback",
263 "DispatchTouchEventCB: Unable to get XComponent id");
264 return;
265 }
266 OH_NativeXComponent_TouchEvent touchEvent;
267 OH_NativeXComponent_GetTouchEvent(component, window, &touchEvent);
268 std::string id(idStr);
269 Container *container = Container::GetInstance(id);
270 float tiltX = 0.0f;
271 float tiltY = 0.0f;
272 OH_NativeXComponent_TouchPointToolType toolType =
273 OH_NativeXComponent_TouchPointToolType::OH_NATIVEXCOMPONENT_TOOL_TYPE_UNKNOWN;
274 OH_NativeXComponent_GetTouchPointToolType(component, 0, &toolType);
275 OH_NativeXComponent_GetTouchPointTiltX(component, 0, &tiltX);
276 OH_NativeXComponent_GetTouchPointTiltY(component, 0, &tiltY);
277 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "OnTouchEvent",
278 "touch info: toolType = %{public}d, tiltX = %{public}lf, tiltY = %{public}lf", toolType, tiltX, tiltY);
279 }
280
RegisterCallback(OH_NativeXComponent * nativeXComponent)281 void Container::RegisterCallback(OH_NativeXComponent *nativeXComponent)
282 {
283 containerCallback_.OnSurfaceCreated = OnSurfaceCreatedCB;
284 containerCallback_.OnSurfaceChanged = OnSurfaceChangedCB;
285 containerCallback_.OnSurfaceDestroyed = OnSurfaceDestroyedCB;
286 containerCallback_.DispatchTouchEvent = DispatchTouchEventCB;
287 OH_NativeXComponent_RegisterCallback(nativeXComponent, &containerCallback_);
288
289 mouseCallback_.DispatchMouseEvent = DispatchMouseEventCB;
290 mouseCallback_.DispatchHoverEvent = DispatchHoverEventCB;
291 OH_NativeXComponent_RegisterMouseEventCallback(nativeXComponent, &mouseCallback_);
292 }
293
OnMouseEvent(OH_NativeXComponent * component,void * window)294 void Container::OnMouseEvent(OH_NativeXComponent *component, void *window)
295 {
296 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Container", "OnMouseEvent");
297 OH_NativeXComponent_MouseEvent mouseEvent;
298 int32_t ret = OH_NativeXComponent_GetMouseEvent(component, window, &mouseEvent);
299 if (ret == OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
300 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Container",
301 "MouseEvent Info: x = %{public}f, y = %{public}f, action = %{public}d, button = %{public}d",
302 mouseEvent.x, mouseEvent.y, mouseEvent.action, mouseEvent.button);
303 } else {
304 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Container", "GetMouseEvent error");
305 }
306 }
307
OnHoverEvent(OH_NativeXComponent * component,bool isHover)308 void Container::OnHoverEvent(OH_NativeXComponent *component, bool isHover)
309 {
310 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Container", "OnHoverEvent isHover_ = %{public}d", isHover);
311 }
312
OnKeyEvent(OH_NativeXComponent * component,void * window)313 void Container::OnKeyEvent(OH_NativeXComponent *component, void *window)
314 {
315 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Container", "OnKeyEvent");
316 }
317 } // namespace NativeXComponentSample
318