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