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