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