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