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
20 #include "adapter/ohos/entrance/ace_view_ohos.h"
21 #include "base/memory/referenced.h"
22 #include "base/utils/utils.h"
23 #include "core/common/container.h"
24 #include "core/components_ng/pattern/window_scene/scene/system_window_scene.h"
25 #include "core/components_v2/inspector/inspector_constants.h"
26 #include "core/components_ng/pattern/text_field/text_field_pattern.h"
27 #include "core/components_ng/pattern/search/search_pattern.h"
28 #include "core/pipeline_ng/pipeline_context.h"
29 #include "session/host/include/session.h"
30 #include "transaction/rs_transaction.h"
31 #include "transaction/rs_transaction_handler.h"
32 #include "transaction/rs_transaction_proxy.h"
33 #include "transaction/rs_sync_transaction_controller.h"
34 #include "transaction/rs_sync_transaction_handler.h"
35 #include "ui/rs_node.h"
36 #include "ui/rs_ui_context.h"
37 #include "ui/rs_ui_director.h"
38
39 #ifndef ACE_UNITTEST
40 #ifdef ENABLE_STANDARD_INPUT
41 #include "input_method_controller.h"
42 #endif
43 #endif
44
45 namespace OHOS::Ace::NG {
FindWindowScene(const RefPtr<FrameNode> & targetNode)46 RefPtr<UINode> WindowSceneHelper::FindWindowScene(const RefPtr<FrameNode>& targetNode)
47 {
48 CHECK_NULL_RETURN(targetNode, nullptr);
49
50 auto container = Container::Current();
51 if (!container || !container->IsSceneBoardWindow() || !container->IsSceneBoardEnabled()) {
52 TAG_LOGD(AceLogTag::ACE_KEYBOARD, "Container nullptr Or not SceneBoardWindow.");
53 return nullptr;
54 }
55
56 if (targetNode->GetTag() == V2::WINDOW_SCENE_ETS_TAG) {
57 return targetNode;
58 }
59
60 TAG_LOGD(AceLogTag::ACE_KEYBOARD, "FindWindowScene start.");
61 auto parent = targetNode->GetParent();
62 while (parent && parent->GetTag() != V2::WINDOW_SCENE_ETS_TAG) {
63 parent = parent->GetParent();
64 }
65 CHECK_NULL_RETURN(parent, nullptr);
66 TAG_LOGD(AceLogTag::ACE_KEYBOARD, "FindWindowScene successfully.");
67
68 return parent;
69 }
70
GetCurSession(const RefPtr<FrameNode> & focusedFrameNode)71 sptr<Rosen::Session> GetCurSession(const RefPtr<FrameNode>& focusedFrameNode)
72 {
73 auto sceneBoardWindowUINode = WindowSceneHelper::FindWindowScene(focusedFrameNode);
74 if (sceneBoardWindowUINode == nullptr) {
75 TAG_LOGD(AceLogTag::ACE_KEYBOARD, "FindWindowScene failed.");
76 return nullptr;
77 }
78
79 auto windowSceneFrameNode = AceType::DynamicCast<FrameNode>(sceneBoardWindowUINode);
80 if (windowSceneFrameNode == nullptr) {
81 TAG_LOGD(AceLogTag::ACE_KEYBOARD, "WindowFrameNode to FrameNode failed.");
82 return nullptr;
83 }
84
85 auto windowScenePattern = windowSceneFrameNode->GetPattern<SystemWindowScene>();
86 if (windowScenePattern == nullptr) {
87 TAG_LOGD(AceLogTag::ACE_KEYBOARD, "windowScenePattern is nullptr.");
88 return nullptr;
89 }
90
91 return windowScenePattern->GetSession();
92 }
93
IsWindowScene(const RefPtr<FrameNode> & focusedFrameNode)94 bool WindowSceneHelper::IsWindowScene(const RefPtr<FrameNode>& focusedFrameNode)
95 {
96 auto window2patternSession = GetCurSession(focusedFrameNode);
97 if (window2patternSession == nullptr) {
98 TAG_LOGD(AceLogTag::ACE_KEYBOARD, "The session between window and pattern is nullptr.");
99 return false;
100 }
101
102 return window2patternSession->GetSessionInfo().isSystem_;
103 }
104
GetFocusSystemWindowId(const RefPtr<FrameNode> & focusedFrameNode)105 int32_t WindowSceneHelper::GetFocusSystemWindowId(const RefPtr<FrameNode>& focusedFrameNode)
106 {
107 int32_t focusSystemWindowId = 0;
108 bool isWindowScene = IsWindowScene(focusedFrameNode);
109 sptr<Rosen::Session> window2patternSession = GetCurSession(focusedFrameNode);
110 if (window2patternSession == nullptr) {
111 TAG_LOGD(AceLogTag::ACE_KEYBOARD, "The session between window and pattern is nullptr.");
112 return focusSystemWindowId;
113 }
114 if (isWindowScene) {
115 focusSystemWindowId = static_cast<int32_t>(window2patternSession->GetPersistentId());
116 TAG_LOGI(AceLogTag::ACE_KEYBOARD, "Get systemWindowScene id:%{public}d successfully.", focusSystemWindowId);
117 }
118
119 return focusSystemWindowId;
120 }
121
GetWindowIdForWindowScene(const RefPtr<FrameNode> & windowSceneNode)122 int32_t WindowSceneHelper::GetWindowIdForWindowScene(const RefPtr<FrameNode>& windowSceneNode)
123 {
124 int32_t windowId = 0;
125 CHECK_NULL_RETURN(windowSceneNode, windowId);
126 if (windowSceneNode->GetTag() != V2::WINDOW_SCENE_ETS_TAG) {
127 return windowId;
128 }
129 auto windowScenePattern = windowSceneNode->GetPattern<SystemWindowScene>();
130 CHECK_NULL_RETURN(windowScenePattern, windowId);
131
132 auto window2patternSession = windowScenePattern->GetSession();
133 CHECK_NULL_RETURN(window2patternSession, windowId);
134
135 windowId = static_cast<int32_t>(window2patternSession->GetPersistentId());
136 return windowId;
137 }
138
IsFocusWindowSceneCloseKeyboard(const RefPtr<FrameNode> & focusedFrameNode)139 bool WindowSceneHelper::IsFocusWindowSceneCloseKeyboard(const RefPtr<FrameNode>& focusedFrameNode)
140 {
141 sptr<Rosen::Session> window2patternSession = GetCurSession(focusedFrameNode);
142 if (window2patternSession == nullptr) {
143 TAG_LOGW(AceLogTag::ACE_KEYBOARD, "The session between window and pattern is nullptr.");
144 return false;
145 }
146
147 return window2patternSession->GetSCBKeepKeyboardFlag();
148 }
149
IsWindowSceneCloseKeyboard(const RefPtr<FrameNode> & frameNode)150 void WindowSceneHelper::IsWindowSceneCloseKeyboard(const RefPtr<FrameNode>& frameNode)
151 {
152 #if defined (ENABLE_STANDARD_INPUT)
153 // If focus pattern does not need softkeyboard, close it, in windowScene.
154 auto curPattern = frameNode->GetPattern<NG::Pattern>();
155 CHECK_NULL_VOID(curPattern);
156 bool isNeedKeyBoard = curPattern->NeedSoftKeyboard();
157 auto saveKeyboard = IsFocusWindowSceneCloseKeyboard(frameNode);
158 TAG_LOGI(AceLogTag::ACE_KEYBOARD,
159 "FrameNode(%{public}s/%{public}d) notNeedSoftKeyboard, Keep:%{public}d, Need:%{public}d)",
160 frameNode->GetTag().c_str(), frameNode->GetId(), !saveKeyboard, !isNeedKeyBoard);
161 if (!saveKeyboard && !isNeedKeyBoard) {
162 auto inputMethod = MiscServices::InputMethodController::GetInstance();
163 if (inputMethod) {
164 inputMethod->RequestHideInput(true);
165 inputMethod->Close();
166 TAG_LOGI(AceLogTag::ACE_KEYBOARD, "scbSoftKeyboard Closes Successfully.");
167 }
168 }
169 #endif
170 }
171
IsCloseKeyboard(const RefPtr<FrameNode> & frameNode)172 void WindowSceneHelper::IsCloseKeyboard(const RefPtr<FrameNode>& frameNode)
173 {
174 #if defined (ENABLE_STANDARD_INPUT)
175 // If focus pattern does not need softkeyboard, close it, not in windowScene.
176 auto curPattern = frameNode->GetPattern<NG::Pattern>();
177 CHECK_NULL_VOID(curPattern);
178 bool isNeedKeyBoard = curPattern->NeedSoftKeyboard();
179 auto saveKeyboard = IsFocusWindowSceneCloseKeyboard(frameNode);
180 TAG_LOGI(AceLogTag::ACE_KEYBOARD,
181 "FrameNode(%{public}s/%{public}d) notNeed SoftKeyboard, Keep:%{public}d, Need:%{public}d)",
182 frameNode->GetTag().c_str(), frameNode->GetId(), !saveKeyboard, !isNeedKeyBoard);
183 if (!saveKeyboard && !isNeedKeyBoard) {
184 auto inputMethod = MiscServices::InputMethodController::GetInstance();
185 if (inputMethod) {
186 inputMethod->RequestHideInput(true);
187 inputMethod->Close();
188 TAG_LOGI(AceLogTag::ACE_KEYBOARD, "SoftKeyboard Closes Successfully.");
189 }
190 }
191 #endif
192 }
193
CaculatePoint(const RefPtr<FrameNode> & node,const std::shared_ptr<OHOS::MMI::PointerEvent> & pointerEvent)194 void CaculatePoint(const RefPtr<FrameNode>& node, const std::shared_ptr<OHOS::MMI::PointerEvent>& pointerEvent)
195 {
196 CHECK_NULL_VOID(node);
197 CHECK_NULL_VOID(pointerEvent);
198
199 auto pointerId = pointerEvent->GetPointerId();
200 auto renderContext = node->GetRenderContext();
201 CHECK_NULL_VOID(renderContext);
202 auto rect = renderContext->GetPaintRectWithoutTransform();
203 MMI::PointerEvent::PointerItem item;
204 if (pointerEvent->GetPointerItem(pointerId, item)) {
205 auto windowX = item.GetWindowX();
206 auto windowY = item.GetWindowY();
207 PointF tmp(item.GetWindowX() + rect.GetX(), item.GetWindowY() + rect.GetY());
208 renderContext->GetPointTransform(tmp);
209 item.SetWindowX(static_cast<int32_t>(std::round(tmp.GetX())));
210 item.SetWindowY(static_cast<int32_t>(std::round(tmp.GetY())));
211 if (pointerEvent->GetSourceType() == OHOS::MMI::PointerEvent::SOURCE_TYPE_TOUCHSCREEN) {
212 // CaculatePoint for double XY Position.
213 PointF tmpPos((NearZero(item.GetWindowXPos()) ? windowX : item.GetWindowXPos()) + rect.GetX(),
214 (NearZero(item.GetWindowYPos()) ? windowY : item.GetWindowYPos()) + rect.GetY());
215 renderContext->GetPointTransform(tmpPos);
216 item.SetWindowXPos(tmpPos.GetX());
217 item.SetWindowYPos(tmpPos.GetY());
218 }
219 pointerEvent->UpdatePointerItem(pointerId, item);
220 }
221 }
222
InjectPointerEvent(const RefPtr<FrameNode> & node,const std::shared_ptr<OHOS::MMI::PointerEvent> & pointerEvent)223 void WindowSceneHelper::InjectPointerEvent(
224 const RefPtr<FrameNode>& node, const std::shared_ptr<OHOS::MMI::PointerEvent>& pointerEvent)
225 {
226 if (!pointerEvent) {
227 TAG_LOGE(AceLogTag::ACE_INPUTTRACKING, "InjectPointerEvent pointerEvent is null return.");
228 return;
229 }
230 if (!node) {
231 MMI::InputManager::GetInstance()->MarkProcessed(
232 pointerEvent->GetId(), pointerEvent->GetActionTime(), pointerEvent->IsMarkEnabled());
233 TAG_LOGE(AceLogTag::ACE_INPUTTRACKING, "InjectPointerEvent eventId:%{public}d node is null return.",
234 pointerEvent->GetId());
235 return;
236 }
237
238 auto container = Container::Current();
239 if (!container) {
240 MMI::InputManager::GetInstance()->MarkProcessed(
241 pointerEvent->GetId(), pointerEvent->GetActionTime(), pointerEvent->IsMarkEnabled());
242 TAG_LOGE(AceLogTag::ACE_INPUTTRACKING, "InjectPointerEvent eventId:%{public}d container is null return.",
243 pointerEvent->GetId());
244 return;
245 }
246 CaculatePoint(node, pointerEvent);
247 auto aceView = AceType::DynamicCast<OHOS::Ace::Platform::AceViewOhos>(container->GetAceView());
248 if (!aceView) {
249 MMI::InputManager::GetInstance()->MarkProcessed(
250 pointerEvent->GetId(), pointerEvent->GetActionTime(), pointerEvent->IsMarkEnabled());
251 TAG_LOGE(AceLogTag::ACE_INPUTTRACKING, "InjectPointerEvent eventId:%{public}d aceView is null return.",
252 pointerEvent->GetId());
253 return;
254 }
255 OHOS::Ace::Platform::AceViewOhos::DispatchTouchEvent(aceView, pointerEvent, node, nullptr, true);
256 }
257
InjectPointerEventForActionCancel(const std::shared_ptr<OHOS::MMI::PointerEvent> & pointerEvent)258 void WindowSceneHelper::InjectPointerEventForActionCancel(const std::shared_ptr<OHOS::MMI::PointerEvent>& pointerEvent)
259 {
260 if (!pointerEvent) {
261 TAG_LOGE(AceLogTag::ACE_INPUTTRACKING, "InjectPointerEventForActionCancel pointerEvent is null return.");
262 return;
263 }
264
265 if (pointerEvent->GetPointerAction() != MMI::PointerEvent::POINTER_ACTION_CANCEL) {
266 MMI::InputManager::GetInstance()->MarkProcessed(
267 pointerEvent->GetId(), pointerEvent->GetActionTime(), pointerEvent->IsMarkEnabled());
268 TAG_LOGE(AceLogTag::ACE_INPUTTRACKING, "InjectPointerEventForActionCancel only handle cancel event.");
269 return;
270 }
271
272 auto container = Container::Current();
273 if (!container) {
274 MMI::InputManager::GetInstance()->MarkProcessed(
275 pointerEvent->GetId(), pointerEvent->GetActionTime(), pointerEvent->IsMarkEnabled());
276 TAG_LOGE(AceLogTag::ACE_INPUTTRACKING,
277 "InjectPointerEventForActionCancel eventId:%{public}d container is null return.", pointerEvent->GetId());
278 return;
279 }
280 auto aceView = AceType::DynamicCast<OHOS::Ace::Platform::AceViewOhos>(container->GetAceView());
281 if (!aceView) {
282 MMI::InputManager::GetInstance()->MarkProcessed(
283 pointerEvent->GetId(), pointerEvent->GetActionTime(), pointerEvent->IsMarkEnabled());
284 TAG_LOGE(AceLogTag::ACE_INPUTTRACKING,
285 "InjectPointerEventForActionCancel eventId:%{public}d aceView is null return.", pointerEvent->GetId());
286 return;
287 }
288 OHOS::Ace::Platform::AceViewOhos::DispatchTouchEvent(aceView, pointerEvent, nullptr, nullptr, true);
289 }
290
InjectKeyEvent(const std::shared_ptr<OHOS::MMI::KeyEvent> & keyEvent,bool isPreIme)291 bool WindowSceneHelper::InjectKeyEvent(const std::shared_ptr<OHOS::MMI::KeyEvent>& keyEvent, bool isPreIme)
292 {
293 CHECK_NULL_RETURN(keyEvent, false);
294 if (!SystemProperties::GetAceCommercialLogEnabled()) {
295 TAG_LOGI(AceLogTag::ACE_INPUTTRACKING,
296 SEC_PLD(, "KeyEvent Process to inject, eventInfo: id:%{public}d, "
297 "keyEvent info: keyCode is %{public}d, "
298 "keyAction is %{public}d, keyActionTime is %{public}" PRId64),
299 SEC_PARAM(keyEvent->GetId(), keyEvent->GetKeyCode(),
300 keyEvent->GetKeyAction(), keyEvent->GetActionTime()));
301 }
302
303 auto container = Container::Current();
304 CHECK_NULL_RETURN(container, false);
305 auto aceView = AceType::DynamicCast<OHOS::Ace::Platform::AceViewOhos>(container->GetAceView());
306 CHECK_NULL_RETURN(aceView, false);
307 return OHOS::Ace::Platform::AceViewOhos::DispatchKeyEvent(aceView, keyEvent, isPreIme);
308 }
309
IsWindowPattern(const RefPtr<FrameNode> & node)310 bool WindowSceneHelper::IsWindowPattern(const RefPtr<FrameNode>& node)
311 {
312 if (!node) {
313 return false;
314 }
315 return node->GetWindowPatternType() > static_cast<uint32_t>(WindowPatternType::SCREEN_SCENE);
316 }
317
HasWindowSession(const RefPtr<FrameNode> & node)318 bool WindowSceneHelper::HasWindowSession(const RefPtr<FrameNode>& node)
319 {
320 if (!node) {
321 return false;
322 }
323 return node->GetWindowPatternType() > static_cast<uint32_t>(WindowPatternType::TRANSFORM_SCENE);
324 }
325
IsTransformScene(uint32_t type)326 bool WindowSceneHelper::IsTransformScene(uint32_t type)
327 {
328 return type == static_cast<uint32_t>(WindowPatternType::TRANSFORM_SCENE);
329 }
330
IsAppOrSubScene(uint32_t type)331 bool WindowSceneHelper::IsAppOrSubScene(uint32_t type)
332 {
333 return type == static_cast<uint32_t>(WindowPatternType::WINDOW_SCENE);
334 }
335
IsSystemWindowScene(uint32_t type)336 bool WindowSceneHelper::IsSystemWindowScene(uint32_t type)
337 {
338 return type == static_cast<uint32_t>(WindowPatternType::SYSTEM_WINDOW_SCENE);
339 }
340
IsPanelScene(uint32_t type)341 bool WindowSceneHelper::IsPanelScene(uint32_t type)
342 {
343 return type == static_cast<uint32_t>(WindowPatternType::PANEL_SCENE);
344 }
345
IsScreenScene(uint32_t type)346 bool WindowSceneHelper::IsScreenScene(uint32_t type)
347 {
348 return type == static_cast<uint32_t>(WindowPatternType::SCREEN_SCENE);
349 }
350
IsNodeInKeyGuardWindow(const RefPtr<FrameNode> & node)351 bool WindowSceneHelper::IsNodeInKeyGuardWindow(const RefPtr<FrameNode>& node)
352 {
353 auto window2patternSession = GetCurSession(node);
354 if (window2patternSession == nullptr) {
355 TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "The session between window and pattern is nullptr.");
356 return false;
357 }
358
359 auto sessionWindowType = window2patternSession->GetWindowType();
360 TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "The windowtype of window scene session is %{public}d", sessionWindowType);
361 return sessionWindowType == Rosen::WindowType::WINDOW_TYPE_KEYGUARD;
362 }
363
GetRSUIContext(const RefPtr<FrameNode> & frameNode)364 std::shared_ptr<Rosen::RSUIContext> WindowSceneHelper::GetRSUIContext(const RefPtr<FrameNode>& frameNode)
365 {
366 CHECK_NULL_RETURN(frameNode, nullptr);
367 auto pipeline = frameNode->GetContext();
368 CHECK_NULL_RETURN(pipeline, nullptr);
369 auto window = pipeline->GetWindow();
370 CHECK_NULL_RETURN(window, nullptr);
371 auto rsUIDirector = window->GetRSUIDirector();
372 CHECK_NULL_RETURN(rsUIDirector, nullptr);
373 auto rsUIContext = rsUIDirector->GetRSUIContext();
374 TAG_LOGD(AceLogTag::ACE_WINDOW, "%{public}s", RSUIContextToStr(rsUIContext).c_str());
375 return rsUIContext;
376 }
377
GetRSTransaction(const sptr<Rosen::Session> & session)378 std::shared_ptr<Rosen::RSTransaction> WindowSceneHelper::GetRSTransaction(const sptr<Rosen::Session>& session)
379 {
380 auto rsUIContext = session->GetRSUIContext(__func__);
381 if (rsUIContext) {
382 if (auto rsSyncTransHandler = rsUIContext->GetSyncTransactionHandler()) {
383 return rsSyncTransHandler->GetRSTransaction();
384 }
385 }
386 TAG_LOGD(AceLogTag::ACE_WINDOW, "Use RSSyncTransactionController");
387 return Rosen::RSSyncTransactionController::GetInstance()->GetRSTransaction();
388 }
389
390
GetRSTransactionHandler(const RefPtr<FrameNode> & frameNode)391 std::shared_ptr<Rosen::RSTransactionHandler> WindowSceneHelper::GetRSTransactionHandler(
392 const RefPtr<FrameNode>& frameNode)
393 {
394 auto rsUIContext = GetRSUIContext(frameNode);
395 CHECK_NULL_RETURN(rsUIContext, nullptr);
396 return rsUIContext->GetRSTransaction();
397 }
398
FlushImplicitTransaction(const RefPtr<FrameNode> & frameNode)399 void WindowSceneHelper::FlushImplicitTransaction(const RefPtr<FrameNode>& frameNode)
400 {
401 if (auto transactionHandler = GetRSTransactionHandler(frameNode)) {
402 transactionHandler->FlushImplicitTransaction();
403 } else {
404 TAG_LOGD(AceLogTag::ACE_WINDOW, "RSTransactionHandler is null, use RSTransactionProxy");
405 Rosen::RSTransactionProxy::GetInstance()->FlushImplicitTransaction();
406 }
407 }
408
RSNodeToStr(const std::shared_ptr<Rosen::RSNode> & rsNode)409 std::string WindowSceneHelper::RSNodeToStr(const std::shared_ptr<Rosen::RSNode>& rsNode)
410 {
411 if (!rsNode) {
412 return "RSNode is null";
413 }
414 std::ostringstream oss;
415 oss << "RSNode [id: " << rsNode->GetId() << "], "
416 << RSUIContextToStr(rsNode->GetRSUIContext());
417 return oss.str();
418 }
419
RSUIContextToStr(const std::shared_ptr<Rosen::RSUIContext> & rsUIContext)420 std::string WindowSceneHelper::RSUIContextToStr(const std::shared_ptr<Rosen::RSUIContext>& rsUIContext)
421 {
422 if (!rsUIContext) {
423 return "RSUIContext is null";
424 }
425 std::ostringstream oss;
426 oss << "RSUIContext [token: " << rsUIContext->GetToken()
427 << ", tid: "
428 << static_cast<int32_t>(rsUIContext->GetToken() >> 32) // 32: tid's offset position in the token
429 << "]";
430 return oss.str();
431 }
432 } // namespace OHOS::Ace::NG
433