• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "core/components_ng/manager/select_content_overlay/select_content_overlay_manager.h"
17 
18 #include <optional>
19 #include <utility>
20 
21 #include "base/memory/ace_type.h"
22 #include "base/memory/referenced.h"
23 #include "base/utils/utils.h"
24 #include "core/common/container.h"
25 #include "core/components_ng/pattern/select_content_overlay/select_content_overlay_pattern.h"
26 #include "core/components_ng/pattern/select_overlay/select_overlay_node.h"
27 #include "core/components_ng/pattern/select_overlay/select_overlay_property.h"
28 #include "core/event/touch_event.h"
29 #include "core/pipeline_ng/pipeline_context.h"
30 
31 namespace OHOS::Ace::NG {
32 namespace {
GetSelectOverlayPattern(const WeakPtr<FrameNode> & overlayNode)33 RefPtr<SelectContentOverlayPattern> GetSelectOverlayPattern(const WeakPtr<FrameNode>& overlayNode)
34 {
35     auto node = overlayNode.Upgrade();
36     CHECK_NULL_RETURN(node, nullptr);
37     auto selectOverlayNode = AceType::DynamicCast<SelectOverlayNode>(node);
38     CHECK_NULL_RETURN(selectOverlayNode, nullptr);
39     return selectOverlayNode->GetPattern<SelectContentOverlayPattern>();
40 }
41 
GetSelectMenuPattern(const WeakPtr<SelectContentOverlayManager> & manager)42 RefPtr<SelectContentOverlayPattern> GetSelectMenuPattern(const WeakPtr<SelectContentOverlayManager>& manager)
43 {
44     auto overlayManager = manager.Upgrade();
45     CHECK_NULL_RETURN(overlayManager, nullptr);
46     auto pattern = overlayManager->GetMenuPattern();
47     return AceType::DynamicCast<SelectContentOverlayPattern>(pattern);
48 }
49 
GetSelectHandlePattern(const WeakPtr<SelectContentOverlayManager> & manager)50 RefPtr<SelectContentOverlayPattern> GetSelectHandlePattern(const WeakPtr<SelectContentOverlayManager>& manager)
51 {
52     auto overlayManager = manager.Upgrade();
53     CHECK_NULL_RETURN(overlayManager, nullptr);
54     auto pattern = overlayManager->GetHandlePattern();
55     return AceType::DynamicCast<SelectContentOverlayPattern>(pattern);
56 }
57 } // namespace
58 
GetOverlayManager(const RefPtr<SelectOverlayHolder> & holder)59 const RefPtr<SelectContentOverlayManager> SelectContentOverlayManager::GetOverlayManager(
60     const RefPtr<SelectOverlayHolder>& holder)
61 {
62     auto pipeline = PipelineContext::GetCurrentContextSafely();
63     CHECK_NULL_RETURN(pipeline, nullptr);
64     auto overlayManager = pipeline->GetSelectOverlayManager();
65     CHECK_NULL_RETURN(overlayManager, nullptr);
66     auto contentManager = overlayManager->GetSelectContentOverlayManager();
67     if (!holder) {
68         return contentManager;
69     }
70     if (!contentManager->HasHolder(holder->GetOwnerId())) {
71         contentManager->SetHolder(holder);
72     }
73     return contentManager;
74 }
75 
SetHolder(const RefPtr<SelectOverlayHolder> & holder)76 void SelectContentOverlayManager::SetHolder(const RefPtr<SelectOverlayHolder>& holder)
77 {
78     CHECK_NULL_VOID(holder);
79     if (!selectOverlayHolder_) {
80         SetHolderInternal(holder);
81         return;
82     }
83     auto prevOwnerId = selectOverlayHolder_->GetOwnerId();
84     auto ownerId = holder->GetOwnerId();
85     if (selectionHoldId_ > 0 && ownerId != selectionHoldId_) {
86         ResetSelectionRect();
87         if (legacyManagerCallbacks_.selectionResetCallback) {
88             legacyManagerCallbacks_.selectionResetCallback();
89         }
90     }
91     if (prevOwnerId == ownerId) {
92         return;
93     }
94     CloseInternal(prevOwnerId, false, CloseReason::CLOSE_REASON_HOLD_BY_OTHER);
95     SetHolderInternal(holder);
96 }
97 
SetHolderInternal(const RefPtr<SelectOverlayHolder> & holder)98 void SelectContentOverlayManager::SetHolderInternal(const RefPtr<SelectOverlayHolder>& holder)
99 {
100     // unbind old holder
101     if (selectOverlayHolder_) {
102         selectOverlayHolder_->OnBind(nullptr);
103     }
104     selectOverlayHolder_ = holder;
105     // bind new holder
106     if (selectOverlayHolder_) {
107         selectOverlayHolder_->OnBind(WeakClaim(this));
108     }
109 }
HasHolder(int32_t id)110 bool SelectContentOverlayManager::HasHolder(int32_t id)
111 {
112     CHECK_NULL_RETURN(selectOverlayHolder_, false);
113     return selectOverlayHolder_->GetOwnerId() == id;
114 }
115 
Show(bool animation,int32_t requestCode)116 void SelectContentOverlayManager::Show(bool animation, int32_t requestCode)
117 {
118     CHECK_NULL_VOID(selectOverlayHolder_);
119     auto info = BuildSelectOverlayInfo(requestCode);
120     if (!info.menuInfo.menuIsShow && info.isUsingMouse) {
121         return;
122     }
123     if (legacyManagerCallbacks_.closeCallback) {
124         legacyManagerCallbacks_.closeCallback(false, true);
125     }
126     info.enableHandleLevel = info.enableHandleLevel && !info.isUsingMouse;
127     if (IsOpen()) {
128         if (info.recreateOverlay || info.menuInfo.menuType != shareOverlayInfo_->menuInfo.menuType) {
129             auto holder = selectOverlayHolder_;
130             CloseInternal(selectOverlayHolder_->GetOwnerId(), false, CloseReason::CLOSE_REASON_BY_RECREATE);
131             SetHolder(holder);
132             CreateSelectOverlay(info, animation);
133             return;
134         }
135         UpdateExistOverlay(info, animation, requestCode);
136     } else {
137         CreateSelectOverlay(info, animation);
138     }
139 }
140 
BuildSelectOverlayInfo(int32_t requestCode)141 SelectOverlayInfo SelectContentOverlayManager::BuildSelectOverlayInfo(int32_t requestCode)
142 {
143     SelectOverlayInfo overlayInfo;
144     UpdateStatusInfos(overlayInfo);
145     overlayInfo.menuCallback.onCopy = MakeMenuCallback(OptionMenuActionId::COPY, overlayInfo);
146     overlayInfo.menuCallback.onPaste = MakeMenuCallback(OptionMenuActionId::PASTE, overlayInfo);
147     overlayInfo.menuCallback.onCut = MakeMenuCallback(OptionMenuActionId::CUT, overlayInfo);
148     overlayInfo.menuCallback.onSelectAll = MakeMenuCallback(OptionMenuActionId::SELECT_ALL, overlayInfo);
149     overlayInfo.menuCallback.onTranslate = MakeMenuCallback(OptionMenuActionId::TRANSLATE, overlayInfo);
150     overlayInfo.menuCallback.onCameraInput = MakeMenuCallback(OptionMenuActionId::CAMERA_INPUT, overlayInfo);
151     overlayInfo.menuCallback.onAIWrite = MakeMenuCallback(OptionMenuActionId::AI_WRITE, overlayInfo);
152     overlayInfo.menuCallback.onAppear = MakeMenuCallback(OptionMenuActionId::APPEAR, overlayInfo);
153     overlayInfo.menuCallback.onDisappear = MakeMenuCallback(OptionMenuActionId::DISAPPEAR, overlayInfo);
154     overlayInfo.isUseOverlayNG = true;
155     RegisterTouchCallback(overlayInfo);
156     RegisterHandleCallback(overlayInfo);
157     selectOverlayHolder_->OnUpdateSelectOverlayInfo(overlayInfo, requestCode);
158     UpdateSelectOverlayInfoInternal(overlayInfo);
159     return overlayInfo;
160 }
161 
UpdateStatusInfos(SelectOverlayInfo & overlayInfo)162 void SelectContentOverlayManager::UpdateStatusInfos(SelectOverlayInfo& overlayInfo)
163 {
164     auto firstHandle = selectOverlayHolder_->GetFirstHandleInfo();
165     auto secondHandle = selectOverlayHolder_->GetSecondHandleInfo();
166     if (firstHandle.has_value()) {
167         overlayInfo.firstHandle = firstHandle.value();
168     } else {
169         overlayInfo.firstHandle.isShow = false;
170     }
171     if (secondHandle.has_value()) {
172         overlayInfo.secondHandle = secondHandle.value();
173     } else {
174         overlayInfo.secondHandle.isShow = false;
175     }
176     SelectMenuInfo menuInfo;
177     selectOverlayHolder_->OnUpdateMenuInfo(menuInfo, DIRTY_ALL_MENU_ITEM);
178     overlayInfo.menuInfo = menuInfo;
179     overlayInfo.callerFrameNode = selectOverlayHolder_->GetOwner();
180     overlayInfo.selectText = selectOverlayHolder_->GetSelectedText();
181     overlayInfo.selectArea = selectOverlayHolder_->GetSelectArea();
182 }
183 
RegisterHandleCallback(SelectOverlayInfo & info)184 void SelectContentOverlayManager::RegisterHandleCallback(SelectOverlayInfo& info)
185 {
186     CHECK_NULL_VOID(selectOverlayHolder_);
187     auto callback = selectOverlayHolder_->GetCallback();
188     CHECK_NULL_VOID(callback);
189     if (!callback->IsRegisterHandleCallback()) {
190         return;
191     }
192     info.onHandleMoveStart =
193         [weakCallback = WeakClaim(AceType::RawPtr(callback))](const GestureEvent& event, bool isFirst) {
194             auto overlayCallback = weakCallback.Upgrade();
195             CHECK_NULL_VOID(overlayCallback);
196             overlayCallback->OnHandleMoveStart(event, isFirst);
197         };
198     info.onHandleMove = [weakCallback = WeakClaim(AceType::RawPtr(callback)), weakManager = WeakClaim(this)](
199                             const RectF& rect, bool isFirst) {
200         auto overlayCallback = weakCallback.Upgrade();
201         CHECK_NULL_VOID(overlayCallback);
202         auto handle = rect;
203         if (weakManager.Upgrade()) {
204             weakManager.Upgrade()->RevertRectRelativeToRoot(handle);
205         }
206         overlayCallback->OnHandleMove(handle, isFirst);
207     };
208     info.onHandleMoveDone = [weakCallback = WeakClaim(AceType::RawPtr(callback)), weakManager = WeakClaim(this)](
209                                 const RectF& rect, bool isFirst) {
210         auto overlayCallback = weakCallback.Upgrade();
211         CHECK_NULL_VOID(overlayCallback);
212         auto handle = rect;
213         if (weakManager.Upgrade()) {
214             weakManager.Upgrade()->RevertRectRelativeToRoot(handle);
215         }
216         overlayCallback->OnHandleMoveDone(rect, isFirst);
217     };
218     info.onHandleReverse = [weakCallback = WeakClaim(AceType::RawPtr(callback))](bool isReverse) {
219         auto overlayCallback = weakCallback.Upgrade();
220         CHECK_NULL_VOID(overlayCallback);
221         overlayCallback->OnHandleReverse(isReverse);
222     };
223     info.onHandleIsHidden = [weakCallback = WeakClaim(AceType::RawPtr(callback))]() {
224         auto overlayCallback = weakCallback.Upgrade();
225         CHECK_NULL_VOID(overlayCallback);
226         overlayCallback->OnHandleIsHidden();
227     };
228 }
229 
RegisterTouchCallback(SelectOverlayInfo & info)230 void SelectContentOverlayManager::RegisterTouchCallback(SelectOverlayInfo& info)
231 {
232     CHECK_NULL_VOID(selectOverlayHolder_);
233     auto callback = selectOverlayHolder_->GetCallback();
234     CHECK_NULL_VOID(callback);
235     if (!callback->IsRegisterTouchCallback()) {
236         return;
237     }
238     info.onTouchDown = [weakCallback = WeakClaim(AceType::RawPtr(callback))](const TouchEventInfo& event) {
239         auto callback = weakCallback.Upgrade();
240         CHECK_NULL_VOID(callback);
241         callback->OnOverlayTouchDown(event);
242     };
243     info.onTouchUp = [weakCallback = WeakClaim(AceType::RawPtr(callback))](const TouchEventInfo& event) {
244         auto callback = weakCallback.Upgrade();
245         CHECK_NULL_VOID(callback);
246         callback->OnOverlayTouchUp(event);
247     };
248     info.onTouchMove = [weakCallback = WeakClaim(AceType::RawPtr(callback))](const TouchEventInfo& event) {
249         auto callback = weakCallback.Upgrade();
250         CHECK_NULL_VOID(callback);
251         callback->OnOverlayTouchMove(event);
252     };
253     info.onClick = [weakCallback = WeakClaim(AceType::RawPtr(callback))](const GestureEvent& event, bool isClickCaret) {
254         auto callback = weakCallback.Upgrade();
255         CHECK_NULL_VOID(callback);
256         callback->OnOverlayClick(event, isClickCaret);
257     };
258     info.onMouseEvent = [weakCallback = WeakClaim(AceType::RawPtr(callback))](const MouseInfo& event) {
259         auto callback = weakCallback.Upgrade();
260         CHECK_NULL_VOID(callback);
261         callback->OnHandleMouseEvent(event);
262     };
263 }
264 
MakeMenuCallback(OptionMenuActionId id,const SelectOverlayInfo & info)265 std::function<void()> SelectContentOverlayManager::MakeMenuCallback(
266     OptionMenuActionId id, const SelectOverlayInfo& info)
267 {
268     auto callback = selectOverlayHolder_->GetCallback();
269     CHECK_NULL_RETURN(callback, nullptr);
270     return [actionId = id, weakCallback = WeakClaim(AceType::RawPtr(callback)), menuType = info.menuInfo.menuType]() {
271         auto callback = weakCallback.Upgrade();
272         CHECK_NULL_VOID(callback);
273         callback->OnMenuItemAction(actionId, menuType);
274     };
275 }
276 
UpdateExistOverlay(const SelectOverlayInfo & info,bool animation,int32_t requestCode)277 void SelectContentOverlayManager::UpdateExistOverlay(const SelectOverlayInfo& info, bool animation, int32_t requestCode)
278 {
279     // update menu node
280     auto menuPattern = GetSelectMenuPattern(WeakClaim(this));
281     if (menuPattern) {
282         if (!info.isSingleHandle) {
283             menuPattern->UpdateSelectArea(info.selectArea);
284             menuPattern->SetSelectInfo(info.selectText);
285         }
286         menuPattern->UpdateMenuInfo(info.menuInfo);
287         menuPattern->UpdateViewPort(info.ancestorViewPort);
288     }
289     // update handle node
290     auto handlePattern = GetSelectHandlePattern(WeakClaim(this));
291     if (handlePattern) {
292         handlePattern->UpdateIsSingleHandle(info.isSingleHandle);
293         handlePattern->UpdateIsShowHandleLine(info.isHandleLineShow);
294         handlePattern->UpdateFirstAndSecondHandleInfo(info.firstHandle, info.secondHandle);
295         TAG_LOGI(AceLogTag::ACE_SELECT_OVERLAY,
296             "Update first %{public}s isShow %{public}d, second %{public}s isShow %{public}d",
297             info.firstHandle.paintRect.ToString().c_str(), info.firstHandle.isShow,
298             info.secondHandle.paintRect.ToString().c_str(), info.secondHandle.isShow);
299         if (info.isSingleHandle) {
300             if (selectOverlayHolder_->CheckRestartHiddenHandleTask(requestCode)) {
301                 handlePattern->RestartHiddenHandleTask(true);
302             }
303         } else {
304             handlePattern->CancelHiddenHandleTask();
305         }
306     }
307     selectOverlayHolder_->OnHandleExistOverlay(info, requestCode);
308     NotifySelectOverlayShow(false);
309 }
310 
SwitchToHandleMode(HandleLevelMode mode,bool forceChange)311 void SelectContentOverlayManager::SwitchToHandleMode(HandleLevelMode mode, bool forceChange)
312 {
313     CHECK_NULL_VOID(shareOverlayInfo_);
314     if (shareOverlayInfo_->handleLevelMode == mode) {
315         return;
316     }
317     if (selectOverlayHolder_ && selectOverlayHolder_->GetCallback()) {
318         if (!forceChange && !selectOverlayHolder_->GetCallback()->CheckSwitchToMode(mode)) {
319             return;
320         }
321         selectOverlayHolder_->GetCallback()->OnHandleLevelModeChanged(mode);
322     }
323     TAG_LOGI(AceLogTag::ACE_SELECT_OVERLAY, "Set handle mode: %{public}d", mode);
324     shareOverlayInfo_->handleLevelMode = mode;
325     auto handleNode = handleNode_.Upgrade();
326     CHECK_NULL_VOID(handleNode);
327     auto taskExecutor = Container::CurrentTaskExecutor();
328     CHECK_NULL_VOID(taskExecutor);
329     if (mode == HandleLevelMode::OVERLAY) {
330         taskExecutor->PostTask(
331             [weak = WeakClaim(this), node = handleNode] {
332                 auto manager = weak.Upgrade();
333                 CHECK_NULL_VOID(manager);
334                 CHECK_NULL_VOID(node);
335                 if (!manager->IsOpen()) {
336                     return;
337                 }
338                 manager->DestroySelectOverlayNode(node);
339                 manager->MountNodeToRoot(node, false, NodeType::HANDLE);
340                 node->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
341             },
342             TaskExecutor::TaskType::UI, "SwitchToOverlayModeTask");
343     } else if (mode == HandleLevelMode::EMBED) {
344         taskExecutor->PostTask(
345             [weak = WeakClaim(this), node = handleNode] {
346                 auto manager = weak.Upgrade();
347                 CHECK_NULL_VOID(manager);
348                 CHECK_NULL_VOID(node);
349                 if (!manager->IsOpen()) {
350                     return;
351                 }
352                 manager->DestroySelectOverlayNode(node);
353                 manager->MountNodeToCaller(node, false);
354                 node->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
355             },
356             TaskExecutor::TaskType::UI, "SwitchToEmbedModeTask");
357     }
358 }
359 
MarkInfoChange(SelectOverlayDirtyFlag dirty)360 void SelectContentOverlayManager::MarkInfoChange(SelectOverlayDirtyFlag dirty)
361 {
362     CHECK_NULL_VOID(selectOverlayHolder_);
363     CHECK_NULL_VOID(IsOpen());
364     auto menuPattern = GetSelectMenuPattern(WeakClaim(this));
365     if (menuPattern) {
366         if ((dirty & DIRTY_SELECT_AREA) == DIRTY_SELECT_AREA) {
367             auto selectArea = selectOverlayHolder_->GetSelectArea();
368             ConvertRectRelativeToParent(selectArea);
369             menuPattern->UpdateSelectArea(selectArea);
370         }
371         if ((dirty & DIRTY_ALL_MENU_ITEM) == DIRTY_ALL_MENU_ITEM) {
372             SelectMenuInfo menuInfo;
373             selectOverlayHolder_->OnUpdateMenuInfo(menuInfo, DIRTY_ALL_MENU_ITEM);
374             menuPattern->UpdateSelectMenuInfo(menuInfo);
375         }
376         if ((dirty & DIRTY_COPY_ALL_ITEM) == DIRTY_COPY_ALL_ITEM) {
377             auto oldMenuInfo = menuPattern->GetSelectMenuInfo();
378             SelectMenuInfo menuInfo = { .showCopy = oldMenuInfo.showCopy, .showCopyAll = oldMenuInfo.showCopyAll };
379             selectOverlayHolder_->OnUpdateMenuInfo(menuInfo, DIRTY_COPY_ALL_ITEM);
380             oldMenuInfo.showCopyAll = menuInfo.showCopyAll;
381             oldMenuInfo.showCopy = menuInfo.showCopy;
382             menuPattern->UpdateSelectMenuInfo(oldMenuInfo);
383         }
384         if ((dirty & DIRTY_SELECT_TEXT) == DIRTY_SELECT_TEXT) {
385             auto selectedInfo = selectOverlayHolder_->GetSelectedText();
386             menuPattern->SetSelectInfo(selectedInfo);
387         }
388     }
389     if ((dirty & DIRTY_VIEWPORT) == DIRTY_VIEWPORT) {
390         auto viewPort = selectOverlayHolder_->GetAncestorNodeViewPort();
391         if (viewPort) {
392             ConvertRectRelativeToParent(*viewPort);
393         }
394         if (menuPattern) {
395             menuPattern->UpdateViewPort(viewPort);
396         }
397     }
398     UpdateHandleInfosWithFlag(dirty);
399     selectOverlayHolder_->OnHandleMarkInfoChange(shareOverlayInfo_, dirty);
400 }
401 
MarkSelectOverlayDirty(PropertyChangeFlag changeFlag)402 void SelectContentOverlayManager::MarkSelectOverlayDirty(PropertyChangeFlag changeFlag)
403 {
404     CHECK_NULL_VOID(IsOpen());
405     selectOverlayNode_.Upgrade()->MarkDirtyNode(changeFlag);
406 }
407 
UpdateHandleInfosWithFlag(int32_t updateFlag)408 void SelectContentOverlayManager::UpdateHandleInfosWithFlag(int32_t updateFlag)
409 {
410     auto pattern = GetSelectHandlePattern(WeakClaim(this));
411     CHECK_NULL_VOID(pattern);
412     std::optional<SelectHandleInfo> firstHandleInfo;
413     if ((static_cast<uint32_t>(updateFlag) & DIRTY_FIRST_HANDLE) == DIRTY_FIRST_HANDLE) {
414         firstHandleInfo = selectOverlayHolder_->GetFirstHandleInfo();
415         if (firstHandleInfo) {
416             ConvertHandleRelativeToParent(*firstHandleInfo);
417         }
418     }
419     std::optional<SelectHandleInfo> secondHandleInfo;
420     if ((static_cast<uint32_t>(updateFlag) & DIRTY_SECOND_HANDLE) == DIRTY_SECOND_HANDLE) {
421         secondHandleInfo = selectOverlayHolder_->GetSecondHandleInfo();
422         if (secondHandleInfo) {
423             ConvertHandleRelativeToParent(*secondHandleInfo);
424         }
425     }
426     if (!firstHandleInfo && !secondHandleInfo) {
427         return;
428     }
429     if (firstHandleInfo && secondHandleInfo) {
430         pattern->UpdateFirstAndSecondHandleInfo(*firstHandleInfo, *secondHandleInfo);
431     } else if (firstHandleInfo) {
432         pattern->UpdateFirstSelectHandleInfo(*firstHandleInfo);
433     } else {
434         pattern->UpdateSecondSelectHandleInfo(*secondHandleInfo);
435     }
436 }
437 
CreateSelectOverlay(SelectOverlayInfo & info,bool animation)438 void SelectContentOverlayManager::CreateSelectOverlay(SelectOverlayInfo& info, bool animation)
439 {
440     if (!info.enableHandleLevel) {
441         CreateNormalSelectOverlay(info, animation);
442         return;
443     }
444     CreateHandleLevelSelectOverlay(info, animation, info.handleLevelMode);
445 }
446 
CreateNormalSelectOverlay(SelectOverlayInfo & info,bool animation)447 void SelectContentOverlayManager::CreateNormalSelectOverlay(SelectOverlayInfo& info, bool animation)
448 {
449     shareOverlayInfo_ = std::make_shared<SelectOverlayInfo>(info);
450     auto overlayNode = SelectOverlayNode::CreateSelectOverlayNode(shareOverlayInfo_);
451     selectOverlayNode_ = overlayNode;
452     auto taskExecutor = Container::CurrentTaskExecutor();
453     CHECK_NULL_VOID(taskExecutor);
454     taskExecutor->PostTask(
455         [animation, weak = WeakClaim(this), node = overlayNode] {
456             auto manager = weak.Upgrade();
457             CHECK_NULL_VOID(manager);
458             if (node && node == manager->selectOverlayNode_) {
459                 CHECK_NULL_VOID(manager->shareOverlayInfo_);
460                 auto nodeType =
461                     manager->shareOverlayInfo_->isUsingMouse ? NodeType::RIGHT_CLICK_MENU : NodeType::HANDLE_WITH_MENU;
462                 manager->MountNodeToRoot(node, animation, nodeType);
463                 manager->NotifySelectOverlayShow(true);
464             }
465         },
466         TaskExecutor::TaskType::UI, "ArkUISelectOverlayCreate");
467 }
468 
CreateHandleLevelSelectOverlay(SelectOverlayInfo & info,bool animation,HandleLevelMode mode)469 void SelectContentOverlayManager::CreateHandleLevelSelectOverlay(
470     SelectOverlayInfo& info, bool animation, HandleLevelMode mode)
471 {
472     TAG_LOGI(AceLogTag::ACE_SELECT_OVERLAY,
473         "Show SelectOverlay, first %{public}s isShow %{public}d, second %{public}s isShow %{public}d",
474         info.firstHandle.paintRect.ToString().c_str(), info.firstHandle.isShow,
475         info.secondHandle.paintRect.ToString().c_str(), info.secondHandle.isShow);
476     shareOverlayInfo_ = std::make_shared<SelectOverlayInfo>(info);
477     auto menuNode = SelectOverlayNode::CreateSelectOverlayNode(shareOverlayInfo_, SelectOverlayMode::MENU_ONLY);
478     menuNode_ = menuNode;
479     auto handleNode = SelectOverlayNode::CreateSelectOverlayNode(shareOverlayInfo_, SelectOverlayMode::HANDLE_ONLY);
480     handleNode_ = handleNode;
481     auto taskExecutor = Container::CurrentTaskExecutorSafely();
482     CHECK_NULL_VOID(taskExecutor);
483     taskExecutor->PostTask(
484         [animation, weak = WeakClaim(this), menuNode, handleNode, mode] {
485             auto manager = weak.Upgrade();
486             CHECK_NULL_VOID(manager);
487             auto isMenuNodeValid = (menuNode && menuNode == manager->menuNode_);
488             auto isHandleNodeValid = (handleNode && handleNode == manager->handleNode_);
489             if (!isMenuNodeValid || !isHandleNodeValid) {
490                 return;
491             }
492             manager->MountNodeToRoot(menuNode, animation, NodeType::TOUCH_MENU);
493             if (mode == HandleLevelMode::EMBED) {
494                 manager->MountNodeToCaller(handleNode, animation);
495             } else if (mode == HandleLevelMode::OVERLAY) {
496                 manager->MountNodeToRoot(handleNode, animation, NodeType::HANDLE);
497             }
498             manager->NotifySelectOverlayShow(true);
499         },
500         TaskExecutor::TaskType::UI, "CreateHandleLevelSelectOverlay");
501 }
502 
MountNodeToRoot(const RefPtr<FrameNode> & overlayNode,bool animation,NodeType nodeType)503 void SelectContentOverlayManager::MountNodeToRoot(
504     const RefPtr<FrameNode>& overlayNode, bool animation, NodeType nodeType)
505 {
506     auto rootNode = GetSelectOverlayRoot();
507     CHECK_NULL_VOID(rootNode);
508     const auto& children = rootNode->GetChildren();
509     auto slotIt = FindSelectOverlaySlot(rootNode, children);
510     auto index = static_cast<int32_t>(std::distance(children.begin(), slotIt));
511     auto slot = (index > 0) ? index : DEFAULT_NODE_SLOT;
512     bool isMeetSpecialNode = false;
513     std::vector<std::string> nodeTags = {
514         V2::KEYBOARD_ETS_TAG, // keep handle and menu node before keyboard node
515         V2::SELECT_OVERLAY_ETS_TAG, // keep handle node before menu node
516         V2::TEXTINPUT_ETS_TAG, // keep handle and menu node before magnifier
517         V2::SHEET_WRAPPER_TAG // keep handle and menu node before SheetWrapper
518     };
519     for (auto it = slotIt; it != children.end(); ++it) {
520         for (const auto& tag : nodeTags) {
521             if ((*it)->GetTag() == tag) {
522                 slot = std::min(slot, index);
523                 isMeetSpecialNode = true;
524                 break;
525             }
526         }
527         if (isMeetSpecialNode) {
528             break;
529         }
530         index++;
531     }
532     if (nodeType == NodeType::TOUCH_MENU || nodeType == NodeType::RIGHT_CLICK_MENU) {
533         slot = index;
534     }
535     TAG_LOGI(AceLogTag::ACE_SELECT_OVERLAY, "MountNodeToRoot:%{public}s, id:%{public}d", rootNode->GetTag().c_str(),
536         rootNode->GetId());
537     overlayNode->MountToParent(rootNode, slot);
538     rootNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
539     if (!shareOverlayInfo_->isUsingMouse) {
540         auto node = DynamicCast<SelectOverlayNode>(overlayNode);
541         if (node) {
542             node->ShowSelectOverlay(animation);
543         }
544     }
545 }
546 
FindSelectOverlaySlot(const RefPtr<FrameNode> & root,const std::list<RefPtr<UINode>> & children)547 std::list<RefPtr<UINode>>::const_iterator SelectContentOverlayManager::FindSelectOverlaySlot(
548     const RefPtr<FrameNode>& root, const std::list<RefPtr<UINode>>& children)
549 {
550     auto begin = children.begin();
551     CHECK_NULL_RETURN(selectOverlayHolder_, begin);
552     auto callerNode = selectOverlayHolder_->GetOwner();
553     CHECK_NULL_RETURN(callerNode, begin);
554     RefPtr<UINode> prevNode = nullptr;
555     auto parent = callerNode->GetParent();
556     while (parent) {
557         if (parent == root) {
558             break;
559         }
560         prevNode = parent;
561         parent = parent->GetParent();
562     }
563     CHECK_NULL_RETURN(parent, begin);
564     CHECK_NULL_RETURN(prevNode, begin);
565     for (auto it = begin; it != children.end(); ++it) {
566         if (prevNode == *it) {
567             return ++it;
568         }
569     }
570     return begin;
571 }
572 
MountNodeToCaller(const RefPtr<FrameNode> & overlayNode,bool animation)573 void SelectContentOverlayManager::MountNodeToCaller(const RefPtr<FrameNode>& overlayNode, bool animation)
574 {
575     CHECK_NULL_VOID(selectOverlayHolder_);
576     auto ownerFrameNode = selectOverlayHolder_->GetOwner();
577     CHECK_NULL_VOID(ownerFrameNode);
578     TAG_LOGI(AceLogTag::ACE_SELECT_OVERLAY,
579         "Mount SelectOverlay node: %{public}s, id: %{public}d", ownerFrameNode->GetTag().c_str(),
580         ownerFrameNode->GetId());
581     ownerFrameNode->SetOverlayNode(overlayNode);
582     overlayNode->SetParent(AceType::WeakClaim(AceType::RawPtr(ownerFrameNode)));
583     overlayNode->SetActive(true);
584     auto overlayProperty = AceType::DynamicCast<LayoutProperty>(overlayNode->GetLayoutProperty());
585     CHECK_NULL_VOID(overlayProperty);
586     overlayProperty->SetIsOverlayNode(true);
587     overlayProperty->UpdateAlignment(Alignment::CENTER);
588     overlayProperty->UpdateMeasureType(MeasureType::MATCH_PARENT);
589     ownerFrameNode->MarkNeedSyncRenderTree();
590     ownerFrameNode->RebuildRenderContextTree();
591     overlayNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
592     if (!shareOverlayInfo_->isUsingMouse) {
593         auto node = DynamicCast<SelectOverlayNode>(overlayNode);
594         if (node) {
595             node->ShowSelectOverlay(animation);
596         }
597     }
598 }
599 
NotifySelectOverlayShow(bool isCreated)600 void SelectContentOverlayManager::NotifySelectOverlayShow(bool isCreated)
601 {
602     CHECK_NULL_VOID(selectOverlayHolder_);
603     auto callback = selectOverlayHolder_->GetCallback();
604     CHECK_NULL_VOID(callback);
605     callback->OnAfterSelectOverlayShow(isCreated);
606 }
607 
GetSelectOverlayRoot()608 const RefPtr<FrameNode> SelectContentOverlayManager::GetSelectOverlayRoot()
609 {
610     auto rootNode = rootNodeWeak_.Upgrade();
611     CHECK_NULL_RETURN(shareOverlayInfo_, rootNode);
612     auto container = Container::Current();
613     if (container && container->IsScenceBoardWindow()) {
614         auto root = FindWindowScene(shareOverlayInfo_->callerFrameNode.Upgrade());
615         rootNode = DynamicCast<FrameNode>(root);
616     } else if (rootNode && selectOverlayHolder_ && selectOverlayHolder_->IsEnableContainerModal()) {
617         auto containerModalRoot = GetContainerModalRoot();
618         if (containerModalRoot) {
619             rootNode = containerModalRoot;
620         }
621     }
622     return rootNode;
623 }
624 
625 /**
626  * @description: This function will be used in SceneBoard Thread only.
627  * if need to show the select-overlay component, it expects to receive the target component bound by
628  * the select-overlay component to find the windowScene component.
629  * if need to hide the select-overlay component, it expects to receive the the select-overlay component
630  * to return the parent component. And the parent component will be the windowScene component exactly.
631  */
FindWindowScene(RefPtr<FrameNode> targetNode)632 RefPtr<UINode> SelectContentOverlayManager::FindWindowScene(RefPtr<FrameNode> targetNode)
633 {
634     auto container = Container::Current();
635     if (!container || !container->IsScenceBoardWindow()) {
636         return rootNodeWeak_.Upgrade();
637     }
638     CHECK_NULL_RETURN(targetNode, nullptr);
639     auto parent = targetNode->GetParent();
640     while (parent && parent->GetTag() != V2::WINDOW_SCENE_ETS_TAG) {
641         parent = parent->GetParent();
642     }
643     CHECK_NULL_RETURN(parent, nullptr);
644     return parent;
645 }
646 
CloseInternal(int32_t id,bool animation,CloseReason reason)647 bool SelectContentOverlayManager::CloseInternal(int32_t id, bool animation, CloseReason reason)
648 {
649     CHECK_NULL_RETURN(selectOverlayHolder_, false);
650     CHECK_NULL_RETURN(selectOverlayHolder_->GetOwnerId() == id, false);
651     CHECK_NULL_RETURN(shareOverlayInfo_, false);
652     LOGI("SelectOverlay: Close selectoverlay by id %{public}d, reason %{public}d", id, reason);
653     auto callback = selectOverlayHolder_->GetCallback();
654     auto menuType = shareOverlayInfo_->menuInfo.menuType;
655     auto pattern = GetSelectHandlePattern(WeakClaim(this));
656     RefPtr<OverlayInfo> info = nullptr;
657     if (pattern) {
658         info = AceType::MakeRefPtr<OverlayInfo>();
659         info->isSingleHandle = shareOverlayInfo_->isSingleHandle;
660         info->isShowMenu = shareOverlayInfo_->menuInfo.menuIsShow;
661         info->isHiddenHandle = pattern->IsHiddenHandle();
662     }
663     auto selectOverlayNode = selectOverlayNode_.Upgrade();
664     auto menuNode = menuNode_.Upgrade();
665     auto handleNode = handleNode_.Upgrade();
666     if (animation && !shareOverlayInfo_->isUsingMouse) {
667         ClearAllStatus();
668         DestroySelectOverlayNodeWithAnimation(selectOverlayNode);
669         DestroySelectOverlayNodeWithAnimation(menuNode);
670         DestroySelectOverlayNodeWithAnimation(handleNode);
671     } else {
672         DestroySelectOverlayNode(selectOverlayNode);
673         DestroySelectOverlayNode(menuNode);
674         DestroySelectOverlayNode(handleNode);
675         ClearAllStatus();
676     }
677     if (callback) {
678         callback->OnCloseOverlay(menuType, reason, info);
679     }
680     return true;
681 }
682 
DestroySelectOverlayNodeWithAnimation(const RefPtr<FrameNode> & node)683 void SelectContentOverlayManager::DestroySelectOverlayNodeWithAnimation(const RefPtr<FrameNode>& node)
684 {
685     auto overlayNode = DynamicCast<SelectOverlayNode>(node);
686     CHECK_NULL_VOID(overlayNode);
687     overlayNode->HideSelectOverlay([weakOverlay = WeakClaim(AceType::RawPtr(node)), managerWeak = WeakClaim(this)]() {
688         auto manager = managerWeak.Upgrade();
689         CHECK_NULL_VOID(manager);
690         manager->DestroySelectOverlayNode(weakOverlay.Upgrade());
691     });
692 }
693 
DestroySelectOverlayNode(const RefPtr<FrameNode> & overlay)694 void SelectContentOverlayManager::DestroySelectOverlayNode(const RefPtr<FrameNode>& overlay)
695 {
696     CHECK_NULL_VOID(overlay);
697     auto parentNode = overlay->GetParent();
698     CHECK_NULL_VOID(parentNode);
699 
700     auto parentFrameNode = DynamicCast<FrameNode>(parentNode);
701     if (parentFrameNode) {
702         auto pattern = overlay->GetPattern<SelectOverlayPattern>();
703         if (pattern && pattern->GetMode() == SelectOverlayMode::HANDLE_ONLY) {
704             parentFrameNode->SetOverlayNode(nullptr);
705             overlay->SetParent(nullptr);
706         }
707     }
708     TAG_LOGI(AceLogTag::ACE_SELECT_OVERLAY,
709         "Remove node [%{public}s, %{public}d] from [%{public}s, %{public}d]", overlay->GetTag().c_str(),
710         overlay->GetId(), parentNode->GetTag().c_str(), parentNode->GetId());
711     parentNode->RemoveChild(overlay);
712     parentNode->MarkNeedSyncRenderTree();
713     parentNode->RebuildRenderContextTree();
714 }
715 
ClearAllStatus()716 void SelectContentOverlayManager::ClearAllStatus()
717 {
718     selectOverlayNode_.Reset();
719     handleNode_.Reset();
720     menuNode_.Reset();
721     shareOverlayInfo_.reset();
722     if (selectOverlayHolder_) {
723         selectOverlayHolder_->OnBind(nullptr);
724     }
725     selectOverlayHolder_.Reset();
726 }
727 
CloseCurrent(bool animation,CloseReason reason)728 bool SelectContentOverlayManager::CloseCurrent(bool animation, CloseReason reason)
729 {
730     CHECK_NULL_RETURN(selectOverlayHolder_, false);
731     CHECK_NULL_RETURN(selectOverlayNode_.Upgrade() || menuNode_.Upgrade() || handleNode_.Upgrade(), false);
732     return CloseInternal(selectOverlayHolder_->GetOwnerId(), animation, reason);
733 }
734 
CloseWithOverlayId(int32_t overlayId,CloseReason reason,bool animation)735 void SelectContentOverlayManager::CloseWithOverlayId(int32_t overlayId, CloseReason reason, bool animation)
736 {
737     CHECK_NULL_VOID(IsOpen());
738     // call from menu button.
739     auto hasOverlayId = (selectOverlayNode_.Upgrade() && overlayId == selectOverlayNode_.Upgrade()->GetId());
740     hasOverlayId = hasOverlayId || (menuNode_.Upgrade() && menuNode_.Upgrade()->GetId());
741     if (hasOverlayId) {
742         CloseInternal(selectOverlayHolder_->GetOwnerId(), animation, reason);
743     }
744 }
745 
Close(int32_t id,bool animation,CloseReason reason)746 void SelectContentOverlayManager::Close(int32_t id, bool animation, CloseReason reason)
747 {
748     CloseInternal(id, animation, reason);
749 }
750 
ShowOptionMenu()751 void SelectContentOverlayManager::ShowOptionMenu()
752 {
753     auto pattern = GetSelectMenuPattern(WeakClaim(this));
754     CHECK_NULL_VOID(pattern);
755     pattern->UpdateMenuIsShow(true);
756 }
757 
HideOptionMenu(bool noAnimation)758 void SelectContentOverlayManager::HideOptionMenu(bool noAnimation)
759 {
760     auto pattern = GetSelectMenuPattern(WeakClaim(this));
761     CHECK_NULL_VOID(pattern);
762     pattern->UpdateMenuIsShow(false, noAnimation);
763 }
764 
ToggleOptionMenu()765 void SelectContentOverlayManager::ToggleOptionMenu()
766 {
767     CHECK_NULL_VOID(shareOverlayInfo_);
768     auto pattern = GetSelectMenuPattern(WeakClaim(this));
769     CHECK_NULL_VOID(pattern);
770     pattern->UpdateMenuIsShow(!shareOverlayInfo_->menuInfo.menuIsShow);
771 }
772 
DisableMenu()773 void SelectContentOverlayManager::DisableMenu()
774 {
775     auto pattern = GetSelectMenuPattern(WeakClaim(this));
776     CHECK_NULL_VOID(pattern);
777     pattern->DisableMenu(true);
778 }
779 
EnableMenu()780 void SelectContentOverlayManager::EnableMenu()
781 {
782     auto pattern = GetSelectMenuPattern(WeakClaim(this));
783     CHECK_NULL_VOID(pattern);
784     pattern->DisableMenu(false);
785 }
786 
HideHandle()787 void SelectContentOverlayManager::HideHandle()
788 {
789     auto pattern = GetSelectHandlePattern(WeakClaim(this));
790     CHECK_NULL_VOID(pattern);
791     pattern->StartHiddenHandleTask(false);
792 }
793 
IsOpen()794 bool SelectContentOverlayManager::IsOpen()
795 {
796     if (!IsEnableHandleLevel()) {
797         auto overlayNode = selectOverlayNode_.Upgrade();
798         return overlayNode && overlayNode->GetParent();
799     }
800     auto hasHandleNode = handleNode_.Upgrade() && handleNode_.Upgrade()->GetParent();
801     auto hasMenuNode = menuNode_.Upgrade() && menuNode_.Upgrade()->GetParent();
802     return hasHandleNode || hasMenuNode;
803 }
804 
IsCreating()805 bool SelectContentOverlayManager::IsCreating()
806 {
807     if (!IsEnableHandleLevel()) {
808         auto overlayNode = selectOverlayNode_.Upgrade();
809         return overlayNode && !overlayNode->GetParent();
810     }
811     auto menuNode = menuNode_.Upgrade();
812     auto handleNode = handleNode_.Upgrade();
813     return (menuNode && !menuNode->GetParent()) || (handleNode && !handleNode->GetParent());
814 }
815 
IsMenuShow()816 bool SelectContentOverlayManager::IsMenuShow()
817 {
818     return IsOpen() && shareOverlayInfo_ && shareOverlayInfo_->menuInfo.menuIsShow;
819 }
820 
IsSingleHandle()821 bool SelectContentOverlayManager::IsSingleHandle()
822 {
823     return IsOpen() && shareOverlayInfo_ && shareOverlayInfo_->isSingleHandle;
824 }
825 
IsHandlesShow()826 bool SelectContentOverlayManager::IsHandlesShow()
827 {
828     return IsOpen() && shareOverlayInfo_ && !shareOverlayInfo_->isSingleHandle;
829 }
830 
IsHandleReverse()831 bool SelectContentOverlayManager::IsHandleReverse()
832 {
833     return IsOpen() && shareOverlayInfo_ && shareOverlayInfo_->handleReverse;
834 }
835 
RestartHiddenHandleTask(bool isDelay)836 void SelectContentOverlayManager::RestartHiddenHandleTask(bool isDelay)
837 {
838     auto pattern = GetSelectHandlePattern(WeakClaim(this));
839     CHECK_NULL_VOID(pattern);
840     pattern->RestartHiddenHandleTask(isDelay);
841 }
842 
CancelHiddenHandleTask()843 void SelectContentOverlayManager::CancelHiddenHandleTask()
844 {
845     auto pattern = GetSelectHandlePattern(WeakClaim(this));
846     CHECK_NULL_VOID(pattern);
847     pattern->CancelHiddenHandleTask();
848 }
849 
GetSelectOverlayNode()850 RefPtr<SelectOverlayNode> SelectContentOverlayManager::GetSelectOverlayNode()
851 {
852     auto overlayNode = IsEnableHandleLevel() ? menuNode_.Upgrade() : selectOverlayNode_.Upgrade();
853     return AceType::DynamicCast<SelectOverlayNode>(overlayNode);
854 }
855 
GetShowMenuType()856 OptionMenuType SelectContentOverlayManager::GetShowMenuType()
857 {
858     return IsOpen() && shareOverlayInfo_ ? shareOverlayInfo_->menuInfo.menuType : OptionMenuType::NO_MENU;
859 }
860 
HandleGlobalEvent(const TouchEvent & touchEvent,const NG::OffsetF & rootOffset)861 void SelectContentOverlayManager::HandleGlobalEvent(const TouchEvent& touchEvent, const NG::OffsetF& rootOffset)
862 {
863     NG::PointF point { touchEvent.x - rootOffset.GetX(), touchEvent.y - rootOffset.GetY() };
864     point = point - GetContainerModalOffset();
865     if (touchEvent.type == TouchType::DOWN) {
866         isIntercept_ = IsTouchInSelectOverlayArea(point);
867     }
868     if (!isIntercept_) {
869         HandleSelectionEvent(point, touchEvent);
870         if (selectOverlayHolder_ && selectOverlayHolder_->GetCallback() && selectOverlayHolder_->GetOwner()) {
871             auto localPoint = point;
872             ConvertPointRelativeToNode(selectOverlayHolder_->GetOwner(), localPoint);
873             selectOverlayHolder_->GetCallback()->OnHandleGlobalEvent(point, localPoint, touchEvent);
874         }
875     }
876     if (touchEvent.type == TouchType::UP) {
877         isIntercept_ = false;
878     }
879 }
880 
IsTouchInSelectOverlayArea(const PointF & point)881 bool SelectContentOverlayManager::IsTouchInSelectOverlayArea(const PointF& point)
882 {
883     if (!IsEnableHandleLevel()) {
884         return IsTouchInNormalSelectOverlayArea(point);
885     }
886     return IsTouchInHandleLevelOverlayArea(point);
887 }
888 
IsTouchInNormalSelectOverlayArea(const PointF & point)889 bool SelectContentOverlayManager::IsTouchInNormalSelectOverlayArea(const PointF& point)
890 {
891     auto current = selectOverlayNode_.Upgrade();
892     CHECK_NULL_RETURN(current, false);
893     auto selectOverlayNode = DynamicCast<SelectOverlayNode>(current);
894     if (selectOverlayNode) {
895         return selectOverlayNode->IsInSelectedOrSelectOverlayArea(point);
896     }
897     // get the menu rect not the out wrapper
898     auto modalOffset = GetContainerModalOffset();
899     const auto& children = current->GetChildren();
900     for (const auto& it : children) {
901         auto child = DynamicCast<FrameNode>(it);
902         if (child == nullptr || !child->GetGeometryNode()) {
903             continue;
904         }
905         auto frameRect =
906             RectF(child->GetTransformRelativeOffset() - modalOffset, child->GetGeometryNode()->GetFrameSize());
907         if (frameRect.IsInRegion(point)) {
908             return true;
909         }
910     }
911     return false;
912 }
913 
IsTouchInHandleLevelOverlayArea(const PointF & point)914 bool SelectContentOverlayManager::IsTouchInHandleLevelOverlayArea(const PointF& point)
915 {
916     auto selectOverlayNode = DynamicCast<SelectOverlayNode>(menuNode_.Upgrade());
917     if (selectOverlayNode && selectOverlayNode->IsInSelectedOrSelectOverlayArea(point)) {
918         return true;
919     }
920     selectOverlayNode = DynamicCast<SelectOverlayNode>(handleNode_.Upgrade());
921     CHECK_NULL_RETURN(selectOverlayNode, false);
922     auto localPoint = point;
923     ConvertPointRelativeToNode(selectOverlayNode->GetAncestorNodeOfFrame(true), localPoint);
924     return selectOverlayNode->IsInSelectedOrSelectOverlayArea(localPoint);
925 }
926 
HandleSelectionEvent(const PointF & point,const TouchEvent & rawTouchEvent)927 void SelectContentOverlayManager::HandleSelectionEvent(const PointF& point, const TouchEvent& rawTouchEvent)
928 {
929     CHECK_NULL_VOID(holdSelectionInfo_);
930     CHECK_NULL_VOID(holdSelectionInfo_->checkTouchInArea);
931     CHECK_NULL_VOID(holdSelectionInfo_->resetSelectionCallback);
932     if (holdSelectionInfo_->IsAcceptEvent(rawTouchEvent.sourceType, rawTouchEvent.type) &&
933         !holdSelectionInfo_->checkTouchInArea(point) && !IsOpen()) {
934         ResetSelectionRect();
935     }
936 }
937 
ResetSelectionRect()938 void SelectContentOverlayManager::ResetSelectionRect()
939 {
940     CHECK_NULL_VOID(holdSelectionInfo_);
941     if (holdSelectionInfo_->resetSelectionCallback) {
942         holdSelectionInfo_->resetSelectionCallback();
943     }
944     selectionHoldId_ = -1;
945     holdSelectionInfo_.reset();
946 }
947 
SetHoldSelectionCallback(int32_t id,const HoldSelectionInfo & selectionInfo)948 void SelectContentOverlayManager::SetHoldSelectionCallback(int32_t id, const HoldSelectionInfo& selectionInfo)
949 {
950     if (id == selectionHoldId_) {
951         return;
952     }
953     if (holdSelectionInfo_ && id != selectionHoldId_ && holdSelectionInfo_->resetSelectionCallback) {
954         holdSelectionInfo_->resetSelectionCallback();
955     }
956     selectionHoldId_ = id;
957     holdSelectionInfo_ = selectionInfo;
958 }
959 
RemoveHoldSelectionCallback(int32_t id)960 void SelectContentOverlayManager::RemoveHoldSelectionCallback(int32_t id)
961 {
962     CHECK_NULL_VOID(holdSelectionInfo_);
963     if (selectionHoldId_ == id) {
964         selectionHoldId_ = -1;
965         holdSelectionInfo_.reset();
966     }
967 }
968 
IsEnableHandleLevel()969 bool SelectContentOverlayManager::IsEnableHandleLevel()
970 {
971     return shareOverlayInfo_ && shareOverlayInfo_->enableHandleLevel;
972 }
973 
GetMenuPattern()974 RefPtr<Pattern> SelectContentOverlayManager::GetMenuPattern()
975 {
976     return IsEnableHandleLevel() ? GetSelectOverlayPattern(menuNode_)
977                                       : GetSelectOverlayPattern(selectOverlayNode_);
978 }
979 
GetHandlePattern()980 RefPtr<Pattern> SelectContentOverlayManager::GetHandlePattern()
981 {
982     return IsEnableHandleLevel() ? GetSelectOverlayPattern(handleNode_)
983                                       : GetSelectOverlayPattern(selectOverlayNode_);
984 }
985 
GetHandleOverlayNode()986 RefPtr<FrameNode> SelectContentOverlayManager::GetHandleOverlayNode()
987 {
988     return handleNode_.Upgrade();
989 }
990 
NotifyUpdateToolBar(bool itemChanged)991 void SelectContentOverlayManager::NotifyUpdateToolBar(bool itemChanged)
992 {
993     auto menuNode = DynamicCast<SelectOverlayNode>(menuNode_.Upgrade());
994     CHECK_NULL_VOID(menuNode);
995     menuNode->UpdateToolBar(itemChanged);
996 }
997 
GetHandleDiameter()998 float SelectContentOverlayManager::GetHandleDiameter()
999 {
1000     return SelectOverlayPattern::GetHandleDiameter();
1001 }
1002 
ConvertPointRelativeToNode(const RefPtr<FrameNode> & node,PointF & point)1003 void SelectContentOverlayManager::ConvertPointRelativeToNode(const RefPtr<FrameNode>& node, PointF& point)
1004 {
1005     CHECK_NULL_VOID(node);
1006     auto rootNode = GetSelectOverlayRoot();
1007     CHECK_NULL_VOID(rootNode);
1008     std::stack<RefPtr<FrameNode>> nodeStack;
1009     auto parent = node;
1010     while (parent && parent != rootNode) {
1011         nodeStack.push(parent);
1012         parent = parent->GetAncestorNodeOfFrame(true);
1013     }
1014     CHECK_NULL_VOID(!nodeStack.empty());
1015     PointF temp(point.GetX(), point.GetY());
1016     while (!nodeStack.empty()) {
1017         parent = nodeStack.top();
1018         CHECK_NULL_VOID(parent);
1019         nodeStack.pop();
1020         auto renderContext = parent->GetRenderContext();
1021         CHECK_NULL_VOID(renderContext);
1022         renderContext->GetPointWithRevert(temp);
1023         auto rectOffset = renderContext->GetPaintRectWithoutTransform().GetOffset();
1024         temp = temp - rectOffset;
1025     }
1026     point.SetX(temp.GetX());
1027     point.SetY(temp.GetY());
1028 }
1029 
IsTouchAtHandle(const PointF & localPoint,const PointF & globalPoint)1030 bool SelectContentOverlayManager::IsTouchAtHandle(const PointF& localPoint, const PointF& globalPoint)
1031 {
1032     auto handleNode = handleNode_.Upgrade();
1033     CHECK_NULL_RETURN(handleNode, false);
1034     auto selectOverlayNode = DynamicCast<SelectOverlayNode>(handleNode);
1035     CHECK_NULL_RETURN(selectOverlayNode, false);
1036     CHECK_NULL_RETURN(selectOverlayHolder_, false);
1037     if (selectOverlayNode->GetParent() == selectOverlayHolder_->GetOwner()) {
1038         return selectOverlayNode->IsInSelectedOrSelectOverlayArea(localPoint);
1039     }
1040     return selectOverlayNode->IsInSelectedOrSelectOverlayArea(globalPoint);
1041 }
1042 
UpdateViewPort()1043 void SelectContentOverlayManager::UpdateViewPort()
1044 {
1045     auto menuNode = menuNode_.Upgrade();
1046     CHECK_NULL_VOID(menuNode);
1047     CHECK_NULL_VOID(selectOverlayHolder_);
1048     CHECK_NULL_VOID(shareOverlayInfo_);
1049     shareOverlayInfo_->ancestorViewPort = selectOverlayHolder_->GetAncestorNodeViewPort();
1050     menuNode->MarkDirtyNode(PROPERTY_UPDATE_LAYOUT);
1051 }
1052 
SetHandleCircleIsShow(bool isFirst,bool isShow)1053 void SelectContentOverlayManager::SetHandleCircleIsShow(bool isFirst, bool isShow)
1054 {
1055     auto pattern = GetSelectHandlePattern(WeakClaim(this));
1056     CHECK_NULL_VOID(pattern);
1057     pattern->SetHandleCircleIsShow(isFirst, isShow);
1058 }
1059 
SetIsHandleLineShow(bool isShow)1060 void SelectContentOverlayManager::SetIsHandleLineShow(bool isShow)
1061 {
1062     auto pattern = GetSelectHandlePattern(WeakClaim(this));
1063     CHECK_NULL_VOID(pattern);
1064     pattern->SetIsHandleLineShow(isShow);
1065 }
1066 
MarkHandleDirtyNode(PropertyChangeFlag flag)1067 void SelectContentOverlayManager::MarkHandleDirtyNode(PropertyChangeFlag flag)
1068 {
1069     auto pattern = GetSelectHandlePattern(WeakClaim(this));
1070     CHECK_NULL_VOID(pattern);
1071     auto host = pattern->GetHost();
1072     CHECK_NULL_VOID(host);
1073     host->MarkDirtyNode(flag);
1074 }
1075 
UpdateSelectOverlayInfoInternal(SelectOverlayInfo & overlayInfo)1076 void SelectContentOverlayManager::UpdateSelectOverlayInfoInternal(SelectOverlayInfo& overlayInfo)
1077 {
1078     if (!selectOverlayHolder_ || !selectOverlayHolder_->IsEnableContainerModal()) {
1079         return;
1080     }
1081     if (overlayInfo.ancestorViewPort) {
1082         ConvertRectRelativeToParent(*overlayInfo.ancestorViewPort);
1083     }
1084     ConvertRectRelativeToParent(overlayInfo.selectArea);
1085     ConvertHandleRelativeToParent(overlayInfo.firstHandle);
1086     ConvertHandleRelativeToParent(overlayInfo.secondHandle);
1087     if (overlayInfo.isUsingMouse) {
1088         overlayInfo.rightClickOffset -= GetContainerModalOffset();
1089     }
1090 }
1091 
GetContainerModalOffset()1092 OffsetF SelectContentOverlayManager::GetContainerModalOffset()
1093 {
1094     CHECK_NULL_RETURN(selectOverlayHolder_, OffsetF());
1095     if (!selectOverlayHolder_->IsEnableContainerModal()) {
1096         return OffsetF();
1097     }
1098     auto rootNode = GetContainerModalRoot();
1099     CHECK_NULL_RETURN(rootNode, OffsetF());
1100     return rootNode->GetTransformRelativeOffset();
1101 }
1102 
ConvertRectRelativeToParent(RectF & rect)1103 void SelectContentOverlayManager::ConvertRectRelativeToParent(RectF& rect)
1104 {
1105     rect.SetOffset(rect.GetOffset() - GetContainerModalOffset());
1106 }
1107 
ConvertHandleRelativeToParent(SelectHandleInfo & info)1108 void SelectContentOverlayManager::ConvertHandleRelativeToParent(SelectHandleInfo& info)
1109 {
1110     auto modalOffset = GetContainerModalOffset();
1111     if (modalOffset.NonOffset()) {
1112         return;
1113     }
1114     ConvertRectRelativeToParent(info.paintRect);
1115     if (info.isPaintHandleWithPoints) {
1116         info.paintInfo = info.paintInfo - modalOffset;
1117     }
1118     if (info.paintInfoConverter) {
1119         info.paintInfoConverter = [weak = WeakClaim(this), converter = std::move(info.paintInfoConverter)](
1120                                       const SelectHandlePaintInfo& paintInfo) {
1121             auto manager = weak.Upgrade();
1122             CHECK_NULL_RETURN(manager, RectF());
1123             auto tmpPaintInfo = paintInfo;
1124             tmpPaintInfo = tmpPaintInfo + manager->GetContainerModalOffset();
1125             return converter(tmpPaintInfo);
1126         };
1127     }
1128 }
1129 
RevertRectRelativeToRoot(RectF & handle)1130 void SelectContentOverlayManager::RevertRectRelativeToRoot(RectF& handle)
1131 {
1132     CHECK_NULL_VOID(shareOverlayInfo_);
1133     if (shareOverlayInfo_->handleLevelMode == HandleLevelMode::EMBED) {
1134         return;
1135     }
1136     handle.SetOffset(handle.GetOffset() + GetContainerModalOffset());
1137 }
1138 
GetContainerModalRoot()1139 RefPtr<FrameNode> SelectContentOverlayManager::GetContainerModalRoot()
1140 {
1141     auto rootNode = rootNodeWeak_.Upgrade();
1142     if (rootNode) {
1143         auto context = rootNode->GetContextRefPtr();
1144         CHECK_NULL_RETURN(context, nullptr);
1145         auto windowModal = context->GetWindowModal();
1146         if (windowModal == WindowModal::CONTAINER_MODAL) {
1147             auto overlayManager = context->GetOverlayManager();
1148             CHECK_NULL_RETURN(overlayManager, nullptr);
1149             auto overlayRoot = overlayManager->GetRootNode();
1150             CHECK_NULL_RETURN(overlayRoot.Upgrade(), nullptr);
1151             return DynamicCast<FrameNode>(overlayRoot.Upgrade());
1152         }
1153     }
1154     return nullptr;
1155 }
1156 
IsStopBackPress() const1157 bool SelectContentOverlayManager::IsStopBackPress() const
1158 {
1159     CHECK_NULL_RETURN(selectOverlayHolder_, true);
1160     return selectOverlayHolder_->IsStopBackPress();
1161 }
1162 } // namespace OHOS::Ace::NG
1163