1 /*
2 * Copyright (c) 2022-2024 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
18 #include "base/geometry/point.h"
19 #include "base/geometry/rect.h"
20 #include "base/log/ace_trace.h"
21 #include "base/utils/system_properties.h"
22 #include "base/utils/time_util.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/common/udmf/udmf_client.h"
27 #include "core/components/common/layout/grid_column_info.h"
28 #include "core/components/common/layout/grid_system_manager.h"
29 #include "core/components_ng/base/frame_node.h"
30 #include "core/components_ng/manager/drag_drop/drag_drop_behavior_reporter/drag_drop_behavior_reporter.h"
31 #include "core/components_ng/manager/drag_drop/drag_drop_func_wrapper.h"
32 #include "core/components_ng/manager/drag_drop/drag_drop_global_controller.h"
33 #include "core/components_ng/pattern/grid/grid_event_hub.h"
34 #include "core/components_ng/pattern/list/list_event_hub.h"
35 #include "core/components_ng/pattern/menu/wrapper/menu_wrapper_pattern.h"
36 #include "core/components_ng/pattern/root/root_pattern.h"
37 #include "core/components_ng/pattern/text_field/text_field_pattern.h"
38 #include "core/components_v2/inspector/inspector_constants.h"
39 #include "core/pipeline_ng/pipeline_context.h"
40
41 namespace OHOS::Ace::NG {
42 namespace {
43 int64_t g_proxyId = 0;
44 constexpr Dimension PRESERVE_HEIGHT = 8.0_vp;
45 constexpr float FIRST_PIXELMAP_OPACITY = 0.6f;
46 constexpr float SECOND_PIXELMAP_OPACITY = 0.3f;
47 constexpr float FIRST_PIXELMAP_ANGLE = 8.0f;
48 constexpr float SECOND_PIXELMAP_ANGLE = -8.0f;
49 constexpr int32_t FIRST_GATHER_PIXEL_MAP = 1;
50 constexpr int32_t SECOND_GATHER_PIXEL_MAP = 2;
51 constexpr int32_t SQUARE_NUMBER = 2;
52 constexpr float TOUCH_DRAG_PIXELMAP_SCALE = 1.05f;
53 constexpr int32_t MAX_RETRY_TIMES = 3;
54 constexpr int32_t MAX_RETRY_DURATION = 800;
55 constexpr float MOVE_DISTANCE_LIMIT = 20.0f;
56 constexpr uint64_t MOVE_TIME_LIMIT = 6L;
57 constexpr float MAX_DISTANCE_TO_PRE_POINTER = 3.0f;
58 constexpr float DEFAULT_SPRING_RESPONSE = 0.347f;
59 constexpr float MIN_SPRING_RESPONSE = 0.05f;
60 constexpr float DEL_SPRING_RESPONSE = 0.005f;
61 constexpr float MIN_UI_EXTENSION_BOUNDARY_DISTANCE = 5.0f;
62 constexpr float MIN_FOLDER_SUBWINDOW_BOUNDARY_DISTANCE = 5.0f;
63 constexpr int32_t RESERVED_DEVICEID_1 = 0xAAAAAAFF;
64 constexpr int32_t RESERVED_DEVICEID_2 = 0xAAAAAAFE;
65 constexpr uint32_t TASK_DELAY_TIME = 5 * 1000;
66 constexpr uint32_t DROP_DELAY_TIME = 2 * 1000;
67 constexpr double DEVICE_TYPE_UNKOWN = 0.0;
68 constexpr double DEVICE_TYPE_SMALL = 600.0;
69 constexpr double DEVICE_TYPE_MEDIUM = 840.0;
70 constexpr int32_t SCALE_TYPE_FIRST = 2;
71 constexpr int32_t SCALE_TYPE_SECOND = 3;
72 constexpr int32_t SCALE_TYPE_THIRD = 4;
73 const RefPtr<InterpolatingSpring> DRAG_TRANSITION_ANIMATION_CURVE =
74 AceType::MakeRefPtr<InterpolatingSpring>(0.0f, 1.0f, 380.0f, 34.0f);
75 } // namespace
76
GetMenuRenderContextFromMenuWrapper(const RefPtr<FrameNode> & menuWrapperNode)77 RefPtr<RenderContext> GetMenuRenderContextFromMenuWrapper(const RefPtr<FrameNode>& menuWrapperNode)
78 {
79 CHECK_NULL_RETURN(menuWrapperNode, nullptr);
80 auto menuWrapperPattern = menuWrapperNode->GetPattern<MenuWrapperPattern>();
81 CHECK_NULL_RETURN(menuWrapperPattern, nullptr);
82 auto menuNode = menuWrapperPattern->GetMenu();
83 CHECK_NULL_RETURN(menuNode, nullptr);
84 return menuNode->GetRenderContext();
85 }
86
GetMenuWrapperNodeFromDrag()87 RefPtr<FrameNode> GetMenuWrapperNodeFromDrag()
88 {
89 auto pipelineContext = PipelineContext::GetMainPipelineContext();
90 CHECK_NULL_RETURN(pipelineContext, nullptr);
91 auto mainDragDropManager = pipelineContext->GetDragDropManager();
92 CHECK_NULL_RETURN(mainDragDropManager, nullptr);
93 return mainDragDropManager->GetMenuWrapperNode();
94 }
95
DragDropManager()96 DragDropManager::DragDropManager()
97 {
98 if (DragDropGlobalController::GetInstance().IsAlreadyGetAppGlobalDrag()) {
99 return;
100 }
101 bool state = false;
102 auto result = InteractionInterface::GetInstance()->GetAppDragSwitchState(state);
103 if (result != 0) {
104 TAG_LOGI(AceLogTag::ACE_DRAG, "get app drag switch state failed!");
105 return;
106 }
107 DragDropGlobalController::GetInstance().SetIsAppGlobalDragEnabled(state);
108 }
109
GetDragMoveLastPointByCurrentPointer(int32_t pointerId)110 const Point DragDropManager::GetDragMoveLastPointByCurrentPointer(int32_t pointerId)
111 {
112 return fingerPointInfo_[pointerId];
113 }
114
UpdatePointInfoForFinger(int32_t pointerId,Point point)115 void DragDropManager::UpdatePointInfoForFinger(int32_t pointerId, Point point)
116 {
117 fingerPointInfo_[pointerId] = point;
118 }
119
SetDelayDragCallBack(const std::function<void ()> & cb)120 void DragDropManager::SetDelayDragCallBack(const std::function<void()>& cb) noexcept
121 {
122 DragDropGlobalController::GetInstance().SetAsyncDragCallback(cb);
123 }
124
ExecuteDeadlineTimer()125 void DragDropManager::ExecuteDeadlineTimer()
126 {
127 auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
128 CHECK_NULL_VOID(pipeline);
129 auto taskScheduler = pipeline->GetTaskExecutor();
130 CHECK_NULL_VOID(taskScheduler);
131 taskScheduler->PostDelayedTask(
132 [weakManager = WeakClaim(this)]() {
133 auto dragDropManager = weakManager.Upgrade();
134 CHECK_NULL_VOID(dragDropManager);
135 if (DragDropGlobalController::GetInstance().GetAsyncDragCallback()) {
136 DragDropGlobalController::GetInstance().GetAsyncDragCallback()();
137 }
138 dragDropManager->RemoveDeadlineTimer();
139 },
140 TaskExecutor::TaskType::UI, TASK_DELAY_TIME, "ArkUIDragDeadlineTimer");
141 }
142
RemoveDeadlineTimer()143 void DragDropManager::RemoveDeadlineTimer()
144 {
145 DragDropGlobalController::GetInstance().SetAsyncDragCallback(nullptr);
146 DragDropGlobalController::GetInstance().SetDragStartRequestStatus(DragStartRequestStatus::READY);
147 auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
148 CHECK_NULL_VOID(pipeline);
149 auto taskScheduler = pipeline->GetTaskExecutor();
150 CHECK_NULL_VOID(taskScheduler);
151 taskScheduler->RemoveTask(TaskExecutor::TaskType::UI, "ArkUIDragDeadlineTimer");
152 }
153
HandleSyncOnDragStart(DragStartRequestStatus dragStartRequestStatus)154 void DragDropManager::HandleSyncOnDragStart(DragStartRequestStatus dragStartRequestStatus)
155 {
156 if (dragStartRequestStatus == DragStartRequestStatus::WAITING) {
157 ExecuteDeadlineTimer();
158 DragDropGlobalController::GetInstance().SetDragStartRequestStatus(dragStartRequestStatus);
159 }
160 if (dragStartRequestStatus == DragStartRequestStatus::READY &&
161 DragDropGlobalController::GetInstance().GetAsyncDragCallback()) {
162 DragDropGlobalController::GetInstance().SetDragStartRequestStatus(dragStartRequestStatus);
163 DragDropGlobalController::GetInstance().GetAsyncDragCallback()();
164 RemoveDeadlineTimer();
165 }
166 }
167
CreateAndShowItemDragOverlay(const RefPtr<PixelMap> & pixelMap,const GestureEvent & info,const RefPtr<EventHub> & eventHub)168 RefPtr<DragDropProxy> DragDropManager::CreateAndShowItemDragOverlay(
169 const RefPtr<PixelMap>& pixelMap, const GestureEvent& info, const RefPtr<EventHub>& eventHub)
170 {
171 CHECK_NULL_RETURN(pixelMap, nullptr);
172 // create Image for drag
173 auto imageNode = FrameNode::GetOrCreateFrameNode(V2::IMAGE_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
174 []() { return AceType::MakeRefPtr<ImagePattern>(); });
175 CHECK_NULL_RETURN(imageNode, nullptr);
176 auto imagePattern = imageNode->GetPattern<ImagePattern>();
177 CHECK_NULL_RETURN(imagePattern, nullptr);
178 imagePattern->SetSyncLoad(true);
179 auto prop = imageNode->GetLayoutProperty<ImageLayoutProperty>();
180 CHECK_NULL_RETURN(prop, nullptr);
181 prop->UpdateAutoResize(false);
182 prop->UpdateImageSourceInfo(ImageSourceInfo(pixelMap));
183 auto targetSize = CalcSize(NG::CalcLength(pixelMap->GetWidth()), NG::CalcLength(pixelMap->GetHeight()));
184 prop->UpdateUserDefinedIdealSize(targetSize);
185 auto renderProp = imageNode->GetPaintProperty<ImageRenderProperty>();
186 renderProp->UpdateImageInterpolation(ImageInterpolation::HIGH);
187 imageNode->MarkDirtyNode(NG::PROPERTY_UPDATE_MEASURE);
188 imageNode->MarkModifyDone();
189 imageNode->SetLayoutDirtyMarked(true);
190 imageNode->SetActive(true);
191 auto context = imageNode->GetContext();
192 if (context) {
193 context->FlushUITaskWithSingleDirtyNode(imageNode);
194 }
195 auto imageContext = imageNode->GetRenderContext();
196 CHECK_NULL_RETURN(imageContext, nullptr);
197 imageContext->UpdatePosition(
198 OffsetT<Dimension>(Dimension(info.GetGlobalPoint().GetX() - pixelMap->GetWidth() / 2), // 2: Average factor.
199 Dimension(info.GetGlobalPoint().GetY() - pixelMap->GetHeight() / 2))); // 2: Average factor.
200 imageContext->OnModifyDone();
201
202 AddItemDrag(imageNode, eventHub);
203
204 itemDragOverlayNode_ = imageNode;
205 SetIsDragged(true);
206 isDragCancel_ = false;
207 currentId_ = ++g_proxyId;
208 return MakeRefPtr<DragDropProxy>(currentId_);
209 }
210
CreateAndShowItemDragOverlay(const RefPtr<UINode> & customNode,const GestureEvent & info,const RefPtr<EventHub> & eventHub)211 RefPtr<DragDropProxy> DragDropManager::CreateAndShowItemDragOverlay(
212 const RefPtr<UINode>& customNode, const GestureEvent& info, const RefPtr<EventHub>& eventHub)
213 {
214 auto frameNode = DynamicCast<FrameNode>(customNode);
215 CHECK_NULL_RETURN(frameNode, nullptr);
216 auto renderContext = frameNode->GetRenderContext();
217 CHECK_NULL_RETURN(renderContext, nullptr);
218 auto geometryNode = frameNode->GetGeometryNode();
219 CHECK_NULL_RETURN(geometryNode, nullptr);
220 auto frameRect = geometryNode->GetFrameSize();
221 renderContext->UpdatePosition(
222 OffsetT<Dimension>(Dimension(info.GetGlobalPoint().GetX() - frameRect.Width() / 2), // 2: Average factor.
223 Dimension(info.GetGlobalPoint().GetY() - frameRect.Height() / 2))); // 2: Average factor.
224 renderContext->OnModifyDone();
225 AddItemDrag(frameNode, eventHub);
226 itemDragOverlayNode_ = frameNode;
227 SetIsDragged(true);
228 isDragCancel_ = false;
229 currentId_ = ++g_proxyId;
230 return MakeRefPtr<DragDropProxy>(currentId_);
231 }
232
CreateTextDragDropProxy()233 RefPtr<DragDropProxy> DragDropManager::CreateTextDragDropProxy()
234 {
235 SetIsDragged(true);
236 isDragCancel_ = false;
237 currentId_ = ++g_proxyId;
238 return MakeRefPtr<DragDropProxy>(currentId_);
239 }
240
GetWindowId()241 int32_t DragDropManager::GetWindowId()
242 {
243 auto windowId = -1;
244 auto container = Container::Current();
245 CHECK_NULL_RETURN(container, windowId);
246
247 if (!container->IsSceneBoardEnabled()) {
248 isDragWindowSubWindow_ = false;
249 return windowId;
250 }
251
252 if (!container->IsMainWindow()) {
253 // The window manager currently does not support creating child windows within child windows,
254 // so the root main window is used here
255 container = Container::GetContainer(CONTAINER_ID_DIVIDE_SIZE);
256 CHECK_NULL_RETURN(container, windowId);
257 if (!container->IsMainWindow()) {
258 isDragWindowSubWindow_ = false;
259 return windowId;
260 }
261 }
262
263 windowId = static_cast<int32_t>(container->GetWindowId());
264 isDragWindowSubWindow_ = true;
265
266 return windowId;
267 }
268
CreateDragRootNode(const RefPtr<UINode> & customNode)269 RefPtr<FrameNode> DragDropManager::CreateDragRootNode(const RefPtr<UINode>& customNode)
270 {
271 auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
272 CHECK_NULL_RETURN(pipeline, nullptr);
273
274 auto rootNode = FrameNode::CreateFrameNodeWithTree(
275 V2::ROOT_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), MakeRefPtr<RootPattern>());
276 rootNode->SetActive(true);
277 rootNode->SetHostRootId(pipeline->GetInstanceId());
278 rootNode->SetHostPageId(-1);
279 rootNode->AddChild(customNode);
280 rootNode->AttachToMainTree(false, AceType::RawPtr(pipeline));
281 rootNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
282 pipeline->FlushUITasks();
283 return rootNode;
284 }
285
AddItemDrag(const RefPtr<FrameNode> & frameNode,const RefPtr<EventHub> & eventHub)286 void DragDropManager::AddItemDrag(const RefPtr<FrameNode>& frameNode, const RefPtr<EventHub>& eventHub)
287 {
288 auto pipeline = frameNode->GetContext();
289 CHECK_NULL_VOID(pipeline);
290 auto rootNode = pipeline->GetRootElement();
291 auto container = Container::Current();
292 if (container && container->IsScenceBoardWindow()) {
293 auto host = eventHub->GetFrameNode();
294 CHECK_NULL_VOID(host);
295 auto overlayManager = pipeline->GetOverlayManager();
296 CHECK_NULL_VOID(overlayManager);
297 rootNode = DynamicCast<FrameNode>(overlayManager->FindWindowScene(host));
298 }
299 CHECK_NULL_VOID(rootNode);
300 frameNode->MountToParent(rootNode);
301 frameNode->OnMountToParentDone();
302 rootNode->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST);
303 }
304
RemoveItemDrag()305 void DragDropManager::RemoveItemDrag()
306 {
307 CHECK_NULL_VOID(itemDragOverlayNode_);
308 auto rootNode = itemDragOverlayNode_->GetParent();
309 CHECK_NULL_VOID(rootNode);
310 rootNode->RemoveChild(itemDragOverlayNode_);
311 rootNode->RebuildRenderContextTree();
312 rootNode->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST);
313 }
314
UpdateItemDragPosition(int32_t globalX,int32_t globalY)315 void DragDropManager::UpdateItemDragPosition(int32_t globalX, int32_t globalY)
316 {
317 CHECK_NULL_VOID(itemDragOverlayNode_);
318 auto rect = itemDragOverlayNode_->GetTransformRectRelativeToWindow();
319 auto pipeline = itemDragOverlayNode_->GetContext();
320 CHECK_NULL_VOID(pipeline);
321 const Rect windowRect = pipeline->GetDisplayWindowRectInfo();
322 auto maxX = static_cast<float>(windowRect.Width() - rect.Width());
323 auto maxY = static_cast<float>(windowRect.Height() - rect.Height());
324 auto renderContext = itemDragOverlayNode_->GetRenderContext();
325 CHECK_NULL_VOID(renderContext);
326 renderContext->UpdatePosition(
327 OffsetT<Dimension>(Dimension(std::min(std::max(globalX - rect.Width() / 2, 0.0f), maxX)), // 2: Average factor.
328 Dimension(std::min(std::max(globalY - rect.Height() / 2, 0.0f), maxY)))); // 2: Average factor.
329 renderContext->OnModifyDone();
330 }
331
HideDragPreviewOverlay()332 void DragDropManager::HideDragPreviewOverlay()
333 {
334 auto pipeline = NG::PipelineContext::GetCurrentContextSafelyWithCheck();
335 CHECK_NULL_VOID(pipeline);
336 auto manager = pipeline->GetOverlayManager();
337 CHECK_NULL_VOID(manager);
338 manager->RemovePixelMap();
339 manager->RemoveGatherNode();
340 manager->RemoveDragPixelMap();
341 SubwindowManager::GetInstance()->HidePreviewNG();
342 }
343
HideDragPreviewWindow(int32_t containerId)344 void DragDropManager::HideDragPreviewWindow(int32_t containerId)
345 {
346 auto overlayManager = GetDragAnimationOverlayManager(containerId);
347 CHECK_NULL_VOID(overlayManager);
348 overlayManager->RemovePixelMap();
349 overlayManager->RemoveGatherNode();
350 overlayManager->RemoveDragPixelMap();
351 SubwindowManager::GetInstance()->HidePreviewNG();
352 }
353
FindTargetInChildNodes(const RefPtr<UINode> parentNode,std::vector<RefPtr<FrameNode>> hitFrameNodes,bool findDrop)354 RefPtr<FrameNode> DragDropManager::FindTargetInChildNodes(
355 const RefPtr<UINode> parentNode, std::vector<RefPtr<FrameNode>> hitFrameNodes, bool findDrop)
356 {
357 CHECK_NULL_RETURN(parentNode, nullptr);
358 auto parentFrameNode = AceType::DynamicCast<FrameNode>(parentNode);
359 if (parentFrameNode && (!parentFrameNode->IsActive() || !parentFrameNode->IsVisible())) {
360 return nullptr;
361 }
362 auto children = parentFrameNode->GetFrameChildren();
363
364 for (auto iter = children.rbegin(); iter != children.rend(); iter++) {
365 auto child = iter->Upgrade();
366 if (child == nullptr) {
367 continue;
368 }
369 auto childNode = AceType::DynamicCast<UINode>(child);
370 auto childFindResult = FindTargetInChildNodes(childNode, hitFrameNodes, findDrop);
371 if (childFindResult) {
372 return childFindResult;
373 }
374 }
375
376 CHECK_NULL_RETURN(parentFrameNode, nullptr);
377 for (auto iter : hitFrameNodes) {
378 if (parentFrameNode == iter) {
379 auto eventHub = parentFrameNode->GetEventHub<EventHub>();
380 if (!eventHub) {
381 continue;
382 }
383 if ((eventHub->HasOnDrop()) || (eventHub->HasOnItemDrop()) || (eventHub->HasCustomerOnDrop())) {
384 return parentFrameNode;
385 }
386 if ((V2::UI_EXTENSION_COMPONENT_ETS_TAG == parentFrameNode->GetTag() ||
387 V2::EMBEDDED_COMPONENT_ETS_TAG == parentFrameNode->GetTag()) &&
388 (!IsUIExtensionShowPlaceholder(parentFrameNode))) {
389 return parentFrameNode;
390 }
391 }
392 }
393 return nullptr;
394 }
395
CheckFrameNodeCanDrop(const RefPtr<FrameNode> & node)396 bool DragDropManager::CheckFrameNodeCanDrop(const RefPtr<FrameNode>& node)
397 {
398 CHECK_NULL_RETURN(node, false);
399 auto eventHub = node->GetEventHub<EventHub>();
400 CHECK_NULL_RETURN(eventHub, false);
401 if ((eventHub->HasOnDrop()) || (eventHub->HasOnItemDrop()) || (eventHub->HasCustomerOnDrop())) {
402 return true;
403 }
404 if ((V2::UI_EXTENSION_COMPONENT_ETS_TAG == node->GetTag() ||
405 V2::EMBEDDED_COMPONENT_ETS_TAG == node->GetTag()) &&
406 (!IsUIExtensionShowPlaceholder(node))) {
407 return true;
408 }
409
410 return false;
411 }
412
FindTargetDropNode(const RefPtr<UINode> parentNode,PointF localPoint)413 RefPtr<FrameNode> DragDropManager::FindTargetDropNode(const RefPtr<UINode> parentNode, PointF localPoint)
414 {
415 CHECK_NULL_RETURN(parentNode, nullptr);
416 auto parentFrameNode = AceType::DynamicCast<FrameNode>(parentNode);
417 CHECK_NULL_RETURN(parentFrameNode, nullptr);
418 if (!parentFrameNode->IsActive() || !parentFrameNode->IsVisible()) {
419 return nullptr;
420 }
421 auto renderContext = parentFrameNode->GetRenderContext();
422 CHECK_NULL_RETURN(renderContext, nullptr);
423 auto paintRect = renderContext->GetPaintRectWithoutTransform();
424 FrameNode::MapPointTo(localPoint, parentFrameNode->GetOrRefreshMatrixFromCache().revertMatrix);
425 auto subLocalPoint = localPoint - paintRect.GetOffset();
426
427 auto children = parentFrameNode->GetFrameChildren();
428 for (auto iter = children.rbegin(); iter != children.rend(); iter++) {
429 auto child = iter->Upgrade();
430 if (child == nullptr) {
431 continue;
432 }
433 auto childNode = AceType::DynamicCast<UINode>(child);
434 auto childFindResult = FindTargetDropNode(childNode, subLocalPoint);
435 if (childFindResult) {
436 return childFindResult;
437 }
438 }
439
440 if (paintRect.IsInRegion(localPoint)) {
441 if (parentFrameNode->GetDragHitTestBlock()) {
442 return parentFrameNode;
443 }
444 if (CheckFrameNodeCanDrop(parentFrameNode)) {
445 return parentFrameNode;
446 }
447 }
448 return nullptr;
449 }
450
FilterSubwindowDragRootNode(const RefPtr<FrameNode> & node)451 RefPtr<FrameNode> DragDropManager::FilterSubwindowDragRootNode(const RefPtr<FrameNode>& node)
452 {
453 auto rootNode = node;
454 auto container = Container::Current();
455 CHECK_NULL_RETURN(container, rootNode);
456 auto containerId = container->GetInstanceId();
457 auto pipeline = PipelineContext::GetMainPipelineContext();
458 CHECK_NULL_RETURN(pipeline, rootNode);
459 if (isReDragStart_ && !DragDropFuncWrapper::IsExpandDisplay(pipeline) && containerId >= MIN_SUBCONTAINER_ID) {
460 rootNode = pipeline->GetRootElement();
461 }
462 return rootNode;
463 }
464
FindDragFrameNodeByPosition(float globalX,float globalY,const RefPtr<FrameNode> & node)465 RefPtr<FrameNode> DragDropManager::FindDragFrameNodeByPosition(float globalX, float globalY,
466 const RefPtr<FrameNode>& node)
467 {
468 auto rootNode = node;
469 if (!rootNode) {
470 auto pipeline = NG::PipelineContext::GetCurrentContextSafelyWithCheck();
471 CHECK_NULL_RETURN(pipeline, nullptr);
472 rootNode = pipeline->GetRootElement();
473 }
474
475 auto result = FindTargetDropNode(rootNode, {globalX, globalY});
476 if (result) {
477 if (CheckFrameNodeCanDrop(result)) {
478 return result;
479 }
480 }
481 return nullptr;
482 }
483
CheckDragDropProxy(int64_t id) const484 bool DragDropManager::CheckDragDropProxy(int64_t id) const
485 {
486 return currentId_ == id;
487 }
488
UpdateDragAllowDrop(const RefPtr<FrameNode> & dragFrameNode,const DragBehavior dragBehavior,const int32_t eventId,bool isCapi)489 void DragDropManager::UpdateDragAllowDrop(
490 const RefPtr<FrameNode>& dragFrameNode, const DragBehavior dragBehavior, const int32_t eventId, bool isCapi)
491 {
492 if (!IsDropAllowed(dragFrameNode)) {
493 // simplified specifications for drag cursor style, no longer showing forbidden drag cursor
494 UpdateDragStyle(DragCursorStyleCore::MOVE, eventId);
495 return;
496 }
497
498 // drop allowed
499 CHECK_NULL_VOID(dragFrameNode);
500 const auto& dragFrameNodeAllowDrop = dragFrameNode->GetAllowDrop();
501 // special handling for no drag data present situation, always show as move
502 // For CAPI ,no ENABLE_DROP and DISABLE_DROP state, skip the judgment and consider it allowed to drop into. Continue
503 // to set dragBehavior.
504 if (!isCapi && (dragFrameNodeAllowDrop.empty() || summaryMap_.empty())) {
505 UpdateDragStyle(DragCursorStyleCore::MOVE, eventId);
506 return;
507 }
508
509 //other case, check drag behavior
510 switch (dragBehavior) {
511 case DragBehavior::UNKNOWN: {
512 // the application does not config the drag behavior, use move when moving within
513 // draggedFrameNode or frameNode is disabled, otherwise use copy
514 auto eventHub = dragFrameNode->GetEventHub<EventHub>();
515 if (draggedFrameNode_ == dragFrameNode || !(eventHub && eventHub->IsEnabled()) ||
516 CheckExtraSituation(dragFrameNode)) {
517 UpdateDragStyle(DragCursorStyleCore::MOVE, eventId);
518 } else {
519 UpdateDragStyle(DragCursorStyleCore::COPY, eventId);
520 }
521 break;
522 }
523 case DragBehavior::MOVE: {
524 UpdateDragStyle(DragCursorStyleCore::MOVE, eventId);
525 break;
526 }
527 case DragBehavior::COPY: {
528 UpdateDragStyle(DragCursorStyleCore::COPY, eventId);
529 break;
530 }
531 default: {
532 UpdateDragStyle(DragCursorStyleCore::COPY, eventId);
533 break;
534 }
535 }
536 }
537
CheckExtraSituation(const RefPtr<FrameNode> & dragFrameNode) const538 bool DragDropManager::CheckExtraSituation(const RefPtr<FrameNode>& dragFrameNode) const
539 {
540 return CheckInRichEditor(dragFrameNode);
541 }
542
CheckInRichEditor(const RefPtr<FrameNode> & dragFrameNode) const543 bool DragDropManager::CheckInRichEditor(const RefPtr<FrameNode>& dragFrameNode) const
544 {
545 CHECK_NULL_RETURN(dragFrameNode && draggedFrameNode_, false);
546 auto parent = draggedFrameNode_->GetAncestorNodeOfFrame(false);
547 CHECK_NULL_RETURN(parent && parent->GetTag() == V2::RICH_EDITOR_ETS_TAG, false);
548 return dragFrameNode == parent;
549 }
550
UpdateDragStyle(const DragCursorStyleCore & dragStyle,int32_t eventId)551 void DragDropManager::UpdateDragStyle(const DragCursorStyleCore& dragStyle, int32_t eventId)
552 {
553 if (dragStyle != dragCursorStyleCore_) {
554 ACE_SCOPED_TRACE("drag: update drag style %d", dragStyle);
555 TAG_LOGI(
556 AceLogTag::ACE_DRAG, "Update DragStyle to %{public}d, pointerEventId: %{public}d.", dragStyle, eventId);
557 auto ret = InteractionInterface::GetInstance()->UpdateDragStyle(dragStyle, eventId);
558 if (ret != 0) {
559 TAG_LOGI(AceLogTag::ACE_DRAG,
560 "Update DragStyle to %{public}d failed, keep %{public}d. pointerEventId: %{public}d. ret = %{public}d",
561 dragStyle, dragCursorStyleCore_, eventId, ret);
562 } else {
563 dragCursorStyleCore_ = dragStyle;
564 }
565 }
566 }
567
CheckParentVisible(const RefPtr<FrameNode> & frameNode)568 bool CheckParentVisible(const RefPtr<FrameNode>& frameNode)
569 {
570 CHECK_NULL_RETURN(frameNode, false);
571 bool isVisible = frameNode->IsVisible();
572 if (!isVisible) {
573 return false;
574 }
575 auto parent = frameNode->GetParent();
576 while (parent && parent->GetDepth() != 1) {
577 auto parentFrameNode = AceType::DynamicCast<FrameNode>(parent);
578 if (parentFrameNode && !parentFrameNode->IsVisible()) {
579 isVisible = false;
580 break;
581 }
582 parent = parent->GetParent();
583 }
584 return isVisible;
585 }
586
FindHitFrameNodes(const Point & point)587 std::unordered_set<int32_t> DragDropManager::FindHitFrameNodes(const Point& point)
588 {
589 std::unordered_set<int32_t> frameNodeList;
590 for (auto iter = nodesForDragNotify_.begin(); iter != nodesForDragNotify_.end(); iter++) {
591 auto frameNode = iter->second.Upgrade();
592 if (!frameNode || !frameNode->IsActive() || !frameNode->IsVisible() || !frameNode->IsOnMainTree()) {
593 continue;
594 }
595 auto geometryNode = frameNode->GetGeometryNode();
596 if (!geometryNode) {
597 continue;
598 }
599 auto globalFrameRect = geometryNode->GetFrameRect();
600 globalFrameRect.SetOffset(frameNode->GetTransformRelativeOffset());
601 if (globalFrameRect.IsInRegion(PointF(static_cast<float>(point.GetX()), static_cast<float>(point.GetY())))) {
602 frameNodeList.emplace(frameNode->GetId());
603 }
604 }
605 return frameNodeList;
606 }
607
UpdateDragListener(const Point & point)608 void DragDropManager::UpdateDragListener(const Point& point)
609 {
610 auto hitNodes = FindHitFrameNodes(point);
611 std::unordered_map<int32_t, WeakPtr<FrameNode>> dragEnterNodes;
612 std::unordered_map<int32_t, WeakPtr<FrameNode>> dragMoveNodes;
613 std::unordered_map<int32_t, WeakPtr<FrameNode>> dragLeaveNodes;
614 for (auto iter = nodesForDragNotify_.begin(); iter != nodesForDragNotify_.end(); iter++) {
615 auto localHitResult = hitNodes.find(iter->first) != hitNodes.end();
616 auto preHitResult = parentHitNodes_.find(iter->first) != parentHitNodes_.end();
617 if (localHitResult && preHitResult) {
618 dragMoveNodes[iter->first] = iter->second;
619 }
620 if (localHitResult && !preHitResult) {
621 dragEnterNodes[iter->first] = iter->second;
622 }
623 if (!localHitResult && preHitResult) {
624 dragLeaveNodes[iter->first] = iter->second;
625 }
626 }
627 RefPtr<NotifyDragEvent> notifyEvent = AceType::MakeRefPtr<NotifyDragEvent>();
628 CHECK_NULL_VOID(notifyEvent);
629 UpdateNotifyDragEvent(notifyEvent, point, DragEventType::MOVE);
630
631 NotifyDragRegisterFrameNode(dragMoveNodes, DragEventType::MOVE, notifyEvent);
632 NotifyDragRegisterFrameNode(dragEnterNodes, DragEventType::ENTER, notifyEvent);
633 NotifyDragRegisterFrameNode(dragLeaveNodes, DragEventType::LEAVE, notifyEvent);
634 parentHitNodes_ = std::move(hitNodes);
635 }
636
NotifyDragRegisterFrameNode(std::unordered_map<int32_t,WeakPtr<FrameNode>> nodes,DragEventType dragEventType,RefPtr<NotifyDragEvent> & notifyEvent)637 void DragDropManager::NotifyDragRegisterFrameNode(std::unordered_map<int32_t, WeakPtr<FrameNode>> nodes,
638 DragEventType dragEventType, RefPtr<NotifyDragEvent>& notifyEvent)
639 {
640 for (auto iter = nodes.begin(); iter != nodes.end(); iter++) {
641 auto frameNode = iter->second.Upgrade();
642 if (!frameNode) {
643 continue;
644 }
645 auto eventHub = frameNode->GetEventHub<EventHub>();
646 if (!CheckParentVisible(frameNode) || (eventHub && !eventHub->IsEnabled())) {
647 continue;
648 }
649 auto pattern = frameNode->GetPattern<Pattern>();
650 if (!pattern) {
651 continue;
652 }
653 pattern->HandleOnDragStatusCallback(dragEventType, notifyEvent);
654 }
655 }
656
NotifyDragFrameNode(const Point & point,const DragEventType & dragEventType,const DragRet & dragRet)657 void DragDropManager::NotifyDragFrameNode(
658 const Point& point, const DragEventType& dragEventType, const DragRet& dragRet)
659 {
660 RefPtr<NotifyDragEvent> notifyEvent = AceType::MakeRefPtr<NotifyDragEvent>();
661 CHECK_NULL_VOID(notifyEvent);
662 UpdateNotifyDragEvent(notifyEvent, point, dragEventType);
663 notifyEvent->SetResult(dragRet);
664 NotifyDragRegisterFrameNode(nodesForDragNotify_, dragEventType, notifyEvent);
665 }
666
GetRootNode()667 RefPtr<FrameNode> DragDropManager::GetRootNode()
668 {
669 auto pipeline = NG::PipelineContext::GetCurrentContextSafelyWithCheck();
670 CHECK_NULL_RETURN(pipeline, nullptr);
671 return pipeline->GetRootElement();
672 }
673
OnDragStart(const Point & point,const RefPtr<FrameNode> & frameNode)674 void DragDropManager::OnDragStart(const Point& point, const RefPtr<FrameNode>& frameNode)
675 {
676 dragDropState_ = DragDropMgrState::DRAGGING;
677 NotifyDragFrameNode(point, DragEventType::START);
678 CHECK_NULL_VOID(frameNode);
679 preTargetFrameNode_ = frameNode;
680 draggedFrameNode_ = preTargetFrameNode_;
681 preMovePoint_ = point;
682 parentHitNodes_.emplace(frameNode->GetId());
683
684 // Reset hover status when drag start.
685 auto pipeline = frameNode->GetContextRefPtr();
686 CHECK_NULL_VOID(pipeline);
687 auto eventManager = pipeline->GetEventManager();
688 CHECK_NULL_VOID(eventManager);
689 eventManager->CleanHoverStatusForDragBegin();
690 }
691
OnDragStart(const Point & point)692 void DragDropManager::OnDragStart(const Point& point)
693 {
694 dragDropState_ = DragDropMgrState::DRAGGING;
695 NotifyDragFrameNode(point, DragEventType::START);
696
697 // Reset hover status when drag start.
698 auto pipeline = PipelineContext::GetCurrentContext();
699 CHECK_NULL_VOID(pipeline);
700 auto eventManager = pipeline->GetEventManager();
701 CHECK_NULL_VOID(eventManager);
702 eventManager->CleanHoverStatusForDragBegin();
703 }
704
PrintDragFrameNode(const OHOS::Ace::DragPointerEvent & pointerEvent,const RefPtr<FrameNode> & dragFrameNode)705 void DragDropManager::PrintDragFrameNode(
706 const OHOS::Ace::DragPointerEvent& pointerEvent, const RefPtr<FrameNode>& dragFrameNode)
707 {
708 CHECK_NULL_VOID(dragFrameNode);
709 auto container = Container::Current();
710 CHECK_NULL_VOID(container);
711 if (preTargetFrameNode_) {
712 TAG_LOGI(AceLogTag::ACE_DRAG,
713 "Current windowId is %{public}d, pointerEventId is %{public}d, "
714 "PreTargetFrameNode is %{public}s, depth is %{public}d, New find "
715 "targetNode is %{public}s, depth is %{public}d.",
716 container->GetWindowId(), pointerEvent.pointerEventId, preTargetFrameNode_->GetTag().c_str(),
717 preTargetFrameNode_->GetDepth(), dragFrameNode->GetTag().c_str(), dragFrameNode->GetDepth());
718 } else {
719 TAG_LOGI(AceLogTag::ACE_DRAG,
720 "Current windowId is %{public}d, pointerEventId is %{public}d, "
721 "PreTargetFrameNode is nullptr, New find targetNode is %{public}s, depth is %{public}d",
722 container->GetWindowId(), pointerEvent.pointerEventId, dragFrameNode->GetTag().c_str(),
723 dragFrameNode->GetDepth());
724 }
725 }
726
PrintGridDragFrameNode(const float globalX,const float globalY,const RefPtr<FrameNode> & dragFrameNode)727 void DragDropManager::PrintGridDragFrameNode(
728 const float globalX, const float globalY, const RefPtr<FrameNode>& dragFrameNode)
729 {
730 CHECK_NULL_VOID(dragFrameNode);
731 auto container = Container::Current();
732 CHECK_NULL_VOID(container);
733 if (preGridTargetFrameNode_) {
734 TAG_LOGI(AceLogTag::ACE_DRAG,
735 "Current windowId is %{public}d"
736 "PreTargetFrameNode is %{public}s, depth is %{public}d,"
737 "New find targetNode is %{public}s, depth is %{public}d.",
738 container->GetWindowId(), preGridTargetFrameNode_->GetTag().c_str(),
739 preGridTargetFrameNode_->GetDepth(), dragFrameNode->GetTag().c_str(), dragFrameNode->GetDepth());
740 } else {
741 TAG_LOGI(AceLogTag::ACE_DRAG,
742 "Current windowId is %{public}d, "
743 "PreTargetFrameNode is nullptr, New find targetNode is %{public}s, depth is %{public}d.",
744 container->GetWindowId(), dragFrameNode->GetTag().c_str(), dragFrameNode->GetDepth());
745 }
746 }
747
TransDragWindowToDragFwk(int32_t windowContainerId)748 void DragDropManager::TransDragWindowToDragFwk(int32_t windowContainerId)
749 {
750 if (isDragFwkShow_) {
751 return;
752 }
753 TAG_LOGI(AceLogTag::ACE_DRAG, "TransDragWindowToDragFwk is %{public}d", isDragFwkShow_);
754 ACE_SCOPED_TRACE("drag: set drag window visible by transfer");
755 if (draggedFrameNode_) {
756 auto gestureHub = draggedFrameNode_->GetOrCreateGestureEventHub();
757 CHECK_NULL_VOID(gestureHub);
758 auto dragEventActuator = gestureHub->GetDragEventActuator();
759 CHECK_NULL_VOID(dragEventActuator);
760 dragEventActuator->NotifyTransDragWindowToFwk();
761 }
762 InteractionInterface::GetInstance()->SetDragWindowVisible(true);
763 DragDropGlobalController::GetInstance().ResetDragDropInitiatingStatus();
764 isDragFwkShow_ = true;
765 auto overlayManager = GetDragAnimationOverlayManager(windowContainerId);
766 CHECK_NULL_VOID(overlayManager);
767 overlayManager->RemoveDragPixelMap();
768 overlayManager->RemoveGatherNode();
769 SubwindowManager::GetInstance()->HidePreviewNG();
770 info_.scale = -1.0;
771 dampingOverflowCount_ = 0;
772 }
773
OnDragMoveOut(const DragPointerEvent & pointerEvent)774 void DragDropManager::OnDragMoveOut(const DragPointerEvent& pointerEvent)
775 {
776 Point point = pointerEvent.GetPoint();
777 auto container = Container::Current();
778 if (container && container->IsScenceBoardWindow()) {
779 if (IsDragged() && IsWindowConsumed()) {
780 SetIsWindowConsumed(false);
781 return;
782 }
783 }
784 isReDragStart_ = false;
785 SetIsWindowConsumed(false);
786 UpdateVelocityTrackerPoint(point, false);
787 UpdateDragListener(Point(-1, -1));
788 NotifyPullEventListener(pointerEvent);
789 if (preTargetFrameNode_) {
790 TAG_LOGI(AceLogTag::ACE_DRAG, "Leave the current window, windowId is %{public}d,"
791 " pointerEventId is %{public}d. PreTargetFrameNode is %{public}s, depth is %{public}d.",
792 container->GetWindowId(), pointerEvent.pointerEventId, preTargetFrameNode_->GetTag().c_str(),
793 preTargetFrameNode_->GetDepth());
794 FireOnDragEvent(preTargetFrameNode_, pointerEvent, DragEventType::LEAVE, extraInfo_);
795 preTargetFrameNode_ = nullptr;
796 }
797 if (IsNeedDisplayInSubwindow() || isDragWithContextMenu_) {
798 TransDragWindowToDragFwk(Container::CurrentId());
799 }
800 }
801
isDistanceLimited(const Point & point)802 bool DragDropManager::isDistanceLimited(const Point& point)
803 {
804 auto distance = sqrt(pow(point.GetX() - preMovePoint_.GetX(), 2) + pow(point.GetY() - preMovePoint_.GetY(), 2));
805 TAG_LOGD(AceLogTag::ACE_DRAG, "onDragMove, distance: %{public}f", distance);
806 if (distance < MOVE_DISTANCE_LIMIT) {
807 TAG_LOGD(AceLogTag::ACE_DRAG, "onDragMove, distance is less than limit");
808 return true;
809 }
810 return false;
811 }
812
isTimeLimited(const DragPointerEvent & pointerEvent,const Point & point)813 bool DragDropManager::isTimeLimited(const DragPointerEvent& pointerEvent, const Point& point)
814 {
815 uint64_t currentTimeStamp = static_cast<uint64_t>(
816 std::chrono::duration_cast<std::chrono::milliseconds>(pointerEvent.time.time_since_epoch()).count());
817 if (currentTimeStamp > preTimeStamp_ && currentTimeStamp - preTimeStamp_ < MOVE_TIME_LIMIT) {
818 TAG_LOGD(AceLogTag::ACE_DRAG, "onDragMove, time is less than limit");
819 return true;
820 }
821 return false;
822 }
823
ReachMoveLimit(const DragPointerEvent & pointerEvent,const Point & point)824 bool DragDropManager::ReachMoveLimit(const DragPointerEvent& pointerEvent, const Point& point)
825 {
826 if (pointerEvent.sourceTool == SourceTool::MOUSE) {
827 if (isTimeLimited(pointerEvent, point) && isDistanceLimited(point)) {
828 return true;
829 }
830 }
831 return false;
832 }
833
HandleOnDragMove(const DragPointerEvent & pointerEvent,const std::string & extraInfo,const RefPtr<FrameNode> & dragFrameNode)834 void DragDropManager::HandleOnDragMove(const DragPointerEvent& pointerEvent, const std::string& extraInfo,
835 const RefPtr<FrameNode>& dragFrameNode)
836 {
837 CHECK_NULL_VOID(dragFrameNode);
838
839 if (dragFrameNode == preTargetFrameNode_) {
840 FireOnDragEvent(dragFrameNode, pointerEvent, DragEventType::MOVE, extraInfo);
841 return;
842 }
843
844 FireOnDragLeave(preTargetFrameNode_, pointerEvent, extraInfo);
845 PrintDragFrameNode(pointerEvent, dragFrameNode);
846 FireOnDragEvent(dragFrameNode, pointerEvent, DragEventType::ENTER, extraInfo);
847 preTargetFrameNode_ = dragFrameNode;
848 }
849
OnDragMove(const DragPointerEvent & pointerEvent,const std::string & extraInfo,const RefPtr<FrameNode> & node)850 void DragDropManager::OnDragMove(const DragPointerEvent& pointerEvent, const std::string& extraInfo,
851 const RefPtr<FrameNode>& node)
852 {
853 RequireSummaryIfNecessary(pointerEvent);
854 Point point = pointerEvent.GetPoint();
855 auto container = Container::Current();
856 CHECK_NULL_VOID(container);
857 if (container && container->IsScenceBoardWindow()) {
858 if (IsDragged() && IsWindowConsumed()) {
859 SetIsWindowConsumed(false);
860 return;
861 }
862 }
863 if (ReachMoveLimit(pointerEvent, point)) {
864 return;
865 }
866 NotifyPullEventListener(pointerEvent);
867 preMovePoint_ = point;
868 preDragPointerEvent_ = pointerEvent;
869 preTimeStamp_ = static_cast<uint64_t>(
870 std::chrono::duration_cast<std::chrono::milliseconds>(pointerEvent.time.time_since_epoch()).count());
871 SetIsWindowConsumed(false);
872 if (isDragFwkShow_) {
873 auto menuWrapper = GetMenuWrapperNodeFromDrag();
874 if (menuWrapper) {
875 auto menuPosition = DragDropFuncWrapper::GetPointRelativeToMainWindow(point);
876 SubwindowManager::GetInstance()->UpdateHideMenuOffsetNG(
877 menuPosition, 1.0, false, menuWrapper ? menuWrapper->GetId() : -1);
878 }
879 }
880 UpdateVelocityTrackerPoint(point, false);
881 UpdateDragListener(point);
882 auto dragFrameNode = FindDragFrameNodeByPosition(
883 static_cast<float>(point.GetX()), static_cast<float>(point.GetY()), node);
884 if (!dragFrameNode) {
885 if (preTargetFrameNode_) {
886 TAG_LOGI(AceLogTag::ACE_DRAG,
887 "Not find drag target node, current windowId is %{public}d, pointerEventId is %{public}d, "
888 "PreTargetFrameNode is %{public}s, depth is %{public}d.",
889 container->GetWindowId(), pointerEvent.pointerEventId, preTargetFrameNode_->GetTag().c_str(),
890 preTargetFrameNode_->GetDepth());
891 FireOnDragEvent(preTargetFrameNode_, pointerEvent, DragEventType::LEAVE, extraInfo);
892 preTargetFrameNode_ = nullptr;
893 }
894
895 if (!isMouseDragged_ || isDragWindowShow_) {
896 UpdateDragStyle(DragCursorStyleCore::MOVE, pointerEvent.pointerEventId);
897 }
898 return;
899 }
900 HandleOnDragMove(pointerEvent, extraInfo, dragFrameNode);
901 }
902
ResetDragDropStatus(const Point & point,const DragDropRet & dragDropRet,int32_t windowId)903 void DragDropManager::ResetDragDropStatus(const Point& point, const DragDropRet& dragDropRet, int32_t windowId)
904 {
905 ACE_SCOPED_TRACE("drag: reset drag %d, %d", dragDropRet.result, dragDropRet.hasCustomAnimation);
906 if (dragDropRet.result != DragRet::DRAG_FAIL || !isMouseDragged_) {
907 InteractionInterface::GetInstance()->SetDragWindowVisible(!dragDropRet.hasCustomAnimation);
908 }
909 InteractionInterface::GetInstance()->StopDrag(dragDropRet);
910 NotifyDragFrameNode(point, DragEventType::DROP, dragDropRet.result);
911 ResetPullId();
912 dragCursorStyleCore_ = DragCursorStyleCore::DEFAULT;
913 isReDragStart_ = false;
914 }
915
ResetPreTargetFrameNode(int32_t instanceId)916 void DragDropManager::ResetPreTargetFrameNode(int32_t instanceId)
917 {
918 auto container = Container::GetContainer(instanceId);
919 if (container && (container->IsScenceBoardWindow() || container->IsUIExtensionWindow())) {
920 return;
921 }
922 // pull-in subwindow, need to notify showMenu and update menu offset.
923 if (instanceId > MIN_SUBCONTAINER_ID) {
924 isDragFwkShow_ = true;
925 }
926 preTargetFrameNode_ = nullptr;
927 }
928
ResetDragEndOption(const DragNotifyMsgCore & notifyMessage,const RefPtr<OHOS::Ace::DragEvent> & dragEvent,int32_t currentId)929 void DragDropManager::ResetDragEndOption(
930 const DragNotifyMsgCore& notifyMessage, const RefPtr<OHOS::Ace::DragEvent>& dragEvent, int32_t currentId)
931 {
932 SetDragResult(notifyMessage, dragEvent);
933 SetDragBehavior(notifyMessage, dragEvent);
934 DoDragReset();
935 SetIsDragged(false);
936 SetDraggingPointer(-1);
937 SetDraggingPressedState(false);
938 ResetDragPreviewInfo();
939 HideDragPreviewWindow(currentId);
940 CHECK_NULL_VOID(dragEvent);
941 dragEvent->SetPressedKeyCodes(GetDragDropPointerEvent().pressedKeyCodes);
942 }
943
DoDragReset()944 void DragDropManager::DoDragReset()
945 {
946 dragDropState_ = DragDropMgrState::IDLE;
947 preTargetFrameNode_ = nullptr;
948 draggedFrameNode_ = nullptr;
949 menuWrapperNode_ = nullptr;
950 preMovePoint_ = Point(0, 0);
951 hasNotifiedTransformation_ = false;
952 badgeNumber_ = -1;
953 isDragWithContextMenu_ = false;
954 dampingOverflowCount_ = 0;
955 isDragNodeNeedClean_ = false;
956 isAnyDraggableHit_ = false;
957 fingerPointInfo_.clear();
958 DragDropGlobalController::GetInstance().ResetDragDropInitiatingStatus();
959 }
960
ResetDraggingStatus(const TouchEvent & touchPoint)961 void DragDropManager::ResetDraggingStatus(const TouchEvent& touchPoint)
962 {
963 if (IsDraggingPressed(touchPoint.id)) {
964 SetDraggingPressedState(false);
965 }
966 DragPointerEvent dragPointerEvent;
967 DragDropFuncWrapper::ConvertPointerEvent(touchPoint, dragPointerEvent);
968 if (!IsItemDragging() && IsDragging() && IsSameDraggingPointer(touchPoint.id)) {
969 TAG_LOGI(AceLogTag::ACE_DRAG, "Reset dragging status, stop drag. pointerId: %{public}d", touchPoint.id);
970 SetIsDisableDefaultDropAnimation(true);
971 OnDragEnd(dragPointerEvent, "");
972 }
973 if (touchPoint.type == TouchType::CANCEL) {
974 if (IsUIExtensionComponent(preTargetFrameNode_)) {
975 HandleUIExtensionDragEvent(preTargetFrameNode_, dragPointerEvent, DragEventType::LEAVE);
976 }
977 NotifyDragFrameNode(dragPointerEvent.GetPoint(), DragEventType::LEAVE);
978 }
979 }
980
HandleOnDragEnd(const DragPointerEvent & pointerEvent,const std::string & extraInfo,const RefPtr<FrameNode> & dragFrameNode)981 void DragDropManager::HandleOnDragEnd(const DragPointerEvent& pointerEvent, const std::string& extraInfo,
982 const RefPtr<FrameNode>& dragFrameNode)
983 {
984 CHECK_NULL_VOID(dragFrameNode);
985 Point point = pointerEvent.GetPoint();
986 auto container = Container::Current();
987 CHECK_NULL_VOID(container);
988 if (!IsDropAllowed(dragFrameNode)) {
989 TAG_LOGI(AceLogTag::ACE_DRAG,
990 "DragDropManager onDragEnd, target data is not allowed to fall into. WindowId is %{public}d, "
991 "pointerEventId is %{public}d.",
992 container->GetWindowId(), pointerEvent.pointerEventId);
993 DragDropBehaviorReporter::GetInstance().UpdateDragStopResult(DragStopResult::APP_REFUSE_DATA);
994 ACE_SCOPED_TRACE("drag: stop drag, not allowed to drop");
995 ResetDragDrop(container->GetWindowId(), point);
996 return;
997 }
998 TAG_LOGI(AceLogTag::ACE_DRAG, "Current windowId is %{public}d, pointerEventId is %{public}d, "
999 "TargetNode is %{public}s.",
1000 container->GetWindowId(), pointerEvent.pointerEventId, dragFrameNode->GetTag().c_str());
1001 if (IsUIExtensionComponent(dragFrameNode)) {
1002 auto pattern = dragFrameNode->GetPattern<Pattern>();
1003 pattern->HandleDragEvent(pointerEvent);
1004 NotifyDragFrameNode(point, DragEventType::DROP);
1005 return;
1006 }
1007
1008 RequestDragSummaryInfoAndPrivilege();
1009 std::string udKey;
1010 InteractionInterface::GetInstance()->GetUdKey(udKey);
1011 auto eventHub = dragFrameNode->GetEventHub<EventHub>();
1012 CHECK_NULL_VOID(eventHub);
1013 if (!eventHub->GetDisableDataPrefetch()) {
1014 if (!CheckRemoteData(dragFrameNode, pointerEvent, udKey)) {
1015 auto unifiedData = RequestUDMFDataWithUDKey(udKey);
1016 DoDropAction(dragFrameNode, pointerEvent, unifiedData, udKey);
1017 }
1018 } else {
1019 DoDropAction(dragFrameNode, pointerEvent, nullptr, udKey);
1020 }
1021 }
1022
OnDragEnd(const DragPointerEvent & pointerEvent,const std::string & extraInfo,const RefPtr<FrameNode> & node,const bool keyEscape)1023 void DragDropManager::OnDragEnd(const DragPointerEvent& pointerEvent, const std::string& extraInfo,
1024 const RefPtr<FrameNode>& node, const bool keyEscape)
1025 {
1026 RemoveDeadlineTimer();
1027 Point point = pointerEvent.GetPoint();
1028 dragDropPointerEvent_ = pointerEvent;
1029 auto preTargetFrameNode = preTargetFrameNode_;
1030 DoDragReset();
1031 auto container = Container::Current();
1032 auto containerId = container->GetInstanceId();
1033 DragDropBehaviorReporter::GetInstance().UpdateContainerId(containerId);
1034 if (container && container->IsScenceBoardWindow()) {
1035 if (IsDragged() && IsWindowConsumed()) {
1036 TAG_LOGD(AceLogTag::ACE_DRAG, "DragDropManager is dragged or window consumed. WindowId is %{public}d",
1037 container->GetWindowId());
1038 return;
1039 }
1040 }
1041 UpdateVelocityTrackerPoint(point, true);
1042 auto dragFrameNode = FindDragFrameNodeByPosition(
1043 static_cast<float>(point.GetX()), static_cast<float>(point.GetY()), FilterSubwindowDragRootNode(node));
1044 if (HandleUIExtensionComponentDragCancel(preTargetFrameNode, dragFrameNode, keyEscape, pointerEvent, point)) {
1045 return;
1046 }
1047 if (isDragCancel_) {
1048 DragDropBehaviorReporter::GetInstance().UpdateDragStopResult(DragStopResult::USER_STOP_DRAG);
1049 TAG_LOGI(AceLogTag::ACE_DRAG, "DragDropManager is dragCancel, finish drag. WindowId is %{public}d, "
1050 "pointerEventId is %{public}d.",
1051 container->GetWindowId(), pointerEvent.pointerEventId);
1052 ACE_SCOPED_TRACE("drag: drag cancelled");
1053 DragDropRet dragDropRet { DragRet::DRAG_CANCEL, false, container->GetWindowId(), DragBehavior::UNKNOWN };
1054 ResetDragDropStatus(point, dragDropRet, container->GetWindowId());
1055 FireOnDragEvent(preTargetFrameNode, pointerEvent, DragEventType::LEAVE, extraInfo);
1056 ClearVelocityInfo();
1057 return;
1058 }
1059 if (IsUIExtensionComponent(preTargetFrameNode) && preTargetFrameNode != dragFrameNode) {
1060 HandleUIExtensionDragEvent(preTargetFrameNode, pointerEvent, DragEventType::LEAVE);
1061 }
1062 if (!dragFrameNode) {
1063 DragDropBehaviorReporter::GetInstance().UpdateDragStopResult(DragStopResult::APP_DATA_UNSUPPORT);
1064 TAG_LOGI(AceLogTag::ACE_DRAG,
1065 "DragDropManager onDragEnd, not find drop target, stop drag. WindowId is %{public}d, "
1066 "pointerEventId is %{public}d.",
1067 container->GetWindowId(), pointerEvent.pointerEventId);
1068 ACE_SCOPED_TRACE("drag: drag stop, not find drop target");
1069 ResetDragDrop(container->GetWindowId(), point);
1070 return;
1071 }
1072 HandleOnDragEnd(pointerEvent, extraInfo, dragFrameNode);
1073 }
1074
HandleUIExtensionComponentDragCancel(const RefPtr<FrameNode> & preTargetFrameNode,const RefPtr<FrameNode> & dragFrameNode,const bool keyEscape,const DragPointerEvent & pointerEvent,const Point & point)1075 bool DragDropManager::HandleUIExtensionComponentDragCancel(const RefPtr<FrameNode>& preTargetFrameNode,
1076 const RefPtr<FrameNode>& dragFrameNode, const bool keyEscape, const DragPointerEvent& pointerEvent,
1077 const Point& point)
1078 {
1079 if (!isDragCancel_) {
1080 return false;
1081 }
1082 if (keyEscape && IsUIExtensionComponent(preTargetFrameNode)) {
1083 HandleUIExtensionDragEvent(preTargetFrameNode, pointerEvent, DragEventType::PULL_CANCEL);
1084 NotifyDragFrameNode(point, DragEventType::DROP);
1085 return true;
1086 }
1087 if (IsUIExtensionComponent(dragFrameNode)) {
1088 auto pattern = dragFrameNode->GetPattern<Pattern>();
1089 CHECK_NULL_RETURN(pattern, true);
1090 pattern->HandleDragEvent(pointerEvent);
1091 NotifyDragFrameNode(point, DragEventType::DROP);
1092 return true;
1093 }
1094 return false;
1095 }
1096
OnDragPullCancel(const DragPointerEvent & pointerEvent,const std::string & extraInfo,const RefPtr<FrameNode> & node)1097 void DragDropManager::OnDragPullCancel(const DragPointerEvent& pointerEvent, const std::string& extraInfo,
1098 const RefPtr<FrameNode>& node)
1099 {
1100 RemoveDeadlineTimer();
1101 Point point = pointerEvent.GetPoint();
1102 auto container = Container::Current();
1103 auto containerId = container->GetInstanceId();
1104 DragDropBehaviorReporter::GetInstance().UpdateContainerId(containerId);
1105 DragDropBehaviorReporter::GetInstance().UpdateDragStopResult(DragStopResult::USER_STOP_DRAG);
1106 TAG_LOGI(AceLogTag::ACE_DRAG, "Drag is canceled, finish drag. WindowId is %{public}d, "
1107 "pointerEventId is %{public}d.",
1108 container->GetWindowId(), pointerEvent.pointerEventId);
1109 if (preTargetFrameNode_) {
1110 TAG_LOGI(AceLogTag::ACE_DRAG, "Cancel from the current window, windowId is %{public}d,"
1111 " pointerEventId is %{public}d. PreTargetFrameNode is %{public}s, depth is %{public}d.",
1112 container->GetWindowId(), pointerEvent.pointerEventId, preTargetFrameNode_->GetTag().c_str(),
1113 preTargetFrameNode_->GetDepth());
1114 FireOnDragEvent(preTargetFrameNode_, pointerEvent, DragEventType::LEAVE, extraInfo_);
1115 preTargetFrameNode_ = nullptr;
1116 }
1117 DragDropRet dragDropRet { DragRet::DRAG_CANCEL, false, container->GetWindowId(), DragBehavior::UNKNOWN };
1118 ResetDragDropStatus(point, dragDropRet, container->GetWindowId());
1119 ClearVelocityInfo();
1120 DoDragReset();
1121 }
1122
IsDropAllowed(const RefPtr<FrameNode> & dragFrameNode)1123 bool DragDropManager::IsDropAllowed(const RefPtr<FrameNode>& dragFrameNode)
1124 {
1125 CHECK_NULL_RETURN(dragFrameNode, false);
1126 // application passed in null to indicate refusing all drag data forcedly
1127 bool isDisallowDropForcedly = dragFrameNode->GetDisallowDropForcedly();
1128 if (isDisallowDropForcedly) {
1129 return false;
1130 }
1131 const auto& dragFrameNodeAllowDrop = dragFrameNode->GetAllowDrop();
1132 // if application does not set allow drop or set with empty, treat as all data types is allowed
1133 if (dragFrameNodeAllowDrop.empty() || summaryMap_.empty()) {
1134 return true;
1135 }
1136 DragDropBehaviorReporter::GetInstance().UpdateAllowDropType(dragFrameNodeAllowDrop);
1137 for (const auto& it : summaryMap_) {
1138 // if one matched found, allow drop
1139 if (dragFrameNodeAllowDrop.find(it.first) != dragFrameNodeAllowDrop.end()) {
1140 return true;
1141 }
1142 }
1143 return false;
1144 }
1145
RequestDragSummaryInfoAndPrivilege()1146 void DragDropManager::RequestDragSummaryInfoAndPrivilege()
1147 {
1148 RequireSummary();
1149 int ret = InteractionInterface::GetInstance()->AddPrivilege();
1150 if (ret != 0 && SystemProperties::GetDebugEnabled()) {
1151 TAG_LOGD(AceLogTag::ACE_DRAG, "Interaction AddPrivilege in DragEnd with code:%{public}d", ret);
1152 }
1153 ShadowOffsetData shadowOffsetData { -1, -1, -1, -1 };
1154 ret = InteractionInterface::GetInstance()->GetShadowOffset(shadowOffsetData);
1155 if (ret == 0) {
1156 previewRect_ =
1157 Rect(shadowOffsetData.offsetX, shadowOffsetData.offsetY, shadowOffsetData.width, shadowOffsetData.height);
1158 } else {
1159 TAG_LOGD(AceLogTag::ACE_DRAG, "Interaction GetShadowOffset in DragEnd with code:%{public}d", ret);
1160 }
1161 }
1162
DoDropAction(const RefPtr<FrameNode> & dragFrameNode,const DragPointerEvent & pointerEvent,const RefPtr<UnifiedData> & unifiedData,const std::string & udKey)1163 void DragDropManager::DoDropAction(const RefPtr<FrameNode>& dragFrameNode, const DragPointerEvent& pointerEvent,
1164 const RefPtr<UnifiedData>& unifiedData, const std::string& udKey)
1165 {
1166 RefPtr<OHOS::Ace::DragEvent> event = AceType::MakeRefPtr<OHOS::Ace::DragEvent>();
1167 CHECK_NULL_VOID(event);
1168 if (!udKey.empty()) {
1169 event->SetUdKey(udKey);
1170 }
1171 if (unifiedData == nullptr) {
1172 event->SetIsGetDataSuccess(false);
1173 } else {
1174 DragDropBehaviorReporter::GetInstance().UpdateRecordSize(unifiedData->GetSize());
1175 event->SetData(unifiedData);
1176 event->SetIsGetDataSuccess(true);
1177 }
1178
1179 OnDragDrop(event, dragFrameNode, pointerEvent);
1180 }
1181
RequestUDMFDataWithUDKey(const std::string & udKey)1182 RefPtr<UnifiedData> DragDropManager::RequestUDMFDataWithUDKey(const std::string& udKey)
1183 {
1184 if (udKey.empty()) {
1185 TAG_LOGI(AceLogTag::ACE_DRAG, "udKey is empty");
1186 return nullptr;
1187 }
1188 ACE_SCOPED_TRACE("drag: get drag data from udmf");
1189 RefPtr<UnifiedData> udData = UdmfClient::GetInstance()->CreateUnifiedData();
1190 auto ret = UdmfClient::GetInstance()->GetData(udData, udKey);
1191 if (ret != 0) {
1192 TAG_LOGI(AceLogTag::ACE_DRAG, "Get udmfData failed");
1193 return nullptr;
1194 }
1195 return udData;
1196 }
1197
TryGetDataBackGround(const RefPtr<FrameNode> & dragFrameNode,const DragPointerEvent & pointerEvent,const std::string & udKey,int32_t count)1198 void DragDropManager::TryGetDataBackGround(const RefPtr<FrameNode>& dragFrameNode, const DragPointerEvent& pointerEvent,
1199 const std::string& udKey, int32_t count)
1200 {
1201 auto pipeline = PipelineContext::GetCurrentContext();
1202 CHECK_NULL_VOID(pipeline);
1203 auto taskScheduler = pipeline->GetTaskExecutor();
1204 CHECK_NULL_VOID(taskScheduler);
1205 taskScheduler->PostTask(
1206 [id = Container::CurrentId(), pipeline, dragFrameNode, pointerEvent, udKey, count,
1207 weakManager = WeakClaim(this)]() {
1208 ContainerScope scope(id);
1209 auto dragDropManager = weakManager.Upgrade();
1210 CHECK_NULL_VOID(dragDropManager);
1211 auto taskScheduler = pipeline->GetTaskExecutor();
1212 CHECK_NULL_VOID(taskScheduler);
1213 auto result = dragDropManager->RequestUDMFDataWithUDKey(udKey);
1214 if (result != nullptr || count >= MAX_RETRY_TIMES) {
1215 taskScheduler->PostTask(
1216 [dragFrameNode, pointerEvent, weakManager, result, udKey]() {
1217 auto dragDropManager = weakManager.Upgrade();
1218 CHECK_NULL_VOID(dragDropManager);
1219 dragDropManager->DoDropAction(dragFrameNode, pointerEvent, result, udKey);
1220 },
1221 TaskExecutor::TaskType::UI, "ArkUIDragDropAction");
1222 } else {
1223 // first temp get udmfData failed, prepare to retryGetData.
1224 taskScheduler->PostDelayedTask(
1225 [dragFrameNode, pointerEvent, weakManager, count, udKey]() {
1226 auto dragDropManager = weakManager.Upgrade();
1227 CHECK_NULL_VOID(dragDropManager);
1228 dragDropManager->TryGetDataBackGround(dragFrameNode, pointerEvent, udKey, count + 1);
1229 },
1230 TaskExecutor::TaskType::UI, MAX_RETRY_DURATION, "ArkUIDragDropRetryGetData");
1231 }
1232 },
1233 TaskExecutor::TaskType::BACKGROUND, "ArkUIDragDropGetDataBackground");
1234 }
1235
CheckRemoteData(const RefPtr<FrameNode> & dragFrameNode,const DragPointerEvent & pointerEvent,const std::string & udKey)1236 bool DragDropManager::CheckRemoteData(
1237 const RefPtr<FrameNode>& dragFrameNode, const DragPointerEvent& pointerEvent, const std::string& udKey)
1238 {
1239 if (udKey.empty()) {
1240 DragDropBehaviorReporter::GetInstance().UpdateDragStopResult(DragStopResult::GET_UDKEY_FAIL);
1241 return false;
1242 }
1243 std::string remoteUdKey = udKey;
1244 auto isRemoteData = UdmfClient::GetInstance()->GetRemoteStatus(remoteUdKey);
1245 if (isRemoteData) {
1246 TAG_LOGI(AceLogTag::ACE_DRAG, "Stop drag with motion drag action.");
1247 TryGetDataBackGround(dragFrameNode, pointerEvent, udKey);
1248 DragDropBehaviorReporter::GetInstance().UpdateDragStopResult(DragStopResult::GET_UDKEY_FAIL);
1249 DragDropBehaviorReporter::GetInstance().UpdateIsCrossing(CrossingEnd::IS_CROSSING);
1250 return isRemoteData;
1251 }
1252 DragDropBehaviorReporter::GetInstance().UpdateIsCrossing(CrossingEnd::NOT_CROSSING);
1253 return isRemoteData;
1254 }
1255
OnDragDrop(RefPtr<OHOS::Ace::DragEvent> & event,const RefPtr<FrameNode> & dragFrameNode,const OHOS::Ace::DragPointerEvent & pointerEvent)1256 void DragDropManager::OnDragDrop(RefPtr<OHOS::Ace::DragEvent>& event, const RefPtr<FrameNode>& dragFrameNode,
1257 const OHOS::Ace::DragPointerEvent& pointerEvent)
1258 {
1259 auto point = pointerEvent.GetPoint();
1260 CHECK_NULL_VOID(dragFrameNode);
1261 auto eventHub = dragFrameNode->GetEventHub<EventHub>();
1262 CHECK_NULL_VOID(eventHub);
1263 UpdateDragEvent(event, pointerEvent);
1264 auto extraParams = eventHub->GetDragExtraParams(extraInfo_, point, DragEventType::DROP);
1265 DragDropGlobalController::GetInstance().SetIsOnOnDropPhase(true);
1266 eventHub->FireCustomerOnDragFunc(DragFuncType::DRAG_DROP, event, extraParams);
1267 if (event->IsDragEndPending() && event->GetRequestIdentify() != -1) {
1268 if (PostStopDrag(dragFrameNode, pointerEvent, event, extraParams)) {
1269 return;
1270 }
1271 }
1272 HandleStopDrag(dragFrameNode, pointerEvent, event, extraParams);
1273 DragDropGlobalController::GetInstance().SetIsOnOnDropPhase(false);
1274 }
1275
HandleStopDrag(const RefPtr<FrameNode> & dragFrameNode,const DragPointerEvent & pointerEvent,const RefPtr<OHOS::Ace::DragEvent> & event,const std::string & extraParams)1276 void DragDropManager::HandleStopDrag(const RefPtr<FrameNode>& dragFrameNode, const DragPointerEvent& pointerEvent,
1277 const RefPtr<OHOS::Ace::DragEvent>& event, const std::string& extraParams)
1278 {
1279 auto point = pointerEvent.GetPoint();
1280 CHECK_NULL_VOID(dragFrameNode);
1281 auto eventHub = dragFrameNode->GetEventHub<EventHub>();
1282 CHECK_NULL_VOID(eventHub);
1283 eventHub->HandleInternalOnDrop(event, extraParams);
1284 ClearVelocityInfo();
1285 SetIsDragged(false);
1286 auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
1287 CHECK_NULL_VOID(pipeline);
1288 auto dragResult = event->GetResult();
1289 if (dragResult == DragRet::DRAG_FAIL) {
1290 DragDropBehaviorReporter::GetInstance().UpdateDragStopResult(DragStopResult::APP_RECEIVE_FAIL);
1291 } else if (dragResult == DragRet::DRAG_CANCEL) {
1292 DragDropBehaviorReporter::GetInstance().UpdateDragStopResult(DragStopResult::USER_STOP_DRAG);
1293 }
1294 auto useCustomAnimation = event->IsUseCustomAnimation();
1295 auto dragBehavior = event->GetDragBehavior();
1296 auto container = Container::Current();
1297 CHECK_NULL_VOID(container);
1298 auto windowId = container->GetWindowId();
1299 ExecuteStopDrag(event, dragResult, useCustomAnimation, windowId, dragBehavior, pointerEvent);
1300 NotifyDragFrameNode(point, DragEventType::DROP, event->GetResult());
1301 dragFrameNode->MarkDirtyNode();
1302 ResetPullId();
1303 dragCursorStyleCore_ = DragCursorStyleCore::DEFAULT;
1304 pipeline->RequestFrame();
1305 }
1306
PostStopDrag(const RefPtr<FrameNode> & dragFrameNode,const DragPointerEvent & pointerEvent,const RefPtr<OHOS::Ace::DragEvent> & event,const std::string & extraParams)1307 bool DragDropManager::PostStopDrag(const RefPtr<FrameNode>& dragFrameNode, const DragPointerEvent& pointerEvent,
1308 const RefPtr<OHOS::Ace::DragEvent>& event, const std::string& extraParams)
1309 {
1310 CHECK_NULL_RETURN(dragFrameNode, false);
1311 CHECK_NULL_RETURN(event, false);
1312 auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
1313 CHECK_NULL_RETURN(pipeline, false);
1314 auto taskScheduler = pipeline->GetTaskExecutor();
1315 CHECK_NULL_RETURN(taskScheduler, false);
1316 taskScheduler->PostDelayedTask(
1317 [pointerEvent, event, extraParams, nodeWeak = WeakClaim(AceType::RawPtr(dragFrameNode)),
1318 weakManager = WeakClaim(this)]() {
1319 if (!DragDropGlobalController::GetInstance().IsOnOnDropPhase() || !event) {
1320 return;
1321 }
1322 auto dragDropManager = weakManager.Upgrade();
1323 if (dragDropManager) {
1324 auto frameNode = nodeWeak.Upgrade();
1325 event->SetResult(DragRet::DRAG_FAIL);
1326 dragDropManager->HandleStopDrag(frameNode, pointerEvent, event, extraParams);
1327 }
1328 DragDropGlobalController::GetInstance().SetIsOnOnDropPhase(false);
1329 },
1330 TaskExecutor::TaskType::UI, DROP_DELAY_TIME, "ArkUIStopDragDeadlineTimer");
1331 return DragDropGlobalController::GetInstance().RequestDragEndCallback(event->GetRequestIdentify(),
1332 event->GetResult(), GetStopDragCallBack(dragFrameNode, pointerEvent, event, extraParams));
1333 }
1334
GetStopDragCallBack(const RefPtr<FrameNode> & dragFrameNode,const DragPointerEvent & pointerEvent,const RefPtr<OHOS::Ace::DragEvent> & event,const std::string & extraParams)1335 std::function<void(const DragRet&)> DragDropManager::GetStopDragCallBack(const RefPtr<FrameNode>& dragFrameNode,
1336 const DragPointerEvent& pointerEvent, const RefPtr<OHOS::Ace::DragEvent>& event, const std::string& extraParams)
1337 {
1338 auto callback = [id = Container::CurrentId(), pointerEvent, event, extraParams,
1339 nodeWeak = WeakClaim(AceType::RawPtr(dragFrameNode)),
1340 weakManager = WeakClaim(this)] (const DragRet& dragResult) {
1341 ContainerScope scope(id);
1342 auto dragDropManager = weakManager.Upgrade();
1343 CHECK_NULL_VOID(dragDropManager);
1344 CHECK_NULL_VOID(event);
1345 event->SetResult(dragResult);
1346 auto frameNode = nodeWeak.Upgrade();
1347 dragDropManager->HandleStopDrag(frameNode, pointerEvent, event, extraParams);
1348 };
1349 return callback;
1350 }
1351
ExecuteStopDrag(const RefPtr<OHOS::Ace::DragEvent> & event,DragRet dragResult,bool useCustomAnimation,int32_t windowId,DragBehavior dragBehavior,const OHOS::Ace::DragPointerEvent & pointerEvent)1352 void DragDropManager::ExecuteStopDrag(const RefPtr<OHOS::Ace::DragEvent>& event, DragRet dragResult,
1353 bool useCustomAnimation, int32_t windowId, DragBehavior dragBehavior,
1354 const OHOS::Ace::DragPointerEvent& pointerEvent)
1355 {
1356 if (useCustomAnimation && event->HasDropAnimation()) {
1357 ExecuteCustomDropAnimation(event, DragDropRet { dragResult, useCustomAnimation, windowId, dragBehavior });
1358 return;
1359 }
1360 auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
1361 CHECK_NULL_VOID(pipeline);
1362 auto overlayManager = GetDragAnimationOverlayManager(pipeline->GetInstanceId());
1363 if (overlayManager && !isDragFwkShow_) {
1364 overlayManager->RemoveDragPixelMap();
1365 overlayManager->RemoveFilter();
1366 pipeline->FlushMessages();
1367 }
1368 pipeline->AddAfterRenderTask([dragResult, useCustomAnimation, windowId, dragBehavior,
1369 pointerEventId = pointerEvent.pointerEventId, weak = WeakClaim(this)]() mutable {
1370 auto manager = weak.Upgrade();
1371 if (manager) {
1372 manager->HideDragPreviewOverlay();
1373 useCustomAnimation = manager->IsDisableDefaultDropAnimation() ? true : useCustomAnimation;
1374 }
1375 TAG_LOGI(AceLogTag::ACE_DRAG,
1376 "Stop drag, start do drop animation. useCustomAnimation is %{public}d,"
1377 "WindowId is %{public}d, pointerEventId is %{public}d.",
1378 useCustomAnimation, windowId, pointerEventId);
1379 InteractionInterface::GetInstance()->SetDragWindowVisible(!useCustomAnimation);
1380 DragDropRet dragDropRet { dragResult, useCustomAnimation, windowId, dragBehavior };
1381 InteractionInterface::GetInstance()->StopDrag(dragDropRet);
1382 });
1383 }
1384
ExecuteCustomDropAnimation(const RefPtr<OHOS::Ace::DragEvent> & event,DragDropRet dragDropRet)1385 void DragDropManager::ExecuteCustomDropAnimation(const RefPtr<OHOS::Ace::DragEvent>& event, DragDropRet dragDropRet)
1386 {
1387 CHECK_NULL_VOID(event);
1388 event->ExecuteDropAnimation();
1389 auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
1390 CHECK_NULL_VOID(pipeline);
1391 auto overlayManager = GetDragAnimationOverlayManager(pipeline->GetInstanceId());
1392 if (overlayManager) {
1393 overlayManager->RemoveDragPixelMap();
1394 overlayManager->RemoveFilter();
1395 }
1396 InteractionInterface::GetInstance()->SetDragWindowVisible(false);
1397 pipeline->FlushMessages();
1398 InteractionInterface::GetInstance()->StopDrag(dragDropRet);
1399 }
1400
RequireSummary()1401 void DragDropManager::RequireSummary()
1402 {
1403 std::map<std::string, int64_t> summary;
1404 int32_t ret = InteractionInterface::GetInstance()->GetDragSummary(summary);
1405 if (ret != 0) {
1406 TAG_LOGI(AceLogTag::ACE_DRAG, "RequireSummary: Interaction GetSummary failed: %{public}d", ret);
1407 } else {
1408 std::string summarys;
1409 for (const auto& [udkey, recordSize] : summary) {
1410 std::string str = udkey + "-" + std::to_string(recordSize) + ";";
1411 summarys += str;
1412 }
1413 TAG_LOGI(AceLogTag::ACE_DRAG, "require summary: %{public}s", summarys.c_str());
1414 DragDropBehaviorReporter::GetInstance().UpdateSummaryType(summarys);
1415 }
1416 std::string extraInfo;
1417 ret = InteractionInterface::GetInstance()->GetDragExtraInfo(extraInfo);
1418 if (ret != 0) {
1419 TAG_LOGI(AceLogTag::ACE_DRAG, "GetExtraInfo: Interaction GetExtraInfo failed: %{public}d", ret);
1420 }
1421 previewRect_ = Rect(-1, -1, -1, -1);
1422 extraInfo_ = extraInfo;
1423 summaryMap_ = summary;
1424 }
1425
ResetRecordSize(uint32_t recordSize)1426 void DragDropManager::ResetRecordSize(uint32_t recordSize)
1427 {
1428 recordSize_ = recordSize;
1429 }
1430
GetRecordSize() const1431 uint32_t DragDropManager::GetRecordSize() const
1432 {
1433 return recordSize_;
1434 }
1435
GetDragWindowRect(const Point & point)1436 Rect DragDropManager::GetDragWindowRect(const Point& point)
1437 {
1438 if (!previewRect_.IsValid()) {
1439 ShadowOffsetData shadowOffsetData { -1, -1, -1, -1 };
1440 int ret = InteractionInterface::GetInstance()->GetShadowOffset(shadowOffsetData);
1441 if (ret == 0) {
1442 previewRect_ = Rect(
1443 shadowOffsetData.offsetX,
1444 shadowOffsetData.offsetY,
1445 shadowOffsetData.width,
1446 shadowOffsetData.height);
1447 }
1448 }
1449 return previewRect_ + Offset(point.GetX(), point.GetY());
1450 }
1451
ClearSummary()1452 void DragDropManager::ClearSummary()
1453 {
1454 previewRect_ = Rect(-1, -1, -1, -1);
1455 ResetPullId();
1456 ResetRecordSize();
1457 }
1458
OnTextDragEnd(float globalX,float globalY,const std::string & extraInfo)1459 void DragDropManager::OnTextDragEnd(float globalX, float globalY, const std::string& extraInfo)
1460 {
1461 dragDropState_ = DragDropMgrState::IDLE;
1462 auto dragFrameNode = FindDragFrameNodeByPosition(globalX, globalY);
1463 if (dragFrameNode) {
1464 auto textFieldPattern = dragFrameNode->GetPattern<TextFieldPattern>();
1465 if (textFieldPattern) {
1466 textFieldPattern->InsertValue(extraInfo);
1467 }
1468 }
1469 SetIsDragged(false);
1470 currentId_ = -1;
1471 }
1472
onDragCancel()1473 void DragDropManager::onDragCancel()
1474 {
1475 preTargetFrameNode_ = nullptr;
1476 draggedFrameNode_ = nullptr;
1477 }
1478
FireOnDragEventWithDragType(const RefPtr<EventHub> & eventHub,DragEventType type,RefPtr<OHOS::Ace::DragEvent> & event,const std::string & extraParams)1479 void DragDropManager::FireOnDragEventWithDragType(const RefPtr<EventHub>& eventHub, DragEventType type,
1480 RefPtr<OHOS::Ace::DragEvent>& event, const std::string& extraParams)
1481 {
1482 switch (type) {
1483 case DragEventType::ENTER: {
1484 eventHub->FireCustomerOnDragFunc(DragFuncType::DRAG_ENTER, event, extraParams);
1485 eventHub->FireOnDragEnter(event, extraParams);
1486 break;
1487 }
1488 case DragEventType::MOVE: {
1489 eventHub->FireCustomerOnDragFunc(DragFuncType::DRAG_MOVE, event, extraParams);
1490 eventHub->FireOnDragMove(event, extraParams);
1491 break;
1492 }
1493 case DragEventType::LEAVE: {
1494 eventHub->FireCustomerOnDragFunc(DragFuncType::DRAG_LEAVE, event, extraParams);
1495 eventHub->FireOnDragLeave(event, extraParams);
1496 break;
1497 }
1498 case DragEventType::DROP: {
1499 eventHub->FireCustomerOnDragFunc(DragFuncType::DRAG_DROP, event, extraParams);
1500 eventHub->HandleInternalOnDrop(event, extraParams);
1501 break;
1502 }
1503 default:
1504 break;
1505 }
1506 }
1507
FireOnDragEvent(const RefPtr<FrameNode> & frameNode,const DragPointerEvent & pointerEvent,DragEventType type,const std::string & extraInfo)1508 void DragDropManager::FireOnDragEvent(
1509 const RefPtr<FrameNode>& frameNode, const DragPointerEvent& pointerEvent,
1510 DragEventType type, const std::string& extraInfo)
1511 {
1512 CHECK_NULL_VOID(frameNode);
1513 if (IsUIExtensionComponent(frameNode)) {
1514 HandleUIExtensionDragEvent(frameNode, pointerEvent, type);
1515 return;
1516 }
1517 auto eventHub = frameNode->GetEventHub<EventHub>();
1518 CHECK_NULL_VOID(eventHub);
1519 if (!eventHub->HasOnDrop() && !eventHub->HasOnItemDrop() && !eventHub->HasCustomerOnDrop()) {
1520 return;
1521 }
1522 auto point = pointerEvent.GetPoint();
1523 auto extraParams = eventHub->GetDragExtraParams(extraInfo_.empty() ? extraInfo : extraInfo_, point, type);
1524 RefPtr<OHOS::Ace::DragEvent> event = AceType::MakeRefPtr<OHOS::Ace::DragEvent>();
1525 CHECK_NULL_VOID(event);
1526 UpdateDragEvent(event, pointerEvent);
1527
1528 FireOnEditableTextComponent(frameNode, type);
1529 FireOnDragEventWithDragType(eventHub, type, event, extraParams);
1530
1531 if (isMouseDragged_ && !isDragWindowShow_) {
1532 return;
1533 }
1534 UpdateDragCursorStyle(frameNode, event, pointerEvent.pointerEventId);
1535 }
1536
UpdateDragCursorStyle(const RefPtr<FrameNode> & frameNode,const RefPtr<OHOS::Ace::DragEvent> & event,const int32_t eventId)1537 void DragDropManager::UpdateDragCursorStyle(const RefPtr<FrameNode>& frameNode,
1538 const RefPtr<OHOS::Ace::DragEvent>& event, const int32_t eventId)
1539 {
1540 if (event->GetResult() == DragRet::ENABLE_DROP) {
1541 if (event->GetDragBehavior() == DragBehavior::MOVE) {
1542 UpdateDragStyle(DragCursorStyleCore::MOVE, eventId);
1543 } else {
1544 UpdateDragStyle(DragCursorStyleCore::COPY, eventId);
1545 }
1546 } else if (event->GetResult() == DragRet::DISABLE_DROP) {
1547 // simplified specifications for drag cursor style, no longer showing forbidden drag cursor
1548 UpdateDragStyle(DragCursorStyleCore::MOVE, eventId);
1549 } else {
1550 UpdateDragAllowDrop(frameNode, event->GetDragBehavior(), eventId, event->IsCapi());
1551 }
1552 }
1553
OnItemDragStart(float globalX,float globalY,const RefPtr<FrameNode> & frameNode)1554 void DragDropManager::OnItemDragStart(float globalX, float globalY, const RefPtr<FrameNode>& frameNode)
1555 {
1556 dragDropState_ = DragDropMgrState::DRAGGING;
1557 preGridTargetFrameNode_ = frameNode;
1558 draggedGridFrameNode_ = frameNode;
1559 }
1560
OnItemDragMove(float globalX,float globalY,int32_t draggedIndex,DragType dragType)1561 void DragDropManager::OnItemDragMove(float globalX, float globalY, int32_t draggedIndex, DragType dragType)
1562 {
1563 auto container = Container::Current();
1564 CHECK_NULL_VOID(container);
1565
1566 UpdateItemDragPosition(globalX, globalY);
1567
1568 OHOS::Ace::ItemDragInfo itemDragInfo;
1569 itemDragInfo.SetX(globalX);
1570 itemDragInfo.SetY(globalY);
1571
1572 // use -1 for grid item not in eventGrid
1573 auto getDraggedIndex = [draggedGrid = draggedGridFrameNode_, draggedIndex, dragType](
1574 const RefPtr<FrameNode>& eventGrid) {
1575 return (dragType == DragType::GRID) ? (eventGrid == draggedGrid ? draggedIndex : -1) : draggedIndex;
1576 };
1577
1578 auto dragFrameNode = FindDragFrameNodeByPosition(globalX, globalY);
1579 if (!dragFrameNode) {
1580 if (preGridTargetFrameNode_) {
1581 TAG_LOGI(AceLogTag::ACE_DRAG, "Not find drag target node, current windowId is %{public}d,"
1582 "PreGridTargetFrameNode is %{public}s, depth is %{public}d.",
1583 container->GetWindowId(), preGridTargetFrameNode_->GetTag().c_str(),
1584 preGridTargetFrameNode_->GetDepth());
1585 FireOnItemDragEvent(preGridTargetFrameNode_, dragType, itemDragInfo, DragEventType::LEAVE,
1586 getDraggedIndex(preGridTargetFrameNode_));
1587 preGridTargetFrameNode_ = nullptr;
1588 }
1589 return;
1590 }
1591
1592 if (dragFrameNode == preGridTargetFrameNode_) {
1593 int32_t insertIndex = GetItemIndex(dragFrameNode, dragType, globalX, globalY);
1594 FireOnItemDragEvent(
1595 dragFrameNode, dragType, itemDragInfo, DragEventType::MOVE, getDraggedIndex(dragFrameNode), insertIndex);
1596 return;
1597 }
1598
1599 if (preGridTargetFrameNode_) {
1600 FireOnItemDragEvent(preGridTargetFrameNode_, dragType, itemDragInfo, DragEventType::LEAVE,
1601 getDraggedIndex(preGridTargetFrameNode_));
1602 }
1603
1604 PrintGridDragFrameNode(globalX, globalY, dragFrameNode);
1605 FireOnItemDragEvent(dragFrameNode, dragType, itemDragInfo, DragEventType::ENTER, getDraggedIndex(dragFrameNode));
1606 preGridTargetFrameNode_ = dragFrameNode;
1607 }
1608
GetWindowScale() const1609 float DragDropManager::GetWindowScale() const
1610 {
1611 float scale = 1.0f;
1612 auto container = Container::Current();
1613 CHECK_NULL_RETURN(container, scale);
1614 scale = container->GetWindowScale();
1615 return scale;
1616 }
1617
OnItemDragEnd(float globalX,float globalY,int32_t draggedIndex,DragType dragType)1618 void DragDropManager::OnItemDragEnd(float globalX, float globalY, int32_t draggedIndex, DragType dragType)
1619 {
1620 dragDropState_ = DragDropMgrState::IDLE;
1621 auto windowScale = isDragWindowSubWindow_ ? 1.0f : GetWindowScale();
1622 auto windowX = globalX * windowScale;
1623 auto windowY = globalY * windowScale;
1624
1625 OHOS::Ace::ItemDragInfo itemDragInfo;
1626 itemDragInfo.SetX(windowX);
1627 itemDragInfo.SetY(windowY);
1628
1629 auto dragFrameNode = FindDragFrameNodeByPosition(globalX, globalY);
1630 if (!dragFrameNode) {
1631 // drag on one grid and drop on other area
1632 if (draggedGridFrameNode_) {
1633 if (dragType == DragType::GRID) {
1634 auto eventHub = draggedGridFrameNode_->GetEventHub<GridEventHub>();
1635 CHECK_NULL_VOID(eventHub);
1636 eventHub->FireOnItemDrop(itemDragInfo, draggedIndex, -1, false);
1637 } else {
1638 auto eventHub = draggedGridFrameNode_->GetEventHub<ListEventHub>();
1639 CHECK_NULL_VOID(eventHub);
1640 eventHub->FireOnItemDrop(itemDragInfo, draggedIndex, -1, false);
1641 }
1642 }
1643 } else {
1644 int32_t insertIndex = GetItemIndex(dragFrameNode, dragType, globalX, globalY);
1645 // drag and drop on the same grid
1646 if (dragFrameNode == draggedGridFrameNode_) {
1647 FireOnItemDropEvent(dragFrameNode, dragType, itemDragInfo, draggedIndex, insertIndex, true);
1648 } else {
1649 // drag and drop on different grid
1650 bool isSuccess = FireOnItemDropEvent(dragFrameNode, dragType, itemDragInfo, -1, insertIndex, true);
1651 if (draggedGridFrameNode_) {
1652 FireOnItemDropEvent(draggedGridFrameNode_, dragType, itemDragInfo, draggedIndex, -1, isSuccess);
1653 }
1654 }
1655 }
1656
1657 preGridTargetFrameNode_ = nullptr;
1658 draggedGridFrameNode_ = nullptr;
1659 }
1660
onItemDragCancel()1661 void DragDropManager::onItemDragCancel()
1662 {
1663 dragDropState_ = DragDropMgrState::IDLE;
1664 preGridTargetFrameNode_ = nullptr;
1665 draggedGridFrameNode_ = nullptr;
1666 }
1667
FireOnItemDragEvent(const RefPtr<FrameNode> & frameNode,DragType dragType,const OHOS::Ace::ItemDragInfo & itemDragInfo,DragEventType type,int32_t draggedIndex,int32_t insertIndex)1668 void DragDropManager::FireOnItemDragEvent(const RefPtr<FrameNode>& frameNode, DragType dragType,
1669 const OHOS::Ace::ItemDragInfo& itemDragInfo, DragEventType type, int32_t draggedIndex, int32_t insertIndex)
1670 {
1671 CHECK_NULL_VOID(frameNode);
1672 if (dragType == DragType::GRID) {
1673 auto eventHub = frameNode->GetEventHub<GridEventHub>();
1674 CHECK_NULL_VOID(eventHub);
1675 switch (type) {
1676 case DragEventType::ENTER:
1677 eventHub->FireOnItemDragEnter(itemDragInfo);
1678 break;
1679 case DragEventType::MOVE:
1680 eventHub->FireOnItemDragMove(itemDragInfo, draggedIndex, insertIndex);
1681 break;
1682 case DragEventType::LEAVE:
1683 eventHub->FireOnItemDragLeave(itemDragInfo, draggedIndex);
1684 break;
1685 default:
1686 break;
1687 }
1688 } else if (dragType == DragType::LIST) {
1689 auto eventHub = frameNode->GetEventHub<ListEventHub>();
1690 CHECK_NULL_VOID(eventHub);
1691 switch (type) {
1692 case DragEventType::ENTER:
1693 eventHub->FireOnItemDragEnter(itemDragInfo);
1694 break;
1695 case DragEventType::MOVE:
1696 eventHub->FireOnItemDragMove(itemDragInfo, draggedIndex, insertIndex);
1697 break;
1698 case DragEventType::LEAVE:
1699 eventHub->FireOnItemDragLeave(itemDragInfo, draggedIndex);
1700 break;
1701 default:
1702 break;
1703 }
1704 }
1705 }
1706
FireOnItemDropEvent(const RefPtr<FrameNode> & frameNode,DragType dragType,const OHOS::Ace::ItemDragInfo & itemDragInfo,int32_t draggedIndex,int32_t insertIndex,bool isSuccess)1707 bool DragDropManager::FireOnItemDropEvent(const RefPtr<FrameNode>& frameNode, DragType dragType,
1708 const OHOS::Ace::ItemDragInfo& itemDragInfo, int32_t draggedIndex, int32_t insertIndex, bool isSuccess)
1709 {
1710 CHECK_NULL_RETURN(frameNode, false);
1711 if (dragType == DragType::GRID) {
1712 auto eventHub = frameNode->GetEventHub<GridEventHub>();
1713 CHECK_NULL_RETURN(eventHub, false);
1714 return eventHub->FireOnItemDrop(itemDragInfo, draggedIndex, insertIndex, isSuccess);
1715 } else if (dragType == DragType::LIST) {
1716 auto eventHub = frameNode->GetEventHub<ListEventHub>();
1717 CHECK_NULL_RETURN(eventHub, false);
1718 return eventHub->FireOnItemDrop(itemDragInfo, draggedIndex, insertIndex, isSuccess);
1719 }
1720 return false;
1721 }
1722
GetItemIndex(const RefPtr<FrameNode> & frameNode,DragType dragType,float globalX,float globalY)1723 int32_t DragDropManager::GetItemIndex(
1724 const RefPtr<FrameNode>& frameNode, DragType dragType, float globalX, float globalY)
1725 {
1726 CHECK_NULL_RETURN(frameNode, -1);
1727 if (dragType == DragType::GRID) {
1728 auto eventHub = frameNode->GetEventHub<GridEventHub>();
1729 CHECK_NULL_RETURN(eventHub, -1);
1730 if (frameNode != draggedGridFrameNode_) {
1731 return eventHub->GetInsertPosition(globalX, globalY);
1732 }
1733 auto itemFrameNode = frameNode->FindChildByPositionWithoutChildTransform(globalX, globalY);
1734 if (!itemFrameNode) {
1735 if (eventHub->CheckPostionInGrid(globalX, globalY)) {
1736 return eventHub->GetFrameNodeChildSize();
1737 }
1738 } else {
1739 return eventHub->GetGridItemIndex(itemFrameNode);
1740 }
1741 } else if (dragType == DragType::LIST) {
1742 auto eventHub = frameNode->GetEventHub<ListEventHub>();
1743 CHECK_NULL_RETURN(eventHub, -1);
1744 return eventHub->GetListItemIndexByPosition(globalX, globalY);
1745 }
1746 return -1;
1747 }
1748
AddDataToClipboard(const std::string & extraInfo)1749 void DragDropManager::AddDataToClipboard(const std::string& extraInfo)
1750 {
1751 auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
1752 CHECK_NULL_VOID(pipeline);
1753 if (!extraInfo.empty()) {
1754 if (!newData_) {
1755 newData_ = JsonUtil::Create(true);
1756 newData_->Put("customDragInfo", extraInfo.c_str());
1757 } else {
1758 newData_->Replace("customDragInfo", extraInfo.c_str());
1759 }
1760 } else {
1761 return;
1762 }
1763 if (!clipboard_) {
1764 clipboard_ = ClipboardProxy::GetInstance()->GetClipboard(pipeline->GetTaskExecutor());
1765 }
1766 if (!addDataCallback_) {
1767 auto callback = [weakManager = WeakClaim(this)](const std::string& data) {
1768 auto dragDropManager = weakManager.Upgrade();
1769 CHECK_NULL_VOID(dragDropManager);
1770 auto addData = dragDropManager->newData_->ToString();
1771 auto clipboardAllData = JsonUtil::Create(true);
1772 clipboardAllData->Put("preData", data.c_str());
1773 clipboardAllData->Put("newData", addData.c_str());
1774 dragDropManager->clipboard_->SetData(clipboardAllData->ToString(), CopyOptions::Local, true);
1775 };
1776 addDataCallback_ = callback;
1777 }
1778 if (clipboard_) {
1779 clipboard_->GetData(addDataCallback_, true);
1780 }
1781 }
1782
GetExtraInfoFromClipboard(std::string & extraInfo)1783 void DragDropManager::GetExtraInfoFromClipboard(std::string& extraInfo)
1784 {
1785 auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
1786 CHECK_NULL_VOID(pipeline);
1787
1788 if (!clipboard_) {
1789 clipboard_ = ClipboardProxy::GetInstance()->GetClipboard(pipeline->GetTaskExecutor());
1790 }
1791
1792 if (!getDataCallback_) {
1793 auto callback = [weak = WeakClaim(this)](const std::string& data) {
1794 auto manager = weak.Upgrade();
1795 CHECK_NULL_VOID(manager);
1796 auto json = JsonUtil::ParseJsonString(data);
1797 auto newData = JsonUtil::ParseJsonString(json->GetString("newData"));
1798 manager->extraInfo_ = newData->GetString("customDragInfo");
1799 };
1800 getDataCallback_ = callback;
1801 }
1802
1803 if (getDataCallback_ && clipboard_) {
1804 clipboard_->GetData(getDataCallback_, true);
1805 }
1806
1807 extraInfo = extraInfo_;
1808 }
1809
RestoreClipboardData()1810 void DragDropManager::RestoreClipboardData()
1811 {
1812 auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
1813 CHECK_NULL_VOID(pipeline);
1814
1815 if (!clipboard_) {
1816 clipboard_ = ClipboardProxy::GetInstance()->GetClipboard(pipeline->GetTaskExecutor());
1817 }
1818
1819 if (!deleteDataCallback_) {
1820 auto callback = [weakManager = WeakClaim(this)](const std::string& data) {
1821 auto dragDropManager = weakManager.Upgrade();
1822 CHECK_NULL_VOID(dragDropManager);
1823 auto json = JsonUtil::ParseJsonString(data);
1824 if (json->Contains("preData")) {
1825 dragDropManager->clipboard_->SetData(json->GetString("preData"));
1826 }
1827 };
1828 deleteDataCallback_ = callback;
1829 }
1830 if (clipboard_) {
1831 clipboard_->GetData(deleteDataCallback_, true);
1832 }
1833 }
1834
DestroyDragWindow()1835 void DragDropManager::DestroyDragWindow()
1836 {
1837 ResetRecordSize();
1838 if (itemDragOverlayNode_) {
1839 RemoveItemDrag();
1840 itemDragOverlayNode_ = nullptr;
1841 }
1842 SetIsDragged(false);
1843 SetIsDragWindowShow(false);
1844 previewRect_ = Rect(-1, -1, -1, -1);
1845 isMouseDragged_ = false;
1846 currentId_ = -1;
1847 }
1848
CancelItemDrag()1849 void DragDropManager::CancelItemDrag()
1850 {
1851 if (draggedGridFrameNode_) {
1852 auto listEventHub = draggedGridFrameNode_->GetEventHub<ListEventHub>();
1853 if (listEventHub) {
1854 listEventHub->HandleOnItemDragCancel();
1855 return;
1856 }
1857 auto gridEventHub = draggedGridFrameNode_->GetEventHub<GridEventHub>();
1858 if (gridEventHub) {
1859 gridEventHub->HandleOnItemDragCancel();
1860 return;
1861 }
1862 }
1863 }
1864
CreateFrameworkDragDropProxy()1865 RefPtr<DragDropProxy> DragDropManager::CreateFrameworkDragDropProxy()
1866 {
1867 SetIsDragged(true);
1868 isDragCancel_ = false;
1869 currentId_ = ++g_proxyId;
1870 return MakeRefPtr<DragDropProxy>(currentId_);
1871 }
1872
UpdateNotifyDragEvent(RefPtr<NotifyDragEvent> & notifyEvent,const Point & point,const DragEventType dragEventType)1873 void DragDropManager::UpdateNotifyDragEvent(
1874 RefPtr<NotifyDragEvent>& notifyEvent, const Point& point, const DragEventType dragEventType)
1875 {
1876 CHECK_NULL_VOID(notifyEvent);
1877 notifyEvent->SetX((double)point.GetX());
1878 notifyEvent->SetY((double)point.GetY());
1879 notifyEvent->SetScreenX((double)point.GetScreenX());
1880 notifyEvent->SetScreenY((double)point.GetScreenY());
1881 if (dragEventType != DragEventType::START) {
1882 if (dragEventType != DragEventType::DROP) {
1883 notifyEvent->SetVelocity(velocityTracker_.GetVelocity());
1884 }
1885 notifyEvent->SetSummary(summaryMap_);
1886 notifyEvent->SetPreviewRect(GetDragWindowRect(point));
1887 }
1888 }
1889
UpdateDragEvent(RefPtr<OHOS::Ace::DragEvent> & event,const OHOS::Ace::DragPointerEvent & pointerEvent)1890 void DragDropManager::UpdateDragEvent(
1891 RefPtr<OHOS::Ace::DragEvent>& event, const OHOS::Ace::DragPointerEvent& pointerEvent)
1892 {
1893 auto point = pointerEvent.GetPoint();
1894 event->SetX(point.GetX());
1895 event->SetY(point.GetY());
1896 event->SetScreenX(point.GetScreenX());
1897 event->SetScreenY(point.GetScreenY());
1898 event->SetDisplayX((double)pointerEvent.GetDisplayX());
1899 event->SetDisplayY((double)pointerEvent.GetDisplayY());
1900 event->SetVelocity(velocityTracker_.GetVelocity());
1901 event->SetSummary(summaryMap_);
1902 event->SetPreviewRect(GetDragWindowRect(point));
1903 event->SetPressedKeyCodes(pointerEvent.pressedKeyCodes);
1904 event->SetSourceTool(pointerEvent.sourceTool);
1905 }
1906
GetExtraInfo()1907 std::string DragDropManager::GetExtraInfo()
1908 {
1909 return extraInfo_;
1910 }
1911
SetExtraInfo(const std::string & extraInfo)1912 void DragDropManager::SetExtraInfo(const std::string& extraInfo)
1913 {
1914 extraInfo_ = extraInfo;
1915 }
1916
ClearExtraInfo()1917 void DragDropManager::ClearExtraInfo()
1918 {
1919 extraInfo_.clear();
1920 }
1921
IsMSDPDragging() const1922 bool DragDropManager::IsMSDPDragging() const
1923 {
1924 ACE_SCOPED_TRACE("drag: get drag state from msdp");
1925 DragState dragState;
1926 InteractionInterface::GetInstance()->GetDragState(dragState);
1927 return dragState == DragState::START;
1928 }
1929
ClearVelocityInfo()1930 void DragDropManager::ClearVelocityInfo()
1931 {
1932 velocityTracker_.Reset();
1933 }
1934
UpdateVelocityTrackerPoint(const Point & point,bool isEnd)1935 void DragDropManager::UpdateVelocityTrackerPoint(const Point& point, bool isEnd)
1936 {
1937 std::chrono::microseconds microseconds(GetMicroTickCount());
1938 TimeStamp curTime(microseconds);
1939 velocityTracker_.UpdateTrackerPoint(point.GetX(), point.GetY(), curTime, isEnd);
1940 }
1941
GetDragPreviewInfo(const RefPtr<OverlayManager> & overlayManager,DragPreviewInfo & dragPreviewInfo,const RefPtr<GestureEventHub> & gestureHub,PreparedInfoForDrag & data)1942 bool DragDropManager::GetDragPreviewInfo(const RefPtr<OverlayManager>& overlayManager, DragPreviewInfo& dragPreviewInfo,
1943 const RefPtr<GestureEventHub>& gestureHub, PreparedInfoForDrag& data)
1944 {
1945 CHECK_NULL_RETURN(overlayManager, false);
1946 if (!overlayManager->GetHasDragPixelMap()) {
1947 return false;
1948 }
1949 auto imageNode = overlayManager->GetDragPixelMapContentNode();
1950 CHECK_NULL_RETURN(imageNode, false);
1951 auto badgeNode = overlayManager->GetDragPixelMapBadgeNode();
1952 if (badgeNode) {
1953 dragPreviewInfo.textNode = badgeNode;
1954 }
1955 CHECK_NULL_RETURN(gestureHub, false);
1956 dragPreviewInfo.isMenuShow = data.isMenuShow;
1957 dragPreviewInfo.dragPreviewRect = data.dragPreviewRect;
1958 auto frameNode = gestureHub->GetFrameNode();
1959 CHECK_NULL_RETURN(frameNode, false);
1960 auto previewOption = imageNode->GetDragPreviewOption();
1961 auto gestureEvent = frameNode->GetOrCreateGestureEventHub();
1962 CHECK_NULL_RETURN(gestureEvent, false);
1963 RectF finalRect = GetFinalDragPreviewRect(imageNode, dragPreviewInfo, overlayManager);
1964 auto width = finalRect.Width();
1965 auto height = finalRect.Height();
1966 auto scaleData = DragDropManager::GetScaleInfo(width, height, gestureEvent->GetTextDraggable());
1967 CHECK_NULL_RETURN(scaleData, false);
1968 dragPreviewInfo.scale =
1969 (imageNode->GetTag() != V2::WEB_ETS_TAG && width > 0 && height > 0 && previewOption.isScaleEnabled)
1970 ? scaleData->scale : 1.0f;
1971 if (!isMouseDragged_ && dragPreviewInfo.scale == 1.0f) {
1972 dragPreviewInfo.scale = TOUCH_DRAG_PIXELMAP_SCALE;
1973 }
1974 // set menu preview scale only for no scale menu preview.
1975 if (isDragWithContextMenu_ && (!previewOption.isScaleEnabled || !scaleData->isNeedScale)) {
1976 auto imageGestureEventHub = imageNode->GetOrCreateGestureEventHub();
1977 if (imageGestureEventHub) {
1978 auto menuPreviewScale = imageGestureEventHub->GetMenuPreviewScale();
1979 dragPreviewInfo.scale =
1980 GreatNotEqual(menuPreviewScale, 0.0f) ? menuPreviewScale : TOUCH_DRAG_PIXELMAP_SCALE;
1981 }
1982 }
1983 dragPreviewInfo.height = static_cast<double>(height);
1984 dragPreviewInfo.width = static_cast<double>(width);
1985 dragPreviewInfo.maxWidth = scaleData->shortSide;
1986 dragPreviewInfo.imageNode = imageNode;
1987 dragPreviewInfo.originOffset = imageNode->GetPositionToWindowWithTransform();
1988 dragPreviewInfo.originScale = imageNode->GetTransformScale();
1989 dragPreviewInfo.menuPreviewNode = data.menuPreviewNode;
1990 dragPreviewInfo.menuPreviewRect = data.menuPreviewRect;
1991 return true;
1992 }
1993
IsNeedDoDragMoveAnimate(const DragPointerEvent & pointerEvent)1994 bool DragDropManager::IsNeedDoDragMoveAnimate(const DragPointerEvent& pointerEvent)
1995 {
1996 if (isDragFwkShow_) {
1997 return false;
1998 }
1999 auto x = pointerEvent.GetPoint().GetX();
2000 auto y = pointerEvent.GetPoint().GetY();
2001 curPointerOffset_ = { x, y };
2002 return true;
2003 }
2004
IsNeedScaleDragPreview()2005 bool DragDropManager::IsNeedScaleDragPreview()
2006 {
2007 return info_.scale > 0 && info_.scale < 1.0f;
2008 }
2009 // calculate the touch position relative to the sub-window which will be used to do animation on,
2010 // the input [x, y] is the position relative to the window which is receiving the touch event,
2011 // and the position is contain the floatTitle offset.
GetTouchOffsetRelativeToSubwindow(int32_t containerId,int32_t x,int32_t y)2012 OffsetF DragDropManager::GetTouchOffsetRelativeToSubwindow(int32_t containerId, int32_t x, int32_t y)
2013 {
2014 auto touchOffset = OffsetF(x, y);
2015 auto pipeline = PipelineContext::GetContextByContainerId(containerId);
2016 CHECK_NULL_RETURN(pipeline, OffsetF(x, y));
2017 auto window = pipeline->GetWindow();
2018 CHECK_NULL_RETURN(window, OffsetF(x, y));
2019 auto windowOffset = window->GetCurrentWindowRect().GetOffset();
2020 touchOffset.SetX(touchOffset.GetX() + windowOffset.GetX());
2021 touchOffset.SetY(touchOffset.GetY() + windowOffset.GetY());
2022 auto subwindow = SubwindowManager::GetInstance()->GetSubwindowByType(containerId >= MIN_SUBCONTAINER_ID ?
2023 SubwindowManager::GetInstance()->GetParentContainerId(containerId) : containerId, SubwindowType::TYPE_MENU);
2024 CHECK_NULL_RETURN(subwindow, OffsetF(x, y));
2025 auto subwindowOffset = subwindow->GetWindowRect().GetOffset();
2026 touchOffset.SetX(touchOffset.GetX() - subwindowOffset.GetX());
2027 touchOffset.SetY(touchOffset.GetY() - subwindowOffset.GetY());
2028 return touchOffset;
2029 }
2030
CalcDragPreviewDistanceWithPoint(const OHOS::Ace::Dimension & preserverHeight,int32_t x,int32_t y,const DragPreviewInfo & info)2031 double DragDropManager::CalcDragPreviewDistanceWithPoint(
2032 const OHOS::Ace::Dimension& preserverHeight, int32_t x, int32_t y, const DragPreviewInfo& info)
2033 {
2034 CHECK_NULL_RETURN(info.imageNode, 0.0);
2035 auto nodeOffset = info.imageNode->GetTransformRelativeOffset();
2036 auto renderContext = info.imageNode->GetRenderContext();
2037 CHECK_NULL_RETURN(renderContext, 0.0);
2038 nodeOffset -= pixelMapOffset_;
2039 auto touchOffset = DragDropManager::GetTouchOffsetRelativeToSubwindow(Container::CurrentId(), x, y);
2040 // calculate distance, so need to pow 2.
2041 return sqrt(pow(nodeOffset.GetX() - touchOffset.GetX(), 2) + pow(nodeOffset.GetY() - touchOffset.GetY(), 2));
2042 }
2043
CalcDragMoveOffset(const OHOS::Ace::Dimension & preserverHeight,int32_t x,int32_t y,const DragPreviewInfo & info)2044 Offset DragDropManager::CalcDragMoveOffset(
2045 const OHOS::Ace::Dimension& preserverHeight, int32_t x, int32_t y, const DragPreviewInfo& info)
2046 {
2047 auto originPoint = info.originOffset;
2048 originPoint.SetX(originPoint.GetX() - pixelMapOffset_.GetX() +
2049 (info.originScale.x - info.scale) * info.width / 2.0f);
2050 originPoint.SetY(originPoint.GetY() - pixelMapOffset_.GetY() +
2051 (info.originScale.y - info.scale) * info.height / 2.0f);
2052 auto touchOffset = DragDropManager::GetTouchOffsetRelativeToSubwindow(Container::CurrentId(), x, y);
2053 Offset newOffset { touchOffset.GetX() - originPoint.GetX(), touchOffset.GetY() - originPoint.GetY() };
2054 return newOffset;
2055 }
2056
CalcContentTrationOffset(const OHOS::Ace::Dimension & preserverHeight,int32_t x,int32_t y,const DragPreviewInfo & info)2057 Offset DragDropManager::CalcContentTrationOffset(
2058 const OHOS::Ace::Dimension& preserverHeight, int32_t x, int32_t y, const DragPreviewInfo& info)
2059 {
2060 auto originPoint = info.originOffset;
2061 auto scalX = info.dragPreviewRect.Width() / info.menuPreviewRect.Width() * info.scale;
2062 originPoint.SetX(originPoint.GetX() - pixelMapOffset_.GetX() + info.menuPreviewRect.Width() * (1 - scalX));
2063 originPoint.SetY(originPoint.GetY() - pixelMapOffset_.GetY());
2064 auto touchOffset = DragDropManager::GetTouchOffsetRelativeToSubwindow(Container::CurrentId(), x, y);
2065 Offset newOffset { touchOffset.GetX() - originPoint.GetX(), touchOffset.GetY() - originPoint.GetY() };
2066 return newOffset;
2067 }
2068
CalculateNewOffset(const RefPtr<FrameNode> & frameNode,const GestureEvent & event,bool isDragStartPending)2069 Offset DragDropManager::CalculateNewOffset(
2070 const RefPtr<FrameNode>& frameNode, const GestureEvent& event, bool isDragStartPending)
2071 {
2072 Offset newOffset = { 0, 0 };
2073 CHECK_NULL_RETURN(frameNode, newOffset);
2074 auto dragMoveLastPoint = GetDragMoveLastPointByCurrentPointer(event.GetPointerId());
2075 if (frameNode->GetDragPreviewOption().sizeChangeEffect == DraggingSizeChangeEffect::DEFAULT || !info_.isMenuShow) {
2076 newOffset = isDragStartPending
2077 ? CalcDragMoveOffset(PRESERVE_HEIGHT, static_cast<int32_t>(dragMoveLastPoint.GetX()),
2078 static_cast<int32_t>(dragMoveLastPoint.GetY()), info_)
2079 : CalcDragMoveOffset(PRESERVE_HEIGHT, static_cast<int32_t>(event.GetGlobalLocation().GetX()),
2080 static_cast<int32_t>(event.GetGlobalLocation().GetY()), info_);
2081 }
2082 if ((frameNode->GetDragPreviewOption().sizeChangeEffect == DraggingSizeChangeEffect::SIZE_TRANSITION ||
2083 frameNode->GetDragPreviewOption().sizeChangeEffect == DraggingSizeChangeEffect::SIZE_CONTENT_TRANSITION) &&
2084 info_.isMenuShow) {
2085 newOffset =
2086 isDragStartPending
2087 ? CalcContentTrationOffset(PRESERVE_HEIGHT, static_cast<int32_t>(dragMoveLastPoint.GetX()),
2088 static_cast<int32_t>(dragMoveLastPoint.GetY()), info_)
2089 : CalcContentTrationOffset(PRESERVE_HEIGHT, static_cast<int32_t>(event.GetGlobalLocation().GetX()),
2090 static_cast<int32_t>(event.GetGlobalLocation().GetY()), info_);
2091 }
2092 return newOffset;
2093 }
2094
UpdateDragMovePositionFinished(bool needDoDragMoveAnimate,bool isMenuShow,const Offset & newOffset,int32_t containerId)2095 bool DragDropManager::UpdateDragMovePositionFinished(
2096 bool needDoDragMoveAnimate, bool isMenuShow, const Offset& newOffset, int32_t containerId)
2097 {
2098 if (!isDragWithContextMenu_) {
2099 return false;
2100 }
2101
2102 CHECK_NULL_RETURN(info_.imageNode, false);
2103 auto renderContext = info_.imageNode->GetRenderContext();
2104 CHECK_NULL_RETURN(renderContext, false);
2105 SubwindowManager::GetInstance()->ContextMenuSwitchDragPreviewAnimation(info_.imageNode,
2106 OffsetF(newOffset.GetX(), newOffset.GetY()));
2107 if (!needDoDragMoveAnimate) {
2108 renderContext->UpdateTransformTranslate({ newOffset.GetX(), newOffset.GetY(), 0.0f });
2109 if (!isMenuShow) {
2110 TransDragWindowToDragFwk(containerId);
2111 }
2112 return true;
2113 }
2114 return false;
2115 }
2116
GetCurrentDistance(float x,float y)2117 float DragDropManager::GetCurrentDistance(float x, float y)
2118 {
2119 auto distance = sqrt(pow(curPointerOffset_.GetX() - x, 2) + pow(curPointerOffset_.GetY() - y, 2));
2120 CHECK_NULL_RETURN(info_.imageNode, distance);
2121 auto containerId = Container::CurrentId();
2122 auto subwindow = SubwindowManager::GetInstance()->GetSubwindowByType(containerId, SubwindowType::TYPE_MENU);
2123 CHECK_NULL_RETURN(subwindow, distance);
2124 auto overlayManager = subwindow->GetOverlayManager();
2125 auto gatherNodeCenter = DragDropFuncWrapper::GetPaintRectCenter(info_.imageNode);
2126 auto gatherDistance = CalcGatherNodeMaxDistanceWithPoint(overlayManager,
2127 gatherNodeCenter.GetX(), gatherNodeCenter.GetY());
2128 return std::max(distance, gatherDistance);
2129 }
2130
DoDragMoveAnimate(const DragPointerEvent & pointerEvent)2131 void DragDropManager::DoDragMoveAnimate(const DragPointerEvent& pointerEvent)
2132 {
2133 bool needDoDragMoveAnimate = IsNeedDoDragMoveAnimate(pointerEvent);
2134 if (!needDoDragMoveAnimate) {
2135 return;
2136 }
2137 isPullMoveReceivedForCurrentDrag_ = true;
2138 CHECK_NULL_VOID(info_.imageNode);
2139 auto containerId = Container::CurrentId();
2140 auto x = pointerEvent.GetDisplayX();
2141 auto y = pointerEvent.GetDisplayY();
2142 if (CheckIsUIExtensionBoundary(x, y, containerId) || CheckIsFolderSubwindowBoundary(x, y, containerId)) {
2143 SetStartAnimation(false);
2144 TransDragWindowToDragFwk(containerId);
2145 return;
2146 }
2147 auto overlayManager = GetDragAnimationOverlayManager(containerId);
2148 CHECK_NULL_VOID(overlayManager);
2149 auto point = pointerEvent.GetPoint();
2150 Offset newOffset = { 0, 0 };
2151 if (info_.imageNode->GetDragPreviewOption().sizeChangeEffect == DraggingSizeChangeEffect::DEFAULT ||
2152 !info_.isMenuShow) {
2153 newOffset = CalcDragMoveOffset(PRESERVE_HEIGHT, point.GetX(), point.GetY(), info_);
2154 }
2155 if ((info_.imageNode->GetDragPreviewOption().sizeChangeEffect == DraggingSizeChangeEffect::SIZE_TRANSITION ||
2156 info_.imageNode->GetDragPreviewOption().sizeChangeEffect ==
2157 DraggingSizeChangeEffect::SIZE_CONTENT_TRANSITION) &&
2158 info_.isMenuShow) {
2159 newOffset = CalcContentTrationOffset(PRESERVE_HEIGHT, point.GetX(), point.GetY(), info_);
2160 }
2161 bool isMenuShow = overlayManager->IsMenuShow();
2162 if (UpdateDragMovePositionFinished(needDoDragMoveAnimate, isMenuShow, newOffset, containerId) ||
2163 !needDoDragMoveAnimate) {
2164 return;
2165 }
2166 DragMoveAnimation(newOffset, overlayManager, point);
2167 }
2168
DragMoveAnimation(const Offset & newOffset,const RefPtr<OverlayManager> & overlayManager,Point point)2169 void DragDropManager::DragMoveAnimation(
2170 const Offset& newOffset, const RefPtr<OverlayManager>& overlayManager, Point point)
2171 {
2172 auto containerId = Container::CurrentId();
2173 bool isMenuShow = overlayManager->IsMenuShow();
2174 AnimationOption option;
2175 auto springResponse =
2176 std::max(DEFAULT_SPRING_RESPONSE - DEL_SPRING_RESPONSE * allAnimationCnt_, MIN_SPRING_RESPONSE);
2177 const RefPtr<Curve> curve = AceType::MakeRefPtr<ResponsiveSpringMotion>(springResponse, 0.99f, 0.0f);
2178 constexpr int32_t animateDuration = 30;
2179 option.SetCurve(curve);
2180 option.SetDuration(animateDuration);
2181 bool dragWithContextMenu = isDragWithContextMenu_;
2182 AddNewDragAnimation();
2183 option.SetOnFinishEvent([weakManager = WeakClaim(this), containerId, dragWithContextMenu, isMenuShow,
2184 x = point.GetX(), y = point.GetY()]() {
2185 auto dragDropManager = weakManager.Upgrade();
2186 CHECK_NULL_VOID(dragDropManager);
2187 if ((dragDropManager->IsAllAnimationFinished() ||
2188 dragDropManager->GetCurrentDistance(x, y) < MAX_DISTANCE_TO_PRE_POINTER) &&
2189 (!dragWithContextMenu || !isMenuShow) && dragDropManager->IsStartAnimationFInished()) {
2190 dragDropManager->SetStartAnimation(false);
2191 dragDropManager->TransDragWindowToDragFwk(containerId);
2192 }
2193 });
2194 auto renderContext = info_.imageNode->GetRenderContext();
2195 CHECK_NULL_VOID(renderContext);
2196 auto offset = OffsetF(point.GetX(), point.GetY());
2197 auto menuWrapperNode = GetMenuWrapperNodeFromDrag();
2198 auto menuPosition = overlayManager->CalculateMenuPosition(menuWrapperNode, offset);
2199 auto menuRenderContext = GetMenuRenderContextFromMenuWrapper(menuWrapperNode);
2200 AnimationUtils::Animate(
2201 option,
2202 [renderContext, localPoint = newOffset, info = info_, overlayManager, menuRenderContext, menuPosition]() {
2203 if (menuRenderContext && !menuPosition.NonOffset()) {
2204 menuRenderContext->UpdatePosition(
2205 OffsetT<Dimension>(Dimension(menuPosition.GetX()), Dimension(menuPosition.GetY())));
2206 }
2207 if (info.imageNode->GetDragPreviewOption().sizeChangeEffect == DraggingSizeChangeEffect::DEFAULT ||
2208 !info.isMenuShow) {
2209 renderContext->UpdateTransformTranslate({ localPoint.GetX(), localPoint.GetY(), 0.0f });
2210 UpdateTextNodePosition(info.textNode, localPoint);
2211 UpdateGatherNodePosition(overlayManager, info.imageNode);
2212 }
2213 },
2214 option.GetOnFinishEvent());
2215 if (info_.imageNode->GetDragPreviewOption().sizeChangeEffect == DraggingSizeChangeEffect::DEFAULT ||
2216 !info_.isMenuShow) {
2217 return;
2218 }
2219 DragDropManager::DragMoveTransitionAnimation(overlayManager, info_, option, newOffset);
2220 }
2221
DragMoveTransitionAnimation(const RefPtr<OverlayManager> & overlayManager,const DragPreviewInfo & info,AnimationOption option,const Offset & newOffset)2222 void DragDropManager::DragMoveTransitionAnimation(const RefPtr<OverlayManager>& overlayManager,
2223 const DragPreviewInfo& info, AnimationOption option, const Offset& newOffset)
2224 {
2225 AddNewDragAnimation();
2226 option.SetCurve(DRAG_TRANSITION_ANIMATION_CURVE);
2227 AnimationUtils::Animate(
2228 option,
2229 [overlayManager, info, newOffset]() {
2230 CHECK_NULL_VOID(overlayManager);
2231 auto relativeContainerNodeRenderContext = info.relativeContainerNode->GetRenderContext();
2232 CHECK_NULL_VOID(relativeContainerNodeRenderContext);
2233 relativeContainerNodeRenderContext->UpdateTransformTranslate({ newOffset.GetX(), newOffset.GetY(), 0.0f });
2234 UpdateGatherNodePosition(overlayManager, info.imageNode);
2235 },
2236 option.GetOnFinishEvent());
2237 }
2238
UpdateDragPreviewScale()2239 void DragDropManager::UpdateDragPreviewScale()
2240 {
2241 CHECK_NULL_VOID(info_.imageNode);
2242 if (IsNeedDisplayInSubwindow()) {
2243 return;
2244 }
2245 auto renderContext = info_.imageNode->GetRenderContext();
2246 CHECK_NULL_VOID(renderContext);
2247 renderContext->UpdateTransformScale({ info_.scale, info_.scale });
2248 }
2249
InitDragAnimationPointerEvent(const GestureEvent & event,bool isDragStartPending)2250 void DragDropManager::InitDragAnimationPointerEvent(const GestureEvent& event, bool isDragStartPending)
2251 {
2252 if (isDragStartPending) {
2253 auto dragMoveLastPoint = GetDragMoveLastPointByCurrentPointer(event.GetPointerId());
2254 dragAnimationPointerEvent_ = DragPointerEvent(dragMoveLastPoint.GetX(),
2255 dragMoveLastPoint.GetY(), dragMoveLastPoint.GetScreenX(), dragMoveLastPoint.GetScreenY());
2256 return;
2257 }
2258 dragAnimationPointerEvent_ = DragPointerEvent(event.GetGlobalLocation().GetX(),
2259 event.GetGlobalLocation().GetY(), event.GetScreenLocation().GetX(), event.GetScreenLocation().GetY());
2260 }
2261
DoDragStartAnimation(const RefPtr<OverlayManager> & overlayManager,const GestureEvent & event,const RefPtr<GestureEventHub> & gestureHub,PreparedInfoForDrag & data)2262 void DragDropManager::DoDragStartAnimation(const RefPtr<OverlayManager>& overlayManager, const GestureEvent& event,
2263 const RefPtr<GestureEventHub>& gestureHub, PreparedInfoForDrag& data)
2264 {
2265 auto containerId = Container::CurrentId();
2266 auto deviceId = static_cast<int32_t>(event.GetDeviceId());
2267 if (deviceId == RESERVED_DEVICEID_1 || deviceId == RESERVED_DEVICEID_2) {
2268 isDragFwkShow_ = false;
2269 TAG_LOGI(AceLogTag::ACE_DRAG, "Do not need animation.");
2270 TransDragWindowToDragFwk(containerId);
2271 return;
2272 }
2273 CHECK_NULL_VOID(overlayManager);
2274 CHECK_NULL_VOID(gestureHub);
2275 bool isDragStartPending = DragDropGlobalController::GetInstance().GetAsyncDragCallback() != nullptr;
2276 if (!(GetDragPreviewInfo(overlayManager, info_, gestureHub, data)) ||
2277 (!IsNeedDisplayInSubwindow() && !data.isMenuShow && !isDragWithContextMenu_ && !isDragStartPending)) {
2278 if (isDragWithContextMenu_) {
2279 UpdateDragPreviewScale();
2280 isDragFwkShow_ = false;
2281 }
2282 return;
2283 }
2284 CHECK_NULL_VOID(info_.imageNode);
2285 isDragFwkShow_ = false;
2286 InitDragAnimationPointerEvent(event, isDragStartPending);
2287 ResetPullMoveReceivedForCurrentDrag();
2288 auto gatherNodeCenter = DragDropFuncWrapper::GetPaintRectCenter(info_.imageNode);
2289 Point point = { static_cast<int32_t>(event.GetGlobalLocation().GetX()),
2290 static_cast<int32_t>(event.GetGlobalLocation().GetY()) };
2291 auto frameNode = gestureHub->GetFrameNode();
2292 Offset newOffset = CalculateNewOffset(frameNode, event, isDragStartPending);
2293 curPointerOffset_ = { newOffset.GetX(), newOffset.GetY() };
2294 currentAnimationCnt_ = 0;
2295 allAnimationCnt_ = 0;
2296 isStartAnimationFinished_ = false;
2297 DragStartAnimation(newOffset, overlayManager, gatherNodeCenter, data, point);
2298 }
2299
DragStartAnimation(const Offset & newOffset,const RefPtr<OverlayManager> & overlayManager,const OffsetF & gatherNodeCenter,PreparedInfoForDrag & data,Point point)2300 void DragDropManager::DragStartAnimation(const Offset& newOffset, const RefPtr<OverlayManager>& overlayManager,
2301 const OffsetF& gatherNodeCenter, PreparedInfoForDrag& data, Point point)
2302 {
2303 CHECK_NULL_VOID(data.imageNode);
2304 auto containerId = Container::CurrentId();
2305 AnimationOption option;
2306 SetDragStartAnimationOption(option, containerId);
2307 AddNewDragStartAnimation();
2308 auto renderContext = info_.imageNode->GetRenderContext();
2309 CHECK_NULL_VOID(renderContext);
2310 auto offset = OffsetF(point.GetX(), point.GetY());
2311 auto menuWrapperNode = GetMenuWrapperNodeFromDrag();
2312 auto menuPosition = overlayManager->CalculateMenuPosition(menuWrapperNode, offset);
2313 auto menuRenderContext = GetMenuRenderContextFromMenuWrapper(menuWrapperNode);
2314 auto callback = [weakManager = WeakClaim(this)](float rate) {
2315 auto dragDropManager = weakManager.Upgrade();
2316 CHECK_NULL_VOID(dragDropManager);
2317 dragDropManager->SetDragStartAnimationRate(rate);
2318 };
2319 auto animateProperty = AceType::MakeRefPtr<NodeAnimatablePropertyFloat>(-1.0, std::move(callback));
2320 CHECK_NULL_VOID(animateProperty);
2321 renderContext->AttachNodeAnimatableProperty(animateProperty);
2322 animateProperty->Set(0.0f);
2323 dragStartAnimationRate_ = 0.0f;
2324 AnimationUtils::Animate(
2325 option,
2326 [data, renderContext, info = info_, newOffset, overlayManager, gatherNodeCenter, menuRenderContext,
2327 menuPosition, animateProperty]() {
2328 CHECK_NULL_VOID(renderContext);
2329 if (menuRenderContext && !menuPosition.NonOffset()) {
2330 menuRenderContext->UpdatePosition(
2331 OffsetT<Dimension>(Dimension(menuPosition.GetX()), Dimension(menuPosition.GetY())));
2332 }
2333 if (data.imageNode->GetDragPreviewOption().sizeChangeEffect == DraggingSizeChangeEffect::DEFAULT ||
2334 !info.isMenuShow) {
2335 renderContext->UpdateTransformScale({ info.scale, info.scale });
2336 renderContext->UpdateTransformTranslate({ newOffset.GetX(), newOffset.GetY(), 0.0f });
2337 UpdateGatherNodePosition(overlayManager, info.imageNode);
2338 UpdateTextNodePosition(info.textNode, newOffset);
2339 }
2340 GatherAnimationInfo gatherAnimationInfo = { info.scale, info.width, info.height, gatherNodeCenter,
2341 renderContext->GetBorderRadius() };
2342 UpdateGatherNodeAttr(overlayManager, gatherAnimationInfo);
2343 if (animateProperty) {
2344 animateProperty->Set(1.0f);
2345 }
2346 },
2347 option.GetOnFinishEvent());
2348 DragStartTransitionAnimation(data, newOffset, info_, option);
2349 }
2350
SetDragStartAnimationOption(AnimationOption & option,int32_t containerId)2351 void DragDropManager::SetDragStartAnimationOption(AnimationOption& option, int32_t containerId)
2352 {
2353 const RefPtr<Curve> curve = AceType::MakeRefPtr<ResponsiveSpringMotion>(0.347f, 0.99f, 0.0f);
2354 constexpr int32_t animateDuration = 300;
2355 option.SetCurve(curve);
2356 option.SetDuration(animateDuration);
2357 option.SetOnFinishEvent([weakManager = WeakClaim(this), containerId]() {
2358 auto dragDropManager = weakManager.Upgrade();
2359 CHECK_NULL_VOID(dragDropManager);
2360 dragDropManager->HandleStartDragAnimationFinish(containerId);
2361 });
2362 }
2363
HandleStartDragAnimationFinish(int32_t containerId)2364 void DragDropManager::HandleStartDragAnimationFinish(int32_t containerId)
2365 {
2366 if (IsAllStartAnimationFinished()) {
2367 SetStartAnimation(true);
2368 }
2369 if (IsPullMoveReceivedForCurrentDrag()) {
2370 TransDragWindowToDragFwk(containerId);
2371 }
2372 auto overlayManager = GetDragAnimationOverlayManager(containerId);
2373 CHECK_NULL_VOID(overlayManager);
2374 auto gatherNode = overlayManager->GetGatherNode();
2375 CHECK_NULL_VOID(gatherNode);
2376 auto info = overlayManager->GetGatherNodeChildrenInfo();
2377 int cnt = 0;
2378 for (auto iter = info.rbegin(); iter != info.rend(); iter++) {
2379 auto imageNode = (*iter).imageNode.Upgrade();
2380 if (cnt > 1) {
2381 gatherNode->RemoveChild(imageNode);
2382 }
2383 cnt++;
2384 }
2385 }
2386
DragStartTransitionAnimation(PreparedInfoForDrag & data,const Offset & newOffset,const DragPreviewInfo & info,AnimationOption option)2387 void DragDropManager::DragStartTransitionAnimation(
2388 PreparedInfoForDrag& data, const Offset& newOffset, const DragPreviewInfo& info, AnimationOption option)
2389 {
2390 CHECK_NULL_VOID(data.imageNode);
2391 if ((data.imageNode->GetDragPreviewOption().sizeChangeEffect == DraggingSizeChangeEffect::SIZE_TRANSITION ||
2392 data.imageNode->GetDragPreviewOption().sizeChangeEffect ==
2393 DraggingSizeChangeEffect::SIZE_CONTENT_TRANSITION) && info_.isMenuShow) {
2394 AddNewDragStartAnimation();
2395 option.SetCurve(DRAG_TRANSITION_ANIMATION_CURVE);
2396 AddNewDragAnimation();
2397 auto callback = [data, relativeContainerNode = data.relativeContainerNode, newOffset, info]() {
2398 auto relativeContainerRenderContext = relativeContainerNode->GetRenderContext();
2399 CHECK_NULL_VOID(relativeContainerRenderContext);
2400 relativeContainerRenderContext->UpdateTransformTranslate({ newOffset.GetX(), newOffset.GetY(), 0.0f });
2401 auto stack = AceType::DynamicCast<FrameNode>(relativeContainerNode->GetChildAtIndex(0));
2402 CHECK_NULL_VOID(stack);
2403 auto stackLayoutProperty = stack->GetLayoutProperty();
2404 CHECK_NULL_VOID(stackLayoutProperty);
2405 stackLayoutProperty->UpdateUserDefinedIdealSize({ CalcLength(info.width * info.scale,
2406 DimensionUnit::PX), CalcLength(info.height * info.scale, DimensionUnit::PX) });
2407 auto stackRenderContext = stack->GetRenderContext();
2408 CHECK_NULL_VOID(stackRenderContext);
2409 if (data.imageNode->GetDragPreviewOption().options.borderRadius.has_value()) {
2410 stackRenderContext->UpdateBorderRadius(
2411 data.imageNode->GetDragPreviewOption().options.borderRadius.value());
2412 } else {
2413 stackRenderContext->UpdateBorderRadius(BorderRadiusProperty(0.0_vp));
2414 }
2415 if (relativeContainerNode->GetDragPreviewOption().sizeChangeEffect ==
2416 DraggingSizeChangeEffect::SIZE_CONTENT_TRANSITION) {
2417 auto stackNode = AceType::DynamicCast<FrameNode>(relativeContainerNode->GetChildByIndex(0));
2418 CHECK_NULL_VOID(stackNode);
2419 auto menuPreviewNode = AceType::DynamicCast<FrameNode>(stack->GetChildAtIndex(1));
2420 CHECK_NULL_VOID(menuPreviewNode);
2421 auto menuPreviewRenderContext = menuPreviewNode->GetRenderContext();
2422 CHECK_NULL_VOID(menuPreviewRenderContext);
2423 menuPreviewRenderContext->UpdateOpacity(0.0f);
2424 CHECK_NULL_VOID(data.imageNode);
2425 auto dragPreviewRenderContext = data.imageNode->GetRenderContext();
2426 CHECK_NULL_VOID(dragPreviewRenderContext);
2427 dragPreviewRenderContext->UpdateOpacity(data.imageNode->GetDragPreviewOption().options.opacity);
2428 }
2429 auto stackContext = stack->GetContext();
2430 CHECK_NULL_VOID(stackContext);
2431 stack->MarkDirtyNode(NG::PROPERTY_UPDATE_MEASURE);
2432 };
2433 auto pipeline = data.relativeContainerNode->GetContext();
2434 CHECK_NULL_VOID(pipeline);
2435 pipeline->Animate(option, option.GetCurve(), callback, option.GetOnFinishEvent());
2436 }
2437 }
2438
NotifyEnterTextEditorArea()2439 void DragDropManager::NotifyEnterTextEditorArea()
2440 {
2441 auto ret = InteractionInterface::GetInstance()->EnterTextEditorArea(true);
2442 if (ret != 0) {
2443 TAG_LOGW(AceLogTag::ACE_DRAG, "Fail to notify entering text editor erea.");
2444 return;
2445 }
2446
2447 hasNotifiedTransformation_ = true;
2448 }
2449
FireOnEditableTextComponent(const RefPtr<FrameNode> & frameNode,DragEventType type)2450 void DragDropManager::FireOnEditableTextComponent(const RefPtr<FrameNode>& frameNode,
2451 DragEventType type)
2452 {
2453 CHECK_NULL_VOID(frameNode);
2454 auto frameTag = frameNode->GetTag();
2455 auto eventHub = frameNode->GetEventHub<EventHub>();
2456 if (!IsEditableTextComponent(frameTag) || !(eventHub && eventHub->IsEnabled()) || !isDragFwkShow_) {
2457 return;
2458 }
2459
2460 // When moving in an editable text component whithout animation, and has not notified msdp yet, notify msdp.
2461 if (type == DragEventType::MOVE && IsEditableTextComponent(frameTag) && isDragFwkShow_ &&
2462 !hasNotifiedTransformation_) {
2463 NotifyEnterTextEditorArea();
2464 return;
2465 }
2466 if (type != DragEventType::ENTER && type != DragEventType::LEAVE) {
2467 TAG_LOGD(AceLogTag::ACE_DRAG, "It is an invalid drag type %{public}d", type);
2468 return;
2469 }
2470
2471 if (type == DragEventType::LEAVE) {
2472 TAG_LOGI(AceLogTag::ACE_DRAG, "The current control has been dragged away.");
2473 hasNotifiedTransformation_ = false;
2474 return;
2475 }
2476
2477 if (hasNotifiedTransformation_) {
2478 TAG_LOGI(AceLogTag::ACE_DRAG, "Coordinates have been transformed.");
2479 return;
2480 }
2481
2482 NotifyEnterTextEditorArea();
2483 }
2484
SetDragResult(const DragNotifyMsgCore & notifyMessage,const RefPtr<OHOS::Ace::DragEvent> & dragEvent)2485 void DragDropManager::SetDragResult(
2486 const DragNotifyMsgCore& notifyMessage, const RefPtr<OHOS::Ace::DragEvent>& dragEvent)
2487 {
2488 DragRet result = DragRet::DRAG_FAIL;
2489 switch (notifyMessage.result) {
2490 case DragRet::DRAG_SUCCESS:
2491 result = DragRet::DRAG_SUCCESS;
2492 break;
2493 case DragRet::DRAG_FAIL:
2494 result = DragRet::DRAG_FAIL;
2495 break;
2496 case DragRet::DRAG_CANCEL:
2497 result = DragRet::DRAG_CANCEL;
2498 break;
2499 default:
2500 break;
2501 }
2502 CHECK_NULL_VOID(dragEvent);
2503 dragEvent->SetResult(result);
2504 }
2505
SetDragBehavior(const DragNotifyMsgCore & notifyMessage,const RefPtr<OHOS::Ace::DragEvent> & dragEvent)2506 void DragDropManager::SetDragBehavior(
2507 const DragNotifyMsgCore& notifyMessage, const RefPtr<OHOS::Ace::DragEvent>& dragEvent)
2508 {
2509 DragBehavior dragBehavior = DragBehavior::UNKNOWN;
2510 switch (notifyMessage.dragBehavior) {
2511 case DragBehavior::COPY:
2512 dragBehavior = DragBehavior::COPY;
2513 break;
2514 case DragBehavior::MOVE:
2515 dragBehavior = DragBehavior::MOVE;
2516 break;
2517 default:
2518 break;
2519 }
2520 CHECK_NULL_VOID(dragEvent);
2521 dragEvent->SetDragBehavior(dragBehavior);
2522 }
2523
UpdateGatherNodeAttr(const RefPtr<OverlayManager> & overlayManager,const GatherAnimationInfo & info)2524 void DragDropManager::UpdateGatherNodeAttr(const RefPtr<OverlayManager>& overlayManager,
2525 const GatherAnimationInfo& info)
2526 {
2527 CHECK_NULL_VOID(overlayManager);
2528 auto gatherNodeChildrenInfo = overlayManager->GetGatherNodeChildrenInfo();
2529 BorderRadiusProperty borderRadius;
2530 if (info.borderRadius.has_value()) {
2531 borderRadius = info.borderRadius.value();
2532 }
2533 borderRadius.multiValued = false;
2534 int32_t cnt = static_cast<int>(gatherNodeChildrenInfo.size());
2535 auto scale = info.scale <= 0.0f ? 1.0f : info.scale;
2536 std::vector<std::pair<float, float>> props(cnt, { 0.0, 0.0 });
2537 if (cnt > 0) {
2538 props[cnt - FIRST_GATHER_PIXEL_MAP] = { FIRST_PIXELMAP_ANGLE, FIRST_PIXELMAP_OPACITY };
2539 }
2540 if (cnt > 1) {
2541 props[cnt - SECOND_GATHER_PIXEL_MAP] = { SECOND_PIXELMAP_ANGLE, SECOND_PIXELMAP_OPACITY };
2542 }
2543 for (int32_t i = 0; i < cnt; ++i) {
2544 auto imageNode = gatherNodeChildrenInfo[i].imageNode.Upgrade();
2545 CHECK_NULL_VOID(imageNode);
2546 auto imageContext = imageNode->GetRenderContext();
2547 CHECK_NULL_VOID(imageContext);
2548 auto& childInfo = gatherNodeChildrenInfo[i];
2549 auto updateScale = scale;
2550 if (((childInfo.width > info.width) || (childInfo.height > info.height)) &&
2551 !NearZero(childInfo.width) && !NearZero(childInfo.height)) {
2552 updateScale *= std::min(info.width / childInfo.width, info.height / childInfo.height);
2553 }
2554 imageContext->UpdateTransformScale({ updateScale, updateScale });
2555 imageContext->UpdateBorderRadius(borderRadius);
2556 imageContext->UpdateOpacity(props[i].second);
2557 Vector5F rotate = Vector5F(0.0f, 0.0f, 1.0f, props[i].first, 0.0f);
2558 imageContext->UpdateTransformRotate(rotate);
2559 }
2560 }
2561
UpdateGatherNodePosition(const RefPtr<OverlayManager> & overlayManager,const RefPtr<FrameNode> & imageNode)2562 void DragDropManager::UpdateGatherNodePosition(const RefPtr<OverlayManager>& overlayManager,
2563 const RefPtr<FrameNode>& imageNode)
2564 {
2565 CHECK_NULL_VOID(imageNode);
2566 CHECK_NULL_VOID(overlayManager);
2567 auto gatherNode = overlayManager->GetGatherNode();
2568 CHECK_NULL_VOID(gatherNode);
2569 auto gatherNodeCenter = DragDropFuncWrapper::GetPaintRectCenterToScreen(imageNode);
2570 gatherNodeCenter -= DragDropFuncWrapper::GetCurrentWindowOffset(gatherNode->GetContextRefPtr());
2571 OffsetF offset;
2572 auto info = overlayManager->GetGatherNodeChildrenInfo();
2573 for (auto iter = info.rbegin(); iter != info.rend(); iter++) {
2574 auto& child = (*iter);
2575 auto imageNode = child.imageNode.Upgrade();
2576 CHECK_NULL_VOID(imageNode);
2577 offset.SetX(gatherNodeCenter.GetX() - child.halfWidth);
2578 offset.SetY(gatherNodeCenter.GetY() - child.halfHeight);
2579 DragDropFuncWrapper::UpdateNodePositionToWindow(imageNode, offset);
2580 }
2581 }
2582
UpdateTextNodePosition(const RefPtr<FrameNode> & textNode,const Offset & localPoint)2583 void DragDropManager::UpdateTextNodePosition(const RefPtr<FrameNode>& textNode, const Offset& localPoint)
2584 {
2585 CHECK_NULL_VOID(textNode);
2586 auto textRenderContext = textNode->GetRenderContext();
2587 CHECK_NULL_VOID(textRenderContext);
2588 textRenderContext->UpdateTransformTranslate({ localPoint.GetX(), localPoint.GetY(), 0.0f });
2589 }
2590
CalcGatherNodeMaxDistanceWithPoint(const RefPtr<OverlayManager> & overlayManager,int32_t x,int32_t y)2591 double DragDropManager::CalcGatherNodeMaxDistanceWithPoint(const RefPtr<OverlayManager>& overlayManager,
2592 int32_t x, int32_t y)
2593 {
2594 CHECK_NULL_RETURN(overlayManager, 0.0f);
2595 auto gatherNodeChildrenInfo = overlayManager->GetGatherNodeChildrenInfo();
2596 double maxDistance = 0.0;
2597 for (const auto& child : gatherNodeChildrenInfo) {
2598 auto imageNode = child.imageNode.Upgrade();
2599 CHECK_NULL_RETURN(imageNode, 0.0f);
2600 auto imageContext = imageNode->GetRenderContext();
2601 CHECK_NULL_RETURN(imageContext, 0.0f);
2602 auto renderPosition = imageContext->GetPropertyOfPosition();
2603 double dis = sqrt(pow(renderPosition.GetX() + child.halfWidth - x, SQUARE_NUMBER) +
2604 pow(renderPosition.GetY() + child.halfHeight - y, SQUARE_NUMBER));
2605 maxDistance = std::max(maxDistance, dis);
2606 }
2607 return maxDistance;
2608 }
2609
IsNeedDisplayInSubwindow()2610 bool DragDropManager::IsNeedDisplayInSubwindow()
2611 {
2612 if (IsNeedScaleDragPreview()) {
2613 return true;
2614 }
2615 auto overlayManager = GetDragAnimationOverlayManager(Container::CurrentId());
2616 CHECK_NULL_RETURN(overlayManager, false);
2617 auto gatherNode = overlayManager->GetGatherNode();
2618 return gatherNode != nullptr;
2619 }
2620
PushGatherPixelMap(const RefPtr<PixelMap> & pixelMap)2621 void DragDropManager::PushGatherPixelMap(const RefPtr<PixelMap>& pixelMap)
2622 {
2623 gatherPixelMaps_.push_back(pixelMap);
2624 }
2625
GetGatherPixelMap(DragDataCore & dragData,float scale,float previewWidth,float previewHeight)2626 void DragDropManager::GetGatherPixelMap(
2627 DragDataCore& dragData, float scale, float previewWidth, float previewHeight)
2628 {
2629 for (const auto& gatherPixelMap : gatherPixelMaps_) {
2630 RefPtr<PixelMap> pixelMapDuplicated = gatherPixelMap;
2631 #if defined(PIXEL_MAP_SUPPORTED)
2632 pixelMapDuplicated = PixelMap::CopyPixelMap(gatherPixelMap);
2633 if (!pixelMapDuplicated) {
2634 TAG_LOGW(AceLogTag::ACE_DRAG, "Copy PixelMap is failure!");
2635 pixelMapDuplicated = gatherPixelMap;
2636 }
2637 #endif
2638 CHECK_NULL_VOID(pixelMapDuplicated);
2639 auto width = pixelMapDuplicated->GetWidth() * scale;
2640 auto height = pixelMapDuplicated->GetHeight() * scale;
2641 auto updateScale = scale;
2642 if (((width > previewWidth) || (height > previewHeight)) && !NearZero(width) && !NearZero(height)) {
2643 updateScale *= std::min(previewWidth / width, previewHeight / height);
2644 }
2645 pixelMapDuplicated->Scale(updateScale, updateScale, AceAntiAliasingOption::HIGH);
2646 dragData.shadowInfos.push_back({pixelMapDuplicated, 0.0f, 0.0f});
2647 }
2648 gatherPixelMaps_.clear();
2649 return;
2650 }
2651
ResetDragDrop(int32_t windowId,const Point & point)2652 void DragDropManager::ResetDragDrop(int32_t windowId, const Point& point)
2653 {
2654 DragDropRet dragDropRet { DragRet::DRAG_FAIL, isMouseDragged_, windowId, DragBehavior::UNKNOWN };
2655 HideDragPreviewOverlay();
2656 ClearVelocityInfo();
2657 ResetDragDropStatus(point, dragDropRet, windowId);
2658 dragCursorStyleCore_ = DragCursorStyleCore::DEFAULT;
2659 }
2660
FireOnDragLeave(const RefPtr<FrameNode> & preTargetFrameNode,const DragPointerEvent & pointerEvent,const std::string & extraInfo)2661 void DragDropManager::FireOnDragLeave(
2662 const RefPtr<FrameNode>& preTargetFrameNode, const DragPointerEvent& pointerEvent, const std::string& extraInfo)
2663 {
2664 auto point = pointerEvent.GetPoint();
2665 if (preTargetFrameNode) {
2666 auto preRect = preTargetFrameNode->GetTransformRectRelativeToWindow();
2667 // If the point is out of the pre node, it means we are totally inside a new node, notify leave anyway
2668 if (!preRect.IsInnerRegion(PointF(static_cast<float>(point.GetX()), static_cast<float>(point.GetY())))) {
2669 FireOnDragEvent(preTargetFrameNode, pointerEvent, DragEventType::LEAVE, extraInfo);
2670 return;
2671 }
2672
2673 // If reach here, it means we are entering one new node's area, but without leaving the area of the pre
2674 // one, this usually happens when moving from parent into its child.
2675 // Check the configuration to decide the notify to parent node.
2676 if (eventStrictReportingEnabled_) {
2677 FireOnDragEvent(preTargetFrameNode_, pointerEvent, DragEventType::LEAVE, extraInfo);
2678 }
2679 }
2680 }
2681
IsUIExtensionShowPlaceholder(const RefPtr<NG::UINode> & node)2682 bool DragDropManager::IsUIExtensionShowPlaceholder(const RefPtr<NG::UINode>& node)
2683 {
2684 #ifdef WINDOW_SCENE_SUPPORTED
2685 CHECK_NULL_RETURN(node, true);
2686 auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
2687 CHECK_NULL_RETURN(pipeline, true);
2688 auto manager = pipeline->GetUIExtensionManager();
2689 CHECK_NULL_RETURN(manager, true);
2690 return manager->IsShowPlaceholder(node->GetId());
2691 #endif
2692 return true;
2693 }
2694
UpdateDragMovePosition(const NG::OffsetF & offset,bool isRedragStart)2695 void DragDropManager::UpdateDragMovePosition(const NG::OffsetF& offset, bool isRedragStart)
2696 {
2697 if (isRedragStart) {
2698 ResetContextMenuRedragPosition();
2699 }
2700 lastDragMovePosition_ = dragMovePosition_;
2701 dragMovePosition_ = offset;
2702 if (lastDragMovePosition_.NonOffset()) {
2703 return;
2704 }
2705 dragTotalMovePosition_ += (dragMovePosition_ - lastDragMovePosition_);
2706 }
2707
IsUIExtensionComponent(const RefPtr<NG::UINode> & node)2708 bool DragDropManager::IsUIExtensionComponent(const RefPtr<NG::UINode>& node)
2709 {
2710 CHECK_NULL_RETURN(node, false);
2711 return (V2::UI_EXTENSION_COMPONENT_ETS_TAG == node->GetTag() || V2::EMBEDDED_COMPONENT_ETS_TAG == node->GetTag()) &&
2712 (!IsUIExtensionShowPlaceholder(node));
2713 }
2714
HandleUIExtensionDragEvent(const RefPtr<FrameNode> & frameNode,const DragPointerEvent & pointerEvent,DragEventType type)2715 void DragDropManager::HandleUIExtensionDragEvent(
2716 const RefPtr<FrameNode>& frameNode, const DragPointerEvent& pointerEvent, DragEventType type)
2717 {
2718 CHECK_NULL_VOID(frameNode);
2719 auto pattern = frameNode->GetPattern<Pattern>();
2720 CHECK_NULL_VOID(pattern);
2721
2722 auto dragEvent = pointerEvent;
2723 if (type == DragEventType::ENTER) {
2724 dragEvent.action = PointerAction::PULL_IN_WINDOW;
2725 } else if (type == DragEventType::LEAVE) {
2726 dragEvent.action = PointerAction::PULL_OUT_WINDOW;
2727 } else if (type == DragEventType::PULL_CANCEL) {
2728 dragEvent.action = PointerAction::PULL_CANCEL;
2729 }
2730 pattern->HandleDragEvent(dragEvent);
2731 }
2732
GetMenuPreviewRect()2733 RectF DragDropManager::GetMenuPreviewRect()
2734 {
2735 auto pipelineContext = PipelineContext::GetCurrentContextSafelyWithCheck();
2736 CHECK_NULL_RETURN(pipelineContext, RectF());
2737 auto dragDropManager = pipelineContext->GetDragDropManager();
2738 CHECK_NULL_RETURN(dragDropManager, RectF());
2739 auto menuWrapperNode = dragDropManager->GetMenuWrapperNode();
2740 CHECK_NULL_RETURN(menuWrapperNode, RectF());
2741 auto menuWrapperPattern = menuWrapperNode->GetPattern<MenuWrapperPattern>();
2742 CHECK_NULL_RETURN(menuWrapperPattern, RectF());
2743 auto menuPreview = menuWrapperPattern->GetPreview();
2744 CHECK_NULL_RETURN(menuPreview, RectF());
2745 auto previewPaintRect = DragDropFuncWrapper::GetPaintRectToScreen(menuPreview);
2746 previewPaintRect -= DragDropFuncWrapper::GetCurrentWindowOffset(pipelineContext);
2747 return previewPaintRect;
2748 }
2749
GetMaxWidthBaseOnGridSystem(const RefPtr<PipelineBase> & pipeline)2750 double DragDropManager::GetMaxWidthBaseOnGridSystem(const RefPtr<PipelineBase>& pipeline)
2751 {
2752 auto context = DynamicCast<NG::PipelineContext>(pipeline);
2753 CHECK_NULL_RETURN(context, -1.0f);
2754 auto dragDropMgr = context->GetDragDropManager();
2755 CHECK_NULL_RETURN(dragDropMgr, -1.0f);
2756 auto& columnInfo = dragDropMgr->columnInfo_;
2757 if (!columnInfo) {
2758 columnInfo = GridSystemManager::GetInstance().GetInfoByType(GridColumnType::DRAG_PANEL);
2759 auto gridContainer = columnInfo->GetParent();
2760 if (gridContainer) {
2761 auto rootWidth = context->GetRootWidth();
2762 if (LessOrEqual(rootWidth, 0.0)) {
2763 auto mainPipeline = PipelineContext::GetMainPipelineContext();
2764 rootWidth = GridSystemManager::GetInstance().GetScreenWidth(mainPipeline);
2765 }
2766 // cannot handle multi-screen
2767 gridContainer->BuildColumnWidth(rootWidth);
2768 }
2769 dragDropMgr->columnInfo_ = columnInfo;
2770 }
2771
2772 auto gridSizeType = GridSystemManager::GetInstance().GetCurrentSize();
2773 if (gridSizeType > GridSizeType::LG) {
2774 gridSizeType = GridSizeType::LG;
2775 }
2776 if (gridSizeType < GridSizeType::SM) {
2777 gridSizeType = GridSizeType::SM;
2778 }
2779 auto columns = columnInfo->GetColumns(gridSizeType);
2780 double maxWidth = columnInfo->GetWidth(columns);
2781 return maxWidth;
2782 }
2783
GetScaleInfo(float width,float height,bool textDraggable)2784 std::shared_ptr<ScaleDataInfo> DragDropManager::GetScaleInfo(float width, float height, bool textDraggable)
2785 {
2786 auto scaleDataInfo = std::make_shared<ScaleDataInfo>();
2787 CHECK_NULL_RETURN(scaleDataInfo, nullptr);
2788 scaleDataInfo->shortSide = fmin(SystemProperties::GetDeviceHeight(), SystemProperties::GetDeviceWidth());
2789 auto shortSide = PipelineBase::Px2VpWithCurrentDensity(scaleDataInfo->shortSide);
2790 if (shortSide <= DEVICE_TYPE_UNKOWN) {
2791 return scaleDataInfo;
2792 } else if (shortSide <= DEVICE_TYPE_SMALL) {
2793 scaleDataInfo = DragDropManager::CalculateScale(width, height,
2794 textDraggable ? scaleDataInfo->shortSide : scaleDataInfo->shortSide / SCALE_TYPE_FIRST,
2795 scaleDataInfo->shortSide / SCALE_TYPE_FIRST);
2796 } else if (shortSide <= DEVICE_TYPE_MEDIUM) {
2797 scaleDataInfo = CalculateScale(width, height,
2798 textDraggable ? scaleDataInfo->shortSide / SCALE_TYPE_FIRST : scaleDataInfo->shortSide / SCALE_TYPE_THIRD,
2799 scaleDataInfo->shortSide / SCALE_TYPE_THIRD);
2800 } else {
2801 scaleDataInfo = CalculateScale(width, height,
2802 textDraggable ? scaleDataInfo->shortSide * SCALE_TYPE_FIRST / SCALE_TYPE_SECOND
2803 : scaleDataInfo->shortSide / SCALE_TYPE_SECOND,
2804 scaleDataInfo->shortSide / SCALE_TYPE_SECOND);
2805 }
2806 return scaleDataInfo;
2807 }
2808
CalculateScale(float width,float height,float widthLimit,float heightLimit)2809 std::shared_ptr<ScaleDataInfo> DragDropManager::CalculateScale(
2810 float width, float height, float widthLimit, float heightLimit)
2811 {
2812 auto scaleDataInfo = std::make_shared<ScaleDataInfo>();
2813 CHECK_NULL_RETURN(scaleDataInfo, nullptr);
2814 if ((width > 0 && height > 0) && (width > widthLimit || height > heightLimit)) {
2815 scaleDataInfo->scale = fmin(widthLimit / width, heightLimit / height);
2816 scaleDataInfo->isNeedScale = true;
2817 }
2818 return scaleDataInfo;
2819 }
2820
GetDragAnimationOverlayManager(int32_t containerId)2821 const RefPtr<NG::OverlayManager> DragDropManager::GetDragAnimationOverlayManager(int32_t containerId)
2822 {
2823 auto subwindow = SubwindowManager::GetInstance()->GetSubwindowByType(containerId >= MIN_SUBCONTAINER_ID ?
2824 SubwindowManager::GetInstance()->GetParentContainerId(containerId) : containerId, SubwindowType::TYPE_MENU);
2825 CHECK_NULL_RETURN(subwindow, nullptr);
2826 return subwindow->GetOverlayManager();
2827 }
2828
RemoveDragFrameNode(int32_t id)2829 void DragDropManager::RemoveDragFrameNode(int32_t id)
2830 {
2831 dragFrameNodes_.erase(id);
2832 gridDragFrameNodes_.erase(id);
2833 listDragFrameNodes_.erase(id);
2834 textFieldDragFrameNodes_.erase(id);
2835 }
2836
SetIsDragged(bool isDragged)2837 void DragDropManager::SetIsDragged(bool isDragged)
2838 {
2839 if (isDragged && isDragged_ != isDragged && notifyInDraggedCallback_) {
2840 notifyInDraggedCallback_();
2841 }
2842 isDragged_ = isDragged;
2843 }
2844
RegisterDragStatusListener(int32_t nodeId,const WeakPtr<FrameNode> & node)2845 void DragDropManager::RegisterDragStatusListener(int32_t nodeId, const WeakPtr<FrameNode>& node)
2846 {
2847 auto ret = nodesForDragNotify_.try_emplace(nodeId, node);
2848 if (!ret.second) {
2849 nodesForDragNotify_[nodeId] = node;
2850 }
2851 }
2852
RegisterPullEventListener(int32_t uniqueIdentify,std::function<void (const DragPointerEvent &)> callback)2853 void DragDropManager::RegisterPullEventListener(
2854 int32_t uniqueIdentify, std::function<void(const DragPointerEvent&)> callback)
2855 {
2856 pullEventListener_[uniqueIdentify] = callback;
2857 }
2858
UnRegisterPullEventListener(int32_t uniqueIdentify)2859 void DragDropManager::UnRegisterPullEventListener(int32_t uniqueIdentify)
2860 {
2861 auto it = pullEventListener_.find(uniqueIdentify);
2862 if (it != pullEventListener_.end()) {
2863 pullEventListener_.erase(it);
2864 }
2865 }
2866
NotifyPullEventListener(const DragPointerEvent & pointerEvent)2867 void DragDropManager::NotifyPullEventListener(const DragPointerEvent& pointerEvent)
2868 {
2869 if (pullEventListener_.empty()) {
2870 return;
2871 }
2872 for (const auto& pair : pullEventListener_) {
2873 if (pair.second) {
2874 pair.second(pointerEvent);
2875 }
2876 }
2877 }
2878
IsDraggingPressed(int32_t currentPointerId) const2879 bool DragDropManager::IsDraggingPressed(int32_t currentPointerId) const
2880 {
2881 if (currentPointerId_ == currentPointerId) {
2882 return draggingPressedState_;
2883 }
2884 return false;
2885 }
2886
ResetContextMenuDragPosition()2887 void DragDropManager::ResetContextMenuDragPosition()
2888 {
2889 dragMovePosition_.Reset();
2890 lastDragMovePosition_.Reset();
2891 dragTotalMovePosition_.Reset();
2892 }
2893
ResetContextMenuRedragPosition()2894 void DragDropManager::ResetContextMenuRedragPosition()
2895 {
2896 dragMovePosition_.Reset();
2897 lastDragMovePosition_.Reset();
2898 }
2899
AddNewDragAnimation()2900 void DragDropManager::AddNewDragAnimation()
2901 {
2902 currentAnimationCnt_++;
2903 allAnimationCnt_++;
2904 }
2905
AddNewDragStartAnimation()2906 void DragDropManager::AddNewDragStartAnimation()
2907 {
2908 currentStartAnimationCnt_++;
2909 allStartAnimationCnt_++;
2910 }
2911
IsAllAnimationFinished()2912 bool DragDropManager::IsAllAnimationFinished()
2913 {
2914 currentAnimationCnt_--;
2915 return currentAnimationCnt_ == 0;
2916 }
2917
IsAllStartAnimationFinished()2918 bool DragDropManager::IsAllStartAnimationFinished()
2919 {
2920 currentStartAnimationCnt_--;
2921 return currentStartAnimationCnt_ == 0;
2922 }
2923
CheckIsNewDrag(const DragPointerEvent & pointerEvent) const2924 bool DragDropManager::CheckIsNewDrag(const DragPointerEvent& pointerEvent) const
2925 {
2926 return (pointerEvent.pullId != -1) && (pointerEvent.pullId != currentPullId_);
2927 }
2928
RequireSummaryIfNecessary(const DragPointerEvent & pointerEvent)2929 void DragDropManager::RequireSummaryIfNecessary(const DragPointerEvent& pointerEvent)
2930 {
2931 if (CheckIsNewDrag(pointerEvent)) {
2932 currentPullId_ = pointerEvent.pullId;
2933 RequireSummary();
2934 }
2935 }
2936
IsAnyDraggableHit(const RefPtr<PipelineBase> & pipeline,int32_t pointId)2937 bool DragDropManager::IsAnyDraggableHit(const RefPtr<PipelineBase>& pipeline, int32_t pointId)
2938 {
2939 if (isAnyDraggableHit_) {
2940 return true;
2941 }
2942
2943 auto pipelineContext = AceType::DynamicCast<PipelineContext>(pipeline);
2944 CHECK_NULL_RETURN(pipelineContext, false);
2945 auto eventManager = pipelineContext->GetEventManager();
2946 CHECK_NULL_RETURN(eventManager, false);
2947 auto touchTestResults = eventManager->touchTestResults_;
2948 const auto iter = touchTestResults.find(pointId);
2949 if (iter == touchTestResults.end() || iter->second.empty()) {
2950 TAG_LOGI(AceLogTag::ACE_DRAG, "touch test result is empty.");
2951 return false;
2952 }
2953 for (const auto& touchTestResult : iter->second) {
2954 auto recognizer = AceType::DynamicCast<NG::NGGestureRecognizer>(touchTestResult);
2955 if (recognizer) {
2956 continue;
2957 }
2958 auto node = touchTestResult->GetAttachedNode().Upgrade();
2959 CHECK_NULL_RETURN(node, false);
2960 if (IsUIExtensionComponent(node)) {
2961 return true;
2962 }
2963 }
2964 return false;
2965 }
2966
CancelUDMFDataLoading(const std::string & key)2967 int32_t DragDropManager::CancelUDMFDataLoading(const std::string& key)
2968 {
2969 return UdmfClient::GetInstance()->Cancel(key);
2970 }
2971
CheckIsFolderSubwindowBoundary(float x,float y,int32_t instanceId)2972 bool DragDropManager::CheckIsFolderSubwindowBoundary(float x, float y, int32_t instanceId)
2973 {
2974 if (!SystemProperties::IsSuperFoldDisplayDevice() || NearZero(info_.scale)) {
2975 return false;
2976 }
2977 auto mainContainerId = instanceId >= MIN_SUBCONTAINER_ID ?
2978 SubwindowManager::GetInstance()->GetParentContainerId(instanceId) : instanceId;
2979 auto container = Container::GetContainer(mainContainerId);
2980 CHECK_NULL_RETURN(container, false);
2981 if (container->GetCurrentFoldStatus() == FoldStatus::EXPAND) {
2982 return false;
2983 }
2984 auto isCrossWindow = container->IsCrossAxisWindow();
2985 auto isScenceBoard = container->IsScenceBoardWindow();
2986 if (isCrossWindow || isScenceBoard) {
2987 return false;
2988 }
2989 auto subwindow = SubwindowManager::GetInstance()->GetCurrentWindow();
2990 CHECK_NULL_RETURN(subwindow, false);
2991 auto rect = subwindow->GetWindowRect();
2992 auto scale = dragStartAnimationRate_ * (info_.scale - info_.originScale.y) + info_.originScale.y;
2993 OffsetF pixelMapOffset = pixelMapOffset_ / info_.scale * scale;
2994 float top = y + pixelMapOffset.GetY();
2995 float bottom = y + pixelMapOffset.GetY() + info_.height * scale;
2996 float distance = std::min(top - rect.Top(), rect.Bottom() - bottom);
2997 return distance < MIN_FOLDER_SUBWINDOW_BOUNDARY_DISTANCE;
2998 }
2999
CheckIsUIExtensionBoundary(float x,float y,int32_t instanceId)3000 bool DragDropManager::CheckIsUIExtensionBoundary(float x, float y, int32_t instanceId)
3001 {
3002 auto container = Container::GetContainer(instanceId);
3003 CHECK_NULL_RETURN(container, false);
3004 if (!container->IsUIExtensionWindow()) {
3005 return false;
3006 }
3007 auto pipeline = container->GetPipelineContext();
3008 CHECK_NULL_RETURN(pipeline, false);
3009 auto rect = pipeline->GetCurrentWindowRect();
3010 auto distance = std::min(std::min(x - rect.Left(), rect.Right() - x),
3011 std::min(y - rect.Top(), rect.Bottom() - y));
3012 return distance < MIN_UI_EXTENSION_BOUNDARY_DISTANCE;
3013 }
3014
GetFinalDragPreviewRect(const RefPtr<FrameNode> & imageNode,DragPreviewInfo & dragPreviewInfo,const RefPtr<OverlayManager> & overlayManager)3015 RectF DragDropManager::GetFinalDragPreviewRect(const RefPtr<FrameNode>& imageNode,
3016 DragPreviewInfo& dragPreviewInfo, const RefPtr<OverlayManager>& overlayManager)
3017 {
3018 RectF finalRect;
3019 CHECK_NULL_RETURN(overlayManager, finalRect);
3020 CHECK_NULL_RETURN(imageNode, finalRect);
3021 auto dragPreviewOption = imageNode->GetDragPreviewOption();
3022 if (dragPreviewOption.sizeChangeEffect == DraggingSizeChangeEffect::DEFAULT || !dragPreviewInfo.isMenuShow) {
3023 finalRect = imageNode->GetGeometryNode()->GetFrameRect();
3024 } else if ((dragPreviewOption.sizeChangeEffect == DraggingSizeChangeEffect::SIZE_TRANSITION ||
3025 dragPreviewOption.sizeChangeEffect == DraggingSizeChangeEffect::SIZE_CONTENT_TRANSITION) &&
3026 dragPreviewInfo.isMenuShow) {
3027 auto relativeContainerNode = overlayManager->GetRelativeContainerNode();
3028 CHECK_NULL_RETURN(relativeContainerNode, finalRect);
3029 dragPreviewInfo.relativeContainerNode = relativeContainerNode;
3030 finalRect = info_.dragPreviewRect;
3031 }
3032 return finalRect;
3033 }
3034 } // namespace OHOS::Ace::NG
3035