1 /*
2 * Copyright (c) 2024 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 "base/image/image_source.h"
17 #include "base/log/ace_trace.h"
18 #include "base/log/log_wrapper.h"
19 #include "base/memory/ace_type.h"
20 #include "base/subwindow/subwindow_manager.h"
21 #include "core/common/container.h"
22 #include "core/common/interaction/interaction_data.h"
23 #include "core/common/interaction/interaction_interface.h"
24 #include "core/components/container_modal/container_modal_constants.h"
25 #include "core/components_ng/event/gesture_event_hub.h"
26 #include "core/components_ng/gestures/gesture_referee.h"
27 #include "core/components_ng/manager/drag_drop/drag_drop_behavior_reporter/drag_drop_behavior_reporter.h"
28 #include "core/components_ng/manager/drag_drop/drag_drop_func_wrapper.h"
29 #include "core/components_ng/manager/drag_drop/drag_drop_global_controller.h"
30 #include "core/components_ng/manager/drag_drop/drag_drop_manager.h"
31 #include "core/components_ng/manager/drag_drop/utils/drag_animation_helper.h"
32 #include "core/components_ng/pattern/image/image_pattern.h"
33 #include "core/components_ng/pattern/relative_container/relative_container_pattern.h"
34 #include "core/components_ng/pattern/scrollable/scrollable_pattern.h"
35 #include "core/components_ng/pattern/text_drag/text_drag_base.h"
36 #include "core/components_ng/pattern/menu/preview/menu_preview_pattern.h"
37 #include "core/common/vibrator/vibrator_utils.h"
38
39 #if defined(PIXEL_MAP_SUPPORTED)
40 #include "image_source.h"
41 #endif
42
43 #include "core/common/udmf/udmf_client.h"
44 #include "core/components_ng/render/adapter/component_snapshot.h"
45 #ifdef WEB_SUPPORTED
46 #if !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM)
47 #include "core/components_ng/pattern/web/web_pattern.h"
48 #else
49 #include "core/components_ng/pattern/web/cross_platform/web_pattern.h"
50 #endif
51 #endif
52 namespace OHOS::Ace::NG {
53 namespace {
54 #if defined(PIXEL_MAP_SUPPORTED)
55 constexpr int32_t CREATE_PIXELMAP_TIME = 30;
56 constexpr int32_t MAX_BUILDER_DEPTH = 5;
57 #endif
58 constexpr uint32_t EXTRA_INFO_MAX_LENGTH = 1024;
59 constexpr int32_t DEFAULT_DRAG_DROP_STATUS = 0;
60 constexpr int32_t NEW_DRAG_DROP_STATUS = 1;
61 constexpr int32_t OLD_DRAG_DROP_STATUS = 3;
62 constexpr float HALF_DIVIDE = 2.0f;
63 const std::unordered_set<std::string> OLD_FRAMEWORK_TAG = {
64 V2::WEB_ETS_TAG,
65 V2::TEXTAREA_ETS_TAG,
66 V2::TEXT_ETS_TAG,
67 V2::TEXTINPUT_ETS_TAG,
68 V2::SEARCH_Field_ETS_TAG,
69 V2::RICH_EDITOR_ETS_TAG,
70 };
71 const std::unordered_set<std::string> VALID_TAG = {
72 V2::WEB_ETS_TAG,
73 };
74 constexpr int32_t HALF_PIXELMAP = 2;
75 constexpr int32_t PASS_THROUGH_EVENT_ID = 100000;
76 } // namespace
77 const std::string DEFAULT_MOUSE_DRAG_IMAGE { "/system/etc/device_status/drag_icon/Copy_Drag.svg" };
78
IsPixelMapNeedScale() const79 bool GestureEventHub::IsPixelMapNeedScale() const
80 {
81 auto frameNode = GetFrameNode();
82 CHECK_NULL_RETURN(frameNode, false);
83 auto scale = DragDropFuncWrapper::GetPixelMapScale(frameNode);
84 return scale != 1.0f;
85 }
86
IsDragNewFwk() const87 bool GestureEventHub::IsDragNewFwk() const
88 {
89 return isDragNewFwk_;
90 }
91
CheckNeedDragDropFrameworkStatus(const std::string & tag)92 bool CheckNeedDragDropFrameworkStatus(const std::string& tag)
93 {
94 auto dragDropFrameworkStatus = SystemProperties::GetDragDropFrameworkStatus();
95 if (dragDropFrameworkStatus == DEFAULT_DRAG_DROP_STATUS &&
96 (OLD_FRAMEWORK_TAG.find(tag) != OLD_FRAMEWORK_TAG.end())) {
97 return false;
98 } else if ((dragDropFrameworkStatus == NEW_DRAG_DROP_STATUS) && (VALID_TAG.find(tag) != VALID_TAG.end())) {
99 return false;
100 } else if (dragDropFrameworkStatus == OLD_DRAG_DROP_STATUS) {
101 return false;
102 }
103 return true;
104 }
105
InitDragDropEvent()106 void GestureEventHub::InitDragDropEvent()
107 {
108 auto frameNode = GetFrameNode();
109 if (frameNode && CheckNeedDragDropFrameworkStatus(frameNode->GetTag())) {
110 SetDragDropEvent();
111 return;
112 }
113 auto actionStartTask = [weak = WeakClaim(this)](const GestureEvent& info) {
114 auto gestureEventHub = weak.Upgrade();
115 CHECK_NULL_VOID(gestureEventHub);
116 gestureEventHub->HandleOnDragStart(info);
117 };
118
119 auto actionUpdateTask = [weak = WeakClaim(this)](const GestureEvent& info) {
120 auto gestureEventHub = weak.Upgrade();
121 CHECK_NULL_VOID(gestureEventHub);
122 gestureEventHub->HandleOnDragUpdate(info);
123 };
124
125 auto actionEndTask = [weak = WeakClaim(this)](const GestureEvent& info) {
126 auto gestureEventHub = weak.Upgrade();
127 CHECK_NULL_VOID(gestureEventHub);
128 gestureEventHub->HandleOnDragEnd(info);
129 };
130
131 auto actionCancelTask = [weak = WeakClaim(this)]() {
132 auto gestureEventHub = weak.Upgrade();
133 CHECK_NULL_VOID(gestureEventHub);
134 gestureEventHub->HandleOnDragCancel();
135 };
136 auto dragEvent = MakeRefPtr<DragEvent>(
137 std::move(actionStartTask), std::move(actionUpdateTask), std::move(actionEndTask), std::move(actionCancelTask));
138 auto distance = SystemProperties::GetDragStartPanDistanceThreshold();
139 SetDragEvent(dragEvent, { PanDirection::ALL }, DEFAULT_PAN_FINGER, Dimension(distance, DimensionUnit::VP));
140 CHECK_NULL_VOID(dragEventActuator_);
141 dragEventActuator_->SetIsForDragDrop(false);
142 }
143
IsAllowedDrag(RefPtr<EventHub> eventHub)144 bool GestureEventHub::IsAllowedDrag(RefPtr<EventHub> eventHub)
145 {
146 auto frameNode = GetFrameNode();
147 CHECK_NULL_RETURN(frameNode, false);
148 auto pattern = frameNode->GetPattern();
149 CHECK_NULL_RETURN(pattern, false);
150
151 if (frameNode->IsDraggable()) {
152 if (!eventHub->HasOnDragStart() && !pattern->DefaultSupportDrag()) {
153 return false;
154 }
155 } else {
156 if (frameNode->IsUserSet()) {
157 return false;
158 }
159 if (!eventHub->HasOnDragStart() && !pattern->DefaultSupportDrag()) {
160 return false;
161 }
162 }
163 return true;
164 }
165
StartLongPressActionForWeb()166 void GestureEventHub::StartLongPressActionForWeb()
167 {
168 TAG_LOGI(AceLogTag::ACE_WEB, "DragDrop start long press action for web");
169 auto pipeline = PipelineContext::GetCurrentContext();
170 CHECK_NULL_VOID(pipeline);
171 auto taskScheduler = pipeline->GetTaskExecutor();
172 CHECK_NULL_VOID(taskScheduler);
173
174 taskScheduler->PostTask(
175 [weak = WeakClaim(this)]() {
176 auto gestureHub = weak.Upgrade();
177 CHECK_NULL_VOID(gestureHub);
178 auto dragEventActuator = gestureHub->dragEventActuator_;
179 CHECK_NULL_VOID(dragEventActuator);
180 dragEventActuator->StartLongPressActionForWeb();
181 },
182 TaskExecutor::TaskType::UI, "ArkUIGestureWebStartLongPress");
183 }
184
CancelDragForWeb()185 void GestureEventHub::CancelDragForWeb()
186 {
187 TAG_LOGD(AceLogTag::ACE_WEB, "DragDrop cancel drag for web");
188 auto pipeline = PipelineContext::GetCurrentContext();
189 CHECK_NULL_VOID(pipeline);
190 auto taskScheduler = pipeline->GetTaskExecutor();
191 CHECK_NULL_VOID(taskScheduler);
192
193 taskScheduler->PostTask(
194 [weak = WeakClaim(this)]() {
195 auto gestureHub = weak.Upgrade();
196 CHECK_NULL_VOID(gestureHub);
197 auto dragEventActuator = gestureHub->dragEventActuator_;
198 CHECK_NULL_VOID(dragEventActuator);
199 dragEventActuator->CancelDragForWeb();
200 },
201 TaskExecutor::TaskType::UI, "ArkUIGestureWebCancelDrag");
202 }
203
ResetDragActionForWeb()204 void GestureEventHub::ResetDragActionForWeb()
205 {
206 TAG_LOGD(AceLogTag::ACE_WEB, "DragDrop reset drag action for web");
207 isReceivedDragGestureInfo_ = false;
208 CHECK_NULL_VOID(dragEventActuator_);
209 dragEventActuator_->ResetDragActionForWeb();
210
211 // fix drag failed when long press drag after 500ms and before 800ms
212 // need to reset the state of the drag manager
213 auto pipeLine = PipelineContext::GetCurrentContext();
214 CHECK_NULL_VOID(pipeLine);
215 auto dragDropManager = pipeLine->GetDragDropManager();
216 CHECK_NULL_VOID(dragDropManager);
217 dragDropManager->ResetDragging();
218 }
219
StartDragTaskForWeb()220 bool GestureEventHub::StartDragTaskForWeb()
221 {
222 if (!isReceivedDragGestureInfo_) {
223 TAG_LOGW(AceLogTag::ACE_WEB, "DragDrop StartDragTaskForWeb failed,"
224 "because not recv gesture info");
225 return false;
226 }
227
228 isReceivedDragGestureInfo_ = false;
229 auto pipeline = PipelineContext::GetCurrentContext();
230 CHECK_NULL_RETURN(pipeline, false);
231 auto taskScheduler = pipeline->GetTaskExecutor();
232 CHECK_NULL_RETURN(taskScheduler, false);
233
234 TAG_LOGI(AceLogTag::ACE_WEB, "DragDrop post a task to start drag for web");
235 taskScheduler->PostTask(
236 [weak = WeakClaim(this)]() {
237 auto gestureHub = weak.Upgrade();
238 CHECK_NULL_VOID(gestureHub);
239 auto dragEventActuator = gestureHub->dragEventActuator_;
240 CHECK_NULL_VOID(dragEventActuator);
241 CHECK_NULL_VOID(gestureHub->gestureInfoForWeb_);
242 TAG_LOGI(AceLogTag::ACE_WEB, "DragDrop start drag task for web in async task");
243 dragEventActuator->StartDragTaskForWeb(*gestureHub->gestureInfoForWeb_);
244 },
245 TaskExecutor::TaskType::UI, "ArkUIGestureWebStartDrag");
246 return true;
247 }
248
CreatePixelMapFromString(const std::string & filePath)249 RefPtr<PixelMap> CreatePixelMapFromString(const std::string& filePath)
250 {
251 auto imageSource = ImageSource::Create(filePath);
252 CHECK_NULL_RETURN(imageSource, nullptr);
253 RefPtr<PixelMap> pixelMap = imageSource->CreatePixelMap();
254 return pixelMap;
255 }
256
CalcFrameNodeOffsetAndSize(const RefPtr<FrameNode> frameNode,bool isMenuShow)257 void GestureEventHub::CalcFrameNodeOffsetAndSize(const RefPtr<FrameNode> frameNode, bool isMenuShow)
258 {
259 CHECK_NULL_VOID(frameNode);
260 auto frameTag = frameNode->GetTag();
261 auto hostPattern = frameNode->GetPattern<TextDragBase>();
262 if (hostPattern && GetTextDraggable() &&
263 (frameTag == V2::RICH_EDITOR_ETS_TAG || frameTag == V2::TEXT_ETS_TAG || frameTag == V2::TEXTINPUT_ETS_TAG ||
264 frameTag == V2::SEARCH_Field_ETS_TAG)) {
265 frameNodeOffset_ = hostPattern->GetDragUpperLeftCoordinates();
266 frameNodeSize_ = SizeF(0.0f, 0.0f);
267 } else {
268 auto center = DragDropFuncWrapper::GetPaintRectCenterToScreen(frameNode) -
269 DragDropFuncWrapper::GetCurrentWindowOffset(PipelineContext::GetCurrentContextSafelyWithCheck());
270 auto geometryNode = frameNode->GetGeometryNode();
271 if (geometryNode) {
272 auto scale = frameNode->GetTransformScaleRelativeToWindow();
273 auto size = geometryNode->GetFrameSize();
274 frameNodeSize_ = SizeF(size.Width() * scale.x, size.Height() * scale.y);
275 } else {
276 frameNodeSize_ = SizeF(0.0f, 0.0f);
277 }
278 frameNodeOffset_ = center - OffsetF(frameNodeSize_.Width(), frameNodeSize_.Height()) / HALF_DIVIDE;
279 #ifdef WEB_SUPPORTED
280 if (frameTag == V2::WEB_ETS_TAG) {
281 auto webPattern = frameNode->GetPattern<WebPattern>();
282 if (webPattern) {
283 frameNodeOffset_.SetX(frameNodeOffset_.GetX() + webPattern->GetDragOffset().GetX());
284 frameNodeOffset_.SetY(frameNodeOffset_.GetY() + webPattern->GetDragOffset().GetY());
285 frameNodeSize_ = webPattern->GetDragPixelMapSize();
286 }
287 }
288 #endif
289 }
290
291 // use menuPreview's size and offset for drag framework.
292 if (!frameNode->GetDragPreview().onlyForLifting && isMenuShow && GreatNotEqual(menuPreviewScale_, 0.0f) &&
293 (GreatNotEqual(DragAnimationHelper::GetPreviewMenuAnimationRate(), 0.0f) ||
294 frameNode->GetDragPreviewOption().sizeChangeEffect == DraggingSizeChangeEffect::DEFAULT)) {
295 auto menuPreviewRect = DragDropManager::GetMenuPreviewRect();
296 if (GreatNotEqual(menuPreviewRect.Width(), 0.0f) && GreatNotEqual(menuPreviewRect.Height(), 0.0f)) {
297 frameNodeOffset_ = menuPreviewRect.GetOffset();
298 frameNodeSize_ = menuPreviewRect.GetSize();
299 }
300 }
301 }
302
GetDefaultPixelMapScale(const RefPtr<FrameNode> & frameNode,const GestureEvent & info,bool isMenuShow,RefPtr<PixelMap> pixelMap)303 float GestureEventHub::GetDefaultPixelMapScale(
304 const RefPtr<FrameNode>& frameNode, const GestureEvent& info, bool isMenuShow, RefPtr<PixelMap> pixelMap)
305 {
306 float defaultPixelMapScale =
307 info.GetInputEventType() == InputEventType::MOUSE_BUTTON ? 1.0f : DEFALUT_DRAG_PPIXELMAP_SCALE;
308 CHECK_NULL_RETURN(pixelMap, defaultPixelMapScale);
309 // use menuPreviewScale for drag framework. this is not final solution.
310 if (!frameNode->GetDragPreview().onlyForLifting && isMenuShow && GreatNotEqual(menuPreviewScale_, 0.0f)) {
311 auto menuPreviewRectWidth = frameNodeSize_.Width();
312 int32_t originPixelMapWidth = pixelMap->GetWidth();
313 if (GreatNotEqual(menuPreviewRectWidth, 0.0f) && GreatNotEqual(originPixelMapWidth, 0.0f) &&
314 menuPreviewRectWidth < originPixelMapWidth * menuPreviewScale_) {
315 defaultPixelMapScale = menuPreviewRectWidth / originPixelMapWidth;
316 } else {
317 defaultPixelMapScale = menuPreviewScale_;
318 }
319 }
320 return defaultPixelMapScale;
321 }
322
CheckInSceneBoardWindow()323 bool CheckInSceneBoardWindow()
324 {
325 auto container = Container::Current();
326 CHECK_NULL_RETURN(container, false);
327 if (!container->IsSubContainer()) {
328 return container->IsSceneBoardWindow();
329 }
330 auto parentContainerId = SubwindowManager::GetInstance()->GetParentContainerId(Container::CurrentId());
331 container = Container::GetContainer(parentContainerId);
332 CHECK_NULL_RETURN(container, false);
333 return container->IsSceneBoardWindow();
334 }
335
CheckOffsetInPixelMap(OffsetF & result,const SizeF & size)336 void CheckOffsetInPixelMap(OffsetF& result, const SizeF& size)
337 {
338 if (result.GetX() >= 0.0f) {
339 result.SetX(-1.0f);
340 }
341 if (result.GetX() + size.Width() <= 0.0f) {
342 result.SetX(1.0f - size.Width());
343 }
344 if (result.GetY() >= 0.0f) {
345 result.SetY(-1.0f);
346 }
347 if (result.GetY() + size.Height() <= 0.0f) {
348 result.SetY(1.0f - size.Height());
349 }
350 }
351
ParseInnerRect(const std::string & extraInfo,const SizeF & size)352 RectF ParseInnerRect(const std::string& extraInfo, const SizeF& size)
353 {
354 auto innerRect = RectF();
355 if (!CheckInSceneBoardWindow() || extraInfo.empty()) {
356 return innerRect;
357 }
358 auto extraJson = JsonUtil::ParseJsonString(extraInfo);
359 CHECK_NULL_RETURN(extraJson, innerRect);
360 auto extraOffsetX = extraJson->GetInt("drag_offset_x");
361 auto extraOffsetY = extraJson->GetInt("drag_offset_y");
362 if (extraOffsetX <= 0 || extraOffsetY <= 0) {
363 return innerRect;
364 }
365 innerRect.SetOffset(OffsetF(Dimension(extraOffsetX, DimensionUnit::VP).ConvertToPx(),
366 Dimension(extraOffsetY, DimensionUnit::VP).ConvertToPx()));
367 innerRect.SetSize(size);
368 return innerRect;
369 }
370
GetPixelMapOffset(const GestureEvent & info,const SizeF & size,const PreparedInfoForDrag & dragInfoData,const float scale,const RectF & innerRect) const371 OffsetF GestureEventHub::GetPixelMapOffset(const GestureEvent& info, const SizeF& size,
372 const PreparedInfoForDrag& dragInfoData, const float scale, const RectF& innerRect) const
373 {
374 OffsetF result = OffsetF(size.Width() * PIXELMAP_WIDTH_RATE, size.Height() * PIXELMAP_HEIGHT_RATE);
375 auto frameNode = GetFrameNode();
376 CHECK_NULL_RETURN(frameNode, result);
377 auto frameTag = frameNode->GetTag();
378 auto coordinateX = frameNodeOffset_.GetX();
379 auto coordinateY = frameNodeOffset_.GetY();
380 if (!innerRect.IsEmpty() && !NearZero(size.Width()) && !NearZero(size.Height())) {
381 auto rateX = innerRect.Width() / size.Width();
382 auto rateY = innerRect.Height() / size.Height();
383 result.SetX(rateX * (coordinateX + innerRect.GetOffset().GetX() - info.GetGlobalLocation().GetX()));
384 result.SetY(rateY * (coordinateY + innerRect.GetOffset().GetY() - info.GetGlobalLocation().GetY()));
385 CheckOffsetInPixelMap(result, size);
386 return result;
387 }
388 if (NearZero(frameNodeSize_.Width()) || NearZero(frameNodeSize_.Height()) ||
389 NearZero(size.Width()) || NearZero(size.Height())) {
390 result.SetX(scale * (coordinateX - info.GetGlobalLocation().GetX()));
391 result.SetY(scale * (coordinateY - info.GetGlobalLocation().GetY()));
392 } else {
393 if (dragInfoData.isNeedCreateTiled) {
394 result.SetX(-size.Width() / HALF_PIXELMAP);
395 result.SetY(-size.Height() / HALF_PIXELMAP);
396 } else if (frameNode->GetDragPreviewOption().isTouchPointCalculationBasedOnFinalPreviewEnable) {
397 auto centerX = coordinateX + frameNodeSize_.Width() / HALF_PIXELMAP;
398 auto centerY = coordinateY + frameNodeSize_.Height() / HALF_PIXELMAP;
399 coordinateX = centerX - dragInfoData.dragPreviewRect.Width() / HALF_PIXELMAP;
400 coordinateY = centerY - dragInfoData.dragPreviewRect.Height() / HALF_PIXELMAP;
401 auto rateX = (info.GetGlobalLocation().GetX() - coordinateX) / dragInfoData.dragPreviewRect.Width();
402 auto rateY = (info.GetGlobalLocation().GetY() - coordinateY) / dragInfoData.dragPreviewRect.Height();
403 result.SetX(-rateX * size.Width());
404 result.SetY(-rateY * size.Height());
405 } else {
406 auto rateX = (info.GetGlobalLocation().GetX() - coordinateX) / frameNodeSize_.Width();
407 auto rateY = (info.GetGlobalLocation().GetY() - coordinateY) / frameNodeSize_.Height();
408 result.SetX(-rateX * size.Width());
409 result.SetY(-rateY * size.Height());
410 }
411 }
412 CheckOffsetInPixelMap(result, size);
413 TAG_LOGD(AceLogTag::ACE_DRAG, "Get pixelMap offset is %{public}f and %{public}f.", result.GetX(), result.GetY());
414 return result;
415 }
416
ProcessMenuPreviewScale(const RefPtr<FrameNode> imageNode,float & scale,float previewScale,float windowScale,float defaultMenuPreviewScale)417 void GestureEventHub::ProcessMenuPreviewScale(const RefPtr<FrameNode> imageNode, float& scale, float previewScale,
418 float windowScale, float defaultMenuPreviewScale)
419 {
420 auto imageGestureEventHub = imageNode->GetOrCreateGestureEventHub();
421 CHECK_NULL_VOID(imageGestureEventHub);
422 if (!IsPixelMapNeedScale()) {
423 if (CheckInSceneBoardWindow()) {
424 imageGestureEventHub->SetMenuPreviewScale(defaultMenuPreviewScale);
425 } else {
426 //if not in sceneboard,use default drag scale
427 scale = previewScale * windowScale;
428 imageGestureEventHub->SetMenuPreviewScale(previewScale);
429 }
430 } else {
431 imageGestureEventHub->SetMenuPreviewScale(scale);
432 }
433 }
434
GetPreScaledPixelMapIfExist(float targetScale,RefPtr<PixelMap> defaultPixelMap)435 RefPtr<PixelMap> GestureEventHub::GetPreScaledPixelMapIfExist(float targetScale, RefPtr<PixelMap> defaultPixelMap)
436 {
437 ACE_SCOPED_TRACE("drag: get scaled pixmal, %f", targetScale);
438 float preScale = 1.0f;
439 CHECK_NULL_RETURN(dragEventActuator_, defaultPixelMap);
440 auto frameNode = GetFrameNode();
441 RefPtr<PixelMap> preScaledPixelMap;
442 if (!(frameNode && frameNode->GetDragPreview().onlyForLifting)) {
443 preScaledPixelMap = dragEventActuator_->GetPreScaledPixelMapForDragThroughTouch(preScale);
444 }
445 if (preScale == targetScale && preScaledPixelMap != nullptr) {
446 return preScaledPixelMap;
447 }
448 #if defined(PIXEL_MAP_SUPPORTED)
449 preScaledPixelMap = PixelMap::CopyPixelMap(defaultPixelMap);
450 if (!preScaledPixelMap) {
451 TAG_LOGW(AceLogTag::ACE_DRAG, "duplicate PixelMap failed!");
452 preScaledPixelMap = defaultPixelMap;
453 }
454 if (!NearEqual(targetScale, 1.0f)) {
455 preScaledPixelMap->Scale(targetScale, targetScale, AceAntiAliasingOption::HIGH);
456 }
457 #else
458 preScaledPixelMap = defaultPixelMap;
459 #endif
460 return preScaledPixelMap;
461 }
462
GetPixelMapScale(const int32_t height,const int32_t width) const463 float GestureEventHub::GetPixelMapScale(const int32_t height, const int32_t width) const
464 {
465 float scale = 1.0f;
466 if (height == 0 || width == 0) {
467 return scale;
468 }
469 auto frameNode = GetFrameNode();
470 CHECK_NULL_RETURN(frameNode, scale);
471 auto pipeline = frameNode->GetContextRefPtr();
472 CHECK_NULL_RETURN(pipeline, scale);
473 auto dragDropManager = pipeline->GetDragDropManager();
474 CHECK_NULL_RETURN(dragDropManager, scale);
475 auto windowScale = dragDropManager->GetWindowScale();
476 if (!frameNode->GetDragPreviewOption().isScaleEnabled || !(frameNode->GetTag() == V2::WEB_ETS_TAG)) {
477 return scale * windowScale;
478 }
479 int32_t deviceHeight = SystemProperties::GetDevicePhysicalHeight();
480 int32_t deviceWidth = SystemProperties::GetDevicePhysicalWidth();
481 int32_t maxDeviceLength = std::max(deviceHeight, deviceWidth);
482 int32_t minDeviceLength = std::min(deviceHeight, deviceWidth);
483 if (maxDeviceLength * PIXELMAP_DEFALUT_LIMIT_SCALE > minDeviceLength) {
484 if (height > minDeviceLength * PIXELMAP_DEFALUT_LIMIT_SCALE) {
485 scale = static_cast<float>(minDeviceLength * PIXELMAP_DEFALUT_LIMIT_SCALE) / height;
486 }
487 } else {
488 if (GetTextDraggable() && height > minDeviceLength / PIXELMAP_DRAG_WGR_SCALE &&
489 width > minDeviceLength * PIXELMAP_DRAG_WGR_TEXT_SCALE / PIXELMAP_DRAG_WGR_SCALE) {
490 scale = fmin(static_cast<float>(minDeviceLength / PIXELMAP_DRAG_WGR_SCALE) / height,
491 static_cast<float>(minDeviceLength * PIXELMAP_DRAG_WGR_TEXT_SCALE / PIXELMAP_DRAG_WGR_SCALE) / width);
492 } else if (height > minDeviceLength / PIXELMAP_DRAG_WGR_SCALE &&
493 width > minDeviceLength / PIXELMAP_DRAG_WGR_SCALE) {
494 scale = fmin(static_cast<float>(minDeviceLength / PIXELMAP_DRAG_WGR_SCALE) / height,
495 static_cast<float>(minDeviceLength / PIXELMAP_DRAG_WGR_SCALE) / width);
496 }
497 }
498 return scale * windowScale;
499 }
500
GenerateMousePixelMap(const GestureEvent & info)501 void GestureEventHub::GenerateMousePixelMap(const GestureEvent& info)
502 {
503 auto frameNode = GetFrameNode();
504 CHECK_NULL_VOID(frameNode);
505 RefPtr<RenderContext> context;
506 if (GetTextDraggable()) {
507 auto pattern = frameNode->GetPattern<TextDragBase>();
508 CHECK_NULL_VOID(pattern);
509 auto dragNode = pattern->MoveDragNode();
510 CHECK_NULL_VOID(dragNode);
511 auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
512 CHECK_NULL_VOID(pipeline);
513 pipeline->FlushPipelineImmediately();
514 context = dragNode->GetRenderContext();
515 } else {
516 context = frameNode->GetRenderContext();
517 }
518 CHECK_NULL_VOID(context);
519 auto thumbnailPixelMap = context->GetThumbnailPixelMap(false, GetTextDraggable());
520 CHECK_NULL_VOID(thumbnailPixelMap);
521 SetPixelMap(thumbnailPixelMap);
522 }
523
HandleNotAllowDrag(const GestureEvent & info)524 void GestureEventHub::HandleNotAllowDrag(const GestureEvent& info)
525 {
526 auto frameNode = GetFrameNode();
527 CHECK_NULL_VOID(frameNode);
528 if (frameNode->GetTag() == V2::WEB_ETS_TAG) {
529 gestureInfoForWeb_ = std::make_shared<GestureEvent>(info);
530 isReceivedDragGestureInfo_ = true;
531 TAG_LOGD(AceLogTag::ACE_WEB, "DragDrop drag gesture info received");
532 }
533 }
534
HandleDragThroughTouch(const RefPtr<FrameNode> frameNode)535 void GestureEventHub::HandleDragThroughTouch(const RefPtr<FrameNode> frameNode)
536 {
537 CHECK_NULL_VOID(frameNode);
538 dragframeNodeInfo_.frameNode = frameNode;
539 auto pipeline = frameNode->GetContextRefPtr();
540 CHECK_NULL_VOID(pipeline);
541 auto dragDropManager = pipeline->GetDragDropManager();
542 CHECK_NULL_VOID(dragDropManager);
543 auto grayedState = dragDropManager->GetGrayedState();
544 if (grayedState) {
545 return;
546 }
547 auto overlayManager = pipeline->GetOverlayManager();
548 CHECK_NULL_VOID(overlayManager);
549 auto gatherNodeChildrenInfo = overlayManager->GetGatherNodeChildrenInfo();
550 if (!gatherNodeChildrenInfo.empty()) {
551 for (const auto& itemFrameNode : gatherNodeChildrenInfo) {
552 auto node = itemFrameNode.preImageNode.Upgrade();
553 CHECK_NULL_VOID(node);
554 dragframeNodeInfo_.gatherFrameNode.push_back(node);
555 DragAnimationHelper::DoDragStartGrayedAnimation(node);
556 }
557 dragframeNodeInfo_.gatherFrameNode.push_back(frameNode);
558 }
559 DragAnimationHelper::DoDragStartGrayedAnimation(frameNode);
560 dragDropManager->SetGrayedState(true);
561 }
562
HandleDragThroughMouse(const RefPtr<FrameNode> frameNode)563 void GestureEventHub::HandleDragThroughMouse(const RefPtr<FrameNode> frameNode)
564 {
565 CHECK_NULL_VOID(frameNode);
566 dragframeNodeInfo_.frameNode = frameNode;
567 auto pipeline = frameNode->GetContextRefPtr();
568 CHECK_NULL_VOID(pipeline);
569 auto dragDropManager = pipeline->GetDragDropManager();
570 CHECK_NULL_VOID(dragDropManager);
571 auto grayedState = dragDropManager->GetGrayedState();
572 if (grayedState) {
573 return;
574 }
575 auto size = GetSelectItemSize();
576 if (size) {
577 auto fatherNode = DragDropFuncWrapper::FindItemParentNode(frameNode);
578 CHECK_NULL_VOID(fatherNode);
579 auto scrollPattern = fatherNode->GetPattern<ScrollablePattern>();
580 CHECK_NULL_VOID(scrollPattern);
581 auto children = scrollPattern->GetVisibleSelectedItems();
582 dragframeNodeInfo_.gatherFrameNode = children;
583 for (const auto& itemFrameNode : children) {
584 DragAnimationHelper::DoDragStartGrayedAnimation(itemFrameNode);
585 }
586 } else {
587 DragAnimationHelper::DoDragStartGrayedAnimation(frameNode);
588 }
589 dragDropManager->SetGrayedState(true);
590 }
591
IsNeedSwitchToSubWindow(const PreparedInfoForDrag & dragInfoData) const592 bool GestureEventHub::IsNeedSwitchToSubWindow(const PreparedInfoForDrag& dragInfoData) const
593 {
594 auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
595 CHECK_NULL_RETURN(pipeline, false);
596 auto dragDropManager = pipeline->GetDragDropManager();
597 CHECK_NULL_RETURN(dragDropManager, false);
598 if (dragInfoData.isMenuShow) {
599 return true;
600 }
601 if (dragInfoData.isNeedCreateTiled) {
602 return false;
603 }
604 if (IsPixelMapNeedScale() || DragDropGlobalController::GetInstance().GetAsyncDragCallback() != nullptr) {
605 return true;
606 }
607 CHECK_NULL_RETURN(dragEventActuator_, false);
608 return dragEventActuator_->IsNeedGather();
609 }
610
HandleOnDragStart(const GestureEvent & info)611 void GestureEventHub::HandleOnDragStart(const GestureEvent& info)
612 {
613 TAG_LOGD(AceLogTag::ACE_DRAG, "Start handle onDragStart.");
614 auto frameNode = GetFrameNode();
615 auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
616 if (!frameNode || !pipeline || !CheckAllowDrag(info, pipeline, frameNode)) {
617 TAG_LOGE(AceLogTag::ACE_DRAG, "Check not allow drag");
618 HandleNotAllowDrag(info);
619 return;
620 }
621
622 // set menu window touchable
623 auto mainPipeline = PipelineContext::GetMainPipelineContext();
624 DragDropFuncWrapper::SetMenuSubWindowTouchable((mainPipeline != pipeline));
625 // set drag drop status is moving
626 DragDropGlobalController::GetInstance().UpdateDragDropInitiatingStatus(frameNode, DragDropInitiatingStatus::MOVING);
627
628 if (info.GetInputEventType() == InputEventType::MOUSE_BUTTON) {
629 SetMouseDragMonitorState(true);
630 }
631
632 CalcFrameNodeOffsetAndSize(frameNode, DragDropGlobalController::GetInstance().IsMenuShowing());
633
634 // create drag event
635 auto event = CreateDragEvent(info, pipeline, frameNode);
636
637 /*
638 * Users may remove frameNode in the js callback function "onDragStart "triggered below,
639 * so save the offset of the framenode relative to the window in advance
640 */
641 DragDropInfo dragPreviewInfo;
642 auto dragDropInfo = GetDragDropInfo(info, frameNode, dragPreviewInfo, event);
643 auto callAnsyncEnd = [weak = WeakClaim(this), frameNode](DragStartRequestStatus dragStatus) {
644 if (dragStatus == DragStartRequestStatus::WAITING) {
645 auto gestureEventHub = weak.Upgrade();
646 CHECK_NULL_VOID(gestureEventHub);
647 auto pipeline = frameNode->GetContextRefPtr();
648 CHECK_NULL_VOID(pipeline);
649 auto eventHub = gestureEventHub->eventHub_.Upgrade();
650 CHECK_NULL_VOID(eventHub);
651 gestureEventHub->FireCustomerOnDragEnd(pipeline, eventHub);
652 }
653 };
654 auto continueFunc = [id = Container::CurrentId(), weak = WeakClaim(this), dragPreviewInfo, info, event,
655 dragDropInfo, frameNode, pipeline]() {
656 ContainerScope scope(id);
657 auto gestureEventHub = weak.Upgrade();
658 CHECK_NULL_VOID(gestureEventHub);
659 if (info.GetInputEventType() == InputEventType::MOUSE_BUTTON) {
660 gestureEventHub->SetMouseDragMonitorState(true);
661 }
662 gestureEventHub->DoOnDragStartHandling(info, frameNode, dragDropInfo, event, dragPreviewInfo, pipeline);
663 };
664 auto dragDropManager = pipeline->GetDragDropManager();
665 CHECK_NULL_VOID(dragDropManager);
666 dragDropManager->ResetBundleInfo();
667 if (DragDropGlobalController::GetInstance().GetDragStartRequestStatus() == DragStartRequestStatus::READY) {
668 DoOnDragStartHandling(info, frameNode, dragDropInfo, event, dragPreviewInfo, pipeline);
669 } else {
670 dragDropManager->SetDelayDragCallBack(continueFunc);
671 dragDropManager->SetCallAnsyncDragEnd(callAnsyncEnd);
672 TAG_LOGI(AceLogTag::ACE_DRAG, "drag start pended");
673 }
674 }
675
ParsePixelMapAsync(DragDropInfo & dragDropInfo,const DragDropInfo & dragPreviewInfo,const GestureEvent & info)676 bool GestureEventHub::ParsePixelMapAsync(DragDropInfo& dragDropInfo, const DragDropInfo& dragPreviewInfo,
677 const GestureEvent& info)
678 {
679 auto frameNode = GetFrameNode();
680 CHECK_NULL_RETURN(frameNode, false);
681 if (DragDropFuncWrapper::IsNeedCreateTiledPixelMap(frameNode, dragEventActuator_, info.GetSourceDevice())) {
682 ACE_SCOPED_TRACE("drag: create titled pixelMap");
683 dragDropInfo.pixelMap = DragDropFuncWrapper::CreateTiledPixelMap(frameNode);
684 return true;
685 }
686
687 if (dragPreviewInfo.inspectorId != "") {
688 ACE_SCOPED_TRACE("drag: handling with inspector");
689 auto dragPreviewPixelMap = GetDragPreviewPixelMap();
690 TAG_LOGI(AceLogTag::ACE_DRAG, "InspectorId exist, get thumbnail.");
691 if (dragPreviewPixelMap == nullptr) {
692 dragPreviewPixelMap = DragDropFuncWrapper::GetPreviewPixelMap(dragPreviewInfo.inspectorId, frameNode);
693 }
694 dragDropInfo.pixelMap = dragPreviewPixelMap;
695 return true;
696 }
697
698 if (info.GetSourceDevice() != SourceType::MOUSE) {
699 if (dragPreviewInfo.pixelMap != nullptr || dragPreviewInfo.customNode != nullptr) {
700 if (dragPreviewPixelMap_ != nullptr) {
701 ACE_SCOPED_TRACE("drag: handling with drag preview");
702 TAG_LOGI(AceLogTag::ACE_DRAG, "Non-mouse dragging, get thumbnail.");
703 dragDropInfo.pixelMap = dragPreviewPixelMap_;
704 return true;
705 }
706 }
707 if (dragDropInfo.pixelMap == nullptr && dragDropInfo.customNode == nullptr &&
708 dragPreviewInfo.pixelMap == nullptr && dragPreviewInfo.customNode == nullptr && pixelMap_ != nullptr &&
709 !frameNode->GetDragPreview().onlyForLifting) {
710 dragDropInfo.pixelMap = pixelMap_;
711 return true;
712 }
713 }
714 if (dragPreviewInfo.pixelMap != nullptr) {
715 ACE_SCOPED_TRACE("drag: handling with pixelmap directly");
716 dragDropInfo.pixelMap = dragPreviewInfo.pixelMap;
717 TAG_LOGI(AceLogTag::ACE_DRAG, "PixelMap exist, get thumbnail.");
718 return true;
719 } else if (dragPreviewInfo.customNode != nullptr) {
720 dragDropInfo.customNode = dragPreviewInfo.customNode;
721 }
722 return dragDropInfo.pixelMap;
723 }
724
DoOnDragStartHandling(const GestureEvent & info,const RefPtr<FrameNode> frameNode,DragDropInfo dragDropInfo,const RefPtr<OHOS::Ace::DragEvent> & event,DragDropInfo dragPreviewInfo,const RefPtr<PipelineContext> & pipeline)725 void GestureEventHub::DoOnDragStartHandling(const GestureEvent& info, const RefPtr<FrameNode> frameNode,
726 DragDropInfo dragDropInfo, const RefPtr<OHOS::Ace::DragEvent>& event, DragDropInfo dragPreviewInfo,
727 const RefPtr<PipelineContext>& pipeline)
728 {
729 CHECK_NULL_VOID(frameNode);
730 GetUnifiedData(frameNode->GetTag(), dragDropInfo, event);
731 // set drag pointer status
732 auto dragDropManager = pipeline->GetDragDropManager();
733 CHECK_NULL_VOID(dragDropManager);
734 dragDropManager->SetDraggingPointer(info.GetPointerId());
735 dragDropManager->SetDraggingPressedState(true);
736
737 if (ParsePixelMapAsync(dragDropInfo, dragPreviewInfo, info)) {
738 OnDragStart(info, pipeline, frameNode, dragDropInfo, event);
739 return;
740 }
741
742 #if defined(PIXEL_MAP_SUPPORTED)
743 if (dragDropInfo.pixelMap == nullptr && dragDropInfo.customNode) {
744 ACE_SCOPED_TRACE("drag: handling for custom builder");
745 StartDragForCustomBuilder(info, pipeline, frameNode, dragDropInfo, event);
746 return;
747 }
748 #endif
749 TAG_LOGI(AceLogTag::ACE_DRAG, "DragDropInfo is empty.");
750 ACE_SCOPED_TRACE("drag: handling without preview");
751 if (!dragDropInfo.pixelMap) {
752 if (info.GetInputEventType() != InputEventType::MOUSE_BUTTON && GetTextDraggable() && pixelMap_) {
753 dragDropInfo.pixelMap = pixelMap_;
754 } else {
755 GenerateMousePixelMap(info);
756 dragDropInfo.pixelMap = pixelMap_;
757 }
758 }
759 if (info.GetInputEventType() == InputEventType::MOUSE_BUTTON && !dragDropInfo.pixelMap) {
760 TAG_LOGD(AceLogTag::ACE_DRAG, "no any pixmap got, get node snapshot final try");
761 ACE_SCOPED_TRACE("drag: no any pixmap got, get node snapshot final try");
762 dragDropInfo.pixelMap = CreatePixelMapFromString(DEFAULT_MOUSE_DRAG_IMAGE);
763 }
764 OnDragStart(info, pipeline, frameNode, dragDropInfo, event);
765 }
766
HideMenu()767 void GestureEventHub::HideMenu()
768 {
769 auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
770 CHECK_NULL_VOID(pipeline);
771 auto dragDrogDropManager = pipeline->GetDragDropManager();
772 CHECK_NULL_VOID(dragDrogDropManager);
773 TAG_LOGI(AceLogTag::ACE_DRAG, "Hide menu. showPreviewAnimation false, startDrag true.");
774 SubwindowManager::GetInstance()->HideMenuNG(false, true);
775 auto menuWrapperNode = dragDrogDropManager->GetMenuWrapperNode();
776 CHECK_NULL_VOID(menuWrapperNode);
777 auto menuWrapperPattern = menuWrapperNode->GetPattern<MenuWrapperPattern>();
778 CHECK_NULL_VOID(menuWrapperPattern);
779 auto imageNode = menuWrapperPattern->GetPreview();
780 CHECK_NULL_VOID(imageNode);
781 auto imageContext = imageNode->GetRenderContext();
782 CHECK_NULL_VOID(imageContext);
783 imageContext->UpdateOpacity(0.0f);
784 }
785
CalcPreviewPaintRect(const RefPtr<FrameNode> menuWrapperNode,PreparedInfoForDrag & data)786 void CalcPreviewPaintRect(const RefPtr<FrameNode> menuWrapperNode, PreparedInfoForDrag& data)
787 {
788 data.originPreviewRect = data.dragPreviewRect;
789 CHECK_NULL_VOID(menuWrapperNode);
790 auto menuWrapperPattern = menuWrapperNode->GetPattern<MenuWrapperPattern>();
791 CHECK_NULL_VOID(menuWrapperPattern);
792 auto menuPreview = menuWrapperPattern->GetPreview();
793 CHECK_NULL_VOID(menuPreview);
794 auto pipeline = PipelineContext::GetCurrentContextPtrSafelyWithCheck();
795 CHECK_NULL_VOID(pipeline);
796 auto menuTheme = pipeline->GetTheme<NG::MenuTheme>();
797 CHECK_NULL_VOID(menuTheme);
798 auto previewBorderRadiusValue = menuTheme->GetPreviewBorderRadius();
799 data.borderRadius = BorderRadiusProperty(previewBorderRadiusValue);
800 auto menuNode = menuWrapperPattern->GetMenu();
801 CHECK_NULL_VOID(menuNode);
802 auto menuPattern = menuNode->GetPattern<MenuPattern>();
803 CHECK_NULL_VOID(menuPattern);
804 auto isShowHoverImage = menuPattern->GetIsShowHoverImage();
805 data.menuPreviewNode = menuPreview;
806 data.originPreviewRect = DragDropFuncWrapper::GetPaintRectToScreen(menuPreview);
807 CHECK_EQUAL_VOID(isShowHoverImage, false);
808 auto animationInfo = menuWrapperPattern->GetPreviewMenuAnimationInfo();
809 auto previewPattern = menuPreview->GetPattern<MenuPreviewPattern>();
810 CHECK_NULL_VOID(previewPattern);
811 auto rate = animationInfo.clipRate;
812 auto scaleBefore = menuPattern->GetPreviewBeforeAnimationScale();
813 auto scaleAfter = menuPattern->GetPreviewAfterAnimationScale();
814 auto previewBeforeAnimationScale =
815 LessNotEqual(scaleBefore, 0.0) ? menuTheme->GetPreviewBeforeAnimationScale() : scaleBefore;
816 auto previewAfterAnimationScale =
817 LessNotEqual(scaleAfter, 0.0) ? menuTheme->GetPreviewAfterAnimationScale() : scaleAfter;
818 auto previewScale = rate * (previewAfterAnimationScale - previewBeforeAnimationScale) + previewBeforeAnimationScale;
819 if (!GreatNotEqual(rate, 0.0f)) {
820 data.sizeChangeEffect = DraggingSizeChangeEffect::SIZE_TRANSITION;
821 data.originPreviewRect = data.dragPreviewRect;
822 return;
823 }
824 auto clipStartWidth = previewPattern->GetHoverImageAfterScaleWidth() * previewScale;
825 auto clipStartHeight = previewPattern->GetHoverImageAfterScaleHeight() * previewScale;
826 auto clipEndWidth = previewPattern->GetStackAfterScaleActualWidth() * previewScale;
827 auto clipEndHeight = previewPattern->GetStackAfterScaleActualHeight() * previewScale;
828 auto curentWidth = rate * (clipEndWidth - clipStartWidth) + clipStartWidth;
829 auto curentHeight = rate * (clipEndHeight - clipStartHeight) + clipStartHeight;
830 auto centerX = data.originPreviewRect.GetX() + data.originPreviewRect.Width() / 2;
831 auto centerY = data.originPreviewRect.GetY() + data.originPreviewRect.Height() / 2;
832 auto x = centerX - curentWidth / 2;
833 auto y = centerY - curentHeight / 2;
834 data.originPreviewRect = RectF(x, y, curentWidth, curentHeight);
835 data.borderRadius = animationInfo.borderRadius;
836 }
837
PrepareDragStartInfo(RefPtr<PipelineContext> & pipeline,PreparedInfoForDrag & data,const RefPtr<FrameNode> frameNode)838 void GestureEventHub::PrepareDragStartInfo(
839 RefPtr<PipelineContext>& pipeline, PreparedInfoForDrag& data, const RefPtr<FrameNode> frameNode)
840 {
841 CHECK_NULL_VOID(pipeline);
842 auto dragDropManager = pipeline->GetDragDropManager();
843 CHECK_NULL_VOID(dragDropManager);
844 auto menuWrapperNode = dragDropManager->GetMenuWrapperNode();
845 CalcPreviewPaintRect(menuWrapperNode, data);
846 auto relativeContainerNode =
847 FrameNode::GetOrCreateFrameNode(V2::RELATIVE_CONTAINER_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
848 []() { return AceType::MakeRefPtr<OHOS::Ace::NG::RelativeContainerPattern>(); });
849 CHECK_NULL_VOID(relativeContainerNode);
850 data.relativeContainerNode = relativeContainerNode;
851 auto relativeContainerLayoutProperty = relativeContainerNode->GetLayoutProperty();
852 CHECK_NULL_VOID(relativeContainerLayoutProperty);
853 relativeContainerLayoutProperty->UpdateUserDefinedIdealSize(
854 { CalcLength(data.originPreviewRect.Width(), DimensionUnit::PX),
855 CalcLength(data.originPreviewRect.Height(), DimensionUnit::PX) });
856 auto relativeContainerRenderContext = relativeContainerNode->GetRenderContext();
857 CHECK_NULL_VOID(relativeContainerRenderContext);
858 relativeContainerRenderContext->UpdateTransformTranslate({ 0, 0, 0.0f });
859 CHECK_NULL_VOID(frameNode);
860 GestureEventHub::UpdateMenuNode(menuWrapperNode, data, frameNode);
861 }
862
OnDragStart(const GestureEvent & info,const RefPtr<PipelineBase> & context,const RefPtr<FrameNode> frameNode,DragDropInfo dragDropInfo,const RefPtr<OHOS::Ace::DragEvent> & dragEvent)863 void GestureEventHub::OnDragStart(const GestureEvent& info, const RefPtr<PipelineBase>& context,
864 const RefPtr<FrameNode> frameNode, DragDropInfo dragDropInfo, const RefPtr<OHOS::Ace::DragEvent>& dragEvent)
865 {
866 ACE_SCOPED_TRACE("drag: to start");
867 auto dragNodePipeline = frameNode->GetContextRefPtr();
868 CHECK_NULL_VOID(dragNodePipeline);
869 auto overlayManager = dragNodePipeline->GetOverlayManager();
870 auto pipeline = AceType::DynamicCast<PipelineContext>(context);
871 CHECK_NULL_VOID(pipeline);
872
873 auto dragDropManager = pipeline->GetDragDropManager();
874 CHECK_NULL_VOID(dragDropManager);
875
876 bool needChangeFwkForLeaveWindow = false;
877 if (DragDropGlobalController::GetInstance().GetAsyncDragCallback()) {
878 auto rootNode = dragDropManager->GetRootNode();
879 CHECK_NULL_VOID(rootNode);
880 auto geometryNode = rootNode->GetGeometryNode();
881 CHECK_NULL_VOID(geometryNode);
882 RectF rectF = geometryNode->GetFrameRect();
883 auto point = dragDropManager->GetDragMoveLastPointByCurrentPointer(info.GetPointerId());
884 if (!rectF.IsInRegion(PointF(static_cast<float>(point.GetX()), static_cast<float>(point.GetY())))) {
885 needChangeFwkForLeaveWindow = true;
886 }
887 }
888 auto eventHub = eventHub_.Upgrade();
889 CHECK_NULL_VOID(eventHub);
890 if (dragDropProxy_) {
891 dragDropProxy_ = nullptr;
892 }
893 CHECK_NULL_VOID(dragEvent);
894 auto eventRet = dragEvent->GetResult();
895 if (eventRet == DragRet::DRAG_FAIL || eventRet == DragRet::DRAG_CANCEL) {
896 TAG_LOGI(AceLogTag::ACE_DRAG, "Drag result is %{public}d, stop dragging.", eventRet);
897 FireCustomerOnDragEnd(pipeline, eventHub);
898 if (info.GetInputEventType() == InputEventType::MOUSE_BUTTON) {
899 SetMouseDragMonitorState(false);
900 }
901 DragDropBehaviorReporter::GetInstance().UpdateDragStartResult(DragStartResult::APP_REFUSE_DRAG);
902 return;
903 }
904 std::string udKey;
905 int32_t ret = -1;
906 DragSummaryInfo dragSummaryInfo;
907 DragDropFuncWrapper::ProcessDragDropData(dragEvent, udKey, dragSummaryInfo, ret);
908 int32_t recordsSize = GetBadgeNumber(dragEvent);
909 RefPtr<PixelMap> pixelMap = dragDropInfo.pixelMap;
910 if (pixelMap) {
911 SetPixelMap(pixelMap);
912 } else if (pixelMap == nullptr) {
913 FireCustomerOnDragEnd(pipeline, eventHub);
914 TAG_LOGW(AceLogTag::ACE_DRAG, "Thumbnail pixelMap is empty.");
915 if (info.GetInputEventType() == InputEventType::MOUSE_BUTTON) {
916 SetMouseDragMonitorState(false);
917 }
918 return;
919 }
920 auto dragPreviewOptions = frameNode->GetDragPreviewOption();
921 if (dragPreviewOptions.isDefaultDragItemGrayEffectEnabled) {
922 (info.GetSourceDevice() == SourceType::MOUSE) ? HandleDragThroughMouse(frameNode)
923 : HandleDragThroughTouch(frameNode);
924 }
925 SetDragGatherPixelMaps(info);
926 bool isMenuShow = DragDropGlobalController::GetInstance().IsMenuShowing();
927 if (isMenuShow) {
928 dragDropManager->SetIsDragWithContextMenu(true);
929 TAG_LOGI(AceLogTag::ACE_DRAG, "Drag with contextMenu.");
930 } else {
931 dragDropManager->SetIsDragWithContextMenu(false);
932 }
933 float defaultPixelMapScale = GetDefaultPixelMapScale(frameNode, info, isMenuShow, pixelMap);
934 auto windowScale = dragDropManager->GetWindowScale();
935 float scale = windowScale * defaultPixelMapScale;
936 auto isNeedCreateTiled =
937 DragDropFuncWrapper::IsNeedCreateTiledPixelMap(frameNode, dragEventActuator_, info.GetSourceDevice());
938 PreparedInfoForDrag data = { isMenuShow, recordsSize, defaultPixelMapScale, isNeedCreateTiled, OffsetF(), OffsetF(),
939 pixelMap, nullptr, dragPreviewOptions.sizeChangeEffect };
940 dragDropManager->ResetContextMenuDragPosition();
941 RefPtr<Subwindow> subWindow = nullptr;
942 data.dragPreviewRect = RectF(0, 0, pixelMap->GetWidth(), pixelMap->GetHeight());
943 data.deviceType = info.GetSourceDevice();
944 if (!needChangeFwkForLeaveWindow && IsNeedSwitchToSubWindow(data)) {
945 GestureEventHub::PrepareDragStartInfo(pipeline, data, frameNode);
946 auto imageNode = overlayManager->GetPixelMapContentNode();
947 DragAnimationHelper::CreatePreviewNode(frameNode, imageNode, defaultPixelMapScale, data);
948 CHECK_NULL_VOID(imageNode);
949 data.imageNode = imageNode;
950 data.dragPreviewOffsetToScreen = GetDragPreviewInitPositionToScreen(context, data);
951 float previewScale =
952 info.GetInputEventType() == InputEventType::MOUSE_BUTTON ? 1.0f : DEFALUT_DRAG_PPIXELMAP_SCALE;
953 if (IsPixelMapNeedScale()) {
954 previewScale = DragDropFuncWrapper::GetPixelMapScale(frameNode);
955 scale = previewScale * windowScale;
956 }
957 data.previewScale = previewScale;
958 // use menu preview scale replace default pixelMap scale.
959 if (isMenuShow) {
960 ProcessMenuPreviewScale(imageNode, scale, previewScale, windowScale, defaultPixelMapScale);
961 }
962 {
963 ACE_SCOPED_TRACE("drag: sub window show");
964 auto mainPipeline = PipelineContext::GetMainPipelineContext();
965 subWindow = SubwindowManager::GetInstance()->ShowPreviewNG((pipeline != mainPipeline));
966 }
967 }
968 if (!overlayManager->GetIsOnAnimation()) {
969 if (dragEventActuator_ != nullptr) {
970 dragEventActuator_->SetIsNotInPreviewState(true);
971 }
972 }
973 RefPtr<PixelMap> pixelMapDuplicated = GetPreScaledPixelMapIfExist(scale, pixelMap);
974 CHECK_NULL_VOID(dragEventActuator_);
975 dragEventActuator_->ResetPreScaledPixelMapForDragThroughTouch();
976 dragPreviewPixelMap_ = nullptr;
977 CHECK_NULL_VOID(pixelMapDuplicated);
978 auto width = pixelMapDuplicated->GetWidth();
979 auto height = pixelMapDuplicated->GetHeight();
980 auto extraInfoLimited = dragDropInfo.extraInfo.size() > EXTRA_INFO_MAX_LENGTH
981 ? dragDropInfo.extraInfo.substr(0, EXTRA_INFO_MAX_LENGTH)
982 : dragDropInfo.extraInfo;
983 auto innerRect = ParseInnerRect(extraInfoLimited, SizeF(width, height));
984 auto pixelMapOffset = GetPixelMapOffset(info, SizeF(width, height), data, scale, innerRect);
985 windowScale = NearZero(windowScale) ? 1.0f : windowScale;
986 dragDropManager->SetPixelMapOffset(pixelMapOffset / windowScale);
987 DragDropFuncWrapper::ResetNode(frameNode);
988 auto arkExtraInfoJson = JsonUtil::Create(true);
989 auto dragNodeGrayscale = pipeline->GetDragNodeGrayscale();
990 auto dipScale = pipeline->GetDipScale();
991 arkExtraInfoJson->Put("scale", scale);
992 arkExtraInfoJson->Put("dip_scale", dipScale);
993 arkExtraInfoJson->Put("drag_node_gray_scale", dragNodeGrayscale);
994 arkExtraInfoJson->Put("event_id", info.GetPointerEventId());
995 UpdateExtraInfo(frameNode, arkExtraInfoJson, scale, data);
996 auto container = Container::Current();
997 CHECK_NULL_VOID(container);
998 DragDropBehaviorReporterTrigger trigger(DragReporterPharse::DRAG_START, container->GetInstanceId());
999 auto windowId = container->GetWindowId();
1000 ShadowInfoCore shadowInfo { pixelMapDuplicated, pixelMapOffset.GetX(), pixelMapOffset.GetY() };
1001 auto dragMoveLastPoint = dragDropManager->GetDragMoveLastPointByCurrentPointer(info.GetPointerId());
1002 auto screenX = DragDropGlobalController::GetInstance().GetAsyncDragCallback() ?
1003 dragMoveLastPoint.GetScreenX() : info.GetScreenLocation().GetX();
1004 auto screenY = DragDropGlobalController::GetInstance().GetAsyncDragCallback() ?
1005 dragMoveLastPoint.GetScreenY() : info.GetScreenLocation().GetY();
1006
1007 const int32_t pointerId = info.GetPassThrough() ? info.GetPointerId() % PASS_THROUGH_EVENT_ID : info.GetPointerId();
1008 DragDataCore dragData { { shadowInfo }, {}, udKey, extraInfoLimited, arkExtraInfoJson->ToString(),
1009 static_cast<int32_t>(info.GetSourceDevice()), recordsSize, pointerId, screenX, screenY,
1010 info.GetTargetDisplayId(), windowId, true, false, dragSummaryInfo.summary, false,
1011 dragSummaryInfo.detailedSummary, dragSummaryInfo.summaryFormat, dragSummaryInfo.version,
1012 dragSummaryInfo.totalSize };
1013 if (AceApplicationInfo::GetInstance().IsMouseTransformEnable() && (info.GetSourceTool() == SourceTool::MOUSE) &&
1014 (info.GetSourceDevice() == SourceType::TOUCH)) {
1015 dragData.sourceType = static_cast<int32_t>(SourceType::MOUSE);
1016 }
1017 std::string summarys = DragDropFuncWrapper::GetSummaryString(dragSummaryInfo.summary);
1018 std::string detailedSummarys = DragDropFuncWrapper::GetSummaryString(dragSummaryInfo.detailedSummary);
1019 DragDropBehaviorReporter::GetInstance().UpdateSummaryType(summarys);
1020 TAG_LOGI(AceLogTag::ACE_DRAG,
1021 "Start drag, frameNode is %{public}s, pixelMap width %{public}d height %{public}d, "
1022 "scale is %{public}f, udkey %{public}s, recordsSize %{public}d, extraInfo length %{public}d, "
1023 "pointerId %{public}d, displayId %{public}d, windowId %{public}d, summary %{public}s, "
1024 "eventId %{public}d, detailedSummary %{public}s.",
1025 frameNode->GetTag().c_str(), width, height, scale, DragDropFuncWrapper::GetAnonyString(udKey).c_str(),
1026 recordsSize, static_cast<int32_t>(extraInfoLimited.length()), pointerId,
1027 info.GetTargetDisplayId(), windowId, summarys.c_str(), info.GetPointerEventId(), detailedSummarys.c_str());
1028 dragDropManager->GetGatherPixelMap(dragData, scale, width, height);
1029 {
1030 ACE_SCOPED_TRACE("drag: call msdp start drag");
1031 ret = InteractionInterface::GetInstance()->StartDrag(dragData, GetDragCallback(pipeline, eventHub));
1032 }
1033 if (ret != 0) {
1034 DragDropBehaviorReporter::GetInstance().UpdateDragStartResult(DragStartResult::DRAGFWK_START_FAIL);
1035 if (subWindow) {
1036 SubwindowManager::GetInstance()->HidePreviewNG();
1037 overlayManager->RemovePixelMap();
1038 }
1039 FireCustomerOnDragEnd(pipeline, eventHub);
1040 TAG_LOGW(AceLogTag::ACE_DRAG, "Start drag failed, return value is %{public}d", ret);
1041 return;
1042 }
1043 StartVibratorByDrag(frameNode);
1044 dragEventActuator_->NotifyDragStart();
1045 DragDropBehaviorReporter::GetInstance().UpdateDragStartResult(DragStartResult::DRAG_START_SUCCESS);
1046 bool isSwitchedToSubWindow = false;
1047 dragDropManager->SetIsMouseDrag(info.GetInputEventType() == InputEventType::MOUSE_BUTTON);
1048 if (!needChangeFwkForLeaveWindow && subWindow && TryDoDragStartAnimation(context, subWindow, info, data)) {
1049 dragDropManager->SetIsReDragStart(pipeline != dragNodePipeline);
1050 isSwitchedToSubWindow = true;
1051 } else {
1052 dragDropManager->SetIsReDragStart(false);
1053 HideMenu();
1054 DragDropGlobalController::GetInstance().ResetDragDropInitiatingStatus();
1055 }
1056 if (info.GetInputEventType() == InputEventType::MOUSE_BUTTON && isSwitchedToSubWindow) {
1057 ret = RegisterCoordinationListener(pipeline);
1058 if (ret != 0) {
1059 TAG_LOGW(AceLogTag::ACE_DRAG, "Register coordination listener failed, error is %{public}d", ret);
1060 }
1061 }
1062 dragDropManager->SetPreviewRect(Rect(pixelMapOffset.GetX(), pixelMapOffset.GetY(), width, height));
1063 dragDropManager->ResetRecordSize(static_cast<uint32_t>(recordsSize));
1064 auto eventManager = pipeline->GetEventManager();
1065 CHECK_NULL_VOID(eventManager);
1066 eventManager->DoMouseActionRelease();
1067 eventManager->SetIsDragging(true);
1068 if (info.GetInputEventType() != InputEventType::MOUSE_BUTTON && needChangeFwkForLeaveWindow) {
1069 overlayManager->RemovePixelMap();
1070 overlayManager->RemovePreviewBadgeNode();
1071 overlayManager->RemoveGatherNode();
1072 dragEventActuator_->NotifyTransDragWindowToFwk();
1073 pipeline->AddAfterRenderTask([]() {
1074 ACE_SCOPED_TRACE("drag: set drag window visible, touch");
1075 InteractionInterface::GetInstance()->SetDragWindowVisible(true);
1076 });
1077 } else if (info.GetInputEventType() != InputEventType::MOUSE_BUTTON && dragEventActuator_ != nullptr &&
1078 dragEventActuator_->GetIsNotInPreviewState()) {
1079 if (!isSwitchedToSubWindow) {
1080 overlayManager->RemovePixelMap();
1081 overlayManager->RemovePreviewBadgeNode();
1082 overlayManager->RemoveGatherNode();
1083 dragEventActuator_->NotifyTransDragWindowToFwk();
1084 pipeline->AddAfterRenderTask([]() {
1085 ACE_SCOPED_TRACE("drag: set drag window visible, touch");
1086 InteractionInterface::GetInstance()->SetDragWindowVisible(true);
1087 });
1088 }
1089 } else if (info.GetInputEventType() == InputEventType::MOUSE_BUTTON) {
1090 if (!isSwitchedToSubWindow) {
1091 dragEventActuator_->NotifyTransDragWindowToFwk();
1092 pipeline->AddDragWindowVisibleTask([]() {
1093 ACE_SCOPED_TRACE("drag: set drag window visible, mouse");
1094 InteractionInterface::GetInstance()->SetDragWindowVisible(true);
1095 });
1096 pipeline->RequestFrame();
1097 }
1098 dragDropManager->SetIsDragWindowShow(true);
1099 }
1100 dragDropManager->FireOnEditableTextComponent(frameNode, DragEventType::ENTER);
1101 dragDropProxy_ = dragDropManager->CreateFrameworkDragDropProxy();
1102 CHECK_NULL_VOID(dragDropProxy_);
1103 dragDropProxy_->OnDragStart(info, extraInfoLimited, GetFrameNode());
1104 if (!dragDropManager->IsDraggingPressed(info.GetPointerId())) {
1105 dragDropManager->SetIsDisableDefaultDropAnimation(true);
1106 dragDropManager->OnDragEnd(
1107 DragPointerEvent(info.GetGlobalPoint().GetX(), info.GetGlobalPoint().GetY()), extraInfoLimited);
1108 }
1109 }
1110
StartVibratorByDrag(const RefPtr<FrameNode> & frameNode)1111 void GestureEventHub::StartVibratorByDrag(const RefPtr<FrameNode>& frameNode)
1112 {
1113 bool enableHapticFeedback = frameNode->GetDragPreviewOption().enableHapticFeedback;
1114 auto parent = frameNode->GetAncestorNodeOfFrame(false);
1115 if (parent && parent->GetTag() == V2::RICH_EDITOR_ETS_TAG) {
1116 enableHapticFeedback = parent->GetDragPreviewOption().enableHapticFeedback;
1117 }
1118 if (!enableHapticFeedback || !DragDropGlobalController::GetInstance().IsDragFilterShowing()) {
1119 return;
1120 }
1121 TAG_LOGI(AceLogTag::ACE_DRAG, "Enable haptic feedback, start vibrator by drag.");
1122 VibratorUtils::StartViratorDirectly("haptic.drag");
1123 DragDropGlobalController::GetInstance().UpdateDragFilterShowingStatus(false);
1124 }
1125
UpdateExtraInfo(const RefPtr<FrameNode> & frameNode,std::unique_ptr<JsonValue> & arkExtraInfoJson,float scale,const PreparedInfoForDrag & dragInfoData)1126 void GestureEventHub::UpdateExtraInfo(const RefPtr<FrameNode>& frameNode, std::unique_ptr<JsonValue>& arkExtraInfoJson,
1127 float scale, const PreparedInfoForDrag& dragInfoData)
1128 {
1129 double opacity = frameNode->GetDragPreviewOption().options.opacity;
1130 auto optionInfo = frameNode->GetDragPreviewOption().options;
1131 arkExtraInfoJson->Put("dip_opacity", opacity);
1132 TAG_LOGD(AceLogTag::ACE_DRAG, "The info of opacity update to the framework is %{public}s",
1133 arkExtraInfoJson->ToString().c_str());
1134
1135 if (optionInfo.blurbgEffect.backGroundEffect.radius.IsValid()) {
1136 optionInfo.blurbgEffect.ToJsonValue(arkExtraInfoJson);
1137 }
1138 DragEventActuator::PrepareShadowParametersForDragData(frameNode, arkExtraInfoJson, scale);
1139 if (dragInfoData.isNeedCreateTiled) {
1140 return;
1141 }
1142 DragEventActuator::PrepareRadiusParametersForDragData(frameNode, arkExtraInfoJson);
1143 }
1144
RegisterCoordinationListener(const RefPtr<PipelineBase> & context)1145 int32_t GestureEventHub::RegisterCoordinationListener(const RefPtr<PipelineBase>& context)
1146 {
1147 auto pipeline = AceType::DynamicCast<PipelineContext>(context);
1148 CHECK_NULL_RETURN(pipeline, -1);
1149 auto callback = [id = Container::CurrentId(), weak = WeakClaim(RawPtr(pipeline))]() {
1150 ContainerScope scope(id);
1151 auto context = weak.Upgrade();
1152 CHECK_NULL_VOID(context);
1153 auto dragDropManager = context->GetDragDropManager();
1154 CHECK_NULL_VOID(dragDropManager);
1155 auto taskScheduler = context->GetTaskExecutor();
1156 CHECK_NULL_VOID(taskScheduler);
1157 taskScheduler->PostTask([dragDropManager]() { dragDropManager->HideDragPreviewOverlay(); },
1158 TaskExecutor::TaskType::UI, "ArkUIGestureHideDragPreviewOverlay");
1159 };
1160 return InteractionInterface::GetInstance()->RegisterCoordinationListener(callback);
1161 }
1162
HandleOnDragUpdate(const GestureEvent & info)1163 void GestureEventHub::HandleOnDragUpdate(const GestureEvent& info)
1164 {
1165 gestureInfoForWeb_ = std::make_shared<GestureEvent>(info);
1166 }
1167
HandleDragEndAction(const DragframeNodeInfo & info)1168 void GestureEventHub::HandleDragEndAction(const DragframeNodeInfo& info)
1169 {
1170 auto weakFrameNode = info.frameNode;
1171 auto frameNode = weakFrameNode.Upgrade();
1172 CHECK_NULL_VOID(frameNode);
1173 auto dragPreviewOptions = frameNode->GetDragPreviewOption();
1174 if (!dragPreviewOptions.isDefaultDragItemGrayEffectEnabled) {
1175 return;
1176 }
1177 auto pipeline = frameNode->GetContextRefPtr();
1178 CHECK_NULL_VOID(pipeline);
1179 auto dragDropManager = pipeline->GetDragDropManager();
1180 CHECK_NULL_VOID(dragDropManager);
1181 auto state = dragDropManager->GetGrayedState();
1182 if (!state) {
1183 return;
1184 }
1185 if (!info.gatherFrameNode.empty()) {
1186 auto gatherFrameNode = info.gatherFrameNode;
1187 for (const auto& itemFrameNode : gatherFrameNode) {
1188 DragAnimationHelper::SetPreOpacity(itemFrameNode);
1189 }
1190 } else {
1191 DragAnimationHelper::SetPreOpacity(frameNode);
1192 }
1193 dragDropManager->SetGrayedState(false);
1194 }
1195
HandleOnDragEnd(const GestureEvent & info)1196 void GestureEventHub::HandleOnDragEnd(const GestureEvent& info)
1197 {
1198 auto pipeline = NG::PipelineContext::GetCurrentContextSafelyWithCheck();
1199 const static int32_t PLATFORM_VERSION_TEN = 10;
1200 if (pipeline && (pipeline->GetMinPlatformVersion() < PLATFORM_VERSION_TEN)) {
1201 auto eventHub = eventHub_.Upgrade();
1202 CHECK_NULL_VOID(eventHub);
1203
1204 auto frameNode = GetFrameNode();
1205 CHECK_NULL_VOID(frameNode);
1206
1207 // Only the onDrop callback of dragged frame node is triggered.
1208 // The onDrop callback of target frame node is triggered in PipelineContext::OnDragEvent.
1209 if (eventHub->HasOnDrop() || eventHub->HasCustomerOnDrop()) {
1210 RefPtr<OHOS::Ace::DragEvent> event = AceType::MakeRefPtr<OHOS::Ace::DragEvent>();
1211 if (frameNode->GetTag() == V2::WEB_ETS_TAG) {
1212 event->SetX(pipeline->ConvertPxToVp(Dimension(info.GetGlobalPoint().GetX(), DimensionUnit::PX)));
1213 event->SetY(pipeline->ConvertPxToVp(Dimension(info.GetGlobalPoint().GetY(), DimensionUnit::PX)));
1214 } else {
1215 event->SetX(info.GetGlobalPoint().GetX());
1216 event->SetY(info.GetGlobalPoint().GetY());
1217 }
1218 event->SetScreenX(info.GetScreenLocation().GetX());
1219 event->SetScreenY(info.GetScreenLocation().GetY());
1220 event->SetGlobalDisplayX(info.GetGlobalDisplayLocation().GetX());
1221 event->SetGlobalDisplayY(info.GetGlobalDisplayLocation().GetY());
1222 event->SetPressedKeyCodes(info.GetPressedKeyCodes());
1223 eventHub->FireCustomerOnDragFunc(DragFuncType::DRAG_DROP, event);
1224 eventHub->HandleInternalOnDrop(event, "");
1225 }
1226 }
1227 HandleDragEndAction(dragframeNodeInfo_);
1228 CHECK_NULL_VOID(dragDropProxy_);
1229 dragDropProxy_->DestroyDragWindow();
1230 dragDropProxy_ = nullptr;
1231 }
1232
HandleOnDragCancel()1233 void GestureEventHub::HandleOnDragCancel()
1234 {
1235 CHECK_NULL_VOID(dragDropProxy_);
1236 dragDropProxy_->DestroyDragWindow();
1237 dragDropProxy_ = nullptr;
1238 }
1239
GetDragCallback(const RefPtr<PipelineBase> & context,const WeakPtr<EventHub> & hub)1240 OnDragCallbackCore GestureEventHub::GetDragCallback(const RefPtr<PipelineBase>& context, const WeakPtr<EventHub>& hub)
1241 {
1242 auto ret = [](const DragNotifyMsgCore& notifyMessage) {};
1243 auto eventHub = hub.Upgrade();
1244 CHECK_NULL_RETURN(eventHub, ret);
1245 auto pipeline = AceType::DynamicCast<PipelineContext>(context);
1246 CHECK_NULL_RETURN(pipeline, ret);
1247 auto taskScheduler = pipeline->GetTaskExecutor();
1248 CHECK_NULL_RETURN(taskScheduler, ret);
1249 auto dragDropManager = pipeline->GetDragDropManager();
1250 CHECK_NULL_RETURN(dragDropManager, ret);
1251 auto eventManager = pipeline->GetEventManager();
1252 RefPtr<OHOS::Ace::DragEvent> dragEvent = AceType::MakeRefPtr<OHOS::Ace::DragEvent>();
1253 auto callback = [id = Container::CurrentId(), eventHub, dragEvent, taskScheduler, dragDropManager, eventManager,
1254 dragframeNodeInfo = dragframeNodeInfo_,
1255 gestureEventHubPtr = AceType::Claim(this)](const DragNotifyMsgCore& notifyMessage) {
1256 ContainerScope scope(id);
1257 taskScheduler->PostTask(
1258 [eventHub, dragEvent, dragDropManager, eventManager, notifyMessage, id, dragframeNodeInfo,
1259 gestureEventHubPtr]() {
1260 auto container = Container::GetContainer(id);
1261 if (!container) {
1262 TAG_LOGE(AceLogTag::ACE_DRAG, "handle drag end callback, can not get container.");
1263 return;
1264 }
1265 DragDropGlobalController::GetInstance().ResetDragDropInitiatingStatus();
1266 TAG_LOGI(
1267 AceLogTag::ACE_DRAG, "handle drag end callback, windowId is %{public}d.", container->GetWindowId());
1268 dragDropManager->ResetDragEndOption(notifyMessage, dragEvent, id);
1269 auto ret = InteractionInterface::GetInstance()->UnRegisterCoordinationListener();
1270 if (ret != 0) {
1271 TAG_LOGW(AceLogTag::ACE_DRAG, "Unregister coordination listener failed, error is %{public}d", ret);
1272 }
1273 if (eventManager) {
1274 eventManager->DoMouseActionRelease();
1275 }
1276 if (notifyMessage.isInnerAndOuterTriggerBothNeeded) {
1277 eventHub->FireCustomerOnDragFunc(DragFuncType::DRAG_END, dragEvent);
1278 }
1279 if (eventHub->HasOnDragEnd()) {
1280 (eventHub->GetOnDragEnd())(dragEvent);
1281 }
1282 gestureEventHubPtr->HandleDragEndAction(dragframeNodeInfo);
1283 auto dragEventActuator = gestureEventHubPtr->GetDragEventActuator();
1284 CHECK_NULL_VOID(dragEventActuator);
1285 dragEventActuator->NotifyDragEnd();
1286 },
1287 TaskExecutor::TaskType::UI, "ArkUIGestureDragEnd");
1288 };
1289 return callback;
1290 }
1291
GetDragDropInfo(const GestureEvent & info,const RefPtr<FrameNode> frameNode,DragDropInfo & dragPreviewInfo,const RefPtr<OHOS::Ace::DragEvent> & dragEvent)1292 DragDropInfo GestureEventHub::GetDragDropInfo(const GestureEvent& info, const RefPtr<FrameNode> frameNode,
1293 DragDropInfo& dragPreviewInfo, const RefPtr<OHOS::Ace::DragEvent>& dragEvent)
1294 {
1295 ACE_SCOPED_TRACE("drag: execute user onDragStart");
1296 DragDropInfo dragDropInfo;
1297 CHECK_NULL_RETURN(dragEventActuator_, dragDropInfo);
1298 dragEventActuator_->SetIsDefaultOnDragStartExecuted(false);
1299 auto eventHub = eventHub_.Upgrade();
1300 CHECK_NULL_RETURN(eventHub, dragDropInfo);
1301 auto extraParams = eventHub->GetDragExtraParams(std::string(), info.GetGlobalPoint(), DragEventType::START);
1302 auto onDragStart = eventHub->GetOnDragStart();
1303 if (!onDragStart && eventHub->HasDefaultOnDragStart()) {
1304 onDragStart = eventHub->GetDefaultOnDragStart();
1305 dragEventActuator_->SetIsDefaultOnDragStartExecuted(true);
1306 }
1307 dragEvent->SetPressedKeyCodes(info.GetPressedKeyCodes());
1308 if (GetTextDraggable() && info.GetInputEventType() == InputEventType::MOUSE_BUTTON) {
1309 GenerateMousePixelMap(info);
1310 }
1311 dragDropInfo = onDragStart(dragEvent, extraParams);
1312
1313 auto frameTag = frameNode->GetTag();
1314 if (GetTextDraggable() && IsTextCategoryComponent(frameTag)) {
1315 TAG_LOGD(AceLogTag::ACE_DRAG,
1316 "Get drag drop info, pixelmap and customNode are set to null "
1317 "when frameTag is %{public}s",
1318 frameTag.c_str());
1319 dragDropInfo.pixelMap = nullptr;
1320 dragDropInfo.customNode = nullptr;
1321 } else {
1322 auto dragPreview = frameNode->GetDragPreview();
1323 if (dragPreview.onlyForLifting) {
1324 return dragDropInfo;
1325 }
1326 if (!dragPreview.customNode && dragPreview.delayCreating && dragPreview.buildFunc) {
1327 dragPreview.customNode = dragPreview.buildFunc();
1328 }
1329 frameNode->SetDragPreview(dragPreview);
1330 dragPreviewInfo = dragPreview;
1331 }
1332 return dragDropInfo;
1333 }
1334
GetUnifiedData(const std::string & frameTag,DragDropInfo & dragDropInfo,const RefPtr<OHOS::Ace::DragEvent> & dragEvent)1335 RefPtr<UnifiedData> GestureEventHub::GetUnifiedData(
1336 const std::string& frameTag, DragDropInfo& dragDropInfo, const RefPtr<OHOS::Ace::DragEvent>& dragEvent)
1337 {
1338 auto eventHub = eventHub_.Upgrade();
1339 CHECK_NULL_RETURN(eventHub, nullptr);
1340 auto unifiedData = dragEvent->GetData();
1341 bool hasData = static_cast<bool>(unifiedData);
1342 if (!unifiedData && eventHub->HasDefaultOnDragStart()) {
1343 auto defaultDropInfo = eventHub->GetDefaultOnDragStart()(dragEvent, "");
1344 if (dragDropInfo.extraInfo.empty()) {
1345 dragDropInfo.extraInfo = defaultDropInfo.extraInfo;
1346 }
1347 CHECK_NULL_RETURN(dragEventActuator_, nullptr);
1348 dragEventActuator_->SetIsDefaultOnDragStartExecuted(true);
1349 unifiedData = dragEvent->GetData();
1350 }
1351 auto defaultOnDragStart = eventHub->GetDefaultOnDragStart();
1352 CHECK_NULL_RETURN(defaultOnDragStart, unifiedData);
1353 if (hasData && IsTextCategoryComponent(frameTag) && !dragEventActuator_->IsDefaultOnDragStartExecuted()) {
1354 defaultOnDragStart(dragEvent, "");
1355 }
1356 return unifiedData;
1357 }
1358
SetDragForbiddenForcely(bool isDragForbiddenForWholeSubTree)1359 void GestureEventHub::SetDragForbiddenForcely(bool isDragForbiddenForWholeSubTree)
1360 {
1361 isDragForbiddenForWholeSubTree_ = isDragForbiddenForWholeSubTree;
1362 }
1363
IsDragForbidden() const1364 bool GestureEventHub::IsDragForbidden() const
1365 {
1366 return isDragForbiddenForWholeSubTree_;
1367 }
1368
SetDragGatherPixelMaps(const GestureEvent & info)1369 void GestureEventHub::SetDragGatherPixelMaps(const GestureEvent& info)
1370 {
1371 CHECK_NULL_VOID(dragEventActuator_);
1372 if (!dragEventActuator_->IsNeedGather()) {
1373 return;
1374 }
1375 if (info.GetInputEventType() == InputEventType::MOUSE_BUTTON) {
1376 SetMouseDragGatherPixelMaps();
1377 } else {
1378 SetNotMouseDragGatherPixelMaps();
1379 }
1380 }
1381
SetMouseDragGatherPixelMaps()1382 void GestureEventHub::SetMouseDragGatherPixelMaps()
1383 {
1384 auto frameNode = GetFrameNode();
1385 CHECK_NULL_VOID(frameNode);
1386 if (frameNode->GetDragPreviewOption().isMultiTiled && !dragEventActuator_->GetRestartDrag()) {
1387 return;
1388 }
1389 auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
1390 CHECK_NULL_VOID(pipeline);
1391 auto dragDropManager = pipeline->GetDragDropManager();
1392 CHECK_NULL_VOID(dragDropManager);
1393 dragDropManager->ClearGatherPixelMap();
1394 CHECK_NULL_VOID(dragEventActuator_);
1395 auto fatherNode = DragDropFuncWrapper::FindItemParentNode(frameNode);
1396 CHECK_NULL_VOID(fatherNode);
1397 auto scrollPattern = fatherNode->GetPattern<ScrollablePattern>();
1398 CHECK_NULL_VOID(scrollPattern);
1399 auto children = scrollPattern->GetVisibleSelectedItems();
1400 int cnt = 0;
1401 for (const auto& itemFrameNode : children) {
1402 if (itemFrameNode == frameNode) {
1403 continue;
1404 }
1405 CHECK_NULL_VOID(itemFrameNode);
1406 DragEventActuator::GetFrameNodePreviewPixelMap(itemFrameNode);
1407 auto gestureHub = itemFrameNode->GetOrCreateGestureEventHub();
1408 CHECK_NULL_VOID(gestureHub);
1409 auto itemPreviewPixelMap = gestureHub->GetDragPreviewPixelMap();
1410 if (!itemPreviewPixelMap) {
1411 continue;
1412 }
1413 dragDropManager->PushGatherPixelMap(itemPreviewPixelMap);
1414 cnt++;
1415 if (cnt > 1) {
1416 break;
1417 }
1418 }
1419 }
1420
SetNotMouseDragGatherPixelMaps()1421 void GestureEventHub::SetNotMouseDragGatherPixelMaps()
1422 {
1423 auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
1424 CHECK_NULL_VOID(pipeline);
1425 auto dragDropManager = pipeline->GetDragDropManager();
1426 CHECK_NULL_VOID(dragDropManager);
1427 dragDropManager->ClearGatherPixelMap();
1428 auto mainPipeline = PipelineContext::GetMainPipelineContext();
1429 CHECK_NULL_VOID(mainPipeline);
1430 auto overlayManager = mainPipeline->GetOverlayManager();
1431 CHECK_NULL_VOID(overlayManager);
1432 auto gatherNodeChildrenInfo = overlayManager->GetGatherNodeChildrenInfo();
1433 int cnt = 0;
1434 for (auto iter = gatherNodeChildrenInfo.rbegin(); iter != gatherNodeChildrenInfo.rend(); ++iter) {
1435 auto imageNode = (*iter).imageNode.Upgrade();
1436 CHECK_NULL_VOID(imageNode);
1437 auto imageLayoutProperty = imageNode->GetLayoutProperty<ImageLayoutProperty>();
1438 CHECK_NULL_VOID(imageLayoutProperty);
1439 auto imageSourceInfo = imageLayoutProperty->GetImageSourceInfo().value_or(ImageSourceInfo());
1440 auto itemPreviewPixelMap = imageSourceInfo.GetPixmap();
1441 if (!itemPreviewPixelMap) {
1442 continue;
1443 }
1444 dragDropManager->PushGatherPixelMap(itemPreviewPixelMap);
1445 cnt++;
1446 if (cnt > 1) {
1447 break;
1448 }
1449 }
1450 }
1451
GetSelectItemSize()1452 int32_t GestureEventHub::GetSelectItemSize()
1453 {
1454 CHECK_NULL_RETURN(dragEventActuator_, 0);
1455 if (!dragEventActuator_->IsNeedGather()) {
1456 return 0;
1457 }
1458 auto fatherNode = DragDropFuncWrapper::FindItemParentNode(GetFrameNode());
1459 CHECK_NULL_RETURN(fatherNode, 0);
1460 auto scrollPattern = fatherNode->GetPattern<ScrollablePattern>();
1461 CHECK_NULL_RETURN(scrollPattern, 0);
1462 auto children = scrollPattern->GetVisibleSelectedItems();
1463 return children.size();
1464 }
1465
FireCustomerOnDragEnd(const RefPtr<PipelineBase> & context,const WeakPtr<EventHub> & hub)1466 void GestureEventHub::FireCustomerOnDragEnd(const RefPtr<PipelineBase>& context, const WeakPtr<EventHub>& hub)
1467 {
1468 DragDropGlobalController::GetInstance().ResetDragDropInitiatingStatus();
1469 auto eventHub = hub.Upgrade();
1470 CHECK_NULL_VOID(eventHub);
1471 auto pipeline = AceType::DynamicCast<PipelineContext>(context);
1472 CHECK_NULL_VOID(pipeline);
1473 auto dragDropManager = pipeline->GetDragDropManager();
1474 CHECK_NULL_VOID(dragDropManager);
1475 dragDropManager->RemoveDeadlineTimer();
1476 auto dragEvent = AceType::MakeRefPtr<OHOS::Ace::DragEvent>();
1477 CHECK_NULL_VOID(dragEvent);
1478 dragEvent->SetResult(DragRet::DRAG_FAIL);
1479 dragEvent->SetDragBehavior(DragBehavior::UNKNOWN);
1480 dragDropManager->DoDragReset();
1481 dragDropManager->SetIsDragged(false);
1482 dragDropManager->ResetDragging();
1483 dragDropManager->SetDraggingPointer(-1);
1484 dragDropManager->SetDraggingPressedState(false);
1485 dragDropManager->ResetDragPreviewInfo();
1486 eventHub->FireCustomerOnDragFunc(DragFuncType::DRAG_END, dragEvent);
1487 if (eventHub->HasOnDragEnd()) {
1488 (eventHub->GetOnDragEnd())(dragEvent);
1489 }
1490 }
1491
1492 #if defined(PIXEL_MAP_SUPPORTED)
PrintBuilderNode(const RefPtr<UINode> & customNode)1493 void GestureEventHub::PrintBuilderNode(const RefPtr<UINode>& customNode)
1494 {
1495 CHECK_NULL_VOID(customNode);
1496 bool hasImageNode = false;
1497 std::list<RefPtr<FrameNode>> imageNodes;
1498 int32_t depth = 1;
1499 PrintIfImageNode(customNode, depth, hasImageNode, imageNodes);
1500 CheckImageDecode(imageNodes);
1501 imageNodes.clear();
1502 }
1503
PrintIfImageNode(const RefPtr<UINode> & builderNode,int32_t depth,bool & hasImageNode,std::list<RefPtr<FrameNode>> & imageNodes)1504 void GestureEventHub::PrintIfImageNode(
1505 const RefPtr<UINode>& builderNode, int32_t depth, bool& hasImageNode, std::list<RefPtr<FrameNode>>& imageNodes)
1506 {
1507 if (depth > MAX_BUILDER_DEPTH) {
1508 return;
1509 }
1510 if (builderNode->GetTag() == V2::IMAGE_ETS_TAG) {
1511 auto frameNode = AceType::DynamicCast<FrameNode>(builderNode);
1512 CHECK_NULL_VOID(frameNode);
1513 auto pattern = frameNode->GetPattern<ImagePattern>();
1514 CHECK_NULL_VOID(pattern);
1515 hasImageNode = true;
1516 imageNodes.push_back(frameNode);
1517 TAG_LOGI(AceLogTag::ACE_DRAG,
1518 "customNode has ImageNode, syncLoad: %{public}d, decode complete: %{public}d",
1519 pattern->GetSyncLoad(), pattern->GetCanvasImage() != nullptr);
1520 }
1521
1522 auto children = builderNode->GetChildren();
1523 for (const auto& child : children) {
1524 PrintIfImageNode(child, depth + 1, hasImageNode, imageNodes);
1525 }
1526 }
1527
CheckImageDecode(std::list<RefPtr<FrameNode>> & imageNodes)1528 void GestureEventHub::CheckImageDecode(std::list<RefPtr<FrameNode>>& imageNodes)
1529 {
1530 if (imageNodes.empty()) {
1531 return;
1532 }
1533
1534 for (const auto& imageNode : imageNodes) {
1535 auto pattern = imageNode->GetPattern<ImagePattern>();
1536 CHECK_NULL_VOID(pattern);
1537 if (!pattern->GetCanvasImage()) {
1538 TAG_LOGW(AceLogTag::ACE_DRAG, "ImageNode did not complete decoding");
1539 }
1540 }
1541 }
1542
StartDragForCustomBuilderSync(const GestureEvent & info,const RefPtr<PipelineBase> & pipeline,const RefPtr<FrameNode> frameNode,DragDropInfo dragDropInfo,const RefPtr<OHOS::Ace::DragEvent> & event)1543 bool GestureEventHub::StartDragForCustomBuilderSync(const GestureEvent& info, const RefPtr<PipelineBase>& pipeline,
1544 const RefPtr<FrameNode> frameNode, DragDropInfo dragDropInfo, const RefPtr<OHOS::Ace::DragEvent>& event)
1545 {
1546 SnapshotParam param;
1547 std::shared_ptr<Media::PixelMap> pixelMap = nullptr;
1548 {
1549 ACE_SCOPED_TRACE("drag: try get builder snapshot sync");
1550 pixelMap = ComponentSnapshot::CreateSync(dragDropInfo.customNode, param);
1551 }
1552
1553 if (pixelMap == nullptr) {
1554 // try failed, need fall back to use async way
1555 return false;
1556 }
1557
1558 // get snapshot successfully, go ahead
1559 dragDropInfo.pixelMap = PixelMap::CreatePixelMap(reinterpret_cast<void*>(&pixelMap));
1560 OnDragStart(info, pipeline, frameNode, dragDropInfo, event);
1561 return true;
1562 }
1563
StartDragForCustomBuilder(const GestureEvent & info,const RefPtr<PipelineBase> & pipeline,const RefPtr<FrameNode> frameNode,DragDropInfo dragDropInfo,const RefPtr<OHOS::Ace::DragEvent> & event)1564 void GestureEventHub::StartDragForCustomBuilder(const GestureEvent& info, const RefPtr<PipelineBase>& pipeline,
1565 const RefPtr<FrameNode> frameNode, DragDropInfo dragDropInfo, const RefPtr<OHOS::Ace::DragEvent>& event)
1566 {
1567 if (StartDragForCustomBuilderSync(info, pipeline, frameNode, dragDropInfo, event)) {
1568 return;
1569 }
1570
1571 TAG_LOGI(AceLogTag::ACE_DRAG, "Snapshot createSync failed, get thumbnail by async.");
1572 auto callback = [id = Container::CurrentId(), pipeline, info, gestureEventHubPtr = AceType::Claim(this), frameNode,
1573 dragDropInfo, event](std::shared_ptr<Media::PixelMap> pixelMap, int32_t arg, std::function<void()>
1574 finishCallback) mutable {
1575 ContainerScope scope(id);
1576 ACE_SCOPED_TRACE("drag: get snapshot async done, post task to UI for next handling");
1577 TAG_LOGI(AceLogTag::ACE_DRAG, "Get thumbnail callback executed.");
1578 if (pixelMap != nullptr) {
1579 dragDropInfo.pixelMap = PixelMap::CreatePixelMap(reinterpret_cast<void*>(&pixelMap));
1580 } else {
1581 DragDropBehaviorReporter::GetInstance().UpdateDragStartResult(DragStartResult::SNAPSHOT_FAIL);
1582 }
1583 auto taskScheduler = pipeline->GetTaskExecutor();
1584 CHECK_NULL_VOID(taskScheduler);
1585 taskScheduler->PostTask(
1586 [pipeline, info, gestureEventHubPtr, frameNode, dragDropInfo, event, finishCallback]() {
1587 TAG_LOGI(AceLogTag::ACE_DRAG, "Get thumbnail finished, start drag.");
1588 if (finishCallback) {
1589 finishCallback();
1590 }
1591 CHECK_NULL_VOID(gestureEventHubPtr);
1592 CHECK_NULL_VOID(frameNode);
1593 gestureEventHubPtr->OnDragStart(info, pipeline, frameNode, dragDropInfo, event);
1594 },
1595 TaskExecutor::TaskType::UI, "ArkUIGestureDragStart");
1596 };
1597 SnapshotParam param;
1598 param.delay = CREATE_PIXELMAP_TIME;
1599 param.checkImageStatus = true;
1600 param.options.waitUntilRenderFinished = true;
1601 ACE_SCOPED_TRACE("drag: try sync failed, to get snapshot async");
1602 NG::ComponentSnapshot::Create(dragDropInfo.customNode, std::move(callback), true, param);
1603 PrintBuilderNode(dragDropInfo.customNode);
1604 }
1605 #endif
1606
GetDragPreviewInitPositionToScreen(const RefPtr<PipelineBase> & context,PreparedInfoForDrag & data)1607 OffsetF GestureEventHub::GetDragPreviewInitPositionToScreen(
1608 const RefPtr<PipelineBase>& context, PreparedInfoForDrag& data)
1609 {
1610 auto frameNode = GetFrameNode();
1611 CHECK_NULL_RETURN(frameNode, OffsetF());
1612 OffsetF previewOffset;
1613 OffsetF pixelMapHalfSize = data.pixelMap ? OffsetF(data.pixelMap->GetWidth() / 2.0f,
1614 data.pixelMap->GetHeight() / 2.0f) : OffsetF();
1615 previewOffset = DragDropFuncWrapper::GetPaintRectCenterToScreen(frameNode) - pixelMapHalfSize;
1616 auto frameTag = frameNode->GetTag();
1617 if (IsPixelMapNeedScale() && GetTextDraggable() && IsTextCategoryComponent(frameTag)) {
1618 auto textDragPattern = frameNode->GetPattern<TextDragBase>();
1619 CHECK_NULL_RETURN(textDragPattern, previewOffset);
1620 auto dragNode = textDragPattern->MoveDragNode();
1621 if (dragNode) {
1622 previewOffset = DragDropFuncWrapper::GetPaintRectCenterToScreen(dragNode) - pixelMapHalfSize;
1623 return previewOffset;
1624 }
1625 }
1626
1627 if (IsPixelMapNeedScale() && frameTag == V2::WEB_ETS_TAG) {
1628 auto offset = DragDropFuncWrapper::GetCurrentWindowOffset(context);
1629 return frameNodeOffset_ + offset;
1630 }
1631
1632 if (data.isMenuShow) {
1633 OffsetF menuPreviewCenter = frameNodeOffset_ + OffsetF(frameNodeSize_.Width(), frameNodeSize_.Height()) / 2.0f;
1634 menuPreviewCenter += DragDropFuncWrapper::GetCurrentWindowOffset(context);
1635 if (data.sizeChangeEffect == DraggingSizeChangeEffect::DEFAULT && data.badgeNumber <= 1) {
1636 previewOffset = menuPreviewCenter - pixelMapHalfSize + data.dragMovePosition;
1637 } else if ((data.sizeChangeEffect == DraggingSizeChangeEffect::SIZE_TRANSITION ||
1638 data.sizeChangeEffect == DraggingSizeChangeEffect::SIZE_CONTENT_TRANSITION) ||
1639 data.badgeNumber > 1) {
1640 previewOffset = menuPreviewCenter - OffsetF(frameNodeSize_.Width(), frameNodeSize_.Height()) / 2.0f +
1641 data.dragMovePosition;
1642 }
1643 }
1644 return previewOffset;
1645 }
1646
UpdateMenuNode(const RefPtr<FrameNode> menuWrapperNode,PreparedInfoForDrag & data,const RefPtr<FrameNode> frameNode)1647 void GestureEventHub::UpdateMenuNode(
1648 const RefPtr<FrameNode> menuWrapperNode, PreparedInfoForDrag& data, const RefPtr<FrameNode> frameNode)
1649 {
1650 CHECK_NULL_VOID(frameNode);
1651 CHECK_NULL_VOID(menuWrapperNode);
1652 auto menuWrapperPattern = menuWrapperNode->GetPattern<MenuWrapperPattern>();
1653 CHECK_NULL_VOID(menuWrapperPattern);
1654 auto animationInfo = menuWrapperPattern->GetPreviewMenuAnimationInfo();
1655 auto rate = animationInfo.clipRate;
1656 auto menuNode = menuWrapperPattern->GetMenu();
1657 CHECK_NULL_VOID(menuNode);
1658 auto menuPattern = menuNode->GetPattern<MenuPattern>();
1659 CHECK_NULL_VOID(menuPattern);
1660 data.isMenuNotShow =
1661 menuWrapperPattern->GetMenuStatus() == MenuStatus::SHOW && rate == -1.0f && menuPattern->GetIsShowHoverImage();
1662 if (frameNode->GetDragPreviewOption().sizeChangeEffect == DraggingSizeChangeEffect::DEFAULT ||
1663 menuWrapperPattern->HasTransitionEffect() || menuWrapperPattern->IsHide()) {
1664 return;
1665 }
1666 auto scrollNode = AceType::DynamicCast<FrameNode>(menuNode->GetChildByIndex(0));
1667 CHECK_NULL_VOID(scrollNode);
1668 data.scrollNode = scrollNode;
1669 auto menuGeometryNode = scrollNode->GetGeometryNode();
1670 CHECK_NULL_VOID(menuGeometryNode);
1671 auto menuNodeSize = menuGeometryNode->GetFrameRect();
1672 RefPtr<FrameNode> imageNode = menuWrapperPattern->GetPreview();
1673 RectF imageNodeSize;
1674 if (imageNode) {
1675 imageNodeSize = DragDropFuncWrapper::GetPaintRectToScreen(imageNode);
1676 data.frameNodeRect = imageNodeSize;
1677 } else {
1678 imageNode = frameNode;
1679 auto imageGeometryNode = imageNode->GetGeometryNode();
1680 CHECK_NULL_VOID(imageGeometryNode);
1681 imageNodeSize = imageGeometryNode->GetFrameRect();
1682 data.frameNodeRect = imageNodeSize;
1683 }
1684 auto imageNodeOffset = imageNode->GetPaintRectOffset(false, true);
1685 auto menuNodeOffset = scrollNode->GetPaintRectOffset(false, true);
1686 data.menuRect = menuNodeSize;
1687 data.menuPositionLeft = menuNodeOffset.GetX() - imageNodeOffset.GetX();
1688 data.menuPositionTop = menuNodeOffset.GetY() - imageNodeOffset.GetY();
1689 data.menuPositionRight =
1690 imageNodeOffset.GetX() + imageNodeSize.Width() - menuNodeOffset.GetX() - menuNodeSize.Width();
1691 data.menuPositionBottom =
1692 imageNodeOffset.GetY() + imageNodeSize.Height() - menuNodeOffset.GetY() - menuNodeSize.Height();
1693 auto menuParam = menuWrapperPattern->GetMenuParam();
1694 data.menuPosition = menuPattern->GetLastPlacement().value_or(Placement::NONE);
1695 auto newMenuNode = menuPattern->DuplicateMenuNode(menuNode, menuParam);
1696 CHECK_NULL_VOID(newMenuNode);
1697 data.menuNode = newMenuNode;
1698 }
1699
GetBadgeNumber(const RefPtr<OHOS::Ace::DragEvent> & dragEvent)1700 int32_t GestureEventHub::GetBadgeNumber(const RefPtr<OHOS::Ace::DragEvent>& dragEvent)
1701 {
1702 CHECK_NULL_RETURN(dragEvent, 1);
1703 auto frameNode = GetFrameNode();
1704 CHECK_NULL_RETURN(frameNode, 1);
1705 auto pattern = frameNode->GetPattern();
1706 CHECK_NULL_RETURN(pattern, 1);
1707 int32_t badgeNumber = 1;
1708 pattern->ResetDragOption();
1709 auto unifiedData = dragEvent->GetData();
1710 auto dataLoadParams = dragEvent->GetDataLoadParams();
1711 auto isUseDataLoadParams = dragEvent->IsUseDataLoadParams();
1712 if (pattern->GetDragRecordSize() >= 0) {
1713 badgeNumber = pattern->GetDragRecordSize();
1714 } else if (unifiedData && !isUseDataLoadParams) {
1715 auto recordSize = unifiedData->GetSize();
1716 badgeNumber = recordSize > 1 ? recordSize : 1;
1717 } else if (dataLoadParams && isUseDataLoadParams) {
1718 auto recodeCount = dataLoadParams->GetRecordCount();
1719 badgeNumber = (recodeCount == 0 || recodeCount > INT32_MAX) ? 1 : static_cast<int32_t>(recodeCount);
1720 }
1721
1722 auto dragPreviewOptions = frameNode->GetDragPreviewOption();
1723 auto customBadgeNumber = dragPreviewOptions.GetCustomerBadgeNumber();
1724 auto selectItemSize = GetSelectItemSize();
1725 if (customBadgeNumber.has_value()) {
1726 badgeNumber = customBadgeNumber.value();
1727 TAG_LOGI(AceLogTag::ACE_DRAG, "Use custom badge number, value is %{public}d", badgeNumber);
1728 } else if (selectItemSize > 1) {
1729 badgeNumber = selectItemSize;
1730 TAG_LOGI(AceLogTag::ACE_DRAG, "Use select item size, value is %{public}d", badgeNumber);
1731 }
1732 return badgeNumber;
1733 }
1734
TryDoDragStartAnimation(const RefPtr<PipelineBase> & context,const RefPtr<Subwindow> & subWindow,const GestureEvent & info,PreparedInfoForDrag & data)1735 bool GestureEventHub::TryDoDragStartAnimation(const RefPtr<PipelineBase>& context, const RefPtr<Subwindow>& subWindow,
1736 const GestureEvent& info, PreparedInfoForDrag& data)
1737 {
1738 auto frameNode = GetFrameNode();
1739 auto container = Container::Current();
1740 auto eventHub = eventHub_.Upgrade();
1741 auto pipeline = AceType::DynamicCast<PipelineContext>(context);
1742 if (!subWindow || !frameNode || !container || !pipeline || !eventHub || !data.imageNode) {
1743 return false;
1744 }
1745
1746 auto dragNodePipeline = frameNode->GetContextRefPtr();
1747 CHECK_NULL_RETURN(dragNodePipeline, false);
1748 auto overlayManager = dragNodePipeline->GetOverlayManager();
1749 CHECK_NULL_RETURN(overlayManager, false);
1750 auto isExpandDisplay = DragDropFuncWrapper::IsExpandDisplay(context);
1751 auto dragDropManager = DragDropFuncWrapper::GetDragDropManagerForDragAnimation(context, dragNodePipeline,
1752 subWindow, isExpandDisplay, container->GetInstanceId());
1753 CHECK_NULL_RETURN(dragDropManager, false);
1754 dragDropManager->SetIsDragWithContextMenu(data.isMenuShow);
1755 // create gatherNode
1756 auto originGatherNode = overlayManager->GetGatherNode();
1757 OffsetF positionToWindow = originGatherNode ? originGatherNode->GetPositionToWindowWithTransform() : OffsetF();
1758 std::vector<GatherNodeChildInfo> childrenInfo;
1759 auto gatherNode = DragAnimationHelper::GetOrCreateGatherNode(overlayManager, dragEventActuator_, childrenInfo);
1760 data.gatherNode = gatherNode;
1761 // creat textNode
1762 DragAnimationHelper::CreateTextNode(data);
1763 auto gatherNodeOffset = isExpandDisplay
1764 ? DragDropManager::GetTouchOffsetRelativeToSubwindow(dragNodePipeline->GetInstanceId()) + positionToWindow
1765 : positionToWindow;
1766 DragEventActuator::UpdateGatherAnimatePosition(childrenInfo, gatherNodeOffset);
1767
1768 // mount node
1769 auto subWindowOverlayManager = subWindow->GetOverlayManager();
1770 CHECK_NULL_RETURN(subWindowOverlayManager, false);
1771 DragEventActuator::MountGatherNode(subWindowOverlayManager, frameNode, gatherNode, childrenInfo);
1772 DragAnimationHelper::MountPixelMap(
1773 subWindowOverlayManager, eventHub->GetOrCreateGestureEventHub(), data, true);
1774
1775 HideMenu();
1776 // update position
1777 UpdateNodePositionBeforeStartAnimation(frameNode, data);
1778 pipeline->FlushSyncGeometryNodeTasks();
1779 overlayManager->RemovePixelMap();
1780 DragAnimationHelper::ShowBadgeAnimation(data.textNode);
1781 DragAnimationHelper::ShowMenuHideAnimation(data);
1782 DragAnimationHelper::HideDragNodeCopy(overlayManager);
1783
1784 dragDropManager->DoDragStartAnimation(
1785 subWindowOverlayManager, info, eventHub->GetOrCreateGestureEventHub(), data);
1786 return true;
1787 }
1788
UpdateNodePositionBeforeStartAnimation(const RefPtr<FrameNode> & frameNode,PreparedInfoForDrag & data)1789 void GestureEventHub::UpdateNodePositionBeforeStartAnimation(const RefPtr<FrameNode>& frameNode,
1790 PreparedInfoForDrag& data)
1791 {
1792 CHECK_NULL_VOID(frameNode);
1793 if (data.sizeChangeEffect == DraggingSizeChangeEffect::DEFAULT && !data.textRowNode) {
1794 DragDropFuncWrapper::UpdateNodePositionToScreen(data.imageNode, data.dragPreviewOffsetToScreen);
1795 DragAnimationHelper::PreLayout(data.imageNode);
1796 } else {
1797 DragDropFuncWrapper::UpdateNodePositionToScreen(data.relativeContainerNode, data.dragPreviewOffsetToScreen);
1798 DragAnimationHelper::PreLayout(data.relativeContainerNode);
1799 }
1800 }
1801
CheckAllowDrag(const GestureEvent & info,const RefPtr<PipelineBase> & context,const RefPtr<FrameNode> & frameNode)1802 bool GestureEventHub::CheckAllowDrag(const GestureEvent& info, const RefPtr<PipelineBase>& context,
1803 const RefPtr<FrameNode>& frameNode)
1804 {
1805 auto eventHub = eventHub_.Upgrade();
1806 CHECK_NULL_RETURN(eventHub, false);
1807 CHECK_NULL_RETURN(frameNode, false);
1808 if (!eventHub->HasOnDragStart()) {
1809 TAG_LOGE(AceLogTag::ACE_DRAG, "FrameNode is not set onDragStart event.");
1810 return false;
1811 }
1812 if (!IsAllowedDrag(eventHub)) {
1813 auto pattern = frameNode->GetPattern();
1814 CHECK_NULL_RETURN(pattern, false);
1815 TAG_LOGE(AceLogTag::ACE_DRAG,
1816 "FrameNode is not allow drag, tag is %{public}s"
1817 "draggable is %{public}d, drag start event is %{public}d,"
1818 "default support drag is %{public}d, user set is %{public}d.",
1819 frameNode->GetTag().c_str(), frameNode->IsDraggable(), eventHub->HasOnDragStart(),
1820 pattern->DefaultSupportDrag(), frameNode->IsUserSet());
1821 return false;
1822 }
1823 auto pipeline = AceType::DynamicCast<PipelineContext>(context);
1824 CHECK_NULL_RETURN(pipeline, false);
1825 auto eventManager = pipeline->GetEventManager();
1826 CHECK_NULL_RETURN(eventManager, false);
1827 if (info.GetInputEventType() == InputEventType::MOUSE_BUTTON && eventManager->IsLastMoveBeforeUp()) {
1828 TAG_LOGE(AceLogTag::ACE_DRAG, "Drag stop because user release mouse button");
1829 return false;
1830 }
1831
1832 return true;
1833 }
1834
CreateDragEvent(const GestureEvent & info,const RefPtr<PipelineBase> & context,const RefPtr<FrameNode> & frameNode)1835 RefPtr<OHOS::Ace::DragEvent> GestureEventHub::CreateDragEvent(const GestureEvent& info,
1836 const RefPtr<PipelineBase>& context, const RefPtr<FrameNode>& frameNode)
1837 {
1838 RefPtr<OHOS::Ace::DragEvent> event = AceType::MakeRefPtr<OHOS::Ace::DragEvent>();
1839 CHECK_NULL_RETURN(frameNode, event);
1840 auto pipeline = AceType::DynamicCast<PipelineContext>(context);
1841 if (frameNode->GetTag() == V2::WEB_ETS_TAG) {
1842 CHECK_NULL_RETURN(pipeline, event);
1843 event->SetX(pipeline->ConvertPxToVp(Dimension(info.GetGlobalPoint().GetX(), DimensionUnit::PX)));
1844 event->SetY(pipeline->ConvertPxToVp(Dimension(info.GetGlobalPoint().GetY(), DimensionUnit::PX)));
1845 } else {
1846 event->SetX(info.GetGlobalPoint().GetX());
1847 event->SetY(info.GetGlobalPoint().GetY());
1848 }
1849 event->SetScreenX(info.GetScreenLocation().GetX());
1850 event->SetScreenY(info.GetScreenLocation().GetY());
1851 event->SetDisplayX(info.GetScreenLocation().GetX());
1852 event->SetDisplayY(info.GetScreenLocation().GetY());
1853 event->SetGlobalDisplayX(info.GetGlobalDisplayLocation().GetX());
1854 event->SetGlobalDisplayY(info.GetGlobalDisplayLocation().GetY());
1855 event->SetSourceTool(info.GetSourceTool());
1856 auto container = Container::Current();
1857 CHECK_NULL_RETURN(container, event);
1858 auto dragBundleName = container->GetBundleName();
1859 event->SetDragSource(dragBundleName);
1860 event->SetRemoteDev(false);
1861 event->SetDisplayId(info.GetTargetDisplayId());
1862 return event;
1863 }
1864
SetMouseDragMonitorState(bool state)1865 void GestureEventHub::SetMouseDragMonitorState(bool state)
1866 {
1867 auto ret = InteractionInterface::GetInstance()->SetMouseDragMonitorState(state);
1868 if (ret != 0) {
1869 TAG_LOGW(AceLogTag::ACE_DRAG, "Set mouse drag monitor state %{public}d failed, return value is %{public}d",
1870 state, ret);
1871 return;
1872 }
1873 TAG_LOGI(AceLogTag::ACE_DRAG, "Set mouse drag monitor state %{public}d success", state);
1874 }
1875
SetBindMenuStatus(bool setIsShow,bool isShow,MenuPreviewMode previewMode)1876 void GestureEventHub::SetBindMenuStatus(bool setIsShow, bool isShow, MenuPreviewMode previewMode)
1877 {
1878 if (setIsShow) {
1879 bindMenuStatus_.isBindCustomMenu = true;
1880 bindMenuStatus_.isShow = isShow;
1881 bindMenuStatus_.isShowPreviewMode = previewMode;
1882 } else {
1883 bindMenuStatus_.isBindLongPressMenu = true;
1884 bindMenuStatus_.longPressPreviewMode = previewMode;
1885 }
1886 }
1887
AddPreviewMenuHandleDragEnd(GestureEventFunc && actionEnd)1888 void GestureEventHub::AddPreviewMenuHandleDragEnd(GestureEventFunc&& actionEnd)
1889 {
1890 if (!scrollableActuator_) {
1891 scrollableActuator_ = MakeRefPtr<ScrollableActuator>(WeakClaim(this));
1892 }
1893 scrollableActuator_->AddPreviewMenuHandleDragEnd(std::move(actionEnd));
1894 }
1895
1896 // Set by user define, which will replace old one.
SetDragEvent(const RefPtr<DragEvent> & dragEvent,PanDirection direction,int32_t fingers,Dimension distance)1897 void GestureEventHub::SetDragEvent(
1898 const RefPtr<DragEvent>& dragEvent, PanDirection direction, int32_t fingers, Dimension distance)
1899 {
1900 if (!dragEventActuator_ || dragEventActuator_->GetIsNewFwk()) {
1901 isDragNewFwk_ = false;
1902 dragEventActuator_ = MakeRefPtr<DragEventActuator>(WeakClaim(this), direction, fingers, distance.ConvertToPx());
1903 }
1904 dragEventActuator_->ReplaceDragEvent(dragEvent);
1905 }
1906
SetDragDropEvent()1907 void GestureEventHub::SetDragDropEvent()
1908 {
1909 if (!dragEventActuator_ || !dragEventActuator_->GetIsNewFwk()) {
1910 isDragNewFwk_ = true;
1911 dragEventActuator_ = MakeRefPtr<DragDropEventActuator>(WeakClaim(this));
1912 }
1913 }
1914
SetCustomDragEvent(const RefPtr<DragEvent> & dragEvent,PanDirection direction,int32_t fingers,Dimension distance)1915 void GestureEventHub::SetCustomDragEvent(
1916 const RefPtr<DragEvent>& dragEvent, PanDirection direction, int32_t fingers, Dimension distance)
1917 {
1918 if (!dragEventActuator_ || dragEventActuator_->GetIsNewFwk()) {
1919 isDragNewFwk_ = false;
1920 dragEventActuator_ = MakeRefPtr<DragEventActuator>(WeakClaim(this), direction, fingers, distance.ConvertToPx());
1921 }
1922 dragEventActuator_->SetCustomDragEvent(dragEvent);
1923 }
1924
HasDragEvent() const1925 bool GestureEventHub::HasDragEvent() const
1926 {
1927 return dragEventActuator_ && (dragEventActuator_->HasDragEvent() || dragEventActuator_->GetIsNewFwk());
1928 }
1929
RemoveDragEvent()1930 void GestureEventHub::RemoveDragEvent()
1931 {
1932 if (!dragEventActuator_) {
1933 return;
1934 }
1935 if (dragEventActuator_->GetIsNewFwk()) {
1936 dragEventActuator_ = nullptr;
1937 return;
1938 }
1939 dragEventActuator_->ClearDragEvent();
1940 }
1941
SetThumbnailCallback(std::function<void (Offset)> && callback)1942 void GestureEventHub::SetThumbnailCallback(std::function<void(Offset)>&& callback)
1943 {
1944 if (dragEventActuator_) {
1945 dragEventActuator_->SetThumbnailCallback(std::move(callback));
1946 }
1947 }
1948
DragNodeDetachFromParent()1949 void GestureEventHub::DragNodeDetachFromParent()
1950 {
1951 if (dragEventActuator_) {
1952 dragEventActuator_->RemovePixelMap();
1953 }
1954 }
1955
GetTextDraggable() const1956 bool GestureEventHub::GetTextDraggable() const
1957 {
1958 return textDraggable_;
1959 }
1960
SetTextDraggable(bool draggable)1961 void GestureEventHub::SetTextDraggable(bool draggable)
1962 {
1963 textDraggable_ = draggable;
1964 }
1965
SetIsTextDraggable(bool isTextDraggable)1966 void GestureEventHub::SetIsTextDraggable(bool isTextDraggable)
1967 {
1968 isTextDraggable_ = isTextDraggable;
1969 }
1970
GetIsTextDraggable()1971 bool GestureEventHub::GetIsTextDraggable()
1972 {
1973 return isTextDraggable_;
1974 }
1975
SetPreviewMode(MenuPreviewMode mode)1976 void GestureEventHub::SetPreviewMode(MenuPreviewMode mode)
1977 {
1978 previewMode_ = mode;
1979 }
1980
GetPreviewMode()1981 MenuPreviewMode GestureEventHub::GetPreviewMode()
1982 {
1983 return previewMode_;
1984 }
1985
SetContextMenuShowStatus(bool contextMenuShowStatus)1986 void GestureEventHub::SetContextMenuShowStatus(bool contextMenuShowStatus)
1987 {
1988 contextMenuShowStatus_ = contextMenuShowStatus;
1989 }
1990
GetContextMenuShowStatus()1991 bool GestureEventHub::GetContextMenuShowStatus()
1992 {
1993 return contextMenuShowStatus_;
1994 }
1995
SetMenuBindingType(MenuBindingType menuBindingType)1996 void GestureEventHub::SetMenuBindingType(MenuBindingType menuBindingType)
1997 {
1998 menuBindingType_ = menuBindingType;
1999 }
2000
GetMenuBindingType()2001 MenuBindingType GestureEventHub::GetMenuBindingType()
2002 {
2003 return menuBindingType_;
2004 }
2005
SetPixelMap(RefPtr<PixelMap> pixelMap)2006 void GestureEventHub::SetPixelMap(RefPtr<PixelMap> pixelMap)
2007 {
2008 pixelMap_ = pixelMap;
2009 }
2010
GetPixelMap()2011 RefPtr<PixelMap> GestureEventHub::GetPixelMap()
2012 {
2013 return pixelMap_;
2014 }
2015
SetDragPreviewPixelMap(RefPtr<PixelMap> pixelMap)2016 void GestureEventHub::SetDragPreviewPixelMap(RefPtr<PixelMap> pixelMap)
2017 {
2018 dragPreviewPixelMap_ = pixelMap;
2019 }
2020
GetDragEventActuator()2021 RefPtr<DragEventActuator> GestureEventHub::GetDragEventActuator()
2022 {
2023 return dragEventActuator_;
2024 }
2025
GetDragPreviewPixelMap()2026 RefPtr<PixelMap> GestureEventHub::GetDragPreviewPixelMap()
2027 {
2028 return dragPreviewPixelMap_;
2029 }
2030
SetMenuPreviewScale(float menuPreviewScale)2031 void GestureEventHub::SetMenuPreviewScale(float menuPreviewScale)
2032 {
2033 menuPreviewScale_ = menuPreviewScale;
2034 }
2035
GetMenuPreviewScale() const2036 float GestureEventHub::GetMenuPreviewScale() const
2037 {
2038 return menuPreviewScale_;
2039 }
2040
GetBindMenuStatus() const2041 const BindMenuStatus& GestureEventHub::GetBindMenuStatus() const
2042 {
2043 return bindMenuStatus_;
2044 }
2045
SetRecognizerDelayStatus(const RecognizerDelayStatus & recognizerDelayStatus)2046 void GestureEventHub::SetRecognizerDelayStatus(const RecognizerDelayStatus& recognizerDelayStatus)
2047 {
2048 auto pipeline = PipelineContext::GetCurrentContextPtrSafelyWithCheck();
2049 CHECK_NULL_VOID(pipeline);
2050 auto eventManager = pipeline->GetEventManager();
2051 CHECK_NULL_VOID(eventManager);
2052 auto refereeNG = eventManager->GetGestureRefereeNG(nullptr);
2053 CHECK_NULL_VOID(refereeNG);
2054 refereeNG->SetRecognizerDelayStatus(recognizerDelayStatus);
2055 }
2056 } // namespace OHOS::Ace::NG
2057