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