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_pattern.h"
17
18 #include "session_manager/include/scene_session_manager.h"
19 #include "ui/rs_surface_node.h"
20
21 #include "adapter/ohos/entrance/mmi_event_convertor.h"
22 #include "base/utils/system_properties.h"
23 #include "core/components_ng/image_provider/image_utils.h"
24 #include "core/components_ng/pattern/image/image_pattern.h"
25 #include "core/components_ng/pattern/window_scene/scene/window_event_process.h"
26 #include "core/components_ng/render/adapter/rosen_render_context.h"
27 #include "core/components_v2/inspector/inspector_constants.h"
28
29 namespace OHOS::Ace::NG {
30 namespace {
31 constexpr uint32_t COLOR_BLACK = 0xff000000;
32 constexpr uint32_t COLOR_WHITE = 0xffffffff;
33 } // namespace
34
35 class LifecycleListener : public Rosen::ILifecycleListener {
36 public:
LifecycleListener(const WeakPtr<WindowPattern> & windowPattern)37 explicit LifecycleListener(const WeakPtr<WindowPattern>& windowPattern) : windowPattern_(windowPattern) {}
38 virtual ~LifecycleListener() = default;
39
OnActivation()40 void OnActivation() override
41 {
42 auto windowPattern = windowPattern_.Upgrade();
43 CHECK_NULL_VOID(windowPattern);
44 windowPattern->OnActivation();
45 }
46
OnConnect()47 void OnConnect() override
48 {
49 auto windowPattern = windowPattern_.Upgrade();
50 CHECK_NULL_VOID(windowPattern);
51 windowPattern->OnConnect();
52 }
53
OnForeground()54 void OnForeground() override
55 {
56 auto windowPattern = windowPattern_.Upgrade();
57 CHECK_NULL_VOID(windowPattern);
58 windowPattern->OnForeground();
59 }
60
OnBackground()61 void OnBackground() override
62 {
63 auto windowPattern = windowPattern_.Upgrade();
64 CHECK_NULL_VOID(windowPattern);
65 windowPattern->OnBackground();
66 }
67
OnDisconnect()68 void OnDisconnect() override
69 {
70 auto windowPattern = windowPattern_.Upgrade();
71 CHECK_NULL_VOID(windowPattern);
72 windowPattern->OnDisconnect();
73 }
74
OnExtensionDied()75 void OnExtensionDied() override {}
76
OnAccessibilityEvent(const Accessibility::AccessibilityEventInfo & info,int64_t uiExtensionIdLevelVec)77 void OnAccessibilityEvent(const Accessibility::AccessibilityEventInfo& info,
78 int64_t uiExtensionIdLevelVec) override {};
79
80 private:
81 WeakPtr<WindowPattern> windowPattern_;
82 };
83
RegisterLifecycleListener()84 void WindowPattern::RegisterLifecycleListener()
85 {
86 CHECK_NULL_VOID(session_);
87 lifecycleListener_ = std::make_shared<LifecycleListener>(WeakClaim(this));
88 session_->RegisterLifecycleListener(lifecycleListener_);
89 }
90
UnregisterLifecycleListener()91 void WindowPattern::UnregisterLifecycleListener()
92 {
93 CHECK_NULL_VOID(session_);
94 session_->UnregisterLifecycleListener(lifecycleListener_);
95 }
96
IsMainWindow() const97 bool WindowPattern::IsMainWindow() const
98 {
99 CHECK_NULL_RETURN(session_, false);
100 return session_->GetWindowType() == Rosen::WindowType::WINDOW_TYPE_APP_MAIN_WINDOW;
101 }
102
OnAttachToFrameNode()103 void WindowPattern::OnAttachToFrameNode()
104 {
105 CreateContentNode();
106 auto host = GetHost();
107 CHECK_NULL_VOID(host);
108 auto state = session_->GetSessionState();
109 TAG_LOGI(AceLogTag::ACE_WINDOW_SCENE, "[WMSMain] id: %{public}d, state: %{public}u, name: %{public}s",
110 session_->GetPersistentId(), state, session_->GetSessionInfo().bundleName_.c_str());
111 if (state == Rosen::SessionState::STATE_DISCONNECT) {
112 if (!HasStartingPage()) {
113 return;
114 }
115 if (session_->GetShowRecent() && session_->GetScenePersistence() &&
116 (session_->GetScenePersistence()->IsSnapshotExisted() ||
117 session_->GetScenePersistence()->IsSavingSnapshot())) {
118 CreateSnapshotNode();
119 host->AddChild(snapshotNode_);
120 return;
121 }
122 CreateStartingNode();
123 host->AddChild(startingNode_);
124 return;
125 }
126
127 if (state == Rosen::SessionState::STATE_BACKGROUND && session_->GetScenePersistence() &&
128 (session_->GetScenePersistence()->IsSnapshotExisted() ||
129 session_->GetScenePersistence()->IsSavingSnapshot())) {
130 CreateSnapshotNode();
131 host->AddChild(snapshotNode_);
132 return;
133 }
134
135 if (session_->GetShowRecent()) {
136 CreateStartingNode();
137 host->AddChild(startingNode_);
138 return;
139 }
140
141 host->AddChild(contentNode_);
142 if (!session_->GetBufferAvailable()) {
143 CreateStartingNode();
144 host->AddChild(startingNode_);
145 auto surfaceNode = session_->GetSurfaceNode();
146 if (surfaceNode) {
147 surfaceNode->SetBufferAvailableCallback(callback_);
148 }
149 }
150 }
151
CreateContentNode()152 void WindowPattern::CreateContentNode()
153 {
154 contentNode_ = FrameNode::CreateFrameNode(
155 V2::WINDOW_SCENE_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<Pattern>());
156 contentNode_->GetLayoutProperty()->UpdateMeasureType(MeasureType::MATCH_PARENT);
157 contentNode_->SetHitTestMode(HitTestMode::HTMNONE);
158 CHECK_NULL_VOID(session_);
159 auto surfaceNode = session_->GetSurfaceNode();
160 if (surfaceNode) {
161 auto context = AceType::DynamicCast<NG::RosenRenderContext>(contentNode_->GetRenderContext());
162 CHECK_NULL_VOID(context);
163 context->SetRSNode(surfaceNode);
164 }
165 }
166
CreateStartingNode()167 void WindowPattern::CreateStartingNode()
168 {
169 startingNode_ = FrameNode::CreateFrameNode(
170 V2::IMAGE_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<ImagePattern>());
171 auto imageLayoutProperty = startingNode_->GetLayoutProperty<ImageLayoutProperty>();
172 imageLayoutProperty->UpdateMeasureType(MeasureType::MATCH_PARENT);
173 startingNode_->SetHitTestMode(HitTestMode::HTMNONE);
174
175 std::string startupPagePath;
176 auto backgroundColor = SystemProperties::GetColorMode() == ColorMode::DARK ? COLOR_BLACK : COLOR_WHITE;
177 const auto& sessionInfo = session_->GetSessionInfo();
178 Rosen::SceneSessionManager::GetInstance().GetStartupPage(sessionInfo, startupPagePath, backgroundColor);
179
180 startingNode_->GetRenderContext()->UpdateBackgroundColor(Color(backgroundColor));
181 imageLayoutProperty->UpdateImageSourceInfo(
182 ImageSourceInfo(startupPagePath, sessionInfo.bundleName_, sessionInfo.moduleName_));
183 imageLayoutProperty->UpdateImageFit(ImageFit::NONE);
184 startingNode_->MarkModifyDone();
185 }
186
CreateSnapshotNode(std::optional<std::shared_ptr<Media::PixelMap>> snapshot)187 void WindowPattern::CreateSnapshotNode(std::optional<std::shared_ptr<Media::PixelMap>> snapshot)
188 {
189 session_->SetNeedSnapshot(false);
190 snapshotNode_ = FrameNode::CreateFrameNode(
191 V2::IMAGE_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<ImagePattern>());
192 auto imageLayoutProperty = snapshotNode_->GetLayoutProperty<ImageLayoutProperty>();
193 imageLayoutProperty->UpdateMeasureType(MeasureType::MATCH_PARENT);
194 auto imagePaintProperty = snapshotNode_->GetPaintProperty<ImageRenderProperty>();
195 imagePaintProperty->UpdateImageInterpolation(ImageInterpolation::MEDIUM);
196 snapshotNode_->SetHitTestMode(HitTestMode::HTMNONE);
197
198 auto backgroundColor = SystemProperties::GetColorMode() == ColorMode::DARK ? COLOR_BLACK : COLOR_WHITE;
199 if (snapshot) {
200 auto pixelMap = PixelMap::CreatePixelMap(&snapshot.value());
201 imageLayoutProperty->UpdateImageSourceInfo(ImageSourceInfo(pixelMap));
202 } else {
203 snapshotNode_->GetRenderContext()->UpdateBackgroundColor(Color(backgroundColor));
204 ImageSourceInfo sourceInfo;
205 if (session_->GetScenePersistence()->IsSavingSnapshot()) {
206 auto snapshotPixelMap = session_->GetSnapshotPixelMap();
207 CHECK_NULL_VOID(snapshotPixelMap);
208 auto pixelMap = PixelMap::CreatePixelMap(&snapshotPixelMap);
209 sourceInfo = ImageSourceInfo(pixelMap);
210 } else {
211 sourceInfo = ImageSourceInfo("file://" + session_->GetScenePersistence()->GetSnapshotFilePathFromAce());
212 }
213
214 imageLayoutProperty->UpdateImageSourceInfo(sourceInfo);
215 auto pipelineContext = PipelineContext::GetCurrentContext();
216 CHECK_NULL_VOID(pipelineContext);
217 auto imageCache = pipelineContext->GetImageCache();
218 CHECK_NULL_VOID(imageCache);
219 auto snapshotSize = session_->GetScenePersistence()->GetSnapshotSize();
220 imageCache->ClearCacheImage(
221 ImageUtils::GenerateImageKey(sourceInfo, SizeF(snapshotSize.first, snapshotSize.second)));
222 imageCache->ClearCacheImage(
223 ImageUtils::GenerateImageKey(sourceInfo, SizeF(snapshotSize.second, snapshotSize.first)));
224 imageCache->ClearCacheImage(sourceInfo.GetKey());
225 }
226 imageLayoutProperty->UpdateImageFit(ImageFit::FILL);
227 snapshotNode_->MarkModifyDone();
228 }
229
DispatchPointerEvent(const std::shared_ptr<MMI::PointerEvent> & pointerEvent)230 void WindowPattern::DispatchPointerEvent(const std::shared_ptr<MMI::PointerEvent>& pointerEvent)
231 {
232 CHECK_NULL_VOID(session_);
233 CHECK_NULL_VOID(pointerEvent);
234 session_->TransferPointerEvent(pointerEvent);
235 if (pointerEvent->GetPointerAction() >= MMI::PointerEvent::POINTER_ACTION_PULL_DOWN &&
236 pointerEvent->GetPointerAction() <= MMI::PointerEvent::POINTER_ACTION_PULL_UP) {
237 auto pipeline = PipelineContext::GetCurrentContext();
238 if (pipeline) {
239 auto manager = pipeline->GetDragDropManager();
240 CHECK_NULL_VOID(manager);
241 manager->SetIsWindowConsumed(true);
242 }
243 }
244 }
245
DispatchKeyEvent(const std::shared_ptr<MMI::KeyEvent> & keyEvent)246 void WindowPattern::DispatchKeyEvent(const std::shared_ptr<MMI::KeyEvent>& keyEvent)
247 {
248 CHECK_NULL_VOID(session_);
249 CHECK_NULL_VOID(keyEvent);
250 session_->TransferKeyEvent(keyEvent);
251 }
252
DispatchKeyEventForConsumed(const std::shared_ptr<MMI::KeyEvent> & keyEvent,bool & isConsumed)253 void WindowPattern::DispatchKeyEventForConsumed(const std::shared_ptr<MMI::KeyEvent>& keyEvent, bool& isConsumed)
254 {
255 CHECK_NULL_VOID(session_);
256 session_->TransferKeyEventForConsumed(keyEvent, isConsumed);
257 }
258
DisPatchFocusActiveEvent(bool isFocusActive)259 void WindowPattern::DisPatchFocusActiveEvent(bool isFocusActive)
260 {
261 CHECK_NULL_VOID(session_);
262 session_->TransferFocusActiveEvent(isFocusActive);
263 }
264
InitTouchEvent(const RefPtr<GestureEventHub> & gestureHub)265 void WindowPattern::InitTouchEvent(const RefPtr<GestureEventHub>& gestureHub)
266 {
267 if (touchEvent_) {
268 return;
269 }
270 auto callback = [weak = WeakClaim(this)](const TouchEventInfo& info) {
271 auto pattern = weak.Upgrade();
272 if (pattern) {
273 pattern->HandleTouchEvent(info);
274 }
275 };
276 if (touchEvent_) {
277 gestureHub->RemoveTouchEvent(touchEvent_);
278 }
279 touchEvent_ = MakeRefPtr<TouchEventImpl>(std::move(callback));
280 gestureHub->AddTouchEvent(touchEvent_);
281 }
282
InitMouseEvent(const RefPtr<InputEventHub> & inputHub)283 void WindowPattern::InitMouseEvent(const RefPtr<InputEventHub>& inputHub)
284 {
285 if (mouseEvent_) {
286 return;
287 }
288 auto callback = [weak = WeakClaim(this)](MouseInfo& info) {
289 auto pattern = weak.Upgrade();
290 if (pattern) {
291 pattern->HandleMouseEvent(info);
292 }
293 };
294 if (mouseEvent_) {
295 inputHub->RemoveOnMouseEvent(mouseEvent_);
296 }
297 mouseEvent_ = MakeRefPtr<InputEvent>(std::move(callback));
298 inputHub->AddOnMouseEvent(mouseEvent_);
299 }
300
CalculateTranslateDegree(int32_t hostId)301 int32_t WindowPattern::CalculateTranslateDegree(int32_t hostId)
302 {
303 auto& translateCfg = NGGestureRecognizer::GetGlobalTransCfg();
304 auto& translateIds = NGGestureRecognizer::GetGlobalTransIds();
305 auto translateIter = translateIds.find(hostId);
306 int32_t udegree = 0;
307 if (translateIter == translateIds.end()) {
308 return udegree;
309 }
310 while (translateIter != translateIds.end()) {
311 int32_t translateId = translateIter->second.parentId;
312 auto translateCfgIter = translateCfg.find(translateId);
313 if (translateCfgIter != translateCfg.end() && translateCfgIter->second.degree != 0) {
314 udegree = static_cast<int32_t>(translateCfgIter->second.degree);
315 break;
316 }
317 translateIter = translateIds.find(translateId);
318 }
319 udegree = udegree % 360;
320 return udegree < 0 ? udegree + 360 : udegree;
321 }
322
HandleTouchEvent(const TouchEventInfo & info)323 void WindowPattern::HandleTouchEvent(const TouchEventInfo& info)
324 {
325 const auto pointerEvent = info.GetPointerEvent();
326 CHECK_NULL_VOID(pointerEvent);
327 if (IsFilterTouchEvent(pointerEvent)) {
328 return;
329 }
330 auto host = GetHost();
331 CHECK_NULL_VOID(host);
332 auto selfGlobalOffset = host->GetTransformRelativeOffset();
333 auto scale = host->GetTransformScale();
334 auto udegree = WindowPattern::CalculateTranslateDegree(host->GetId());
335 Platform::CalculateWindowCoordinate(selfGlobalOffset, pointerEvent, scale, udegree);
336 SetWindowSceneConsumed(pointerEvent->GetPointerAction());
337 DispatchPointerEvent(pointerEvent);
338 if (SystemProperties::GetDebugEnabled()) {
339 int32_t pointerId = pointerEvent->GetPointerId();
340 MMI::PointerEvent::PointerItem item;
341 pointerEvent->GetPointerItem(pointerId, item);
342 }
343 }
344
FilterInvalidPointerItem(const std::shared_ptr<MMI::PointerEvent> & pointerEvent)345 void WindowPattern::FilterInvalidPointerItem(const std::shared_ptr<MMI::PointerEvent>& pointerEvent)
346 {
347 auto host = GetHost();
348 CHECK_NULL_VOID(host);
349 auto ids = pointerEvent->GetPointerIds();
350 if (ids.size() <= 1) {
351 return;
352 }
353 for (auto&& id : ids) {
354 MMI::PointerEvent::PointerItem item;
355 bool ret = pointerEvent->GetPointerItem(id, item);
356 if (!ret) {
357 continue;
358 }
359 const NG::PointF point { static_cast<float>(item.GetDisplayX()), static_cast<float>(item.GetDisplayY()) };
360 if (host->IsOutOfTouchTestRegion(point, MMI::PointerEvent::SOURCE_TYPE_TOUCHSCREEN)) {
361 pointerEvent->RemovePointerItem(id);
362 }
363 }
364 }
365
IsFilterTouchEvent(const std::shared_ptr<MMI::PointerEvent> & pointerEvent)366 bool WindowPattern::IsFilterTouchEvent(const std::shared_ptr<MMI::PointerEvent>& pointerEvent)
367 {
368 return (pointerEvent->GetSourceType() == MMI::PointerEvent::SOURCE_TYPE_MOUSE &&
369 (pointerEvent->GetPointerAction() == MMI::PointerEvent::POINTER_ACTION_BUTTON_DOWN ||
370 pointerEvent->GetButtonId() == MMI::PointerEvent::BUTTON_NONE)) ||
371 (pointerEvent->GetPointerAction() == MMI::PointerEvent::POINTER_ACTION_PULL_MOVE ||
372 pointerEvent->GetPointerAction() == MMI::PointerEvent::POINTER_ACTION_PULL_UP);
373 }
374
HandleMouseEvent(const MouseInfo & info)375 void WindowPattern::HandleMouseEvent(const MouseInfo& info)
376 {
377 const auto pointerEvent = info.GetPointerEvent();
378 CHECK_NULL_VOID(pointerEvent);
379 if (IsFilterMouseEvent(pointerEvent)) {
380 return;
381 }
382 auto host = GetHost();
383 CHECK_NULL_VOID(host);
384 auto selfGlobalOffset = host->GetTransformRelativeOffset();
385 auto scale = host->GetTransformScale();
386 Platform::CalculateWindowCoordinate(selfGlobalOffset, pointerEvent, scale);
387 DelayedSingleton<WindowEventProcess>::GetInstance()->ProcessWindowMouseEvent(
388 host->GetId(), session_, pointerEvent);
389 int32_t action = pointerEvent->GetPointerAction();
390 if (action == MMI::PointerEvent::POINTER_ACTION_PULL_MOVE) {
391 DelayedSingleton<WindowEventProcess>::GetInstance()->ProcessWindowDragEvent(
392 host->GetId(), session_, pointerEvent);
393 }
394 if (action == MMI::PointerEvent::POINTER_ACTION_PULL_UP) {
395 DelayedSingleton<WindowEventProcess>::GetInstance()->CleanWindowDragEvent();
396 }
397 SetWindowSceneConsumed(action);
398 DispatchPointerEvent(pointerEvent);
399 }
400
GetSession()401 sptr<Rosen::Session> WindowPattern::GetSession()
402 {
403 return session_;
404 }
405
IsFilterMouseEvent(const std::shared_ptr<MMI::PointerEvent> & pointerEvent)406 bool WindowPattern::IsFilterMouseEvent(const std::shared_ptr<MMI::PointerEvent>& pointerEvent)
407 {
408 int32_t pointerAction = pointerEvent->GetPointerAction();
409 if ((pointerEvent->GetSourceType() == MMI::PointerEvent::SOURCE_TYPE_TOUCHSCREEN) &&
410 (pointerAction != MMI::PointerEvent::POINTER_ACTION_PULL_MOVE) &&
411 (pointerAction != MMI::PointerEvent::POINTER_ACTION_PULL_UP)) {
412 return true;
413 }
414 return pointerEvent->GetButtonId() == MMI::PointerEvent::MOUSE_BUTTON_LEFT &&
415 (pointerAction == MMI::PointerEvent::POINTER_ACTION_MOVE ||
416 pointerAction == MMI::PointerEvent::POINTER_ACTION_BUTTON_UP);
417 }
418
OnModifyDone()419 void WindowPattern::OnModifyDone()
420 {
421 Pattern::OnModifyDone();
422 }
423
TransferFocusState(bool focusState)424 void WindowPattern::TransferFocusState(bool focusState)
425 {
426 CHECK_NULL_VOID(session_);
427 session_->TransferFocusStateEvent(focusState);
428 }
429
GetHotAreas()430 std::vector<Rosen::Rect> WindowPattern::GetHotAreas()
431 {
432 if (session_ == nullptr) {
433 return std::vector<Rosen::Rect>();
434 }
435 return session_->GetTouchHotAreas();
436 }
437
SetWindowSceneConsumed(int32_t action)438 void WindowPattern::SetWindowSceneConsumed(int32_t action)
439 {
440 auto pipeline = PipelineContext::GetCurrentContext();
441 if (pipeline) {
442 if (action == MMI::PointerEvent::POINTER_ACTION_DOWN ||
443 action == MMI::PointerEvent::POINTER_ACTION_BUTTON_DOWN) {
444 pipeline->SetWindowSceneConsumed(true);
445 }
446 if (action == MMI::PointerEvent::POINTER_ACTION_UP ||
447 action == MMI::PointerEvent::POINTER_ACTION_BUTTON_UP ||
448 action == MMI::PointerEvent::POINTER_ACTION_PULL_UP) {
449 pipeline->SetWindowSceneConsumed(false);
450 }
451 }
452 }
453 } // namespace OHOS::Ace::NG
454