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