• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2022 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/web/render_web.h"
17 
18 #include <cinttypes>
19 #include <iomanip>
20 #include <sstream>
21 
22 #include "base/log/log.h"
23 #include "base/mousestyle/mouse_style.h"
24 #include "base/utils/linear_map.h"
25 #include "base/utils/utils.h"
26 #include "core/common/manager_interface.h"
27 #include "core/components/positioned/positioned_component.h"
28 #include "core/components/web/resource/web_resource.h"
29 #include "core/event/ace_events.h"
30 #include "core/event/ace_event_helper.h"
31 
32 namespace OHOS::Ace {
33 namespace {
34 const LinearEnumMapNode<OHOS::NWeb::CursorType, MouseFormat> g_cursorTypeMap[] = {
35     { OHOS::NWeb::CursorType::CT_CROSS, MouseFormat::CROSS },
36     { OHOS::NWeb::CursorType::CT_HAND, MouseFormat::HAND_POINTING },
37     { OHOS::NWeb::CursorType::CT_IBEAM, MouseFormat::TEXT_CURSOR },
38     { OHOS::NWeb::CursorType::CT_HELP, MouseFormat::HELP },
39     { OHOS::NWeb::CursorType::CT_EASTRESIZE, MouseFormat::WEST_EAST },
40     { OHOS::NWeb::CursorType::CT_NORTHRESIZE, MouseFormat::NORTH_SOUTH },
41     { OHOS::NWeb::CursorType::CT_NORTHEASTRESIZE, MouseFormat::NORTH_EAST_SOUTH_WEST },
42     { OHOS::NWeb::CursorType::CT_NORTHWESTRESIZE, MouseFormat::NORTH_WEST_SOUTH_EAST },
43     { OHOS::NWeb::CursorType::CT_SOUTHRESIZE, MouseFormat::NORTH_SOUTH },
44     { OHOS::NWeb::CursorType::CT_SOUTHEASTRESIZE, MouseFormat::NORTH_WEST_SOUTH_EAST },
45     { OHOS::NWeb::CursorType::CT_SOUTHWESTRESIZE, MouseFormat::NORTH_EAST_SOUTH_WEST },
46     { OHOS::NWeb::CursorType::CT_WESTRESIZE, MouseFormat::WEST_EAST },
47     { OHOS::NWeb::CursorType::CT_NORTHSOUTHRESIZE, MouseFormat::NORTH_SOUTH },
48     { OHOS::NWeb::CursorType::CT_EASTWESTRESIZE, MouseFormat::WEST_EAST },
49     { OHOS::NWeb::CursorType::CT_NORTHEASTSOUTHWESTRESIZE, MouseFormat::NORTH_EAST_SOUTH_WEST },
50     { OHOS::NWeb::CursorType::CT_NORTHWESTSOUTHEASTRESIZE, MouseFormat::NORTH_WEST_SOUTH_EAST },
51     { OHOS::NWeb::CursorType::CT_COLUMNRESIZE, MouseFormat::RESIZE_LEFT_RIGHT },
52     { OHOS::NWeb::CursorType::CT_ROWRESIZE, MouseFormat::RESIZE_UP_DOWN },
53     { OHOS::NWeb::CursorType::CT_MOVE, MouseFormat::CURSOR_MOVE },
54     { OHOS::NWeb::CursorType::CT_NODROP, MouseFormat::CURSOR_FORBID },
55     { OHOS::NWeb::CursorType::CT_COPY, MouseFormat::CURSOR_COPY },
56     { OHOS::NWeb::CursorType::CT_NOTALLOWED, MouseFormat::CURSOR_FORBID },
57     { OHOS::NWeb::CursorType::CT_ZOOMIN, MouseFormat::ZOOM_IN },
58     { OHOS::NWeb::CursorType::CT_ZOOMOUT, MouseFormat::ZOOM_OUT },
59     { OHOS::NWeb::CursorType::CT_GRABBING, MouseFormat::HAND_GRABBING },
60 };
61 } // namespace
62 
63 constexpr int32_t SINGLE_CLICK_NUM = 1;
64 constexpr int32_t DOUBLE_CLICK_NUM = 2;
65 constexpr int32_t DEFAULT_NUMS_ONE = 1;
66 constexpr double DEFAULT_DBCLICK_INTERVAL = 0.5f;
67 constexpr double DEFAULT_AXIS_RATIO = -0.06f;
68 
RenderWeb()69 RenderWeb::RenderWeb() : RenderNode(true)
70 {
71 #ifdef OHOS_STANDARD_SYSTEM
72     InitEnhanceSurfaceFlag();
73     Initialize();
74 #endif
75 }
76 
InitEnhanceSurfaceFlag()77 void RenderWeb::InitEnhanceSurfaceFlag()
78 {
79     if (SystemProperties::GetExtSurfaceEnabled()) {
80         isEnhanceSurface_ = true;
81     } else {
82         isEnhanceSurface_ = false;
83     }
84 }
85 
OnAttachContext()86 void RenderWeb::OnAttachContext()
87 {
88     LOGI("OnAttachContext");
89     auto pipelineContext = context_.Upgrade();
90     if (!pipelineContext) {
91         LOGE("OnAttachContext context null");
92         return;
93     }
94     if (delegate_) {
95         // web component is displayed in full screen by default.
96         drawSize_ = Size(pipelineContext->GetRootWidth(), pipelineContext->GetRootHeight());
97         drawSizeCache_ = drawSize_;
98         position_ = Offset(0, 0);
99         delegate_->SetEnhanceSurfaceFlag(isEnhanceSurface_);
100         delegate_->SetDrawSize(drawSize_);
101 #ifdef OHOS_STANDARD_SYSTEM
102         delegate_->InitOHOSWeb(context_);
103 #else
104         delegate_->CreatePlatformResource(drawSize_, position_, context_);
105 #endif
106     }
107 }
108 
RegistVirtualKeyBoardListener()109 void RenderWeb::RegistVirtualKeyBoardListener()
110 {
111     if (!needUpdateWeb_) {
112         return;
113     }
114     auto pipelineContext = context_.Upgrade();
115     if (!pipelineContext) {
116         return;
117     }
118     pipelineContext->SetVirtualKeyBoardCallback(
119         [weak = AceType::WeakClaim(this)](int32_t width, int32_t height, double keyboard) {
120             auto renderWeb = weak.Upgrade();
121             if (renderWeb) {
122                 return renderWeb->ProcessVirtualKeyBoard(width, height, keyboard);
123             }
124             return false;
125         });
126     needUpdateWeb_ = false;
127 }
128 
Update(const RefPtr<Component> & component)129 void RenderWeb::Update(const RefPtr<Component>& component)
130 {
131     const RefPtr<WebComponent> web = AceType::DynamicCast<WebComponent>(component);
132     if (!web) {
133         LOGE("WebComponent is null");
134         return;
135     }
136 
137     onMouse_ = web->GetOnMouseEventCallback();
138     onKeyEvent_ = web->GetOnKeyEventCallback();
139     onPreKeyEvent_ = web->GetOnInterceptKeyEventCallback();
140     RegistVirtualKeyBoardListener();
141 #ifdef OHOS_STANDARD_SYSTEM
142     InitPanEvent();
143 #endif
144     web_ = web;
145     if (delegate_) {
146         delegate_->SetComponent(web);
147         delegate_->UpdateJavaScriptEnabled(web->GetJsEnabled());
148         delegate_->UpdateBlockNetworkImage(web->GetOnLineImageAccessEnabled());
149         delegate_->UpdateAllowFileAccess(web->GetFileAccessEnabled());
150         delegate_->UpdateLoadsImagesAutomatically(web->GetImageAccessEnabled());
151         delegate_->UpdateMixedContentMode(web->GetMixedMode());
152         delegate_->UpdateSupportZoom(web->GetZoomAccessEnabled());
153         delegate_->UpdateDomStorageEnabled(web->GetDomStorageAccessEnabled());
154         delegate_->UpdateGeolocationEnabled(web->GetGeolocationAccessEnabled());
155         delegate_->UpdateCacheMode(web->GetCacheMode());
156         delegate_->UpdateOverviewModeEnabled(web->GetOverviewModeAccessEnabled());
157         delegate_->UpdateFileFromUrlEnabled(web->GetFileFromUrlAccessEnabled());
158         delegate_->UpdateDatabaseEnabled(web->GetDatabaseAccessEnabled());
159         delegate_->UpdateTextZoomRatio(web->GetTextZoomRatio());
160         delegate_->UpdateWebDebuggingAccess(web->GetWebDebuggingAccessEnabled());
161         delegate_->UpdateMediaPlayGestureAccess(web->IsMediaPlayGestureAccess());
162         delegate_->UpdatePinchSmoothModeEnabled(web->GetPinchSmoothModeEnabled());
163         delegate_->UpdateMultiWindowAccess(web->GetMultiWindowAccessEnabled());
164         auto userAgent = web->GetUserAgent();
165         if (!userAgent.empty()) {
166             delegate_->UpdateUserAgent(userAgent);
167         }
168         if (web->GetBackgroundColorEnabled()) {
169             delegate_->UpdateBackgroundColor(web->GetBackgroundColor());
170         }
171         if (web->GetIsInitialScaleSet()) {
172             delegate_->UpdateInitialScale(web->GetInitialScale());
173         }
174         delegate_->SetRenderWeb(AceType::WeakClaim(this));
175         onDragStart_ = web->GetOnDragStartId();
176         onDragEnter_ = web->GetOnDragEnterId();
177         onDragMove_ = web->GetOnDragMoveId();
178         onDragLeave_ = web->GetOnDragLeaveId();
179         onDrop_ = web->GetOnDropId();
180     }
181     MarkNeedLayout();
182 }
183 
ProcessVirtualKeyBoard(int32_t width,int32_t height,double keyboard)184 bool RenderWeb::ProcessVirtualKeyBoard(int32_t width, int32_t height, double keyboard)
185 {
186     LOGI("Web ProcessVirtualKeyBoard width=%{public}d height=%{public}d keyboard=%{public}f",
187         width, height, keyboard);
188     if (delegate_) {
189         offsetFix_ = 0;
190         if (!isFocus_) {
191             if (isVirtualKeyBoardShow_ == VkState::VK_SHOW) {
192                 drawSize_.SetSize(drawSizeCache_);
193                 delegate_->SetBoundsOrResize(drawSize_, GetGlobalOffset());
194                 SyncGeometryProperties();
195                 SetRootView(width, height, 0);
196                 isVirtualKeyBoardShow_ = VkState::VK_HIDE;
197             }
198             return false;
199         }
200         if (NearZero(keyboard)) {
201             drawSize_.SetSize(drawSizeCache_);
202             delegate_->SetBoundsOrResize(drawSize_, GetGlobalOffset());
203             SyncGeometryProperties();
204             SetRootView(width, height, 0);
205             isVirtualKeyBoardShow_ = VkState::VK_HIDE;
206         } else if (isVirtualKeyBoardShow_ != VkState::VK_SHOW) {
207             drawSizeCache_.SetSize(drawSize_);
208             if (drawSize_.Height() <= (height - keyboard - GetCoordinatePoint().GetY())) {
209                 SetRootView(width, height, 0);
210                 isVirtualKeyBoardShow_ = VkState::VK_SHOW;
211                 return true;
212             }
213             if (height - GetCoordinatePoint().GetY() < keyboard) {
214                 return true;
215             }
216             drawSize_.SetHeight(height - keyboard - GetCoordinatePoint().GetY());
217             delegate_->SetBoundsOrResize(drawSize_, GetGlobalOffset());
218             SyncGeometryProperties();
219             SetRootView(width, height, DEFAULT_NUMS_ONE);
220             isVirtualKeyBoardShow_ = VkState::VK_SHOW;
221         }
222     }
223     return true;
224 }
225 
SetRootView(int32_t width,int32_t height,int32_t offset)226 void RenderWeb::SetRootView(int32_t width, int32_t height, int32_t offset)
227 {
228     auto pipelineContext = context_.Upgrade();
229     if (!pipelineContext) {
230         return;
231     }
232     pipelineContext->SetRootRect(width, height, offset);
233 }
234 
SendDoubleClickEvent(const MouseClickInfo & info)235 void RenderWeb::SendDoubleClickEvent(const MouseClickInfo& info)
236 {
237     if (!delegate_) {
238         LOGE("Touch cancel delegate_ is nullptr");
239         return;
240     }
241     delegate_->OnMouseEvent(info.x,
242         info.y, MouseButton::LEFT_BUTTON, MouseAction::PRESS, DOUBLE_CLICK_NUM);
243 }
244 
HandleDoubleClickEvent(const MouseEvent & event)245 bool RenderWeb::HandleDoubleClickEvent(const MouseEvent& event)
246 {
247     if (event.button != MouseButton::LEFT_BUTTON || event.action != MouseAction::PRESS) {
248         return false;
249     }
250     auto localLocation = event.GetOffset() - Offset(GetCoordinatePoint().GetX(), GetCoordinatePoint().GetY());
251     MouseClickInfo info;
252     info.x = localLocation.GetX();
253     info.y = localLocation.GetY();
254     info.start = event.time;
255     if (doubleClickQueue_.empty()) {
256         doubleClickQueue_.push(info);
257         return false;
258     }
259     std::chrono::duration<float> timeout_ = info.start - doubleClickQueue_.back().start;
260     if (timeout_.count() < DEFAULT_DBCLICK_INTERVAL) {
261         SendDoubleClickEvent(info);
262         std::queue<MouseClickInfo> empty;
263         swap(empty, doubleClickQueue_);
264         return true;
265     }
266     if (doubleClickQueue_.size() == 1) {
267         doubleClickQueue_.push(info);
268         return false;
269     }
270     doubleClickQueue_.pop();
271     doubleClickQueue_.push(info);
272     return false;
273 }
274 
OnMouseEvent(const MouseEvent & event)275 void RenderWeb::OnMouseEvent(const MouseEvent& event)
276 {
277     if (!delegate_) {
278         LOGE("Delegate_ is nullptr");
279         return;
280     }
281 
282     if (web_ && event.action == MouseAction::RELEASE) {
283         LOGI("mouse event request focus");
284         web_->RequestFocus();
285     }
286 
287     auto localLocation = event.GetOffset() - Offset(GetCoordinatePoint().GetX(), GetCoordinatePoint().GetY());
288     if (!HandleDoubleClickEvent(event)) {
289         delegate_->OnMouseEvent(localLocation.GetX(), localLocation.GetY(), event.button, event.action, SINGLE_CLICK_NUM);
290     }
291 
292     // clear the recording position, for not move content when virtual keyboard popup when web get focused.
293     auto context = GetContext().Upgrade();
294     if (context && context->GetTextFieldManager()) {
295         context->GetTextFieldManager()->SetClickPosition(Offset());
296     }
297 }
298 
HandleMouseEvent(const MouseEvent & event)299 bool RenderWeb::HandleMouseEvent(const MouseEvent& event)
300 {
301     OnMouseEvent(event);
302     if (!onMouse_) {
303         LOGW("RenderWeb::HandleMouseEvent, Mouse Event is null");
304         return false;
305     }
306 
307     MouseInfo info;
308     info.SetButton(event.button);
309     info.SetAction(event.action);
310     info.SetGlobalLocation(event.GetOffset());
311     info.SetLocalLocation(event.GetOffset() - Offset(GetCoordinatePoint().GetX(), GetCoordinatePoint().GetY()));
312     info.SetScreenLocation(event.GetScreenOffset());
313     info.SetTimeStamp(event.time);
314     info.SetDeviceId(event.deviceId);
315     info.SetSourceDevice(event.sourceType);
316     LOGD("RenderWeb::HandleMouseEvent: Do mouse callback with mouse event{ Global(%{public}f,%{public}f), "
317          "Local(%{public}f,%{public}f)}, Button(%{public}d), Action(%{public}d), Time(%{public}lld), "
318          "DeviceId(%{public}" PRId64 ", SourceType(%{public}d) }. Return: %{public}d",
319         info.GetGlobalLocation().GetX(), info.GetGlobalLocation().GetY(), info.GetLocalLocation().GetX(),
320         info.GetLocalLocation().GetY(), info.GetButton(), info.GetAction(),
321         info.GetTimeStamp().time_since_epoch().count(), info.GetDeviceId(), info.GetSourceDevice(),
322         info.IsStopPropagation());
323     onMouse_(info);
324     return info.IsStopPropagation();
325 }
326 
HandleKeyEvent(const KeyEvent & keyEvent)327 bool RenderWeb::HandleKeyEvent(const KeyEvent& keyEvent)
328 {
329     KeyEventInfo info(keyEvent);
330     if (onKeyEvent_) {
331         onKeyEvent_(info);
332     }
333     if (onPreKeyEvent_) {
334         return onPreKeyEvent_(info);
335     }
336     return false;
337 }
338 
PerformLayout()339 void RenderWeb::PerformLayout()
340 {
341     if (!NeedLayout()) {
342         LOGI("RenderWeb::PerformLayout No Need to Layout");
343         return;
344     }
345 
346     // render web do not support child.
347     drawSize_ = Size(GetLayoutParam().GetMaxSize().Width(), GetLayoutParam().GetMaxSize().Height());
348     drawSizeCache_ = drawSize_;
349     SetLayoutSize(drawSize_);
350     SetNeedLayout(false);
351     MarkNeedRender();
352 }
353 
354 #ifdef OHOS_STANDARD_SYSTEM
OnAppShow()355 void RenderWeb::OnAppShow()
356 {
357     RenderNode::OnAppShow();
358     if (delegate_) {
359         delegate_->ShowWebView();
360     }
361 }
362 
OnAppHide()363 void RenderWeb::OnAppHide()
364 {
365     RenderNode::OnAppHide();
366     needOnFocus_ = false;
367     if (delegate_) {
368         delegate_->HideWebView();
369     }
370 }
371 
OnGlobalPositionChanged()372 void RenderWeb::OnGlobalPositionChanged()
373 {
374     UpdateGlobalPos();
375     if (!textOverlay_ || !updateHandlePosition_) {
376         return;
377     }
378     OnTouchSelectionChanged(insertHandle_, startSelectionHandle_, endSelectionHandle_);
379 }
380 
OnPositionChanged()381 void RenderWeb::OnPositionChanged()
382 {
383     PopTextOverlay();
384 }
385 
OnSizeChanged()386 void RenderWeb::OnSizeChanged()
387 {
388     if (drawSize_.IsWidthInfinite() || drawSize_.IsHeightInfinite() ||
389         drawSize_.Width() == 0 || drawSize_.Height() == 0) {
390         LOGE("size is invalid");
391         return;
392     }
393     auto context = context_.Upgrade();
394     if (!context) {
395         LOGE("context is nullptr");
396         return;
397     }
398     UpdateGlobalPos();
399     if (delegate_ && !isUrlLoaded_) {
400         delegate_->SetBoundsOrResize(drawSize_, GetGlobalOffset());
401         if (!delegate_->LoadDataWithRichText()) {
402             LOGI("RenderWeb::Paint start LoadUrl");
403             delegate_->LoadUrl();
404         }
405         isUrlLoaded_ = true;
406     }
407 }
408 
Initialize()409 void RenderWeb::Initialize()
410 {
411     touchRecognizer_ = AceType::MakeRefPtr<RawRecognizer>();
412     touchRecognizer_->SetOnTouchDown([weakItem = AceType::WeakClaim(this)](const TouchEventInfo& info) {
413         auto item = weakItem.Upgrade();
414         if (item) {
415             item->HandleTouchDown(info, false);
416         }
417     });
418     touchRecognizer_->SetOnTouchUp([weakItem = AceType::WeakClaim(this)](const TouchEventInfo& info) {
419         auto item = weakItem.Upgrade();
420         if (item) {
421             item->HandleTouchUp(info, false);
422         }
423     });
424     touchRecognizer_->SetOnTouchMove([weakItem = AceType::WeakClaim(this)](const TouchEventInfo& info) {
425         auto item = weakItem.Upgrade();
426         if (item) {
427             item->HandleTouchMove(info, false);
428         }
429     });
430     touchRecognizer_->SetOnTouchCancel([weakItem = AceType::WeakClaim(this)](const TouchEventInfo& info) {
431         auto item = weakItem.Upgrade();
432         if (item) {
433             item->HandleTouchCancel(info);
434         }
435     });
436 }
437 
InitPanEvent()438 void RenderWeb::InitPanEvent()
439 {
440     auto context = context_.Upgrade();
441     if (panRecognizer_ || !context) {
442         return;
443     }
444     PanDirection panDirection;
445     panDirection.type = PanDirection::VERTICAL;
446     panRecognizer_ = AceType::MakeRefPtr<PanRecognizer>(
447         context, DEFAULT_PAN_FINGER, panDirection, DEFAULT_PAN_DISTANCE);
448     panRecognizer_->SetOnActionUpdate([weakItem = AceType::WeakClaim(this)](const GestureEvent& event) {
449         auto item = weakItem.Upgrade();
450         if (item) {
451             item->HandleDragMove(event);
452         }
453     });
454 }
455 
HandleDragMove(const GestureEvent & event)456 void RenderWeb::HandleDragMove(const GestureEvent& event)
457 {
458     if (event.GetInputEventType() == InputEventType::AXIS) {
459         if (!delegate_) {
460             LOGE("HandleDragMove delegate_ is nullptr");
461             return;
462         }
463         auto localLocation = event.GetLocalLocation();
464         delegate_->HandleAxisEvent(
465             localLocation.GetX(), localLocation.GetY(),
466             event.GetDelta().GetX() * DEFAULT_AXIS_RATIO,
467             event.GetDelta().GetY() *DEFAULT_AXIS_RATIO);
468     }
469 }
470 
HandleTouchDown(const TouchEventInfo & info,bool fromOverlay)471 void RenderWeb::HandleTouchDown(const TouchEventInfo& info, bool fromOverlay)
472 {
473     if (!delegate_) {
474         LOGE("Touch down delegate_ is nullptr");
475         return;
476     }
477     Offset touchOffset = Offset(0, 0);
478     std::list<TouchInfo> touchInfos;
479     if (!ParseTouchInfo(info, touchInfos, TouchType::DOWN)) {
480         LOGE("Touch down error");
481         return;
482     }
483     for (auto& touchPoint : touchInfos) {
484         if (fromOverlay) {
485             touchPoint.x -= GetGlobalOffset().GetX();
486             touchPoint.y -= GetGlobalOffset().GetY() + offsetFix_;
487         }
488         touchOffset = Offset(touchPoint.x, touchPoint.y);
489         delegate_->HandleTouchDown(touchPoint.id, touchPoint.x, touchPoint.y);
490     }
491     // clear the recording position, for not move content when virtual keyboard popup when web get focused.
492     auto context = GetContext().Upgrade();
493     if (context && context->GetTextFieldManager()) {
494         context->GetTextFieldManager()->SetClickPosition(Offset());
495     }
496 }
497 
HandleTouchUp(const TouchEventInfo & info,bool fromOverlay)498 void RenderWeb::HandleTouchUp(const TouchEventInfo& info, bool fromOverlay)
499 {
500     if (!delegate_) {
501         LOGE("Touch up delegate_ is nullptr");
502         return;
503     }
504     std::list<TouchInfo> touchInfos;
505     if (!ParseTouchInfo(info, touchInfos, TouchType::UP)) {
506         LOGE("Touch up error");
507         return;
508     }
509     for (auto& touchPoint : touchInfos) {
510         if (fromOverlay) {
511             touchPoint.x -= GetGlobalOffset().GetX();
512             touchPoint.y -= GetGlobalOffset().GetY() + offsetFix_;
513         }
514         delegate_->HandleTouchUp(touchPoint.id, touchPoint.x, touchPoint.y);
515     }
516     if (web_ && !touchInfos.empty()) {
517         web_->RequestFocus();
518     }
519 }
520 
HandleTouchMove(const TouchEventInfo & info,bool fromOverlay)521 void RenderWeb::HandleTouchMove(const TouchEventInfo& info, bool fromOverlay)
522 {
523     if (isDragging_) {
524         return;
525     }
526 
527     if (!delegate_) {
528         LOGE("Touch move delegate_ is nullptr");
529         return;
530     }
531     std::list<TouchInfo> touchInfos;
532     if (!ParseTouchInfo(info, touchInfos, TouchType::MOVE)) {
533         LOGE("Touch move error");
534         return;
535     }
536     for (auto& touchPoint : touchInfos) {
537         if (fromOverlay) {
538             touchPoint.x -= GetGlobalOffset().GetX();
539             touchPoint.y -= GetGlobalOffset().GetY() + offsetFix_;
540         }
541         delegate_->HandleTouchMove(touchPoint.id, touchPoint.x, touchPoint.y);
542     }
543 }
544 
HandleTouchCancel(const TouchEventInfo & info)545 void RenderWeb::HandleTouchCancel(const TouchEventInfo& info)
546 {
547     if (!delegate_) {
548         LOGE("Touch cancel delegate_ is nullptr");
549         return;
550     }
551     delegate_->HandleTouchCancel();
552 }
553 
ParseTouchInfo(const TouchEventInfo & info,std::list<TouchInfo> & touchInfos,const TouchType & touchType)554 bool RenderWeb::ParseTouchInfo(const TouchEventInfo& info, std::list<TouchInfo>& touchInfos, const TouchType& touchType)
555 {
556     auto context = context_.Upgrade();
557     if (!context) {
558         return false;
559     }
560     auto viewScale = context->GetViewScale();
561     if (touchType == TouchType::DOWN) {
562         if (!info.GetTouches().empty()) {
563             for (auto& point : info.GetTouches()) {
564                 TouchInfo touchInfo;
565                 touchInfo.id = point.GetFingerId();
566                 Offset location = point.GetLocalLocation();
567                 touchInfo.x = location.GetX() * viewScale;
568                 touchInfo.y = location.GetY() * viewScale;
569                 touchInfos.emplace_back(touchInfo);
570             }
571         } else {
572             return false;
573         }
574     } else if (touchType == TouchType::MOVE) {
575         if (!info.GetChangedTouches().empty()) {
576             for (auto& point : info.GetChangedTouches()) {
577                 TouchInfo touchInfo;
578                 touchInfo.id = point.GetFingerId();
579                 Offset location = point.GetLocalLocation();
580                 touchInfo.x = location.GetX() * viewScale;
581                 touchInfo.y = location.GetY() * viewScale;
582                 touchInfos.emplace_back(touchInfo);
583             }
584         } else {
585             return false;
586         }
587     } else if (touchType == TouchType::UP) {
588         if (!info.GetChangedTouches().empty()) {
589             for (auto& point : info.GetChangedTouches()) {
590                 TouchInfo touchInfo;
591                 touchInfo.id = point.GetFingerId();
592                 Offset location = point.GetLocalLocation();
593                 touchInfo.x = location.GetX() * viewScale;
594                 touchInfo.y = location.GetY() * viewScale;
595                 touchInfos.emplace_back(touchInfo);
596             }
597         } else {
598             return false;
599         }
600     }
601     return true;
602 }
603 
SetUpdateHandlePosition(const std::function<void (const OverlayShowOption &,float,float)> & updateHandlePosition)604 void RenderWeb::SetUpdateHandlePosition(
605     const std::function<void(const OverlayShowOption&, float, float)>& updateHandlePosition)
606 {
607     updateHandlePosition_ = updateHandlePosition;
608 }
609 
OnTouchTestHit(const Offset & coordinateOffset,const TouchRestrict & touchRestrict,TouchTestResult & result)610 void RenderWeb::OnTouchTestHit(const Offset& coordinateOffset, const TouchRestrict& touchRestrict,
611     TouchTestResult& result)
612 {
613     if (dragDropGesture_) {
614         dragDropGesture_->SetCoordinateOffset(coordinateOffset);
615         result.emplace_back(dragDropGesture_);
616         MarkIsNotSiblingAddRecognizerToResult(true);
617     }
618 
619     if (panRecognizer_) {
620         panRecognizer_->SetCoordinateOffset(coordinateOffset);
621         result.emplace_back(panRecognizer_);
622     }
623 
624     if (!touchRecognizer_) {
625         LOGE("TouchTestHit touchRecognizer_ is nullptr");
626         return;
627     }
628 
629     if (touchRestrict.sourceType != SourceType::TOUCH) {
630         LOGI("TouchTestHit got invalid source type: %{public}d", touchRestrict.sourceType);
631         return;
632     }
633     touchRecognizer_->SetCoordinateOffset(coordinateOffset);
634     result.emplace_back(touchRecognizer_);
635 }
636 
IsAxisScrollable(AxisDirection direction)637 bool RenderWeb::IsAxisScrollable(AxisDirection direction)
638 {
639     return true;
640 }
641 
CheckAxisNode()642 WeakPtr<RenderNode> RenderWeb::CheckAxisNode()
643 {
644     return AceType::WeakClaim<RenderNode>(this);
645 }
646 
PushTextOverlayToStack()647 void RenderWeb::PushTextOverlayToStack()
648 {
649     if (!textOverlay_) {
650         LOGE("TextOverlay is null");
651         return;
652     }
653 
654     auto context = context_.Upgrade();
655     if (!context) {
656         LOGE("Context is nullptr");
657         return;
658     }
659     auto lastStack = context->GetLastStack();
660     if (!lastStack) {
661         LOGE("LastStack is null");
662         return;
663     }
664     lastStack->PushComponent(textOverlay_, false);
665     stackElement_ = WeakClaim(RawPtr(lastStack));
666 }
667 
TextOverlayMenuShouldShow() const668 bool RenderWeb::TextOverlayMenuShouldShow() const
669 {
670     return showTextOveralyMenu_;
671 }
672 
GetShowStartTouchHandle() const673 bool RenderWeb::GetShowStartTouchHandle() const
674 {
675     return showStartTouchHandle_;
676 }
677 
GetShowEndTouchHandle() const678 bool RenderWeb::GetShowEndTouchHandle() const
679 {
680     return showEndTouchHandle_;
681 }
682 
RunQuickMenu(std::shared_ptr<OHOS::NWeb::NWebQuickMenuParams> params,std::shared_ptr<OHOS::NWeb::NWebQuickMenuCallback> callback)683 bool RenderWeb::RunQuickMenu(
684     std::shared_ptr<OHOS::NWeb::NWebQuickMenuParams> params,
685     std::shared_ptr<OHOS::NWeb::NWebQuickMenuCallback> callback)
686 {
687     auto context = context_.Upgrade();
688     if (!context || !params || !callback) {
689         return false;
690     }
691 
692     std::shared_ptr<OHOS::NWeb::NWebTouchHandleState> insertTouchHandle =
693         params->GetTouchHandleState(OHOS::NWeb::NWebTouchHandleState::TouchHandleType::INSERT_HANDLE);
694     std::shared_ptr<OHOS::NWeb::NWebTouchHandleState> beginTouchHandle =
695         params->GetTouchHandleState(OHOS::NWeb::NWebTouchHandleState::TouchHandleType::SELECTION_BEGIN_HANDLE);
696     std::shared_ptr<OHOS::NWeb::NWebTouchHandleState> endTouchHandle =
697         params->GetTouchHandleState(OHOS::NWeb::NWebTouchHandleState::TouchHandleType::SELECTION_END_HANDLE);
698     WebOverlayType overlayType = GetTouchHandleOverlayType(insertTouchHandle,
699                                                            beginTouchHandle,
700                                                            endTouchHandle);
701     insertHandle_ = insertTouchHandle;
702     startSelectionHandle_ = beginTouchHandle;
703     endSelectionHandle_ = endTouchHandle;
704     if (textOverlay_ || overlayType == INVALID_OVERLAY) {
705         PopTextOverlay();
706     }
707     textOverlay_ = CreateTextOverlay(insertTouchHandle, beginTouchHandle, endTouchHandle);
708     if (!textOverlay_) {
709         return false;
710     }
711 
712     showTextOveralyMenu_ = true;
713     showStartTouchHandle_ = (overlayType == INSERT_OVERLAY) ?
714         IsTouchHandleShow(insertTouchHandle) : IsTouchHandleShow(beginTouchHandle);
715     showEndTouchHandle_ = (overlayType == INSERT_OVERLAY) ?
716         IsTouchHandleShow(insertTouchHandle) : IsTouchHandleShow(endTouchHandle);
717 
718     RegisterTextOverlayCallback(params->GetEditStateFlags(), callback);
719     PushTextOverlayToStack();
720     return true;
721 }
722 
OnQuickMenuDismissed()723 void RenderWeb::OnQuickMenuDismissed()
724 {
725     PopTextOverlay();
726 }
727 
PopTextOverlay()728 void RenderWeb::PopTextOverlay()
729 {
730     auto context = context_.Upgrade();
731     if (!context) {
732         return;
733     }
734 
735     if (!textOverlay_) {
736         LOGE("no need to hide web overlay");
737         return;
738     }
739 
740     const auto& stackElement = stackElement_.Upgrade();
741     if (stackElement) {
742         stackElement->PopTextOverlay();
743     }
744 
745     textOverlay_ = nullptr;
746     showTextOveralyMenu_ = false;
747     showStartTouchHandle_ = false;
748     showEndTouchHandle_ = false;
749 }
750 
RegisterTextOverlayCallback(int32_t flags,std::shared_ptr<OHOS::NWeb::NWebQuickMenuCallback> callback)751 void RenderWeb::RegisterTextOverlayCallback(int32_t flags,
752     std::shared_ptr<OHOS::NWeb::NWebQuickMenuCallback> callback)
753 {
754     if (!callback || !textOverlay_) {
755         return;
756     }
757 
758     if (flags & OHOS::NWeb::NWebQuickMenuParams::QM_EF_CAN_CUT) {
759         textOverlay_->SetOnCut([weak = AceType::WeakClaim(this), callback] {
760             if (callback) {
761                 callback->Continue(OHOS::NWeb::NWebQuickMenuParams::QM_EF_CAN_CUT,
762                     OHOS::NWeb::MenuEventFlags::EF_LEFT_MOUSE_BUTTON);
763             }
764         });
765     }
766     if (flags & OHOS::NWeb::NWebQuickMenuParams::QM_EF_CAN_COPY) {
767         textOverlay_->SetOnCopy([weak = AceType::WeakClaim(this), callback] {
768             if (callback) {
769                 callback->Continue(OHOS::NWeb::NWebQuickMenuParams::QM_EF_CAN_COPY,
770                     OHOS::NWeb::MenuEventFlags::EF_LEFT_MOUSE_BUTTON);
771             }
772         });
773     }
774     if (flags & OHOS::NWeb::NWebQuickMenuParams::QM_EF_CAN_PASTE) {
775         textOverlay_->SetOnPaste([weak = AceType::WeakClaim(this), callback] {
776             if (callback) {
777                 callback->Continue(OHOS::NWeb::NWebQuickMenuParams::QM_EF_CAN_PASTE,
778                     OHOS::NWeb::MenuEventFlags::EF_LEFT_MOUSE_BUTTON);
779             }
780         });
781     }
782     if (flags & OHOS::NWeb::NWebQuickMenuParams::QM_EF_CAN_SELECT_ALL) {
783         textOverlay_->SetOnCopyAll(
784             [weak = AceType::WeakClaim(this), callback]
785             (const std::function<void(const Offset&, const Offset&)>& temp) {
786                 callback->Continue(OHOS::NWeb::NWebQuickMenuParams::QM_EF_CAN_SELECT_ALL,
787                     OHOS::NWeb::MenuEventFlags::EF_LEFT_MOUSE_BUTTON);
788             });
789     }
790 }
791 
792 
IsTouchHandleValid(std::shared_ptr<OHOS::NWeb::NWebTouchHandleState> handle)793 bool RenderWeb::IsTouchHandleValid(
794     std::shared_ptr<OHOS::NWeb::NWebTouchHandleState> handle)
795 {
796     return (handle != nullptr) && (handle->IsEnable());
797 }
798 
IsTouchHandleShow(std::shared_ptr<OHOS::NWeb::NWebTouchHandleState> handle)799 bool RenderWeb::IsTouchHandleShow(
800     std::shared_ptr<OHOS::NWeb::NWebTouchHandleState> handle)
801 {
802     if (handle->GetAlpha() > 0 &&
803         GreatOrEqual(handle->GetY(), static_cast<int32_t>(handle->GetEdgeHeight())) &&
804         GreatNotEqual(GetLayoutSize().Height(), handle->GetY())) {
805         return true;
806     }
807     return false;
808 }
809 
GetTouchHandleOverlayType(std::shared_ptr<OHOS::NWeb::NWebTouchHandleState> insertHandle,std::shared_ptr<OHOS::NWeb::NWebTouchHandleState> startSelectionHandle,std::shared_ptr<OHOS::NWeb::NWebTouchHandleState> endSelectionHandle)810 WebOverlayType RenderWeb::GetTouchHandleOverlayType(
811     std::shared_ptr<OHOS::NWeb::NWebTouchHandleState> insertHandle,
812     std::shared_ptr<OHOS::NWeb::NWebTouchHandleState> startSelectionHandle,
813     std::shared_ptr<OHOS::NWeb::NWebTouchHandleState> endSelectionHandle)
814 {
815     if (IsTouchHandleValid(insertHandle) &&
816         !IsTouchHandleValid(startSelectionHandle) &&
817         !IsTouchHandleValid(endSelectionHandle)) {
818         return INSERT_OVERLAY;
819     }
820 
821     if (!IsTouchHandleValid(insertHandle) &&
822         IsTouchHandleValid(startSelectionHandle) &&
823         IsTouchHandleValid(endSelectionHandle)) {
824         return SELECTION_OVERLAY;
825     }
826 
827     return INVALID_OVERLAY;
828 }
829 
CreateTextOverlay(std::shared_ptr<OHOS::NWeb::NWebTouchHandleState> insertHandle,std::shared_ptr<OHOS::NWeb::NWebTouchHandleState> startSelectionHandle,std::shared_ptr<OHOS::NWeb::NWebTouchHandleState> endSelectionHandle)830 RefPtr<TextOverlayComponent> RenderWeb::CreateTextOverlay(
831     std::shared_ptr<OHOS::NWeb::NWebTouchHandleState> insertHandle,
832     std::shared_ptr<OHOS::NWeb::NWebTouchHandleState> startSelectionHandle,
833     std::shared_ptr<OHOS::NWeb::NWebTouchHandleState> endSelectionHandle)
834 {
835     auto context = context_.Upgrade();
836     if (!context) {
837         return nullptr;
838     }
839 
840     WebOverlayType overlayType = GetTouchHandleOverlayType(insertHandle,
841                                                            startSelectionHandle,
842                                                            endSelectionHandle);
843     if (overlayType == INVALID_OVERLAY) {
844         return nullptr;
845     }
846 
847     RefPtr<TextOverlayComponent> textOverlay =
848         AceType::MakeRefPtr<TextOverlayComponent>(context->GetThemeManager(), context->GetAccessibilityManager());
849     if (!textOverlay) {
850         LOGE("textOverlay_ not null or is showing");
851         return nullptr;
852     }
853 
854     Offset startOffset;
855     Offset endOffset;
856     float startEdgeHeight;
857     float endEdgeHeight;
858     if (overlayType == INSERT_OVERLAY) {
859         float lineHeight = GreatNotEqual(insertHandle->GetEdgeHeight(), insertHandle->GetY()) ?
860             insertHandle->GetY() : insertHandle->GetEdgeHeight();
861         startOffset = NormalizeTouchHandleOffset(insertHandle->GetX()+1, insertHandle->GetY());
862         endOffset = startOffset;
863         startEdgeHeight = lineHeight;
864         endEdgeHeight = lineHeight;
865     } else {
866         startOffset = NormalizeTouchHandleOffset(startSelectionHandle->GetX(), startSelectionHandle->GetY());
867         endOffset = NormalizeTouchHandleOffset(endSelectionHandle->GetX(), endSelectionHandle->GetY());
868         startEdgeHeight = startSelectionHandle->GetEdgeHeight();
869         endEdgeHeight = endSelectionHandle->GetEdgeHeight();
870     }
871     textOverlay->SetWeakWeb(WeakClaim(this));
872     textOverlay->SetIsSingleHandle(false);
873     Rect clipRect(0.0, 0.0, Size::INFINITE_SIZE, Size::INFINITE_SIZE);
874     textOverlay->SetLineHeight(startEdgeHeight);
875     textOverlay->SetStartHandleHeight(startEdgeHeight);
876     textOverlay->SetEndHandleHeight(endEdgeHeight);
877     textOverlay->SetClipRect(clipRect);
878     textOverlay->SetNeedCilpRect(false);
879     textOverlay->SetStartHandleOffset(startOffset);
880     textOverlay->SetEndHandleOffset(endOffset);
881     textOverlay->SetTextDirection(TextDirection::LTR);
882     textOverlay->SetRealTextDirection(TextDirection::LTR);
883     textOverlay->SetContext(context_);
884     textOverlay->SetIsUsingMouse(false);
885     return textOverlay;
886 }
887 
NormalizeTouchHandleOffset(float x,float y)888 Offset RenderWeb::NormalizeTouchHandleOffset(float x, float y)
889 {
890     Offset renderWebOffset = GetGlobalOffset();
891     Size renderWebSize = GetLayoutSize();
892     float resultX;
893     float resultY;
894     if (x < 0) {
895         resultX = x;
896     } else if (x > renderWebSize.Width()) {
897         resultX = renderWebOffset.GetX() + renderWebSize.Width();
898     } else {
899         resultX = x + renderWebOffset.GetX();
900     }
901 
902     if (y < 0) {
903         resultY = renderWebOffset.GetY();
904     } else if (y > renderWebSize.Height()) {
905         resultY = renderWebOffset.GetY() + renderWebSize.Height();
906     } else {
907         resultY = y + renderWebOffset.GetY();
908     }
909     resultY += offsetFix_;
910     return {resultX, resultY};
911 }
912 
OnTouchSelectionChanged(std::shared_ptr<OHOS::NWeb::NWebTouchHandleState> insertHandle,std::shared_ptr<OHOS::NWeb::NWebTouchHandleState> startSelectionHandle,std::shared_ptr<OHOS::NWeb::NWebTouchHandleState> endSelectionHandle)913 void RenderWeb::OnTouchSelectionChanged(
914     std::shared_ptr<OHOS::NWeb::NWebTouchHandleState> insertHandle,
915     std::shared_ptr<OHOS::NWeb::NWebTouchHandleState> startSelectionHandle,
916     std::shared_ptr<OHOS::NWeb::NWebTouchHandleState> endSelectionHandle)
917 {
918     auto context = context_.Upgrade();
919     if (!context) {
920         return;
921     }
922 
923     WebOverlayType overlayType = GetTouchHandleOverlayType(insertHandle,
924                                                            startSelectionHandle,
925                                                            endSelectionHandle);
926     insertHandle_ = insertHandle;
927     startSelectionHandle_ = startSelectionHandle;
928     endSelectionHandle_ = endSelectionHandle;
929     if (overlayType == INVALID_OVERLAY) {
930         PopTextOverlay();
931         return;
932     }
933 
934     if (!textOverlay_) {
935         if (overlayType == INSERT_OVERLAY) {
936             showTextOveralyMenu_ = false;
937             showStartTouchHandle_ = IsTouchHandleShow(insertHandle);
938             showEndTouchHandle_ = IsTouchHandleShow(insertHandle);
939             if (!showStartTouchHandle_) {
940                 return;
941             }
942             textOverlay_ = CreateTextOverlay(insertHandle, startSelectionHandle, endSelectionHandle);
943             PushTextOverlayToStack();
944         }
945         return;
946     }
947 
948     if (overlayType == INSERT_OVERLAY) {
949         showStartTouchHandle_ = IsTouchHandleShow(insertHandle);
950         showEndTouchHandle_ = IsTouchHandleShow(insertHandle);
951         if (!showStartTouchHandle_) {
952             PopTextOverlay();
953             return;
954         }
955         float lineHeight = GreatNotEqual(insertHandle->GetEdgeHeight(), insertHandle->GetY()) ?
956             insertHandle->GetY() : insertHandle->GetEdgeHeight();
957         textOverlay_->SetStartHandleHeight(lineHeight);
958         showTextOveralyMenu_ = false;
959         OverlayShowOption option {
960             .showMenu = showTextOveralyMenu_,
961             .isSingleHandle = true,
962             .startHandleOffset = NormalizeTouchHandleOffset(insertHandle->GetX() + 1, insertHandle->GetY()),
963             .endHandleOffset = NormalizeTouchHandleOffset(insertHandle->GetX() + 1, insertHandle->GetY()),
964             .showStartHandle = showStartTouchHandle_,
965             .showEndHandle = showEndTouchHandle_,
966         };
967         if (updateHandlePosition_) {
968             updateHandlePosition_(option, lineHeight, lineHeight);
969         }
970     } else {
971         showStartTouchHandle_ = IsTouchHandleShow(startSelectionHandle);
972         showEndTouchHandle_ = IsTouchHandleShow(endSelectionHandle);
973         textOverlay_->SetStartHandleHeight(startSelectionHandle->GetEdgeHeight());
974         textOverlay_->SetEndHandleHeight(endSelectionHandle->GetEdgeHeight());
975         OverlayShowOption option {
976             .showMenu = true,
977             .isSingleHandle = false,
978             .startHandleOffset = NormalizeTouchHandleOffset(startSelectionHandle->GetX(), startSelectionHandle->GetY()),
979             .endHandleOffset = NormalizeTouchHandleOffset(endSelectionHandle->GetX(), endSelectionHandle->GetY()),
980             .showStartHandle = showStartTouchHandle_,
981             .showEndHandle = showEndTouchHandle_,
982         };
983         if (updateHandlePosition_) {
984             updateHandlePosition_(option, startSelectionHandle->GetEdgeHeight(), endSelectionHandle->GetEdgeHeight());
985         }
986     }
987 }
988 
OnCursorChange(const OHOS::NWeb::CursorType & type,const OHOS::NWeb::NWebCursorInfo & info)989 bool RenderWeb::OnCursorChange(const OHOS::NWeb::CursorType& type, const OHOS::NWeb::NWebCursorInfo& info)
990 {
991     (void)info;
992     auto context = GetContext().Upgrade();
993     if (!context) {
994         return false;
995     }
996     auto windowId = context->GetWindowId();
997     auto mouseStyle = MouseStyle::CreateMouseStyle();
998     int32_t curPointerStyle = 0;
999     if (mouseStyle->GetPointerStyle(windowId, curPointerStyle) == -1) {
1000         LOGE("OnCursorChange GetPointerStyle failed");
1001         return false;
1002     }
1003     MouseFormat pointStyle = MouseFormat::DEFAULT;
1004     int64_t idx = BinarySearchFindIndex(g_cursorTypeMap, ArraySize(g_cursorTypeMap), type);
1005     if (idx >= 0) {
1006         pointStyle = g_cursorTypeMap[idx].value;
1007     }
1008     if ((int32_t)pointStyle != curPointerStyle) {
1009         mouseStyle->SetPointerStyle(windowId, pointStyle);
1010     }
1011     return true;
1012 }
1013 
GenerateDragItemInfo(const RefPtr<PipelineContext> & context,const GestureEvent & info)1014 DragItemInfo RenderWeb::GenerateDragItemInfo(const RefPtr<PipelineContext>& context, const GestureEvent& info)
1015 {
1016     DragItemInfo itemInfo;
1017     if (delegate_) {
1018         itemInfo.pixelMap =  delegate_->GetDragPixelMap();
1019     }
1020 
1021     if (itemInfo.pixelMap) {
1022         LOGI("get w3c drag info");
1023         isW3cDragEvent_ = true;
1024         return itemInfo;
1025     }
1026 
1027     if (onDragStart_) {
1028         LOGI("user has set onDragStart");
1029         isW3cDragEvent_ = false;
1030         RefPtr<DragEvent> event = AceType::MakeRefPtr<DragEvent>();
1031         event->SetX(context->ConvertPxToVp(Dimension(info.GetGlobalPoint().GetX(), DimensionUnit::PX)));
1032         event->SetY(context->ConvertPxToVp(Dimension(info.GetGlobalPoint().GetY(), DimensionUnit::PX)));
1033         selectedItemSize_ = GetLayoutSize();
1034         auto extraParams = JsonUtil::Create(true);
1035         return onDragStart_(event, extraParams->ToString());
1036     }
1037 
1038     return itemInfo;
1039 }
1040 
OnDragWindowStartEvent(RefPtr<PipelineContext> pipelineContext,const GestureEvent & info,const DragItemInfo & dragItemInfo)1041 void RenderWeb::OnDragWindowStartEvent(RefPtr<PipelineContext> pipelineContext, const GestureEvent& info,
1042     const DragItemInfo& dragItemInfo)
1043 {
1044     LOGI("create drag window");
1045     auto rect = pipelineContext->GetCurrentWindowRect();
1046     int32_t globalX = static_cast<int32_t>(info.GetGlobalPoint().GetX());
1047     int32_t globalY = static_cast<int32_t>(info.GetGlobalPoint().GetY());
1048     dragWindow_ = DragWindow::CreateDragWindow("APP_DRAG_WINDOW", globalX + rect.Left(), globalY + rect.Top(),
1049         dragItemInfo.pixelMap->GetWidth(), dragItemInfo.pixelMap->GetHeight());
1050     dragWindow_->SetOffset(rect.Left(), rect.Top());
1051     dragWindow_->DrawPixelMap(dragItemInfo.pixelMap);
1052     if (isW3cDragEvent_ && delegate_) {
1053         LOGI("w3c drag start");
1054         auto viewScale = pipelineContext->GetViewScale();
1055         int32_t localX = static_cast<int32_t>(globalX - GetCoordinatePoint().GetX());
1056         int32_t localY = static_cast<int32_t>(globalY - GetCoordinatePoint().GetY());
1057         delegate_->HandleDragEvent(localX * viewScale, localY * viewScale, DragAction::DRAG_ENTER);
1058     }
1059 }
1060 
PanOnActionStart(const GestureEvent & info)1061 void RenderWeb::PanOnActionStart(const GestureEvent& info)
1062 {
1063     LOGI("web drag action start");
1064     auto pipelineContext = context_.Upgrade();
1065     if (!pipelineContext) {
1066         LOGE("Context is null.");
1067         return;
1068     }
1069 
1070     isDragging_ = true;
1071     GestureEvent newInfo = info;
1072     newInfo.SetGlobalPoint(startPoint_);
1073     auto dragItemInfo = GenerateDragItemInfo(pipelineContext, newInfo);
1074 #if !defined(WINDOWS_PLATFORM) and !defined(MAC_PLATFORM)
1075     if (dragItemInfo.pixelMap) {
1076         auto initRenderNode = AceType::Claim(this);
1077         isDragDropNode_  = true;
1078         pipelineContext->SetInitRenderNode(initRenderNode);
1079         AddDataToClipboard(pipelineContext, dragItemInfo.extraInfo, "", "");
1080         if (!dragWindow_) {
1081             OnDragWindowStartEvent(pipelineContext, info, dragItemInfo);
1082         }
1083         return;
1084     }
1085 #endif
1086     if (!dragItemInfo.customComponent) {
1087         LOGW("the drag custom component is null");
1088         isDragging_ = false;
1089         return;
1090     }
1091 
1092     hasDragItem_ = true;
1093     auto positionedComponent = AceType::MakeRefPtr<PositionedComponent>(dragItemInfo.customComponent);
1094     positionedComponent->SetTop(Dimension(GetGlobalOffset().GetY()));
1095     positionedComponent->SetLeft(Dimension(GetGlobalOffset().GetX()));
1096     SetLocalPoint(info.GetGlobalPoint() - GetGlobalOffset());
1097     auto updatePosition = [renderBox = AceType::Claim(this)](
1098                                 const std::function<void(const Dimension&, const Dimension&)>& func) {
1099         if (!renderBox) {
1100             return;
1101         }
1102         renderBox->SetUpdateBuilderFuncId(func);
1103     };
1104     positionedComponent->SetUpdatePositionFuncId(updatePosition);
1105     auto stackElement = pipelineContext->GetLastStack();
1106     stackElement->PushComponent(positionedComponent);
1107 }
1108 
OnDragWindowMoveEvent(RefPtr<PipelineContext> pipelineContext,const GestureEvent & info)1109 void RenderWeb::OnDragWindowMoveEvent(RefPtr<PipelineContext> pipelineContext, const GestureEvent& info)
1110 {
1111     int32_t globalX = static_cast<int32_t>(info.GetGlobalPoint().GetX());
1112     int32_t globalY = static_cast<int32_t>(info.GetGlobalPoint().GetY());
1113     LOGD("drag window position update, x = %{public}d, y = %{public}d", globalX, globalY);
1114     dragWindow_->MoveTo(globalX, globalY);
1115     if (isW3cDragEvent_ && delegate_) {
1116         LOGD("w3c drag update");
1117         auto viewScale = pipelineContext->GetViewScale();
1118         int32_t localX = static_cast<int32_t>(globalX - GetCoordinatePoint().GetX());
1119         int32_t localY = static_cast<int32_t>(globalY - GetCoordinatePoint().GetY());
1120         delegate_->HandleDragEvent(localX * viewScale, localY * viewScale, DragAction::DRAG_OVER);
1121     }
1122 }
1123 
PanOnActionUpdate(const GestureEvent & info)1124 void RenderWeb::PanOnActionUpdate(const GestureEvent& info)
1125 {
1126     LOGD("web drag action update");
1127     auto pipelineContext = context_.Upgrade();
1128     if (!pipelineContext) {
1129         LOGE("Context is null.");
1130         return;
1131     }
1132 
1133 #if !defined(WINDOWS_PLATFORM) and !defined(MAC_PLATFORM)
1134     if (isDragDropNode_  && dragWindow_) {
1135         OnDragWindowMoveEvent(pipelineContext, info);
1136         return;
1137     }
1138 #endif
1139 
1140     RefPtr<DragEvent> event = AceType::MakeRefPtr<DragEvent>();
1141     event->SetX(pipelineContext->ConvertPxToVp(Dimension(info.GetGlobalPoint().GetX(), DimensionUnit::PX)));
1142     event->SetY(pipelineContext->ConvertPxToVp(Dimension(info.GetGlobalPoint().GetY(), DimensionUnit::PX)));
1143 
1144     Offset offset = info.GetGlobalPoint() - GetLocalPoint();
1145     if (GetUpdateBuilderFuncId()) {
1146         GetUpdateBuilderFuncId()(Dimension(offset.GetX()), Dimension(offset.GetY()));
1147     }
1148 
1149     auto extraParams = JsonUtil::Create(true);
1150     auto targetDragDropNode = FindDragDropNode(pipelineContext, info);
1151     auto preDragDropNode = GetPreDragDropNode();
1152     if (preDragDropNode == targetDragDropNode) {
1153         if (targetDragDropNode && targetDragDropNode->GetOnDragMove()) {
1154             (targetDragDropNode->GetOnDragMove())(event, extraParams->ToString());
1155         }
1156         return;
1157     }
1158     if (preDragDropNode && preDragDropNode->GetOnDragLeave()) {
1159         (preDragDropNode->GetOnDragLeave())(event, extraParams->ToString());
1160     }
1161     if (targetDragDropNode && targetDragDropNode->GetOnDragEnter()) {
1162         (targetDragDropNode->GetOnDragEnter())(event, extraParams->ToString());
1163     }
1164     SetPreDragDropNode(targetDragDropNode);
1165 }
1166 
OnDragWindowDropEvent(RefPtr<PipelineContext> pipelineContext,const GestureEvent & info)1167 void RenderWeb::OnDragWindowDropEvent(RefPtr<PipelineContext> pipelineContext, const GestureEvent& info)
1168 {
1169     if (GetOnDrop()) {
1170         RefPtr<DragEvent> event = AceType::MakeRefPtr<DragEvent>();
1171         RefPtr<PasteData> pasteData = AceType::MakeRefPtr<PasteData>();
1172         event->SetPasteData(pasteData);
1173         event->SetX(pipelineContext->ConvertPxToVp(Dimension(info.GetGlobalPoint().GetX(), DimensionUnit::PX)));
1174         event->SetY(pipelineContext->ConvertPxToVp(Dimension(info.GetGlobalPoint().GetY(), DimensionUnit::PX)));
1175 
1176         auto extraParams = JsonUtil::Create(true);
1177         (GetOnDrop())(event, extraParams->ToString());
1178         pipelineContext->SetInitRenderNode(nullptr);
1179     }
1180 
1181     if (isW3cDragEvent_ && delegate_) {
1182         LOGI("w3c drag end");
1183         auto viewScale = pipelineContext->GetViewScale();
1184         int32_t localX = static_cast<int32_t>(info.GetGlobalPoint().GetX() - GetCoordinatePoint().GetX());
1185         int32_t localY = static_cast<int32_t>(info.GetGlobalPoint().GetY() - GetCoordinatePoint().GetY());
1186         delegate_->HandleDragEvent(localX * viewScale, localY * viewScale, DragAction::DRAG_DROP);
1187         delegate_->HandleDragEvent(localX * viewScale, localY * viewScale, DragAction::DRAG_END);
1188     }
1189 }
1190 
PanOnActionEnd(const GestureEvent & info)1191 void RenderWeb::PanOnActionEnd(const GestureEvent& info)
1192 {
1193     LOGI("web drag action end");
1194     isDragging_ = false;
1195     auto pipelineContext = context_.Upgrade();
1196     if (!pipelineContext) {
1197         LOGE("Context is null.");
1198         return;
1199     }
1200 #if !defined(WINDOWS_PLATFORM) and !defined(MAC_PLATFORM)
1201     if (isDragDropNode_) {
1202         isDragDropNode_  = false;
1203         RestoreCilpboardData(pipelineContext);
1204         OnDragWindowDropEvent(pipelineContext, info);
1205     }
1206 
1207     if (dragWindow_) {
1208         dragWindow_->Destroy();
1209         dragWindow_ = nullptr;
1210         return;
1211     }
1212 #endif
1213 
1214     RefPtr<DragEvent> event = AceType::MakeRefPtr<DragEvent>();
1215     RefPtr<PasteData> pasteData = AceType::MakeRefPtr<PasteData>();
1216     event->SetPasteData(pasteData);
1217     event->SetX(pipelineContext->ConvertPxToVp(Dimension(info.GetGlobalPoint().GetX(), DimensionUnit::PX)));
1218     event->SetY(pipelineContext->ConvertPxToVp(Dimension(info.GetGlobalPoint().GetY(), DimensionUnit::PX)));
1219 
1220     Offset offset = info.GetGlobalPoint() - GetLocalPoint();
1221     if (GetUpdateBuilderFuncId()) {
1222         GetUpdateBuilderFuncId()(Dimension(offset.GetX()), Dimension(offset.GetY()));
1223     }
1224     if (hasDragItem_) {
1225         auto stackElement = pipelineContext->GetLastStack();
1226         stackElement->PopComponent();
1227     }
1228     hasDragItem_ = false;
1229 
1230     ACE_DCHECK(GetPreDragDropNode() == FindTargetRenderNode<DragDropEvent>(pipelineContext, info));
1231     auto targetDragDropNode = GetPreDragDropNode();
1232     if (!targetDragDropNode) {
1233         return;
1234     }
1235     if (targetDragDropNode->GetOnDrop()) {
1236         auto extraParams = JsonUtil::Create(true);
1237         (targetDragDropNode->GetOnDrop())(event, extraParams->ToString());
1238     }
1239     SetPreDragDropNode(nullptr);
1240 }
1241 
PanOnActionCancel()1242 void RenderWeb::PanOnActionCancel()
1243 {
1244     LOGI("drag cancel");
1245     isDragging_ = false;
1246     auto pipelineContext = context_.Upgrade();
1247     if (!pipelineContext) {
1248         LOGE("Context is null.");
1249         return;
1250     }
1251 
1252 #if !defined(WINDOWS_PLATFORM) and !defined(MAC_PLATFORM)
1253     if (isDragDropNode_) {
1254         RestoreCilpboardData(pipelineContext);
1255         isDragDropNode_ = false;
1256         if (isW3cDragEvent_ && delegate_) {
1257             LOGI("w3c drag cancel");
1258             delegate_->HandleDragEvent(0, 0, DragAction::DRAG_CANCEL);
1259         }
1260     }
1261 
1262     if (dragWindow_) {
1263         dragWindow_->Destroy();
1264         dragWindow_ = nullptr;
1265     }
1266 #endif
1267 
1268     if (hasDragItem_) {
1269         auto stackElement = pipelineContext->GetLastStack();
1270         stackElement->PopComponent();
1271         hasDragItem_ = false;
1272     }
1273     SetPreDragDropNode(nullptr);
1274 }
1275 
UpdateGlobalPos()1276 void RenderWeb::UpdateGlobalPos()
1277 {
1278     auto position = GetGlobalOffset();
1279     if (delegate_) {
1280         delegate_->SetWebRendeGlobalPos(position);
1281     }
1282 }
1283 
BuildSelectMenu(const std::string & value)1284 RefPtr<OptionComponent> RenderWeb::BuildSelectMenu(const std::string& value)
1285 {
1286     auto context = context_.Upgrade();
1287     if (!context) {
1288         return nullptr;
1289     }
1290     if (!themeManager_) {
1291         themeManager_ = context->GetThemeManager();
1292     }
1293     if (!accessibilityManager_) {
1294         accessibilityManager_ = context->GetAccessibilityManager();
1295     }
1296     auto optionComponent = AceType::MakeRefPtr<OptionComponent>();
1297     if (!optionComponent) {
1298         return nullptr;
1299     }
1300     optionComponent->SetNeedDrawDividerLine(false);
1301     auto textComponent = AceType::MakeRefPtr<TextComponent>(value);
1302     optionComponent->SetText(textComponent);
1303     optionComponent->SetValue(value);
1304     optionComponent->InitTheme(themeManager_);
1305     optionComponent->Initialize(accessibilityManager_);
1306     return optionComponent;
1307 }
1308 
OnSelectPopupMenu(std::shared_ptr<OHOS::NWeb::NWebSelectPopupMenuParam> params,std::shared_ptr<OHOS::NWeb::NWebSelectPopupMenuCallback> callback)1309 void RenderWeb::OnSelectPopupMenu(
1310     std::shared_ptr<OHOS::NWeb::NWebSelectPopupMenuParam> params,
1311     std::shared_ptr<OHOS::NWeb::NWebSelectPopupMenuCallback> callback)
1312 {
1313     auto context = context_.Upgrade();
1314     if (!context || !params || !callback) {
1315         return;
1316     }
1317     const auto pipeline = context_.Upgrade();
1318     if (!pipeline) {
1319         return;
1320     }
1321     auto stackElement = pipeline->GetLastStack();
1322     if (!stackElement) {
1323         return;
1324     }
1325     popup_ = AceType::MakeRefPtr<SelectPopupComponent>();
1326     auto themeManager = context->GetThemeManager();
1327     popup_->InitTheme(themeManager);
1328     for (size_t index = 0; index < params->menuItems.size(); index++) {
1329         RefPtr<OptionComponent> option = BuildSelectMenu(params->menuItems[index].label);
1330         if (!option) {
1331             continue;
1332         }
1333         popup_->AppendSelectOption(option);
1334         if (index == params->selectedItem) {
1335             option->SetSelected(true);
1336         }
1337     }
1338     popup_->SetOptionClickedCallback([callback](std::size_t index) {
1339         std::vector<int32_t> indices { static_cast<int32_t>(index) };
1340         callback->Continue(indices);
1341     });
1342     popup_->SetPopupCanceledCallback([callback]() {
1343         callback->Cancel();
1344     });
1345 
1346     Offset leftTop = { params->bounds.x + GetGlobalOffset().GetX(),
1347                        params->bounds.y + GetGlobalOffset().GetY() };
1348     Offset rightBottom = { params->bounds.x + GetGlobalOffset().GetX() + params->bounds.width,
1349                            params->bounds.y + GetGlobalOffset().GetY() + params->bounds.height };
1350     popup_->ShowDialog(stackElement, leftTop, rightBottom, false);
1351 }
1352 #endif
1353 } // namespace OHOS::Ace
1354