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