1 /*
2 * Copyright (c) 2022-2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "core/components_ng/manager/drag_drop/drag_drop_manager.h"
17
18 #include "base/geometry/ng/offset_t.h"
19 #include "base/geometry/point.h"
20 #include "base/utils/utils.h"
21 #include "core/components_ng/pattern/grid/grid_event_hub.h"
22 #include "core/components_ng/pattern/list/list_event_hub.h"
23 #include "core/components_ng/pattern/root/root_pattern.h"
24 #include "core/components_ng/pattern/text_field/text_field_pattern.h"
25 #include "core/components_v2/inspector/inspector_constants.h"
26 #include "core/pipeline_ng/pipeline_context.h"
27 #include "base/utils/time_util.h"
28
29 #ifdef ENABLE_DRAG_FRAMEWORK
30 #include "base/geometry/rect.h"
31 #include "base/msdp/device_status/interfaces/innerkits/interaction/include/interaction_manager.h"
32 #include "core/common/udmf/udmf_client.h"
33 #endif // ENABLE_DRAG_FRAMEWORK
34
35 namespace OHOS::Ace::NG {
36 #ifdef ENABLE_DRAG_FRAMEWORK
37 using namespace Msdp::DeviceStatus;
38 #endif // ENABLE_DRAG_FRAMEWORK
39 namespace {
40 int64_t g_proxyId = 0;
41 #ifdef ENABLE_DRAG_FRAMEWORK
42 constexpr float PIXELMAP_POSITION_WIDTH = 0.5f;
43 constexpr float PIXELMAP_POSITION_HEIGHT = 0.2f;
44 #endif // ENABLE_DRAG_FRAMEWORK
45 } // namespace
46
CreateAndShowDragWindow(const RefPtr<PixelMap> & pixelMap,const GestureEvent & info)47 RefPtr<DragDropProxy> DragDropManager::CreateAndShowDragWindow(
48 const RefPtr<PixelMap>& pixelMap, const GestureEvent& info)
49 {
50 CHECK_NULL_RETURN(pixelMap, nullptr);
51 SetIsDragged(true);
52 isDragCancel_ = false;
53 #if !defined(PREVIEW)
54 if (dragWindow_) {
55 LOGW("CreateAndShowDragWindow: There is a drag window, create drag window failed.");
56 return nullptr;
57 }
58
59 CreateDragWindow(info, pixelMap->GetWidth(), pixelMap->GetHeight());
60 if (!dragWindow_) {
61 return nullptr;
62 }
63 dragWindow_->DrawPixelMap(pixelMap);
64 #endif
65 currentId_ = ++g_proxyId;
66 return MakeRefPtr<DragDropProxy>(currentId_);
67 }
68
CreateAndShowDragWindow(const RefPtr<UINode> & customNode,const GestureEvent & info)69 RefPtr<DragDropProxy> DragDropManager::CreateAndShowDragWindow(
70 const RefPtr<UINode>& customNode, const GestureEvent& info)
71 {
72 dragWindowRootNode_ = CreateDragRootNode(customNode);
73 CHECK_NULL_RETURN(dragWindowRootNode_, nullptr);
74 SetIsDragged(true);
75 isDragCancel_ = false;
76 #if !defined(PREVIEW)
77 if (dragWindow_) {
78 LOGW("CreateAndShowDragWindow: There is a drag window, create drag window failed.");
79 return nullptr;
80 }
81
82 auto geometryNode = dragWindowRootNode_->GetGeometryNode();
83 CHECK_NULL_RETURN(geometryNode, nullptr);
84
85 auto frameRect = geometryNode->GetFrameSize();
86 CreateDragWindow(info, static_cast<uint32_t>(frameRect.Width()), static_cast<uint32_t>(frameRect.Height()));
87 if (!dragWindow_) {
88 return nullptr;
89 }
90 dragWindow_->DrawFrameNode(dragWindowRootNode_);
91 #endif
92 currentId_ = ++g_proxyId;
93 return MakeRefPtr<DragDropProxy>(currentId_);
94 }
95
CreateTextDragDropProxy()96 RefPtr<DragDropProxy> DragDropManager::CreateTextDragDropProxy()
97 {
98 SetIsDragged(true);
99 isDragCancel_ = false;
100 currentId_ = ++g_proxyId;
101 return MakeRefPtr<DragDropProxy>(currentId_);
102 }
103
CreateDragWindow(const GestureEvent & info,uint32_t width,uint32_t height)104 void DragDropManager::CreateDragWindow(const GestureEvent& info, uint32_t width, uint32_t height)
105 {
106 LOGI("CreateDragWindow");
107 #if !defined(PREVIEW)
108 auto pipeline = PipelineContext::GetCurrentContext();
109 CHECK_NULL_VOID(pipeline);
110 auto rect = pipeline->GetCurrentWindowRect();
111 dragWindow_ = DragWindow::CreateDragWindow("APP_DRAG_WINDOW",
112 static_cast<int32_t>(info.GetGlobalPoint().GetX()) + rect.Left(),
113 static_cast<int32_t>(info.GetGlobalPoint().GetY()) + rect.Top(), width, height);
114 if (dragWindow_) {
115 dragWindow_->SetOffset(rect.Left(), rect.Top());
116 } else {
117 LOGE("dragWindow create failed!");
118 }
119 #endif
120 }
121
CreateDragRootNode(const RefPtr<UINode> & customNode)122 RefPtr<FrameNode> DragDropManager::CreateDragRootNode(const RefPtr<UINode>& customNode)
123 {
124 auto pipeline = PipelineContext::GetCurrentContext();
125 CHECK_NULL_RETURN(pipeline, nullptr);
126
127 auto rootNode = FrameNode::CreateFrameNodeWithTree(
128 V2::ROOT_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), MakeRefPtr<RootPattern>());
129 rootNode->SetActive(true);
130 rootNode->SetHostRootId(pipeline->GetInstanceId());
131 rootNode->SetHostPageId(-1);
132 rootNode->AddChild(customNode);
133 rootNode->AttachToMainTree();
134 rootNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
135 pipeline->FlushUITasks();
136 return rootNode;
137 }
138
UpdateDragWindowPosition(int32_t globalX,int32_t globalY)139 void DragDropManager::UpdateDragWindowPosition(int32_t globalX, int32_t globalY)
140 {
141 #if !defined(PREVIEW)
142 CHECK_NULL_VOID(dragWindow_);
143 dragWindow_->MoveTo(globalX, globalY);
144 #endif
145 }
146
147 #ifdef ENABLE_DRAG_FRAMEWORK
UpdatePixelMapPosition(int32_t globalX,int32_t globalY)148 void DragDropManager::UpdatePixelMapPosition(int32_t globalX, int32_t globalY)
149 {
150 auto pipeline = NG::PipelineContext::GetCurrentContext();
151 CHECK_NULL_VOID(pipeline);
152 auto manager = pipeline->GetOverlayManager();
153 CHECK_NULL_VOID(manager);
154 auto rootNode = pipeline->GetRootElement();
155 CHECK_NULL_VOID(rootNode);
156 if (manager->GetHasPixelMap()) {
157 auto columnNode = AceType::DynamicCast<NG::FrameNode>(rootNode->GetLastChild());
158 CHECK_NULL_VOID(columnNode);
159 auto imageNode = AceType::DynamicCast<NG::FrameNode>(columnNode->GetLastChild());
160 CHECK_NULL_VOID(imageNode);
161 auto geometryNode = imageNode->GetGeometryNode();
162 CHECK_NULL_VOID(geometryNode);
163 auto width = geometryNode->GetFrameSize().Width();
164 auto height = geometryNode->GetFrameSize().Height();
165 auto imageContext = imageNode->GetRenderContext();
166 CHECK_NULL_VOID(imageContext);
167 CHECK_NULL_VOID(draggedFrameNode_);
168 auto hub = draggedFrameNode_->GetOrCreateGestureEventHub();
169 CHECK_NULL_VOID(hub);
170 if (!hub->GetTextDraggable()) {
171 hub = columnNode->GetOrCreateGestureEventHub();
172 CHECK_NULL_VOID(hub);
173 }
174 RefPtr<PixelMap> pixelMap = hub->GetPixelMap();
175 CHECK_NULL_VOID(pixelMap);
176 float scale = NearZero(width) ? 1.0f : pixelMap->GetWidth() / width;
177 imageContext->UpdatePosition(NG::OffsetT<Dimension>(
178 Dimension(globalX - width * PIXELMAP_POSITION_WIDTH * scale - width / 2.0f + width * scale / 2.0f),
179 Dimension(globalY - height * PIXELMAP_POSITION_HEIGHT * scale - height / 2.0f + height * scale / 2.0f)));
180 imageContext->OnModifyDone();
181 }
182 }
183 #endif // ENABLE_DRAG_FRAMEWORK
184
FindTargetInChildNodes(const RefPtr<UINode> parentNode,std::vector<RefPtr<FrameNode>> hitFrameNodes,bool findDrop)185 RefPtr<FrameNode> DragDropManager::FindTargetInChildNodes(
186 const RefPtr<UINode> parentNode, std::vector<RefPtr<FrameNode>> hitFrameNodes, bool findDrop)
187 {
188 CHECK_NULL_RETURN(parentNode, nullptr);
189 auto parentFrameNode = AceType::DynamicCast<FrameNode>(parentNode);
190 if (parentFrameNode && (!parentFrameNode->IsActive() || !parentFrameNode->IsVisible())) {
191 return nullptr;
192 }
193 auto children = parentNode->GetChildren();
194
195 for (auto iter = children.rbegin(); iter != children.rend(); iter++) {
196 auto child = *iter;
197 if (child == nullptr) {
198 LOGW("when findding target in child nodes, find child is nullptr");
199 continue;
200 }
201 auto childFindResult = FindTargetInChildNodes(child, hitFrameNodes, findDrop);
202 if (childFindResult) {
203 return childFindResult;
204 }
205 }
206
207 CHECK_NULL_RETURN_NOLOG(parentFrameNode, nullptr);
208 for (auto iter : hitFrameNodes) {
209 if (parentFrameNode == iter) {
210 auto eventHub = parentFrameNode->GetEventHub<EventHub>();
211 if (!eventHub) {
212 continue;
213 }
214 if ((findDrop && (eventHub->HasOnDrop() || eventHub->HasOnItemDrop()))
215 || (!findDrop && (eventHub->HasOnDrop() || eventHub->HasOnItemDrop()))) {
216 return parentFrameNode;
217 }
218 if (SystemProperties::GetDebugEnabled()) {
219 LOGW("Iter is in hitFrameNodes, but findDrop not suit with bind function.");
220 }
221 }
222 }
223 return nullptr;
224 }
225
FindDragFrameNodeByPosition(float globalX,float globalY,DragType dragType,bool findDrop)226 RefPtr<FrameNode> DragDropManager::FindDragFrameNodeByPosition(
227 float globalX, float globalY, DragType dragType, bool findDrop)
228 {
229 std::map<int32_t, WeakPtr<FrameNode>> frameNodes;
230 switch (dragType) {
231 case DragType::COMMON:
232 frameNodes = dragFrameNodes_;
233 break;
234 case DragType::GRID:
235 frameNodes = gridDragFrameNodes_;
236 break;
237 case DragType::LIST:
238 frameNodes = listDragFrameNodes_;
239 break;
240 case DragType::TEXT:
241 frameNodes = textFieldDragFrameNodes_;
242 break;
243 default:
244 break;
245 }
246
247 if (frameNodes.empty()) {
248 if (SystemProperties::GetDebugEnabled()) {
249 LOGW("FrameNodes which have onDragMove or onDrop set is empty, cannot find targetNode.");
250 }
251 return nullptr;
252 }
253
254 PointF point(globalX, globalY);
255 std::vector<RefPtr<FrameNode>> hitFrameNodes;
256 for (auto iterOfFrameNode = frameNodes.begin(); iterOfFrameNode != frameNodes.end(); iterOfFrameNode++) {
257 auto frameNode = iterOfFrameNode->second.Upgrade();
258 if (!frameNode || !frameNode->IsVisible()) {
259 continue;
260 }
261 auto geometryNode = frameNode->GetGeometryNode();
262 if (!geometryNode) {
263 continue;
264 }
265 auto globalFrameRect = geometryNode->GetFrameRect();
266 globalFrameRect.SetOffset(frameNode->GetTransformRelativeOffset());
267 if (globalFrameRect.IsInRegion(point)) {
268 hitFrameNodes.push_back(frameNode);
269 }
270 }
271
272 if (hitFrameNodes.empty()) {
273 if (SystemProperties::GetDebugEnabled()) {
274 LOGW("HitFrameNodes vector is empty, cannot find targetNode.");
275 }
276 return nullptr;
277 }
278 auto pipeline = NG::PipelineContext::GetCurrentContext();
279 CHECK_NULL_RETURN(pipeline, nullptr);
280 auto manager = pipeline->GetOverlayManager();
281 CHECK_NULL_RETURN(manager, nullptr);
282 auto rootNode = pipeline->GetRootElement();
283
284 auto result = FindTargetInChildNodes(rootNode, hitFrameNodes, findDrop);
285 if (result) {
286 return result;
287 }
288 if (SystemProperties::GetDebugEnabled()) {
289 LOGW("Don't find targetNode by position in rootNode, return nullptr.");
290 }
291 return nullptr;
292 }
293
CheckDragDropProxy(int64_t id) const294 bool DragDropManager::CheckDragDropProxy(int64_t id) const
295 {
296 return currentId_ == id;
297 }
298
299 #ifdef ENABLE_DRAG_FRAMEWORK
UpdateDragAllowDrop(const RefPtr<FrameNode> & dragFrameNode,const bool isCopy)300 void DragDropManager::UpdateDragAllowDrop(const RefPtr<FrameNode>& dragFrameNode, const bool isCopy)
301 {
302 const auto& dragFrameNodeAllowDrop = dragFrameNode->GetAllowDrop();
303 if (dragFrameNodeAllowDrop.empty() || summaryMap_.empty()) {
304 auto recordSize = summaryMap_.size();
305 if (recordSize > 1) {
306 InteractionManager::GetInstance()->UpdateDragStyle(DragCursorStyle::MOVE);
307 } else {
308 InteractionManager::GetInstance()->UpdateDragStyle(DragCursorStyle::DEFAULT);
309 }
310 return;
311 }
312 for (const auto& it : summaryMap_) {
313 if (dragFrameNodeAllowDrop.find(it.first) == dragFrameNodeAllowDrop.end()) {
314 InteractionManager::GetInstance()->UpdateDragStyle(DragCursorStyle::FORBIDDEN);
315 return;
316 }
317 }
318 InteractionManager::GetInstance()->UpdateDragStyle(isCopy ? DragCursorStyle::COPY : DragCursorStyle::MOVE);
319 }
320 #endif // ENABLE_DRAG_FRAMEWORK
321
OnDragStart(const Point & point,const RefPtr<FrameNode> & frameNode)322 void DragDropManager::OnDragStart(const Point& point, const RefPtr<FrameNode>& frameNode)
323 {
324 CHECK_NULL_VOID(frameNode);
325 preTargetFrameNode_ = frameNode;
326 draggedFrameNode_ = preTargetFrameNode_;
327 if (SystemProperties::GetDebugEnabled()) {
328 LOGI("DragDropManager onDragStart. Dragged frameNode is %{public}s, depth is %{public}d.",
329 frameNode->GetTag().c_str(), frameNode->GetDepth());
330 }
331 }
332
PrintDragFrameNode(const Point & point,const RefPtr<FrameNode> & dragFrameNode)333 void DragDropManager::PrintDragFrameNode(const Point& point, const RefPtr<FrameNode>& dragFrameNode)
334 {
335 CHECK_NULL_VOID(dragFrameNode);
336 if (SystemProperties::GetDebugEnabled()) {
337 if (preTargetFrameNode_) {
338 LOGI("Position is %{public}f and %{public}f.",
339 static_cast<float>(point.GetX()), static_cast<float>(point.GetY()));
340 LOGI("PreTargetFrameNode is %{public}s, depth is %{public}d.",
341 preTargetFrameNode_->GetTag().c_str(), preTargetFrameNode_->GetDepth());
342 LOGI("New find targetNode is %{public}s, depth is %{public}d.",
343 dragFrameNode->GetTag().c_str(), dragFrameNode->GetDepth());
344 } else {
345 LOGI("Position is %{public}f and %{public}f.",
346 static_cast<float>(point.GetX()), static_cast<float>(point.GetY()));
347 LOGI("PreTargetFrameNode is nullptr.");
348 LOGI("New find targetNode is %{public}s, depth is %{public}d.",
349 dragFrameNode->GetTag().c_str(), dragFrameNode->GetDepth());
350 }
351 }
352 }
353
OnDragMove(const Point & point,const std::string & extraInfo)354 void DragDropManager::OnDragMove(const Point& point, const std::string& extraInfo)
355 {
356 #ifdef ENABLE_DRAG_FRAMEWORK
357 auto container = Container::Current();
358 if (container && container->IsScenceBoardWindow()) {
359 if (IsDragged() && IsWindowConsumed()) {
360 LOGD("The event does not need to be handled");
361 SetIsWindowConsumed(false);
362 return;
363 }
364 }
365 SetIsWindowConsumed(false);
366 #endif // ENABLE_DRAG_FRAMEWORK
367 UpdateVelocityTrackerPoint(point, false);
368 auto dragFrameNode = FindDragFrameNodeByPosition(
369 static_cast<float>(point.GetX()), static_cast<float>(point.GetY()), DragType::COMMON, false);
370 PrintDragFrameNode(point, dragFrameNode);
371 if (!dragFrameNode) {
372 if (preTargetFrameNode_) {
373 FireOnDragEvent(preTargetFrameNode_, point, DragEventType::LEAVE, extraInfo);
374 preTargetFrameNode_ = nullptr;
375 }
376
377 #ifdef ENABLE_DRAG_FRAMEWORK
378 if (!isMouseDragged_ || isDragWindowShow_) {
379 InteractionManager::GetInstance()->UpdateDragStyle(
380 summaryMap_.size() > 1 ? DragCursorStyle::MOVE : DragCursorStyle::DEFAULT);
381 }
382 #endif // ENABLE_DRAG_FRAMEWORK
383 return;
384 }
385
386 if (dragFrameNode == preTargetFrameNode_) {
387 FireOnDragEvent(dragFrameNode, point, DragEventType::MOVE, extraInfo);
388 return;
389 }
390
391 if (preTargetFrameNode_) {
392 auto preRect = preTargetFrameNode_->GetTransformRectRelativeToWindow();
393 if (!preRect.IsInRegion(PointF(static_cast<float>(point.GetX()), static_cast<float>(point.GetY())))) {
394 FireOnDragEvent(preTargetFrameNode_, point, DragEventType::LEAVE, extraInfo);
395 }
396 }
397 FireOnDragEvent(dragFrameNode, point, DragEventType::ENTER, extraInfo);
398 preTargetFrameNode_ = dragFrameNode;
399 }
400
401 #ifdef ENABLE_DRAG_FRAMEWORK
TranslateDragResult(DragRet dragResult)402 DragResult TranslateDragResult(DragRet dragResult)
403 {
404 switch (dragResult) {
405 case DragRet::DRAG_SUCCESS:
406 return DragResult::DRAG_SUCCESS;
407 case DragRet::DRAG_FAIL:
408 return DragResult::DRAG_FAIL;
409 case DragRet::DRAG_CANCEL:
410 return DragResult::DRAG_CANCEL;
411 default:
412 return DragResult::DRAG_SUCCESS;
413 }
414 }
415 #endif // ENABLE_DRAG_FRAMEWORK
416
OnDragEnd(const Point & point,const std::string & extraInfo)417 void DragDropManager::OnDragEnd(const Point& point, const std::string& extraInfo)
418 {
419 preTargetFrameNode_ = nullptr;
420 #ifdef ENABLE_DRAG_FRAMEWORK
421 auto container = Container::Current();
422 if (container && container->IsScenceBoardWindow()) {
423 if (IsDragged() && IsWindowConsumed()) {
424 LOGD("The event does not need to be handled");
425 return;
426 }
427 }
428 if (isDragCancel_) {
429 if (SystemProperties::GetDebugEnabled()) {
430 LOGI("DragDropManager is dragCancel, finish drag.");
431 }
432 InteractionManager::GetInstance()->SetDragWindowVisible(false);
433 InteractionManager::GetInstance()->StopDrag(DragResult::DRAG_CANCEL, false);
434 summaryMap_.clear();
435 ClearVelocityInfo();
436 return;
437 }
438 #endif // ENABLE_DRAG_FRAMEWORK
439 UpdateVelocityTrackerPoint(point, true);
440 auto dragFrameNode = FindDragFrameNodeByPosition(
441 static_cast<float>(point.GetX()), static_cast<float>(point.GetY()), DragType::COMMON, true);
442 if (SystemProperties::GetDebugEnabled()) {
443 if (dragFrameNode) {
444 LOGI("Position is %{public}f and %{public}f. TargetNode is %{public}s.",
445 static_cast<float>(point.GetX()), static_cast<float>(point.GetY()),
446 dragFrameNode->GetTag().c_str());
447 } else {
448 LOGI("Position is %{public}f and %{public}f. TargetNode is nullptr.",
449 static_cast<float>(point.GetX()), static_cast<float>(point.GetY()));
450 }
451 }
452 #ifdef ENABLE_DRAG_FRAMEWORK
453 if (!dragFrameNode) {
454 if (SystemProperties::GetDebugEnabled()) {
455 LOGW("DragDropManager onDragEnd, not find drop target, stop drag.");
456 }
457 InteractionManager::GetInstance()->StopDrag(DragResult::DRAG_FAIL, isMouseDragged_);
458 summaryMap_.clear();
459 return;
460 }
461 #endif // ENABLE_DRAG_FRAMEWORK
462 CHECK_NULL_VOID_NOLOG(dragFrameNode);
463 auto eventHub = dragFrameNode->GetEventHub<EventHub>();
464 CHECK_NULL_VOID(eventHub);
465 RefPtr<OHOS::Ace::DragEvent> event = AceType::MakeRefPtr<OHOS::Ace::DragEvent>();
466 auto extraParams = eventHub->GetDragExtraParams(extraInfo_, point, DragEventType::DROP);
467 UpdateDragEvent(event, point);
468 eventHub->FireOnDrop(event, extraParams);
469 ClearVelocityInfo();
470 #ifdef ENABLE_DRAG_FRAMEWORK
471 SetIsDragged(false);
472 if (SystemProperties::GetDebugEnabled()) {
473 LOGI("DragDropManager finish drop, start do drop animation. UseCustomAnimation is %{public}d.",
474 event->IsUseCustomAnimation());
475 }
476 auto pipeline = PipelineContext::GetCurrentContext();
477 CHECK_NULL_VOID(pipeline);
478 auto dragResult = TranslateDragResult(event->GetResult());
479 auto useCustomAnimation = event->IsUseCustomAnimation();
480 pipeline->SetDragCleanTask([dragResult, useCustomAnimation, isMouseDragged = isMouseDragged_]() {
481 InteractionManager::GetInstance()->SetDragWindowVisible(
482 isMouseDragged ? !isMouseDragged : !useCustomAnimation);
483 InteractionManager::GetInstance()->StopDrag(dragResult, isMouseDragged ? isMouseDragged : useCustomAnimation);
484 });
485 dragFrameNode->MarkDirtyNode();
486 summaryMap_.clear();
487 #endif // ENABLE_DRAG_FRAMEWORK
488 }
489
490 #ifdef ENABLE_DRAG_FRAMEWORK
RequireSummary()491 void DragDropManager::RequireSummary()
492 {
493 std::string udKey;
494 InteractionManager::GetInstance()->GetUdKey(udKey);
495 if (SystemProperties::GetDebugEnabled()) {
496 if (udKey.empty()) {
497 LOGW("Requiry summary get empty udKey.");
498 } else {
499 LOGI("Requiry summary get udKey %{public}s", udKey.c_str());
500 }
501 }
502 std::map<std::string, int64_t> summary;
503 int32_t ret = UdmfClient::GetInstance()->GetSummary(udKey, summary);
504 if (ret != 0) {
505 LOGW("OnDragStart: UDMF GetSummary failed: %{public}d", ret);
506 }
507 summaryMap_ = summary;
508 }
509
ClearSummary()510 void DragDropManager::ClearSummary()
511 {
512 summaryMap_.clear();
513 }
514 #endif // ENABLE_DRAG_FRAMEWORK
515
OnTextDragEnd(float globalX,float globalY,const std::string & extraInfo)516 void DragDropManager::OnTextDragEnd(float globalX, float globalY, const std::string& extraInfo)
517 {
518 auto dragFrameNode = FindDragFrameNodeByPosition(globalX, globalY, DragType::TEXT, true);
519 if (dragFrameNode) {
520 auto textFieldPattern = dragFrameNode->GetPattern<TextFieldPattern>();
521 if (textFieldPattern) {
522 textFieldPattern->InsertValue(extraInfo);
523 }
524 }
525 LOGI("OnTextDragEnd");
526 SetIsDragged(false);
527 currentId_ = -1;
528 }
529
onDragCancel()530 void DragDropManager::onDragCancel()
531 {
532 preTargetFrameNode_ = nullptr;
533 draggedFrameNode_ = nullptr;
534 }
535
FireOnDragEvent(const RefPtr<FrameNode> & frameNode,const Point & point,DragEventType type,const std::string & extraInfo)536 void DragDropManager::FireOnDragEvent(
537 const RefPtr<FrameNode>& frameNode, const Point& point, DragEventType type, const std::string& extraInfo)
538 {
539 auto eventHub = frameNode->GetEventHub<EventHub>();
540 CHECK_NULL_VOID(eventHub);
541 auto pipeline = PipelineContext::GetCurrentContext();
542 CHECK_NULL_VOID(pipeline);
543
544 auto extraParams = eventHub->GetDragExtraParams(extraInfo_.empty() ? extraInfo : extraInfo_, point, type);
545 RefPtr<OHOS::Ace::DragEvent> event = AceType::MakeRefPtr<OHOS::Ace::DragEvent>();
546 event->SetX((double)point.GetX());
547 event->SetY((double)point.GetY());
548 event->SetScreenX((double)point.GetScreenX());
549 event->SetScreenY((double)point.GetScreenY());
550 event->SetVelocity(velocityTracker_.GetVelocity());
551
552 switch (type) {
553 case DragEventType::ENTER:
554 eventHub->FireOnDragEnter(event, extraParams);
555 break;
556 case DragEventType::MOVE:
557 eventHub->FireOnDragMove(event, extraParams);
558 break;
559 case DragEventType::LEAVE:
560 eventHub->FireOnDragLeave(event, extraParams);
561 break;
562 case DragEventType::DROP:
563 eventHub->FireOnDrop(event, extraParams);
564 break;
565 default:
566 break;
567 }
568
569 #ifdef ENABLE_DRAG_FRAMEWORK
570 if (isMouseDragged_ && !isDragWindowShow_) {
571 return;
572 }
573 if (event->GetResult() == DragRet::ENABLE_DROP) {
574 if (event->IsCopy()) {
575 InteractionManager::GetInstance()->UpdateDragStyle(DragCursorStyle::COPY);
576 } else {
577 InteractionManager::GetInstance()->UpdateDragStyle(DragCursorStyle::MOVE);
578 }
579 } else if (event->GetResult() == DragRet::DISABLE_DROP) {
580 InteractionManager::GetInstance()->UpdateDragStyle(DragCursorStyle::FORBIDDEN);
581 } else {
582 UpdateDragAllowDrop(frameNode, event->IsCopy());
583 }
584 #endif // ENABLE_DRAG_FRAMEWORK
585 }
586
OnItemDragStart(float globalX,float globalY,const RefPtr<FrameNode> & frameNode)587 void DragDropManager::OnItemDragStart(float globalX, float globalY, const RefPtr<FrameNode>& frameNode)
588 {
589 preGridTargetFrameNode_ = frameNode;
590 draggedGridFrameNode_ = frameNode;
591 }
592
OnItemDragMove(float globalX,float globalY,int32_t draggedIndex,DragType dragType)593 void DragDropManager::OnItemDragMove(float globalX, float globalY, int32_t draggedIndex, DragType dragType)
594 {
595 auto pipeline = PipelineContext::GetCurrentContext();
596 CHECK_NULL_VOID(pipeline);
597
598 UpdateDragWindowPosition(static_cast<int32_t>(globalX), static_cast<int32_t>(globalY));
599
600 OHOS::Ace::ItemDragInfo itemDragInfo;
601 itemDragInfo.SetX(pipeline->ConvertPxToVp(Dimension(globalX, DimensionUnit::PX)));
602 itemDragInfo.SetY(pipeline->ConvertPxToVp(Dimension(globalY, DimensionUnit::PX)));
603
604 // use -1 for grid item not in eventGrid
605 auto getDraggedIndex = [draggedGrid = draggedGridFrameNode_, draggedIndex, dragType](
606 const RefPtr<FrameNode>& eventGrid) {
607 return (dragType == DragType::GRID) ? (eventGrid == draggedGrid ? draggedIndex : -1) : draggedIndex;
608 };
609
610 auto dragFrameNode = FindDragFrameNodeByPosition(globalX, globalY, dragType, false);
611 if (!dragFrameNode) {
612 if (preGridTargetFrameNode_) {
613 FireOnItemDragEvent(preGridTargetFrameNode_, dragType, itemDragInfo, DragEventType::LEAVE,
614 getDraggedIndex(preGridTargetFrameNode_));
615 preGridTargetFrameNode_ = nullptr;
616 }
617 return;
618 }
619
620 if (dragFrameNode == preGridTargetFrameNode_) {
621 int32_t insertIndex = GetItemIndex(dragFrameNode, dragType, globalX, globalY);
622 FireOnItemDragEvent(
623 dragFrameNode, dragType, itemDragInfo, DragEventType::MOVE, getDraggedIndex(dragFrameNode), insertIndex);
624 return;
625 }
626
627 if (preGridTargetFrameNode_) {
628 FireOnItemDragEvent(preGridTargetFrameNode_, dragType, itemDragInfo, DragEventType::LEAVE,
629 getDraggedIndex(preGridTargetFrameNode_));
630 }
631
632 FireOnItemDragEvent(dragFrameNode, dragType, itemDragInfo, DragEventType::ENTER, getDraggedIndex(dragFrameNode));
633 preGridTargetFrameNode_ = dragFrameNode;
634 }
635
OnItemDragEnd(float globalX,float globalY,int32_t draggedIndex,DragType dragType)636 void DragDropManager::OnItemDragEnd(float globalX, float globalY, int32_t draggedIndex, DragType dragType)
637 {
638 auto pipeline = PipelineContext::GetCurrentContext();
639 CHECK_NULL_VOID(pipeline);
640
641 OHOS::Ace::ItemDragInfo itemDragInfo;
642 itemDragInfo.SetX(pipeline->ConvertPxToVp(Dimension(globalX, DimensionUnit::PX)));
643 itemDragInfo.SetY(pipeline->ConvertPxToVp(Dimension(globalY, DimensionUnit::PX)));
644
645 auto dragFrameNode = FindDragFrameNodeByPosition(globalX, globalY, dragType, true);
646 if (!dragFrameNode) {
647 // drag on one grid and drop on other area
648 if (draggedGridFrameNode_) {
649 if (dragType == DragType::GRID) {
650 auto eventHub = draggedGridFrameNode_->GetEventHub<GridEventHub>();
651 CHECK_NULL_VOID(eventHub);
652 eventHub->FireOnItemDrop(itemDragInfo, draggedIndex, -1, false);
653 } else {
654 auto eventHub = draggedGridFrameNode_->GetEventHub<ListEventHub>();
655 CHECK_NULL_VOID(eventHub);
656 eventHub->FireOnItemDrop(itemDragInfo, draggedIndex, -1, false);
657 }
658 }
659 } else {
660 int32_t insertIndex = GetItemIndex(dragFrameNode, dragType, globalX, globalY);
661 // drag and drop on the same grid
662 if (dragFrameNode == draggedGridFrameNode_) {
663 FireOnItemDropEvent(dragFrameNode, dragType, itemDragInfo, draggedIndex, insertIndex, true);
664 } else {
665 // drag and drop on different grid
666 bool isSuccess = FireOnItemDropEvent(dragFrameNode, dragType, itemDragInfo, -1, insertIndex, true);
667 if (draggedGridFrameNode_) {
668 FireOnItemDropEvent(draggedGridFrameNode_, dragType, itemDragInfo, draggedIndex, -1, isSuccess);
669 }
670 }
671 }
672
673 preGridTargetFrameNode_ = nullptr;
674 draggedGridFrameNode_ = nullptr;
675 }
676
onItemDragCancel()677 void DragDropManager::onItemDragCancel()
678 {
679 preGridTargetFrameNode_ = nullptr;
680 draggedGridFrameNode_ = nullptr;
681 }
682
FireOnItemDragEvent(const RefPtr<FrameNode> & frameNode,DragType dragType,const OHOS::Ace::ItemDragInfo & itemDragInfo,DragEventType type,int32_t draggedIndex,int32_t insertIndex)683 void DragDropManager::FireOnItemDragEvent(const RefPtr<FrameNode>& frameNode, DragType dragType,
684 const OHOS::Ace::ItemDragInfo& itemDragInfo, DragEventType type, int32_t draggedIndex, int32_t insertIndex)
685 {
686 if (dragType == DragType::GRID) {
687 auto eventHub = frameNode->GetEventHub<GridEventHub>();
688 CHECK_NULL_VOID(eventHub);
689 switch (type) {
690 case DragEventType::ENTER:
691 eventHub->FireOnItemDragEnter(itemDragInfo);
692 break;
693 case DragEventType::MOVE:
694 eventHub->FireOnItemDragMove(itemDragInfo, draggedIndex, insertIndex);
695 break;
696 case DragEventType::LEAVE:
697 eventHub->FireOnItemDragLeave(itemDragInfo, draggedIndex);
698 break;
699 default:
700 break;
701 }
702 } else if (dragType == DragType::LIST) {
703 auto eventHub = frameNode->GetEventHub<ListEventHub>();
704 CHECK_NULL_VOID(eventHub);
705 switch (type) {
706 case DragEventType::ENTER:
707 eventHub->FireOnItemDragEnter(itemDragInfo);
708 break;
709 case DragEventType::MOVE:
710 eventHub->FireOnItemDragMove(itemDragInfo, draggedIndex, insertIndex);
711 break;
712 case DragEventType::LEAVE:
713 eventHub->FireOnItemDragLeave(itemDragInfo, draggedIndex);
714 break;
715 default:
716 break;
717 }
718 }
719 }
720
FireOnItemDropEvent(const RefPtr<FrameNode> & frameNode,DragType dragType,const OHOS::Ace::ItemDragInfo & itemDragInfo,int32_t draggedIndex,int32_t insertIndex,bool isSuccess)721 bool DragDropManager::FireOnItemDropEvent(const RefPtr<FrameNode>& frameNode, DragType dragType,
722 const OHOS::Ace::ItemDragInfo& itemDragInfo, int32_t draggedIndex, int32_t insertIndex, bool isSuccess)
723 {
724 if (dragType == DragType::GRID) {
725 auto eventHub = frameNode->GetEventHub<GridEventHub>();
726 CHECK_NULL_RETURN(eventHub, false);
727 return eventHub->FireOnItemDrop(itemDragInfo, draggedIndex, insertIndex, isSuccess);
728 } else if (dragType == DragType::LIST) {
729 auto eventHub = frameNode->GetEventHub<ListEventHub>();
730 CHECK_NULL_RETURN(eventHub, false);
731 return eventHub->FireOnItemDrop(itemDragInfo, draggedIndex, insertIndex, isSuccess);
732 }
733 return false;
734 }
735
GetItemIndex(const RefPtr<FrameNode> & frameNode,DragType dragType,float globalX,float globalY)736 int32_t DragDropManager::GetItemIndex(
737 const RefPtr<FrameNode>& frameNode, DragType dragType, float globalX, float globalY)
738 {
739 CHECK_NULL_RETURN(frameNode, -1);
740 if (dragType == DragType::GRID) {
741 auto eventHub = frameNode->GetEventHub<GridEventHub>();
742 CHECK_NULL_RETURN(eventHub, -1);
743 if (frameNode != draggedGridFrameNode_) {
744 return eventHub->GetInsertPosition(globalX, globalY);
745 }
746 auto itemFrameNode = frameNode->FindChildByPosition(globalX, globalY);
747 if (!itemFrameNode) {
748 if (eventHub->CheckPostionInGrid(globalX, globalY)) {
749 return eventHub->GetFrameNodeChildSize();
750 }
751 } else {
752 return eventHub->GetGridItemIndex(itemFrameNode);
753 }
754 } else if (dragType == DragType::LIST) {
755 auto eventHub = frameNode->GetEventHub<ListEventHub>();
756 CHECK_NULL_RETURN(eventHub, -1);
757 return eventHub->GetListItemIndexByPosition(globalX, globalY);
758 }
759 return -1;
760 }
761
AddDataToClipboard(const std::string & extraInfo)762 void DragDropManager::AddDataToClipboard(const std::string& extraInfo)
763 {
764 auto pipeline = PipelineContext::GetCurrentContext();
765 CHECK_NULL_VOID(pipeline);
766 if (!extraInfo.empty()) {
767 if (!newData_) {
768 newData_ = JsonUtil::Create(true);
769 newData_->Put("customDragInfo", extraInfo.c_str());
770 } else {
771 newData_->Replace("customDragInfo", extraInfo.c_str());
772 }
773 } else {
774 return;
775 }
776 if (!clipboard_) {
777 clipboard_ = ClipboardProxy::GetInstance()->GetClipboard(pipeline->GetTaskExecutor());
778 }
779 if (!addDataCallback_) {
780 auto callback = [weakManager = WeakClaim(this)](const std::string& data) {
781 auto dragDropManager = weakManager.Upgrade();
782 auto addData = dragDropManager->newData_->ToString();
783 CHECK_NULL_VOID_NOLOG(dragDropManager);
784 auto clipboardAllData = JsonUtil::Create(true);
785 clipboardAllData->Put("preData", data.c_str());
786 clipboardAllData->Put("newData", addData.c_str());
787 dragDropManager->clipboard_->SetData(clipboardAllData->ToString(), CopyOptions::Local, true);
788 };
789 addDataCallback_ = callback;
790 }
791 if (clipboard_) {
792 clipboard_->GetData(addDataCallback_, true);
793 }
794 #ifdef ENABLE_DRAG_FRAMEWORK
795 extraInfo_ = extraInfo;
796 #endif // ENABLE_DRAG_FRAMEWORK
797 }
798
GetExtraInfoFromClipboard(std::string & extraInfo)799 void DragDropManager::GetExtraInfoFromClipboard(std::string& extraInfo)
800 {
801 auto pipeline = PipelineContext::GetCurrentContext();
802 CHECK_NULL_VOID(pipeline);
803
804 if (!clipboard_) {
805 clipboard_ = ClipboardProxy::GetInstance()->GetClipboard(pipeline->GetTaskExecutor());
806 }
807
808 if (!getDataCallback_) {
809 auto callback = [weak = WeakClaim(this)](const std::string& data) {
810 auto manager = weak.Upgrade();
811 CHECK_NULL_VOID_NOLOG(manager);
812 auto json = JsonUtil::ParseJsonString(data);
813 auto newData = JsonUtil::ParseJsonString(json->GetString("newData"));
814 manager->extraInfo_ = newData->GetString("customDragInfo");
815 };
816 getDataCallback_ = callback;
817 }
818
819 if (getDataCallback_ && clipboard_) {
820 clipboard_->GetData(getDataCallback_, true);
821 }
822
823 extraInfo = extraInfo_;
824 if (SystemProperties::GetDebugEnabled()) {
825 LOGI("DragDropManager get extra info from clipBoard, extraInfo is %{public}s",
826 extraInfo_.c_str());
827 }
828 }
829
RestoreClipboardData()830 void DragDropManager::RestoreClipboardData()
831 {
832 auto pipeline = PipelineContext::GetCurrentContext();
833 CHECK_NULL_VOID(pipeline);
834
835 if (!clipboard_) {
836 clipboard_ = ClipboardProxy::GetInstance()->GetClipboard(pipeline->GetTaskExecutor());
837 }
838
839 if (!deleteDataCallback_) {
840 auto callback = [weakManager = WeakClaim(this)](const std::string& data) {
841 auto dragDropManager = weakManager.Upgrade();
842 CHECK_NULL_VOID_NOLOG(dragDropManager);
843 auto json = JsonUtil::ParseJsonString(data);
844 if (json->Contains("preData")) {
845 dragDropManager->clipboard_->SetData(json->GetString("preData"));
846 }
847 };
848 deleteDataCallback_ = callback;
849 }
850 if (clipboard_) {
851 clipboard_->GetData(deleteDataCallback_, true);
852 }
853 }
854
DestroyDragWindow()855 void DragDropManager::DestroyDragWindow()
856 {
857 #if !defined(PREVIEW) && !defined(ENABLE_DRAG_FRAMEWORK)
858 CHECK_NULL_VOID(dragWindow_);
859 dragWindow_->Destroy();
860 dragWindow_ = nullptr;
861 #elif defined(ENABLE_DRAG_FRAMEWORK)
862 if (dragWindow_ != nullptr) {
863 dragWindow_->Destroy();
864 dragWindow_ = nullptr;
865 }
866 #endif // ENABLE_DRAG_FRAMEWORK
867 if (dragWindowRootNode_) {
868 dragWindowRootNode_ = nullptr;
869 }
870 LOGI("DestroyDragWindow");
871 SetIsDragged(false);
872 SetIsDragWindowShow(false);
873 isMouseDragged_ = false;
874 currentId_ = -1;
875 }
876
877 #ifdef ENABLE_DRAG_FRAMEWORK
CreateFrameworkDragDropProxy()878 RefPtr<DragDropProxy> DragDropManager::CreateFrameworkDragDropProxy()
879 {
880 SetIsDragged(true);
881 isDragCancel_ = false;
882 currentId_ = ++g_proxyId;
883 return MakeRefPtr<DragDropProxy>(currentId_);
884 }
885 #endif // ENABLE_DRAG_FRAMEWORK
886
UpdateDragEvent(RefPtr<OHOS::Ace::DragEvent> & event,const Point & point)887 void DragDropManager::UpdateDragEvent(RefPtr<OHOS::Ace::DragEvent>& event, const Point& point)
888 {
889 auto pipeline = PipelineContext::GetCurrentContext();
890 CHECK_NULL_VOID(pipeline);
891 event->SetX(point.GetX());
892 event->SetY(point.GetY());
893 event->SetScreenX(point.GetScreenX());
894 event->SetScreenY(point.GetScreenY());
895 #ifdef ENABLE_DRAG_FRAMEWORK
896 std::string udKey;
897 InteractionManager::GetInstance()->GetUdKey(udKey);
898 if (udKey.empty()) {
899 LOGW("InteractionManager GetUdkey is null");
900 event->SetIsGetDataSuccess(false);
901 } else {
902 event->SetUdKey(udKey);
903 }
904 RefPtr<UnifiedData> udData = UdmfClient::GetInstance()->CreateUnifiedData();
905 int ret = UdmfClient::GetInstance()->GetData(udData, udKey);
906 if (ret != 0) {
907 LOGW("UDMF GetData failed: %{public}d", ret);
908 event->SetIsGetDataSuccess(false);
909 } else {
910 event->SetIsGetDataSuccess(true);
911 }
912 auto unifiedData = udData;
913 event->SetData(unifiedData);
914 int x = -1;
915 int y = -1;
916 int width = -1;
917 int height = -1;
918 int retOffset = InteractionManager::GetInstance()->GetShadowOffset(x, y, width, height);
919 if (retOffset == 0) {
920 Rect rect(point.GetX() + x, point.GetY() + y, width, height);
921 event->SetPreviewRect(rect);
922 } else {
923 Rect rect(x, y, width, height);
924 event->SetPreviewRect(rect);
925 LOGW("InteractionManager GetShadowOffset is failed:%{public}d", retOffset);
926 }
927 #endif // ENABLE_DRAG_FRAMEWORK
928 }
929
930 #ifdef ENABLE_DRAG_FRAMEWORK
GetExtraInfo()931 std::string DragDropManager::GetExtraInfo()
932 {
933 return extraInfo_;
934 }
935
SetExtraInfo(const std::string & extraInfo)936 void DragDropManager::SetExtraInfo(const std::string& extraInfo)
937 {
938 extraInfo_ = extraInfo;
939 }
940
ClearExtraInfo()941 void DragDropManager::ClearExtraInfo()
942 {
943 extraInfo_.clear();
944 }
945 #endif // ENABLE_DRAG_FRAMEWORK
946
ClearVelocityInfo()947 void DragDropManager::ClearVelocityInfo()
948 {
949 velocityTracker_.Reset();
950 }
951
UpdateVelocityTrackerPoint(const Point & point,bool isEnd)952 void DragDropManager::UpdateVelocityTrackerPoint(const Point& point, bool isEnd)
953 {
954 std::chrono::microseconds microseconds(GetMicroTickCount());
955 TimeStamp curTime(microseconds);
956 velocityTracker_.UpdateTrackerPoint(point.GetX(), point.GetY(), curTime, isEnd);
957 }
958
959 } // namespace OHOS::Ace::NG
960