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