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