• 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 "base/memory/ace_type.h"
19 #include "base/memory/referenced.h"
20 #include "base/utils/utils.h"
21 #include "base/subwindow/subwindow_manager.h"
22 #include "core/common/container.h"
23 #include "core/components_ng/pattern/select_content_overlay/select_content_overlay_pattern.h"
24 #include "core/components_ng/pattern/select_overlay/select_overlay_node.h"
25 #include "core/components_ng/pattern/select_overlay/select_overlay_property.h"
26 #include "core/event/touch_event.h"
27 #include "core/pipeline_ng/pipeline_context.h"
28 
29 namespace OHOS::Ace::NG {
30 namespace {
GetSelectOverlayPattern(const WeakPtr<FrameNode> & overlayNode)31 RefPtr<SelectContentOverlayPattern> GetSelectOverlayPattern(const WeakPtr<FrameNode>& overlayNode)
32 {
33     auto node = overlayNode.Upgrade();
34     CHECK_NULL_RETURN(node, nullptr);
35     auto selectOverlayNode = AceType::DynamicCast<SelectOverlayNode>(node);
36     CHECK_NULL_RETURN(selectOverlayNode, nullptr);
37     return selectOverlayNode->GetPattern<SelectContentOverlayPattern>();
38 }
39 
GetSelectMenuPattern(const WeakPtr<SelectContentOverlayManager> & manager)40 RefPtr<SelectContentOverlayPattern> GetSelectMenuPattern(const WeakPtr<SelectContentOverlayManager>& manager)
41 {
42     auto overlayManager = manager.Upgrade();
43     CHECK_NULL_RETURN(overlayManager, nullptr);
44     auto pattern = overlayManager->GetMenuPattern();
45     return AceType::DynamicCast<SelectContentOverlayPattern>(pattern);
46 }
47 
GetSelectHandlePattern(const WeakPtr<SelectContentOverlayManager> & manager)48 RefPtr<SelectContentOverlayPattern> GetSelectHandlePattern(const WeakPtr<SelectContentOverlayManager>& manager)
49 {
50     auto overlayManager = manager.Upgrade();
51     CHECK_NULL_RETURN(overlayManager, nullptr);
52     auto pattern = overlayManager->GetHandlePattern();
53     return AceType::DynamicCast<SelectContentOverlayPattern>(pattern);
54 }
55 
FindAccessibleFocusNode(const RefPtr<UINode> & node)56 RefPtr<UINode> FindAccessibleFocusNode(const RefPtr<UINode>& node)
57 {
58     CHECK_NULL_RETURN(node, nullptr);
59     bool isPasteOption = SelectContentOverlayManager::IsPasteOption(node);
60     auto child = node->GetFirstChild();
61     if (isPasteOption && child) {
62         return child->GetFirstChild();
63     }
64     if (node->GetTag() == V2::MENU_ITEM_ETS_TAG || node->GetTag() == "SelectMenuButton" ||
65         node->GetTag() == V2::PASTE_BUTTON_ETS_TAG || node->GetTag() == V2::OPTION_ETS_TAG ||
66         node->GetTag() == V2::BUTTON_ETS_TAG) {
67         return node;
68     }
69     CHECK_NULL_RETURN(child, nullptr);
70     return FindAccessibleFocusNode(child);
71 }
72 } // namespace
73 
GetOverlayManager(const RefPtr<SelectOverlayHolder> & holder)74 const RefPtr<SelectContentOverlayManager> SelectContentOverlayManager::GetOverlayManager(
75     const RefPtr<SelectOverlayHolder>& holder)
76 {
77     auto pipeline = PipelineContext::GetCurrentContextSafely();
78     CHECK_NULL_RETURN(pipeline, nullptr);
79     auto overlayManager = pipeline->GetSelectOverlayManager();
80     CHECK_NULL_RETURN(overlayManager, nullptr);
81     auto contentManager = overlayManager->GetSelectContentOverlayManager();
82     if (!holder) {
83         return contentManager;
84     }
85     if (!contentManager->HasHolder(holder->GetOwnerId())) {
86         contentManager->SetHolder(holder);
87     }
88     return contentManager;
89 }
90 
SetHolder(const RefPtr<SelectOverlayHolder> & holder)91 void SelectContentOverlayManager::SetHolder(const RefPtr<SelectOverlayHolder>& holder)
92 {
93     CHECK_NULL_VOID(holder);
94     if (!selectOverlayHolder_) {
95         SetHolderInternal(holder);
96         return;
97     }
98     auto prevOwnerId = selectOverlayHolder_->GetOwnerId();
99     auto ownerId = holder->GetOwnerId();
100     if (selectionHoldId_ > 0 && ownerId != selectionHoldId_) {
101         ResetSelectionRect();
102         if (legacyManagerCallbacks_.selectionResetCallback) {
103             legacyManagerCallbacks_.selectionResetCallback();
104         }
105     }
106     if (prevOwnerId == ownerId) {
107         return;
108     }
109     CloseInternal(prevOwnerId, false, CloseReason::CLOSE_REASON_HOLD_BY_OTHER);
110     SetHolderInternal(holder);
111 }
112 
SetHolderInternal(const RefPtr<SelectOverlayHolder> & holder)113 void SelectContentOverlayManager::SetHolderInternal(const RefPtr<SelectOverlayHolder>& holder)
114 {
115     // unbind old holder
116     if (selectOverlayHolder_) {
117         selectOverlayHolder_->OnBind(nullptr);
118     }
119     selectOverlayHolder_ = holder;
120     // bind new holder
121     if (selectOverlayHolder_) {
122         selectOverlayHolder_->OnBind(WeakClaim(this));
123     }
124 }
HasHolder(int32_t id)125 bool SelectContentOverlayManager::HasHolder(int32_t id)
126 {
127     CHECK_NULL_RETURN(selectOverlayHolder_, false);
128     return selectOverlayHolder_->GetOwnerId() == id;
129 }
130 
FocusFirstFocusableChildInMenu()131 void SelectContentOverlayManager::FocusFirstFocusableChildInMenu()
132 {
133     auto menuNode = menuNode_.Upgrade();
134     CHECK_NULL_VOID(menuNode);
135     auto context = menuNode->GetContext();
136     CHECK_NULL_VOID(context);
137     context->AddAfterLayoutTask([weakNode = menuNode_, weakManager = WeakClaim(this)]() {
138         auto menuNode = weakNode.Upgrade();
139         CHECK_NULL_VOID(menuNode);
140         auto manager = weakManager.Upgrade();
141         CHECK_NULL_VOID(manager);
142         if (!manager->IsMenuShow()) {
143             return;
144         }
145         auto firstChild = menuNode->GetFirstChild();
146         CHECK_NULL_VOID(firstChild);
147         auto focusableNode = FindAccessibleFocusNode(firstChild);
148         CHECK_NULL_VOID(focusableNode);
149         auto frameFocusableNode = AceType::DynamicCast<FrameNode>(focusableNode);
150         CHECK_NULL_VOID(frameFocusableNode);
151         frameFocusableNode->OnAccessibilityEvent(AccessibilityEventType::REQUEST_FOCUS);
152     });
153 }
154 
NotifyAccessibilityOwner()155 void SelectContentOverlayManager::NotifyAccessibilityOwner()
156 {
157     auto menuNode = menuNode_.Upgrade();
158     CHECK_NULL_VOID(menuNode);
159     auto context = menuNode->GetContext();
160     CHECK_NULL_VOID(context);
161     CHECK_NULL_VOID(selectOverlayHolder_);
162     auto owner = selectOverlayHolder_->GetOwner();
163     CHECK_NULL_VOID(owner);
164     context->AddAfterLayoutTask([weakNode = WeakClaim(RawPtr(owner)), weakManager = WeakClaim(this)]() {
165         auto owner = weakNode.Upgrade();
166         CHECK_NULL_VOID(owner);
167         owner->OnAccessibilityEvent(AccessibilityEventType::REQUEST_FOCUS);
168     });
169 }
170 
Show(bool animation,int32_t requestCode)171 void SelectContentOverlayManager::Show(bool animation, int32_t requestCode)
172 {
173     CHECK_NULL_VOID(selectOverlayHolder_);
174     auto info = BuildSelectOverlayInfo(requestCode);
175     if (!info.menuInfo.menuIsShow && info.isUsingMouse) {
176         return;
177     }
178     if (legacyManagerCallbacks_.closeCallback) {
179         legacyManagerCallbacks_.closeCallback(false, true);
180     }
181     info.enableHandleLevel = info.enableHandleLevel && !info.isUsingMouse;
182     if (IsOpen()) {
183         if (info.recreateOverlay || info.menuInfo.menuType != shareOverlayInfo_->menuInfo.menuType) {
184             auto holder = selectOverlayHolder_;
185             CloseInternal(selectOverlayHolder_->GetOwnerId(), false, CloseReason::CLOSE_REASON_BY_RECREATE);
186             SetHolder(holder);
187             CreateSelectOverlay(info, animation);
188             FocusFirstFocusableChildInMenu();
189             return;
190         }
191         UpdateExistOverlay(info, animation, requestCode);
192     } else {
193         CreateSelectOverlay(info, animation);
194     }
195     FocusFirstFocusableChildInMenu();
196 }
197 
BuildSelectOverlayInfo(int32_t requestCode)198 SelectOverlayInfo SelectContentOverlayManager::BuildSelectOverlayInfo(int32_t requestCode)
199 {
200     SelectOverlayInfo overlayInfo;
201     UpdateStatusInfos(overlayInfo);
202     overlayInfo.menuCallback.onCopy = MakeMenuCallback(OptionMenuActionId::COPY, overlayInfo);
203     overlayInfo.menuCallback.onPaste = MakeMenuCallback(OptionMenuActionId::PASTE, overlayInfo);
204     overlayInfo.menuCallback.onCut = MakeMenuCallback(OptionMenuActionId::CUT, overlayInfo);
205     overlayInfo.menuCallback.onSelectAll = MakeMenuCallback(OptionMenuActionId::SELECT_ALL, overlayInfo);
206     overlayInfo.menuCallback.onTranslate = MakeMenuCallback(OptionMenuActionId::TRANSLATE, overlayInfo);
207     overlayInfo.menuCallback.onSearch = MakeMenuCallback(OptionMenuActionId::SEARCH, overlayInfo);
208     overlayInfo.menuCallback.onShare = MakeMenuCallback(OptionMenuActionId::SHARE, overlayInfo);
209     overlayInfo.menuCallback.onCameraInput = MakeMenuCallback(OptionMenuActionId::CAMERA_INPUT, overlayInfo);
210     overlayInfo.menuCallback.onAIWrite = MakeMenuCallback(OptionMenuActionId::AI_WRITE, overlayInfo);
211     overlayInfo.menuCallback.onAppear = MakeMenuCallback(OptionMenuActionId::APPEAR, overlayInfo);
212     overlayInfo.menuCallback.onDisappear = MakeMenuCallback(OptionMenuActionId::DISAPPEAR, overlayInfo);
213     overlayInfo.menuCallback.onAIMenuOption =
214         MakeMenuCallbackWithInfo(OptionMenuActionId::AI_MENU_OPTION, overlayInfo);
215     overlayInfo.menuCallback.onAskCelia = MakeMenuCallback(OptionMenuActionId::ASK_CELIA, overlayInfo);
216     overlayInfo.isUseOverlayNG = true;
217     RegisterTouchCallback(overlayInfo);
218     RegisterHandleCallback(overlayInfo);
219     selectOverlayHolder_->OnUpdateSelectOverlayInfo(overlayInfo, requestCode);
220     UpdateSelectOverlayInfoInternal(overlayInfo);
221     TAG_LOGI(AceLogTag::ACE_SELECT_OVERLAY, "Build selectoverlay with menu info: %{public}s, requested by %{public}s",
222         overlayInfo.menuInfo.ToString().c_str(), GetOwnerDebugInfo().c_str());
223     return overlayInfo;
224 }
225 
UpdateStatusInfos(SelectOverlayInfo & overlayInfo)226 void SelectContentOverlayManager::UpdateStatusInfos(SelectOverlayInfo& overlayInfo)
227 {
228     auto firstHandle = selectOverlayHolder_->GetFirstHandleInfo();
229     auto secondHandle = selectOverlayHolder_->GetSecondHandleInfo();
230     if (firstHandle.has_value()) {
231         overlayInfo.firstHandle = firstHandle.value();
232     } else {
233         overlayInfo.firstHandle.isShow = false;
234     }
235     if (secondHandle.has_value()) {
236         overlayInfo.secondHandle = secondHandle.value();
237     } else {
238         overlayInfo.secondHandle.isShow = false;
239     }
240     SelectMenuInfo menuInfo;
241     selectOverlayHolder_->OnUpdateMenuInfo(menuInfo, DIRTY_ALL_MENU_ITEM);
242     overlayInfo.menuInfo = menuInfo;
243     overlayInfo.callerFrameNode = selectOverlayHolder_->GetOwner();
244     overlayInfo.selectText = selectOverlayHolder_->GetSelectedText();
245     overlayInfo.selectArea = selectOverlayHolder_->GetSelectArea();
246 }
247 
RegisterHandleCallback(SelectOverlayInfo & info)248 void SelectContentOverlayManager::RegisterHandleCallback(SelectOverlayInfo& info)
249 {
250     CHECK_NULL_VOID(selectOverlayHolder_);
251     auto callback = selectOverlayHolder_->GetCallback();
252     CHECK_NULL_VOID(callback);
253     if (!callback->IsRegisterHandleCallback()) {
254         return;
255     }
256     std::string ownerInfo = GetOwnerDebugInfo();
257     info.onHandleMoveStart = [weakCallback = WeakClaim(AceType::RawPtr(callback)), ownerInfo](
258                                  const GestureEvent& event, bool isFirst) {
259         auto overlayCallback = weakCallback.Upgrade();
260         CHECK_NULL_VOID(overlayCallback);
261         TAG_LOGI(
262             AceLogTag::ACE_SELECT_OVERLAY, "Start move %{public}d handle - %{public}s", isFirst, ownerInfo.c_str());
263         overlayCallback->OnHandleMoveStart(event, isFirst);
264     };
265     info.onHandleMove = [weakCallback = WeakClaim(AceType::RawPtr(callback)), weakManager = WeakClaim(this)](
266                             const RectF& rect, bool isFirst) {
267         auto overlayCallback = weakCallback.Upgrade();
268         CHECK_NULL_VOID(overlayCallback);
269         auto handle = rect;
270         if (weakManager.Upgrade()) {
271             weakManager.Upgrade()->RevertRectRelativeToRoot(handle);
272         }
273         overlayCallback->OnHandleMove(handle, isFirst);
274     };
275     info.onHandleMoveDone = [weakCallback = WeakClaim(AceType::RawPtr(callback)), weakManager = WeakClaim(this),
276                                 ownerInfo](const RectF& rect, bool isFirst) {
277         auto overlayCallback = weakCallback.Upgrade();
278         CHECK_NULL_VOID(overlayCallback);
279         auto handle = rect;
280         if (weakManager.Upgrade()) {
281             weakManager.Upgrade()->RevertRectRelativeToRoot(handle);
282         }
283         TAG_LOGI(AceLogTag::ACE_SELECT_OVERLAY, "Stop move %{public}d handle %{public}s", isFirst, ownerInfo.c_str());
284         overlayCallback->OnHandleMoveDone(rect, isFirst);
285     };
286     info.onHandleReverse = [weakCallback = WeakClaim(AceType::RawPtr(callback))](bool isReverse) {
287         auto overlayCallback = weakCallback.Upgrade();
288         CHECK_NULL_VOID(overlayCallback);
289         overlayCallback->OnHandleReverse(isReverse);
290     };
291     info.onHandleIsHidden = [weakCallback = WeakClaim(AceType::RawPtr(callback))]() {
292         auto overlayCallback = weakCallback.Upgrade();
293         CHECK_NULL_VOID(overlayCallback);
294         overlayCallback->OnHandleIsHidden();
295     };
296 }
297 
RegisterTouchCallback(SelectOverlayInfo & info)298 void SelectContentOverlayManager::RegisterTouchCallback(SelectOverlayInfo& info)
299 {
300     CHECK_NULL_VOID(selectOverlayHolder_);
301     auto callback = selectOverlayHolder_->GetCallback();
302     CHECK_NULL_VOID(callback);
303     if (!callback->IsRegisterTouchCallback()) {
304         return;
305     }
306     info.onTouchDown = [weakCallback = WeakClaim(AceType::RawPtr(callback))](const TouchEventInfo& event) {
307         auto callback = weakCallback.Upgrade();
308         CHECK_NULL_VOID(callback);
309         callback->OnOverlayTouchDown(event);
310     };
311     info.onTouchUp = [weakCallback = WeakClaim(AceType::RawPtr(callback))](const TouchEventInfo& event) {
312         auto callback = weakCallback.Upgrade();
313         CHECK_NULL_VOID(callback);
314         callback->OnOverlayTouchUp(event);
315     };
316     info.onTouchMove = [weakCallback = WeakClaim(AceType::RawPtr(callback))](const TouchEventInfo& event) {
317         auto callback = weakCallback.Upgrade();
318         CHECK_NULL_VOID(callback);
319         callback->OnOverlayTouchMove(event);
320     };
321     info.onClick = [weakCallback = WeakClaim(AceType::RawPtr(callback))](const GestureEvent& event, bool isClickCaret) {
322         auto callback = weakCallback.Upgrade();
323         CHECK_NULL_VOID(callback);
324         callback->OnOverlayClick(event, isClickCaret);
325     };
326     info.onMouseEvent = [weakCallback = WeakClaim(AceType::RawPtr(callback))](const MouseInfo& event) {
327         auto callback = weakCallback.Upgrade();
328         CHECK_NULL_VOID(callback);
329         callback->OnHandleMouseEvent(event);
330     };
331 }
332 
MakeMenuCallback(OptionMenuActionId id,const SelectOverlayInfo & info)333 std::function<void()> SelectContentOverlayManager::MakeMenuCallback(
334     OptionMenuActionId id, const SelectOverlayInfo& info)
335 {
336     auto callback = selectOverlayHolder_->GetCallback();
337     CHECK_NULL_RETURN(callback, nullptr);
338     return [actionId = id, weakCallback = WeakClaim(AceType::RawPtr(callback)), menuType = info.menuInfo.menuType,
339                logInfo = GetOwnerDebugInfo()]() {
340         auto callback = weakCallback.Upgrade();
341         CHECK_NULL_VOID(callback);
342         TAG_LOGI(AceLogTag::ACE_SELECT_OVERLAY,
343             "OnMenuItemAction called, menu id %{public}d, menu type %{public}d, consumer %{public}s", actionId,
344             menuType, logInfo.c_str());
345         callback->OnMenuItemAction(actionId, menuType);
346     };
347 }
348 
349 // return callback funtion with label information as input
MakeMenuCallbackWithInfo(OptionMenuActionId id,const SelectOverlayInfo & info)350 std::function<void(std::string)> SelectContentOverlayManager::MakeMenuCallbackWithInfo(
351     OptionMenuActionId id, const SelectOverlayInfo& info)
352 {
353     auto callback = selectOverlayHolder_->GetCallback();
354     CHECK_NULL_RETURN(callback, nullptr);
355     return [actionId = id, weakCallback = WeakClaim(AceType::RawPtr(callback)),
356             menuType = info.menuInfo.menuType, logInfo = GetOwnerDebugInfo()](const std::string& labelInfo = "") {
357         auto callback = weakCallback.Upgrade();
358         CHECK_NULL_VOID(callback);
359         TAG_LOGI(AceLogTag::ACE_SELECT_OVERLAY,
360             "MakeMenuCallbackWithInfo called, menu id %{public}d, menu type %{public}d, consumer %{public}s", actionId,
361             menuType, logInfo.c_str());
362         callback->OnMenuItemAction(actionId, menuType, labelInfo);
363     };
364 }
365 
UpdateExistOverlay(const SelectOverlayInfo & info,bool animation,int32_t requestCode)366 void SelectContentOverlayManager::UpdateExistOverlay(const SelectOverlayInfo& info, bool animation, int32_t requestCode)
367 {
368     TAG_LOGI(AceLogTag::ACE_SELECT_OVERLAY, "UpdateExistOverlay called by %{public}s", GetOwnerDebugInfo().c_str());
369     // update menu node
370     auto menuPattern = GetSelectMenuPattern(WeakClaim(this));
371     if (menuPattern) {
372         if (!info.isSingleHandle) {
373             menuPattern->UpdateSelectArea(info.selectArea);
374             menuPattern->SetSelectInfo(info.selectText);
375         }
376         menuPattern->UpdateMenuInfo(info.menuInfo);
377         menuPattern->UpdateViewPort(info.ancestorViewPort);
378     }
379     // update handle node
380     auto handlePattern = GetSelectHandlePattern(WeakClaim(this));
381     if (handlePattern) {
382         handlePattern->UpdateIsSingleHandle(info.isSingleHandle);
383         handlePattern->UpdateIsShowHandleLine(info.isHandleLineShow);
384         handlePattern->UpdateFirstAndSecondHandleInfo(info.firstHandle, info.secondHandle);
385         TAG_LOGI(AceLogTag::ACE_SELECT_OVERLAY,
386             "Update first %{public}s isShow %{public}d, second %{public}s isShow %{public}d",
387             info.firstHandle.paintRect.ToString().c_str(), info.firstHandle.isShow,
388             info.secondHandle.paintRect.ToString().c_str(), info.secondHandle.isShow);
389         if (info.isSingleHandle) {
390             if (selectOverlayHolder_->CheckRestartHiddenHandleTask(requestCode)) {
391                 handlePattern->RestartHiddenHandleTask(true);
392             }
393         } else {
394             handlePattern->CancelHiddenHandleTask();
395         }
396     }
397     selectOverlayHolder_->OnHandleExistOverlay(info, requestCode);
398     NotifySelectOverlayShow(false);
399 }
400 
SwitchToHandleMode(HandleLevelMode mode,bool forceChange)401 void SelectContentOverlayManager::SwitchToHandleMode(HandleLevelMode mode, bool forceChange)
402 {
403     CHECK_NULL_VOID(shareOverlayInfo_);
404     if (shareOverlayInfo_->handleLevelMode == mode) {
405         return;
406     }
407     if (selectOverlayHolder_ && selectOverlayHolder_->GetCallback()) {
408         if (!forceChange && !selectOverlayHolder_->GetCallback()->CheckSwitchToMode(mode)) {
409             return;
410         }
411         selectOverlayHolder_->GetCallback()->OnHandleLevelModeChanged(mode);
412     }
413     TAG_LOGI(AceLogTag::ACE_SELECT_OVERLAY, "Set handle mode: %{public}d", mode);
414     shareOverlayInfo_->handleLevelMode = mode;
415     auto handleNode = handleNode_.Upgrade();
416     CHECK_NULL_VOID(handleNode);
417     auto taskExecutor = Container::CurrentTaskExecutor();
418     CHECK_NULL_VOID(taskExecutor);
419     if (mode == HandleLevelMode::OVERLAY) {
420         taskExecutor->PostTask(
421             [weak = WeakClaim(this), node = handleNode] {
422                 auto manager = weak.Upgrade();
423                 CHECK_NULL_VOID(manager);
424                 CHECK_NULL_VOID(node);
425                 if (!manager->IsOpen()) {
426                     return;
427                 }
428                 manager->DestroySelectOverlayNode(node);
429                 manager->MountNodeToRoot(node, false, NodeType::HANDLE);
430                 node->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
431             },
432             TaskExecutor::TaskType::UI, "SwitchToOverlayModeTask");
433     } else if (mode == HandleLevelMode::EMBED) {
434         taskExecutor->PostTask(
435             [weak = WeakClaim(this), node = handleNode] {
436                 auto manager = weak.Upgrade();
437                 CHECK_NULL_VOID(manager);
438                 CHECK_NULL_VOID(node);
439                 if (!manager->IsOpen()) {
440                     return;
441                 }
442                 manager->DestroySelectOverlayNode(node);
443                 manager->MountNodeToCaller(node, false);
444                 node->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
445             },
446             TaskExecutor::TaskType::UI, "SwitchToEmbedModeTask");
447     }
448 }
449 
HandleDirtyViewPort(RefPtr<SelectContentOverlayPattern> & menuPattern)450 void SelectContentOverlayManager::HandleDirtyViewPort(RefPtr<SelectContentOverlayPattern>& menuPattern)
451 {
452     auto viewPort = selectOverlayHolder_->GetAncestorNodeViewPort();
453     if (viewPort) {
454         ConvertRectRelativeToParent(*viewPort);
455     }
456     if (menuPattern) {
457         menuPattern->UpdateViewPort(viewPort);
458     }
459     auto handlePattern = GetSelectHandlePattern(WeakClaim(this));
460     if (handlePattern) {
461         handlePattern->UpdateViewPort(viewPort);
462     }
463 }
464 
MarkInfoChange(SelectOverlayDirtyFlag dirty)465 void SelectContentOverlayManager::MarkInfoChange(SelectOverlayDirtyFlag dirty)
466 {
467     CHECK_NULL_VOID(selectOverlayHolder_);
468     CHECK_NULL_VOID(IsOpen());
469     auto menuPattern = GetSelectMenuPattern(WeakClaim(this));
470     if (menuPattern) {
471         if ((dirty & DIRTY_SELECT_AREA) == DIRTY_SELECT_AREA) {
472             auto selectArea = selectOverlayHolder_->GetSelectArea();
473             ConvertRectRelativeToParent(selectArea);
474             menuPattern->UpdateSelectArea(selectArea);
475         }
476         if ((dirty & DIRTY_ALL_MENU_ITEM) == DIRTY_ALL_MENU_ITEM) {
477             SelectMenuInfo menuInfo;
478             selectOverlayHolder_->OnUpdateMenuInfo(menuInfo, DIRTY_ALL_MENU_ITEM);
479             TAG_LOGI(AceLogTag::ACE_SELECT_OVERLAY, "Update all menu item: %{public}s - %{public}s",
480                 menuInfo.ToString().c_str(), GetOwnerDebugInfo().c_str());
481             menuPattern->UpdateSelectMenuInfo(menuInfo);
482         } else if (
483             (dirty & DIRTY_COPY_ALL_ITEM) == DIRTY_COPY_ALL_ITEM ||
484             (dirty & DIRTY_AI_MENU_ITEM) == DIRTY_AI_MENU_ITEM ||
485             (dirty & DIRTY_ASK_CELIA) == DIRTY_ASK_CELIA) {
486             auto localReplacedMenuInfo = menuPattern->GetSelectMenuInfo();
487             SelectMenuInfo menuInfo;
488             selectOverlayHolder_->OnUpdateMenuInfo(menuInfo, DIRTY_ALL_MENU_ITEM);
489             if ((dirty & DIRTY_COPY_ALL_ITEM) == DIRTY_COPY_ALL_ITEM) { // can extract to function
490                 localReplacedMenuInfo.showCopyAll = menuInfo.showCopyAll;
491                 localReplacedMenuInfo.showCopy = menuInfo.showCopy;
492             }
493             if ((dirty & DIRTY_AI_MENU_ITEM) == DIRTY_AI_MENU_ITEM) {
494                 localReplacedMenuInfo.aiMenuOptionType = menuInfo.aiMenuOptionType;
495             }
496             if ((dirty & DIRTY_ASK_CELIA) == DIRTY_ASK_CELIA) {
497                 localReplacedMenuInfo.isAskCeliaEnabled = menuInfo.isAskCeliaEnabled;
498             }
499             localReplacedMenuInfo.hasOnPrepareMenuCallback = menuInfo.hasOnPrepareMenuCallback;
500             TAG_LOGI(AceLogTag::ACE_SELECT_OVERLAY, "Update select all menu: %{public}s - %{public}s",
501                 localReplacedMenuInfo.ToString().c_str(), GetOwnerDebugInfo().c_str());
502             menuPattern->UpdateSelectMenuInfo(localReplacedMenuInfo);
503         }
504         if ((dirty & DIRTY_SELECT_TEXT) == DIRTY_SELECT_TEXT) {
505             auto selectedInfo = selectOverlayHolder_->GetSelectedText();
506             menuPattern->SetSelectInfo(selectedInfo);
507         }
508     }
509     if ((dirty & DIRTY_VIEWPORT) == DIRTY_VIEWPORT) {
510         HandleDirtyViewPort(menuPattern);
511     }
512     UpdateHandleInfosWithFlag(dirty);
513     shareOverlayInfo_->containerModalOffset = GetContainerModalOffset();
514     selectOverlayHolder_->OnHandleMarkInfoChange(shareOverlayInfo_, dirty);
515 }
516 
MarkSelectOverlayDirty(PropertyChangeFlag changeFlag)517 void SelectContentOverlayManager::MarkSelectOverlayDirty(PropertyChangeFlag changeFlag)
518 {
519     CHECK_NULL_VOID(IsOpen());
520     selectOverlayNode_.Upgrade()->MarkDirtyNode(changeFlag);
521 }
522 
UpdateHandleInfosWithFlag(int32_t updateFlag)523 void SelectContentOverlayManager::UpdateHandleInfosWithFlag(int32_t updateFlag)
524 {
525     auto pattern = GetSelectHandlePattern(WeakClaim(this));
526     CHECK_NULL_VOID(pattern);
527     std::optional<SelectHandleInfo> firstHandleInfo;
528     if ((static_cast<uint32_t>(updateFlag) & DIRTY_FIRST_HANDLE) == DIRTY_FIRST_HANDLE) {
529         firstHandleInfo = selectOverlayHolder_->GetFirstHandleInfo();
530         if (firstHandleInfo) {
531             ConvertHandleRelativeToParent(*firstHandleInfo);
532             TAG_LOGI(AceLogTag::ACE_SELECT_OVERLAY, "Update first handle info %{public}s - %{public}s",
533                 firstHandleInfo->ToString().c_str(), GetOwnerDebugInfo().c_str());
534         }
535     }
536     std::optional<SelectHandleInfo> secondHandleInfo;
537     if ((static_cast<uint32_t>(updateFlag) & DIRTY_SECOND_HANDLE) == DIRTY_SECOND_HANDLE) {
538         secondHandleInfo = selectOverlayHolder_->GetSecondHandleInfo();
539         if (secondHandleInfo) {
540             ConvertHandleRelativeToParent(*secondHandleInfo);
541             TAG_LOGI(AceLogTag::ACE_SELECT_OVERLAY, "Update second handle info %{public}s - %{public}s",
542                 secondHandleInfo->ToString().c_str(), GetOwnerDebugInfo().c_str());
543         }
544     }
545     if (!firstHandleInfo && !secondHandleInfo) {
546         return;
547     }
548     if (firstHandleInfo && secondHandleInfo) {
549         pattern->UpdateFirstAndSecondHandleInfo(*firstHandleInfo, *secondHandleInfo);
550     } else if (firstHandleInfo) {
551         pattern->UpdateFirstSelectHandleInfo(*firstHandleInfo);
552     } else {
553         pattern->UpdateSecondSelectHandleInfo(*secondHandleInfo);
554     }
555 }
556 
CreateSelectOverlay(SelectOverlayInfo & info,bool animation)557 void SelectContentOverlayManager::CreateSelectOverlay(SelectOverlayInfo& info, bool animation)
558 {
559     if (!info.enableHandleLevel) {
560         CreateNormalSelectOverlay(info, animation);
561     } else {
562         CreateHandleLevelSelectOverlay(info, animation, info.handleLevelMode);
563     }
564     if (!info.menuInfo.menuBuilder) {
565         AceApplicationInfo::GetInstance().SetTextMenuOnChangeCallback([weak = WeakClaim(this)]() {
566             auto manager = weak.Upgrade();
567             CHECK_NULL_RETURN(manager, false);
568             auto menuNode = manager->menuNode_.Upgrade();
569             CHECK_NULL_RETURN(menuNode, false);
570             manager->NotifyUpdateToolBar(true);
571             return true;
572         });
573     }
574 }
575 
CreateNormalSelectOverlay(SelectOverlayInfo & info,bool animation)576 void SelectContentOverlayManager::CreateNormalSelectOverlay(SelectOverlayInfo& info, bool animation)
577 {
578     shareOverlayInfo_ = std::make_shared<SelectOverlayInfo>(info);
579     auto overlayNode = SelectOverlayNode::CreateSelectOverlayNode(shareOverlayInfo_);
580     selectOverlayNode_ = overlayNode;
581     auto taskExecutor = Container::CurrentTaskExecutor();
582     CHECK_NULL_VOID(taskExecutor);
583     taskExecutor->PostTask(
584         [animation, weak = WeakClaim(this), node = overlayNode] {
585             auto manager = weak.Upgrade();
586             CHECK_NULL_VOID(manager);
587             if (node && node == manager->selectOverlayNode_) {
588                 CHECK_NULL_VOID(manager->shareOverlayInfo_);
589                 auto nodeType =
590                     manager->shareOverlayInfo_->isUsingMouse ? NodeType::RIGHT_CLICK_MENU : NodeType::HANDLE_WITH_MENU;
591                 if (nodeType == NodeType::RIGHT_CLICK_MENU && manager->IsEnableSubWindowMenu()) {
592                     manager->MountMenuNodeToSubWindow(node, animation, nodeType);
593                 } else {
594                     manager->MountNodeToRoot(node, animation, nodeType);
595                 }
596                 manager->NotifySelectOverlayShow(true);
597             }
598         },
599         TaskExecutor::TaskType::UI, "ArkUISelectOverlayCreate");
600 }
601 
CreateHandleLevelSelectOverlay(SelectOverlayInfo & info,bool animation,HandleLevelMode mode)602 void SelectContentOverlayManager::CreateHandleLevelSelectOverlay(
603     SelectOverlayInfo& info, bool animation, HandleLevelMode mode)
604 {
605     TAG_LOGI(AceLogTag::ACE_SELECT_OVERLAY,
606         "Show SelectOverlay, first %{public}s isShow %{public}d, second %{public}s isShow %{public}d",
607         info.firstHandle.paintRect.ToString().c_str(), info.firstHandle.isShow,
608         info.secondHandle.paintRect.ToString().c_str(), info.secondHandle.isShow);
609     shareOverlayInfo_ = std::make_shared<SelectOverlayInfo>(info);
610     auto menuNode = SelectOverlayNode::CreateSelectOverlayNode(shareOverlayInfo_, SelectOverlayMode::MENU_ONLY);
611     menuNode_ = menuNode;
612     auto handleNode = SelectOverlayNode::CreateSelectOverlayNode(shareOverlayInfo_, SelectOverlayMode::HANDLE_ONLY);
613     handleNode_ = handleNode;
614     auto taskExecutor = Container::CurrentTaskExecutorSafely();
615     CHECK_NULL_VOID(taskExecutor);
616     taskExecutor->PostTask(
617         [animation, weak = WeakClaim(this), menuNode, handleNode, mode] {
618             auto manager = weak.Upgrade();
619             CHECK_NULL_VOID(manager);
620             auto isMenuNodeValid = (menuNode && menuNode == manager->menuNode_);
621             auto isHandleNodeValid = (handleNode && handleNode == manager->handleNode_);
622             if (!isMenuNodeValid || !isHandleNodeValid) {
623                 return;
624             }
625             if (manager->IsEnableSubWindowMenu()) {
626                 manager->MountMenuNodeToSubWindow(menuNode, animation, NodeType::TOUCH_MENU);
627             } else {
628                 manager->MountNodeToRoot(menuNode, animation, NodeType::TOUCH_MENU);
629             }
630             if (mode == HandleLevelMode::EMBED) {
631                 manager->MountNodeToCaller(handleNode, animation);
632             } else if (mode == HandleLevelMode::OVERLAY) {
633                 manager->MountNodeToRoot(handleNode, animation, NodeType::HANDLE);
634             }
635             manager->NotifySelectOverlayShow(true);
636         },
637         TaskExecutor::TaskType::UI, "CreateHandleLevelSelectOverlay");
638 }
639 
MountNodeToRoot(const RefPtr<FrameNode> & overlayNode,bool animation,NodeType nodeType)640 void SelectContentOverlayManager::MountNodeToRoot(
641     const RefPtr<FrameNode>& overlayNode, bool animation, NodeType nodeType)
642 {
643     auto rootNode = GetSelectOverlayRoot();
644     CHECK_NULL_VOID(rootNode);
645     const auto& children = rootNode->GetChildren();
646     auto slotIt = FindSelectOverlaySlot(rootNode, children);
647     auto index = static_cast<int32_t>(std::distance(children.begin(), slotIt));
648     auto slot = (index > 0) ? index : DEFAULT_NODE_SLOT;
649     bool isMeetSpecialNode = false;
650     std::vector<std::string> nodeTags = {
651         V2::KEYBOARD_ETS_TAG, // keep handle and menu node before keyboard node
652         V2::SELECT_OVERLAY_ETS_TAG, // keep handle node before menu node
653         V2::MAGNIFIER_TAG, // keep handle and menu node before magnifier
654         V2::SHEET_WRAPPER_TAG // keep handle and menu node before SheetWrapper
655     };
656     for (auto it = slotIt; it != children.end(); ++it) {
657         for (const auto& tag : nodeTags) {
658             if ((*it)->GetTag() == tag) {
659                 slot = std::min(slot, index);
660                 isMeetSpecialNode = true;
661                 break;
662             }
663         }
664         if (isMeetSpecialNode) {
665             break;
666         }
667         index++;
668     }
669     if (nodeType == NodeType::TOUCH_MENU || nodeType == NodeType::RIGHT_CLICK_MENU) {
670         slot = index;
671     }
672     TAG_LOGI(AceLogTag::ACE_SELECT_OVERLAY, "MountNodeToRoot:%{public}s, id:%{public}d", rootNode->GetTag().c_str(),
673         rootNode->GetId());
674     overlayNode->MountToParent(rootNode, slot);
675     rootNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
676     if (!shareOverlayInfo_->isUsingMouse) {
677         auto node = DynamicCast<SelectOverlayNode>(overlayNode);
678         if (node) {
679             node->ShowSelectOverlay(animation);
680         }
681     }
682 }
683 
FindSelectOverlaySlot(const RefPtr<FrameNode> & root,const std::list<RefPtr<UINode>> & children)684 std::list<RefPtr<UINode>>::const_iterator SelectContentOverlayManager::FindSelectOverlaySlot(
685     const RefPtr<FrameNode>& root, const std::list<RefPtr<UINode>>& children)
686 {
687     auto begin = children.begin();
688     CHECK_NULL_RETURN(selectOverlayHolder_, begin);
689     auto callerNode = selectOverlayHolder_->GetOwner();
690     CHECK_NULL_RETURN(callerNode, begin);
691     RefPtr<UINode> prevNode = nullptr;
692     auto parent = callerNode->GetParent();
693     while (parent) {
694         if (parent == root) {
695             break;
696         }
697         prevNode = parent;
698         parent = parent->GetParent();
699     }
700     CHECK_NULL_RETURN(parent, begin);
701     CHECK_NULL_RETURN(prevNode, begin);
702     for (auto it = begin; it != children.end(); ++it) {
703         if (prevNode == *it) {
704             return ++it;
705         }
706     }
707     return begin;
708 }
709 
MountNodeToCaller(const RefPtr<FrameNode> & overlayNode,bool animation)710 void SelectContentOverlayManager::MountNodeToCaller(const RefPtr<FrameNode>& overlayNode, bool animation)
711 {
712     CHECK_NULL_VOID(selectOverlayHolder_);
713     auto ownerFrameNode = selectOverlayHolder_->GetOwner();
714     CHECK_NULL_VOID(ownerFrameNode);
715     TAG_LOGI(AceLogTag::ACE_SELECT_OVERLAY,
716         "Mount SelectOverlay node: %{public}s, id: %{public}d", ownerFrameNode->GetTag().c_str(),
717         ownerFrameNode->GetId());
718     ownerFrameNode->SetOverlayNode(overlayNode);
719     overlayNode->SetParent(AceType::WeakClaim(AceType::RawPtr(ownerFrameNode)));
720     overlayNode->SetActive(true);
721     auto overlayProperty = AceType::DynamicCast<LayoutProperty>(overlayNode->GetLayoutProperty());
722     CHECK_NULL_VOID(overlayProperty);
723     overlayProperty->SetIsOverlayNode(true);
724     overlayProperty->UpdateAlignment(Alignment::CENTER);
725     overlayProperty->UpdateMeasureType(MeasureType::MATCH_PARENT);
726     ownerFrameNode->MarkNeedSyncRenderTree();
727     ownerFrameNode->RebuildRenderContextTree();
728     overlayNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
729     if (!shareOverlayInfo_->isUsingMouse) {
730         auto node = DynamicCast<SelectOverlayNode>(overlayNode);
731         if (node) {
732             node->ShowSelectOverlay(animation);
733         }
734     }
735 }
736 
NotifySelectOverlayShow(bool isCreated)737 void SelectContentOverlayManager::NotifySelectOverlayShow(bool isCreated)
738 {
739     CHECK_NULL_VOID(selectOverlayHolder_);
740     auto callback = selectOverlayHolder_->GetCallback();
741     CHECK_NULL_VOID(callback);
742     callback->OnAfterSelectOverlayShow(isCreated);
743 }
744 
GetSelectOverlayRoot()745 const RefPtr<FrameNode> SelectContentOverlayManager::GetSelectOverlayRoot()
746 {
747     auto rootNode = rootNodeWeak_.Upgrade();
748     CHECK_NULL_RETURN(shareOverlayInfo_, rootNode);
749     auto container = Container::Current();
750     if (container && container->IsSceneBoardWindow()) {
751         auto root = FindWindowScene(shareOverlayInfo_->callerFrameNode.Upgrade());
752         rootNode = DynamicCast<FrameNode>(root);
753     } else if (rootNode && selectOverlayHolder_ && selectOverlayHolder_->IsEnableContainerModal()) {
754         auto containerModalRoot = GetContainerModalRoot();
755         if (containerModalRoot) {
756             rootNode = containerModalRoot;
757         }
758     }
759     return rootNode;
760 }
761 
762 /**
763  * @description: This function will be used in SceneBoard Thread only.
764  * if need to show the select-overlay component, it expects to receive the target component bound by
765  * the select-overlay component to find the windowScene component.
766  * if need to hide the select-overlay component, it expects to receive the the select-overlay component
767  * to return the parent component. And the parent component will be the windowScene component exactly.
768  */
FindWindowScene(RefPtr<FrameNode> targetNode)769 RefPtr<UINode> SelectContentOverlayManager::FindWindowScene(RefPtr<FrameNode> targetNode)
770 {
771     auto container = Container::Current();
772     if (!container || !container->IsSceneBoardWindow()) {
773         return rootNodeWeak_.Upgrade();
774     }
775     CHECK_NULL_RETURN(targetNode, nullptr);
776     auto parent = targetNode->GetParent();
777     while (parent && parent->GetTag() != V2::WINDOW_SCENE_ETS_TAG) {
778         parent = parent->GetParent();
779     }
780     CHECK_NULL_RETURN(parent, nullptr);
781     return parent;
782 }
783 
CloseInternal(int32_t id,bool animation,CloseReason reason)784 bool SelectContentOverlayManager::CloseInternal(int32_t id, bool animation, CloseReason reason)
785 {
786     CHECK_NULL_RETURN(selectOverlayHolder_, false);
787     CHECK_NULL_RETURN(selectOverlayHolder_->GetOwnerId() == id, false);
788     CHECK_NULL_RETURN(shareOverlayInfo_, false);
789     TAG_LOGI(AceLogTag::ACE_SELECT_OVERLAY, "Close SelectOverlay, by id:%{public}d, reason %{public}d", id, reason);
790     auto callback = selectOverlayHolder_->GetCallback();
791     auto menuType = shareOverlayInfo_->menuInfo.menuType;
792     auto pattern = GetSelectHandlePattern(WeakClaim(this));
793     RefPtr<OverlayInfo> info = nullptr;
794     if (pattern) {
795         info = AceType::MakeRefPtr<OverlayInfo>();
796         info->isSingleHandle = shareOverlayInfo_->isSingleHandle;
797         info->isShowMenu = shareOverlayInfo_->menuInfo.menuIsShow;
798         info->isHiddenHandle = pattern->IsHiddenHandle();
799     }
800     auto selectOverlayNode = selectOverlayNode_.Upgrade();
801     auto menuNode = menuNode_.Upgrade();
802     auto handleNode = handleNode_.Upgrade();
803     auto owner = selectOverlayHolder_->GetOwner();
804     if (owner && IsMenuShow()) {
805         auto ownerTag = owner->GetTag();
806         if (ownerTag != V2::RICH_EDITOR_ETS_TAG ||
807             (reason != CloseReason::CLOSE_REASON_SELECT_ALL && reason != CloseReason::CLOSE_REASON_BY_RECREATE)) {
808             NotifyAccessibilityOwner();
809         }
810     }
811     if (animation && !shareOverlayInfo_->isUsingMouse) {
812         ClearAllStatus();
813         DestroySelectOverlayNodeWithAnimation(selectOverlayNode);
814         DestroySelectOverlayNodeWithAnimation(menuNode);
815         DestroySelectOverlayNodeWithAnimation(handleNode);
816     } else {
817         DestroySelectOverlayNode(selectOverlayNode);
818         DestroySelectOverlayNode(menuNode);
819         DestroySelectOverlayNode(handleNode);
820         ClearAllStatus();
821     }
822     if (callback) {
823         TAG_LOGI(AceLogTag::ACE_SELECT_OVERLAY, "SelectOverlay is closed with reason %{public}d - %{public}s",
824             reason, GetOwnerDebugInfo().c_str());
825         callback->OnCloseOverlay(menuType, reason, info);
826     }
827     AceApplicationInfo::GetInstance().SetTextMenuOnChangeCallback(nullptr);
828     return true;
829 }
830 
DestroySelectOverlayNodeWithAnimation(const RefPtr<FrameNode> & node)831 void SelectContentOverlayManager::DestroySelectOverlayNodeWithAnimation(const RefPtr<FrameNode>& node)
832 {
833     auto overlayNode = DynamicCast<SelectOverlayNode>(node);
834     CHECK_NULL_VOID(overlayNode);
835     overlayNode->HideSelectOverlay([weakOverlay = WeakClaim(AceType::RawPtr(node)), managerWeak = WeakClaim(this)]() {
836         auto manager = managerWeak.Upgrade();
837         CHECK_NULL_VOID(manager);
838         manager->DestroySelectOverlayNode(weakOverlay.Upgrade());
839     });
840 }
841 
DestroySelectOverlayNode(const RefPtr<FrameNode> & overlay)842 void SelectContentOverlayManager::DestroySelectOverlayNode(const RefPtr<FrameNode>& overlay)
843 {
844     CHECK_NULL_VOID(overlay);
845     auto parentNode = overlay->GetParent();
846     CHECK_NULL_VOID(parentNode);
847     auto pattern = overlay->GetPattern<SelectOverlayPattern>();
848     auto parentFrameNode = DynamicCast<FrameNode>(parentNode);
849     if (parentFrameNode) {
850         if (pattern && pattern->GetMode() == SelectOverlayMode::HANDLE_ONLY) {
851             parentFrameNode->SetOverlayNode(nullptr);
852             overlay->SetParent(nullptr);
853         }
854     }
855     TAG_LOGI(AceLogTag::ACE_SELECT_OVERLAY,
856         "Remove node [%{public}s, %{public}d] from [%{public}s, %{public}d]", overlay->GetTag().c_str(),
857         overlay->GetId(), parentNode->GetTag().c_str(), parentNode->GetId());
858     parentNode->RemoveChild(overlay);
859     parentNode->MarkNeedSyncRenderTree();
860     parentNode->RebuildRenderContextTree();
861     if (pattern && pattern->GetIsMenuShowInSubWindow()) {
862         SubwindowManager::GetInstance()->DeleteSelectOverlayHotAreas(pattern->GetContainerId(), overlay->GetId());
863         SubwindowManager::GetInstance()->HideSelectOverlay(pattern->GetContainerId());
864     } else {
865         auto menuWrapperPattern = overlay->GetPattern<MenuWrapperPattern>();
866         CHECK_NULL_VOID(menuWrapperPattern);
867         if (menuWrapperPattern->GetIsSelectOverlaySubWindowWrapper()) {
868             SubwindowManager::GetInstance()->DeleteSelectOverlayHotAreas(
869                 menuWrapperPattern->GetContainerId(), overlay->GetId());
870             SubwindowManager::GetInstance()->HideSelectOverlay(menuWrapperPattern->GetContainerId());
871         }
872     }
873 }
874 
ClearAllStatus()875 void SelectContentOverlayManager::ClearAllStatus()
876 {
877     selectOverlayNode_.Reset();
878     handleNode_.Reset();
879     menuNode_.Reset();
880     shareOverlayInfo_.reset();
881     if (selectOverlayHolder_) {
882         selectOverlayHolder_->OnBind(nullptr);
883     }
884     selectOverlayHolder_.Reset();
885 }
886 
CloseCurrent(bool animation,CloseReason reason)887 bool SelectContentOverlayManager::CloseCurrent(bool animation, CloseReason reason)
888 {
889     CHECK_NULL_RETURN(selectOverlayHolder_, false);
890     CHECK_NULL_RETURN(selectOverlayNode_.Upgrade() || menuNode_.Upgrade() || handleNode_.Upgrade(), false);
891     return CloseInternal(selectOverlayHolder_->GetOwnerId(), animation, reason);
892 }
893 
CloseWithOverlayId(int32_t overlayId,CloseReason reason,bool animation)894 void SelectContentOverlayManager::CloseWithOverlayId(int32_t overlayId, CloseReason reason, bool animation)
895 {
896     CHECK_NULL_VOID(IsOpen());
897     // call from menu button.
898     auto hasOverlayId = (selectOverlayNode_.Upgrade() && overlayId == selectOverlayNode_.Upgrade()->GetId());
899     hasOverlayId = hasOverlayId || (menuNode_.Upgrade() && menuNode_.Upgrade()->GetId());
900     if (hasOverlayId) {
901         CloseInternal(selectOverlayHolder_->GetOwnerId(), animation, reason);
902     }
903 }
904 
Close(int32_t id,bool animation,CloseReason reason)905 void SelectContentOverlayManager::Close(int32_t id, bool animation, CloseReason reason)
906 {
907     CloseInternal(id, animation, reason);
908 }
909 
ShowOptionMenu()910 void SelectContentOverlayManager::ShowOptionMenu()
911 {
912     auto pattern = GetSelectMenuPattern(WeakClaim(this));
913     CHECK_NULL_VOID(pattern);
914     pattern->UpdateMenuIsShow(true);
915 }
916 
HideOptionMenu(bool noAnimation)917 void SelectContentOverlayManager::HideOptionMenu(bool noAnimation)
918 {
919     auto pattern = GetSelectMenuPattern(WeakClaim(this));
920     CHECK_NULL_VOID(pattern);
921     pattern->UpdateMenuIsShow(false, noAnimation);
922 }
923 
ToggleOptionMenu()924 void SelectContentOverlayManager::ToggleOptionMenu()
925 {
926     CHECK_NULL_VOID(shareOverlayInfo_);
927     auto pattern = GetSelectMenuPattern(WeakClaim(this));
928     CHECK_NULL_VOID(pattern);
929     SelectMenuInfo menuInfo;
930     selectOverlayHolder_->IsAIMenuOptionChanged(menuInfo);
931     shareOverlayInfo_->menuInfo.isShowAIMenuOptionChanged = menuInfo.isShowAIMenuOptionChanged;
932     shareOverlayInfo_->menuInfo.aiMenuOptionType = menuInfo.aiMenuOptionType;
933     shareOverlayInfo_->menuInfo.isAskCeliaEnabled = menuInfo.isAskCeliaEnabled;
934     pattern->UpdateMenuIsShow(!shareOverlayInfo_->menuInfo.menuIsShow);
935 }
936 
DisableMenu()937 void SelectContentOverlayManager::DisableMenu()
938 {
939     auto pattern = GetSelectMenuPattern(WeakClaim(this));
940     CHECK_NULL_VOID(pattern);
941     pattern->DisableMenu(true);
942 }
943 
EnableMenu()944 void SelectContentOverlayManager::EnableMenu()
945 {
946     auto pattern = GetSelectMenuPattern(WeakClaim(this));
947     CHECK_NULL_VOID(pattern);
948     pattern->DisableMenu(false);
949 }
950 
HideHandle()951 void SelectContentOverlayManager::HideHandle()
952 {
953     auto pattern = GetSelectHandlePattern(WeakClaim(this));
954     CHECK_NULL_VOID(pattern);
955     pattern->StartHiddenHandleTask(false);
956 }
957 
IsOpen()958 bool SelectContentOverlayManager::IsOpen()
959 {
960     if (!IsEnableHandleLevel()) {
961         auto overlayNode = selectOverlayNode_.Upgrade();
962         return overlayNode && overlayNode->GetParent();
963     }
964     auto hasHandleNode = handleNode_.Upgrade() && handleNode_.Upgrade()->GetParent();
965     auto hasMenuNode = menuNode_.Upgrade() && menuNode_.Upgrade()->GetParent();
966     return hasHandleNode || hasMenuNode;
967 }
968 
IsCreating()969 bool SelectContentOverlayManager::IsCreating()
970 {
971     if (!IsEnableHandleLevel()) {
972         auto overlayNode = selectOverlayNode_.Upgrade();
973         return overlayNode && !overlayNode->GetParent();
974     }
975     auto menuNode = menuNode_.Upgrade();
976     auto handleNode = handleNode_.Upgrade();
977     return (menuNode && !menuNode->GetParent()) || (handleNode && !handleNode->GetParent());
978 }
979 
IsMenuShow()980 bool SelectContentOverlayManager::IsMenuShow()
981 {
982     return IsOpen() && shareOverlayInfo_ && shareOverlayInfo_->menuInfo.menuIsShow;
983 }
984 
IsSingleHandle()985 bool SelectContentOverlayManager::IsSingleHandle()
986 {
987     return IsOpen() && shareOverlayInfo_ && shareOverlayInfo_->isSingleHandle;
988 }
989 
IsHandlesShow()990 bool SelectContentOverlayManager::IsHandlesShow()
991 {
992     return IsOpen() && shareOverlayInfo_ && !shareOverlayInfo_->isSingleHandle;
993 }
994 
IsHandleReverse()995 bool SelectContentOverlayManager::IsHandleReverse()
996 {
997     return IsOpen() && shareOverlayInfo_ && shareOverlayInfo_->handleReverse;
998 }
999 
RestartHiddenHandleTask(bool isDelay)1000 void SelectContentOverlayManager::RestartHiddenHandleTask(bool isDelay)
1001 {
1002     auto pattern = GetSelectHandlePattern(WeakClaim(this));
1003     CHECK_NULL_VOID(pattern);
1004     pattern->RestartHiddenHandleTask(isDelay);
1005 }
1006 
CancelHiddenHandleTask()1007 void SelectContentOverlayManager::CancelHiddenHandleTask()
1008 {
1009     auto pattern = GetSelectHandlePattern(WeakClaim(this));
1010     CHECK_NULL_VOID(pattern);
1011     pattern->CancelHiddenHandleTask();
1012 }
1013 
GetSelectOverlayNode()1014 RefPtr<SelectOverlayNode> SelectContentOverlayManager::GetSelectOverlayNode()
1015 {
1016     auto overlayNode = IsEnableHandleLevel() ? menuNode_.Upgrade() : selectOverlayNode_.Upgrade();
1017     return AceType::DynamicCast<SelectOverlayNode>(overlayNode);
1018 }
1019 
GetShowMenuType()1020 OptionMenuType SelectContentOverlayManager::GetShowMenuType()
1021 {
1022     return IsOpen() && shareOverlayInfo_ ? shareOverlayInfo_->menuInfo.menuType : OptionMenuType::NO_MENU;
1023 }
1024 
HandleGlobalEvent(const TouchEvent & touchEvent,const NG::OffsetF & rootOffset)1025 void SelectContentOverlayManager::HandleGlobalEvent(const TouchEvent& touchEvent, const NG::OffsetF& rootOffset)
1026 {
1027     NG::PointF point { touchEvent.x - rootOffset.GetX(), touchEvent.y - rootOffset.GetY() };
1028     point = point - GetContainerModalOffset();
1029     if (touchEvent.type == TouchType::DOWN) {
1030         isIntercept_ = IsTouchInSelectOverlayArea(point);
1031     }
1032     if (!isIntercept_) {
1033         HandleSelectionEvent(point, touchEvent);
1034         if (selectOverlayHolder_ && selectOverlayHolder_->GetCallback() && selectOverlayHolder_->GetOwner()) {
1035             auto localPoint = point;
1036             ConvertPointRelativeToNode(selectOverlayHolder_->GetOwner(), localPoint, touchEvent.passThrough);
1037             selectOverlayHolder_->GetCallback()->OnHandleGlobalEvent(point, localPoint, touchEvent);
1038         }
1039     }
1040     if (touchEvent.type == TouchType::UP) {
1041         isIntercept_ = false;
1042     }
1043 }
1044 
IsTouchInSelectOverlayArea(const PointF & point)1045 bool SelectContentOverlayManager::IsTouchInSelectOverlayArea(const PointF& point)
1046 {
1047     if (!IsEnableHandleLevel()) {
1048         return IsTouchInNormalSelectOverlayArea(point);
1049     }
1050     return IsTouchInHandleLevelOverlayArea(point);
1051 }
1052 
IsTouchInNormalSelectOverlayArea(const PointF & point)1053 bool SelectContentOverlayManager::IsTouchInNormalSelectOverlayArea(const PointF& point)
1054 {
1055     auto current = selectOverlayNode_.Upgrade();
1056     CHECK_NULL_RETURN(current, false);
1057     auto selectOverlayNode = DynamicCast<SelectOverlayNode>(current);
1058     if (selectOverlayNode) {
1059         return selectOverlayNode->IsInSelectedOrSelectOverlayArea(point);
1060     }
1061     // get the menu rect not the out wrapper
1062     auto modalOffset = GetContainerModalOffset();
1063     const auto& children = current->GetChildren();
1064     for (const auto& it : children) {
1065         auto child = DynamicCast<FrameNode>(it);
1066         if (child == nullptr || !child->GetGeometryNode()) {
1067             continue;
1068         }
1069         auto frameRect =
1070             RectF(child->GetTransformRelativeOffset() - modalOffset, child->GetGeometryNode()->GetFrameSize());
1071         if (frameRect.IsInRegion(point)) {
1072             return true;
1073         }
1074     }
1075     return false;
1076 }
1077 
IsTouchInHandleLevelOverlayArea(const PointF & point)1078 bool SelectContentOverlayManager::IsTouchInHandleLevelOverlayArea(const PointF& point)
1079 {
1080     auto selectOverlayNode = DynamicCast<SelectOverlayNode>(menuNode_.Upgrade());
1081     if (selectOverlayNode && selectOverlayNode->IsInSelectedOrSelectOverlayArea(point)) {
1082         return true;
1083     }
1084     selectOverlayNode = DynamicCast<SelectOverlayNode>(handleNode_.Upgrade());
1085     CHECK_NULL_RETURN(selectOverlayNode, false);
1086     auto localPoint = point;
1087     ConvertPointRelativeToNode(selectOverlayNode->GetAncestorNodeOfFrame(true), localPoint);
1088     return selectOverlayNode->IsInSelectedOrSelectOverlayArea(localPoint);
1089 }
1090 
HandleSelectionEvent(const PointF & point,const TouchEvent & rawTouchEvent)1091 void SelectContentOverlayManager::HandleSelectionEvent(const PointF& point, const TouchEvent& rawTouchEvent)
1092 {
1093     CHECK_NULL_VOID(holdSelectionInfo_);
1094     CHECK_NULL_VOID(holdSelectionInfo_->checkTouchInArea);
1095     CHECK_NULL_VOID(holdSelectionInfo_->resetSelectionCallback);
1096     if (holdSelectionInfo_->IsAcceptEvent(rawTouchEvent.sourceType, rawTouchEvent.type) &&
1097         !holdSelectionInfo_->checkTouchInArea(point, rawTouchEvent.passThrough) && !IsOpen()) {
1098         ResetSelectionRect();
1099     }
1100 }
1101 
ResetSelectionRect()1102 void SelectContentOverlayManager::ResetSelectionRect()
1103 {
1104     CHECK_NULL_VOID(holdSelectionInfo_);
1105     if (holdSelectionInfo_->resetSelectionCallback) {
1106         holdSelectionInfo_->resetSelectionCallback();
1107     }
1108     selectionHoldId_ = -1;
1109     holdSelectionInfo_.reset();
1110 }
1111 
SetHoldSelectionCallback(int32_t id,const HoldSelectionInfo & selectionInfo)1112 void SelectContentOverlayManager::SetHoldSelectionCallback(int32_t id, const HoldSelectionInfo& selectionInfo)
1113 {
1114     if (id == selectionHoldId_) {
1115         return;
1116     }
1117     if (holdSelectionInfo_ && id != selectionHoldId_ && holdSelectionInfo_->resetSelectionCallback) {
1118         holdSelectionInfo_->resetSelectionCallback();
1119     }
1120     selectionHoldId_ = id;
1121     holdSelectionInfo_ = selectionInfo;
1122 }
1123 
RemoveHoldSelectionCallback(int32_t id)1124 void SelectContentOverlayManager::RemoveHoldSelectionCallback(int32_t id)
1125 {
1126     CHECK_NULL_VOID(holdSelectionInfo_);
1127     if (selectionHoldId_ == id) {
1128         selectionHoldId_ = -1;
1129         holdSelectionInfo_.reset();
1130     }
1131 }
1132 
IsEnableHandleLevel()1133 bool SelectContentOverlayManager::IsEnableHandleLevel()
1134 {
1135     return shareOverlayInfo_ && shareOverlayInfo_->enableHandleLevel;
1136 }
1137 
GetMenuPattern()1138 RefPtr<Pattern> SelectContentOverlayManager::GetMenuPattern()
1139 {
1140     return IsEnableHandleLevel() ? GetSelectOverlayPattern(menuNode_)
1141                                       : GetSelectOverlayPattern(selectOverlayNode_);
1142 }
1143 
GetHandlePattern()1144 RefPtr<Pattern> SelectContentOverlayManager::GetHandlePattern()
1145 {
1146     return IsEnableHandleLevel() ? GetSelectOverlayPattern(handleNode_)
1147                                       : GetSelectOverlayPattern(selectOverlayNode_);
1148 }
1149 
GetHandleOverlayNode()1150 RefPtr<FrameNode> SelectContentOverlayManager::GetHandleOverlayNode()
1151 {
1152     return handleNode_.Upgrade();
1153 }
1154 
NotifyUpdateToolBar(bool itemChanged,bool withoutAnimation)1155 void SelectContentOverlayManager::NotifyUpdateToolBar(bool itemChanged, bool withoutAnimation)
1156 {
1157     auto menuNode = DynamicCast<SelectOverlayNode>(menuNode_.Upgrade());
1158     CHECK_NULL_VOID(menuNode);
1159     menuNode->UpdateToolBar(itemChanged, withoutAnimation);
1160 }
1161 
GetHandleDiameter()1162 float SelectContentOverlayManager::GetHandleDiameter()
1163 {
1164     return SelectOverlayPattern::GetHandleDiameter();
1165 }
1166 
ConvertPointRelativeToNode(const RefPtr<FrameNode> & node,PointF & point,bool passThrough)1167 void SelectContentOverlayManager::ConvertPointRelativeToNode(
1168     const RefPtr<FrameNode>& node, PointF& point, bool passThrough)
1169 {
1170     CHECK_NULL_VOID(node);
1171     RefPtr<FrameNode> rootNode;
1172     // for post mouse event, need change the root node to the post node
1173     if (passThrough) {
1174         auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
1175         if (pipeline) {
1176             auto postEventManager = pipeline->GetPostEventManager();
1177             rootNode = postEventManager ? postEventManager->GetPostTargetNode() : nullptr;
1178         }
1179     }
1180     if (!rootNode) {
1181         rootNode = GetSelectOverlayRoot();
1182     }
1183     CHECK_NULL_VOID(rootNode);
1184     std::stack<RefPtr<FrameNode>> nodeStack;
1185     auto parent = node;
1186     while (parent && parent != rootNode) {
1187         nodeStack.push(parent);
1188         parent = parent->GetAncestorNodeOfFrame(true);
1189     }
1190     CHECK_NULL_VOID(!nodeStack.empty());
1191     PointF temp(point.GetX(), point.GetY());
1192     while (!nodeStack.empty()) {
1193         parent = nodeStack.top();
1194         CHECK_NULL_VOID(parent);
1195         nodeStack.pop();
1196         auto renderContext = parent->GetRenderContext();
1197         CHECK_NULL_VOID(renderContext);
1198         renderContext->GetPointWithRevert(temp);
1199         auto rectOffset = renderContext->GetPaintRectWithoutTransform().GetOffset();
1200         temp = temp - rectOffset;
1201     }
1202     point.SetX(temp.GetX());
1203     point.SetY(temp.GetY());
1204 }
1205 
IsTouchAtHandle(const PointF & localPoint,const PointF & globalPoint)1206 bool SelectContentOverlayManager::IsTouchAtHandle(const PointF& localPoint, const PointF& globalPoint)
1207 {
1208     auto handleNode = handleNode_.Upgrade();
1209     CHECK_NULL_RETURN(handleNode, false);
1210     auto selectOverlayNode = DynamicCast<SelectOverlayNode>(handleNode);
1211     CHECK_NULL_RETURN(selectOverlayNode, false);
1212     auto pattern = selectOverlayNode->GetPattern<SelectOverlayPattern>();
1213     CHECK_NULL_RETURN(pattern, false);
1214     if (pattern->IsHiddenHandle()) {
1215         return false;
1216     }
1217     CHECK_NULL_RETURN(selectOverlayHolder_, false);
1218     if (selectOverlayNode->GetParent() == selectOverlayHolder_->GetOwner()) {
1219         return selectOverlayNode->IsInSelectedOrSelectOverlayArea(localPoint);
1220     }
1221     return selectOverlayNode->IsInSelectedOrSelectOverlayArea(globalPoint);
1222 }
1223 
UpdateViewPort()1224 void SelectContentOverlayManager::UpdateViewPort()
1225 {
1226     auto menuNode = menuNode_.Upgrade();
1227     CHECK_NULL_VOID(menuNode);
1228     CHECK_NULL_VOID(selectOverlayHolder_);
1229     CHECK_NULL_VOID(shareOverlayInfo_);
1230     shareOverlayInfo_->ancestorViewPort = selectOverlayHolder_->GetAncestorNodeViewPort();
1231     menuNode->MarkDirtyNode(PROPERTY_UPDATE_LAYOUT);
1232 }
1233 
SetHandleCircleIsShow(bool isFirst,bool isShow)1234 void SelectContentOverlayManager::SetHandleCircleIsShow(bool isFirst, bool isShow)
1235 {
1236     auto pattern = GetSelectHandlePattern(WeakClaim(this));
1237     CHECK_NULL_VOID(pattern);
1238     pattern->SetHandleCircleIsShow(isFirst, isShow);
1239 }
1240 
SetIsHandleLineShow(bool isShow)1241 void SelectContentOverlayManager::SetIsHandleLineShow(bool isShow)
1242 {
1243     auto pattern = GetSelectHandlePattern(WeakClaim(this));
1244     CHECK_NULL_VOID(pattern);
1245     pattern->SetIsHandleLineShow(isShow);
1246 }
1247 
MarkHandleDirtyNode(PropertyChangeFlag flag)1248 void SelectContentOverlayManager::MarkHandleDirtyNode(PropertyChangeFlag flag)
1249 {
1250     auto pattern = GetSelectHandlePattern(WeakClaim(this));
1251     CHECK_NULL_VOID(pattern);
1252     auto host = pattern->GetHost();
1253     CHECK_NULL_VOID(host);
1254     host->MarkDirtyNode(flag);
1255 }
1256 
IsHiddenHandle()1257 bool SelectContentOverlayManager::IsHiddenHandle()
1258 {
1259     auto pattern = GetSelectHandlePattern(WeakClaim(this));
1260     CHECK_NULL_RETURN(pattern, false);
1261     return pattern->IsHiddenHandle();
1262 }
1263 
UpdateSelectOverlayInfoInternal(SelectOverlayInfo & overlayInfo)1264 void SelectContentOverlayManager::UpdateSelectOverlayInfoInternal(SelectOverlayInfo& overlayInfo)
1265 {
1266     if (!selectOverlayHolder_ || !selectOverlayHolder_->IsEnableContainerModal()) {
1267         return;
1268     }
1269     if (overlayInfo.ancestorViewPort) {
1270         ConvertRectRelativeToParent(*overlayInfo.ancestorViewPort);
1271     }
1272     ConvertRectRelativeToParent(overlayInfo.selectArea);
1273     ConvertHandleRelativeToParent(overlayInfo.firstHandle);
1274     ConvertHandleRelativeToParent(overlayInfo.secondHandle);
1275     auto containerModalOffset = GetContainerModalOffset();
1276     if (overlayInfo.isUsingMouse) {
1277         overlayInfo.rightClickOffset -= containerModalOffset;
1278     }
1279     overlayInfo.containerModalOffset = containerModalOffset;
1280 }
1281 
GetContainerModalOffset()1282 OffsetF SelectContentOverlayManager::GetContainerModalOffset()
1283 {
1284     CHECK_NULL_RETURN(selectOverlayHolder_, OffsetF());
1285     if (!selectOverlayHolder_->IsEnableContainerModal()) {
1286         return OffsetF();
1287     }
1288     auto rootNode = GetContainerModalRoot();
1289     CHECK_NULL_RETURN(rootNode, OffsetF());
1290     return rootNode->GetTransformRelativeOffset();
1291 }
1292 
ConvertRectRelativeToParent(RectF & rect)1293 void SelectContentOverlayManager::ConvertRectRelativeToParent(RectF& rect)
1294 {
1295     rect.SetOffset(rect.GetOffset() - GetContainerModalOffset());
1296 }
1297 
ConvertHandleRelativeToParent(SelectHandleInfo & info)1298 void SelectContentOverlayManager::ConvertHandleRelativeToParent(SelectHandleInfo& info)
1299 {
1300     auto modalOffset = GetContainerModalOffset();
1301     if (modalOffset.NonOffset()) {
1302         return;
1303     }
1304     ConvertRectRelativeToParent(info.paintRect);
1305     if (info.isPaintHandleWithPoints) {
1306         info.paintInfo = info.paintInfo - modalOffset;
1307     }
1308     if (info.paintInfoConverter) {
1309         info.paintInfoConverter = [weak = WeakClaim(this), converter = std::move(info.paintInfoConverter)](
1310                                       const SelectHandlePaintInfo& paintInfo) {
1311             auto manager = weak.Upgrade();
1312             CHECK_NULL_RETURN(manager, RectF());
1313             auto tmpPaintInfo = paintInfo;
1314             tmpPaintInfo = tmpPaintInfo + manager->GetContainerModalOffset();
1315             return converter(tmpPaintInfo);
1316         };
1317     }
1318 }
1319 
RevertRectRelativeToRoot(RectF & handle)1320 void SelectContentOverlayManager::RevertRectRelativeToRoot(RectF& handle)
1321 {
1322     CHECK_NULL_VOID(shareOverlayInfo_);
1323     if (shareOverlayInfo_->handleLevelMode == HandleLevelMode::EMBED) {
1324         return;
1325     }
1326     handle.SetOffset(handle.GetOffset() + GetContainerModalOffset());
1327 }
1328 
GetContainerModalRoot()1329 RefPtr<FrameNode> SelectContentOverlayManager::GetContainerModalRoot()
1330 {
1331     auto rootNode = rootNodeWeak_.Upgrade();
1332     if (rootNode) {
1333         auto context = rootNode->GetContextRefPtr();
1334         CHECK_NULL_RETURN(context, nullptr);
1335         auto windowModal = context->GetWindowModal();
1336         if (windowModal == WindowModal::CONTAINER_MODAL) {
1337             auto overlayManager = context->GetOverlayManager();
1338             CHECK_NULL_RETURN(overlayManager, nullptr);
1339             auto overlayRoot = overlayManager->GetRootNode();
1340             CHECK_NULL_RETURN(overlayRoot.Upgrade(), nullptr);
1341             return DynamicCast<FrameNode>(overlayRoot.Upgrade());
1342         }
1343     }
1344     return nullptr;
1345 }
1346 
IsStopBackPress() const1347 bool SelectContentOverlayManager::IsStopBackPress() const
1348 {
1349     CHECK_NULL_RETURN(selectOverlayHolder_, true);
1350     return selectOverlayHolder_->IsStopBackPress();
1351 }
1352 
GetOwnerDebugInfo()1353 std::string SelectContentOverlayManager::GetOwnerDebugInfo()
1354 {
1355     CHECK_NULL_RETURN(selectOverlayHolder_, "Holder NA");
1356     std::stringstream ownerInfo;
1357     if (selectOverlayHolder_->GetOwner()) {
1358         ownerInfo << "[" << selectOverlayHolder_->GetOwner()->GetTag() << "," << selectOverlayHolder_->GetOwnerId()
1359                   << "]";
1360     }
1361     return ownerInfo.str();
1362 }
1363 
MountMenuNodeToSubWindow(const RefPtr<FrameNode> & overlayNode,bool animation,NodeType nodeType)1364 void SelectContentOverlayManager::MountMenuNodeToSubWindow(
1365     const RefPtr<FrameNode>& overlayNode, bool animation, NodeType nodeType)
1366 {
1367     CHECK_NULL_VOID(shareOverlayInfo_);
1368     CHECK_NULL_VOID(overlayNode);
1369     containerId_ = SubwindowManager::GetInstance()->ShowSelectOverlay(overlayNode);
1370     if (containerId_ == -1) {
1371         TAG_LOGW(AceLogTag::ACE_SELECT_OVERLAY,
1372             "Failed to display selectoverlay menu in the subwindow, still displayed in the main window.");
1373         MountNodeToRoot(overlayNode, animation, nodeType);
1374         return;
1375     }
1376     if (!shareOverlayInfo_->isUsingMouse) {
1377         auto node = DynamicCast<SelectOverlayNode>(overlayNode);
1378         if (node) {
1379             node->ShowSelectOverlay(animation);
1380         }
1381     }
1382 
1383     if (shareOverlayInfo_->isUsingMouse && !shareOverlayInfo_->menuInfo.menuBuilder) {
1384         // if menu is "SelectOverlayMenuByRightClick", menuWrapper need containerId to set menu hot areas in subwindow
1385         auto menuWrapperPattern = overlayNode->GetPattern<MenuWrapperPattern>();
1386         CHECK_NULL_VOID(menuWrapperPattern);
1387         menuWrapperPattern->SetContainerId(containerId_);
1388         menuWrapperPattern->SetIsSelectOverlaySubWindowWrapper(true);
1389         UpdateRightClickSubWindowMenuProps(overlayNode);
1390     } else {
1391         auto selectOverlayNode = DynamicCast<SelectOverlayNode>(overlayNode);
1392         CHECK_NULL_VOID(selectOverlayNode);
1393         auto selectOverlayPattern = selectOverlayNode->GetPattern<SelectOverlayPattern>();
1394         CHECK_NULL_VOID(selectOverlayPattern);
1395         selectOverlayPattern->SetContainerId(containerId_);
1396         selectOverlayPattern->SetIsMenuShowInSubWindow(true);
1397     }
1398 }
1399 
UpdateRightClickSubWindowMenuProps(const RefPtr<FrameNode> & overlayNode)1400 void SelectContentOverlayManager::UpdateRightClickSubWindowMenuProps(const RefPtr<FrameNode>& overlayNode)
1401 {
1402     CHECK_NULL_VOID(shareOverlayInfo_);
1403     CHECK_NULL_VOID(overlayNode);
1404     auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
1405     CHECK_NULL_VOID(pipeline);
1406     auto menu = DynamicCast<FrameNode>(overlayNode->GetChildAtIndex(0));
1407     CHECK_NULL_VOID(menu);
1408     auto windowManager = pipeline->GetWindowManager();
1409     auto isContainerModal = pipeline->GetWindowModal() == WindowModal::CONTAINER_MODAL && windowManager &&
1410                             windowManager->GetWindowMode() == WindowMode::WINDOW_MODE_FLOATING;
1411     if (!isContainerModal) {
1412         auto props = menu->GetLayoutProperty<MenuLayoutProperty>();
1413         CHECK_NULL_VOID(props);
1414         OffsetF containerModalOffset = GetContainerModalOffset();
1415 
1416         props->UpdateMenuOffset(shareOverlayInfo_->rightClickOffset + containerModalOffset);
1417         TAG_LOGD(AceLogTag::ACE_SELECT_OVERLAY,
1418             "UpdateRightClickSubWindowMenuProps rightClickOffset:%{public}s containerModalOffset:%{public}s",
1419             shareOverlayInfo_->rightClickOffset.ToString().c_str(), containerModalOffset.ToString().c_str());
1420     }
1421     auto overlayNodePipeline = overlayNode->GetContext();
1422     CHECK_NULL_VOID(overlayNodePipeline);
1423     auto overlayNodeContainerId = overlayNodePipeline->GetInstanceId();
1424     ContainerScope scope(overlayNodeContainerId);
1425     menu->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1426 }
1427 
IsEnableSubWindowMenu()1428 bool SelectContentOverlayManager::IsEnableSubWindowMenu()
1429 {
1430     CHECK_NULL_RETURN(shareOverlayInfo_, false);
1431     CHECK_NULL_RETURN(shareOverlayInfo_->enableSubWindowMenu, false);
1432     auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
1433     CHECK_NULL_RETURN(pipeline, false);
1434     auto overlayManager = pipeline->GetSelectOverlayManager();
1435     CHECK_NULL_RETURN(overlayManager, false);
1436     auto showMode = overlayManager->GetMenuShowMode();
1437     TAG_LOGI(AceLogTag::ACE_SELECT_OVERLAY, "IsEnableSubWindowMenu showMode:%{public}d", showMode);
1438     if (showMode != TextMenuShowMode::PREFER_WINDOW) {
1439         return false;
1440     }
1441 #if defined(PREVIEW)
1442     TAG_LOGI(AceLogTag::ACE_SELECT_OVERLAY, "Unable to use the subWindow in the Previewer. Use default mode instead.");
1443     return false;
1444 #endif
1445     if (selectOverlayHolder_ && !selectOverlayHolder_->GetIsHostNodeEnableSubWindowMenu()) {
1446         TAG_LOGW(AceLogTag::ACE_SELECT_OVERLAY, "The callerNode does not support show menu in subwinodw.");
1447         return false;
1448     }
1449     auto containerId = Container::CurrentIdSafelyWithCheck();
1450     auto callerFrameNode = shareOverlayInfo_->callerFrameNode.Upgrade();
1451     CHECK_NULL_RETURN(callerFrameNode, false);
1452     return SubwindowManager::GetInstance()->IsWindowEnableSubWindowMenu(containerId, callerFrameNode);
1453 }
1454 
1455 // whether the menu is the default right click menu which root node is menu wrapper and is displayed in subwindow
IsRightClickSubWindowMenu()1456 bool SelectContentOverlayManager::IsRightClickSubWindowMenu()
1457 {
1458     CHECK_NULL_RETURN(shareOverlayInfo_, false);
1459     if (shareOverlayInfo_->isUsingMouse && !shareOverlayInfo_->menuInfo.menuBuilder) {
1460         auto selectOverlayNode = selectOverlayNode_.Upgrade();
1461         CHECK_NULL_RETURN(selectOverlayNode, false);
1462         auto menuWrapperPattern = selectOverlayNode->GetPattern<MenuWrapperPattern>();
1463         CHECK_NULL_RETURN(menuWrapperPattern, false);
1464         return menuWrapperPattern->GetIsSelectOverlaySubWindowWrapper();
1465     }
1466 
1467     return false;
1468 }
1469 
1470 // whether the menu is the text selection menu which root node is selectoverlay and is displayed in subwindow
IsSelectOverlaySubWindowMenu()1471 bool SelectContentOverlayManager::IsSelectOverlaySubWindowMenu()
1472 {
1473     CHECK_NULL_RETURN(shareOverlayInfo_, false);
1474     if (shareOverlayInfo_->isUsingMouse && !shareOverlayInfo_->menuInfo.menuBuilder) {
1475         return false;
1476     }
1477     RefPtr<FrameNode> menuNode;
1478     if (shareOverlayInfo_->isUsingMouse) {
1479         menuNode = selectOverlayNode_.Upgrade();
1480     } else {
1481         menuNode = menuNode_.Upgrade();
1482     }
1483     CHECK_NULL_RETURN(menuNode, false);
1484     auto selectOverlayNode = DynamicCast<SelectOverlayNode>(menuNode);
1485     CHECK_NULL_RETURN(selectOverlayNode, false);
1486     auto selectOverlayPattern = selectOverlayNode->GetPattern<SelectOverlayPattern>();
1487     CHECK_NULL_RETURN(selectOverlayPattern, false);
1488     return selectOverlayPattern->GetIsMenuShowInSubWindow();
1489 }
1490 
IsPasteOption(const RefPtr<UINode> & node)1491 bool SelectContentOverlayManager::IsPasteOption(const RefPtr<UINode>& node)
1492 {
1493     CHECK_NULL_RETURN(node, false);
1494     if (node->GetTag() != V2::OPTION_ETS_TAG) {
1495         return false;
1496     }
1497 
1498     auto child = node->GetFirstChild();
1499     CHECK_NULL_RETURN(child, false);
1500     if (child->GetTag() != V2::ROW_ETS_TAG) {
1501         return false;
1502     }
1503     auto grandChild = child->GetFirstChild();
1504     if (grandChild && grandChild->GetTag() == V2::PASTE_BUTTON_ETS_TAG) {
1505         return true;
1506     }
1507     return false;
1508 }
1509 
UpdateIsSingleHandle(bool isSingleHandle)1510 void SelectContentOverlayManager::UpdateIsSingleHandle(bool isSingleHandle)
1511 {
1512     if (IsOpen() && shareOverlayInfo_) {
1513         shareOverlayInfo_->isSingleHandle = isSingleHandle;
1514     }
1515 }
1516 } // namespace OHOS::Ace::NG
1517