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