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