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/utils/system_properties.h"
19 #include "base/utils/utils.h"
20 #include "core/common/container.h"
21 #include "core/components_ng/base/frame_node.h"
22 #include "core/components_ng/event/gesture_event_hub.h"
23 #include "core/components_ng/gestures/recognizers/long_press_recognizer.h"
24 #include "core/components_ng/gestures/recognizers/pan_recognizer.h"
25 #include "core/components_ng/gestures/recognizers/sequenced_recognizer.h"
26 #include "core/pipeline_ng/pipeline_context.h"
27
28 #ifdef ENABLE_DRAG_FRAMEWORK
29 #include "base/msdp/device_status/interfaces/innerkits/interaction/include/interaction_manager.h"
30 #include "base/subwindow/subwindow_manager.h"
31 #include "core/animation/animation_pub.h"
32 #include "core/components/container_modal/container_modal_constants.h"
33 #include "core/components_ng/pattern/image/image_layout_property.h"
34 #include "core/components_ng/pattern/image/image_pattern.h"
35 #include "core/components_ng/pattern/linear_layout/linear_layout_pattern.h"
36 #include "core/components_ng/pattern/text/text_base.h"
37 #include "core/components_ng/pattern/text_drag/text_drag_base.h"
38 #include "core/components_ng/pattern/text_drag/text_drag_pattern.h"
39 #include "core/components_ng/render/adapter/rosen_render_context.h"
40 #include "core/components_ng/render/render_context.h"
41 #include "core/components_v2/inspector/inspector_constants.h"
42 #endif // ENABLE_DRAG_FRAMEWORK
43
44 #ifdef WEB_SUPPORTED
45 #include "core/components_ng/pattern/web/web_pattern.h"
46 #endif // WEB_SUPPORTED
47
48 namespace OHOS::Ace::NG {
49 namespace {
50 constexpr int32_t PAN_FINGER = 1;
51 constexpr double PAN_DISTANCE = 5.0;
52 constexpr int32_t LONG_PRESS_DURATION = 500;
53 constexpr int32_t PREVIEW_LONG_PRESS_RECONGNIZER = 800;
54 #ifdef ENABLE_DRAG_FRAMEWORK
55 constexpr Dimension FILTER_VALUE(0.0f);
56 constexpr Dimension FILTER_RADIUS(100.0f);
57 constexpr float PIXELMAP_DRAG_SCALE_MULTIPLE = 1.05f;
58 constexpr int32_t PIXELMAP_ANIMATION_TIME = 800;
59 constexpr float SCALE_NUMBER = 0.95f;
60 constexpr int32_t FILTER_TIMES = 250;
61 constexpr float PIXELMAP_ANIMATION_SCALE = 1.1f;
62 constexpr int32_t PIXELMAP_ANIMATION_DURATION = 300;
63 constexpr float SPRING_RESPONSE = 0.416f;
64 constexpr float SPRING_DAMPING_FRACTION = 0.73f;
65 #endif // ENABLE_DRAG_FRAMEWORK
66 } // namespace
67
DragEventActuator(const WeakPtr<GestureEventHub> & gestureEventHub,PanDirection direction,int32_t fingers,float distance)68 DragEventActuator::DragEventActuator(
69 const WeakPtr<GestureEventHub>& gestureEventHub, PanDirection direction, int32_t fingers, float distance)
70 : gestureEventHub_(gestureEventHub), direction_(direction), fingers_(fingers), distance_(distance)
71 {
72 if (fingers_ < PAN_FINGER) {
73 fingers_ = PAN_FINGER;
74 }
75
76 if (LessOrEqual(distance_, PAN_DISTANCE)) {
77 distance_ = PAN_DISTANCE;
78 }
79
80 panRecognizer_ = MakeRefPtr<PanRecognizer>(fingers_, direction_, distance_);
81 longPressRecognizer_ = AceType::MakeRefPtr<LongPressRecognizer>(LONG_PRESS_DURATION, fingers_, false, false);
82 previewLongPressRecognizer_ =
83 AceType::MakeRefPtr<LongPressRecognizer>(PREVIEW_LONG_PRESS_RECONGNIZER, fingers_, false, true);
84 isNotInPreviewState_ = false;
85 }
86
StartDragTaskForWeb(const GestureEvent & info)87 void DragEventActuator::StartDragTaskForWeb(const GestureEvent& info)
88 {
89 auto gestureInfo = const_cast<GestureEvent&>(info);
90 if (actionStart_) {
91 actionStart_(gestureInfo);
92 }
93 }
94
StartLongPressActionForWeb()95 void DragEventActuator::StartLongPressActionForWeb()
96 {
97 if (!isReceivedLongPress_) {
98 LOGW("not received long press action, don't start long press action for web");
99 return;
100 }
101 if (longPressUpdate_) {
102 longPressUpdate_(longPressInfo_);
103 }
104 isReceivedLongPress_ = false;
105 }
106
CancelDragForWeb()107 void DragEventActuator::CancelDragForWeb()
108 {
109 if (actionCancel_) {
110 actionCancel_();
111 }
112 }
113
OnCollectTouchTarget(const OffsetF & coordinateOffset,const TouchRestrict & touchRestrict,const GetEventTargetImpl & getEventTargetImpl,TouchTestResult & result)114 void DragEventActuator::OnCollectTouchTarget(const OffsetF& coordinateOffset, const TouchRestrict& touchRestrict,
115 const GetEventTargetImpl& getEventTargetImpl, TouchTestResult& result)
116 {
117 CHECK_NULL_VOID_NOLOG(userCallback_);
118 auto actionStart = [weak = WeakClaim(this), this](GestureEvent& info) {
119 if (SystemProperties::GetDebugEnabled()) {
120 LOGI("DragEvent panRecognizer onActionStart.");
121 }
122 auto actuator = weak.Upgrade();
123 CHECK_NULL_VOID(actuator);
124 #ifdef ENABLE_DRAG_FRAMEWORK
125 auto gestureHub = actuator->gestureEventHub_.Upgrade();
126 CHECK_NULL_VOID(gestureHub);
127 auto frameNode = gestureHub->GetFrameNode();
128 CHECK_NULL_VOID(frameNode);
129 auto renderContext = frameNode->GetRenderContext();
130 if (info.GetSourceDevice() != SourceType::MOUSE) {
131 if (gestureHub->GetTextDraggable()) {
132 auto pattern = frameNode->GetPattern<TextBase>();
133 CHECK_NULL_VOID(pattern);
134 frameNode->SetDraggable(isTextReceivedLongPress_);
135 if (gestureHub->GetIsTextDraggable()) {
136 HideTextAnimation(true, info.GetGlobalLocation().GetX(), info.GetGlobalLocation().GetY());
137 }
138 } else if (!isNotInPreviewState_) {
139 HideEventColumn();
140 HidePixelMap(true, info.GetGlobalLocation().GetX(), info.GetGlobalLocation().GetY());
141 HideFilter();
142 SubwindowManager::GetInstance()->HideMenuNG();
143 AnimationOption option;
144 option.SetDuration(PIXELMAP_ANIMATION_DURATION);
145 option.SetCurve(Curves::SHARP);
146 AnimationUtils::Animate(
147 option, [renderContext]() { renderContext->UpdateOpacity(SCALE_NUMBER); },
148 option.GetOnFinishEvent());
149 }
150 }
151
152 if (info.GetSourceDevice() == SourceType::MOUSE) {
153 auto pattern = frameNode->GetPattern<TextBase>();
154 if (gestureHub->GetTextDraggable() && pattern) {
155 if (!pattern->IsSelected() || pattern->GetMouseStatus() == MouseStatus::MOVE) {
156 frameNode->SetDraggable(false);
157 return;
158 }
159 if (pattern->BetweenSelectedPosition(info.GetGlobalLocation())) {
160 frameNode->SetDraggable(true);
161 textDragCallback_(info.GetGlobalLocation());
162 }
163 }
164 }
165
166 #endif // ENABLE_DRAG_FRAMEWORK
167 // Trigger drag start event set by user.
168 CHECK_NULL_VOID(actuator->userCallback_);
169 auto userActionStart = actuator->userCallback_->GetActionStartEventFunc();
170 if (userActionStart) {
171 userActionStart(info);
172 }
173 // Trigger custom drag start event
174 CHECK_NULL_VOID(actuator->customCallback_);
175 auto customActionStart = actuator->customCallback_->GetActionStartEventFunc();
176 if (customActionStart) {
177 customActionStart(info);
178 }
179 };
180 actionStart_ = actionStart;
181 panRecognizer_->SetOnActionStart(actionStart);
182
183 #ifdef ENABLE_DRAG_FRAMEWORK
184 if (touchRestrict.sourceType == SourceType::MOUSE) {
185 auto&& callback = [weakPtr = gestureEventHub_, weak = WeakClaim(this)]() {
186 auto gestureHub = weakPtr.Upgrade();
187 CHECK_NULL_VOID(gestureHub);
188 std::shared_ptr<Media::PixelMap> pixelMap;
189 auto frameNode = gestureHub->GetFrameNode();
190 CHECK_NULL_VOID(frameNode);
191 if (gestureHub->GetTextDraggable()) {
192 auto pattern = frameNode->GetPattern<TextDragBase>();
193 CHECK_NULL_VOID(pattern);
194 auto dragNode = pattern->MoveDragNode();
195 CHECK_NULL_VOID(dragNode);
196 auto context = dragNode->GetRenderContext();
197 CHECK_NULL_VOID(context);
198 auto thumbnailPixelMap = context->GetThumbnailPixelMap();
199 CHECK_NULL_VOID(thumbnailPixelMap);
200 pixelMap = thumbnailPixelMap->GetPixelMapSharedPtr();
201 } else {
202 auto context = frameNode->GetRenderContext();
203 CHECK_NULL_VOID(context);
204 auto thumbnailPixelMap = context->GetThumbnailPixelMap();
205 CHECK_NULL_VOID(thumbnailPixelMap);
206 pixelMap = thumbnailPixelMap->GetPixelMapSharedPtr();
207 }
208 CHECK_NULL_VOID(pixelMap);
209 float scale = gestureHub->GetPixelMapScale(pixelMap->GetHeight(), pixelMap->GetWidth());
210 pixelMap->scale(scale, scale);
211 auto pipeline = PipelineContext::GetCurrentContext();
212 CHECK_NULL_VOID(pipeline);
213 auto dragDropManager = pipeline->GetDragDropManager();
214 CHECK_NULL_VOID(dragDropManager);
215 if (!dragDropManager->IsDragged()) {
216 return;
217 }
218 int32_t width = pixelMap->GetWidth();
219 int32_t height = pixelMap->GetHeight();
220 Msdp::DeviceStatus::ShadowInfo shadowInfo { pixelMap, width * PIXELMAP_WIDTH_RATE,
221 height * PIXELMAP_HEIGHT_RATE };
222 int ret = Msdp::DeviceStatus::InteractionManager::GetInstance()->UpdateShadowPic(shadowInfo);
223 if (ret != 0) {
224 LOGE("InteractionManager: UpdateShadowPic error");
225 return;
226 }
227 if (SystemProperties::GetDebugEnabled()) {
228 LOGI("In setThumbnailPixelMap callback, set DragWindowVisible true.");
229 }
230 Msdp::DeviceStatus::InteractionManager::GetInstance()->SetDragWindowVisible(true);
231 dragDropManager->SetIsDragWindowShow(true);
232 };
233 auto gestureHub = gestureEventHub_.Upgrade();
234 CHECK_NULL_VOID(gestureHub);
235 if (!gestureHub->HasThumbnailCallback()) {
236 gestureHub->SetThumbnailPixelMapCallback(callback);
237 }
238 };
239 #endif // ENABLE_DRAG_FRAMEWORK
240
241 auto actionUpdate = [weak = WeakClaim(this)](GestureEvent& info) {
242 if (SystemProperties::GetDebugEnabled()) {
243 LOGI("DragEvent panRecognizer onActionUpdate.");
244 }
245 auto actuator = weak.Upgrade();
246 CHECK_NULL_VOID(actuator);
247 CHECK_NULL_VOID(actuator->userCallback_);
248 auto userActionUpdate = actuator->userCallback_->GetActionUpdateEventFunc();
249 if (userActionUpdate) {
250 userActionUpdate(info);
251 }
252 CHECK_NULL_VOID(actuator->customCallback_);
253 auto customActionUpdate = actuator->customCallback_->GetActionUpdateEventFunc();
254 if (customActionUpdate) {
255 customActionUpdate(info);
256 }
257 };
258 panRecognizer_->SetOnActionUpdate(actionUpdate);
259
260 auto actionEnd = [weak = WeakClaim(this)](GestureEvent& info) {
261 if (SystemProperties::GetDebugEnabled()) {
262 LOGI("DragEvent panRecognizer onActionEnd.");
263 }
264 auto actuator = weak.Upgrade();
265 CHECK_NULL_VOID(actuator);
266 CHECK_NULL_VOID(actuator->userCallback_);
267 auto userActionEnd = actuator->userCallback_->GetActionEndEventFunc();
268 if (userActionEnd) {
269 userActionEnd(info);
270 }
271 CHECK_NULL_VOID(actuator->customCallback_);
272 auto customActionEnd = actuator->customCallback_->GetActionEndEventFunc();
273 if (customActionEnd) {
274 customActionEnd(info);
275 }
276 actuator->SetIsNotInPreviewState(false);
277 };
278 panRecognizer_->SetOnActionEnd(actionEnd);
279 #ifdef ENABLE_DRAG_FRAMEWORK
280 auto actionCancel = [weak = WeakClaim(this), this]() {
281 #else
282 auto actionCancel = [weak = WeakClaim(this)]() {
283 #endif // ENABLE_DRAG_FRAMEWORK
284 if (SystemProperties::GetDebugEnabled()) {
285 LOGI("DragEvent panRecognizer onActionCancel.");
286 }
287 auto actuator = weak.Upgrade();
288 CHECK_NULL_VOID(actuator);
289 #ifdef ENABLE_DRAG_FRAMEWORK
290 auto gestureHub = actuator->gestureEventHub_.Upgrade();
291 CHECK_NULL_VOID(gestureHub);
292 if (!GetIsBindOverlayValue(actuator)) {
293 if (gestureHub->GetTextDraggable()) {
294 if (gestureHub->GetIsTextDraggable()) {
295 HideTextAnimation();
296 }
297 } else {
298 auto frameNode = gestureHub->GetFrameNode();
299 CHECK_NULL_VOID(frameNode);
300 auto renderContext = frameNode->GetRenderContext();
301 BorderRadiusProperty borderRadius;
302 if (renderContext->GetBorderRadius().has_value()) {
303 borderRadius.UpdateWithCheck(renderContext->GetBorderRadius().value());
304 }
305 borderRadius.multiValued = false;
306 AnimationOption option;
307 option.SetDuration(PIXELMAP_ANIMATION_DURATION);
308 option.SetCurve(Curves::FRICTION);
309 AnimationUtils::Animate(
310 option,
311 [renderContext_ = renderContext, borderRadius_ = borderRadius]() {
312 renderContext_->UpdateBorderRadius(borderRadius_);
313 },
314 option.GetOnFinishEvent());
315 HideEventColumn();
316 HidePixelMap();
317 HideFilter();
318 }
319 } else {
320 if (actuator->panRecognizer_->getDeviceType() == SourceType::MOUSE) {
321 if (!gestureHub->GetTextDraggable()) {
322 HideEventColumn();
323 HidePixelMap();
324 HideFilter();
325 }
326 }
327 }
328 actuator->SetIsNotInPreviewState(false);
329 #endif // ENABLE_DRAG_FRAMEWORK
330 CHECK_NULL_VOID(actuator->userCallback_);
331 auto userActionCancel = actuator->userCallback_->GetActionCancelEventFunc();
332 if (userActionCancel) {
333 userActionCancel();
334 }
335 CHECK_NULL_VOID(actuator->customCallback_);
336 auto customActionCancel = actuator->customCallback_->GetActionCancelEventFunc();
337 if (customActionCancel) {
338 customActionCancel();
339 }
340 };
341 panRecognizer_->SetIsForDrag(true);
342 panRecognizer_->SetMouseDistance(DRAG_PAN_DISTANCE_MOUSE);
343 actionCancel_ = actionCancel;
344 panRecognizer_->SetOnActionCancel(actionCancel);
345 auto gestureHub = gestureEventHub_.Upgrade();
346 CHECK_NULL_VOID(gestureHub);
347 #ifdef ENABLE_DRAG_FRAMEWORK
348 if (touchRestrict.sourceType == SourceType::MOUSE) {
349 std::vector<RefPtr<NGGestureRecognizer>> recognizers { panRecognizer_ };
350 SequencedRecognizer_ = AceType::MakeRefPtr<SequencedRecognizer>(recognizers);
351 SequencedRecognizer_->RemainChildOnResetStatus();
352 SequencedRecognizer_->SetCoordinateOffset(Offset(coordinateOffset.GetX(), coordinateOffset.GetY()));
353 SequencedRecognizer_->SetGetEventTargetImpl(getEventTargetImpl);
354 result.emplace_back(SequencedRecognizer_);
355 return;
356 }
357 auto menuLongPress = gestureHub->GetLongPressRecognizer();
358 if (menuLongPress) {
359 menuLongPress->SetIsForDrag(true);
360 }
361 auto longPressUpdateValue = [weak = WeakClaim(this)](GestureEvent& info) {
362 if (SystemProperties::GetDebugEnabled()) {
363 LOGI("DragEvent longPressRecognizer onActionUpdate.");
364 }
365 auto actuator = weak.Upgrade();
366 CHECK_NULL_VOID(actuator);
367 actuator->SetIsNotInPreviewState(true);
368 };
369 longPressRecognizer_->SetOnActionUpdate(longPressUpdateValue);
370 auto longPressUpdate = [weak = WeakClaim(this)](GestureEvent& info) {
371 if (SystemProperties::GetDebugEnabled()) {
372 LOGI("DragEvent previewLongPressRecognizer onActionUpdate.");
373 }
374 auto actuator = weak.Upgrade();
375 CHECK_NULL_VOID(actuator);
376 auto gestureHub = actuator->gestureEventHub_.Upgrade();
377 CHECK_NULL_VOID(gestureHub);
378 if (gestureHub->GetTextDraggable()) {
379 actuator->SetIsNotInPreviewState(false);
380 if (gestureHub->GetIsTextDraggable()) {
381 actuator->SetTextAnimation(gestureHub, info.GetGlobalLocation());
382 }
383 return;
384 }
385
386 bool isAllowedDrag = actuator->IsAllowedDrag();
387 if (!isAllowedDrag) {
388 actuator->longPressInfo_ = info;
389 actuator->isReceivedLongPress_ = true;
390 return;
391 }
392
393 actuator->SetFilter(actuator);
394 auto pipeline = PipelineContext::GetCurrentContext();
395 CHECK_NULL_VOID(pipeline);
396 auto manager = pipeline->GetOverlayManager();
397 CHECK_NULL_VOID(manager);
398 actuator->SetIsNotInPreviewState(false);
399 actuator->SetPixelMap(actuator);
400 auto motion = AceType::MakeRefPtr<ResponsiveSpringMotion>(SPRING_RESPONSE, SPRING_DAMPING_FRACTION, 0);
401 auto column = manager->GetPixelMapNode();
402 CHECK_NULL_VOID(column);
403
404 auto imageNode = AceType::DynamicCast<FrameNode>(column->GetFirstChild());
405 CHECK_NULL_VOID(imageNode);
406 auto imageContext = imageNode->GetRenderContext();
407 CHECK_NULL_VOID(imageContext);
408 AnimationOption option;
409 option.SetDuration(PIXELMAP_ANIMATION_TIME);
410 option.SetCurve(motion);
411 AnimationUtils::Animate(
412 option,
413 [imageContext]() {
414 imageContext->UpdateTransformScale({ PIXELMAP_DRAG_SCALE_MULTIPLE, PIXELMAP_DRAG_SCALE_MULTIPLE });
415 },
416 option.GetOnFinishEvent());
417 actuator->SetEventColumn(actuator);
418 };
419 longPressUpdate_ = longPressUpdate;
420 previewLongPressRecognizer_->SetOnAction(longPressUpdate);
421 #endif // ENABLE_DRAG_FRAMEWORK
422 previewLongPressRecognizer_->SetGestureHub(gestureEventHub_);
423 auto frameNode = gestureHub->GetFrameNode();
424 CHECK_NULL_VOID(frameNode);
425 auto eventHub = frameNode->GetEventHub<EventHub>();
426 CHECK_NULL_VOID(eventHub);
427 bool isAllowedDrag = gestureHub->IsAllowedDrag(eventHub);
428 if (!longPressRecognizer_->HasThumbnailCallback() && isAllowedDrag) {
429 auto callback = [weakPtr = gestureEventHub_](Offset point) {
430 auto gestureHub = weakPtr.Upgrade();
431 CHECK_NULL_VOID(gestureHub);
432 auto frameNode = gestureHub->GetFrameNode();
433 CHECK_NULL_VOID(frameNode);
434 auto context = frameNode->GetRenderContext();
435 CHECK_NULL_VOID(context);
436 auto pixelMap = context->GetThumbnailPixelMap();
437 gestureHub->SetPixelMap(pixelMap);
438 };
439 longPressRecognizer_->SetThumbnailCallback(std::move(callback));
440 }
441 std::vector<RefPtr<NGGestureRecognizer>> recognizers { longPressRecognizer_, panRecognizer_ };
442 SequencedRecognizer_ = AceType::MakeRefPtr<SequencedRecognizer>(recognizers);
443 SequencedRecognizer_->RemainChildOnResetStatus();
444 SequencedRecognizer_->SetCoordinateOffset(Offset(coordinateOffset.GetX(), coordinateOffset.GetY()));
445 SequencedRecognizer_->SetGetEventTargetImpl(getEventTargetImpl);
446 result.emplace_back(SequencedRecognizer_);
447 result.emplace_back(previewLongPressRecognizer_);
448 }
449
450 #ifdef ENABLE_DRAG_FRAMEWORK
451 void DragEventActuator::SetFilter(const RefPtr<DragEventActuator>& actuator)
452 {
453 if (SystemProperties::GetDebugEnabled()) {
454 LOGI("DragEvent start setFilter.");
455 }
456 auto gestureHub = actuator->gestureEventHub_.Upgrade();
457 CHECK_NULL_VOID(gestureHub);
458 auto frameNode = gestureHub->GetFrameNode();
459 CHECK_NULL_VOID(frameNode);
460 auto parent = frameNode->GetParent();
461 CHECK_NULL_VOID(parent);
462 while (parent->GetDepth() != 1) {
463 parent = parent->GetParent();
464 }
465 auto pipelineContext = PipelineContext::GetCurrentContext();
466 CHECK_NULL_VOID(pipelineContext);
467 auto manager = pipelineContext->GetOverlayManager();
468 CHECK_NULL_VOID(manager);
469 if (!manager->GetHasFilter() && !manager->GetIsOnAnimation()) {
470 if (frameNode->GetTag() == V2::WEB_ETS_TAG) {
471 #ifdef WEB_SUPPORTED
472 auto webPattern = frameNode->GetPattern<WebPattern>();
473 CHECK_NULL_VOID(webPattern);
474 bool isWebmageDrag = webPattern->IsImageDrag();
475 CHECK_NULL_VOID(isWebmageDrag && SystemProperties::GetDeviceType() == DeviceType::PHONE);
476 #endif
477 } else {
478 bool isBindOverlayValue = frameNode->GetLayoutProperty()->GetIsBindOverlayValue(false);
479 CHECK_NULL_VOID_NOLOG(isBindOverlayValue && SystemProperties::GetDeviceType() == DeviceType::PHONE);
480 }
481 // insert columnNode to rootNode
482 auto columnNode = FrameNode::CreateFrameNode(V2::COLUMN_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
483 AceType::MakeRefPtr<LinearLayoutPattern>(true));
484 columnNode->GetLayoutProperty()->UpdateMeasureType(MeasureType::MATCH_PARENT);
485 // set filter
486 LOGI("User Device use default Filter");
487 auto container = Container::Current();
488 if (container && container->IsScenceBoardWindow()) {
489 auto windowScene = manager->FindWindowScene(frameNode);
490 manager->MountFilterToWindowScene(columnNode, windowScene);
491 } else {
492 columnNode->MountToParent(parent);
493 columnNode->OnMountToParentDone();
494 manager->SetHasFilter(true);
495 manager->SetFilterColumnNode(columnNode);
496 parent->MarkDirtyNode(NG::PROPERTY_UPDATE_BY_CHILD_REQUEST);
497 }
498 AnimationOption option;
499 option.SetDuration(FILTER_TIMES);
500 option.SetCurve(Curves::SHARP);
501 columnNode->GetRenderContext()->UpdateBackBlurRadius(FILTER_VALUE);
502 AnimationUtils::Animate(
503 option, [columnNode]() { columnNode->GetRenderContext()->UpdateBackBlurRadius(FILTER_RADIUS); },
504 option.GetOnFinishEvent());
505 }
506 if (SystemProperties::GetDebugEnabled()) {
507 LOGI("DragEvent set filter success.");
508 }
509 }
510
511 OffsetF DragEventActuator::GetFloatImageOffset(const RefPtr<FrameNode>& frameNode)
512 {
513 auto offsetToWindow = frameNode->GetPaintRectOffset();
514 auto offsetX = offsetToWindow.GetX();
515 auto offsetY = offsetToWindow.GetY();
516 #ifdef WEB_SUPPORTED
517 if (frameNode->GetTag() == V2::WEB_ETS_TAG) {
518 auto webPattern = frameNode->GetPattern<WebPattern>();
519 if (webPattern) {
520 offsetX += webPattern->GetDragOffset().GetX();
521 offsetY += webPattern->GetDragOffset().GetY();
522 }
523 }
524 #endif
525 return OffsetF(offsetX, offsetY);
526 }
527
528 void DragEventActuator::SetPixelMap(const RefPtr<DragEventActuator>& actuator)
529 {
530 if (SystemProperties::GetDebugEnabled()) {
531 LOGI("DragEvent start set pixelMap");
532 }
533 auto pipelineContext = PipelineContext::GetCurrentContext();
534 CHECK_NULL_VOID(pipelineContext);
535 auto manager = pipelineContext->GetOverlayManager();
536 CHECK_NULL_VOID(manager);
537 if (manager->GetHasPixelMap()) {
538 if (SystemProperties::GetDebugEnabled()) {
539 LOGW("DragDropManager don't have pixelMap, set pixelMap fail.");
540 }
541 return;
542 }
543 auto gestureHub = actuator->gestureEventHub_.Upgrade();
544 CHECK_NULL_VOID(gestureHub);
545 auto frameNode = gestureHub->GetFrameNode();
546 CHECK_NULL_VOID(frameNode);
547 RefPtr<PixelMap> pixelMap = gestureHub->GetPixelMap();
548 CHECK_NULL_VOID(pixelMap);
549 auto width = pixelMap->GetWidth();
550 auto height = pixelMap->GetHeight();
551 auto offsetX = GetFloatImageOffset(frameNode).GetX();
552 auto offsetY = GetFloatImageOffset(frameNode).GetY();
553 // Check web tag.
554 if (pipelineContext->HasFloatTitle()) {
555 offsetX -= static_cast<float>((CONTAINER_BORDER_WIDTH + CONTENT_PADDING).ConvertToPx());
556 offsetY -= static_cast<float>((CONTAINER_TITLE_HEIGHT + CONTAINER_BORDER_WIDTH).ConvertToPx());
557 }
558 // create imageNode
559 auto imageNode = FrameNode::GetOrCreateFrameNode(V2::IMAGE_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
560 []() { return AceType::MakeRefPtr<ImagePattern>(); });
561 auto props = imageNode->GetLayoutProperty<ImageLayoutProperty>();
562 props->UpdateImageSourceInfo(ImageSourceInfo(pixelMap));
563 auto targetSize = CalcSize(NG::CalcLength(width), NG::CalcLength(height));
564 props->UpdateUserDefinedIdealSize(targetSize);
565 auto imageContext = imageNode->GetRenderContext();
566 CHECK_NULL_VOID(imageContext);
567 imageContext->UpdatePosition(OffsetT<Dimension>(Dimension(offsetX), Dimension(offsetY)));
568 ClickEffectInfo clickEffectInfo;
569 clickEffectInfo.level = ClickEffectLevel::LIGHT;
570 clickEffectInfo.scaleNumber = SCALE_NUMBER;
571 imageContext->UpdateClickEffectLevel(clickEffectInfo);
572 // create columnNode
573 auto columnNode = FrameNode::CreateFrameNode(V2::COLUMN_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
574 AceType::MakeRefPtr<LinearLayoutPattern>(true));
575 columnNode->AddChild(imageNode);
576 auto hub = columnNode->GetOrCreateGestureEventHub();
577 CHECK_NULL_VOID(hub);
578 hub->SetPixelMap(gestureHub->GetPixelMap());
579 // mount to rootNode
580 auto container = Container::Current();
581 if (container && container->IsScenceBoardWindow()) {
582 auto windowScene = manager->FindWindowScene(frameNode);
583 manager->MountPixelMapToWindowScene(columnNode, windowScene);
584 } else {
585 manager->MountPixelMapToRootNode(columnNode);
586 }
587 imageNode->MarkModifyDone();
588 ShowPixelMapAnimation(imageNode);
589 if (SystemProperties::GetDebugEnabled()) {
590 LOGI("DragEvent set pixelMap success.");
591 }
592 }
593
594 void DragEventActuator::SetEventColumn(const RefPtr<DragEventActuator>& actuator)
595 {
596 if (SystemProperties::GetDebugEnabled()) {
597 LOGI("DragEvent start set eventColumn.");
598 }
599 auto pipelineContext = PipelineContext::GetCurrentContext();
600 CHECK_NULL_VOID(pipelineContext);
601 auto manager = pipelineContext->GetOverlayManager();
602 CHECK_NULL_VOID(manager);
603 if (manager->GetHasEvent()) {
604 if (SystemProperties::GetDebugEnabled()) {
605 LOGW("DragDropManager don't have event, set event column fail.");
606 }
607 return;
608 }
609 auto rootNode = pipelineContext->GetRootElement();
610 CHECK_NULL_VOID(rootNode);
611 auto geometryNode = rootNode->GetGeometryNode();
612 CHECK_NULL_VOID(geometryNode);
613 auto width = geometryNode->GetFrameSize().Width();
614 auto height = geometryNode->GetFrameSize().Height();
615 // create columnNode
616 auto columnNode = FrameNode::CreateFrameNode(V2::COLUMN_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
617 AceType::MakeRefPtr<LinearLayoutPattern>(true));
618 auto props = columnNode->GetLayoutProperty<LinearLayoutProperty>();
619 auto targetSize = CalcSize(NG::CalcLength(width), NG::CalcLength(height));
620 props->UpdateUserDefinedIdealSize(targetSize);
621 BindClickEvent(columnNode);
622 columnNode->MarkModifyDone();
623 auto container = Container::Current();
624 if (container && container->IsScenceBoardWindow()) {
625 auto gestureHub = actuator->gestureEventHub_.Upgrade();
626 CHECK_NULL_VOID(gestureHub);
627 auto frameNode = gestureHub->GetFrameNode();
628 CHECK_NULL_VOID(frameNode);
629 auto windowScene = manager->FindWindowScene(frameNode);
630 manager->MountEventToWindowScene(columnNode, windowScene);
631 } else {
632 manager->MountEventToRootNode(columnNode);
633 }
634 if (SystemProperties::GetDebugEnabled()) {
635 LOGI("DragEvent set eventColumn success.");
636 }
637 }
638
639 void DragEventActuator::HideFilter()
640 {
641 auto pipelineContext = PipelineContext::GetCurrentContext();
642 CHECK_NULL_VOID(pipelineContext);
643 auto manager = pipelineContext->GetOverlayManager();
644 CHECK_NULL_VOID(manager);
645 manager->RemoveFilter();
646 }
647
648 void DragEventActuator::HidePixelMap(bool startDrag, double x, double y)
649 {
650 auto pipelineContext = PipelineContext::GetCurrentContext();
651 CHECK_NULL_VOID(pipelineContext);
652 auto manager = pipelineContext->GetOverlayManager();
653 CHECK_NULL_VOID(manager);
654 manager->RemovePixelMapAnimation(startDrag, x, y);
655 }
656
657 void DragEventActuator::HideEventColumn()
658 {
659 auto pipelineContext = PipelineContext::GetCurrentContext();
660 CHECK_NULL_VOID(pipelineContext);
661 auto manager = pipelineContext->GetOverlayManager();
662 CHECK_NULL_VOID(manager);
663 manager->RemoveEventColumn();
664 }
665
666 void DragEventActuator::BindClickEvent(const RefPtr<FrameNode>& columnNode)
667 {
668 auto callback = [this, weak = WeakClaim(this)](GestureEvent& /* info */) {
669 HideEventColumn();
670 HidePixelMap();
671 HideFilter();
672 };
673 auto columnGestureHub = columnNode->GetOrCreateGestureEventHub();
674 CHECK_NULL_VOID(columnGestureHub);
675 auto clickListener = MakeRefPtr<ClickEvent>(std::move(callback));
676 columnGestureHub->AddClickEvent(clickListener);
677 }
678
679 void DragEventActuator::ShowPixelMapAnimation(const RefPtr<FrameNode>& imageNode)
680 {
681 auto imageContext = imageNode->GetRenderContext();
682 CHECK_NULL_VOID(imageContext);
683 // pixel map animation
684 AnimationOption option;
685 option.SetDuration(PIXELMAP_ANIMATION_DURATION);
686 option.SetCurve(Curves::SHARP);
687 imageContext->UpdateTransformScale({ 1, 1 });
688 auto shadow = imageContext->GetBackShadow();
689 if (!shadow.has_value()) {
690 shadow = Shadow::CreateShadow(ShadowStyle::None);
691 }
692 imageContext->UpdateBackShadow(shadow.value());
693
694 AnimationUtils::Animate(
695 option,
696 [imageContext, shadow]() mutable {
697 auto color = shadow->GetColor();
698 auto newColor = Color::FromARGB(100, color.GetRed(), color.GetGreen(), color.GetBlue());
699 shadow->SetColor(newColor);
700 imageContext->UpdateBackShadow(shadow.value());
701 imageContext->UpdateTransformScale({ PIXELMAP_ANIMATION_SCALE, PIXELMAP_ANIMATION_SCALE });
702 },
703 option.GetOnFinishEvent());
704 }
705
706 void DragEventActuator::SetThumbnailCallback(std::function<void(Offset)>&& callback)
707 {
708 textDragCallback_ = callback;
709 longPressRecognizer_->SetThumbnailCallback(std::move(callback));
710 }
711
712 void DragEventActuator::GetTextPixelMap(bool startDrag)
713 {
714 if (SystemProperties::GetDebugEnabled()) {
715 LOGI("DragEvent start getTextPixelMap.");
716 }
717 auto gestureHub = gestureEventHub_.Upgrade();
718 CHECK_NULL_VOID(gestureHub);
719 bool isAllowedDrag = IsAllowedDrag();
720 if (!gestureHub->GetTextDraggable() || !isAllowedDrag) {
721 if (SystemProperties::GetDebugEnabled()) {
722 LOGW("Text is not draggable, stop get text pixelMap.");
723 }
724 return;
725 }
726 auto frameNode = gestureHub->GetFrameNode();
727 CHECK_NULL_VOID(frameNode);
728 auto pattern = frameNode->GetPattern<TextDragBase>();
729 CHECK_NULL_VOID(pattern);
730 auto pixelMap = gestureHub->GetPixelMap();
731 CHECK_NULL_VOID(pixelMap);
732 auto pipeline = PipelineContext::GetCurrentContext();
733 CHECK_NULL_VOID(pipeline);
734 auto manager = pipeline->GetOverlayManager();
735 CHECK_NULL_VOID(manager);
736 manager->RemovePixelMap();
737 if (!startDrag) {
738 CHECK_NULL_VOID(pattern);
739 pattern->CreateHandles();
740 }
741 auto dragDropManager = pipeline->GetDragDropManager();
742 CHECK_NULL_VOID(dragDropManager);
743 if (!dragDropManager->IsDragged()) {
744 if (SystemProperties::GetDebugEnabled()) {
745 LOGW("DragDropManger is not dragged, stop get text pixelMap.");
746 }
747 return;
748 }
749 std::shared_ptr<Media::PixelMap> mediaPixelMap = pixelMap->GetPixelMapSharedPtr();
750 float scale = gestureHub->GetPixelMapScale(mediaPixelMap->GetHeight(), mediaPixelMap->GetWidth());
751 mediaPixelMap->scale(scale, scale);
752 int32_t width = mediaPixelMap->GetWidth();
753 int32_t height = mediaPixelMap->GetHeight();
754 Msdp::DeviceStatus::ShadowInfo shadowInfo { mediaPixelMap, width * PIXELMAP_WIDTH_RATE,
755 height * PIXELMAP_HEIGHT_RATE };
756 int ret = Msdp::DeviceStatus::InteractionManager::GetInstance()->UpdateShadowPic(shadowInfo);
757 if (ret != 0) {
758 LOGE("InteractionManager: UpdateShadowPic error");
759 return;
760 }
761 if (SystemProperties::GetDebugEnabled()) {
762 LOGI("In function getTextPixelMap, set DragWindowVisible true.");
763 }
764 Msdp::DeviceStatus::InteractionManager::GetInstance()->SetDragWindowVisible(true);
765 dragDropManager->SetIsDragWindowShow(true);
766 gestureHub->SetPixelMap(nullptr);
767 }
768
769 void DragEventActuator::SetTextAnimation(const RefPtr<GestureEventHub>& gestureHub, const Offset& globalLocation)
770 {
771 if (SystemProperties::GetDebugEnabled()) {
772 LOGI("DragEvent start set textAnimation.");
773 }
774 auto pipelineContext = PipelineContext::GetCurrentContext();
775 CHECK_NULL_VOID(pipelineContext);
776 auto manager = pipelineContext->GetOverlayManager();
777 CHECK_NULL_VOID(manager);
778 manager->SetHasFilter(false);
779 CHECK_NULL_VOID(gestureHub);
780 auto frameNode = gestureHub->GetFrameNode();
781 CHECK_NULL_VOID(frameNode);
782 auto pattern = frameNode->GetPattern<TextDragBase>();
783 auto textBase = frameNode->GetPattern<TextBase>();
784 CHECK_NULL_VOID(pattern);
785 CHECK_NULL_VOID(textBase);
786 if (!textBase->BetweenSelectedPosition(globalLocation)) {
787 if (SystemProperties::GetDebugEnabled()) {
788 LOGW("Position is between selected position, stop set text animation.");
789 }
790 return;
791 }
792 pattern->CloseSelectOverlay();
793 pattern->CloseKeyboard(true);
794 auto dragNode = pattern->MoveDragNode();
795 CHECK_NULL_VOID(dragNode);
796 auto pixelMap = dragNode->GetRenderContext()->GetThumbnailPixelMap();
797 CHECK_NULL_VOID(pixelMap);
798 gestureHub->SetPixelMap(pixelMap);
799 // create columnNode
800 auto columnNode = FrameNode::CreateFrameNode(V2::COLUMN_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
801 AceType::MakeRefPtr<LinearLayoutPattern>(true));
802 columnNode->AddChild(dragNode);
803 // mount to rootNode
804 manager->MountPixelMapToRootNode(columnNode);
805 auto modifier = dragNode->GetPattern<TextDragPattern>()->GetOverlayModifier();
806 modifier->StartAnimate();
807 isTextReceivedLongPress_ = true;
808 if (SystemProperties::GetDebugEnabled()) {
809 LOGI("DragEvent set text animation success.");
810 }
811 }
812
813 void DragEventActuator::HideTextAnimation(bool startDrag, double globalX, double globalY)
814 {
815 if (SystemProperties::GetDebugEnabled()) {
816 LOGI("DragEvent start hide text animation.");
817 }
818 auto gestureHub = gestureEventHub_.Upgrade();
819 CHECK_NULL_VOID(gestureHub);
820 bool isAllowedDrag = IsAllowedDrag();
821 if (!gestureHub->GetTextDraggable() || !isAllowedDrag) {
822 if (SystemProperties::GetDebugEnabled()) {
823 LOGW("Text is not draggable, stop set hide text animation.");
824 }
825 return;
826 }
827 auto frameNode = gestureHub->GetFrameNode();
828 CHECK_NULL_VOID(frameNode);
829 auto pattern = frameNode->GetPattern<TextDragBase>();
830 CHECK_NULL_VOID(pattern);
831 auto pixelMap = gestureHub->GetPixelMap();
832 CHECK_NULL_VOID(pixelMap);
833 auto removeColumnNode = [id = Container::CurrentId(), startDrag, weakPattern = WeakPtr<TextDragBase>(pattern),
834 weakEvent = gestureEventHub_] {
835 ContainerScope scope(id);
836 auto pipeline = PipelineContext::GetCurrentContext();
837 CHECK_NULL_VOID(pipeline);
838 auto manager = pipeline->GetOverlayManager();
839 CHECK_NULL_VOID(manager);
840 manager->RemovePixelMap();
841 if (!startDrag) {
842 auto pattern = weakPattern.Upgrade();
843 CHECK_NULL_VOID(pattern);
844 pattern->CreateHandles();
845 }
846 if (SystemProperties::GetDebugEnabled()) {
847 LOGI("In removeColumnNode callback, set DragWindowVisible true.");
848 }
849 Msdp::DeviceStatus::InteractionManager::GetInstance()->SetDragWindowVisible(true);
850 auto gestureHub = weakEvent.Upgrade();
851 CHECK_NULL_VOID(gestureHub);
852 gestureHub->SetPixelMap(nullptr);
853 };
854 AnimationOption option;
855 option.SetDuration(PIXELMAP_ANIMATION_DURATION);
856 option.SetCurve(Curves::SHARP);
857 option.SetOnFinishEvent(removeColumnNode);
858
859 auto pipeline = PipelineContext::GetCurrentContext();
860 CHECK_NULL_VOID(pipeline);
861 auto manager = pipeline->GetOverlayManager();
862 auto dragNode = manager->GetPixelMapNode();
863 CHECK_NULL_VOID(dragNode);
864 auto dragFrame = dragNode->GetGeometryNode()->GetFrameRect();
865 auto frameWidth = dragFrame.Width();
866 auto frameHeight = dragFrame.Height();
867 float scale = gestureHub->GetPixelMapScale(pixelMap->GetHeight(), pixelMap->GetWidth());
868 auto context = dragNode->GetRenderContext();
869 CHECK_NULL_VOID(context);
870 context->UpdateTransformScale(VectorF(1.0f, 1.0f));
871 AnimationUtils::Animate(
872 option,
873 [context, startDrag, globalX, globalY, frameWidth, frameHeight, scale]() {
874 if (startDrag) {
875 context->UpdatePosition(OffsetT<Dimension>(Dimension(globalX + frameWidth * PIXELMAP_WIDTH_RATE),
876 Dimension(globalY + frameHeight * PIXELMAP_HEIGHT_RATE)));
877 context->UpdateTransformScale(VectorF(scale, scale));
878 context->OnModifyDone();
879 }
880 },
881 option.GetOnFinishEvent());
882 if (SystemProperties::GetDebugEnabled()) {
883 LOGI("DragEvent set hide text animation success.");
884 }
885 }
886 bool DragEventActuator::GetIsBindOverlayValue(const RefPtr<DragEventActuator>& actuator)
887 {
888 auto gestureHub = actuator->gestureEventHub_.Upgrade();
889 CHECK_NULL_RETURN(gestureHub, true);
890 auto frameNode = gestureHub->GetFrameNode();
891 CHECK_NULL_RETURN(frameNode, true);
892 bool isBindOverlayValue = frameNode->GetLayoutProperty()->GetIsBindOverlayValue(false);
893 return isBindOverlayValue;
894 }
895
896 bool DragEventActuator::IsAllowedDrag()
897 {
898 auto gestureHub = gestureEventHub_.Upgrade();
899 CHECK_NULL_RETURN(gestureHub, false);
900 auto frameNode = gestureHub->GetFrameNode();
901 CHECK_NULL_RETURN(frameNode, false);
902 auto eventHub = frameNode->GetEventHub<EventHub>();
903 CHECK_NULL_RETURN(eventHub, false);
904 bool isAllowedDrag = gestureHub->IsAllowedDrag(eventHub);
905 return isAllowedDrag;
906 }
907 #endif // ENABLE_DRAG_FRAMEWORK
908 } // namespace OHOS::Ace::NG
909