1 /*
2 * Copyright (c) 2023 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_ng/pattern/ui_extension/ui_extension_pattern.h"
17
18 #include <cstdint>
19
20 #include "session/host/include/extension_session.h"
21 #include "session_manager/include/extension_session_manager.h"
22 #include "ui/rs_surface_node.h"
23
24 #include "adapter/ohos/entrance/ace_container.h"
25 #include "adapter/ohos/entrance/mmi_event_convertor.h"
26 #include "adapter/ohos/osal/want_wrap_ohos.h"
27 #include "base/utils/utils.h"
28 #include "core/components_ng/event/event_hub.h"
29 #include "core/components_ng/pattern/pattern.h"
30 #include "core/components_ng/pattern/text_field/text_field_manager.h"
31 #include "core/components_ng/pattern/ui_extension/ui_extension_layout_algorithm.h"
32 #include "core/components_ng/pattern/ui_extension/ui_extension_proxy.h"
33 #include "core/components_ng/pattern/window_scene/scene/window_pattern.h"
34 #include "core/components_ng/render/adapter/rosen_render_context.h"
35 #include "core/event/ace_events.h"
36 #include "core/event/mouse_event.h"
37 #include "core/event/touch_event.h"
38 #include "core/pipeline_ng/pipeline_context.h"
39
40 namespace OHOS::Ace::NG {
UIExtensionPattern(const RefPtr<OHOS::Ace::WantWrap> & wantWrap)41 UIExtensionPattern::UIExtensionPattern(const RefPtr<OHOS::Ace::WantWrap>& wantWrap)
42 {
43 auto container = AceType::DynamicCast<Platform::AceContainer>(Container::Current());
44 CHECK_NULL_VOID_NOLOG(container);
45 auto callerToken = container->GetToken();
46 auto want = AceType::DynamicCast<WantWrapOhos>(wantWrap)->GetWant();
47 if (want.GetElement().GetBundleName() == "AbilityComp") {
48 return;
49 }
50 Rosen::SessionInfo extensionSessionInfo = {
51 .bundleName_ = want.GetElement().GetBundleName(),
52 .abilityName_ = want.GetElement().GetAbilityName(),
53 .callerToken_ = callerToken,
54 .want = new (std::nothrow) Want(want),
55 };
56 session_ = Rosen::ExtensionSessionManager::GetInstance().RequestExtensionSession(extensionSessionInfo);
57 CHECK_NULL_VOID(session_);
58 RegisterLifecycleListener();
59 LOGI("UIExtension request UIExtensionAbility start");
60 RequestExtensionSessionActivation();
61 sptr<Rosen::ExtensionSession> extensionSession(static_cast<Rosen::ExtensionSession*>(session_.GetRefPtr()));
62 sptr<Rosen::ExtensionSession::ExtensionSessionEventCallback> extSessionEventCallback =
63 new (std::nothrow) Rosen::ExtensionSession::ExtensionSessionEventCallback();
64 extensionSession->RegisterExtensionSessionEventCallback(extSessionEventCallback);
65 }
66
UIExtensionPattern(const AAFwk::Want & want)67 UIExtensionPattern::UIExtensionPattern(const AAFwk::Want& want)
68 {
69 auto container = AceType::DynamicCast<Platform::AceContainer>(Container::Current());
70 CHECK_NULL_VOID_NOLOG(container);
71 auto callerToken = container->GetToken();
72 Rosen::SessionInfo extensionSessionInfo = {
73 .bundleName_ = want.GetElement().GetBundleName(),
74 .abilityName_ = want.GetElement().GetAbilityName(),
75 .callerToken_ = callerToken,
76 .want = new (std::nothrow) Want(want),
77 };
78 session_ = Rosen::ExtensionSessionManager::GetInstance().RequestExtensionSession(extensionSessionInfo);
79 CHECK_NULL_VOID(session_);
80 RegisterLifecycleListener();
81 LOGI("Native Modal UIExtension request UIExtensionAbility start");
82 RequestExtensionSessionActivation();
83 sptr<Rosen::ExtensionSession> extensionSession(static_cast<Rosen::ExtensionSession*>(session_.GetRefPtr()));
84 sptr<Rosen::ExtensionSession::ExtensionSessionEventCallback> extSessionEventCallback =
85 new (std::nothrow) Rosen::ExtensionSession::ExtensionSessionEventCallback();
86 extensionSession->RegisterExtensionSessionEventCallback(extSessionEventCallback);
87 }
88
~UIExtensionPattern()89 UIExtensionPattern::~UIExtensionPattern()
90 {
91 UnregisterLifecycleListener();
92 UnregisterAbilityResultListener();
93 RequestExtensionSessionDestruction();
94 }
95
OnConnect()96 void UIExtensionPattern::OnConnect()
97 {
98 LOGI("UIExtension OnConnect called");
99 ContainerScope scope(instanceId_);
100 auto pipeline = PipelineBase::GetCurrentContext();
101 CHECK_NULL_VOID_NOLOG(pipeline);
102 auto taskExecutor = pipeline->GetTaskExecutor();
103 CHECK_NULL_VOID_NOLOG(taskExecutor);
104 taskExecutor->PostTask(
105 [weak = WeakClaim(this)]() {
106 auto extensionPattern = weak.Upgrade();
107 CHECK_NULL_VOID_NOLOG(extensionPattern);
108 extensionPattern->OnConnectInner();
109 },
110 TaskExecutor::TaskType::UI);
111 }
112
OnConnectInner()113 void UIExtensionPattern::OnConnectInner()
114 {
115 ContainerScope scope(instanceId_);
116 auto surfaceNode = session_->GetSurfaceNode();
117 CHECK_NULL_VOID_NOLOG(surfaceNode);
118 CHECK_NULL_VOID_NOLOG(contentNode_);
119 auto context = AceType::DynamicCast<NG::RosenRenderContext>(contentNode_->GetRenderContext());
120 CHECK_NULL_VOID_NOLOG(context);
121 context->SetRSNode(surfaceNode);
122 auto host = GetHost();
123 CHECK_NULL_VOID_NOLOG(host);
124 host->AddChild(contentNode_, 0);
125 host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
126 surfaceNode->CreateNodeInRenderThread();
127 auto pipeline = PipelineBase::GetCurrentContext();
128 if (onRemoteReadyCallback_) {
129 onRemoteReadyCallback_(MakeRefPtr<UIExtensionProxy>(session_));
130 }
131 RegisterVisibleAreaChange();
132 TransferFocusState(IsCurrentFocus());
133 }
134
OnDisconnect()135 void UIExtensionPattern::OnDisconnect()
136 {
137 LOGI("UIExtension OnDisconnect called");
138 ContainerScope scope(instanceId_);
139 auto pipeline = PipelineBase::GetCurrentContext();
140 CHECK_NULL_VOID_NOLOG(pipeline);
141 auto taskExecutor = pipeline->GetTaskExecutor();
142 CHECK_NULL_VOID_NOLOG(taskExecutor);
143 isDestruction_ = true;
144 taskExecutor->PostTask(
145 [weak = WeakClaim(this)]() {
146 auto extensionPattern = weak.Upgrade();
147 CHECK_NULL_VOID_NOLOG(extensionPattern);
148 if (extensionPattern->onReleaseCallback_) {
149 extensionPattern->onReleaseCallback_(static_cast<int32_t>(ReleaseCode::DESTROY_NORMAL));
150 }
151 },
152 TaskExecutor::TaskType::UI);
153 }
154
OnExtensionDied()155 void UIExtensionPattern::OnExtensionDied()
156 {
157 LOGI("UIExtensionPattern OnExtensionDied called");
158 ContainerScope scope(instanceId_);
159 auto pipeline = PipelineBase::GetCurrentContext();
160 CHECK_NULL_VOID_NOLOG(pipeline);
161 auto taskExecutor = pipeline->GetTaskExecutor();
162 CHECK_NULL_VOID_NOLOG(taskExecutor);
163 taskExecutor->PostTask(
164 [weak = WeakClaim(this)]() {
165 auto extensionPattern = weak.Upgrade();
166 CHECK_NULL_VOID_NOLOG(extensionPattern);
167 if (extensionPattern->onReleaseCallback_) {
168 extensionPattern->isDestruction_ = true;
169 extensionPattern->onReleaseCallback_(static_cast<int32_t>(ReleaseCode::CONNECT_BROKEN));
170 }
171 },
172 TaskExecutor::TaskType::UI);
173 }
174
OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper> & dirty,const DirtySwapConfig & config)175 bool UIExtensionPattern::OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dirty, const DirtySwapConfig& config)
176 {
177 CHECK_NULL_RETURN(dirty, false);
178 auto host = dirty->GetHostNode();
179 CHECK_NULL_RETURN(host, false);
180 auto globalOffsetWithTranslate = host->GetPaintRectGlobalOffsetWithTranslate();
181 auto geometryNode = dirty->GetGeometryNode();
182 CHECK_NULL_RETURN(geometryNode, false);
183 auto frameRect = geometryNode->GetFrameRect();
184
185 Rosen::WSRect windowRect {
186 .posX_ = std::round(globalOffsetWithTranslate.GetX()),
187 .posY_ = std::round(globalOffsetWithTranslate.GetY()),
188 .width_ = std::round(frameRect.Width()),
189 .height_ = std::round(frameRect.Height())
190 };
191
192 CHECK_NULL_RETURN(session_, false);
193 session_->UpdateRect(windowRect, Rosen::SizeChangeReason::UNDEFINED);
194 return false;
195 }
196
OnWindowShow()197 void UIExtensionPattern::OnWindowShow()
198 {
199 RequestExtensionSessionActivation();
200 }
201
OnWindowHide()202 void UIExtensionPattern::OnWindowHide()
203 {
204 RequestExtensionSessionBackground();
205 }
206
RequestExtensionSessionActivation()207 void UIExtensionPattern::RequestExtensionSessionActivation()
208 {
209 auto pipeline = PipelineBase::GetCurrentContext();
210 CHECK_NULL_VOID_NOLOG(pipeline);
211 auto hostWindowId = pipeline->GetFocusWindowId();
212 LOGI("ui_extension request host windowId %{public}u", hostWindowId);
213 sptr<Rosen::ExtensionSession> extensionSession(static_cast<Rosen::ExtensionSession*>(session_.GetRefPtr()));
214 auto errcode = Rosen::ExtensionSessionManager::GetInstance().RequestExtensionSessionActivation(
215 extensionSession, hostWindowId);
216 if (errcode != OHOS::Rosen::WSError::WS_OK) {
217 int32_t code = static_cast<int32_t>(errcode);
218 std::string name = "start_ability_fail";
219 std::string message = "Start ui extension ability failed, please check the want of UIextensionAbility.";
220 lastError_ = { code, name, message };
221 if (onErrorCallback_) {
222 ErrorMsg error;
223 std::swap(lastError_, error);
224 onErrorCallback_(error.code, error.name, error.message);
225 }
226 }
227 }
228
RequestExtensionSessionBackground()229 void UIExtensionPattern::RequestExtensionSessionBackground()
230 {
231 LOGI("UIExtension request UIExtensionAbility background, isDestruction_=%{public}u", isDestruction_);
232 if (!isDestruction_) {
233 sptr<Rosen::ExtensionSession> extensionSession(static_cast<Rosen::ExtensionSession*>(session_.GetRefPtr()));
234 auto errcode =
235 Rosen::ExtensionSessionManager::GetInstance().RequestExtensionSessionBackground(extensionSession);
236 if (errcode != OHOS::Rosen::WSError::WS_OK) {
237 if (onErrorCallback_) {
238 int32_t code = static_cast<int32_t>(errcode);
239 std::string name = "background_fail";
240 std::string message = "background ui extension ability failed, please check AMS log.";
241 onErrorCallback_(code, name, message);
242 }
243 }
244 }
245 }
246
RequestExtensionSessionDestruction()247 void UIExtensionPattern::RequestExtensionSessionDestruction()
248 {
249 LOGI("UIExtension request UIExtensionAbility destroy, isDestruction_=%{public}u", isDestruction_);
250 if (!isDestruction_) {
251 sptr<Rosen::ExtensionSession> extensionSession(static_cast<Rosen::ExtensionSession*>(session_.GetRefPtr()));
252 auto errcode =
253 Rosen::ExtensionSessionManager::GetInstance().RequestExtensionSessionDestruction(extensionSession);
254 if (errcode != OHOS::Rosen::WSError::WS_OK) {
255 if (onErrorCallback_) {
256 int32_t code = static_cast<int32_t>(errcode);
257 std::string name = "terminate_fail";
258 std::string message = "terminate ui extension ability failed, please check AMS log.";
259 onErrorCallback_(code, name, message);
260 }
261 }
262 }
263 }
264
CreateLayoutAlgorithm()265 RefPtr<LayoutAlgorithm> UIExtensionPattern::CreateLayoutAlgorithm()
266 {
267 return MakeRefPtr<UIExtensionLayoutAlgorithm>();
268 }
269
OnDetachFromFrameNode(FrameNode * frameNode)270 void UIExtensionPattern::OnDetachFromFrameNode(FrameNode* frameNode)
271 {
272 auto id = frameNode->GetId();
273 auto pipeline = AceType::DynamicCast<PipelineContext>(PipelineBase::GetCurrentContext());
274 CHECK_NULL_VOID_NOLOG(pipeline);
275 pipeline->RemoveWindowStateChangedCallback(id);
276 auto textFieldManager = DynamicCast<TextFieldManagerNG>(pipeline->GetTextFieldManager());
277 if (textFieldManager) {
278 textFieldManager->ClearOnFocusTextField();
279 }
280 }
281
GetFocusPattern() const282 FocusPattern UIExtensionPattern::GetFocusPattern() const
283 {
284 return { FocusType::NODE, true, FocusStyleType::NONE };
285 }
286
InitOnKeyEvent(const RefPtr<FocusHub> & focusHub)287 void UIExtensionPattern::InitOnKeyEvent(const RefPtr<FocusHub>& focusHub)
288 {
289 focusHub->SetOnFocusInternal([weak = WeakClaim(this)]() {
290 auto pattern = weak.Upgrade();
291 if (pattern) {
292 pattern->HandleFocusEvent();
293 }
294 });
295
296 focusHub->SetOnBlurInternal([weak = WeakClaim(this)]() {
297 auto pattern = weak.Upgrade();
298 if (pattern) {
299 pattern->HandleBlurEvent();
300 }
301 });
302
303 focusHub->SetOnClearFocusStateInternal([weak = WeakClaim(this)]() {
304 auto pattern = weak.Upgrade();
305 if (pattern) {
306 pattern->DisPatchFocusActiveEvent(false);
307 }
308 });
309 focusHub->SetOnPaintFocusStateInternal([weak = WeakClaim(this)]() -> bool {
310 auto pattern = weak.Upgrade();
311 if (pattern) {
312 pattern->DisPatchFocusActiveEvent(true);
313 return true;
314 }
315 return false;
316 });
317
318 focusHub->SetOnKeyEventInternal([wp = WeakClaim(this)](const KeyEvent& event) -> bool {
319 auto pattern = wp.Upgrade();
320 if (pattern) {
321 return pattern->OnKeyEvent(event);
322 }
323 return false;
324 });
325 }
326
HandleFocusEvent()327 void UIExtensionPattern::HandleFocusEvent()
328 {
329 auto pipeline = PipelineContext::GetCurrentContext();
330 if (pipeline->GetIsFocusActive()) {
331 WindowPattern::DisPatchFocusActiveEvent(true);
332 }
333 TransferFocusState(true);
334 }
335
HandleBlurEvent()336 void UIExtensionPattern::HandleBlurEvent()
337 {
338 WindowPattern::DisPatchFocusActiveEvent(false);
339 TransferFocusState(false);
340 auto pipeline = AceType::DynamicCast<PipelineContext>(PipelineBase::GetCurrentContext());
341 CHECK_NULL_VOID_NOLOG(pipeline);
342 auto textFieldManager = DynamicCast<TextFieldManagerNG>(pipeline->GetTextFieldManager());
343 if (textFieldManager) {
344 textFieldManager->ClearOnFocusTextField();
345 }
346 }
347
KeyEventConsumed(const KeyEvent & event)348 bool UIExtensionPattern::KeyEventConsumed(const KeyEvent& event)
349 {
350 bool isConsumed = false;
351 WindowPattern::DispatchKeyEventForConsumed(event.rawKeyEvent, isConsumed);
352 return isConsumed;
353 }
354
OnKeyEvent(const KeyEvent & event)355 bool UIExtensionPattern::OnKeyEvent(const KeyEvent& event)
356 {
357 if (event.code == KeyCode::KEY_TAB && event.action == KeyAction::DOWN) {
358 auto pipeline = PipelineContext::GetCurrentContext();
359 CHECK_NULL_RETURN(pipeline, false);
360 // tab trigger consume the key event
361 return pipeline->IsTabJustTriggerOnKeyEvent();
362 } else {
363 return KeyEventConsumed(event);
364 }
365 }
366
InitTouchEvent(const RefPtr<GestureEventHub> & gestureHub)367 void UIExtensionPattern::InitTouchEvent(const RefPtr<GestureEventHub>& gestureHub)
368 {
369 if (touchEvent_) {
370 return;
371 }
372 auto callback = [weak = WeakClaim(this)](const TouchEventInfo& info) {
373 auto pattern = weak.Upgrade();
374 if (pattern) {
375 pattern->HandleTouchEvent(info);
376 }
377 };
378 if (touchEvent_) {
379 gestureHub->RemoveTouchEvent(touchEvent_);
380 }
381 touchEvent_ = MakeRefPtr<TouchEventImpl>(std::move(callback));
382 gestureHub->AddTouchEvent(touchEvent_);
383 }
384
InitMouseEvent(const RefPtr<InputEventHub> & inputHub)385 void UIExtensionPattern::InitMouseEvent(const RefPtr<InputEventHub>& inputHub)
386 {
387 if (mouseEvent_) {
388 return;
389 }
390 auto callback = [weak = WeakClaim(this)](MouseInfo& info) {
391 auto pattern = weak.Upgrade();
392 if (pattern) {
393 pattern->HandleMouseEvent(info);
394 }
395 };
396 if (mouseEvent_) {
397 inputHub->RemoveOnMouseEvent(mouseEvent_);
398 }
399 mouseEvent_ = MakeRefPtr<InputEvent>(std::move(callback));
400 inputHub->AddOnMouseEvent(mouseEvent_);
401 }
402
HandleTouchEvent(const TouchEventInfo & info)403 void UIExtensionPattern::HandleTouchEvent(const TouchEventInfo& info)
404 {
405 if (info.GetSourceDevice() != SourceType::TOUCH) {
406 return;
407 }
408 const auto pointerEvent = info.GetPointerEvent();
409 CHECK_NULL_VOID_NOLOG(pointerEvent);
410 auto host = GetHost();
411 CHECK_NULL_VOID_NOLOG(host);
412 auto selfGlobalOffset = host->GetTransformRelativeOffset();
413 auto scale = host->GetTransformScale();
414 Platform::CalculatePointerEvent(selfGlobalOffset, pointerEvent, scale);
415 auto hub = host->GetFocusHub();
416 CHECK_NULL_VOID(hub);
417 hub->RequestFocusImmediately();
418
419 auto touchType = info.GetTouches().front().GetTouchType();
420 if (touchType == TouchType::DOWN) {
421 auto touchOffsetToWindow = info.GetTouches().front().GetGlobalLocation();
422 auto touchOffsetToFrameNode = info.GetTouches().front().GetLocalLocation();
423 auto rectToWindow = host->GetTransformRectRelativeToWindow();
424 UpdateTextFieldManager({ rectToWindow.GetOffset().GetX(), touchOffsetToWindow.GetY() },
425 rectToWindow.Height() - touchOffsetToFrameNode.GetY());
426 }
427
428 WindowPattern::DispatchPointerEvent(pointerEvent);
429 }
430
HandleMouseEvent(const MouseInfo & info)431 void UIExtensionPattern::HandleMouseEvent(const MouseInfo& info)
432 {
433 if (info.GetSourceDevice() != SourceType::MOUSE) {
434 return;
435 }
436 const auto pointerEvent = info.GetPointerEvent();
437 CHECK_NULL_VOID_NOLOG(pointerEvent);
438 auto host = GetHost();
439 CHECK_NULL_VOID_NOLOG(host);
440 auto selfGlobalOffset = host->GetTransformRelativeOffset();
441 auto scale = host->GetTransformScale();
442 Platform::CalculatePointerEvent(selfGlobalOffset, pointerEvent, scale);
443 if (info.GetAction() == MouseAction::PRESS) {
444 auto hub = host->GetFocusHub();
445 CHECK_NULL_VOID(hub);
446 hub->RequestFocusImmediately();
447
448 auto mouseOffsetToWindow = info.GetGlobalLocation();
449 auto mouseOffsetToFrameNode = info.GetLocalLocation();
450 auto rectToWindow = host->GetTransformRectRelativeToWindow();
451 UpdateTextFieldManager({ rectToWindow.GetOffset().GetX(), mouseOffsetToWindow.GetY() },
452 rectToWindow.Height() - mouseOffsetToFrameNode.GetY());
453 }
454 WindowPattern::DispatchPointerEvent(pointerEvent);
455 }
456
OnModifyDone()457 void UIExtensionPattern::OnModifyDone()
458 {
459 Pattern::OnModifyDone();
460 auto host = GetHost();
461 CHECK_NULL_VOID_NOLOG(host);
462 auto hub = host->GetEventHub<EventHub>();
463 CHECK_NULL_VOID_NOLOG(hub);
464 auto gestureHub = hub->GetOrCreateGestureEventHub();
465 CHECK_NULL_VOID_NOLOG(gestureHub);
466 InitTouchEvent(gestureHub);
467 auto inputHub = hub->GetOrCreateInputEventHub();
468 CHECK_NULL_VOID_NOLOG(inputHub);
469 InitMouseEvent(inputHub);
470 auto focusHub = host->GetFocusHub();
471 CHECK_NULL_VOID_NOLOG(focusHub);
472 InitOnKeyEvent(focusHub);
473 }
474
UnregisterAbilityResultListener()475 void UIExtensionPattern::UnregisterAbilityResultListener()
476 {
477 sptr<Rosen::ExtensionSession> extensionSession(static_cast<Rosen::ExtensionSession*>(session_.GetRefPtr()));
478 }
479
SetOnRemoteReadyCallback(const std::function<void (const RefPtr<UIExtensionProxy> &)> && callback)480 void UIExtensionPattern::SetOnRemoteReadyCallback(const std::function<void(const RefPtr<UIExtensionProxy>&)>&& callback)
481 {
482 onRemoteReadyCallback_ = std::move(callback);
483
484 auto pipeline = PipelineBase::GetCurrentContext();
485 CHECK_NULL_VOID_NOLOG(pipeline);
486 auto taskExecutor = pipeline->GetTaskExecutor();
487 CHECK_NULL_VOID_NOLOG(taskExecutor);
488 sptr<Rosen::ExtensionSession> extensionSession(static_cast<Rosen::ExtensionSession*>(session_.GetRefPtr()));
489 auto extSessionEventCallback = extensionSession->GetExtensionSessionEventCallback();
490 extSessionEventCallback->notifyRemoteReadyFunc_ =
491 [weak = WeakClaim(this), instanceId = instanceId_, taskExecutor]() {
492 taskExecutor->PostTask([weak, instanceId]() {
493 ContainerScope scope(instanceId);
494 LOGI("UIExtension OnRemoteReady called");
495 auto pattern = weak.Upgrade();
496 if (pattern && pattern->onRemoteReadyCallback_) {
497 pattern->onRemoteReadyCallback_(MakeRefPtr<UIExtensionProxy>(pattern->session_));
498 }
499 }, TaskExecutor::TaskType::UI);
500 };
501 }
502
SetOnReleaseCallback(const std::function<void (int32_t)> && callback)503 void UIExtensionPattern::SetOnReleaseCallback(const std::function<void(int32_t)>&& callback)
504 {
505 onReleaseCallback_ = std::move(callback);
506 }
507
SetOnErrorCallback(const std::function<void (int32_t code,const std::string & name,const std::string & message)> && callback)508 void UIExtensionPattern::SetOnErrorCallback(
509 const std::function<void(int32_t code, const std::string& name, const std::string& message)>&& callback)
510 {
511 onErrorCallback_ = std::move(callback);
512 if (lastError_.code != 0) {
513 ErrorMsg error;
514 std::swap(lastError_, error);
515 onErrorCallback_(error.code, error.name, error.message);
516 }
517 }
518
SetOnResultCallback(const std::function<void (int32_t,const AAFwk::Want &)> && callback)519 void UIExtensionPattern::SetOnResultCallback(const std::function<void(int32_t, const AAFwk::Want&)>&& callback)
520 {
521 onResultCallback_ = std::move(callback);
522
523 auto pipeline = PipelineBase::GetCurrentContext();
524 CHECK_NULL_VOID_NOLOG(pipeline);
525 auto taskExecutor = pipeline->GetTaskExecutor();
526 CHECK_NULL_VOID_NOLOG(taskExecutor);
527 sptr<Rosen::ExtensionSession> extensionSession(static_cast<Rosen::ExtensionSession*>(session_.GetRefPtr()));
528 auto extSessionEventCallback = extensionSession->GetExtensionSessionEventCallback();
529 extSessionEventCallback->transferAbilityResultFunc_ =
530 [weak = WeakClaim(this), instanceId = instanceId_, taskExecutor](int32_t code, const AAFwk::Want& want) {
531 taskExecutor->PostTask([weak, instanceId, code, want]() {
532 ContainerScope scope(instanceId);
533 LOGI("UIExtension OnResult called");
534 auto pattern = weak.Upgrade();
535 if (pattern && pattern->onResultCallback_) {
536 pattern->onResultCallback_(code, want);
537 }
538 }, TaskExecutor::TaskType::UI);
539 };
540 }
541
SetOnReceiveCallback(const std::function<void (const AAFwk::WantParams &)> && callback)542 void UIExtensionPattern::SetOnReceiveCallback(const std::function<void(const AAFwk::WantParams&)>&& callback)
543 {
544 onReceiveCallback_ = std::move(callback);
545
546 auto pipeline = PipelineBase::GetCurrentContext();
547 CHECK_NULL_VOID_NOLOG(pipeline);
548 auto taskExecutor = pipeline->GetTaskExecutor();
549 CHECK_NULL_VOID_NOLOG(taskExecutor);
550 sptr<Rosen::ExtensionSession> extensionSession(static_cast<Rosen::ExtensionSession*>(session_.GetRefPtr()));
551 auto extSessionEventCallback = extensionSession->GetExtensionSessionEventCallback();
552 extSessionEventCallback->transferExtensionDataFunc_ =
553 [weak = WeakClaim(this), instanceId = instanceId_, taskExecutor](const AAFwk::WantParams& params) {
554 taskExecutor->PostTask([weak, instanceId, params]() {
555 ContainerScope scope(instanceId);
556 LOGI("UIExtension OnReceive called");
557 auto pattern = weak.Upgrade();
558 if (pattern && pattern->onReceiveCallback_) {
559 pattern->onReceiveCallback_(params);
560 }
561 }, TaskExecutor::TaskType::UI);
562 };
563 }
564
OnVisibleChange(bool visible)565 void UIExtensionPattern::OnVisibleChange(bool visible)
566 {
567 if (visible) {
568 RequestExtensionSessionActivation();
569 } else {
570 RequestExtensionSessionBackground();
571 }
572 }
573
RegisterVisibleAreaChange()574 void UIExtensionPattern::RegisterVisibleAreaChange()
575 {
576 auto pipeline = PipelineContext::GetCurrentContext();
577 CHECK_NULL_VOID_NOLOG(pipeline);
578 auto callback = [weak = WeakClaim(this)](bool visible, double ratio) {
579 auto uiExtension = weak.Upgrade();
580 CHECK_NULL_VOID_NOLOG(uiExtension);
581 uiExtension->OnVisibleChange(visible);
582 };
583 auto host = GetHost();
584 CHECK_NULL_VOID_NOLOG(host);
585 pipeline->AddVisibleAreaChangeNode(host, 0.0f, callback, false);
586 }
587
UpdateTextFieldManager(const Offset & offset,float height)588 void UIExtensionPattern::UpdateTextFieldManager(const Offset& offset, float height)
589 {
590 if (!IsCurrentFocus()) {
591 return;
592 }
593 auto context = GetHost()->GetContext();
594 CHECK_NULL_VOID(context);
595 auto textFieldManager = DynamicCast<TextFieldManagerNG>(context->GetTextFieldManager());
596 CHECK_NULL_VOID(textFieldManager);
597 textFieldManager->SetClickPosition(offset);
598 textFieldManager->SetHeight(height);
599 textFieldManager->SetOnFocusTextField(WeakClaim(this));
600 }
601
IsCurrentFocus() const602 bool UIExtensionPattern::IsCurrentFocus() const
603 {
604 auto host = GetHost();
605 CHECK_NULL_RETURN_NOLOG(host, false);
606 auto focusHub = host->GetFocusHub();
607 CHECK_NULL_RETURN_NOLOG(focusHub, false);
608 return focusHub->IsCurrentFocus();
609 }
610
GetSessionId()611 int32_t UIExtensionPattern::GetSessionId()
612 {
613 CHECK_NULL_RETURN(session_, 0);
614 return session_->GetPersistentId();
615 }
616 } // namespace OHOS::Ace::NG
617