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 #include "form_renderer_dispatcher_impl.h"
16 #include <transaction/rs_interfaces.h>
17 #include <transaction/rs_transaction.h>
18 #include "base/log/ace_trace.h"
19 
20 #include <condition_variable>
21 #include <mutex>
22 
23 #include "form_renderer.h"
24 #include "form_renderer_hilog.h"
25 #include "wm_common.h"
26 #include "core/components_ng/gestures/gesture_group.h"
27 
28 namespace OHOS {
29 namespace Ace {
30 constexpr int32_t PROCESS_WAIT_TIME = 20;
31 constexpr float DOUBLE = 2.0;
32 constexpr int32_t DEFAULT_FORM_ROTATION_ANIM_DURATION = 600;
FormRendererDispatcherImpl(const std::shared_ptr<UIContent> uiContent,const std::shared_ptr<FormRenderer> formRenderer,std::weak_ptr<OHOS::AppExecFwk::EventHandler> eventHandler)33 FormRendererDispatcherImpl::FormRendererDispatcherImpl(
34     const std::shared_ptr<UIContent> uiContent,
35     const std::shared_ptr<FormRenderer> formRenderer,
36     std::weak_ptr<OHOS::AppExecFwk::EventHandler> eventHandler)
37     : uiContent_(uiContent), formRenderer_(formRenderer), eventHandler_(eventHandler)
38 {}
39 
40 std::recursive_mutex FormRendererDispatcherImpl::globalLock_;
41 
DispatchPointerEvent(const std::shared_ptr<OHOS::MMI::PointerEvent> & pointerEvent,SerializedGesture & serializedGesture)42 void FormRendererDispatcherImpl::DispatchPointerEvent(
43     const std::shared_ptr<OHOS::MMI::PointerEvent>& pointerEvent,
44     SerializedGesture& serializedGesture)
45 {
46     auto handler = eventHandler_.lock();
47     if (!handler) {
48         HILOG_ERROR("eventHandler is nullptr");
49         return;
50     }
51     serializedGesture.data.clear();
52 
53     if (pointerEvent && pointerEvent->GetPointerAction() == OHOS::MMI::PointerEvent::POINTER_ACTION_DOWN) {
54         HILOG_INFO("renderer receive down event");
55         auto uiContent = uiContent_.lock();
56         if (!uiContent) {
57             HILOG_ERROR("uiContent is nullptr");
58             return;
59         }
60 
61         struct FormSerializedResultData {
62             std::mutex mtx;
63             std::condition_variable cv;
64         };
65 
66         std::shared_ptr<FormSerializedResultData> serializedResultData = std::make_shared<FormSerializedResultData>();
67         auto callback = [serializedResultData]() {
68             std::unique_lock<std::mutex> lock(serializedResultData->mtx);
69             serializedResultData->cv.notify_all();
70         };
71         {
72             std::unique_lock<std::mutex> lock(serializedResultData->mtx);
73             uiContent->ProcessPointerEventWithCallback(pointerEvent, callback);
74             if (serializedResultData->cv.wait_for(lock, std::chrono::milliseconds(PROCESS_WAIT_TIME)) ==
75                 std::cv_status::timeout) {
76                 HILOG_ERROR("formRender ProcessPointerEvent dispatch timeout");
77             } else {
78                 serializedGesture = uiContent->GetFormSerializedGesture();
79             }
80         }
81     } else {
82         handler->PostTask([content = uiContent_, pointerEvent]() {
83             auto uiContent = content.lock();
84             if (!uiContent) {
85                 HILOG_ERROR("uiContent is nullptr");
86                 return;
87             }
88 
89             uiContent->ProcessPointerEvent(pointerEvent);
90         });
91     }
92 }
93 
IsAllowUpdate()94 bool FormRendererDispatcherImpl::IsAllowUpdate()
95 {
96     return allowUpdate_;
97 }
98 
SetAllowUpdate(bool allowUpdate)99 void FormRendererDispatcherImpl::SetAllowUpdate(bool allowUpdate)
100 {
101     allowUpdate_ = allowUpdate;
102 }
103 
SetVisible(bool isVisible)104 void FormRendererDispatcherImpl::SetVisible(bool isVisible)
105 {
106     isVisible_ = isVisible;
107 }
108 
IsVisible()109 bool FormRendererDispatcherImpl::IsVisible()
110 {
111     return isVisible_;
112 }
113 
DispatchSurfaceChangeEvent(float width,float height,uint32_t reason,const std::shared_ptr<Rosen::RSTransaction> & rsTransaction,float borderWidth)114 void FormRendererDispatcherImpl::DispatchSurfaceChangeEvent(float width, float height, uint32_t reason,
115     const std::shared_ptr<Rosen::RSTransaction>& rsTransaction, float borderWidth)
116 {
117     auto handler = eventHandler_.lock();
118     if (!handler) {
119         HILOG_ERROR("eventHandler is nullptr");
120         return;
121     }
122 
123     // form existed in Sceneboard window always get undefined sizeChangeReason, use Visible to control anim instead
124     reason = isVisible_ ? static_cast<uint32_t>(Rosen::WindowSizeChangeReason::ROTATION) :
125         static_cast<uint32_t>(Rosen::WindowSizeChangeReason::UNDEFINED);
126     handler->PostTask([content = uiContent_, width, height, reason, rsTransaction, borderWidth, this]() {
127         auto uiContent = content.lock();
128         if (!uiContent) {
129             HILOG_ERROR("uiContent is nullptr");
130             return;
131         }
132 
133         HandleSurfaceChangeEvent(uiContent, width, height, reason, rsTransaction, borderWidth);
134     });
135 
136     auto formRenderer = formRenderer_.lock();
137     if (!formRenderer) {
138         return;
139     }
140     formRenderer->OnSurfaceChange(width, height, borderWidth);
141 }
142 
HandleSurfaceChangeEvent(const std::shared_ptr<UIContent> & uiContent,float width,float height,uint32_t reason,const std::shared_ptr<Rosen::RSTransaction> & rsTransaction,float borderWidth)143 void FormRendererDispatcherImpl::HandleSurfaceChangeEvent(const std::shared_ptr<UIContent>& uiContent, float width,
144     float height, uint32_t reason, const std::shared_ptr<Rosen::RSTransaction>& rsTransaction, float borderWidth)
145 {
146     int32_t duration = DEFAULT_FORM_ROTATION_ANIM_DURATION;
147     bool needSync = false;
148     if (rsTransaction && rsTransaction->GetSyncId() > 0) {
149         // extract high 32 bits of SyncId as pid
150         auto SyncTransactionPid = static_cast<int32_t>(rsTransaction->GetSyncId() >> 32);
151         if (rsTransaction->IsOpenSyncTransaction() || SyncTransactionPid != rsTransaction->GetParentPid()) {
152             needSync = true;
153         }
154     }
155 
156     if (needSync) {
157         duration = rsTransaction->GetDuration() ? rsTransaction->GetDuration() : duration;
158         globalLock_.lock();
159         Rosen::RSTransaction::FlushImplicitTransaction();
160         rsTransaction->Begin();
161     }
162     Rosen::RSAnimationTimingProtocol protocol;
163     protocol.SetDuration(duration);
164     // animation curve: cubic [0.2, 0.0, 0.2, 1.0]
165     auto curve = Rosen::RSAnimationTimingCurve::CreateCubicCurve(0.2, 0.0, 0.2, 1.0);
166     Rosen::RSNode::OpenImplicitAnimation(protocol, curve, []() {});
167 
168     float uiWidth = width - borderWidth * DOUBLE;
169     float uiHeight = height - borderWidth * DOUBLE;
170     uiContent->SetFormWidth(uiWidth);
171     uiContent->SetFormHeight(uiHeight);
172     uiContent->OnFormSurfaceChange(uiWidth, uiHeight, static_cast<OHOS::Rosen::WindowSizeChangeReason>(reason),
173         rsTransaction);
174     Rosen::RSNode::CloseImplicitAnimation();
175     if (needSync) {
176         rsTransaction->Commit();
177         globalLock_.unlock();
178     } else {
179         Rosen::RSTransaction::FlushImplicitTransaction();
180     }
181 }
182 
SetObscured(bool isObscured)183 void FormRendererDispatcherImpl::SetObscured(bool isObscured)
184 {
185     auto handler = eventHandler_.lock();
186     if (!handler) {
187         HILOG_ERROR("eventHandler is nullptr");
188         return;
189     }
190     handler->PostTask([content = uiContent_, isObscured]() {
191         auto uiContent = content.lock();
192         if (!uiContent) {
193             HILOG_ERROR("uiContent is nullptr");
194             return;
195         }
196         HILOG_INFO("Update ChangeSensitiveNodes: %{public}s", isObscured ? "true" : "false");
197         uiContent->ChangeSensitiveNodes(isObscured);
198     });
199 }
200 
OnAccessibilityChildTreeRegister(uint32_t windowId,int32_t treeId,int64_t accessibilityId)201 void FormRendererDispatcherImpl::OnAccessibilityChildTreeRegister(
202     uint32_t windowId, int32_t treeId, int64_t accessibilityId)
203 {
204     auto handler = eventHandler_.lock();
205     if (!handler) {
206         HILOG_ERROR("eventHandler is nullptr");
207         return;
208     }
209 
210     handler->PostTask([content = uiContent_, formRenderer = formRenderer_, windowId, treeId, accessibilityId]() {
211         auto uiContent = content.lock();
212         if (!uiContent) {
213             HILOG_ERROR("uiContent is nullptr");
214             return;
215         }
216         HILOG_INFO("OnAccessibilityChildTreeRegister: %{public}d %{public}" PRId64, treeId, accessibilityId);
217         uiContent->RegisterAccessibilityChildTree(windowId, treeId, accessibilityId);
218         uiContent->SetAccessibilityGetParentRectHandler([formRenderer](int32_t &top, int32_t &left) {
219             auto formRendererPtr = formRenderer.lock();
220             if (!formRendererPtr) {
221                 HILOG_ERROR("formRenderer is nullptr");
222                 return;
223             }
224             formRendererPtr->GetRectRelativeToWindow(top, left);
225         });
226     });
227 }
228 
OnAccessibilityChildTreeDeregister()229 void FormRendererDispatcherImpl::OnAccessibilityChildTreeDeregister()
230 {
231     auto handler = eventHandler_.lock();
232     if (!handler) {
233         HILOG_ERROR("eventHandler is nullptr");
234         return;
235     }
236     handler->PostTask([content = uiContent_]() {
237         auto uiContent = content.lock();
238         if (!uiContent) {
239             HILOG_ERROR("uiContent is nullptr");
240             return;
241         }
242         HILOG_INFO("OnAccessibilityChildTreeDeregister");
243         uiContent->DeregisterAccessibilityChildTree();
244     });
245 }
246 
OnAccessibilityDumpChildInfo(const std::vector<std::string> & params,std::vector<std::string> & info)247 void FormRendererDispatcherImpl::OnAccessibilityDumpChildInfo(
248     const std::vector<std::string>& params, std::vector<std::string>& info)
249 {
250     auto handler = eventHandler_.lock();
251     if (!handler) {
252         HILOG_ERROR("eventHandler is nullptr");
253         return;
254     }
255     handler->PostSyncTask([content = uiContent_, params, &info]() {
256         auto uiContent = content.lock();
257         if (!uiContent) {
258             HILOG_ERROR("uiContent is nullptr");
259             return;
260         }
261         HILOG_INFO("OnAccessibilityDumpChildInfo");
262         uiContent->AccessibilityDumpChildInfo(params, info);
263     });
264 }
265 
OnAccessibilityTransferHoverEvent(float pointX,float pointY,int32_t sourceType,int32_t eventType,int64_t timeMs)266 void FormRendererDispatcherImpl::OnAccessibilityTransferHoverEvent(float pointX, float pointY, int32_t sourceType,
267     int32_t eventType, int64_t timeMs)
268 {
269     auto handler = eventHandler_.lock();
270     if (!handler) {
271         HILOG_ERROR("eventHandler is nullptr");
272         return;
273     }
274     handler->PostTask([content = uiContent_, pointX, pointY, sourceType, eventType, timeMs]() {
275         auto uiContent = content.lock();
276         if (!uiContent) {
277             HILOG_ERROR("uiContent is nullptr");
278             return;
279         }
280         HILOG_INFO("OnAccessibilityTransferHoverEvent");
281         uiContent->HandleAccessibilityHoverEvent(pointX, pointY, sourceType, eventType, timeMs);
282     });
283 }
284 } // namespace Ace
285 } // namespace OHOS
286