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 session_->UpdateRect(windowRect, Rosen::SizeChangeReason::UNDEFINED, "OnBoundsChanged");
66 }
67
OnVisibleChange(bool visible)68 void SystemWindowScene::OnVisibleChange(bool visible)
69 {
70 CHECK_NULL_VOID(session_);
71 TAG_LOGI(AceLogTag::ACE_WINDOW_SCENE, "Visibility of %{public}s[id:%{public}d] changed: %{public}s",
72 session_->GetSessionInfo().bundleName_.c_str(), session_->GetPersistentId(), visible ? "visible" : "invisible");
73 if (visible && session_->NeedCheckContextTransparent()) {
74 PostCheckContextTransparentTask();
75 } else if (session_->NeedCheckContextTransparent()) {
76 checkContextTransparentTask_.Cancel();
77 }
78 if (SystemProperties::GetFaultInjectEnabled() && session_->NeedCheckContextTransparent()) {
79 PostFaultInjectTask();
80 }
81 }
82
OnAttachToFrameNode()83 void SystemWindowScene::OnAttachToFrameNode()
84 {
85 CHECK_NULL_VOID(session_);
86 auto host = GetHost();
87 CHECK_NULL_VOID(host);
88 ACE_SCOPED_TRACE("OnAttachToFrameNode[id:%d][self:%d][type:%d][name:%s]",
89 session_->GetPersistentId(), host->GetId(), session_->GetWindowType(), session_->GetWindowName().c_str());
90 TAG_LOGI(AceLogTag::ACE_WINDOW_SCENE,
91 "OnAttachToFrameNode id: %{public}d, node id: %{public}d, type: %{public}d, name: %{public}s",
92 session_->GetPersistentId(), host->GetId(), session_->GetWindowType(), session_->GetWindowName().c_str());
93
94 host->SetWindowBoundary();
95 session_->SetUINodeId(host->GetAccessibilityId());
96 auto surfaceNode = session_->GetSurfaceNode();
97 CHECK_NULL_VOID(surfaceNode);
98 auto context = AceType::DynamicCast<NG::RosenRenderContext>(host->GetRenderContext());
99 CHECK_NULL_VOID(context);
100 context->SetRSNode(surfaceNode);
101 surfaceNode->SetBoundsChangedCallback(boundsChangedCallback_);
102
103 auto mouseEventHub = host->GetOrCreateInputEventHub();
104 auto mouseCallback = [weakThis = WeakClaim(this), weakSession = wptr(session_)](MouseInfo& info) {
105 auto self = weakThis.Upgrade();
106 CHECK_NULL_VOID(self);
107 auto session = weakSession.promote();
108 CHECK_NULL_VOID(session);
109 const auto pointerEvent = info.GetPointerEvent();
110 CHECK_NULL_VOID(pointerEvent);
111 auto host = self->GetHost();
112 if (host != nullptr) {
113 DelayedSingleton<WindowEventProcess>::GetInstance()->ProcessWindowMouseEvent(
114 host->GetId(), session, pointerEvent);
115 DelayedSingleton<WindowEventProcess>::GetInstance()->ProcessWindowDragEvent(
116 host->GetId(), session, pointerEvent);
117 }
118 session->TransferPointerEvent(pointerEvent);
119 };
120 mouseEventHub->SetMouseEvent(std::move(mouseCallback));
121
122 RegisterFocusCallback();
123 RegisterEventCallback();
124 RegisterResponseRegionCallback();
125
126 if (session_->NeedCheckContextTransparent()) {
127 PostCheckContextTransparentTask();
128 }
129 }
130
OnDetachFromFrameNode(FrameNode * frameNode)131 void SystemWindowScene::OnDetachFromFrameNode(FrameNode* frameNode)
132 {
133 CHECK_NULL_VOID(session_);
134 CHECK_NULL_VOID(frameNode);
135 ACE_SCOPED_TRACE("OnDetachFromFrameNode[id:%d][self:%d][type:%d][name:%s]",
136 session_->GetPersistentId(), frameNode->GetId(), session_->GetWindowType(), session_->GetWindowName().c_str());
137 TAG_LOGI(AceLogTag::ACE_WINDOW_SCENE,
138 "OnDetachFromFrameNode id: %{public}d, node id: %{public}d, type: %{public}d, name: %{public}s",
139 session_->GetPersistentId(), frameNode->GetId(), session_->GetWindowType(), session_->GetWindowName().c_str());
140 if (session_->NeedCheckContextTransparent()) {
141 checkContextTransparentTask_.Cancel();
142 }
143 }
144
OnAttachToMainTree()145 void SystemWindowScene::OnAttachToMainTree()
146 {
147 auto host = GetHost();
148 CHECK_NULL_VOID(host);
149 auto context = host->GetRenderContext();
150 CHECK_NULL_VOID(context);
151 context->SetIsNeedRebuildRSTree(true);
152 }
153
OnDetachFromMainTree()154 void SystemWindowScene::OnDetachFromMainTree()
155 {
156 auto host = GetHost();
157 CHECK_NULL_VOID(host);
158 auto context = host->GetRenderContext();
159 CHECK_NULL_VOID(context);
160 context->SetIsNeedRebuildRSTree(false);
161 }
162
RegisterEventCallback()163 void SystemWindowScene::RegisterEventCallback()
164 {
165 CHECK_NULL_VOID(session_);
166 auto pointerEventCallback =
167 [weakThis = WeakClaim(this), instanceId = instanceId_](std::shared_ptr<MMI::PointerEvent> PointerEvent) {
168 ContainerScope Scope(instanceId);
169 auto pipelineContext = PipelineContext::GetCurrentContext();
170 if (!pipelineContext) {
171 TAG_LOGE(AceLogTag::ACE_INPUTTRACKING,
172 "PipelineContext GetCurrentContext null,id:%{public}d", PointerEvent->GetId());
173 PointerEvent->MarkProcessed();
174 return;
175 }
176 auto taskExecutor = pipelineContext->GetTaskExecutor();
177 if (!taskExecutor) {
178 TAG_LOGE(AceLogTag::ACE_INPUTTRACKING, "taskExecutor is null,id:%{public}d", PointerEvent->GetId());
179 PointerEvent->MarkProcessed();
180 return;
181 }
182 taskExecutor->PostTask([weakThis, PointerEvent]() {
183 auto self = weakThis.Upgrade();
184 if (!self) {
185 TAG_LOGE(AceLogTag::ACE_INPUTTRACKING,
186 "weakThis Upgrade null,id:%{public}d", PointerEvent->GetId());
187 PointerEvent->MarkProcessed();
188 return;
189 }
190 auto host = self->GetHost();
191 if (!host) {
192 TAG_LOGE(AceLogTag::ACE_INPUTTRACKING,
193 "GetHost null,id:%{public}d", PointerEvent->GetId());
194 PointerEvent->MarkProcessed();
195 return;
196 }
197 WindowSceneHelper::InjectPointerEvent(host, PointerEvent);
198 },
199 TaskExecutor::TaskType::UI, "ArkUIWindowInjectPointerEvent", PriorityType::VIP);
200 };
201 session_->SetNotifySystemSessionPointerEventFunc(std::move(pointerEventCallback));
202
203 auto keyEventCallback = [instanceId = instanceId_](std::shared_ptr<MMI::KeyEvent> KeyEvent,
204 bool isPreImeEvent) -> bool {
205 ContainerScope Scope(instanceId);
206 return WindowSceneHelper::InjectKeyEvent(KeyEvent, isPreImeEvent);
207 };
208 session_->SetNotifySystemSessionKeyEventFunc(std::move(keyEventCallback));
209 }
210
RegisterResponseRegionCallback()211 void SystemWindowScene::RegisterResponseRegionCallback()
212 {
213 auto host = GetHost();
214 CHECK_NULL_VOID(host);
215 auto gestureHub = host->GetOrCreateGestureEventHub();
216 CHECK_NULL_VOID(gestureHub);
217
218 auto touchCallback = [weakSession = wptr(session_)](TouchEventInfo& info) {
219 auto session = weakSession.promote();
220 CHECK_NULL_VOID(session);
221 const auto pointerEvent = info.GetPointerEvent();
222 CHECK_NULL_VOID(pointerEvent);
223 session->TransferPointerEvent(pointerEvent);
224 };
225 gestureHub->SetTouchEvent(std::move(touchCallback));
226
227 auto responseRegionCallback = [weakThis = WeakClaim(this), weakSession = wptr(session_)](
228 const std::vector<DimensionRect>& responseRegion) {
229 auto self = weakThis.Upgrade();
230 CHECK_NULL_VOID(self);
231 auto session = weakSession.promote();
232 CHECK_NULL_VOID(session);
233 std::vector<Rosen::Rect> hotAreas;
234 for (auto& rect : responseRegion) {
235 Rosen::Rect windowRect {
236 .posX_ = std::round(rect.GetOffset().GetX().Value()),
237 .posY_ = std::round(rect.GetOffset().GetY().Value()),
238 .width_ = std::round(rect.GetWidth().Value()),
239 .height_ = std::round(rect.GetHeight().Value()),
240 };
241 hotAreas.push_back(windowRect);
242 }
243 session->SetTouchHotAreas(hotAreas);
244 };
245 gestureHub->SetResponseRegionFunc(responseRegionCallback);
246 }
247
GetWindowPatternType() const248 uint32_t SystemWindowScene::GetWindowPatternType() const
249 {
250 return static_cast<uint32_t>(WindowPatternType::SYSTEM_WINDOW_SCENE);
251 }
252
RegisterFocusCallback()253 void SystemWindowScene::RegisterFocusCallback()
254 {
255 CHECK_NULL_VOID(session_);
256
257 auto requestFocusCallback = [weakThis = WeakClaim(this), frameNode = frameNode_, instanceId = instanceId_]() {
258 ContainerScope scope(instanceId);
259 auto pipelineContext = PipelineContext::GetCurrentContext();
260 CHECK_NULL_VOID(pipelineContext);
261 pipelineContext->SetFocusedWindowSceneNode(frameNode);
262 pipelineContext->PostAsyncEvent([weakThis]() {
263 auto pipeline = PipelineContext::GetCurrentContext();
264 CHECK_NULL_VOID(pipeline);
265 pipeline->SetIsFocusActive(false);
266 auto self = weakThis.Upgrade();
267 CHECK_NULL_VOID(self);
268 self->FocusViewShow();
269 }, "ArkUIWindowFocusViewShow", TaskExecutor::TaskType::UI);
270 };
271 session_->SetNotifyUIRequestFocusFunc(requestFocusCallback);
272
273 auto lostFocusCallback = [weakThis = WeakClaim(this), instanceId = instanceId_]() {
274 ContainerScope scope(instanceId);
275 auto pipelineContext = PipelineContext::GetCurrentContext();
276 CHECK_NULL_VOID(pipelineContext);
277 pipelineContext->PostAsyncEvent([weakThis]() {
278 auto pipeline = PipelineContext::GetCurrentContext();
279 CHECK_NULL_VOID(pipeline);
280 auto self = weakThis.Upgrade();
281 CHECK_NULL_VOID(self);
282 CHECK_NULL_VOID(self->GetSession());
283 pipeline->RestoreDefault(self->GetSession()->GetPersistentId());
284 }, "ArkUIWindowLostFocus", TaskExecutor::TaskType::UI);
285 };
286 session_->SetNotifyUILostFocusFunc(lostFocusCallback);
287 }
288
LostViewFocus()289 void SystemWindowScene::LostViewFocus()
290 {
291 TAG_LOGI(
292 AceLogTag::ACE_FOCUS, "Focus view: %{public}s/%{public}d lost focus", GetFrameName().c_str(), GetFrameId());
293 auto focusHub = GetFocusHub();
294 if (!focusHub || !focusHub->IsCurrentFocus()) {
295 return;
296 }
297 auto pipeline = PipelineContext::GetCurrentContext();
298 CHECK_NULL_VOID(pipeline);
299 auto screenNode = pipeline->GetScreenNode();
300 CHECK_NULL_VOID(screenNode);
301 auto screenNodeFocusHub = screenNode->GetFocusHub();
302 CHECK_NULL_VOID(screenNodeFocusHub);
303 screenNodeFocusHub->LostFocus(BlurReason::VIEW_SWITCH);
304 }
305
PostCheckContextTransparentTask()306 void SystemWindowScene::PostCheckContextTransparentTask()
307 {
308 checkContextTransparentTask_.Reset([weakThis = WeakClaim(this)]() {
309 auto self = weakThis.Upgrade();
310 CHECK_NULL_VOID(self);
311 CHECK_NULL_VOID(self->GetHost());
312 CHECK_NULL_VOID(self->session_);
313 if (self->session_->NeedCheckContextTransparent() && self->GetHost()->IsContextTransparent()) {
314 self->session_->NotifyContextTransparent();
315 }
316 });
317
318 auto pipelineContext = PipelineContext::GetCurrentContext();
319 CHECK_NULL_VOID(pipelineContext);
320 auto taskExecutor = pipelineContext->GetTaskExecutor();
321 CHECK_NULL_VOID(taskExecutor);
322 taskExecutor->PostDelayedTask(std::move(checkContextTransparentTask_), TaskExecutor::TaskType::UI,
323 DELAY_TIME, "ArkUIWindowCheckContextTransparent");
324 }
325
PostFaultInjectTask()326 void SystemWindowScene::PostFaultInjectTask()
327 {
328 auto task = ([weakThis = WeakClaim(this)]() {
329 auto self = weakThis.Upgrade();
330 CHECK_NULL_VOID(self);
331 auto host = self->GetHost();
332 CHECK_NULL_VOID(host);
333 auto renderContext = AceType::DynamicCast<NG::RosenRenderContext>(host->GetRenderContext());
334 renderContext->SetOpacity(0.0f);
335 host->MarkDirtyNode();
336 });
337
338 auto pipelineContext = PipelineContext::GetCurrentContext();
339 CHECK_NULL_VOID(pipelineContext);
340 auto taskExecutor = pipelineContext->GetTaskExecutor();
341 CHECK_NULL_VOID(taskExecutor);
342 taskExecutor->PostDelayedTask(
343 std::move(task), TaskExecutor::TaskType::UI, DELAY_TIME, "ArkUIWindowFaultInject");
344 }
345 } // namespace OHOS::Ace::NG
346