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