1 /*
2  * Copyright (c) 2024 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 "bridge/cj_frontend/interfaces/cj_ffi/cj_interactable_view_ffi.h"
17 
18 #include <cinttypes>
19 
20 #include "cj_lambda.h"
21 
22 #include "bridge/cj_frontend/interfaces/cj_ffi/utils.h"
23 #include "bridge/declarative_frontend/view_stack_processor.h"
24 #include "core/components_ng/base/view_abstract_model_ng.h"
25 #include "core/components_ng/base/view_stack_model.h"
26 #include "core/components_ng/pattern/image/image_model_ng.h"
27 #include "core/event/ace_event_handler.h"
28 #include "core/gestures/click_recognizer.h"
29 #ifndef _NON_OHOS_
30 #include "foundation/multimedia/image_framework/frameworks/kits/cj/include/pixel_map_impl.h"
31 
32 #include "adapter/ohos/osal/pixel_map_ohos.h"
33 #endif
34 
35 using namespace OHOS::Ace;
36 using namespace OHOS::Ace::Framework;
37 
38 namespace OHOS::Ace {
FFiSetDragInfo(const RefPtr<DragEvent> & info,const std::string & extraParams,CJPosition & cjPosition,CJDragInfo & ffiDragInfo)39 void FFiSetDragInfo(
40     const RefPtr<DragEvent>& info, const std::string& extraParams, CJPosition& cjPosition, CJDragInfo& ffiDragInfo)
41 {
42     cjPosition.x = info->GetX();
43     cjPosition.y = info->GetY();
44     ffiDragInfo.extraParams = extraParams.c_str();
45 }
46 
ParseDragNode(void (* builder)())47 RefPtr<AceType> ParseDragNode(void (*builder)())
48 {
49     if (builder == nullptr) {
50         return nullptr;
51     }
52     std::function<void(void)> builderFunc = CJLambda::Create(builder);
53     // use another VSP instance while executing the builder function
54     ViewStackModel::GetInstance()->NewScope();
55     {
56         builderFunc();
57     }
58     return ViewStackModel::GetInstance()->Finish();
59 }
60 
ParseDragPixelMap(int64_t pixelMapId)61 RefPtr<PixelMap> ParseDragPixelMap(int64_t pixelMapId)
62 {
63 #ifndef _NON_OHOS_
64     if (pixelMapId == 0) {
65         return nullptr;
66     }
67     auto pixelMapImpl = OHOS::FFI::FFIData::GetData<OHOS::Media::PixelMapImpl>(pixelMapId);
68     if (pixelMapImpl == nullptr) {
69         LOGE("DragStart error, Cannot get PixelMapProxy by id: %{public}" PRId64, pixelMapId);
70         return nullptr;
71     }
72     auto pixMap = pixelMapImpl->GetRealPixelMap();
73     if (pixMap == nullptr) {
74         LOGE("DragStart error, Cannot get pixMap in PixelMapProxy");
75         return nullptr;
76     }
77     auto pixMapOhos = PixelMap::CreatePixelMap(&pixMap);
78     if (pixMapOhos == nullptr) {
79         LOGE("DragStart error, Cannot create PixelMapOhos by pixMap");
80         return nullptr;
81     }
82     return pixMapOhos;
83 #else
84     return nullptr;
85 #endif
86 }
87 
88 } // namespace OHOS::Ace
89 
90 extern "C" {
ToString() const91 std::string CJClickInfo::ToString() const
92 {
93     std::string result = "x: " + std::to_string(x);
94     result = result + ", y: " + std::to_string(y);
95     result = result + ", windowX: " + std::to_string(windowX);
96     result = result + ", windowY: " + std::to_string(windowY);
97     result = result + ", displayX: " + std::to_string(displayX);
98     result = result + ", displayY: " + std::to_string(displayY);
99     result = result + ", timestamp: " + std::to_string(timestamp);
100     result = result + ", target.area.width: " + std::to_string(target->area->width);
101     result = result + ", target.area.height: " + std::to_string(target->area->width);
102     result = result + ", target.area.position.x: " + std::to_string(target->area->position->x);
103     result = result + ", target.area.position.y: " + std::to_string(target->area->position->y);
104     result = result + ", target.area.globalPosition.x: " + std::to_string(target->area->globalPosition->y);
105     result = result + ", target.area.globalPosition.y: " + std::to_string(target->area->globalPosition->y);
106     return result;
107 }
108 
ToString() const109 std::string CJTouchEvent::ToString() const
110 {
111     std::string result = "type: " + std::to_string(eventType);
112     result = result + ", touchesSize: " + std::to_string(touchesSize);
113     result = result + ", changedTouchesSize: " + std::to_string(changedTouchesSize);
114     return result;
115 }
116 
FfiOHOSAceFrameworkInteractableViewOnClick(void (* callback)(CJClickInfo clickInfo))117 void FfiOHOSAceFrameworkInteractableViewOnClick(void (*callback)(CJClickInfo clickInfo))
118 {
119     auto lambda = [ffiOnClick = CJLambda::Create(callback)](const GestureEvent& event) -> void {
120         CJClickInfo cjClickInfo {};
121         CJEventTarget cjEventTarget {};
122         CJArea cjArea {};
123         CJPosition cjPosition {};
124         CJPosition cjGlobalPosition {};
125         AssambleCJClickInfo(event, cjClickInfo, cjEventTarget, cjArea, cjPosition, cjGlobalPosition);
126         ffiOnClick(cjClickInfo);
127     };
128     ViewAbstractModel::GetInstance()->SetOnClick(std::move(lambda), nullptr);
129 }
130 
FfiOHOSAceFrameworkInteractableViewOnTouch(bool (* callback)(CJTouchEvent touchInfo))131 void FfiOHOSAceFrameworkInteractableViewOnTouch(bool (*callback)(CJTouchEvent touchInfo))
132 {
133     auto onTouch = [ffiCallback = CJLambda::Create(callback)](TouchEventInfo& touchEventInfo) {
134         CJTouchEvent ffiTouchInfo;
135 
136         auto& touches = touchEventInfo.GetTouches();
137         ffiTouchInfo.touches = new CJTouchInfo[touches.size()];
138         TransformNativeTouchLocationInfo(ffiTouchInfo.touches, touches);
139         ffiTouchInfo.touchesSize = static_cast<int32_t>(touches.size());
140 
141         auto& changedTouches = touchEventInfo.GetChangedTouches();
142         auto changeTouchArr = new CJTouchInfo[changedTouches.size()];
143         TransformNativeTouchLocationInfo(changeTouchArr, touchEventInfo.GetChangedTouches());
144         ffiTouchInfo.changedTouches = changeTouchArr;
145         ffiTouchInfo.changedTouchesSize = static_cast<int32_t>(changedTouches.size());
146 
147         ffiTouchInfo.eventType = 0;
148         if (changedTouches.size() > 0) {
149             ffiTouchInfo.eventType = static_cast<uint8_t>(changedTouches.front().GetTouchType());
150         }
151         ffiTouchInfo.timestamp = touchEventInfo.GetTimeStamp().time_since_epoch().count();
152         ffiTouchInfo.sourceType = static_cast<int32_t>(touchEventInfo.GetSourceDevice());
153         CJArea cjArea {};
154         CJEventTarget cjEventTarget {};
155         CJPosition cjPosition {};
156         CJPosition cjGlobalPosition {};
157         AssambleCJEventTarget(touchEventInfo.GetTarget(), cjArea, cjPosition, cjGlobalPosition);
158         cjArea.position = &cjPosition;
159         cjArea.globalPosition = &cjGlobalPosition;
160         cjEventTarget.area = &cjArea;
161 
162         ffiTouchInfo.target = &cjEventTarget;
163 
164         auto flag = ffiCallback(ffiTouchInfo);
165         touchEventInfo.SetStopPropagation(flag);
166         delete[] ffiTouchInfo.touches;
167         delete[] ffiTouchInfo.changedTouches;
168     };
169     ViewAbstractModel::GetInstance()->SetOnTouch(std::move(onTouch));
170 }
FfiOHOSAceFrameworkInteractableViewOnAppear(void (* callback)())171 void FfiOHOSAceFrameworkInteractableViewOnAppear(void (*callback)())
172 {
173     auto onAppear = CJLambda::Create(callback);
174     ViewAbstractModel::GetInstance()->SetOnAppear([onAppear]() { onAppear(); });
175 }
176 
FfiOHOSAceFrameworkInteractableViewOnDisAppear(void (* callback)())177 void FfiOHOSAceFrameworkInteractableViewOnDisAppear(void (*callback)())
178 {
179     auto onDisappear = CJLambda::Create(callback);
180     ViewAbstractModel::GetInstance()->SetOnDisAppear([onDisappear]() { onDisappear(); });
181 }
182 
FfiOHOSAceFrameworkInteractableViewOnHover(void (* callback)(bool))183 void FfiOHOSAceFrameworkInteractableViewOnHover(void (*callback)(bool))
184 {
185     auto onHover = CJLambda::Create(callback);
186     ViewAbstractModel::GetInstance()->SetOnHover([onHover](bool param, HoverInfo& info) { onHover(param); });
187 }
188 
FfiOHOSAceFrameworkInteractableViewOnAreaChanged(void (* callback)(CJArea,CJArea))189 void FfiOHOSAceFrameworkInteractableViewOnAreaChanged(void (*callback)(CJArea, CJArea))
190 {
191     auto onAreaChanged = CJLambda::Create(callback);
192     ViewAbstractModel::GetInstance()->SetOnAreaChanged(
193         [onAreaChanged](const Rect& lastRect, const Offset& lastOrigin, const Rect& rect, const Offset& origin) {
194             CJArea lastCjArea {};
195             lastCjArea.width = lastRect.Width();
196             lastCjArea.height = lastRect.Height();
197             CJPosition lastCjPosition {};
198             CJPosition lastCjGlobalPosition {};
199             lastCjPosition.x = lastRect.GetOffset().GetX();
200             lastCjPosition.y = lastRect.GetOffset().GetY();
201             lastCjGlobalPosition.x = lastRect.GetOffset().GetX() + lastOrigin.GetX();
202             lastCjGlobalPosition.y = lastRect.GetOffset().GetY() + lastOrigin.GetY();
203             lastCjArea.position = &lastCjPosition;
204             lastCjArea.globalPosition = &lastCjGlobalPosition;
205 
206             CJArea cjArea {};
207             cjArea.width = rect.Width();
208             cjArea.height = rect.Height();
209             CJPosition cjPosition {};
210             CJPosition cjGlobalPosition {};
211             cjPosition.x = rect.GetOffset().GetX();
212             cjPosition.y = rect.GetOffset().GetY();
213             cjGlobalPosition.x = rect.GetOffset().GetX() + origin.GetX();
214             cjGlobalPosition.y = rect.GetOffset().GetY() + origin.GetY();
215             cjArea.position = &cjPosition;
216             cjArea.globalPosition = &cjGlobalPosition;
217 
218             onAreaChanged(lastCjArea, cjArea);
219         });
220 }
221 
FfiOHOSAceFrameworkInteractableViewOnVisibleAreaChange(VectorFloat64Handle raitosValsHandle,void (* callback)(bool isVisible,double currentRatio))222 void FfiOHOSAceFrameworkInteractableViewOnVisibleAreaChange(
223     VectorFloat64Handle raitosValsHandle, void (*callback)(bool isVisible, double currentRatio))
224 {
225     auto onVisibleChange = CJLambda::Create(callback);
226     const auto& ratios = *reinterpret_cast<std::vector<double>*>(raitosValsHandle);
227 
228     ViewAbstractModel::GetInstance()->SetOnVisibleChange(
229         [onVisibleChange](bool isVisible, double currentRatio) { onVisibleChange(isVisible, currentRatio); }, ratios);
230 }
231 
FfiOHOSAceFrameworkInteractableViewOnMouse(void (* callback)(CJMouseEvent))232 void FfiOHOSAceFrameworkInteractableViewOnMouse(void (*callback)(CJMouseEvent))
233 {
234     auto onMouse = [func = CJLambda::Create(callback)](MouseInfo& mouseInfo) {
235         CJMouseEvent cjMouseEvent {};
236         cjMouseEvent.timestamp = static_cast<int64_t>(mouseInfo.GetTimeStamp().time_since_epoch().count());
237         Offset globalOffset = mouseInfo.GetGlobalLocation();
238         Offset localOffset = mouseInfo.GetLocalLocation();
239         cjMouseEvent.screenX = PipelineBase::Px2VpWithCurrentDensity(globalOffset.GetX());
240         cjMouseEvent.screenY = PipelineBase::Px2VpWithCurrentDensity(globalOffset.GetY());
241         cjMouseEvent.x = PipelineBase::Px2VpWithCurrentDensity(localOffset.GetX());
242         cjMouseEvent.y = PipelineBase::Px2VpWithCurrentDensity(localOffset.GetY());
243         cjMouseEvent.button = static_cast<int32_t>(mouseInfo.GetButton());
244         cjMouseEvent.action = static_cast<int32_t>(mouseInfo.GetAction());
245         func(cjMouseEvent);
246     };
247 
248     ViewAbstractModel::GetInstance()->SetOnMouse(std::move(onMouse));
249 }
250 
251 // can not trigged this event on eTS app
FfiOHOSAceFrameworkInteractableViewOnKey(bool (* callback)(CJKeyEvent info))252 void FfiOHOSAceFrameworkInteractableViewOnKey(bool (*callback)(CJKeyEvent info))
253 {
254     auto onKeyEvent = [ffiCallback = CJLambda::Create(callback)](KeyEventInfo& keyInfo) -> bool  {
255         CJKeyEvent ffiKeyInfo {};
256         ffiKeyInfo.keyText = keyInfo.GetKeyText();
257         ffiKeyInfo.type = static_cast<int32_t>(keyInfo.GetKeyType());
258         ffiKeyInfo.keyCode = static_cast<int32_t>(keyInfo.GetKeyCode());
259         ffiKeyInfo.keySource = static_cast<int32_t>(keyInfo.GetKeySource());
260         ffiKeyInfo.metaKey = keyInfo.GetMetaKey();
261         ffiKeyInfo.deviceId = keyInfo.GetDeviceId();
262         ffiKeyInfo.timestamp = keyInfo.GetTimeStamp().time_since_epoch().count();
263         auto ret = ffiCallback(ffiKeyInfo);
264         keyInfo.SetStopPropagation(ret);
265         return ret;
266     };
267     ViewAbstractModel::GetInstance()->SetOnKeyEvent(onKeyEvent);
268 }
269 
FfiOHOSAceFrameworkInteractableViewOnDelete(void (* callback)())270 void FfiOHOSAceFrameworkInteractableViewOnDelete(void (*callback)())
271 {
272     ViewAbstractModel::GetInstance()->SetOnDelete(CJLambda::Create(callback));
273 }
274 
FfiOHOSAceFrameworkInteractableViewOnFocus(void (* callback)())275 void FfiOHOSAceFrameworkInteractableViewOnFocus(void (*callback)())
276 {
277     ViewAbstractModel::GetInstance()->SetOnFocus(CJLambda::Create(callback));
278 }
279 
FfiOHOSAceFrameworkInteractableViewOnBlur(void (* callback)())280 void FfiOHOSAceFrameworkInteractableViewOnBlur(void (*callback)())
281 {
282     ViewAbstractModel::GetInstance()->SetOnBlur(CJLambda::Create(callback));
283 }
284 
FfiOHOSAceFrameworkInteractableViewOnDragStart(CJDragItemInfo (* callback)(CJDragInfo info),uint32_t componentName)285 void FfiOHOSAceFrameworkInteractableViewOnDragStart(CJDragItemInfo (*callback)(CJDragInfo info), uint32_t componentName)
286 {
287     if (!Container::IsCurrentUseNewPipeline()) {
288         LOGE("not supported");
289         return;
290     }
291     WeakPtr<NG::FrameNode> frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
292     auto ffiCallback = CJLambda::Create(callback);
293     auto onDragStart = [ffiCallback, fnode = frameNode](
294                            const RefPtr<DragEvent>& info, const std::string& extraParams) -> NG::DragDropBaseInfo {
295         LOGD("extraParams: %{public}s", extraParams.c_str());
296         PipelineContext::SetCallBackNode(fnode);
297         NG::DragDropBaseInfo itemInfo;
298         CJDragInfo ffiDragInfo {};
299         CJPosition cjPosition {};
300         FFiSetDragInfo(info, extraParams, cjPosition, ffiDragInfo);
301         ffiDragInfo.position = &cjPosition;
302         auto ret = ffiCallback(ffiDragInfo);
303         LOGD("piexlMapId: %{public}" PRId64 ", extraInfo: %{public}s", ret.pixelMapId, ret.extraInfo);
304         auto node = ParseDragNode(ret.builder);
305 #if defined(PIXEL_MAP_SUPPORTED)
306         itemInfo.pixelMap = ParseDragPixelMap(ret.pixelMapId);
307 #endif
308         itemInfo.extraInfo = ret.extraInfo;
309         itemInfo.node = node;
310         return itemInfo;
311     };
312 
313     ViewAbstractModel::GetInstance()->SetOnDragStart(std::move(onDragStart));
314 }
315 
FfiOHOSAceFrameworkInteractableViewOnDragEnter(void (* callback)(CJDragInfo info),uint32_t componentName)316 void FfiOHOSAceFrameworkInteractableViewOnDragEnter(void (*callback)(CJDragInfo info), uint32_t componentName)
317 {
318     WeakPtr<NG::FrameNode> frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
319     auto ffiCallback = CJLambda::Create(callback);
320     auto onDragEnter = [ffiCallback, fnode = frameNode](const RefPtr<DragEvent>& info, const std::string& extraParams) {
321         LOGD("extraParams: %{public}s", extraParams.c_str());
322         PipelineContext::SetCallBackNode(fnode);
323         NG::DragDropBaseInfo itemInfo;
324         CJDragInfo ffiDragInfo {};
325         CJPosition cjPosition {};
326         FFiSetDragInfo(info, extraParams, cjPosition, ffiDragInfo);
327         ffiDragInfo.position = &cjPosition;
328         ffiCallback(ffiDragInfo);
329     };
330 
331     ViewAbstractModel::GetInstance()->SetOnDragEnter(std::move(onDragEnter));
332 }
333 
FfiOHOSAceFrameworkInteractableViewOnDragMove(void (* callback)(CJDragInfo info),uint32_t componentName)334 void FfiOHOSAceFrameworkInteractableViewOnDragMove(void (*callback)(CJDragInfo info), uint32_t componentName)
335 {
336     WeakPtr<NG::FrameNode> frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
337     auto ffiCallback = CJLambda::Create(callback);
338     auto onDragMove = [ffiCallback, fnode = frameNode](const RefPtr<DragEvent>& info, const std::string& extraParams) {
339         LOGD("extraParams: %{public}s", extraParams.c_str());
340         PipelineContext::SetCallBackNode(fnode);
341         NG::DragDropBaseInfo itemInfo;
342         CJDragInfo ffiDragInfo {};
343         CJPosition cjPosition {};
344         FFiSetDragInfo(info, extraParams, cjPosition, ffiDragInfo);
345         ffiDragInfo.position = &cjPosition;
346         ffiCallback(ffiDragInfo);
347     };
348 
349     ViewAbstractModel::GetInstance()->SetOnDragMove(std::move(onDragMove));
350 }
351 
FfiOHOSAceFrameworkInteractableViewOnDragLeave(void (* callback)(CJDragInfo info),uint32_t componentName)352 void FfiOHOSAceFrameworkInteractableViewOnDragLeave(void (*callback)(CJDragInfo info), uint32_t componentName)
353 {
354     WeakPtr<NG::FrameNode> frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
355     auto ffiCallback = CJLambda::Create(callback);
356     auto onDragLeave = [ffiCallback, fnode = frameNode](const RefPtr<DragEvent>& info, const std::string& extraParams) {
357         LOGD("extraParams: %{public}s", extraParams.c_str());
358         PipelineContext::SetCallBackNode(fnode);
359         NG::DragDropBaseInfo itemInfo;
360         CJDragInfo ffiDragInfo {};
361         CJPosition cjPosition {};
362         FFiSetDragInfo(info, extraParams, cjPosition, ffiDragInfo);
363         ffiDragInfo.position = &cjPosition;
364         ffiCallback(ffiDragInfo);
365     };
366 
367     ViewAbstractModel::GetInstance()->SetOnDragLeave(std::move(onDragLeave));
368 }
369 
FfiOHOSAceFrameworkInteractableViewOnDrop(void (* callback)(CJDragInfo info),uint32_t componentName)370 void FfiOHOSAceFrameworkInteractableViewOnDrop(void (*callback)(CJDragInfo info), uint32_t componentName)
371 {
372     WeakPtr<NG::FrameNode> frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
373     auto ffiCallback = CJLambda::Create(callback);
374     auto onDrop = [ffiCallback, fnode = frameNode](const RefPtr<DragEvent>& info, const std::string& extraParams) {
375         LOGD("extraParams: %{public}s", extraParams.c_str());
376         PipelineContext::SetCallBackNode(fnode);
377         NG::DragDropBaseInfo itemInfo;
378         CJDragInfo ffiDragInfo {};
379         CJPosition cjPosition {};
380         FFiSetDragInfo(info, extraParams, cjPosition, ffiDragInfo);
381         ffiDragInfo.position = &cjPosition;
382         ffiCallback(ffiDragInfo);
383     };
384 
385     ViewAbstractModel::GetInstance()->SetOnDrop(std::move(onDrop));
386 }
387 }
388