1 /*
2 * Copyright (c) 2022-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/ability_component/ability_component_pattern.h"
17
18 #include "session/host/include/extension_session.h"
19 #include "session_manager/include/extension_session_manager.h"
20
21 #include "adapter/ohos/entrance/ace_container.h"
22 #include "adapter/ohos/entrance/mmi_event_convertor.h"
23 #include "adapter/ohos/osal/want_wrap_ohos.h"
24 #include "base/utils/utils.h"
25 #include "core/common/container.h"
26 #include "core/pipeline_ng/pipeline_context.h"
27
28 namespace OHOS::Ace::NG {
AbilityComponentPattern(const std::string & bundleName,const std::string & abilityName)29 AbilityComponentPattern::AbilityComponentPattern(const std::string& bundleName, const std::string& abilityName)
30 {
31 auto container = AceType::DynamicCast<Platform::AceContainer>(Container::Current());
32 if (container && container->IsSceneBoardEnabled()) {
33 auto wantWrap = Ace::WantWrap::CreateWantWrap(bundleName, abilityName);
34 auto want = AceType::DynamicCast<WantWrapOhos>(wantWrap)->GetWant();
35 Rosen::SessionInfo extensionSessionInfo = {
36 .bundleName_ = bundleName,
37 .abilityName_ = abilityName,
38 .callerToken_ = container->GetToken(),
39 .want = new (std::nothrow) Want(want),
40 };
41 session_ = Rosen::ExtensionSessionManager::GetInstance().RequestExtensionSession(extensionSessionInfo);
42 }
43 }
44
OnModifyDone()45 void AbilityComponentPattern::OnModifyDone()
46 {
47 auto container = Container::Current();
48 if (container && container->IsSceneBoardEnabled()) {
49 Pattern::OnModifyDone();
50 auto host = GetHost();
51 CHECK_NULL_VOID(host);
52 auto hub = host->GetEventHub<EventHub>();
53 CHECK_NULL_VOID(hub);
54 auto gestureHub = hub->GetOrCreateGestureEventHub();
55 CHECK_NULL_VOID(gestureHub);
56 InitTouchEvent(gestureHub);
57 auto inputHub = hub->GetOrCreateInputEventHub();
58 CHECK_NULL_VOID(inputHub);
59 InitMouseEvent(inputHub);
60 auto focusHub = host->GetFocusHub();
61 CHECK_NULL_VOID(focusHub);
62 InitOnKeyEvent(focusHub);
63 }
64 if (adapter_) {
65 UpdateWindowRect();
66 } else {
67 auto pipelineContext = PipelineContext::GetCurrentContext();
68 CHECK_NULL_VOID(pipelineContext);
69 auto windowId = pipelineContext->GetWindowId();
70 auto host = GetHost();
71 CHECK_NULL_VOID(host);
72 adapter_ = WindowExtensionConnectionProxyNG::CreateAdapter();
73 CHECK_NULL_VOID(adapter_);
74 if (container && container->IsSceneBoardEnabled()) {
75 CHECK_NULL_VOID(session_);
76 sptr<Rosen::ExtensionSession> extensionSession(static_cast<Rosen::ExtensionSession*>(session_.GetRefPtr()));
77 CHECK_NULL_VOID(extensionSession);
78 adapter_->SetExtensionSession(extensionSession);
79 }
80 adapter_->ConnectExtension(GetHost(), windowId);
81 pipelineContext->AddOnAreaChangeNode(host->GetId());
82 pipelineContext->AddWindowStateChangedCallback(host->GetId());
83 LOGI("connect to windows extension begin %{public}s", GetHost()->GetTag().c_str());
84 }
85 }
86
FireConnect()87 void AbilityComponentPattern::FireConnect()
88 {
89 hasConnectionToAbility_ = true;
90 UpdateWindowRect();
91 auto pipeline = PipelineBase::GetCurrentContext();
92 TransferFocusState(IsCurrentFocus());
93
94 auto abilityComponentEventHub = GetEventHub<AbilityComponentEventHub>();
95 CHECK_NULL_VOID(abilityComponentEventHub);
96 abilityComponentEventHub->FireOnConnect();
97 }
98
FireDisConnect()99 void AbilityComponentPattern::FireDisConnect()
100 {
101 hasConnectionToAbility_ = false;
102 auto abilityComponentEventHub = GetEventHub<AbilityComponentEventHub>();
103 CHECK_NULL_VOID(abilityComponentEventHub);
104 abilityComponentEventHub->FireOnDisConnect();
105 }
106
OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper> &,const DirtySwapConfig & config)107 bool AbilityComponentPattern::OnDirtyLayoutWrapperSwap(
108 const RefPtr<LayoutWrapper>& /*dirty*/, const DirtySwapConfig& config)
109 {
110 if (config.frameSizeChange || config.frameOffsetChange) {
111 UpdateWindowRect();
112 }
113 return false;
114 }
115
GetFocusPattern() const116 FocusPattern AbilityComponentPattern::GetFocusPattern() const
117 {
118 return { FocusType::NODE, true, FocusStyleType::NONE };
119 }
120
UpdateWindowRect()121 void AbilityComponentPattern::UpdateWindowRect()
122 {
123 if (!hasConnectionToAbility_) {
124 LOGD("AbilityComponent has not be connected");
125 return;
126 }
127 auto host = GetHost();
128 CHECK_NULL_VOID(host);
129 auto size = host->GetGeometryNode()->GetFrameSize();
130 auto offset = host->GetTransformRelativeOffset();
131 auto pipeline = PipelineContext::GetCurrentContext();
132 CHECK_NULL_VOID(pipeline);
133 Rect rect = pipeline->GetDisplayWindowRectInfo();
134 rect = Rect(offset.GetX() + rect.Left(), offset.GetY() + rect.Top(), size.Width(), size.Height());
135
136 if (adapter_ && rect != lastRect_) {
137 LOGI("ConnectExtension: %{public}f %{public}f %{public}f %{public}f", offset.GetX(), offset.GetY(),
138 size.Width(), size.Height());
139 adapter_->UpdateRect(rect);
140 lastRect_ = rect;
141 }
142 }
143
OnAreaChangedInner()144 void AbilityComponentPattern::OnAreaChangedInner()
145 {
146 UpdateWindowRect();
147 }
148
InitTouchEvent(const RefPtr<GestureEventHub> & gestureHub)149 void AbilityComponentPattern::InitTouchEvent(const RefPtr<GestureEventHub>& gestureHub)
150 {
151 if (touchEvent_) {
152 return;
153 }
154 auto callback = [weak = WeakClaim(this)](const TouchEventInfo& info) {
155 auto pattern = weak.Upgrade();
156 if (pattern) {
157 pattern->HandleTouchEvent(info);
158 }
159 };
160 if (touchEvent_) {
161 gestureHub->RemoveTouchEvent(touchEvent_);
162 }
163 touchEvent_ = MakeRefPtr<TouchEventImpl>(std::move(callback));
164 gestureHub->AddTouchEvent(touchEvent_);
165 }
166
InitMouseEvent(const RefPtr<InputEventHub> & inputHub)167 void AbilityComponentPattern::InitMouseEvent(const RefPtr<InputEventHub>& inputHub)
168 {
169 if (mouseEvent_) {
170 return;
171 }
172 auto callback = [weak = WeakClaim(this)](MouseInfo& info) {
173 auto pattern = weak.Upgrade();
174 if (pattern) {
175 pattern->HandleMouseEvent(info);
176 }
177 };
178 if (mouseEvent_) {
179 inputHub->RemoveOnMouseEvent(mouseEvent_);
180 }
181 mouseEvent_ = MakeRefPtr<InputEvent>(std::move(callback));
182 inputHub->AddOnMouseEvent(mouseEvent_);
183 }
184
HandleTouchEvent(const TouchEventInfo & info)185 void AbilityComponentPattern::HandleTouchEvent(const TouchEventInfo& info)
186 {
187 if (info.GetSourceDevice() != SourceType::TOUCH) {
188 return;
189 }
190 const auto pointerEvent = info.GetPointerEvent();
191 CHECK_NULL_VOID(pointerEvent);
192 auto host = GetHost();
193 CHECK_NULL_VOID_NOLOG(host);
194 auto selfGlobalOffset = host->GetTransformRelativeOffset();
195 auto scale = host->GetTransformScale();
196 Platform::CalculatePointerEvent(selfGlobalOffset, pointerEvent, scale);
197 WindowPattern::DispatchPointerEvent(pointerEvent);
198 auto hub = host->GetFocusHub();
199 CHECK_NULL_VOID(hub);
200 hub->RequestFocusImmediately();
201 }
202
HandleMouseEvent(const MouseInfo & info)203 void AbilityComponentPattern::HandleMouseEvent(const MouseInfo& info)
204 {
205 if (info.GetSourceDevice() != SourceType::MOUSE) {
206 return;
207 }
208 const auto pointerEvent = info.GetPointerEvent();
209 CHECK_NULL_VOID_NOLOG(pointerEvent);
210 auto host = GetHost();
211 CHECK_NULL_VOID_NOLOG(host);
212 auto selfGlobalOffset = host->GetTransformRelativeOffset();
213 auto scale = host->GetTransformScale();
214 Platform::CalculatePointerEvent(selfGlobalOffset, pointerEvent, scale);
215 if (info.GetAction() == MouseAction::PRESS) {
216 auto hub = host->GetFocusHub();
217 CHECK_NULL_VOID(hub);
218 hub->RequestFocusImmediately();
219 }
220 WindowPattern::DispatchPointerEvent(pointerEvent);
221 }
222
InitOnKeyEvent(const RefPtr<FocusHub> & focusHub)223 void AbilityComponentPattern::InitOnKeyEvent(const RefPtr<FocusHub>& focusHub)
224 {
225 focusHub->SetOnFocusInternal([weak = WeakClaim(this)]() {
226 auto pattern = weak.Upgrade();
227 if (pattern) {
228 pattern->HandleFocusEvent();
229 }
230 });
231
232 focusHub->SetOnBlurInternal([weak = WeakClaim(this)]() {
233 auto pattern = weak.Upgrade();
234 if (pattern) {
235 pattern->HandleBlurEvent();
236 }
237 });
238
239 focusHub->SetOnClearFocusStateInternal([weak = WeakClaim(this)]() {
240 auto pattern = weak.Upgrade();
241 if (pattern) {
242 pattern->DisPatchFocusActiveEvent(false);
243 }
244 });
245 focusHub->SetOnPaintFocusStateInternal([weak = WeakClaim(this)]() -> bool {
246 auto pattern = weak.Upgrade();
247 if (pattern) {
248 pattern->DisPatchFocusActiveEvent(true);
249 return true;
250 }
251 return false;
252 });
253
254 focusHub->SetOnKeyEventInternal([wp = WeakClaim(this)](const KeyEvent& event) -> bool {
255 auto pattern = wp.Upgrade();
256 if (pattern) {
257 return pattern->OnKeyEvent(event);
258 }
259 return false;
260 });
261 }
262
HandleFocusEvent()263 void AbilityComponentPattern::HandleFocusEvent()
264 {
265 auto pipeline = PipelineContext::GetCurrentContext();
266 if (pipeline->GetIsFocusActive()) {
267 WindowPattern::DisPatchFocusActiveEvent(true);
268 }
269 TransferFocusState(true);
270 }
271
HandleBlurEvent()272 void AbilityComponentPattern::HandleBlurEvent()
273 {
274 WindowPattern::DisPatchFocusActiveEvent(false);
275 TransferFocusState(false);
276 }
277
KeyEventConsumed(const KeyEvent & event)278 bool AbilityComponentPattern::KeyEventConsumed(const KeyEvent& event)
279 {
280 bool isConsumed = false;
281 WindowPattern::DispatchKeyEventForConsumed(event.rawKeyEvent, isConsumed);
282 return isConsumed;
283 }
284
OnKeyEvent(const KeyEvent & event)285 bool AbilityComponentPattern::OnKeyEvent(const KeyEvent& event)
286 {
287 if (event.code == KeyCode::KEY_TAB && event.action == KeyAction::DOWN) {
288 auto pipeline = PipelineContext::GetCurrentContext();
289 CHECK_NULL_RETURN(pipeline, false);
290 // tab trigger consume the key event
291 return pipeline->IsTabJustTriggerOnKeyEvent();
292 } else {
293 return KeyEventConsumed(event);
294 }
295 }
296
IsCurrentFocus() const297 bool AbilityComponentPattern::IsCurrentFocus() const
298 {
299 auto host = GetHost();
300 CHECK_NULL_RETURN_NOLOG(host, false);
301 auto focusHub = host->GetFocusHub();
302 CHECK_NULL_RETURN_NOLOG(focusHub, false);
303 return focusHub->IsCurrentFocus();
304 }
305 } // namespace OHOS::Ace::NG
306