• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 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 <cstddef>
17 #include <cstdint>
18 #include <cstring>
19 #include <optional>
20 
21 #include "interfaces/napi/kits/utils/napi_utils.h"
22 #include "js_native_api.h"
23 #include "js_native_api_types.h"
24 #include "napi/native_common.h"
25 #include "native_engine/impl/ark/ark_native_engine.h"
26 #include "native_value.h"
27 #include "core/common/udmf/data_load_params.h"
28 
29 #if defined(ENABLE_DRAG_FRAMEWORK) && defined(PIXEL_MAP_SUPPORTED)
30 #include "jsnapi.h"
31 #include "pixel_map.h"
32 #include "pixel_map_napi.h"
33 #include "interaction_manager.h"
34 
35 #include "adapter/ohos/capability/interaction/start_drag_listener_impl.h"
36 #include "base/log/log_wrapper.h"
37 #include "base/memory/referenced.h"
38 #include "base/geometry/ng/offset_t.h"
39 #include "base/subwindow/subwindow.h"
40 #include "base/utils/utils.h"
41 #include "bridge/common/utils/utils.h"
42 #include "bridge/declarative_frontend/engine/functions/js_drag_function.h"
43 #include "bridge/declarative_frontend/engine/jsi/jsi_declarative_engine.h"
44 #include "bridge/js_frontend/engine/jsi/ark_js_runtime.h"
45 #include "core/common/ace_engine.h"
46 #include "core/common/container_scope.h"
47 #include "core/common/udmf/udmf_client.h"
48 #include "core/components/common/layout/grid_system_manager.h"
49 #include "core/components_ng/manager/drag_drop/drag_drop_func_wrapper.h"
50 #include "core/components_ng/manager/drag_drop/drag_drop_controller_func_wrapper.h"
51 #include "core/components_ng/manager/drag_drop/drag_drop_manager.h"
52 #include "core/event/ace_events.h"
53 #include "core/pipeline_ng/pipeline_context.h"
54 #include "frameworks/bridge/common/utils/engine_helper.h"
55 #include "frameworks/base/json/json_util.h"
56 #include "frameworks/core/event/pointer_event.h"
57 #include "drag_preview.h"
58 #endif
59 namespace OHOS::Ace::Napi {
60 class DragAction;
61 static constexpr uint32_t DRAG_STARTED = 0;
62 static constexpr uint32_t DRAG_ENDED = 1;
63 #if defined(ENABLE_DRAG_FRAMEWORK) && defined(PIXEL_MAP_SUPPORTED)
64 namespace {
65 constexpr float PIXELMAP_WIDTH_RATE = -0.5f;
66 constexpr float PIXELMAP_HEIGHT_RATE = -0.2f;
67 constexpr size_t STR_BUFFER_SIZE = 1024;
68 constexpr int32_t PARAMETER_NUM = 2;
69 constexpr int32_t ARG_COUNT_3 = 3;
70 constexpr int32_t SOURCE_TYPE_MOUSE = 1;
71 constexpr int32_t MOUSE_POINTER_ID = 1001;
72 constexpr int32_t SOURCE_TOOL_PEN = 1;
73 constexpr int32_t SOURCE_TYPE_TOUCH = 2;
74 constexpr int32_t PEN_POINTER_ID = 102;
75 constexpr int32_t CREATE_PIXELMAP_DELAY_TIME = 80;
76 
77 using DragNotifyMsg = Msdp::DeviceStatus::DragNotifyMsg;
78 using DragRet = OHOS::Ace::DragRet;
79 using OnDragCallback = std::function<void(const DragNotifyMsg&)>;
80 using StopDragCallback = std::function<void()>;
81 using PixelMapNapiEntry = void* (*)(void*, void*);
82 
83 enum class DragState { PENDING, SENDING, REJECT, SUCCESS };
84 enum class DragStatus { STARTED, ENDED };
85 enum class ParameterType { CUSTOMBUILDER, DRAGITEMINFO, DRAGITEMINFO_ARRAY, MIX, ERROR };
86 
87 // the context of drag controller
88 struct DragControllerAsyncCtx {
89     napi_env env = nullptr;
90     size_t argc = ARG_COUNT_3;
91     napi_value argv[ARG_COUNT_3] { nullptr };
92     napi_ref callbackRef = nullptr;
93     napi_deferred deferred = nullptr;
94     std::shared_ptr<Media::PixelMap> pixelMap = nullptr;
95     std::vector<std::shared_ptr<Media::PixelMap>> pixelMapList;
96     bool isArray = false;
97     bool isSwitchedToSubWindow = false;
98     napi_value customBuilder;
99     std::vector<napi_ref> customBuilderList;
100     RefPtr<OHOS::Ace::UnifiedData> unifiedData;
101     RefPtr<OHOS::Ace::DataLoadParams> dataLoadParams;
102     std::string extraParams;
103     int32_t instanceId = -1;
104     int32_t errCode = -1;
105     int32_t badgeNumber = 1;
106     std::mutex mutex;
107     bool hasHandle = false;
108     DragPointerEvent dragPointerEvent;
109     float windowScale = 1.0f;
110     float dipScale = 0.0;
111     int parseBuilderCount = 0;
112     std::mutex dragStateMutex;
113     DragState dragState = DragState::PENDING;
114     DimensionOffset touchPoint = DimensionOffset(0.0_vp, 0.0_vp);
115     bool hasTouchPoint = false;
116     DragAction *dragAction = nullptr;
117     NG::DragPreviewOption dragPreviewOption;
118     ~DragControllerAsyncCtx();
119 };
120 } // namespace
121 
122 void OnMultipleComplete(std::shared_ptr<DragControllerAsyncCtx> asyncCtx);
123 void OnComplete(std::shared_ptr<DragControllerAsyncCtx> asyncCtx);
124 bool GetPixelMapByCustom(std::shared_ptr<DragControllerAsyncCtx> asyncCtx);
125 bool GetPixelMapArrayByCustom(std::shared_ptr<DragControllerAsyncCtx> asyncCtx,
126     napi_value customBuilder, int arrayLength);
127 ParameterType getParameterType(std::shared_ptr<DragControllerAsyncCtx> asyncCtx);
128 void SetMouseDragMonitorState(std::shared_ptr<DragControllerAsyncCtx> asyncCtx, bool state);
129 void HandleExecuteDrag(napi_env env, std::shared_ptr<DragControllerAsyncCtx> asyncCtx);
130 bool TryToStartDrag(std::shared_ptr<DragControllerAsyncCtx> asyncCtx);
131 void ExecuteHandleOnDragStart(std::shared_ptr<DragControllerAsyncCtx> asyncCtx);
132 
133 class DragAction {
134 public:
DragAction(std::shared_ptr<DragControllerAsyncCtx> asyncCtx)135     DragAction(std::shared_ptr<DragControllerAsyncCtx> asyncCtx) : asyncCtx_(asyncCtx) {}
~DragAction()136     ~DragAction()
137     {
138         if (asyncCtx_) {
139             asyncCtx_->dragAction = nullptr;
140         }
141         CHECK_NULL_VOID(env_);
142         for (auto& item : cbList_) {
143             napi_delete_reference(env_, item);
144         }
145     }
146 
OnNapiCallback(napi_value resultArg)147     void OnNapiCallback(napi_value resultArg)
148     {
149         std::vector<napi_value> cbList(cbList_.size());
150         for (auto& cbRef : cbList_) {
151             napi_value cb = nullptr;
152             napi_get_reference_value(env_, cbRef, &cb);
153             cbList.push_back(cb);
154         }
155         for (auto& cb : cbList) {
156             napi_call_function(env_, nullptr, cb, 1, &resultArg, nullptr);
157         }
158     }
159 
NapiSerializer(napi_env & env,napi_value & result)160     void NapiSerializer(napi_env& env, napi_value& result)
161     {
162         napi_wrap(
163             env, result, this,
164             [](napi_env env, void* data, void* hint) {
165                 DragAction* dragAction = static_cast<DragAction*>(data);
166                 if (dragAction != nullptr) {
167                     dragAction->DeleteRef();
168                     delete dragAction;
169                 }
170             },
171             nullptr, nullptr);
172 
173         /* insert callback functions */
174         const char* funName = "on";
175         napi_value funcValue = nullptr;
176         napi_create_function(env, funName, NAPI_AUTO_LENGTH, On, nullptr, &funcValue);
177         napi_set_named_property(env, result, funName, funcValue);
178 
179         funName = "off";
180         napi_create_function(env, funName, NAPI_AUTO_LENGTH, Off, nullptr, &funcValue);
181         napi_set_named_property(env, result, funName, funcValue);
182 
183         funName = "startDrag";
184         napi_create_function(env, funName, NAPI_AUTO_LENGTH, StartDrag, nullptr, &funcValue);
185         napi_set_named_property(env, result, funName, funcValue);
186     }
187 
DeleteRef()188     void DeleteRef()
189     {
190         CHECK_NULL_VOID(asyncCtx_);
191         for (auto customBuilderValue : asyncCtx_->customBuilderList) {
192             if (customBuilderValue == nullptr) {
193                 continue;
194             }
195             napi_delete_reference(asyncCtx_->env, customBuilderValue);
196         }
197         asyncCtx_->dragAction = nullptr;
198         asyncCtx_ = nullptr;
199     }
200 
On(napi_env env,napi_callback_info info)201     static napi_value On(napi_env env, napi_callback_info info)
202     {
203         TAG_LOGI(AceLogTag::ACE_DRAG, "drag action On function called.");
204         napi_handle_scope scope = nullptr;
205         napi_open_handle_scope(env, &scope);
206         CHECK_NULL_RETURN(scope, nullptr);
207         napi_value thisVar = nullptr;
208         napi_value cb = nullptr;
209         size_t argc = ParseArgs(env, info, thisVar, cb);
210         if (argc != ARG_COUNT_2 || thisVar == nullptr || cb == nullptr) {
211             TAG_LOGE(AceLogTag::ACE_DRAG, "Invalid arguments");
212             napi_close_handle_scope(env, scope);
213             return nullptr;
214         }
215         napi_valuetype valueType = napi_undefined;
216         napi_typeof(env, cb, &valueType);
217         if (valueType != napi_function) {
218             NapiThrow(env, "Check param failed", ERROR_CODE_PARAM_INVALID);
219             napi_close_handle_scope(env, scope);
220             return nullptr;
221         }
222         DragAction* dragAction = ConvertDragAction(env, thisVar);
223         if (!dragAction) {
224             NapiThrow(env, "convert drag action failed.", ERROR_CODE_PARAM_INVALID);
225             napi_close_handle_scope(env, scope);
226             return nullptr;
227         }
228         auto iter = dragAction->FindCbList(cb);
229         if (iter != dragAction->cbList_.end()) {
230             NapiThrow(env, "get js callback function error.", ERROR_CODE_PARAM_INVALID);
231             napi_close_handle_scope(env, scope);
232             return nullptr;
233         }
234         napi_ref ref = nullptr;
235         napi_create_reference(env, cb, 1, &ref);
236         dragAction->cbList_.emplace_back(ref);
237         napi_close_handle_scope(env, scope);
238         return nullptr;
239     }
240 
Off(napi_env env,napi_callback_info info)241     static napi_value Off(napi_env env, napi_callback_info info)
242     {
243         TAG_LOGI(AceLogTag::ACE_DRAG, "drag action Off function called.");
244         napi_handle_scope scope = nullptr;
245         napi_open_handle_scope(env, &scope);
246         CHECK_NULL_RETURN(scope, nullptr);
247         napi_value thisVar = nullptr;
248         napi_value cb = nullptr;
249         size_t argc = ParseArgs(env, info, thisVar, cb);
250         DragAction* dragAction = ConvertDragAction(env, thisVar);
251         if (!dragAction) {
252             NapiThrow(env, "convert drag action failed.", ERROR_CODE_PARAM_INVALID);
253             napi_close_handle_scope(env, scope);
254             return nullptr;
255         }
256         if (argc == 1) {
257             for (const auto& item : dragAction->cbList_) {
258                 napi_delete_reference(dragAction->env_, item);
259             }
260             dragAction->cbList_.clear();
261         } else {
262             NAPI_ASSERT(env, (argc == ARG_COUNT_2 && dragAction != nullptr && cb != nullptr), "Invalid arguments");
263             napi_valuetype valueType = napi_undefined;
264             napi_typeof(env, cb, &valueType);
265             if (valueType != napi_function) {
266                 NapiThrow(env, "Check param failed", ERROR_CODE_PARAM_INVALID);
267                 napi_close_handle_scope(env, scope);
268                 return nullptr;
269             }
270             auto iter = dragAction->FindCbList(cb);
271             if (iter != dragAction->cbList_.end()) {
272                 napi_delete_reference(dragAction->env_, *iter);
273                 dragAction->cbList_.erase(iter);
274             }
275         }
276         napi_close_handle_scope(env, scope);
277         return nullptr;
278     }
279 
StartDrag(napi_env env,napi_callback_info info)280     static napi_value StartDrag(napi_env env, napi_callback_info info)
281     {
282         TAG_LOGI(AceLogTag::ACE_DRAG, "drag action StartDrag function called.");
283         napi_escapable_handle_scope scope = nullptr;
284         napi_open_escapable_handle_scope(env, &scope);
285         CHECK_NULL_RETURN(scope, nullptr);
286         napi_value thisVar = nullptr;
287         napi_value cb = nullptr;
288         size_t argc = ParseArgs(env, info, thisVar, cb);
289         if (argc != 0 || thisVar == nullptr) {
290             TAG_LOGE(AceLogTag::ACE_DRAG, "Invalid arguments");
291             napi_close_escapable_handle_scope(env, scope);
292             return nullptr;
293         }
294         DragAction* dragAction = ConvertDragAction(env, thisVar);
295         if (!dragAction) {
296             NapiThrow(env, "convert drag action failed.", ERROR_CODE_INTERNAL_ERROR);
297             napi_close_escapable_handle_scope(env, scope);
298             return nullptr;
299         }
300         if (dragAction->asyncCtx_ == nullptr) {
301             NapiThrow(env, "drag action must be recreated for each dragging", ERROR_CODE_INTERNAL_ERROR);
302             napi_close_escapable_handle_scope(env, scope);
303             return nullptr;
304         }
305         napi_value promiseResult = nullptr;
306         napi_status status = napi_create_promise(env, &dragAction->asyncCtx_->deferred, &promiseResult);
307         if (status != napi_ok) {
308             NapiThrow(env, "ace engine delegate is null", ERROR_CODE_INTERNAL_ERROR);
309             napi_close_escapable_handle_scope(env, scope);
310             return nullptr;
311         }
312 
313         SetMouseDragMonitorState(dragAction->asyncCtx_, true);
314         dragAction->StartDragInternal(dragAction->asyncCtx_);
315         napi_escape_handle(env, scope, promiseResult, &promiseResult);
316         napi_close_escapable_handle_scope(env, scope);
317         return promiseResult;
318     }
319 
FindCbList(napi_value cb)320     std::list<napi_ref>::iterator FindCbList(napi_value cb)
321     {
322         return std::find_if(cbList_.begin(), cbList_.end(), [env = env_, cb](const napi_ref& item) -> bool {
323             bool result = false;
324             napi_value refItem;
325             napi_get_reference_value(env, item, &refItem);
326             napi_strict_equals(env, refItem, cb, &result);
327             return result;
328         });
329     }
330 
331 private:
Initialize(napi_env env,napi_value thisVar)332     void Initialize(napi_env env, napi_value thisVar)
333     {
334         env_ = env;
335     }
336 
ParseArgs(napi_env & env,napi_callback_info & info,napi_value & thisVar,napi_value & cb)337     static size_t ParseArgs(napi_env& env, napi_callback_info& info, napi_value& thisVar, napi_value& cb)
338     {
339         size_t argc = ARG_COUNT_2;
340         napi_value argv[ARG_COUNT_2] = { 0 };
341         void* data = nullptr;
342         napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
343         if (argc == 0) {
344             return argc;
345         }
346         NAPI_ASSERT_BASE(env, argc > 0, "too few parameter", 0);
347 
348         napi_valuetype napiType;
349         NAPI_CALL_BASE(env, napi_typeof(env, argv[0], &napiType), 0);
350         NAPI_ASSERT_BASE(env, napiType == napi_string, "parameter 1 should be string", 0);
351         char type[STR_BUFFER_SIZE] = { 0 };
352         size_t len = 0;
353         napi_get_value_string_utf8(env, argv[0], type, STR_BUFFER_SIZE, &len);
354         NAPI_ASSERT_BASE(env, len < STR_BUFFER_SIZE, "condition string too long", 0);
355         NAPI_ASSERT_BASE(env, strcmp("statusChange", type) == 0, "type mismatch('change')", 0);
356         if (argc <= 1) {
357             return argc;
358         }
359         NAPI_CALL_BASE(env, napi_typeof(env, argv[1], &napiType), 0);
360         NAPI_ASSERT_BASE(env, napiType == napi_function, "type mismatch for parameter 2", 0);
361         cb = argv[1];
362         return argc;
363     }
364 
ConvertDragAction(napi_env env,napi_value thisVar)365     static DragAction* ConvertDragAction(napi_env env, napi_value thisVar)
366     {
367         DragAction* dragAction = nullptr;
368         napi_unwrap(env, thisVar, (void**)&dragAction);
369         if (dragAction) {
370             dragAction->Initialize(env, thisVar);
371         }
372         return dragAction;
373     }
374 
StartDragInternal(std::shared_ptr<DragControllerAsyncCtx> dragCtx)375     void StartDragInternal(std::shared_ptr<DragControllerAsyncCtx> dragCtx)
376     {
377         CHECK_NULL_VOID(dragCtx);
378         ParameterType parameterType = getParameterType(dragCtx);
379         TAG_LOGI(AceLogTag::ACE_DRAG, "parameter type is %{public}d", static_cast<int32_t>(parameterType));
380         if (parameterType == ParameterType::DRAGITEMINFO_ARRAY) {
381             OnMultipleComplete(dragCtx);
382         } else if (parameterType == ParameterType::MIX) {
383             int32_t arrayLenth = static_cast<int32_t>(dragCtx->customBuilderList.size());
384             for (auto customBuilderValue: dragCtx->customBuilderList) {
385                 napi_value cb = nullptr;
386                 napi_get_reference_value(dragCtx->env, customBuilderValue, &cb);
387                 GetPixelMapArrayByCustom(dragCtx, cb, arrayLenth);
388             }
389         } else {
390             NapiThrow(dragCtx->env, "parameter parsing failed.", ERROR_CODE_PARAM_INVALID);
391         }
392     }
393 
394     napi_env env_ = nullptr;
395     std::list<napi_ref> cbList_;
396     std::shared_ptr<DragControllerAsyncCtx> asyncCtx_;
397 };
398 
~DragControllerAsyncCtx()399 DragControllerAsyncCtx::~DragControllerAsyncCtx()
400 {
401     if (!dragAction) {
402         dragAction = nullptr;
403     }
404 }
405 
IsExecutingWithDragAction(std::shared_ptr<DragControllerAsyncCtx> asyncCtx)406 bool IsExecutingWithDragAction(std::shared_ptr<DragControllerAsyncCtx> asyncCtx)
407 {
408     CHECK_NULL_RETURN(asyncCtx, false);
409     return (asyncCtx->isArray && asyncCtx->argc == ARG_COUNT_2);
410 }
411 
CreateCallbackErrorValue(napi_env env,int32_t errCode,const std::string & errMsg="")412 napi_value CreateCallbackErrorValue(napi_env env, int32_t errCode, const std::string& errMsg = "")
413 {
414     napi_value code = nullptr;
415     std::string strCode = std::to_string(errCode);
416     napi_create_string_utf8(env, strCode.c_str(), strCode.length(), &code);
417     napi_value msg = nullptr;
418     napi_create_string_utf8(env, errMsg.c_str(), errMsg.length(), &msg);
419     napi_value error = nullptr;
420     napi_create_error(env, code, msg, &error);
421     return error;
422 }
423 
ConvertToPx(std::shared_ptr<DragControllerAsyncCtx> asyncCtx,const Dimension & dimension,double size)424 double ConvertToPx(std::shared_ptr<DragControllerAsyncCtx> asyncCtx, const Dimension& dimension, double size)
425 {
426     auto unit = dimension.Unit();
427     auto value = dimension.Value();
428     if (unit == DimensionUnit::PERCENT) {
429         return value * size;
430     }
431     if (unit == DimensionUnit::NONE || unit == DimensionUnit::PX) {
432         return value;
433     }
434     auto container = AceEngine::Get().GetContainer(asyncCtx->instanceId);
435     if (!container) {
436         return 0.0;
437     }
438     auto pipeline = container->GetPipelineContext();
439     CHECK_NULL_RETURN(pipeline, 0.0);
440     if (unit == DimensionUnit::VP) {
441         return value * pipeline->GetDipScale();
442     }
443     if (unit == DimensionUnit::FP) {
444         return value * pipeline->GetDipScale() * pipeline->GetFontScale();
445     }
446     if (unit == DimensionUnit::LPX) {
447         return value * pipeline->GetLogicScale();
448     }
449     return 0.0;
450 }
451 
HandleDimensionType(napi_value parameterNapi,napi_env env)452 static std::optional<Dimension> HandleDimensionType(napi_value parameterNapi, napi_env env)
453 {
454     size_t ret = 0;
455     std::string parameterStr;
456     napi_valuetype valueType = napi_undefined;
457     napi_typeof(env, parameterNapi, &valueType);
458     Dimension parameter;
459     if (valueType == napi_number) {
460         double parameterValue;
461         napi_get_value_double(env, parameterNapi, &parameterValue);
462         parameter.SetValue(parameterValue);
463         parameter.SetUnit(DimensionUnit::VP);
464     } else if (valueType == napi_string) {
465         size_t parameterLen = GetParamLen(env, parameterNapi) + 1;
466         std::unique_ptr<char[]> parameterTemp = std::make_unique<char[]>(parameterLen);
467         napi_get_value_string_utf8(env, parameterNapi, parameterTemp.get(), parameterLen, &ret);
468         parameterStr = parameterTemp.get();
469         parameter = StringUtils::StringToDimensionWithUnit(parameterStr, DimensionUnit::VP);
470     } else if (valueType == napi_object) {
471         ResourceInfo recv;
472         if (!ParseResourceParam(env, parameterNapi, recv)) {
473             return std::nullopt;
474         }
475         if (!ParseString(recv, parameterStr)) {
476             return std::nullopt;
477         }
478         parameter = StringUtils::StringToDimensionWithUnit(parameterStr, DimensionUnit::VP);
479     } else {
480         return std::nullopt;
481     }
482     return parameter;
483 }
484 
CallBackForJs(std::shared_ptr<DragControllerAsyncCtx> asyncCtx,napi_value result)485 void CallBackForJs(std::shared_ptr<DragControllerAsyncCtx> asyncCtx, napi_value result)
486 {
487     CHECK_NULL_VOID(asyncCtx);
488     CHECK_NULL_VOID(result);
489 
490     if (IsExecutingWithDragAction(asyncCtx) && asyncCtx->dragAction) {
491         asyncCtx->dragAction->OnNapiCallback(result);
492         if (asyncCtx->deferred != nullptr) {
493             napi_value promiseResult = nullptr;
494             napi_get_undefined(asyncCtx->env, &promiseResult);
495             napi_resolve_deferred(asyncCtx->env, asyncCtx->deferred, promiseResult);
496         }
497     } else {
498         napi_value resultVal[PARAMETER_NUM] = { nullptr };
499         napi_get_undefined(asyncCtx->env, &resultVal[0]);
500         napi_get_undefined(asyncCtx->env, &resultVal[1]);
501         resultVal[1] = result;
502         if (asyncCtx->callbackRef) {
503             napi_value ret = nullptr;
504             napi_value napiCallback = nullptr;
505             napi_get_reference_value(asyncCtx->env, asyncCtx->callbackRef, &napiCallback);
506             napi_call_function(asyncCtx->env, nullptr, napiCallback, PARAMETER_NUM, resultVal, &ret);
507             napi_delete_reference(asyncCtx->env, asyncCtx->callbackRef);
508         } else {
509             napi_resolve_deferred(asyncCtx->env, asyncCtx->deferred, resultVal[1]);
510         }
511     }
512     asyncCtx->deferred = nullptr;
513     asyncCtx->hasHandle = false;
514 }
515 
TranslateDragResult(Msdp::DeviceStatus::DragResult dragResult)516 DragRet TranslateDragResult(Msdp::DeviceStatus::DragResult dragResult)
517 {
518     switch (dragResult) {
519         case Msdp::DeviceStatus::DragResult::DRAG_SUCCESS:
520             return DragRet::DRAG_SUCCESS;
521         case Msdp::DeviceStatus::DragResult::DRAG_FAIL:
522             return DragRet::DRAG_FAIL;
523         case Msdp::DeviceStatus::DragResult::DRAG_CANCEL:
524             return DragRet::DRAG_CANCEL;
525         default:
526             return DragRet::DRAG_FAIL;
527     }
528 }
SetDragEventForJs(std::shared_ptr<DragControllerAsyncCtx> asyncCtx,const napi_value & eventNapi,const DragNotifyMsg & dragNotifyMsg)529 bool SetDragEventForJs(
530     std::shared_ptr<DragControllerAsyncCtx> asyncCtx, const napi_value& eventNapi, const DragNotifyMsg& dragNotifyMsg)
531 {
532     CHECK_NULL_RETURN(asyncCtx, false);
533     auto localRef = NapiValueToLocalValue(eventNapi);
534     if (localRef->IsNull()) {
535         TAG_LOGE(AceLogTag::ACE_DRAG, "napi value convert to local value failed.");
536         return false;
537     }
538     auto vm = reinterpret_cast<NativeEngine*>(asyncCtx->env)->GetEcmaVm();
539     auto* jsDragEvent =
540         static_cast<Framework::JsDragEvent*>(Local<panda::ObjectRef>(localRef)->GetNativePointerField(vm, 0));
541     CHECK_NULL_RETURN(jsDragEvent, false);
542     auto dragEvent = AceType::MakeRefPtr<DragEvent>();
543     if (!dragEvent) {
544         TAG_LOGE(AceLogTag::ACE_DRAG, "create dragEvent failed.");
545         return false;
546     }
547     dragEvent->SetResult(TranslateDragResult(dragNotifyMsg.result));
548     dragEvent->SetDragBehavior(static_cast<DragBehavior>(dragNotifyMsg.dragBehavior));
549     jsDragEvent->SetDragEvent(dragEvent);
550     return true;
551 }
552 
GetCallBackDataForJs(std::shared_ptr<DragControllerAsyncCtx> asyncCtx,const DragNotifyMsg & dragNotifyMsg,const DragStatus dragStatus)553 void GetCallBackDataForJs(std::shared_ptr<DragControllerAsyncCtx> asyncCtx, const DragNotifyMsg& dragNotifyMsg,
554     const DragStatus dragStatus)
555 {
556     CHECK_NULL_VOID(asyncCtx);
557     napi_handle_scope scope = nullptr;
558     napi_open_handle_scope(asyncCtx->env, &scope);
559     napi_value result = nullptr;
560     napi_get_undefined(asyncCtx->env, &result);
561     napi_create_object(asyncCtx->env, &result);
562     napi_value eventNapi = nullptr;
563     napi_value globalObj = nullptr;
564     napi_value customDragEvent = nullptr;
565     napi_create_object(asyncCtx->env, &customDragEvent);
566     napi_get_global(asyncCtx->env, &globalObj);
567     napi_get_named_property(asyncCtx->env, globalObj, "DragEvent", &customDragEvent);
568     napi_status status = napi_new_instance(asyncCtx->env, customDragEvent, 0, nullptr, &eventNapi);
569     if (status != napi_ok) {
570         TAG_LOGE(AceLogTag::ACE_DRAG,
571             "create new instance dragEvent failed, return value is %{public}d", status);
572         napi_close_handle_scope(asyncCtx->env, scope);
573         return;
574     }
575     if (!SetDragEventForJs(asyncCtx, eventNapi, dragNotifyMsg)) {
576         TAG_LOGE(AceLogTag::ACE_DRAG, "set dragEvent for JS failed.");
577         napi_close_handle_scope(asyncCtx->env, scope);
578         return;
579     }
580     napi_set_named_property(asyncCtx->env, result, "event", eventNapi);
581 
582     napi_value extraParamsNapi = nullptr;
583     napi_create_string_utf8(
584         asyncCtx->env, asyncCtx->extraParams.c_str(), asyncCtx->extraParams.length(), &extraParamsNapi);
585     napi_set_named_property(asyncCtx->env, result, "extraParams", extraParamsNapi);
586 
587     if (asyncCtx->isArray) {
588         napi_value dragStatusValue = nullptr;
589         napi_create_int32(asyncCtx->env, static_cast<int32_t>(dragStatus), &dragStatusValue);
590         napi_set_named_property(asyncCtx->env, result, "status", dragStatusValue);
591     }
592 
593     CallBackForJs(asyncCtx, result);
594     napi_close_handle_scope(asyncCtx->env, scope);
595 }
596 
SetMouseDragMonitorState(std::shared_ptr<DragControllerAsyncCtx> asyncCtx,bool state)597 void SetMouseDragMonitorState(std::shared_ptr<DragControllerAsyncCtx> asyncCtx, bool state)
598 {
599     if (asyncCtx->dragPointerEvent.sourceType != SOURCE_TYPE_MOUSE) {
600         return;
601     }
602     auto ret = InteractionInterface::GetInstance()->SetMouseDragMonitorState(state);
603     if (ret != 0) {
604         TAG_LOGW(AceLogTag::ACE_DRAG, "Set mouse drag monitor state %{public}d failed, return value is %{public}d",
605             state, ret);
606         return;
607     }
608     TAG_LOGI(AceLogTag::ACE_DRAG, "Set mouse drag monitor state %{public}d success", state);
609 }
610 
HandleExecuteDrag(napi_env env,std::shared_ptr<DragControllerAsyncCtx> asyncCtx)611 void HandleExecuteDrag(napi_env env, std::shared_ptr<DragControllerAsyncCtx> asyncCtx)
612 {
613     ParameterType parameterType = getParameterType(asyncCtx);
614     if (parameterType == ParameterType::DRAGITEMINFO) {
615         OnComplete(asyncCtx);
616     } else if (parameterType == ParameterType::CUSTOMBUILDER) {
617         GetPixelMapByCustom(asyncCtx);
618     } else {
619         NapiThrow(env, "parameter parsing error.", ERROR_CODE_PARAM_INVALID);
620     }
621 }
622 
HandleSuccess(std::shared_ptr<DragControllerAsyncCtx> asyncCtx,const DragNotifyMsg & dragNotifyMsg,const DragStatus dragStatus)623 void HandleSuccess(std::shared_ptr<DragControllerAsyncCtx> asyncCtx, const DragNotifyMsg& dragNotifyMsg,
624     const DragStatus dragStatus)
625 {
626     TAG_LOGI(AceLogTag::ACE_DRAG, "drag notify message result is %{public}d.", dragNotifyMsg.result);
627     CHECK_NULL_VOID(asyncCtx);
628     bool hasHandle = false;
629     {
630         std::lock_guard<std::mutex> lock(asyncCtx->mutex);
631         hasHandle = asyncCtx->hasHandle;
632         asyncCtx->hasHandle = true;
633     }
634     if (hasHandle) {
635         return;
636     }
637     auto container = AceEngine::Get().GetContainer(asyncCtx->instanceId);
638     CHECK_NULL_VOID(container);
639     auto taskExecutor = container->GetTaskExecutor();
640     CHECK_NULL_VOID(taskExecutor);
641     if (dragStatus == DragStatus::ENDED) {
642         auto pipelineContext = container->GetPipelineContext();
643         CHECK_NULL_VOID(pipelineContext);
644         pipelineContext->ResetDragging();
645         taskExecutor->PostTask(
646             [asyncCtx, dragNotifyMsg, dragStatus]() {
647                 CHECK_NULL_VOID(asyncCtx);
648                 GetCallBackDataForJs(asyncCtx, dragNotifyMsg, dragStatus);
649             },
650             TaskExecutor::TaskType::JS, "ArkUIDragHandleSuccess", PriorityType::VIP);
651         return;
652     }
653     taskExecutor->PostSyncTask(
654         [asyncCtx, dragNotifyMsg, dragStatus]() {
655             CHECK_NULL_VOID(asyncCtx);
656             GetCallBackDataForJs(asyncCtx, dragNotifyMsg, dragStatus);
657         },
658         TaskExecutor::TaskType::JS, "ArkUIDragHandleSuccess");
659 }
660 
HandleFail(std::shared_ptr<DragControllerAsyncCtx> asyncCtx,int32_t errorCode,const std::string & errMsg="")661 void HandleFail(std::shared_ptr<DragControllerAsyncCtx> asyncCtx, int32_t errorCode, const std::string& errMsg = "")
662 {
663     CHECK_NULL_VOID(asyncCtx);
664     bool hasHandle = false;
665     {
666         std::lock_guard<std::mutex> lock(asyncCtx->mutex);
667         hasHandle = asyncCtx->hasHandle;
668         asyncCtx->hasHandle = true;
669     }
670     if (hasHandle) {
671         return;
672     }
673     napi_value result[PARAMETER_NUM] = { nullptr };
674     result[0] = CreateCallbackErrorValue(asyncCtx->env, errorCode, errMsg);
675     if (asyncCtx->callbackRef) {
676         napi_value ret = nullptr;
677         napi_value napiCallback = nullptr;
678         napi_get_reference_value(asyncCtx->env, asyncCtx->callbackRef, &napiCallback);
679         napi_create_object(asyncCtx->env, &result[1]);
680         napi_call_function(asyncCtx->env, nullptr, napiCallback, PARAMETER_NUM, result, &ret);
681         napi_delete_reference(asyncCtx->env, asyncCtx->callbackRef);
682     } else {
683         napi_reject_deferred(asyncCtx->env, asyncCtx->deferred, result[0]);
684     }
685 }
686 
HandleDragEnd(std::shared_ptr<DragControllerAsyncCtx> asyncCtx,const DragNotifyMsg & dragNotifyMsg)687 void HandleDragEnd(std::shared_ptr<DragControllerAsyncCtx> asyncCtx, const DragNotifyMsg& dragNotifyMsg)
688 {
689     TAG_LOGI(AceLogTag::ACE_DRAG, "handleDragEnd notify message result is %{public}d.", dragNotifyMsg.result);
690     CHECK_NULL_VOID(asyncCtx);
691     auto container = AceEngine::Get().GetContainer(asyncCtx->instanceId);
692     CHECK_NULL_VOID(container);
693     auto pipelineContext = container->GetPipelineContext();
694     CHECK_NULL_VOID(pipelineContext);
695     pipelineContext->ResetDragging();
696     auto taskExecutor = container->GetTaskExecutor();
697     CHECK_NULL_VOID(taskExecutor);
698     taskExecutor->PostTask(
699         [asyncCtx, dragNotifyMsg]() {
700             CHECK_NULL_VOID(asyncCtx);
701             GetCallBackDataForJs(asyncCtx, dragNotifyMsg, DragStatus::ENDED);
702         },
703         TaskExecutor::TaskType::JS, "ArkUIDragHandleDragEnd", PriorityType::VIP);
704 }
705 
HandleOnDragStart(std::shared_ptr<DragControllerAsyncCtx> asyncCtx)706 void HandleOnDragStart(std::shared_ptr<DragControllerAsyncCtx> asyncCtx)
707 {
708     ContainerScope scope(asyncCtx->instanceId);
709     auto container = Container::CurrentSafely();
710     CHECK_NULL_VOID(container);
711     auto pipelineContext = container->GetPipelineContext();
712     CHECK_NULL_VOID(pipelineContext);
713     pipelineContext->OnDragEvent({ asyncCtx->dragPointerEvent.displayX, asyncCtx->dragPointerEvent.displayY },
714         DragEventAction::DRAG_EVENT_START_FOR_CONTROLLER);
715 }
716 
CopyMediaPixelMap(const RefPtr<PixelMap> & pixelMap)717 std::shared_ptr<Media::PixelMap> CopyMediaPixelMap(const RefPtr<PixelMap>& pixelMap)
718 {
719     CHECK_NULL_RETURN(pixelMap, nullptr);
720     OHOS::Media::InitializationOptions opts;
721     auto mediaPixelMap = pixelMap->GetPixelMapSharedPtr();
722     std::unique_ptr<Media::PixelMap> uniquePixelMap = Media::PixelMap::Create(*mediaPixelMap, opts);
723     CHECK_NULL_RETURN(uniquePixelMap, nullptr);
724     Media::PixelMap* pixelMapRelease = uniquePixelMap.release();
725     CHECK_NULL_RETURN(pixelMapRelease, nullptr);
726     std::shared_ptr<Media::PixelMap> newPixelMap(pixelMapRelease);
727     CHECK_NULL_RETURN(newPixelMap, nullptr);
728     return newPixelMap;
729 }
730 
GetShadowInfo(std::shared_ptr<DragControllerAsyncCtx> asyncCtx,Msdp::DeviceStatus::ShadowInfo & shadowInfo,RefPtr<PixelMap> refPixelMap,float scale)731 bool GetShadowInfo(std::shared_ptr<DragControllerAsyncCtx> asyncCtx, Msdp::DeviceStatus::ShadowInfo& shadowInfo,
732     RefPtr<PixelMap> refPixelMap, float scale)
733 {
734     CHECK_NULL_RETURN(asyncCtx, false);
735     auto pixelMapDuplicated = CopyMediaPixelMap(refPixelMap);
736     if (!pixelMapDuplicated) {
737         TAG_LOGW(AceLogTag::ACE_DRAG, "duplicate PixelMap failed!");
738         pixelMapDuplicated = asyncCtx->pixelMap;
739     }
740     CHECK_NULL_RETURN(pixelMapDuplicated, false);
741     pixelMapDuplicated->scale(scale, scale, Media::AntiAliasingOption::HIGH);
742     int32_t width = pixelMapDuplicated->GetWidth();
743     int32_t height = pixelMapDuplicated->GetHeight();
744     CHECK_NULL_RETURN(pixelMapDuplicated, false);
745     double x = ConvertToPx(asyncCtx, asyncCtx->touchPoint.GetX(), width);
746     double y = ConvertToPx(asyncCtx, asyncCtx->touchPoint.GetY(), height);
747     if (!asyncCtx->hasTouchPoint) {
748         x = -width * PIXELMAP_WIDTH_RATE;
749         y = -height * PIXELMAP_HEIGHT_RATE;
750     } else if (x < 0 || y < 0 || x > static_cast<double>(width) || y > static_cast<double>(height)) {
751         napi_handle_scope scope = nullptr;
752         napi_open_handle_scope(asyncCtx->env, &scope);
753         HandleFail(asyncCtx, ERROR_CODE_PARAM_INVALID, "touchPoint's coordinate out of range");
754         napi_close_handle_scope(asyncCtx->env, scope);
755         return false;
756     }
757     shadowInfo = { pixelMapDuplicated, -x, -y };
758     return true;
759 }
760 
SetIsDragging(const RefPtr<Container> & container,bool isDragging)761 static void SetIsDragging(const RefPtr<Container>& container, bool isDragging)
762 {
763     CHECK_NULL_VOID(container);
764     auto pipelineContext = container->GetPipelineContext();
765     CHECK_NULL_VOID(pipelineContext);
766     pipelineContext->SetIsDragging(isDragging);
767 }
768 
JudgeCoordinateCanDrag(Msdp::DeviceStatus::ShadowInfo & shadowInfo)769 bool JudgeCoordinateCanDrag(Msdp::DeviceStatus::ShadowInfo& shadowInfo)
770 {
771     CHECK_NULL_RETURN(shadowInfo.pixelMap, false);
772     int32_t x = -shadowInfo.x;
773     int32_t y = -shadowInfo.y;
774     int32_t width = shadowInfo.pixelMap->GetWidth();
775     int32_t height = shadowInfo.pixelMap->GetHeight();
776     if (x < 0 || y < 0 || x > width || y > height) {
777         return false;
778     }
779     return true;
780 }
781 
SetUnifiedData(std::shared_ptr<DragControllerAsyncCtx> asyncCtx,std::string & udKey,DragSummaryInfo & dragSummaryInfo)782 int32_t SetUnifiedData(std::shared_ptr<DragControllerAsyncCtx> asyncCtx, std::string& udKey,
783     DragSummaryInfo& dragSummaryInfo)
784 {
785     int32_t dataSize = 1;
786     int32_t ret = 1;
787     CHECK_NULL_RETURN(asyncCtx, dataSize);
788     if (asyncCtx->dataLoadParams) {
789         ret = UdmfClient::GetInstance()->SetDelayInfo(asyncCtx->dataLoadParams, udKey);
790         if (ret != 0) {
791             TAG_LOGI(AceLogTag::ACE_DRAG, "udmf set delayInfo failed, return value is %{public}d", ret);
792         }
793         auto recodeCount = asyncCtx->dataLoadParams->GetRecordCount();
794         dataSize = (recodeCount == 0 || recodeCount > INT32_MAX) ? 1 : static_cast<int32_t>(recodeCount);
795     }
796     if (asyncCtx->unifiedData) {
797         ret = UdmfClient::GetInstance()->SetData(asyncCtx->unifiedData, udKey);
798         if (ret != 0) {
799             TAG_LOGI(AceLogTag::ACE_DRAG, "udmf set data failed, return value is %{public}d", ret);
800         }
801         dataSize = static_cast<int32_t>(asyncCtx->unifiedData->GetSize());
802     }
803     if (ret == 0) {
804         ret = UdmfClient::GetInstance()->GetSummary(udKey, dragSummaryInfo);
805         if (ret != 0) {
806             TAG_LOGI(AceLogTag::ACE_DRAG, "get summary failed, return value is %{public}d", ret);
807         }
808     }
809     return dataSize;
810 }
811 
EnvelopedDragData(std::shared_ptr<DragControllerAsyncCtx> asyncCtx,std::optional<Msdp::DeviceStatus::DragData> & dragData,std::vector<Msdp::DeviceStatus::ShadowInfo> & shadowInfos)812 bool EnvelopedDragData(std::shared_ptr<DragControllerAsyncCtx> asyncCtx,
813     std::optional<Msdp::DeviceStatus::DragData>& dragData, std::vector<Msdp::DeviceStatus::ShadowInfo>& shadowInfos)
814 {
815     auto container = AceEngine::Get().GetContainer(asyncCtx->instanceId);
816     CHECK_NULL_RETURN(container, false);
817     if (shadowInfos.empty()) {
818         napi_handle_scope scope = nullptr;
819         napi_open_handle_scope(asyncCtx->env, &scope);
820         HandleFail(asyncCtx, ERROR_CODE_PARAM_INVALID, "shadowInfo array is empty");
821         napi_close_handle_scope(asyncCtx->env, scope);
822         TAG_LOGE(AceLogTag::ACE_DRAG, "shadowInfo array is empty");
823         return false;
824     }
825     if (!JudgeCoordinateCanDrag(shadowInfos[0])) {
826         napi_handle_scope scope = nullptr;
827         napi_open_handle_scope(asyncCtx->env, &scope);
828         HandleFail(asyncCtx, ERROR_CODE_PARAM_INVALID, "touchPoint's coordinate out of range");
829         napi_close_handle_scope(asyncCtx->env, scope);
830         TAG_LOGE(AceLogTag::ACE_DRAG, "touchPoint's coordinate out of range");
831         return false;
832     }
833     if (!container->GetLastMovingPointerPosition(asyncCtx->dragPointerEvent)) {
834         napi_handle_scope scope = nullptr;
835         napi_open_handle_scope(asyncCtx->env, &scope);
836         HandleFail(asyncCtx, ERROR_CODE_INTERNAL_ERROR, "can not find current pointerId or not in press");
837         napi_close_handle_scope(asyncCtx->env, scope);
838         TAG_LOGE(AceLogTag::ACE_DRAG, "can not find current pointerId or not in press");
839         return false;
840     }
841     std::string udKey;
842     DragSummaryInfo dragSummaryInfo;
843     int32_t dataSize = SetUnifiedData(asyncCtx, udKey, dragSummaryInfo);
844     int32_t recordSize = (dataSize != 0 ? dataSize : static_cast<int32_t>(shadowInfos.size()));
845     auto badgeNumber = asyncCtx->dragPreviewOption.GetCustomerBadgeNumber();
846     if (badgeNumber.has_value()) {
847         recordSize = badgeNumber.value();
848         TAG_LOGI(AceLogTag::ACE_DRAG, "Use custom badge number, value is %{public}d", recordSize);
849     }
850     auto windowId = container->GetWindowId();
851     auto arkExtraInfoJson = JsonUtil::Create(true);
852     arkExtraInfoJson->Put("dip_scale", asyncCtx->dipScale);
853     arkExtraInfoJson->Put("event_id", asyncCtx->dragPointerEvent.pointerEventId);
854     NG::DragDropFuncWrapper::UpdateExtraInfo(arkExtraInfoJson, asyncCtx->dragPreviewOption);
855     dragData = { shadowInfos, {}, udKey, asyncCtx->extraParams, arkExtraInfoJson->ToString(),
856         asyncCtx->dragPointerEvent.sourceType, recordSize, asyncCtx->dragPointerEvent.pointerId,
857         asyncCtx->dragPointerEvent.displayX, asyncCtx->dragPointerEvent.displayY,
858         asyncCtx->dragPointerEvent.displayId, windowId, true, false, dragSummaryInfo.summary, false,
859         dragSummaryInfo.detailedSummary, dragSummaryInfo.summaryFormat, dragSummaryInfo.version,
860         dragSummaryInfo.totalSize };
861     return true;
862 }
863 
864 #ifdef CROSS_PLATFORM
TranslateDragResult(Ace::DragRet ret)865 Msdp::DeviceStatus::DragResult TranslateDragResult(Ace::DragRet ret)
866 {
867     switch (ret) {
868         case Ace::DragRet::DRAG_SUCCESS:
869             return Msdp::DeviceStatus::DragResult::DRAG_SUCCESS;
870         case Ace::DragRet::DRAG_FAIL:
871             return Msdp::DeviceStatus::DragResult::DRAG_FAIL;
872         case Ace::DragRet::DRAG_CANCEL:
873             return Msdp::DeviceStatus::DragResult::DRAG_CANCEL;
874         default:
875             TAG_LOGW(AceLogTag::ACE_DRAG, "translate drag result unknown type %{public}d", static_cast<int32_t>(ret));
876             return Msdp::DeviceStatus::DragResult::DRAG_EXCEPTION;
877     }
878 }
879 
TranslateDragBehavior(Ace::DragBehavior ret)880 Msdp::DeviceStatus::DragBehavior TranslateDragBehavior(Ace::DragBehavior ret)
881 {
882     switch (ret) {
883         case Ace::DragBehavior::UNKNOWN:
884             return Msdp::DeviceStatus::DragBehavior::UNKNOWN;
885         case Ace::DragBehavior::COPY:
886             return Msdp::DeviceStatus::DragBehavior::COPY;
887         case Ace::DragBehavior::MOVE:
888             return Msdp::DeviceStatus::DragBehavior::MOVE;
889         default:
890             TAG_LOGW(AceLogTag::ACE_DRAG, "translate drag behavior unknown type %{public}d", static_cast<int32_t>(ret));
891             return Msdp::DeviceStatus::DragBehavior::UNKNOWN;
892     }
893 }
894 
StartDrag(std::shared_ptr<DragControllerAsyncCtx> asyncCtx,const Msdp::DeviceStatus::DragData & dragData,bool isStartDragService)895 int32_t StartDrag(std::shared_ptr<DragControllerAsyncCtx> asyncCtx, const Msdp::DeviceStatus::DragData& dragData,
896     bool isStartDragService)
897 {
898     OHOS::Ace::DragDataCore dragDataCore { {}, {}, dragData.udKey, dragData.extraInfo, dragData.filterInfo,
899         MMI::PointerEvent::SOURCE_TYPE_TOUCHSCREEN, dragData.dragNum, dragData.pointerId,
900         dragData.displayX, dragData.displayY, dragData.displayId, dragData.mainWindow, dragData.hasCanceledAnimation,
901         dragData.hasCoordinateCorrected, dragData.summarys };
902     for (const auto& shadowInfo : dragData.shadowInfos) {
903         auto pixelMap = shadowInfo.pixelMap;
904         if (pixelMap) {
905             dragDataCore.shadowInfos.push_back(
906                 { OHOS::Ace::PixelMap::CreatePixelMap(reinterpret_cast<void*>(&pixelMap)), shadowInfo.x,
907                     shadowInfo.y });
908         } else {
909             dragDataCore.shadowInfos.push_back({ nullptr, shadowInfo.x, shadowInfo.y });
910         }
911     }
912     auto callback = [asyncCtx, isStartDragService](const OHOS::Ace::DragNotifyMsg& msg) {
913         DragNotifyMsg dragNotifyMsg = DragNotifyMsg();
914         dragNotifyMsg.displayX = msg.displayX;
915         dragNotifyMsg.displayY = msg.displayY;
916         dragNotifyMsg.targetPid = msg.targetPid;
917         dragNotifyMsg.result = TranslateDragResult(msg.result);
918         dragNotifyMsg.dragBehavior = TranslateDragBehavior(msg.dragBehavior);
919         if (isStartDragService) {
920             HandleDragEnd(asyncCtx, dragNotifyMsg);
921         } else {
922             HandleSuccess(asyncCtx, dragNotifyMsg, DragStatus::ENDED);
923         }
924     };
925     auto interactionInterface = OHOS::Ace::InteractionInterface::GetInstance();
926     int32_t ret = interactionInterface->StartDrag(dragDataCore, callback);
927     interactionInterface->SetDragWindowVisible(true);
928     return ret;
929 }
930 #endif
931 
LogDragInfoInner(std::shared_ptr<DragControllerAsyncCtx> asyncCtx,const Msdp::DeviceStatus::DragData & dragData)932 void LogDragInfoInner(std::shared_ptr<DragControllerAsyncCtx> asyncCtx, const Msdp::DeviceStatus::DragData& dragData)
933 {
934     auto pixelMap = dragData.shadowInfos[0].pixelMap;
935     std::string summarys = NG::DragDropFuncWrapper::GetSummaryString(dragData.summarys);
936     TAG_LOGI(AceLogTag::ACE_DRAG,
937         "dragData, pixelMap width %{public}d height %{public}d, udkey %{public}s, recordSize %{public}d, "
938         "extraParams length %{public}d, pointerId %{public}d, summary %{public}s, eventId %{public}d",
939         pixelMap->GetWidth(), pixelMap->GetHeight(),
940         NG::DragDropFuncWrapper::GetAnonyString(dragData.udKey).c_str(), dragData.dragNum,
941         static_cast<int32_t>(asyncCtx->extraParams.length()), asyncCtx->dragPointerEvent.pointerId,
942         summarys.c_str(), asyncCtx->dragPointerEvent.pointerEventId);
943 }
944 
CreatePreviewNodeAndScale(std::shared_ptr<DragControllerAsyncCtx> asyncCtx,NG::PreparedInfoForDrag & data,NG::PreparedAsyncCtxForAnimate & asyncCtxData,Msdp::DeviceStatus::ShadowInfo & shadowInfo,std::shared_ptr<Media::PixelMap> pixelMap)945 bool CreatePreviewNodeAndScale(std::shared_ptr<DragControllerAsyncCtx> asyncCtx,
946     NG::PreparedInfoForDrag& data, NG::PreparedAsyncCtxForAnimate& asyncCtxData,
947     Msdp::DeviceStatus::ShadowInfo& shadowInfo, std::shared_ptr<Media::PixelMap> pixelMap)
948 {
949     CHECK_NULL_RETURN(asyncCtx, false);
950     auto container = AceEngine::Get().GetContainer(asyncCtx->instanceId);
951     auto pipeline = container->GetPipelineContext();
952     CHECK_NULL_RETURN(pipeline, false);
953     auto dragNodePipeline = AceType::DynamicCast<NG::PipelineContext>(pipeline);
954     CHECK_NULL_RETURN(dragNodePipeline, false);
955     auto scaleData =
956         NG::DragControllerFuncWrapper::GetScaleInfo(asyncCtx->instanceId, pixelMap->GetWidth(), pixelMap->GetHeight());
957     CHECK_NULL_RETURN(scaleData, false);
958     auto scale = asyncCtx->windowScale;
959     CHECK_NULL_RETURN(pixelMap, false);
960     RefPtr<PixelMap> refPixelMap = PixelMap::CreatePixelMap(reinterpret_cast<void*>(&pixelMap));
961     CHECK_NULL_RETURN(refPixelMap, false);
962     auto badgeNumber = asyncCtx->dragPreviewOption.GetCustomerBadgeNumber();
963     if (badgeNumber.has_value()) {
964         asyncCtx->badgeNumber = badgeNumber.value();
965     }
966     data = { false, asyncCtx->badgeNumber, 1.0f, false,
967         NG::OffsetF(), NG::DragControllerFuncWrapper::GetUpdateDragMovePosition(asyncCtx->instanceId), refPixelMap };
968     NG::DragControllerFuncWrapper::ResetContextMenuDragPosition(asyncCtx->instanceId);
969     if (scaleData->isNeedScale && asyncCtx->dragPreviewOption.isScaleEnabled) {
970         auto overlayManager = dragNodePipeline->GetOverlayManager();
971         auto imageNode = overlayManager->GetPixelMapContentNode();
972         scale = scaleData->scale * asyncCtx->windowScale;
973         data.previewScale = scale;
974         NG::DragControllerFuncWrapper::CreatePreviewNode(imageNode, data, asyncCtxData);
975         CHECK_NULL_RETURN(imageNode, false);
976         data.imageNode = imageNode;
977         data.dragPreviewOffsetToScreen = NG::DragControllerFuncWrapper::GetOriginNodeOffset(data, asyncCtxData);
978     }
979     auto result = GetShadowInfo(asyncCtx, shadowInfo, refPixelMap, scale);
980     if (!result) {
981         return false;
982     }
983     asyncCtxData = {asyncCtx->instanceId, asyncCtx->hasTouchPoint, asyncCtx->dragPointerEvent,
984         asyncCtx->dragPreviewOption, asyncCtx->touchPoint, asyncCtx->pixelMapList};
985     return true;
986 }
987 
HideDragPreviewWindow(std::shared_ptr<DragControllerAsyncCtx> asyncCtx)988 void HideDragPreviewWindow(std::shared_ptr<DragControllerAsyncCtx> asyncCtx)
989 {
990     auto container = Container::CurrentSafely();
991     CHECK_NULL_VOID(container);
992     auto taskExecutor = container->GetTaskExecutor();
993     CHECK_NULL_VOID(taskExecutor);
994     taskExecutor->PostTask([asyncCtx]() { NG::DragControllerFuncWrapper::HideDragPreviewWindow(asyncCtx->instanceId); },
995         TaskExecutor::TaskType::UI, "ArkUIHideDragPreviewWindow", PriorityType::VIP);
996 }
997 
StartDragService(std::shared_ptr<DragControllerAsyncCtx> asyncCtx,int32_t & ret)998 void StartDragService(std::shared_ptr<DragControllerAsyncCtx> asyncCtx, int32_t& ret)
999 {
1000     CHECK_NULL_VOID(asyncCtx);
1001     auto container = AceEngine::Get().GetContainer(asyncCtx->instanceId);
1002     CHECK_NULL_VOID(container);
1003     auto pipeline = container->GetPipelineContext();
1004     CHECK_NULL_VOID(pipeline);
1005     NG::PreparedInfoForDrag data;
1006     NG::PreparedAsyncCtxForAnimate asyncCtxData;
1007     std::vector<Msdp::DeviceStatus::ShadowInfo> shadowInfos;
1008     Msdp::DeviceStatus::ShadowInfo shadowInfo;
1009     asyncCtxData = {asyncCtx->instanceId, asyncCtx->hasTouchPoint, asyncCtx->dragPointerEvent,
1010         asyncCtx->dragPreviewOption, asyncCtx->touchPoint, asyncCtx->pixelMapList};
1011     auto subWindow = NG::DragControllerFuncWrapper::SubWindowShow(pipeline);
1012     for (auto& pixelMap: asyncCtx->pixelMapList) {
1013         if (!pixelMap) {
1014             TAG_LOGD(AceLogTag::ACE_DRAG, "Skipping null pixelMap");
1015             continue;
1016         }
1017         auto ret = CreatePreviewNodeAndScale(asyncCtx, data, asyncCtxData, shadowInfo, pixelMap);
1018         if (!ret) {
1019             return;
1020         }
1021         shadowInfos.push_back(shadowInfo);
1022     }
1023     std::optional<Msdp::DeviceStatus::DragData> dragData;
1024     if (!EnvelopedDragData(asyncCtx, dragData, shadowInfos)) {
1025         return;
1026     }
1027     OnDragCallback callback = [asyncCtx](const DragNotifyMsg& dragNotifyMsg) {
1028         HideDragPreviewWindow(asyncCtx);
1029         HandleDragEnd(asyncCtx, dragNotifyMsg);
1030     };
1031     NG::DragDropFuncWrapper::SetDraggingPointerAndPressedState(
1032         asyncCtx->dragPointerEvent.pointerId, asyncCtx->instanceId);
1033     NG::DragDropFuncWrapper::SetExtraInfo(asyncCtx->instanceId, asyncCtx->extraParams);
1034     LogDragInfoInner(asyncCtx, dragData.value());
1035 #ifdef CROSS_PLATFORM
1036     ret = StartDrag(asyncCtx, dragData.value(), true);
1037 #else
1038     ret = Msdp::DeviceStatus::InteractionManager::GetInstance()->StartDrag(dragData.value(),
1039         std::make_shared<OHOS::Ace::StartDragListenerImpl>(callback));
1040 #endif
1041     if (ret == 0) {
1042         asyncCtxData.dragPointerEvent = asyncCtx->dragPointerEvent;
1043         if (NG::DragControllerFuncWrapper::TryDoDragStartAnimation(subWindow, data, asyncCtxData)) {
1044             asyncCtx->isSwitchedToSubWindow = true;
1045         }
1046     }
1047 }
1048 
OnMultipleComplete(std::shared_ptr<DragControllerAsyncCtx> asyncCtx)1049 void OnMultipleComplete(std::shared_ptr<DragControllerAsyncCtx> asyncCtx)
1050 {
1051     auto container = AceEngine::Get().GetContainer(asyncCtx->instanceId);
1052     CHECK_NULL_VOID(container);
1053     auto taskExecutor = container->GetTaskExecutor();
1054     CHECK_NULL_VOID(taskExecutor);
1055     auto windowScale = container->GetWindowScale();
1056     asyncCtx->windowScale = windowScale;
1057     taskExecutor->PostTask(
1058         [asyncCtx]() {
1059             CHECK_NULL_VOID(asyncCtx);
1060             ContainerScope scope(asyncCtx->instanceId);
1061             DragState dragState = DragState::PENDING;
1062             {
1063                 std::lock_guard<std::mutex> lock(asyncCtx->dragStateMutex);
1064                 if (asyncCtx->dragState == DragState::PENDING) {
1065                     asyncCtx->dragState = DragState::SENDING;
1066                 }
1067                 dragState = asyncCtx->dragState;
1068             }
1069             if (dragState == DragState::REJECT) {
1070                 napi_handle_scope scope = nullptr;
1071                 napi_open_handle_scope(asyncCtx->env, &scope);
1072                 HandleFail(asyncCtx, ERROR_CODE_INTERNAL_ERROR, "drag state is reject.");
1073                 SetMouseDragMonitorState(asyncCtx, false);
1074                 napi_close_handle_scope(asyncCtx->env, scope);
1075                 return;
1076             }
1077             int32_t ret = 0;
1078             StartDragService(asyncCtx, ret);
1079             if (ret != 0) {
1080                 napi_handle_scope scope = nullptr;
1081                 napi_open_handle_scope(asyncCtx->env, &scope);
1082                 HandleFail(asyncCtx, ERROR_CODE_INTERNAL_ERROR, "msdp start drag failed.");
1083                 napi_close_handle_scope(asyncCtx->env, scope);
1084                 return;
1085             }
1086             HandleSuccess(asyncCtx, DragNotifyMsg {}, DragStatus::STARTED);
1087             auto container = AceEngine::Get().GetContainer(asyncCtx->instanceId);
1088             CHECK_NULL_VOID(container);
1089             SetIsDragging(container, true);
1090             TAG_LOGI(AceLogTag::ACE_DRAG, "msdp start drag successfully");
1091             ExecuteHandleOnDragStart(asyncCtx);
1092         },
1093         TaskExecutor::TaskType::JS, "ArkUIDragMultipleComplete", PriorityType::VIP);
1094 }
1095 
OnComplete(std::shared_ptr<DragControllerAsyncCtx> asyncCtx)1096 void OnComplete(std::shared_ptr<DragControllerAsyncCtx> asyncCtx)
1097 {
1098     auto container = AceEngine::Get().GetContainer(asyncCtx->instanceId);
1099     CHECK_NULL_VOID(container);
1100     auto taskExecutor = container->GetTaskExecutor();
1101     CHECK_NULL_VOID(taskExecutor);
1102     auto windowScale = container->GetWindowScale();
1103     asyncCtx->windowScale = windowScale;
1104     taskExecutor->PostTask(
1105         [asyncCtx]() {
1106             CHECK_NULL_VOID(asyncCtx);
1107             ContainerScope scope(asyncCtx->instanceId);
1108             DragState dragState = DragState::PENDING;
1109             {
1110                 std::lock_guard<std::mutex> lock(asyncCtx->dragStateMutex);
1111                 if (asyncCtx->dragState == DragState::PENDING) {
1112                     asyncCtx->dragState = DragState::SENDING;
1113                 }
1114                 dragState = asyncCtx->dragState;
1115             }
1116             if (dragState == DragState::REJECT) {
1117                 napi_handle_scope scope = nullptr;
1118                 napi_open_handle_scope(asyncCtx->env, &scope);
1119                 HandleFail(asyncCtx, ERROR_CODE_INTERNAL_ERROR, "drag state is reject.");
1120                 napi_close_handle_scope(asyncCtx->env, scope);
1121                 return;
1122             }
1123             if (!TryToStartDrag(asyncCtx)) {
1124                 TAG_LOGW(AceLogTag::ACE_DRAG, "msdp start drag failed.");
1125                 return;
1126             }
1127             auto container = AceEngine::Get().GetContainer(asyncCtx->instanceId);
1128             CHECK_NULL_VOID(container);
1129             SetIsDragging(container, true);
1130             TAG_LOGI(AceLogTag::ACE_DRAG, "msdp start drag successfully");
1131             ExecuteHandleOnDragStart(asyncCtx);
1132         },
1133         TaskExecutor::TaskType::JS, "ArkUIDragComplete", PriorityType::VIP);
1134 }
1135 
ExecuteHandleOnDragStart(std::shared_ptr<DragControllerAsyncCtx> asyncCtx)1136 void ExecuteHandleOnDragStart(std::shared_ptr<DragControllerAsyncCtx> asyncCtx)
1137 {
1138     CHECK_NULL_VOID(asyncCtx);
1139     {
1140         std::lock_guard<std::mutex> lock(asyncCtx->dragStateMutex);
1141         if (asyncCtx->dragState == DragState::SENDING) {
1142             asyncCtx->dragState = DragState::SUCCESS;
1143             if (!asyncCtx->isSwitchedToSubWindow) {
1144                 Msdp::DeviceStatus::InteractionManager::GetInstance()->SetDragWindowVisible(true);
1145             }
1146             napi_handle_scope scope = nullptr;
1147             napi_open_handle_scope(asyncCtx->env, &scope);
1148             HandleOnDragStart(asyncCtx);
1149             napi_close_handle_scope(asyncCtx->env, scope);
1150         }
1151     }
1152 }
1153 
PrepareDragData(std::shared_ptr<DragControllerAsyncCtx> asyncCtx,Msdp::DeviceStatus::DragData & dragData,Msdp::DeviceStatus::ShadowInfo & shadowInfo)1154 bool PrepareDragData(std::shared_ptr<DragControllerAsyncCtx> asyncCtx,
1155     Msdp::DeviceStatus::DragData& dragData, Msdp::DeviceStatus::ShadowInfo& shadowInfo)
1156 {
1157     CHECK_NULL_RETURN(asyncCtx, false);
1158     CHECK_NULL_RETURN(asyncCtx->pixelMap, false);
1159     int32_t dataSize = 1;
1160     std::string udKey;
1161     DragSummaryInfo dragSummaryInfo;
1162     dataSize = SetUnifiedData(asyncCtx, udKey, dragSummaryInfo);
1163     auto badgeNumber = asyncCtx->dragPreviewOption.GetCustomerBadgeNumber();
1164     if (badgeNumber.has_value()) {
1165         dataSize = badgeNumber.value();
1166     }
1167     auto container = AceEngine::Get().GetContainer(asyncCtx->instanceId);
1168     CHECK_NULL_RETURN(container, false);
1169     if (!container->GetLastMovingPointerPosition(asyncCtx->dragPointerEvent)) {
1170         napi_handle_scope scope = nullptr;
1171         napi_open_handle_scope(asyncCtx->env, &scope);
1172         HandleFail(asyncCtx, ERROR_CODE_INTERNAL_ERROR, "can not find current pointerId or not in press");
1173         napi_close_handle_scope(asyncCtx->env, scope);
1174         return false;
1175     }
1176     auto arkExtraInfoJson = JsonUtil::Create(true);
1177     arkExtraInfoJson->Put("dip_scale", asyncCtx->dipScale);
1178     arkExtraInfoJson->Put("event_id", asyncCtx->dragPointerEvent.pointerEventId);
1179     NG::DragDropFuncWrapper::UpdateExtraInfo(arkExtraInfoJson, asyncCtx->dragPreviewOption);
1180     auto windowId = container->GetWindowId();
1181     dragData = { { shadowInfo }, {}, udKey, asyncCtx->extraParams,
1182         arkExtraInfoJson->ToString(), asyncCtx->dragPointerEvent.sourceType, dataSize,
1183         asyncCtx->dragPointerEvent.pointerId, asyncCtx->dragPointerEvent.displayX,
1184         asyncCtx->dragPointerEvent.displayY, asyncCtx->dragPointerEvent.displayId,
1185         windowId, true, false, dragSummaryInfo.summary, false, dragSummaryInfo.detailedSummary,
1186         dragSummaryInfo.summaryFormat, dragSummaryInfo.version, dragSummaryInfo.totalSize };
1187     return true;
1188 }
1189 
TryToStartDrag(std::shared_ptr<DragControllerAsyncCtx> asyncCtx)1190 bool TryToStartDrag(std::shared_ptr<DragControllerAsyncCtx> asyncCtx)
1191 {
1192     CHECK_NULL_RETURN(asyncCtx, false);
1193     auto container = AceEngine::Get().GetContainer(asyncCtx->instanceId);
1194     CHECK_NULL_RETURN(container, false);
1195     auto pipeline = container->GetPipelineContext();
1196     CHECK_NULL_RETURN(pipeline, false);
1197     NG::PreparedInfoForDrag data;
1198     NG::PreparedAsyncCtxForAnimate asyncCtxData;
1199     Msdp::DeviceStatus::ShadowInfo shadowInfo;
1200     asyncCtxData = {asyncCtx->instanceId, asyncCtx->hasTouchPoint, asyncCtx->dragPointerEvent,
1201         asyncCtx->dragPreviewOption, asyncCtx->touchPoint, asyncCtx->pixelMapList};
1202     auto subWindow = NG::DragControllerFuncWrapper::SubWindowShow(pipeline);
1203     auto ret = CreatePreviewNodeAndScale(asyncCtx, data, asyncCtxData, shadowInfo, asyncCtx->pixelMap);
1204     if (!ret) {
1205         return false;
1206     }
1207     Msdp::DeviceStatus::DragData dragData;
1208     if (!PrepareDragData(asyncCtx, dragData, shadowInfo)) {
1209         TAG_LOGW(AceLogTag::ACE_DRAG, "prepare drag data failed!");
1210         return false;
1211     }
1212     OnDragCallback callback = [asyncCtx](const DragNotifyMsg& dragNotifyMsg) {
1213         HideDragPreviewWindow(asyncCtx);
1214         HandleSuccess(asyncCtx, dragNotifyMsg, DragStatus::ENDED);
1215     };
1216     NG::DragDropFuncWrapper::SetDraggingPointerAndPressedState(
1217         asyncCtx->dragPointerEvent.pointerId, asyncCtx->instanceId);
1218     LogDragInfoInner(asyncCtx, dragData);
1219 #ifdef CROSS_PLATFORM
1220     int32_t result = StartDrag(asyncCtx, dragData, false);
1221 #else
1222     int32_t result = Msdp::DeviceStatus::InteractionManager::GetInstance()->StartDrag(dragData,
1223         std::make_shared<OHOS::Ace::StartDragListenerImpl>(callback));
1224 #endif
1225     if (result != 0) {
1226         napi_handle_scope scope = nullptr;
1227         napi_open_handle_scope(asyncCtx->env, &scope);
1228         HandleFail(asyncCtx, ERROR_CODE_INTERNAL_ERROR, "msdp start drag failed.");
1229         napi_close_handle_scope(asyncCtx->env, scope);
1230         return false;
1231     }
1232     if (NG::DragControllerFuncWrapper::TryDoDragStartAnimation(subWindow, data, asyncCtxData)) {
1233         asyncCtx->isSwitchedToSubWindow = true;
1234     }
1235     return true;
1236 }
1237 
ParseTouchPoint(std::shared_ptr<DragControllerAsyncCtx> asyncCtx,napi_valuetype & valueType)1238 bool ParseTouchPoint(std::shared_ptr<DragControllerAsyncCtx> asyncCtx, napi_valuetype& valueType)
1239 {
1240     napi_value touchPointNapi = nullptr;
1241     napi_get_named_property(asyncCtx->env, asyncCtx->argv[1], "touchPoint", &touchPointNapi);
1242     napi_typeof(asyncCtx->env, touchPointNapi, &valueType);
1243     if (valueType == napi_object) {
1244         napi_value xNapi = nullptr;
1245         napi_get_named_property(asyncCtx->env, touchPointNapi, "x", &xNapi);
1246         std::optional<Dimension> dx = HandleDimensionType(xNapi, asyncCtx->env);
1247         if (dx == std::nullopt) {
1248             return false;
1249         }
1250         napi_value yNapi = nullptr;
1251         napi_get_named_property(asyncCtx->env, touchPointNapi, "y", &yNapi);
1252         std::optional<Dimension> dy = HandleDimensionType(yNapi, asyncCtx->env);
1253         if (dy == std::nullopt) {
1254             return false;
1255         }
1256         asyncCtx->touchPoint = DimensionOffset(dx.value(), dy.value());
1257     } else {
1258         return false;
1259     }
1260     return true;
1261 }
1262 
ParseDataLoadParams(std::shared_ptr<DragControllerAsyncCtx> asyncCtx,napi_valuetype & valueType)1263 bool ParseDataLoadParams(std::shared_ptr<DragControllerAsyncCtx> asyncCtx, napi_valuetype& valueType)
1264 {
1265     CHECK_NULL_RETURN(asyncCtx, false);
1266     napi_value dataLoadParamsNApi = nullptr;
1267     napi_get_named_property(asyncCtx->env, asyncCtx->argv[1], "dataLoadParams", &dataLoadParamsNApi);
1268     napi_typeof(asyncCtx->env, dataLoadParamsNApi, &valueType);
1269     if (valueType == napi_object) {
1270         auto dataLoadParams = UdmfClient::GetInstance()->TransformDataLoadParams(asyncCtx->env, dataLoadParamsNApi);
1271         CHECK_NULL_RETURN(dataLoadParams, false);
1272         asyncCtx->dataLoadParams = dataLoadParams;
1273         asyncCtx->unifiedData = nullptr;
1274         return true;
1275     }
1276     return false;
1277 }
1278 
ParseDragItemInfoParam(std::shared_ptr<DragControllerAsyncCtx> asyncCtx,std::string & errMsg)1279 bool ParseDragItemInfoParam(std::shared_ptr<DragControllerAsyncCtx> asyncCtx, std::string& errMsg)
1280 {
1281     CHECK_NULL_RETURN(asyncCtx, false);
1282     napi_valuetype valueType = napi_undefined;
1283     napi_typeof(asyncCtx->env, asyncCtx->argv[0], &valueType);
1284     if (valueType == napi_function) {
1285         asyncCtx->customBuilder = asyncCtx->argv[0];
1286         return true;
1287     }
1288 
1289     if (valueType != napi_object) {
1290         errMsg = "The type of first parameter is incorrect.";
1291         return false;
1292     }
1293     // Parse the DragItemInfo
1294     napi_value pixelMapValue;
1295     napi_get_named_property(asyncCtx->env, asyncCtx->argv[0], "pixelMap", &pixelMapValue);
1296     PixelMapNapiEntry pixelMapNapiEntry = Framework::JsEngine::GetPixelMapNapiEntry();
1297     if (pixelMapNapiEntry == nullptr) {
1298         TAG_LOGW(AceLogTag::ACE_DRAG, "failed to parse pixelMap from the first argument");
1299     } else {
1300         void* pixmapPtrAddr = pixelMapNapiEntry(asyncCtx->env, pixelMapValue);
1301         if (pixmapPtrAddr == nullptr) {
1302             napi_get_named_property(asyncCtx->env, asyncCtx->argv[0], "builder", &(asyncCtx->customBuilder));
1303             napi_typeof(asyncCtx->env, asyncCtx->customBuilder, &valueType);
1304             if (valueType != napi_function) {
1305                 errMsg = "The first parameter is not a pixelMap or customBuilder.";
1306                 return false;
1307             }
1308         } else {
1309             asyncCtx->pixelMap = *(reinterpret_cast<std::shared_ptr<Media::PixelMap>*>(pixmapPtrAddr));
1310         }
1311     }
1312 
1313     napi_value extraInfoValue;
1314     napi_get_named_property(asyncCtx->env, asyncCtx->argv[0], "extraInfo", &extraInfoValue);
1315     napi_typeof(asyncCtx->env, extraInfoValue, &valueType);
1316     if (valueType == napi_string) {
1317         GetNapiString(asyncCtx->env, extraInfoValue, asyncCtx->extraParams, valueType);
1318     } else if (valueType != napi_undefined) {
1319         errMsg = "The type of extraInfo of the first parameter is incorrect.";
1320         return false;
1321     }
1322     return true;
1323 }
1324 
GetPixelMapByCustom(std::shared_ptr<DragControllerAsyncCtx> asyncCtx)1325 bool GetPixelMapByCustom(std::shared_ptr<DragControllerAsyncCtx> asyncCtx)
1326 {
1327     CHECK_NULL_RETURN(asyncCtx, false);
1328     napi_escapable_handle_scope scope = nullptr;
1329     napi_open_escapable_handle_scope(asyncCtx->env, &scope);
1330     auto delegate = EngineHelper::GetCurrentDelegateSafely();
1331     if (!delegate) {
1332         NapiThrow(asyncCtx->env, "ace engine delegate is null", ERROR_CODE_INTERNAL_ERROR);
1333         napi_close_escapable_handle_scope(asyncCtx->env, scope);
1334         return false;
1335     }
1336     auto callback = [asyncCtx](std::shared_ptr<Media::PixelMap> pixelMap, int32_t errCode,
1337         std::function<void()> finishCallback) {
1338         CHECK_NULL_VOID(asyncCtx);
1339         auto container = AceEngine::Get().GetContainer(asyncCtx->instanceId);
1340         CHECK_NULL_VOID(container);
1341         auto taskExecutor = container->GetTaskExecutor();
1342         CHECK_NULL_VOID(taskExecutor);
1343         taskExecutor->PostTask(
1344             [finishCallback]() {
1345                 CHECK_NULL_VOID(finishCallback);
1346                 finishCallback();
1347             },
1348             TaskExecutor::TaskType::JS, "ArkUIGetPixelMapByCustom");
1349         CHECK_NULL_VOID(pixelMap);
1350         asyncCtx->errCode = errCode;
1351         asyncCtx->pixelMap = std::move(pixelMap);
1352         OnComplete(asyncCtx);
1353     };
1354     auto builder = [build = asyncCtx->customBuilder, env = asyncCtx->env] {
1355         napi_call_function(env, nullptr, build, 0, nullptr, nullptr);
1356     };
1357     NG::SnapshotParam param;
1358     param.delay = CREATE_PIXELMAP_DELAY_TIME;
1359     param.checkImageStatus = true;
1360     param.options.waitUntilRenderFinished = true;
1361     delegate->CreateSnapshot(builder, callback, true, param);
1362     napi_close_escapable_handle_scope(asyncCtx->env, scope);
1363     return true;
1364 }
1365 
GetPixelMapArrayByCustom(std::shared_ptr<DragControllerAsyncCtx> asyncCtx,napi_value customBuilder,int arrayLength)1366 bool GetPixelMapArrayByCustom(std::shared_ptr<DragControllerAsyncCtx> asyncCtx,
1367     napi_value customBuilder, int arrayLength)
1368 {
1369     CHECK_NULL_RETURN(asyncCtx, false);
1370     napi_escapable_handle_scope scope = nullptr;
1371     napi_open_escapable_handle_scope(asyncCtx->env, &scope);
1372 
1373     auto delegate = EngineHelper::GetCurrentDelegateSafely();
1374     if (!delegate) {
1375         NapiThrow(asyncCtx->env, "ace engine delegate is null", ERROR_CODE_INTERNAL_ERROR);
1376         napi_close_escapable_handle_scope(asyncCtx->env, scope);
1377         return false;
1378     }
1379     auto callback = [asyncCtx, arrayLength](
1380         std::shared_ptr<Media::PixelMap> pixelMap, int32_t errCode, std::function<void()> finishCallback) {
1381         CHECK_NULL_VOID(asyncCtx);
1382         auto container = AceEngine::Get().GetContainer(asyncCtx->instanceId);
1383         CHECK_NULL_VOID(container);
1384         auto taskExecutor = container->GetTaskExecutor();
1385         CHECK_NULL_VOID(taskExecutor);
1386         taskExecutor->PostTask(
1387             [finishCallback]() {
1388                 CHECK_NULL_VOID(finishCallback);
1389                 finishCallback();
1390             },
1391             TaskExecutor::TaskType::JS, "ArkUIGetPixelMapArrayByCustom");
1392         CHECK_NULL_VOID(pixelMap);
1393         asyncCtx->errCode = errCode;
1394         asyncCtx->pixelMapList.push_back(std::move(pixelMap));
1395         asyncCtx->parseBuilderCount++;
1396         if (asyncCtx->parseBuilderCount == arrayLength) {
1397             OnMultipleComplete(asyncCtx);
1398         }
1399     };
1400     auto builder = [build = customBuilder, env = asyncCtx->env] {
1401         napi_call_function(env, nullptr, build, 0, nullptr, nullptr);
1402     };
1403     NG::SnapshotParam param;
1404     param.delay = CREATE_PIXELMAP_DELAY_TIME;
1405     param.checkImageStatus = true;
1406     param.options.waitUntilRenderFinished = true;
1407     delegate->CreateSnapshot(builder, callback, true, param);
1408     napi_close_escapable_handle_scope(asyncCtx->env, scope);
1409     return true;
1410 }
1411 
ParseExtraInfo(std::shared_ptr<DragControllerAsyncCtx> asyncCtx,std::string & errMsg,napi_value element)1412 bool ParseExtraInfo(std::shared_ptr<DragControllerAsyncCtx> asyncCtx, std::string& errMsg, napi_value element)
1413 {
1414     CHECK_NULL_RETURN(asyncCtx, false);
1415     napi_value extraInfoValue;
1416     napi_get_named_property(asyncCtx->env, element, "extraInfo", &extraInfoValue);
1417     napi_valuetype valueType = napi_undefined;
1418     napi_typeof(asyncCtx->env, extraInfoValue, &valueType);
1419     if (valueType != napi_string && valueType != napi_undefined) {
1420         errMsg = "The type of extraInfo of the first parameter is incorrect.";
1421         return false;
1422     }
1423     GetNapiString(asyncCtx->env, extraInfoValue, asyncCtx->extraParams, valueType);
1424     return true;
1425 }
1426 
ParsePixelMapAndBuilder(std::shared_ptr<DragControllerAsyncCtx> asyncCtx,std::string & errMsg,napi_value element)1427 bool ParsePixelMapAndBuilder(std::shared_ptr<DragControllerAsyncCtx> asyncCtx, std::string& errMsg, napi_value element)
1428 {
1429     CHECK_NULL_RETURN(asyncCtx, false);
1430     napi_value pixelMapValue;
1431     napi_get_named_property(asyncCtx->env, element, "pixelMap", &pixelMapValue);
1432     PixelMapNapiEntry pixelMapNapiEntry = Framework::JsEngine::GetPixelMapNapiEntry();
1433     if (pixelMapNapiEntry == nullptr) {
1434         TAG_LOGW(AceLogTag::ACE_DRAG, "failed to parse pixelMap from the first argument");
1435     } else {
1436         void* pixmapPtrAddr = pixelMapNapiEntry(asyncCtx->env, pixelMapValue);
1437         if (pixmapPtrAddr == nullptr) {
1438             TAG_LOGW(AceLogTag::ACE_DRAG, "the pixelMap parsed from the first argument is null");
1439             napi_value customBuilderValue;
1440             napi_get_named_property(asyncCtx->env, element, "builder", &customBuilderValue);
1441             napi_valuetype valueType = napi_undefined;
1442             napi_typeof(asyncCtx->env, customBuilderValue, &valueType);
1443             if (valueType != napi_function) {
1444                 errMsg = "The type of customBuilder of the first parameter is incorrect.";
1445                 return false;
1446             }
1447             napi_ref ref = nullptr;
1448             napi_create_reference(asyncCtx->env, customBuilderValue, 1, &ref);
1449             asyncCtx->customBuilderList.push_back(ref);
1450         } else {
1451             asyncCtx->pixelMapList.push_back(*(reinterpret_cast<std::shared_ptr<Media::PixelMap>*>(pixmapPtrAddr)));
1452         }
1453     }
1454     return true;
1455 }
1456 
ParseDragItemListInfoParam(std::shared_ptr<DragControllerAsyncCtx> asyncCtx,std::string & errMsg)1457 bool ParseDragItemListInfoParam(std::shared_ptr<DragControllerAsyncCtx> asyncCtx, std::string& errMsg)
1458 {
1459     CHECK_NULL_RETURN(asyncCtx, false);
1460     bool isParseSucess;
1461     uint32_t arrayLength = 0;
1462     napi_get_array_length(asyncCtx->env, asyncCtx->argv[0], &arrayLength);
1463     for (size_t i = 0; i < arrayLength; i++) {
1464         bool hasElement = false;
1465         napi_has_element(asyncCtx->env, asyncCtx->argv[0], i, &hasElement);
1466         napi_value element = nullptr;
1467         napi_get_element(asyncCtx->env, asyncCtx->argv[0], i, &element);
1468         napi_valuetype valueType = napi_undefined;
1469         napi_typeof(asyncCtx->env, element, &valueType);
1470         if (valueType == napi_function) {
1471             napi_ref ref = nullptr;
1472             napi_create_reference(asyncCtx->env, element, 1, &ref);
1473             asyncCtx->customBuilderList.push_back(ref);
1474             isParseSucess = true;
1475             continue;
1476         }
1477         if (valueType != napi_object) {
1478             errMsg = "The type of first parameter is incorrect";
1479             isParseSucess = false;
1480             break;
1481         }
1482         if (!ParseExtraInfo(asyncCtx, errMsg, element)) {
1483             errMsg = "The type of first parameter is incorrect by extraInfo";
1484             isParseSucess = false;
1485             break;
1486         }
1487         if (!ParsePixelMapAndBuilder(asyncCtx, errMsg, element)) {
1488             errMsg = "The type of first parameter is incorrect by pixelMap or builder";
1489             isParseSucess = false;
1490             break;
1491         }
1492         isParseSucess = true;
1493         continue;
1494     }
1495     return isParseSucess;
1496 }
1497 
ParseDragParam(std::shared_ptr<DragControllerAsyncCtx> asyncCtx,std::string & errMsg)1498 bool ParseDragParam(std::shared_ptr<DragControllerAsyncCtx> asyncCtx, std::string& errMsg)
1499 {
1500     CHECK_NULL_RETURN(asyncCtx, false);
1501     napi_valuetype valueType = napi_undefined;
1502     napi_typeof(asyncCtx->env, asyncCtx->argv[0], &valueType);
1503     if (valueType == napi_function) {
1504         asyncCtx->customBuilder = asyncCtx->argv[0];
1505         return true;
1506     }
1507     if (valueType != napi_object) {
1508         errMsg = "The type of first parameter is incorrect.";
1509         return false;
1510     }
1511 
1512     bool isArray = false;
1513     napi_is_array(asyncCtx->env, asyncCtx->argv[0], &isArray);
1514     if (isArray) {
1515         TAG_LOGI(AceLogTag::ACE_DRAG, "drag controller is multi object drag.");
1516         asyncCtx->isArray = true;
1517         return ParseDragItemListInfoParam(asyncCtx, errMsg);
1518     }
1519     asyncCtx->isArray = false;
1520     return ParseDragItemInfoParam(asyncCtx, errMsg);
1521 }
1522 
ApplyPreviewOptionsFromModifier(std::shared_ptr<DragControllerAsyncCtx> asyncCtx,napi_value modifierObj,NG::DragPreviewOption & option)1523 bool ApplyPreviewOptionsFromModifier(
1524     std::shared_ptr<DragControllerAsyncCtx> asyncCtx, napi_value modifierObj, NG::DragPreviewOption& option)
1525 {
1526     CHECK_NULL_RETURN(asyncCtx, false);
1527     napi_valuetype valueType = napi_undefined;
1528     napi_typeof(asyncCtx->env, modifierObj, &valueType);
1529     if (valueType == napi_undefined) {
1530         return true;
1531     }
1532     if (valueType != napi_object) {
1533         return false;
1534     }
1535 
1536     napi_value globalObj = nullptr;
1537     napi_get_global(asyncCtx->env, &globalObj);
1538     napi_value globalFunc = nullptr;
1539     napi_get_named_property(asyncCtx->env, globalObj, "applyImageModifierToNode", &globalFunc);
1540     napi_typeof(asyncCtx->env, globalFunc, &valueType);
1541     if (globalFunc == nullptr || valueType != napi_function) {
1542         return false;
1543     }
1544 
1545     auto applyOnNodeSync =
1546         [modifierObj, globalFunc, asyncCtx](WeakPtr<NG::FrameNode> frameNode) {
1547             // convert nodeptr to js value
1548             auto nodePtr = frameNode.Upgrade();
1549             const size_t size = 64; // fake size for gc
1550             napi_value nodeJsValue = nullptr;
1551             napi_create_external_with_size(
1552                 asyncCtx->env, static_cast<void*>(AceType::RawPtr(nodePtr)),
1553                 [](napi_env env, void* data, void* hint) {}, static_cast<void*>(AceType::RawPtr(nodePtr)),
1554                 &nodeJsValue, size);
1555             if (nodeJsValue == nullptr) {
1556                 return;
1557             }
1558             // apply modifier
1559             napi_value ret;
1560             napi_value params[2];
1561             params[0] = modifierObj;
1562             params[1] = nodeJsValue;
1563             napi_call_function(asyncCtx->env, nullptr, globalFunc, 2, params, &ret);
1564         };
1565 
1566     NG::DragDropFuncWrapper::UpdateDragPreviewOptionsFromModifier(applyOnNodeSync, option);
1567     return true;
1568 }
1569 
GetNamedPropertyModifier(std::shared_ptr<DragControllerAsyncCtx> asyncCtx,napi_value previewOptionsNApi,std::string & errMsg)1570 bool GetNamedPropertyModifier(
1571     std::shared_ptr<DragControllerAsyncCtx> asyncCtx, napi_value previewOptionsNApi, std::string& errMsg)
1572 {
1573     napi_value modifierObj = nullptr;
1574     napi_get_named_property(asyncCtx->env, previewOptionsNApi, "modifier", &modifierObj);
1575     if (!ApplyPreviewOptionsFromModifier(asyncCtx, modifierObj, asyncCtx->dragPreviewOption)) {
1576         errMsg = "apply modifier failed.";
1577         return false;
1578     }
1579     return true;
1580 }
1581 
SetDragPreviewOptionMode(std::shared_ptr<DragControllerAsyncCtx> asyncCtx,napi_value & modeNApi,std::string & errMsg,bool & isAuto)1582 bool SetDragPreviewOptionMode(std::shared_ptr<DragControllerAsyncCtx> asyncCtx, napi_value& modeNApi,
1583     std::string& errMsg, bool& isAuto)
1584 {
1585     napi_valuetype valueType = napi_undefined;
1586     napi_typeof(asyncCtx->env, modeNApi, &valueType);
1587     if (valueType == napi_undefined) {
1588         return true;
1589     } else if (valueType != napi_number) {
1590         errMsg = "mode type is wrong";
1591         return false;
1592     } else if (isAuto) {
1593         return true;
1594     }
1595 
1596     int32_t dragPreviewMode = 0;
1597     napi_get_value_int32(asyncCtx->env, modeNApi, &dragPreviewMode);
1598     auto mode = static_cast<NG::DragPreviewMode>(dragPreviewMode);
1599     switch (mode) {
1600         case NG::DragPreviewMode::AUTO:
1601             asyncCtx->dragPreviewOption.ResetDragPreviewMode();
1602             isAuto = true;
1603             break;
1604         case NG::DragPreviewMode::DISABLE_SCALE:
1605             asyncCtx->dragPreviewOption.isScaleEnabled = false;
1606             break;
1607         case NG::DragPreviewMode::ENABLE_DEFAULT_SHADOW:
1608             asyncCtx->dragPreviewOption.isDefaultShadowEnabled = true;
1609             break;
1610         case NG::DragPreviewMode::ENABLE_DEFAULT_RADIUS:
1611             asyncCtx->dragPreviewOption.isDefaultRadiusEnabled = true;
1612             break;
1613         default:
1614             break;
1615     }
1616     return true;
1617 }
1618 
ParseDragPreviewMode(std::shared_ptr<DragControllerAsyncCtx> asyncCtx,napi_value & previewOptionsNApi,std::string & errMsg)1619 bool ParseDragPreviewMode(std::shared_ptr<DragControllerAsyncCtx> asyncCtx,
1620     napi_value& previewOptionsNApi, std::string& errMsg)
1621 {
1622     napi_value modeNApi = nullptr;
1623     napi_get_named_property(asyncCtx->env, previewOptionsNApi, "mode", &modeNApi);
1624     bool isArray = false;
1625     bool isAuto = false;
1626     napi_is_array(asyncCtx->env, modeNApi, &isArray);
1627     if (isArray) {
1628         uint32_t arrayLength = 0;
1629         napi_get_array_length(asyncCtx->env, modeNApi, &arrayLength);
1630         for (size_t i = 0; i < arrayLength; i++) {
1631             bool hasElement = false;
1632             napi_has_element(asyncCtx->env, modeNApi, i, &hasElement);
1633             if (!hasElement) {
1634                 continue;
1635             }
1636             napi_value element = nullptr;
1637             napi_get_element(asyncCtx->env, modeNApi, i, &element);
1638             if (!SetDragPreviewOptionMode(asyncCtx, element, errMsg, isAuto)) {
1639                 return false;
1640             }
1641         }
1642     } else if (!SetDragPreviewOptionMode(asyncCtx, modeNApi, errMsg, isAuto)) {
1643         return false;
1644     }
1645     NG::DragDropFuncWrapper::UpdatePreviewOptionDefaultAttr(asyncCtx->dragPreviewOption);
1646     return true;
1647 }
1648 
GetCurrentDipScale(std::shared_ptr<DragControllerAsyncCtx> asyncCtx)1649 void GetCurrentDipScale(std::shared_ptr<DragControllerAsyncCtx> asyncCtx)
1650 {
1651     auto container = AceEngine::Get().GetContainer(asyncCtx->instanceId);
1652     CHECK_NULL_VOID(container);
1653     auto pipeline = container->GetPipelineContext();
1654     CHECK_NULL_VOID(pipeline);
1655     asyncCtx->dipScale = pipeline->GetDipScale();
1656 }
1657 
ParsePreviewOptions(std::shared_ptr<DragControllerAsyncCtx> asyncCtx,napi_valuetype & valueType,std::string & errMsg)1658 bool ParsePreviewOptions(
1659     std::shared_ptr<DragControllerAsyncCtx> asyncCtx, napi_valuetype& valueType, std::string& errMsg)
1660 {
1661     CHECK_NULL_RETURN(asyncCtx, false);
1662     napi_handle_scope scope = nullptr;
1663     napi_open_handle_scope(asyncCtx->env, &scope);
1664     asyncCtx->dragPreviewOption.isNumber = false;
1665     asyncCtx->dragPreviewOption.isShowBadge = true;
1666     napi_value previewOptionsNApi = nullptr;
1667     napi_get_named_property(asyncCtx->env, asyncCtx->argv[1], "previewOptions", &previewOptionsNApi);
1668     napi_typeof(asyncCtx->env, previewOptionsNApi, &valueType);
1669     if (valueType == napi_object) {
1670         if (!ParseDragPreviewMode(asyncCtx, previewOptionsNApi, errMsg)) {
1671             napi_close_handle_scope(asyncCtx->env, scope);
1672             return false;
1673         }
1674 
1675         napi_value numberBadgeNApi = nullptr;
1676         napi_get_named_property(asyncCtx->env, previewOptionsNApi, "numberBadge", &numberBadgeNApi);
1677         napi_typeof(asyncCtx->env, numberBadgeNApi, &valueType);
1678         if (valueType == napi_number) {
1679             int64_t number = 0;
1680             napi_get_value_int64(asyncCtx->env, numberBadgeNApi, &number);
1681             if (number < 0 || number > INT_MAX) {
1682                 asyncCtx->dragPreviewOption.isNumber = false;
1683                 asyncCtx->dragPreviewOption.isShowBadge = true;
1684             } else {
1685                 asyncCtx->dragPreviewOption.isNumber = true;
1686                 asyncCtx->dragPreviewOption.isShowBadge = false;
1687                 asyncCtx->dragPreviewOption.badgeNumber = number;
1688             }
1689         } else if (valueType == napi_boolean) {
1690             asyncCtx->dragPreviewOption.isNumber = false;
1691             napi_get_value_bool(asyncCtx->env, numberBadgeNApi, &asyncCtx->dragPreviewOption.isShowBadge);
1692         } else if (valueType != napi_undefined) {
1693             errMsg = "numberBadge type is wrong.";
1694             napi_close_handle_scope(asyncCtx->env, scope);
1695             return false;
1696         }
1697 
1698         if (!(GetNamedPropertyModifier(asyncCtx, previewOptionsNApi, errMsg))) {
1699             napi_close_handle_scope(asyncCtx->env, scope);
1700             return false;
1701         }
1702     } else if (valueType != napi_undefined) {
1703         errMsg = "previewOptions type is wrong";
1704         napi_close_handle_scope(asyncCtx->env, scope);
1705         return false;
1706     }
1707     napi_close_handle_scope(asyncCtx->env, scope);
1708     return true;
1709 }
1710 
ParseDragInfoParam(std::shared_ptr<DragControllerAsyncCtx> asyncCtx,std::string & errMsg)1711 bool ParseDragInfoParam(std::shared_ptr<DragControllerAsyncCtx> asyncCtx, std::string& errMsg)
1712 {
1713     CHECK_NULL_RETURN(asyncCtx, false);
1714     napi_valuetype valueType = napi_undefined;
1715     napi_typeof(asyncCtx->env, asyncCtx->argv[1], &valueType);
1716     if (valueType != napi_object) {
1717         errMsg = "The type of second parameter is incorrect.";
1718         return false;
1719     }
1720     napi_value pointerIdNApi = nullptr;
1721     napi_status status = napi_ok;
1722     napi_get_named_property(asyncCtx->env, asyncCtx->argv[1], "pointerId", &pointerIdNApi);
1723     napi_typeof(asyncCtx->env, pointerIdNApi, &valueType);
1724     if (valueType != napi_number) {
1725         errMsg = "pointerId which type is number must be given";
1726         return false;
1727     }
1728     status = napi_get_value_int32(asyncCtx->env, pointerIdNApi, &asyncCtx->dragPointerEvent.pointerId);
1729     if (status != napi_ok) {
1730         errMsg = "parse pointerId fail";
1731         return false;
1732     }
1733 
1734     napi_value dataNApi = nullptr;
1735     napi_get_named_property(asyncCtx->env, asyncCtx->argv[1], "data", &dataNApi);
1736     napi_typeof(asyncCtx->env, dataNApi, &valueType);
1737     if (valueType == napi_object) {
1738         asyncCtx->unifiedData = UdmfClient::GetInstance()->TransformUnifiedData(dataNApi);
1739     } else if (valueType != napi_undefined) {
1740         errMsg = "data's type is wrong";
1741         return false;
1742     }
1743 
1744     napi_value extraParamsNApi = nullptr;
1745     napi_get_named_property(asyncCtx->env, asyncCtx->argv[1], "extraParams", &extraParamsNApi);
1746     napi_typeof(asyncCtx->env, extraParamsNApi, &valueType);
1747     if (valueType == napi_string) {
1748         GetNapiString(asyncCtx->env, extraParamsNApi, asyncCtx->extraParams, valueType);
1749     } else if (valueType != napi_undefined) {
1750         errMsg = "extraParams's type is wrong";
1751         return false;
1752     }
1753 
1754     if (!ParsePreviewOptions(asyncCtx, valueType, errMsg)) {
1755         return false;
1756     }
1757 
1758     GetCurrentDipScale(asyncCtx);
1759     asyncCtx->hasTouchPoint = ParseTouchPoint(asyncCtx, valueType);
1760 
1761     ParseDataLoadParams(asyncCtx, valueType);
1762     return true;
1763 }
1764 
CheckAndParseParams(std::shared_ptr<DragControllerAsyncCtx> asyncCtx,std::string & errMsg)1765 bool CheckAndParseParams(std::shared_ptr<DragControllerAsyncCtx> asyncCtx, std::string& errMsg)
1766 {
1767     // Check the number of the argument
1768     CHECK_NULL_RETURN(asyncCtx, false);
1769     if ((asyncCtx->argc != ARG_COUNT_2) && (asyncCtx->argc != ARG_COUNT_3)) {
1770         errMsg = "The number of parameters must be 2 or 3.";
1771         return false;
1772     }
1773 
1774     // Check and parse the first parameter
1775     if (!ParseDragParam(asyncCtx, errMsg)) {
1776         return false;
1777     }
1778 
1779     // Check and parse the second parameter
1780     return ParseDragInfoParam(asyncCtx, errMsg);
1781 }
1782 
CreateCallback(std::shared_ptr<DragControllerAsyncCtx> asyncCtx,napi_value * result)1783 void CreateCallback(std::shared_ptr<DragControllerAsyncCtx> asyncCtx, napi_value* result)
1784 {
1785     CHECK_NULL_VOID(asyncCtx);
1786     if (asyncCtx->argc == ARG_COUNT_3) {
1787         // Create the JsCallback
1788         napi_create_reference(asyncCtx->env, asyncCtx->argv[2], 1, &asyncCtx->callbackRef);
1789     }
1790     if (!asyncCtx->callbackRef) {
1791         // Create the promise
1792         napi_create_promise(asyncCtx->env, &asyncCtx->deferred, result);
1793     } else {
1794         napi_get_undefined(asyncCtx->env, result);
1795     }
1796 }
1797 
InitializeDragControllerCtx(napi_env env,napi_callback_info info,std::shared_ptr<DragControllerAsyncCtx> asyncCtx)1798 void InitializeDragControllerCtx(napi_env env, napi_callback_info info,
1799     std::shared_ptr<DragControllerAsyncCtx> asyncCtx)
1800 {
1801     CHECK_NULL_VOID(asyncCtx);
1802     napi_value thisVar = nullptr;
1803     void* data = nullptr;
1804     asyncCtx->instanceId = Container::CurrentIdSafely();
1805     asyncCtx->env = env;
1806     // get arguments from JS
1807     napi_get_cb_info(asyncCtx->env, info, &(asyncCtx->argc), asyncCtx->argv, &thisVar, &data);
1808 }
1809 
getParameterType(std::shared_ptr<DragControllerAsyncCtx> asyncCtx)1810 ParameterType getParameterType(std::shared_ptr<DragControllerAsyncCtx> asyncCtx)
1811 {
1812     CHECK_NULL_RETURN(asyncCtx, ParameterType::ERROR);
1813     if (asyncCtx->pixelMap != nullptr) {
1814         return ParameterType::DRAGITEMINFO;
1815     }
1816     if (asyncCtx->customBuilder != nullptr) {
1817         return ParameterType::CUSTOMBUILDER;
1818     }
1819     if (!asyncCtx->pixelMapList.empty() && asyncCtx->customBuilderList.empty()) {
1820         return ParameterType::DRAGITEMINFO_ARRAY;
1821     }
1822     if (!asyncCtx->customBuilderList.empty() || !asyncCtx->pixelMapList.empty()) {
1823         return ParameterType::MIX;
1824     } else {
1825         return ParameterType::ERROR;
1826     }
1827 }
1828 
HandleStopDragCallback(std::shared_ptr<DragControllerAsyncCtx> asyncCtx,const RefPtr<Container> & container)1829 void HandleStopDragCallback(std::shared_ptr<DragControllerAsyncCtx> asyncCtx, const RefPtr<Container>& container)
1830 {
1831     CHECK_NULL_VOID(asyncCtx);
1832     CHECK_NULL_VOID(container);
1833     bool needPostStopDrag = false;
1834     {
1835         std::lock_guard<std::mutex> lock(asyncCtx->dragStateMutex);
1836         needPostStopDrag = (asyncCtx->dragState == DragState::SENDING);
1837         asyncCtx->dragState = DragState::REJECT;
1838     }
1839     if (needPostStopDrag) {
1840         auto pipelineContext = container->GetPipelineContext();
1841         CHECK_NULL_VOID(pipelineContext);
1842         pipelineContext->ResetDragging();
1843         auto taskExecutor = container->GetTaskExecutor();
1844         CHECK_NULL_VOID(taskExecutor);
1845         auto windowId = container->GetWindowId();
1846         taskExecutor->PostTask(
1847             [asyncCtx, windowId]() {
1848                 CHECK_NULL_VOID(asyncCtx);
1849                 napi_handle_scope scope = nullptr;
1850                 napi_open_handle_scope(asyncCtx->env, &scope);
1851                 HandleFail(asyncCtx, ERROR_CODE_INTERNAL_ERROR, "drag state error, stop drag.");
1852                 napi_close_handle_scope(asyncCtx->env, scope);
1853                 TAG_LOGI(AceLogTag::ACE_DRAG,
1854                     "drag state is reject, stop drag, windowId is %{public}d.", windowId);
1855                 Msdp::DeviceStatus::DragDropResult dropResult { Msdp::DeviceStatus::DragResult::DRAG_CANCEL, false,
1856                     windowId, Msdp::DeviceStatus::DragBehavior::UNKNOWN };
1857                 Msdp::DeviceStatus::InteractionManager::GetInstance()->StopDrag(dropResult);
1858                 Msdp::DeviceStatus::InteractionManager::GetInstance()->SetDragWindowVisible(false);
1859             },
1860             TaskExecutor::TaskType::JS, "ArkUIDragStop",  PriorityType::VIP);
1861     }
1862 }
1863 
ConfirmCurPointerEventInfo(std::shared_ptr<DragControllerAsyncCtx> asyncCtx,const RefPtr<Container> & container)1864 bool ConfirmCurPointerEventInfo(std::shared_ptr<DragControllerAsyncCtx> asyncCtx, const RefPtr<Container>& container)
1865 {
1866     CHECK_NULL_RETURN(asyncCtx, false);
1867     CHECK_NULL_RETURN(container, false);
1868     StopDragCallback stopDragCallback = [asyncCtx, container]() {
1869         HandleStopDragCallback(asyncCtx, container);
1870     };
1871     bool getPointSuccess = container->GetCurPointerEventInfo(
1872         asyncCtx->dragPointerEvent, std::move(stopDragCallback));
1873     if (asyncCtx->dragPointerEvent.sourceType == SOURCE_TYPE_MOUSE) {
1874         asyncCtx->dragPointerEvent.pointerId = MOUSE_POINTER_ID;
1875     } else if (asyncCtx->dragPointerEvent.sourceType == SOURCE_TYPE_TOUCH &&
1876         static_cast<int32_t>(asyncCtx->dragPointerEvent.sourceTool) == SOURCE_TOOL_PEN) {
1877         asyncCtx->dragPointerEvent.pointerId = PEN_POINTER_ID;
1878     }
1879     return getPointSuccess;
1880 }
1881 
CheckDragging(const RefPtr<Container> & container)1882 static bool CheckDragging(const RefPtr<Container>& container)
1883 {
1884     CHECK_NULL_RETURN(container, false);
1885     auto pipelineContext = container->GetPipelineContext();
1886     if (!pipelineContext || !pipelineContext->IsDragging()) {
1887         return false;
1888     }
1889     return true;
1890 }
1891 
JSExecuteDrag(napi_env env,napi_callback_info info)1892 static napi_value JSExecuteDrag(napi_env env, napi_callback_info info)
1893 {
1894     TAG_LOGI(AceLogTag::ACE_DRAG, "executeDrag fuction called.");
1895     napi_escapable_handle_scope scope = nullptr;
1896     napi_open_escapable_handle_scope(env, &scope);
1897 
1898     auto dragAsyncContext = std::make_shared<DragControllerAsyncCtx>();
1899     if (dragAsyncContext == nullptr) {
1900         NapiThrow(env, "create drag controller async context failed.", ERROR_CODE_INTERNAL_ERROR);
1901         napi_close_escapable_handle_scope(env, scope);
1902         return nullptr;
1903     }
1904     InitializeDragControllerCtx(env, info, dragAsyncContext);
1905 
1906     std::string errMsg;
1907     if (!CheckAndParseParams(dragAsyncContext, errMsg)) {
1908         NapiThrow(env, errMsg, ERROR_CODE_PARAM_INVALID);
1909         napi_close_escapable_handle_scope(env, scope);
1910         return nullptr;
1911     }
1912     napi_value result = nullptr;
1913     CreateCallback(dragAsyncContext, &result);
1914     auto container = AceEngine::Get().GetContainer(dragAsyncContext->instanceId);
1915     if (!container) {
1916         NapiThrow(env, "get container failed.", ERROR_CODE_INTERNAL_ERROR);
1917         napi_close_escapable_handle_scope(env, scope);
1918         return nullptr;
1919     }
1920     if (CheckDragging(container)) {
1921         NapiThrow(env, "only one drag is allowed at the same time", ERROR_CODE_INTERNAL_ERROR);
1922         napi_close_escapable_handle_scope(env, scope);
1923         return nullptr;
1924     }
1925     auto getPointSuccess = ConfirmCurPointerEventInfo(dragAsyncContext, container);
1926     if (!getPointSuccess) {
1927         NapiThrow(env, "confirm current point info failed.", ERROR_CODE_INTERNAL_ERROR);
1928         napi_escape_handle(env, scope, result, &result);
1929         napi_close_escapable_handle_scope(env, scope);
1930         return result;
1931     }
1932     SetMouseDragMonitorState(dragAsyncContext, true);
1933     HandleExecuteDrag(env, dragAsyncContext);
1934     napi_escape_handle(env, scope, result, &result);
1935     napi_close_escapable_handle_scope(env, scope);
1936     return result;
1937 }
1938 
JSCreateDragAction(napi_env env,napi_callback_info info)1939 static napi_value JSCreateDragAction(napi_env env, napi_callback_info info)
1940 {
1941     napi_escapable_handle_scope scope = nullptr;
1942     napi_open_escapable_handle_scope(env, &scope);
1943 
1944     auto dragAsyncContext = std::make_shared<DragControllerAsyncCtx>();
1945     if (dragAsyncContext == nullptr) {
1946         NapiThrow(env, "create drag controller async context failed.", ERROR_CODE_INTERNAL_ERROR);
1947         napi_close_escapable_handle_scope(env, scope);
1948         return nullptr;
1949     }
1950     InitializeDragControllerCtx(env, info, dragAsyncContext);
1951 
1952     std::string errMsg = "";
1953     if (!CheckAndParseParams(dragAsyncContext, errMsg)) {
1954         NapiThrow(env, errMsg, ERROR_CODE_PARAM_INVALID);
1955         napi_close_escapable_handle_scope(env, scope);
1956         return nullptr;
1957     }
1958 
1959     auto container = AceEngine::Get().GetContainer(dragAsyncContext->instanceId);
1960     if (!container) {
1961         NapiThrow(env, "get container failed.", ERROR_CODE_INTERNAL_ERROR);
1962         napi_close_escapable_handle_scope(env, scope);
1963         return nullptr;
1964     }
1965 
1966     if (CheckDragging(container)) {
1967         NapiThrow(env, "only one dragAction is allowed at the same time", ERROR_CODE_INTERNAL_ERROR);
1968         napi_close_escapable_handle_scope(env, scope);
1969         return nullptr;
1970     }
1971 
1972     auto getPointSuccess = ConfirmCurPointerEventInfo(dragAsyncContext, container);
1973     if (!getPointSuccess) {
1974         NapiThrow(env, "confirm pointer info failed", ERROR_CODE_PARAM_INVALID);
1975         napi_close_escapable_handle_scope(env, scope);
1976         return nullptr;
1977     }
1978 
1979     napi_value result = nullptr;
1980     napi_create_object(env, &result);
1981     DragAction* dragAction = new DragAction(dragAsyncContext);
1982     dragAction->NapiSerializer(env, result);
1983     if (!result) {
1984         dragAction->DeleteRef();
1985         delete dragAction;
1986         napi_close_escapable_handle_scope(env, scope);
1987         return nullptr;
1988     }
1989     dragAsyncContext->dragAction = dragAction;
1990     napi_escape_handle(env, scope, result, &result);
1991     napi_close_escapable_handle_scope(env, scope);
1992     return result;
1993 }
1994 
JSGetDragPreview(napi_env env,napi_callback_info info)1995 static napi_value JSGetDragPreview(napi_env env, napi_callback_info info)
1996 {
1997     DragPreview* dragPreview = new DragPreview();
1998     napi_value result = nullptr;
1999     napi_create_object(env, &result);
2000     dragPreview->NapiSerializer(env, result);
2001     if (!result) {
2002         delete dragPreview;
2003         return nullptr;
2004     }
2005     return result;
2006 }
2007 #else
2008 
JSGetDragPreview(napi_env env,napi_callback_info info)2009 static napi_value JSGetDragPreview(napi_env env, napi_callback_info info)
2010 {
2011     napi_escapable_handle_scope scope = nullptr;
2012     napi_open_escapable_handle_scope(env, &scope);
2013     NapiThrow(env, "The current environment does not enable drag framework or does not support drag preview.",
2014         ERROR_CODE_INTERNAL_ERROR);
2015     napi_close_escapable_handle_scope(env, scope);
2016     return nullptr;
2017 }
2018 
JSExecuteDrag(napi_env env,napi_callback_info info)2019 static napi_value JSExecuteDrag(napi_env env, napi_callback_info info)
2020 {
2021     napi_escapable_handle_scope scope = nullptr;
2022     napi_open_escapable_handle_scope(env, &scope);
2023     NapiThrow(env, "The current environment does not enable drag framework or does not support pixelMap.",
2024         ERROR_CODE_INTERNAL_ERROR);
2025     napi_close_escapable_handle_scope(env, scope);
2026     return nullptr;
2027 }
2028 
JSCreateDragAction(napi_env env,napi_callback_info info)2029 static napi_value JSCreateDragAction(napi_env env, napi_callback_info info)
2030 {
2031     napi_escapable_handle_scope scope = nullptr;
2032     napi_open_escapable_handle_scope(env, &scope);
2033     NapiThrow(env, "The current environment does not enable drag framework or does not support pixelMap.",
2034         ERROR_CODE_INTERNAL_ERROR);
2035     napi_close_escapable_handle_scope(env, scope);
2036     return nullptr;
2037 }
2038 #endif
2039 
2040 // The default empty implementation function setForegroundColor for dragPreview.
JsDragPreviewSetForegroundColor(napi_env env,napi_callback_info info)2041 static napi_value JsDragPreviewSetForegroundColor(napi_env env, napi_callback_info info)
2042 {
2043     return nullptr;
2044 }
2045 
2046 // The default empty implementation function animate for dragPreview.
JsDragPreviewAnimate(napi_env env,napi_callback_info info)2047 static napi_value JsDragPreviewAnimate(napi_env env, napi_callback_info info)
2048 {
2049     return nullptr;
2050 }
2051 
2052 // The default empty constructor for dragPreview.
DragPreviewConstructor(napi_env env,napi_callback_info info)2053 static napi_value DragPreviewConstructor(napi_env env, napi_callback_info info)
2054 {
2055     napi_value thisArg = nullptr;
2056     void* data = nullptr;
2057     napi_get_cb_info(env, info, nullptr, nullptr, &thisArg, &data);
2058     napi_value global = nullptr;
2059     napi_get_global(env, &global);
2060     return thisArg;
2061 }
2062 
DragControllerExport(napi_env env,napi_value exports)2063 static napi_value DragControllerExport(napi_env env, napi_value exports)
2064 {
2065     napi_value dragStatus = nullptr;
2066     napi_create_object(env, &dragStatus);
2067     napi_value prop = nullptr;
2068     napi_create_uint32(env, DRAG_STARTED, &prop);
2069     napi_set_named_property(env, dragStatus, "STARTED", prop);
2070     napi_create_uint32(env, DRAG_ENDED, &prop);
2071     napi_set_named_property(env, dragStatus, "ENDED", prop);
2072 
2073     napi_property_descriptor dragPreviewDesc[] = {
2074         DECLARE_NAPI_FUNCTION("setForegroundColor", JsDragPreviewSetForegroundColor),
2075         DECLARE_NAPI_FUNCTION("animate", JsDragPreviewAnimate),
2076     };
2077     napi_value classDragPreview = nullptr;
2078     napi_define_class(env, "DragPreview", NAPI_AUTO_LENGTH, DragPreviewConstructor, nullptr,
2079         sizeof(dragPreviewDesc) / sizeof(*dragPreviewDesc), dragPreviewDesc, &classDragPreview);
2080 
2081     napi_property_descriptor dragControllerDesc[] = {
2082         DECLARE_NAPI_FUNCTION("executeDrag", JSExecuteDrag),
2083         DECLARE_NAPI_FUNCTION("getDragPreview", JSGetDragPreview),
2084         DECLARE_NAPI_FUNCTION("createDragAction", JSCreateDragAction),
2085         DECLARE_NAPI_PROPERTY("DragStatus", dragStatus),
2086         DECLARE_NAPI_PROPERTY("DragPreview", classDragPreview),
2087     };
2088     NAPI_CALL(env, napi_define_properties(
2089         env, exports, sizeof(dragControllerDesc) / sizeof(dragControllerDesc[0]), dragControllerDesc));
2090     return exports;
2091 }
2092 
2093 static napi_module dragControllerModule = {
2094     .nm_version = 1,
2095     .nm_flags = 0,
2096     .nm_filename = nullptr,
2097     .nm_register_func = DragControllerExport,
2098     .nm_modname = "arkui.dragController",
2099     .nm_priv = ((void*)0),
2100     .reserved = { 0 },
2101 };
2102 
DragControllerRegister()2103 extern "C" __attribute__((constructor)) void DragControllerRegister()
2104 {
2105     napi_module_register(&dragControllerModule);
2106 }
2107 } // namespace OHOS::Ace::Napi
2108