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