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 }
135
OnDetachFromFrameNode(FrameNode * frameNode)136 void SystemWindowScene::OnDetachFromFrameNode(FrameNode* frameNode)
137 {
138 CHECK_NULL_VOID(session_);
139 CHECK_NULL_VOID(frameNode);
140 ACE_SCOPED_TRACE("OnDetachFromFrameNode[id:%d][self:%d][type:%d][name:%s]",
141 session_->GetPersistentId(), frameNode->GetId(), session_->GetWindowType(), session_->GetWindowName().c_str());
142 TAG_LOGI(AceLogTag::ACE_WINDOW_SCENE,
143 "OnDetachFromFrameNode id: %{public}d, node id: %{public}d, type: %{public}d, name: %{public}s",
144 session_->GetPersistentId(), frameNode->GetId(), session_->GetWindowType(), session_->GetWindowName().c_str());
145 if (session_->NeedCheckContextTransparent()) {
146 checkContextTransparentTask_.Cancel();
147 }
148 }
149
OnAttachToMainTree()150 void SystemWindowScene::OnAttachToMainTree()
151 {
152 auto host = GetHost();
153 CHECK_NULL_VOID(host);
154 auto context = host->GetRenderContext();
155 CHECK_NULL_VOID(context);
156 context->SetIsNeedRebuildRSTree(true);
157 }
158
OnDetachFromMainTree()159 void SystemWindowScene::OnDetachFromMainTree()
160 {
161 auto host = GetHost();
162 CHECK_NULL_VOID(host);
163 auto context = host->GetRenderContext();
164 CHECK_NULL_VOID(context);
165 context->SetIsNeedRebuildRSTree(false);
166 }
167
RegisterEventCallback()168 void SystemWindowScene::RegisterEventCallback()
169 {
170 CHECK_NULL_VOID(session_);
171 auto pointerEventCallback =
172 [weakThis = WeakClaim(this), instanceId = instanceId_](std::shared_ptr<MMI::PointerEvent> PointerEvent) {
173 ContainerScope Scope(instanceId);
174 auto pipelineContext = PipelineContext::GetCurrentContext();
175 if (!pipelineContext) {
176 TAG_LOGE(AceLogTag::ACE_INPUTTRACKING,
177 "PipelineContext GetCurrentContext null,id:%{public}d", PointerEvent->GetId());
178 PointerEvent->MarkProcessed();
179 return;
180 }
181 auto taskExecutor = pipelineContext->GetTaskExecutor();
182 if (!taskExecutor) {
183 TAG_LOGE(AceLogTag::ACE_INPUTTRACKING, "taskExecutor is null,id:%{public}d", PointerEvent->GetId());
184 PointerEvent->MarkProcessed();
185 return;
186 }
187 taskExecutor->PostTask([weakThis, PointerEvent]() {
188 auto self = weakThis.Upgrade();
189 if (!self) {
190 TAG_LOGE(AceLogTag::ACE_INPUTTRACKING,
191 "weakThis Upgrade null,id:%{public}d", PointerEvent->GetId());
192 PointerEvent->MarkProcessed();
193 return;
194 }
195 auto host = self->GetHost();
196 if (!host) {
197 TAG_LOGE(AceLogTag::ACE_INPUTTRACKING,
198 "GetHost null,id:%{public}d", PointerEvent->GetId());
199 PointerEvent->MarkProcessed();
200 return;
201 }
202 WindowSceneHelper::InjectPointerEvent(host, PointerEvent);
203 },
204 TaskExecutor::TaskType::UI, "ArkUIWindowInjectPointerEvent", PriorityType::VIP);
205 };
206 session_->SetNotifySystemSessionPointerEventFunc(std::move(pointerEventCallback));
207
208 auto keyEventCallback = [instanceId = instanceId_](std::shared_ptr<MMI::KeyEvent> KeyEvent,
209 bool isPreImeEvent) -> bool {
210 ContainerScope Scope(instanceId);
211 return WindowSceneHelper::InjectKeyEvent(KeyEvent, isPreImeEvent);
212 };
213 session_->SetNotifySystemSessionKeyEventFunc(std::move(keyEventCallback));
214 }
215
RegisterResponseRegionCallback()216 void SystemWindowScene::RegisterResponseRegionCallback()
217 {
218 auto host = GetHost();
219 CHECK_NULL_VOID(host);
220 auto gestureHub = host->GetOrCreateGestureEventHub();
221 CHECK_NULL_VOID(gestureHub);
222
223 auto touchCallback = [weakSession = wptr(session_)](TouchEventInfo& info) {
224 auto session = weakSession.promote();
225 CHECK_NULL_VOID(session);
226 const auto pointerEvent = info.GetPointerEvent();
227 CHECK_NULL_VOID(pointerEvent);
228 session->TransferPointerEvent(pointerEvent);
229 };
230 gestureHub->SetTouchEvent(std::move(touchCallback));
231
232 auto responseRegionCallback = [weakThis = WeakClaim(this), weakSession = wptr(session_)](
233 const std::vector<DimensionRect>& responseRegion) {
234 auto self = weakThis.Upgrade();
235 CHECK_NULL_VOID(self);
236 auto session = weakSession.promote();
237 CHECK_NULL_VOID(session);
238 std::vector<Rosen::Rect> hotAreas;
239 for (auto& rect : responseRegion) {
240 Rosen::Rect windowRect {
241 .posX_ = std::round(rect.GetOffset().GetX().Value()),
242 .posY_ = std::round(rect.GetOffset().GetY().Value()),
243 .width_ = std::round(rect.GetWidth().Value()),
244 .height_ = std::round(rect.GetHeight().Value()),
245 };
246 hotAreas.push_back(windowRect);
247 }
248 session->SetTouchHotAreas(hotAreas);
249 };
250 gestureHub->SetResponseRegionFunc(responseRegionCallback);
251 }
252
GetWindowPatternType() const253 uint32_t SystemWindowScene::GetWindowPatternType() const
254 {
255 return static_cast<uint32_t>(WindowPatternType::SYSTEM_WINDOW_SCENE);
256 }
257
RegisterFocusCallback()258 void SystemWindowScene::RegisterFocusCallback()
259 {
260 CHECK_NULL_VOID(session_);
261
262 auto requestFocusCallback = [weakThis = WeakClaim(this), frameNode = frameNode_, instanceId = instanceId_]() {
263 ContainerScope scope(instanceId);
264 auto pipelineContext = PipelineContext::GetCurrentContext();
265 CHECK_NULL_VOID(pipelineContext);
266 pipelineContext->SetFocusedWindowSceneNode(frameNode);
267 pipelineContext->PostAsyncEvent([weakThis]() {
268 auto pipeline = PipelineContext::GetCurrentContext();
269 CHECK_NULL_VOID(pipeline);
270 pipeline->SetIsFocusActive(false);
271 auto self = weakThis.Upgrade();
272 CHECK_NULL_VOID(self);
273 self->FocusViewShow();
274 }, "ArkUIWindowFocusViewShow", TaskExecutor::TaskType::UI);
275 };
276 session_->SetNotifyUIRequestFocusFunc(requestFocusCallback);
277
278 auto lostFocusCallback = [weakThis = WeakClaim(this), instanceId = instanceId_]() {
279 ContainerScope scope(instanceId);
280 auto pipelineContext = PipelineContext::GetCurrentContext();
281 CHECK_NULL_VOID(pipelineContext);
282 pipelineContext->PostAsyncEvent([weakThis]() {
283 auto pipeline = PipelineContext::GetCurrentContext();
284 CHECK_NULL_VOID(pipeline);
285 auto self = weakThis.Upgrade();
286 CHECK_NULL_VOID(self);
287 CHECK_NULL_VOID(self->GetSession());
288 pipeline->RestoreDefault(self->GetSession()->GetPersistentId());
289 }, "ArkUIWindowLostFocus", TaskExecutor::TaskType::UI);
290 };
291 session_->SetNotifyUILostFocusFunc(lostFocusCallback);
292 }
293
LostViewFocus()294 void SystemWindowScene::LostViewFocus()
295 {
296 TAG_LOGI(
297 AceLogTag::ACE_FOCUS, "Focus view: %{public}s/%{public}d lost focus", GetFrameName().c_str(), GetFrameId());
298 auto focusHub = GetFocusHub();
299 if (!focusHub || !focusHub->IsCurrentFocus()) {
300 return;
301 }
302 auto pipeline = PipelineContext::GetCurrentContext();
303 CHECK_NULL_VOID(pipeline);
304 auto screenNode = pipeline->GetScreenNode();
305 CHECK_NULL_VOID(screenNode);
306 auto screenNodeFocusHub = screenNode->GetFocusHub();
307 CHECK_NULL_VOID(screenNodeFocusHub);
308 screenNodeFocusHub->LostFocus(BlurReason::VIEW_SWITCH);
309 }
310
RegisterVisibleChangeCallback(int32_t nodeId,std::function<void (bool)> callback)311 void SystemWindowScene::RegisterVisibleChangeCallback(
312 int32_t nodeId, std::function<void(bool)> callback)
313 {
314 CHECK_NULL_VOID(callback);
315 CHECK_NULL_VOID(session_);
316 TAG_LOGI(AceLogTag::ACE_WINDOW_SCENE, "RegisterVisibleChangeCallback %{public}s[id:%{public}d]"
317 " nodeId: %{public}d, mapSize: %{public}zu", session_->GetSessionInfo().bundleName_.c_str(),
318 session_->GetPersistentId(), nodeId, visibleChangeCallbackMap_.size());
319 visibleChangeCallbackMap_[nodeId] = callback;
320 }
321
UnRegisterVisibleChangeCallback(int32_t nodeId)322 void SystemWindowScene::UnRegisterVisibleChangeCallback(int32_t nodeId)
323 {
324 CHECK_NULL_VOID(session_);
325 TAG_LOGI(AceLogTag::ACE_WINDOW_SCENE, "UnRegisterVisibleChangeCallback %{public}s[id:%{public}d]"
326 " nodeId: %{public}d, mapSize: %{public}zu", session_->GetSessionInfo().bundleName_.c_str(),
327 session_->GetPersistentId(), nodeId, visibleChangeCallbackMap_.size());
328 auto iter = visibleChangeCallbackMap_.find(nodeId);
329 if (iter == visibleChangeCallbackMap_.end()) {
330 return;
331 }
332
333 visibleChangeCallbackMap_.erase(nodeId);
334 }
335
HandleVisibleChangeCallback(bool visible)336 void SystemWindowScene::HandleVisibleChangeCallback(bool visible)
337 {
338 for (const auto& item : visibleChangeCallbackMap_) {
339 item.second(visible);
340 }
341 }
342
PostCheckContextTransparentTask()343 void SystemWindowScene::PostCheckContextTransparentTask()
344 {
345 checkContextTransparentTask_.Reset([weakThis = WeakClaim(this)]() {
346 auto self = weakThis.Upgrade();
347 CHECK_NULL_VOID(self);
348 CHECK_NULL_VOID(self->GetHost());
349 CHECK_NULL_VOID(self->session_);
350 if (self->session_->NeedCheckContextTransparent() && self->GetHost()->IsContextTransparent()) {
351 self->session_->NotifyContextTransparent();
352 }
353 });
354
355 auto pipelineContext = PipelineContext::GetCurrentContext();
356 CHECK_NULL_VOID(pipelineContext);
357 auto taskExecutor = pipelineContext->GetTaskExecutor();
358 CHECK_NULL_VOID(taskExecutor);
359 taskExecutor->PostDelayedTask(std::move(checkContextTransparentTask_), TaskExecutor::TaskType::UI,
360 DELAY_TIME, "ArkUIWindowCheckContextTransparent");
361 }
362
PostFaultInjectTask()363 void SystemWindowScene::PostFaultInjectTask()
364 {
365 auto task = ([weakThis = WeakClaim(this)]() {
366 auto self = weakThis.Upgrade();
367 CHECK_NULL_VOID(self);
368 auto host = self->GetHost();
369 CHECK_NULL_VOID(host);
370 auto renderContext = AceType::DynamicCast<NG::RosenRenderContext>(host->GetRenderContext());
371 renderContext->SetOpacity(0.0f);
372 host->MarkDirtyNode();
373 });
374
375 auto pipelineContext = PipelineContext::GetCurrentContext();
376 CHECK_NULL_VOID(pipelineContext);
377 auto taskExecutor = pipelineContext->GetTaskExecutor();
378 CHECK_NULL_VOID(taskExecutor);
379 taskExecutor->PostDelayedTask(
380 std::move(task), TaskExecutor::TaskType::UI, DELAY_TIME, "ArkUIWindowFaultInject");
381 }
382 } // namespace OHOS::Ace::NG
383