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/helper/window_scene_helper.h"
17 
18 #include "input_manager.h"
19 #include "key_event.h"
20 #include "pointer_event.h"
21 
22 #include "adapter/ohos/entrance/ace_view_ohos.h"
23 #include "base/memory/referenced.h"
24 #include "base/utils/utils.h"
25 #include "core/common/container.h"
26 #include "core/components_ng/pattern/window_scene/scene/system_window_scene.h"
27 #include "core/components_v2/inspector/inspector_constants.h"
28 #include "core/components_ng/pattern/text_field/text_field_pattern.h"
29 #include "core/components_ng/pattern/search/search_pattern.h"
30 #include "core/pipeline_ng/pipeline_context.h"
31 #include "session/host/include/session.h"
32 
33 #include "key_event.h"
34 #include "pointer_event.h"
35 #include "adapter/ohos/entrance/ace_view_ohos.h"
36 #include "core/pipeline_ng/pipeline_context.h"
37 
38 #ifndef ACE_UNITTEST
39 #ifdef ENABLE_STANDARD_INPUT
40 #include "input_method_controller.h"
41 #endif
42 #endif
43 
44 namespace OHOS::Ace::NG {
FindWindowScene(const RefPtr<FrameNode> & targetNode)45 RefPtr<UINode> WindowSceneHelper::FindWindowScene(const RefPtr<FrameNode>& targetNode)
46 {
47     CHECK_NULL_RETURN(targetNode, nullptr);
48 
49     auto container = Container::Current();
50     if (!container || !container->IsScenceBoardWindow() || !container->IsSceneBoardEnabled()) {
51         TAG_LOGD(AceLogTag::ACE_KEYBOARD, "Container null Or not ScenceBoardWindow.");
52         return nullptr;
53     }
54 
55     TAG_LOGD(AceLogTag::ACE_KEYBOARD, "FindWindowScene start.");
56     auto parent = targetNode->GetParent();
57     while (parent && parent->GetTag() != V2::WINDOW_SCENE_ETS_TAG) {
58         parent = parent->GetParent();
59     }
60     CHECK_NULL_RETURN(parent, nullptr);
61     TAG_LOGD(AceLogTag::ACE_KEYBOARD, "FindWindowScene successfully.");
62 
63     return parent;
64 }
65 
GetCurSession(const RefPtr<FrameNode> & focusedFrameNode)66 sptr<Rosen::Session> GetCurSession(const RefPtr<FrameNode>& focusedFrameNode)
67 {
68     auto sceneBoardWindowUINode = WindowSceneHelper::FindWindowScene(focusedFrameNode);
69     if (sceneBoardWindowUINode == nullptr) {
70         TAG_LOGD(AceLogTag::ACE_KEYBOARD, "FindWindowScene failed.");
71         return nullptr;
72     }
73 
74     auto windowSceneFrameNode = AceType::DynamicCast<FrameNode>(sceneBoardWindowUINode);
75     if (windowSceneFrameNode == nullptr) {
76         TAG_LOGD(AceLogTag::ACE_KEYBOARD, "WindowFrameNode to FrameNode failed.");
77         return nullptr;
78     }
79 
80     auto windowScenePattern = windowSceneFrameNode->GetPattern<SystemWindowScene>();
81     if (windowScenePattern == nullptr) {
82         TAG_LOGD(AceLogTag::ACE_KEYBOARD, "windowScenePattern is null.");
83         return nullptr;
84     }
85 
86     return windowScenePattern->GetSession();
87 }
88 
IsWindowScene(const RefPtr<FrameNode> & focusedFrameNode)89 bool WindowSceneHelper::IsWindowScene(const RefPtr<FrameNode>& focusedFrameNode)
90 {
91     auto window2patternSession = GetCurSession(focusedFrameNode);
92     if (window2patternSession == nullptr) {
93         TAG_LOGD(AceLogTag::ACE_KEYBOARD, "The session between window and pattern is nullptr.");
94         return false;
95     }
96 
97     return window2patternSession->GetSessionInfo().isSystem_;
98 }
99 
GetFocusSystemWindowId(const RefPtr<FrameNode> & focusedFrameNode)100 int32_t WindowSceneHelper::GetFocusSystemWindowId(const RefPtr<FrameNode>& focusedFrameNode)
101 {
102     int32_t  focusSystemWindowId = 0;
103     bool isWindowScene = IsWindowScene(focusedFrameNode);
104     sptr<Rosen::Session> window2patternSession = GetCurSession(focusedFrameNode);
105     if (window2patternSession == nullptr) {
106         TAG_LOGD(AceLogTag::ACE_KEYBOARD, "The session between window and pattern is null.");
107         return focusSystemWindowId;
108     }
109     if (isWindowScene) {
110         focusSystemWindowId = static_cast<int32_t>(window2patternSession->GetPersistentId());
111         TAG_LOGI(AceLogTag::ACE_KEYBOARD, "Get systemWindowScene id:%{public}d successfully.", focusSystemWindowId);
112     }
113 
114     return focusSystemWindowId;
115 }
116 
GetWindowIdForWindowScene(const RefPtr<FrameNode> & windowSceneNode)117 int32_t WindowSceneHelper::GetWindowIdForWindowScene(const RefPtr<FrameNode>& windowSceneNode)
118 {
119     int32_t windowId = 0;
120     CHECK_NULL_RETURN(windowSceneNode, windowId);
121     if (windowSceneNode->GetTag() != V2::WINDOW_SCENE_ETS_TAG) {
122         return windowId;
123     }
124     auto windowScenePattern = windowSceneNode->GetPattern<SystemWindowScene>();
125     CHECK_NULL_RETURN(windowScenePattern, windowId);
126 
127     auto window2patternSession = windowScenePattern->GetSession();
128     CHECK_NULL_RETURN(window2patternSession, windowId);
129 
130     windowId = static_cast<int32_t>(window2patternSession->GetPersistentId());
131     return windowId;
132 }
133 
IsFocusWindowSceneCloseKeyboard(const RefPtr<FrameNode> & focusedFrameNode)134 bool WindowSceneHelper::IsFocusWindowSceneCloseKeyboard(const RefPtr<FrameNode>& focusedFrameNode)
135 {
136     sptr<Rosen::Session> window2patternSession = GetCurSession(focusedFrameNode);
137     if (window2patternSession == nullptr) {
138         TAG_LOGW(AceLogTag::ACE_KEYBOARD, "The session between window and pattern is nullptr.");
139         return false;
140     }
141 
142     return window2patternSession->GetSCBKeepKeyboardFlag();
143 }
144 
IsWindowSceneCloseKeyboard(const RefPtr<FrameNode> & frameNode)145 void WindowSceneHelper::IsWindowSceneCloseKeyboard(const RefPtr<FrameNode>& frameNode)
146 {
147 #if defined (ENABLE_STANDARD_INPUT)
148     // If focus pattern does not need softkeyboard, close it, in windowScene.
149     auto curPattern = frameNode->GetPattern<NG::Pattern>();
150     CHECK_NULL_VOID(curPattern);
151     bool isNeedKeyBoard = curPattern->NeedSoftKeyboard();
152     auto saveKeyboard = IsFocusWindowSceneCloseKeyboard(frameNode);
153     TAG_LOGI(AceLogTag::ACE_KEYBOARD,
154         "FrameNode(%{public}s/%{public}d) notNeedSoftKeyboard, Keep:%{public}d, Need:%{public}d)",
155         frameNode->GetTag().c_str(), frameNode->GetId(), !saveKeyboard, !isNeedKeyBoard);
156     if (!saveKeyboard && !isNeedKeyBoard) {
157         auto inputMethod = MiscServices::InputMethodController::GetInstance();
158         if (inputMethod) {
159             inputMethod->RequestHideInput();
160             inputMethod->Close();
161             TAG_LOGI(AceLogTag::ACE_KEYBOARD, "scbSoftKeyboard Closes Successfully.");
162         }
163     }
164 #endif
165 }
166 
IsCloseKeyboard(const RefPtr<FrameNode> & frameNode)167 void WindowSceneHelper::IsCloseKeyboard(const RefPtr<FrameNode>& frameNode)
168 {
169 #if defined (ENABLE_STANDARD_INPUT)
170     // If focus pattern does not need softkeyboard, close it, not in windowScene.
171     auto curPattern = frameNode->GetPattern<NG::Pattern>();
172     CHECK_NULL_VOID(curPattern);
173     bool isNeedKeyBoard = curPattern->NeedSoftKeyboard();
174     auto saveKeyboard = IsFocusWindowSceneCloseKeyboard(frameNode);
175     TAG_LOGI(AceLogTag::ACE_KEYBOARD,
176         "FrameNode(%{public}s/%{public}d) notNeed SoftKeyboard, Keep:%{public}d, Need:%{public}d)",
177         frameNode->GetTag().c_str(), frameNode->GetId(), !saveKeyboard, !isNeedKeyBoard);
178     if (!saveKeyboard && !isNeedKeyBoard) {
179         auto inputMethod = MiscServices::InputMethodController::GetInstance();
180         if (inputMethod) {
181             inputMethod->RequestHideInput();
182             inputMethod->Close();
183             TAG_LOGI(AceLogTag::ACE_KEYBOARD, "SoftKeyboard Closes Successfully.");
184         }
185     }
186 #endif
187 }
188 
CaculatePoint(const RefPtr<FrameNode> & node,const std::shared_ptr<OHOS::MMI::PointerEvent> & pointerEvent)189 void CaculatePoint(const RefPtr<FrameNode>& node, const std::shared_ptr<OHOS::MMI::PointerEvent>& pointerEvent)
190 {
191     CHECK_NULL_VOID(node);
192     CHECK_NULL_VOID(pointerEvent);
193 
194     auto pointerId = pointerEvent->GetPointerId();
195     auto renderContext = node->GetRenderContext();
196     CHECK_NULL_VOID(renderContext);
197     auto rect = renderContext->GetPaintRectWithoutTransform();
198     MMI::PointerEvent::PointerItem item;
199     if (pointerEvent->GetPointerItem(pointerId, item)) {
200         PointF tmp(item.GetWindowX() + rect.GetX(), item.GetWindowY() + rect.GetY());
201         renderContext->GetPointTransform(tmp);
202         item.SetWindowX(static_cast<int32_t>(std::round(tmp.GetX())));
203         item.SetWindowY(static_cast<int32_t>(std::round(tmp.GetY())));
204         if (pointerEvent->GetSourceType() == OHOS::MMI::PointerEvent::SOURCE_TYPE_TOUCHSCREEN &&
205             item.GetToolType() == OHOS::MMI::PointerEvent::TOOL_TYPE_PEN) {
206             // CaculatePoint for double XY Position.
207             PointF tmpPos(item.GetWindowXPos() + rect.GetX(), item.GetWindowYPos() + rect.GetY());
208             renderContext->GetPointTransform(tmpPos);
209             item.SetWindowXPos(tmpPos.GetX());
210             item.SetWindowYPos(tmpPos.GetY());
211         }
212         pointerEvent->UpdatePointerItem(pointerId, item);
213     }
214 }
215 
InjectPointerEvent(const RefPtr<FrameNode> & node,const std::shared_ptr<OHOS::MMI::PointerEvent> & pointerEvent)216 void WindowSceneHelper::InjectPointerEvent(
217     const RefPtr<FrameNode>& node, const std::shared_ptr<OHOS::MMI::PointerEvent>& pointerEvent)
218 {
219     if (!pointerEvent) {
220         TAG_LOGE(AceLogTag::ACE_INPUTTRACKING, "InjectPointerEvent pointerEvent is null return.");
221         return;
222     }
223     if (!node) {
224         MMI::InputManager::GetInstance()->MarkProcessed(
225             pointerEvent->GetId(), pointerEvent->GetActionTime(), pointerEvent->IsMarkEnabled());
226         TAG_LOGE(AceLogTag::ACE_INPUTTRACKING, "InjectPointerEvent eventId:%{public}d node is null return.",
227             pointerEvent->GetId());
228         return;
229     }
230 
231     auto container = Container::Current();
232     if (!container) {
233         MMI::InputManager::GetInstance()->MarkProcessed(
234             pointerEvent->GetId(), pointerEvent->GetActionTime(), pointerEvent->IsMarkEnabled());
235         TAG_LOGE(AceLogTag::ACE_INPUTTRACKING, "InjectPointerEvent eventId:%{public}d container is null return.",
236             pointerEvent->GetId());
237         return;
238     }
239     CaculatePoint(node, pointerEvent);
240     auto aceView = AceType::DynamicCast<OHOS::Ace::Platform::AceViewOhos>(container->GetAceView());
241     if (!aceView) {
242         MMI::InputManager::GetInstance()->MarkProcessed(
243             pointerEvent->GetId(), pointerEvent->GetActionTime(), pointerEvent->IsMarkEnabled());
244         TAG_LOGE(AceLogTag::ACE_INPUTTRACKING, "InjectPointerEvent eventId:%{public}d aceView is null return.",
245             pointerEvent->GetId());
246         return;
247     }
248     OHOS::Ace::Platform::AceViewOhos::DispatchTouchEvent(aceView, pointerEvent, node, nullptr, true);
249 }
250 
InjectKeyEvent(const std::shared_ptr<OHOS::MMI::KeyEvent> & keyEvent,bool isPreIme)251 bool WindowSceneHelper::InjectKeyEvent(const std::shared_ptr<OHOS::MMI::KeyEvent>& keyEvent, bool isPreIme)
252 {
253     CHECK_NULL_RETURN(keyEvent, false);
254     if (!SystemProperties::GetAceCommercialLogEnabled()) {
255         TAG_LOGI(AceLogTag::ACE_INPUTTRACKING,
256             SEC_PLD(, "KeyEvent Process to inject, eventInfo: id:%{public}d, "
257             "keyEvent info: keyCode is %{public}d, "
258             "keyAction is %{public}d, keyActionTime is %{public}" PRId64),
259             SEC_PARAM(keyEvent->GetId(), keyEvent->GetKeyCode(),
260             keyEvent->GetKeyAction(), keyEvent->GetActionTime()));
261     }
262 
263     auto container = Container::Current();
264     CHECK_NULL_RETURN(container, false);
265     auto aceView = AceType::DynamicCast<OHOS::Ace::Platform::AceViewOhos>(container->GetAceView());
266     CHECK_NULL_RETURN(aceView, false);
267     return OHOS::Ace::Platform::AceViewOhos::DispatchKeyEvent(aceView, keyEvent, isPreIme);
268 }
269 
IsWindowPattern(const RefPtr<FrameNode> & node)270 bool WindowSceneHelper::IsWindowPattern(const RefPtr<FrameNode>& node)
271 {
272     if (!node) {
273         return false;
274     }
275     return node->GetWindowPatternType() > static_cast<uint32_t>(WindowPatternType::SCREEN_SCENE);
276 }
277 
HasWindowSession(const RefPtr<FrameNode> & node)278 bool WindowSceneHelper::HasWindowSession(const RefPtr<FrameNode>& node)
279 {
280     if (!node) {
281         return false;
282     }
283     return node->GetWindowPatternType() > static_cast<uint32_t>(WindowPatternType::TRANSFORM_SCENE);
284 }
285 
IsTransformScene(uint32_t type)286 bool WindowSceneHelper::IsTransformScene(uint32_t type)
287 {
288     return type == static_cast<uint32_t>(WindowPatternType::TRANSFORM_SCENE);
289 }
290 
IsSystemWindowScene(uint32_t type)291 bool WindowSceneHelper::IsSystemWindowScene(uint32_t type)
292 {
293     return type == static_cast<uint32_t>(WindowPatternType::SYSTEM_WINDOW_SCENE);
294 }
295 
IsPanelScene(uint32_t type)296 bool WindowSceneHelper::IsPanelScene(uint32_t type)
297 {
298     return type == static_cast<uint32_t>(WindowPatternType::PANEL_SCENE);
299 }
300 
IsScreenScene(uint32_t type)301 bool WindowSceneHelper::IsScreenScene(uint32_t type)
302 {
303     return type == static_cast<uint32_t>(WindowPatternType::SCREEN_SCENE);
304 }
305 } // namespace OHOS::Ace::NG
306