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