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