1 /*
2 * Copyright (c) 2023-2024 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/pipeline_ng/pipeline_context.h"
17
18 #include "base/subwindow/subwindow_manager.h"
19
20 #ifdef ENABLE_ROSEN_BACKEND
21 #include "render_service_client/core/transaction/rs_transaction.h"
22 #include "render_service_client/core/ui/rs_ui_director.h"
23 #endif
24 #if !defined(PREVIEW) && !defined(ACE_UNITTEST) && defined(OHOS_PLATFORM)
25 #include "interfaces/inner_api/ui_session/ui_session_manager.h"
26 #include "frameworks/core/components_ng/base/inspector.h"
27 #endif
28
29 #include "base/geometry/ng/offset_t.h"
30 #include "base/geometry/ng/rect_t.h"
31 #include "base/log/ace_performance_monitor.h"
32 #include "base/log/ace_trace.h"
33 #include "base/log/ace_tracker.h"
34 #include "base/log/dump_log.h"
35 #include "base/log/event_report.h"
36 #include "base/memory/ace_type.h"
37 #include "base/perfmonitor/perf_monitor.h"
38 #include "base/ressched/ressched_report.h"
39 #include "core/common/ace_engine.h"
40 #include "core/common/font_manager.h"
41 #include "core/common/font_change_observer.h"
42 #include "core/common/ime/input_method_manager.h"
43 #include "core/common/layout_inspector.h"
44 #include "core/common/stylus/stylus_detector_default.h"
45 #include "core/common/stylus/stylus_detector_mgr.h"
46 #include "core/common/text_field_manager.h"
47 #include "core/components_ng/base/view_advanced_register.h"
48 #include "core/components_ng/pattern/container_modal/container_modal_view_factory.h"
49 #include "core/components_ng/pattern/container_modal/enhance/container_modal_pattern_enhance.h"
50 #include "core/components_ng/pattern/navigation/navigation_pattern.h"
51 #include "core/components_ng/pattern/navigation/nav_bar_node.h"
52 #include "core/components_ng/pattern/root/root_pattern.h"
53 #include "core/components_ng/pattern/text_field/text_field_manager.h"
54 #ifdef WINDOW_SCENE_SUPPORTED
55 #include "core/components_ng/pattern/window_scene/scene/window_scene_layout_manager.h"
56 #endif
57 #include "core/image/image_file_cache.h"
58 #include "core/pipeline/pipeline_context.h"
59
60 namespace {
61 constexpr uint64_t ONE_MS_IN_NS = 1 * 1000 * 1000;
62 constexpr uint64_t ONE_S_IN_NS = 1 * 1000 * 1000 * 1000;
63 constexpr uint64_t INTERPOLATION_THRESHOLD = 100 * 1000 * 1000; // 100ms
64 constexpr int32_t INDEX_X = 0;
65 constexpr int32_t INDEX_Y = 1;
66 constexpr int32_t INDEX_TIME = 2;
67 constexpr int32_t INDEX_X_SLOPE = 2;
68 constexpr int32_t INDEX_Y_SLOPE = 3;
69 constexpr int32_t TIME_THRESHOLD = 2 * 1000000; // 3 millisecond
70 constexpr int32_t PLATFORM_VERSION_TEN = 10;
71 constexpr int32_t USED_ID_FIND_FLAG = 3; // if args >3 , it means use id to find
72 constexpr int32_t MILLISECONDS_TO_NANOSECONDS = 1000000; // Milliseconds to nanoseconds
73 constexpr int32_t RESAMPLE_COORD_TIME_THRESHOLD = 20 * 1000 * 1000;
74 constexpr int32_t VSYNC_PERIOD_COUNT = 5;
75 constexpr int32_t MIN_IDLE_TIME = 1000000;
76 constexpr uint8_t SINGLECOLOR_UPDATE_ALPHA = 75;
77 constexpr int8_t RENDERING_SINGLE_COLOR = 1;
78 constexpr int32_t MAX_MISS_COUNT = 3;
79 constexpr int32_t DELAY_TIME = 500;
80
81 } // namespace
82
83 namespace OHOS::Ace::NG {
84
PipelineContext(std::shared_ptr<Window> window,RefPtr<TaskExecutor> taskExecutor,RefPtr<AssetManager> assetManager,RefPtr<PlatformResRegister> platformResRegister,const RefPtr<Frontend> & frontend,int32_t instanceId)85 PipelineContext::PipelineContext(std::shared_ptr<Window> window, RefPtr<TaskExecutor> taskExecutor,
86 RefPtr<AssetManager> assetManager, RefPtr<PlatformResRegister> platformResRegister,
87 const RefPtr<Frontend>& frontend, int32_t instanceId)
88 : PipelineBase(window, std::move(taskExecutor), std::move(assetManager), frontend, instanceId, platformResRegister)
89 {
90 window_->OnHide();
91 }
92
PipelineContext(std::shared_ptr<Window> window,RefPtr<TaskExecutor> taskExecutor,RefPtr<AssetManager> assetManager,const RefPtr<Frontend> & frontend,int32_t instanceId)93 PipelineContext::PipelineContext(std::shared_ptr<Window> window, RefPtr<TaskExecutor> taskExecutor,
94 RefPtr<AssetManager> assetManager, const RefPtr<Frontend>& frontend, int32_t instanceId)
95 : PipelineBase(window, std::move(taskExecutor), std::move(assetManager), frontend, instanceId)
96 {
97 window_->OnHide();
98 }
99
GetCurrentContext()100 RefPtr<PipelineContext> PipelineContext::GetCurrentContext()
101 {
102 auto currentContainer = Container::Current();
103 CHECK_NULL_RETURN(currentContainer, nullptr);
104 return DynamicCast<PipelineContext>(currentContainer->GetPipelineContext());
105 }
106
GetCurrentContextSafely()107 RefPtr<PipelineContext> PipelineContext::GetCurrentContextSafely()
108 {
109 auto currentContainer = Container::CurrentSafely();
110 CHECK_NULL_RETURN(currentContainer, nullptr);
111 return DynamicCast<PipelineContext>(currentContainer->GetPipelineContext());
112 }
113
GetCurrentContextSafelyWithCheck()114 RefPtr<PipelineContext> PipelineContext::GetCurrentContextSafelyWithCheck()
115 {
116 auto currentContainer = Container::CurrentSafelyWithCheck();
117 CHECK_NULL_RETURN(currentContainer, nullptr);
118 return DynamicCast<PipelineContext>(currentContainer->GetPipelineContext());
119 }
120
GetCurrentContextPtrSafely()121 PipelineContext* PipelineContext::GetCurrentContextPtrSafely()
122 {
123 auto currentContainer = Container::CurrentSafely();
124 CHECK_NULL_RETURN(currentContainer, nullptr);
125 const auto& base = currentContainer->GetPipelineContext();
126 CHECK_NULL_RETURN(base, nullptr);
127 return DynamicCast<PipelineContext>(RawPtr(base));
128 }
129
GetCurrentContextPtrSafelyWithCheck()130 PipelineContext* PipelineContext::GetCurrentContextPtrSafelyWithCheck()
131 {
132 auto currentContainer = Container::CurrentSafelyWithCheck();
133 CHECK_NULL_RETURN(currentContainer, nullptr);
134 const auto& base = currentContainer->GetPipelineContext();
135 CHECK_NULL_RETURN(base, nullptr);
136 return DynamicCast<PipelineContext>(RawPtr(base));
137 }
138
GetMainPipelineContext()139 RefPtr<PipelineContext> PipelineContext::GetMainPipelineContext()
140 {
141 auto pipeline = PipelineBase::GetMainPipelineContext();
142 CHECK_NULL_RETURN(pipeline, nullptr);
143 return DynamicCast<PipelineContext>(pipeline);
144 }
145
NeedSoftKeyboard()146 bool PipelineContext::NeedSoftKeyboard()
147 {
148 auto needKeyboard = InputMethodManager::GetInstance()->NeedSoftKeyboard();
149 TAG_LOGI(AceLogTag::ACE_KEYBOARD, "need keyboard : %{public}d.", needKeyboard);
150 return needKeyboard;
151 }
152
GetContextByContainerId(int32_t containerId)153 RefPtr<PipelineContext> PipelineContext::GetContextByContainerId(int32_t containerId)
154 {
155 auto preContainer = Container::GetContainer(containerId);
156 CHECK_NULL_RETURN(preContainer, nullptr);
157 return DynamicCast<PipelineContext>(preContainer->GetPipelineContext());
158 }
159
GetCurrentRootWidth()160 float PipelineContext::GetCurrentRootWidth()
161 {
162 auto context = GetCurrentContext();
163 CHECK_NULL_RETURN(context, 0.0f);
164 return static_cast<float>(context->rootWidth_);
165 }
166
GetCurrentRootHeight()167 float PipelineContext::GetCurrentRootHeight()
168 {
169 auto context = GetCurrentContext();
170 CHECK_NULL_RETURN(context, 0.0f);
171 return static_cast<float>(context->rootHeight_);
172 }
173
AddDirtyPropertyNode(const RefPtr<FrameNode> & dirtyNode)174 void PipelineContext::AddDirtyPropertyNode(const RefPtr<FrameNode>& dirtyNode)
175 {
176 if (!CheckThreadSafe()) {
177 LOGW("AddDirtyPropertyNode doesn't run on UI thread!");
178 }
179 dirtyPropertyNodes_.emplace(dirtyNode);
180 hasIdleTasks_ = true;
181 RequestFrame();
182 }
183
AddDirtyCustomNode(const RefPtr<UINode> & dirtyNode)184 void PipelineContext::AddDirtyCustomNode(const RefPtr<UINode>& dirtyNode)
185 {
186 CHECK_RUN_ON(UI);
187 CHECK_NULL_VOID(dirtyNode);
188 auto customNode = DynamicCast<CustomNode>(dirtyNode);
189 if (customNode && !dirtyNode->GetInspectorIdValue("").empty()) {
190 ACE_BUILD_TRACE_BEGIN("AddDirtyCustomNode[%s][self:%d][parent:%d][key:%s]",
191 customNode->GetJSViewName().c_str(),
192 dirtyNode->GetId(), dirtyNode->GetParent() ? dirtyNode->GetParent()->GetId() : 0,
193 dirtyNode->GetInspectorIdValue("").c_str());
194 ACE_BUILD_TRACE_END()
195 } else if (customNode) {
196 ACE_BUILD_TRACE_BEGIN("AddDirtyCustomNode[%s][self:%d][parent:%d]",
197 customNode->GetJSViewName().c_str(),
198 dirtyNode->GetId(), dirtyNode->GetParent() ? dirtyNode->GetParent()->GetId() : 0);
199 ACE_BUILD_TRACE_END()
200 }
201 dirtyNodes_.emplace(dirtyNode);
202 hasIdleTasks_ = true;
203 RequestFrame();
204 }
205
AddDirtyLayoutNode(const RefPtr<FrameNode> & dirty)206 void PipelineContext::AddDirtyLayoutNode(const RefPtr<FrameNode>& dirty)
207 {
208 CHECK_RUN_ON(UI);
209 CHECK_NULL_VOID(dirty);
210 if (IsDestroyed()) {
211 LOGW("Cannot add dirty layout node as the pipeline context is destroyed.");
212 return;
213 }
214 if (!dirty->GetInspectorIdValue("").empty()) {
215 ACE_BUILD_TRACE_BEGIN("AddDirtyLayoutNode[%s][self:%d][parent:%d][key:%s]",
216 dirty->GetTag().c_str(),
217 dirty->GetId(), dirty->GetParent() ? dirty->GetParent()->GetId() : 0,
218 dirty->GetInspectorIdValue("").c_str());
219 ACE_BUILD_TRACE_END()
220 } else {
221 ACE_BUILD_TRACE_BEGIN("AddDirtyLayoutNode[%s][self:%d][parent:%d]", dirty->GetTag().c_str(),
222 dirty->GetId(), dirty->GetParent() ? dirty->GetParent()->GetId() : 0);
223 ACE_BUILD_TRACE_END()
224 }
225 if (!dirty->IsOnMainTree() && predictNode_) {
226 predictNode_->AddPredictLayoutNode(dirty);
227 return;
228 }
229 taskScheduler_->AddDirtyLayoutNode(dirty);
230 ForceLayoutForImplicitAnimation();
231 #ifdef UICAST_COMPONENT_SUPPORTED
232 do {
233 auto container = Container::Current();
234 CHECK_NULL_BREAK(container);
235 auto distributedUI = container->GetDistributedUI();
236 CHECK_NULL_BREAK(distributedUI);
237 distributedUI->AddDirtyLayoutNode(dirty->GetId());
238 } while (false);
239 #endif
240 hasIdleTasks_ = true;
241 if (dirty->GetTag() == V2::ROOT_ETS_TAG && isFirstRootLayout_) {
242 isFirstRootLayout_ = false;
243 LOGI("Root node request first frame.");
244 }
245 RequestFrame();
246 }
247
AddLayoutNode(const RefPtr<FrameNode> & layoutNode)248 void PipelineContext::AddLayoutNode(const RefPtr<FrameNode>& layoutNode)
249 {
250 taskScheduler_->AddLayoutNode(layoutNode);
251 }
252
AddDirtyRenderNode(const RefPtr<FrameNode> & dirty)253 void PipelineContext::AddDirtyRenderNode(const RefPtr<FrameNode>& dirty)
254 {
255 CHECK_RUN_ON(UI);
256 CHECK_NULL_VOID(dirty);
257 if (IsDestroyed()) {
258 LOGW("Cannot add dirty render node as the pipeline context is destroyed.");
259 return;
260 }
261 if (!dirty->GetInspectorIdValue("").empty()) {
262 ACE_BUILD_TRACE_BEGIN("AddDirtyRenderNode[%s][self:%d][parent:%d][key:%s]", dirty->GetTag().c_str(),
263 dirty->GetId(), dirty->GetParent() ? dirty->GetParent()->GetId() : 0,
264 dirty->GetInspectorIdValue("").c_str());
265 ACE_BUILD_TRACE_END()
266 } else {
267 ACE_BUILD_TRACE_BEGIN("AddDirtyRenderNode[%s][self:%d][parent:%d]", dirty->GetTag().c_str(),
268 dirty->GetId(), dirty->GetParent() ? dirty->GetParent()->GetId() : 0);
269 ACE_BUILD_TRACE_END()
270 }
271 taskScheduler_->AddDirtyRenderNode(dirty);
272 ForceRenderForImplicitAnimation();
273 #ifdef UICAST_COMPONENT_SUPPORTED
274 do {
275 auto container = Container::Current();
276 CHECK_NULL_BREAK(container);
277 auto distributedUI = container->GetDistributedUI();
278 CHECK_NULL_BREAK(distributedUI);
279 distributedUI->AddDirtyRenderNode(dirty->GetId());
280 } while (false);
281 #endif
282 hasIdleTasks_ = true;
283 RequestFrame();
284 }
285
AddDirtyFreezeNode(FrameNode * node)286 void PipelineContext::AddDirtyFreezeNode(FrameNode* node)
287 {
288 dirtyFreezeNode_.emplace_back(WeakClaim(node));
289 hasIdleTasks_ = true;
290 RequestFrame();
291 }
292
FlushFreezeNode()293 void PipelineContext::FlushFreezeNode()
294 {
295 std::set<RefPtr<FrameNode>, NodeCompare<RefPtr<FrameNode>>> dirtyFreezeNodeSet;
296 auto dirtyFreezeNodes = std::move(dirtyFreezeNode_);
297 dirtyFreezeNode_.clear();
298 for (auto&& weakNode : dirtyFreezeNodes) {
299 auto node = weakNode.Upgrade();
300 if (node) {
301 dirtyFreezeNodeSet.emplace(node);
302 }
303 }
304 // Process parentNode before childNode
305 for (auto&& node : dirtyFreezeNodeSet) {
306 node->ProcessFreezeNode();
307 }
308 }
309
FlushDirtyPropertyNodes()310 void PipelineContext::FlushDirtyPropertyNodes()
311 {
312 // node api property diff before ets update.
313 if (!CheckThreadSafe()) {
314 LOGW("FlushDirtyNodeUpdate doesn't run on UI thread!");
315 }
316 decltype(dirtyPropertyNodes_) dirtyPropertyNodes(std::move(dirtyPropertyNodes_));
317 dirtyPropertyNodes_.clear();
318 for (const auto& node : dirtyPropertyNodes) {
319 node->ProcessPropertyDiff();
320 }
321 }
322
FlushDirtyNodeUpdate()323 void PipelineContext::FlushDirtyNodeUpdate()
324 {
325 CHECK_RUN_ON(UI);
326 ACE_FUNCTION_TRACE();
327 if (FrameReport::GetInstance().GetEnable()) {
328 FrameReport::GetInstance().BeginFlushBuild();
329 }
330
331 // freeze node unlock before build begin.
332 FlushFreezeNode();
333
334 FlushDirtyPropertyNodes();
335
336 if (!ViewStackProcessor::GetInstance()->IsEmpty() && !dirtyNodes_.empty()) {
337 ACE_SCOPED_TRACE("Error update, node stack non-empty");
338 LOGW("stack is not empty when call FlushDirtyNodeUpdate, node may be mounted to incorrect pos!");
339 }
340 // SomeTimes, customNode->Update may add some dirty custom nodes to dirtyNodes_,
341 // use maxFlushTimes to avoid dead cycle.
342 int maxFlushTimes = 3;
343 while (!dirtyNodes_.empty() && maxFlushTimes > 0) {
344 ArkUIPerfMonitor::GetInstance().RecordStateMgmtNode(dirtyNodes_.size());
345 decltype(dirtyNodes_) dirtyNodes(std::move(dirtyNodes_));
346 for (const auto& node : dirtyNodes) {
347 if (AceType::InstanceOf<NG::CustomNodeBase>(node)) {
348 auto customNode = AceType::DynamicCast<NG::CustomNodeBase>(node);
349 ACE_SCOPED_TRACE("CustomNodeUpdate %s", customNode->GetJSViewName().c_str());
350 customNode->Update();
351 }
352 }
353 --maxFlushTimes;
354 }
355
356 if (FrameReport::GetInstance().GetEnable()) {
357 FrameReport::GetInstance().EndFlushBuild();
358 }
359 }
360
AddScheduleTask(const RefPtr<ScheduleTask> & task)361 uint32_t PipelineContext::AddScheduleTask(const RefPtr<ScheduleTask>& task)
362 {
363 CHECK_RUN_ON(UI);
364 scheduleTasks_.try_emplace(++nextScheduleTaskId_, task);
365 RequestFrame();
366 return nextScheduleTaskId_;
367 }
368
RemoveScheduleTask(uint32_t id)369 void PipelineContext::RemoveScheduleTask(uint32_t id)
370 {
371 CHECK_RUN_ON(UI);
372 scheduleTasks_.erase(id);
373 }
374
LinearInterpolation(const std::tuple<float,float,uint64_t> & history,const std::tuple<float,float,uint64_t> & current,const uint64_t nanoTimeStamp)375 std::tuple<float, float, float, float> PipelineContext::LinearInterpolation(
376 const std::tuple<float, float, uint64_t>& history, const std::tuple<float, float, uint64_t>& current,
377 const uint64_t nanoTimeStamp)
378 {
379 if (nanoTimeStamp == std::get<INDEX_TIME>(history) || nanoTimeStamp == std::get<INDEX_TIME>(current)) {
380 return std::make_tuple(0.0f, 0.0f, 0.0f, 0.0f);
381 }
382 if (std::get<INDEX_TIME>(current) <= std::get<INDEX_TIME>(history)) {
383 return std::make_tuple(0.0f, 0.0f, 0.0f, 0.0f);
384 }
385 if (std::get<INDEX_TIME>(current) - std::get<INDEX_TIME>(history) > INTERPOLATION_THRESHOLD) {
386 return std::make_tuple(0.0f, 0.0f, 0.0f, 0.0f);
387 }
388 if (nanoTimeStamp < std::get<INDEX_TIME>(history)) {
389 return std::make_tuple(0.0f, 0.0f, 0.0f, 0.0f);
390 }
391 auto inputXDeltaSlope = (std::get<INDEX_X>(current) - std::get<INDEX_X>(history)) * ONE_S_IN_NS /
392 (float)(std::get<INDEX_TIME>(current) - std::get<INDEX_TIME>(history));
393 auto inputYDeltaSlope = (std::get<INDEX_Y>(current) - std::get<INDEX_Y>(history)) * ONE_S_IN_NS /
394 (float)(std::get<INDEX_TIME>(current) - std::get<INDEX_TIME>(history));
395 if (nanoTimeStamp < std::get<INDEX_TIME>(current)) {
396 float alpha = (float)(nanoTimeStamp - std::get<INDEX_TIME>(history)) /
397 (float)(std::get<INDEX_TIME>(current) - std::get<INDEX_TIME>(history));
398 float x = std::get<INDEX_X>(history) + alpha * (std::get<INDEX_X>(current) - std::get<INDEX_X>(history));
399 float y = std::get<INDEX_Y>(history) + alpha * (std::get<INDEX_Y>(current) - std::get<INDEX_Y>(history));
400 return std::make_tuple(x, y, inputXDeltaSlope, inputYDeltaSlope);
401 } else if (nanoTimeStamp > std::get<INDEX_TIME>(current)) {
402 float alpha = (float)(nanoTimeStamp - std::get<INDEX_TIME>(current)) /
403 (float)(std::get<INDEX_TIME>(current) - std::get<INDEX_TIME>(history));
404 float x = std::get<INDEX_X>(current) + alpha * (std::get<INDEX_X>(current) - std::get<INDEX_X>(history));
405 float y = std::get<INDEX_Y>(current) + alpha * (std::get<INDEX_Y>(current) - std::get<INDEX_Y>(history));
406 return std::make_tuple(x, y, inputXDeltaSlope, inputYDeltaSlope);
407 }
408 return std::make_tuple(0.0f, 0.0f, 0.0f, 0.0f);
409 }
410
GetAvgPoint(const std::vector<TouchEvent> & events,const bool isScreen)411 std::tuple<float, float, uint64_t> PipelineContext::GetAvgPoint(
412 const std::vector<TouchEvent>& events, const bool isScreen)
413 {
414 float avgX = 0.0f;
415 float avgY = 0.0f;
416 uint64_t avgTime = 0;
417 int32_t i = 0;
418 uint64_t lastTime = 0;
419 for (auto iter = events.begin(); iter != events.end(); iter++) {
420 if (lastTime == 0 || static_cast<uint64_t>(iter->time.time_since_epoch().count()) != lastTime) {
421 if (!isScreen) {
422 avgX += iter->x;
423 avgY += iter->y;
424 } else {
425 avgX += iter->screenX;
426 avgY += iter->screenY;
427 }
428 avgTime += static_cast<uint64_t>(iter->time.time_since_epoch().count());
429 i++;
430 lastTime = static_cast<uint64_t>(iter->time.time_since_epoch().count());
431 }
432 }
433 if (i > 0) {
434 avgX /= i;
435 avgY /= i;
436 avgTime /= static_cast<uint64_t>(i);
437 }
438 return std::make_tuple(avgX, avgY, avgTime);
439 }
440
GetResampleCoord(const std::vector<TouchEvent> & history,const std::vector<TouchEvent> & current,const uint64_t nanoTimeStamp,const bool isScreen)441 std::tuple<float, float, float, float> PipelineContext::GetResampleCoord(const std::vector<TouchEvent>& history,
442 const std::vector<TouchEvent>& current, const uint64_t nanoTimeStamp, const bool isScreen)
443 {
444 if (history.empty() || current.empty()) {
445 return std::make_tuple(0.0f, 0.0f, 0.0f, 0.0f);
446 }
447 uint64_t lastNanoTime = 0;
448 float x = 0.0f;
449 float y = 0.0f;
450 for (const auto& item : current) {
451 uint64_t currentNanoTime = static_cast<uint64_t>(item.time.time_since_epoch().count());
452 if (lastNanoTime < currentNanoTime) {
453 lastNanoTime = currentNanoTime;
454 x = item.x;
455 y = item.y;
456 }
457 }
458 if (nanoTimeStamp > RESAMPLE_COORD_TIME_THRESHOLD + lastNanoTime) {
459 return std::make_tuple(x, y, 0.0f, 0.0f);
460 }
461 auto historyPoint = GetAvgPoint(history, isScreen);
462 auto currentPoint = GetAvgPoint(current, isScreen);
463
464 if (SystemProperties::GetDebugEnabled()) {
465 TAG_LOGD(AceLogTag::ACE_UIEVENT, "input time is %{public}" PRIu64 "", nanoTimeStamp);
466 for (auto iter : history) {
467 TAG_LOGD(AceLogTag::ACE_UIEVENT, "history point x %{public}f, y %{public}f, time %{public}" PRIu64 "",
468 iter.x, iter.y, static_cast<uint64_t>(iter.time.time_since_epoch().count()));
469 }
470 TAG_LOGD(AceLogTag::ACE_UIEVENT, "historyAvgPoint is x %{public}f, y %{public}f, time %{public}" PRIu64 "",
471 std::get<INDEX_X>(historyPoint), std::get<INDEX_Y>(historyPoint), std::get<INDEX_TIME>(historyPoint));
472 for (auto iter : current) {
473 TAG_LOGD(AceLogTag::ACE_UIEVENT, "current point x %{public}f, y %{public}f, time %{public}" PRIu64 "",
474 iter.x, iter.y, static_cast<uint64_t>(iter.time.time_since_epoch().count()));
475 }
476 TAG_LOGD(AceLogTag::ACE_UIEVENT, "currentAvgPoint is x %{public}f, y %{public}f, time %{public}" PRIu64 "",
477 std::get<INDEX_X>(currentPoint), std::get<INDEX_Y>(currentPoint), std::get<INDEX_TIME>(currentPoint));
478 }
479 return LinearInterpolation(historyPoint, currentPoint, nanoTimeStamp);
480 }
481
GetResampleTouchEvent(const std::vector<TouchEvent> & history,const std::vector<TouchEvent> & current,const uint64_t nanoTimeStamp,TouchEvent & newTouchEvent)482 bool PipelineContext::GetResampleTouchEvent(const std::vector<TouchEvent>& history,
483 const std::vector<TouchEvent>& current, const uint64_t nanoTimeStamp, TouchEvent& newTouchEvent)
484 {
485 auto newXy = GetResampleCoord(history, current, nanoTimeStamp, false);
486 auto newScreenXy = GetResampleCoord(history, current, nanoTimeStamp, true);
487 newTouchEvent = GetLatestPoint(current, nanoTimeStamp);
488 bool ret = false;
489 if (std::get<INDEX_X>(newXy) != 0 && std::get<INDEX_Y>(newXy) != 0) {
490 newTouchEvent.x = std::get<INDEX_X>(newXy);
491 newTouchEvent.y = std::get<INDEX_Y>(newXy);
492 newTouchEvent.screenX = std::get<INDEX_X>(newScreenXy);
493 newTouchEvent.screenY = std::get<INDEX_Y>(newScreenXy);
494 std::chrono::nanoseconds nanoseconds(nanoTimeStamp);
495 newTouchEvent.time = TimeStamp(nanoseconds);
496 newTouchEvent.history = current;
497 newTouchEvent.isInterpolated = true;
498 newTouchEvent.inputXDeltaSlope = std::get<INDEX_X_SLOPE>(newXy);
499 newTouchEvent.inputYDeltaSlope = std::get<INDEX_Y_SLOPE>(newXy);
500 ret = true;
501 }
502 if (SystemProperties::GetDebugEnabled()) {
503 TAG_LOGD(AceLogTag::ACE_UIEVENT,
504 "Interpolate point is %{public}d, %{public}f, %{public}f, %{public}f, %{public}f, %{public}" PRIu64 "",
505 newTouchEvent.id, newTouchEvent.x, newTouchEvent.y, newTouchEvent.screenX, newTouchEvent.screenY,
506 static_cast<uint64_t>(newTouchEvent.time.time_since_epoch().count()));
507 }
508 return ret;
509 }
510
GetLatestPoint(const std::vector<TouchEvent> & current,const uint64_t nanoTimeStamp)511 TouchEvent PipelineContext::GetLatestPoint(const std::vector<TouchEvent>& current, const uint64_t nanoTimeStamp)
512 {
513 TouchEvent result;
514 uint64_t gap = UINT64_MAX;
515 for (auto iter = current.begin(); iter != current.end(); iter++) {
516 uint64_t timeStamp = static_cast<uint64_t>(iter->time.time_since_epoch().count());
517 if (timeStamp == nanoTimeStamp) {
518 result = *iter;
519 return result;
520 } else if (timeStamp > nanoTimeStamp) {
521 if (timeStamp - nanoTimeStamp < gap) {
522 gap = timeStamp - nanoTimeStamp;
523 result = *iter;
524 }
525 } else {
526 if (nanoTimeStamp - timeStamp < gap) {
527 gap = nanoTimeStamp - timeStamp;
528 result = *iter;
529 }
530 }
531 }
532 return result;
533 }
534
FlushOnceVsyncTask()535 void PipelineContext::FlushOnceVsyncTask()
536 {
537 if (onceVsyncListener_ != nullptr) {
538 onceVsyncListener_();
539 onceVsyncListener_ = nullptr;
540 }
541 }
542
FlushVsync(uint64_t nanoTimestamp,uint32_t frameCount)543 void PipelineContext::FlushVsync(uint64_t nanoTimestamp, uint32_t frameCount)
544 {
545 CHECK_RUN_ON(UI);
546 if (IsDestroyed()) {
547 LOGW("Cannot flush vsync as the pipeline context is destroyed.");
548 return;
549 }
550 SetVsyncTime(nanoTimestamp);
551 ACE_SCOPED_TRACE_COMMERCIAL("UIVsyncTask[timestamp:%" PRIu64 "][vsyncID:%" PRIu64 "][instanceID:%d]", nanoTimestamp,
552 static_cast<uint64_t>(frameCount), instanceId_);
553 window_->Lock();
554 static const std::string abilityName = AceApplicationInfo::GetInstance().GetProcessName().empty()
555 ? AceApplicationInfo::GetInstance().GetPackageName()
556 : AceApplicationInfo::GetInstance().GetProcessName();
557 window_->RecordFrameTime(nanoTimestamp, abilityName);
558 resampleTimeStamp_ = nanoTimestamp - static_cast<uint64_t>(window_->GetVSyncPeriod()) + ONE_MS_IN_NS -\
559 compensationValue_;
560 #ifdef UICAST_COMPONENT_SUPPORTED
561 do {
562 auto container = Container::Current();
563 CHECK_NULL_BREAK(container);
564 auto distributedUI = container->GetDistributedUI();
565 CHECK_NULL_BREAK(distributedUI);
566 distributedUI->ApplyOneUpdate();
567 } while (false);
568 #endif
569 ProcessDelayTasks();
570 DispatchDisplaySync(nanoTimestamp);
571 FlushAnimation(nanoTimestamp);
572 FlushFrameCallback(nanoTimestamp);
573 auto hasRunningAnimation = FlushModifierAnimation(nanoTimestamp);
574 FlushTouchEvents();
575 FlushBuild();
576 if (isFormRender_ && drawDelegate_ && rootNode_) {
577 auto renderContext = AceType::DynamicCast<NG::RenderContext>(rootNode_->GetRenderContext());
578 drawDelegate_->DrawRSFrame(renderContext);
579 drawDelegate_ = nullptr;
580 }
581 if (!taskScheduler_->isEmpty()) {
582 #if !defined(PREVIEW)
583 LayoutInspector::SupportInspector();
584 #endif
585 }
586
587 taskScheduler_->StartRecordFrameInfo(GetCurrentFrameInfo(recvTime_, nanoTimestamp));
588 taskScheduler_->FlushTask();
589 UIObserverHandler::GetInstance().HandleLayoutDoneCallBack();
590 // flush correct rect again
591 taskScheduler_->FlushPersistAfterLayoutTask();
592 taskScheduler_->FinishRecordFrameInfo();
593 FlushNodeChangeFlag();
594 FlushAnimationClosure();
595 TryCallNextFrameLayoutCallback();
596
597 #ifdef UICAST_COMPONENT_SUPPORTED
598 do {
599 auto container = Container::Current();
600 CHECK_NULL_BREAK(container);
601 auto distributedUI = container->GetDistributedUI();
602 CHECK_NULL_BREAK(distributedUI);
603 distributedUI->OnTreeUpdate();
604 } while (false);
605 #endif
606
607 if (hasRunningAnimation || window_->HasUIRunningAnimation()) {
608 RequestFrame();
609 }
610 window_->FlushModifier();
611 FlushFrameRate();
612 if (dragWindowVisibleCallback_) {
613 dragWindowVisibleCallback_();
614 dragWindowVisibleCallback_ = nullptr;
615 }
616 if (isFirstFlushMessages_) {
617 isFirstFlushMessages_ = false;
618 LOGI("ArkUi flush first frame messages.");
619 }
620 FlushMessages();
621 FlushWindowPatternInfo();
622 InspectDrew();
623 UIObserverHandler::GetInstance().HandleDrawCommandSendCallBack();
624 if (onShow_ && onFocus_ && isWindowHasFocused_) {
625 auto isDynamicRender = Container::Current() == nullptr ? false : Container::Current()->IsDynamicRender();
626 if ((!isFormRender_) || isDynamicRender) {
627 FlushFocusView();
628 FlushFocus();
629 FlushFocusScroll();
630 }
631 }
632 HandleOnAreaChangeEvent(nanoTimestamp);
633 HandleVisibleAreaChangeEvent(nanoTimestamp);
634 if (isNeedFlushMouseEvent_) {
635 FlushMouseEvent();
636 isNeedFlushMouseEvent_ = false;
637 }
638 if (isNeedFlushAnimationStartTime_) {
639 window_->FlushAnimationStartTime(animationTimeStamp_);
640 isNeedFlushAnimationStartTime_ = false;
641 }
642 needRenderNode_.clear();
643 taskScheduler_->FlushAfterRenderTask();
644 window_->FlushLayoutSize(width_, height_);
645 if (IsFocusWindowIdSetted()) {
646 FireAllUIExtensionEvents();
647 }
648 FireAccessibilityEvents();
649 // Keep the call sent at the end of the function
650 ResSchedReport::GetInstance().LoadPageEvent(ResDefine::LOAD_PAGE_COMPLETE_EVENT);
651 window_->Unlock();
652 }
653
FlushWindowPatternInfo()654 void PipelineContext::FlushWindowPatternInfo()
655 {
656 #ifdef WINDOW_SCENE_SUPPORTED
657 auto container = Container::Current();
658 CHECK_NULL_VOID(container);
659 if (!container->IsScenceBoardWindow()) {
660 return;
661 }
662 auto screenNode = screenNode_.Upgrade();
663 if (!screenNode) {
664 return;
665 }
666 ACE_SCOPED_TRACE("FlushWindowPatternInfo");
667 auto instance = WindowSceneLayoutManager::GetInstance();
668 if (instance != nullptr) {
669 instance->FlushWindowPatternInfo(screenNode);
670 }
671 #endif
672 }
673
InspectDrew()674 void PipelineContext::InspectDrew()
675 {
676 CHECK_RUN_ON(UI);
677 if (!needRenderNode_.empty()) {
678 auto needRenderNode = std::move(needRenderNode_);
679 for (auto&& nodeWeak : needRenderNode) {
680 auto node = nodeWeak.Upgrade();
681 if (node) {
682 OnDrawCompleted(node->GetInspectorId()->c_str());
683 }
684 }
685 }
686 }
687
ProcessDelayTasks()688 void PipelineContext::ProcessDelayTasks()
689 {
690 if (delayedTasks_.empty()) {
691 return;
692 }
693 auto currentTimeStamp = GetSysTimestamp();
694 auto delayedTasks = std::move(delayedTasks_);
695 auto result = std::remove_if(delayedTasks.begin(), delayedTasks.end(), [this, currentTimeStamp](const auto& task) {
696 if (task.timeStamp + static_cast<int64_t>(task.time) * MILLISECONDS_TO_NANOSECONDS > currentTimeStamp) {
697 delayedTasks_.emplace_back(task);
698 return true;
699 }
700 return false;
701 });
702 delayedTasks.erase(result, delayedTasks.end());
703 std::for_each(delayedTasks.begin(), delayedTasks.end(), [this](auto& delayedTask) {
704 if (delayedTask.task) {
705 delayedTask.task();
706 }
707 });
708 }
709
DispatchDisplaySync(uint64_t nanoTimestamp)710 void PipelineContext::DispatchDisplaySync(uint64_t nanoTimestamp)
711 {
712 CHECK_RUN_ON(UI);
713 ACE_FUNCTION_TRACE();
714
715 GetOrCreateUIDisplaySyncManager()->SetRefreshRateMode(window_->GetCurrentRefreshRateMode());
716 GetOrCreateUIDisplaySyncManager()->SetVsyncPeriod(window_->GetVSyncPeriod());
717
718 if (FrameReport::GetInstance().GetEnable()) {
719 FrameReport::GetInstance().BeginFlushAnimation();
720 }
721
722 scheduleTasks_.clear();
723 GetOrCreateUIDisplaySyncManager()->DispatchFunc(nanoTimestamp);
724
725 if (FrameReport::GetInstance().GetEnable()) {
726 FrameReport::GetInstance().EndFlushAnimation();
727 }
728
729 int32_t displaySyncRate = GetOrCreateUIDisplaySyncManager()->GetDisplaySyncRate();
730 frameRateManager_->SetDisplaySyncRate(displaySyncRate);
731 ArkUIPerfMonitor::GetInstance().RecordDisplaySyncRate(displaySyncRate);
732 }
733
FlushAnimation(uint64_t nanoTimestamp)734 void PipelineContext::FlushAnimation(uint64_t nanoTimestamp)
735 {
736 CHECK_RUN_ON(UI);
737 ACE_FUNCTION_TRACE();
738 if (scheduleTasks_.empty()) {
739 return;
740 }
741 }
742
FlushModifier()743 void PipelineContext::FlushModifier()
744 {
745 window_->FlushModifier();
746 }
747
FlushMessages()748 void PipelineContext::FlushMessages()
749 {
750 ACE_FUNCTION_TRACE();
751 if (IsFreezeFlushMessage()) {
752 SetIsFreezeFlushMessage(false);
753 LOGI("Flush message is freezed.");
754 return;
755 }
756 window_->FlushTasks();
757 }
758
FlushUITasks(bool triggeredByImplicitAnimation)759 void PipelineContext::FlushUITasks(bool triggeredByImplicitAnimation)
760 {
761 window_->Lock();
762 if (!CheckThreadSafe()) {
763 LOGW("FlushUITasks doesn't run on UI thread!");
764 }
765 decltype(dirtyPropertyNodes_) dirtyPropertyNodes(std::move(dirtyPropertyNodes_));
766 dirtyPropertyNodes_.clear();
767 for (const auto& dirtyNode : dirtyPropertyNodes) {
768 dirtyNode->ProcessPropertyDiff();
769 }
770 taskScheduler_->FlushTaskWithCheck(triggeredByImplicitAnimation);
771 window_->Unlock();
772 }
773
FlushUITaskWithSingleDirtyNode(const RefPtr<FrameNode> & node)774 void PipelineContext::FlushUITaskWithSingleDirtyNode(const RefPtr<FrameNode>& node)
775 {
776 CHECK_NULL_VOID(node);
777 if (IsLayouting()) {
778 taskScheduler_->AddSingleNodeToFlush(node);
779 return;
780 }
781 auto layoutProperty = node->GetLayoutProperty();
782 CHECK_NULL_VOID(layoutProperty);
783 auto layoutConstraint = node->GetLayoutConstraint();
784 auto originLayoutingFlag = IsLayouting();
785 SetIsLayouting(true);
786 if (layoutProperty->GetLayoutRect()) {
787 node->SetActive(true, true);
788 node->Measure(std::nullopt);
789 node->Layout();
790 } else {
791 auto ancestorNodeOfFrame = node->GetAncestorNodeOfFrame();
792 {
793 ACE_SCOPED_TRACE("FlushUITaskWithSingleDirtyNodeMeasure[%s][self:%d][parent:%d][layoutConstraint:%s]"
794 "[pageId:%d][depth:%d]",
795 node->GetTag().c_str(), node->GetId(), ancestorNodeOfFrame ? ancestorNodeOfFrame->GetId() : 0,
796 layoutConstraint.ToString().c_str(), node->GetPageId(), node->GetDepth());
797 node->Measure(layoutConstraint);
798 }
799 {
800 ACE_SCOPED_TRACE("FlushUITaskWithSingleDirtyNodeLayout[%s][self:%d][parent:%d][pageId:%d][depth:%d]",
801 node->GetTag().c_str(), node->GetId(), ancestorNodeOfFrame ? ancestorNodeOfFrame->GetId() : 0,
802 node->GetPageId(), node->GetDepth());
803 node->Layout();
804 }
805 }
806 SetIsLayouting(originLayoutingFlag);
807 }
808
FlushAfterLayoutCallbackInImplicitAnimationTask()809 void PipelineContext::FlushAfterLayoutCallbackInImplicitAnimationTask()
810 {
811 if (AnimationUtils::IsImplicitAnimationOpen()) {
812 TAG_LOGI(AceLogTag::ACE_ANIMATION,
813 "Can not flush implicit animation task after layout because implicit animation is open.");
814 return;
815 }
816 window_->Lock();
817 taskScheduler_->FlushAfterLayoutCallbackInImplicitAnimationTask();
818 window_->Unlock();
819 }
820
SetNeedRenderNode(const WeakPtr<FrameNode> & node)821 void PipelineContext::SetNeedRenderNode(const WeakPtr<FrameNode>& node)
822 {
823 CHECK_RUN_ON(UI);
824 needRenderNode_.insert(node);
825 }
826
FlushFocus()827 void PipelineContext::FlushFocus()
828 {
829 CHECK_RUN_ON(UI);
830 ACE_FUNCTION_TRACK();
831 ACE_FUNCTION_TRACE();
832
833 FlushRequestFocus();
834
835 auto focusNode = dirtyFocusNode_.Upgrade();
836 if (!focusNode || focusNode->GetFocusType() != FocusType::NODE) {
837 dirtyFocusNode_.Reset();
838 } else {
839 FlushFocusWithNode(focusNode, false);
840 return;
841 }
842 auto focusScope = dirtyFocusScope_.Upgrade();
843 if (!focusScope || focusScope->GetFocusType() != FocusType::SCOPE) {
844 dirtyFocusScope_.Reset();
845 } else {
846 FlushFocusWithNode(focusScope, true);
847 return;
848 }
849 focusManager_->WindowFocusMoveEnd();
850 }
851
FlushFocusWithNode(RefPtr<FrameNode> focusNode,bool isScope)852 void PipelineContext::FlushFocusWithNode(RefPtr<FrameNode> focusNode, bool isScope)
853 {
854 auto focusNodeHub = focusNode->GetFocusHub();
855 if (focusNodeHub && !focusNodeHub->RequestFocusImmediately()) {
856 auto unfocusableParentFocusNode = focusNodeHub->GetUnfocusableParentFocusNode().Upgrade();
857 if (unfocusableParentFocusNode) {
858 TAG_LOGI(AceLogTag::ACE_FOCUS,
859 "Request focus on %{public}s: %{public}s/%{public}d return false, unfocusable node: "
860 "%{public}s/%{public}d, focusable = %{public}d, shown = %{public}d, enabled = %{public}d",
861 isScope ? "scope" : "node", focusNode->GetTag().c_str(), focusNode->GetId(),
862 unfocusableParentFocusNode->GetFrameName().c_str(), unfocusableParentFocusNode->GetFrameId(),
863 unfocusableParentFocusNode->GetFocusable(), unfocusableParentFocusNode->IsShow(),
864 unfocusableParentFocusNode->IsEnabled());
865 unfocusableParentFocusNode = nullptr;
866 } else {
867 TAG_LOGI(AceLogTag::ACE_FOCUS, "Request focus on %{public}s: %{public}s/%{public}d return false",
868 isScope ? "scope" : "node", focusNode->GetTag().c_str(), focusNode->GetId());
869 }
870 }
871 dirtyFocusNode_.Reset();
872 dirtyFocusScope_.Reset();
873 dirtyRequestFocusNode_.Reset();
874 focusManager_->WindowFocusMoveEnd();
875 }
876
FlushRequestFocus()877 void PipelineContext::FlushRequestFocus()
878 {
879 CHECK_RUN_ON(UI);
880
881 auto requestFocusNode = dirtyRequestFocusNode_.Upgrade();
882 if (!requestFocusNode) {
883 dirtyRequestFocusNode_.Reset();
884 } else {
885 auto focusNodeHub = requestFocusNode->GetFocusHub();
886 if (focusNodeHub && !focusNodeHub->RequestFocusImmediately()) {
887 auto unfocusableParentFocusNode = focusNodeHub->GetUnfocusableParentFocusNode().Upgrade();
888 if (unfocusableParentFocusNode) {
889 TAG_LOGI(AceLogTag::ACE_FOCUS,
890 "Request focus by id on node: %{public}s/%{public}d return false, unfocusable node: "
891 "%{public}s/%{public}d, focusable = %{public}d, shown = %{public}d, enabled = %{public}d",
892 requestFocusNode->GetTag().c_str(), requestFocusNode->GetId(),
893 unfocusableParentFocusNode->GetFrameName().c_str(), unfocusableParentFocusNode->GetFrameId(),
894 unfocusableParentFocusNode->GetFocusable(), unfocusableParentFocusNode->IsShow(),
895 unfocusableParentFocusNode->IsEnabled());
896 unfocusableParentFocusNode = nullptr;
897 } else {
898 TAG_LOGI(AceLogTag::ACE_FOCUS, "Request focus by id on node: %{public}s/%{public}d return false",
899 requestFocusNode->GetTag().c_str(), requestFocusNode->GetId());
900 }
901 }
902 dirtyFocusNode_.Reset();
903 dirtyFocusScope_.Reset();
904 dirtyRequestFocusNode_.Reset();
905 return;
906 }
907 }
908
FlushFocusView()909 void PipelineContext::FlushFocusView()
910 {
911 CHECK_NULL_VOID(focusManager_);
912 auto lastFocusView = (focusManager_->GetLastFocusView()).Upgrade();
913 CHECK_NULL_VOID(lastFocusView);
914 auto lastFocusViewHub = lastFocusView->GetFocusHub();
915 CHECK_NULL_VOID(lastFocusViewHub);
916 auto container = Container::Current();
917 if (container && (container->IsUIExtensionWindow() || container->IsDynamicRender()) &&
918 (!lastFocusView->IsRootScopeCurrentFocus())) {
919 lastFocusView->SetIsViewRootScopeFocused(false);
920 }
921 if (lastFocusView && (!lastFocusView->IsRootScopeCurrentFocus() || !lastFocusView->GetIsViewHasFocused()) &&
922 lastFocusViewHub->IsFocusableNode()) {
923 lastFocusView->RequestDefaultFocus();
924 focusManager_->SetFocusViewStackState(FocusViewStackState::IDLE);
925 }
926 }
927
FlushFocusScroll()928 void PipelineContext::FlushFocusScroll()
929 {
930 CHECK_NULL_VOID(focusManager_);
931 if (!focusManager_->GetNeedTriggerScroll()) {
932 return;
933 }
934 auto lastFocusStateNode = focusManager_->GetLastFocusStateNode();
935 CHECK_NULL_VOID(lastFocusStateNode);
936 if (!lastFocusStateNode->TriggerFocusScroll()) {
937 focusManager_->SetNeedTriggerScroll(false);
938 }
939 }
940
FlushPipelineImmediately()941 void PipelineContext::FlushPipelineImmediately()
942 {
943 CHECK_RUN_ON(UI);
944 ACE_FUNCTION_TRACE();
945 FlushPipelineWithoutAnimation();
946 }
947
RebuildFontNode()948 void PipelineContext::RebuildFontNode()
949 {
950 if (fontManager_) {
951 fontManager_->RebuildFontNodeNG();
952 }
953 }
954
FlushPipelineWithoutAnimation()955 void PipelineContext::FlushPipelineWithoutAnimation()
956 {
957 ACE_FUNCTION_TRACE();
958 window_->Lock();
959 FlushBuild();
960 FlushTouchEvents();
961 taskScheduler_->FlushTask();
962 FlushAnimationClosure();
963 window_->FlushModifier();
964 FlushMessages();
965 FlushFocus();
966 window_->Unlock();
967 }
968
FlushFrameRate()969 void PipelineContext::FlushFrameRate()
970 {
971 frameRateManager_->SetAnimateRate(window_->GetAnimateExpectedRate());
972 int32_t currAnimatorExpectedFrameRate = GetOrCreateUIDisplaySyncManager()->GetAnimatorRate();
973 if (frameRateManager_->IsRateChanged() || currAnimatorExpectedFrameRate != lastAnimatorExpectedFrameRate_) {
974 auto [rate, rateType] = frameRateManager_->GetExpectedRate();
975 ACE_SCOPED_TRACE("FlushFrameRate Expected frameRate = %d frameRateType = %d "
976 "currAnimatorExpectedFrameRate = %d, lastAnimatorExpectedFrameRate = %d",
977 rate, rateType, currAnimatorExpectedFrameRate, lastAnimatorExpectedFrameRate_);
978 TAG_LOGD(AceLogTag::ACE_DISPLAY_SYNC, "FlushFrameRate Expected frameRate = %{public}d "
979 "frameRateType = %{public}d currAnimatorExpectedFrameRate = %{public}d, lastRate = %{public}d",
980 rate, rateType, currAnimatorExpectedFrameRate, lastAnimatorExpectedFrameRate_);
981 window_->FlushFrameRate(rate, currAnimatorExpectedFrameRate, rateType);
982 frameRateManager_->SetIsRateChanged(false);
983 lastAnimatorExpectedFrameRate_ = currAnimatorExpectedFrameRate;
984 }
985 }
986
FlushBuild()987 void PipelineContext::FlushBuild()
988 {
989 if (vsyncListener_ != nullptr) {
990 ACE_SCOPED_TRACE("arkoala build");
991 vsyncListener_();
992 }
993 FlushOnceVsyncTask();
994 isRebuildFinished_ = false;
995 FlushDirtyNodeUpdate();
996 isRebuildFinished_ = true;
997 FlushBuildFinishCallbacks();
998 }
999
AddAnimationClosure(std::function<void ()> && animation)1000 void PipelineContext::AddAnimationClosure(std::function<void()>&& animation)
1001 {
1002 animationClosuresList_.emplace_back(std::move(animation));
1003 }
1004
FlushAnimationClosure()1005 void PipelineContext::FlushAnimationClosure()
1006 {
1007 if (animationClosuresList_.empty()) {
1008 return;
1009 }
1010 window_->Lock();
1011 taskScheduler_->FlushTask();
1012
1013 decltype(animationClosuresList_) temp(std::move(animationClosuresList_));
1014 for (const auto& animation : temp) {
1015 animation();
1016 }
1017 window_->Unlock();
1018 }
1019
FlushBuildFinishCallbacks()1020 void PipelineContext::FlushBuildFinishCallbacks()
1021 {
1022 decltype(buildFinishCallbacks_) buildFinishCallbacks(std::move(buildFinishCallbacks_));
1023 for (const auto& func : buildFinishCallbacks) {
1024 if (func) {
1025 func();
1026 }
1027 }
1028 }
1029
RegisterRootEvent()1030 void PipelineContext::RegisterRootEvent()
1031 {
1032 if (!IsFormRender()) {
1033 return;
1034 }
1035 auto accessibilityProperty = rootNode_->GetAccessibilityProperty<AccessibilityProperty>();
1036 if (accessibilityProperty != nullptr) {
1037 accessibilityProperty->SetAccessibilityLevel(AccessibilityProperty::Level::NO_STR);
1038 }
1039
1040 // To avoid conflicts between longPress and click events on the card,
1041 // use an empty longPress event placeholder in the EtsCard scenario
1042 auto hub = rootNode_->GetOrCreateGestureEventHub();
1043 CHECK_NULL_VOID(hub);
1044 auto event = [](const GestureEvent& info) mutable {};
1045 auto longPress = AceType::MakeRefPtr<NG::LongPressEvent>(std::move(event));
1046 hub->SetLongPressEvent(longPress, false, true);
1047 }
1048
SetupRootElement()1049 void PipelineContext::SetupRootElement()
1050 {
1051 CHECK_RUN_ON(UI);
1052 rootNode_ = FrameNode::CreateFrameNodeWithTree(
1053 V2::ROOT_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), MakeRefPtr<RootPattern>());
1054 rootNode_->SetHostRootId(GetInstanceId());
1055 rootNode_->SetHostPageId(-1);
1056 rootNode_->SetActive(true);
1057 RegisterRootEvent();
1058 CalcSize idealSize { CalcLength(rootWidth_), CalcLength(rootHeight_) };
1059 MeasureProperty layoutConstraint;
1060 layoutConstraint.selfIdealSize = idealSize;
1061 layoutConstraint.maxSize = idealSize;
1062 rootNode_->UpdateLayoutConstraint(layoutConstraint);
1063 auto rootFocusHub = rootNode_->GetOrCreateFocusHub();
1064 rootFocusHub->SetFocusType(FocusType::SCOPE);
1065 rootFocusHub->SetFocusable(true);
1066 window_->SetRootFrameNode(rootNode_);
1067 rootNode_->AttachToMainTree(false, this);
1068 auto stagePattern = ViewAdvancedRegister::GetInstance()->GeneratePattern(V2::STAGE_ETS_TAG);
1069 if (!stagePattern) {
1070 stagePattern = MakeRefPtr<StagePattern>();
1071 }
1072 auto stageNode = FrameNode::CreateFrameNode(
1073 V2::STAGE_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), stagePattern);
1074 RefPtr<AppBarView> appBar = AceType::MakeRefPtr<AppBarView>();
1075 auto atomicService = installationFree_ ? appBar->Create(stageNode) : nullptr;
1076 auto container = Container::Current();
1077 if (container) {
1078 container->SetAppBar(appBar);
1079 }
1080 if (windowModal_ == WindowModal::CONTAINER_MODAL) {
1081 MaximizeMode maximizeMode = GetWindowManager()->GetWindowMaximizeMode();
1082 rootNode_->AddChild(
1083 ContainerModalViewFactory::GetView(atomicService ? atomicService : stageNode, maximizeMode));
1084 } else {
1085 rootNode_->AddChild(atomicService ? atomicService : stageNode);
1086 }
1087 #ifdef ENABLE_ROSEN_BACKEND
1088 if (!IsJsCard() && !isFormRender_) {
1089 auto window = GetWindow();
1090 if (window) {
1091 auto rsUIDirector = window->GetRSUIDirector();
1092 if (rsUIDirector) {
1093 rsUIDirector->SetAbilityBGAlpha(appBgColor_.GetAlpha());
1094 }
1095 }
1096 }
1097 #endif
1098 #ifdef WINDOW_SCENE_SUPPORTED
1099 uiExtensionManager_ = MakeRefPtr<UIExtensionManager>();
1100 #endif
1101 accessibilityManagerNG_ = MakeRefPtr<AccessibilityManagerNG>();
1102 stageManager_ = ViewAdvancedRegister::GetInstance()->GenerateStageManager(stageNode);
1103 if (!stageManager_) {
1104 stageManager_ = MakeRefPtr<StageManager>(stageNode);
1105 }
1106 overlayManager_ = MakeRefPtr<OverlayManager>(
1107 DynamicCast<FrameNode>(installationFree_ ? stageNode->GetParent()->GetParent() : stageNode->GetParent()));
1108 fullScreenManager_ = MakeRefPtr<FullScreenManager>(rootNode_);
1109 selectOverlayManager_ = MakeRefPtr<SelectOverlayManager>(rootNode_);
1110 fontManager_->AddFontObserver(selectOverlayManager_);
1111 if (!privacySensitiveManager_) {
1112 privacySensitiveManager_ = MakeRefPtr<PrivacySensitiveManager>();
1113 }
1114 postEventManager_ = MakeRefPtr<PostEventManager>();
1115 dragDropManager_ = MakeRefPtr<DragDropManager>();
1116 focusManager_ = GetOrCreateFocusManager();
1117 sharedTransitionManager_ = MakeRefPtr<SharedOverlayManager>(
1118 DynamicCast<FrameNode>(installationFree_ ? stageNode->GetParent()->GetParent() : stageNode->GetParent()));
1119
1120 OnAreaChangedFunc onAreaChangedFunc = [weakOverlayManger = AceType::WeakClaim(AceType::RawPtr(overlayManager_))](
1121 const RectF& /* oldRect */, const OffsetF& /* oldOrigin */,
1122 const RectF& /* rect */, const OffsetF& /* origin */) {
1123 TAG_LOGD(AceLogTag::ACE_OVERLAY, "start OnAreaChangedFunc");
1124 auto overlay = weakOverlayManger.Upgrade();
1125 CHECK_NULL_VOID(overlay);
1126 overlay->HideAllMenus();
1127 SubwindowManager::GetInstance()->HideMenuNG(false);
1128 overlay->HideCustomPopups();
1129 SubwindowManager::GetInstance()->ClearToastInSubwindow();
1130 SubwindowManager::GetInstance()->ClearToastInSystemSubwindow();
1131 overlay->UpdateCustomKeyboardPosition();
1132 };
1133 rootNode_->SetOnAreaChangeCallback(std::move(onAreaChangedFunc));
1134 AddOnAreaChangeNode(rootNode_->GetId());
1135 }
1136
SetOnWindowFocused(const std::function<void ()> & callback)1137 void PipelineContext::SetOnWindowFocused(const std::function<void()>& callback)
1138 {
1139 CHECK_NULL_VOID(taskExecutor_);
1140 taskExecutor_->PostTask([weak = WeakClaim(this), callback]() {
1141 auto pipeline = weak.Upgrade();
1142 CHECK_NULL_VOID(pipeline);
1143 pipeline->focusOnNodeCallback_ = callback;
1144 }, TaskExecutor::TaskType::UI, "ArkUISetOnWindowFocusedCallback");
1145 }
1146
SetupSubRootElement()1147 void PipelineContext::SetupSubRootElement()
1148 {
1149 CHECK_RUN_ON(UI);
1150 appBgColor_ = Color::TRANSPARENT;
1151 rootNode_ = FrameNode::CreateFrameNodeWithTree(
1152 V2::ROOT_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), MakeRefPtr<RootPattern>());
1153 rootNode_->SetHostRootId(GetInstanceId());
1154 rootNode_->SetHostPageId(-1);
1155 rootNode_->SetActive(true);
1156 CalcSize idealSize { CalcLength(rootWidth_), CalcLength(rootHeight_) };
1157 MeasureProperty layoutConstraint;
1158 layoutConstraint.selfIdealSize = idealSize;
1159 layoutConstraint.maxSize = idealSize;
1160 rootNode_->UpdateLayoutConstraint(layoutConstraint);
1161 auto rootFocusHub = rootNode_->GetOrCreateFocusHub();
1162 rootFocusHub->SetFocusType(FocusType::SCOPE);
1163 rootFocusHub->SetFocusable(true);
1164 window_->SetRootFrameNode(rootNode_);
1165 rootNode_->AttachToMainTree(false, this);
1166
1167 #ifdef ENABLE_ROSEN_BACKEND
1168 if (!IsJsCard()) {
1169 auto window = GetWindow();
1170 if (window) {
1171 auto rsUIDirector = window->GetRSUIDirector();
1172 if (rsUIDirector) {
1173 rsUIDirector->SetAbilityBGAlpha(appBgColor_.GetAlpha());
1174 }
1175 }
1176 }
1177 #endif
1178 #ifdef WINDOW_SCENE_SUPPORTED
1179 uiExtensionManager_ = MakeRefPtr<UIExtensionManager>();
1180 #endif
1181 accessibilityManagerNG_ = MakeRefPtr<AccessibilityManagerNG>();
1182 // the subwindow for overlay not need stage
1183 stageManager_ = ViewAdvancedRegister::GetInstance()->GenerateStageManager(nullptr);
1184 if (!stageManager_) {
1185 stageManager_ = MakeRefPtr<StageManager>(nullptr);
1186 }
1187 overlayManager_ = MakeRefPtr<OverlayManager>(rootNode_);
1188 fullScreenManager_ = MakeRefPtr<FullScreenManager>(rootNode_);
1189 selectOverlayManager_ = MakeRefPtr<SelectOverlayManager>(rootNode_);
1190 fontManager_->AddFontObserver(selectOverlayManager_);
1191 dragDropManager_ = MakeRefPtr<DragDropManager>();
1192 focusManager_ = GetOrCreateFocusManager();
1193 postEventManager_ = MakeRefPtr<PostEventManager>();
1194 }
1195
GetAccessibilityManagerNG()1196 RefPtr<AccessibilityManagerNG> PipelineContext::GetAccessibilityManagerNG()
1197 {
1198 return accessibilityManagerNG_;
1199 }
1200
SendEventToAccessibilityWithNode(const AccessibilityEvent & accessibilityEvent,const RefPtr<FrameNode> & node)1201 void PipelineContext::SendEventToAccessibilityWithNode(
1202 const AccessibilityEvent& accessibilityEvent, const RefPtr<FrameNode>& node)
1203 {
1204 auto accessibilityManager = GetAccessibilityManager();
1205 if (!accessibilityManager || !AceApplicationInfo::GetInstance().IsAccessibilityEnabled()) {
1206 return;
1207 }
1208 accessibilityManager->SendEventToAccessibilityWithNode(accessibilityEvent, node, Claim(this));
1209 }
1210
GetStageManager()1211 const RefPtr<StageManager>& PipelineContext::GetStageManager()
1212 {
1213 return stageManager_;
1214 }
1215
GetDragDropManager()1216 const RefPtr<DragDropManager>& PipelineContext::GetDragDropManager()
1217 {
1218 return dragDropManager_;
1219 }
1220
GetFocusManager() const1221 const RefPtr<FocusManager>& PipelineContext::GetFocusManager() const
1222 {
1223 return focusManager_;
1224 }
1225
GetOrCreateFocusManager()1226 const RefPtr<FocusManager>& PipelineContext::GetOrCreateFocusManager()
1227 {
1228 if (!focusManager_) {
1229 focusManager_ = MakeRefPtr<FocusManager>(AceType::Claim(this));
1230 RegisterFocusCallback();
1231 }
1232 return focusManager_;
1233 }
1234
GetSelectOverlayManager()1235 const RefPtr<SelectOverlayManager>& PipelineContext::GetSelectOverlayManager()
1236 {
1237 return selectOverlayManager_;
1238 }
1239
GetOverlayManager()1240 const RefPtr<OverlayManager>& PipelineContext::GetOverlayManager()
1241 {
1242 return overlayManager_;
1243 }
1244
GetFullScreenManager()1245 const RefPtr<FullScreenManager>& PipelineContext::GetFullScreenManager()
1246 {
1247 return fullScreenManager_;
1248 }
1249
OnSurfaceChanged(int32_t width,int32_t height,WindowSizeChangeReason type,const std::shared_ptr<Rosen::RSTransaction> & rsTransaction)1250 void PipelineContext::OnSurfaceChanged(int32_t width, int32_t height, WindowSizeChangeReason type,
1251 const std::shared_ptr<Rosen::RSTransaction>& rsTransaction)
1252 {
1253 CHECK_RUN_ON(UI);
1254 width_ = width;
1255 height_ = height;
1256 if (NearEqual(rootWidth_, width) && NearEqual(rootHeight_, height) &&
1257 type == WindowSizeChangeReason::CUSTOM_ANIMATION && !isDensityChanged_) {
1258 TryCallNextFrameLayoutCallback();
1259 return;
1260 }
1261 ExecuteSurfaceChangedCallbacks(width, height, type);
1262 auto callback = [weakFrontend = weakFrontend_, width, height]() {
1263 auto frontend = weakFrontend.Upgrade();
1264 if (frontend) {
1265 frontend->OnSurfaceChanged(width, height);
1266 }
1267 };
1268 auto container = Container::Current();
1269 if (!container) {
1270 return;
1271 }
1272 if (container->IsUseStageModel()) {
1273 callback();
1274 FlushBuild();
1275 } else {
1276 taskExecutor_->PostTask(callback, TaskExecutor::TaskType::JS, "ArkUISurfaceChanged");
1277 }
1278
1279 FlushWindowSizeChangeCallback(width, height, type);
1280 UpdateHalfFoldHoverProperty(width, height);
1281 UpdateSizeChangeReason(type, rsTransaction);
1282
1283 #ifdef ENABLE_ROSEN_BACKEND
1284 StartWindowSizeChangeAnimate(width, height, type, rsTransaction);
1285 #else
1286 SetRootRect(width, height, 0.0);
1287 #endif
1288 }
1289
UpdateHalfFoldHoverProperty(int32_t windowWidth,int32_t windowHeight)1290 void PipelineContext::UpdateHalfFoldHoverProperty(int32_t windowWidth, int32_t windowHeight)
1291 {
1292 isHoverModeChanged_ = false;
1293 preIsHalfFoldHoverStatus_ = isHalfFoldHoverStatus_;
1294 UpdateHalfFoldHoverStatus(windowWidth, windowHeight);
1295 if (preIsHalfFoldHoverStatus_ != isHalfFoldHoverStatus_) {
1296 isHoverModeChanged_ = true;
1297 }
1298 }
1299
OnLayoutCompleted(const std::string & componentId)1300 void PipelineContext::OnLayoutCompleted(const std::string& componentId)
1301 {
1302 CHECK_RUN_ON(UI);
1303 auto frontend = weakFrontend_.Upgrade();
1304 if (frontend) {
1305 frontend->OnLayoutCompleted(componentId);
1306 }
1307 }
1308
OnDrawCompleted(const std::string & componentId)1309 void PipelineContext::OnDrawCompleted(const std::string& componentId)
1310 {
1311 CHECK_RUN_ON(UI);
1312 auto frontend = weakFrontend_.Upgrade();
1313 if (frontend) {
1314 frontend->OnDrawCompleted(componentId);
1315 }
1316 }
1317
ExecuteSurfaceChangedCallbacks(int32_t newWidth,int32_t newHeight,WindowSizeChangeReason type)1318 void PipelineContext::ExecuteSurfaceChangedCallbacks(int32_t newWidth, int32_t newHeight, WindowSizeChangeReason type)
1319 {
1320 for (auto&& [id, callback] : surfaceChangedCallbackMap_) {
1321 if (callback) {
1322 callback(newWidth, newHeight, rootWidth_, rootHeight_, type);
1323 }
1324 }
1325 }
1326
OnSurfacePositionChanged(int32_t posX,int32_t posY)1327 void PipelineContext::OnSurfacePositionChanged(int32_t posX, int32_t posY)
1328 {
1329 for (auto&& [id, callback] : surfacePositionChangedCallbackMap_) {
1330 if (callback) {
1331 callback(posX, posY);
1332 }
1333 }
1334 }
1335
OnFoldStatusChange(FoldStatus foldStatus)1336 void PipelineContext::OnFoldStatusChange(FoldStatus foldStatus)
1337 {
1338 for (auto&& [id, callback] : foldStatusChangedCallbackMap_) {
1339 if (callback) {
1340 callback(foldStatus);
1341 }
1342 }
1343 StartFoldStatusDelayTask(foldStatus);
1344 }
1345
OnFoldDisplayModeChange(FoldDisplayMode foldDisplayMode)1346 void PipelineContext::OnFoldDisplayModeChange(FoldDisplayMode foldDisplayMode)
1347 {
1348 for (auto&& [id, callback] : foldDisplayModeChangedCallbackMap_) {
1349 if (callback) {
1350 callback(foldDisplayMode);
1351 }
1352 }
1353 }
1354
OnTransformHintChanged(uint32_t transform)1355 void PipelineContext::OnTransformHintChanged(uint32_t transform)
1356 {
1357 for (auto&& [id, callback] : transformHintChangedCallbackMap_) {
1358 if (callback) {
1359 callback(transform);
1360 }
1361 }
1362 transform_ = transform;
1363 }
1364
StartWindowSizeChangeAnimate(int32_t width,int32_t height,WindowSizeChangeReason type,const std::shared_ptr<Rosen::RSTransaction> & rsTransaction)1365 void PipelineContext::StartWindowSizeChangeAnimate(int32_t width, int32_t height, WindowSizeChangeReason type,
1366 const std::shared_ptr<Rosen::RSTransaction>& rsTransaction)
1367 {
1368 static const bool IsWindowSizeAnimationEnabled = SystemProperties::IsWindowSizeAnimationEnabled();
1369 if (!IsWindowSizeAnimationEnabled) {
1370 SetRootRect(width, height, 0.0);
1371 return;
1372 }
1373 switch (type) {
1374 case WindowSizeChangeReason::FULL_TO_SPLIT:
1375 case WindowSizeChangeReason::FULL_TO_FLOATING: {
1376 StartFullToMultWindowAnimation(width, height, type, rsTransaction);
1377 break;
1378 }
1379 case WindowSizeChangeReason::RECOVER:
1380 case WindowSizeChangeReason::MAXIMIZE: {
1381 StartWindowMaximizeAnimation(width, height, rsTransaction);
1382 break;
1383 }
1384 case WindowSizeChangeReason::ROTATION: {
1385 if (UsingCaretAvoidMode()) {
1386 safeAreaManager_->UpdateKeyboardSafeArea(0.0f);
1387 }
1388 safeAreaManager_->UpdateKeyboardOffset(0.0);
1389 SetRootRect(width, height, 0.0);
1390 FlushUITasks();
1391 if (textFieldManager_) {
1392 DynamicCast<TextFieldManagerNG>(textFieldManager_)->ScrollTextFieldToSafeArea();
1393 }
1394 FlushUITasks();
1395 if (!textFieldManager_) {
1396 break;
1397 }
1398 PostKeyboardAvoidTask();
1399 break;
1400 }
1401 case WindowSizeChangeReason::DRAG_START:
1402 case WindowSizeChangeReason::DRAG:
1403 case WindowSizeChangeReason::DRAG_END:
1404 case WindowSizeChangeReason::RESIZE:
1405 case WindowSizeChangeReason::UNDEFINED:
1406 default: {
1407 SetRootRect(width, height, 0.0f);
1408 }
1409 }
1410 }
1411
PostKeyboardAvoidTask()1412 void PipelineContext::PostKeyboardAvoidTask()
1413 {
1414 auto textFieldManager = DynamicCast<TextFieldManagerNG>(textFieldManager_);
1415 CHECK_NULL_VOID(textFieldManager);
1416 if (textFieldManager->UsingCustomKeyboardAvoid()) {
1417 taskExecutor_->PostTask(
1418 [weak = WeakPtr<TextFieldManagerNG>(textFieldManager)] {
1419 auto manager = weak.Upgrade();
1420 CHECK_NULL_VOID(manager);
1421 manager->TriggerCustomKeyboardAvoid();
1422 },
1423 TaskExecutor::TaskType::UI, "ArkUICustomKeyboardAvoid");
1424 return;
1425 }
1426 CHECK_NULL_VOID(textFieldManager->GetLaterAvoid());
1427 auto container = Container::Current();
1428 if (container) {
1429 auto displayInfo = container->GetDisplayInfo();
1430 if (displayInfo && textFieldManager->GetLaterOrientation() != (int32_t)displayInfo->GetRotation()) {
1431 TAG_LOGI(AceLogTag::ACE_KEYBOARD, "orientation not match, clear laterAvoid");
1432 textFieldManager->SetLaterAvoid(false);
1433 return;
1434 }
1435 }
1436 TAG_LOGI(AceLogTag::ACE_KEYBOARD, "after rotation set root, trigger avoid now");
1437 taskExecutor_->PostTask(
1438 [weakContext = WeakClaim(this), keyboardRect = textFieldManager->GetLaterAvoidKeyboardRect(),
1439 positionY = textFieldManager->GetLaterAvoidPositionY(),
1440 height = textFieldManager->GetLaterAvoidHeight(),
1441 weakManager = WeakPtr<TextFieldManagerNG>(textFieldManager)] {
1442 auto context = weakContext.Upgrade();
1443 CHECK_NULL_VOID(context);
1444 context->OnVirtualKeyboardAreaChange(keyboardRect, positionY, height);
1445 auto manager = weakManager.Upgrade();
1446 CHECK_NULL_VOID(manager);
1447 manager->SetLaterAvoid(false);
1448 },
1449 TaskExecutor::TaskType::UI, "ArkUIVirtualKeyboardAreaChange");
1450 }
1451
StartWindowMaximizeAnimation(int32_t width,int32_t height,const std::shared_ptr<Rosen::RSTransaction> & rsTransaction)1452 void PipelineContext::StartWindowMaximizeAnimation(
1453 int32_t width, int32_t height, const std::shared_ptr<Rosen::RSTransaction>& rsTransaction)
1454 {
1455 TAG_LOGI(AceLogTag::ACE_ANIMATION,
1456 "Root node start RECOVER/MAXIMIZE animation, width = %{public}d, height = %{public}d", width, height);
1457 #ifdef ENABLE_ROSEN_BACKEND
1458 if (rsTransaction) {
1459 FlushMessages();
1460 rsTransaction->Begin();
1461 }
1462 #endif
1463 AnimationOption option;
1464 int32_t duration = 400;
1465 MaximizeMode maximizeMode = GetWindowManager()->GetWindowMaximizeMode();
1466 bool freeMultiWindowModeEnabled = GetWindowManager()->GetFreeMultiWindowModeEnabledState();
1467 if (maximizeMode == MaximizeMode::MODE_FULL_FILL || maximizeMode == MaximizeMode::MODE_AVOID_SYSTEM_BAR ||
1468 freeMultiWindowModeEnabled) {
1469 int32_t preWidth = GetRootRect().Width();
1470 int32_t preHeight = GetRootRect().Height();
1471 if (width > preWidth && height > preHeight) {
1472 duration = 0;
1473 }
1474 }
1475 option.SetDuration(duration);
1476 auto curve = Curves::EASE_OUT;
1477 option.SetCurve(curve);
1478 auto weak = WeakClaim(this);
1479 Animate(option, curve, [width, height, weak]() {
1480 auto pipeline = weak.Upgrade();
1481 CHECK_NULL_VOID(pipeline);
1482 pipeline->SetRootRect(width, height, 0.0);
1483 pipeline->FlushUITasks();
1484 });
1485 #ifdef ENABLE_ROSEN_BACKEND
1486 if (rsTransaction) {
1487 rsTransaction->Commit();
1488 }
1489 #endif
1490 }
1491
StartFullToMultWindowAnimation(int32_t width,int32_t height,WindowSizeChangeReason type,const std::shared_ptr<Rosen::RSTransaction> & rsTransaction)1492 void PipelineContext::StartFullToMultWindowAnimation(int32_t width, int32_t height,
1493 WindowSizeChangeReason type, const std::shared_ptr<Rosen::RSTransaction>& rsTransaction)
1494 {
1495 TAG_LOGI(AceLogTag::ACE_ANIMATION,
1496 "Root node start multiple window animation, type = %{public}d, width = %{public}d, height = %{public}d", type,
1497 width, height);
1498 #ifdef ENABLE_ROSEN_BACKEND
1499 if (rsTransaction) {
1500 FlushMessages();
1501 rsTransaction->Begin();
1502 }
1503 #endif
1504 float response = 0.5f;
1505 float dampingFraction = 1.0f;
1506 AnimationOption option;
1507 if (type == WindowSizeChangeReason::FULL_TO_FLOATING) {
1508 response = 0.45f;
1509 dampingFraction = 0.75f;
1510 }
1511 auto springMotion = AceType::MakeRefPtr<ResponsiveSpringMotion>(response, dampingFraction, 0);
1512 option.SetCurve(springMotion);
1513 auto weak = WeakClaim(this);
1514 Animate(option, springMotion, [width, height, weak]() {
1515 auto pipeline = weak.Upgrade();
1516 CHECK_NULL_VOID(pipeline);
1517 pipeline->SetRootRect(width, height, 0.0);
1518 pipeline->FlushUITasks();
1519 });
1520 #ifdef ENABLE_ROSEN_BACKEND
1521 if (rsTransaction) {
1522 rsTransaction->Commit();
1523 }
1524 #endif
1525 }
1526
SetRootRect(double width,double height,double offset)1527 void PipelineContext::SetRootRect(double width, double height, double offset)
1528 {
1529 CHECK_RUN_ON(UI);
1530 UpdateRootSizeAndScale(width, height);
1531 CHECK_NULL_VOID(rootNode_);
1532 if (Container::CurrentId() < MIN_SUBCONTAINER_ID) {
1533 ScreenSystemManager::GetInstance().SetWindowInfo(rootWidth_, density_, dipScale_);
1534 ScreenSystemManager::GetInstance().OnSurfaceChanged(width);
1535 } else {
1536 ScreenSystemManager::GetInstance().SetWindowInfo(density_, dipScale_);
1537 }
1538 SizeF sizeF { static_cast<float>(width), static_cast<float>(height) };
1539 if (rootNode_->GetGeometryNode()->GetFrameSize() != sizeF || rootNode_->IsLayoutDirtyMarked()) {
1540 CalcSize idealSize { CalcLength(width), CalcLength(height) };
1541 MeasureProperty layoutConstraint;
1542 layoutConstraint.selfIdealSize = idealSize;
1543 layoutConstraint.maxSize = idealSize;
1544 rootNode_->UpdateLayoutConstraint(layoutConstraint);
1545 // reset parentLayoutConstraint to update itself when next measure task
1546 rootNode_->GetGeometryNode()->ResetParentLayoutConstraint();
1547 rootNode_->MarkDirtyNode();
1548 }
1549 if (rootNode_->GetGeometryNode()->GetFrameOffset().GetY() != offset) {
1550 OffsetF newOffset = rootNode_->GetGeometryNode()->GetFrameOffset();
1551 newOffset.SetY(static_cast<float>(offset));
1552 rootNode_->GetGeometryNode()->SetMarginFrameOffset(newOffset);
1553 auto rootContext = rootNode_->GetRenderContext();
1554 rootContext->SyncGeometryProperties(RawPtr(rootNode_->GetGeometryNode()));
1555 RequestFrame();
1556 }
1557 if (isDensityChanged_) {
1558 rootNode_->GetGeometryNode()->ResetParentLayoutConstraint();
1559 rootNode_->MarkForceMeasure();
1560 isDensityChanged_ = false;
1561 }
1562 #if defined(ANDROID_PLATFORM) || defined(IOS_PLATFORM)
1563 // For cross-platform build, flush tasks when first resize, speed up for fisrt frame.
1564 if (window_ && rootNode_->GetRenderContext() && !NearZero(width) && !NearZero(height)) {
1565 rootNode_->GetRenderContext()->SetBounds(0.0, 0.0, width, height);
1566 window_->FlushTasks();
1567 FlushVsync(GetTimeFromExternalTimer(), 0);
1568 }
1569 #endif
1570 }
1571
UpdateSystemSafeArea(const SafeAreaInsets & systemSafeArea)1572 void PipelineContext::UpdateSystemSafeArea(const SafeAreaInsets& systemSafeArea)
1573 {
1574 CHECK_NULL_VOID(minPlatformVersion_ >= PLATFORM_VERSION_TEN);
1575 if (safeAreaManager_->UpdateSystemSafeArea(systemSafeArea)) {
1576 AnimateOnSafeAreaUpdate();
1577 }
1578 }
1579
UpdateCutoutSafeArea(const SafeAreaInsets & cutoutSafeArea)1580 void PipelineContext::UpdateCutoutSafeArea(const SafeAreaInsets& cutoutSafeArea)
1581 {
1582 CHECK_NULL_VOID(minPlatformVersion_ >= PLATFORM_VERSION_TEN);
1583 if (safeAreaManager_->UpdateCutoutSafeArea(cutoutSafeArea)) {
1584 AnimateOnSafeAreaUpdate();
1585 }
1586 }
1587
UpdateNavSafeArea(const SafeAreaInsets & navSafeArea)1588 void PipelineContext::UpdateNavSafeArea(const SafeAreaInsets& navSafeArea)
1589 {
1590 CHECK_NULL_VOID(minPlatformVersion_ >= PLATFORM_VERSION_TEN);
1591 if (safeAreaManager_->UpdateNavArea(navSafeArea)) {
1592 AnimateOnSafeAreaUpdate();
1593 }
1594 }
1595
CheckAndUpdateKeyboardInset(float keyboardHeight)1596 void PipelineContext::CheckAndUpdateKeyboardInset(float keyboardHeight)
1597 {
1598 safeAreaManager_->UpdateKeyboardSafeArea(keyboardHeight);
1599 }
1600
UpdateOriginAvoidArea(const Rosen::AvoidArea & avoidArea,uint32_t type)1601 void PipelineContext::UpdateOriginAvoidArea(const Rosen::AvoidArea& avoidArea, uint32_t type)
1602 {
1603 #ifdef WINDOW_SCENE_SUPPORTED
1604 CHECK_NULL_VOID(uiExtensionManager_);
1605 uiExtensionManager_->TransferOriginAvoidArea(avoidArea, type);
1606 #endif
1607 }
1608
UpdateSizeChangeReason(WindowSizeChangeReason type,const std::shared_ptr<Rosen::RSTransaction> & rsTransaction)1609 void PipelineContext::UpdateSizeChangeReason(
1610 WindowSizeChangeReason type, const std::shared_ptr<Rosen::RSTransaction>& rsTransaction)
1611 {
1612 #ifdef WINDOW_SCENE_SUPPORTED
1613 CHECK_NULL_VOID(uiExtensionManager_);
1614 uiExtensionManager_->NotifySizeChangeReason(type, rsTransaction);
1615 #endif
1616 }
1617
SetEnableKeyBoardAvoidMode(KeyBoardAvoidMode value)1618 void PipelineContext::SetEnableKeyBoardAvoidMode(KeyBoardAvoidMode value)
1619 {
1620 if (safeAreaManager_->SetKeyBoardAvoidMode(value)) {
1621 SyncSafeArea(SafeAreaSyncType::SYNC_TYPE_KEYBOARD);
1622 TAG_LOGI(AceLogTag::ACE_KEYBOARD, "keyboardAvoid Mode update:%{public}d", value);
1623 }
1624 }
1625
GetEnableKeyBoardAvoidMode()1626 KeyBoardAvoidMode PipelineContext::GetEnableKeyBoardAvoidMode()
1627 {
1628 return safeAreaManager_->GetKeyBoardAvoidMode();
1629 }
1630
IsEnableKeyBoardAvoidMode()1631 bool PipelineContext::IsEnableKeyBoardAvoidMode()
1632 {
1633 return safeAreaManager_->KeyboardSafeAreaEnabled();
1634 }
1635
SetIgnoreViewSafeArea(bool value)1636 void PipelineContext::SetIgnoreViewSafeArea(bool value)
1637 {
1638 if (safeAreaManager_->SetIgnoreSafeArea(value)) {
1639 SyncSafeArea(SafeAreaSyncType::SYNC_TYPE_WINDOW_IGNORE);
1640 }
1641 }
1642
SetIsLayoutFullScreen(bool value)1643 void PipelineContext::SetIsLayoutFullScreen(bool value)
1644 {
1645 if (safeAreaManager_->SetIsFullScreen(value)) {
1646 SyncSafeArea(SafeAreaSyncType::SYNC_TYPE_WINDOW_IGNORE);
1647 }
1648 }
1649
SetIsNeedAvoidWindow(bool value)1650 void PipelineContext::SetIsNeedAvoidWindow(bool value)
1651 {
1652 if (safeAreaManager_->SetIsNeedAvoidWindow(value)) {
1653 SyncSafeArea(SafeAreaSyncType::SYNC_TYPE_WINDOW_IGNORE);
1654 }
1655 }
1656
GetSafeArea() const1657 PipelineBase::SafeAreaInsets PipelineContext::GetSafeArea() const
1658 {
1659 return safeAreaManager_->GetSafeArea();
1660 }
1661
GetSafeAreaWithoutProcess() const1662 PipelineBase::SafeAreaInsets PipelineContext::GetSafeAreaWithoutProcess() const
1663 {
1664 return safeAreaManager_->GetSafeAreaWithoutProcess();
1665 }
1666
GetPageAvoidOffset()1667 float PipelineContext::GetPageAvoidOffset()
1668 {
1669 return safeAreaManager_->GetKeyboardOffset();
1670 }
1671
CheckNeedAvoidInSubWindow()1672 bool PipelineContext::CheckNeedAvoidInSubWindow()
1673 {
1674 CHECK_NULL_RETURN(NearZero(GetPageAvoidOffset()), true);
1675 CHECK_NULL_RETURN(safeAreaManager_->KeyboardSafeAreaEnabled(), false);
1676 auto KeyboardInsetLength = safeAreaManager_->GetKeyboardInset().Length();
1677 return GreatNotEqual(KeyboardInsetLength, 0.0f);
1678 }
1679
SyncSafeArea(SafeAreaSyncType syncType)1680 void PipelineContext::SyncSafeArea(SafeAreaSyncType syncType)
1681 {
1682 bool keyboardSafeArea =
1683 syncType == SafeAreaSyncType::SYNC_TYPE_KEYBOARD && !safeAreaManager_->KeyboardSafeAreaEnabled();
1684 CHECK_NULL_VOID(stageManager_);
1685 stageManager_->SyncPageSafeArea(keyboardSafeArea);
1686 SubwindowManager::GetInstance()->MarkDirtyDialogSafeArea();
1687 if (overlayManager_) {
1688 overlayManager_->MarkDirty(PROPERTY_UPDATE_MEASURE);
1689 }
1690 if (selectOverlayManager_) {
1691 selectOverlayManager_->MarkDirty(PROPERTY_UPDATE_MEASURE);
1692 }
1693 auto&& restoreNodes = safeAreaManager_->GetGeoRestoreNodes();
1694 for (auto&& wk : restoreNodes) {
1695 auto node = wk.Upgrade();
1696 if (node) {
1697 bool needMeasure = (syncType == SafeAreaSyncType::SYNC_TYPE_KEYBOARD && node->SelfExpansiveToKeyboard()) ||
1698 (syncType == SafeAreaSyncType::SYNC_TYPE_AVOID_AREA ||
1699 syncType == SafeAreaSyncType::SYNC_TYPE_WINDOW_IGNORE);
1700 node->MarkDirtyNode(needMeasure ? PROPERTY_UPDATE_MEASURE : PROPERTY_UPDATE_LAYOUT);
1701 }
1702 }
1703 }
1704
DetachNode(RefPtr<UINode> uiNode)1705 void PipelineContext::DetachNode(RefPtr<UINode> uiNode)
1706 {
1707 auto frameNode = DynamicCast<FrameNode>(uiNode);
1708 attachedNodeSet_.erase(RawPtr(uiNode));
1709 CHECK_NULL_VOID(frameNode);
1710
1711 RemoveStoredNode(frameNode->GetRestoreId());
1712 if (frameNode->IsPrivacySensitive()) {
1713 auto privacyManager = GetPrivacySensitiveManager();
1714 privacyManager->RemoveNode(AceType::WeakClaim(AceType::RawPtr(frameNode)));
1715 }
1716
1717 if (!CheckThreadSafe()) {
1718 LOGW("DetachNode doesn't run on UI thread!");
1719 }
1720 dirtyPropertyNodes_.erase(frameNode);
1721 needRenderNode_.erase(WeakPtr<FrameNode>(frameNode));
1722
1723 if (dirtyFocusNode_ == frameNode) {
1724 dirtyFocusNode_.Reset();
1725 }
1726
1727 if (dirtyFocusScope_ == frameNode) {
1728 dirtyFocusScope_.Reset();
1729 }
1730
1731 if (dirtyRequestFocusNode_ == frameNode) {
1732 dirtyRequestFocusNode_.Reset();
1733 }
1734
1735 if (activeNode_ == frameNode) {
1736 activeNode_.Reset();
1737 }
1738
1739 if (focusNode_ == frameNode) {
1740 focusNode_.Reset();
1741 }
1742 }
1743
OnVirtualKeyboardHeightChange(float keyboardHeight,const std::shared_ptr<Rosen::RSTransaction> & rsTransaction,const float safeHeight,const bool supportAvoidance,bool forceChange)1744 void PipelineContext::OnVirtualKeyboardHeightChange(float keyboardHeight,
1745 const std::shared_ptr<Rosen::RSTransaction>& rsTransaction, const float safeHeight, const bool supportAvoidance,
1746 bool forceChange)
1747 {
1748 CHECK_RUN_ON(UI);
1749 // prevent repeated trigger with same keyboardHeight
1750 if (!forceChange && NearEqual(keyboardHeight, safeAreaManager_->GetKeyboardInset().Length())) {
1751 return;
1752 }
1753
1754 ACE_FUNCTION_TRACE();
1755 #ifdef ENABLE_ROSEN_BACKEND
1756 if (rsTransaction) {
1757 FlushMessages();
1758 rsTransaction->Begin();
1759 }
1760 #endif
1761
1762 if (supportAvoidance) {
1763 AvoidanceLogic(keyboardHeight, rsTransaction, safeHeight, supportAvoidance);
1764 } else {
1765 OriginalAvoidanceLogic(keyboardHeight, rsTransaction);
1766 }
1767
1768 #ifdef ENABLE_ROSEN_BACKEND
1769 if (rsTransaction) {
1770 rsTransaction->Commit();
1771 }
1772 #endif
1773 }
1774
AvoidanceLogic(float keyboardHeight,const std::shared_ptr<Rosen::RSTransaction> & rsTransaction,const float safeHeight,const bool supportAvoidance)1775 void PipelineContext::AvoidanceLogic(float keyboardHeight, const std::shared_ptr<Rosen::RSTransaction>& rsTransaction,
1776 const float safeHeight, const bool supportAvoidance)
1777 {
1778 auto func = [this, keyboardHeight, safeHeight, supportAvoidance]() mutable {
1779 safeAreaManager_->UpdateKeyboardSafeArea(keyboardHeight);
1780 keyboardHeight += safeAreaManager_->GetSafeHeight();
1781 float positionY = 0.0f;
1782 float textfieldHeight = 0.0f;
1783 float keyboardPosition = rootHeight_ - keyboardHeight;
1784 auto manager = DynamicCast<TextFieldManagerNG>(PipelineBase::GetTextFieldManager());
1785 float keyboardOffset = manager ? manager->GetClickPositionOffset() : safeAreaManager_->GetKeyboardOffset();
1786 if (manager) {
1787 positionY = static_cast<float>(manager->GetClickPosition().GetY()) - keyboardOffset;
1788 textfieldHeight = manager->GetHeight();
1789 }
1790 if (!NearZero(keyboardOffset)) {
1791 auto offsetY = keyboardPosition - safeAreaManager_->GetLastKeyboardPoistion();
1792 safeAreaManager_->UpdateKeyboardOffset(keyboardOffset + offsetY);
1793 } else {
1794 if (NearZero(keyboardHeight)) {
1795 safeAreaManager_->UpdateKeyboardOffset(0.0f);
1796 } else if (LessOrEqual(positionY + safeHeight + textfieldHeight, rootHeight_ - keyboardHeight)) {
1797 safeAreaManager_->UpdateKeyboardOffset(0.0f);
1798 } else if (positionY + safeHeight + textfieldHeight > rootHeight_ - keyboardHeight) {
1799 safeAreaManager_->UpdateKeyboardOffset(
1800 -(positionY - rootHeight_ + keyboardHeight)- safeHeight - textfieldHeight);
1801 } else {
1802 safeAreaManager_->UpdateKeyboardOffset(0.0f);
1803 }
1804 }
1805 safeAreaManager_->SetLastKeyboardPoistion(keyboardPosition);
1806 SyncSafeArea(SafeAreaSyncType::SYNC_TYPE_KEYBOARD);
1807 CHECK_NULL_VOID(manager);
1808 manager->AvoidKeyBoardInNavigation();
1809 // layout before scrolling textfield to safeArea, because of getting correct position
1810 FlushUITasks();
1811 bool scrollResult = manager->ScrollTextFieldToSafeArea();
1812 if (scrollResult) {
1813 FlushUITasks();
1814 }
1815
1816 TAG_LOGI(AceLogTag::ACE_KEYBOARD,
1817 "AvoidanceLogic keyboardHeight: %{public}f, positionY: %{public}f, safeHeight: %{public}f, "
1818 "rootHeight_ %{public}f final calculate keyboard offset is %{public}f",
1819 keyboardHeight, positionY, safeHeight, rootHeight_, safeAreaManager_->GetKeyboardOffset());
1820 };
1821 FlushUITasks();
1822 DoKeyboardAvoidAnimate(keyboardAnimationConfig_, keyboardHeight, func);
1823 }
1824
OriginalAvoidanceLogic(float keyboardHeight,const std::shared_ptr<Rosen::RSTransaction> & rsTransaction)1825 void PipelineContext::OriginalAvoidanceLogic(
1826 float keyboardHeight, const std::shared_ptr<Rosen::RSTransaction>& rsTransaction)
1827 {
1828 auto func = [this, keyboardHeight]() mutable {
1829 safeAreaManager_->UpdateKeyboardSafeArea(keyboardHeight);
1830 if (keyboardHeight > 0) {
1831 // add height of navigation bar
1832 keyboardHeight += safeAreaManager_->GetSystemSafeArea().bottom_.Length();
1833 }
1834 float positionY = 0.0f;
1835 auto manager = DynamicCast<TextFieldManagerNG>(PipelineBase::GetTextFieldManager());
1836 float height = 0.0f;
1837 if (manager) {
1838 height = manager->GetHeight();
1839 positionY = static_cast<float>(manager->GetClickPosition().GetY());
1840 }
1841 SizeF rootSize { static_cast<float>(rootWidth_), static_cast<float>(rootHeight_) };
1842 float keyboardOffset = manager ? manager->GetClickPositionOffset() : safeAreaManager_->GetKeyboardOffset();
1843 float positionYWithOffset = positionY - keyboardOffset;
1844 float offsetFix = (rootSize.Height() - positionYWithOffset) > 100.0f
1845 ? keyboardHeight - (rootSize.Height() - positionYWithOffset) / 2.0f
1846 : keyboardHeight;
1847 #if defined(ANDROID_PLATFORM) || defined(IOS_PLATFORM)
1848 if (offsetFix > 0.0f && positionYWithOffset < offsetFix) {
1849 offsetFix = keyboardHeight - (rootSize.Height() - positionYWithOffset - height);
1850 }
1851 #endif
1852 if (NearZero(keyboardHeight)) {
1853 safeAreaManager_->UpdateKeyboardOffset(0.0f);
1854 } else if (LessOrEqual(rootSize.Height() - positionYWithOffset - height, height) &&
1855 LessOrEqual(rootSize.Height() - positionYWithOffset, keyboardHeight)) {
1856 safeAreaManager_->UpdateKeyboardOffset(-keyboardHeight);
1857 } else if (positionYWithOffset + height > (rootSize.Height() - keyboardHeight) && offsetFix > 0.0f) {
1858 safeAreaManager_->UpdateKeyboardOffset(-offsetFix);
1859 } else if ((positionYWithOffset + height > rootSize.Height() - keyboardHeight &&
1860 positionYWithOffset < rootSize.Height() - keyboardHeight && height < keyboardHeight / 2.0f) &&
1861 NearZero(rootNode_->GetGeometryNode()->GetFrameOffset().GetY())) {
1862 safeAreaManager_->UpdateKeyboardOffset(-height - offsetFix / 2.0f);
1863 } else {
1864 safeAreaManager_->UpdateKeyboardOffset(0.0f);
1865 }
1866 SyncSafeArea(SafeAreaSyncType::SYNC_TYPE_KEYBOARD);
1867 CHECK_NULL_VOID(manager);
1868 manager->AvoidKeyBoardInNavigation();
1869 // layout before scrolling textfield to safeArea, because of getting correct position
1870 FlushUITasks();
1871 bool scrollResult = manager->ScrollTextFieldToSafeArea();
1872 if (scrollResult) {
1873 FlushUITasks();
1874 }
1875 };
1876 FlushUITasks();
1877 DoKeyboardAvoidAnimate(keyboardAnimationConfig_, keyboardHeight, func);
1878 }
1879
OnVirtualKeyboardHeightChange(float keyboardHeight,double positionY,double height,const std::shared_ptr<Rosen::RSTransaction> & rsTransaction,bool forceChange)1880 void PipelineContext::OnVirtualKeyboardHeightChange(float keyboardHeight, double positionY, double height,
1881 const std::shared_ptr<Rosen::RSTransaction>& rsTransaction, bool forceChange)
1882 {
1883 CHECK_RUN_ON(UI);
1884 // prevent repeated trigger with same keyboardHeight
1885 CHECK_NULL_VOID(safeAreaManager_);
1886 if (UsingCaretAvoidMode()) {
1887 OnCaretPositionChangeOrKeyboardHeightChange(keyboardHeight,
1888 positionY, height, rsTransaction, forceChange);
1889 return;
1890 }
1891 auto manager = DynamicCast<TextFieldManagerNG>(PipelineBase::GetTextFieldManager());
1892 CHECK_NULL_VOID(manager);
1893 if (!forceChange && NearEqual(keyboardHeight, safeAreaManager_->GetKeyboardInset().Length()) &&
1894 prevKeyboardAvoidMode_ == safeAreaManager_->GetKeyBoardAvoidMode() && manager->PrevHasTextFieldPattern()) {
1895 safeAreaManager_->UpdateKeyboardSafeArea(keyboardHeight);
1896 TAG_LOGD(
1897 AceLogTag::ACE_KEYBOARD, "KeyboardHeight as same as last time, don't need to calculate keyboardOffset");
1898 return;
1899 }
1900
1901 if (!forceChange && (NearEqual(keyboardHeight + 1, safeAreaManager_->GetKeyboardInset().Length()) ||
1902 NearEqual(keyboardHeight - 1, safeAreaManager_->GetKeyboardInset().Length())) &&
1903 prevKeyboardAvoidMode_ == safeAreaManager_->GetKeyBoardAvoidMode() && manager->PrevHasTextFieldPattern()) {
1904 TAG_LOGI(
1905 AceLogTag::ACE_KEYBOARD, "Ignore ileagal keyboard height change");
1906 return;
1907 }
1908
1909 if (keyboardHeight > rootHeight_) {
1910 TAG_LOGI(AceLogTag::ACE_KEYBOARD, "Keyboard higher than whole rootrect, no need to avoid");
1911 return;
1912 }
1913
1914 if (manager->UsingCustomKeyboardAvoid()) {
1915 TAG_LOGI(AceLogTag::ACE_KEYBOARD, "Using Custom Avoid Instead");
1916 return;
1917 }
1918
1919 manager->UpdatePrevHasTextFieldPattern();
1920 prevKeyboardAvoidMode_ = safeAreaManager_->GetKeyBoardAvoidMode();
1921
1922 ACE_FUNCTION_TRACE();
1923 #ifdef ENABLE_ROSEN_BACKEND
1924 if (rsTransaction) {
1925 FlushMessages();
1926 rsTransaction->Begin();
1927 }
1928 #endif
1929
1930 auto weak = WeakClaim(this);
1931 auto func = [weak, keyboardHeight, positionY, height, manager]() mutable {
1932 auto context = weak.Upgrade();
1933 CHECK_NULL_VOID(context);
1934 context->SetIsLayouting(false);
1935 context->safeAreaManager_->UpdateKeyboardSafeArea(keyboardHeight);
1936 context->SetKeyboardAction(NearZero(keyboardHeight) ? KeyboardAction::CLOSING : KeyboardAction::OPENING);
1937 if (keyboardHeight > 0) {
1938 // add height of navigation bar
1939 keyboardHeight += context->safeAreaManager_->GetSystemSafeArea().bottom_.Length();
1940 }
1941
1942 SizeF rootSize { static_cast<float>(context->rootWidth_), static_cast<float>(context->rootHeight_) };
1943
1944 TAG_LOGI(AceLogTag::ACE_KEYBOARD,
1945 "origin positionY: %{public}f, height %{public}f", positionY, height);
1946
1947 float positionYWithOffset = positionY;
1948 float keyboardOffset = manager ? manager->GetClickPositionOffset() :
1949 context->safeAreaManager_->GetKeyboardOffset();
1950 float currentPos = manager->GetClickPosition().GetY() - context->GetRootRect().GetOffset().GetY() -
1951 keyboardOffset;
1952
1953 auto onFocusField = manager->GetOnFocusTextField().Upgrade();
1954 float adjust = 0.0f;
1955 if (onFocusField && onFocusField->GetHost() && onFocusField->GetHost()->GetGeometryNode()) {
1956 auto adjustRect = onFocusField->GetHost()->GetGeometryNode()->GetParentAdjust();
1957 adjust = adjustRect.Top();
1958 }
1959 currentPos += adjust;
1960
1961 if (!onFocusField) {
1962 TAG_LOGI(AceLogTag::ACE_KEYBOARD, "use origin arg from the window");
1963 } else if (manager->GetIfFocusTextFieldIsInline()) {
1964 manager->GetInlineTextFieldAvoidPositionYAndHeight(positionY, height);
1965 positionYWithOffset = positionY;
1966 } else if (!NearEqual(positionY, currentPos) && !context->IsEnableKeyBoardAvoidMode()) {
1967 positionY = currentPos;
1968 positionYWithOffset = currentPos;
1969 height = manager->GetHeight();
1970 }
1971
1972 if (rootSize.Height() - positionY - height < 0) {
1973 height = rootSize.Height() - positionY;
1974 }
1975 float offsetFix = (rootSize.Height() - positionY - height) < keyboardHeight
1976 ? keyboardHeight - (rootSize.Height() - positionY - height)
1977 : keyboardHeight;
1978 auto lastKeyboardOffset = context->safeAreaManager_->GetKeyboardOffset();
1979 float newKeyboardOffset = 0.0f;
1980 if (NearZero(keyboardHeight)) {
1981 newKeyboardOffset = 0.0f;
1982 } else if (positionYWithOffset + height > (rootSize.Height() - keyboardHeight) && offsetFix > 0.0f) {
1983 newKeyboardOffset = -offsetFix;
1984 } else if (LessOrEqual(rootSize.Height() - positionYWithOffset - height, height) &&
1985 LessOrEqual(rootSize.Height() - positionYWithOffset, keyboardHeight)) {
1986 newKeyboardOffset = -keyboardHeight;
1987 } else if ((positionYWithOffset + height > rootSize.Height() - keyboardHeight &&
1988 positionYWithOffset < rootSize.Height() - keyboardHeight && height < keyboardHeight / 2.0f) &&
1989 NearZero(context->rootNode_->GetGeometryNode()->GetFrameOffset().GetY())) {
1990 newKeyboardOffset = -height - offsetFix / 2.0f;
1991 } else {
1992 newKeyboardOffset = 0.0f;
1993 }
1994
1995 if (NearZero(keyboardHeight) || LessOrEqual(newKeyboardOffset, lastKeyboardOffset) ||
1996 manager->GetOnFocusTextFieldId() == manager->GetLastAvoidFieldId()) {
1997 context->safeAreaManager_->UpdateKeyboardOffset(newKeyboardOffset);
1998 } else {
1999 TAG_LOGI(AceLogTag::ACE_KEYBOARD, "Different field, Calculated offfset %{public}f is smaller than current"
2000 "keyboardOffset, so keep current keyboardOffset", newKeyboardOffset);
2001 }
2002 manager->SetLastAvoidFieldId(manager->GetOnFocusTextFieldId());
2003
2004 TAG_LOGI(AceLogTag::ACE_KEYBOARD,
2005 "keyboardHeight: %{public}f, positionY: %{public}f, textHeight: %{public}f, "
2006 "rootSize.Height() %{public}f final calculate keyboard offset is %{public}f",
2007 keyboardHeight, positionY, height, rootSize.Height(), context->safeAreaManager_->GetKeyboardOffset());
2008 context->SyncSafeArea(SafeAreaSyncType::SYNC_TYPE_KEYBOARD);
2009 manager->AvoidKeyBoardInNavigation();
2010 // layout before scrolling textfield to safeArea, because of getting correct position
2011 context->FlushUITasks();
2012 bool scrollResult = manager->ScrollTextFieldToSafeArea();
2013 if (scrollResult) {
2014 context->FlushUITasks();
2015 }
2016 context->SetKeyboardAction(KeyboardAction::NONE);
2017 };
2018 FlushUITasks();
2019 SetIsLayouting(true);
2020 DoKeyboardAvoidAnimate(keyboardAnimationConfig_, keyboardHeight, func);
2021
2022 #ifdef ENABLE_ROSEN_BACKEND
2023 if (rsTransaction) {
2024 rsTransaction->Commit();
2025 }
2026 #endif
2027 }
2028
UsingCaretAvoidMode()2029 bool PipelineContext::UsingCaretAvoidMode()
2030 {
2031 CHECK_NULL_RETURN(safeAreaManager_, false);
2032 return safeAreaManager_->GetKeyBoardAvoidMode() == KeyBoardAvoidMode::OFFSET_WITH_CARET ||
2033 safeAreaManager_->GetKeyBoardAvoidMode() == KeyBoardAvoidMode::RESIZE_WITH_CARET;
2034 }
2035
OnCaretPositionChangeOrKeyboardHeightChange(float keyboardHeight,double positionY,double height,const std::shared_ptr<Rosen::RSTransaction> & rsTransaction,bool forceChange)2036 void PipelineContext::OnCaretPositionChangeOrKeyboardHeightChange(
2037 float keyboardHeight, double positionY, double height,
2038 const std::shared_ptr<Rosen::RSTransaction>& rsTransaction, bool forceChange)
2039 {
2040 CHECK_RUN_ON(UI);
2041 CHECK_NULL_VOID(safeAreaManager_);
2042 auto manager = DynamicCast<TextFieldManagerNG>(PipelineBase::GetTextFieldManager());
2043 CHECK_NULL_VOID(manager);
2044 if (manager->UsingCustomKeyboardAvoid()) {
2045 TAG_LOGI(AceLogTag::ACE_KEYBOARD, "Using Custom Avoid Instead");
2046 return;
2047 }
2048 manager->UpdatePrevHasTextFieldPattern();
2049 prevKeyboardAvoidMode_ = safeAreaManager_->GetKeyBoardAvoidMode();
2050 ACE_FUNCTION_TRACE();
2051 #ifdef ENABLE_ROSEN_BACKEND
2052 if (rsTransaction) {
2053 FlushMessages();
2054 rsTransaction->Begin();
2055 }
2056 #endif
2057
2058 bool keyboardHeightChanged = NearEqual(keyboardHeight, safeAreaManager_->GetKeyboardInset().Length());
2059 auto weak = WeakClaim(this);
2060 auto func = [weak, keyboardHeight, positionY, height, manager, keyboardHeightChanged]() mutable {
2061 auto context = weak.Upgrade();
2062 CHECK_NULL_VOID(context);
2063 context->SetIsLayouting(false);
2064 context->safeAreaManager_->UpdateKeyboardSafeArea(keyboardHeight);
2065 if (keyboardHeight > 0) {
2066 // add height of navigation bar
2067 keyboardHeight += context->safeAreaManager_->GetSystemSafeArea().bottom_.Length();
2068 }
2069 SizeF rootSize { static_cast<float>(context->rootWidth_), static_cast<float>(context->rootHeight_) };
2070 TAG_LOGI(AceLogTag::ACE_KEYBOARD, "origin positionY: %{public}f, height %{public}f", positionY, height);
2071 float caretPos = manager->GetFocusedNodeCaretRect().Top() - context->GetRootRect().GetOffset().GetY() -
2072 context->GetSafeAreaManager()->GetKeyboardOffsetDirectly();
2073 auto onFocusField = manager->GetOnFocusTextField().Upgrade();
2074 float adjust = 0.0f;
2075 if (onFocusField && onFocusField->GetHost() && onFocusField->GetHost()->GetGeometryNode()) {
2076 adjust = onFocusField->GetHost()->GetGeometryNode()->GetParentAdjust().Top();
2077 positionY = caretPos;
2078 height = manager->GetHeight();
2079 }
2080 positionY += adjust;
2081 if (rootSize.Height() - positionY - height < 0 && manager->IsScrollableChild()) {
2082 height = rootSize.Height() - positionY;
2083 }
2084 auto lastKeyboardOffset = context->safeAreaManager_->GetKeyboardOffsetDirectly();
2085 auto newKeyboardOffset = context->CalcNewKeyboardOffset(keyboardHeight, positionY, height, rootSize);
2086 if (NearZero(keyboardHeight) || LessOrEqual(newKeyboardOffset, lastKeyboardOffset) ||
2087 (manager->GetOnFocusTextFieldId() == manager->GetLastAvoidFieldId() && !keyboardHeightChanged)) {
2088 context->safeAreaManager_->UpdateKeyboardOffset(newKeyboardOffset);
2089 } else {
2090 TAG_LOGI(AceLogTag::ACE_KEYBOARD, "calc offset %{public}f is smaller, keep current", newKeyboardOffset);
2091 manager->SetLastAvoidFieldId(manager->GetOnFocusTextFieldId());
2092 return;
2093 }
2094 manager->SetLastAvoidFieldId(manager->GetOnFocusTextFieldId());
2095 TAG_LOGI(AceLogTag::ACE_KEYBOARD,
2096 "keyboardHeight: %{public}f, caretPos: %{public}f, caretHeight: %{public}f, "
2097 "rootSize.Height() %{public}f adjust: %{public}f lastOffset: %{public}f, "
2098 "final calculate keyboard offset is %{public}f",
2099 keyboardHeight, positionY, height, rootSize.Height(), adjust, lastKeyboardOffset,
2100 context->safeAreaManager_->GetKeyboardOffset());
2101 context->SyncSafeArea(SafeAreaSyncType::SYNC_TYPE_KEYBOARD);
2102 manager->AvoidKeyBoardInNavigation();
2103 // layout before scrolling textfield to safeArea, because of getting correct position
2104 context->FlushUITasks();
2105 bool scrollResult = manager->ScrollTextFieldToSafeArea();
2106 if (scrollResult) {
2107 context->FlushUITasks();
2108 }
2109 };
2110 FlushUITasks();
2111 SetIsLayouting(true);
2112 DoKeyboardAvoidAnimate(keyboardAnimationConfig_, keyboardHeight, func);
2113
2114 #ifdef ENABLE_ROSEN_BACKEND
2115 if (rsTransaction) {
2116 rsTransaction->Commit();
2117 }
2118 #endif
2119 }
2120
CalcNewKeyboardOffset(float keyboardHeight,float positionY,float height,SizeF & rootSize)2121 float PipelineContext::CalcNewKeyboardOffset(float keyboardHeight, float positionY,
2122 float height, SizeF& rootSize)
2123 {
2124 auto newKeyboardOffset = CalcAvoidOffset(keyboardHeight, positionY, height, rootSize);
2125 CHECK_NULL_RETURN(safeAreaManager_, newKeyboardOffset);
2126 auto manager = DynamicCast<TextFieldManagerNG>(PipelineBase::GetTextFieldManager());
2127 CHECK_NULL_RETURN(manager, newKeyboardOffset);
2128 auto onFocusField = manager->GetOnFocusTextField().Upgrade();
2129 CHECK_NULL_RETURN(onFocusField, newKeyboardOffset);
2130 auto host = onFocusField->GetHost();
2131 CHECK_NULL_RETURN(host, newKeyboardOffset);
2132 auto geometryNode = host->GetGeometryNode();
2133 CHECK_NULL_RETURN(geometryNode, newKeyboardOffset);
2134 auto paintOffset = host->GetPaintRectOffset();
2135 auto frameSize = geometryNode->GetFrameSize();
2136 auto offset = CalcAvoidOffset(keyboardHeight, paintOffset.GetY() - safeAreaManager_->GetKeyboardOffsetDirectly(),
2137 frameSize.Height(), rootSize);
2138 return std::max(offset, newKeyboardOffset);
2139 }
2140
CalcAvoidOffset(float keyboardHeight,float positionY,float height,SizeF rootSize)2141 float PipelineContext::CalcAvoidOffset(float keyboardHeight, float positionY,
2142 float height, SizeF rootSize)
2143 {
2144 float offsetFix = (rootSize.Height() - positionY - height) < keyboardHeight
2145 ? keyboardHeight - (rootSize.Height() - positionY - height)
2146 : keyboardHeight;
2147 if (NearZero(keyboardHeight)) {
2148 return 0.0f;
2149 }
2150 if (positionY + height > (rootSize.Height() - keyboardHeight) && offsetFix > 0.0f) {
2151 return -offsetFix;
2152 }
2153 if (LessOrEqual(rootSize.Height() - positionY - height, height) &&
2154 LessOrEqual(rootSize.Height() - positionY, keyboardHeight)) {
2155 return -keyboardHeight;
2156 }
2157 if ((positionY + height > rootSize.Height() - keyboardHeight &&
2158 positionY < rootSize.Height() - keyboardHeight && height < keyboardHeight / 2.0f) &&
2159 NearZero(rootNode_->GetGeometryNode()->GetFrameOffset().GetY())) {
2160 return -height - offsetFix / 2.0f;
2161 }
2162 return 0.0f;
2163 }
2164
OnBackPressed()2165 bool PipelineContext::OnBackPressed()
2166 {
2167 CHECK_RUN_ON(PLATFORM);
2168 auto frontend = weakFrontend_.Upgrade();
2169 if (!frontend) {
2170 // return back.
2171 return false;
2172 }
2173
2174 // If the tag of the last child of the rootnode is video, exit full screen.
2175 if (fullScreenManager_->OnBackPressed()) {
2176 LOGI("fullscreen component: video or web consumed backpressed event");
2177 return true;
2178 }
2179
2180 // if has sharedTransition, back press will stop the sharedTransition
2181 if (sharedTransitionManager_ && sharedTransitionManager_->OnBackPressed()) {
2182 LOGI("sharedTransition consumed backpressed event");
2183 return true;
2184 }
2185
2186 // if has popup, back press would hide popup and not trigger page back
2187 auto textfieldMgr = DynamicCast<TextFieldManagerNG>(PipelineBase::GetTextFieldManager());
2188 if (textfieldMgr) {
2189 auto lastRequestKeyboardNodeId = textfieldMgr->GetLastRequestKeyboardId();
2190 auto lastRequestKeyboardNode = DynamicCast<FrameNode>(
2191 ElementRegister::GetInstance()->GetUINodeById(lastRequestKeyboardNodeId));
2192 if (lastRequestKeyboardNode && lastRequestKeyboardNode->GetPageId() == -1 &&
2193 textfieldMgr->OnBackPressed()) {
2194 LOGI("textfield consumed backpressed event");
2195 return true;
2196 }
2197 }
2198
2199 auto hasOverlay = false;
2200 taskExecutor_->PostSyncTask(
2201 [weakOverlay = AceType::WeakClaim(AceType::RawPtr(overlayManager_)),
2202 weakSelectOverlay = AceType::WeakClaim(AceType::RawPtr(selectOverlayManager_)), &hasOverlay]() {
2203 // Destroy behaviour of Select Overlay shouble be adjusted.
2204 auto overlay = weakOverlay.Upgrade();
2205 CHECK_NULL_VOID(overlay);
2206 auto selectOverlay = weakSelectOverlay.Upgrade();
2207 CHECK_NULL_VOID(selectOverlay);
2208 hasOverlay = selectOverlay->ResetSelectionAndDestroySelectOverlay(true);
2209 hasOverlay |= overlay->RemoveOverlay(true);
2210 },
2211 TaskExecutor::TaskType::UI, "ArkUIBackPressedRemoveOverlay");
2212 if (hasOverlay) {
2213 LOGI("Overlay consumed backpressed event");
2214 return true;
2215 }
2216
2217 auto textfieldManager = DynamicCast<TextFieldManagerNG>(PipelineBase::GetTextFieldManager());
2218 if (textfieldManager && textfieldManager->OnBackPressed()) {
2219 LOGI("textfield consumed backpressed event");
2220 return true;
2221 }
2222
2223 auto result = false;
2224 taskExecutor_->PostSyncTask(
2225 [weakFrontend = weakFrontend_, weakPipelineContext = WeakClaim(this), stageManager = stageManager_, &result]() {
2226 auto frontend = weakFrontend.Upgrade();
2227 if (!frontend) {
2228 result = false;
2229 return;
2230 }
2231 auto context = weakPipelineContext.Upgrade();
2232 if (!context) {
2233 result = false;
2234 return;
2235 }
2236 CHECK_NULL_VOID(stageManager);
2237 auto lastPage = stageManager->GetLastPage();
2238 CHECK_NULL_VOID(lastPage);
2239 bool isEntry = false;
2240 auto navigationGroupNode =
2241 AceType::DynamicCast<NavigationGroupNode>(context->FindNavigationNodeToHandleBack(lastPage, isEntry));
2242 if (navigationGroupNode) {
2243 result = true;
2244 }
2245 },
2246 TaskExecutor::TaskType::UI, "ArkUIBackPressedFindNavigationGroup");
2247
2248 if (result) {
2249 // user accept
2250 LOGI("Navigation consumed backpressed event");
2251 return true;
2252 }
2253
2254 taskExecutor_->PostSyncTask(
2255 [weakFrontend = weakFrontend_, weakPipelineContext = WeakClaim(this), &result]() {
2256 auto frontend = weakFrontend.Upgrade();
2257 if (!frontend) {
2258 result = false;
2259 return;
2260 }
2261 result = frontend->OnBackPressed();
2262 },
2263 TaskExecutor::TaskType::JS, "ArkUIBackPressed");
2264
2265 if (result) {
2266 // user accept
2267 LOGI("router consumed backpressed event");
2268 return true;
2269 }
2270 return false;
2271 }
2272
FindNavigationNodeToHandleBack(const RefPtr<UINode> & node,bool & isEntry)2273 RefPtr<FrameNode> PipelineContext::FindNavigationNodeToHandleBack(const RefPtr<UINode>& node, bool& isEntry)
2274 {
2275 CHECK_NULL_RETURN(node, nullptr);
2276 const auto& children = node->GetChildren();
2277 for (auto iter = children.rbegin(); iter != children.rend(); ++iter) {
2278 auto& child = *iter;
2279 auto childNode = AceType::DynamicCast<FrameNode>(child);
2280 if (childNode && childNode->GetLayoutProperty()) {
2281 auto property = childNode->GetLayoutProperty();
2282 if (property->GetVisibilityValue(VisibleType::VISIBLE) != VisibleType::VISIBLE ||
2283 !childNode->IsActive()) {
2284 continue;
2285 }
2286 }
2287 if (childNode && childNode->GetTag() == V2::NAVIGATION_VIEW_ETS_TAG) {
2288 auto navigationGroupNode = AceType::DynamicCast<NavigationGroupNode>(childNode);
2289 auto topChild = navigationGroupNode->GetTopDestination();
2290 // find navigation from top destination
2291 auto targetNodeFromDestination = FindNavigationNodeToHandleBack(topChild, isEntry);
2292 if (targetNodeFromDestination) {
2293 return targetNodeFromDestination;
2294 }
2295 if (isEntry) {
2296 return nullptr;
2297 }
2298 targetNodeFromDestination = childNode;
2299 auto targetNavigation = AceType::DynamicCast<NavigationGroupNode>(targetNodeFromDestination);
2300 // check if the destination responds
2301 if (targetNavigation && targetNavigation->CheckCanHandleBack(isEntry)) {
2302 return targetNavigation;
2303 }
2304 if (isEntry) {
2305 return nullptr;
2306 }
2307 // if the destination does not responds, find navigation from navbar
2308 auto navBarNode = AceType::DynamicCast<NavBarNode>(navigationGroupNode->GetNavBarNode());
2309 auto navigationLayoutProperty = navigationGroupNode->GetLayoutProperty<NavigationLayoutProperty>();
2310 CHECK_NULL_RETURN(navigationLayoutProperty, nullptr);
2311 if (navigationLayoutProperty->GetHideNavBarValue(false)) {
2312 return nullptr;
2313 }
2314 auto targetNodeFromNavbar = FindNavigationNodeToHandleBack(navBarNode, isEntry);
2315 if (targetNodeFromNavbar) {
2316 return targetNodeFromNavbar;
2317 }
2318 return nullptr;
2319 }
2320 auto target = FindNavigationNodeToHandleBack(child, isEntry);
2321 if (target) {
2322 return target;
2323 }
2324 if (isEntry) {
2325 return nullptr;
2326 }
2327 }
2328 return nullptr;
2329 }
2330
SetIsFocusActive(bool isFocusActive,FocusActiveReason reason,bool autoFocusInactive)2331 bool PipelineContext::SetIsFocusActive(bool isFocusActive, FocusActiveReason reason, bool autoFocusInactive)
2332 {
2333 if (reason == FocusActiveReason::USE_API) {
2334 TAG_LOGI(AceLogTag::ACE_FOCUS, "autoFocusInactive turns to %{public}d", autoFocusInactive);
2335 autoFocusInactive_ = autoFocusInactive;
2336 }
2337 if (!isFocusActive && reason == FocusActiveReason::POINTER_EVENT && !autoFocusInactive_) {
2338 TAG_LOGI(AceLogTag::ACE_FOCUS, "focus cannot be deactived automaticly by pointer event");
2339 return false;
2340 }
2341
2342 if (isFocusActive_ == isFocusActive) {
2343 return false;
2344 }
2345 TAG_LOGI(AceLogTag::ACE_FOCUS, "Pipeline focus turns to %{public}s", isFocusActive ? "active" : "inactive");
2346 isFocusActive_ = isFocusActive;
2347 for (auto& pair : isFocusActiveUpdateEvents_) {
2348 if (pair.second) {
2349 pair.second(isFocusActive_);
2350 }
2351 }
2352 CHECK_NULL_RETURN(rootNode_, false);
2353 auto rootFocusHub = rootNode_->GetFocusHub();
2354 CHECK_NULL_RETURN(rootFocusHub, false);
2355 if (isFocusActive_) {
2356 return rootFocusHub->PaintAllFocusState();
2357 }
2358 rootFocusHub->ClearAllFocusState();
2359 return true;
2360 }
2361
OnTouchEvent(const TouchEvent & point,bool isSubPipe,bool isEventsPassThrough)2362 void PipelineContext::OnTouchEvent(const TouchEvent& point, bool isSubPipe, bool isEventsPassThrough)
2363 {
2364 OnTouchEvent(point, rootNode_, isSubPipe, isEventsPassThrough);
2365 }
2366
OnMouseEvent(const MouseEvent & event)2367 void PipelineContext::OnMouseEvent(const MouseEvent& event)
2368 {
2369 OnMouseEvent(event, rootNode_);
2370 }
2371
OnAxisEvent(const AxisEvent & event)2372 void PipelineContext::OnAxisEvent(const AxisEvent& event)
2373 {
2374 OnAxisEvent(event, rootNode_);
2375 }
2376
OnTouchEvent(const TouchEvent & point,const RefPtr<FrameNode> & node,bool isSubPipe,bool isEventsPassThrough)2377 void PipelineContext::OnTouchEvent(
2378 const TouchEvent& point, const RefPtr<FrameNode>& node, bool isSubPipe, bool isEventsPassThrough)
2379 {
2380 CHECK_RUN_ON(UI);
2381
2382 HandlePenHoverOut(point);
2383
2384 #ifdef UICAST_COMPONENT_SUPPORTED
2385 do {
2386 auto container = Container::Current();
2387 CHECK_NULL_BREAK(container);
2388 auto distributedUI = container->GetDistributedUI();
2389 CHECK_NULL_BREAK(distributedUI);
2390 if (distributedUI->IsSinkMode()) {
2391 distributedUI->BypassEvent(point, isSubPipe);
2392 return;
2393 }
2394 } while (false);
2395 #endif
2396
2397 SerializedGesture etsSerializedGesture;
2398 if (point.type != TouchType::DOWN) {
2399 HandleEtsCardTouchEvent(point, etsSerializedGesture);
2400 }
2401
2402 auto oriPoint = point;
2403 auto scalePoint = point.CreateScalePoint(GetViewScale());
2404 eventManager_->CheckDownEvent(scalePoint);
2405 ResSchedReport::GetInstance().OnTouchEvent(scalePoint);
2406
2407 if (scalePoint.type != TouchType::MOVE && scalePoint.type != TouchType::PULL_MOVE &&
2408 scalePoint.type != TouchType::HOVER_MOVE) {
2409 eventManager_->GetEventTreeRecord(EventTreeType::TOUCH).AddTouchPoint(scalePoint);
2410 if (SystemProperties::GetAceCommercialLogEnabled() || scalePoint.isPrivacyMode) {
2411 TAG_LOGI(AceLogTag::ACE_INPUTKEYFLOW,
2412 "InputTracking id:%{public}d, fingerId:%{public}d, type=%{public}d, inject=%{public}d, "
2413 "isPrivacyMode=%{public}d",
2414 scalePoint.touchEventId, scalePoint.id, (int)scalePoint.type, scalePoint.isInjected,
2415 scalePoint.isPrivacyMode);
2416 } else {
2417 TAG_LOGI(AceLogTag::ACE_INPUTKEYFLOW,
2418 "InputTracking id:%{public}d, fingerId:%{public}d, x=%{public}.3f, y=%{public}.3f type=%{public}d, "
2419 "inject=%{public}d",
2420 scalePoint.touchEventId, scalePoint.id, scalePoint.x, scalePoint.y, (int)scalePoint.type,
2421 scalePoint.isInjected);
2422 }
2423 }
2424
2425 if (scalePoint.type == TouchType::MOVE) {
2426 for (auto listenerItem : listenerVector_) {
2427 if (listenerItem) {
2428 listenerItem->OnTouchEvent();
2429 }
2430 }
2431 }
2432
2433 eventManager_->SetInstanceId(GetInstanceId());
2434 if (scalePoint.type != TouchType::MOVE && historyPointsById_.find(scalePoint.id) != historyPointsById_.end()) {
2435 historyPointsById_.erase(scalePoint.id);
2436 }
2437 if (scalePoint.type == TouchType::DOWN) {
2438 // Set focus state inactive while touch down event received
2439 SetIsFocusActive(false, FocusActiveReason::POINTER_EVENT);
2440 TouchRestrict touchRestrict { TouchRestrict::NONE };
2441 touchRestrict.sourceType = point.sourceType;
2442 touchRestrict.touchEvent = point;
2443 touchRestrict.inputEventType = InputEventType::TOUCH_SCREEN;
2444
2445 eventManager_->TouchTest(scalePoint, node, touchRestrict, GetPluginEventOffset(), viewScale_, isSubPipe);
2446 if (!touchRestrict.childTouchTestList.empty()) {
2447 scalePoint.childTouchTestList = touchRestrict.childTouchTestList;
2448 }
2449 touchTestResults_ = eventManager_->touchTestResults_;
2450 if (StylusDetectorMgr::GetInstance()->IsNeedInterceptedTouchEvent(scalePoint, touchTestResults_)) {
2451 eventManager_->ClearTouchTestTargetForPenStylus(scalePoint);
2452 return;
2453 }
2454
2455 HandleEtsCardTouchEvent(oriPoint, etsSerializedGesture);
2456
2457 if (etsSerializedGesture.data.size() != 0) {
2458 GestureGroup rebirth(GestureMode::Exclusive);
2459 rebirth.Deserialize(etsSerializedGesture.data.data());
2460 auto recognizer = rebirth.CreateRecognizer();
2461 if (recognizer) {
2462 recognizer->SetInnerFlag(true);
2463 recognizer->BeginReferee(scalePoint.id, true);
2464 std::list<RefPtr<NGGestureRecognizer>> combined;
2465 combined.emplace_back(recognizer);
2466 for (auto iter = touchTestResults_[point.id].begin();
2467 iter != touchTestResults_[point.id].end(); iter++) {
2468 auto outRecognizer = AceType::DynamicCast<NGGestureRecognizer>(*iter);
2469 if (outRecognizer) {
2470 combined.emplace_back(outRecognizer);
2471 touchTestResults_[point.id].erase(iter);
2472 break;
2473 }
2474 }
2475 auto exclusiveRecognizer = AceType::MakeRefPtr<ExclusiveRecognizer>(std::move(combined));
2476 exclusiveRecognizer->AttachFrameNode(node);
2477 exclusiveRecognizer->BeginReferee(scalePoint.id);
2478 touchTestResults_[point.id].emplace_back(exclusiveRecognizer);
2479 eventManager_->touchTestResults_ = touchTestResults_;
2480 eventManager_->SetInnerFlag(true);
2481 }
2482 }
2483 if (IsFormRender() && touchTestResults_.find(point.id) != touchTestResults_.end()) {
2484 for (const auto& touchResult : touchTestResults_[point.id]) {
2485 auto recognizer = AceType::DynamicCast<NG::RecognizerGroup>(touchResult);
2486 if (recognizer) {
2487 auto gesture = recognizer->CreateGestureFromRecognizer();
2488 if (gesture) {
2489 serializedGesture_.data = std::vector<char>(gesture->SizeofMe());
2490 gesture->Serialize(serializedGesture_.data.data());
2491 }
2492 break;
2493 }
2494 }
2495 }
2496 for (const auto& weakContext : touchPluginPipelineContext_) {
2497 auto pipelineContext = DynamicCast<OHOS::Ace::PipelineBase>(weakContext.Upgrade());
2498 if (!pipelineContext) {
2499 continue;
2500 }
2501 auto pluginPoint =
2502 point.UpdateScalePoint(viewScale_, static_cast<float>(pipelineContext->GetPluginEventOffset().GetX()),
2503 static_cast<float>(pipelineContext->GetPluginEventOffset().GetY()), point.id);
2504 // eventManager_ instance Id may changed.
2505 pipelineContext->OnTouchEvent(pluginPoint, true);
2506 }
2507
2508 // restore instance Id.
2509 eventManager_->SetInstanceId(GetInstanceId());
2510 }
2511 auto rootOffset = GetRootRect().GetOffset();
2512 eventManager_->HandleGlobalEventNG(scalePoint, selectOverlayManager_, rootOffset);
2513
2514 if (isSubPipe) {
2515 return;
2516 }
2517
2518 // Currently, SetupRootElement is executed later than InitializeCallback in AceContainer.
2519 // We need to check whether accessibilityManagerNG_ is created.
2520 if (accessibilityManagerNG_ != nullptr) {
2521 accessibilityManagerNG_->HandleAccessibilityHoverEvent(node, scalePoint);
2522 }
2523
2524 if (scalePoint.type == TouchType::MOVE) {
2525 if (isEventsPassThrough) {
2526 scalePoint.isPassThroughMode = true;
2527 eventManager_->DispatchTouchEvent(scalePoint);
2528 hasIdleTasks_ = true;
2529 RequestFrame();
2530 return;
2531 }
2532 if (!eventManager_->GetInnerFlag()) {
2533 auto mockPoint = point;
2534 mockPoint.type = TouchType::CANCEL;
2535 HandleEtsCardTouchEvent(mockPoint, etsSerializedGesture);
2536 RemoveEtsCardTouchEventCallback(mockPoint.id);
2537 }
2538 touchEvents_.emplace_back(point);
2539 hasIdleTasks_ = true;
2540 RequestFrame();
2541 return;
2542 }
2543
2544 if (scalePoint.type == TouchType::UP) {
2545 lastTouchTime_ = GetTimeFromExternalTimer();
2546 CompensateTouchMoveEvent(scalePoint);
2547 if (thpExtraMgr_ != nullptr) {
2548 const uint32_t delay = 800; // 800: ms
2549 taskExecutor_->RemoveTask(TaskExecutor::TaskType::UI, "NotifyResponseRegionChanged");
2550 auto task = [weak = WeakClaim(this)]() {
2551 auto pipeline = weak.Upgrade();
2552 CHECK_NULL_VOID(pipeline);
2553 pipeline->NotifyResponseRegionChanged(pipeline->GetRootElement());
2554 };
2555 taskExecutor_->PostDelayedTask(task, TaskExecutor::TaskType::UI, delay, "NotifyResponseRegionChanged");
2556 }
2557 }
2558
2559 eventManager_->DispatchTouchEvent(scalePoint);
2560
2561 if ((scalePoint.type == TouchType::UP) || (scalePoint.type == TouchType::CANCEL)) {
2562 // need to reset touchPluginPipelineContext_ for next touch down event.
2563 touchPluginPipelineContext_.clear();
2564 RemoveEtsCardTouchEventCallback(point.id);
2565 ResetDraggingStatus(scalePoint, node);
2566 }
2567 if (scalePoint.type != TouchType::MOVE) {
2568 lastDispatchTime_.erase(scalePoint.id);
2569 idToTouchPoints_.erase(scalePoint.id);
2570 }
2571
2572 hasIdleTasks_ = true;
2573 RequestFrame();
2574 }
2575
CompensateTouchMoveEventFromUnhandledEvents(const TouchEvent & event)2576 bool PipelineContext::CompensateTouchMoveEventFromUnhandledEvents(const TouchEvent& event)
2577 {
2578 std::vector<TouchEvent> history;
2579 if (!touchEvents_.empty()) {
2580 for (auto iter = touchEvents_.begin(); iter != touchEvents_.end();) {
2581 auto movePoint = (*iter).CreateScalePoint(GetViewScale());
2582 if (event.id == movePoint.id) {
2583 history.emplace_back(movePoint);
2584 iter = touchEvents_.erase(iter);
2585 } else {
2586 auto& pointers = iter->pointers;
2587 for (auto pointerIter = pointers.begin(); pointerIter != pointers.end();) {
2588 if (pointerIter->id == event.id) {
2589 pointerIter = pointers.erase(pointerIter);
2590 } else {
2591 ++pointerIter;
2592 }
2593 }
2594 ++iter;
2595 }
2596 }
2597 if (!history.empty()) {
2598 TouchEvent lastMoveEvent(history.back());
2599 lastMoveEvent.history.swap(history);
2600 eventManager_->SetLastMoveBeforeUp(event.sourceType == SourceType::MOUSE);
2601 eventManager_->DispatchTouchEvent(lastMoveEvent);
2602 eventManager_->SetLastMoveBeforeUp(false);
2603 } else {
2604 TAG_LOGI(AceLogTag::ACE_INPUTTRACKING,
2605 "Finger id: %{public}d, not found unhandled move event, compensate failed.", event.id);
2606 }
2607 return true;
2608 }
2609 return false;
2610 }
2611
CompensateTouchMoveEvent(const TouchEvent & event)2612 void PipelineContext::CompensateTouchMoveEvent(const TouchEvent& event)
2613 {
2614 if (event.type != TouchType::UP) {
2615 // If not up, no need to compensate touch move event.
2616 return;
2617 }
2618 if (!CompensateTouchMoveEventFromUnhandledEvents(event)) {
2619 // Compensate touch move event with all touch move Event before up has been handled.
2620 auto lastEventIter = idToTouchPoints_.find(event.id);
2621 if (lastEventIter != idToTouchPoints_.end()) {
2622 auto iter = lastDispatchTime_.find(lastEventIter->first);
2623 if (iter != lastDispatchTime_.end()) {
2624 ACE_SCOPED_TRACE("CompensateTouchMoveEvent last move event time: %s last dispatch time: %s",
2625 std::to_string(static_cast<uint64_t>(lastEventIter->second.time.time_since_epoch().count()))
2626 .c_str(),
2627 std::to_string(iter->second).c_str());
2628 if (static_cast<uint64_t>(lastEventIter->second.time.time_since_epoch().count()) > iter->second) {
2629 eventManager_->SetLastMoveBeforeUp(event.sourceType == SourceType::MOUSE);
2630 eventManager_->DispatchTouchEvent(lastEventIter->second);
2631 eventManager_->SetLastMoveBeforeUp(false);
2632 }
2633 }
2634 }
2635 }
2636
2637 auto lastEventIter = idToTouchPoints_.find(event.id);
2638 if (lastEventIter != idToTouchPoints_.end()) {
2639 ACE_SCOPED_TRACE("Finger id: %d process last move event eventId: %d", lastEventIter->first,
2640 lastEventIter->second.touchEventId);
2641 }
2642 }
2643
ResetDraggingStatus(const TouchEvent & touchPoint,const RefPtr<FrameNode> & node)2644 void PipelineContext::ResetDraggingStatus(const TouchEvent& touchPoint, const RefPtr<FrameNode>& node)
2645 {
2646 auto manager = GetDragDropManager();
2647 CHECK_NULL_VOID(manager);
2648 manager->ResetDraggingStatus(touchPoint);
2649 }
2650
OnSurfaceDensityChanged(double density)2651 void PipelineContext::OnSurfaceDensityChanged(double density)
2652 {
2653 CHECK_RUN_ON(UI);
2654 if (!NearEqual(density, density_)) {
2655 isDensityChanged_ = true;
2656 }
2657 density_ = density;
2658 if (!NearZero(viewScale_)) {
2659 dipScale_ = density_ / viewScale_;
2660 }
2661 if (isDensityChanged_) {
2662 UIObserverHandler::GetInstance().NotifyDensityChange(density_);
2663 PipelineBase::OnSurfaceDensityChanged(density);
2664 }
2665 }
2666
DumpPageViewData(const RefPtr<FrameNode> & node,RefPtr<ViewDataWrap> viewDataWrap,bool skipSubAutoFillContainer,bool needsRecordData)2667 bool PipelineContext::DumpPageViewData(const RefPtr<FrameNode>& node, RefPtr<ViewDataWrap> viewDataWrap,
2668 bool skipSubAutoFillContainer, bool needsRecordData)
2669 {
2670 CHECK_NULL_RETURN(viewDataWrap, false);
2671 RefPtr<FrameNode> pageNode = nullptr;
2672 RefPtr<FrameNode> dumpNode = nullptr;
2673 if (node == nullptr) {
2674 if (stageManager_) {
2675 pageNode = stageManager_->GetLastPage();
2676 dumpNode = pageNode;
2677 }
2678 } else {
2679 pageNode = node->GetPageNode();
2680 dumpNode = node;
2681 }
2682 CHECK_NULL_RETURN(dumpNode, false);
2683 dumpNode->DumpViewDataPageNodes(viewDataWrap, skipSubAutoFillContainer, needsRecordData);
2684 // The page path may not be obtained in the container, use the node tag as the page path.
2685 if (node) {
2686 const auto& nodeTag = node->GetTag();
2687 if (nodeTag == V2::DIALOG_ETS_TAG || nodeTag == V2::SHEET_PAGE_TAG || nodeTag == V2::MODAL_PAGE_TAG) {
2688 viewDataWrap->SetPageUrl(nodeTag);
2689 return true;
2690 }
2691 }
2692 CHECK_NULL_RETURN(pageNode, false);
2693 auto pagePattern = pageNode->GetPattern<NG::PagePattern>();
2694 CHECK_NULL_RETURN(pagePattern, false);
2695 auto pageInfo = pagePattern->GetPageInfo();
2696 CHECK_NULL_RETURN(pageInfo, false);
2697 viewDataWrap->SetPageUrl(pageInfo->GetPageUrl());
2698 return true;
2699 }
2700
CheckNeedAutoSave()2701 bool PipelineContext::CheckNeedAutoSave()
2702 {
2703 CHECK_NULL_RETURN(stageManager_, false);
2704 auto pageNode = stageManager_->GetLastPage();
2705 CHECK_NULL_RETURN(pageNode, false);
2706 return pageNode->NeedRequestAutoSave();
2707 }
2708
CheckOverlayFocus()2709 bool PipelineContext::CheckOverlayFocus()
2710 {
2711 CHECK_NULL_RETURN(overlayManager_, false);
2712 auto overlayNode = overlayManager_->GetOverlayNode();
2713 CHECK_NULL_RETURN(overlayNode, false);
2714 return overlayNode->GetFocusHub() && overlayNode->GetFocusHub()->IsCurrentFocus();
2715 }
2716
NotifyFillRequestSuccess(AceAutoFillType autoFillType,RefPtr<ViewDataWrap> viewDataWrap)2717 void PipelineContext::NotifyFillRequestSuccess(AceAutoFillType autoFillType, RefPtr<ViewDataWrap> viewDataWrap)
2718 {
2719 CHECK_NULL_VOID(viewDataWrap);
2720 auto pageNodeInfoWraps = viewDataWrap->GetPageNodeInfoWraps();
2721 for (const auto& item : pageNodeInfoWraps) {
2722 if (item == nullptr) {
2723 continue;
2724 }
2725 auto frameNode = DynamicCast<FrameNode>(ElementRegister::GetInstance()->GetUINodeById(item->GetId()));
2726 if (frameNode == nullptr) {
2727 TAG_LOGW(AceLogTag::ACE_AUTO_FILL, "frameNode is not found, id=%{public}d", item->GetId());
2728 continue;
2729 }
2730 frameNode->NotifyFillRequestSuccess(viewDataWrap, item, autoFillType);
2731 }
2732 }
2733
NotifyFillRequestFailed(RefPtr<FrameNode> node,int32_t errCode,const std::string & fillContent,bool isPopup)2734 void PipelineContext::NotifyFillRequestFailed(RefPtr<FrameNode> node, int32_t errCode,
2735 const std::string& fillContent, bool isPopup)
2736 {
2737 CHECK_NULL_VOID(node);
2738 node->NotifyFillRequestFailed(errCode, fillContent, isPopup);
2739 }
2740
OnDumpInfo(const std::vector<std::string> & params) const2741 bool PipelineContext::OnDumpInfo(const std::vector<std::string>& params) const
2742 {
2743 ACE_DCHECK(!params.empty());
2744 if (window_) {
2745 DumpLog::GetInstance().Print(1, "LastRequestVsyncTime: " + std::to_string(window_->GetLastRequestVsyncTime()));
2746 #ifdef ENABLE_ROSEN_BACKEND
2747 auto rsUIDirector = window_->GetRSUIDirector();
2748 if (rsUIDirector) {
2749 DumpLog::GetInstance().Print(1, "transactionFlags: [" + std::to_string(getpid()) + "," +
2750 std::to_string(rsUIDirector->GetIndex()) + "]");
2751 }
2752 #endif
2753 }
2754 DumpLog::GetInstance().Print(1, "last vsyncId: " + std::to_string(GetFrameCount()));
2755 if (params[0] == "-element") {
2756 if (params.size() > 1 && params[1] == "-lastpage") {
2757 auto lastPage = stageManager_->GetLastPage();
2758 if (params.size() < USED_ID_FIND_FLAG && lastPage) {
2759 lastPage->DumpTree(0);
2760 DumpLog::GetInstance().OutPutBySize();
2761 }
2762 if (params.size() == USED_ID_FIND_FLAG && lastPage && !lastPage->DumpTreeById(0, params[2])) {
2763 DumpLog::GetInstance().Print(
2764 "There is no id matching the ID in the parameter,please check whether the id is correct");
2765 }
2766 } else {
2767 if (params.size() == USED_ID_FIND_FLAG && !rootNode_->DumpTreeById(0, params[2])) {
2768 DumpLog::GetInstance().Print(
2769 "There is no id matching the ID in the parameter,please check whether the id is correct");
2770 }
2771 if (params.size() < USED_ID_FIND_FLAG) {
2772 rootNode_->DumpTree(0);
2773 DumpLog::GetInstance().OutPutBySize();
2774 }
2775 }
2776 } else if (params[0] == "-navigation") {
2777 auto navigationDumpMgr = GetNavigationManager();
2778 if (navigationDumpMgr) {
2779 navigationDumpMgr->OnDumpInfo();
2780 }
2781 } else if (params[0] == "-focus") {
2782 if (rootNode_->GetFocusHub()) {
2783 rootNode_->GetFocusHub()->DumpFocusTree(0);
2784 }
2785 } else if (params[0] == "-focuswindowscene") {
2786 auto windowSceneNode = GetFocusedWindowSceneNode();
2787 auto windowSceneFocusHub = windowSceneNode ? windowSceneNode->GetFocusHub() : nullptr;
2788 if (windowSceneFocusHub) {
2789 windowSceneFocusHub->DumpFocusTree(0);
2790 }
2791 } else if (params[0] == "-focusmanager") {
2792 if (focusManager_) {
2793 focusManager_->DumpFocusManager();
2794 }
2795 } else if (params[0] == "-accessibility" || params[0] == "-inspector") {
2796 auto accessibilityManager = GetAccessibilityManager();
2797 if (accessibilityManager) {
2798 accessibilityManager->OnDumpInfoNG(params, windowId_);
2799 }
2800 } else if (params[0] == "-rotation" && params.size() >= 2) {
2801 } else if (params[0] == "-animationscale" && params.size() >= 2) {
2802 } else if (params[0] == "-velocityscale" && params.size() >= 2) {
2803 } else if (params[0] == "-scrollfriction" && params.size() >= 2) {
2804 } else if (params[0] == "-threadstuck" && params.size() >= 3) {
2805 } else if (params[0] == "-pipeline") {
2806 DumpPipelineInfo();
2807 } else if (params[0] == "-jsdump") {
2808 std::vector<std::string> jsParams;
2809 if (params.begin() != params.end()) {
2810 jsParams = std::vector<std::string>(params.begin() + 1, params.end());
2811 }
2812
2813 auto stageNode = stageManager_->GetStageNode();
2814 CHECK_NULL_RETURN(stageNode, false);
2815 auto children = stageNode->GetChildren();
2816 for (const auto& pageNode : children) {
2817 auto frameNode = AceType::DynamicCast<FrameNode>(pageNode);
2818 CHECK_NULL_RETURN(frameNode, false);
2819 auto pagePattern = frameNode->GetPattern<PagePattern>();
2820 CHECK_NULL_RETURN(pagePattern, false);
2821 pagePattern->FireDumpListener(jsParams);
2822 }
2823 } else if (params[0] == "-event") {
2824 if (eventManager_) {
2825 eventManager_->DumpEvent(EventTreeType::TOUCH);
2826 }
2827 DumpUIExt();
2828 } else if (params[0] == "-postevent") {
2829 if (eventManager_) {
2830 eventManager_->DumpEvent(EventTreeType::POST_EVENT);
2831 }
2832 } else if (params[0] == "-imagecache") {
2833 if (imageCache_) {
2834 imageCache_->DumpCacheInfo();
2835 }
2836 DumpUIExt();
2837 } else if (params[0] == "-imagefilecache") {
2838 ImageFileCache::GetInstance().DumpCacheInfo();
2839 DumpUIExt();
2840 } else if (params[0] == "-allelements") {
2841 AceEngine::Get().NotifyContainers([](const RefPtr<Container>& container) {
2842 auto pipeline = AceType::DynamicCast<NG::PipelineContext>(container->GetPipelineContext());
2843 auto rootNode = pipeline->GetRootElement();
2844 if (rootNode) {
2845 DumpLog::GetInstance().Print(0, "ContainerId: " + std::to_string(Container::CurrentId()));
2846 rootNode->DumpTree(0);
2847 DumpLog::GetInstance().OutPutBySize();
2848 }
2849 });
2850 } else if (params[0] == "-default") {
2851 rootNode_->DumpTree(0);
2852 DumpLog::GetInstance().OutPutDefault();
2853 } else if (params[0] == "--stylus") {
2854 StylusDetectorDefault::GetInstance()->ExecuteCommand(params);
2855 } else if (params[0] == "-overlay") {
2856 if (overlayManager_) {
2857 overlayManager_->DumpOverlayInfo();
2858 }
2859 } else if (params[0] == "-simplify") {
2860 auto root = JsonUtil::Create(true);
2861 rootNode_->DumpSimplifyTree(0, root);
2862 auto json = root->ToString();
2863 json.erase(std::remove(json.begin(), json.end(), ' '), json.end());
2864 DumpLog::GetInstance().Print(json);
2865 }
2866 return true;
2867 }
2868
DumpUIExt() const2869 void PipelineContext::DumpUIExt() const
2870 {
2871 #ifdef WINDOW_SCENE_SUPPORTED
2872 if (uiExtensionManager_) {
2873 uiExtensionManager_->DumpUIExt();
2874 }
2875 #endif
2876 }
2877
GetCurrentFrameInfo(uint64_t recvTime,uint64_t timeStamp)2878 FrameInfo* PipelineContext::GetCurrentFrameInfo(uint64_t recvTime, uint64_t timeStamp)
2879 {
2880 if (SystemProperties::GetDumpFrameCount() == 0) {
2881 return nullptr;
2882 }
2883 if (dumpFrameInfos_.size() >= SystemProperties::GetDumpFrameCount()) {
2884 dumpFrameInfos_.pop_front();
2885 }
2886
2887 dumpFrameInfos_.push_back({ .frameRecvTime_ = recvTime, .frameTimeStamp_ = timeStamp });
2888 return &dumpFrameInfos_.back();
2889 }
2890
DumpPipelineInfo() const2891 void PipelineContext::DumpPipelineInfo() const
2892 {
2893 DumpLog::GetInstance().Print("PipelineInfo:");
2894 if (window_) {
2895 DumpLog::GetInstance().Print(1, "DisplayRefreshRate: " + std::to_string(window_->GetRefreshRate()));
2896 DumpLog::GetInstance().Print(1, "LastRequestVsyncTime: " + std::to_string(window_->GetLastRequestVsyncTime()));
2897 DumpLog::GetInstance().Print(1, "NowTime: " + std::to_string(GetSysTimestamp()));
2898 }
2899 if (!dumpFrameInfos_.empty()) {
2900 DumpLog::GetInstance().Print("==================================FrameTask==================================");
2901 for (const auto& info : dumpFrameInfos_) {
2902 DumpLog::GetInstance().Print("Task: " + info.GetTimeInfo());
2903 DumpLog::GetInstance().Print(1, "LayoutTask:");
2904 for (const auto& layout : info.layoutInfos_) {
2905 DumpLog::GetInstance().Print(2, layout.ToString());
2906 }
2907 DumpLog::GetInstance().Print(1, "RenderTask:");
2908 for (const auto& layout : info.renderInfos_) {
2909 DumpLog::GetInstance().Print(2, layout.ToString());
2910 }
2911 DumpLog::GetInstance().Print(
2912 "==================================FrameTask==================================");
2913 }
2914 }
2915 }
2916
CollectTouchEventsBeforeVsync(std::list<TouchEvent> & touchEvents)2917 void PipelineContext::CollectTouchEventsBeforeVsync(std::list<TouchEvent>& touchEvents)
2918 {
2919 auto targetTimeStamp = GetVsyncTime() - compensationValue_;
2920 for (auto iter = touchEvents_.begin(); iter != touchEvents_.end();) {
2921 auto timeStamp = std::chrono::duration_cast<std::chrono::nanoseconds>(iter->time.time_since_epoch()).count();
2922 if (targetTimeStamp < static_cast<uint64_t>(timeStamp)) {
2923 iter++;
2924 continue;
2925 }
2926 touchEvents.emplace_back(*iter);
2927 iter = touchEvents_.erase(iter);
2928 }
2929 }
2930
FlushTouchEvents()2931 void PipelineContext::FlushTouchEvents()
2932 {
2933 CHECK_RUN_ON(UI);
2934 CHECK_NULL_VOID(rootNode_);
2935 {
2936 std::unordered_set<int32_t> moveEventIds;
2937 std::list<TouchEvent> touchEvents;
2938 CollectTouchEventsBeforeVsync(touchEvents);
2939 if (touchEvents.empty()) {
2940 canUseLongPredictTask_ = true;
2941 return;
2942 }
2943 canUseLongPredictTask_ = false;
2944 eventManager_->FlushTouchEventsBegin(touchEvents_);
2945 std::unordered_map<int, TouchEvent> idToTouchPoints;
2946 bool needInterpolation = true;
2947 std::unordered_map<int32_t, TouchEvent> newIdTouchPoints;
2948 for (auto iter = touchEvents.rbegin(); iter != touchEvents.rend(); ++iter) {
2949 auto scalePoint = (*iter).CreateScalePoint(GetViewScale());
2950 idToTouchPoints.emplace(scalePoint.id, scalePoint);
2951 idToTouchPoints[scalePoint.id].history.insert(idToTouchPoints[scalePoint.id].history.begin(), scalePoint);
2952 needInterpolation = iter->type != TouchType::MOVE ? false : true;
2953 }
2954 if (focusWindowId_.has_value()) {
2955 needInterpolation = false;
2956 }
2957 if (needInterpolation && SystemProperties::IsNeedResampleTouchPoints()) {
2958 auto targetTimeStamp = resampleTimeStamp_;
2959 for (const auto& idIter : idToTouchPoints) {
2960 auto stamp =
2961 std::chrono::duration_cast<std::chrono::nanoseconds>(idIter.second.time.time_since_epoch()).count();
2962 if (targetTimeStamp > static_cast<uint64_t>(stamp)) {
2963 continue;
2964 }
2965 TouchEvent newTouchEvent;
2966 if (GetResampleTouchEvent(
2967 historyPointsById_[idIter.first], idIter.second.history, targetTimeStamp, newTouchEvent)) {
2968 newIdTouchPoints[idIter.first] = newTouchEvent;
2969 }
2970 historyPointsById_[idIter.first] = idIter.second.history;
2971 }
2972 }
2973 std::list<TouchEvent> touchPoints;
2974 for (const auto& iter : idToTouchPoints) {
2975 lastDispatchTime_[iter.first] = GetVsyncTime() - compensationValue_;
2976 auto it = newIdTouchPoints.find(iter.first);
2977 if (it != newIdTouchPoints.end()) {
2978 touchPoints.emplace_back(it->second);
2979 } else {
2980 touchPoints.emplace_back(iter.second);
2981 }
2982 }
2983 auto maxSize = touchPoints.size();
2984 for (auto iter = touchPoints.rbegin(); iter != touchPoints.rend(); ++iter) {
2985 maxSize--;
2986 if (maxSize == 0) {
2987 eventManager_->FlushTouchEventsEnd(touchPoints);
2988 }
2989 eventManager_->DispatchTouchEvent(*iter);
2990 }
2991 idToTouchPoints_ = std::move(idToTouchPoints);
2992 }
2993 }
2994
OnAccessibilityHoverEvent(const TouchEvent & point,const RefPtr<NG::FrameNode> & node)2995 void PipelineContext::OnAccessibilityHoverEvent(const TouchEvent& point, const RefPtr<NG::FrameNode>& node)
2996 {
2997 CHECK_RUN_ON(UI);
2998 auto scaleEvent = point.CreateScalePoint(viewScale_);
2999 if (scaleEvent.type != TouchType::HOVER_MOVE) {
3000 #ifdef IS_RELEASE_VERSION
3001 TAG_LOGI(AceLogTag::ACE_INPUTTRACKING,
3002 "OnAccessibilityHoverEvent event id:%{public}d, fingerId:%{public}d,"
3003 "type=%{public}d, "
3004 "inject=%{public}d",
3005 scaleEvent.touchEventId, scaleEvent.id, (int)scaleEvent.type, scaleEvent.isInjected);
3006 #else
3007 TAG_LOGI(AceLogTag::ACE_INPUTTRACKING,
3008 "OnAccessibilityHoverEvent event id:%{public}d, fingerId:%{public}d, x=%{public}f y=%{public}f "
3009 "type=%{public}d, "
3010 "inject=%{public}d",
3011 scaleEvent.touchEventId, scaleEvent.id, scaleEvent.x, scaleEvent.y, (int)scaleEvent.type,
3012 scaleEvent.isInjected);
3013 #endif
3014 }
3015 auto targerNode = node ? node : rootNode_;
3016 if (accessibilityManagerNG_ != nullptr) {
3017 accessibilityManagerNG_->HandleAccessibilityHoverEvent(targerNode, scaleEvent);
3018 }
3019 TouchRestrict touchRestrict { TouchRestrict::NONE };
3020 touchRestrict.sourceType = scaleEvent.sourceType;
3021 // use mouse to collect accessibility hover target
3022 touchRestrict.hitTestType = SourceType::MOUSE;
3023 touchRestrict.inputEventType = InputEventType::TOUCH_SCREEN;
3024 eventManager_->AccessibilityHoverTest(scaleEvent, targerNode, touchRestrict);
3025 eventManager_->DispatchAccessibilityHoverEventNG(scaleEvent);
3026 RequestFrame();
3027 }
3028
OnPenHoverEvent(const TouchEvent & point,const RefPtr<NG::FrameNode> & node)3029 void PipelineContext::OnPenHoverEvent(const TouchEvent& point, const RefPtr<NG::FrameNode>& node)
3030 {
3031 CHECK_RUN_ON(UI);
3032 auto scaleEvent = point.CreateScalePoint(viewScale_);
3033 if (scaleEvent.type != TouchType::MOVE) {
3034 TAG_LOGI(AceLogTag::ACE_INPUTTRACKING,
3035 "OnPenHoverEvent event id:%{public}d, fingerId:%{public}d "
3036 "type=%{public}d, "
3037 "inject=%{public}d",
3038 scaleEvent.touchEventId, scaleEvent.id, (int)scaleEvent.type,
3039 scaleEvent.isInjected);
3040 }
3041
3042 auto targerNode = node ? node : rootNode_;
3043 TouchRestrict touchRestrict { TouchRestrict::NONE };
3044 touchRestrict.sourceType = scaleEvent.sourceType;
3045 touchRestrict.touchEvent.sourceTool = scaleEvent.sourceTool;
3046 touchRestrict.touchEvent.type = scaleEvent.type;
3047 touchRestrict.touchEvent.force = scaleEvent.force;
3048
3049 // use mouse to collect pen hover target
3050 touchRestrict.hitTestType = SourceType::MOUSE;
3051 touchRestrict.inputEventType = InputEventType::TOUCH_SCREEN;
3052 eventManager_->PenHoverTest(scaleEvent, targerNode, touchRestrict);
3053 eventManager_->DispatchPenHoverEventNG(scaleEvent);
3054 RequestFrame();
3055 }
3056
HandlePenHoverOut(const TouchEvent & point)3057 void PipelineContext::HandlePenHoverOut(const TouchEvent& point)
3058 {
3059 if (point.sourceTool != SourceTool::PEN || point.type != TouchType::DOWN || NearZero(point.force)) {
3060 return;
3061 }
3062
3063 CHECK_RUN_ON(UI);
3064 auto oriPoint = point;
3065 oriPoint.type = TouchType::PROXIMITY_OUT;
3066
3067 TouchTestResult testResult;
3068 eventManager_->UpdatePenHoverNode(oriPoint, testResult);
3069 eventManager_->DispatchPenHoverEventNG(oriPoint);
3070 }
3071
OnMouseEvent(const MouseEvent & event,const RefPtr<FrameNode> & node)3072 void PipelineContext::OnMouseEvent(const MouseEvent& event, const RefPtr<FrameNode>& node)
3073 {
3074 CHECK_RUN_ON(UI);
3075 if (!lastMouseEvent_) {
3076 lastMouseEvent_ = std::make_unique<MouseEvent>();
3077 }
3078 lastMouseEvent_->x = event.x;
3079 lastMouseEvent_->y = event.y;
3080 lastMouseEvent_->button = event.button;
3081 lastMouseEvent_->action = event.action;
3082 lastMouseEvent_->sourceType = event.sourceType;
3083 lastMouseEvent_->time = event.time;
3084 lastMouseEvent_->touchEventId = event.touchEventId;
3085
3086 if (event.button == MouseButton::RIGHT_BUTTON && event.action == MouseAction::PRESS) {
3087 // Mouse right button press event set focus inactive here.
3088 // Mouse left button press event will set focus inactive in touch process.
3089 SetIsFocusActive(false, FocusActiveReason::POINTER_EVENT);
3090 }
3091
3092 auto manager = GetDragDropManager();
3093 if (manager) {
3094 if (event.button == MouseButton::RIGHT_BUTTON &&
3095 (event.action == MouseAction::PRESS || event.action == MouseAction::PULL_UP)) {
3096 manager->SetIsDragCancel(true);
3097 } else {
3098 manager->SetIsDragCancel(false);
3099 }
3100 } else {
3101 TAG_LOGW(AceLogTag::ACE_INPUTTRACKING, "InputTracking id:%{public}d, OnMouseEvent GetDragDropManager is null",
3102 event.touchEventId);
3103 }
3104
3105 auto container = Container::Current();
3106 if (((event.action == MouseAction::RELEASE || event.action == MouseAction::PRESS ||
3107 event.action == MouseAction::MOVE) &&
3108 (event.button == MouseButton::LEFT_BUTTON || event.pressedButtons == MOUSE_PRESS_LEFT)) ||
3109 event.action == MouseAction::CANCEL) {
3110 auto touchPoint = event.CreateTouchPoint();
3111 if (event.pullAction == MouseAction::PULL_MOVE) {
3112 touchPoint.pullType = TouchType::PULL_MOVE;
3113 }
3114 OnTouchEvent(touchPoint, node);
3115 } else {
3116 auto touchPoint = event.CreateTouchPoint();
3117 auto scalePoint = touchPoint.CreateScalePoint(GetViewScale());
3118 auto rootOffset = GetRootRect().GetOffset();
3119 eventManager_->HandleGlobalEventNG(scalePoint, selectOverlayManager_, rootOffset);
3120 }
3121
3122 CHECK_NULL_VOID(node);
3123 auto scaleEvent = event.CreateScaleEvent(viewScale_);
3124 TouchRestrict touchRestrict { TouchRestrict::NONE };
3125 touchRestrict.sourceType = event.sourceType;
3126 touchRestrict.hitTestType = SourceType::MOUSE;
3127 touchRestrict.inputEventType = InputEventType::MOUSE_BUTTON;
3128 eventManager_->MouseTest(scaleEvent, node, touchRestrict);
3129 eventManager_->DispatchMouseEventNG(scaleEvent);
3130 eventManager_->DispatchMouseHoverEventNG(scaleEvent);
3131 eventManager_->DispatchMouseHoverAnimationNG(scaleEvent);
3132 accessibilityManagerNG_->HandleAccessibilityHoverEvent(node, scaleEvent);
3133 RequestFrame();
3134 }
3135
FlushMouseEvent()3136 void PipelineContext::FlushMouseEvent()
3137 {
3138 if (!lastMouseEvent_ || lastMouseEvent_->action == MouseAction::WINDOW_LEAVE) {
3139 return;
3140 }
3141 auto container = Container::Current();
3142 if (container) {
3143 int32_t sourceType = 0;
3144 auto result = container->GetCurPointerEventSourceType(sourceType);
3145 if (result) {
3146 TAG_LOGI(AceLogTag::ACE_MOUSE,
3147 "FlushMouseEvent: last pointer event id %{public}d sourceType:%{public}d last mouse event "
3148 "time:%{public}" PRId64 " current time %{public}" PRId64 "",
3149 lastMouseEvent_->touchEventId, sourceType,
3150 static_cast<int64_t>(lastMouseEvent_->time.time_since_epoch().count()), GetSysTimestamp());
3151 }
3152 }
3153 MouseEvent event;
3154 event.x = lastMouseEvent_->x;
3155 event.y = lastMouseEvent_->y;
3156 event.time = lastMouseEvent_->time;
3157 event.action = MouseAction::MOVE;
3158 event.button = MouseButton::NONE_BUTTON;
3159 event.sourceType = SourceType::MOUSE;
3160
3161 CHECK_RUN_ON(UI);
3162 CHECK_NULL_VOID(rootNode_);
3163 auto scaleEvent = event.CreateScaleEvent(viewScale_);
3164 TouchRestrict touchRestrict { TouchRestrict::NONE };
3165 touchRestrict.sourceType = event.sourceType;
3166 touchRestrict.hitTestType = SourceType::MOUSE;
3167 touchRestrict.inputEventType = InputEventType::MOUSE_BUTTON;
3168 eventManager_->MouseTest(scaleEvent, rootNode_, touchRestrict);
3169 eventManager_->DispatchMouseEventNG(scaleEvent);
3170 eventManager_->DispatchMouseHoverEventNG(scaleEvent);
3171 eventManager_->DispatchMouseHoverAnimationNG(scaleEvent);
3172 }
3173
ChangeMouseStyle(int32_t nodeId,MouseFormat format,int32_t windowId,bool isByPass)3174 bool PipelineContext::ChangeMouseStyle(int32_t nodeId, MouseFormat format, int32_t windowId, bool isByPass)
3175 {
3176 auto window = GetWindow();
3177 if (window && window->IsUserSetCursor()) {
3178 return false;
3179 }
3180 if (mouseStyleNodeId_ != nodeId || isByPass) {
3181 return false;
3182 }
3183 auto mouseStyle = MouseStyle::CreateMouseStyle();
3184 CHECK_NULL_RETURN(mouseStyle, false);
3185 if (windowId) {
3186 return mouseStyle->ChangePointerStyle(windowId, format);
3187 }
3188 return mouseStyle->ChangePointerStyle(GetFocusWindowId(), format);
3189 }
3190
TriggerKeyEventDispatch(const KeyEvent & event)3191 bool PipelineContext::TriggerKeyEventDispatch(const KeyEvent& event)
3192 {
3193 auto curFocusView = focusManager_ ? focusManager_->GetLastFocusView().Upgrade() : nullptr;
3194 auto curEntryFocusView = curFocusView ? curFocusView->GetEntryFocusView() : nullptr;
3195 auto curEntryFocusViewFrame = curEntryFocusView ? curEntryFocusView->GetFrameNode() : nullptr;
3196 if (event.isPreIme) {
3197 return eventManager_->DispatchKeyEventNG(event, curEntryFocusViewFrame);
3198 }
3199
3200 if (!IsSkipShortcutAndFocusMove() && DispatchTabKey(event, curFocusView)) {
3201 return true;
3202 }
3203 return eventManager_->DispatchKeyEventNG(event, curEntryFocusViewFrame);
3204 }
3205
IsSkipShortcutAndFocusMove()3206 bool PipelineContext::IsSkipShortcutAndFocusMove()
3207 {
3208 // Web component will NOT dispatch shortcut during the first event dispatch process.
3209 // Web component will NOT trigger focus move during the third event dispatch process.
3210 auto focusHub = focusManager_ ? focusManager_->GetCurrentFocus() : nullptr;
3211 RefPtr<FrameNode> curFrameNode = focusHub ? focusHub->GetFrameNode() : nullptr;
3212 return EventManager::IsSkipEventNode(curFrameNode);
3213 }
3214
DispatchTabKey(const KeyEvent & event,const RefPtr<FocusView> & curFocusView)3215 bool PipelineContext::DispatchTabKey(const KeyEvent& event, const RefPtr<FocusView>& curFocusView)
3216 {
3217 auto curEntryFocusView = curFocusView ? curFocusView->GetEntryFocusView() : nullptr;
3218 auto curEntryFocusViewFrame = curEntryFocusView ? curEntryFocusView->GetFrameNode() : nullptr;
3219 auto isKeyTabDown = event.action == KeyAction::DOWN && event.IsKey({ KeyCode::KEY_TAB });
3220 auto isViewRootScopeFocused = curFocusView ? curFocusView->GetIsViewRootScopeFocused() : true;
3221 isTabJustTriggerOnKeyEvent_ = false;
3222
3223 if (isKeyTabDown && isViewRootScopeFocused && curFocusView) {
3224 // Current focused on the view root scope. Tab key used to extend focus.
3225 // If return true. This tab key will just trigger onKeyEvent process.
3226 isTabJustTriggerOnKeyEvent_ = curFocusView->TriggerFocusMove();
3227 }
3228
3229 // Tab key set focus state from inactive to active.
3230 // If return true. This tab key will just trigger onKeyEvent process.
3231 bool isHandleFocusActive = isKeyTabDown && SetIsFocusActive(true);
3232 isTabJustTriggerOnKeyEvent_ = isTabJustTriggerOnKeyEvent_ || isHandleFocusActive;
3233 if (eventManager_->DispatchTabIndexEventNG(event, curEntryFocusViewFrame)) {
3234 return true;
3235 }
3236 return false;
3237 }
3238
ReDispatch(KeyEvent & keyEvent)3239 void PipelineContext::ReDispatch(KeyEvent& keyEvent)
3240 {
3241 CHECK_NULL_VOID(eventManager_);
3242 TAG_LOGD(AceLogTag::ACE_WEB, "Web ReDispach key event: code:%{public}d/action:%{public}d.", keyEvent.code,
3243 keyEvent.action);
3244 // Set keyEvent coming from Redispatch
3245 keyEvent.isRedispatch = true;
3246
3247 if (eventManager_->DispatchKeyboardShortcut(keyEvent)) {
3248 return;
3249 }
3250
3251 auto curFocusView = focusManager_ ? focusManager_->GetLastFocusView().Upgrade() : nullptr;
3252 auto curEntryFocusView = curFocusView ? curFocusView->GetEntryFocusView() : nullptr;
3253 auto curEntryFocusViewFrame = curEntryFocusView ? curEntryFocusView->GetFrameNode() : nullptr;
3254 if (DispatchTabKey(keyEvent, curFocusView)) {
3255 return;
3256 }
3257 eventManager_->DispatchKeyEventNG(keyEvent, curEntryFocusViewFrame);
3258 }
3259
OnKeyEvent(const KeyEvent & event)3260 bool PipelineContext::OnKeyEvent(const KeyEvent& event)
3261 {
3262 CHECK_NULL_RETURN(eventManager_, false);
3263 eventManager_->SetPressedKeyCodes(event.pressedCodes);
3264
3265 // onKeyPreIme
3266 if (event.isPreIme) {
3267 if (TriggerKeyEventDispatch(event)) {
3268 return true;
3269 }
3270 if (!IsSkipShortcutAndFocusMove()) {
3271 return eventManager_->DispatchKeyboardShortcut(event);
3272 }
3273 return false;
3274 }
3275
3276 // process drag cancel
3277 if (event.code == KeyCode::KEY_ESCAPE) {
3278 auto manager = GetDragDropManager();
3279 if (manager && manager->IsMSDPDragging()) {
3280 manager->SetIsDragCancel(true);
3281 manager->OnDragEnd(PointerEvent(0, 0), "");
3282 manager->SetIsDragCancel(false);
3283 return true;
3284 }
3285 }
3286
3287 // OnKeyEvent
3288 if (TriggerKeyEventDispatch(event)) {
3289 return true;
3290 }
3291
3292 // process exit overlay
3293 if (event.code == KeyCode::KEY_ESCAPE && event.action == KeyAction::DOWN) {
3294 CHECK_NULL_RETURN(overlayManager_, false);
3295 auto currentContainer = Container::Current();
3296 if (currentContainer->IsSubContainer() || currentContainer->IsDialogContainer()) {
3297 return overlayManager_->RemoveOverlayInSubwindow();
3298 } else {
3299 return overlayManager_->RemoveOverlay(false);
3300 }
3301 }
3302 return false;
3303 }
3304
RequestFocus(const std::string & targetNodeId,bool isSyncRequest)3305 bool PipelineContext::RequestFocus(const std::string& targetNodeId, bool isSyncRequest)
3306 {
3307 auto rootNode = GetFocusedWindowSceneNode();
3308 if (!rootNode) {
3309 rootNode = rootNode_;
3310 }
3311 CHECK_NULL_RETURN(rootNode, false);
3312 auto focusHub = rootNode->GetFocusHub();
3313 CHECK_NULL_RETURN(focusHub, false);
3314 auto currentFocusChecked = focusHub->RequestFocusImmediatelyById(targetNodeId, isSyncRequest);
3315 if (!isSubPipeline_ || currentFocusChecked) {
3316 return currentFocusChecked;
3317 }
3318 auto parentPipelineBase = parentPipeline_.Upgrade();
3319 CHECK_NULL_RETURN(parentPipelineBase, false);
3320 auto parentPipelineContext = AceType::DynamicCast<NG::PipelineContext>(parentPipelineBase);
3321 CHECK_NULL_RETURN(parentPipelineContext, false);
3322 return parentPipelineContext->RequestFocus(targetNodeId, isSyncRequest);
3323 }
3324
AddDirtyFocus(const RefPtr<FrameNode> & node)3325 void PipelineContext::AddDirtyFocus(const RefPtr<FrameNode>& node)
3326 {
3327 CHECK_RUN_ON(UI);
3328 CHECK_NULL_VOID(node);
3329 if (node->GetFocusType() == FocusType::NODE) {
3330 dirtyFocusNode_ = WeakClaim(RawPtr(node));
3331 } else {
3332 dirtyFocusScope_ = WeakClaim(RawPtr(node));
3333 }
3334 RequestFrame();
3335 }
3336
AddDirtyRequestFocus(const RefPtr<FrameNode> & node)3337 void PipelineContext::AddDirtyRequestFocus(const RefPtr<FrameNode>& node)
3338 {
3339 CHECK_RUN_ON(UI);
3340 CHECK_NULL_VOID(node);
3341 dirtyRequestFocusNode_ = WeakPtr<FrameNode>(node);
3342 RequestFrame();
3343 }
3344
RootLostFocus(BlurReason reason) const3345 void PipelineContext::RootLostFocus(BlurReason reason) const
3346 {
3347 CHECK_NULL_VOID(rootNode_);
3348 auto focusHub = rootNode_->GetFocusHub();
3349 CHECK_NULL_VOID(focusHub);
3350 focusHub->LostFocus(reason);
3351 CHECK_NULL_VOID(overlayManager_);
3352 overlayManager_->HideAllMenus();
3353 }
3354
ConvertAxisToMouse(const AxisEvent & event)3355 MouseEvent ConvertAxisToMouse(const AxisEvent& event)
3356 {
3357 MouseEvent result;
3358 result.x = event.x;
3359 result.y = event.y;
3360 result.action = MouseAction::MOVE;
3361 result.button = MouseButton::NONE_BUTTON;
3362 result.time = event.time;
3363 result.deviceId = event.deviceId;
3364 result.sourceType = event.sourceType;
3365 result.sourceTool = event.sourceTool;
3366 result.touchEventId = event.touchEventId;
3367 result.pointerEvent = event.pointerEvent;
3368 result.screenX = event.screenX;
3369 result.screenY = event.screenY;
3370 return result;
3371 }
3372
OnAxisEvent(const AxisEvent & event,const RefPtr<FrameNode> & node)3373 void PipelineContext::OnAxisEvent(const AxisEvent& event, const RefPtr<FrameNode>& node)
3374 {
3375 auto scaleEvent = event.CreateScaleEvent(viewScale_);
3376
3377 auto dragManager = GetDragDropManager();
3378 if (dragManager && !dragManager->IsDragged()) {
3379 if (event.action == AxisAction::BEGIN) {
3380 isBeforeDragHandleAxis_ = true;
3381 TouchRestrict touchRestrict { TouchRestrict::NONE };
3382 touchRestrict.sourceType = event.sourceType;
3383 touchRestrict.hitTestType = SourceType::TOUCH;
3384 touchRestrict.inputEventType = InputEventType::AXIS;
3385 // If received rotate event, no need to touchtest.
3386 if (!event.isRotationEvent) {
3387 eventManager_->TouchTest(scaleEvent, node, touchRestrict);
3388 }
3389 }
3390 eventManager_->DispatchTouchEvent(scaleEvent);
3391 } else if (isBeforeDragHandleAxis_ && event.action == AxisAction::END) {
3392 eventManager_->DispatchTouchEvent(scaleEvent);
3393 isBeforeDragHandleAxis_ = false;
3394 }
3395
3396 if (event.action == AxisAction::BEGIN || event.action == AxisAction::UPDATE) {
3397 eventManager_->AxisTest(scaleEvent, node);
3398 eventManager_->DispatchAxisEventNG(scaleEvent);
3399 }
3400 if (event.action == AxisAction::BEGIN || event.action == AxisAction::CANCEL || event.action == AxisAction::END) {
3401 eventManager_->GetEventTreeRecord(EventTreeType::TOUCH).AddAxis(scaleEvent);
3402 }
3403
3404 auto mouseEvent = ConvertAxisToMouse(event);
3405 OnMouseEvent(mouseEvent, node);
3406 }
3407
HasDifferentDirectionGesture() const3408 bool PipelineContext::HasDifferentDirectionGesture() const
3409 {
3410 CHECK_NULL_RETURN(eventManager_, false);
3411 return eventManager_->HasDifferentDirectionGesture();
3412 }
3413
AddVisibleAreaChangeNode(const int32_t nodeId)3414 void PipelineContext::AddVisibleAreaChangeNode(const int32_t nodeId)
3415 {
3416 onVisibleAreaChangeNodeIds_.emplace(nodeId);
3417 }
3418
AddVisibleAreaChangeNode(const RefPtr<FrameNode> & node,const std::vector<double> & ratios,const VisibleRatioCallback & callback,bool isUserCallback,bool isCalculateInnerClip)3419 void PipelineContext::AddVisibleAreaChangeNode(const RefPtr<FrameNode>& node,
3420 const std::vector<double>& ratios, const VisibleRatioCallback& callback, bool isUserCallback,
3421 bool isCalculateInnerClip)
3422 {
3423 CHECK_NULL_VOID(node);
3424 VisibleCallbackInfo addInfo;
3425 addInfo.callback = callback;
3426 addInfo.isCurrentVisible = false;
3427 onVisibleAreaChangeNodeIds_.emplace(node->GetId());
3428 if (isUserCallback) {
3429 node->SetVisibleAreaUserCallback(ratios, addInfo);
3430 } else {
3431 node->SetVisibleAreaInnerCallback(ratios, addInfo, isCalculateInnerClip);
3432 }
3433 }
3434
RemoveVisibleAreaChangeNode(int32_t nodeId)3435 void PipelineContext::RemoveVisibleAreaChangeNode(int32_t nodeId)
3436 {
3437 onVisibleAreaChangeNodeIds_.erase(nodeId);
3438 }
3439
HandleVisibleAreaChangeEvent(uint64_t nanoTimestamp)3440 void PipelineContext::HandleVisibleAreaChangeEvent(uint64_t nanoTimestamp)
3441 {
3442 ACE_FUNCTION_TRACE();
3443 if (onVisibleAreaChangeNodeIds_.empty()) {
3444 return;
3445 }
3446 auto nodes = FrameNode::GetNodesById(onVisibleAreaChangeNodeIds_);
3447 for (auto&& frameNode : nodes) {
3448 frameNode->TriggerVisibleAreaChangeCallback(nanoTimestamp);
3449 }
3450 }
3451
AddOnAreaChangeNode(int32_t nodeId)3452 void PipelineContext::AddOnAreaChangeNode(int32_t nodeId)
3453 {
3454 onAreaChangeNodeIds_.emplace(nodeId);
3455 isOnAreaChangeNodesCacheVaild_ = false;
3456 }
3457
RemoveOnAreaChangeNode(int32_t nodeId)3458 void PipelineContext::RemoveOnAreaChangeNode(int32_t nodeId)
3459 {
3460 onAreaChangeNodeIds_.erase(nodeId);
3461 isOnAreaChangeNodesCacheVaild_ = false;
3462 }
3463
HasOnAreaChangeNode(int32_t nodeId)3464 bool PipelineContext::HasOnAreaChangeNode(int32_t nodeId)
3465 {
3466 return onAreaChangeNodeIds_.find(nodeId) != onAreaChangeNodeIds_.end();
3467 }
3468
HandleOnAreaChangeEvent(uint64_t nanoTimestamp)3469 void PipelineContext::HandleOnAreaChangeEvent(uint64_t nanoTimestamp)
3470 {
3471 ACE_FUNCTION_TRACE();
3472 if (onAreaChangeNodeIds_.empty()) {
3473 return;
3474 }
3475 auto nodes = FrameNode::GetNodesById(onAreaChangeNodeIds_);
3476 for (auto&& frameNode : nodes) {
3477 frameNode->TriggerOnAreaChangeCallback(nanoTimestamp);
3478 }
3479 UpdateFormLinkInfos();
3480 }
3481
UpdateFormLinkInfos()3482 void PipelineContext::UpdateFormLinkInfos()
3483 {
3484 if (formLinkInfoUpdateHandler_ && !formLinkInfoMap_.empty()) {
3485 std::vector<std::string> formLinkInfos;
3486 for (auto iter = formLinkInfoMap_.rbegin(); iter != formLinkInfoMap_.rend(); ++iter) {
3487 auto info = iter->second;
3488 formLinkInfos.push_back(info);
3489 }
3490 formLinkInfoUpdateHandler_(formLinkInfos);
3491 }
3492 }
3493
OnShow()3494 void PipelineContext::OnShow()
3495 {
3496 CHECK_RUN_ON(UI);
3497 onShow_ = true;
3498 window_->OnShow();
3499 PerfMonitor::GetPerfMonitor()->SetAppForeground(true);
3500 RequestFrame();
3501 FlushWindowStateChangedCallback(true);
3502 AccessibilityEvent event;
3503 event.windowChangeTypes = WindowUpdateType::WINDOW_UPDATE_ACTIVE;
3504 event.type = AccessibilityEventType::PAGE_CHANGE;
3505 SendEventToAccessibility(event);
3506 }
3507
OnHide()3508 void PipelineContext::OnHide()
3509 {
3510 CHECK_RUN_ON(UI);
3511 auto dragDropManager = GetDragDropManager();
3512 if (dragDropManager && dragDropManager->IsItemDragging()) {
3513 dragDropManager->CancelItemDrag();
3514 }
3515 onShow_ = false;
3516 window_->OnHide();
3517 PerfMonitor::GetPerfMonitor()->SetAppForeground(false);
3518 RequestFrame();
3519 OnVirtualKeyboardAreaChange(Rect());
3520 FlushWindowStateChangedCallback(false);
3521 auto rootNode = GetRootElement();
3522 CHECK_NULL_VOID(rootNode);
3523 rootNode->OnAccessibilityEvent(AccessibilityEventType::PAGE_CLOSE);
3524 }
3525
WindowFocus(bool isFocus)3526 void PipelineContext::WindowFocus(bool isFocus)
3527 {
3528 CHECK_RUN_ON(UI);
3529 onFocus_ = isFocus;
3530 if (!isFocus) {
3531 TAG_LOGI(AceLogTag::ACE_FOCUS, "Window id: %{public}d lost focus.", windowId_);
3532 RestoreDefault();
3533 RootLostFocus(BlurReason::WINDOW_BLUR);
3534 NotifyPopupDismiss();
3535 } else {
3536 TAG_LOGI(AceLogTag::ACE_FOCUS, "Window id: %{public}d get focus.", windowId_);
3537 isWindowHasFocused_ = true;
3538 InputMethodManager::GetInstance()->SetWindowFocus(true);
3539 }
3540 GetOrCreateFocusManager()->WindowFocus(isFocus);
3541 FlushWindowFocusChangedCallback(isFocus);
3542 }
3543
ContainerModalUnFocus()3544 void PipelineContext::ContainerModalUnFocus()
3545 {
3546 if (windowModal_ != WindowModal::CONTAINER_MODAL) {
3547 return;
3548 }
3549 CHECK_NULL_VOID(rootNode_);
3550 auto containerNode = AceType::DynamicCast<FrameNode>(rootNode_->GetChildren().front());
3551 CHECK_NULL_VOID(containerNode);
3552 auto containerPattern = containerNode->GetPattern<ContainerModalPattern>();
3553 CHECK_NULL_VOID(containerPattern);
3554 containerPattern->OnWindowForceUnfocused();
3555 }
3556
ShowContainerTitle(bool isShow,bool hasDeco,bool needUpdate)3557 void PipelineContext::ShowContainerTitle(bool isShow, bool hasDeco, bool needUpdate)
3558 {
3559 if (windowModal_ != WindowModal::CONTAINER_MODAL) {
3560 return;
3561 }
3562 CHECK_NULL_VOID(rootNode_);
3563 auto containerNode = AceType::DynamicCast<FrameNode>(rootNode_->GetChildren().front());
3564 CHECK_NULL_VOID(containerNode);
3565 auto containerPattern = containerNode->GetPattern<ContainerModalPattern>();
3566 CHECK_NULL_VOID(containerPattern);
3567 containerPattern->ShowTitle(isShow, hasDeco, needUpdate);
3568 isShowTitle_ = isShow && hasDeco;
3569 }
3570
UpdateTitleInTargetPos(bool isShow,int32_t height)3571 void PipelineContext::UpdateTitleInTargetPos(bool isShow, int32_t height)
3572 {
3573 if (windowModal_ != WindowModal::CONTAINER_MODAL) {
3574 return;
3575 }
3576 CHECK_NULL_VOID(rootNode_);
3577 auto containerNode = AceType::DynamicCast<FrameNode>(rootNode_->GetChildren().front());
3578 CHECK_NULL_VOID(containerNode);
3579 auto containerPattern = containerNode->GetPattern<ContainerModalPatternEnhance>();
3580 CHECK_NULL_VOID(containerPattern);
3581 containerPattern->UpdateTitleInTargetPos(isShow, height);
3582 }
3583
SetContainerWindow(bool isShow)3584 void PipelineContext::SetContainerWindow(bool isShow)
3585 {
3586 #ifdef ENABLE_ROSEN_BACKEND
3587 if (!IsJsCard()) {
3588 auto window = GetWindow();
3589 if (window) {
3590 auto rsUIDirector = window->GetRSUIDirector();
3591 if (rsUIDirector) {
3592 // set container window show state to render service
3593 rsUIDirector->SetContainerWindow(isShow, density_);
3594 }
3595 }
3596 }
3597 #endif
3598 }
3599
SetAppBgColor(const Color & color)3600 void PipelineContext::SetAppBgColor(const Color& color)
3601 {
3602 appBgColor_ = color;
3603 #ifdef ENABLE_ROSEN_BACKEND
3604 if (!IsJsCard()) {
3605 auto window = GetWindow();
3606 if (window) {
3607 auto rsUIDirector = window->GetRSUIDirector();
3608 if (rsUIDirector) {
3609 rsUIDirector->SetAbilityBGAlpha(appBgColor_.GetAlpha());
3610 }
3611 }
3612 }
3613 #endif
3614 CHECK_NULL_VOID(stageManager_);
3615 auto stage = stageManager_->GetStageNode();
3616 CHECK_NULL_VOID(stage);
3617 auto renderContext = stage->GetRenderContext();
3618 CHECK_NULL_VOID(renderContext);
3619 renderContext->UpdateBackgroundColor(color);
3620 }
3621
SetAppTitle(const std::string & title)3622 void PipelineContext::SetAppTitle(const std::string& title)
3623 {
3624 if (windowModal_ != WindowModal::CONTAINER_MODAL) {
3625 return;
3626 }
3627 CHECK_NULL_VOID(rootNode_);
3628 auto containerNode = AceType::DynamicCast<FrameNode>(rootNode_->GetChildren().front());
3629 CHECK_NULL_VOID(containerNode);
3630 auto containerPattern = containerNode->GetPattern<ContainerModalPattern>();
3631 CHECK_NULL_VOID(containerPattern);
3632 containerPattern->SetAppTitle(title);
3633 }
3634
SetAppIcon(const RefPtr<PixelMap> & icon)3635 void PipelineContext::SetAppIcon(const RefPtr<PixelMap>& icon)
3636 {
3637 if (windowModal_ != WindowModal::CONTAINER_MODAL) {
3638 return;
3639 }
3640 CHECK_NULL_VOID(rootNode_);
3641 auto containerNode = AceType::DynamicCast<FrameNode>(rootNode_->GetChildren().front());
3642 CHECK_NULL_VOID(containerNode);
3643 auto containerPattern = containerNode->GetPattern<ContainerModalPattern>();
3644 CHECK_NULL_VOID(containerPattern);
3645 containerPattern->SetAppIcon(icon);
3646 }
3647
FlushReload(const ConfigurationChange & configurationChange,bool fullUpdate)3648 void PipelineContext::FlushReload(const ConfigurationChange& configurationChange, bool fullUpdate)
3649 {
3650 AnimationOption option;
3651 const int32_t duration = 400;
3652 option.SetDuration(duration);
3653 option.SetCurve(Curves::FRICTION);
3654 RecycleManager::Notify(configurationChange);
3655 AnimationUtils::Animate(option, [weak = WeakClaim(this), configurationChange,
3656 weakOverlayManager = AceType::WeakClaim(AceType::RawPtr(overlayManager_)), fullUpdate]() {
3657 auto pipeline = weak.Upgrade();
3658 CHECK_NULL_VOID(pipeline);
3659 if (configurationChange.IsNeedUpdate()) {
3660 auto rootNode = pipeline->GetRootElement();
3661 rootNode->UpdateConfigurationUpdate(configurationChange);
3662 auto overlay = weakOverlayManager.Upgrade();
3663 if (overlay) {
3664 overlay->ReloadBuilderNodeConfig();
3665 }
3666 }
3667 if (fullUpdate) {
3668 CHECK_NULL_VOID(pipeline->stageManager_);
3669 pipeline->SetIsReloading(true);
3670 pipeline->stageManager_->ReloadStage();
3671 pipeline->SetIsReloading(false);
3672 pipeline->FlushUITasks();
3673 }
3674 });
3675 auto stage = stageManager_->GetStageNode();
3676 CHECK_NULL_VOID(stage);
3677 auto renderContext = stage->GetRenderContext();
3678 CHECK_NULL_VOID(renderContext);
3679 renderContext->UpdateWindowBlur();
3680 }
3681
Destroy()3682 void PipelineContext::Destroy()
3683 {
3684 CHECK_RUN_ON(UI);
3685 SetDestroyed();
3686 rootNode_->DetachFromMainTree();
3687 std::unordered_set<UINode*> nodeSet;
3688 std::swap(nodeSet, attachedNodeSet_);
3689 for (auto& node : nodeSet) {
3690 node->DetachFromMainTree();
3691 }
3692 rootNode_->FireCustomDisappear();
3693 taskScheduler_->CleanUp();
3694 scheduleTasks_.clear();
3695 dirtyNodes_.clear();
3696 rootNode_.Reset();
3697 accessibilityManagerNG_.Reset();
3698 stageManager_.Reset();
3699 if (overlayManager_) {
3700 overlayManager_->ClearUIExtensionNode();
3701 }
3702 overlayManager_.Reset();
3703 sharedTransitionManager_.Reset();
3704 dragDropManager_.Reset();
3705 TAG_LOGI(AceLogTag::ACE_DRAG, "PipelineContext::Destroy Reset dragDropManager_");
3706 focusManager_.Reset();
3707 selectOverlayManager_.Reset();
3708 fullScreenManager_.Reset();
3709 touchEvents_.clear();
3710 buildFinishCallbacks_.clear();
3711 onWindowStateChangedCallbacks_.clear();
3712 onWindowFocusChangedCallbacks_.clear();
3713 nodesToNotifyMemoryLevel_.clear();
3714 dirtyFocusNode_.Reset();
3715 dirtyFocusScope_.Reset();
3716 needRenderNode_.clear();
3717 dirtyRequestFocusNode_.Reset();
3718 if (textFieldManager_ && textFieldManager_->GetImeShow()) {
3719 InputMethodManager::GetInstance()->CloseKeyboardInPipelineDestroy();
3720 }
3721 #ifdef WINDOW_SCENE_SUPPORTED
3722 uiExtensionManager_.Reset();
3723 #endif
3724 PipelineBase::Destroy();
3725 }
3726
AddBuildFinishCallBack(std::function<void ()> && callback)3727 void PipelineContext::AddBuildFinishCallBack(std::function<void()>&& callback)
3728 {
3729 buildFinishCallbacks_.emplace_back(std::move(callback));
3730 }
3731
AddWindowStateChangedCallback(int32_t nodeId)3732 void PipelineContext::AddWindowStateChangedCallback(int32_t nodeId)
3733 {
3734 if (!CheckThreadSafe()) {
3735 LOGW("AddWindowStateChangedCallback doesn't run on UI thread!");
3736 }
3737 onWindowStateChangedCallbacks_.emplace(nodeId);
3738 }
3739
RemoveWindowStateChangedCallback(int32_t nodeId)3740 void PipelineContext::RemoveWindowStateChangedCallback(int32_t nodeId)
3741 {
3742 if (!CheckThreadSafe()) {
3743 LOGW("RemoveWindowStateChangedCallback doesn't run on UI thread!");
3744 }
3745 onWindowStateChangedCallbacks_.erase(nodeId);
3746 }
3747
FlushWindowStateChangedCallback(bool isShow)3748 void PipelineContext::FlushWindowStateChangedCallback(bool isShow)
3749 {
3750 if (!CheckThreadSafe()) {
3751 LOGW("FlushWindowStateChangedCallback doesn't run on UI thread!");
3752 }
3753 auto iter = onWindowStateChangedCallbacks_.begin();
3754 while (iter != onWindowStateChangedCallbacks_.end()) {
3755 auto node = ElementRegister::GetInstance()->GetUINodeById(*iter);
3756 if (!node) {
3757 iter = onWindowStateChangedCallbacks_.erase(iter);
3758 } else {
3759 if (isShow) {
3760 node->OnWindowShow();
3761 } else {
3762 node->OnWindowHide();
3763 }
3764 ++iter;
3765 }
3766 }
3767 HandleVisibleAreaChangeEvent(GetTimeFromExternalTimer());
3768 HandleSubwindow(isShow);
3769 }
3770
AddWindowFocusChangedCallback(int32_t nodeId)3771 void PipelineContext::AddWindowFocusChangedCallback(int32_t nodeId)
3772 {
3773 onWindowFocusChangedCallbacks_.emplace(nodeId);
3774 }
3775
RemoveWindowFocusChangedCallback(int32_t nodeId)3776 void PipelineContext::RemoveWindowFocusChangedCallback(int32_t nodeId)
3777 {
3778 onWindowFocusChangedCallbacks_.erase(nodeId);
3779 }
3780
FlushWindowFocusChangedCallback(bool isFocus)3781 void PipelineContext::FlushWindowFocusChangedCallback(bool isFocus)
3782 {
3783 auto iter = onWindowFocusChangedCallbacks_.begin();
3784 while (iter != onWindowFocusChangedCallbacks_.end()) {
3785 auto node = ElementRegister::GetInstance()->GetUINodeById(*iter);
3786 if (!node) {
3787 iter = onWindowFocusChangedCallbacks_.erase(iter);
3788 } else {
3789 if (isFocus) {
3790 node->OnWindowFocused();
3791 } else {
3792 node->OnWindowUnfocused();
3793 }
3794 ++iter;
3795 }
3796 }
3797 }
3798
AddWindowSizeChangeCallback(int32_t nodeId)3799 void PipelineContext::AddWindowSizeChangeCallback(int32_t nodeId)
3800 {
3801 onWindowSizeChangeCallbacks_.emplace_back(nodeId);
3802 }
3803
RemoveWindowSizeChangeCallback(int32_t nodeId)3804 void PipelineContext::RemoveWindowSizeChangeCallback(int32_t nodeId)
3805 {
3806 onWindowSizeChangeCallbacks_.remove(nodeId);
3807 }
3808
AddNavigationNode(int32_t pageId,WeakPtr<UINode> navigationNode)3809 void PipelineContext::AddNavigationNode(int32_t pageId, WeakPtr<UINode> navigationNode)
3810 {
3811 CHECK_RUN_ON(UI);
3812 pageToNavigationNodes_[pageId].push_back(navigationNode);
3813 }
3814
RemoveNavigationNode(int32_t pageId,int32_t nodeId)3815 void PipelineContext::RemoveNavigationNode(int32_t pageId, int32_t nodeId)
3816 {
3817 CHECK_RUN_ON(UI);
3818 auto it = pageToNavigationNodes_.find(pageId);
3819 if (it != pageToNavigationNodes_.end() && !it->second.empty()) {
3820 for (auto iter = it->second.begin(); iter != it->second.end();) {
3821 auto navigationNode = AceType::DynamicCast<NavigationGroupNode>((*iter).Upgrade());
3822 if (navigationNode && navigationNode->GetId() == nodeId) {
3823 iter = it->second.erase(iter);
3824 } else {
3825 iter++;
3826 }
3827 }
3828 }
3829 }
3830
FirePageChanged(int32_t pageId,bool isOnShow)3831 void PipelineContext::FirePageChanged(int32_t pageId, bool isOnShow)
3832 {
3833 CHECK_RUN_ON(UI);
3834 for (auto navigationNode : pageToNavigationNodes_[pageId]) {
3835 NavigationPattern::FireNavigationChange(navigationNode.Upgrade(), isOnShow, true);
3836 }
3837 }
3838
FlushWindowSizeChangeCallback(int32_t width,int32_t height,WindowSizeChangeReason type)3839 void PipelineContext::FlushWindowSizeChangeCallback(int32_t width, int32_t height, WindowSizeChangeReason type)
3840 {
3841 auto iter = onWindowSizeChangeCallbacks_.begin();
3842 while (iter != onWindowSizeChangeCallbacks_.end()) {
3843 auto node = ElementRegister::GetInstance()->GetUINodeById(*iter);
3844 if (!node) {
3845 iter = onWindowSizeChangeCallbacks_.erase(iter);
3846 } else {
3847 node->OnWindowSizeChanged(width, height, type);
3848 ++iter;
3849 }
3850 }
3851 }
3852
RequireSummary()3853 void PipelineContext::RequireSummary()
3854 {
3855 auto manager = GetDragDropManager();
3856 if (!manager) {
3857 TAG_LOGW(AceLogTag::ACE_DRAG, "require summary, dragDropManager is null");
3858 return;
3859 }
3860 manager->RequireSummary();
3861 }
3862
OnDragEvent(const PointerEvent & pointerEvent,DragEventAction action,const RefPtr<NG::FrameNode> & node)3863 void PipelineContext::OnDragEvent(const PointerEvent& pointerEvent, DragEventAction action,
3864 const RefPtr<NG::FrameNode>& node)
3865 {
3866 auto manager = GetDragDropManager();
3867 CHECK_NULL_VOID(manager);
3868 std::string extraInfo;
3869 auto container = Container::Current();
3870 if (container && container->IsScenceBoardWindow()) {
3871 if (!manager->IsDragged() && manager->IsWindowConsumed()) {
3872 manager->SetIsWindowConsumed(false);
3873 return;
3874 }
3875 }
3876 if (action == DragEventAction::DRAG_EVENT_START_FOR_CONTROLLER) {
3877 manager->RequireSummary();
3878 manager->OnDragStart(pointerEvent.GetPoint());
3879 return;
3880 }
3881 if (action == DragEventAction::DRAG_EVENT_OUT) {
3882 manager->OnDragMoveOut(pointerEvent);
3883 manager->ClearSummary();
3884 manager->ClearExtraInfo();
3885 manager->SetDragCursorStyleCore(DragCursorStyleCore::DEFAULT);
3886 return;
3887 }
3888
3889 if (action == DragEventAction::DRAG_EVENT_START) {
3890 manager->ResetPreTargetFrameNode(GetInstanceId());
3891 manager->RequireSummaryIfNecessary(pointerEvent);
3892 manager->SetDragCursorStyleCore(DragCursorStyleCore::DEFAULT);
3893 TAG_LOGI(AceLogTag::ACE_DRAG, "start drag, current windowId is %{public}d", container->GetWindowId());
3894 }
3895 extraInfo = manager->GetExtraInfo();
3896 if (action == DragEventAction::DRAG_EVENT_END) {
3897 manager->OnDragEnd(pointerEvent, extraInfo, node);
3898 return;
3899 }
3900 if (action == DragEventAction::DRAG_EVENT_MOVE) {
3901 manager->DoDragMoveAnimate(pointerEvent);
3902 }
3903 manager->OnDragMove(pointerEvent, extraInfo, node);
3904 }
3905
AddNodesToNotifyMemoryLevel(int32_t nodeId)3906 void PipelineContext::AddNodesToNotifyMemoryLevel(int32_t nodeId)
3907 {
3908 nodesToNotifyMemoryLevel_.emplace_back(nodeId);
3909 }
3910
RemoveNodesToNotifyMemoryLevel(int32_t nodeId)3911 void PipelineContext::RemoveNodesToNotifyMemoryLevel(int32_t nodeId)
3912 {
3913 nodesToNotifyMemoryLevel_.remove(nodeId);
3914 }
3915
NotifyMemoryLevel(int32_t level)3916 void PipelineContext::NotifyMemoryLevel(int32_t level)
3917 {
3918 auto iter = nodesToNotifyMemoryLevel_.begin();
3919 while (iter != nodesToNotifyMemoryLevel_.end()) {
3920 auto node = ElementRegister::GetInstance()->GetUINodeById(*iter);
3921 if (!node) {
3922 iter = nodesToNotifyMemoryLevel_.erase(iter);
3923 } else {
3924 node->OnNotifyMemoryLevel(level);
3925 ++iter;
3926 }
3927 }
3928 }
AddPredictTask(PredictTask && task)3929 void PipelineContext::AddPredictTask(PredictTask&& task)
3930 {
3931 taskScheduler_->AddPredictTask(std::move(task));
3932 RequestFrame();
3933 }
3934
AddFrameCallback(FrameCallbackFunc && frameCallbackFunc,FrameCallbackFunc && idleCallbackFunc,int64_t delayMillis)3935 void PipelineContext::AddFrameCallback(FrameCallbackFunc&& frameCallbackFunc, FrameCallbackFunc&& idleCallbackFunc,
3936 int64_t delayMillis)
3937 {
3938 if (delayMillis <= 0) {
3939 if (frameCallbackFunc != nullptr) {
3940 frameCallbackFuncs_.emplace_back(std::move(frameCallbackFunc));
3941 }
3942 if (idleCallbackFunc != nullptr) {
3943 idleCallbackFuncs_.emplace_back(std::move(idleCallbackFunc));
3944 }
3945 RequestFrame();
3946 return;
3947 }
3948 auto taskScheduler = GetTaskExecutor();
3949 CHECK_NULL_VOID(taskScheduler);
3950 if (frameCallbackFunc != nullptr) {
3951 taskScheduler->PostDelayedTask(
3952 [weak = WeakClaim(this), callbackFunc = std::move(frameCallbackFunc)]() -> void {
3953 auto pipeline = weak.Upgrade();
3954 CHECK_NULL_VOID(pipeline);
3955 auto callback = const_cast<FrameCallbackFunc&>(callbackFunc);
3956 pipeline->frameCallbackFuncs_.emplace_back(std::move(callback));
3957 pipeline->RequestFrame();
3958 },
3959 TaskExecutor::TaskType::UI, delayMillis, "ArkUIPostFrameCallbackFuncDelayed");
3960 }
3961 if (idleCallbackFunc != nullptr) {
3962 taskScheduler->PostDelayedTask(
3963 [weak = WeakClaim(this), callbackFunc = std::move(idleCallbackFunc)]() -> void {
3964 auto pipeline = weak.Upgrade();
3965 CHECK_NULL_VOID(pipeline);
3966 auto callback = const_cast<FrameCallbackFunc&>(callbackFunc);
3967 pipeline->idleCallbackFuncs_.emplace_back(std::move(callback));
3968 pipeline->RequestFrame();
3969 },
3970 TaskExecutor::TaskType::UI, delayMillis, "ArkUIPostIdleCallbackFuncDelayed");
3971 }
3972 }
3973
TriggerIdleCallback(int64_t deadline)3974 void PipelineContext::TriggerIdleCallback(int64_t deadline)
3975 {
3976 if (idleCallbackFuncs_.empty()) {
3977 return;
3978 }
3979 int64_t currentTime = GetSysTimestamp();
3980 if (deadline - currentTime < MIN_IDLE_TIME) {
3981 RequestFrame();
3982 return;
3983 }
3984 decltype(idleCallbackFuncs_) tasks(std::move(idleCallbackFuncs_));
3985 for (const auto& idleCallbackFunc : tasks) {
3986 idleCallbackFunc(deadline - currentTime);
3987 currentTime = GetSysTimestamp();
3988 }
3989 }
3990
OnIdle(int64_t deadline)3991 void PipelineContext::OnIdle(int64_t deadline)
3992 {
3993 int64_t currentTime = GetSysTimestamp();
3994 if (deadline == 0) {
3995 int64_t lastTaskEndTimestamp = window_->GetLastVsyncEndTimestamp();
3996 if (eventManager_) {
3997 lastTaskEndTimestamp = std::max(lastTaskEndTimestamp, eventManager_->GetLastTouchEventEndTimestamp());
3998 }
3999 if (lastTaskEndTimestamp > 0 && currentTime > lastTaskEndTimestamp
4000 && currentTime - lastTaskEndTimestamp > VSYNC_PERIOD_COUNT * window_->GetVSyncPeriod()) {
4001 auto frontend = weakFrontend_.Upgrade();
4002 if (frontend) {
4003 frontend->NotifyUIIdle();
4004 }
4005 }
4006 }
4007 if (deadline == 0 || isWindowAnimation_) {
4008 canUseLongPredictTask_ = false;
4009 return;
4010 }
4011 if (canUseLongPredictTask_) {
4012 // check new incoming event after vsync.
4013 if (!touchEvents_.empty()) {
4014 canUseLongPredictTask_ = false;
4015 }
4016 }
4017 CHECK_RUN_ON(UI);
4018 ACE_SCOPED_TRACE("OnIdle, targettime:%" PRId64 "", deadline);
4019 taskScheduler_->FlushPredictTask(deadline - TIME_THRESHOLD, canUseLongPredictTask_);
4020 canUseLongPredictTask_ = false;
4021 if (currentTime < deadline) {
4022 ElementRegister::GetInstance()->CallJSCleanUpIdleTaskFunc();
4023 }
4024 TriggerIdleCallback(deadline);
4025 }
4026
Finish(bool) const4027 void PipelineContext::Finish(bool /* autoFinish */) const
4028 {
4029 CHECK_RUN_ON(UI);
4030 if (finishEventHandler_) {
4031 finishEventHandler_();
4032 }
4033 }
4034
AddAfterLayoutTask(std::function<void ()> && task,bool isFlushInImplicitAnimationTask)4035 void PipelineContext::AddAfterLayoutTask(std::function<void()>&& task, bool isFlushInImplicitAnimationTask)
4036 {
4037 taskScheduler_->AddAfterLayoutTask(std::move(task), isFlushInImplicitAnimationTask);
4038 }
4039
AddPersistAfterLayoutTask(std::function<void ()> && task)4040 void PipelineContext::AddPersistAfterLayoutTask(std::function<void()>&& task)
4041 {
4042 taskScheduler_->AddPersistAfterLayoutTask(std::move(task));
4043 }
4044
AddAfterRenderTask(std::function<void ()> && task)4045 void PipelineContext::AddAfterRenderTask(std::function<void()>&& task)
4046 {
4047 taskScheduler_->AddAfterRenderTask(std::move(task));
4048 }
4049
AddSafeAreaPaddingProcessTask(FrameNode * node)4050 void PipelineContext::AddSafeAreaPaddingProcessTask(FrameNode* node)
4051 {
4052 taskScheduler_->AddSafeAreaPaddingProcessTask(node);
4053 }
4054
RemoveSafeAreaPaddingProcessTask(FrameNode * node)4055 void PipelineContext::RemoveSafeAreaPaddingProcessTask(FrameNode* node)
4056 {
4057 taskScheduler_->RemoveSafeAreaPaddingProcessTask(node);
4058 }
4059
FlushSafeAreaPaddingProcess()4060 void PipelineContext::FlushSafeAreaPaddingProcess()
4061 {
4062 taskScheduler_->FlushSafeAreaPaddingProcess();
4063 }
4064
RestoreNodeInfo(std::unique_ptr<JsonValue> nodeInfo)4065 void PipelineContext::RestoreNodeInfo(std::unique_ptr<JsonValue> nodeInfo)
4066 {
4067 auto child = nodeInfo->GetChild();
4068 while (child->IsValid()) {
4069 auto key = child->GetKey();
4070 auto value = child->GetString();
4071 restoreNodeInfo_.try_emplace(StringUtils::StringToInt(key), value);
4072 child = child->GetNext();
4073 }
4074 }
4075
GetStoredNodeInfo()4076 std::unique_ptr<JsonValue> PipelineContext::GetStoredNodeInfo()
4077 {
4078 auto jsonNodeInfo = JsonUtil::Create(true);
4079 auto iter = storeNode_.begin();
4080 while (iter != storeNode_.end()) {
4081 auto node = (iter->second).Upgrade();
4082 if (node) {
4083 std::string info = node->ProvideRestoreInfo();
4084 if (!info.empty()) {
4085 jsonNodeInfo->Put(std::to_string(iter->first).c_str(), info.c_str());
4086 }
4087 }
4088 ++iter;
4089 }
4090 return jsonNodeInfo;
4091 }
4092
StoreNode(int32_t restoreId,const WeakPtr<FrameNode> & node)4093 void PipelineContext::StoreNode(int32_t restoreId, const WeakPtr<FrameNode>& node)
4094 {
4095 auto ret = storeNode_.try_emplace(restoreId, node);
4096 if (!ret.second) {
4097 storeNode_[restoreId] = node;
4098 }
4099 }
4100
GetRestoreInfo(int32_t restoreId,std::string & restoreInfo)4101 bool PipelineContext::GetRestoreInfo(int32_t restoreId, std::string& restoreInfo)
4102 {
4103 auto iter = restoreNodeInfo_.find(restoreId);
4104 if (iter != restoreNodeInfo_.end()) {
4105 restoreInfo = iter->second;
4106 restoreNodeInfo_.erase(iter);
4107 return true;
4108 }
4109 return false;
4110 }
4111
SetContainerButtonHide(bool hideSplit,bool hideMaximize,bool hideMinimize,bool hideClose)4112 void PipelineContext::SetContainerButtonHide(bool hideSplit, bool hideMaximize, bool hideMinimize, bool hideClose)
4113 {
4114 if (windowModal_ != WindowModal::CONTAINER_MODAL) {
4115 LOGW("Set app icon failed, Window modal is not container.");
4116 return;
4117 }
4118 CHECK_NULL_VOID(rootNode_);
4119 auto containerNode = AceType::DynamicCast<FrameNode>(rootNode_->GetChildren().front());
4120 CHECK_NULL_VOID(containerNode);
4121 auto containerPattern = containerNode->GetPattern<ContainerModalPattern>();
4122 CHECK_NULL_VOID(containerPattern);
4123 containerPattern->SetContainerButtonHide(hideSplit, hideMaximize, hideMinimize, hideClose);
4124 }
4125
EnableContainerModalGesture(bool isEnable)4126 void PipelineContext::EnableContainerModalGesture(bool isEnable)
4127 {
4128 CHECK_NULL_VOID(rootNode_);
4129 auto containerNode = AceType::DynamicCast<FrameNode>(rootNode_->GetChildren().front());
4130 if (!containerNode) {
4131 LOGW("container node is null when set event on gesture row");
4132 return;
4133 }
4134 auto containerPattern = containerNode->GetPattern<ContainerModalPattern>();
4135 CHECK_NULL_VOID(containerPattern);
4136 containerPattern->EnableContainerModalGesture(isEnable);
4137 }
4138
GetContainerFloatingTitleVisible()4139 bool PipelineContext::GetContainerFloatingTitleVisible()
4140 {
4141 CHECK_NULL_RETURN(rootNode_, false);
4142 auto containerNode = AceType::DynamicCast<FrameNode>(rootNode_->GetChildren().front());
4143 CHECK_NULL_RETURN(containerNode, false);
4144 auto containerPattern = containerNode->GetPattern<ContainerModalPattern>();
4145 CHECK_NULL_RETURN(containerPattern, false);
4146 return containerPattern->GetFloatingTitleVisible();
4147 }
4148
GetContainerCustomTitleVisible()4149 bool PipelineContext::GetContainerCustomTitleVisible()
4150 {
4151 CHECK_NULL_RETURN(rootNode_, false);
4152 auto containerNode = AceType::DynamicCast<FrameNode>(rootNode_->GetChildren().front());
4153 CHECK_NULL_RETURN(containerNode, false);
4154 auto containerPattern = containerNode->GetPattern<ContainerModalPattern>();
4155 CHECK_NULL_RETURN(containerPattern, false);
4156 return containerPattern->GetCustomTitleVisible();
4157 }
4158
GetContainerControlButtonVisible()4159 bool PipelineContext::GetContainerControlButtonVisible()
4160 {
4161 CHECK_NULL_RETURN(rootNode_, false);
4162 auto containerNode = AceType::DynamicCast<FrameNode>(rootNode_->GetChildren().front());
4163 CHECK_NULL_RETURN(containerNode, false);
4164 auto containerPattern = containerNode->GetPattern<ContainerModalPattern>();
4165 CHECK_NULL_RETURN(containerPattern, false);
4166 return containerPattern->GetControlButtonVisible();
4167 }
4168
AddFontNodeNG(const WeakPtr<UINode> & node)4169 void PipelineContext::AddFontNodeNG(const WeakPtr<UINode>& node)
4170 {
4171 if (fontManager_) {
4172 fontManager_->AddFontNodeNG(node);
4173 }
4174 }
4175
RemoveFontNodeNG(const WeakPtr<UINode> & node)4176 void PipelineContext::RemoveFontNodeNG(const WeakPtr<UINode>& node)
4177 {
4178 if (fontManager_) {
4179 fontManager_->RemoveFontNodeNG(node);
4180 }
4181 }
4182
SetWindowSceneConsumed(bool isConsumed)4183 void PipelineContext::SetWindowSceneConsumed(bool isConsumed)
4184 {
4185 isWindowSceneConsumed_ = isConsumed;
4186 }
4187
IsWindowSceneConsumed()4188 bool PipelineContext::IsWindowSceneConsumed()
4189 {
4190 return isWindowSceneConsumed_;
4191 }
4192
SetCloseButtonStatus(bool isEnabled)4193 void PipelineContext::SetCloseButtonStatus(bool isEnabled)
4194 {
4195 if (windowModal_ != WindowModal::CONTAINER_MODAL) {
4196 return;
4197 }
4198 CHECK_NULL_VOID(rootNode_);
4199 auto containerNode = AceType::DynamicCast<FrameNode>(rootNode_->GetChildren().front());
4200 CHECK_NULL_VOID(containerNode);
4201 auto containerPattern = containerNode->GetPattern<ContainerModalPattern>();
4202 CHECK_NULL_VOID(containerPattern);
4203 containerPattern->SetCloseButtonStatus(isEnabled);
4204 }
4205
AnimateOnSafeAreaUpdate()4206 void PipelineContext::AnimateOnSafeAreaUpdate()
4207 {
4208 // complete other layout tasks before animation
4209 FlushUITasks();
4210 AnimationOption option;
4211 option.SetCurve(safeAreaManager_->GetSafeAreaCurve());
4212 AnimationUtils::Animate(option, [weak = WeakClaim(this)]() {
4213 auto self = weak.Upgrade();
4214 CHECK_NULL_VOID(self);
4215 self->SyncSafeArea(SafeAreaSyncType::SYNC_TYPE_AVOID_AREA);
4216 self->FlushUITasks();
4217 });
4218 }
4219
HandleSubwindow(bool isShow)4220 void PipelineContext::HandleSubwindow(bool isShow)
4221 {
4222 // When the main window is applied to the background,
4223 // there are sub windows that do not immediately hide, such as Toast floating window
4224 if (!isShow) {
4225 overlayManager_->ClearToastInSubwindow();
4226 }
4227 }
4228
AddIsFocusActiveUpdateEvent(const RefPtr<FrameNode> & node,const std::function<void (bool)> & eventCallback)4229 void PipelineContext::AddIsFocusActiveUpdateEvent(
4230 const RefPtr<FrameNode>& node, const std::function<void(bool)>& eventCallback)
4231 {
4232 CHECK_NULL_VOID(node);
4233 isFocusActiveUpdateEvents_.insert_or_assign(node->GetId(), eventCallback);
4234 }
4235
RemoveIsFocusActiveUpdateEvent(const RefPtr<FrameNode> & node)4236 void PipelineContext::RemoveIsFocusActiveUpdateEvent(const RefPtr<FrameNode>& node)
4237 {
4238 CHECK_NULL_VOID(node);
4239 auto iter = isFocusActiveUpdateEvents_.find(node->GetId());
4240 if (iter != isFocusActiveUpdateEvents_.end()) {
4241 isFocusActiveUpdateEvents_.erase(iter);
4242 }
4243 }
4244
GetNavigationController(const std::string & id)4245 std::shared_ptr<NavigationController> PipelineContext::GetNavigationController(const std::string& id)
4246 {
4247 std::lock_guard lock(navigationMutex_);
4248 auto iter = navigationNodes_.find(id);
4249 if (iter == navigationNodes_.end()) {
4250 return nullptr;
4251 }
4252
4253 auto navigationGroupNode = iter->second.Upgrade();
4254 CHECK_NULL_RETURN(navigationGroupNode, nullptr);
4255
4256 auto navigationPattern = navigationGroupNode->GetPattern<NavigationPattern>();
4257 CHECK_NULL_RETURN(navigationPattern, nullptr);
4258 return navigationPattern->GetNavigationController();
4259 }
4260
AddOrReplaceNavigationNode(const std::string & id,const WeakPtr<FrameNode> & node)4261 void PipelineContext::AddOrReplaceNavigationNode(const std::string& id, const WeakPtr<FrameNode>& node)
4262 {
4263 std::lock_guard lock(navigationMutex_);
4264 auto frameNode = node.Upgrade();
4265 CHECK_NULL_VOID(frameNode);
4266 auto navigationGroupNode = AceType::DynamicCast<NavigationGroupNode>(frameNode);
4267 CHECK_NULL_VOID(navigationGroupNode);
4268 auto oldId = navigationGroupNode->GetCurId();
4269 if (!oldId.empty() && navigationNodes_.find(oldId) != navigationNodes_.end()) {
4270 navigationNodes_.erase(oldId);
4271 }
4272
4273 if (!id.empty()) {
4274 navigationNodes_[id] = node;
4275 }
4276 }
4277
DeleteNavigationNode(const std::string & id)4278 void PipelineContext::DeleteNavigationNode(const std::string& id)
4279 {
4280 std::lock_guard lock(navigationMutex_);
4281 if (!id.empty() && navigationNodes_.find(id) != navigationNodes_.end()) {
4282 navigationNodes_.erase(id);
4283 }
4284 }
4285
SetCursor(int32_t cursorValue)4286 void PipelineContext::SetCursor(int32_t cursorValue)
4287 {
4288 if (cursorValue >= 0 && cursorValue <= static_cast<int32_t>(MouseFormat::RUNNING)) {
4289 auto window = GetWindow();
4290 CHECK_NULL_VOID(window);
4291 auto mouseStyle = MouseStyle::CreateMouseStyle();
4292 CHECK_NULL_VOID(mouseStyle);
4293 auto cursor = static_cast<MouseFormat>(cursorValue);
4294 window->SetCursor(cursor);
4295 window->SetUserSetCursor(true);
4296 mouseStyle->ChangePointerStyle(GetFocusWindowId(), cursor);
4297 }
4298 }
4299
RestoreDefault(int32_t windowId)4300 void PipelineContext::RestoreDefault(int32_t windowId)
4301 {
4302 auto window = GetWindow();
4303 CHECK_NULL_VOID(window);
4304 auto mouseStyle = MouseStyle::CreateMouseStyle();
4305 CHECK_NULL_VOID(mouseStyle);
4306 window->SetCursor(MouseFormat::DEFAULT);
4307 window->SetUserSetCursor(false);
4308 mouseStyle->ChangePointerStyle(windowId > 0 ? windowId : GetFocusWindowId(), MouseFormat::DEFAULT);
4309 }
4310
GetCurrentExtraInfo()4311 std::string PipelineContext::GetCurrentExtraInfo()
4312 {
4313 auto node = activeNode_.Upgrade();
4314 return node ? node->GetCurrentCustomNodeInfo() : std::string();
4315 }
4316
OpenFrontendAnimation(const AnimationOption & option,const RefPtr<Curve> & curve,const std::function<void ()> & finishCallback)4317 void PipelineContext::OpenFrontendAnimation(
4318 const AnimationOption& option, const RefPtr<Curve>& curve, const std::function<void()>& finishCallback)
4319 {
4320 // push false to show we already open a animation closure.
4321 pendingFrontendAnimation_.push(false);
4322
4323 // flush ui tasks before open animation closure.
4324 if (!isReloading_ && !IsLayouting()) {
4325 FlushUITasks();
4326 }
4327 auto wrapFinishCallback = GetWrappedAnimationCallback(finishCallback);
4328 if (IsFormRender()) {
4329 SetIsFormAnimation(true);
4330 if (!IsFormAnimationFinishCallback()) {
4331 SetFormAnimationStartTime(GetMicroTickCount());
4332 }
4333 }
4334 AnimationUtils::OpenImplicitAnimation(option, curve, wrapFinishCallback);
4335 }
4336
CloseFrontendAnimation()4337 void PipelineContext::CloseFrontendAnimation()
4338 {
4339 if (pendingFrontendAnimation_.empty()) {
4340 return;
4341 }
4342
4343 if (pendingFrontendAnimation_.top()) {
4344 if (!isReloading_ && !IsLayouting()) {
4345 FlushUITasks();
4346 } else if (IsLayouting()) {
4347 TAG_LOGW(AceLogTag::ACE_ANIMATION,
4348 "IsLayouting, CloseFrontendAnimation has tasks not flushed, maybe some layout animation not generated");
4349 }
4350 }
4351 if (!pendingFrontendAnimation_.empty()) {
4352 pendingFrontendAnimation_.pop();
4353 }
4354 AnimationUtils::CloseImplicitAnimation();
4355 }
4356
SetContainerModalTitleVisible(bool customTitleSettedShow,bool floatingTitleSettedShow)4357 void PipelineContext::SetContainerModalTitleVisible(bool customTitleSettedShow, bool floatingTitleSettedShow)
4358 {
4359 if (windowModal_ != WindowModal::CONTAINER_MODAL) {
4360 return;
4361 }
4362 CHECK_NULL_VOID(rootNode_);
4363 auto containerNode = AceType::DynamicCast<FrameNode>(rootNode_->GetFirstChild());
4364 CHECK_NULL_VOID(containerNode);
4365 auto containerPattern = containerNode->GetPattern<ContainerModalPattern>();
4366 CHECK_NULL_VOID(containerPattern);
4367 containerPattern->SetContainerModalTitleVisible(customTitleSettedShow, floatingTitleSettedShow);
4368 customTitleSettedShow_ = customTitleSettedShow;
4369 }
4370
SetContainerModalTitleHeight(int32_t height)4371 void PipelineContext::SetContainerModalTitleHeight(int32_t height)
4372 {
4373 if (windowModal_ != WindowModal::CONTAINER_MODAL) {
4374 return;
4375 }
4376 CHECK_NULL_VOID(rootNode_);
4377 auto containerNode = AceType::DynamicCast<FrameNode>(rootNode_->GetFirstChild());
4378 CHECK_NULL_VOID(containerNode);
4379 auto containerPattern = containerNode->GetPattern<ContainerModalPattern>();
4380 CHECK_NULL_VOID(containerPattern);
4381 containerPattern->SetContainerModalTitleHeight(height);
4382 }
4383
GetContainerModalTitleHeight()4384 int32_t PipelineContext::GetContainerModalTitleHeight()
4385 {
4386 if (windowModal_ != WindowModal::CONTAINER_MODAL) {
4387 return -1;
4388 }
4389 CHECK_NULL_RETURN(rootNode_, -1);
4390 auto containerNode = AceType::DynamicCast<FrameNode>(rootNode_->GetFirstChild());
4391 CHECK_NULL_RETURN(containerNode, -1);
4392 auto containerPattern = containerNode->GetPattern<ContainerModalPattern>();
4393 CHECK_NULL_RETURN(containerPattern, -1);
4394 return containerPattern->GetContainerModalTitleHeight();
4395 }
4396
GetContainerModalNode()4397 RefPtr<FrameNode> PipelineContext::GetContainerModalNode()
4398 {
4399 if (windowModal_ != WindowModal::CONTAINER_MODAL) {
4400 return nullptr;
4401 }
4402 CHECK_NULL_RETURN(rootNode_, nullptr);
4403 return AceType::DynamicCast<FrameNode>(rootNode_->GetFirstChild());
4404 }
4405
DoKeyboardAvoidAnimate(const KeyboardAnimationConfig & keyboardAnimationConfig,float keyboardHeight,const std::function<void ()> & func)4406 void PipelineContext::DoKeyboardAvoidAnimate(const KeyboardAnimationConfig& keyboardAnimationConfig,
4407 float keyboardHeight, const std::function<void()>& func)
4408 {
4409 if (isDoKeyboardAvoidAnimate_) {
4410 AnimationOption option = AnimationUtil::CreateKeyboardAnimationOption(keyboardAnimationConfig, keyboardHeight);
4411 Animate(option, option.GetCurve(), func);
4412 } else {
4413 func();
4414 }
4415 }
4416
GetCustomTitleHeight()4417 Dimension PipelineContext::GetCustomTitleHeight()
4418 {
4419 auto containerModal = GetContainerModalNode();
4420 CHECK_NULL_RETURN(containerModal, Dimension());
4421 return containerModal->GetPattern<ContainerModalPattern>()->GetCustomTitleHeight();
4422 }
4423
GetContainerModalButtonsRect(RectF & containerModal,RectF & buttons)4424 bool PipelineContext::GetContainerModalButtonsRect(RectF& containerModal, RectF& buttons)
4425 {
4426 if (windowModal_ != WindowModal::CONTAINER_MODAL) {
4427 return false;
4428 }
4429 CHECK_NULL_RETURN(rootNode_, false);
4430 auto containerNode = AceType::DynamicCast<FrameNode>(rootNode_->GetFirstChild());
4431 CHECK_NULL_RETURN(containerNode, false);
4432 auto containerPattern = containerNode->GetPattern<ContainerModalPattern>();
4433 CHECK_NULL_RETURN(containerPattern, false);
4434 return containerPattern->GetContainerModalButtonsRect(containerModal, buttons);
4435 }
4436
SubscribeContainerModalButtonsRectChange(std::function<void (RectF & containerModal,RectF & buttons)> && callback)4437 void PipelineContext::SubscribeContainerModalButtonsRectChange(
4438 std::function<void(RectF& containerModal, RectF& buttons)>&& callback)
4439 {
4440 if (windowModal_ != WindowModal::CONTAINER_MODAL) {
4441 return;
4442 }
4443 CHECK_NULL_VOID(rootNode_);
4444 auto containerNode = AceType::DynamicCast<FrameNode>(rootNode_->GetFirstChild());
4445 CHECK_NULL_VOID(containerNode);
4446 auto containerPattern = containerNode->GetPattern<ContainerModalPattern>();
4447 CHECK_NULL_VOID(containerPattern);
4448 containerPattern->SubscribeContainerModalButtonsRectChange(std::move(callback));
4449 }
4450
GetWindowPaintRectWithoutMeasureAndLayout(RectInt & rect)4451 void PipelineContext::GetWindowPaintRectWithoutMeasureAndLayout(RectInt& rect)
4452 {
4453 if (windowModal_ != WindowModal::CONTAINER_MODAL) {
4454 return;
4455 }
4456 CHECK_NULL_VOID(rootNode_);
4457 auto containerNode = AceType::DynamicCast<FrameNode>(rootNode_->GetFirstChild());
4458 CHECK_NULL_VOID(containerNode);
4459 auto containerPattern = containerNode->GetPattern<ContainerModalPattern>();
4460 CHECK_NULL_VOID(containerPattern);
4461 containerPattern->GetWindowPaintRectWithoutMeasureAndLayout(rect);
4462 }
4463
IsDragging() const4464 bool PipelineContext::IsDragging() const
4465 {
4466 if (!dragDropManager_) {
4467 return false;
4468 }
4469 bool isDragging = dragDropManager_->IsDragging();
4470 isDragging = (isDragging || dragDropManager_->IsMSDPDragging());
4471 return isDragging;
4472 }
4473
SetIsDragging(bool isDragging)4474 void PipelineContext::SetIsDragging(bool isDragging)
4475 {
4476 if (!eventManager_) {
4477 return;
4478 }
4479 eventManager_->SetIsDragging(isDragging);
4480 }
4481
ResetDragging()4482 void PipelineContext::ResetDragging()
4483 {
4484 CHECK_NULL_VOID(dragDropManager_);
4485 dragDropManager_->ResetDragging();
4486 }
4487
GetPostEventManager()4488 const RefPtr<PostEventManager>& PipelineContext::GetPostEventManager()
4489 {
4490 return postEventManager_;
4491 }
4492
GetSerializedGesture() const4493 const SerializedGesture& PipelineContext::GetSerializedGesture() const
4494 {
4495 return serializedGesture_;
4496 }
4497
PrintVsyncInfoIfNeed() const4498 bool PipelineContext::PrintVsyncInfoIfNeed() const
4499 {
4500 if (dumpFrameInfos_.empty()) {
4501 return false;
4502 }
4503 auto lastFrameInfo = dumpFrameInfos_.back();
4504 const uint64_t timeout = 1000000000; // unit is ns, 1s
4505 if (lastFrameInfo.frameRecvTime_ < window_->GetLastRequestVsyncTime() &&
4506 static_cast<uint64_t>(GetSysTimestamp()) - window_->GetLastRequestVsyncTime() >= timeout) {
4507 LOGW("lastRequestVsyncTime is %{public}" PRIu64 ", now time is %{public}" PRId64
4508 ", timeout, window foreground:%{public}d, lastReceiveVsync info:%{public}s",
4509 window_->GetLastRequestVsyncTime(), GetSysTimestamp(), onShow_, lastFrameInfo.GetTimeInfo().c_str());
4510 return true;
4511 }
4512 return false;
4513 }
4514
StopWindowAnimation()4515 void PipelineContext::StopWindowAnimation()
4516 {
4517 isWindowAnimation_ = false;
4518 if (taskScheduler_ && !taskScheduler_->IsPredictTaskEmpty()) {
4519 RequestFrame();
4520 }
4521 }
4522
AddSyncGeometryNodeTask(std::function<void ()> && task)4523 void PipelineContext::AddSyncGeometryNodeTask(std::function<void()>&& task)
4524 {
4525 taskScheduler_->AddSyncGeometryNodeTask(std::move(task));
4526 }
4527
FlushSyncGeometryNodeTasks()4528 void PipelineContext::FlushSyncGeometryNodeTasks()
4529 {
4530 taskScheduler_->FlushSyncGeometryNodeTasks();
4531 }
4532
SetUIExtensionImeShow(bool imeShow)4533 void PipelineContext::SetUIExtensionImeShow(bool imeShow)
4534 {
4535 textFieldManager_->SetUIExtensionImeShow(imeShow);
4536 }
4537
SetOverlayNodePositions(std::vector<Ace::RectF> rects)4538 void PipelineContext::SetOverlayNodePositions(std::vector<Ace::RectF> rects)
4539 {
4540 overlayNodePositions_ = rects;
4541 }
4542
SetCallBackNode(const WeakPtr<NG::FrameNode> & node)4543 void PipelineContext::SetCallBackNode(const WeakPtr<NG::FrameNode>& node)
4544 {
4545 auto frameNode = node.Upgrade();
4546 CHECK_NULL_VOID(frameNode);
4547 auto pipelineContext = frameNode->GetContext();
4548 CHECK_NULL_VOID(pipelineContext);
4549 pipelineContext->UpdateCurrentActiveNode(node);
4550 }
4551
GetOverlayNodePositions()4552 std::vector<Ace::RectF> PipelineContext::GetOverlayNodePositions()
4553 {
4554 return overlayNodePositions_;
4555 }
4556
RegisterOverlayNodePositionsUpdateCallback(const std::function<void (std::vector<Ace::RectF>)> && callback)4557 void PipelineContext::RegisterOverlayNodePositionsUpdateCallback(
4558 const std::function<void(std::vector<Ace::RectF>)>&& callback)
4559 {
4560 overlayNodePositionUpdateCallback_ = std::move(callback);
4561 }
4562
TriggerOverlayNodePositionsUpdateCallback(std::vector<Ace::RectF> rects)4563 void PipelineContext::TriggerOverlayNodePositionsUpdateCallback(std::vector<Ace::RectF> rects)
4564 {
4565 if (overlayNodePositionUpdateCallback_) {
4566 overlayNodePositionUpdateCallback_(rects);
4567 }
4568 }
4569
IsContainerModalVisible()4570 bool PipelineContext::IsContainerModalVisible()
4571 {
4572 if (windowModal_ != WindowModal::CONTAINER_MODAL) {
4573 return false;
4574 }
4575 auto windowManager = GetWindowManager();
4576 bool isFloatingWindow = windowManager->GetWindowMode() == WindowMode::WINDOW_MODE_FLOATING;
4577 return isShowTitle_ && isFloatingWindow && customTitleSettedShow_;
4578 }
4579
CheckNeedUpdateBackgroundColor(Color & color)4580 void PipelineContext::CheckNeedUpdateBackgroundColor(Color& color)
4581 {
4582 if (!isFormRender_ || (renderingMode_ != RENDERING_SINGLE_COLOR)) {
4583 return;
4584 }
4585 Color replaceColor = color.ChangeAlpha(SINGLECOLOR_UPDATE_ALPHA);
4586 color = replaceColor;
4587 }
4588
CheckNeedDisableUpdateBackgroundImage()4589 bool PipelineContext::CheckNeedDisableUpdateBackgroundImage()
4590 {
4591 if (!isFormRender_ || (renderingMode_ != RENDERING_SINGLE_COLOR)) {
4592 return false;
4593 }
4594 return true;
4595 }
4596
ChangeDarkModeBrightness()4597 void PipelineContext::ChangeDarkModeBrightness()
4598 {
4599 auto windowManager = GetWindowManager();
4600 CHECK_NULL_VOID(windowManager);
4601 auto mode = windowManager->GetWindowMode();
4602 auto container = Container::CurrentSafely();
4603 CHECK_NULL_VOID(container);
4604 auto percent = SystemProperties::GetDarkModeBrightnessPercent();
4605 auto stage = stageManager_->GetStageNode();
4606 CHECK_NULL_VOID(stage);
4607 auto renderContext = stage->GetRenderContext();
4608 CHECK_NULL_VOID(renderContext);
4609 CalcDimension dimension;
4610 dimension.SetValue(1);
4611 if (SystemProperties::GetColorMode() == ColorMode::DARK && appBgColor_.ColorToString().compare("#FF000000") == 0 &&
4612 mode != WindowMode::WINDOW_MODE_FULLSCREEN && !container->IsUIExtensionWindow() &&
4613 !container->IsDynamicRender() && !container->IsFormRender() && !IsJsCard()) {
4614 if (!onFocus_ && mode == WindowMode::WINDOW_MODE_FLOATING) {
4615 dimension.SetValue(1 + percent.second);
4616 } else {
4617 dimension.SetValue(1 + percent.first);
4618 }
4619 }
4620 renderContext->UpdateFrontBrightness(dimension);
4621 }
4622
PreLayout(uint64_t nanoTimestamp,uint32_t frameCount)4623 void PipelineContext::PreLayout(uint64_t nanoTimestamp, uint32_t frameCount)
4624 {
4625 FlushVsync(nanoTimestamp, frameCount);
4626 }
4627
CheckAndLogLastReceivedTouchEventInfo(int32_t eventId,TouchType type)4628 void PipelineContext::CheckAndLogLastReceivedTouchEventInfo(int32_t eventId, TouchType type)
4629 {
4630 eventManager_->CheckAndLogLastReceivedTouchEventInfo(eventId, type);
4631 }
4632
CheckAndLogLastConsumedTouchEventInfo(int32_t eventId,TouchType type)4633 void PipelineContext::CheckAndLogLastConsumedTouchEventInfo(int32_t eventId, TouchType type)
4634 {
4635 eventManager_->CheckAndLogLastConsumedTouchEventInfo(eventId, type);
4636 }
4637
CheckAndLogLastReceivedMouseEventInfo(int32_t eventId,MouseAction action)4638 void PipelineContext::CheckAndLogLastReceivedMouseEventInfo(int32_t eventId, MouseAction action)
4639 {
4640 eventManager_->CheckAndLogLastReceivedMouseEventInfo(eventId, action);
4641 }
4642
CheckAndLogLastConsumedMouseEventInfo(int32_t eventId,MouseAction action)4643 void PipelineContext::CheckAndLogLastConsumedMouseEventInfo(int32_t eventId, MouseAction action)
4644 {
4645 eventManager_->CheckAndLogLastConsumedMouseEventInfo(eventId, action);
4646 }
4647
CheckAndLogLastReceivedAxisEventInfo(int32_t eventId,AxisAction action)4648 void PipelineContext::CheckAndLogLastReceivedAxisEventInfo(int32_t eventId, AxisAction action)
4649 {
4650 eventManager_->CheckAndLogLastReceivedAxisEventInfo(eventId, action);
4651 }
4652
CheckAndLogLastConsumedAxisEventInfo(int32_t eventId,AxisAction action)4653 void PipelineContext::CheckAndLogLastConsumedAxisEventInfo(int32_t eventId, AxisAction action)
4654 {
4655 eventManager_->CheckAndLogLastConsumedAxisEventInfo(eventId, action);
4656 }
4657
RegisterTouchEventListener(const std::shared_ptr<ITouchEventCallback> & listener)4658 void PipelineContext::RegisterTouchEventListener(const std::shared_ptr<ITouchEventCallback>& listener)
4659 {
4660 if (!listener) {
4661 return;
4662 }
4663 listenerVector_.emplace_back(listener);
4664 }
4665
UnregisterTouchEventListener(const WeakPtr<NG::Pattern> & pattern)4666 void PipelineContext::UnregisterTouchEventListener(const WeakPtr<NG::Pattern>& pattern)
4667 {
4668 for (auto iter = listenerVector_.begin(); iter != listenerVector_.end();) {
4669 auto patternPtr = (*iter)->GetPatternFromListener();
4670 if (patternPtr.Invalid() || patternPtr == pattern) {
4671 iter = listenerVector_.erase(iter);
4672 } else {
4673 iter++;
4674 }
4675 }
4676 }
4677
FlushFrameCallback(uint64_t nanoTimestamp)4678 void PipelineContext::FlushFrameCallback(uint64_t nanoTimestamp)
4679 {
4680 if (!frameCallbackFuncs_.empty()) {
4681 decltype(frameCallbackFuncs_) tasks(std::move(frameCallbackFuncs_));
4682 for (const auto& frameCallbackFunc : tasks) {
4683 frameCallbackFunc(nanoTimestamp);
4684 }
4685 }
4686 }
4687
RegisterFocusCallback()4688 void PipelineContext::RegisterFocusCallback()
4689 {
4690 focusManager_->AddFocusListener([](const WeakPtr<FocusHub>& last, const RefPtr<FocusHub>& current,
4691 FocusReason focusReason) {
4692 CHECK_NULL_VOID(current);
4693 auto node = current->GetFrameNode();
4694 CHECK_NULL_VOID(node);
4695 InputMethodManager::GetInstance()->OnFocusNodeChange(node);
4696 });
4697 }
4698
AddFrameNodeChangeListener(const WeakPtr<FrameNode> & node)4699 void PipelineContext::AddFrameNodeChangeListener(const WeakPtr<FrameNode>& node)
4700 {
4701 CHECK_NULL_VOID(node.Upgrade());
4702 if (std::find(changeInfoListeners_.begin(), changeInfoListeners_.end(), node) == changeInfoListeners_.end()) {
4703 changeInfoListeners_.push_back(node);
4704 }
4705 }
4706
RemoveFrameNodeChangeListener(int32_t nodeId)4707 void PipelineContext::RemoveFrameNodeChangeListener(int32_t nodeId)
4708 {
4709 if (changeInfoListeners_.empty()) {
4710 return;
4711 }
4712 changeInfoListeners_.remove_if([nodeId](const WeakPtr<FrameNode>& node) {
4713 return !node.Upgrade() || nodeId == node.Upgrade()->GetId();
4714 });
4715 }
4716
AddChangedFrameNode(const WeakPtr<FrameNode> & node)4717 bool PipelineContext::AddChangedFrameNode(const WeakPtr<FrameNode>& node)
4718 {
4719 CHECK_NULL_RETURN(node.Upgrade(), false);
4720 if (changeInfoListeners_.empty()) {
4721 return false;
4722 }
4723 if (std::find(changedNodes_.begin(), changedNodes_.end(), node) == changedNodes_.end()) {
4724 changedNodes_.push_back(node);
4725 }
4726 return true;
4727 }
4728
RemoveChangedFrameNode(int32_t nodeId)4729 void PipelineContext::RemoveChangedFrameNode(int32_t nodeId)
4730 {
4731 if (changedNodes_.empty()) {
4732 return;
4733 }
4734 changedNodes_.remove_if([nodeId](const WeakPtr<FrameNode>& node) {
4735 return !node.Upgrade() || nodeId == node.Upgrade()->GetId();
4736 });
4737 }
4738
FlushNodeChangeFlag()4739 void PipelineContext::FlushNodeChangeFlag()
4740 {
4741 ACE_FUNCTION_TRACE();
4742 if (!changeInfoListeners_.empty()) {
4743 for (const auto& it : changeInfoListeners_) {
4744 auto listener = it.Upgrade();
4745 if (listener) {
4746 listener->ProcessFrameNodeChangeFlag();
4747 }
4748 }
4749 }
4750 CleanNodeChangeFlag();
4751 }
4752
CleanNodeChangeFlag()4753 void PipelineContext::CleanNodeChangeFlag()
4754 {
4755 auto cleanNodes = std::move(changedNodes_);
4756 changedNodes_.clear();
4757 for (const auto& it : cleanNodes) {
4758 auto changeNode = it.Upgrade();
4759 if (changeNode) {
4760 changeNode->ClearChangeInfoFlag();
4761 }
4762 }
4763 }
4764
GetInspectorTree()4765 void PipelineContext::GetInspectorTree()
4766 {
4767 #if !defined(PREVIEW) && !defined(ACE_UNITTEST) && defined(OHOS_PLATFORM)
4768 bool needThrow = false;
4769 NG::InspectorFilter filter;
4770 filter.AddFilterAttr("content");
4771 auto nodeInfos = NG::Inspector::GetInspector(false, filter, needThrow);
4772 UiSessionManager::GetInstance().AddValueForTree(0, nodeInfos);
4773 #endif
4774 rootNode_->GetInspectorValue();
4775 }
4776
NotifyAllWebPattern(bool isRegister)4777 void PipelineContext::NotifyAllWebPattern(bool isRegister)
4778 {
4779 rootNode_->NotifyWebPattern(isRegister);
4780 }
4781
4782 #if defined(SUPPORT_TOUCH_TARGET_TEST)
4783
OnTouchTargetHitTest(const TouchEvent & point,bool isSubPipe,const std::string & target)4784 bool PipelineContext::OnTouchTargetHitTest(const TouchEvent& point, bool isSubPipe, const std::string& target)
4785 {
4786 auto scalePoint = point.CreateScalePoint(GetViewScale());
4787 if (scalePoint.type == TouchType::DOWN) {
4788 TouchRestrict touchRestrict { TouchRestrict::NONE };
4789 touchRestrict.sourceType = point.sourceType;
4790 touchRestrict.touchEvent = point;
4791 bool isTouchTarget = eventManager_->TouchTargetHitTest(
4792 scalePoint, rootNode_, touchRestrict, GetPluginEventOffset(), viewScale_, isSubPipe, target);
4793 return isTouchTarget;
4794 }
4795 return false;
4796 }
4797 #endif
4798
UpdateHalfFoldHoverStatus(int32_t windowWidth,int32_t windowHeight)4799 void PipelineContext::UpdateHalfFoldHoverStatus(int32_t windowWidth, int32_t windowHeight)
4800 {
4801 if (Container::LessThanAPIVersion(PlatformVersion::VERSION_THIRTEEN)) {
4802 isHalfFoldHoverStatus_ = false;
4803 return;
4804 }
4805 auto container = Container::Current();
4806 CHECK_NULL_VOID(container);
4807 bool isFoldable = container->IsFoldable();
4808 if (!isFoldable && !SystemProperties::IsSmallFoldProduct()) {
4809 isHalfFoldHoverStatus_ = false;
4810 return;
4811 }
4812 auto displayInfo = container->GetDisplayInfo();
4813 CHECK_NULL_VOID(displayInfo);
4814 auto windowManager = GetWindowManager();
4815 auto windowMode = windowManager->GetWindowMode();
4816 auto isHalfFolded = displayInfo->GetFoldStatus() == FoldStatus::HALF_FOLD;
4817 auto displayWidth = displayInfo->GetWidth();
4818 auto displayHeight = displayInfo->GetHeight();
4819 auto isFullScreen = windowMode == WindowMode::WINDOW_MODE_FULLSCREEN ||
4820 (NearEqual(displayWidth, windowWidth) && NearEqual(displayHeight, windowHeight));
4821 if (!isFullScreen || !isHalfFolded) {
4822 isHalfFoldHoverStatus_ = false;
4823 return;
4824 }
4825 auto rotation = displayInfo->GetRotation();
4826 if (SystemProperties::IsSmallFoldProduct()) {
4827 isHalfFoldHoverStatus_ = rotation == Rotation::ROTATION_0 || rotation == Rotation::ROTATION_180;
4828 } else {
4829 isHalfFoldHoverStatus_ = rotation == Rotation::ROTATION_90 || rotation == Rotation::ROTATION_270;
4830 }
4831 }
4832
OnHalfFoldHoverChangedCallback()4833 void PipelineContext::OnHalfFoldHoverChangedCallback()
4834 {
4835 for (auto&& [id, callback] : halfFoldHoverChangedCallbackMap_) {
4836 if (callback) {
4837 callback(isHalfFoldHoverStatus_);
4838 }
4839 }
4840 }
4841
StartFoldStatusDelayTask(FoldStatus foldStatus)4842 void PipelineContext::StartFoldStatusDelayTask(FoldStatus foldStatus)
4843 {
4844 if (foldStatusDelayTask_) {
4845 foldStatusDelayTask_.Cancel();
4846 }
4847 foldStatusDelayTask_.Reset([weak = WeakClaim(this)]() {
4848 auto context = weak.Upgrade();
4849 CHECK_NULL_VOID(context);
4850 context->UpdateHalfFoldHoverProperty(context->GetRootWidth(), context->GetRootHeight());
4851 context->OnHalfFoldHoverChangedCallback();
4852 });
4853 taskExecutor_->PostDelayedTask(
4854 foldStatusDelayTask_, TaskExecutor::TaskType::UI, DELAY_TIME, "ArkUIHalfFoldHoverStatusChange");
4855 }
4856
CatchInteractiveAnimations(const std::function<void ()> & animationCallback)4857 bool PipelineContext::CatchInteractiveAnimations(const std::function<void()>& animationCallback)
4858 {
4859 CHECK_NULL_RETURN(navigationMgr_, false);
4860 if (navigationMgr_->IsInteractive()) {
4861 return navigationMgr_->AddInteractiveAnimation(animationCallback);
4862 }
4863 return false;
4864 }
4865
GetResponseRegion(const RefPtr<FrameNode> & rootNode)4866 std::string PipelineContext::GetResponseRegion(const RefPtr<FrameNode>& rootNode)
4867 {
4868 CHECK_NULL_RETURN(rootNode, "");
4869 std::vector<RectF> responseRegionList;
4870 rootNode->GetResponseRegionListByTraversal(responseRegionList);
4871 std::string responseRegionStrOrigin;
4872 std::string responseRegionStrFilter;
4873 for (const auto& rect : responseRegionList) {
4874 int32_t left = static_cast<int32_t>(rect.Left());
4875 int32_t top = static_cast<int32_t>(rect.Top());
4876 int32_t width = static_cast<int32_t>(rect.Width());
4877 int32_t height = static_cast<int32_t>(rect.Height());
4878 int32_t right = static_cast<int32_t>(rect.Right());
4879 int32_t bottom = static_cast<int32_t>(rect.Bottom());
4880 std::string rectStr = std::to_string(left) + "," +
4881 std::to_string(top) + "," +
4882 std::to_string(right) + "," +
4883 std::to_string(bottom);
4884
4885 responseRegionStrOrigin += rectStr + "#";
4886 if (thpExtraMgr_ && width <= thpExtraMgr_->GetWidth() && height <= thpExtraMgr_->GetHeight()) {
4887 responseRegionStrFilter += rectStr + "#";
4888 }
4889 }
4890 if (!responseRegionStrFilter.empty()) {
4891 responseRegionStrFilter.pop_back();
4892 }
4893 LOGD("THP_UpdateViewsLocation origin responseRegion = %{public}s", responseRegionStrOrigin.c_str());
4894 return responseRegionStrFilter;
4895 }
4896
NotifyResponseRegionChanged(const RefPtr<FrameNode> & rootNode)4897 void PipelineContext::NotifyResponseRegionChanged(const RefPtr<FrameNode>& rootNode)
4898 {
4899 ACE_FUNCTION_TRACE();
4900 if (!thpExtraMgr_) {
4901 return;
4902 }
4903 std::string responseRegion = GetResponseRegion(rootNode);
4904 std::string parameters = "thp#Location#" + responseRegion;
4905 LOGD("THP_UpdateViewsLocation responseRegion = %{public}s", parameters.c_str());
4906 thpExtraMgr_->ThpExtraRunCommand("THP_UpdateViewsLocation", parameters.c_str());
4907 }
4908
CheckThreadSafe() const4909 bool PipelineContext::CheckThreadSafe() const
4910 {
4911 CHECK_NULL_RETURN(taskExecutor_, true);
4912 if (!isFormRender_ && !taskExecutor_->WillRunOnCurrentThread(OHOS::Ace::TaskExecutor::TaskType::UI)) {
4913 OHOS::Ace::LogBacktrace();
4914 return false;
4915 }
4916 return true;
4917 }
4918
AdjustVsyncTimeStamp(uint64_t nanoTimestamp)4919 uint64_t PipelineContext::AdjustVsyncTimeStamp(uint64_t nanoTimestamp)
4920 {
4921 auto period = window_->GetVSyncPeriod();
4922 if (period > 0 && recvTime_ > static_cast<int64_t>(nanoTimestamp) + MAX_MISS_COUNT * period) {
4923 return static_cast<uint64_t>(recvTime_ - ((recvTime_ - static_cast<int64_t>(nanoTimestamp)) % period));
4924 }
4925 return nanoTimestamp;
4926 }
4927
FlushModifierAnimation(uint64_t nanoTimestamp)4928 bool PipelineContext::FlushModifierAnimation(uint64_t nanoTimestamp)
4929 {
4930 auto animationTimeStamp = AdjustVsyncTimeStamp(nanoTimestamp);
4931 if (animationTimeStamp < animationTimeStamp_) {
4932 ACE_SCOPED_TRACE("skip ModifierAnimation");
4933 TAG_LOGW(AceLogTag::ACE_ANIMATION,
4934 "Time decreases, skip ModifierAnimation, lastTime:%{public}" PRIu64 ", nowTime:%{public}" PRIu64,
4935 animationTimeStamp_, animationTimeStamp);
4936 return true;
4937 }
4938 animationTimeStamp_ = animationTimeStamp;
4939 return window_->FlushAnimation(animationTimeStamp);
4940 }
4941
RegisterAttachedNode(UINode * uiNode)4942 void PipelineContext::RegisterAttachedNode(UINode* uiNode)
4943 {
4944 attachedNodeSet_.emplace(uiNode);
4945 }
4946
RemoveAttachedNode(UINode * uiNode)4947 void PipelineContext::RemoveAttachedNode(UINode* uiNode)
4948 {
4949 attachedNodeSet_.erase(uiNode);
4950 }
4951
ScopedLayout(PipelineContext * pipeline)4952 ScopedLayout::ScopedLayout(PipelineContext* pipeline)
4953 {
4954 if (!pipeline) {
4955 return;
4956 }
4957 // save flag before measure
4958 pipeline_ = pipeline;
4959 isLayouting_ = pipeline_->IsLayouting();
4960 pipeline_->SetIsLayouting(true);
4961 }
4962
~ScopedLayout()4963 ScopedLayout::~ScopedLayout()
4964 {
4965 if (!pipeline_) {
4966 return;
4967 }
4968 // set layout flag back
4969 pipeline_->SetIsLayouting(isLayouting_);
4970 }
4971
GetBundleName()4972 std::string PipelineContext::GetBundleName()
4973 {
4974 auto container = Container::GetContainer(instanceId_);
4975 CHECK_NULL_RETURN(container, "");
4976 return container->GetBundleName();
4977 }
4978
GetModuleName()4979 std::string PipelineContext::GetModuleName()
4980 {
4981 auto container = Container::GetContainer(instanceId_);
4982 CHECK_NULL_RETURN(container, "");
4983 return container->GetModuleName();
4984 }
4985 } // namespace OHOS::Ace::NG
4986