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/system_window_scene.h"
17
18 #include "ui/rs_canvas_node.h"
19 #include "ui/rs_surface_node.h"
20
21 #include "adapter/ohos/entrance/mmi_event_convertor.h"
22 #include "core/components_ng/pattern/window_scene/helper/window_scene_helper.h"
23 #include "core/components_ng/pattern/window_scene/scene/window_event_process.h"
24 #include "core/components_ng/render/adapter/rosen_render_context.h"
25 #include "core/pipeline_ng/pipeline_context.h"
26
27 namespace OHOS::Ace::NG {
SystemWindowScene(const sptr<Rosen::Session> & session)28 SystemWindowScene::SystemWindowScene(const sptr<Rosen::Session>& session) : session_(session)
29 {
30 boundsChangedCallback_ = [weakThis = WeakClaim(this)](const Rosen::Vector4f& bounds) {
31 auto self = weakThis.Upgrade();
32 CHECK_NULL_VOID(self);
33 self->OnBoundsChanged(bounds);
34 };
35 }
36
GetSession()37 sptr<Rosen::Session> SystemWindowScene::GetSession()
38 {
39 return session_;
40 }
41
OnBoundsChanged(const Rosen::Vector4f & bounds)42 void SystemWindowScene::OnBoundsChanged(const Rosen::Vector4f& bounds)
43 {
44 Rosen::WSRect windowRect {
45 .posX_ = std::round(bounds.x_),
46 .posY_ = std::round(bounds.y_),
47 .width_ = std::round(bounds.z_),
48 .height_ = std::round(bounds.w_),
49 };
50
51 CHECK_NULL_VOID(session_);
52 Rosen::WSRectF originBounds = {
53 .posX_ = bounds.x_,
54 .posY_ = bounds.y_,
55 .width_ = bounds.z_,
56 .height_ = bounds.w_,
57 };
58 session_->SetBounds(originBounds);
59 windowRect.posX_ = std::round(bounds.x_ + session_->GetOffsetX());
60 windowRect.posY_ = std::round(bounds.y_ + session_->GetOffsetY());
61 session_->UpdateRect(windowRect, Rosen::SizeChangeReason::UNDEFINED);
62 }
63
OnAttachToFrameNode()64 void SystemWindowScene::OnAttachToFrameNode()
65 {
66 CHECK_NULL_VOID(session_);
67 auto surfaceNode = session_->GetSurfaceNode();
68 CHECK_NULL_VOID(surfaceNode);
69
70 auto host = GetHost();
71 CHECK_NULL_VOID(host);
72 host->SetWindowBoundary();
73 session_->SetUINodeId(host->GetAccessibilityId());
74 auto context = AceType::DynamicCast<NG::RosenRenderContext>(host->GetRenderContext());
75 CHECK_NULL_VOID(context);
76
77 if (!session_->IsSystemInput()) {
78 context->SetRSNode(surfaceNode);
79 surfaceNode->SetBoundsChangedCallback(boundsChangedCallback_);
80 } else {
81 auto rsNode = Rosen::RSCanvasNode::Create();
82 context->SetRSNode(rsNode);
83 rsNode->SetBoundsChangedCallback(boundsChangedCallback_);
84 }
85
86 auto mouseEventHub = host->GetOrCreateInputEventHub();
87 auto mouseCallback = [weakThis = WeakClaim(this), weakSession = wptr(session_)](MouseInfo& info) {
88 auto self = weakThis.Upgrade();
89 CHECK_NULL_VOID(self);
90 auto session = weakSession.promote();
91 CHECK_NULL_VOID(session);
92 const auto pointerEvent = info.GetPointerEvent();
93 CHECK_NULL_VOID(pointerEvent);
94 auto host = self->GetHost();
95 if (host != nullptr) {
96 DelayedSingleton<WindowEventProcess>::GetInstance()->ProcessWindowMouseEvent(
97 host->GetId(), session, pointerEvent);
98 DelayedSingleton<WindowEventProcess>::GetInstance()->ProcessWindowDragEvent(
99 host->GetId(), session, pointerEvent);
100 }
101 session->TransferPointerEvent(pointerEvent);
102 };
103 mouseEventHub->SetMouseEvent(std::move(mouseCallback));
104
105 RegisterFocusCallback();
106 RegisterEventCallback();
107 RegisterResponseRegionCallback();
108 }
109
RegisterEventCallback()110 void SystemWindowScene::RegisterEventCallback()
111 {
112 CHECK_NULL_VOID(session_);
113 auto pointerEventCallback =
114 [weakThis = WeakClaim(this), instanceId = instanceId_](std::shared_ptr<MMI::PointerEvent> PointerEvent) {
115 ContainerScope Scope(instanceId);
116 auto pipelineContext = PipelineContext::GetCurrentContext();
117 CHECK_NULL_VOID(pipelineContext);
118 pipelineContext->PostAsyncEvent([weakThis, PointerEvent]() {
119 auto self = weakThis.Upgrade();
120 auto host = self->GetHost();
121 CHECK_NULL_VOID(host);
122 WindowSceneHelper::InjectPointerEvent(host, PointerEvent);
123 },
124 TaskExecutor::TaskType::UI);
125 };
126 session_->SetNotifySystemSessionPointerEventFunc(std::move(pointerEventCallback));
127
128 auto keyEventCallback = [instanceId = instanceId_](std::shared_ptr<MMI::KeyEvent> KeyEvent) {
129 ContainerScope Scope(instanceId);
130 auto pipelineContext = PipelineContext::GetCurrentContext();
131 CHECK_NULL_VOID(pipelineContext);
132 pipelineContext->PostAsyncEvent([KeyEvent]() {
133 WindowSceneHelper::InjectKeyEvent(KeyEvent);
134 },
135 TaskExecutor::TaskType::UI);
136 };
137 session_->SetNotifySystemSessionKeyEventFunc(std::move(keyEventCallback));
138 }
139
RegisterResponseRegionCallback()140 void SystemWindowScene::RegisterResponseRegionCallback()
141 {
142 auto host = GetHost();
143 CHECK_NULL_VOID(host);
144 auto gestureHub = host->GetOrCreateGestureEventHub();
145 CHECK_NULL_VOID(gestureHub);
146
147 auto touchCallback = [weakSession = wptr(session_)](TouchEventInfo& info) {
148 auto session = weakSession.promote();
149 CHECK_NULL_VOID(session);
150 const auto pointerEvent = info.GetPointerEvent();
151 CHECK_NULL_VOID(pointerEvent);
152 session->TransferPointerEvent(pointerEvent);
153 };
154 gestureHub->SetTouchEvent(std::move(touchCallback));
155
156 auto responseRegionCallback = [weakThis = WeakClaim(this), weakSession = wptr(session_)](
157 const std::vector<DimensionRect>& responseRegion) {
158 auto self = weakThis.Upgrade();
159 CHECK_NULL_VOID(self);
160 auto session = weakSession.promote();
161 CHECK_NULL_VOID(session);
162 std::vector<Rosen::Rect> hotAreas;
163 for (auto& rect : responseRegion) {
164 Rosen::Rect windowRect {
165 .posX_ = std::round(rect.GetOffset().GetX().Value()),
166 .posY_ = std::round(rect.GetOffset().GetY().Value()),
167 .width_ = std::round(rect.GetWidth().Value()),
168 .height_ = std::round(rect.GetHeight().Value()),
169 };
170 hotAreas.push_back(windowRect);
171 }
172 session->SetTouchHotAreas(hotAreas);
173 };
174 gestureHub->SetResponseRegionFunc(responseRegionCallback);
175 }
176
RegisterFocusCallback()177 void SystemWindowScene::RegisterFocusCallback()
178 {
179 CHECK_NULL_VOID(session_);
180
181 auto requestFocusCallback = [weakThis = WeakClaim(this), instanceId = instanceId_]() {
182 ContainerScope scope(instanceId);
183 auto pipelineContext = PipelineContext::GetCurrentContext();
184 CHECK_NULL_VOID(pipelineContext);
185 pipelineContext->PostAsyncEvent([weakThis]() {
186 auto self = weakThis.Upgrade();
187 CHECK_NULL_VOID(self);
188 auto host = self->GetHost();
189 CHECK_NULL_VOID(host);
190 auto focusHub = host->GetFocusHub();
191 CHECK_NULL_VOID(focusHub);
192 focusHub->SetParentFocusable(true);
193 focusHub->RequestFocusWithDefaultFocusFirstly();
194 },
195 TaskExecutor::TaskType::UI);
196 };
197 session_->SetNotifyUIRequestFocusFunc(requestFocusCallback);
198
199 auto lostFocusCallback = [weakThis = WeakClaim(this), instanceId = instanceId_]() {
200 ContainerScope scope(instanceId);
201 auto pipelineContext = PipelineContext::GetCurrentContext();
202 CHECK_NULL_VOID(pipelineContext);
203 pipelineContext->PostAsyncEvent([weakThis]() {
204 auto self = weakThis.Upgrade();
205 CHECK_NULL_VOID(self);
206 auto host = self->GetHost();
207 CHECK_NULL_VOID(host);
208 auto focusHub = host->GetFocusHub();
209 CHECK_NULL_VOID(focusHub);
210 focusHub->SetParentFocusable(false);
211 },
212 TaskExecutor::TaskType::UI);
213 };
214 session_->SetNotifyUILostFocusFunc(lostFocusCallback);
215 }
216 } // namespace OHOS::Ace::NG
217