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