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