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