• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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