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/window_node.h"
17
18 #include "core/components_ng/pattern/window_scene/scene/window_pattern.h"
19 #include "core/components_ng/pattern/window_scene/screen/screen_pattern.h"
20 #include "core/pipeline_ng/pipeline_context.h"
21 #include "session_manager/include/scene_session_manager.h"
22
23 namespace OHOS::Ace::NG {
24 namespace {
25 constexpr float MOUSE_RECT_HOT_VP = 4.0f;
26 constexpr float TOUCH_RECT_HOT_VP = 20.0f;
27 constexpr double DEFAULT_HOT_DENSITY = 1.5f;
28 std::map<int32_t, std::map<int32_t, WeakPtr<WindowNode>>> g_windowNodeMap;
29 }
30
WindowNode(const std::string & tag,int32_t nodeId,const RefPtr<Pattern> & pattern,bool isRoot)31 WindowNode::WindowNode(const std::string& tag,
32 int32_t nodeId, const RefPtr<Pattern>& pattern, bool isRoot)
33 : FrameNode(tag, nodeId, pattern, isRoot) {}
34
WindowNode(const std::string & tag,int32_t nodeId,int32_t sessionId,const RefPtr<Pattern> & pattern,bool isRoot,int32_t screenId)35 WindowNode::WindowNode(const std::string& tag,
36 int32_t nodeId, int32_t sessionId, const RefPtr<Pattern>& pattern, bool isRoot, int32_t screenId)
37 : FrameNode(tag, nodeId, pattern, isRoot)
38 {
39 screenId_ = screenId;
40 sessionId_ = sessionId;
41 }
42
~WindowNode()43 WindowNode::~WindowNode()
44 {
45 g_windowNodeMap[screenId_].erase(sessionId_);
46 }
47
GetOrCreateWindowNode(const std::string & tag,int32_t nodeId,int32_t sessionId,const std::function<RefPtr<Pattern> (void)> & patternCreator)48 RefPtr<WindowNode> WindowNode::GetOrCreateWindowNode(const std::string& tag,
49 int32_t nodeId, int32_t sessionId, const std::function<RefPtr<Pattern>(void)>& patternCreator)
50 {
51 auto windowNode = ElementRegister::GetInstance()->GetSpecificItemById<WindowNode>(nodeId);
52 if (windowNode) {
53 if (windowNode->GetTag() == tag) {
54 return windowNode;
55 }
56 bool removed = ElementRegister::GetInstance()->RemoveItemSilently(nodeId);
57 if (!removed) {
58 TAG_LOGW(AceLogTag::ACE_WINDOW_SCENE,
59 "Remove item silently failed, node id: %{public}d", nodeId);
60 }
61 auto parent = windowNode->GetParent();
62 if (parent) {
63 parent->RemoveChild(windowNode);
64 }
65 }
66
67 auto sceneSession = Rosen::SceneSessionManager::GetInstance().GetSceneSession(sessionId);
68 if (sceneSession == nullptr) {
69 TAG_LOGE(AceLogTag::ACE_WINDOW_SCENE, "sessionId: %{public}d", sessionId);
70 return nullptr;
71 }
72 auto screenId = static_cast<int>(sceneSession->GetScreenId());
73 auto screenIter = g_windowNodeMap.find(screenId);
74 if (screenIter != g_windowNodeMap.end()) {
75 auto sessionMap = screenIter->second;
76 auto iter = sessionMap.find(sessionId);
77 if (iter != sessionMap.end()) {
78 auto node = iter->second.Upgrade();
79 if (node) {
80 TAG_LOGW(AceLogTag::ACE_WINDOW_SCENE,
81 "screenId: %{public}d, node id: %{public}d, sessionId: %{public}d",
82 screenId, node->GetId(), sessionId);
83 return node;
84 }
85 }
86 }
87
88 auto pattern = patternCreator ? patternCreator() : AceType::MakeRefPtr<Pattern>();
89 windowNode = AceType::MakeRefPtr<WindowNode>(tag, nodeId, sessionId, pattern, false, screenId);
90 windowNode->InitializePatternAndContext();
91 bool added = ElementRegister::GetInstance()->AddUINode(windowNode);
92 if (!added) {
93 TAG_LOGW(AceLogTag::ACE_WINDOW_SCENE, "Add UINode failed, node id: %{public}d",
94 nodeId);
95 }
96 g_windowNodeMap[screenId][sessionId] = WeakPtr<WindowNode>(windowNode);
97 return windowNode;
98 }
99
SetParent(const WeakPtr<UINode> & parent,bool needDetect)100 void WindowNode::SetParent(const WeakPtr<UINode>& parent, bool needDetect)
101 {
102 auto prevParent = GetParent();
103 if (prevParent && prevParent != parent.Upgrade()) {
104 RemoveFromParentCleanly(Claim(this), prevParent);
105 }
106 UINode::SetParent(parent);
107 }
108
IsOutOfTouchTestRegion(const PointF & parentLocalPoint,const TouchEvent & touchEvent,std::vector<RectF> * regionList)109 bool WindowNode::IsOutOfTouchTestRegion(const PointF& parentLocalPoint, const TouchEvent& touchEvent,
110 std::vector<RectF>* regionList)
111 {
112 auto pattern = GetPattern<WindowPattern>();
113 if (pattern != nullptr) {
114 auto hotAreas = pattern->GetHotAreas();
115 if (!hotAreas.empty()) {
116 return IsOutOfHotAreas(hotAreas, parentLocalPoint);
117 }
118 }
119 const auto& rect = GetPaintRectWithTransform();
120 const auto& hotRect = ConvertHotRect(rect, static_cast<int32_t>(touchEvent.sourceType));
121 if (!hotRect.IsInRegion(parentLocalPoint)) {
122 return true;
123 }
124 return false;
125 }
126
GetResponseRegionList(const RectF & rect,int32_t sourceType)127 std::vector<RectF> WindowNode::GetResponseRegionList(const RectF& rect, int32_t sourceType)
128 {
129 auto pattern = GetPattern<WindowPattern>();
130 if (pattern != nullptr) {
131 auto hotAreas = pattern->GetHotAreas();
132 if (!hotAreas.empty()) {
133 return ConvertHotRects(hotAreas);
134 }
135 }
136 std::vector<RectF> responseRegionList;
137 responseRegionList.emplace_back(ConvertHotRect(rect, sourceType));
138 return responseRegionList;
139 }
140
ConvertHotRects(const std::vector<Rosen::Rect> & hotAreas)141 std::vector<RectF> WindowNode::ConvertHotRects(const std::vector<Rosen::Rect>& hotAreas)
142 {
143 std::vector<RectF> responseRegionList;
144 for (size_t i = 0; i < hotAreas.size(); i++) {
145 float hotX = static_cast<float>(hotAreas[i].posX_);
146 float hotY = static_cast<float>(hotAreas[i].posY_);
147 float hotWidth = static_cast<float>(hotAreas[i].width_);
148 float hotHeight = static_cast<float>(hotAreas[i].height_);
149 RectF rectHot(hotX, hotY, hotWidth, hotHeight);
150 responseRegionList.emplace_back(rectHot);
151 }
152 return responseRegionList;
153 }
154
IsOutOfHotAreas(const std::vector<Rosen::Rect> & hotAreas,const PointF & parentLocalPoint)155 bool WindowNode::IsOutOfHotAreas(const std::vector<Rosen::Rect>& hotAreas, const PointF& parentLocalPoint)
156 {
157 auto hotRects = ConvertHotRects(hotAreas);
158 for (auto& hotRect : hotRects) {
159 if (hotRect.IsInRegion(parentLocalPoint)) {
160 return false;
161 }
162 }
163 return true;
164 }
165
ConvertHotRect(const RectF & rect,int32_t sourceType)166 RectF WindowNode::ConvertHotRect(const RectF& rect, int32_t sourceType)
167 {
168 auto pattern = GetPattern<WindowPattern>();
169 if (pattern != nullptr && pattern->GetSession() != nullptr &&
170 (pattern->GetSession()->GetWindowType() != Rosen::WindowType::WINDOW_TYPE_APP_MAIN_WINDOW &&
171 pattern->GetSession()->GetWindowType() != Rosen::WindowType::WINDOW_TYPE_APP_SUB_WINDOW)) {
172 return rect;
173 }
174 float hotOffsetVp = (sourceType == static_cast<int32_t>(Ace::SourceType::MOUSE)) ?
175 MOUSE_RECT_HOT_VP : TOUCH_RECT_HOT_VP;
176 auto context = PipelineContext::GetCurrentContext();
177 double density = (context != nullptr) ? context->GetDensity() : DEFAULT_HOT_DENSITY;
178 float hotOffset = static_cast<float>(hotOffsetVp * density);
179 float hotX = rect.GetX() - hotOffset;
180 float hotY = rect.GetY() - hotOffset;
181 float hotWidth = rect.Width() + hotOffset * 2;
182 float hotHeight = rect.Height() + hotOffset * 2;
183 RectF rectHot(hotX, hotY, hotWidth, hotHeight);
184 return rectHot;
185 }
186 } // namespace OHOS::Ace::NG
187