1 /*
2  * Copyright (c) 2022 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/event/drag_event.h"
17 
18 #include "base/subwindow/subwindow_manager.h"
19 #include "base/utils/system_properties.h"
20 #include "base/utils/utils.h"
21 #include "core/animation/animation_pub.h"
22 #include "core/common/container.h"
23 #include "core/common/interaction/interaction_data.h"
24 #include "core/common/interaction/interaction_interface.h"
25 #include "core/components/common/layout/constants.h"
26 #include "core/components/container_modal/container_modal_constants.h"
27 #include "core/components/theme/blur_style_theme.h"
28 #include "core/components/theme/shadow_theme.h"
29 #include "core/components_ng/base/frame_node.h"
30 #include "core/components_ng/base/inspector.h"
31 #include "core/components_ng/event/gesture_event_hub.h"
32 #include "core/components_ng/event/gesture_info.h"
33 #include "core/components_ng/gestures/recognizers/long_press_recognizer.h"
34 #include "core/components_ng/gestures/recognizers/pan_recognizer.h"
35 #include "core/components_ng/gestures/recognizers/sequenced_recognizer.h"
36 #include "core/components_ng/manager/drag_drop/drag_drop_behavior_reporter/drag_drop_behavior_reporter.h"
37 #include "core/components_ng/manager/drag_drop/utils/drag_animation_helper.h"
38 #include "core/components_ng/pattern/grid/grid_item_pattern.h"
39 #include "core/components_ng/pattern/image/image_layout_property.h"
40 #include "core/components_ng/pattern/image/image_pattern.h"
41 #include "core/components_ng/pattern/linear_layout/linear_layout_pattern.h"
42 #include "core/components_ng/pattern/list/list_item_pattern.h"
43 #include "core/components_ng/pattern/menu/menu_theme.h"
44 #include "core/components_ng/pattern/scrollable/scrollable_pattern.h"
45 #include "core/components_ng/pattern/stack/stack_pattern.h"
46 #include "core/components_ng/pattern/text/text_base.h"
47 #include "core/components_ng/pattern/text/text_pattern.h"
48 #include "core/components_ng/pattern/text_drag/text_drag_base.h"
49 #include "core/components_ng/pattern/text_drag/text_drag_pattern.h"
50 #include "core/components_ng/render/adapter/component_snapshot.h"
51 #include "core/components_ng/render/render_context.h"
52 #include "core/components_v2/inspector/inspector_constants.h"
53 
54 #include "core/pipeline_ng/pipeline_context.h"
55 
56 #ifdef WEB_SUPPORTED
57 #if !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM)
58 #include "core/components_ng/pattern/web/web_pattern.h"
59 #else
60 #include "core/components_ng/pattern/web/cross_platform/web_pattern.h"
61 #endif
62 #endif // WEB_SUPPORTED
63 
64 namespace OHOS::Ace::NG {
65 namespace {
66 constexpr int32_t PAN_FINGER = 1;
67 constexpr double PAN_DISTANCE = 5.0;
68 constexpr int32_t LONG_PRESS_DURATION = 500;
69 constexpr int32_t PREVIEW_LONG_PRESS_RECONGNIZER = 800;
70 constexpr Dimension FILTER_VALUE(0.0f);
71 constexpr float PIXELMAP_DRAG_SCALE_MULTIPLE = 1.05f;
72 constexpr int32_t PIXELMAP_ANIMATION_TIME = 800;
73 constexpr float SCALE_NUMBER = 0.95f;
74 constexpr int32_t FILTER_TIMES = 250;
75 constexpr int32_t PRE_DRAG_TIMER_DEADLINE = 50; // 50ms
76 constexpr int32_t PIXELMAP_ANIMATION_DURATION = 300;
77 constexpr float SPRING_RESPONSE = 0.416f;
78 constexpr float SPRING_DAMPING_FRACTION = 0.73f;
79 constexpr Dimension PIXELMAP_BORDER_RADIUS = 16.0_vp;
80 constexpr Dimension PREVIEW_BORDER_RADIUS = 12.0_vp;
81 constexpr float BLUR_SIGMA_SCALE = 0.57735f;
82 constexpr float SCALE_HALF = 0.5f;
83 constexpr float DEFAULT_ANIMATION_SCALE = 0.95f;
84 constexpr Dimension BADGE_RELATIVE_OFFSET = 8.0_vp;
85 constexpr float DEFAULT_OPACITY = 0.95f;
86 constexpr float MIN_OPACITY { 0.0f };
87 constexpr float MAX_OPACITY { 1.0f };
88 constexpr float MENU_DRAG_SCALE = 0.05f;
89 #if defined(PIXEL_MAP_SUPPORTED)
90 constexpr int32_t CREATE_PIXELMAP_TIME = 80;
91 #endif
92 } // namespace
93 
DragEventActuator(const WeakPtr<GestureEventHub> & gestureEventHub,PanDirection direction,int32_t fingers,float distance)94 DragEventActuator::DragEventActuator(
95     const WeakPtr<GestureEventHub>& gestureEventHub, PanDirection direction, int32_t fingers, float distance)
96     : gestureEventHub_(gestureEventHub), direction_(direction), fingers_(fingers), distance_(distance)
97 {
98     if (fingers_ < PAN_FINGER) {
99         fingers_ = PAN_FINGER;
100     }
101 
102     if (LessOrEqual(distance_, PAN_DISTANCE)) {
103         distance_ = PAN_DISTANCE;
104     }
105 
106     panRecognizer_ = MakeRefPtr<PanRecognizer>(fingers_, direction_, distance_);
107     panRecognizer_->SetGestureInfo(MakeRefPtr<GestureInfo>(GestureTypeName::DRAG, GestureTypeName::DRAG, true));
108     longPressRecognizer_ = AceType::MakeRefPtr<LongPressRecognizer>(LONG_PRESS_DURATION, fingers_, false, true);
109     longPressRecognizer_->SetGestureInfo(MakeRefPtr<GestureInfo>(GestureTypeName::DRAG, GestureTypeName::DRAG, true));
110     previewLongPressRecognizer_ =
111         AceType::MakeRefPtr<LongPressRecognizer>(PREVIEW_LONG_PRESS_RECONGNIZER, fingers_, false, true);
112     previewLongPressRecognizer_->SetGestureInfo(
113         MakeRefPtr<GestureInfo>(GestureTypeName::DRAG, GestureTypeName::DRAG, true));
114     previewLongPressRecognizer_->SetThumbnailDeadline(PRE_DRAG_TIMER_DEADLINE);
115     isNotInPreviewState_ = false;
116 }
117 
StartDragTaskForWeb(const GestureEvent & info)118 void DragEventActuator::StartDragTaskForWeb(const GestureEvent& info)
119 {
120     auto gestureInfo = const_cast<GestureEvent&>(info);
121     if (actionStart_) {
122         TAG_LOGI(AceLogTag::ACE_WEB, "DragDrop start drag task for web success");
123         actionStart_(gestureInfo);
124     } else {
125         TAG_LOGE(AceLogTag::ACE_WEB, "DragDrop start drag task for web failed,"
126             "because actionStart function is null");
127     }
128 }
129 
StartLongPressActionForWeb(bool isFloatImage)130 void DragEventActuator::StartLongPressActionForWeb(bool isFloatImage)
131 {
132     TAG_LOGW(AceLogTag::ACE_WEB, "StartLongPressActionForWeb isFloatImage:%{public}d", isFloatImage);
133     isFloatImage_ = isFloatImage;
134     if (!isReceivedLongPress_) {
135         TAG_LOGW(AceLogTag::ACE_WEB, "DragDrop not received long press action,"
136             "don't start long press action for web");
137         return;
138     }
139     if (longPressUpdate_) {
140         TAG_LOGI(AceLogTag::ACE_WEB, "DragDrop call long press update,"
141             "after update set false again");
142         longPressUpdate_(longPressInfo_);
143     } else {
144         TAG_LOGE(AceLogTag::ACE_WEB, "DragDrop long press update null");
145     }
146     isReceivedLongPress_ = false;
147 }
148 
CancelDragForWeb()149 void DragEventActuator::CancelDragForWeb()
150 {
151     if (actionCancel_) {
152         TAG_LOGD(AceLogTag::ACE_WEB, "DragDrop call action cancel success");
153         actionCancel_();
154     } else {
155         TAG_LOGE(AceLogTag::ACE_WEB, "DragDrop action cancel null");
156     }
157 }
158 
159 /**
160  * Do some nessessary check before returning the gesture recognizer collection result
161  * to parent during the hittest process. For example, if there is one drag operation
162  * already in our system, it is not allowed to start new interation for drag operation.
163  */
IsGlobalStatusSuitableForDragging()164 bool DragEventActuator::IsGlobalStatusSuitableForDragging()
165 {
166     auto pipeline = PipelineContext::GetCurrentContext();
167     CHECK_NULL_RETURN(pipeline, false);
168     auto dragDropManager = pipeline->GetDragDropManager();
169     CHECK_NULL_RETURN(dragDropManager, false);
170     if (dragDropManager->IsDragging()) {
171         TAG_LOGI(AceLogTag::ACE_DRAG, "No need to collect drag gestures result, is dragging status");
172         return false;
173     }
174 
175     if (dragDropManager->IsMSDPDragging()) {
176         TAG_LOGI(AceLogTag::ACE_DRAG, "No need to collect drag gestures result, is msdp dragging status");
177         return false;
178     }
179 
180     return true;
181 }
182 
IsSelfAndParentDragForbidden(const RefPtr<FrameNode> & frameNode) const183 bool DragEventActuator::IsSelfAndParentDragForbidden(const RefPtr<FrameNode>& frameNode) const
184 {
185     auto parent = frameNode;
186     while (parent) {
187         auto eventHub = parent->GetEventHub<EventHub>();
188         parent = parent->GetAncestorNodeOfFrame(true);
189         if (!eventHub) {
190             continue;
191         }
192         auto gestureEventHub = eventHub->GetGestureEventHub();
193         if (!gestureEventHub) {
194             continue;
195         }
196         if (gestureEventHub->IsDragForbidden()) {
197             return true;
198         }
199     }
200     return false;
201 }
202 
203 /**
204  * check the current node's status to decide if it can initiate one drag operation
205  */
IsCurrentNodeStatusSuitableForDragging(const RefPtr<FrameNode> & frameNode,const TouchRestrict & touchRestrict)206 bool DragEventActuator::IsCurrentNodeStatusSuitableForDragging(
207     const RefPtr<FrameNode>& frameNode, const TouchRestrict& touchRestrict)
208 {
209     CHECK_NULL_RETURN(frameNode, false);
210     auto gestureHub = gestureEventHub_.Upgrade();
211     CHECK_NULL_RETURN(gestureHub, false);
212 
213     if (gestureHub->IsDragForbidden() || (!frameNode->IsDraggable() && frameNode->IsCustomerSet()) ||
214         touchRestrict.inputEventType == InputEventType::AXIS || IsBelongToMultiItemNode(frameNode)) {
215         TAG_LOGI(AceLogTag::ACE_DRAG,
216             "No need to collect drag gestures result, drag forbidden set is %{public}d,"
217             "frameNode draggable is %{public}d, custom set is %{public}d",
218             gestureHub->IsDragForbidden(), frameNode->IsDraggable(), frameNode->IsCustomerSet());
219         return false;
220     }
221 
222     if (gestureHub->GetTextDraggable()) {
223         auto pattern = frameNode->GetPattern<TextBase>();
224         if (pattern && !pattern->IsSelected()) {
225             TAG_LOGI(AceLogTag::ACE_DRAG, "No need to collect drag gestures result, text is not selected.");
226             return false;
227         }
228     }
229 
230     if (IsSelfAndParentDragForbidden(frameNode)) {
231         TAG_LOGI(AceLogTag::ACE_DRAG,
232             "No need to collect drag gestures result, parent is drag forbidden.");
233         return false;
234     }
235 
236     return true;
237 }
238 
RestartDragTask(const GestureEvent & info)239 void DragEventActuator::RestartDragTask(const GestureEvent& info)
240 {
241     if (info.GetInputEventType() == InputEventType::AXIS) {
242         TAG_LOGI(AceLogTag::ACE_DRAG, "Trigger drag pan event by axis");
243         return;
244     }
245     auto gestureHub = gestureEventHub_.Upgrade();
246     CHECK_NULL_VOID(gestureHub);
247     auto frameNode = gestureHub->GetFrameNode();
248     CHECK_NULL_VOID(frameNode);
249     UpdatePreviewOptionFromModifier(frameNode);
250     auto gestureInfo = const_cast<GestureEvent&>(info);
251     if (actionStart_) {
252         TAG_LOGI(AceLogTag::ACE_DRAG, "Restart drag for lifting status");
253         actionStart_(gestureInfo);
254     }
255 }
256 
IsNotNeedShowPreviewForWeb(const RefPtr<FrameNode> & frameNode)257 bool DragEventActuator::IsNotNeedShowPreviewForWeb(const RefPtr<FrameNode>& frameNode)
258 {
259 #ifdef WEB_SUPPORTED
260     bool isNotNeedShowPreview = false;
261     if (frameNode && frameNode->GetTag() == V2::WEB_ETS_TAG) {
262         auto webPattern = frameNode->GetPattern<WebPattern>();
263         CHECK_NULL_RETURN(webPattern, false);
264         isNotNeedShowPreview = webPattern->IsPreviewMenuNotNeedShowPreview();
265     }
266     return isNotNeedShowPreview;
267 #else
268     return false;
269 #endif
270 }
271 
272 // this pan cancel only for no drag action.
HandleOnPanActionCancel()273 void DragEventActuator::HandleOnPanActionCancel()
274 {
275     bool isAllowedDrag = IsAllowedDrag();
276     CHECK_NULL_VOID(!isAllowedDrag);
277     CHECK_NULL_VOID(userCallback_);
278     isDragPrepareFinish_ = false;
279     auto userActionCancel = userCallback_->GetActionCancelEventFunc();
280     if (userActionCancel) {
281         userActionCancel();
282     }
283 }
284 
OnCollectTouchTarget(const OffsetF & coordinateOffset,const TouchRestrict & touchRestrict,const GetEventTargetImpl & getEventTargetImpl,TouchTestResult & result,ResponseLinkResult & responseLinkResult)285 void DragEventActuator::OnCollectTouchTarget(const OffsetF& coordinateOffset, const TouchRestrict& touchRestrict,
286     const GetEventTargetImpl& getEventTargetImpl, TouchTestResult& result, ResponseLinkResult& responseLinkResult)
287 {
288     CHECK_NULL_VOID(userCallback_);
289     isDragUserReject_ = false;
290     auto gestureHub = gestureEventHub_.Upgrade();
291     CHECK_NULL_VOID(gestureHub);
292     auto frameNode = gestureHub->GetFrameNode();
293     CHECK_NULL_VOID(frameNode);
294     auto pipeline = PipelineContext::GetCurrentContext();
295     CHECK_NULL_VOID(pipeline);
296     auto dragDropManager = pipeline->GetDragDropManager();
297     CHECK_NULL_VOID(dragDropManager);
298     dragDropManager->SetPrepareDragFrameNode(nullptr);
299     dragDropManager->SetIsDragNodeNeedClean(false);
300     if (!IsGlobalStatusSuitableForDragging() || !IsCurrentNodeStatusSuitableForDragging(frameNode, touchRestrict)) {
301         return;
302     }
303     auto focusHub = frameNode->GetFocusHub();
304     bool hasContextMenuUsingGesture = focusHub == nullptr
305                               ? false : focusHub->FindContextMenuOnKeyEvent(OnKeyEventType::CONTEXT_MENU);
306     dragDropManager->SetPreDragStatus(PreDragStatus::ACTION_DETECTING_STATUS);
307     auto actionStart = [weak = WeakClaim(this), this](GestureEvent& info) {
308         auto containerId = Container::CurrentId();
309         TAG_LOGI(AceLogTag::ACE_DRAG, "Trigger drag action start.");
310         auto actuator = weak.Upgrade();
311         if (!actuator) {
312             DragEventActuator::ResetDragStatus();
313             return;
314         }
315         auto pipeline = PipelineContext::GetCurrentContext();
316         CHECK_NULL_VOID(pipeline);
317         auto dragDropManager = pipeline->GetDragDropManager();
318         CHECK_NULL_VOID(dragDropManager);
319         actuator->ResetResponseRegion();
320         actuator->SetGatherNode(nullptr);
321         actuator->isDragPrepareFinish_ = false;
322         if (dragDropManager->IsDragging() || dragDropManager->IsMSDPDragging()) {
323             DragDropBehaviorReporterTrigger trigger(DragReporterPharse::DRAG_START, containerId);
324             DragDropBehaviorReporter::GetInstance().UpdateDragStartResult(DragStartResult::REPEAT_DRAG_FAIL);
325             TAG_LOGI(AceLogTag::ACE_DRAG,
326                 "It's already dragging now, dragging is %{public}d, MSDP dragging is %{public}d",
327                 dragDropManager->IsDragging(), dragDropManager->IsMSDPDragging());
328             return;
329         }
330         if (dragDropManager->GetPreDragStatus() >= PreDragStatus::PREVIEW_LANDING_FINISHED) {
331             TAG_LOGI(AceLogTag::ACE_DRAG, "Drag preview is landing finished, stop dragging.");
332             return;
333         }
334         if (dragDropManager->IsDragNodeNeedClean()) {
335             TAG_LOGI(AceLogTag::ACE_DRAG, "Drag node have been cleaned by backpress, stop dragging.");
336             return;
337         }
338         dragDropManager->SetHasGatherNode(false);
339         dragDropManager->ResetDragging(DragDropMgrState::ABOUT_TO_PREVIEW);
340         auto gestureHub = actuator->gestureEventHub_.Upgrade();
341         CHECK_NULL_VOID(gestureHub);
342         auto frameNode = gestureHub->GetFrameNode();
343         CHECK_NULL_VOID(frameNode);
344         auto renderContext = frameNode->GetRenderContext();
345         if (info.GetSourceDevice() != SourceType::MOUSE) {
346             if (gestureHub->GetTextDraggable()) {
347                 auto pattern = frameNode->GetPattern<TextBase>();
348                 CHECK_NULL_VOID(pattern);
349                 if (!pattern->IsSelected()) {
350                     dragDropManager->ResetDragging();
351                     gestureHub->SetIsTextDraggable(false);
352                     TAG_LOGW(AceLogTag::ACE_DRAG, "Text is not selected, stop dragging.");
353                     DragDropBehaviorReporterTrigger trigger(DragReporterPharse::DRAG_START, containerId);
354                     DragDropBehaviorReporter::GetInstance().UpdateDragStartResult(DragStartResult::TEXT_NOT_SELECT);
355                     return;
356                 }
357                 if (gestureHub->GetIsTextDraggable()) {
358                     SetTextPixelMap(gestureHub);
359                 } else {
360                     gestureHub->SetPixelMap(nullptr);
361                 }
362             } else {
363                 HideEventColumn();
364                 if (gestureHub->GetTextDraggable()) {
365                     HideTextAnimation(true, info.GetGlobalLocation().GetX(), info.GetGlobalLocation().GetY());
366                 } else {
367                     HideFilter();
368                     RecordMenuWrapperNodeForDrag(frameNode->GetId());
369                     SubwindowManager::GetInstance()->HideMenuNG(false, true);
370                 }
371             }
372             if (!gestureHub->GetTextDraggable()) {
373                 frameNode->SetOptionsAfterApplied(actuator->GetOptionsAfterApplied());
374             }
375         }
376 
377         if (info.GetSourceDevice() == SourceType::MOUSE) {
378             frameNode->MarkModifyDone();
379             dragDropManager->SetIsShowBadgeAnimation(true);
380             auto pattern = frameNode->GetPattern<TextBase>();
381             if (gestureHub->GetTextDraggable() && pattern) {
382                 if (!pattern->IsSelected() || pattern->GetMouseStatus() == MouseStatus::MOVE) {
383                     dragDropManager->ResetDragging();
384                     gestureHub->SetIsTextDraggable(false);
385                     TAG_LOGW(AceLogTag::ACE_DRAG, "Text isSelected: %{public}d, stop dragging.", pattern->IsSelected());
386                     DragDropBehaviorReporterTrigger trigger(DragReporterPharse::DRAG_START, containerId);
387                     DragDropBehaviorReporter::GetInstance().UpdateDragStartResult(DragStartResult::TEXT_NOT_SELECT);
388                     return;
389                 }
390                 if (pattern->BetweenSelectedPosition(info.GetGlobalLocation())) {
391                     gestureHub->SetIsTextDraggable(true);
392                     if (textDragCallback_) {
393                         textDragCallback_(info.GetGlobalLocation());
394                     }
395                 } else if (!gestureHub->GetIsTextDraggable()) {
396                     gestureHub->SetPixelMap(nullptr);
397                 }
398             } else {
399                 HideEventColumn();
400                 HidePixelMap(true, info.GetGlobalLocation().GetX(), info.GetGlobalLocation().GetY());
401                 HideFilter();
402                 RecordMenuWrapperNodeForDrag(frameNode->GetId());
403                 SubwindowManager::GetInstance()->HideMenuNG(false, true);
404                 actuator->UpdatePreviewOptionFromModifier(frameNode);
405             }
406         }
407         if (gestureHub->GetTextDraggable() && !gestureHub->GetIsTextDraggable()) {
408             TAG_LOGI(AceLogTag::ACE_DRAG, "Text category component does not meet the drag condition, forbidden drag.");
409             dragDropManager->ResetDragging();
410             return;
411         }
412        // Trigger drag start event set by user.
413         CHECK_NULL_VOID(actuator->userCallback_);
414         auto userActionStart = actuator->userCallback_->GetActionStartEventFunc();
415         if (userActionStart) {
416             TAG_LOGI(AceLogTag::ACE_DRAG, "Trigger drag start event set by user.");
417             userActionStart(info);
418         }
419         // Trigger custom drag start event
420         CHECK_NULL_VOID(actuator->customCallback_);
421         auto customActionStart = actuator->customCallback_->GetActionStartEventFunc();
422         if (customActionStart) {
423             customActionStart(info);
424         }
425     };
426     actionStart_ = actionStart;
427     panRecognizer_->SetOnActionStart(actionStart);
428 
429     auto actionUpdate = [weak = WeakClaim(this)](GestureEvent& info) {
430         TAG_LOGD(AceLogTag::ACE_DRAG, "DragEvent panRecognizer onActionUpdate.");
431         auto actuator = weak.Upgrade();
432         CHECK_NULL_VOID(actuator);
433         CHECK_NULL_VOID(actuator->userCallback_);
434         auto userActionUpdate = actuator->userCallback_->GetActionUpdateEventFunc();
435         if (userActionUpdate) {
436             userActionUpdate(info);
437         }
438         CHECK_NULL_VOID(actuator->customCallback_);
439         auto customActionUpdate = actuator->customCallback_->GetActionUpdateEventFunc();
440         if (customActionUpdate) {
441             customActionUpdate(info);
442         }
443     };
444     panRecognizer_->SetOnActionUpdate(actionUpdate);
445 
446     auto actionEnd = [weak = WeakClaim(this)](GestureEvent& info) {
447         TAG_LOGI(AceLogTag::ACE_DRAG, "Trigger drag action end.");
448         auto pipelineContext = PipelineContext::GetCurrentContext();
449         CHECK_NULL_VOID(pipelineContext);
450         auto dragDropManager = pipelineContext->GetDragDropManager();
451         CHECK_NULL_VOID(dragDropManager);
452         dragDropManager->SetHasGatherNode(false);
453         if (dragDropManager->IsAboutToPreview()) {
454             dragDropManager->ResetDragging();
455         }
456         dragDropManager->SetIsDragNodeNeedClean(false);
457         auto actuator = weak.Upgrade();
458         if (!actuator) {
459             auto overlayManager = pipelineContext->GetOverlayManager();
460             CHECK_NULL_VOID(overlayManager);
461             overlayManager->RemovePixelMap();
462             return;
463         }
464         CHECK_NULL_VOID(actuator->userCallback_);
465         auto gestureHub = actuator->gestureEventHub_.Upgrade();
466         CHECK_NULL_VOID(gestureHub);
467         actuator->HideEventColumn();
468         if (gestureHub->GetTextDraggable()) {
469             actuator->textPixelMap_ = nullptr;
470             actuator->HideTextAnimation();
471         } else {
472             actuator->HidePixelMap();
473         }
474         auto userActionEnd = actuator->userCallback_->GetActionEndEventFunc();
475         if (userActionEnd) {
476             TAG_LOGI(AceLogTag::ACE_DRAG, "Trigger drag end event set by user.");
477             userActionEnd(info);
478         }
479         CHECK_NULL_VOID(actuator->customCallback_);
480         auto customActionEnd = actuator->customCallback_->GetActionEndEventFunc();
481         if (customActionEnd) {
482             customActionEnd(info);
483         }
484         actuator->SetIsNotInPreviewState(false);
485     };
486     panRecognizer_->SetOnActionEnd(actionEnd);
487     auto actionCancel = [weak = WeakClaim(this), touchSourceType = touchRestrict.sourceType]() {
488         TAG_LOGD(AceLogTag::ACE_DRAG, "Drag event has been canceled.");
489         auto pipelineContext = PipelineContext::GetCurrentContext();
490         CHECK_NULL_VOID(pipelineContext);
491         auto dragDropManager = pipelineContext->GetDragDropManager();
492         CHECK_NULL_VOID(dragDropManager);
493         dragDropManager->SetHasGatherNode(false);
494         auto actuator = weak.Upgrade();
495         if (!actuator) {
496             DragEventActuator::ResetDragStatus();
497             return;
498         }
499         actuator->isDragPrepareFinish_ = false;
500         auto gestureHub = actuator->gestureEventHub_.Upgrade();
501         CHECK_NULL_VOID(gestureHub);
502         auto frameNode = gestureHub->GetFrameNode();
503         CHECK_NULL_VOID(frameNode);
504         auto longPressRecognizer = actuator->longPressRecognizer_;
505         if (touchSourceType != SourceType::MOUSE && longPressRecognizer &&
506             longPressRecognizer->GetGestureState() != RefereeState::SUCCEED &&
507             longPressRecognizer->GetGestureState() != RefereeState::SUCCEED_BLOCKED) {
508             return;
509         }
510         actuator->ResetResponseRegion();
511         actuator->SetGatherNode(nullptr);
512         if (actuator->GetIsNotInPreviewState() && !gestureHub->GetTextDraggable()) {
513             DragEventActuator::ExecutePreDragAction(PreDragStatus::ACTION_CANCELED_BEFORE_DRAG, frameNode);
514         }
515         if (!gestureHub->GetBindMenuStatus().IsNotNeedShowPreview() &&
516             !actuator->IsNotNeedShowPreviewForWeb(frameNode)) {
517             if (gestureHub->GetTextDraggable()) {
518                 if (gestureHub->GetIsTextDraggable()) {
519                     actuator->HideEventColumn();
520                     actuator->textPixelMap_ = nullptr;
521                     actuator->HideTextAnimation();
522                 }
523             } else {
524                 auto renderContext = frameNode->GetRenderContext();
525                 BorderRadiusProperty borderRadius;
526                 if (renderContext->GetBorderRadius().has_value()) {
527                     borderRadius.UpdateWithCheck(renderContext->GetBorderRadius().value());
528                 }
529                 borderRadius.multiValued = false;
530                 AnimationOption option;
531                 option.SetDuration(PIXELMAP_ANIMATION_DURATION);
532                 option.SetCurve(Curves::FRICTION);
533                 AnimationUtils::Animate(
534                     option,
535                     [renderContext_ = renderContext, borderRadius_ = borderRadius]() {
536                         renderContext_->UpdateBorderRadius(borderRadius_);
537                     },
538                     option.GetOnFinishEvent());
539                 actuator->HidePixelMap();
540                 actuator->HideFilter();
541             }
542         } else {
543             if (actuator->panRecognizer_->getDeviceType() == SourceType::MOUSE) {
544                 if (!gestureHub->GetTextDraggable()) {
545                     actuator->HideEventColumn();
546                     actuator->HidePixelMap();
547                     actuator->HideFilter();
548                 }
549             }
550         }
551         actuator->SetIsNotInPreviewState(false);
552         CHECK_NULL_VOID(actuator->userCallback_);
553         auto userActionCancel = actuator->userCallback_->GetActionCancelEventFunc();
554         if (userActionCancel) {
555             userActionCancel();
556         }
557         CHECK_NULL_VOID(actuator->customCallback_);
558         auto customActionCancel = actuator->customCallback_->GetActionCancelEventFunc();
559         if (customActionCancel) {
560             customActionCancel();
561         }
562     };
563     auto panOnReject = [weak = WeakClaim(this)]() {
564         TAG_LOGI(AceLogTag::ACE_DRAG, "Trigger pan onReject");
565         auto actuator = weak.Upgrade();
566         CHECK_NULL_VOID(actuator);
567         auto gestureHub = actuator->gestureEventHub_.Upgrade();
568         CHECK_NULL_VOID(gestureHub);
569         actuator->ResetResponseRegion();
570         auto pipelineContext = PipelineContext::GetCurrentContext();
571         CHECK_NULL_VOID(pipelineContext);
572         auto manager = pipelineContext->GetOverlayManager();
573         CHECK_NULL_VOID(manager);
574         if (manager->IsGatherWithMenu() || !actuator->GetGatherNode()) {
575             return;
576         }
577         TAG_LOGI(AceLogTag::ACE_DRAG, "Pan reject, try remove gather node");
578         actuator->SetGatherNode(nullptr);
579         actuator->ClearGatherNodeChildrenInfo();
580         auto dragDropManager = pipelineContext->GetDragDropManager();
581         CHECK_NULL_VOID(dragDropManager);
582         auto preDragStatus = dragDropManager->GetPreDragStatus();
583         if (preDragStatus <= PreDragStatus::READY_TO_TRIGGER_DRAG_ACTION) {
584             manager->RemoveGatherNode();
585         } else {
586             manager->RemoveGatherNodeWithAnimation();
587         }
588     };
589     panRecognizer_->SetOnReject(panOnReject);
590     panRecognizer_->SetIsForDrag(true);
591     panRecognizer_->SetMouseDistance(DRAG_PAN_DISTANCE_MOUSE.ConvertToPx());
592     actionCancel_ = actionCancel;
593     panRecognizer_->SetCoordinateOffset(Offset(coordinateOffset.GetX(), coordinateOffset.GetY()));
594     panRecognizer_->SetGetEventTargetImpl(getEventTargetImpl);
595     auto panOnActionCancel = [weak = WeakClaim(this)]() {
596         auto actuator = weak.Upgrade();
597         CHECK_NULL_VOID(actuator);
598         actuator->HandleOnPanActionCancel();
599     };
600     panRecognizer_->SetOnActionCancel(panOnActionCancel);
601     if (touchRestrict.sourceType == SourceType::MOUSE) {
602         std::vector<RefPtr<NGGestureRecognizer>> recognizers { panRecognizer_ };
603         SequencedRecognizer_ = AceType::MakeRefPtr<SequencedRecognizer>(recognizers);
604         SequencedRecognizer_->RemainChildOnResetStatus();
605         SequencedRecognizer_->SetCoordinateOffset(Offset(coordinateOffset.GetX(), coordinateOffset.GetY()));
606         SequencedRecognizer_->SetOnActionCancel(actionCancel);
607         SequencedRecognizer_->SetGetEventTargetImpl(getEventTargetImpl);
608         result.emplace_back(SequencedRecognizer_);
609         return;
610     }
611     auto longPressUpdateValue = [weak = WeakClaim(this), hasContextMenuUsingGesture = hasContextMenuUsingGesture](
612                                     GestureEvent& info) {
613         TAG_LOGI(AceLogTag::ACE_DRAG, "Trigger long press for 500ms.");
614         auto actuator = weak.Upgrade();
615         CHECK_NULL_VOID(actuator);
616         actuator->SetIsNotInPreviewState(true);
617         if (actuator->userCallback_ && !actuator->isDragPrepareFinish_) {
618             auto customLongPress = actuator->userCallback_->GetLongPressEventFunc();
619             if (customLongPress) {
620                 customLongPress(info);
621             }
622         }
623         actuator->isDragPrepareFinish_ = true;
624         auto pipelineContext = PipelineContext::GetCurrentContext();
625         CHECK_NULL_VOID(pipelineContext);
626         auto dragDropManager = pipelineContext->GetDragDropManager();
627         CHECK_NULL_VOID(dragDropManager);
628         dragDropManager->SetIsShowBadgeAnimation(true);
629         auto gestureHub = actuator->gestureEventHub_.Upgrade();
630         CHECK_NULL_VOID(gestureHub);
631         auto frameNode = gestureHub->GetFrameNode();
632         CHECK_NULL_VOID(frameNode);
633         dragDropManager->SetPrepareDragFrameNode(frameNode);
634         if (!gestureHub->GetTextDraggable()) {
635             // For the drag initiacating from long press gesture, the preview option set by the modifier
636             // should also be applied in floating pharse, so we need to update the preview option here.
637             actuator->UpdatePreviewOptionFromModifier(frameNode);
638             DragEventActuator::ExecutePreDragAction(PreDragStatus::READY_TO_TRIGGER_DRAG_ACTION, frameNode);
639         }
640         if (hasContextMenuUsingGesture) {
641             actuator->SetDragDampStartPointInfo(info.GetGlobalPoint(), info.GetPointerId());
642         }
643     };
644     longPressRecognizer_->SetOnAction(longPressUpdateValue);
645     auto longPressUpdate = [weak = WeakClaim(this), hasContextMenuUsingGesture = hasContextMenuUsingGesture](
646                                 GestureEvent& info) {
647         TAG_LOGI(AceLogTag::ACE_DRAG, "Trigger long press for 800ms.");
648         auto pipeline = PipelineContext::GetCurrentContext();
649         CHECK_NULL_VOID(pipeline);
650 
651         auto overlayManager = pipeline->GetOverlayManager();
652         CHECK_NULL_VOID(overlayManager);
653         if (overlayManager->GetHasPixelMap()) {
654             return;
655         }
656 
657         auto dragDropManager = pipeline->GetDragDropManager();
658         CHECK_NULL_VOID(dragDropManager);
659         if (dragDropManager->IsAboutToPreview() || dragDropManager->IsDragging() ||
660             dragDropManager->IsDragNodeNeedClean()) {
661             TAG_LOGI(AceLogTag::ACE_DRAG, "No need to show drag preview, is about to preview: %{public}d,"
662                 "is dragging: %{public}d, is need clean drag node: %{public}d",
663                 dragDropManager->IsAboutToPreview(), dragDropManager->IsDragging(),
664                 dragDropManager->IsDragNodeNeedClean());
665             return;
666         }
667         auto actuator = weak.Upgrade();
668         CHECK_NULL_VOID(actuator);
669         actuator->isOnBeforeLiftingAnimation = false;
670         auto gestureHub = actuator->gestureEventHub_.Upgrade();
671         CHECK_NULL_VOID(gestureHub);
672         if (gestureHub->GetBindMenuStatus().IsNotNeedShowPreview()) {
673             TAG_LOGI(AceLogTag::ACE_DRAG, "Not need to show drag preview because of bind context menu");
674             return;
675         }
676         auto frameNode = gestureHub->GetFrameNode();
677         CHECK_NULL_VOID(frameNode);
678         if (!frameNode->GetDragPreviewOption().isDragPreviewEnabled) {
679             TAG_LOGI(AceLogTag::ACE_DRAG, "Not need to show drag preview because disable drag preview");
680             return;
681         }
682         if (gestureHub->GetTextDraggable()) {
683             actuator->SetIsNotInPreviewState(false);
684             if (gestureHub->GetIsTextDraggable()) {
685                 actuator->SetTextAnimation(gestureHub, info.GetGlobalLocation());
686                 actuator->SetEventColumn(actuator);
687             }
688             return;
689         }
690         if (!actuator->isFloatImage_) {
691             actuator->isFloatImage_ = true;
692             return;
693         }
694 
695         bool isAllowedDrag = actuator->IsAllowedDrag();
696         if (!isAllowedDrag) {
697             actuator->longPressInfo_ = info;
698             actuator->isReceivedLongPress_ = true;
699             TAG_LOGD(AceLogTag::ACE_WEB, "DragDrop long press and info received");
700             return;
701         }
702         dragDropManager->SetPrepareDragFrameNode(frameNode);
703         if (frameNode->GetTag() == V2::WEB_ETS_TAG) {
704             actuator->SetFilter(actuator);
705         }
706         auto manager = pipeline->GetOverlayManager();
707         CHECK_NULL_VOID(manager);
708         actuator->SetIsNotInPreviewState(false);
709         actuator->SetGatherNodeAboveFilter(actuator);
710         actuator->SetPixelMap(actuator);
711         auto motion = AceType::MakeRefPtr<ResponsiveSpringMotion>(SPRING_RESPONSE, SPRING_DAMPING_FRACTION, 0);
712         auto column = manager->GetPixelMapNode();
713         CHECK_NULL_VOID(column);
714 
715         auto imageNode = AceType::DynamicCast<FrameNode>(column->GetFirstChild());
716         CHECK_NULL_VOID(imageNode);
717         auto imageContext = imageNode->GetRenderContext();
718         CHECK_NULL_VOID(imageContext);
719         if (actuator->IsNeedGather()) {
720             DragAnimationHelper::PlayGatherAnimation(imageNode, manager);
721             actuator->ShowPreviewBadgeAnimation(actuator, manager);
722         }
723         AnimationOption option;
724         option.SetDuration(PIXELMAP_ANIMATION_TIME);
725         option.SetCurve(motion);
726         DragEventActuator::ExecutePreDragAction(PreDragStatus::PREVIEW_LIFT_STARTED);
727         dragDropManager->SetDraggingPointer(info.GetPointerId());
728         dragDropManager->SetDraggingPressedState(true);
729         option.SetOnFinishEvent(
730             [id = Container::CurrentId(), pointerId = info.GetPointerId(), hasContextMenuUsingGesture]() {
731                 ContainerScope scope(id);
732                 auto pipeline = PipelineContext::GetCurrentContext();
733                 CHECK_NULL_VOID(pipeline);
734                 auto dragDropManager = pipeline->GetDragDropManager();
735                 CHECK_NULL_VOID(dragDropManager);
736                 if (dragDropManager->IsDraggingPressed(pointerId) || hasContextMenuUsingGesture) {
737                     DragEventActuator::ExecutePreDragAction(PreDragStatus::PREVIEW_LIFT_FINISHED);
738                 }
739             });
740         AnimationUtils::Animate(
741             option,
742             [imageContext]() {
743                 imageContext->UpdateTransformScale({ PIXELMAP_DRAG_SCALE_MULTIPLE, PIXELMAP_DRAG_SCALE_MULTIPLE });
744             },
745             option.GetOnFinishEvent());
746         actuator->SetEventColumn(actuator);
747     };
748     auto longPressCancel = [weak = WeakClaim(this)] {
749         // remove drag overlay info by Cancel event.
750         TAG_LOGD(AceLogTag::ACE_DRAG, "Long press event has been canceled.");
751         auto actuator = weak.Upgrade();
752         CHECK_NULL_VOID(actuator);
753         actuator->HideEventColumn();
754         actuator->HidePixelMap(true, 0, 0, false);
755         actuator->HideFilter();
756         actuator->SetIsNotInPreviewState(false);
757     };
758     longPressUpdate_ = longPressUpdate;
759     auto preDragCallback = [weak = WeakClaim(this)](Offset point) {
760         auto actuator = weak.Upgrade();
761         CHECK_NULL_VOID(actuator);
762         auto gestureHub = actuator->gestureEventHub_.Upgrade();
763         CHECK_NULL_VOID(gestureHub);
764         auto frameNode = gestureHub->GetFrameNode();
765         CHECK_NULL_VOID(frameNode);
766         if (!gestureHub->GetTextDraggable()) {
767             DragEventActuator::ExecutePreDragAction(PreDragStatus::ACTION_DETECTING_STATUS, frameNode);
768         }
769     };
770     previewLongPressRecognizer_->SetOnAction(longPressUpdate);
771     previewLongPressRecognizer_->SetOnActionCancel(longPressCancel);
772     previewLongPressRecognizer_->SetThumbnailCallback(std::move(preDragCallback));
773     previewLongPressRecognizer_->SetGestureHub(gestureEventHub_);
774     auto eventHub = frameNode->GetEventHub<EventHub>();
775     CHECK_NULL_VOID(eventHub);
776     bool isAllowedDrag = gestureHub->IsAllowedDrag(eventHub);
777     if (!longPressRecognizer_->HasThumbnailCallback() && isAllowedDrag) {
778         auto callback = [weakPtr = gestureEventHub_, weak = WeakClaim(this)](Offset point) {
779             TAG_LOGI(AceLogTag::ACE_DRAG, "Trigger 150ms timer Thumbnail callback.");
780             auto gestureHub = weakPtr.Upgrade();
781             CHECK_NULL_VOID(gestureHub);
782             auto frameNode = gestureHub->GetFrameNode();
783             CHECK_NULL_VOID(frameNode);
784             auto pipeline = PipelineContext::GetCurrentContext();
785             CHECK_NULL_VOID(pipeline);
786             auto actuator = weak.Upgrade();
787             CHECK_NULL_VOID(actuator);
788             auto dragPreviewInfo = frameNode->GetDragPreview();
789             if (dragPreviewInfo.inspectorId != "") {
790                 TAG_LOGI(AceLogTag::ACE_DRAG, "Get thumbnail through inspectorId.");
791                 auto previewPixelMap = GetPreviewPixelMap(dragPreviewInfo.inspectorId, frameNode);
792                 gestureHub->SetPixelMap(previewPixelMap);
793                 gestureHub->SetDragPreviewPixelMap(previewPixelMap);
794                 actuator->PrepareFinalPixelMapForDragThroughTouch(previewPixelMap, false);
795             } else if (dragPreviewInfo.pixelMap != nullptr) {
796                 TAG_LOGI(AceLogTag::ACE_DRAG, "Get thumbnail through pixelMap.");
797                 gestureHub->SetPixelMap(dragPreviewInfo.pixelMap);
798                 gestureHub->SetDragPreviewPixelMap(dragPreviewInfo.pixelMap);
799                 actuator->PrepareFinalPixelMapForDragThroughTouch(dragPreviewInfo.pixelMap, false);
800             } else if (dragPreviewInfo.customNode != nullptr) {
801 #if defined(PIXEL_MAP_SUPPORTED)
802                 TAG_LOGI(AceLogTag::ACE_DRAG, "Get thumbnail through customNode.");
803                 auto callback = [id = Container::CurrentId(), pipeline, gestureHub, weak]
804                     (std::shared_ptr<Media::PixelMap> pixelMap, int32_t arg, std::function<void()> finishCallback) {
805                     ContainerScope scope(id);
806                     CHECK_NULL_VOID(pipeline);
807                     auto taskScheduler = pipeline->GetTaskExecutor();
808                     CHECK_NULL_VOID(taskScheduler);
809                     taskScheduler->PostTask(
810                         [finishCallback]() {
811                             if (finishCallback) {
812                                 finishCallback();
813                             }
814                         },
815                         TaskExecutor::TaskType::UI, "ArkUIDragRemoveCustomNode");
816                     if (pixelMap != nullptr) {
817                         auto customPixelMap = PixelMap::CreatePixelMap(reinterpret_cast<void*>(&pixelMap));
818                         taskScheduler->PostTask(
819                             [gestureHub, customPixelMap, weak]() {
820                                 CHECK_NULL_VOID(gestureHub);
821                                 gestureHub->SetPixelMap(customPixelMap);
822                                 gestureHub->SetDragPreviewPixelMap(customPixelMap);
823                                 auto actuator = weak.Upgrade();
824                                 CHECK_NULL_VOID(actuator);
825                                 actuator->PrepareFinalPixelMapForDragThroughTouch(customPixelMap, true);
826                             },
827                             TaskExecutor::TaskType::UI, "ArkUIDragSetCustomPixelMap");
828                     } else {
829                         TAG_LOGI(AceLogTag::ACE_DRAG, "PixelMap is null.");
830                         DragDropBehaviorReporter::GetInstance().UpdateDragStartResult(DragStartResult::SNAPSHOT_FAIL);
831                     }
832                 };
833                 SnapshotParam param;
834                 param.delay = CREATE_PIXELMAP_TIME;
835                 param.checkImageStatus = true;
836                 param.options.waitUntilRenderFinished = true;
837                 OHOS::Ace::NG::ComponentSnapshot::Create(
838                     dragPreviewInfo.customNode, std::move(callback), true, param);
839                 gestureHub->PrintBuilderNode(dragPreviewInfo.customNode);
840 #endif
841             } else {
842                 actuator->GetThumbnailPixelMapAsync(gestureHub);
843             }
844             auto longPressRecognizer = actuator->longPressRecognizer_;
845             if (longPressRecognizer && longPressRecognizer->GetGestureDisposal() != GestureDisposal::REJECT) {
846                 if (!CreateGatherNode(actuator)) {
847                     actuator->isOnBeforeLiftingAnimation = false;
848                     return;
849                 }
850                 actuator->isOnBeforeLiftingAnimation = true;
851                 DragAnimationHelper::PlayGatherAnimationBeforeLifting(actuator);
852                 DragAnimationHelper::PlayNodeAnimationBeforeLifting(frameNode);
853                 actuator->SetResponseRegionFull();
854             } else {
855                 actuator->isOnBeforeLiftingAnimation = false;
856             }
857         };
858 
859         longPressRecognizer_->SetThumbnailCallback(std::move(callback));
860     }
861     std::vector<RefPtr<NGGestureRecognizer>> recognizers { longPressRecognizer_, panRecognizer_ };
862     SequencedRecognizer_ = AceType::MakeRefPtr<SequencedRecognizer>(recognizers);
863     SequencedRecognizer_->RemainChildOnResetStatus();
864     previewLongPressRecognizer_->SetCoordinateOffset(Offset(coordinateOffset.GetX(), coordinateOffset.GetY()));
865     previewLongPressRecognizer_->SetGetEventTargetImpl(getEventTargetImpl);
866     longPressRecognizer_->SetCoordinateOffset(Offset(coordinateOffset.GetX(), coordinateOffset.GetY()));
867     longPressRecognizer_->SetGetEventTargetImpl(getEventTargetImpl);
868     SequencedRecognizer_->SetCoordinateOffset(Offset(coordinateOffset.GetX(), coordinateOffset.GetY()));
869     SequencedRecognizer_->SetOnActionCancel(actionCancel);
870     SequencedRecognizer_->SetGetEventTargetImpl(getEventTargetImpl);
871     SequencedRecognizer_->SetIsEventHandoverNeeded(true);
872     result.emplace_back(SequencedRecognizer_);
873     result.emplace_back(previewLongPressRecognizer_);
874 }
875 
ResetDragStatus()876 void DragEventActuator::ResetDragStatus()
877 {
878     auto pipelineContext = PipelineContext::GetCurrentContext();
879     CHECK_NULL_VOID(pipelineContext);
880     auto overlayManager = pipelineContext->GetOverlayManager();
881     CHECK_NULL_VOID(overlayManager);
882     overlayManager->RemovePreviewBadgeNode();
883     overlayManager->RemoveGatherNode();
884     overlayManager->RemovePixelMap();
885     overlayManager->RemoveEventColumn();
886     overlayManager->RemoveFilter();
887 }
888 
SetDragDampStartPointInfo(const Point & point,int32_t pointerId)889 void DragEventActuator::SetDragDampStartPointInfo(const Point& point, int32_t pointerId)
890 {
891     auto pipeline = PipelineContext::GetCurrentContext();
892     CHECK_NULL_VOID(pipeline);
893     auto dragDropManager = pipeline->GetDragDropManager();
894     CHECK_NULL_VOID(dragDropManager);
895     dragDropManager->SetDragDampStartPoint(point);
896     dragDropManager->SetDraggingPointer(pointerId);
897     isRedragStart_ = false;
898 }
899 
HandleDragDampingMove(const Point & point,int32_t pointerId,bool isRedragStart)900 void DragEventActuator::HandleDragDampingMove(const Point& point, int32_t pointerId, bool isRedragStart)
901 {
902     auto pipeline = PipelineContext::GetCurrentContext();
903     CHECK_NULL_VOID(pipeline);
904     auto dragDropManager = pipeline->GetDragDropManager();
905     CHECK_NULL_VOID(dragDropManager);
906     auto overlayManager = pipeline->GetOverlayManager();
907     CHECK_NULL_VOID(overlayManager);
908     if (dragDropManager->IsAboutToPreview() ||
909         dragDropManager->IsDragging() || !dragDropManager->IsSameDraggingPointer(pointerId)) {
910         return;
911     }
912     auto startPoint = dragDropManager->GetDragDampStartPoint();
913     //get the number with VP unit
914     auto distance = SystemProperties::GetDragStartPanDistanceThreshold();
915     auto dragPanDistance = Dimension(distance, DimensionUnit::VP).ConvertToPx();
916     auto dragStartDampingRatio = SystemProperties::GetDragStartDampingRatio();
917     auto dragTotalDistance = dragDropManager->GetUpdateDragMovePosition();
918     auto delta = Offset(dragTotalDistance.GetX(), dragTotalDistance.GetY());
919     // delta.GetDistance(): pixelMap real move distance
920     if (delta.GetDistance() > dragPanDistance * dragStartDampingRatio) {
921         if (dragDropManager->GetDampingOverflowCount() == 1) {
922             return;
923         }
924         dragDropManager->SetDampingOverflowCount();
925     }
926     // linear decrease for menu scale from 100% to 95% within drag damping range
927     auto previewMenuSacle = 1.0f - delta.GetDistance() / (dragPanDistance * dragStartDampingRatio) * MENU_DRAG_SCALE;
928     auto updateOffset =
929         OffsetF(dragStartDampingRatio * point.GetX() + (1 - dragStartDampingRatio) * startPoint.GetX(),
930             dragStartDampingRatio * point.GetY() + (1 - dragStartDampingRatio) * startPoint.GetY());
931     auto menuWrapperNode = dragDropManager->GetMenuWrapperNode();
932     auto menuWrapperId = menuWrapperNode ? menuWrapperNode->GetId() : -1;
933     if (isRedragStart && !isRedragStart_) {
934         isRedragStart_ = true;
935         SubwindowManager::GetInstance()->UpdateHideMenuOffsetNG(updateOffset, previewMenuSacle, true, menuWrapperId);
936         dragDropManager->UpdateDragMovePosition(updateOffset, true);
937     } else {
938         SubwindowManager::GetInstance()->UpdateHideMenuOffsetNG(updateOffset, previewMenuSacle, false, menuWrapperId);
939         dragDropManager->UpdateDragMovePosition(updateOffset, false);
940     }
941     SubwindowManager::GetInstance()->UpdatePreviewPosition();
942 }
943 
SetFilter(const RefPtr<DragEventActuator> & actuator)944 void DragEventActuator::SetFilter(const RefPtr<DragEventActuator>& actuator)
945 {
946     TAG_LOGD(AceLogTag::ACE_DRAG, "DragEvent start setFilter.");
947     auto gestureHub = actuator->gestureEventHub_.Upgrade();
948     CHECK_NULL_VOID(gestureHub);
949     auto frameNode = gestureHub->GetFrameNode();
950     CHECK_NULL_VOID(frameNode);
951     auto parent = frameNode->GetParent();
952     CHECK_NULL_VOID(parent);
953     while (parent && parent->GetDepth() != 1) {
954         parent = parent->GetParent();
955     }
956     if (!parent) {
957         TAG_LOGD(AceLogTag::ACE_DRAG, "DragFrameNode is %{public}s, depth %{public}d, can not find filter root",
958             frameNode->GetTag().c_str(), frameNode->GetDepth());
959         return;
960     }
961     auto pipelineContext = PipelineContext::GetCurrentContext();
962     CHECK_NULL_VOID(pipelineContext);
963     auto manager = pipelineContext->GetOverlayManager();
964     CHECK_NULL_VOID(manager);
965     if (!manager->GetHasFilter() && !manager->GetIsOnAnimation()) {
966         if (frameNode->GetTag() == V2::WEB_ETS_TAG) {
967 #ifdef WEB_SUPPORTED
968             auto webPattern = frameNode->GetPattern<WebPattern>();
969             CHECK_NULL_VOID(webPattern);
970             bool isWebmageDrag = webPattern->IsImageDrag();
971             WebInfoType type = webPattern->GetWebInfoType();
972             CHECK_NULL_VOID(isWebmageDrag && type == WebInfoType::TYPE_MOBILE);
973 #endif
974         } else {
975             bool isBindOverlayValue = frameNode->GetLayoutProperty()->GetIsBindOverlayValue(false);
976             CHECK_NULL_VOID(isBindOverlayValue && SystemProperties::GetDeviceType() == DeviceType::PHONE);
977         }
978         // insert columnNode to rootNode
979         auto columnNode = FrameNode::CreateFrameNode(V2::COLUMN_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
980             AceType::MakeRefPtr<LinearLayoutPattern>(true));
981         columnNode->GetLayoutProperty()->UpdateMeasureType(MeasureType::MATCH_PARENT);
982         // set filter
983         TAG_LOGI(AceLogTag::ACE_DRAG, "User Device use default Filter");
984         auto container = Container::Current();
985         if (container && container->IsScenceBoardWindow()) {
986             auto windowScene = manager->FindWindowScene(frameNode);
987             manager->MountFilterToWindowScene(columnNode, windowScene);
988         } else {
989             columnNode->MountToParent(parent);
990             columnNode->OnMountToParentDone();
991             manager->SetHasFilter(true);
992             manager->SetFilterColumnNode(columnNode);
993             parent->MarkDirtyNode(NG::PROPERTY_UPDATE_BY_CHILD_REQUEST);
994         }
995         AnimationOption option;
996         BlurStyleOption styleOption;
997         styleOption.blurStyle = static_cast<BlurStyle>(BlurStyle::BACKGROUND_THIN);
998         styleOption.colorMode = static_cast<ThemeColorMode>(static_cast<int32_t>(ThemeColorMode::SYSTEM));
999         option.SetDuration(FILTER_TIMES);
1000         option.SetCurve(Curves::SHARP);
1001         option.SetOnFinishEvent([pipelineWeak = WeakClaim(RawPtr(pipelineContext))] {
1002             auto pipelineContext = pipelineWeak.Upgrade();
1003             CHECK_NULL_VOID(pipelineContext);
1004             auto manager = pipelineContext->GetOverlayManager();
1005             CHECK_NULL_VOID(manager);
1006             manager->SetFilterActive(false);
1007         });
1008         columnNode->GetRenderContext()->UpdateBackBlurRadius(FILTER_VALUE);
1009         AnimationUtils::Animate(
1010             option, [columnNode, styleOption]() { columnNode->GetRenderContext()->UpdateBackBlurStyle(styleOption); },
1011             option.GetOnFinishEvent());
1012     }
1013     TAG_LOGD(AceLogTag::ACE_DRAG, "DragEvent set filter success.");
1014 }
1015 
GetFloatImageOffset(const RefPtr<FrameNode> & frameNode,const RefPtr<PixelMap> & pixelMap)1016 OffsetF DragEventActuator::GetFloatImageOffset(const RefPtr<FrameNode>& frameNode, const RefPtr<PixelMap>& pixelMap)
1017 {
1018     CHECK_NULL_RETURN(frameNode, OffsetF());
1019     auto centerPosition = frameNode->GetPaintRectCenter(true);
1020     float width = 0.0f;
1021     float height = 0.0f;
1022     if (pixelMap) {
1023         width = pixelMap->GetWidth();
1024         height = pixelMap->GetHeight();
1025     }
1026     auto offsetX = centerPosition.GetX() - width / 2.0f;
1027     auto offsetY = centerPosition.GetY() - height / 2.0f;
1028 #ifdef WEB_SUPPORTED
1029     if (frameNode->GetTag() == V2::WEB_ETS_TAG) {
1030         auto webPattern = frameNode->GetPattern<WebPattern>();
1031         if (webPattern) {
1032             auto offsetToWindow = frameNode->GetPaintRectOffset();
1033             offsetX = offsetToWindow.GetX() + webPattern->GetDragOffset().GetX();
1034             offsetY = offsetToWindow.GetY() + webPattern->GetDragOffset().GetY();
1035         }
1036     }
1037 #endif
1038     // Check web tag.
1039     auto pipelineContext = PipelineContext::GetCurrentContext();
1040     CHECK_NULL_RETURN(pipelineContext, OffsetF());
1041     if (pipelineContext->HasFloatTitle()) {
1042         offsetX -= static_cast<float>((CONTAINER_BORDER_WIDTH + CONTENT_PADDING).ConvertToPx());
1043         offsetY -= static_cast<float>((pipelineContext->GetCustomTitleHeight() + CONTAINER_BORDER_WIDTH).ConvertToPx());
1044     }
1045     return OffsetF(offsetX, offsetY);
1046 }
1047 
UpdatePreviewPositionAndScale(const RefPtr<FrameNode> & imageNode,const OffsetF & frameOffset,float scale)1048 void DragEventActuator::UpdatePreviewPositionAndScale(
1049     const RefPtr<FrameNode>& imageNode, const OffsetF& frameOffset, float scale)
1050 {
1051     auto imageContext = imageNode->GetRenderContext();
1052     CHECK_NULL_VOID(imageContext);
1053     imageContext->UpdatePosition(OffsetT<Dimension>(Dimension(frameOffset.GetX()), Dimension(frameOffset.GetY())));
1054     if (GreatNotEqual(scale, 0.0f)) {
1055         imageContext->UpdateTransformScale({ scale, scale });
1056     }
1057     ClickEffectInfo clickEffectInfo;
1058     clickEffectInfo.level = ClickEffectLevel::LIGHT;
1059     clickEffectInfo.scaleNumber = SCALE_NUMBER;
1060     imageContext->UpdateClickEffectLevel(clickEffectInfo);
1061 }
1062 
UpdatePreviewAttr(const RefPtr<FrameNode> & frameNode,const RefPtr<FrameNode> & imageNode)1063 void DragEventActuator::UpdatePreviewAttr(const RefPtr<FrameNode>& frameNode, const RefPtr<FrameNode>& imageNode)
1064 {
1065     CHECK_NULL_VOID(frameNode);
1066     auto frameTag = frameNode->GetTag();
1067     auto gestureHub = frameNode->GetOrCreateGestureEventHub();
1068     CHECK_NULL_VOID(gestureHub);
1069     CHECK_NULL_VOID(imageNode);
1070     auto imageContext = imageNode->GetRenderContext();
1071     CHECK_NULL_VOID(imageContext);
1072     auto dragPreviewOption = frameNode->GetDragPreviewOption();
1073     if (gestureHub->IsTextCategoryComponent(frameTag) && gestureHub->GetTextDraggable()) {
1074         if (dragPreviewOption.options.shadow.has_value()) {
1075             auto shadow = dragPreviewOption.options.shadow.value();
1076             shadow.SetIsFilled(true);
1077             imageContext->UpdateBackShadow(shadow);
1078         }
1079         return;
1080     }
1081     imageContext->UpdateOpacity(dragPreviewOption.options.opacity);
1082     if (dragPreviewOption.options.shadow.has_value()) {
1083         imageContext->UpdateBackShadow(dragPreviewOption.options.shadow.value());
1084     }
1085     if (dragPreviewOption.options.borderRadius.has_value()) {
1086         imageContext->UpdateBorderRadius(dragPreviewOption.options.borderRadius.value());
1087         imageContext->UpdateClipEdge(true);
1088     }
1089     auto optionsFromModifier = frameNode->GetDragPreviewOption().options;
1090     if (optionsFromModifier.blurbgEffect.backGroundEffect.radius.IsValid()) {
1091         ACE_UPDATE_NODE_RENDER_CONTEXT(BackgroundEffect, optionsFromModifier.blurbgEffect.backGroundEffect, imageNode);
1092     }
1093 }
1094 
CreatePreviewNode(const RefPtr<FrameNode> & frameNode,RefPtr<FrameNode> & imageNode,float dragPreviewScale)1095 void DragEventActuator::CreatePreviewNode(
1096     const RefPtr<FrameNode>& frameNode, RefPtr<FrameNode>& imageNode, float dragPreviewScale)
1097 {
1098     CHECK_NULL_VOID(frameNode);
1099     auto pixelMap = frameNode->GetPixelMap();
1100     CHECK_NULL_VOID(pixelMap);
1101     auto center = frameNode->GetPaintRectCenter();
1102     auto frameOffset = OffsetF(center.GetX() - (pixelMap->GetWidth() / 2.0f),
1103         center.GetY() - (pixelMap->GetHeight() / 2.0f));
1104     imageNode = FrameNode::GetOrCreateFrameNode(V2::IMAGE_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
1105         []() {return AceType::MakeRefPtr<ImagePattern>(); });
1106     CHECK_NULL_VOID(imageNode);
1107     imageNode->SetDragPreviewOptions(frameNode->GetDragPreviewOption());
1108 
1109     auto renderProps = imageNode->GetPaintProperty<ImageRenderProperty>();
1110     renderProps->UpdateImageInterpolation(ImageInterpolation::HIGH);
1111     auto props = imageNode->GetLayoutProperty<ImageLayoutProperty>();
1112     props->UpdateAutoResize(false);
1113     props->UpdateImageSourceInfo(ImageSourceInfo(pixelMap));
1114     auto targetSize = CalcSize(NG::CalcLength(pixelMap->GetWidth()), NG::CalcLength(pixelMap->GetHeight()));
1115     props->UpdateUserDefinedIdealSize(targetSize);
1116 
1117     auto imagePattern = imageNode->GetPattern<ImagePattern>();
1118     CHECK_NULL_VOID(imagePattern);
1119     imagePattern->SetSyncLoad(true);
1120 
1121     UpdatePreviewPositionAndScale(imageNode, frameOffset, dragPreviewScale);
1122     UpdatePreviewAttr(frameNode, imageNode);
1123     imageNode->MarkDirtyNode(NG::PROPERTY_UPDATE_MEASURE);
1124     imageNode->MarkModifyDone();
1125     imageNode->SetLayoutDirtyMarked(true);
1126     imageNode->SetActive(true);
1127     auto context = imageNode->GetContext();
1128     if (context) {
1129         context->FlushUITaskWithSingleDirtyNode(imageNode);
1130     }
1131     FlushSyncGeometryNodeTasks();
1132 }
1133 
SetPreviewDefaultAnimateProperty(const RefPtr<FrameNode> & imageNode)1134 void DragEventActuator::SetPreviewDefaultAnimateProperty(const RefPtr<FrameNode>& imageNode)
1135 {
1136     if (imageNode->IsPreviewNeedScale()) {
1137         auto imageContext = imageNode->GetRenderContext();
1138         CHECK_NULL_VOID(imageContext);
1139         imageContext->UpdateTransformScale({ 1.0f, 1.0f });
1140         imageContext->UpdateTransformTranslate({ 0.0f, 0.0f, 0.0f });
1141     }
1142 }
1143 
MountPixelMap(const RefPtr<OverlayManager> & manager,const RefPtr<GestureEventHub> & gestureHub,const RefPtr<FrameNode> & imageNode,const RefPtr<FrameNode> & textNode,bool isDragPixelMap)1144 void DragEventActuator::MountPixelMap(const RefPtr<OverlayManager>& manager, const RefPtr<GestureEventHub>& gestureHub,
1145     const RefPtr<FrameNode>& imageNode, const RefPtr<FrameNode>& textNode, bool isDragPixelMap)
1146 {
1147     CHECK_NULL_VOID(manager);
1148     CHECK_NULL_VOID(imageNode);
1149     CHECK_NULL_VOID(gestureHub);
1150     auto columnNode = FrameNode::CreateFrameNode(V2::COLUMN_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
1151         AceType::MakeRefPtr<LinearLayoutPattern>(true));
1152     columnNode->AddChild(imageNode);
1153     auto hub = columnNode->GetOrCreateGestureEventHub();
1154     CHECK_NULL_VOID(hub);
1155     hub->SetPixelMap(gestureHub->GetPixelMap());
1156     if (textNode) {
1157         columnNode->AddChild(textNode);
1158     }
1159     auto container = Container::Current();
1160     if (container && container->IsScenceBoardWindow()) {
1161         auto frameNode = gestureHub->GetFrameNode();
1162         CHECK_NULL_VOID(frameNode);
1163         auto windowScene = manager->FindWindowScene(frameNode);
1164         manager->MountPixelMapToWindowScene(columnNode, windowScene, isDragPixelMap);
1165     } else {
1166         manager->MountPixelMapToRootNode(columnNode, isDragPixelMap);
1167     }
1168     SetPreviewDefaultAnimateProperty(imageNode);
1169     columnNode->MarkDirtyNode(NG::PROPERTY_UPDATE_MEASURE);
1170     columnNode->MarkModifyDone();
1171     columnNode->SetActive(true);
1172     auto context = columnNode->GetContext();
1173     if (context) {
1174         context->FlushUITaskWithSingleDirtyNode(columnNode);
1175     }
1176     FlushSyncGeometryNodeTasks();
1177 }
1178 
1179 /* Retrieves a preview PixelMap for a given drag event action.
1180  * This function attempts to obtain a screenshot of a frameNode associated with an inspector ID.
1181  * If the frameNode with the given ID does not exist or hasn't been rendered,
1182  * it falls back to taking a screenshot of the provided frame node.
1183  *
1184  * @param inspectorId A string representing the unique identifier for the frameNode's ID.
1185  * @param selfFrameNode A RefPtr to the frame node associated with the drag event.
1186  * @return A RefPtr to a PixelMap containing the preview image, or nullptr if not found.
1187  */
GetPreviewPixelMap(const std::string & inspectorId,const RefPtr<FrameNode> & selfFrameNode)1188 RefPtr<PixelMap> DragEventActuator::GetPreviewPixelMap(
1189     const std::string& inspectorId, const RefPtr<FrameNode>& selfFrameNode)
1190 {
1191     // Attempt to retrieve the PixelMap using the inspector ID.
1192     auto previewPixelMap = GetPreviewPixelMapByInspectorId(inspectorId);
1193     // If a preview PixelMap was found, return it.
1194     if (previewPixelMap != nullptr) {
1195         return previewPixelMap;
1196     }
1197 
1198     // If not found by inspector ID, attempt to get a screenshot of the frame node.
1199     return GetScreenShotPixelMap(selfFrameNode);
1200 }
1201 
1202 /* Retrieves a preview PixelMap based on an inspector ID.
1203  * This function attempts to find a frame node associated with the given inspector ID and then takes a screenshot of it.
1204  *
1205  * @param inspectorId The unique identifier for a frameNode.
1206  * @return A RefPtr to a PixelMap containing the preview image, or nullptr if not found or the ID is empty.
1207  */
GetPreviewPixelMapByInspectorId(const std::string & inspectorId)1208 RefPtr<PixelMap> DragEventActuator::GetPreviewPixelMapByInspectorId(const std::string& inspectorId)
1209 {
1210     // Check for an empty inspector ID and return nullptr if it is empty.
1211     if (inspectorId == "") {
1212         return nullptr;
1213     }
1214 
1215     // Retrieve the frame node using the inspector's ID.
1216     auto dragPreviewFrameNode = Inspector::GetFrameNodeByKey(inspectorId);
1217     CHECK_NULL_RETURN(dragPreviewFrameNode, nullptr);
1218 
1219     auto layoutProperty = dragPreviewFrameNode->GetLayoutProperty();
1220     CHECK_NULL_RETURN(layoutProperty, nullptr);
1221 
1222     auto visibility = layoutProperty->GetVisibilityValue(VisibleType::VISIBLE);
1223     if (visibility == VisibleType::INVISIBLE || visibility == VisibleType::GONE) {
1224         return nullptr;
1225     }
1226 
1227     // Take a screenshot of the frame node and return it as a PixelMap.
1228     return GetScreenShotPixelMap(dragPreviewFrameNode);
1229 }
1230 
1231 /* Captures a screenshot of the specified frame node and encapsulates it in a PixelMap.
1232  *
1233  * @param frameNode A RefPtr reference to the frame node from which to capture the screenshot.
1234  * @return A RefPtr to a PixelMap containing the screenshot.
1235  */
GetScreenShotPixelMap(const RefPtr<FrameNode> & frameNode)1236 RefPtr<PixelMap> DragEventActuator::GetScreenShotPixelMap(const RefPtr<FrameNode>& frameNode)
1237 {
1238     // Ensure the frame node is not nulls before proceeding.
1239     CHECK_NULL_RETURN(frameNode, nullptr);
1240 
1241     // Obtain the rendering context from the frame node.
1242     auto context = frameNode->GetRenderContext();
1243 
1244     // If the rendering context is not available, return nullptr.
1245     CHECK_NULL_RETURN(context, nullptr);
1246 
1247     // Capture and return the thumbnail PixelMap from the rendering context.
1248     return context->GetThumbnailPixelMap(true);
1249 }
1250 
SetPixelMap(const RefPtr<DragEventActuator> & actuator)1251 void DragEventActuator::SetPixelMap(const RefPtr<DragEventActuator>& actuator)
1252 {
1253     TAG_LOGD(AceLogTag::ACE_DRAG, "DragEvent start set pixelMap");
1254     auto pipelineContext = PipelineContext::GetCurrentContext();
1255     CHECK_NULL_VOID(pipelineContext);
1256     auto manager = pipelineContext->GetOverlayManager();
1257     CHECK_NULL_VOID(manager);
1258     if (manager->GetHasPixelMap()) {
1259         TAG_LOGI(AceLogTag::ACE_DRAG, "Dragging animation is currently executing, unable to float other pixelMap.");
1260         return;
1261     }
1262     auto gestureHub = actuator->gestureEventHub_.Upgrade();
1263     CHECK_NULL_VOID(gestureHub);
1264     auto frameNode = gestureHub->GetFrameNode();
1265     CHECK_NULL_VOID(frameNode);
1266     RefPtr<PixelMap> pixelMap = gestureHub->GetPixelMap();
1267     CHECK_NULL_VOID(pixelMap);
1268     auto width = pixelMap->GetWidth();
1269     auto height = pixelMap->GetHeight();
1270     auto offset = GetFloatImageOffset(frameNode, pixelMap);
1271     // create imageNode
1272     auto imageNode = FrameNode::GetOrCreateFrameNode(V2::IMAGE_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
1273         []() { return AceType::MakeRefPtr<ImagePattern>(); });
1274     CHECK_NULL_VOID(imageNode);
1275     auto imagePattern = imageNode->GetPattern<ImagePattern>();
1276     CHECK_NULL_VOID(imagePattern);
1277     imagePattern->SetSyncLoad(true);
1278     imageNode->SetDragPreviewOptions(frameNode->GetDragPreviewOption());
1279     auto renderProps = imageNode->GetPaintProperty<ImageRenderProperty>();
1280     renderProps->UpdateImageInterpolation(ImageInterpolation::HIGH);
1281     auto props = imageNode->GetLayoutProperty<ImageLayoutProperty>();
1282     props->UpdateAutoResize(false);
1283     props->UpdateImageSourceInfo(ImageSourceInfo(pixelMap));
1284     auto targetSize = CalcSize(NG::CalcLength(width), NG::CalcLength(height));
1285     props->UpdateUserDefinedIdealSize(targetSize);
1286     auto imageContext = imageNode->GetRenderContext();
1287     CHECK_NULL_VOID(imageContext);
1288     imageContext->UpdatePosition(OffsetT<Dimension>(Dimension(offset.GetX()), Dimension(offset.GetY())));
1289     ClickEffectInfo clickEffectInfo;
1290     clickEffectInfo.level = ClickEffectLevel::LIGHT;
1291     clickEffectInfo.scaleNumber = SCALE_NUMBER;
1292     imageContext->UpdateClickEffectLevel(clickEffectInfo);
1293     // create columnNode
1294     auto columnNode = FrameNode::CreateFrameNode(V2::COLUMN_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
1295         AceType::MakeRefPtr<LinearLayoutPattern>(true));
1296     columnNode->AddChild(imageNode);
1297     auto hub = columnNode->GetOrCreateGestureEventHub();
1298     CHECK_NULL_VOID(hub);
1299     hub->SetPixelMap(gestureHub->GetPixelMap());
1300     // mount to rootNode
1301     auto container = Container::Current();
1302     if (container && container->IsScenceBoardWindow()) {
1303         auto windowScene = manager->FindWindowScene(frameNode);
1304         manager->MountPixelMapToWindowScene(columnNode, windowScene);
1305     } else {
1306         manager->MountPixelMapToRootNode(columnNode);
1307     }
1308     imageNode->MarkModifyDone();
1309     imageNode->SetLayoutDirtyMarked(true);
1310     imageNode->SetActive(true);
1311     auto context = imageNode->GetContext();
1312     if (context) {
1313         context->FlushUITaskWithSingleDirtyNode(imageNode);
1314     }
1315     FlushSyncGeometryNodeTasks();
1316     auto focusHub = frameNode->GetFocusHub();
1317     bool hasContextMenu = focusHub == nullptr
1318                               ? false : focusHub->FindContextMenuOnKeyEvent(OnKeyEventType::CONTEXT_MENU);
1319     ShowPixelMapAnimation(imageNode, frameNode, hasContextMenu);
1320     TAG_LOGD(AceLogTag::ACE_DRAG, "DragEvent set pixelMap success.");
1321     SetPreviewDefaultAnimateProperty(imageNode);
1322 }
1323 
1324 // called when the preview floating or drag begin, this method will try to execute the modifier
1325 // on one temporary frame node, and then get the value user setted from the modifier
UpdatePreviewOptionFromModifier(const RefPtr<FrameNode> & frameNode)1326 void DragEventActuator::UpdatePreviewOptionFromModifier(const RefPtr<FrameNode>& frameNode)
1327 {
1328     UpdatePreviewOptionDefaultAttr(frameNode);
1329     auto modifierOnApply = frameNode->GetDragPreviewOption().onApply;
1330     if (!modifierOnApply) {
1331         optionsAfterApplied_ = frameNode->GetDragPreviewOption().options;
1332         return;
1333     }
1334 
1335     // create one temporary frame node for receiving the value from the modifier
1336     auto imageNode = FrameNode::GetOrCreateFrameNode(V2::IMAGE_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
1337         []() { return AceType::MakeRefPtr<ImagePattern>(); });
1338     CHECK_NULL_VOID(imageNode);
1339 
1340     // execute the modifier
1341     modifierOnApply(WeakClaim(RawPtr(imageNode)));
1342 
1343     // get values from the temporary frame node
1344     auto imageContext = imageNode->GetRenderContext();
1345     CHECK_NULL_VOID(imageContext);
1346     auto opacity = imageContext->GetOpacity();
1347 
1348     OptionsAfterApplied options = frameNode->GetDragPreviewOption().options;
1349     if (opacity.has_value() && (opacity.value()) <= MAX_OPACITY && (opacity.value()) > MIN_OPACITY) {
1350         options.opacity = opacity.value();
1351     } else {
1352         options.opacity = DEFAULT_OPACITY;
1353     }
1354 
1355     auto shadow = imageContext->GetBackShadow();
1356     if (shadow.has_value()) {
1357         options.shadow = shadow;
1358     }
1359 
1360     auto borderRadius = imageContext->GetBorderRadius();
1361     if (borderRadius.has_value()) {
1362         options.borderRadius = borderRadius;
1363     }
1364 
1365     // get the old preview option
1366     DragPreviewOption dragPreviewOption = frameNode->GetDragPreviewOption();
1367     auto bgEffect = imageContext->GetBackgroundEffect();
1368     if (bgEffect.has_value()) {
1369         options.blurbgEffect.backGroundEffect = bgEffect.value();
1370     } else {
1371         auto blurstyletmp = imageContext->GetBackBlurStyle();
1372         if (blurstyletmp.has_value()) {
1373             bgEffect = BrulStyleToEffection(blurstyletmp);
1374             if (bgEffect.has_value()) {
1375                 options.blurbgEffect.backGroundEffect = bgEffect.value();
1376             }
1377         }
1378     }
1379     dragPreviewOption.options = options; // replace the options with the new one after applied
1380     frameNode->SetDragPreviewOptions(dragPreviewOption);
1381     optionsAfterApplied_ = options;
1382 }
1383 
UpdatePreviewOptionDefaultAttr(const RefPtr<FrameNode> & frameNode)1384 void DragEventActuator::UpdatePreviewOptionDefaultAttr(const RefPtr<FrameNode>& frameNode)
1385 {
1386     auto dragPreviewOption = frameNode->GetDragPreviewOption();
1387     dragPreviewOption.options.opacity = DEFAULT_OPACITY;
1388     if (dragPreviewOption.isDefaultShadowEnabled) {
1389         dragPreviewOption.options.shadow = GetDefaultShadow();
1390     } else {
1391         dragPreviewOption.options.shadow = std::nullopt;
1392     }
1393     if (dragPreviewOption.isDefaultRadiusEnabled || dragPreviewOption.isMultiSelectionEnabled) {
1394         dragPreviewOption.options.borderRadius = GetDefaultBorderRadius();
1395     } else {
1396         dragPreviewOption.options.borderRadius = std::nullopt;
1397     }
1398     frameNode->SetDragPreviewOptions(dragPreviewOption); // replace the options with the new one
1399 }
1400 
RadiusToSigma(float radius)1401 float DragEventActuator::RadiusToSigma(float radius)
1402 {
1403     return GreatNotEqual(radius, 0.0f) ? BLUR_SIGMA_SCALE * radius + SCALE_HALF : 0.0f;
1404 }
1405 
BrulStyleToEffection(const std::optional<BlurStyleOption> & blurStyleOp)1406 std::optional<EffectOption> DragEventActuator::BrulStyleToEffection(const std::optional<BlurStyleOption>& blurStyleOp)
1407 {
1408     auto pipeline = PipelineContext::GetCurrentContext();
1409     CHECK_NULL_RETURN(pipeline, std::nullopt);
1410     auto blurStyleTheme = pipeline->GetTheme<BlurStyleTheme>();
1411     if (!blurStyleTheme) {
1412         LOGW("cannot find theme of blurStyle, create blurStyle failed");
1413         return std::nullopt;
1414     }
1415     ThemeColorMode colorMode = blurStyleOp->colorMode;
1416     if (blurStyleOp->colorMode == ThemeColorMode::SYSTEM) {
1417         colorMode = SystemProperties::GetColorMode() == ColorMode::DARK ? ThemeColorMode::DARK : ThemeColorMode::LIGHT;
1418     }
1419     auto blurParam = blurStyleTheme->GetBlurParameter(blurStyleOp->blurStyle, colorMode);
1420     CHECK_NULL_RETURN(blurParam, std::nullopt);
1421     auto ratio = blurStyleOp->scale;
1422     auto maskColor = blurParam->maskColor.BlendOpacity(ratio);
1423     auto radiusPx = blurParam->radius * pipeline->GetDipScale();
1424     auto radiusBlur = RadiusToSigma(radiusPx) * ratio;
1425     auto saturation = (blurParam->saturation - 1) * ratio + 1.0;
1426     auto brightness = (blurParam->brightness - 1) * ratio + 1.0;
1427     Dimension dimen(radiusBlur);
1428     EffectOption bgEffection = {dimen, saturation, brightness, maskColor,
1429         blurStyleOp->adaptiveColor, blurStyleOp->blurOption};
1430     return std::optional<EffectOption>(bgEffection);
1431 }
1432 
ApplyNewestOptionExecutedFromModifierToNode(const RefPtr<FrameNode> & optionHolderNode,const RefPtr<FrameNode> & targetNode)1433 void DragEventActuator::ApplyNewestOptionExecutedFromModifierToNode(
1434     const RefPtr<FrameNode>& optionHolderNode, const RefPtr<FrameNode>& targetNode)
1435 {
1436     auto optionsFromModifier = targetNode->GetDragPreviewOption().options;
1437     ACE_UPDATE_NODE_RENDER_CONTEXT(Opacity, optionsFromModifier.opacity, targetNode);
1438     if (optionsFromModifier.blurbgEffect.backGroundEffect.radius.IsValid()) {
1439         ACE_UPDATE_NODE_RENDER_CONTEXT(BackgroundEffect, optionsFromModifier.blurbgEffect.backGroundEffect, targetNode);
1440     }
1441     if (optionsFromModifier.shadow.has_value()) {
1442         // if shadow is unfilled, set shadow after animation
1443         if (optionsFromModifier.shadow->GetIsFilled()) {
1444             ACE_UPDATE_NODE_RENDER_CONTEXT(BackShadow, optionsFromModifier.shadow.value(), targetNode);
1445         }
1446     }
1447 
1448     const auto& target = targetNode->GetRenderContext();
1449     if (optionsFromModifier.borderRadius.has_value()) {
1450         target->UpdateBorderRadius(optionsFromModifier.borderRadius.value());
1451         target->UpdateClipEdge(true);
1452     }
1453 }
1454 
SetEventColumn(const RefPtr<DragEventActuator> & actuator)1455 void DragEventActuator::SetEventColumn(const RefPtr<DragEventActuator>& actuator)
1456 {
1457     TAG_LOGI(AceLogTag::ACE_DRAG, "DragEvent start set eventColumn.");
1458     auto pipelineContext = PipelineContext::GetCurrentContext();
1459     CHECK_NULL_VOID(pipelineContext);
1460     auto manager = pipelineContext->GetOverlayManager();
1461     CHECK_NULL_VOID(manager);
1462     if (manager->GetHasEvent()) {
1463         return;
1464     }
1465     auto rootNode = pipelineContext->GetRootElement();
1466     CHECK_NULL_VOID(rootNode);
1467     auto geometryNode = rootNode->GetGeometryNode();
1468     CHECK_NULL_VOID(geometryNode);
1469     auto width = geometryNode->GetFrameSize().Width();
1470     auto height = geometryNode->GetFrameSize().Height();
1471     // create columnNode
1472     auto columnNode = FrameNode::CreateFrameNode(V2::COLUMN_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
1473         AceType::MakeRefPtr<LinearLayoutPattern>(true));
1474     auto props = columnNode->GetLayoutProperty<LinearLayoutProperty>();
1475     auto targetSize = CalcSize(NG::CalcLength(width), NG::CalcLength(height));
1476     props->UpdateUserDefinedIdealSize(targetSize);
1477     BindClickEvent(columnNode);
1478     columnNode->MarkModifyDone();
1479     auto container = Container::Current();
1480     if (container && container->IsScenceBoardWindow()) {
1481         auto gestureHub = actuator->gestureEventHub_.Upgrade();
1482         CHECK_NULL_VOID(gestureHub);
1483         auto frameNode = gestureHub->GetFrameNode();
1484         CHECK_NULL_VOID(frameNode);
1485         auto windowScene = manager->FindWindowScene(frameNode);
1486         manager->MountEventToWindowScene(columnNode, windowScene);
1487     } else {
1488         manager->MountEventToRootNode(columnNode);
1489     }
1490     TAG_LOGI(AceLogTag::ACE_DRAG, "DragEvent set eventColumn success.");
1491 }
1492 
HideFilter()1493 void DragEventActuator::HideFilter()
1494 {
1495     auto gestureEventHub = gestureEventHub_.Upgrade();
1496     CHECK_NULL_VOID(gestureEventHub);
1497     auto frameNode = gestureEventHub->GetFrameNode();
1498     CHECK_NULL_VOID(frameNode);
1499     if (frameNode->GetTag() != V2::WEB_ETS_TAG) {
1500         return;
1501     }
1502     auto pipelineContext = PipelineContext::GetCurrentContext();
1503     CHECK_NULL_VOID(pipelineContext);
1504     auto manager = pipelineContext->GetOverlayManager();
1505     CHECK_NULL_VOID(manager);
1506     manager->RemoveFilterAnimation();
1507 }
1508 
HidePixelMap(bool startDrag,double x,double y,bool showAnimation)1509 void DragEventActuator::HidePixelMap(bool startDrag, double x, double y, bool showAnimation)
1510 {
1511     auto gestureEventHub = gestureEventHub_.Upgrade();
1512     CHECK_NULL_VOID(gestureEventHub);
1513     auto frameNode = gestureEventHub->GetFrameNode();
1514     CHECK_NULL_VOID(frameNode);
1515     auto pipelineContext = frameNode->GetContextRefPtr();
1516     CHECK_NULL_VOID(pipelineContext);
1517     auto manager = pipelineContext->GetOverlayManager();
1518     CHECK_NULL_VOID(manager);
1519     if (!startDrag) {
1520         manager->RemovePreviewBadgeNode();
1521         manager->RemoveGatherNodeWithAnimation();
1522     }
1523 
1524     if (showAnimation) {
1525         manager->RemovePixelMapAnimation(startDrag, x, y);
1526     } else {
1527         manager->RemovePixelMap();
1528     }
1529 }
1530 
HideEventColumn()1531 void DragEventActuator::HideEventColumn()
1532 {
1533     auto pipelineContext = PipelineContext::GetCurrentContext();
1534     CHECK_NULL_VOID(pipelineContext);
1535     auto manager = pipelineContext->GetOverlayManager();
1536     CHECK_NULL_VOID(manager);
1537     manager->RemoveEventColumn();
1538 }
1539 
BindClickEvent(const RefPtr<FrameNode> & columnNode)1540 void DragEventActuator::BindClickEvent(const RefPtr<FrameNode>& columnNode)
1541 {
1542     auto callback = [weak = WeakClaim(this)](GestureEvent& /* info */) {
1543         TAG_LOGI(AceLogTag::ACE_DRAG, "start click event callback");
1544         auto actuator = weak.Upgrade();
1545         CHECK_NULL_VOID(actuator);
1546         auto gestureHub = actuator->gestureEventHub_.Upgrade();
1547         CHECK_NULL_VOID(gestureHub);
1548         actuator->HideEventColumn();
1549         if (gestureHub->GetTextDraggable()) {
1550             actuator->HideTextAnimation();
1551         } else {
1552             actuator->HidePixelMap();
1553             actuator->HideFilter();
1554         }
1555     };
1556     auto columnGestureHub = columnNode->GetOrCreateGestureEventHub();
1557     CHECK_NULL_VOID(columnGestureHub);
1558     auto clickListener = MakeRefPtr<ClickEvent>(std::move(callback));
1559     columnGestureHub->AddClickEvent(clickListener);
1560     if (!GetIsBindOverlayValue(Claim(this))) {
1561         columnGestureHub->SetHitTestMode(HitTestMode::HTMBLOCK);
1562     }
1563 }
1564 
ShowPixelMapAnimation(const RefPtr<FrameNode> & imageNode,const RefPtr<FrameNode> & frameNode,bool hasContextMenu)1565 void DragEventActuator::ShowPixelMapAnimation(const RefPtr<FrameNode>& imageNode,
1566     const RefPtr<FrameNode>& frameNode, bool hasContextMenu)
1567 {
1568     CHECK_NULL_VOID(imageNode);
1569     auto imageContext = imageNode->GetRenderContext();
1570     CHECK_NULL_VOID(imageContext);
1571     CHECK_NULL_VOID(frameNode);
1572     frameNode->SetOptionsAfterApplied(optionsAfterApplied_);
1573     SetImageNodeInitAttr(frameNode, imageNode);
1574     // pixel map animation
1575     AnimationOption option;
1576     option.SetDuration(PIXELMAP_ANIMATION_DURATION);
1577     option.SetCurve(Curves::SHARP);
1578     option.SetOnFinishEvent([imageNode, frameNode]() {
1579         DragEventActuator::SetImageNodeFinishAttr(frameNode, imageNode);
1580     });
1581 
1582     AnimationUtils::Animate(
1583         option,
1584         [imageNode, hasContextMenu, weak = WeakClaim(RawPtr(frameNode))]() mutable {
1585             auto imageContext = imageNode->GetRenderContext();
1586             CHECK_NULL_VOID(imageContext);
1587             auto frameNode = weak.Upgrade();
1588             ApplyNewestOptionExecutedFromModifierToNode(frameNode, imageNode);
1589             if (hasContextMenu) {
1590                 BorderRadiusProperty borderRadius;
1591                 borderRadius.SetRadius(PIXELMAP_BORDER_RADIUS);
1592                 imageContext->UpdateBorderRadius(borderRadius);
1593             }
1594             DragEventActuator::ResetNode(frameNode);
1595         },
1596         option.GetOnFinishEvent());
1597 }
1598 
ExecutePreDragAction(const PreDragStatus preDragStatus,const RefPtr<FrameNode> & frameNode)1599 void DragEventActuator::ExecutePreDragAction(const PreDragStatus preDragStatus, const RefPtr<FrameNode>& frameNode)
1600 {
1601     auto mainPipeline = PipelineContext::GetMainPipelineContext();
1602     CHECK_NULL_VOID(mainPipeline);
1603     auto dragDropManager = mainPipeline->GetDragDropManager();
1604     CHECK_NULL_VOID(dragDropManager);
1605     if (dragDropManager->IsDragging() || dragDropManager->IsMSDPDragging()) {
1606         return;
1607     }
1608     RefPtr<EventHub> eventHub;
1609     if (frameNode) {
1610         eventHub = frameNode->GetEventHub<EventHub>();
1611     } else {
1612         auto preDragFrameNode = dragDropManager->GetPrepareDragFrameNode().Upgrade();
1613         CHECK_NULL_VOID(preDragFrameNode);
1614         eventHub = preDragFrameNode->GetEventHub<EventHub>();
1615     }
1616     CHECK_NULL_VOID(eventHub);
1617     auto gestureHub = eventHub->GetOrCreateGestureEventHub();
1618     CHECK_NULL_VOID(gestureHub);
1619     if (!gestureHub->IsAllowedDrag(eventHub) || gestureHub->GetTextDraggable()) {
1620         return;
1621     }
1622     auto onPreDragStatus = PreDragStatus::ACTION_CANCELED_BEFORE_DRAG;
1623     if (dragDropManager->GetPreDragStatus() <= preDragStatus &&
1624         preDragStatus != PreDragStatus::ACTION_CANCELED_BEFORE_DRAG) {
1625         auto nextPreDragStatus = static_cast<PreDragStatus>(static_cast<int32_t>(preDragStatus) + 1);
1626         dragDropManager->SetPreDragStatus(nextPreDragStatus);
1627         onPreDragStatus = preDragStatus;
1628     }
1629     auto onPreDragFunc = eventHub->GetOnPreDrag();
1630     CHECK_NULL_VOID(onPreDragFunc);
1631     if (preDragStatus == PreDragStatus::PREVIEW_LIFT_FINISHED ||
1632         preDragStatus == PreDragStatus::PREVIEW_LANDING_FINISHED) {
1633         auto taskScheduler = mainPipeline->GetTaskExecutor();
1634         CHECK_NULL_VOID(taskScheduler);
1635         taskScheduler->PostTask(
1636             [onPreDragStatus, callback = onPreDragFunc]() {
1637                 CHECK_NULL_VOID(callback);
1638                 callback(onPreDragStatus);
1639             },
1640             TaskExecutor::TaskType::UI, "ArkUIDragExecutePreDrag");
1641     } else {
1642         onPreDragFunc(onPreDragStatus);
1643     }
1644 }
1645 
SetThumbnailCallback(std::function<void (Offset)> && callback)1646 void DragEventActuator::SetThumbnailCallback(std::function<void(Offset)>&& callback)
1647 {
1648     textDragCallback_ = callback;
1649     longPressRecognizer_->SetThumbnailCallback(std::move(callback));
1650 }
1651 
SetTextPixelMap(const RefPtr<GestureEventHub> & gestureHub)1652 void DragEventActuator::SetTextPixelMap(const RefPtr<GestureEventHub>& gestureHub)
1653 {
1654     auto frameNode = gestureHub->GetFrameNode();
1655     CHECK_NULL_VOID(frameNode);
1656     auto pattern = frameNode->GetPattern<TextDragBase>();
1657     CHECK_NULL_VOID(pattern);
1658 
1659     auto dragNode = pattern->MoveDragNode();
1660     pattern->CloseSelectOverlay();
1661     CHECK_NULL_VOID(dragNode);
1662     auto pixelMap = dragNode->GetRenderContext()->GetThumbnailPixelMap();
1663     if (textPixelMap_) {
1664         gestureHub->SetPixelMap(textPixelMap_);
1665         textPixelMap_ = nullptr;
1666     } else if (pixelMap) {
1667         gestureHub->SetPixelMap(pixelMap);
1668     } else {
1669         gestureHub->SetPixelMap(nullptr);
1670     }
1671 }
1672 
SetTextAnimation(const RefPtr<GestureEventHub> & gestureHub,const Offset & globalLocation)1673 void DragEventActuator::SetTextAnimation(const RefPtr<GestureEventHub>& gestureHub, const Offset& globalLocation)
1674 {
1675     TAG_LOGD(AceLogTag::ACE_DRAG, "DragEvent start set textAnimation.");
1676     auto pipelineContext = PipelineContext::GetCurrentContext();
1677     CHECK_NULL_VOID(pipelineContext);
1678     auto manager = pipelineContext->GetOverlayManager();
1679     CHECK_NULL_VOID(manager);
1680     manager->SetHasFilter(false);
1681     CHECK_NULL_VOID(gestureHub);
1682     auto frameNode = gestureHub->GetFrameNode();
1683     CHECK_NULL_VOID(frameNode);
1684     auto pattern = frameNode->GetPattern<TextDragBase>();
1685     auto textBase = frameNode->GetPattern<TextBase>();
1686     CHECK_NULL_VOID(pattern);
1687     CHECK_NULL_VOID(textBase);
1688     if (!textBase->BetweenSelectedPosition(globalLocation)) {
1689         TAG_LOGD(AceLogTag::ACE_DRAG, "Position is between selected position, stop set text animation.");
1690         return;
1691     }
1692     auto isHandlesShow = pattern->IsHandlesShow();
1693     auto dragNode = pattern->MoveDragNode();
1694     CHECK_NULL_VOID(dragNode);
1695     dragNode->SetDragPreviewOptions(frameNode->GetDragPreviewOption());
1696     // create columnNode
1697     auto columnNode = FrameNode::CreateFrameNode(V2::COLUMN_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
1698         AceType::MakeRefPtr<LinearLayoutPattern>(true));
1699     columnNode->AddChild(dragNode);
1700     auto columnRenderContext = columnNode->GetRenderContext();
1701     if (columnRenderContext) {
1702         columnRenderContext->UpdatePosition(OffsetT<Dimension>(Dimension(0.0f), Dimension(0.0f)));
1703     }
1704     // mount to rootNode
1705     manager->MountPixelMapToRootNode(columnNode);
1706     auto textDragPattern = dragNode->GetPattern<TextDragPattern>();
1707     CHECK_NULL_VOID(textDragPattern);
1708     auto modifier = textDragPattern->GetOverlayModifier();
1709     CHECK_NULL_VOID(modifier);
1710     modifier->UpdateHandlesShowFlag(isHandlesShow);
1711     auto renderContext = dragNode->GetRenderContext();
1712     if (renderContext) {
1713         textPixelMap_ = renderContext->GetThumbnailPixelMap();
1714     }
1715     modifier->StartFloatingAnimate();
1716     pattern->CloseHandleAndSelect();
1717     TAG_LOGD(AceLogTag::ACE_DRAG, "DragEvent set text animation success.");
1718 }
1719 
HideTextAnimation(bool startDrag,double globalX,double globalY)1720 void DragEventActuator::HideTextAnimation(bool startDrag, double globalX, double globalY)
1721 {
1722     TAG_LOGD(AceLogTag::ACE_DRAG, "DragEvent start hide text animation.");
1723     auto gestureHub = gestureEventHub_.Upgrade();
1724     CHECK_NULL_VOID(gestureHub);
1725     bool isAllowedDrag = IsAllowedDrag();
1726     if (!gestureHub->GetTextDraggable() || !isAllowedDrag) {
1727         TAG_LOGD(AceLogTag::ACE_DRAG, "Text is not draggable, stop set hide text animation.");
1728         return;
1729     }
1730     auto frameNode = gestureHub->GetFrameNode();
1731     CHECK_NULL_VOID(frameNode);
1732     auto pattern = frameNode->GetPattern<TextDragBase>();
1733     CHECK_NULL_VOID(pattern);
1734     auto node = pattern->MoveDragNode();
1735     CHECK_NULL_VOID(node);
1736     auto textDragPattern = node->GetPattern<TextDragPattern>();
1737     CHECK_NULL_VOID(textDragPattern);
1738     auto modifier = textDragPattern->GetOverlayModifier();
1739     CHECK_NULL_VOID(modifier);
1740     auto removeColumnNode = [id = Container::CurrentId(), startDrag, weakPattern = WeakPtr<TextDragBase>(pattern),
1741             weakEvent = gestureEventHub_, weakModifier = WeakPtr<TextDragOverlayModifier>(modifier)] {
1742         ContainerScope scope(id);
1743         if (!startDrag) {
1744             auto pattern = weakPattern.Upgrade();
1745             CHECK_NULL_VOID(pattern);
1746             auto modifier = weakModifier.Upgrade();
1747             CHECK_NULL_VOID(modifier);
1748             pattern->ShowHandles(modifier->IsHandlesShow());
1749         }
1750         auto pipeline = PipelineContext::GetCurrentContext();
1751         CHECK_NULL_VOID(pipeline);
1752         auto manager = pipeline->GetOverlayManager();
1753         CHECK_NULL_VOID(manager);
1754         manager->RemovePixelMap();
1755         TAG_LOGD(AceLogTag::ACE_DRAG, "In removeColumnNode callback, set DragWindowVisible true.");
1756         auto gestureHub = weakEvent.Upgrade();
1757         CHECK_NULL_VOID(gestureHub);
1758         if (!gestureHub->IsPixelMapNeedScale()) {
1759             InteractionInterface::GetInstance()->SetDragWindowVisible(true);
1760         }
1761         gestureHub->SetPixelMap(nullptr);
1762     };
1763     AnimationOption option;
1764     option.SetDuration(PIXELMAP_ANIMATION_DURATION);
1765     option.SetCurve(Curves::SHARP);
1766     option.SetOnFinishEvent(removeColumnNode);
1767 
1768     auto pipeline = PipelineContext::GetCurrentContext();
1769     CHECK_NULL_VOID(pipeline);
1770     auto manager = pipeline->GetOverlayManager();
1771     auto dragNode = manager->GetPixelMapNode();
1772     CHECK_NULL_VOID(dragNode);
1773     auto dragFrame = dragNode->GetGeometryNode()->GetFrameRect();
1774     auto frameWidth = dragFrame.Width();
1775     auto frameHeight = dragFrame.Height();
1776     auto pixelMap = gestureHub->GetPixelMap();
1777     float scale = 1.0f;
1778     if (pixelMap) {
1779         scale = gestureHub->GetPixelMapScale(pixelMap->GetHeight(), pixelMap->GetWidth());
1780     }
1781     auto context = dragNode->GetRenderContext();
1782     CHECK_NULL_VOID(context);
1783     context->UpdateTransformScale(VectorF(1.0f, 1.0f));
1784     AnimationUtils::Animate(
1785         option,
1786         [context, startDrag, globalX, globalY, frameWidth, frameHeight, scale]() {
1787             if (startDrag) {
1788                 context->UpdatePosition(OffsetT<Dimension>(Dimension(globalX + frameWidth * PIXELMAP_WIDTH_RATE),
1789                     Dimension(globalY + frameHeight * PIXELMAP_HEIGHT_RATE)));
1790                 context->UpdateTransformScale(VectorF(scale, scale));
1791                 context->OnModifyDone();
1792             }
1793         },
1794         option.GetOnFinishEvent());
1795     TAG_LOGD(AceLogTag::ACE_DRAG, "DragEvent set hide text animation success.");
1796 }
1797 
1798 // update ImageNode default attr before floating
SetImageNodeInitAttr(const RefPtr<FrameNode> & frameNode,const RefPtr<FrameNode> & imageNode)1799 void DragEventActuator::SetImageNodeInitAttr(const RefPtr<FrameNode>& frameNode, const RefPtr<FrameNode>& imageNode)
1800 {
1801     CHECK_NULL_VOID(imageNode);
1802     CHECK_NULL_VOID(frameNode);
1803     auto imageContext = imageNode->GetRenderContext();
1804     CHECK_NULL_VOID(imageContext);
1805     auto dragPreviewOption = frameNode->GetDragPreviewOption();
1806 
1807     // update default scale
1808     bool defaultAnimationBeforeLifting = dragPreviewOption.defaultAnimationBeforeLifting;
1809     if (defaultAnimationBeforeLifting) {
1810         auto layoutProperty = frameNode->GetLayoutProperty();
1811         if (layoutProperty) {
1812             layoutProperty->UpdateVisibility(VisibleType::INVISIBLE);
1813         }
1814         imageContext->UpdateTransformScale({ DEFAULT_ANIMATION_SCALE, DEFAULT_ANIMATION_SCALE });
1815     } else {
1816         imageContext->UpdateTransformScale({ 1.0f, 1.0f });
1817     }
1818 
1819     // update shadow
1820     auto shadow = Shadow::CreateShadow(ShadowStyle::None);
1821     if (dragPreviewOption.options.shadow.has_value()) {
1822         shadow = dragPreviewOption.options.shadow.value();
1823         shadow.SetColor(Color(0x00000000));
1824     }
1825     imageContext->UpdateBackShadow(shadow);
1826 
1827     // update radius
1828     BorderRadiusProperty borderRadius;
1829     borderRadius.SetRadius(0.0_vp);
1830     imageContext->UpdateBorderRadius(borderRadius);
1831 
1832     // update opacity
1833     imageContext->UpdateOpacity(1.0f);
1834 }
1835 
SetImageNodeFinishAttr(const RefPtr<FrameNode> & frameNode,const RefPtr<FrameNode> & imageNode)1836 void DragEventActuator::SetImageNodeFinishAttr(const RefPtr<FrameNode>& frameNode,
1837     const RefPtr<FrameNode>& imageNode)
1838 {
1839     CHECK_NULL_VOID(imageNode);
1840     CHECK_NULL_VOID(frameNode);
1841     auto imageContext = imageNode->GetRenderContext();
1842     CHECK_NULL_VOID(imageContext);
1843     auto dragPreviewOption = frameNode->GetDragPreviewOption();
1844     if (dragPreviewOption.options.shadow.has_value() && !dragPreviewOption.options.shadow->GetIsFilled()) {
1845         imageContext->UpdateBackShadow(dragPreviewOption.options.shadow.value());
1846     }
1847 }
1848 
GetIsBindOverlayValue(const RefPtr<DragEventActuator> & actuator)1849 bool DragEventActuator::GetIsBindOverlayValue(const RefPtr<DragEventActuator>& actuator)
1850 {
1851     auto gestureHub = actuator->gestureEventHub_.Upgrade();
1852     CHECK_NULL_RETURN(gestureHub, true);
1853     auto frameNode = gestureHub->GetFrameNode();
1854     CHECK_NULL_RETURN(frameNode, true);
1855     bool isBindOverlayValue = frameNode->GetLayoutProperty()->GetIsBindOverlayValue(false);
1856     return isBindOverlayValue;
1857 }
1858 
IsAllowedDrag()1859 bool DragEventActuator::IsAllowedDrag()
1860 {
1861     auto gestureHub = gestureEventHub_.Upgrade();
1862     CHECK_NULL_RETURN(gestureHub, false);
1863     auto frameNode = gestureHub->GetFrameNode();
1864     CHECK_NULL_RETURN(frameNode, false);
1865     auto eventHub = frameNode->GetEventHub<EventHub>();
1866     CHECK_NULL_RETURN(eventHub, false);
1867     bool isAllowedDrag = gestureHub->IsAllowedDrag(eventHub);
1868     return isAllowedDrag;
1869 }
1870 
CopyDragEvent(const RefPtr<DragEventActuator> & dragEventActuator)1871 void DragEventActuator::CopyDragEvent(const RefPtr<DragEventActuator>& dragEventActuator)
1872 {
1873     userCallback_ = dragEventActuator->userCallback_;
1874     customCallback_ = dragEventActuator->customCallback_;
1875     panRecognizer_ = MakeRefPtr<PanRecognizer>(fingers_, direction_, distance_);
1876     panRecognizer_->SetGestureInfo(MakeRefPtr<GestureInfo>(GestureTypeName::DRAG, GestureTypeName::DRAG, true));
1877     longPressRecognizer_ = AceType::MakeRefPtr<LongPressRecognizer>(LONG_PRESS_DURATION, fingers_, false, false);
1878     longPressRecognizer_->SetGestureInfo(MakeRefPtr<GestureInfo>(GestureTypeName::DRAG, GestureTypeName::DRAG, true));
1879     previewLongPressRecognizer_ =
1880         AceType::MakeRefPtr<LongPressRecognizer>(PREVIEW_LONG_PRESS_RECONGNIZER, fingers_, false, false);
1881     previewLongPressRecognizer_->SetGestureInfo(
1882         MakeRefPtr<GestureInfo>(GestureTypeName::DRAG, GestureTypeName::DRAG, true));
1883     isNotInPreviewState_ = false;
1884     actionStart_ = dragEventActuator->actionStart_;
1885     longPressUpdate_ = dragEventActuator->longPressUpdate_;
1886     actionCancel_ = dragEventActuator->actionCancel_;
1887     textDragCallback_ = dragEventActuator->textDragCallback_;
1888     longPressInfo_ = dragEventActuator->longPressInfo_;
1889 }
1890 
FlushSyncGeometryNodeTasks()1891 void DragEventActuator::FlushSyncGeometryNodeTasks()
1892 {
1893     auto pipeline = PipelineBase::GetCurrentContext();
1894     CHECK_NULL_VOID(pipeline);
1895     pipeline->FlushSyncGeometryNodeTasks();
1896 }
1897 
SetGatherNodeAboveFilter(const RefPtr<DragEventActuator> & actuator)1898 void DragEventActuator::SetGatherNodeAboveFilter(const RefPtr<DragEventActuator>& actuator)
1899 {
1900     CHECK_NULL_VOID(actuator);
1901     if (!actuator->IsNeedGather()) {
1902         return;
1903     }
1904     auto pipelineContext = PipelineContext::GetCurrentContext();
1905     CHECK_NULL_VOID(pipelineContext);
1906     auto manager = pipelineContext->GetOverlayManager();
1907     CHECK_NULL_VOID(manager);
1908     auto gestureHub = actuator->gestureEventHub_.Upgrade();
1909     CHECK_NULL_VOID(gestureHub);
1910     auto frameNode = gestureHub->GetFrameNode();
1911     CHECK_NULL_VOID(frameNode);
1912     auto gatherNode = manager->GetGatherNode();
1913     auto gatherNodeChildrenInfo = manager->GetGatherNodeChildrenInfo();
1914     manager->RemoveGatherNode();
1915     MountGatherNode(manager, frameNode, gatherNode, gatherNodeChildrenInfo);
1916 }
1917 
GetOrCreateGatherNode(const RefPtr<NG::OverlayManager> & overlayManager,const RefPtr<DragEventActuator> & actuator,std::vector<GatherNodeChildInfo> & gatherNodeChildrenInfo)1918 RefPtr<FrameNode> DragEventActuator::GetOrCreateGatherNode(const RefPtr<NG::OverlayManager>& overlayManager,
1919     const RefPtr<DragEventActuator>& actuator, std::vector<GatherNodeChildInfo>& gatherNodeChildrenInfo)
1920 {
1921     CHECK_NULL_RETURN(actuator, nullptr);
1922     if (!actuator->IsNeedGather()) {
1923         return nullptr;
1924     }
1925     auto gestureHub = actuator->gestureEventHub_.Upgrade();
1926     CHECK_NULL_RETURN(gestureHub, nullptr);
1927     auto frameNode = gestureHub->GetFrameNode();
1928     CHECK_NULL_RETURN(frameNode, nullptr);
1929     auto previewOptions = frameNode->GetDragPreviewOption();
1930     if (!previewOptions.isMultiSelectionEnabled) {
1931         return nullptr;
1932     }
1933     CHECK_NULL_RETURN(overlayManager, nullptr);
1934     auto gatherNode = overlayManager->GetGatherNode();
1935     if (!gatherNode) {
1936         auto gatherNode = CreateGatherNode(actuator);
1937         if (gatherNode) {
1938             MarkDirtyGatherNode(gatherNode);
1939         }
1940         gatherNodeChildrenInfo = actuator->GetGatherNodeChildrenInfo();
1941         actuator->ClearGatherNodeChildrenInfo();
1942         actuator->SetGatherNode(nullptr);
1943         return gatherNode;
1944     } else {
1945         gatherNodeChildrenInfo = overlayManager->GetGatherNodeChildrenInfo();
1946         overlayManager->RemoveGatherNode();
1947     }
1948     return gatherNode;
1949 }
1950 
CreateGatherNode(const RefPtr<DragEventActuator> & actuator)1951 RefPtr<FrameNode> DragEventActuator::CreateGatherNode(const RefPtr<DragEventActuator>& actuator)
1952 {
1953     CHECK_NULL_RETURN(actuator, nullptr);
1954     auto gestureHub = actuator->gestureEventHub_.Upgrade();
1955     CHECK_NULL_RETURN(gestureHub, nullptr);
1956     auto frameNode = gestureHub->GetFrameNode();
1957     CHECK_NULL_RETURN(frameNode, nullptr);
1958 
1959     auto pipelineContext = PipelineContext::GetCurrentContext();
1960     CHECK_NULL_RETURN(pipelineContext, nullptr);
1961     auto manager = pipelineContext->GetOverlayManager();
1962     CHECK_NULL_RETURN(manager, nullptr);
1963 
1964     if (manager->GetHasGatherNode()) {
1965         TAG_LOGW(AceLogTag::ACE_DRAG, "Not need create gather node, already have");
1966         return nullptr;
1967     }
1968 
1969     if (!actuator->IsNeedGather()) {
1970         TAG_LOGI(AceLogTag::ACE_DRAG, "Not need create gather node, not need gather");
1971         return nullptr;
1972     }
1973     auto fatherNode = actuator->itemParentNode_.Upgrade();
1974     CHECK_NULL_RETURN(fatherNode, nullptr);
1975     auto scrollPattern = fatherNode->GetPattern<ScrollablePattern>();
1976     CHECK_NULL_RETURN(scrollPattern, nullptr);
1977     auto children = scrollPattern->GetVisibleSelectedItems();
1978     if (children.size() < 1) {
1979         return nullptr;
1980     }
1981     auto stackNode = FrameNode::GetOrCreateFrameNode(V2::STACK_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
1982         []() { return AceType::MakeRefPtr<StackPattern>(); });
1983     actuator->ClearGatherNodeChildrenInfo();
1984     auto geometryNode = stackNode->GetGeometryNode();
1985     CHECK_NULL_RETURN(geometryNode, nullptr);
1986     geometryNode->SetFrameOffset({0.0f, 0.0f});
1987 
1988     for (auto iter = children.rbegin(); iter != children.rend(); iter++) {
1989         auto itemFrameNode = (*iter);
1990         if (itemFrameNode == frameNode) {
1991             continue;
1992         }
1993         GatherNodeChildInfo gatherNodeChildInfo;
1994         auto imageNode = CreateImageNode(itemFrameNode, gatherNodeChildInfo);
1995         CHECK_NULL_RETURN(imageNode, nullptr);
1996         stackNode->AddChild(imageNode);
1997         actuator->PushBackGatherNodeChild(gatherNodeChildInfo);
1998     }
1999     actuator->SetGatherNode(stackNode);
2000     TAG_LOGI(AceLogTag::ACE_DRAG, "Create gather node success, count %{public}d",
2001         static_cast<int32_t>(children.size()));
2002     return stackNode;
2003 }
2004 
CreateImageNode(const RefPtr<FrameNode> & frameNode,GatherNodeChildInfo & gatherNodeChildInfo)2005 RefPtr<FrameNode> DragEventActuator::CreateImageNode(const RefPtr<FrameNode>& frameNode,
2006     GatherNodeChildInfo& gatherNodeChildInfo)
2007 {
2008     auto context = frameNode->GetRenderContext();
2009     CHECK_NULL_RETURN(context, nullptr);
2010     GetFrameNodePreviewPixelMap(frameNode);
2011     auto gestureHub = frameNode->GetOrCreateGestureEventHub();
2012     CHECK_NULL_RETURN(gestureHub, nullptr);
2013     auto pixelMap = gestureHub->GetDragPreviewPixelMap();
2014     int32_t width = 0;
2015     int32_t height = 0;
2016     if (pixelMap) {
2017         width = pixelMap->GetWidth();
2018         height = pixelMap->GetHeight();
2019     }
2020     auto offset = GetFloatImageOffset(frameNode, pixelMap);
2021     auto imageNode = FrameNode::GetOrCreateFrameNode(V2::IMAGE_ETS_TAG,
2022         ElementRegister::GetInstance()->MakeUniqueId(), []() { return AceType::MakeRefPtr<ImagePattern>(); });
2023 
2024     imageNode->SetDragPreviewOptions(frameNode->GetDragPreviewOption());
2025     auto renderProps = imageNode->GetPaintProperty<ImageRenderProperty>();
2026     CHECK_NULL_RETURN(renderProps, nullptr);
2027     renderProps->UpdateImageInterpolation(ImageInterpolation::HIGH);
2028     renderProps->UpdateNeedBorderRadius(false);
2029     auto props = imageNode->GetLayoutProperty<ImageLayoutProperty>();
2030     CHECK_NULL_RETURN(props, nullptr);
2031     props->UpdateAutoResize(false);
2032     props->UpdateImageSourceInfo(ImageSourceInfo(pixelMap));
2033     auto targetSize = CalcSize(NG::CalcLength(width), NG::CalcLength(height));
2034     props->UpdateUserDefinedIdealSize(targetSize);
2035     auto imageContext = imageNode->GetRenderContext();
2036     CHECK_NULL_RETURN(imageContext, nullptr);
2037     imageContext->UpdatePosition(OffsetT<Dimension>(Dimension(offset.GetX()), Dimension(offset.GetY())));
2038     Vector5F rotate = Vector5F(0.0f, 0.0f, 1.0f, 0.0f, 0.0f);
2039     imageContext->UpdateTransformRotate(rotate);
2040     imageContext->UpdateClipEdge(true);
2041     imageContext->UpdateBorderRadius(BorderRadiusProperty(Dimension()));
2042     imageContext->UpdateOpacity(1.0f);
2043     ClickEffectInfo clickEffectInfo;
2044     clickEffectInfo.level = ClickEffectLevel::LIGHT;
2045     clickEffectInfo.scaleNumber = SCALE_NUMBER;
2046     imageContext->UpdateClickEffectLevel(clickEffectInfo);
2047 
2048     gatherNodeChildInfo = {imageNode, offset, width, height, width / 2.0f, height / 2.0f};
2049     return imageNode;
2050 }
2051 
MarkDirtyGatherNode(const RefPtr<FrameNode> & gatherNode)2052 void DragEventActuator::MarkDirtyGatherNode(const RefPtr<FrameNode>& gatherNode)
2053 {
2054     CHECK_NULL_VOID(gatherNode);
2055     gatherNode->MarkModifyDone();
2056     gatherNode->SetLayoutDirtyMarked(true);
2057     auto context = gatherNode->GetContext();
2058     if (context) {
2059         context->FlushUITaskWithSingleDirtyNode(gatherNode);
2060     }
2061 
2062     auto children = gatherNode->GetChildren();
2063     for (const auto& child : children) {
2064         CHECK_NULL_VOID(child);
2065         auto imageNode = AceType::DynamicCast<FrameNode>(child);
2066         CHECK_NULL_VOID(imageNode);
2067         imageNode->MarkModifyDone();
2068         imageNode->SetLayoutDirtyMarked(true);
2069         if (context) {
2070             context->FlushUITaskWithSingleDirtyNode(imageNode);
2071         }
2072     }
2073 }
2074 
ResetNode(const RefPtr<FrameNode> & frameNode)2075 void DragEventActuator::ResetNode(const RefPtr<FrameNode>& frameNode)
2076 {
2077     CHECK_NULL_VOID(frameNode);
2078     bool defaultAnimationBeforeLifting = frameNode->GetDragPreviewOption().defaultAnimationBeforeLifting;
2079     if (!defaultAnimationBeforeLifting) {
2080         return;
2081     }
2082     auto frameContext = frameNode->GetRenderContext();
2083     CHECK_NULL_VOID(frameContext);
2084     frameContext->UpdateTransformScale({ 1.0f, 1.0f });
2085     auto layoutProperty = frameNode->GetLayoutProperty();
2086     if (layoutProperty) {
2087         layoutProperty->UpdateVisibility(VisibleType::VISIBLE);
2088     }
2089 }
2090 
MountGatherNode(const RefPtr<OverlayManager> & overlayManager,const RefPtr<FrameNode> & frameNode,const RefPtr<FrameNode> & gatherNode,const std::vector<GatherNodeChildInfo> & gatherNodeChildrenInfo)2091 void DragEventActuator::MountGatherNode(const RefPtr<OverlayManager>& overlayManager,
2092     const RefPtr<FrameNode>& frameNode, const RefPtr<FrameNode>& gatherNode,
2093     const std::vector<GatherNodeChildInfo>& gatherNodeChildrenInfo)
2094 {
2095     if (!overlayManager || !frameNode || !gatherNode) {
2096         return;
2097     }
2098     TAG_LOGI(AceLogTag::ACE_DRAG, "Mount gather node");
2099     auto container = Container::Current();
2100     if (container && container->IsScenceBoardWindow()) {
2101         auto windowScene = overlayManager->FindWindowScene(frameNode);
2102         overlayManager->MountGatherNodeToWindowScene(gatherNode, gatherNodeChildrenInfo, windowScene);
2103     } else {
2104         overlayManager->MountGatherNodeToRootNode(gatherNode, gatherNodeChildrenInfo);
2105     }
2106     MarkDirtyGatherNode(gatherNode);
2107 }
2108 
GetFrameNodePreviewPixelMap(const RefPtr<FrameNode> & frameNode)2109 void DragEventActuator::GetFrameNodePreviewPixelMap(const RefPtr<FrameNode>& frameNode)
2110 {
2111     CHECK_NULL_VOID(frameNode);
2112     auto gestureHub = frameNode->GetOrCreateGestureEventHub();
2113     CHECK_NULL_VOID(gestureHub);
2114     auto dragPreviewInfo = frameNode->GetDragPreview();
2115     auto pipeline = PipelineContext::GetCurrentContext();
2116     CHECK_NULL_VOID(pipeline);
2117     if (dragPreviewInfo.inspectorId != "") {
2118         auto previewPixelMap = GetPreviewPixelMap(dragPreviewInfo.inspectorId, frameNode);
2119         gestureHub->SetDragPreviewPixelMap(previewPixelMap);
2120         return;
2121     } else if (dragPreviewInfo.pixelMap != nullptr) {
2122         gestureHub->SetDragPreviewPixelMap(dragPreviewInfo.pixelMap);
2123         return;
2124     }
2125     auto context = frameNode->GetRenderContext();
2126     CHECK_NULL_VOID(context);
2127     auto pixelMap = context->GetThumbnailPixelMap(true);
2128     gestureHub->SetDragPreviewPixelMap(pixelMap);
2129 }
2130 
IsBelongToMultiItemNode(const RefPtr<FrameNode> & frameNode)2131 bool DragEventActuator::IsBelongToMultiItemNode(const RefPtr<FrameNode>& frameNode)
2132 {
2133     CHECK_NULL_RETURN(frameNode, false);
2134     auto pipeline = PipelineContext::GetCurrentContext();
2135     CHECK_NULL_RETURN(pipeline, false);
2136     auto dragDropManager = pipeline->GetDragDropManager();
2137     CHECK_NULL_RETURN(dragDropManager, false);
2138     if (IsSelectedItemNode(frameNode)) {
2139         isSelectedItemNode_ = true;
2140         FindItemParentNode(frameNode);
2141         return false;
2142     }
2143     isSelectedItemNode_ = false;
2144     auto uiNode = frameNode->GetParent();
2145     CHECK_NULL_RETURN(uiNode, false);
2146     while (!IsSelectedItemNode(uiNode)) {
2147         uiNode = uiNode->GetParent();
2148         CHECK_NULL_RETURN(uiNode, false);
2149     }
2150     return true;
2151 }
2152 
IsSelectedItemNode(const RefPtr<UINode> & uiNode)2153 bool DragEventActuator::IsSelectedItemNode(const RefPtr<UINode>& uiNode)
2154 {
2155     auto frameNode = AceType::DynamicCast<FrameNode>(uiNode);
2156     CHECK_NULL_RETURN(frameNode, false);
2157     auto gestureHub = frameNode->GetOrCreateGestureEventHub();
2158     CHECK_NULL_RETURN(gestureHub, false);
2159     auto eventHub = frameNode->GetEventHub<EventHub>();
2160     CHECK_NULL_RETURN(eventHub, false);
2161     auto dragPreview = frameNode->GetDragPreviewOption();
2162     if (!dragPreview.isMultiSelectionEnabled) {
2163         return false;
2164     }
2165     bool isAllowedDrag = gestureHub->IsAllowedDrag(eventHub);
2166     if (!isAllowedDrag) {
2167         return false;
2168     }
2169     if (frameNode->GetTag() == V2::GRID_ITEM_ETS_TAG) {
2170         auto itemPattern = frameNode->GetPattern<GridItemPattern>();
2171         CHECK_NULL_RETURN(itemPattern, false);
2172         if (itemPattern->IsSelected()) {
2173             return true;
2174         }
2175     }
2176     if (frameNode->GetTag() == V2::LIST_ITEM_ETS_TAG) {
2177         auto itemPattern = frameNode->GetPattern<ListItemPattern>();
2178         CHECK_NULL_RETURN(itemPattern, false);
2179         if (itemPattern->IsSelected()) {
2180             return true;
2181         }
2182     }
2183     return false;
2184 }
2185 
FindItemParentNode(const RefPtr<FrameNode> & frameNode)2186 void DragEventActuator::FindItemParentNode(const RefPtr<FrameNode>& frameNode)
2187 {
2188     itemParentNode_ = nullptr;
2189     CHECK_NULL_VOID(frameNode);
2190     if (frameNode->GetTag() != V2::GRID_ITEM_ETS_TAG && frameNode->GetTag() != V2::LIST_ITEM_ETS_TAG) {
2191         return;
2192     }
2193     auto parentType = frameNode->GetTag() == V2::GRID_ITEM_ETS_TAG ? V2::GRID_ETS_TAG : V2::LIST_ETS_TAG;
2194     auto uiNode = frameNode->GetParent();
2195     CHECK_NULL_VOID(uiNode);
2196     while (uiNode->GetTag() != parentType) {
2197         uiNode = uiNode->GetParent();
2198         CHECK_NULL_VOID(uiNode);
2199     }
2200     auto parentNode = AceType::DynamicCast<FrameNode>(uiNode);
2201     itemParentNode_ = parentNode;
2202 }
2203 
IsNeedGather() const2204 bool DragEventActuator::IsNeedGather() const
2205 {
2206     auto fatherNode = itemParentNode_.Upgrade();
2207     CHECK_NULL_RETURN(fatherNode, false);
2208     auto scrollPattern = fatherNode->GetPattern<ScrollablePattern>();
2209     CHECK_NULL_RETURN(scrollPattern, false);
2210     auto children = scrollPattern->GetVisibleSelectedItems();
2211     if (!isSelectedItemNode_ || children.size() < 1) {
2212         return false;
2213     }
2214     return true;
2215 }
2216 
AddTouchListener(const TouchRestrict & touchRestrict)2217 void DragEventActuator::AddTouchListener(const TouchRestrict& touchRestrict)
2218 {
2219     CHECK_NULL_VOID(userCallback_);
2220     auto gestureHub = gestureEventHub_.Upgrade();
2221     CHECK_NULL_VOID(gestureHub);
2222     auto frameNode = gestureHub->GetFrameNode();
2223     CHECK_NULL_VOID(frameNode);
2224     if (!IsGlobalStatusSuitableForDragging() || !IsCurrentNodeStatusSuitableForDragging(frameNode, touchRestrict)) {
2225         gestureHub->RemoveTouchEvent(touchListener_);
2226         return;
2227     }
2228     auto focusHub = frameNode->GetFocusHub();
2229     bool hasContextMenuUsingGesture = focusHub ?
2230         focusHub->FindContextMenuOnKeyEvent(OnKeyEventType::CONTEXT_MENU) : false;
2231     auto touchTask = [hasContextMenuUsingGesture, weak = WeakClaim(this)](const TouchEventInfo& info) {
2232         auto actuator = weak.Upgrade();
2233         CHECK_NULL_VOID(actuator);
2234         if (info.GetTouches().empty()) {
2235             return;
2236         }
2237         if (info.GetTouches().front().GetTouchType() == TouchType::UP) {
2238             actuator->HandleTouchUpEvent();
2239         } else if (info.GetTouches().front().GetTouchType() == TouchType::CANCEL) {
2240             actuator->HandleTouchCancelEvent();
2241         } else if (info.GetTouches().front().GetTouchType() == TouchType::MOVE) {
2242             if (hasContextMenuUsingGesture) {
2243                 auto point = Point(info.GetTouches().front().GetGlobalLocation().GetX(),
2244                                    info.GetTouches().front().GetGlobalLocation().GetY());
2245                 actuator->HandleDragDampingMove(point, info.GetTouches().front().GetFingerId());
2246             }
2247             actuator->HandleTouchMoveEvent();
2248         }
2249     };
2250     gestureHub->RemoveTouchEvent(touchListener_);
2251     touchListener_ = AceType::MakeRefPtr<TouchEventImpl>(std::move(touchTask));
2252     gestureHub->AddTouchEvent(touchListener_);
2253 }
2254 
HandleTouchUpEvent()2255 void DragEventActuator::HandleTouchUpEvent()
2256 {
2257     auto pipelineContext = PipelineContext::GetCurrentContext();
2258     CHECK_NULL_VOID(pipelineContext);
2259     auto dragDropManager = pipelineContext->GetDragDropManager();
2260     CHECK_NULL_VOID(dragDropManager);
2261     dragDropManager->SetHasGatherNode(false);
2262     DragAnimationHelper::PlayNodeResetAnimation(Claim(this));
2263     ResetResponseRegion();
2264     auto manager = pipelineContext->GetOverlayManager();
2265     CHECK_NULL_VOID(manager);
2266     if (IsNeedGather() && !manager->IsGatherWithMenu()) {
2267         SetGatherNode(nullptr);
2268         ClearGatherNodeChildrenInfo();
2269         auto manager = pipelineContext->GetOverlayManager();
2270         CHECK_NULL_VOID(manager);
2271         manager->RemoveGatherNodeWithAnimation();
2272     }
2273 }
2274 
HandleTouchCancelEvent()2275 void DragEventActuator::HandleTouchCancelEvent()
2276 {
2277     auto pipelineContext = PipelineContext::GetCurrentContext();
2278     CHECK_NULL_VOID(pipelineContext);
2279     auto dragDropManager = pipelineContext->GetDragDropManager();
2280     CHECK_NULL_VOID(dragDropManager);
2281     dragDropManager->SetHasGatherNode(false);
2282     ResetResponseRegion();
2283 }
2284 
HandleTouchMoveEvent()2285 void DragEventActuator::HandleTouchMoveEvent()
2286 {
2287     if (longPressRecognizer_ && isOnBeforeLiftingAnimation &&
2288         longPressRecognizer_->GetGestureDisposal() == GestureDisposal::REJECT) {
2289         SetGatherNode(nullptr);
2290         ClearGatherNodeChildrenInfo();
2291         auto pipelineContext = PipelineContext::GetCurrentContext();
2292         CHECK_NULL_VOID(pipelineContext);
2293         auto manager = pipelineContext->GetOverlayManager();
2294         CHECK_NULL_VOID(manager);
2295         manager->RemoveGatherNode();
2296         isOnBeforeLiftingAnimation = false;
2297         ResetResponseRegion();
2298     }
2299 }
2300 
SetGatherNode(const RefPtr<FrameNode> & gatherNode)2301 void DragEventActuator::SetGatherNode(const RefPtr<FrameNode>& gatherNode)
2302 {
2303     gatherNode_ = gatherNode;
2304 }
2305 
GetGatherNode() const2306 RefPtr<FrameNode> DragEventActuator::GetGatherNode() const
2307 {
2308     return gatherNode_;
2309 }
2310 
GetGatherNodeChildrenInfo() const2311 const std::vector<GatherNodeChildInfo>& DragEventActuator::GetGatherNodeChildrenInfo() const
2312 {
2313     return gatherNodeChildrenInfo_;
2314 }
2315 
ClearGatherNodeChildrenInfo()2316 void DragEventActuator::ClearGatherNodeChildrenInfo()
2317 {
2318     gatherNodeChildrenInfo_.clear();
2319 }
2320 
PushBackGatherNodeChild(GatherNodeChildInfo & gatherNodeChild)2321 void DragEventActuator::PushBackGatherNodeChild(GatherNodeChildInfo& gatherNodeChild)
2322 {
2323     gatherNodeChildrenInfo_.emplace_back(gatherNodeChild);
2324 }
2325 
GetItemParentNode() const2326 const RefPtr<FrameNode> DragEventActuator::GetItemParentNode() const
2327 {
2328     return itemParentNode_.Upgrade();
2329 }
2330 
GetFrameNode()2331 RefPtr<FrameNode> DragEventActuator::GetFrameNode()
2332 {
2333     auto gestureHub = gestureEventHub_.Upgrade();
2334     CHECK_NULL_RETURN(gestureHub, nullptr);
2335     auto frameNode = gestureHub->GetFrameNode();
2336     return frameNode;
2337 }
2338 
PrepareShadowParametersForDragData(const RefPtr<FrameNode> & frameNode,std::unique_ptr<JsonValue> & arkExtraInfoJson,float scale)2339 void DragEventActuator::PrepareShadowParametersForDragData(const RefPtr<FrameNode>& frameNode,
2340     std::unique_ptr<JsonValue>& arkExtraInfoJson, float scale)
2341 {
2342     CHECK_NULL_VOID(frameNode);
2343     CHECK_NULL_VOID(arkExtraInfoJson);
2344     auto dragPreviewOption = frameNode->GetDragPreviewOption();
2345     auto shadow = dragPreviewOption.options.shadow;
2346     if (!shadow.has_value() || !shadow->IsValid()) {
2347         arkExtraInfoJson->Put("shadow_enable", false);
2348         return;
2349     }
2350     auto frameTag = frameNode->GetTag();
2351     auto gestureHub = frameNode->GetOrCreateGestureEventHub();
2352     CHECK_NULL_VOID(gestureHub);
2353     if (gestureHub->IsTextCategoryComponent(frameTag) && gestureHub->GetTextDraggable() &&
2354         gestureHub->GetIsTextDraggable()) {
2355         auto stringPath = dragPreviewOption.options.shadowPath;
2356         RSPath path;
2357         if (path.BuildFromSVGString(stringPath)) {
2358             RSMatrix matrix;
2359             matrix.Set(RSMatrix::SCALE_X, scale);
2360             matrix.Set(RSMatrix::SCALE_Y, scale);
2361             path.Transform(matrix);
2362             stringPath = path.ConvertToSVGString();
2363         }
2364         arkExtraInfoJson->Put("drag_type", "text");
2365         arkExtraInfoJson->Put("drag_shadow_path", stringPath.c_str());
2366     } else {
2367         arkExtraInfoJson->Put("drag_type", "non-text");
2368     }
2369     arkExtraInfoJson->Put("shadow_enable", true);
2370     ParseShadowInfo(shadow.value(), arkExtraInfoJson);
2371 }
2372 
ParseShadowInfo(Shadow & shadow,std::unique_ptr<JsonValue> & arkExtraInfoJson)2373 void DragEventActuator::ParseShadowInfo(Shadow& shadow, std::unique_ptr<JsonValue>& arkExtraInfoJson)
2374 {
2375     arkExtraInfoJson->Put("shadow_is_filled", shadow.GetIsFilled());
2376     arkExtraInfoJson->Put("drag_shadow_OffsetX", shadow.GetOffset().GetX());
2377     arkExtraInfoJson->Put("drag_shadow_OffsetY", shadow.GetOffset().GetY());
2378     arkExtraInfoJson->Put("shadow_mask", shadow.GetShadowType() == ShadowType::BLUR);
2379     int32_t argb = static_cast<int32_t>(shadow.GetColor().GetValue());
2380     arkExtraInfoJson->Put("drag_shadow_argb", argb);
2381     int64_t strategy = static_cast<int64_t>(shadow.GetShadowColorStrategy());
2382     arkExtraInfoJson->Put("shadow_color_strategy", strategy);
2383     arkExtraInfoJson->Put("shadow_corner", shadow.GetBlurRadius());
2384     arkExtraInfoJson->Put("shadow_elevation", shadow.GetElevation());
2385     arkExtraInfoJson->Put("shadow_is_hardwareacceleration", shadow.GetHardwareAcceleration());
2386 }
2387 
GetDefaultShadow()2388 std::optional<Shadow> DragEventActuator::GetDefaultShadow()
2389 {
2390     auto pipelineContext = PipelineContext::GetCurrentContext();
2391     CHECK_NULL_RETURN(pipelineContext, std::nullopt);
2392     auto shadowTheme = pipelineContext->GetTheme<ShadowTheme>();
2393     CHECK_NULL_RETURN(shadowTheme, std::nullopt);
2394     auto colorMode = SystemProperties::GetColorMode();
2395     auto shadow = shadowTheme->GetShadow(ShadowStyle::OuterFloatingSM, colorMode);
2396     shadow.SetIsFilled(true);
2397     return shadow;
2398 }
2399 
PrepareRadiusParametersForDragData(const RefPtr<FrameNode> & frameNode,std::unique_ptr<JsonValue> & arkExtraInfoJson)2400 void DragEventActuator::PrepareRadiusParametersForDragData(const RefPtr<FrameNode>& frameNode,
2401     std::unique_ptr<JsonValue>& arkExtraInfoJson)
2402 {
2403     CHECK_NULL_VOID(frameNode);
2404     CHECK_NULL_VOID(arkExtraInfoJson);
2405     auto dragPreviewOption = frameNode->GetDragPreviewOption();
2406     auto borderRadius = dragPreviewOption.options.borderRadius;
2407     if (borderRadius.has_value()) {
2408         if (borderRadius.value().radiusTopLeft.has_value()) {
2409             arkExtraInfoJson->Put("drag_corner_radius1", borderRadius.value().radiusTopLeft.value().Value());
2410         }
2411         if (borderRadius.value().radiusTopRight.has_value()) {
2412             arkExtraInfoJson->Put("drag_corner_radius2", borderRadius.value().radiusTopRight.value().Value());
2413         }
2414         if (borderRadius.value().radiusBottomRight.has_value()) {
2415             arkExtraInfoJson->Put("drag_corner_radius3", borderRadius.value().radiusBottomRight.value().Value());
2416         }
2417         if (borderRadius.value().radiusBottomLeft.has_value()) {
2418             arkExtraInfoJson->Put("drag_corner_radius4", borderRadius.value().radiusBottomLeft.value().Value());
2419         }
2420     }
2421 }
2422 
GetDefaultBorderRadius()2423 std::optional<BorderRadiusProperty> DragEventActuator::GetDefaultBorderRadius()
2424 {
2425     BorderRadiusProperty borderRadius;
2426     borderRadius.SetRadius(PREVIEW_BORDER_RADIUS);
2427     return borderRadius;
2428 }
2429 
ShowPreviewBadgeAnimation(const RefPtr<DragEventActuator> & actuator,const RefPtr<OverlayManager> & manager)2430 void DragEventActuator::ShowPreviewBadgeAnimation(
2431     const RefPtr<DragEventActuator>& actuator, const RefPtr<OverlayManager>& manager)
2432 {
2433     auto gestureEventHub = actuator->gestureEventHub_.Upgrade();
2434     CHECK_NULL_VOID(gestureEventHub);
2435     auto frameNode = gestureEventHub->GetFrameNode();
2436     CHECK_NULL_VOID(frameNode);
2437     auto dragPreviewOptions = frameNode->GetDragPreviewOption();
2438     auto badgeNumber = dragPreviewOptions.GetCustomerBadgeNumber();
2439     int32_t childSize = badgeNumber.has_value() ? badgeNumber.value()
2440                                             : static_cast<int32_t>(manager->GetGatherNodeChildrenInfo().size()) + 1;
2441     auto textNode = CreateBadgeTextNode(frameNode, childSize, PIXELMAP_DRAG_SCALE_MULTIPLE, true);
2442     CHECK_NULL_VOID(textNode);
2443     auto column = manager->GetPixelMapNode();
2444     CHECK_NULL_VOID(column);
2445     column->AddChild(textNode);
2446 
2447     DragAnimationHelper::ShowBadgeAnimation(textNode);
2448 }
2449 
CreateBadgeTextNode(const RefPtr<FrameNode> & frameNode,int32_t childSize,float previewScale,bool isUsePixelMapOffset,OffsetF previewOffset)2450 RefPtr<FrameNode> DragEventActuator::CreateBadgeTextNode(const RefPtr<FrameNode>& frameNode, int32_t childSize,
2451     float previewScale, bool isUsePixelMapOffset, OffsetF previewOffset)
2452 {
2453     if (childSize <= 1) {
2454         return nullptr;
2455     }
2456     CHECK_NULL_RETURN(frameNode, nullptr);
2457     auto textNode = FrameNode::GetOrCreateFrameNode(V2::TEXT_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
2458         []() { return AceType::MakeRefPtr<TextPattern>(); });
2459     CHECK_NULL_RETURN(textNode, nullptr);
2460     auto badgeLength = std::to_string(childSize).size();
2461     DragAnimationHelper::UpdateBadgeLayoutAndRenderContext(textNode, badgeLength, childSize);
2462 
2463     auto textRenderContext = textNode->GetRenderContext();
2464     CHECK_NULL_RETURN(textRenderContext, nullptr);
2465     auto pixelMap = frameNode->GetPixelMap();
2466     CHECK_NULL_RETURN(pixelMap, nullptr);
2467     auto width = pixelMap->GetWidth();
2468     auto height = pixelMap->GetHeight();
2469     auto offset = isUsePixelMapOffset ? GetFloatImageOffset(frameNode, pixelMap) : frameNode->GetPaintRectOffset();
2470     if (!previewOffset.NonOffset()) {
2471         offset = previewOffset;
2472     }
2473     double textOffsetX = offset.GetX() + width * (previewScale + 1) / 2 -
2474         BADGE_RELATIVE_OFFSET.ConvertToPx() - (BADGE_RELATIVE_OFFSET.ConvertToPx() * badgeLength);
2475     double textOffsetY = offset.GetY() - height * (previewScale - 1) / 2 - BADGE_RELATIVE_OFFSET.ConvertToPx();
2476     textRenderContext->UpdatePosition(OffsetT<Dimension>(Dimension(textOffsetX), Dimension(textOffsetY)));
2477     textNode->MarkDirtyNode(NG::PROPERTY_UPDATE_MEASURE);
2478     textNode->MarkModifyDone();
2479     textNode->SetLayoutDirtyMarked(true);
2480     textNode->SetActive(true);
2481     auto context = textNode->GetContext();
2482     if (context) {
2483         context->FlushUITaskWithSingleDirtyNode(textNode);
2484     }
2485     FlushSyncGeometryNodeTasks();
2486     return textNode;
2487 }
2488 
GetThumbnailPixelMapAsync(const RefPtr<GestureEventHub> & gestureHub)2489 void DragEventActuator::GetThumbnailPixelMapAsync(const RefPtr<GestureEventHub>& gestureHub)
2490 {
2491     CHECK_NULL_VOID(gestureHub);
2492     auto callback = [id = Container::CurrentId(), gestureHub](const RefPtr<PixelMap>& pixelMap) {
2493         ContainerScope scope(id);
2494         if (pixelMap != nullptr) {
2495             auto taskScheduler = Container::CurrentTaskExecutor();
2496             CHECK_NULL_VOID(taskScheduler);
2497             taskScheduler->PostTask(
2498                 [gestureHub, pixelMap]() {
2499                     CHECK_NULL_VOID(gestureHub);
2500                     gestureHub->SetPixelMap(pixelMap);
2501                     TAG_LOGI(AceLogTag::ACE_DRAG, "Set thumbnail pixelMap async success.");
2502                 },
2503                 TaskExecutor::TaskType::UI, "ArkUIDragSetPixelMap");
2504         }
2505     };
2506     auto frameNode = gestureHub->GetFrameNode();
2507     CHECK_NULL_VOID(frameNode);
2508     auto context = frameNode->GetRenderContext();
2509     CHECK_NULL_VOID(context);
2510     if (!context->CreateThumbnailPixelMapAsyncTask(true, std::move(callback))) {
2511         DragDropBehaviorReporter::GetInstance().UpdateDragStartResult(DragStartResult::SNAPSHOT_FAIL);
2512         TAG_LOGW(AceLogTag::ACE_DRAG, "Create thumbnail pixelMap async task failed!");
2513     }
2514 }
2515 
SetResponseRegionFull()2516 void DragEventActuator::SetResponseRegionFull()
2517 {
2518     if (!IsNeedGather() || isResponseRegionFull) {
2519         return;
2520     }
2521     auto gestureHub = gestureEventHub_.Upgrade();
2522     CHECK_NULL_VOID(gestureHub);
2523 
2524     responseRegion_ = gestureHub->GetResponseRegion();
2525     DimensionRect hotZoneRegion;
2526 
2527     auto frameNode = gestureHub->GetFrameNode();
2528     CHECK_NULL_VOID(frameNode);
2529     auto renderContext = frameNode->GetRenderContext();
2530     CHECK_NULL_VOID(renderContext);
2531     auto paintRect = renderContext->GetPaintRectWithoutTransform();
2532     hotZoneRegion.SetOffset(DimensionOffset(Dimension(-paintRect.GetOffset().GetX()),
2533         Dimension(-paintRect.GetOffset().GetY())));
2534 
2535     auto pipelineContext = frameNode->GetContextRefPtr();
2536     CHECK_NULL_VOID(pipelineContext);
2537     auto rootNode = pipelineContext->GetRootElement();
2538     CHECK_NULL_VOID(rootNode);
2539     auto geometryNode = rootNode->GetGeometryNode();
2540     CHECK_NULL_VOID(geometryNode);
2541     auto width = geometryNode->GetFrameSize().Width();
2542     auto height = geometryNode->GetFrameSize().Height();
2543     hotZoneRegion.SetSize(DimensionSize(Dimension(width), Dimension(height)));
2544     gestureHub->SetResponseRegion(std::vector<DimensionRect>({ hotZoneRegion }));
2545     isResponseRegionFull = true;
2546 }
2547 
ResetResponseRegion()2548 void DragEventActuator::ResetResponseRegion()
2549 {
2550     if (isResponseRegionFull) {
2551         auto gestureHub = gestureEventHub_.Upgrade();
2552         CHECK_NULL_VOID(gestureHub);
2553         gestureHub->SetResponseRegion(responseRegion_);
2554         isResponseRegionFull = false;
2555     }
2556 }
2557 
PrepareFinalPixelMapForDragThroughTouch(RefPtr<PixelMap> pixelMap,bool immediately)2558 void DragEventActuator::PrepareFinalPixelMapForDragThroughTouch(RefPtr<PixelMap> pixelMap, bool immediately)
2559 {
2560     ResetPreScaledPixelMapForDragThroughTouch();
2561     auto pipeline = PipelineContext::GetCurrentContext();
2562     CHECK_NULL_VOID(pipeline);
2563     auto dragDropManager = pipeline->GetDragDropManager();
2564     CHECK_NULL_VOID(dragDropManager);
2565     auto windowScale = dragDropManager->GetWindowScale();
2566     float scale = windowScale * PIXELMAP_DRAG_SCALE_MULTIPLE;
2567 
2568     auto task = [weak = WeakClaim(this), pixelMap, scale] () {
2569         auto actuator = weak.Upgrade();
2570         CHECK_NULL_VOID(actuator);
2571         actuator->DoPixelMapScaleForDragThroughTouch(pixelMap, scale);
2572     };
2573 
2574     if (immediately) {
2575         task();
2576         return;
2577     }
2578 
2579     auto taskScheduler = pipeline->GetTaskExecutor();
2580     CHECK_NULL_VOID(taskScheduler);
2581     taskScheduler->PostTask(task, TaskExecutor::TaskType::UI, "ArkUIPrepareScaledPixel", PriorityType::VIP);
2582 }
2583 
DoPixelMapScaleForDragThroughTouch(RefPtr<PixelMap> pixelMap,float targetScale)2584 void DragEventActuator::DoPixelMapScaleForDragThroughTouch(RefPtr<PixelMap> pixelMap, float targetScale)
2585 {
2586 #if defined(PIXEL_MAP_SUPPORTED)
2587     preScaledPixelMap_ = PixelMap::CopyPixelMap(pixelMap);
2588     if (!preScaledPixelMap_) {
2589         TAG_LOGW(AceLogTag::ACE_DRAG, "Copy preScaledPixelMap_ is failure!");
2590         return;
2591     }
2592     preScaledPixelMap_->Scale(targetScale, targetScale, AceAntiAliasingOption::HIGH);
2593     preScaleValue_ = targetScale;
2594 #endif
2595 }
2596 
GetPreScaledPixelMapForDragThroughTouch(float & preScale)2597 RefPtr<PixelMap> DragEventActuator::GetPreScaledPixelMapForDragThroughTouch(float& preScale)
2598 {
2599     preScale = preScaleValue_;
2600     return preScaledPixelMap_;
2601 }
2602 
ResetPreScaledPixelMapForDragThroughTouch()2603 void DragEventActuator::ResetPreScaledPixelMapForDragThroughTouch()
2604 {
2605     preScaledPixelMap_ = nullptr;
2606     preScaleValue_ = 1.0f;
2607 }
2608 
RecordMenuWrapperNodeForDrag(int32_t targetId)2609 void DragEventActuator::RecordMenuWrapperNodeForDrag(int32_t targetId)
2610 {
2611     auto subWindow = SubwindowManager::GetInstance()->GetCurrentWindow();
2612     CHECK_NULL_VOID(subWindow);
2613     auto overlayManager = subWindow->GetOverlayManager();
2614     CHECK_NULL_VOID(overlayManager);
2615     auto menuWrapperNode = overlayManager->GetMenuNode(targetId);
2616     CHECK_NULL_VOID(menuWrapperNode);
2617 
2618     auto pipeline = PipelineContext::GetCurrentContext();
2619     CHECK_NULL_VOID(pipeline);
2620     auto dragDropManager = pipeline->GetDragDropManager();
2621     CHECK_NULL_VOID(dragDropManager);
2622     dragDropManager->SetMenuWrapperNode(menuWrapperNode);
2623 }
2624 } // namespace OHOS::Ace::NG
2625