• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 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/pattern/web/web_select_overlay.h"
17 
18 #include <algorithm>
19 #include <optional>
20 
21 #include "base/utils/utils.h"
22 #include "core/components_ng/manager/select_content_overlay/select_content_overlay_manager.h"
23 #include "core/components_ng/manager/select_overlay/select_overlay_manager.h"
24 #include "core/components_ng/pattern/web/web_pattern.h"
25 #include "core/components_ng/pattern/web/view_data_common.h"
26 #include "core/components_ng/pattern/web/transitional_node_info.h"
27 #include "core/components/web/resource/web_delegate.h"
28 #include "core/components/text_overlay/text_overlay_theme.h"
29 #include "core/event/event_info_convertor.h"
30 #include "nweb_handler.h"
31 
32 namespace OHOS::Ace::NG {
33 constexpr Dimension SELECT_HANDLE_DEFAULT_HEIGHT = 16.0_vp;
34 constexpr float SELECT_MENE_HEIGHT = 140.0f;
35 constexpr int32_t HALF = 2;
36 
RunQuickMenu(std::shared_ptr<OHOS::NWeb::NWebQuickMenuParams> params,std::shared_ptr<OHOS::NWeb::NWebQuickMenuCallback> callback)37 bool WebSelectOverlay::RunQuickMenu(std::shared_ptr<OHOS::NWeb::NWebQuickMenuParams> params,
38     std::shared_ptr<OHOS::NWeb::NWebQuickMenuCallback> callback)
39 {
40     needResetHandleReverse_ = false;
41     auto pattern = GetPattern<WebPattern>();
42     CHECK_NULL_RETURN(pattern, false);
43     auto pipeline = PipelineContext::GetCurrentContext();
44     CHECK_NULL_RETURN(pipeline, false);
45     CHECK_NULL_RETURN(params, false);
46     std::shared_ptr<OHOS::NWeb::NWebTouchHandleState> insertTouchHandle =
47         params->GetTouchHandleState(OHOS::NWeb::NWebTouchHandleState::TouchHandleType::INSERT_HANDLE);
48     std::shared_ptr<OHOS::NWeb::NWebTouchHandleState> beginTouchHandle =
49         params->GetTouchHandleState(OHOS::NWeb::NWebTouchHandleState::TouchHandleType::SELECTION_BEGIN_HANDLE);
50     std::shared_ptr<OHOS::NWeb::NWebTouchHandleState> endTouchHandle =
51         params->GetTouchHandleState(OHOS::NWeb::NWebTouchHandleState::TouchHandleType::SELECTION_END_HANDLE);
52     WebOverlayType overlayType = GetTouchHandleOverlayType(insertTouchHandle, beginTouchHandle, endTouchHandle);
53     if (overlayType == INVALID_OVERLAY) { return false; }
54     if (params->GetIsLongPressActived()) {
55         TAG_LOGI(AceLogTag::ACE_WEB, "ShowMagnifier");
56         pattern->ShowMagnifier(static_cast<int>(pattern->touchPointX), static_cast<int>(pattern->touchPointY));
57         return false;
58     }
59     selectTemporarilyHidden_ = false;
60     selectTemporarilyHiddenByScroll_ = false;
61     SelectOverlayInfo selectInfo;
62     selectInfo.isSingleHandle = (overlayType == INSERT_OVERLAY);
63     UpdateRunQuickMenuSelectInfo(selectInfo, params, insertTouchHandle, beginTouchHandle, endTouchHandle);
64     if (isQuickMenuMouseTrigger_) {
65         return false;
66     }
67     SetMenuOptions(selectInfo, params, callback);
68     RegisterSelectOverlayEvent(selectInfo);
69     selectInfo.ancestorViewPort = pattern->GetViewPort();
70     if (selectInfo.isNewAvoid) {
71         ShowMenu();
72         selectInfo.menuInfo.menuIsShow = true;
73     }
74     dropParams_ = params;
75     selectMenuInfo_ = selectInfo.menuInfo;
76     insertHandle_ = insertTouchHandle;
77     startSelectionHandle_ = beginTouchHandle;
78     endSelectionHandle_ = endTouchHandle;
79     isShowHandle_ = true;
80     webSelectInfo_ = selectInfo;
81     auto host = pattern->GetHost();
82     CHECK_NULL_RETURN(host, false);
83     StartListenSelectOverlayParentScroll(host);
84     ProcessOverlay({ .animation = true });
85     return true;
86 }
87 
OnTouchSelectionChanged(std::shared_ptr<OHOS::NWeb::NWebTouchHandleState> insertHandle,std::shared_ptr<OHOS::NWeb::NWebTouchHandleState> startSelectionHandle,std::shared_ptr<OHOS::NWeb::NWebTouchHandleState> endSelectionHandle)88 void WebSelectOverlay::OnTouchSelectionChanged(std::shared_ptr<OHOS::NWeb::NWebTouchHandleState> insertHandle,
89     std::shared_ptr<OHOS::NWeb::NWebTouchHandleState> startSelectionHandle,
90     std::shared_ptr<OHOS::NWeb::NWebTouchHandleState> endSelectionHandle)
91 {
92     needResetHandleReverse_ = false;
93     auto pattern = GetPattern<WebPattern>();
94     CHECK_NULL_VOID(pattern);
95     WebOverlayType overlayType = GetTouchHandleOverlayType(insertHandle, startSelectionHandle, endSelectionHandle);
96     if (overlayType == INVALID_OVERLAY) {
97         pattern->CloseSelectOverlay();
98         return;
99     }
100     auto pipeline = PipelineContext::GetCurrentContext();
101     CHECK_NULL_VOID(pipeline);
102     insertHandle_ = insertHandle;
103     startSelectionHandle_ = startSelectionHandle;
104     endSelectionHandle_ = endSelectionHandle;
105     if (selectTemporarilyHidden_ || selectTemporarilyHiddenByScroll_) {
106         TAG_LOGD(AceLogTag::ACE_WEB, "select menu temporarily hidden");
107         return;
108     }
109     if (!isShowHandle_) {
110         if (overlayType == INSERT_OVERLAY) {
111             SelectOverlayInfo selectInfo;
112             selectInfo.isSingleHandle = true;
113             selectInfo.firstHandle.paintRect = ComputeTouchHandleRect(insertHandle_);
114             CheckHandles(selectInfo.firstHandle, insertHandle_);
115             selectInfo.secondHandle.isShow = false;
116             selectInfo.menuInfo.menuDisable = true;
117             selectInfo.menuInfo.menuIsShow = false;
118             selectInfo.hitTestMode = HitTestMode::HTMDEFAULT;
119             RegisterSelectOverlayEvent(selectInfo);
120             selectInfo.isHandleLineShow = false;
121             isShowHandle_ = true;
122             webSelectInfo_ = selectInfo;
123             ProcessOverlay({ .animation = true });
124             return;
125         }
126     } else {
127         if (overlayType == INSERT_OVERLAY) {
128             if (!selectOverlayDragging_) {
129                 UpdateTouchHandleForOverlay(false);
130             }
131         } else {
132             UpdateSelectHandleInfo();
133             if (!selectOverlayDragging_) {
134                 UpdateTouchHandleForOverlay(false);
135             }
136         }
137     }
138 }
139 
RegisterSelectOverlayEvent(SelectOverlayInfo & selectInfo)140 void WebSelectOverlay::RegisterSelectOverlayEvent(SelectOverlayInfo& selectInfo)
141 {
142     selectInfo.onClick = [weak = AceType::WeakClaim(this)](const GestureEvent& info, bool isFirst) {
143         auto overlay = weak.Upgrade();
144         CHECK_NULL_VOID(overlay);
145         overlay->OnOverlayClick(info, isFirst);
146     };
147 }
148 
IsSelectHandleReverse()149 bool WebSelectOverlay::IsSelectHandleReverse()
150 {
151     if (startSelectionHandle_->GetTouchHandleType() ==
152         OHOS::NWeb::NWebTouchHandleState::SELECTION_BEGIN_HANDLE &&
153         endSelectionHandle_->GetTouchHandleType() ==
154         OHOS::NWeb::NWebTouchHandleState::SELECTION_BEGIN_HANDLE) {
155         return true;
156     } else if (startSelectionHandle_->GetTouchHandleType() ==
157         OHOS::NWeb::NWebTouchHandleState::SELECTION_END_HANDLE &&
158         endSelectionHandle_->GetTouchHandleType() ==
159         OHOS::NWeb::NWebTouchHandleState::SELECTION_END_HANDLE) {
160         return true;
161     }
162     return false;
163 }
164 
UpdateSelectHandleInfo()165 void WebSelectOverlay::UpdateSelectHandleInfo()
166 {
167     bool needReverse = IsSelectHandleReverse();
168     SelectHandleInfo handleInfo;
169     if (!needReverse) {
170         if (!isCurrentStartHandleDragging_) {
171             handleInfo.paintRect = ComputeTouchHandleRect(startSelectionHandle_);
172             CheckHandles(handleInfo, startSelectionHandle_);
173             webSelectInfo_.firstHandle = handleInfo;
174             UpdateFirstHandleOffset();
175         } else {
176             handleInfo.paintRect = ComputeTouchHandleRect(endSelectionHandle_);
177             CheckHandles(handleInfo, endSelectionHandle_);
178             webSelectInfo_.secondHandle = handleInfo;
179             UpdateSecondHandleOffset();
180         }
181     } else {
182         if (!isCurrentStartHandleDragging_) {
183             handleInfo.paintRect = ComputeTouchHandleRect(endSelectionHandle_);
184             CheckHandles(handleInfo, endSelectionHandle_);
185             webSelectInfo_.firstHandle = handleInfo;
186             UpdateFirstHandleOffset();
187         } else {
188             handleInfo.paintRect = ComputeTouchHandleRect(startSelectionHandle_);
189             CheckHandles(handleInfo, startSelectionHandle_);
190             webSelectInfo_.secondHandle = handleInfo;
191             UpdateSecondHandleOffset();
192         }
193     }
194 }
195 
OnSelectHandleStart(const GestureEvent & event,bool isFirst)196 void WebSelectOverlay::OnSelectHandleStart(const GestureEvent& event, bool isFirst)
197 {
198 }
199 
ChangeHandleHeight(const GestureEvent & event,bool isFirst)200 RectF WebSelectOverlay::ChangeHandleHeight(const GestureEvent& event, bool isFirst)
201 {
202     auto touchOffset = event.GetLocalLocation();
203     auto handle = isFirst ? webSelectInfo_.firstHandle : webSelectInfo_.secondHandle;
204     auto handleHeight = SELECT_HANDLE_DEFAULT_HEIGHT.ConvertToPx();
205     handleHeight = std::min(static_cast<float>(handleHeight), handle.paintRect.Height());
206     bool isTouchHandleCircle = isFirst ?
207         LessNotEqual(touchOffset.GetY(), handle.paintRect.Top()) :
208         GreatNotEqual(touchOffset.GetY(), handle.paintRect.Bottom());
209     if (isFirst) {
210         if (!isTouchHandleCircle) {
211             handle.paintRect.SetTop(static_cast<float>(touchOffset.GetY()) - handleHeight / HALF);
212         }
213         handle.paintRect.SetHeight(handleHeight);
214         webSelectInfo_.firstHandle = handle;
215         webSelectInfo_.firstHandle.isCircleShow = false;
216         UpdateFirstHandleOffset();
217     } else {
218         auto handleOffsetY = isTouchHandleCircle
219                             ? handle.paintRect.Bottom() - handleHeight
220                             : static_cast<float>(touchOffset.GetY()) - handleHeight / HALF;
221         handle.paintRect.SetTop(handleOffsetY);
222         handle.paintRect.SetHeight(handleHeight);
223         webSelectInfo_.secondHandle = handle;
224         webSelectInfo_.secondHandle.isCircleShow = false;
225         UpdateSecondHandleOffset();
226     }
227     return handle.paintRect;
228 }
229 
OnMagnifierHandleMove(const RectF & handleRect,bool isFirst)230 void WebSelectOverlay::OnMagnifierHandleMove(const RectF& handleRect, bool isFirst)
231 {
232     auto pattern = GetPattern<WebPattern>();
233     CHECK_NULL_VOID(pattern);
234     pattern->OnMagnifierHandleMove(handleRect, isFirst);
235 }
236 
UpdateTouchHandleForOverlay(bool fromOverlay)237 void WebSelectOverlay::UpdateTouchHandleForOverlay(bool fromOverlay)
238 {
239     auto pattern = GetPattern<WebPattern>();
240     CHECK_NULL_VOID(pattern);
241     WebOverlayType overlayType = GetTouchHandleOverlayType(insertHandle_, startSelectionHandle_, endSelectionHandle_);
242     if (overlayType == INVALID_OVERLAY) {
243         pattern->CloseSelectOverlay();
244         return;
245     }
246     SelectHandleInfo firstHandleInfo;
247     SelectHandleInfo secondHandleInfo;
248     if (overlayType == INSERT_OVERLAY) {
249         if (!fromOverlay) {
250             HideMenu(true);
251             webSelectInfo_.menuInfo.menuIsShow = false;
252         }
253         firstHandleInfo.paintRect = ComputeTouchHandleRect(insertHandle_);
254         CheckHandles(firstHandleInfo, insertHandle_);
255         firstHandleInfo.needLayout = true;
256         webSelectInfo_.firstHandle = firstHandleInfo;
257         if (SelectOverlayIsOn()) {
258             UpdateFirstHandleOffset();
259         } else {
260             ProcessOverlay({ .animation = true });
261             isShowHandle_ = true;
262         }
263     } else {
264         if (selectTemporarilyHidden_ || selectTemporarilyHiddenByScroll_) {
265             return;
266         }
267         firstHandleInfo.paintRect = ComputeTouchHandleRect(startSelectionHandle_);
268         secondHandleInfo.paintRect = ComputeTouchHandleRect(endSelectionHandle_);
269         CheckHandles(firstHandleInfo, startSelectionHandle_);
270         CheckHandles(secondHandleInfo, endSelectionHandle_);
271         webSelectInfo_.firstHandle = firstHandleInfo;
272         webSelectInfo_.secondHandle = secondHandleInfo;
273         if (firstHandleInfo.isShow || secondHandleInfo.isShow) {
274             webSelectInfo_.isNewAvoid = false;
275         }
276         webSelectInfo_.handleReverse = false;
277         if (SelectOverlayIsOn()) {
278             UpdateSelectMenuOptions();
279             UpdateAllHandlesOffset();
280         } else {
281             ProcessOverlay({ .animation = true });
282             isShowHandle_ = true;
283         }
284     }
285 }
286 
HideMagnifier()287 void WebSelectOverlay::HideMagnifier()
288 {
289     auto pattern = GetPattern<WebPattern>();
290     CHECK_NULL_VOID(pattern);
291     pattern->HideMagnifier();
292 }
293 
SetMenuOptions(SelectOverlayInfo & selectInfo,std::shared_ptr<OHOS::NWeb::NWebQuickMenuParams> params,std::shared_ptr<OHOS::NWeb::NWebQuickMenuCallback> callback)294 void WebSelectOverlay::SetMenuOptions(SelectOverlayInfo& selectInfo,
295     std::shared_ptr<OHOS::NWeb::NWebQuickMenuParams> params,
296     std::shared_ptr<OHOS::NWeb::NWebQuickMenuCallback> callback)
297 {
298     quickMenuCallback_ = callback;
299     auto pattern = GetPattern<WebPattern>();
300     CHECK_NULL_VOID(pattern);
301     auto delegate = pattern->delegate_;
302     CHECK_NULL_VOID(delegate);
303     auto copyOption = delegate->GetCopyOptionMode();
304     uint32_t flags = static_cast<uint32_t>(params->GetEditStateFlags());
305     if (!(flags & OHOS::NWeb::NWebQuickMenuParams::QM_EF_CAN_CUT) ||
306         copyOption == OHOS::NWeb::NWebPreference::CopyOptionMode::NONE) {
307         selectInfo.menuInfo.showCut = false;
308     } else {
309         selectInfo.menuInfo.showCut = true;
310     }
311     if (!(flags & OHOS::NWeb::NWebQuickMenuParams::QM_EF_CAN_COPY)) {
312         selectInfo.menuInfo.showCopy = false;
313     } else {
314         selectInfo.menuInfo.showCopy = true;
315     }
316     if (!(flags & OHOS::NWeb::NWebQuickMenuParams::QM_EF_CAN_PASTE)) {
317         selectInfo.menuInfo.showPaste = false;
318     } else {
319         selectInfo.menuInfo.showPaste = true;
320     }
321     if (!(flags & OHOS::NWeb::NWebQuickMenuParams::QM_EF_CAN_SELECT_ALL)) {
322         selectInfo.menuInfo.showCopyAll = false;
323     } else {
324         selectInfo.menuInfo.showCopyAll = true;
325     }
326     auto value = GetSelectedText();
327     auto queryWord = std::regex_replace(value, std::regex("^\\s+|\\s+$"), "");
328     if (!queryWord.empty()) {
329         selectInfo.menuInfo.showSearch = true;
330         selectInfo.menuInfo.showTranslate = true;
331     } else {
332         selectInfo.menuInfo.showSearch = false;
333         selectInfo.menuInfo.showTranslate = false;
334     }
335 }
336 
HideHandleAndQuickMenuIfNecessary(bool hide,bool isScroll)337 void WebSelectOverlay::HideHandleAndQuickMenuIfNecessary(bool hide, bool isScroll)
338 {
339     WebOverlayType overlayType = GetTouchHandleOverlayType(insertHandle_, startSelectionHandle_, endSelectionHandle_);
340     TAG_LOGI(AceLogTag::ACE_WEB,
341         "HideHandleAndQuickMenuIfNecessary hide:%{public}d, overlayType:%{public}d, isScroll:%{public}d",
342         hide, overlayType, isScroll);
343     if (overlayType != SELECTION_OVERLAY) {
344         return;
345     }
346     SelectHandleInfo firstInfo;
347     SelectHandleInfo secondInfo;
348     if (!isScroll) {
349         selectTemporarilyHidden_ = hide;
350         if (selectTemporarilyHiddenByScroll_) {
351             return;
352         }
353     }
354     if (hide) {
355         HideMenu(true);
356         webSelectInfo_.menuInfo.menuIsShow = false;
357         firstInfo.isShow = false;
358         firstInfo.paintRect = ComputeTouchHandleRect(startSelectionHandle_);
359         secondInfo.isShow = false;
360         secondInfo.paintRect = ComputeTouchHandleRect(endSelectionHandle_);
361         webSelectInfo_.firstHandle = firstInfo;
362         webSelectInfo_.secondHandle = secondInfo;
363         UpdateAllHandlesOffset();
364     } else {
365         firstInfo.paintRect = ComputeTouchHandleRect(startSelectionHandle_);
366         secondInfo.paintRect = ComputeTouchHandleRect(endSelectionHandle_);
367         CheckHandles(firstInfo, startSelectionHandle_);
368         CheckHandles(secondInfo, endSelectionHandle_);
369         webSelectInfo_.firstHandle = firstInfo;
370         webSelectInfo_.secondHandle = secondInfo;
371         if (firstInfo.isShow || secondInfo.isShow) {
372             ShowMenu();
373             webSelectInfo_.menuInfo.menuIsShow = true;
374             webSelectInfo_.isNewAvoid = false;
375         } else if (dropParams_) {
376             bool isNewAvoid = false;
377             auto selectArea = ComputeClippedSelectionBounds(
378                 dropParams_, startSelectionHandle_, endSelectionHandle_, isNewAvoid);
379             webSelectInfo_.isNewAvoid = false;
380             webSelectInfo_.selectArea = selectArea;
381         }
382         UpdateAllHandlesOffset();
383     }
384 }
385 
OnParentScrollStartOrEndCallback(bool isEnd)386 void WebSelectOverlay::OnParentScrollStartOrEndCallback(bool isEnd)
387 {
388     if (webSelectInfo_.isSingleHandle && !isEnd)  {
389         webSelectInfo_.menuInfo.menuIsShow = false;
390         return;
391     }
392     selectTemporarilyHiddenByScroll_ = !isEnd;
393     if (selectTemporarilyHidden_) {
394         return;
395     }
396     HideHandleAndQuickMenuIfNecessary(selectTemporarilyHiddenByScroll_, true);
397 }
398 
StopListenSelectOverlayParentScroll(const RefPtr<FrameNode> & host)399 void WebSelectOverlay::StopListenSelectOverlayParentScroll(const RefPtr<FrameNode>& host)
400 {
401     CHECK_NULL_VOID(host);
402     auto context = host->GetContext();
403     CHECK_NULL_VOID(context);
404     auto manager = context->GetSelectOverlayManager();
405     CHECK_NULL_VOID(manager);
406     manager->RemoveScrollCallback(host->GetId());
407 }
408 
RegisterSelectOverlayParentScrollCallback(int32_t parentId,int32_t callbackId)409 void WebSelectOverlay::RegisterSelectOverlayParentScrollCallback(int32_t parentId, int32_t callbackId)
410 {
411     auto pattern = GetPattern<WebPattern>();
412     CHECK_NULL_VOID(pattern);
413     auto host = pattern->GetHost();
414     CHECK_NULL_VOID(host);
415     auto context = host->GetContext();
416     CHECK_NULL_VOID(context);
417     auto manager = context->GetSelectOverlayManager();
418     CHECK_NULL_VOID(manager);
419     auto scrollCallback = [weak = WeakClaim(this)](Axis axis, float offset, int32_t source) {
420         auto client = weak.Upgrade();
421         CHECK_NULL_VOID(client);
422         if (source == SCROLL_FROM_START) {
423             client->OnParentScrollStartOrEndCallback(false);
424         } else if (source == -1) {
425             client->OnParentScrollStartOrEndCallback(true);
426         }
427     };
428     manager->RegisterScrollCallback(parentId, callbackId, scrollCallback);
429 }
430 
StartListenSelectOverlayParentScroll(const RefPtr<FrameNode> & host)431 void WebSelectOverlay::StartListenSelectOverlayParentScroll(const RefPtr<FrameNode>& host)
432 {
433     if (!scrollableParentInfo_.hasParent) {
434         TAG_LOGI(AceLogTag::ACE_WEB, "has no scrollable parent");
435         return;
436     }
437     CHECK_NULL_VOID(host);
438     auto context = host->GetContext();
439     CHECK_NULL_VOID(context);
440     auto hostId = host->GetId();
441     if (!scrollableParentInfo_.parentIds.empty()) {
442         for (const auto& scrollId : scrollableParentInfo_.parentIds) {
443             RegisterSelectOverlayParentScrollCallback(scrollId, hostId);
444         }
445         return;
446     }
447     auto parent = host->GetParent();
448     while (parent && parent->GetTag() != V2::PAGE_ETS_TAG) {
449         auto parentNode = AceType::DynamicCast<FrameNode>(parent);
450         if (parentNode) {
451             auto pattern = parentNode->GetPattern<ScrollablePattern>();
452             if (pattern) {
453                 scrollableParentInfo_.parentIds.emplace_back(parentNode->GetId());
454                 RegisterSelectOverlayParentScrollCallback(parentNode->GetId(), hostId);
455             }
456         }
457         parent = parent->GetParent();
458     }
459     scrollableParentInfo_.hasParent = !scrollableParentInfo_.parentIds.empty();
460     TAG_LOGI(AceLogTag::ACE_WEB, "find scrollable parent %{public}d", scrollableParentInfo_.hasParent);
461 }
462 
UpdateRunQuickMenuSelectInfo(SelectOverlayInfo & selectInfo,std::shared_ptr<OHOS::NWeb::NWebQuickMenuParams> params,std::shared_ptr<OHOS::NWeb::NWebTouchHandleState> insertTouchHandle,std::shared_ptr<OHOS::NWeb::NWebTouchHandleState> beginTouchHandle,std::shared_ptr<OHOS::NWeb::NWebTouchHandleState> endTouchHandle)463 void WebSelectOverlay::UpdateRunQuickMenuSelectInfo(SelectOverlayInfo& selectInfo,
464     std::shared_ptr<OHOS::NWeb::NWebQuickMenuParams> params,
465     std::shared_ptr<OHOS::NWeb::NWebTouchHandleState> insertTouchHandle,
466     std::shared_ptr<OHOS::NWeb::NWebTouchHandleState> beginTouchHandle,
467     std::shared_ptr<OHOS::NWeb::NWebTouchHandleState> endTouchHandle)
468 {
469     selectInfo.hitTestMode = HitTestMode::HTMDEFAULT;
470     isQuickMenuMouseTrigger_ = false;
471     auto pattern = GetPattern<WebPattern>();
472     if (selectInfo.isSingleHandle) {
473         selectInfo.firstHandle.paintRect = ComputeTouchHandleRect(insertTouchHandle);
474         CheckHandles(selectInfo.firstHandle, insertTouchHandle);
475         selectInfo.secondHandle.isShow = false;
476         if (!selectInfo.firstHandle .isShow) {
477             selectInfo.isNewAvoid = true;
478         }
479     } else {
480         selectInfo.firstHandle.paintRect = ComputeTouchHandleRect(beginTouchHandle);
481         selectInfo.secondHandle.paintRect = ComputeTouchHandleRect(endTouchHandle);
482         CheckHandles(selectInfo.firstHandle, beginTouchHandle);
483         CheckHandles(selectInfo.secondHandle, endTouchHandle);
484         QuickMenuIsNeedNewAvoid(selectInfo, params, beginTouchHandle, endTouchHandle);
485         if (pattern && !(pattern->onCreateMenuCallback_ && pattern->onMenuItemClick_)) {
486             selectInfo.menuOptionItems = pattern->menuOptionParam_;
487         }
488     }
489     selectInfo.menuInfo.menuIsShow = true;
490     selectInfo.handleReverse = false;
491     if (pattern && pattern->onCreateMenuCallback_ && pattern->onMenuItemClick_) {
492         selectInfo.onCreateCallback.onCreateMenuCallback = pattern->onCreateMenuCallback_;
493         selectInfo.onCreateCallback.onMenuItemClick = pattern->onMenuItemClick_;
494         auto textRange = [](int32_t& start, int32_t& end) {
495             start = -1;
496             end = -1;
497         };
498         selectInfo.onCreateCallback.textRangeCallback = textRange;
499     }
500 }
501 
QuickMenuIsNeedNewAvoid(SelectOverlayInfo & selectInfo,std::shared_ptr<OHOS::NWeb::NWebQuickMenuParams> params,std::shared_ptr<OHOS::NWeb::NWebTouchHandleState> startHandle,std::shared_ptr<OHOS::NWeb::NWebTouchHandleState> endHandle)502 void WebSelectOverlay::QuickMenuIsNeedNewAvoid(
503     SelectOverlayInfo& selectInfo,
504     std::shared_ptr<OHOS::NWeb::NWebQuickMenuParams> params,
505     std::shared_ptr<OHOS::NWeb::NWebTouchHandleState> startHandle,
506     std::shared_ptr<OHOS::NWeb::NWebTouchHandleState> endHandle)
507 {
508     isQuickMenuMouseTrigger_ = false;
509     if (!selectInfo.firstHandle.isShow && !selectInfo.secondHandle.isShow) {
510         selectInfo.isNewAvoid = true;
511         if ((startHandle->GetEdgeHeight() == 0 && startHandle->GetTouchHandleId() == -1) &&
512             (endHandle->GetEdgeHeight() == 0 && endHandle->GetTouchHandleId() == -1)) {
513             isQuickMenuMouseTrigger_ = true;
514             selectInfo.selectArea = ComputeMouseClippedSelectionBounds(
515                 params->GetSelectX(), params->GetSelectY(), params->GetSelectWidth(), params->GetSelectXHeight());
516         } else {
517             selectInfo.selectArea =
518                 ComputeClippedSelectionBounds(params, startHandle, endHandle, selectInfo.isNewAvoid);
519         }
520     } else {
521         float selectX = params->GetSelectX();
522         float selectY = params->GetSelectY();
523         float selectWidth = params->GetSelectWidth();
524         float selectHeight = params->GetSelectXHeight();
525         selectInfo.selectArea = RectF(selectX, selectY, selectWidth, selectHeight);
526     }
527 }
528 
ComputeClippedSelectionBounds(std::shared_ptr<OHOS::NWeb::NWebQuickMenuParams> params,std::shared_ptr<OHOS::NWeb::NWebTouchHandleState> startHandle,std::shared_ptr<OHOS::NWeb::NWebTouchHandleState> endHandle,bool & isNewAvoid)529 RectF WebSelectOverlay::ComputeClippedSelectionBounds(
530     std::shared_ptr<OHOS::NWeb::NWebQuickMenuParams> params,
531     std::shared_ptr<OHOS::NWeb::NWebTouchHandleState> startHandle,
532     std::shared_ptr<OHOS::NWeb::NWebTouchHandleState> endHandle, bool& isNewAvoid)
533 {
534     auto pattern = GetPattern<WebPattern>();
535     CHECK_NULL_RETURN(pattern, RectF());
536     auto pipeline = PipelineBase::GetCurrentContext();
537     CHECK_NULL_RETURN(pipeline, RectF());
538     auto host = pattern->GetHost();
539     CHECK_NULL_RETURN(host, RectF());
540     float selectX = params->GetSelectX();
541     float selectY = params->GetSelectY();
542     float selectWidth = params->GetSelectWidth();
543     float selectHeight = params->GetSelectXHeight();
544     float viewPortX = static_cast<float>((startHandle->GetViewPortX() + endHandle->GetViewPortX())) / 2;
545     float viewPortY = static_cast<float>((startHandle->GetViewPortY() + endHandle->GetViewPortY())) / 2;
546     auto offset = pattern->GetCoordinatePoint().value_or(OffsetF());
547     RectF visibleRect;
548     RectF visibleInnerRect;
549     RectF frameRect;
550     host->GetVisibleRectWithClip(visibleRect, visibleInnerRect, frameRect);
551     auto visibleTop = visibleInnerRect.Top();
552     auto visibleBottom = visibleInnerRect.Bottom();
553     isNewAvoid = true;
554     if (LessOrEqual(visibleBottom, selectY + viewPortY + offset.GetY()) ||
555         LessOrEqual(selectY + selectHeight + offset.GetY(), visibleTop)) {
556         isNewAvoid = false;
557         return RectF();
558     } else if (LessOrEqual(selectY + offset.GetY(), visibleTop) &&
559         LessOrEqual(visibleBottom, selectY + viewPortY + selectHeight + offset.GetY())) {
560         return RectF(offset.GetX(), offset.GetY(), pattern->drawSize_.Width(), pattern->drawSize_.Height());
561     }
562     auto theme = pipeline->GetTheme<TextOverlayTheme>();
563     float radius = theme ? theme->GetHandleHotZoneRadius().ConvertToPx() : 0.0;
564     if (LessOrEqual(visibleBottom, selectY + viewPortY + startHandle->GetEdgeHeight() + offset.GetY())) {
565         selectX = startHandle->GetX() + offset.GetX();
566         selectY = startHandle->GetY() + offset.GetY() - radius - startHandle->GetEdgeHeight() - SELECT_MENE_HEIGHT;
567         selectWidth = SelectHandleInfo::GetDefaultLineWidth().ConvertToPx();
568     } else if (LessOrEqual(selectY + selectHeight - endHandle->GetEdgeHeight() + offset.GetY(), visibleTop)) {
569         selectX = endHandle->GetX() + offset.GetX();
570         selectY = endHandle->GetY() + offset.GetY() + radius;
571         selectWidth = SelectHandleInfo::GetDefaultLineWidth().ConvertToPx();
572     } else {
573         selectX = selectX + viewPortX + offset.GetX();
574         selectY = selectY + viewPortY + offset.GetY() - SELECT_MENE_HEIGHT - radius;
575         if (selectY < offset.GetY())
576             selectY = offset.GetY();
577     }
578     return RectF(selectX, selectY, selectWidth, SELECT_MENE_HEIGHT);
579 }
580 
ComputeMouseClippedSelectionBounds(int32_t x,int32_t y,int32_t w,int32_t h)581 RectF WebSelectOverlay::ComputeMouseClippedSelectionBounds(int32_t x, int32_t y, int32_t w, int32_t h)
582 {
583     auto pattern = GetPattern<WebPattern>();
584     CHECK_NULL_RETURN(pattern, RectF());
585     auto offset = pattern->GetCoordinatePoint().value_or(OffsetF());
586     float selectX = offset.GetX() + x;
587     float selectY = offset.GetY();
588     float selectWidth = w;
589     float selectHeight = h;
590     if (LessOrEqual(pattern->GetHostFrameSize().value_or(SizeF()).Height(), y)) {
591         selectY += pattern->GetHostFrameSize().value_or(SizeF()).Height();
592     } else if (y + h <= 0) {
593         selectY -= h;
594     } else {
595         selectY += y;
596     }
597     return RectF(selectX, selectY, selectWidth, selectHeight);
598 }
599 
CheckHandles(SelectHandleInfo & handleInfo,const std::shared_ptr<OHOS::NWeb::NWebTouchHandleState> & handle)600 void WebSelectOverlay::CheckHandles(SelectHandleInfo& handleInfo,
601     const std::shared_ptr<OHOS::NWeb::NWebTouchHandleState>& handle)
602 {
603     auto pattern = GetPattern<WebPattern>();
604     CHECK_NULL_VOID(pattern);
605     CHECK_NULL_VOID(handle);
606     auto pipeline = PipelineBase::GetCurrentContext();
607     CHECK_NULL_VOID(pipeline);
608     int y = static_cast<int32_t>(handle->GetY() / pipeline->GetDipScale());
609     int edgeHeight = static_cast<int32_t>(handle->GetEdgeHeight() / pipeline->GetDipScale()) - 1;
610     if (handle->GetAlpha() <= 0 || y < edgeHeight) {
611         handleInfo.isShow = false;
612         return;
613     }
614     auto host = pattern->GetHost();
615     CHECK_NULL_VOID(host);
616     float viewPortY = handle->GetViewPortY();
617     RectF visibleRect;
618     RectF visibleInnerRect;
619     RectF frameRect;
620     host->GetVisibleRectWithClip(visibleRect, visibleInnerRect, frameRect);
621     visibleInnerRect.SetRect(visibleInnerRect.GetX(), visibleInnerRect.GetY() + viewPortY - 1,
622         visibleInnerRect.Width(), visibleInnerRect.Height() - viewPortY + 1);
623     auto paintRect = handleInfo.paintRect;
624     PointF bottomPoint = { paintRect.Left(), paintRect.Bottom() };
625     PointF topPoint = { paintRect.Left(), paintRect.Top() };
626     handleInfo.isShow = (visibleInnerRect.IsInRegion(bottomPoint) && visibleInnerRect.IsInRegion(topPoint));
627 }
628 
ComputeTouchHandleRect(std::shared_ptr<OHOS::NWeb::NWebTouchHandleState> touchHandle)629 RectF WebSelectOverlay::ComputeTouchHandleRect(std::shared_ptr<OHOS::NWeb::NWebTouchHandleState> touchHandle)
630 {
631     auto pattern = GetPattern<WebPattern>();
632     CHECK_NULL_RETURN(pattern, RectF());
633     CHECK_NULL_RETURN(touchHandle, RectF());
634     RectF paintRect;
635     auto offset = pattern->GetCoordinatePoint().value_or(OffsetF());
636     auto size = pattern->GetHostFrameSize().value_or(SizeF());
637     float edgeHeight = touchHandle->GetEdgeHeight();
638     float x = touchHandle->GetX();
639     float y = touchHandle->GetY();
640     if (x > size.Width()) {
641         x = offset.GetX() + size.Width();
642     } else {
643         x = x + offset.GetX();
644     }
645 
646     if (y < 0) {
647         y = offset.GetY();
648     } else if (y > size.Height()) {
649         y = offset.GetY() + size.Height();
650     } else {
651         float diff = 0;
652         auto pipeline = PipelineBase::GetCurrentContext();
653         if (pipeline) {
654             auto dipScale = pipeline->GetDipScale();
655             if (dipScale != 0) {
656                 diff = edgeHeight - static_cast<int32_t>(static_cast<int32_t>(edgeHeight / dipScale) * dipScale);
657             }
658         }
659         y = y + offset.GetY() - edgeHeight + diff;
660     }
661 
662     paintRect.SetOffset({ x, y });
663     paintRect.SetSize({ SelectHandleInfo::GetDefaultLineWidth().ConvertToPx(), edgeHeight });
664     return paintRect;
665 }
666 
GetTouchHandleOverlayType(std::shared_ptr<OHOS::NWeb::NWebTouchHandleState> insertHandle,std::shared_ptr<OHOS::NWeb::NWebTouchHandleState> startSelectionHandle,std::shared_ptr<OHOS::NWeb::NWebTouchHandleState> endSelectionHandle)667 WebOverlayType WebSelectOverlay::GetTouchHandleOverlayType(
668     std::shared_ptr<OHOS::NWeb::NWebTouchHandleState> insertHandle,
669     std::shared_ptr<OHOS::NWeb::NWebTouchHandleState> startSelectionHandle,
670     std::shared_ptr<OHOS::NWeb::NWebTouchHandleState> endSelectionHandle)
671 {
672     if (IsTouchHandleValid(insertHandle) && !IsTouchHandleValid(startSelectionHandle) &&
673         !IsTouchHandleValid(endSelectionHandle)) {
674         return INSERT_OVERLAY;
675     }
676 
677     if (!IsTouchHandleValid(insertHandle) && IsTouchHandleValid(startSelectionHandle) &&
678         IsTouchHandleValid(endSelectionHandle)) {
679         return SELECTION_OVERLAY;
680     }
681 
682     return INVALID_OVERLAY;
683 }
684 
RegisterSelectOverLayOnClose(SelectOverlayInfo & selectInfo)685 void WebSelectOverlay::RegisterSelectOverLayOnClose(SelectOverlayInfo& selectInfo)
686 {
687     selectInfo.onClose = [weak = AceType::WeakClaim(this)] (bool isGlobalTouchEvent) {
688         if (!isGlobalTouchEvent) {
689             return;
690         }
691         TAG_LOGI(AceLogTag::ACE_WEB, "globalTouchEvent, close web select overLayer.");
692         auto selectOverlay = weak.Upgrade();
693         CHECK_NULL_VOID(selectOverlay);
694         selectOverlay->CloseOverlay(false, CloseReason::CLOSE_REASON_CLICK_OUTSIDE);
695         selectOverlay->SelectCancel();
696     };
697 }
698 
SelectCancel()699 void WebSelectOverlay::SelectCancel()
700 {
701     CHECK_NULL_VOID(quickMenuCallback_);
702     quickMenuCallback_->Cancel();
703     insertHandle_ = nullptr;
704     startSelectionHandle_ = nullptr;
705     endSelectionHandle_ = nullptr;
706     quickMenuCallback_ = nullptr;
707 }
708 
UpdateClippedSelectionBounds(int32_t x,int32_t y,int32_t w,int32_t h)709 void WebSelectOverlay::UpdateClippedSelectionBounds(int32_t x, int32_t y, int32_t w, int32_t h)
710 {
711     webSelectInfo_.selectArea = ComputeMouseClippedSelectionBounds(x, y, w, h);
712 }
713 
ChangeVisibilityOfQuickMenu()714 void WebSelectOverlay::ChangeVisibilityOfQuickMenu()
715 {
716     WebOverlayType overlayType = GetTouchHandleOverlayType(insertHandle_, startSelectionHandle_, endSelectionHandle_);
717     if (overlayType == SELECTION_OVERLAY && !selectTemporarilyHidden_ && !selectTemporarilyHiddenByScroll_) {
718         bool isMenuShow = IsShowMenu();
719         if (isMenuShow) {
720             HideMenu(true);
721             SetMenuIsShow(false);
722             webSelectInfo_.menuInfo.menuIsShow = false;
723         } else {
724             ShowMenu();
725             SetMenuIsShow(true);
726             webSelectInfo_.menuInfo.menuIsShow = true;
727         }
728         TAG_LOGI(AceLogTag::ACE_WEB, "Current menu display status is %{public}d.", isMenuShow);
729     }
730 }
731 
PreProcessOverlay(const OverlayRequest & request)732 bool WebSelectOverlay::PreProcessOverlay(const OverlayRequest& request)
733 {
734     auto pattern = GetPattern<WebPattern>();
735     CHECK_NULL_RETURN(pattern, false);
736     auto pipeline = PipelineContext::GetCurrentContextSafely();
737     CHECK_NULL_RETURN(pipeline, false);
738     auto host = pattern->GetHost();
739     CHECK_NULL_RETURN(host, false);
740     SetEnableHandleLevel(true);
741     SetEnableSubWindowMenu(true);
742     SetMenuTranslateIsSupport(true);
743     SetIsSupportMenuSearch(true);
744     pipeline->AddOnAreaChangeNode(host->GetId());
745     return true;
746 }
747 
CheckHandleVisible(const RectF & paintRect)748 bool WebSelectOverlay::CheckHandleVisible(const RectF& paintRect)
749 {
750     return true;
751 }
752 
GetFirstHandleInfo()753 std::optional<SelectHandleInfo> WebSelectOverlay::GetFirstHandleInfo()
754 {
755     if (webSelectInfo_.secondHandle.paintRect.IsEmpty() && !webSelectInfo_.secondHandle.isShow) {
756         webSelectInfo_.handleReverse = false;
757         needResetHandleReverse_ = true;
758     }
759     return webSelectInfo_.firstHandle;
760 }
761 
GetSecondHandleInfo()762 std::optional<SelectHandleInfo> WebSelectOverlay::GetSecondHandleInfo()
763 {
764     return webSelectInfo_.secondHandle;
765 }
766 
OnUpdateMenuInfo(SelectMenuInfo & menuInfo,SelectOverlayDirtyFlag dirtyFlag)767 void WebSelectOverlay::OnUpdateMenuInfo(SelectMenuInfo& menuInfo, SelectOverlayDirtyFlag dirtyFlag)
768 {
769     menuInfo = webSelectInfo_.menuInfo;
770 }
771 
GetSelectArea()772 RectF WebSelectOverlay::GetSelectArea()
773 {
774     return webSelectInfo_.selectArea;
775 }
776 
GetSelectedText()777 std::string WebSelectOverlay::GetSelectedText()
778 {
779     auto pattern = GetPattern<WebPattern>();
780     CHECK_NULL_RETURN(pattern, "");
781     return pattern->GetSelectInfo();
782 }
783 
IsTouchHandleValid(std::shared_ptr<OHOS::NWeb::NWebTouchHandleState> handle)784 bool WebSelectOverlay::IsTouchHandleValid(std::shared_ptr<OHOS::NWeb::NWebTouchHandleState> handle)
785 {
786     return (handle != nullptr) && (handle->IsEnable());
787 }
788 
OnMenuItemAction(OptionMenuActionId id,OptionMenuType type)789 void WebSelectOverlay::OnMenuItemAction(OptionMenuActionId id, OptionMenuType type)
790 {
791     auto pattern = GetPattern<WebPattern>();
792     CHECK_NULL_VOID(pattern);
793     if (!quickMenuCallback_) {
794         pattern->CloseSelectOverlay();
795         return;
796     }
797     switch (id) {
798         case OptionMenuActionId::COPY:
799             quickMenuCallback_->Continue(
800                 OHOS::NWeb::NWebQuickMenuParams::QM_EF_CAN_COPY, OHOS::NWeb::MenuEventFlags::EF_LEFT_MOUSE_BUTTON);
801             pattern->CloseSelectOverlay();
802             break;
803         case OptionMenuActionId::CUT:
804             quickMenuCallback_->Continue(
805                 OHOS::NWeb::NWebQuickMenuParams::QM_EF_CAN_CUT, OHOS::NWeb::MenuEventFlags::EF_LEFT_MOUSE_BUTTON);
806             pattern->CloseSelectOverlay();
807             break;
808         case OptionMenuActionId::PASTE:
809             quickMenuCallback_->Continue(
810                 OHOS::NWeb::NWebQuickMenuParams::QM_EF_CAN_PASTE, OHOS::NWeb::MenuEventFlags::EF_LEFT_MOUSE_BUTTON);
811             pattern->CloseSelectOverlay();
812             break;
813         case OptionMenuActionId::SELECT_ALL:
814             quickMenuCallback_->Continue(OHOS::NWeb::NWebQuickMenuParams::QM_EF_CAN_SELECT_ALL,
815                 OHOS::NWeb::MenuEventFlags::EF_LEFT_MOUSE_BUTTON);
816             break;
817         case OptionMenuActionId::TRANSLATE:
818             HandleOnTranslate();
819             pattern->CloseSelectOverlay();
820             SelectCancel();
821             return;
822         case OptionMenuActionId::SEARCH:
823             HandleOnSearch();
824             pattern->CloseSelectOverlay();
825             SelectCancel();
826             return;
827         case OptionMenuActionId::DISAPPEAR:
828             pattern->CloseSelectOverlay();
829             SelectCancel();
830         default:
831             TAG_LOGI(AceLogTag::ACE_WEB, "Unsupported menu option id %{public}d", id);
832             break;
833     }
834 }
835 
OnHandleMove(const RectF & handleRect,bool isFirst)836 void WebSelectOverlay::OnHandleMove(const RectF& handleRect, bool isFirst)
837 {
838     auto pattern = GetPattern<WebPattern>();
839     CHECK_NULL_VOID(pattern);
840     auto pipeline = PipelineContext::GetCurrentContext();
841     CHECK_NULL_VOID(pipeline);
842     auto manager = pipeline->GetDragDropManager();
843     CHECK_NULL_VOID(manager);
844     if (pattern->isDragging_ || manager->IsDragged()) {
845         return;
846     }
847     TouchInfo touchPoint;
848     touchPoint.id = 0;
849     touchPoint.x = handleRect.GetX() - pattern->webOffset_.GetX();
850     touchPoint.y = handleRect.GetY() - pattern->webOffset_.GetY() + handleRect.Height() / HALF;
851     if (pattern->IsOverlayCreating()) {
852         pattern->UpdateImageOverlayTouchInfo(touchPoint.x, touchPoint.y, TouchType::MOVE);
853     } else {
854         std::vector<std::shared_ptr<OHOS::NWeb::NWebTouchPointInfo>> touch_point_infos;
855         std::shared_ptr<OHOS::NWeb::NWebTouchPointInfo> touch_point_info =
856             std::make_shared<NWebTouchPointInfoImpl>(touchPoint.id, touchPoint.x, touchPoint.y);
857         touch_point_infos.emplace_back(touch_point_info);
858         pattern->delegate_->HandleTouchMove(touch_point_infos, true);
859     }
860     OnMagnifierHandleMove(handleRect, isFirst);
861 }
862 
OnHandleMoveStart(const GestureEvent & event,bool isFirst)863 void WebSelectOverlay::OnHandleMoveStart(const GestureEvent& event, bool isFirst)
864 {
865     selectOverlayDragging_ = true;
866     isCurrentStartHandleDragging_ = isFirst;
867     auto pattern = GetPattern<WebPattern>();
868     CHECK_NULL_VOID(pattern);
869     auto delegate = pattern->delegate_;
870     CHECK_NULL_VOID(delegate);
871     RectF handleRect = ChangeHandleHeight(event, isFirst);
872     TouchInfo touchPoint;
873     touchPoint.id = 0;
874     touchPoint.x = handleRect.GetX() - pattern->webOffset_.GetX();
875     touchPoint.y = handleRect.GetY() - pattern->webOffset_.GetY() + handleRect.Height() / HALF;
876     pattern->PushOverlayInfo(touchPoint.x, touchPoint.y, touchPoint.id);
877     delegate->HandleTouchDown(touchPoint.id, touchPoint.x, touchPoint.y, true);
878     if (pattern->IsOverlayCreating()) {
879         pattern->UpdateImageOverlayTouchInfo(touchPoint.x, touchPoint.y, TouchType::DOWN);
880     }
881     pattern->WebOverlayRequestFocus();
882 }
883 
OnHandleMoveDone(const RectF & rect,bool isFirst)884 void WebSelectOverlay::OnHandleMoveDone(const RectF& rect, bool isFirst)
885 {
886     HideMagnifier();
887     selectOverlayDragging_ = false;
888     auto pattern = GetPattern<WebPattern>();
889     CHECK_NULL_VOID(pattern);
890     auto delegate = pattern->delegate_;
891     CHECK_NULL_VOID(delegate);
892     TouchInfo touchPoint;
893     touchPoint.id = 0;
894     touchPoint.x = rect.GetX() - pattern->webOffset_.GetX();
895     touchPoint.y = rect.GetY() - pattern->webOffset_.GetY() + rect.Height() / HALF;
896     pattern->DelTouchOverlayInfoByTouchId(touchPoint.id);
897     if (!pattern->IsOverlayCreating()) {
898         delegate->HandleTouchUp(touchPoint.id, touchPoint.x, touchPoint.y, true);
899     } else if (pattern->imageAnalyzerManager_) {
900         pattern->UpdateImageOverlayTouchInfo(touchPoint.x, touchPoint.y, TouchType::UP);
901         pattern->SetOverlayCreating(false);
902         delegate->HandleTouchCancel();
903     }
904     UpdateTouchHandleForOverlay(true);
905     if (!IsShowMenu()) {
906         ChangeVisibilityOfQuickMenu();
907     }
908     if (startSelectionHandle_ && endSelectionHandle_) {
909         auto offset = pattern->GetCoordinatePoint().value_or(OffsetF());
910         auto size = pattern->GetHostFrameSize().value_or(SizeF());
911         TAG_LOGI(AceLogTag::ACE_WEB, "OnSelectHandleDone offset(%{public}f,%{public}f) size(%{public}f,%{public}f)"
912             "start(%{public}d,%{public}d) end(%{public}d,%{public}d)", offset.GetX(), offset.GetY(),
913             size.Width(), size.Height(), startSelectionHandle_->GetX(), startSelectionHandle_->GetY(),
914             endSelectionHandle_->GetX(), endSelectionHandle_->GetY());
915     }
916     WebOverlayType overlayType = GetTouchHandleOverlayType(insertHandle_, startSelectionHandle_, endSelectionHandle_);
917     if (overlayType == SELECTION_OVERLAY && !pattern->IsSelectInfoValid()) {
918         TAG_LOGI(AceLogTag::ACE_WEB, "Close handles and menu.");
919         pattern->CloseSelectOverlay();
920         SelectCancel();
921     }
922 }
923 
OnCloseOverlay(OptionMenuType menuType,CloseReason reason,RefPtr<OverlayInfo> info)924 void WebSelectOverlay::OnCloseOverlay(OptionMenuType menuType, CloseReason reason, RefPtr<OverlayInfo> info)
925 {
926     selectOverlayDragging_ = false;
927     selectTemporarilyHidden_ = false;
928     selectTemporarilyHiddenByScroll_ = false;
929     isShowHandle_ = false;
930     if (CloseReason::CLOSE_REASON_BACK_PRESSED == reason) {
931         SelectCancel();
932     }
933     auto pattern = GetPattern<WebPattern>();
934     CHECK_NULL_VOID(pattern);
935     auto host = pattern->GetHost();
936     CHECK_NULL_VOID(host);
937     StopListenSelectOverlayParentScroll(host);
938 }
939 
AfterCloseOverlay()940 void WebSelectOverlay::AfterCloseOverlay()
941 {
942     selectOverlayDragging_ = false;
943     isShowHandle_ = false;
944 }
945 
OnOverlayClick(const GestureEvent & event,bool isClickCaret)946 void WebSelectOverlay::OnOverlayClick(const GestureEvent& event, bool isClickCaret)
947 {
948     auto pattern = GetPattern<WebPattern>();
949     CHECK_NULL_VOID(pattern);
950     auto host = pattern->GetHost();
951     CHECK_NULL_VOID(host);
952     auto focusHub = host->GetOrCreateFocusHub();
953     CHECK_NULL_VOID(focusHub);
954     auto delegate = pattern->delegate_;
955     CHECK_NULL_VOID(delegate);
956     if (!focusHub->IsFocusable() || event.GetSourceDevice() == SourceType::MOUSE) {
957         return;
958     }
959     if (selectOverlayDragging_) {
960         TAG_LOGI(AceLogTag::ACE_WEB, "HandleTouchClickEvent fail when handle dragging.");
961         return;
962     }
963     if (!IsTouchHandleValid(insertHandle_)) {
964         return;
965     }
966     auto globalLocation = event.GetGlobalLocation();
967     TouchInfo touchPoint;
968     touchPoint.id = 0;
969     touchPoint.x = globalLocation.GetX() - pattern->webOffset_.GetX();
970     touchPoint.y = globalLocation.GetY() - pattern->webOffset_.GetY();
971     auto pipeline = host->GetContext();
972     CHECK_NULL_VOID(pipeline);
973     auto theme = pipeline->GetTheme<TextOverlayTheme>();
974     CHECK_NULL_VOID(theme);
975     float hotZone = theme->GetHandleHotZoneRadius().ConvertToPx();
976     RectF edgeRect(insertHandle_->GetX() - hotZone / HALF,
977                    insertHandle_->GetY() - insertHandle_->GetEdgeHeight(),
978                    hotZone,
979                    insertHandle_->GetEdgeHeight());
980     bool isInRegion = edgeRect.IsInRegion({touchPoint.x, touchPoint.y});
981     TAG_LOGI(AceLogTag::ACE_WEB, "point.x:%{public}f. y:%{public}f, isInRegion:%{public}d",
982         touchPoint.x, touchPoint.y, isInRegion);
983     TAG_LOGI(AceLogTag::ACE_WEB, "edgeRect:%{public}s", edgeRect.ToString().c_str());
984     delegate->HandleTouchDown(touchPoint.id, touchPoint.x, touchPoint.y, !isInRegion);
985     delegate->HandleTouchUp(touchPoint.id, touchPoint.x, touchPoint.y, !isInRegion);
986 }
987 
CheckTouchInHostNode(const PointF & touchPoint)988 bool WebSelectOverlay::CheckTouchInHostNode(const PointF& touchPoint)
989 {
990     return true;
991 }
992 
OnHandleReverse(bool isReverse)993 void WebSelectOverlay::OnHandleReverse(bool isReverse)
994 {
995     if (isReverse && needResetHandleReverse_) {
996         TAG_LOGI(AceLogTag::ACE_WEB, "WebSelectOverlay should reset handleReverse.");
997         auto manager = GetManager<SelectContentOverlayManager>();
998         CHECK_NULL_VOID(manager);
999         manager->MarkInfoChange(DIRTY_DOUBLE_HANDLE);
1000     } else {
1001         needResetHandleReverse_ = false;
1002     }
1003 }
1004 
OnHandleGlobalTouchEvent(SourceType sourceType,TouchType touchType,bool touchInside)1005 void WebSelectOverlay::OnHandleGlobalTouchEvent(SourceType sourceType, TouchType touchType, bool touchInside)
1006 {
1007     if (EventInfoConvertor::MatchCompatibleCondition() && IsMouseClickDown(sourceType, touchType)) {
1008         return;
1009     }
1010     if (IsMouseClickDown(sourceType, touchType) || IsTouchUp(sourceType, touchType)) {
1011         CloseOverlay(false, CloseReason::CLOSE_REASON_CLICK_OUTSIDE);
1012         SelectCancel();
1013     }
1014 }
1015 
OnUpdateSelectOverlayInfo(SelectOverlayInfo & selectInfo,int32_t requestCode)1016 void WebSelectOverlay::OnUpdateSelectOverlayInfo(SelectOverlayInfo &selectInfo, int32_t requestCode)
1017 {
1018     selectInfo.isNewAvoid = webSelectInfo_.isNewAvoid;
1019     selectInfo.isSingleHandle = webSelectInfo_.isSingleHandle;
1020     selectInfo.menuOptionItems = webSelectInfo_.menuOptionItems;
1021     selectInfo.handleReverse = webSelectInfo_.handleReverse;
1022     selectInfo.hitTestMode = webSelectInfo_.hitTestMode;
1023     selectInfo.onCreateCallback = webSelectInfo_.onCreateCallback;
1024     selectInfo.onClose = webSelectInfo_.onClose;
1025     selectInfo.onClick = webSelectInfo_.onClick;
1026     selectInfo.enableHandleLevel = true;
1027     selectInfo.enableSubWindowMenu = true;
1028     selectInfo.isHandleLineShow = webSelectInfo_.isHandleLineShow;
1029 }
1030 
OnHandleMarkInfoChange(const std::shared_ptr<SelectOverlayInfo> info,SelectOverlayDirtyFlag flag)1031 void WebSelectOverlay::OnHandleMarkInfoChange(
1032     const std::shared_ptr<SelectOverlayInfo> info, SelectOverlayDirtyFlag flag)
1033 {
1034     auto manager = GetManager<SelectContentOverlayManager>();
1035     CHECK_NULL_VOID(manager);
1036     if ((flag & DIRTY_HANDLE_COLOR_FLAG) == DIRTY_HANDLE_COLOR_FLAG) {
1037         info->handlerColor = GetHandleColor();
1038         manager->MarkHandleDirtyNode(PROPERTY_UPDATE_RENDER);
1039     }
1040     if ((flag & DIRTY_FIRST_HANDLE) == DIRTY_FIRST_HANDLE || (flag & DIRTY_SECOND_HANDLE) == DIRTY_SECOND_HANDLE) {
1041         if (info->menuInfo.showShare != (IsSupportMenuShare() && AllowShare() && IsNeedMenuShare())) {
1042             info->menuInfo.showShare = !info->menuInfo.showShare;
1043             manager->NotifyUpdateToolBar(true);
1044         }
1045     }
1046     if ((flag & DIRTY_DOUBLE_HANDLE) == DIRTY_DOUBLE_HANDLE) {
1047         if (needResetHandleReverse_) {
1048             TAG_LOGI(AceLogTag::ACE_WEB, "WebSelectOverlay OnHandleMarkInfoChange reset handleReverse.");
1049             info->handleReverse = webSelectInfo_.handleReverse;
1050             manager->MarkHandleDirtyNode(PROPERTY_UPDATE_RENDER);
1051             needResetHandleReverse_ = false;
1052         }
1053     }
1054 }
1055 
OnAfterSelectOverlayShow(bool isCreated)1056 void WebSelectOverlay::OnAfterSelectOverlayShow(bool isCreated)
1057 {
1058     if (needResetHandleReverse_) {
1059         OnHandleReverse(true);
1060         needResetHandleReverse_ = false;
1061     }
1062 }
1063 
UpdateSelectMenuOptions()1064 void WebSelectOverlay::UpdateSelectMenuOptions()
1065 {
1066     auto value = GetSelectedText();
1067     auto queryWord = std::regex_replace(value, std::regex("^\\s+|\\s+$"), "");
1068     if (!queryWord.empty()) {
1069         webSelectInfo_.menuInfo.showSearch = true;
1070         webSelectInfo_.menuInfo.showTranslate = true;
1071     } else {
1072         webSelectInfo_.menuInfo.showSearch = false;
1073         webSelectInfo_.menuInfo.showTranslate = false;
1074     }
1075     TAG_LOGI(AceLogTag::ACE_WEB, "WebSelectInfo MenuInfo ShowSearch is %{public}d", webSelectInfo_.menuInfo.showSearch);
1076     TAG_LOGI(AceLogTag::ACE_WEB, "WebSelectInfo MenuInfo ShowTranslate is %{public}d",
1077         webSelectInfo_.menuInfo.showTranslate);
1078     OnUpdateMenuInfo(webSelectInfo_.menuInfo, DIRTY_FIRST_HANDLE);
1079     auto manager = GetManager<SelectContentOverlayManager>();
1080     CHECK_NULL_VOID(manager);
1081     manager->MarkInfoChange(DIRTY_ALL_MENU_ITEM);
1082 }
1083 } // namespace OHOS::Ace::NG
1084