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