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/window_scene/scene/system_window_scene.h"
17
18 #include "ui/rs_canvas_node.h"
19 #include "ui/rs_surface_node.h"
20
21 #include "adapter/ohos/entrance/mmi_event_convertor.h"
22 #include "core/components_ng/pattern/window_scene/helper/window_scene_helper.h"
23 #include "core/components_ng/pattern/window_scene/scene/window_event_process.h"
24 #include "core/components_ng/render/adapter/rosen_render_context.h"
25 #include "core/pipeline_ng/pipeline_context.h"
26
27 namespace OHOS::Ace::NG {
28 namespace {
29 constexpr uint32_t DELAY_TIME = 3000;
30 } // namespace
31
SystemWindowScene(const sptr<Rosen::Session> & session)32 SystemWindowScene::SystemWindowScene(const sptr<Rosen::Session>& session) : session_(session)
33 {
34 boundsChangedCallback_ = [weakThis = WeakClaim(this)](const Rosen::Vector4f& bounds) {
35 auto self = weakThis.Upgrade();
36 CHECK_NULL_VOID(self);
37 self->OnBoundsChanged(bounds);
38 };
39 }
40
GetSession()41 sptr<Rosen::Session> SystemWindowScene::GetSession()
42 {
43 return session_;
44 }
45
OnBoundsChanged(const Rosen::Vector4f & bounds)46 void SystemWindowScene::OnBoundsChanged(const Rosen::Vector4f& bounds)
47 {
48 Rosen::WSRect windowRect {
49 .posX_ = std::round(bounds.x_),
50 .posY_ = std::round(bounds.y_),
51 .width_ = std::round(bounds.z_),
52 .height_ = std::round(bounds.w_),
53 };
54
55 CHECK_NULL_VOID(session_);
56 Rosen::WSRectF originBounds = {
57 .posX_ = bounds.x_,
58 .posY_ = bounds.y_,
59 .width_ = bounds.z_,
60 .height_ = bounds.w_,
61 };
62 session_->SetBounds(originBounds);
63 windowRect.posX_ = std::round(bounds.x_ + session_->GetOffsetX());
64 windowRect.posY_ = std::round(bounds.y_ + session_->GetOffsetY());
65 auto ret = session_->UpdateRect(windowRect, Rosen::SizeChangeReason::UNDEFINED, "OnBoundsChanged");
66 if (ret != Rosen::WSError::WS_OK) {
67 TAG_LOGI(AceLogTag::ACE_WINDOW_SCENE, "Update rect failed, id: %{public}d, ret: %{public}d",
68 session_->GetPersistentId(), static_cast<int32_t>(ret));
69 }
70 }
71
OnVisibleChange(bool visible)72 void SystemWindowScene::OnVisibleChange(bool visible)
73 {
74 CHECK_NULL_VOID(session_);
75 TAG_LOGI(AceLogTag::ACE_WINDOW_SCENE, "Visibility of %{public}s[id:%{public}d] changed: %{public}s",
76 session_->GetSessionInfo().bundleName_.c_str(), session_->GetPersistentId(), visible ? "visible" : "invisible");
77 if (visible && session_->NeedCheckContextTransparent()) {
78 PostCheckContextTransparentTask();
79 } else if (session_->NeedCheckContextTransparent()) {
80 checkContextTransparentTask_.Cancel();
81 }
82 if (SystemProperties::GetFaultInjectEnabled() && session_->NeedCheckContextTransparent()) {
83 PostFaultInjectTask();
84 }
85 HandleVisibleChangeCallback(visible);
86 }
87
OnAttachToFrameNode()88 void SystemWindowScene::OnAttachToFrameNode()
89 {
90 CHECK_NULL_VOID(session_);
91 auto host = GetHost();
92 CHECK_NULL_VOID(host);
93 ACE_SCOPED_TRACE("OnAttachToFrameNode[id:%d][self:%d][type:%d][name:%s]",
94 session_->GetPersistentId(), host->GetId(), session_->GetWindowType(), session_->GetWindowName().c_str());
95 TAG_LOGI(AceLogTag::ACE_WINDOW_SCENE,
96 "OnAttachToFrameNode id: %{public}d, node id: %{public}d, type: %{public}d, name: %{public}s",
97 session_->GetPersistentId(), host->GetId(), session_->GetWindowType(), session_->GetWindowName().c_str());
98
99 host->SetWindowBoundary();
100 session_->SetUINodeId(host->GetAccessibilityId());
101 auto surfaceNode = session_->GetSurfaceNode();
102 CHECK_NULL_VOID(surfaceNode);
103 auto context = AceType::DynamicCast<NG::RosenRenderContext>(host->GetRenderContext());
104 CHECK_NULL_VOID(context);
105 context->SetRSNode(surfaceNode);
106 surfaceNode->SetBoundsChangedCallback(boundsChangedCallback_);
107
108 auto mouseEventHub = host->GetOrCreateInputEventHub();
109 auto mouseCallback = [weakThis = WeakClaim(this), weakSession = wptr(session_)](MouseInfo& info) {
110 auto self = weakThis.Upgrade();
111 CHECK_NULL_VOID(self);
112 auto session = weakSession.promote();
113 CHECK_NULL_VOID(session);
114 const auto pointerEvent = info.GetPointerEvent();
115 CHECK_NULL_VOID(pointerEvent);
116 auto host = self->GetHost();
117 if (host != nullptr) {
118 DelayedSingleton<WindowEventProcess>::GetInstance()->ProcessWindowMouseEvent(
119 host->GetId(), session, pointerEvent);
120 DelayedSingleton<WindowEventProcess>::GetInstance()->ProcessWindowDragEvent(
121 host->GetId(), session, pointerEvent);
122 }
123 session->TransferPointerEvent(pointerEvent);
124 };
125 mouseEventHub->SetMouseEvent(std::move(mouseCallback));
126
127 RegisterFocusCallback();
128 RegisterEventCallback();
129 RegisterResponseRegionCallback();
130
131 if (session_->NeedCheckContextTransparent()) {
132 PostCheckContextTransparentTask();
133 }
134 SetWindowScenePosition();
135 }
136
SetWindowScenePosition()137 void SystemWindowScene::SetWindowScenePosition()
138 {
139 // set window scene position (x, y) and scale data, jsAccessibilityManager will use it
140 CHECK_NULL_VOID(session_);
141 auto host = GetHost();
142 CHECK_NULL_VOID(host);
143 auto accessibilityProperty = host->GetAccessibilityProperty<NG::AccessibilityProperty>();
144 CHECK_NULL_VOID(accessibilityProperty);
145 accessibilityProperty->SetGetWindowScenePosition([weakSession = wptr(session_)] (
146 NG::WindowSceneInfo& windowSceneInfo) {
147 auto session = weakSession.promote();
148 CHECK_NULL_VOID(session);
149 auto windowRect = session->GetSessionGlobalRect();
150
151 // get transform info in single hand mode,
152 // adjust the position (x, y) of window scene with the transform pos and scale data.
153 OHOS::Rosen::SingleHandTransform transform =
154 session->GetSingleHandTransform();
155 windowSceneInfo.left = windowRect.posX_ * transform.scaleX + transform.posX;
156 windowSceneInfo.top = windowRect.posY_ * transform.scaleY + transform.posY;
157 windowSceneInfo.scaleX = session->GetScaleX() * transform.scaleX;
158 windowSceneInfo.scaleY = session->GetScaleY() * transform.scaleY;
159 windowSceneInfo.innerWindowId = session->GetPersistentId();
160 });
161 }
162
OnDetachFromFrameNode(FrameNode * frameNode)163 void SystemWindowScene::OnDetachFromFrameNode(FrameNode* frameNode)
164 {
165 CHECK_NULL_VOID(session_);
166 CHECK_NULL_VOID(frameNode);
167 ACE_SCOPED_TRACE("OnDetachFromFrameNode[id:%d][self:%d][type:%d][name:%s]",
168 session_->GetPersistentId(), frameNode->GetId(), session_->GetWindowType(), session_->GetWindowName().c_str());
169 TAG_LOGI(AceLogTag::ACE_WINDOW_SCENE,
170 "OnDetachFromFrameNode id: %{public}d, node id: %{public}d, type: %{public}d, name: %{public}s",
171 session_->GetPersistentId(), frameNode->GetId(), session_->GetWindowType(), session_->GetWindowName().c_str());
172 if (session_->NeedCheckContextTransparent()) {
173 checkContextTransparentTask_.Cancel();
174 }
175 }
176
OnAttachToMainTree()177 void SystemWindowScene::OnAttachToMainTree()
178 {
179 auto host = GetHost();
180 CHECK_NULL_VOID(host);
181 auto context = host->GetRenderContext();
182 CHECK_NULL_VOID(context);
183 context->SetIsNeedRebuildRSTree(true);
184 }
185
OnDetachFromMainTree()186 void SystemWindowScene::OnDetachFromMainTree()
187 {
188 auto host = GetHost();
189 CHECK_NULL_VOID(host);
190 auto context = host->GetRenderContext();
191 CHECK_NULL_VOID(context);
192 context->SetIsNeedRebuildRSTree(false);
193 }
194
RegisterEventCallback()195 void SystemWindowScene::RegisterEventCallback()
196 {
197 CHECK_NULL_VOID(session_);
198 auto pointerEventCallback =
199 [weakThis = WeakClaim(this), instanceId = instanceId_](std::shared_ptr<MMI::PointerEvent> PointerEvent) {
200 ContainerScope Scope(instanceId);
201 auto pipelineContext = PipelineContext::GetCurrentContext();
202 if (!pipelineContext) {
203 TAG_LOGE(AceLogTag::ACE_INPUTTRACKING,
204 "PipelineContext GetCurrentContext null,id:%{public}d", PointerEvent->GetId());
205 PointerEvent->MarkProcessed();
206 return;
207 }
208 auto taskExecutor = pipelineContext->GetTaskExecutor();
209 if (!taskExecutor) {
210 TAG_LOGE(AceLogTag::ACE_INPUTTRACKING, "taskExecutor is null,id:%{public}d", PointerEvent->GetId());
211 PointerEvent->MarkProcessed();
212 return;
213 }
214 taskExecutor->PostTask([weakThis, PointerEvent]() {
215 auto self = weakThis.Upgrade();
216 if (!self) {
217 TAG_LOGE(AceLogTag::ACE_INPUTTRACKING,
218 "weakThis Upgrade null,id:%{public}d", PointerEvent->GetId());
219 PointerEvent->MarkProcessed();
220 return;
221 }
222 auto host = self->GetHost();
223 if (!host) {
224 TAG_LOGE(AceLogTag::ACE_INPUTTRACKING,
225 "GetHost null,id:%{public}d", PointerEvent->GetId());
226 PointerEvent->MarkProcessed();
227 return;
228 }
229 WindowSceneHelper::InjectPointerEvent(host, PointerEvent);
230 },
231 TaskExecutor::TaskType::UI, "ArkUIWindowInjectPointerEvent", PriorityType::VIP);
232 };
233 session_->SetNotifySystemSessionPointerEventFunc(std::move(pointerEventCallback));
234
235 auto keyEventCallback = [instanceId = instanceId_](std::shared_ptr<MMI::KeyEvent> KeyEvent,
236 bool isPreImeEvent) -> bool {
237 ContainerScope Scope(instanceId);
238 return WindowSceneHelper::InjectKeyEvent(KeyEvent, isPreImeEvent);
239 };
240 session_->SetNotifySystemSessionKeyEventFunc(std::move(keyEventCallback));
241 }
242
RegisterResponseRegionCallback()243 void SystemWindowScene::RegisterResponseRegionCallback()
244 {
245 auto host = GetHost();
246 CHECK_NULL_VOID(host);
247 auto gestureHub = host->GetOrCreateGestureEventHub();
248 CHECK_NULL_VOID(gestureHub);
249
250 auto touchCallback = [weakSession = wptr(session_)](TouchEventInfo& info) {
251 auto session = weakSession.promote();
252 CHECK_NULL_VOID(session);
253 const auto pointerEvent = info.GetPointerEvent();
254 CHECK_NULL_VOID(pointerEvent);
255 session->TransferPointerEvent(pointerEvent);
256 };
257 gestureHub->SetTouchEvent(std::move(touchCallback));
258
259 auto responseRegionCallback = [weakThis = WeakClaim(this), weakSession = wptr(session_)](
260 const std::vector<DimensionRect>& responseRegion) {
261 auto self = weakThis.Upgrade();
262 CHECK_NULL_VOID(self);
263 auto session = weakSession.promote();
264 CHECK_NULL_VOID(session);
265 std::vector<Rosen::Rect> hotAreas;
266 for (auto& rect : responseRegion) {
267 Rosen::Rect windowRect {
268 .posX_ = std::round(rect.GetOffset().GetX().Value()),
269 .posY_ = std::round(rect.GetOffset().GetY().Value()),
270 .width_ = std::round(rect.GetWidth().Value()),
271 .height_ = std::round(rect.GetHeight().Value()),
272 };
273 hotAreas.push_back(windowRect);
274 }
275 session->SetTouchHotAreas(hotAreas);
276 };
277 gestureHub->SetResponseRegionFunc(responseRegionCallback);
278 }
279
GetWindowPatternType() const280 uint32_t SystemWindowScene::GetWindowPatternType() const
281 {
282 return static_cast<uint32_t>(WindowPatternType::SYSTEM_WINDOW_SCENE);
283 }
284
RegisterFocusCallback()285 void SystemWindowScene::RegisterFocusCallback()
286 {
287 CHECK_NULL_VOID(session_);
288
289 auto requestFocusCallback = [weakThis = WeakClaim(this), frameNode = frameNode_, instanceId = instanceId_]() {
290 ContainerScope scope(instanceId);
291 auto pipelineContext = PipelineContext::GetCurrentContext();
292 CHECK_NULL_VOID(pipelineContext);
293 pipelineContext->SetFocusedWindowSceneNode(frameNode);
294 pipelineContext->PostAsyncEvent([weakThis]() {
295 auto pipeline = PipelineContext::GetCurrentContext();
296 CHECK_NULL_VOID(pipeline);
297 pipeline->SetIsFocusActive(false);
298 auto self = weakThis.Upgrade();
299 CHECK_NULL_VOID(self);
300 self->FocusViewShow();
301
302 CHECK_NULL_VOID(self->GetSession());
303 TAG_LOGD(AceLogTag::ACE_WINDOW_SCENE, "focus callback id:%{public}d, use-control-session:%{public}u",
304 self->GetSession()->GetPersistentId(), self->GetSession()->GetIsUseControlSession());
305 CHECK_EQUAL_VOID(self->GetSession()->GetIsUseControlSession(), false);
306 auto host = self->GetHost();
307 CHECK_NULL_VOID(host);
308 auto parentScene = WindowSceneHelper::FindWindowScene(host);
309 CHECK_NULL_VOID(parentScene);
310 auto parentFrame = AceType::DynamicCast<FrameNode>(parentScene);
311 CHECK_NULL_VOID(parentFrame);
312 auto parentType = parentFrame->GetWindowPatternType();
313 TAG_LOGD(AceLogTag::ACE_WINDOW_SCENE, "focus callback node:%{public}d, parent:%{public}d,"
314 " parentType:%{public}d", host->GetId(), parentFrame->GetId(), parentType);
315 CHECK_EQUAL_VOID(WindowSceneHelper::IsAppOrSubScene(parentType), false);
316 auto parentFocusHub = parentFrame->GetFocusHub();
317 CHECK_NULL_VOID(parentFocusHub);
318 parentFocusHub->SetParentFocusable(true);
319 }, "ArkUIWindowFocusViewShow", TaskExecutor::TaskType::UI);
320 };
321 session_->SetNotifyUIRequestFocusFunc(requestFocusCallback);
322
323 auto lostFocusCallback = [weakThis = WeakClaim(this), instanceId = instanceId_]() {
324 ContainerScope scope(instanceId);
325 auto pipelineContext = PipelineContext::GetCurrentContext();
326 CHECK_NULL_VOID(pipelineContext);
327 pipelineContext->PostAsyncEvent([weakThis]() {
328 auto pipeline = PipelineContext::GetCurrentContext();
329 CHECK_NULL_VOID(pipeline);
330 auto self = weakThis.Upgrade();
331 CHECK_NULL_VOID(self);
332 CHECK_NULL_VOID(self->GetSession());
333 pipeline->RestoreDefault(self->GetSession()->GetPersistentId());
334 }, "ArkUIWindowLostFocus", TaskExecutor::TaskType::UI);
335 };
336 session_->SetNotifyUILostFocusFunc(lostFocusCallback);
337 }
338
LostViewFocus()339 void SystemWindowScene::LostViewFocus()
340 {
341 TAG_LOGI(
342 AceLogTag::ACE_FOCUS, "Focus view: %{public}s/%{public}d lost focus", GetFrameName().c_str(), GetFrameId());
343 auto focusHub = GetFocusHub();
344 if (!focusHub || !focusHub->IsCurrentFocus()) {
345 return;
346 }
347 auto pipeline = PipelineContext::GetCurrentContext();
348 CHECK_NULL_VOID(pipeline);
349 auto screenNode = pipeline->GetScreenNode();
350 CHECK_NULL_VOID(screenNode);
351 auto screenNodeFocusHub = screenNode->GetFocusHub();
352 CHECK_NULL_VOID(screenNodeFocusHub);
353 screenNodeFocusHub->LostFocus(BlurReason::VIEW_SWITCH);
354 }
355
RegisterVisibleChangeCallback(int32_t nodeId,std::function<void (bool)> callback)356 void SystemWindowScene::RegisterVisibleChangeCallback(
357 int32_t nodeId, std::function<void(bool)> callback)
358 {
359 CHECK_NULL_VOID(callback);
360 CHECK_NULL_VOID(session_);
361 TAG_LOGI(AceLogTag::ACE_WINDOW_SCENE, "RegisterVisibleChangeCallback %{public}s[id:%{public}d]"
362 " nodeId: %{public}d, mapSize: %{public}zu", session_->GetSessionInfo().bundleName_.c_str(),
363 session_->GetPersistentId(), nodeId, visibleChangeCallbackMap_.size());
364 visibleChangeCallbackMap_[nodeId] = callback;
365 }
366
UnRegisterVisibleChangeCallback(int32_t nodeId)367 void SystemWindowScene::UnRegisterVisibleChangeCallback(int32_t nodeId)
368 {
369 CHECK_NULL_VOID(session_);
370 TAG_LOGI(AceLogTag::ACE_WINDOW_SCENE, "UnRegisterVisibleChangeCallback %{public}s[id:%{public}d]"
371 " nodeId: %{public}d, mapSize: %{public}zu", session_->GetSessionInfo().bundleName_.c_str(),
372 session_->GetPersistentId(), nodeId, visibleChangeCallbackMap_.size());
373 auto iter = visibleChangeCallbackMap_.find(nodeId);
374 if (iter == visibleChangeCallbackMap_.end()) {
375 return;
376 }
377
378 visibleChangeCallbackMap_.erase(nodeId);
379 }
380
HandleVisibleChangeCallback(bool visible)381 void SystemWindowScene::HandleVisibleChangeCallback(bool visible)
382 {
383 for (const auto& item : visibleChangeCallbackMap_) {
384 item.second(visible);
385 }
386 }
387
PostCheckContextTransparentTask()388 void SystemWindowScene::PostCheckContextTransparentTask()
389 {
390 checkContextTransparentTask_.Reset([weakThis = WeakClaim(this)]() {
391 auto self = weakThis.Upgrade();
392 CHECK_NULL_VOID(self);
393 CHECK_NULL_VOID(self->GetHost());
394 CHECK_NULL_VOID(self->session_);
395 if (self->session_->NeedCheckContextTransparent() && self->GetHost()->IsContextTransparent()) {
396 self->session_->NotifyContextTransparent();
397 }
398 });
399
400 auto pipelineContext = PipelineContext::GetCurrentContext();
401 CHECK_NULL_VOID(pipelineContext);
402 auto taskExecutor = pipelineContext->GetTaskExecutor();
403 CHECK_NULL_VOID(taskExecutor);
404 taskExecutor->PostDelayedTask(std::move(checkContextTransparentTask_), TaskExecutor::TaskType::UI,
405 DELAY_TIME, "ArkUIWindowCheckContextTransparent");
406 }
407
PostFaultInjectTask()408 void SystemWindowScene::PostFaultInjectTask()
409 {
410 auto task = ([weakThis = WeakClaim(this)]() {
411 auto self = weakThis.Upgrade();
412 CHECK_NULL_VOID(self);
413 auto host = self->GetHost();
414 CHECK_NULL_VOID(host);
415 auto renderContext = AceType::DynamicCast<NG::RosenRenderContext>(host->GetRenderContext());
416 renderContext->SetOpacity(0.0f);
417 host->MarkDirtyNode();
418 });
419
420 auto pipelineContext = PipelineContext::GetCurrentContext();
421 CHECK_NULL_VOID(pipelineContext);
422 auto taskExecutor = pipelineContext->GetTaskExecutor();
423 CHECK_NULL_VOID(taskExecutor);
424 taskExecutor->PostDelayedTask(
425 std::move(task), TaskExecutor::TaskType::UI, DELAY_TIME, "ArkUIWindowFaultInject");
426 }
427 } // namespace OHOS::Ace::NG
428