1 /*
2  * Copyright (c) 2022-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 "core/components_ng/manager/drag_drop/drag_drop_manager.h"
17 #include "drag_drop_manager.h"
18 
19 #include "base/geometry/ng/offset_t.h"
20 #include "base/geometry/point.h"
21 #include "base/subwindow/subwindow_manager.h"
22 #include "base/utils/system_properties.h"
23 #include "base/utils/utils.h"
24 #include "core/common/interaction/interaction_data.h"
25 #include "core/common/interaction/interaction_interface.h"
26 #include "core/components/common/layout/grid_system_manager.h"
27 #include "core/components/common/layout/grid_column_info.h"
28 #include "core/components_ng/manager/drag_drop/drag_drop_behavior_reporter/drag_drop_behavior_reporter.h"
29 #include "core/components_ng/pattern/grid/grid_event_hub.h"
30 #include "core/components_ng/pattern/list/list_event_hub.h"
31 #include "core/components_ng/pattern/menu/wrapper/menu_wrapper_pattern.h"
32 #include "core/components_ng/pattern/root/root_pattern.h"
33 #include "core/components_ng/pattern/text_field/text_field_pattern.h"
34 #include "core/components_v2/inspector/inspector_constants.h"
35 #include "core/pipeline_ng/pipeline_context.h"
36 #include "base/utils/time_util.h"
37 
38 #include "base/geometry/rect.h"
39 #include "core/common/udmf/udmf_client.h"
40 
41 namespace OHOS::Ace::NG {
42 namespace {
43 int64_t g_proxyId = 0;
44 constexpr int32_t MAX_RETRY_TIMES = 3;
45 constexpr int32_t MAX_RETRY_DURATION = 800;
46 constexpr float MOVE_DISTANCE_LIMIT = 20.0f;
47 constexpr uint64_t MOVE_TIME_LIMIT = 6L;
48 constexpr Dimension PRESERVE_HEIGHT = 8.0_vp;
49 constexpr float FIRST_PIXELMAP_OPACITY = 0.6f;
50 constexpr float SECOND_PIXELMAP_OPACITY = 0.3f;
51 constexpr float FIRST_PIXELMAP_ANGLE = 8.0f;
52 constexpr float SECOND_PIXELMAP_ANGLE = -8.0f;
53 constexpr int32_t FIRST_GATHER_PIXEL_MAP = 1;
54 constexpr int32_t SECOND_GATHER_PIXEL_MAP = 2;
55 constexpr int32_t SQUARE_NUMBER = 2;
56 constexpr float TOUCH_DRAG_PIXELMAP_SCALE = 1.05f;
57 constexpr float MAX_DISTANCE_TO_PRE_POINTER = 3.0f;
58 constexpr float DEFAULT_SPRING_RESPONSE = 0.347f;
59 constexpr float MIN_SPRING_RESPONSE = 0.05f;
60 constexpr float DEL_SPRING_RESPONSE = 0.005f;
61 constexpr int32_t RESERVED_DEVICEID = 0xAAAAAAFF;
62 } // namespace
63 
GetMenuRenderContextFromMenuWrapper(const RefPtr<FrameNode> & menuWrapperNode)64 RefPtr<RenderContext> GetMenuRenderContextFromMenuWrapper(const RefPtr<FrameNode>& menuWrapperNode)
65 {
66     CHECK_NULL_RETURN(menuWrapperNode, nullptr);
67     auto menuWrapperPattern = menuWrapperNode->GetPattern<MenuWrapperPattern>();
68     CHECK_NULL_RETURN(menuWrapperPattern, nullptr);
69     auto menuNode = menuWrapperPattern->GetMenu();
70     CHECK_NULL_RETURN(menuNode, nullptr);
71     return menuNode->GetRenderContext();
72 }
73 
GetMenuWrapperNodeFromDrag()74 RefPtr<FrameNode> GetMenuWrapperNodeFromDrag()
75 {
76     auto pipeline = PipelineContext::GetMainPipelineContext();
77     CHECK_NULL_RETURN(pipeline, nullptr);
78     auto dragDropManager = pipeline->GetDragDropManager();
79     CHECK_NULL_RETURN(dragDropManager, nullptr);
80     return dragDropManager->GetMenuWrapperNode();
81 }
82 
CreateAndShowDragWindow(const RefPtr<PixelMap> & pixelMap,const GestureEvent & info)83 RefPtr<DragDropProxy> DragDropManager::CreateAndShowDragWindow(
84     const RefPtr<PixelMap>& pixelMap, const GestureEvent& info)
85 {
86     CHECK_NULL_RETURN(pixelMap, nullptr);
87     SetIsDragged(true);
88     isDragCancel_ = false;
89 #if !defined(PREVIEW)
90     if (GetWindowId() == -1) {
91         const float windowScale = GetWindowScale();
92         pixelMap->Scale(windowScale, windowScale, AceAntiAliasingOption::HIGH);
93     }
94     CreateDragWindow(info, pixelMap->GetWidth(), pixelMap->GetHeight());
95     CHECK_NULL_RETURN(dragWindow_, nullptr);
96     dragWindow_->DrawPixelMap(pixelMap);
97 #endif
98     currentId_ = ++g_proxyId;
99     return MakeRefPtr<DragDropProxy>(currentId_);
100 }
101 
CreateAndShowDragWindow(const RefPtr<UINode> & customNode,const GestureEvent & info)102 RefPtr<DragDropProxy> DragDropManager::CreateAndShowDragWindow(
103     const RefPtr<UINode>& customNode, const GestureEvent& info)
104 {
105     dragWindowRootNode_ = CreateDragRootNode(customNode);
106     CHECK_NULL_RETURN(dragWindowRootNode_, nullptr);
107     SetIsDragged(true);
108     isDragCancel_ = false;
109 #if !defined(PREVIEW)
110     if (dragWindow_) {
111         return nullptr;
112     }
113 
114     auto geometryNode = dragWindowRootNode_->GetGeometryNode();
115     CHECK_NULL_RETURN(geometryNode, nullptr);
116 
117     auto frameRect = geometryNode->GetFrameSize();
118     CreateDragWindow(info, static_cast<uint32_t>(frameRect.Width()), static_cast<uint32_t>(frameRect.Height()));
119     CHECK_NULL_RETURN(dragWindow_, nullptr);
120     dragWindow_->DrawFrameNode(dragWindowRootNode_);
121 #endif
122     currentId_ = ++g_proxyId;
123     return MakeRefPtr<DragDropProxy>(currentId_);
124 }
125 
CreateTextDragDropProxy()126 RefPtr<DragDropProxy> DragDropManager::CreateTextDragDropProxy()
127 {
128     SetIsDragged(true);
129     isDragCancel_ = false;
130     currentId_ = ++g_proxyId;
131     return MakeRefPtr<DragDropProxy>(currentId_);
132 }
133 
CreateDragWindow(const GestureEvent & info,uint32_t width,uint32_t height)134 void DragDropManager::CreateDragWindow(const GestureEvent& info, uint32_t width, uint32_t height)
135 {
136 #if !defined(PREVIEW)
137     auto pipeline = PipelineContext::GetCurrentContext();
138     CHECK_NULL_VOID(pipeline);
139     const int32_t windowId = GetWindowId();
140     const float windowScale = isDragWindowSubWindow_ ? 1.0f : GetWindowScale();
141     const Rect rect = pipeline->GetDisplayWindowRectInfo();
142     const int32_t windowY = static_cast<int32_t>(info.GetGlobalPoint().GetY() * windowScale);
143     const int32_t windowX = static_cast<int32_t>(info.GetGlobalPoint().GetX() * windowScale);
144     dragWindow_ = DragWindow::CreateDragWindow(
145         { "APP_DRAG_WINDOW", windowX + rect.Left(), windowY + rect.Top(), width, height, windowId });
146     if (dragWindow_) {
147         dragWindow_->SetOffset(rect.Left(), rect.Top());
148     } else {
149         TAG_LOGW(AceLogTag::ACE_DRAG, "Create drag window failed!");
150     }
151 #endif
152 }
153 
GetWindowId()154 int32_t DragDropManager::GetWindowId()
155 {
156     auto windowId = -1;
157     auto container = Container::Current();
158     CHECK_NULL_RETURN(container, windowId);
159 
160     if (!container->IsSceneBoardEnabled()) {
161         isDragWindowSubWindow_ = false;
162         return windowId;
163     }
164 
165     if (!container->IsMainWindow()) {
166         // The window manager currently does not support creating child windows within child windows,
167         // so the root main window is used here
168         container = Container::GetContainer(CONTAINER_ID_DIVIDE_SIZE);
169         CHECK_NULL_RETURN(container, windowId);
170         if (!container->IsMainWindow()) {
171             isDragWindowSubWindow_ = false;
172             return windowId;
173         }
174     }
175 
176     windowId = static_cast<int32_t>(container->GetWindowId());
177     isDragWindowSubWindow_ = true;
178 
179     return windowId;
180 }
181 
CreateDragRootNode(const RefPtr<UINode> & customNode)182 RefPtr<FrameNode> DragDropManager::CreateDragRootNode(const RefPtr<UINode>& customNode)
183 {
184     auto pipeline = PipelineContext::GetCurrentContext();
185     CHECK_NULL_RETURN(pipeline, nullptr);
186 
187     auto rootNode = FrameNode::CreateFrameNodeWithTree(
188         V2::ROOT_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), MakeRefPtr<RootPattern>());
189     rootNode->SetActive(true);
190     rootNode->SetHostRootId(pipeline->GetInstanceId());
191     rootNode->SetHostPageId(-1);
192     rootNode->AddChild(customNode);
193     rootNode->AttachToMainTree(false, AceType::RawPtr(pipeline));
194     rootNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
195     pipeline->FlushUITasks();
196     return rootNode;
197 }
198 
UpdateDragWindowPosition(int32_t globalX,int32_t globalY)199 void DragDropManager::UpdateDragWindowPosition(int32_t globalX, int32_t globalY)
200 {
201 #if !defined(PREVIEW)
202     CHECK_NULL_VOID(dragWindow_);
203     dragWindow_->MoveTo(globalX, globalY);
204 #endif
205 }
206 
HideDragPreviewOverlay()207 void DragDropManager::HideDragPreviewOverlay()
208 {
209     auto pipeline = NG::PipelineContext::GetCurrentContext();
210     CHECK_NULL_VOID(pipeline);
211     auto manager = pipeline->GetOverlayManager();
212     CHECK_NULL_VOID(manager);
213     manager->RemovePixelMap();
214     manager->RemoveGatherNode();
215     manager->RemoveDragPixelMap();
216     SubwindowManager::GetInstance()->HidePreviewNG();
217 }
218 
HideDragPreviewWindow(int32_t containerId)219 void DragDropManager::HideDragPreviewWindow(int32_t containerId)
220 {
221     auto overlayManager = GetDragAnimationOverlayManager(containerId);
222     CHECK_NULL_VOID(overlayManager);
223     overlayManager->RemovePixelMap();
224     overlayManager->RemoveGatherNode();
225     overlayManager->RemoveDragPixelMap();
226     SubwindowManager::GetInstance()->HidePreviewNG();
227 }
228 
FindTargetInChildNodes(const RefPtr<UINode> parentNode,std::vector<RefPtr<FrameNode>> hitFrameNodes,bool findDrop)229 RefPtr<FrameNode> DragDropManager::FindTargetInChildNodes(
230     const RefPtr<UINode> parentNode, std::vector<RefPtr<FrameNode>> hitFrameNodes, bool findDrop)
231 {
232     CHECK_NULL_RETURN(parentNode, nullptr);
233     auto parentFrameNode = AceType::DynamicCast<FrameNode>(parentNode);
234     if (parentFrameNode && (!parentFrameNode->IsActive() || !parentFrameNode->IsVisible())) {
235         return nullptr;
236     }
237     auto children = parentFrameNode->GetFrameChildren();
238 
239     for (auto iter = children.rbegin(); iter != children.rend(); iter++) {
240         auto child = iter->Upgrade();
241         if (child == nullptr) {
242             continue;
243         }
244         auto childNode = AceType::DynamicCast<UINode>(child);
245         auto childFindResult = FindTargetInChildNodes(childNode, hitFrameNodes, findDrop);
246         if (childFindResult) {
247             return childFindResult;
248         }
249     }
250 
251     CHECK_NULL_RETURN(parentFrameNode, nullptr);
252     for (auto iter : hitFrameNodes) {
253         if (parentFrameNode == iter) {
254             auto eventHub = parentFrameNode->GetEventHub<EventHub>();
255             if (!eventHub) {
256                 continue;
257             }
258             if ((eventHub->HasOnDrop()) || (eventHub->HasOnItemDrop()) || (eventHub->HasCustomerOnDrop())) {
259                 return parentFrameNode;
260             }
261             if ((V2::UI_EXTENSION_COMPONENT_ETS_TAG == parentFrameNode->GetTag() ||
262                 V2::EMBEDDED_COMPONENT_ETS_TAG == parentFrameNode->GetTag()) &&
263                 (!IsUIExtensionShowPlaceholder(parentFrameNode))) {
264                 return parentFrameNode;
265             }
266         }
267     }
268     return nullptr;
269 }
270 
CheckFrameNodeCanDrop(const RefPtr<FrameNode> & node)271 bool DragDropManager::CheckFrameNodeCanDrop(const RefPtr<FrameNode>& node)
272 {
273     CHECK_NULL_RETURN(node, false);
274     auto eventHub = node->GetEventHub<EventHub>();
275     CHECK_NULL_RETURN(eventHub, false);
276     if ((eventHub->HasOnDrop()) || (eventHub->HasOnItemDrop()) || (eventHub->HasCustomerOnDrop())) {
277         return true;
278     }
279     if ((V2::UI_EXTENSION_COMPONENT_ETS_TAG == node->GetTag() ||
280         V2::EMBEDDED_COMPONENT_ETS_TAG == node->GetTag()) &&
281         (!IsUIExtensionShowPlaceholder(node))) {
282         return true;
283     }
284 
285     return false;
286 }
287 
FindTargetDropNode(const RefPtr<UINode> parentNode,PointF localPoint)288 RefPtr<FrameNode> DragDropManager::FindTargetDropNode(const RefPtr<UINode> parentNode, PointF localPoint)
289 {
290     CHECK_NULL_RETURN(parentNode, nullptr);
291     auto parentFrameNode = AceType::DynamicCast<FrameNode>(parentNode);
292     CHECK_NULL_RETURN(parentFrameNode, nullptr);
293     if (!parentFrameNode->IsActive() || !parentFrameNode->IsVisible()) {
294         return nullptr;
295     }
296     auto renderContext = parentFrameNode->GetRenderContext();
297     CHECK_NULL_RETURN(renderContext, nullptr);
298     auto paintRect = renderContext->GetPaintRectWithoutTransform();
299     FrameNode::MapPointTo(localPoint, parentFrameNode->GetOrRefreshRevertMatrixFromCache());
300     auto subLocalPoint = localPoint - paintRect.GetOffset();
301 
302     auto children = parentFrameNode->GetFrameChildren();
303     for (auto iter = children.rbegin(); iter != children.rend(); iter++) {
304         auto child = iter->Upgrade();
305         if (child == nullptr) {
306             continue;
307         }
308         auto childNode = AceType::DynamicCast<UINode>(child);
309         auto childFindResult = FindTargetDropNode(childNode, subLocalPoint);
310         if (childFindResult) {
311             return childFindResult;
312         }
313     }
314 
315     if (paintRect.IsInRegion(localPoint)) {
316         if (parentFrameNode->GetDragHitTestBlock()) {
317             return parentFrameNode;
318         }
319         if (CheckFrameNodeCanDrop(parentFrameNode)) {
320             return parentFrameNode;
321         }
322     }
323     return nullptr;
324 }
325 
FindDragFrameNodeByPosition(float globalX,float globalY,const RefPtr<FrameNode> & node)326 RefPtr<FrameNode> DragDropManager::FindDragFrameNodeByPosition(float globalX, float globalY,
327     const RefPtr<FrameNode>& node)
328 {
329     auto rootNode = node;
330     if (!rootNode) {
331         auto pipeline = NG::PipelineContext::GetCurrentContext();
332         CHECK_NULL_RETURN(pipeline, nullptr);
333         rootNode = pipeline->GetRootElement();
334     }
335 
336     auto result = FindTargetDropNode(rootNode, {globalX, globalY});
337     if (result) {
338         if (CheckFrameNodeCanDrop(result)) {
339             return result;
340         }
341     }
342     return nullptr;
343 }
344 
CheckDragDropProxy(int64_t id) const345 bool DragDropManager::CheckDragDropProxy(int64_t id) const
346 {
347     return currentId_ == id;
348 }
349 
UpdateDragAllowDrop(const RefPtr<FrameNode> & dragFrameNode,const DragBehavior dragBehavior,const int32_t eventId,bool isCapi)350 void DragDropManager::UpdateDragAllowDrop(
351     const RefPtr<FrameNode>& dragFrameNode, const DragBehavior dragBehavior, const int32_t eventId, bool isCapi)
352 {
353     if (!IsDropAllowed(dragFrameNode)) {
354         // simplified specifications for drag cursor style, no longer showing forbidden drag cursor
355         UpdateDragStyle(DragCursorStyleCore::MOVE, eventId);
356         return;
357     }
358 
359     // drop allowed
360     CHECK_NULL_VOID(dragFrameNode);
361     const auto& dragFrameNodeAllowDrop = dragFrameNode->GetAllowDrop();
362     // special handling for no drag data present situation, always show as move
363     // For CAPI ,no ENABLE_DROP and DISABLE_DROP state, skip the judgment and consider it allowed to drop into. Continue
364     // to set dragBehavior.
365     if (!isCapi && (dragFrameNodeAllowDrop.empty() || summaryMap_.empty())) {
366         UpdateDragStyle(DragCursorStyleCore::MOVE, eventId);
367         return;
368     }
369 
370     //other case, check drag behavior
371     switch (dragBehavior) {
372         case DragBehavior::UNKNOWN: {
373             // the application does not config the drag behavior, use move when moving within
374             // draggedFrameNode or frameNode is disabled, otherwise use copy
375             auto eventHub = dragFrameNode->GetEventHub<EventHub>();
376             if (draggedFrameNode_ == dragFrameNode || !(eventHub && eventHub->IsEnabled()) ||
377                 CheckExtraSituation(dragFrameNode)) {
378                 UpdateDragStyle(DragCursorStyleCore::MOVE, eventId);
379             } else {
380                 UpdateDragStyle(DragCursorStyleCore::COPY, eventId);
381             }
382             break;
383         }
384         case DragBehavior::MOVE: {
385             UpdateDragStyle(DragCursorStyleCore::MOVE, eventId);
386             break;
387         }
388         case DragBehavior::COPY: {
389             UpdateDragStyle(DragCursorStyleCore::COPY, eventId);
390             break;
391         }
392         default: {
393             UpdateDragStyle(DragCursorStyleCore::COPY, eventId);
394             break;
395         }
396     }
397 }
398 
CheckExtraSituation(const RefPtr<FrameNode> & dragFrameNode) const399 bool DragDropManager::CheckExtraSituation(const RefPtr<FrameNode>& dragFrameNode) const
400 {
401     return CheckInRichEditor(dragFrameNode);
402 }
403 
CheckInRichEditor(const RefPtr<FrameNode> & dragFrameNode) const404 bool DragDropManager::CheckInRichEditor(const RefPtr<FrameNode>& dragFrameNode) const
405 {
406     CHECK_NULL_RETURN(dragFrameNode && draggedFrameNode_, false);
407     auto parent = draggedFrameNode_->GetAncestorNodeOfFrame();
408     CHECK_NULL_RETURN(parent && parent->GetTag() == V2::RICH_EDITOR_ETS_TAG, false);
409     return dragFrameNode == parent;
410 }
411 
UpdateDragStyle(const DragCursorStyleCore & dragStyle,int32_t eventId)412 void DragDropManager::UpdateDragStyle(const DragCursorStyleCore& dragStyle, int32_t eventId)
413 {
414     if (dragStyle != dragCursorStyleCore_) {
415         TAG_LOGI(
416             AceLogTag::ACE_DRAG, "Update DragStyle to %{public}d, pointerEventId: %{public}d.", dragStyle, eventId);
417         auto ret = InteractionInterface::GetInstance()->UpdateDragStyle(dragStyle, eventId);
418         if (ret != 0) {
419             TAG_LOGI(AceLogTag::ACE_DRAG,
420                 "Update DragStyle to %{public}d failed, keep %{public}d. pointerEventId: %{public}d. ret = %{public}d",
421                 dragStyle, dragCursorStyleCore_, eventId, ret);
422         } else {
423             dragCursorStyleCore_ = dragStyle;
424         }
425     }
426 }
427 
CheckParentVisible(const RefPtr<FrameNode> & frameNode)428 bool CheckParentVisible(const RefPtr<FrameNode>& frameNode)
429 {
430     bool isVisible = frameNode->IsVisible();
431     if (!isVisible) {
432         return false;
433     }
434     auto parent = frameNode->GetParent();
435     while (parent && parent->GetDepth() != 1) {
436         auto parentFrameNode = AceType::DynamicCast<FrameNode>(parent);
437         if (parentFrameNode && !parentFrameNode->IsVisible()) {
438             isVisible = false;
439             break;
440         }
441         parent = parent->GetParent();
442     }
443     return isVisible;
444 }
445 
FindHitFrameNodes(const Point & point)446 std::unordered_set<int32_t> DragDropManager::FindHitFrameNodes(const Point& point)
447 {
448     std::unordered_set<int32_t> frameNodeList;
449     for (auto iter = nodesForDragNotify_.begin(); iter != nodesForDragNotify_.end(); iter++) {
450         auto frameNode = iter->second.Upgrade();
451         if (!frameNode || !frameNode->IsActive() || !frameNode->IsVisible() || frameNode->GetDepth() < 0) {
452             continue;
453         }
454         auto geometryNode = frameNode->GetGeometryNode();
455         if (!geometryNode) {
456             continue;
457         }
458         auto globalFrameRect = geometryNode->GetFrameRect();
459         globalFrameRect.SetOffset(frameNode->GetTransformRelativeOffset());
460         if (globalFrameRect.IsInRegion(PointF(static_cast<float>(point.GetX()), static_cast<float>(point.GetY())))) {
461             frameNodeList.emplace(frameNode->GetId());
462         }
463     }
464     return frameNodeList;
465 }
466 
UpdateDragListener(const Point & point)467 void DragDropManager::UpdateDragListener(const Point& point)
468 {
469     auto hitNodes = FindHitFrameNodes(point);
470     std::unordered_map<int32_t, WeakPtr<FrameNode>> dragEnterNodes;
471     std::unordered_map<int32_t, WeakPtr<FrameNode>> dragMoveNodes;
472     std::unordered_map<int32_t, WeakPtr<FrameNode>> dragLeaveNodes;
473     for (auto iter = nodesForDragNotify_.begin(); iter != nodesForDragNotify_.end(); iter++) {
474         auto localHitResult = hitNodes.find(iter->first) != hitNodes.end();
475         auto preHitResult = parentHitNodes_.find(iter->first) != parentHitNodes_.end();
476         if (localHitResult && preHitResult) {
477             dragMoveNodes[iter->first] = iter->second;
478         }
479         if (localHitResult && !preHitResult) {
480             dragEnterNodes[iter->first] = iter->second;
481         }
482         if (!localHitResult && preHitResult) {
483             dragLeaveNodes[iter->first] = iter->second;
484         }
485     }
486     RefPtr<NotifyDragEvent> notifyEvent = AceType::MakeRefPtr<NotifyDragEvent>();
487     UpdateNotifyDragEvent(notifyEvent, point, DragEventType::MOVE);
488 
489     NotifyDragRegisterFrameNode(dragMoveNodes, DragEventType::MOVE, notifyEvent);
490     NotifyDragRegisterFrameNode(dragEnterNodes, DragEventType::ENTER, notifyEvent);
491     NotifyDragRegisterFrameNode(dragLeaveNodes, DragEventType::LEAVE, notifyEvent);
492     parentHitNodes_ = std::move(hitNodes);
493 }
494 
NotifyDragRegisterFrameNode(std::unordered_map<int32_t,WeakPtr<FrameNode>> nodes,DragEventType dragEventType,RefPtr<NotifyDragEvent> & notifyEvent)495 void DragDropManager::NotifyDragRegisterFrameNode(std::unordered_map<int32_t, WeakPtr<FrameNode>> nodes,
496     DragEventType dragEventType, RefPtr<NotifyDragEvent>& notifyEvent)
497 {
498     for (auto iter = nodes.begin(); iter != nodes.end(); iter++) {
499         auto frameNode = iter->second.Upgrade();
500         if (!frameNode) {
501             continue;
502         }
503         auto eventHub = frameNode->GetEventHub<EventHub>();
504         if (!CheckParentVisible(frameNode) || (eventHub && !eventHub->IsEnabled())) {
505             continue;
506         }
507         auto pattern = frameNode->GetPattern<Pattern>();
508         if (!pattern) {
509             continue;
510         }
511         pattern->HandleOnDragStatusCallback(dragEventType, notifyEvent);
512     }
513 }
514 
NotifyDragFrameNode(const Point & point,const DragEventType & dragEventType,const DragRet & dragRet)515 void DragDropManager::NotifyDragFrameNode(
516     const Point& point, const DragEventType& dragEventType, const DragRet& dragRet)
517 {
518     RefPtr<NotifyDragEvent> notifyEvent = AceType::MakeRefPtr<NotifyDragEvent>();
519     UpdateNotifyDragEvent(notifyEvent, point, dragEventType);
520     notifyEvent->SetResult(dragRet);
521     NotifyDragRegisterFrameNode(nodesForDragNotify_, dragEventType, notifyEvent);
522 }
523 
OnDragStart(const Point & point,const RefPtr<FrameNode> & frameNode)524 void DragDropManager::OnDragStart(const Point& point, const RefPtr<FrameNode>& frameNode)
525 {
526     dragDropState_ = DragDropMgrState::DRAGGING;
527     NotifyDragFrameNode(point, DragEventType::START);
528     CHECK_NULL_VOID(frameNode);
529     preTargetFrameNode_ = frameNode;
530     draggedFrameNode_ = preTargetFrameNode_;
531     preMovePoint_ = point;
532     parentHitNodes_.emplace(frameNode->GetId());
533 }
534 
OnDragStart(const Point & point)535 void DragDropManager::OnDragStart(const Point& point)
536 {
537     dragDropState_ = DragDropMgrState::DRAGGING;
538     NotifyDragFrameNode(point, DragEventType::START);
539 }
540 
PrintDragFrameNode(const OHOS::Ace::PointerEvent & pointerEvent,const RefPtr<FrameNode> & dragFrameNode)541 void DragDropManager::PrintDragFrameNode(
542     const OHOS::Ace::PointerEvent& pointerEvent, const RefPtr<FrameNode>& dragFrameNode)
543 {
544     CHECK_NULL_VOID(dragFrameNode);
545     auto container = Container::Current();
546     CHECK_NULL_VOID(container);
547     if (preTargetFrameNode_) {
548         TAG_LOGI(AceLogTag::ACE_DRAG,
549             "Current windowId is %{public}d, pointerEventId is %{public}d, "
550             "PreTargetFrameNode is %{public}s, depth is %{public}d, New find "
551             "targetNode is %{public}s, depth is %{public}d.",
552             container->GetWindowId(), pointerEvent.pointerEventId, preTargetFrameNode_->GetTag().c_str(),
553             preTargetFrameNode_->GetDepth(), dragFrameNode->GetTag().c_str(), dragFrameNode->GetDepth());
554     } else {
555         TAG_LOGI(AceLogTag::ACE_DRAG,
556             "Current windowId is %{public}d, pointerEventId is %{public}d "
557             "PreTargetFrameNode is nullptr, New find targetNode is %{public}s, depth is %{public}d.",
558             container->GetWindowId(), pointerEvent.pointerEventId, dragFrameNode->GetTag().c_str(),
559             dragFrameNode->GetDepth());
560     }
561 }
562 
PrintGridDragFrameNode(const float globalX,const float globalY,const RefPtr<FrameNode> & dragFrameNode)563 void DragDropManager::PrintGridDragFrameNode(
564     const float globalX, const float globalY, const RefPtr<FrameNode>& dragFrameNode)
565 {
566     CHECK_NULL_VOID(dragFrameNode);
567     auto container = Container::Current();
568     CHECK_NULL_VOID(container);
569     if (preGridTargetFrameNode_) {
570         TAG_LOGI(AceLogTag::ACE_DRAG,
571             "Current windowId is %{public}d,"
572             "PreTargetFrameNode is %{public}s, depth is %{public}d,"
573             "New find targetNode is %{public}s, depth is %{public}d.",
574             container->GetWindowId(), preGridTargetFrameNode_->GetTag().c_str(),
575             preGridTargetFrameNode_->GetDepth(), dragFrameNode->GetTag().c_str(), dragFrameNode->GetDepth());
576     } else {
577         TAG_LOGI(AceLogTag::ACE_DRAG,
578             "Current windowId is %{public}d, "
579             "PreTargetFrameNode is nullptr, New find targetNode is %{public}s, depth is %{public}d.",
580             container->GetWindowId(), dragFrameNode->GetTag().c_str(), dragFrameNode->GetDepth());
581     }
582 }
583 
TransDragWindowToDragFwk(int32_t windowContainerId)584 void DragDropManager::TransDragWindowToDragFwk(int32_t windowContainerId)
585 {
586     if (isDragFwkShow_) {
587         return;
588     }
589     TAG_LOGI(AceLogTag::ACE_DRAG, "TransDragWindowToDragFwk is %{public}d", isDragFwkShow_);
590     InteractionInterface::GetInstance()->SetDragWindowVisible(true);
591     isDragFwkShow_ = true;
592     menuWrapperNode_ = nullptr;
593     auto overlayManager = GetDragAnimationOverlayManager(windowContainerId);
594     CHECK_NULL_VOID(overlayManager);
595     overlayManager->RemoveDragPixelMap();
596     overlayManager->RemoveGatherNode();
597     SubwindowManager::GetInstance()->HidePreviewNG();
598     info_.scale = -1.0;
599     dampingOverflowCount_ = 0;
600 }
601 
OnDragMoveOut(const PointerEvent & pointerEvent)602 void DragDropManager::OnDragMoveOut(const PointerEvent& pointerEvent)
603 {
604     Point point = pointerEvent.GetPoint();
605     auto container = Container::Current();
606     if (container && container->IsScenceBoardWindow()) {
607         if (IsDragged() && IsWindowConsumed()) {
608             SetIsWindowConsumed(false);
609             return;
610         }
611     }
612     SetIsWindowConsumed(false);
613     UpdateVelocityTrackerPoint(point, false);
614     UpdateDragListener(Point(-1, -1));
615     if (preTargetFrameNode_) {
616         TAG_LOGI(AceLogTag::ACE_DRAG, "Leave the current window, windowId is %{public}d,"
617             "PreTargetFrameNode is %{public}s, depth is %{public}d.",
618             container->GetWindowId(), preTargetFrameNode_->GetTag().c_str(), preTargetFrameNode_->GetDepth());
619         FireOnDragEvent(preTargetFrameNode_, pointerEvent, DragEventType::LEAVE, extraInfo_);
620         preTargetFrameNode_ = nullptr;
621     }
622     if (IsNeedDisplayInSubwindow() || isDragWithContextMenu_) {
623         TransDragWindowToDragFwk(Container::CurrentId());
624     }
625 }
626 
isDistanceLimited(const Point & point)627 bool DragDropManager::isDistanceLimited(const Point& point)
628 {
629     auto distance = sqrt(pow(point.GetX() - preMovePoint_.GetX(), 2) + pow(point.GetY() - preMovePoint_.GetY(), 2));
630     TAG_LOGD(AceLogTag::ACE_DRAG, "onDragMove, distance: %{public}f", distance);
631     if (distance < MOVE_DISTANCE_LIMIT) {
632         TAG_LOGD(AceLogTag::ACE_DRAG, "onDragMove, distance is less than limit");
633         return true;
634     }
635     return false;
636 }
637 
isTimeLimited(const PointerEvent & pointerEvent,const Point & point)638 bool DragDropManager::isTimeLimited(const PointerEvent& pointerEvent, const Point& point)
639 {
640     uint64_t currentTimeStamp = static_cast<uint64_t>(
641         std::chrono::duration_cast<std::chrono::milliseconds>(pointerEvent.time.time_since_epoch()).count());
642     if (currentTimeStamp > preTimeStamp_ && currentTimeStamp - preTimeStamp_ < MOVE_TIME_LIMIT) {
643         TAG_LOGD(AceLogTag::ACE_DRAG, "onDragMove, time is less than limit");
644         return true;
645     }
646     return false;
647 }
648 
ReachMoveLimit(const PointerEvent & pointerEvent,const Point & point)649 bool DragDropManager::ReachMoveLimit(const PointerEvent& pointerEvent, const Point& point)
650 {
651     if (pointerEvent.sourceTool == SourceTool::MOUSE) {
652         if (isTimeLimited(pointerEvent, point) && isDistanceLimited(point)) {
653             return true;
654         }
655     }
656     return false;
657 }
658 
HandleOnDragMove(const PointerEvent & pointerEvent,const std::string & extraInfo,const RefPtr<FrameNode> & dragFrameNode)659 void DragDropManager::HandleOnDragMove(const PointerEvent& pointerEvent, const std::string& extraInfo,
660     const RefPtr<FrameNode>& dragFrameNode)
661 {
662     CHECK_NULL_VOID(dragFrameNode);
663 
664     if (dragFrameNode == preTargetFrameNode_) {
665         FireOnDragEvent(dragFrameNode, pointerEvent, DragEventType::MOVE, extraInfo);
666         return;
667     }
668 
669     FireOnDragLeave(preTargetFrameNode_, pointerEvent, extraInfo);
670     PrintDragFrameNode(pointerEvent, dragFrameNode);
671     FireOnDragEvent(dragFrameNode, pointerEvent, DragEventType::ENTER, extraInfo);
672     preTargetFrameNode_ = dragFrameNode;
673 }
674 
OnDragMove(const PointerEvent & pointerEvent,const std::string & extraInfo,const RefPtr<FrameNode> & node)675 void DragDropManager::OnDragMove(const PointerEvent& pointerEvent, const std::string& extraInfo,
676     const RefPtr<FrameNode>& node)
677 {
678     RequireSummaryIfNecessary(pointerEvent);
679     Point point = pointerEvent.GetPoint();
680     auto container = Container::Current();
681     CHECK_NULL_VOID(container);
682     if (container && container->IsScenceBoardWindow()) {
683         if (IsDragged() && IsWindowConsumed()) {
684             SetIsWindowConsumed(false);
685             return;
686         }
687     }
688     if (ReachMoveLimit(pointerEvent, point)) {
689         return;
690     }
691     preMovePoint_ = point;
692     preTimeStamp_ = static_cast<uint64_t>(
693         std::chrono::duration_cast<std::chrono::milliseconds>(pointerEvent.time.time_since_epoch()).count());
694     SetIsWindowConsumed(false);
695     if (isDragFwkShow_) {
696         auto menuWrapper = GetMenuWrapperNodeFromDrag();
697         SubwindowManager::GetInstance()->UpdateHideMenuOffsetNG(OffsetF(static_cast<float>(point.GetX()),
698             static_cast<float>(point.GetY())), 1.0, false, menuWrapper ? menuWrapper->GetId() : -1);
699     }
700     UpdateVelocityTrackerPoint(point, false);
701     UpdateDragListener(point);
702     auto dragFrameNode = FindDragFrameNodeByPosition(
703         static_cast<float>(point.GetX()), static_cast<float>(point.GetY()), node);
704     if (!dragFrameNode) {
705         if (preTargetFrameNode_) {
706             TAG_LOGI(AceLogTag::ACE_DRAG,
707                 "Not find drag target node, current windowId is %{public}d,"
708                 "pointerEventId is %{public}d. PreTargetFrameNode is %{public}s, depth is %{public}d.",
709                 container->GetWindowId(), pointerEvent.pointerEventId, preTargetFrameNode_->GetTag().c_str(),
710                 preTargetFrameNode_->GetDepth());
711             FireOnDragEvent(preTargetFrameNode_, pointerEvent, DragEventType::LEAVE, extraInfo);
712             preTargetFrameNode_ = nullptr;
713         }
714 
715         if (!isMouseDragged_ || isDragWindowShow_) {
716             UpdateDragStyle(DragCursorStyleCore::MOVE, pointerEvent.pointerEventId);
717         }
718         return;
719     }
720     HandleOnDragMove(pointerEvent, extraInfo, dragFrameNode);
721 }
722 
ResetDragDropStatus(const Point & point,const DragDropRet & dragDropRet,int32_t windowId)723 void DragDropManager::ResetDragDropStatus(const Point& point, const DragDropRet& dragDropRet, int32_t windowId)
724 {
725     if (dragDropRet.result != DragRet::DRAG_FAIL || !isMouseDragged_) {
726         InteractionInterface::GetInstance()->SetDragWindowVisible(!dragDropRet.hasCustomAnimation);
727     }
728     InteractionInterface::GetInstance()->StopDrag(dragDropRet);
729     NotifyDragFrameNode(point, DragEventType::DROP, dragDropRet.result);
730     ResetPullId();
731     dragCursorStyleCore_ = DragCursorStyleCore::DEFAULT;
732 }
733 
ResetPreTargetFrameNode(int32_t instanceId)734 void DragDropManager::ResetPreTargetFrameNode(int32_t instanceId)
735 {
736     auto container = Container::GetContainer(instanceId);
737     if (container && (container->IsScenceBoardWindow() || container->IsUIExtensionWindow())) {
738         return;
739     }
740     preTargetFrameNode_ = nullptr;
741 }
742 
DoDragReset()743 void DragDropManager::DoDragReset()
744 {
745     dragDropState_ = DragDropMgrState::IDLE;
746     preTargetFrameNode_ = nullptr;
747     draggedFrameNode_ = nullptr;
748     menuWrapperNode_ = nullptr;
749     preMovePoint_ = Point(0, 0);
750     hasNotifiedTransformation_ = false;
751     badgeNumber_ = -1;
752     isDragWithContextMenu_ = false;
753     dampingOverflowCount_ = 0;
754     isDragNodeNeedClean_ = false;
755 }
756 
ResetDraggingStatus(const TouchEvent & touchPoint)757 void DragDropManager::ResetDraggingStatus(const TouchEvent& touchPoint)
758 {
759     if (IsDraggingPressed(touchPoint.id)) {
760         SetDraggingPressedState(false);
761     }
762     if (!IsItemDragging() && IsDragging() && IsSameDraggingPointer(touchPoint.id)) {
763         OnDragEnd(
764             PointerEvent(touchPoint.touchEventId, touchPoint.x, touchPoint.y, touchPoint.screenX, touchPoint.screenY),
765             "");
766     }
767 }
768 
HandleOnDragEnd(const PointerEvent & pointerEvent,const std::string & extraInfo,const RefPtr<FrameNode> & dragFrameNode)769 void DragDropManager::HandleOnDragEnd(const PointerEvent& pointerEvent, const std::string& extraInfo,
770     const RefPtr<FrameNode>& dragFrameNode)
771 {
772     CHECK_NULL_VOID(dragFrameNode);
773     Point point = pointerEvent.GetPoint();
774     auto container = Container::Current();
775     CHECK_NULL_VOID(container);
776     if (!IsDropAllowed(dragFrameNode)) {
777         TAG_LOGI(AceLogTag::ACE_DRAG,
778             "DragDropManager onDragEnd, target data is not allowed to fall into. WindowId is %{public}d, "
779             "pointerEventId is %{public}d.",
780             container->GetWindowId(), pointerEvent.pointerEventId);
781         DragDropBehaviorReporter::GetInstance().UpdateDragStopResult(DragStopResult::APP_REFUSE_DATA);
782         ResetDragDrop(container->GetWindowId(), point);
783         return;
784     }
785     TAG_LOGI(AceLogTag::ACE_DRAG,
786         "Current windowId is %{public}d, pointerEventId is %{public}d. TargetNode is %{public}s.",
787         container->GetWindowId(), pointerEvent.pointerEventId, dragFrameNode->GetTag().c_str());
788     if (IsUIExtensionComponent(dragFrameNode)) {
789         auto pattern = dragFrameNode->GetPattern<Pattern>();
790         pattern->HandleDragEvent(pointerEvent);
791         return;
792     }
793 
794     RequestDragSummaryInfoAndPrivilege();
795     std::string udKey;
796     InteractionInterface::GetInstance()->GetUdKey(udKey);
797     if (!CheckRemoteData(dragFrameNode, pointerEvent, udKey)) {
798         auto unifiedData = RequestUDMFDataWithUDKey(udKey);
799         DoDropAction(dragFrameNode, pointerEvent, unifiedData, udKey);
800     }
801 }
802 
OnDragEnd(const PointerEvent & pointerEvent,const std::string & extraInfo,const RefPtr<FrameNode> & node)803 void DragDropManager::OnDragEnd(const PointerEvent& pointerEvent, const std::string& extraInfo,
804     const RefPtr<FrameNode>& node)
805 {
806     Point point = pointerEvent.GetPoint();
807     DoDragReset();
808     dragDropPointerEvent_ = pointerEvent;
809     auto container = Container::Current();
810     auto containerId = container->GetInstanceId();
811     DragDropBehaviorReporter::GetInstance().UpdateContainerId(containerId);
812     if (container && container->IsScenceBoardWindow()) {
813         if (IsDragged() && IsWindowConsumed()) {
814             TAG_LOGD(AceLogTag::ACE_DRAG, "DragDropManager is dragged or window consumed. WindowId is %{public}d",
815                 container->GetWindowId());
816             return;
817         }
818     }
819     if (isDragCancel_) {
820         DragDropBehaviorReporter::GetInstance().UpdateDragStopResult(DragStopResult::USER_STOP_DRAG);
821         TAG_LOGI(AceLogTag::ACE_DRAG, "DragDropManager is dragCancel, finish drag. WindowId is %{public}d, "
822             "pointerEventId is %{public}d.",
823             container->GetWindowId(), pointerEvent.pointerEventId);
824         DragDropRet dragDropRet { DragRet::DRAG_CANCEL, false, container->GetWindowId(), DragBehavior::UNKNOWN };
825         ResetDragDropStatus(point, dragDropRet, container->GetWindowId());
826         ClearVelocityInfo();
827         return;
828     }
829     UpdateVelocityTrackerPoint(point, true);
830     auto dragFrameNode = FindDragFrameNodeByPosition(
831         static_cast<float>(point.GetX()), static_cast<float>(point.GetY()), node);
832     if (!dragFrameNode) {
833         DragDropBehaviorReporter::GetInstance().UpdateDragStopResult(DragStopResult::APP_DATA_UNSUPPORT);
834         TAG_LOGI(AceLogTag::ACE_DRAG,
835             "DragDropManager onDragEnd, not find drop target, stop drag. WindowId is %{public}d, "
836             "pointerEventId is %{public}d.",
837             container->GetWindowId(), pointerEvent.pointerEventId);
838         ResetDragDrop(container->GetWindowId(), point);
839         return;
840     }
841     HandleOnDragEnd(pointerEvent, extraInfo, dragFrameNode);
842 }
843 
IsDropAllowed(const RefPtr<FrameNode> & dragFrameNode)844 bool DragDropManager::IsDropAllowed(const RefPtr<FrameNode>& dragFrameNode)
845 {
846     // application passed in null to indicate refusing all drag data forcedly
847     bool isDisallowDropForcedly = dragFrameNode->GetDisallowDropForcedly();
848     if (isDisallowDropForcedly) {
849         return false;
850     }
851     const auto& dragFrameNodeAllowDrop = dragFrameNode->GetAllowDrop();
852     // if application does not set allow drop or set with empty, treat as all data types is allowed
853     if (dragFrameNodeAllowDrop.empty() || summaryMap_.empty()) {
854         return true;
855     }
856     DragDropBehaviorReporter::GetInstance().UpdateAllowDropType(dragFrameNodeAllowDrop);
857     for (const auto& it : summaryMap_) {
858         // if one matched found, allow drop
859         if (dragFrameNodeAllowDrop.find(it.first) != dragFrameNodeAllowDrop.end()) {
860             return true;
861         }
862     }
863     return false;
864 }
865 
RequestDragSummaryInfoAndPrivilege()866 void DragDropManager::RequestDragSummaryInfoAndPrivilege()
867 {
868     RequireSummary();
869     int ret = InteractionInterface::GetInstance()->AddPrivilege();
870     if (ret != 0 && SystemProperties::GetDebugEnabled()) {
871         TAG_LOGD(AceLogTag::ACE_DRAG, "Interaction AddPrivilege in DragEnd with code:%{public}d", ret);
872     }
873     ShadowOffsetData shadowOffsetData { -1, -1, -1, -1 };
874     ret = InteractionInterface::GetInstance()->GetShadowOffset(shadowOffsetData);
875     if (ret == 0) {
876         previewRect_ =
877             Rect(shadowOffsetData.offsetX, shadowOffsetData.offsetY, shadowOffsetData.width, shadowOffsetData.height);
878     } else {
879         TAG_LOGD(AceLogTag::ACE_DRAG, "Interaction GetShadowOffset in DragEnd with code:%{public}d", ret);
880     }
881 }
882 
DoDropAction(const RefPtr<FrameNode> & dragFrameNode,const PointerEvent & pointerEvent,const RefPtr<UnifiedData> & unifiedData,const std::string & udKey)883 void DragDropManager::DoDropAction(const RefPtr<FrameNode>& dragFrameNode, const PointerEvent& pointerEvent,
884     const RefPtr<UnifiedData>& unifiedData, const std::string& udKey)
885 {
886     RefPtr<OHOS::Ace::DragEvent> event = AceType::MakeRefPtr<OHOS::Ace::DragEvent>();
887     if (!udKey.empty()) {
888         event->SetUdKey(udKey);
889     }
890     if (unifiedData == nullptr) {
891         event->SetIsGetDataSuccess(false);
892     } else {
893         DragDropBehaviorReporter::GetInstance().UpdateRecordSize(unifiedData->GetSize());
894         event->SetData(unifiedData);
895         event->SetIsGetDataSuccess(true);
896     }
897     event->SetPressedKeyCodes(pointerEvent.pressedKeyCodes_);
898     OnDragDrop(event, dragFrameNode, pointerEvent);
899 }
900 
RequestUDMFDataWithUDKey(const std::string & udKey)901 RefPtr<UnifiedData> DragDropManager::RequestUDMFDataWithUDKey(const std::string& udKey)
902 {
903     if (udKey.empty()) {
904         TAG_LOGI(AceLogTag::ACE_DRAG, "udKey is empty");
905         return nullptr;
906     }
907     RefPtr<UnifiedData> udData = UdmfClient::GetInstance()->CreateUnifiedData();
908     auto ret = UdmfClient::GetInstance()->GetData(udData, udKey);
909     if (ret != 0) {
910         TAG_LOGI(AceLogTag::ACE_DRAG, "Get udmfData failed");
911         return nullptr;
912     }
913     return udData;
914 }
915 
TryGetDataBackGround(const RefPtr<FrameNode> & dragFrameNode,const PointerEvent & pointerEvent,const std::string & udKey,int32_t count)916 void DragDropManager::TryGetDataBackGround(
917     const RefPtr<FrameNode>& dragFrameNode, const PointerEvent& pointerEvent, const std::string& udKey, int32_t count)
918 {
919     auto pipeline = PipelineContext::GetCurrentContext();
920     CHECK_NULL_VOID(pipeline);
921     auto taskScheduler = pipeline->GetTaskExecutor();
922     CHECK_NULL_VOID(taskScheduler);
923     taskScheduler->PostTask(
924         [id = Container::CurrentId(), pipeline, dragFrameNode, pointerEvent, udKey, count,
925         weakManager = WeakClaim(this)]() {
926             ContainerScope scope(id);
927             auto dragDropManager = weakManager.Upgrade();
928             CHECK_NULL_VOID(dragDropManager);
929             auto taskScheduler = pipeline->GetTaskExecutor();
930             CHECK_NULL_VOID(taskScheduler);
931             auto result = dragDropManager->RequestUDMFDataWithUDKey(udKey);
932             if (result != nullptr || count >= MAX_RETRY_TIMES) {
933                 taskScheduler->PostTask(
934                     [dragFrameNode, pointerEvent, weakManager, result, udKey]() {
935                         auto dragDropManager = weakManager.Upgrade();
936                         CHECK_NULL_VOID(dragDropManager);
937                         dragDropManager->DoDropAction(dragFrameNode, pointerEvent, result, udKey);
938                     },
939                     TaskExecutor::TaskType::UI, "ArkUIDragDropAction");
940             } else {
941                 // first temp get udmfData failed, prepare to retryGetData.
942                 taskScheduler->PostDelayedTask(
943                     [dragFrameNode, pointerEvent, weakManager, count, udKey]() {
944                         auto dragDropManager = weakManager.Upgrade();
945                         CHECK_NULL_VOID(dragDropManager);
946                         dragDropManager->TryGetDataBackGround(dragFrameNode, pointerEvent, udKey, count + 1);
947                     },
948                     TaskExecutor::TaskType::UI, MAX_RETRY_DURATION, "ArkUIDragDropRetryGetData");
949             }
950         },
951         TaskExecutor::TaskType::BACKGROUND, "ArkUIDragDropGetDataBackground");
952 }
953 
CheckRemoteData(const RefPtr<FrameNode> & dragFrameNode,const PointerEvent & pointerEvent,const std::string & udKey)954 bool DragDropManager::CheckRemoteData(
955     const RefPtr<FrameNode>& dragFrameNode, const PointerEvent& pointerEvent, const std::string& udKey)
956 {
957     if (udKey.empty()) {
958         DragDropBehaviorReporter::GetInstance().UpdateDragStopResult(DragStopResult::GET_UDKEY_FAIL);
959         return false;
960     }
961     std::string remoteUdKey = udKey;
962     auto isRemoteData = UdmfClient::GetInstance()->GetRemoteStatus(remoteUdKey);
963     if (isRemoteData) {
964         TAG_LOGI(AceLogTag::ACE_DRAG, "Stop drag with motion drag action.");
965         TryGetDataBackGround(dragFrameNode, pointerEvent, udKey);
966         DragDropBehaviorReporter::GetInstance().UpdateDragStopResult(DragStopResult::GET_UDKEY_FAIL);
967         DragDropBehaviorReporter::GetInstance().UpdateIsCrossing(CrossingEnd::IS_CROSSING);
968         return isRemoteData;
969     }
970     DragDropBehaviorReporter::GetInstance().UpdateIsCrossing(CrossingEnd::NOT_CROSSING);
971     return isRemoteData;
972 }
973 
OnDragDrop(RefPtr<OHOS::Ace::DragEvent> & event,const RefPtr<FrameNode> & dragFrameNode,const OHOS::Ace::PointerEvent & pointerEvent)974 void DragDropManager::OnDragDrop(RefPtr<OHOS::Ace::DragEvent>& event, const RefPtr<FrameNode>& dragFrameNode,
975     const OHOS::Ace::PointerEvent& pointerEvent)
976 {
977     auto point = pointerEvent.GetPoint();
978     auto eventHub = dragFrameNode->GetEventHub<EventHub>();
979     CHECK_NULL_VOID(eventHub);
980     UpdateDragEvent(event, pointerEvent);
981     auto extraParams = eventHub->GetDragExtraParams(extraInfo_, point, DragEventType::DROP);
982     eventHub->FireCustomerOnDragFunc(DragFuncType::DRAG_DROP, event, extraParams);
983     eventHub->HandleInternalOnDrop(event, extraParams);
984     ClearVelocityInfo();
985     SetIsDragged(false);
986     auto pipeline = PipelineContext::GetCurrentContext();
987     CHECK_NULL_VOID(pipeline);
988     auto dragResult = event->GetResult();
989     if (dragResult == DragRet::DRAG_FAIL) {
990         DragDropBehaviorReporter::GetInstance().UpdateDragStopResult(DragStopResult::APP_RECEIVE_FAIL);
991     } else if (dragResult == DragRet::DRAG_CANCEL) {
992         DragDropBehaviorReporter::GetInstance().UpdateDragStopResult(DragStopResult::USER_STOP_DRAG);
993     }
994     auto useCustomAnimation = event->IsUseCustomAnimation();
995     auto dragBehavior = event->GetDragBehavior();
996     auto container = Container::Current();
997     CHECK_NULL_VOID(container);
998     auto windowId = container->GetWindowId();
999     pipeline->AddAfterRenderTask([dragResult, useCustomAnimation, windowId, dragBehavior,
1000                                      pointerEventId = pointerEvent.pointerEventId, weak = WeakClaim(this)]() {
1001         TAG_LOGI(AceLogTag::ACE_DRAG,
1002             "Stop drag, start do drop animation. UseCustomAnimation is %{public}d,"
1003             "WindowId is %{public}d, pointerEventId is %{public}d.",
1004             useCustomAnimation, windowId, pointerEventId);
1005         auto manager = weak.Upgrade();
1006         if (manager) {
1007             manager->HideDragPreviewOverlay();
1008         }
1009         InteractionInterface::GetInstance()->SetDragWindowVisible(!useCustomAnimation);
1010         DragDropRet dragDropRet { dragResult, useCustomAnimation, windowId, dragBehavior };
1011         InteractionInterface::GetInstance()->StopDrag(dragDropRet);
1012     });
1013     NotifyDragFrameNode(point, DragEventType::DROP, event->GetResult());
1014     dragFrameNode->MarkDirtyNode();
1015     ResetPullId();
1016     dragCursorStyleCore_ = DragCursorStyleCore::DEFAULT;
1017     pipeline->RequestFrame();
1018 }
1019 
RequireSummary()1020 void DragDropManager::RequireSummary()
1021 {
1022     std::map<std::string, int64_t> summary;
1023     int32_t ret = InteractionInterface::GetInstance()->GetDragSummary(summary);
1024     if (ret != 0) {
1025         TAG_LOGI(AceLogTag::ACE_DRAG, "RequireSummary: Interaction GetSummary failed: %{public}d", ret);
1026     } else {
1027         std::string summarys;
1028         for (const auto& [udkey, recordSize] : summary) {
1029             std::string str = udkey + "-" + std::to_string(recordSize) + ";";
1030             summarys += str;
1031         }
1032         TAG_LOGI(AceLogTag::ACE_DRAG, "require summary: %{public}s", summarys.c_str());
1033         DragDropBehaviorReporter::GetInstance().UpdateSummaryType(summarys);
1034     }
1035     std::string extraInfo;
1036     ret = InteractionInterface::GetInstance()->GetDragExtraInfo(extraInfo);
1037     if (ret != 0) {
1038         TAG_LOGI(AceLogTag::ACE_DRAG, "GetExtraInfo: Interaction GetExtraInfo failed: %{public}d", ret);
1039     }
1040     previewRect_ = Rect(-1, -1, -1, -1);
1041     extraInfo_ = extraInfo;
1042     summaryMap_ = summary;
1043 }
1044 
ResetRecordSize(uint32_t recordSize)1045 void DragDropManager::ResetRecordSize(uint32_t recordSize)
1046 {
1047     recordSize_ = recordSize;
1048 }
1049 
GetRecordSize() const1050 uint32_t DragDropManager::GetRecordSize() const
1051 {
1052     return recordSize_;
1053 }
1054 
GetDragWindowRect(const Point & point)1055 Rect DragDropManager::GetDragWindowRect(const Point& point)
1056 {
1057     if (!previewRect_.IsValid()) {
1058         ShadowOffsetData shadowOffsetData { -1, -1, -1, -1 };
1059         int ret = InteractionInterface::GetInstance()->GetShadowOffset(shadowOffsetData);
1060         if (ret == 0) {
1061             previewRect_ = Rect(
1062                 shadowOffsetData.offsetX,
1063                 shadowOffsetData.offsetY,
1064                 shadowOffsetData.width,
1065                 shadowOffsetData.height);
1066         }
1067     }
1068     return previewRect_ + Offset(point.GetX(), point.GetY());
1069 }
1070 
ClearSummary()1071 void DragDropManager::ClearSummary()
1072 {
1073     previewRect_ = Rect(-1, -1, -1, -1);
1074     ResetPullId();
1075     ResetRecordSize();
1076 }
1077 
OnTextDragEnd(float globalX,float globalY,const std::string & extraInfo)1078 void DragDropManager::OnTextDragEnd(float globalX, float globalY, const std::string& extraInfo)
1079 {
1080     dragDropState_ = DragDropMgrState::IDLE;
1081     auto dragFrameNode = FindDragFrameNodeByPosition(globalX, globalY);
1082     if (dragFrameNode) {
1083         auto textFieldPattern = dragFrameNode->GetPattern<TextFieldPattern>();
1084         if (textFieldPattern) {
1085             textFieldPattern->InsertValue(extraInfo);
1086         }
1087     }
1088     SetIsDragged(false);
1089     currentId_ = -1;
1090 }
1091 
onDragCancel()1092 void DragDropManager::onDragCancel()
1093 {
1094     preTargetFrameNode_ = nullptr;
1095     draggedFrameNode_ = nullptr;
1096 }
1097 
FireOnDragEventWithDragType(const RefPtr<EventHub> & eventHub,DragEventType type,RefPtr<OHOS::Ace::DragEvent> & event,const std::string & extraParams)1098 void DragDropManager::FireOnDragEventWithDragType(const RefPtr<EventHub>& eventHub, DragEventType type,
1099     RefPtr<OHOS::Ace::DragEvent>& event, const std::string& extraParams)
1100 {
1101     switch (type) {
1102         case DragEventType::ENTER: {
1103             eventHub->FireCustomerOnDragFunc(DragFuncType::DRAG_ENTER, event, extraParams);
1104             eventHub->FireOnDragEnter(event, extraParams);
1105             break;
1106         }
1107         case DragEventType::MOVE: {
1108             eventHub->FireCustomerOnDragFunc(DragFuncType::DRAG_MOVE, event, extraParams);
1109             eventHub->FireOnDragMove(event, extraParams);
1110             break;
1111         }
1112         case DragEventType::LEAVE: {
1113             eventHub->FireCustomerOnDragFunc(DragFuncType::DRAG_LEAVE, event, extraParams);
1114             eventHub->FireOnDragLeave(event, extraParams);
1115             break;
1116         }
1117         case DragEventType::DROP: {
1118             eventHub->FireCustomerOnDragFunc(DragFuncType::DRAG_DROP, event, extraParams);
1119             eventHub->HandleInternalOnDrop(event, extraParams);
1120             break;
1121         }
1122         default:
1123             break;
1124     }
1125 }
1126 
FireOnDragEvent(const RefPtr<FrameNode> & frameNode,const PointerEvent & pointerEvent,DragEventType type,const std::string & extraInfo)1127 void DragDropManager::FireOnDragEvent(
1128     const RefPtr<FrameNode>& frameNode, const PointerEvent& pointerEvent,
1129     DragEventType type, const std::string& extraInfo)
1130 {
1131     if (IsUIExtensionComponent(frameNode)) {
1132         auto dragEvent = pointerEvent;
1133         if (type == DragEventType::ENTER) {
1134             dragEvent.action = PointerAction::PULL_IN_WINDOW;
1135         } else if (type == DragEventType::LEAVE) {
1136             dragEvent.action = PointerAction::PULL_OUT_WINDOW;
1137         }
1138         auto pattern = frameNode->GetPattern<Pattern>();
1139         CHECK_NULL_VOID(pattern);
1140         pattern->HandleDragEvent(dragEvent);
1141         return;
1142     }
1143     auto eventHub = frameNode->GetEventHub<EventHub>();
1144     CHECK_NULL_VOID(eventHub);
1145     auto pipeline = PipelineContext::GetCurrentContext();
1146     CHECK_NULL_VOID(pipeline);
1147     if (!eventHub->HasOnDrop() && !eventHub->HasOnItemDrop() && !eventHub->HasCustomerOnDrop()) {
1148         return;
1149     }
1150     auto point = pointerEvent.GetPoint();
1151     auto extraParams = eventHub->GetDragExtraParams(extraInfo_.empty() ? extraInfo : extraInfo_, point, type);
1152     RefPtr<OHOS::Ace::DragEvent> event = AceType::MakeRefPtr<OHOS::Ace::DragEvent>();
1153     event->SetX((double)point.GetX());
1154     event->SetY((double)point.GetY());
1155     event->SetScreenX((double)point.GetScreenX());
1156     event->SetScreenY((double)point.GetScreenY());
1157     event->SetDisplayX((double)pointerEvent.GetDisplayX());
1158     event->SetDisplayY((double)pointerEvent.GetDisplayY());
1159     event->SetVelocity(velocityTracker_.GetVelocity());
1160     event->SetSummary(summaryMap_);
1161     event->SetPreviewRect(GetDragWindowRect(point));
1162     event->SetPressedKeyCodes(pointerEvent.pressedKeyCodes_);
1163 
1164     FireOnEditableTextComponent(frameNode, type);
1165     FireOnDragEventWithDragType(eventHub, type, event, extraParams);
1166 
1167     if (isMouseDragged_ && !isDragWindowShow_) {
1168         return;
1169     }
1170     if (event->GetResult() == DragRet::ENABLE_DROP) {
1171         if (event->GetDragBehavior() == DragBehavior::MOVE) {
1172             UpdateDragStyle(DragCursorStyleCore::MOVE, pointerEvent.pointerEventId);
1173         } else {
1174             UpdateDragStyle(DragCursorStyleCore::COPY, pointerEvent.pointerEventId);
1175         }
1176     } else if (event->GetResult() == DragRet::DISABLE_DROP) {
1177         // simplified specifications for drag cursor style, no longer showing forbidden drag cursor
1178         UpdateDragStyle(DragCursorStyleCore::MOVE, pointerEvent.pointerEventId);
1179     } else {
1180         UpdateDragAllowDrop(frameNode, event->GetDragBehavior(), pointerEvent.pointerEventId, event->IsCapi());
1181     }
1182 }
1183 
OnItemDragStart(float globalX,float globalY,const RefPtr<FrameNode> & frameNode)1184 void DragDropManager::OnItemDragStart(float globalX, float globalY, const RefPtr<FrameNode>& frameNode)
1185 {
1186     dragDropState_ = DragDropMgrState::DRAGGING;
1187     preGridTargetFrameNode_ = frameNode;
1188     draggedGridFrameNode_ = frameNode;
1189 }
1190 
OnItemDragMove(float globalX,float globalY,int32_t draggedIndex,DragType dragType)1191 void DragDropManager::OnItemDragMove(float globalX, float globalY, int32_t draggedIndex, DragType dragType)
1192 {
1193     auto container = Container::Current();
1194     CHECK_NULL_VOID(container);
1195 
1196     const float windowScale = isDragWindowSubWindow_ ? 1.0f : GetWindowScale();
1197     const float windowX = globalX * windowScale;
1198     const float windowY = globalY * windowScale;
1199     UpdateDragWindowPosition(static_cast<int32_t>(windowX), static_cast<int32_t>(windowY));
1200 
1201     OHOS::Ace::ItemDragInfo itemDragInfo;
1202     itemDragInfo.SetX(windowX);
1203     itemDragInfo.SetY(windowY);
1204 
1205     // use -1 for grid item not in eventGrid
1206     auto getDraggedIndex = [draggedGrid = draggedGridFrameNode_, draggedIndex, dragType](
1207                                const RefPtr<FrameNode>& eventGrid) {
1208         return (dragType == DragType::GRID) ? (eventGrid == draggedGrid ? draggedIndex : -1) : draggedIndex;
1209     };
1210 
1211     auto dragFrameNode = FindDragFrameNodeByPosition(globalX, globalY);
1212     if (!dragFrameNode) {
1213         if (preGridTargetFrameNode_) {
1214             TAG_LOGI(AceLogTag::ACE_DRAG, "Not find drag target node, current windowId is %{public}d,"
1215                 "PreGridTargetFrameNode is %{public}s, depth is %{public}d.",
1216                 container->GetWindowId(), preGridTargetFrameNode_->GetTag().c_str(),
1217                 preGridTargetFrameNode_->GetDepth());
1218             FireOnItemDragEvent(preGridTargetFrameNode_, dragType, itemDragInfo, DragEventType::LEAVE,
1219                 getDraggedIndex(preGridTargetFrameNode_));
1220             preGridTargetFrameNode_ = nullptr;
1221         }
1222         return;
1223     }
1224 
1225     if (dragFrameNode == preGridTargetFrameNode_) {
1226         int32_t insertIndex = GetItemIndex(dragFrameNode, dragType, globalX, globalY);
1227         FireOnItemDragEvent(
1228             dragFrameNode, dragType, itemDragInfo, DragEventType::MOVE, getDraggedIndex(dragFrameNode), insertIndex);
1229         return;
1230     }
1231 
1232     if (preGridTargetFrameNode_) {
1233         FireOnItemDragEvent(preGridTargetFrameNode_, dragType, itemDragInfo, DragEventType::LEAVE,
1234             getDraggedIndex(preGridTargetFrameNode_));
1235     }
1236 
1237     PrintGridDragFrameNode(globalX, globalY, dragFrameNode);
1238     FireOnItemDragEvent(dragFrameNode, dragType, itemDragInfo, DragEventType::ENTER, getDraggedIndex(dragFrameNode));
1239     preGridTargetFrameNode_ = dragFrameNode;
1240 }
1241 
GetWindowScale() const1242 float DragDropManager::GetWindowScale() const
1243 {
1244     float scale = 1.0f;
1245     auto container = Container::Current();
1246     CHECK_NULL_RETURN(container, scale);
1247     scale = container->GetWindowScale();
1248     return scale;
1249 }
1250 
OnItemDragEnd(float globalX,float globalY,int32_t draggedIndex,DragType dragType)1251 void DragDropManager::OnItemDragEnd(float globalX, float globalY, int32_t draggedIndex, DragType dragType)
1252 {
1253     dragDropState_ = DragDropMgrState::IDLE;
1254     auto windowScale = isDragWindowSubWindow_ ? 1.0f : GetWindowScale();
1255     auto windowX = globalX * windowScale;
1256     auto windowY = globalY * windowScale;
1257 
1258     OHOS::Ace::ItemDragInfo itemDragInfo;
1259     itemDragInfo.SetX(windowX);
1260     itemDragInfo.SetY(windowY);
1261 
1262     auto dragFrameNode = FindDragFrameNodeByPosition(globalX, globalY);
1263     if (!dragFrameNode) {
1264         // drag on one grid and drop on other area
1265         if (draggedGridFrameNode_) {
1266             if (dragType == DragType::GRID) {
1267                 auto eventHub = draggedGridFrameNode_->GetEventHub<GridEventHub>();
1268                 CHECK_NULL_VOID(eventHub);
1269                 eventHub->FireOnItemDrop(itemDragInfo, draggedIndex, -1, false);
1270             } else {
1271                 auto eventHub = draggedGridFrameNode_->GetEventHub<ListEventHub>();
1272                 CHECK_NULL_VOID(eventHub);
1273                 eventHub->FireOnItemDrop(itemDragInfo, draggedIndex, -1, false);
1274             }
1275         }
1276     } else {
1277         int32_t insertIndex = GetItemIndex(dragFrameNode, dragType, globalX, globalY);
1278         // drag and drop on the same grid
1279         if (dragFrameNode == draggedGridFrameNode_) {
1280             FireOnItemDropEvent(dragFrameNode, dragType, itemDragInfo, draggedIndex, insertIndex, true);
1281         } else {
1282             // drag and drop on different grid
1283             bool isSuccess = FireOnItemDropEvent(dragFrameNode, dragType, itemDragInfo, -1, insertIndex, true);
1284             if (draggedGridFrameNode_) {
1285                 FireOnItemDropEvent(draggedGridFrameNode_, dragType, itemDragInfo, draggedIndex, -1, isSuccess);
1286             }
1287         }
1288     }
1289 
1290     preGridTargetFrameNode_ = nullptr;
1291     draggedGridFrameNode_ = nullptr;
1292 }
1293 
onItemDragCancel()1294 void DragDropManager::onItemDragCancel()
1295 {
1296     dragDropState_ = DragDropMgrState::IDLE;
1297     preGridTargetFrameNode_ = nullptr;
1298     draggedGridFrameNode_ = nullptr;
1299 }
1300 
FireOnItemDragEvent(const RefPtr<FrameNode> & frameNode,DragType dragType,const OHOS::Ace::ItemDragInfo & itemDragInfo,DragEventType type,int32_t draggedIndex,int32_t insertIndex)1301 void DragDropManager::FireOnItemDragEvent(const RefPtr<FrameNode>& frameNode, DragType dragType,
1302     const OHOS::Ace::ItemDragInfo& itemDragInfo, DragEventType type, int32_t draggedIndex, int32_t insertIndex)
1303 {
1304     if (dragType == DragType::GRID) {
1305         auto eventHub = frameNode->GetEventHub<GridEventHub>();
1306         CHECK_NULL_VOID(eventHub);
1307         switch (type) {
1308             case DragEventType::ENTER:
1309                 eventHub->FireOnItemDragEnter(itemDragInfo);
1310                 break;
1311             case DragEventType::MOVE:
1312                 eventHub->FireOnItemDragMove(itemDragInfo, draggedIndex, insertIndex);
1313                 break;
1314             case DragEventType::LEAVE:
1315                 eventHub->FireOnItemDragLeave(itemDragInfo, draggedIndex);
1316                 break;
1317             default:
1318                 break;
1319         }
1320     } else if (dragType == DragType::LIST) {
1321         auto eventHub = frameNode->GetEventHub<ListEventHub>();
1322         CHECK_NULL_VOID(eventHub);
1323         switch (type) {
1324             case DragEventType::ENTER:
1325                 eventHub->FireOnItemDragEnter(itemDragInfo);
1326                 break;
1327             case DragEventType::MOVE:
1328                 eventHub->FireOnItemDragMove(itemDragInfo, draggedIndex, insertIndex);
1329                 break;
1330             case DragEventType::LEAVE:
1331                 eventHub->FireOnItemDragLeave(itemDragInfo, draggedIndex);
1332                 break;
1333             default:
1334                 break;
1335         }
1336     }
1337 }
1338 
FireOnItemDropEvent(const RefPtr<FrameNode> & frameNode,DragType dragType,const OHOS::Ace::ItemDragInfo & itemDragInfo,int32_t draggedIndex,int32_t insertIndex,bool isSuccess)1339 bool DragDropManager::FireOnItemDropEvent(const RefPtr<FrameNode>& frameNode, DragType dragType,
1340     const OHOS::Ace::ItemDragInfo& itemDragInfo, int32_t draggedIndex, int32_t insertIndex, bool isSuccess)
1341 {
1342     if (dragType == DragType::GRID) {
1343         auto eventHub = frameNode->GetEventHub<GridEventHub>();
1344         CHECK_NULL_RETURN(eventHub, false);
1345         return eventHub->FireOnItemDrop(itemDragInfo, draggedIndex, insertIndex, isSuccess);
1346     } else if (dragType == DragType::LIST) {
1347         auto eventHub = frameNode->GetEventHub<ListEventHub>();
1348         CHECK_NULL_RETURN(eventHub, false);
1349         return eventHub->FireOnItemDrop(itemDragInfo, draggedIndex, insertIndex, isSuccess);
1350     }
1351     return false;
1352 }
1353 
GetItemIndex(const RefPtr<FrameNode> & frameNode,DragType dragType,float globalX,float globalY)1354 int32_t DragDropManager::GetItemIndex(
1355     const RefPtr<FrameNode>& frameNode, DragType dragType, float globalX, float globalY)
1356 {
1357     CHECK_NULL_RETURN(frameNode, -1);
1358     if (dragType == DragType::GRID) {
1359         auto eventHub = frameNode->GetEventHub<GridEventHub>();
1360         CHECK_NULL_RETURN(eventHub, -1);
1361         if (frameNode != draggedGridFrameNode_) {
1362             return eventHub->GetInsertPosition(globalX, globalY);
1363         }
1364         auto itemFrameNode = frameNode->FindChildByPositionWithoutChildTransform(globalX, globalY);
1365         if (!itemFrameNode) {
1366             if (eventHub->CheckPostionInGrid(globalX, globalY)) {
1367                 return eventHub->GetFrameNodeChildSize();
1368             }
1369         } else {
1370             return eventHub->GetGridItemIndex(itemFrameNode);
1371         }
1372     } else if (dragType == DragType::LIST) {
1373         auto eventHub = frameNode->GetEventHub<ListEventHub>();
1374         CHECK_NULL_RETURN(eventHub, -1);
1375         return eventHub->GetListItemIndexByPosition(globalX, globalY);
1376     }
1377     return -1;
1378 }
1379 
AddDataToClipboard(const std::string & extraInfo)1380 void DragDropManager::AddDataToClipboard(const std::string& extraInfo)
1381 {
1382     auto pipeline = PipelineContext::GetCurrentContext();
1383     CHECK_NULL_VOID(pipeline);
1384     if (!extraInfo.empty()) {
1385         if (!newData_) {
1386             newData_ = JsonUtil::Create(true);
1387             newData_->Put("customDragInfo", extraInfo.c_str());
1388         } else {
1389             newData_->Replace("customDragInfo", extraInfo.c_str());
1390         }
1391     } else {
1392         return;
1393     }
1394     if (!clipboard_) {
1395         clipboard_ = ClipboardProxy::GetInstance()->GetClipboard(pipeline->GetTaskExecutor());
1396     }
1397     if (!addDataCallback_) {
1398         auto callback = [weakManager = WeakClaim(this)](const std::string& data) {
1399             auto dragDropManager = weakManager.Upgrade();
1400             auto addData = dragDropManager->newData_->ToString();
1401             CHECK_NULL_VOID(dragDropManager);
1402             auto clipboardAllData = JsonUtil::Create(true);
1403             clipboardAllData->Put("preData", data.c_str());
1404             clipboardAllData->Put("newData", addData.c_str());
1405             dragDropManager->clipboard_->SetData(clipboardAllData->ToString(), CopyOptions::Local, true);
1406         };
1407         addDataCallback_ = callback;
1408     }
1409     if (clipboard_) {
1410         clipboard_->GetData(addDataCallback_, true);
1411     }
1412 }
1413 
GetExtraInfoFromClipboard(std::string & extraInfo)1414 void DragDropManager::GetExtraInfoFromClipboard(std::string& extraInfo)
1415 {
1416     auto pipeline = PipelineContext::GetCurrentContext();
1417     CHECK_NULL_VOID(pipeline);
1418 
1419     if (!clipboard_) {
1420         clipboard_ = ClipboardProxy::GetInstance()->GetClipboard(pipeline->GetTaskExecutor());
1421     }
1422 
1423     if (!getDataCallback_) {
1424         auto callback = [weak = WeakClaim(this)](const std::string& data) {
1425             auto manager = weak.Upgrade();
1426             CHECK_NULL_VOID(manager);
1427             auto json = JsonUtil::ParseJsonString(data);
1428             auto newData = JsonUtil::ParseJsonString(json->GetString("newData"));
1429             manager->extraInfo_ = newData->GetString("customDragInfo");
1430         };
1431         getDataCallback_ = callback;
1432     }
1433 
1434     if (getDataCallback_ && clipboard_) {
1435         clipboard_->GetData(getDataCallback_, true);
1436     }
1437 
1438     extraInfo = extraInfo_;
1439 }
1440 
RestoreClipboardData()1441 void DragDropManager::RestoreClipboardData()
1442 {
1443     auto pipeline = PipelineContext::GetCurrentContext();
1444     CHECK_NULL_VOID(pipeline);
1445 
1446     if (!clipboard_) {
1447         clipboard_ = ClipboardProxy::GetInstance()->GetClipboard(pipeline->GetTaskExecutor());
1448     }
1449 
1450     if (!deleteDataCallback_) {
1451         auto callback = [weakManager = WeakClaim(this)](const std::string& data) {
1452             auto dragDropManager = weakManager.Upgrade();
1453             CHECK_NULL_VOID(dragDropManager);
1454             auto json = JsonUtil::ParseJsonString(data);
1455             if (json->Contains("preData")) {
1456                 dragDropManager->clipboard_->SetData(json->GetString("preData"));
1457             }
1458         };
1459         deleteDataCallback_ = callback;
1460     }
1461     if (clipboard_) {
1462         clipboard_->GetData(deleteDataCallback_, true);
1463     }
1464 }
1465 
DestroyDragWindow()1466 void DragDropManager::DestroyDragWindow()
1467 {
1468     if (dragWindow_ != nullptr) {
1469         dragWindow_->Destroy();
1470         dragWindow_ = nullptr;
1471     }
1472     ResetRecordSize();
1473     if (dragWindowRootNode_) {
1474         dragWindowRootNode_ = nullptr;
1475     }
1476     SetIsDragged(false);
1477     SetIsDragWindowShow(false);
1478     previewRect_ = Rect(-1, -1, -1, -1);
1479     isMouseDragged_ = false;
1480     currentId_ = -1;
1481 }
1482 
CancelItemDrag()1483 void DragDropManager::CancelItemDrag()
1484 {
1485     if (draggedGridFrameNode_) {
1486         auto listEventHub = draggedGridFrameNode_->GetEventHub<ListEventHub>();
1487         if (listEventHub) {
1488             listEventHub->HandleOnItemDragCancel();
1489             return;
1490         }
1491         auto gridEventHub = draggedGridFrameNode_->GetEventHub<GridEventHub>();
1492         if (gridEventHub) {
1493             gridEventHub->HandleOnItemDragCancel();
1494             return;
1495         }
1496     }
1497 }
1498 
CreateFrameworkDragDropProxy()1499 RefPtr<DragDropProxy> DragDropManager::CreateFrameworkDragDropProxy()
1500 {
1501     SetIsDragged(true);
1502     isDragCancel_ = false;
1503     currentId_ = ++g_proxyId;
1504     return MakeRefPtr<DragDropProxy>(currentId_);
1505 }
1506 
UpdateNotifyDragEvent(RefPtr<NotifyDragEvent> & notifyEvent,const Point & point,const DragEventType dragEventType)1507 void DragDropManager::UpdateNotifyDragEvent(
1508     RefPtr<NotifyDragEvent>& notifyEvent, const Point& point, const DragEventType dragEventType)
1509 {
1510     notifyEvent->SetX((double)point.GetX());
1511     notifyEvent->SetY((double)point.GetY());
1512     notifyEvent->SetScreenX((double)point.GetScreenX());
1513     notifyEvent->SetScreenY((double)point.GetScreenY());
1514     if (dragEventType != DragEventType::START) {
1515         if (dragEventType != DragEventType::DROP) {
1516             notifyEvent->SetVelocity(velocityTracker_.GetVelocity());
1517         }
1518         notifyEvent->SetSummary(summaryMap_);
1519         notifyEvent->SetPreviewRect(GetDragWindowRect(point));
1520     }
1521 }
1522 
UpdateDragEvent(RefPtr<OHOS::Ace::DragEvent> & event,const OHOS::Ace::PointerEvent & pointerEvent)1523 void DragDropManager::UpdateDragEvent(RefPtr<OHOS::Ace::DragEvent>& event, const OHOS::Ace::PointerEvent& pointerEvent)
1524 {
1525     auto point = pointerEvent.GetPoint();
1526     event->SetX(point.GetX());
1527     event->SetY(point.GetY());
1528     event->SetScreenX(point.GetScreenX());
1529     event->SetScreenY(point.GetScreenY());
1530     event->SetDisplayX((double)pointerEvent.GetDisplayX());
1531     event->SetDisplayY((double)pointerEvent.GetDisplayY());
1532     event->SetVelocity(velocityTracker_.GetVelocity());
1533     event->SetSummary(summaryMap_);
1534     event->SetPreviewRect(GetDragWindowRect(point));
1535 }
1536 
GetExtraInfo()1537 std::string DragDropManager::GetExtraInfo()
1538 {
1539     return extraInfo_;
1540 }
1541 
SetExtraInfo(const std::string & extraInfo)1542 void DragDropManager::SetExtraInfo(const std::string& extraInfo)
1543 {
1544     extraInfo_ = extraInfo;
1545 }
1546 
ClearExtraInfo()1547 void DragDropManager::ClearExtraInfo()
1548 {
1549     extraInfo_.clear();
1550 }
1551 
IsMSDPDragging() const1552 bool DragDropManager::IsMSDPDragging() const
1553 {
1554     DragState dragState;
1555     InteractionInterface::GetInstance()->GetDragState(dragState);
1556     return dragState == DragState::START;
1557 }
1558 
ClearVelocityInfo()1559 void DragDropManager::ClearVelocityInfo()
1560 {
1561     velocityTracker_.Reset();
1562 }
1563 
UpdateVelocityTrackerPoint(const Point & point,bool isEnd)1564 void DragDropManager::UpdateVelocityTrackerPoint(const Point& point, bool isEnd)
1565 {
1566     std::chrono::microseconds microseconds(GetMicroTickCount());
1567     TimeStamp curTime(microseconds);
1568     velocityTracker_.UpdateTrackerPoint(point.GetX(), point.GetY(), curTime, isEnd);
1569 }
1570 
NotifyEnterTextEditorArea()1571 void DragDropManager::NotifyEnterTextEditorArea()
1572 {
1573     auto ret = InteractionInterface::GetInstance()->EnterTextEditorArea(true);
1574     if (ret != 0) {
1575         TAG_LOGW(AceLogTag::ACE_DRAG, "Fail to notify entering text editor erea.");
1576         return;
1577     }
1578 
1579     hasNotifiedTransformation_ = true;
1580 }
1581 
FireOnEditableTextComponent(const RefPtr<FrameNode> & frameNode,DragEventType type)1582 void DragDropManager::FireOnEditableTextComponent(const RefPtr<FrameNode>& frameNode,
1583     DragEventType type)
1584 {
1585     CHECK_NULL_VOID(frameNode);
1586     auto frameTag = frameNode->GetTag();
1587     auto eventHub = frameNode->GetEventHub<EventHub>();
1588     if (!IsEditableTextComponent(frameTag) || !(eventHub && eventHub->IsEnabled()) || !isDragFwkShow_) {
1589         return;
1590     }
1591 
1592     // When moving in an editable text component whithout animation, and has not notified msdp yet, notify msdp.
1593     if (type == DragEventType::MOVE && IsEditableTextComponent(frameTag) && isDragFwkShow_ &&
1594         !hasNotifiedTransformation_) {
1595         NotifyEnterTextEditorArea();
1596         return;
1597     }
1598     if (type != DragEventType::ENTER && type != DragEventType::LEAVE) {
1599         TAG_LOGD(AceLogTag::ACE_DRAG, "It is an invalid drag type %{public}d", type);
1600         return;
1601     }
1602 
1603     if (type == DragEventType::LEAVE) {
1604         TAG_LOGI(AceLogTag::ACE_DRAG, "The current control has been dragged away.");
1605         hasNotifiedTransformation_ = false;
1606         return;
1607     }
1608 
1609     if (hasNotifiedTransformation_) {
1610         TAG_LOGI(AceLogTag::ACE_DRAG, "Coordinates have been transformed.");
1611         return;
1612     }
1613 
1614     NotifyEnterTextEditorArea();
1615 }
1616 
GetDragPreviewInfo(const RefPtr<OverlayManager> & overlayManager,DragPreviewInfo & dragPreviewInfo,const RefPtr<GestureEventHub> & gestureHub)1617 bool DragDropManager::GetDragPreviewInfo(const RefPtr<OverlayManager>& overlayManager,
1618     DragPreviewInfo& dragPreviewInfo, const RefPtr<GestureEventHub>& gestureHub)
1619 {
1620     if (!overlayManager->GetHasDragPixelMap()) {
1621         return false;
1622     }
1623     auto imageNode = overlayManager->GetDragPixelMapContentNode();
1624     CHECK_NULL_RETURN(imageNode, false);
1625     auto badgeNode = overlayManager->GetDragPixelMapBadgeNode();
1626     if (badgeNode) {
1627         dragPreviewInfo.textNode = badgeNode;
1628     }
1629     CHECK_NULL_RETURN(gestureHub, false);
1630     auto frameNode = gestureHub->GetFrameNode();
1631     double maxWidth = DragDropManager::GetMaxWidthBaseOnGridSystem(frameNode->GetContextRefPtr());
1632     auto width = imageNode->GetGeometryNode()->GetFrameRect().Width();
1633     auto previewOption = imageNode->GetDragPreviewOption();
1634     if (imageNode->GetTag() != V2::WEB_ETS_TAG && width != 0 && width > maxWidth && previewOption.isScaleEnabled) {
1635         dragPreviewInfo.scale = maxWidth / width;
1636     } else {
1637         dragPreviewInfo.scale = 1.0f;
1638     }
1639 
1640     if (!isMouseDragged_ && dragPreviewInfo.scale == 1.0f) {
1641         dragPreviewInfo.scale = TOUCH_DRAG_PIXELMAP_SCALE;
1642     }
1643     // set menu preview scale only for no scale menu preview.
1644     if (isDragWithContextMenu_ && (!previewOption.isScaleEnabled || width < maxWidth)) {
1645         auto imageGestureEventHub = imageNode->GetOrCreateGestureEventHub();
1646         if (imageGestureEventHub) {
1647             auto menuPreviewScale = imageGestureEventHub->GetMenuPreviewScale();
1648             dragPreviewInfo.scale =
1649                 GreatNotEqual(menuPreviewScale, 0.0f) ? menuPreviewScale : TOUCH_DRAG_PIXELMAP_SCALE;
1650         }
1651     }
1652     dragPreviewInfo.height = imageNode->GetGeometryNode()->GetFrameRect().Height();
1653     dragPreviewInfo.width = static_cast<double>(width);
1654     dragPreviewInfo.maxWidth = maxWidth;
1655     dragPreviewInfo.imageNode = imageNode;
1656     dragPreviewInfo.originOffset = imageNode->GetPositionToWindowWithTransform();
1657     dragPreviewInfo.originScale = imageNode->GetTransformScale();
1658     return true;
1659 }
1660 
IsNeedDoDragMoveAnimate(const PointerEvent & pointerEvent)1661 bool DragDropManager::IsNeedDoDragMoveAnimate(const PointerEvent& pointerEvent)
1662 {
1663     if (!(IsNeedDisplayInSubwindow() || isDragWithContextMenu_) || isDragFwkShow_) {
1664         return false;
1665     }
1666     auto x = pointerEvent.GetPoint().GetX();
1667     auto y = pointerEvent.GetPoint().GetY();
1668     curPointerOffset_ = { x, y };
1669     return true;
1670 }
1671 
IsNeedScaleDragPreview()1672 bool DragDropManager::IsNeedScaleDragPreview()
1673 {
1674     return info_.scale > 0 && info_.scale < 1.0f;
1675 }
1676 
GetTouchOffsetRelativeToSubwindow(int32_t x,int32_t y)1677 OffsetF GetTouchOffsetRelativeToSubwindow(int32_t x, int32_t y)
1678 {
1679     auto touchOffset = OffsetF(x, y);
1680     auto pipeline = PipelineContext::GetCurrentContext();
1681     if (pipeline) {
1682         auto window = pipeline->GetWindow();
1683         if (window) {
1684             auto windowOffset = window->GetCurrentWindowRect().GetOffset();
1685             touchOffset.SetX(touchOffset.GetX() + windowOffset.GetX());
1686             touchOffset.SetY(touchOffset.GetY() + windowOffset.GetY());
1687         }
1688     }
1689     auto containerId = Container::CurrentId();
1690     auto subwindow = SubwindowManager::GetInstance()->GetSubwindow(
1691         containerId >= MIN_SUBCONTAINER_ID ? SubwindowManager::GetInstance()->GetParentContainerId(containerId)
1692                                            : containerId);
1693     if (subwindow) {
1694         auto subwindowOffset = subwindow->GetRect().GetOffset();
1695         touchOffset.SetX(touchOffset.GetX() - subwindowOffset.GetX());
1696         touchOffset.SetY(touchOffset.GetY() - subwindowOffset.GetY());
1697     }
1698     return touchOffset;
1699 }
1700 
CalcDragPreviewDistanceWithPoint(const OHOS::Ace::Dimension & preserverHeight,int32_t x,int32_t y,const DragPreviewInfo & info)1701 double DragDropManager::CalcDragPreviewDistanceWithPoint(
1702     const OHOS::Ace::Dimension& preserverHeight, int32_t x, int32_t y, const DragPreviewInfo& info)
1703 {
1704     CHECK_NULL_RETURN(info.imageNode, 0.0);
1705     auto nodeOffset = info.imageNode->GetTransformRelativeOffset();
1706     auto renderContext = info.imageNode->GetRenderContext();
1707     CHECK_NULL_RETURN(renderContext, 0.0);
1708     nodeOffset -= pixelMapOffset_;
1709     auto touchOffset = GetTouchOffsetRelativeToSubwindow(x, y);
1710     // calculate distance, so need to pow 2.
1711     return sqrt(pow(nodeOffset.GetX() - touchOffset.GetX(), 2) + pow(nodeOffset.GetY() - touchOffset.GetY(), 2));
1712 }
1713 
CalcDragMoveOffset(const OHOS::Ace::Dimension & preserverHeight,int32_t x,int32_t y,const DragPreviewInfo & info)1714 Offset DragDropManager::CalcDragMoveOffset(
1715     const OHOS::Ace::Dimension& preserverHeight, int32_t x, int32_t y, const DragPreviewInfo& info)
1716 {
1717     auto originPoint = info.originOffset;
1718     originPoint.SetX(originPoint.GetX() - pixelMapOffset_.GetX() +
1719         (info.originScale.x - info.scale) * info.width / 2.0f);
1720     originPoint.SetY(originPoint.GetY() - pixelMapOffset_.GetY() +
1721         (info.originScale.y - info.scale) * info.height / 2.0f);
1722     auto touchOffset = GetTouchOffsetRelativeToSubwindow(x, y);
1723     Offset newOffset { touchOffset.GetX() - originPoint.GetX(), touchOffset.GetY() - originPoint.GetY() };
1724     return newOffset;
1725 }
1726 
UpdateDragMovePositionFinished(bool needDoDragMoveAnimate,bool isMenuShow,const Offset & newOffset,int32_t containerId)1727 bool DragDropManager::UpdateDragMovePositionFinished(
1728     bool needDoDragMoveAnimate, bool isMenuShow, const Offset& newOffset, int32_t containerId)
1729 {
1730     if (!isDragWithContextMenu_) {
1731         return false;
1732     }
1733 
1734     CHECK_NULL_RETURN(info_.imageNode, false);
1735     auto renderContext = info_.imageNode->GetRenderContext();
1736     CHECK_NULL_RETURN(renderContext, false);
1737     SubwindowManager::GetInstance()->ContextMenuSwitchDragPreviewAnimation(info_.imageNode,
1738         OffsetF(newOffset.GetX(), newOffset.GetY()));
1739     if (!needDoDragMoveAnimate) {
1740         renderContext->UpdateTransformTranslate({ newOffset.GetX(), newOffset.GetY(), 0.0f });
1741         if (!isMenuShow) {
1742             TransDragWindowToDragFwk(containerId);
1743         }
1744         return true;
1745     }
1746     return false;
1747 }
1748 
GetCurrentDistance(float x,float y)1749 float DragDropManager::GetCurrentDistance(float x, float y)
1750 {
1751     auto distance = sqrt(pow(curPointerOffset_.GetX() - x, 2) + pow(curPointerOffset_.GetY() - y, 2));
1752     CHECK_NULL_RETURN(info_.imageNode, distance);
1753     auto containerId = Container::CurrentId();
1754     auto subwindow = SubwindowManager::GetInstance()->GetSubwindow(containerId);
1755     CHECK_NULL_RETURN(subwindow, distance);
1756     auto overlayManager = subwindow->GetOverlayManager();
1757     auto gatherNodeCenter = info_.imageNode->GetPaintRectCenter();
1758     auto gatherDistance = CalcGatherNodeMaxDistanceWithPoint(overlayManager,
1759         gatherNodeCenter.GetX(), gatherNodeCenter.GetY());
1760     return std::max(distance, gatherDistance);
1761 }
1762 
DoDragMoveAnimate(const PointerEvent & pointerEvent)1763 void DragDropManager::DoDragMoveAnimate(const PointerEvent& pointerEvent)
1764 {
1765     bool needDoDragMoveAnimate = IsNeedDoDragMoveAnimate(pointerEvent);
1766     if (!needDoDragMoveAnimate) {
1767         return;
1768     }
1769     isPullMoveReceivedForCurrentDrag_ = true;
1770     CHECK_NULL_VOID(info_.imageNode);
1771     auto containerId = Container::CurrentId();
1772     auto overlayManager = GetDragAnimationOverlayManager(containerId);
1773     CHECK_NULL_VOID(overlayManager);
1774     auto point = pointerEvent.GetPoint();
1775     Offset newOffset = CalcDragMoveOffset(PRESERVE_HEIGHT, point.GetX(), point.GetY(), info_);
1776     bool isMenuShow = overlayManager->IsMenuShow();
1777     if (UpdateDragMovePositionFinished(needDoDragMoveAnimate, isMenuShow, newOffset, containerId) ||
1778         !needDoDragMoveAnimate) {
1779         return;
1780     }
1781     DragMoveAnimation(newOffset, overlayManager, point);
1782 }
1783 
DragMoveAnimation(const Offset & newOffset,const RefPtr<OverlayManager> & overlayManager,Point point)1784 void DragDropManager::DragMoveAnimation(
1785     const Offset& newOffset, const RefPtr<OverlayManager>& overlayManager, Point point)
1786 {
1787     auto containerId = Container::CurrentId();
1788     bool isMenuShow = overlayManager->IsMenuShow();
1789     AnimationOption option;
1790     auto springResponse =
1791         std::max(DEFAULT_SPRING_RESPONSE - DEL_SPRING_RESPONSE * allAnimationCnt_, MIN_SPRING_RESPONSE);
1792     const RefPtr<Curve> curve = AceType::MakeRefPtr<ResponsiveSpringMotion>(springResponse, 0.99f, 0.0f);
1793     constexpr int32_t animateDuration = 30;
1794     option.SetCurve(curve);
1795     option.SetDuration(animateDuration);
1796     bool dragWithContextMenu = isDragWithContextMenu_;
1797     AddNewDragAnimation();
1798     option.SetOnFinishEvent([weakManager = WeakClaim(this), containerId, dragWithContextMenu, isMenuShow,
1799                                 x = point.GetX(), y = point.GetY()]() {
1800         auto dragDropManager = weakManager.Upgrade();
1801         CHECK_NULL_VOID(dragDropManager);
1802         if ((dragDropManager->IsAllAnimationFinished() ||
1803                 dragDropManager->GetCurrentDistance(x, y) < MAX_DISTANCE_TO_PRE_POINTER) &&
1804             (!dragWithContextMenu || !isMenuShow)) {
1805             dragDropManager->TransDragWindowToDragFwk(containerId);
1806         }
1807     });
1808     auto renderContext = info_.imageNode->GetRenderContext();
1809     CHECK_NULL_VOID(renderContext);
1810     auto offset = OffsetF(point.GetX(), point.GetY());
1811     auto menuWrapperNode = GetMenuWrapperNodeFromDrag();
1812     auto menuPosition = overlayManager->CalculateMenuPosition(menuWrapperNode, offset);
1813     auto menuRenderContext = GetMenuRenderContextFromMenuWrapper(menuWrapperNode);
1814     AnimationUtils::Animate(
1815         option,
1816         [renderContext, localPoint = newOffset, info = info_, overlayManager, menuRenderContext, menuPosition]() {
1817             if (menuRenderContext && !menuPosition.NonOffset()) {
1818                 menuRenderContext->UpdatePosition(
1819                     OffsetT<Dimension>(Dimension(menuPosition.GetX()), Dimension(menuPosition.GetY())));
1820             }
1821             renderContext->UpdateTransformTranslate({ localPoint.GetX(), localPoint.GetY(), 0.0f });
1822             UpdateGatherNodePosition(overlayManager, info.imageNode);
1823             UpdateTextNodePosition(info.textNode, localPoint);
1824         },
1825         option.GetOnFinishEvent());
1826 }
1827 
UpdateDragPreviewScale()1828 void DragDropManager::UpdateDragPreviewScale()
1829 {
1830     CHECK_NULL_VOID(info_.imageNode);
1831     if (IsNeedDisplayInSubwindow()) {
1832         return;
1833     }
1834     auto renderContext = info_.imageNode->GetRenderContext();
1835     CHECK_NULL_VOID(renderContext);
1836     renderContext->UpdateTransformScale({ info_.scale, info_.scale });
1837 }
1838 
DoDragStartAnimation(const RefPtr<OverlayManager> & overlayManager,const GestureEvent & event,const RefPtr<GestureEventHub> & gestureHub,bool isSubwindowOverlay)1839 void DragDropManager::DoDragStartAnimation(const RefPtr<OverlayManager>& overlayManager,
1840     const GestureEvent& event, const RefPtr<GestureEventHub>& gestureHub, bool isSubwindowOverlay)
1841 {
1842     auto containerId = Container::CurrentId();
1843     auto deviceId = static_cast<int32_t>(event.GetDeviceId());
1844     if (deviceId == RESERVED_DEVICEID) {
1845         isDragFwkShow_ = false;
1846         TAG_LOGI(AceLogTag::ACE_DRAG, "Do not need animation.");
1847         TransDragWindowToDragFwk(containerId);
1848         return;
1849     }
1850     CHECK_NULL_VOID(overlayManager);
1851     CHECK_NULL_VOID(gestureHub);
1852     if (!(GetDragPreviewInfo(overlayManager, info_, gestureHub))
1853         || (!IsNeedDisplayInSubwindow() && !isSubwindowOverlay && !isDragWithContextMenu_)) {
1854         if (isDragWithContextMenu_) {
1855             UpdateDragPreviewScale();
1856             isDragFwkShow_ = false;
1857         }
1858         return;
1859     }
1860     CHECK_NULL_VOID(info_.imageNode);
1861     isDragFwkShow_ = false;
1862     ResetPullMoveReceivedForCurrentDrag();
1863     auto gatherNodeCenter = info_.imageNode->GetPaintRectCenter();
1864     Point point = { static_cast<int32_t>(event.GetGlobalLocation().GetX()),
1865         static_cast<int32_t>(event.GetGlobalLocation().GetY()) };
1866     Offset newOffset = CalcDragMoveOffset(PRESERVE_HEIGHT, static_cast<int32_t>(event.GetGlobalLocation().GetX()),
1867         static_cast<int32_t>(event.GetGlobalLocation().GetY()), info_);
1868     curPointerOffset_ = { newOffset.GetX(), newOffset.GetY() };
1869     currentAnimationCnt_ = 0;
1870     allAnimationCnt_ = 0;
1871     DragStartAnimation(newOffset, overlayManager, gatherNodeCenter, point);
1872 }
1873 
DragStartAnimation(const Offset & newOffset,const RefPtr<OverlayManager> & overlayManager,const OffsetF & gatherNodeCenter,Point point)1874 void DragDropManager::DragStartAnimation(
1875     const Offset& newOffset, const RefPtr<OverlayManager>& overlayManager, const OffsetF& gatherNodeCenter, Point point)
1876 {
1877     auto containerId = Container::CurrentId();
1878     AnimationOption option;
1879     const RefPtr<Curve> curve = AceType::MakeRefPtr<ResponsiveSpringMotion>(0.347f, 0.99f, 0.0f);
1880     constexpr int32_t animateDuration = 300;
1881     option.SetCurve(curve);
1882     option.SetDuration(animateDuration);
1883     option.SetOnFinishEvent([weakManager = WeakClaim(this), containerId]() {
1884         auto dragDropManager = weakManager.Upgrade();
1885         if (dragDropManager && !dragDropManager->IsPullMoveReceivedForCurrentDrag()) {
1886             dragDropManager->TransDragWindowToDragFwk(containerId);
1887         }
1888     });
1889     auto renderContext = info_.imageNode->GetRenderContext();
1890     CHECK_NULL_VOID(renderContext);
1891     auto offset = OffsetF(point.GetX(), point.GetY());
1892     auto menuWrapperNode = GetMenuWrapperNodeFromDrag();
1893     auto menuPosition = overlayManager->CalculateMenuPosition(menuWrapperNode, offset);
1894     auto menuRenderContext = GetMenuRenderContextFromMenuWrapper(menuWrapperNode);
1895     AnimationUtils::Animate(
1896         option,
1897         [renderContext, info = info_, newOffset, overlayManager, gatherNodeCenter, menuRenderContext, menuPosition]() {
1898             CHECK_NULL_VOID(renderContext);
1899             if (menuRenderContext && !menuPosition.NonOffset()) {
1900                 menuRenderContext->UpdatePosition(
1901                     OffsetT<Dimension>(Dimension(menuPosition.GetX()), Dimension(menuPosition.GetY())));
1902             }
1903             renderContext->UpdateTransformScale({ info.scale, info.scale });
1904             renderContext->UpdateTransformTranslate({ newOffset.GetX(), newOffset.GetY(), 0.0f });
1905             GatherAnimationInfo gatherAnimationInfo = { info.scale, info.width, info.height,
1906                 gatherNodeCenter, renderContext->GetBorderRadius() };
1907             UpdateGatherNodeAttr(overlayManager, gatherAnimationInfo);
1908             UpdateTextNodePosition(info.textNode, newOffset);
1909         },
1910         option.GetOnFinishEvent());
1911 }
1912 
SetDragResult(const DragNotifyMsgCore & notifyMessage,const RefPtr<OHOS::Ace::DragEvent> & dragEvent)1913 void DragDropManager::SetDragResult(
1914     const DragNotifyMsgCore& notifyMessage, const RefPtr<OHOS::Ace::DragEvent>& dragEvent)
1915 {
1916     DragRet result = DragRet::DRAG_FAIL;
1917     switch (notifyMessage.result) {
1918         case DragRet::DRAG_SUCCESS:
1919             result = DragRet::DRAG_SUCCESS;
1920             break;
1921         case DragRet::DRAG_FAIL:
1922             result = DragRet::DRAG_FAIL;
1923             break;
1924         case DragRet::DRAG_CANCEL:
1925             result = DragRet::DRAG_CANCEL;
1926             break;
1927         default:
1928             break;
1929     }
1930     CHECK_NULL_VOID(dragEvent);
1931     dragEvent->SetResult(result);
1932 }
1933 
SetDragBehavior(const DragNotifyMsgCore & notifyMessage,const RefPtr<OHOS::Ace::DragEvent> & dragEvent)1934 void DragDropManager::SetDragBehavior(
1935     const DragNotifyMsgCore& notifyMessage, const RefPtr<OHOS::Ace::DragEvent>& dragEvent)
1936 {
1937     DragBehavior dragBehavior = DragBehavior::UNKNOWN;
1938     switch (notifyMessage.dragBehavior) {
1939         case DragBehavior::COPY:
1940             dragBehavior = DragBehavior::COPY;
1941             break;
1942         case DragBehavior::MOVE:
1943             dragBehavior = DragBehavior::MOVE;
1944             break;
1945         default:
1946             break;
1947     }
1948     CHECK_NULL_VOID(dragEvent);
1949     dragEvent->SetDragBehavior(dragBehavior);
1950 }
1951 
UpdateGatherNodeAttr(const RefPtr<OverlayManager> & overlayManager,const GatherAnimationInfo & info)1952 void DragDropManager::UpdateGatherNodeAttr(const RefPtr<OverlayManager>& overlayManager,
1953     const GatherAnimationInfo& info)
1954 {
1955     CHECK_NULL_VOID(overlayManager);
1956     auto gatherNodeChildrenInfo = overlayManager->GetGatherNodeChildrenInfo();
1957     BorderRadiusProperty borderRadius;
1958     if (info.borderRadius.has_value()) {
1959         borderRadius = info.borderRadius.value();
1960     }
1961     borderRadius.multiValued = false;
1962     int32_t cnt = static_cast<int>(gatherNodeChildrenInfo.size());
1963     auto scale = info.scale <= 0.0f ? 1.0f : info.scale;
1964     std::vector<std::pair<float, float>> props(cnt, { 0.0, 0.0 });
1965     if (cnt > 0) {
1966         props[cnt - FIRST_GATHER_PIXEL_MAP] = { FIRST_PIXELMAP_ANGLE, FIRST_PIXELMAP_OPACITY };
1967     }
1968     if (cnt > 1) {
1969         props[cnt - SECOND_GATHER_PIXEL_MAP] = { SECOND_PIXELMAP_ANGLE, SECOND_PIXELMAP_OPACITY };
1970     }
1971     for (int32_t i = 0; i < cnt; ++i) {
1972         auto imageNode = gatherNodeChildrenInfo[i].imageNode.Upgrade();
1973         CHECK_NULL_VOID(imageNode);
1974         auto imageContext = imageNode->GetRenderContext();
1975         CHECK_NULL_VOID(imageContext);
1976         auto& childInfo = gatherNodeChildrenInfo[i];
1977         imageContext->UpdatePosition(OffsetT<Dimension>(
1978             Dimension(info.gatherNodeCenter.GetX() - childInfo.halfWidth),
1979             Dimension(info.gatherNodeCenter.GetY() - childInfo.halfHeight)));
1980         auto updateScale = scale;
1981         if (((childInfo.width > info.width) || (childInfo.height > info.height)) &&
1982             !NearZero(childInfo.width) && !NearZero(childInfo.height)) {
1983             updateScale *= std::min(info.width / childInfo.width, info.height / childInfo.height);
1984         }
1985         imageContext->UpdateTransformScale({ updateScale, updateScale });
1986         imageContext->UpdateBorderRadius(borderRadius);
1987         imageContext->UpdateOpacity(props[i].second);
1988         Vector5F rotate = Vector5F(0.0f, 0.0f, 1.0f, props[i].first, 0.0f);
1989         imageContext->UpdateTransformRotate(rotate);
1990     }
1991 }
1992 
UpdateGatherNodePosition(const RefPtr<OverlayManager> & overlayManager,const RefPtr<FrameNode> & imageNode)1993 void DragDropManager::UpdateGatherNodePosition(const RefPtr<OverlayManager>& overlayManager,
1994     const RefPtr<FrameNode>& imageNode)
1995 {
1996     CHECK_NULL_VOID(imageNode);
1997     auto gatherNodeCenter = imageNode->GetPaintRectCenter();
1998     CHECK_NULL_VOID(overlayManager);
1999     Dimension x = Dimension(0.0f);
2000     Dimension y = Dimension(0.0f);
2001     OffsetT<Dimension> offset(x, y);
2002     auto gatherNodeChildrenInfo = overlayManager->GetGatherNodeChildrenInfo();
2003     for (const auto& child : gatherNodeChildrenInfo) {
2004         auto imageNode = child.imageNode.Upgrade();
2005         CHECK_NULL_VOID(imageNode);
2006         auto imageContext = imageNode->GetRenderContext();
2007         CHECK_NULL_VOID(imageContext);
2008         x.SetValue(gatherNodeCenter.GetX() - child.halfWidth);
2009         y.SetValue(gatherNodeCenter.GetY() - child.halfHeight);
2010         offset.SetX(x);
2011         offset.SetY(y);
2012         imageContext->UpdatePosition(offset);
2013     }
2014 }
2015 
UpdateTextNodePosition(const RefPtr<FrameNode> & textNode,const Offset & localPoint)2016 void DragDropManager::UpdateTextNodePosition(const RefPtr<FrameNode>& textNode, const Offset& localPoint)
2017 {
2018     CHECK_NULL_VOID(textNode);
2019     auto textRenderContext = textNode->GetRenderContext();
2020     CHECK_NULL_VOID(textRenderContext);
2021     textRenderContext->UpdateTransformTranslate({ localPoint.GetX(), localPoint.GetY(), 0.0f });
2022 }
2023 
CalcGatherNodeMaxDistanceWithPoint(const RefPtr<OverlayManager> & overlayManager,int32_t x,int32_t y)2024 double DragDropManager::CalcGatherNodeMaxDistanceWithPoint(const RefPtr<OverlayManager>& overlayManager,
2025     int32_t x, int32_t y)
2026 {
2027     CHECK_NULL_RETURN(overlayManager, 0.0f);
2028     auto gatherNodeChildrenInfo = overlayManager->GetGatherNodeChildrenInfo();
2029     double maxDistance = 0.0;
2030     for (const auto& child : gatherNodeChildrenInfo) {
2031         auto imageNode = child.imageNode.Upgrade();
2032         CHECK_NULL_RETURN(imageNode, 0.0f);
2033         auto imageContext = imageNode->GetRenderContext();
2034         CHECK_NULL_RETURN(imageContext, 0.0f);
2035         auto renderPosition = imageContext->GetPropertyOfPosition();
2036         double dis = sqrt(pow(renderPosition.GetX() + child.halfWidth - x, SQUARE_NUMBER) +
2037             pow(renderPosition.GetY() + child.halfHeight - y, SQUARE_NUMBER));
2038         maxDistance = std::max(maxDistance, dis);
2039     }
2040     return maxDistance;
2041 }
2042 
IsNeedDisplayInSubwindow()2043 bool DragDropManager::IsNeedDisplayInSubwindow()
2044 {
2045     if (IsNeedScaleDragPreview()) {
2046         return true;
2047     }
2048     auto overlayManager = GetDragAnimationOverlayManager(Container::CurrentId());
2049     CHECK_NULL_RETURN(overlayManager, false);
2050     auto gatherNode = overlayManager->GetGatherNode();
2051     return gatherNode != nullptr;
2052 }
2053 
PushGatherPixelMap(const RefPtr<PixelMap> & pixelMap)2054 void DragDropManager::PushGatherPixelMap(const RefPtr<PixelMap>& pixelMap)
2055 {
2056     gatherPixelMaps_.push_back(pixelMap);
2057 }
2058 
GetGatherPixelMap(DragDataCore & dragData,float scale,float previewWidth,float previewHeight)2059 void DragDropManager::GetGatherPixelMap(DragDataCore& dragData, float scale, float previewWidth, float previewHeight)
2060 {
2061     for (const auto& gatherPixelMap : gatherPixelMaps_) {
2062         RefPtr<PixelMap> pixelMapDuplicated = gatherPixelMap;
2063 #if defined(PIXEL_MAP_SUPPORTED)
2064         pixelMapDuplicated = PixelMap::CopyPixelMap(gatherPixelMap);
2065         if (!pixelMapDuplicated) {
2066             TAG_LOGW(AceLogTag::ACE_DRAG, "Copy PixelMap is failure!");
2067             pixelMapDuplicated = gatherPixelMap;
2068         }
2069 #endif
2070         auto width = pixelMapDuplicated->GetWidth() * scale;
2071         auto height = pixelMapDuplicated->GetHeight() * scale;
2072         auto updateScale = scale;
2073         if (((width > previewWidth) || (height > previewHeight)) && !NearZero(width) && !NearZero(height)) {
2074             updateScale *= std::min(previewWidth / width, previewHeight / height);
2075         }
2076         pixelMapDuplicated->Scale(updateScale, updateScale, AceAntiAliasingOption::HIGH);
2077         dragData.shadowInfos.push_back({pixelMapDuplicated, 0.0f, 0.0f});
2078     }
2079     gatherPixelMaps_.clear();
2080     return;
2081 }
2082 
ResetDragDrop(int32_t windowId,const Point & point)2083 void DragDropManager::ResetDragDrop(int32_t windowId, const Point& point)
2084 {
2085     DragDropRet dragDropRet { DragRet::DRAG_FAIL, isMouseDragged_, windowId, DragBehavior::UNKNOWN };
2086     HideDragPreviewOverlay();
2087     ClearVelocityInfo();
2088     ResetDragDropStatus(point, dragDropRet, windowId);
2089     dragCursorStyleCore_ = DragCursorStyleCore::DEFAULT;
2090 }
2091 
FireOnDragLeave(const RefPtr<FrameNode> & preTargetFrameNode,const PointerEvent & pointerEvent,const std::string & extraInfo)2092 void DragDropManager::FireOnDragLeave(
2093     const RefPtr<FrameNode>& preTargetFrameNode, const PointerEvent& pointerEvent, const std::string& extraInfo)
2094 {
2095     auto point = pointerEvent.GetPoint();
2096     if (preTargetFrameNode) {
2097         auto preRect = preTargetFrameNode->GetTransformRectRelativeToWindow();
2098         // If the point is out of the pre node, it means we are totally inside a new node, notify leave anyway
2099         if (!preRect.IsInnerRegion(PointF(static_cast<float>(point.GetX()), static_cast<float>(point.GetY())))) {
2100             FireOnDragEvent(preTargetFrameNode, pointerEvent, DragEventType::LEAVE, extraInfo);
2101             return;
2102         }
2103 
2104         // If reach here, it means we are entering one new node's area, but without leaving the area of the pre
2105         // one, this usually happens when moving from parent into its child.
2106         // Check the configuration to decide the notify to parent node.
2107         if (eventStrictReportingEnabled_) {
2108             FireOnDragEvent(preTargetFrameNode_, pointerEvent, DragEventType::LEAVE, extraInfo);
2109         }
2110     }
2111 }
2112 
IsUIExtensionShowPlaceholder(const RefPtr<NG::UINode> & node)2113 bool DragDropManager::IsUIExtensionShowPlaceholder(const RefPtr<NG::UINode>& node)
2114 {
2115 #ifdef WINDOW_SCENE_SUPPORTED
2116     CHECK_NULL_RETURN(node, true);
2117     auto pipeline = PipelineContext::GetCurrentContext();
2118     CHECK_NULL_RETURN(pipeline, true);
2119     auto manager = pipeline->GetUIExtensionManager();
2120     CHECK_NULL_RETURN(manager, true);
2121     return manager->IsShowPlaceholder(node->GetId());
2122 #endif
2123     return true;
2124 }
2125 
UpdateDragMovePosition(const NG::OffsetF & offset,bool isRedragStart)2126 void DragDropManager::UpdateDragMovePosition(const NG::OffsetF& offset, bool isRedragStart)
2127 {
2128     if (isRedragStart) {
2129         ResetContextMenuRedragPosition();
2130     }
2131     lastDragMovePosition_ = dragMovePosition_;
2132     dragMovePosition_ = offset;
2133     if (lastDragMovePosition_.NonOffset()) {
2134         return;
2135     }
2136     dragTotalMovePosition_ += (dragMovePosition_ - lastDragMovePosition_);
2137 }
2138 
IsUIExtensionComponent(const RefPtr<NG::UINode> & node)2139 bool DragDropManager::IsUIExtensionComponent(const RefPtr<NG::UINode>& node)
2140 {
2141     return (V2::UI_EXTENSION_COMPONENT_ETS_TAG == node->GetTag() || V2::EMBEDDED_COMPONENT_ETS_TAG == node->GetTag()) &&
2142            (!IsUIExtensionShowPlaceholder(node));
2143 }
2144 
GetMenuPreviewRect()2145 RectF DragDropManager::GetMenuPreviewRect()
2146 {
2147     auto pipelineContext = PipelineContext::GetCurrentContext();
2148     CHECK_NULL_RETURN(pipelineContext, RectF());
2149     auto dragDropManager = pipelineContext->GetDragDropManager();
2150     CHECK_NULL_RETURN(dragDropManager, RectF());
2151     auto menuWrapperNode = dragDropManager->GetMenuWrapperNode();
2152     CHECK_NULL_RETURN(menuWrapperNode, RectF());
2153     auto menuWrapperPattern = menuWrapperNode->GetPattern<MenuWrapperPattern>();
2154     CHECK_NULL_RETURN(menuWrapperPattern, RectF());
2155     auto menuPreview = menuWrapperPattern->GetPreview();
2156     CHECK_NULL_RETURN(menuPreview, RectF());
2157     auto menuRenderContext = menuPreview->GetRenderContext();
2158     CHECK_NULL_RETURN(menuRenderContext, RectF());
2159     auto previewPaintRect = menuRenderContext->GetPaintRectWithTransform();
2160     return previewPaintRect;
2161 }
2162 
GetMaxWidthBaseOnGridSystem(const RefPtr<PipelineBase> & pipeline)2163 double DragDropManager::GetMaxWidthBaseOnGridSystem(const RefPtr<PipelineBase>& pipeline)
2164 {
2165     auto context = DynamicCast<NG::PipelineContext>(pipeline);
2166     CHECK_NULL_RETURN(context, -1.0f);
2167     auto dragDropMgr = context->GetDragDropManager();
2168     CHECK_NULL_RETURN(dragDropMgr, -1.0f);
2169     auto& columnInfo = dragDropMgr->columnInfo_;
2170     if (!columnInfo) {
2171         columnInfo = GridSystemManager::GetInstance().GetInfoByType(GridColumnType::DRAG_PANEL);
2172         auto gridContainer = columnInfo->GetParent();
2173         if (gridContainer) {
2174             auto rootWidth = context->GetRootWidth();
2175             if (LessOrEqual(rootWidth, 0.0)) {
2176                 auto mainPipeline = PipelineContext::GetMainPipelineContext();
2177                 rootWidth = GridSystemManager::GetInstance().GetScreenWidth(mainPipeline);
2178             }
2179             // cannot handle multi-screen
2180             gridContainer->BuildColumnWidth(rootWidth);
2181         }
2182         dragDropMgr->columnInfo_ = columnInfo;
2183     }
2184 
2185     auto gridSizeType = GridSystemManager::GetInstance().GetCurrentSize();
2186     if (gridSizeType > GridSizeType::LG) {
2187         gridSizeType = GridSizeType::LG;
2188     }
2189     if (gridSizeType < GridSizeType::SM) {
2190         gridSizeType = GridSizeType::SM;
2191     }
2192     auto columns = columnInfo->GetColumns(gridSizeType);
2193     double maxWidth = columnInfo->GetWidth(columns);
2194     return maxWidth;
2195 }
2196 
GetDragAnimationOverlayManager(int32_t containerId)2197 const RefPtr<NG::OverlayManager> DragDropManager::GetDragAnimationOverlayManager(int32_t containerId)
2198 {
2199     auto subwindow = SubwindowManager::GetInstance()->GetSubwindow(containerId >= MIN_SUBCONTAINER_ID ?
2200         SubwindowManager::GetInstance()->GetParentContainerId(containerId) : containerId);
2201     CHECK_NULL_RETURN(subwindow, nullptr);
2202     return subwindow->GetOverlayManager();
2203 }
2204 
RemoveDragFrameNode(int32_t id)2205 void DragDropManager::RemoveDragFrameNode(int32_t id)
2206 {
2207     dragFrameNodes_.erase(id);
2208     gridDragFrameNodes_.erase(id);
2209     listDragFrameNodes_.erase(id);
2210     textFieldDragFrameNodes_.erase(id);
2211 }
2212 
SetIsDragged(bool isDragged)2213 void DragDropManager::SetIsDragged(bool isDragged)
2214 {
2215     if (isDragged && isDragged_ != isDragged && notifyInDraggedCallback_) {
2216         notifyInDraggedCallback_();
2217     }
2218     isDragged_ = isDragged;
2219 }
2220 
RegisterDragStatusListener(int32_t nodeId,const WeakPtr<FrameNode> & node)2221 void DragDropManager::RegisterDragStatusListener(int32_t nodeId, const WeakPtr<FrameNode>& node)
2222 {
2223     auto ret = nodesForDragNotify_.try_emplace(nodeId, node);
2224     if (!ret.second) {
2225         nodesForDragNotify_[nodeId] = node;
2226     }
2227 }
2228 
IsDraggingPressed(int32_t currentPointerId) const2229 bool DragDropManager::IsDraggingPressed(int32_t currentPointerId) const
2230 {
2231     if (currentPointerId_ == currentPointerId) {
2232         return draggingPressedState_;
2233     }
2234     return false;
2235 }
2236 
ResetContextMenuDragPosition()2237 void DragDropManager::ResetContextMenuDragPosition()
2238 {
2239     dragMovePosition_ = OffsetF(0.0f, 0.0f);
2240     lastDragMovePosition_ = OffsetF(0.0f, 0.0f);
2241     dragTotalMovePosition_ = OffsetF(0.0f, 0.0f);
2242 }
2243 
ResetContextMenuRedragPosition()2244 void DragDropManager::ResetContextMenuRedragPosition()
2245 {
2246     dragMovePosition_ = OffsetF(0.0f, 0.0f);
2247     lastDragMovePosition_ = OffsetF(0.0f, 0.0f);
2248 }
2249 
AddNewDragAnimation()2250 void DragDropManager::AddNewDragAnimation()
2251 {
2252     currentAnimationCnt_++;
2253     allAnimationCnt_++;
2254 }
2255 
IsAllAnimationFinished()2256 bool DragDropManager::IsAllAnimationFinished()
2257 {
2258     currentAnimationCnt_--;
2259     return currentAnimationCnt_ == 0;
2260 }
2261 
CheckIsNewDrag(const PointerEvent & pointerEvent) const2262 bool DragDropManager::CheckIsNewDrag(const PointerEvent& pointerEvent) const
2263 {
2264     return (pointerEvent.pullId != -1) && (pointerEvent.pullId != currentPullId_);
2265 }
2266 
RequireSummaryIfNecessary(const PointerEvent & pointerEvent)2267 void DragDropManager::RequireSummaryIfNecessary(const PointerEvent& pointerEvent)
2268 {
2269     if (CheckIsNewDrag(pointerEvent)) {
2270         currentPullId_ = pointerEvent.pullId;
2271         RequireSummary();
2272     }
2273 }
2274 } // namespace OHOS::Ace::NG
2275